diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9de6644..f604cfb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,12 +40,6 @@ jobs: - name: Build Package run: python -m build - - name: Publish to PyPI - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} - run: twine upload dist/* - - name: Create GitHub Release uses: softprops/action-gh-release@v1 with: @@ -53,3 +47,9 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Publish to PyPI + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} + run: twine upload dist/* + diff --git a/atest/config/config_with_colors.toml b/atest/config/config_with_colors.toml index 193392a..3e38030 100644 --- a/atest/config/config_with_colors.toml +++ b/atest/config/config_with_colors.toml @@ -4,7 +4,7 @@ verbose_mode = true [colors] # DEFAULT THEME: -default = "robot" +default = "dark" # OR CUSTOM THEME: # background = "#000028" # inner_color = "#000028" diff --git a/src/testdoc/__main__.py b/src/testdoc/__main__.py index 95f3538..502a396 100644 --- a/src/testdoc/__main__.py +++ b/src/testdoc/__main__.py @@ -1,3 +1,4 @@ from testdoc.cli import main + if __name__ == "__main__": main() \ No newline at end of file diff --git a/src/testdoc/default.toml b/src/testdoc/default.toml new file mode 100644 index 0000000..812d283 --- /dev/null +++ b/src/testdoc/default.toml @@ -0,0 +1,3 @@ +# Find here some default settings like the used default theme +[default] +theme = "dark" diff --git a/src/testdoc/html/themes/theme_config.py b/src/testdoc/html/themes/theme_config.py index c94e64d..f5dcda3 100644 --- a/src/testdoc/html/themes/theme_config.py +++ b/src/testdoc/html/themes/theme_config.py @@ -1,10 +1,17 @@ from ...helper.cliargs import CommandLineArguments from .themes import DEFAULT_THEME, ROBOT_THEME, DARK_THEME, BLUE_THEME +import os +import tomli + class ThemeConfig(): + default_config = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", "default.toml") + def __init__(self): self.args = CommandLineArguments().data + with open(self.default_config, "rb") as file: + self.config = tomli.load(file) def theme(self): _theme = self.args.colors @@ -12,7 +19,7 @@ def theme(self): if "default" in _theme: return self._get_predefined_theme(_theme.get("default")) return _theme - return DARK_THEME + return self._get_predefined_theme(self.config["default"]["theme"]) def _get_predefined_theme(self, theme: str): theme = theme.strip() diff --git a/src/testdoc/parser/modifier/sourceprefixmodifier.py b/src/testdoc/parser/modifier/sourceprefixmodifier.py index 1ae33a4..7219d38 100644 --- a/src/testdoc/parser/modifier/sourceprefixmodifier.py +++ b/src/testdoc/parser/modifier/sourceprefixmodifier.py @@ -1,23 +1,45 @@ import os +from abc import ABC, abstractmethod from robot.api import TestSuite from ...helper.cliargs import CommandLineArguments from ...helper.logger import Logger +available_implementations = "gitlab" + +######################################## +# Interface +######################################## +class SourceModifier(ABC): + @abstractmethod + def apply(self, suite_dict, prefix): + pass + +######################################## +# Factory +######################################## +class SourceModifierFactory: + @staticmethod + def get_modifier(prefix_type: str) -> SourceModifier: + if prefix_type.lower() == "gitlab": + return GitLabModifier() + # EXAMPLE Extension: + # elif prefix_type.lower() == "github": + # return GitHubModifier() + raise ValueError( + f"No source modifier found for type '{prefix_type}' - actually available implementation are:\n{available_implementations}" + ) + +######################################## +# Prefix Modifier - Implementation +######################################## class SourcePrefixModifier(): GITLAB_CONNECTOR = "-/blob/main/" def __init__(self): self.args = CommandLineArguments().data - - def _modify(self, suite: TestSuite, prefix: str): - prefix_type, prefix = self._prefix_validation(prefix) - if "gitlab" in prefix_type: - SourcePrefixGitLab()._apply_gitlab_source_to_suite(suite, prefix) - else: - raise ValueError(f"No matching source-prefix modifier found for: {prefix_type} with prefix: {prefix}") def _prefix_validation(self, prefix: str) -> list: if "::" not in prefix: @@ -27,11 +49,16 @@ def _prefix_validation(self, prefix: str) -> list: def modify_source_prefix(self, suite_object: TestSuite) -> TestSuite: Logger().LogKeyValue("Using Prefix for Source: ", self.args.sourceprefix, "yellow") if self.args.verbose_mode else None + prefix_type, prefix = self._prefix_validation(self.args.sourceprefix) + modifier = SourceModifierFactory.get_modifier(prefix_type) for suite in suite_object: - self._modify(suite, self.args.sourceprefix) + modifier.apply(suite, prefix) return suite_object -class SourcePrefixGitLab(): +######################################## +# Low-Level Implementation for GitLab +######################################## +class GitLabModifier(): """ Source Prefix Modifier for "GitLab" Projects. Expected CMD Line Arg: "gitlab::prefix" @@ -62,7 +89,7 @@ def _convert_to_gitlab_url(self, file_path, prefix): rel_path = os.path.relpath(file_path, git_root).replace(os.sep, "/") return prefix.rstrip("/") + "/-/blob/" + git_branch + "/" + rel_path - def _apply_gitlab_source_to_suite(self, suite_dict, prefix): + def apply(self, suite_dict, prefix): try: suite_dict["source"] = self._convert_to_gitlab_url(suite_dict["source"], prefix) except: @@ -75,4 +102,9 @@ def _apply_gitlab_source_to_suite(self, suite_dict, prefix): test["source"] = "GitLink error" for sub_suite in suite_dict.get("sub_suites", []): - self._apply_gitlab_source_to_suite(sub_suite, prefix) + self.apply(sub_suite, prefix) + +######################################## +# Low-Level Implementation for ... +# [FUTURE EXTENSIONS LIKE GITHUB] +######################################## \ No newline at end of file diff --git a/src/testdoc/parser/modifier/suitefilemodifier.py b/src/testdoc/parser/modifier/suitefilemodifier.py index 7039e8c..1c0048e 100644 --- a/src/testdoc/parser/modifier/suitefilemodifier.py +++ b/src/testdoc/parser/modifier/suitefilemodifier.py @@ -18,9 +18,6 @@ def run(self, suite_object: TestSuite = None): self.suite = suite_object # Modify generic params / hide some params - self._modify_root_suite_name() - self._modify_root_suite_doc() - self._modify_root_suite_metadata() self._modify_tags() self._modify_test_doc() self._modify_suite_doc() @@ -29,29 +26,16 @@ def run(self, suite_object: TestSuite = None): return self.suite ############################################################################################################################# - - def _modify_root_suite_name(self): - if not self.args.name: - return - Logger().LogKeyValue("Modified Name of Root Suite: ", self.args.name, "yellow") if self.args.verbose_mode else None - self.suite[0]["name"] = self.args.name - - ############################################################################################################################# - - def _modify_root_suite_doc(self): - if not self.args.doc: - return - Logger().LogKeyValue("Modified Doc of Root Suite: ", self.args.name, "yellow") if self.args.verbose_mode else None - self.suite[0]["doc"] = self.args.doc - - ############################################################################################################################# - - def _modify_root_suite_metadata(self): - if not self.args.metadata: - return - Logger().LogKeyValue("Modified Metadata of Root Suite: ", self.args.metadata, "yellow") if self.args.verbose_mode else None - formatted_metadata = "
".join([f"{k}: {v}" for k, v in self.args.metadata.items()]) - self.suite[0]["metadata"] = formatted_metadata + + # Modify name, doc & metadata via officially provided robot api + def _modify_root_suite_details(self, suite: TestSuite): + if self.args.name: + suite.configure(name=self.args.name) + if self.args.doc: + suite.configure(doc=self.args.doc) + if self.args.metadata: + suite.configure(metadata=self.args.metadata) + return suite ############################################################################################################################# diff --git a/src/testdoc/parser/testcaseparser.py b/src/testdoc/parser/testcaseparser.py index 1662d7d..1ce0c05 100644 --- a/src/testdoc/parser/testcaseparser.py +++ b/src/testdoc/parser/testcaseparser.py @@ -23,6 +23,7 @@ def parse_test(self, suite_info["tests"].append(test_info) return suite_info + # Consider tags via officially provided robot api def consider_tags(self, suite: TestSuite) -> TestSuite: if len(self.args.include) > 0: suite.configure(include_tags=self.args.include) diff --git a/src/testdoc/parser/testsuiteparser.py b/src/testdoc/parser/testsuiteparser.py index fe06638..606ca5a 100644 --- a/src/testdoc/parser/testsuiteparser.py +++ b/src/testdoc/parser/testsuiteparser.py @@ -2,6 +2,7 @@ from robot.api import SuiteVisitor, TestSuite from .testcaseparser import TestCaseParser +from .modifier.suitefilemodifier import SuiteFileModifier class RobotSuiteParser(SuiteVisitor): def __init__(self): @@ -23,7 +24,7 @@ def visit_suite(self, suite): "total_tests": 0, "tests": [], "sub_suites": [], - "metadata": None + "metadata": "
".join([f"{k}: {v}" for k, v in suite.metadata.items()]) if suite.metadata else None } # Parse Test Cases @@ -39,6 +40,7 @@ def visit_suite(self, suite): def parse_suite(self, suite_path): suite = TestSuite.from_file_system(suite_path) suite = TestCaseParser().consider_tags(suite) + suite = SuiteFileModifier()._modify_root_suite_details(suite) suite.visit(self) return self.suites @@ -65,4 +67,4 @@ def _is_directory(self, suite) -> bool: def _already_parsed(self, suite): existing_suite = next((s for s in self.suites if s["name"] == suite.name), None) if existing_suite: - return \ No newline at end of file + return