Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ticket8378 add linting action #80

Merged
merged 7 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ignore ruff format and --fix
7d074d129ef30f64dee361531fe3d6a020cdff98
3c5addd30d6e6f6ae34b02333d34360d773ed3bf
7 changes: 7 additions & 0 deletions .github/workflows/linter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: Linter
on: [pull_request]
jobs:
call-workflow:
uses: ISISComputingGroup/reusable-workflows/.github/workflows/linters.yml@main
with:
compare-branch: origin/master
6 changes: 5 additions & 1 deletion check_version.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import upgrade, sys
import sys

import upgrade


def compare_version_number(version_to_check):

Check failure on line 6 in check_version.py

View workflow job for this annotation

GitHub Actions / call-workflow / ruff

Ruff (ANN201)

check_version.py:6:5: ANN201 Missing return type annotation for public function `compare_version_number`

Check failure on line 6 in check_version.py

View workflow job for this annotation

GitHub Actions / call-workflow / ruff

Ruff (ANN001)

check_version.py:6:28: ANN001 Missing type annotation for function argument `version_to_check`
latest_version, _ = upgrade.UPGRADE_STEPS[-1]

if latest_version == version_to_check:
Expand All @@ -8,6 +11,7 @@
else:
return 1


if __name__ == "__main__":
version_to_check = str(sys.argv[1])
sys.exit(compare_version_number(version_to_check))
18 changes: 13 additions & 5 deletions run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,29 @@
# Add root path for access to server_commons
import os
import sys

# Set MYDIRBLOCK so that example_base can be found
os.environ["MYDIRBLOCK"] = ".."
sys.path.insert(0, os.path.abspath(".."))
# Standard imports
import argparse
import unittest

import xmlrunner
import argparse

DEFAULT_DIRECTORY = os.path.join('..', '..', '..', 'test-reports')
DEFAULT_DIRECTORY = os.path.join("..", "..", "..", "test-reports")

if __name__ == '__main__':
if __name__ == "__main__":
# get output directory from command line arguments
parser = argparse.ArgumentParser()
parser.add_argument('-o', '--output_dir', nargs=1, type=str, default=[DEFAULT_DIRECTORY],
help='The directory to save the test reports')
parser.add_argument(
"-o",
"--output_dir",
nargs=1,
type=str,
default=[DEFAULT_DIRECTORY],
help="The directory to save the test reports",
)
args = parser.parse_args()
xml_dir = args.output_dir[0]

Expand Down
50 changes: 24 additions & 26 deletions src/common_upgrades/add_to_base_iocs.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
from xml.dom import minidom
from xml.parsers.expat import ExpatError

from src.local_logger import LocalLogger

IOC_FILENAME = "configurations\components\_base\iocs.xml"

FILE_TO_CHECK_STR = "IOC default component file"
Expand All @@ -12,24 +10,21 @@


class AddToBaseIOCs:
"""
Add the ioc autostart to _base ioc so that it autostarts
"""
"""Add the ioc autostart to _base ioc so that it autostarts"""

def __init__(self, ioc_to_add, add_after_ioc, xml_to_add):

Check failure on line 15 in src/common_upgrades/add_to_base_iocs.py

View workflow job for this annotation

GitHub Actions / call-workflow / ruff

Ruff (ANN204)

src/common_upgrades/add_to_base_iocs.py:15:9: ANN204 Missing return type annotation for special method `__init__`

Check failure on line 15 in src/common_upgrades/add_to_base_iocs.py

View workflow job for this annotation

GitHub Actions / call-workflow / ruff

Ruff (ANN001)

src/common_upgrades/add_to_base_iocs.py:15:24: ANN001 Missing type annotation for function argument `ioc_to_add`

Check failure on line 15 in src/common_upgrades/add_to_base_iocs.py

View workflow job for this annotation

GitHub Actions / call-workflow / ruff

Ruff (ANN001)

src/common_upgrades/add_to_base_iocs.py:15:36: ANN001 Missing type annotation for function argument `add_after_ioc`

Check failure on line 15 in src/common_upgrades/add_to_base_iocs.py

View workflow job for this annotation

GitHub Actions / call-workflow / ruff

Ruff (ANN001)

src/common_upgrades/add_to_base_iocs.py:15:51: ANN001 Missing type annotation for function argument `xml_to_add`
self._ioc_to_add = ioc_to_add
self._add_after_ioc = add_after_ioc
self._xml_to_add = xml_to_add

def perform(self, file_access, logger):

Check failure on line 20 in src/common_upgrades/add_to_base_iocs.py

View workflow job for this annotation

GitHub Actions / call-workflow / ruff

Ruff (ANN201)

src/common_upgrades/add_to_base_iocs.py:20:9: ANN201 Missing return type annotation for public function `perform`

Check failure on line 20 in src/common_upgrades/add_to_base_iocs.py

View workflow job for this annotation

GitHub Actions / call-workflow / ruff

Ruff (ANN001)

src/common_upgrades/add_to_base_iocs.py:20:23: ANN001 Missing type annotation for function argument `file_access`

Check failure on line 20 in src/common_upgrades/add_to_base_iocs.py

View workflow job for this annotation

GitHub Actions / call-workflow / ruff

Ruff (ANN001)

src/common_upgrades/add_to_base_iocs.py:20:36: ANN001 Missing type annotation for function argument `logger`
"""
Add the autostart of the given.
"""Add the autostart of the given.

Args:
file_access (FileAccess): file access.
logger (LocalLogger): logger.

Returns:
Returns:
exit code 0 success; anything else fail.

"""
Expand All @@ -48,7 +43,9 @@
return -2

modified_file_contents = self._add_ioc(ioc_file_contents, logger)
logger.info("Adding {what} ioc to autostart in {0}.".format(IOC_FILENAME, what=self._ioc_to_add))
logger.info(
"Adding {what} ioc to autostart in {0}.".format(IOC_FILENAME, what=self._ioc_to_add)
)

if not self._check_final_file_contains_one_of_added_ioc(logger, modified_file_contents):
return -3
Expand All @@ -57,9 +54,8 @@
return 0

@staticmethod
def _get_ioc_names(xml):

Check failure on line 57 in src/common_upgrades/add_to_base_iocs.py

View workflow job for this annotation

GitHub Actions / call-workflow / ruff

Ruff (ANN205)

src/common_upgrades/add_to_base_iocs.py:57:9: ANN205 Missing return type annotation for staticmethod `_get_ioc_names`
"""
Gets the names of all the iocs in the xml.
"""Gets the names of all the iocs in the xml.

Args:
xml: XML to check.
Expand All @@ -70,13 +66,12 @@
return [ioc.getAttribute("name") for ioc in xml.getElementsByTagName("ioc")]

def _check_final_file_contains_one_of_added_ioc(self, logger, xml):
"""
Check the file to make sure it now contains one and only one ioc added entry.

"""Check the file to make sure it now contains one and only one ioc added entry.

Args:
logger (Logger): Logger to write to.
xml: XML to check.

Returns:
True if ok, else False.
"""
Expand All @@ -90,13 +85,12 @@
return True

def _check_prerequistes_for_file(self, xml, logger):
"""
Check the file can be modified.

"""Check the file can be modified.

Args:
xml: XML to check
logger (Logger): logger to write errors to.

Returns:
True if everything is ok, else False.
"""
Expand All @@ -108,17 +102,18 @@

node_count = ioc_names.count(self._add_after_ioc)
if node_count != 1:
logger.error(ADD_AFTER_MISSING.format(FILE_TO_CHECK_STR, node_count, self._add_after_ioc))
logger.error(
ADD_AFTER_MISSING.format(FILE_TO_CHECK_STR, node_count, self._add_after_ioc)
)
return False
return True

def _add_ioc(self, ioc_xml, logger):
"""
Add IOC entry after add after ioc specified if it exists.

"""Add IOC entry after add after ioc specified if it exists.

Args:
ioc_xml: XML to add to.

Returns:
The XML with the added note.
"""
Expand All @@ -130,6 +125,9 @@
ioc_xml.firstChild.insertBefore(ioc_xml.createTextNode("\n "), new_ioc_node)
return ioc_xml

logger.error("Could not find {0} ioc in file so no {1} ioc added.".format(
self._add_after_ioc, self._ioc_to_add))
logger.error(
"Could not find {0} ioc in file so no {1} ioc added.".format(
self._add_after_ioc, self._ioc_to_add
)
)
return ioc_xml
71 changes: 32 additions & 39 deletions src/common_upgrades/change_macro_in_globals.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import re

from src.common_upgrades.utils.constants import GLOBALS_FILENAME


class ChangeMacroInGlobals(object):
"""
An interface to replace arbitrary macros in a globals.txt file
"""
"""An interface to replace arbitrary macros in a globals.txt file"""

def __init__(self, file_access, logger):
"""
Initialise.
"""Initialise.

Args:
file_access: Object to allow for file access.
Expand All @@ -20,22 +18,19 @@ def __init__(self, file_access, logger):
self._loaded_file = self.load_globals_file()

def load_globals_file(self):
"""
Loads in a globals file as a list of strings.
"""Loads in a globals file as a list of strings.

Returns:
Globals file loaded as list of strings if globals file exists.
Empty list otherwise.
"""

if self._file_access.exists(GLOBALS_FILENAME):
return self._file_access.open_file(GLOBALS_FILENAME)
else:
return []

def change_macros(self, ioc_name, macros_to_change):
"""
Changes a list of macros in the globals.txt file for a specific IOC.
"""Changes a list of macros in the globals.txt file for a specific IOC.

Args:
ioc_name: Name of the IOC.
Expand All @@ -45,16 +40,14 @@ def change_macros(self, ioc_name, macros_to_change):
Returns:
None
"""

for old_macro, new_macro in macros_to_change:
for index in self._globals_filter_generator(ioc_name):
self._apply_regex_macro_change(ioc_name, old_macro, new_macro, index)

self.write_modified_globals_file()

def change_ioc_name(self, old_ioc_name, new_ioc_name):
"""
Changes the name of an IOC in a globals.txt file.
"""Changes the name of an IOC in a globals.txt file.

Args:
old_ioc_name: String, the old name of the IOC
Expand All @@ -64,15 +57,13 @@ def change_ioc_name(self, old_ioc_name, new_ioc_name):
None

"""

for index in self._globals_filter_generator(old_ioc_name):
self._change_ioc_name(old_ioc_name, new_ioc_name, index)

self.write_modified_globals_file()

def _globals_filter_generator(self, ioc_to_change):
"""
Returns lines containing specified IOCs from globals.txt
"""Returns lines containing specified IOCs from globals.txt

Generator that gives all the lines for a given IOC in globals.txt.
This will match IOCs with the same name as the root plus any that have a number
Expand All @@ -84,15 +75,13 @@ def _globals_filter_generator(self, ioc_to_change):
Yields:
Index that the ioc is on.
"""

for index, line in enumerate(self._loaded_file):
if line.startswith("{}_".format(ioc_to_change)):
self._logger.info("Found line '{}' in {}".format(line, GLOBALS_FILENAME))
yield index

def _determine_replacement_values(self, old_macro, new_macro):
"""
Determines the strings to search for and replace.
"""Determines the strings to search for and replace.

Args:
old_macro: Old Macro object with old macro name and old macro value.
Expand All @@ -101,7 +90,6 @@ def _determine_replacement_values(self, old_macro, new_macro):
Returns:
regex_changes: Dictionary of regex representations of the strings to search for/replace.
"""

if old_macro.value is None:
old_value_search = r".*"

Expand All @@ -113,36 +101,42 @@ def _determine_replacement_values(self, old_macro, new_macro):
old_value_search = old_macro.value
new_value_replacement = new_macro.value

regex_changes = {'old_macro_search': old_macro.name,
'new_macro_replacement': new_macro.name,
'old_value_search': old_value_search,
'new_value_replacement': new_value_replacement}
regex_changes = {
"old_macro_search": old_macro.name,
"new_macro_replacement": new_macro.name,
"old_value_search": old_value_search,
"new_value_replacement": new_value_replacement,
}

return regex_changes

def _apply_regex_macro_change(self, ioc_name, old_macro, new_macro, line_number):
"""
Applies a regular expression to modify a macro.
"""Applies a regular expression to modify a macro.

Args:
ioc_name: Name of the IOC to

Returns:
None
"""

regex_args = self._determine_replacement_values(old_macro, new_macro)

replace_regex = re.compile(r"({}_\d\d__)({})=({})".format(ioc_name, regex_args["old_macro_search"],
regex_args["old_value_search"]))
replace_regex = re.compile(
r"({}_\d\d__)({})=({})".format(
ioc_name, regex_args["old_macro_search"], regex_args["old_value_search"]
)
)

self._loaded_file[line_number] = re.sub(replace_regex, r"\1{}={}".format(regex_args["new_macro_replacement"],
regex_args["new_value_replacement"]),
self._loaded_file[line_number])
self._loaded_file[line_number] = re.sub(
replace_regex,
r"\1{}={}".format(
regex_args["new_macro_replacement"], regex_args["new_value_replacement"]
),
self._loaded_file[line_number],
)

def _change_ioc_name(self, ioc_name, new_ioc_name, line_number):
"""
If a new name is supplied, changes the name of the IOC
"""If a new name is supplied, changes the name of the IOC

Args:
ioc_name: String, the current name of the IOC
Expand All @@ -151,17 +145,16 @@ def _change_ioc_name(self, ioc_name, new_ioc_name, line_number):
Returns:
None
"""

if new_ioc_name is not None:
self._loaded_file[line_number] = self._loaded_file[line_number].replace(ioc_name, new_ioc_name.upper())
self._loaded_file[line_number] = self._loaded_file[line_number].replace(
ioc_name, new_ioc_name.upper()
)

def write_modified_globals_file(self):
"""
Writes the modified globals file if it has been loaded.
"""Writes the modified globals file if it has been loaded.

Returns:
None
"""

if self._loaded_file:
self._file_access.write_file(GLOBALS_FILENAME, self._loaded_file)
Loading
Loading