Source code for repo_helper.core

#!/usr/bin/env python
#
#  core.py
"""
Core functionality of ``repo_helper``.
"""
#
#  Copyright © 2020 Dominic Davis-Foster <dominic@davis-foster.co.uk>
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#  GNU Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#

# stdlib
import os.path
from typing import List, Tuple, Type

# 3rd party
import jinja2
from domdf_python_tools.import_tools import discover
from domdf_python_tools.paths import PathPlus, traverse_to_file
from domdf_python_tools.typing import PathLike
from domdf_python_tools.utils import enquote_value

# this package
import repo_helper.files
from repo_helper.configuration import parse_yaml
from repo_helper.files import Management, is_registered, management
from repo_helper.files.docs import copy_docs_styling
from repo_helper.files.linting import code_only_warning, lint_warn_list
from repo_helper.files.testing import make_formate_toml, make_isort
from repo_helper.templates import Environment, init_repo_template_dir, template_dir
from repo_helper.utils import brace, discover_entry_points

__all__ = [
		"RepoHelper",
		"import_registered_functions",
		]


[docs]def import_registered_functions() -> List[Type]: """ Returns a list of all registered functions. """ local_functions = discover(repo_helper.files, is_registered) third_party_commands = discover_entry_points("repo_helper.command", is_registered) return [*local_functions, *third_party_commands]
[docs]class RepoHelper: """ Repo Helper: Manage configuration files with ease. :param target_repo: The path to the root of the repository to manage files for. :param managed_message: Message placed at the top of files to indicate that they are managed by ``repo_helper``. """ #: The target repository target_repo: PathPlus #: Provides the templates and stores the configuration. templates: Environment #: List of functions to manage files. files: Management def __init__( self, target_repo: PathLike, managed_message: str = "This file is managed by 'repo_helper'. Don't edit it directly." ): import_registered_functions() # Walk up the tree until a "repo_helper.yml" or "git_helper.yml" (old name) file is found. self.target_repo = traverse_to_file(PathPlus(target_repo), "repo_helper.yml", "git_helper.yml") self.templates = Environment( # nosec: B701 loader=jinja2.FileSystemLoader(str(template_dir)), undefined=jinja2.StrictUndefined, ) self.templates.globals["managed_message"] = managed_message self.templates.globals["brace"] = brace # isort and formate.toml must always run last self.files = management + [(make_isort, "isort", [])] self.files = management + [(make_formate_toml, "formate", [])] @property def managed_message(self) -> str: """ Message placed at the top of files to indicate that they are managed by ``repo_helper``. """ return self.templates.globals["managed_message"] @managed_message.setter def managed_message(self, value: str) -> None: """ Message placed at the top of files to indicate that they are managed by ``repo_helper``. """ self.templates.globals["managed_message"] = str(value)
[docs] def load_settings(self, allow_unknown_keys: bool = False) -> None: """ Load settings from the ``repo_helper.yml`` file in the repository. :param allow_unknown_keys: Whether unknown keys should be allowed in the configuration file. .. versionchanged:: 2021.2.18 * This method is no longer called automatically when instantiating the :class:`~.RepoHelper` class. * Added the ``allow_unknown_keys`` argument. """ config_vars = parse_yaml(self.target_repo, allow_unknown_keys=allow_unknown_keys) self.templates.globals.update(config_vars) self.templates.globals["lint_warn_list"] = lint_warn_list self.templates.globals["code_only_warning"] = code_only_warning self.templates.globals["enquote_value"] = enquote_value self.templates.globals["len"] = len self.templates.globals["join_path"] = os.path.join
@property def exclude_files(self) -> Tuple[str, ...]: """ A tuple of excluded files that should **NOT** be managed by Git Helper. """ return tuple(self.templates.globals["exclude_files"]) @property def repo_name(self) -> str: """ The name of the repository being managed. """ return self.templates.globals["repo_name"]
[docs] def run(self) -> List[str]: """ Run Git Helper for the repository and update all managed files. :return: A list of files managed by Git Helper, regardless of whether they were added, removed or modified. """ all_managed_files = [] if ( self.templates.globals["enable_docs"] and not (self.target_repo / self.templates.globals["docs_dir"]).exists() ): # this package from repo_helper.cli.commands.init import enable_docs init_repo_templates = Environment( # nosec: B701 loader=jinja2.FileSystemLoader(str(init_repo_template_dir)), undefined=jinja2.StrictUndefined, ) init_repo_templates.globals.update(self.templates.globals) all_managed_files.extend(enable_docs(self.target_repo, self.templates, init_repo_templates)) if not self.templates.globals["preserve_custom_theme"] and self.templates.globals["enable_docs"]: all_managed_files.extend(copy_docs_styling(self.target_repo, self.templates)) # TODO: this isn't respecting "enable_docs" for function_, exclude_name, other_requirements in self.files: if exclude_name not in self.exclude_files and all([ self.templates.globals[req] for req in other_requirements ]): # print(f"{function_.__name__}{'.'*(75-len(function_.__name__))}", end='') # sys.stdout.flush() output_filenames = function_(self.target_repo, self.templates) # print(f"{Back.GREEN('Done')}") for filename in output_filenames: all_managed_files.append(str(filename)) all_managed_files.append("repo_helper.yml") all_managed_files.append("git_helper.yml") return sorted(set(all_managed_files))
# Legacy alias GitHelper = RepoHelper