Skip to content

Commit

Permalink
Introduction of a way to provide a configuration file and folder from…
Browse files Browse the repository at this point in the history
… the CLI. (#380)

* Introduction of a way to provide a configuration file from the CLI.

This patch fixes #377.

Contributors:
  * @spirillen

* cleanup: make downloaders less dependent from PyFunceble.storage.

* cleanup: allow overwrite of config directory.

* cleanup: do not declare a var if only used once.

* Introduction of a way provide a custom configuration folder.

This patch fixes #377.

Contributors:
  * @spirillen

* fix issue when reloading configuration.

Indeed, before this patch, any custom configuration may have been
destroyed when config_file and config_dir has been changed.

* Add missing unit tests.

* Fix some loopholes in unit tests.
  • Loading branch information
funilrys authored Oct 3, 2024
1 parent 4bbf6ab commit ee4d076
Show file tree
Hide file tree
Showing 36 changed files with 795 additions and 194 deletions.
22 changes: 22 additions & 0 deletions PyFunceble/cli/entry_points/pyfunceble/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1197,6 +1197,28 @@ def get_default_group_data() -> List[Tuple[List[str], dict]]:
"version": "%(prog)s " + PyFunceble.storage.PROJECT_VERSION,
},
),
(
[
"--config-file",
],
{
"dest": "config_file",
"type": str,
"help": "Sets the configuration file to use. It can be a\n"
"local or remote file. Please note that this configuration can be\n"
"overwritten by your overwrite configuration file.",
},
),
(
[
"--config-dir",
],
{
"dest": "config_dir",
"type": os.path.realpath,
"help": "Sets the configuration directory to use.",
},
),
]


Expand Down
3 changes: 1 addition & 2 deletions PyFunceble/cli/filesystem/dir_structure/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
import importlib_resources as package_resources


import PyFunceble.storage
from PyFunceble.cli.filesystem.cleanup import FilesystemCleanup
from PyFunceble.cli.filesystem.dir_base import FilesystemDirBase

Expand All @@ -78,7 +77,7 @@ def __init__(
) -> None:
with package_resources.path(
"PyFunceble.data.infrastructure",
PyFunceble.storage.DISTRIBUTED_DIR_STRUCTURE_FILENAME,
"dir_structure_production.json",
) as file_path:
self.std_source_file = str(file_path)

Expand Down
48 changes: 47 additions & 1 deletion PyFunceble/cli/migrators/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@

from sqlalchemy.orm import Session

import PyFunceble.storage
from PyFunceble.cli.continuous_integration.base import ContinuousIntegrationBase


Expand All @@ -66,18 +67,63 @@ class MigratorBase:
continuous_integration: Optional[ContinuousIntegrationBase] = None
db_session: Optional[Session] = None

_config_dir: Optional[str] = None
print_action_to_stdout: bool = False

def __init__(self, print_action_to_stdout: bool = False) -> None:
def __init__(
self, print_action_to_stdout: bool = False, *, config_dir: Optional[str] = None
) -> None:
self.print_action_to_stdout = print_action_to_stdout

if config_dir is not None:
self._config_dir = config_dir
else:
self._config_dir = PyFunceble.storage.CONFIG_DIRECTORY

self.__post_init__()

def __post_init__(self) -> None:
"""
A method to be called (automatically) after the __init__ execution.
"""

@property
def config_dir(self) -> Optional[str]:
"""
Provides the current state of the :code:`_config_dir` attribute.
"""

return self._config_dir

@config_dir.setter
def config_dir(self, value: str) -> None:
"""
Sets the configuration directory.
:param value:
The value to set.
:raise TypeError:
When value is not a :py:class:`str`.
"""

if not isinstance(value, str):
raise TypeError(f"<value> should be {str}, {type(value)} given.")

self._config_dir = value

def set_config_dir(self, value: str) -> "MigratorBase":
"""
Sets the configuration directory.
:param value:
The value to set.
"""

self.config_dir = value

return self

def start(self) -> "MigratorBase":
"""
Starts the migration.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class InactiveDatasetDeleteSourceColumnMigrator(CSVFileMigratorBase):

def __post_init__(self) -> None:
self.source_file = os.path.join(
PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.cli.storage.INACTIVE_DB_FILE
self.config_dir, PyFunceble.cli.storage.INACTIVE_DB_FILE
)

return super().__post_init__()
2 changes: 1 addition & 1 deletion PyFunceble/cli/migrators/csv_file/whois_registrar_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class WhoisDatasetAddRegistrarColumnMigrator(CSVFileMigratorBase):

def __post_init__(self) -> None:
self.source_file = os.path.join(
PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.cli.storage.WHOIS_DB_FILE
self.config_dir, PyFunceble.cli.storage.WHOIS_DB_FILE
)

return super().__post_init__()
2 changes: 1 addition & 1 deletion PyFunceble/cli/migrators/file_cleanup/hashes_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class HashesFileCleanupMigrator(FileClenupMigratorBase):

def __post_init__(self) -> None:
self.source_file = os.path.join(
PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.cli.storage.HASHES_FILENAME
self.config_dir, PyFunceble.cli.storage.HASHES_FILENAME
)

return super().__post_init__()
2 changes: 1 addition & 1 deletion PyFunceble/cli/migrators/file_cleanup/mining_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class MiningFileCleanupMigrator(FileClenupMigratorBase):

def __post_init__(self) -> None:
self.source_file = os.path.join(
PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.cli.storage.MINING_OLD_FILE
self.config_dir, PyFunceble.cli.storage.MINING_OLD_FILE
)

return super().__post_init__()
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class ProductionConfigFileCleanupMigrator(FileClenupMigratorBase):

def __post_init__(self) -> None:
self.source_file = os.path.join(
PyFunceble.storage.CONFIG_DIRECTORY,
self.config_dir,
PyFunceble.storage.DISTRIBUTED_CONFIGURATION_FILENAME,
)

Expand Down
2 changes: 1 addition & 1 deletion PyFunceble/cli/migrators/json2csv/inactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class InactiveJSON2CSVMigrator(JSON2CSVMigratorBase):

def __post_init__(self) -> None:
self.source_file = os.path.join(
PyFunceble.storage.CONFIG_DIRECTORY,
self.config_dir,
PyFunceble.cli.storage.INACTIVE_DB_OLD_FILE,
)

Expand Down
2 changes: 1 addition & 1 deletion PyFunceble/cli/migrators/json2csv/whois.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class WhoisJSON2CSVMigrator(JSON2CSVMigratorBase):

def __post_init__(self) -> None:
self.source_file = os.path.join(
PyFunceble.storage.CONFIG_DIRECTORY,
self.config_dir,
PyFunceble.cli.storage.WHOIS_DB_OLD_FILE,
)

Expand Down
93 changes: 67 additions & 26 deletions PyFunceble/cli/scripts/production.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,6 @@ class ProductionPrep:
you should run this only if your are developing PyFunceble.
"""

VERSION_FILE_PATH: str = os.path.join(
PyFunceble.storage.CONFIG_DIRECTORY,
PyFunceble.cli.storage.DISTRIBUTED_VERSION_FILENAME,
)
AVAILABLE_BRANCHES: List[str] = ["dev", "master"]

regex_helper: RegexHelper = RegexHelper()
Expand All @@ -101,15 +97,23 @@ class ProductionPrep:
"""

_branch: Optional[str] = None
_config_dir: Optional[str] = None

previous_version: Optional[str] = None
"""
Provides the previous version (from :code:`version_file_content`)
"""

def __init__(self, branch: Optional[str] = None) -> None:
def __init__(
self, branch: Optional[str] = None, *, config_dir: Optional[str] = None
) -> None:
if config_dir is not None:
self.config_dir = config_dir
else:
self.config_dir = PyFunceble.storage.CONFIG_DIRECTORY

self.version_file_content = self.dict_helper.from_yaml_file(
self.VERSION_FILE_PATH
self.version_file_path
)

self.previous_version = copy.deepcopy(
Expand Down Expand Up @@ -138,6 +142,54 @@ def wrapper(self, *args, **kwargs):

return wrapper

@property
def config_dir(self) -> Optional[str]:
"""
Provides the current state of the :code:`_config_dir` attribute.
"""

return self._config_dir

@config_dir.setter
def config_dir(self, value: str) -> None:
"""
Sets the configuration directory.
:param value:
The value to set.
:raise TypeError:
When value is not a :py:class:`str`.
"""

if not isinstance(value, str):
raise TypeError(f"<value> should be {str}, {type(value)} given.")

self._config_dir = value

def set_config_dir(self, value: str) -> "ProductionPrep":
"""
Sets the configuration directory.
:param value:
The value to set.
"""

self.config_dir = value

return self

@property
def version_file_path(self) -> str:
"""
Provides the path to the version file.
"""

return os.path.join(
self.config_dir,
PyFunceble.cli.storage.DISTRIBUTED_VERSION_FILENAME,
)

@property
def branch(self) -> Optional[str]:
"""
Expand Down Expand Up @@ -270,8 +322,7 @@ def update_urls(self, file: str) -> "ProductionPrep":

return self

@staticmethod
def update_code_format() -> "ProductionPrep":
def update_code_format(self) -> "ProductionPrep":
"""
Updates the format of the source code using black.
"""
Expand Down Expand Up @@ -304,16 +355,14 @@ def format_file(file: str, isortconfig: isort.settings.Config) -> None:
isort_config = isort.settings.Config(settings_file="setup.cfg")

files = [
os.path.join(PyFunceble.storage.CONFIG_DIRECTORY, "setup.py"),
os.path.join(self.config_dir, "setup.py"),
]

for file in files:
format_file(file, isort_config)

for root, _, files in os.walk(
os.path.join(
PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.PROJECT_NAME
)
os.path.join(self.config_dir, PyFunceble.storage.PROJECT_NAME)
):
if "__pycache__" in root:
continue
Expand All @@ -324,9 +373,7 @@ def format_file(file: str, isortconfig: isort.settings.Config) -> None:

format_file(os.path.join(root, file), isort_config)

for root, _, files in os.walk(
os.path.join(PyFunceble.storage.CONFIG_DIRECTORY, "tests")
):
for root, _, files in os.walk(os.path.join(self.config_dir, "tests")):
if "__pycache__" in root:
continue

Expand All @@ -346,12 +393,10 @@ def update_code_urls(self) -> "ProductionPrep":
".keep",
]

self.update_urls(os.path.join(PyFunceble.storage.CONFIG_DIRECTORY, "setup.py"))
self.update_urls(os.path.join(self.config_dir, "setup.py"))

for root, _, files in os.walk(
os.path.join(
PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.PROJECT_NAME
)
os.path.join(self.config_dir, PyFunceble.storage.PROJECT_NAME)
):
if "__pycache__" in root:
continue
Expand All @@ -362,9 +407,7 @@ def update_code_urls(self) -> "ProductionPrep":

self.update_urls(os.path.join(root, file))

for root, _, files in os.walk(
os.path.join(PyFunceble.storage.CONFIG_DIRECTORY, "tests")
):
for root, _, files in os.walk(os.path.join(self.config_dir, "tests")):
if "__pycache__" in root:
continue

Expand Down Expand Up @@ -409,9 +452,7 @@ def update_setup_py(self) -> "ProductionPrep":
),
]

self.file_helper.set_path(
os.path.join(PyFunceble.storage.CONFIG_DIRECTORY, "setup.py")
)
self.file_helper.set_path(os.path.join(self.config_dir, "setup.py"))

if not self.file_helper.exists():
raise FileNotFoundError(self.file_helper.path)
Expand Down Expand Up @@ -453,7 +494,7 @@ def update_version_file(self) -> "ProductionPrep":
)

self.dict_helper.set_subject(self.version_file_content).to_yaml_file(
self.VERSION_FILE_PATH
self.version_file_path
)

PyFunceble.facility.Logger.info(
Expand Down
Loading

0 comments on commit ee4d076

Please sign in to comment.