-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refacto: move rules context into a structured object (#491)
This PR is a following up of #481. It's mainly a code structure improvement which aims to improve readability, testing and maintainability: - create an object - move it from utils to profiles since it's only related to QDT profiles management - add methods to export as dict and JSON - add unit test - use it in documentation and GenericJob.filter_on_rules Next (spoiler alert): a CLI command to generate the rules context to make the rules writing more handy
- Loading branch information
Showing
6 changed files
with
209 additions
and
126 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
#! python3 # noqa: E265 | ||
|
||
""" | ||
Rules context. | ||
Author: Julien Moura (https://github.com/guts) | ||
""" | ||
|
||
|
||
# ############################################################################# | ||
# ########## Libraries ############# | ||
# ################################## | ||
|
||
# Standard library | ||
import json | ||
import logging | ||
import platform | ||
from datetime import date | ||
from getpass import getuser | ||
from sys import platform as opersys | ||
|
||
# package | ||
from qgis_deployment_toolbelt.utils.user_groups import ( | ||
get_user_domain_groups, | ||
get_user_local_groups, | ||
) | ||
|
||
# ############################################################################# | ||
# ########## Globals ############### | ||
# ################################## | ||
|
||
# logs | ||
logger = logging.getLogger(__name__) | ||
|
||
|
||
# ############################################################################# | ||
# ########## Functions ############# | ||
# ################################## | ||
|
||
|
||
class QdtRulesContext: | ||
pass | ||
|
||
@property | ||
def _context_date(self) -> dict: | ||
"""Returns a context dictionary with date informations that can be used in QDT | ||
various places: rules... | ||
Returns: | ||
dict: dict with current date informations | ||
""" | ||
today = date.today() | ||
return { | ||
"current_day": today.day, | ||
"current_weekday": today.weekday(), # monday = 0, sunday = 6 | ||
"current_month": today.month, | ||
"current_year": today.year, | ||
} | ||
|
||
@property | ||
def _context_environment(self) -> dict: | ||
"""Returns a dictionary containing some environment information (computer, network, | ||
platform) that can be used in QDT various places: rules... | ||
Returns: | ||
dict: dict with some environment metadata to use in rules. | ||
""" | ||
try: | ||
linux_distribution_name = f"{platform.freedesktop_os_release().get('NAME')}" | ||
linux_distribution_version = ( | ||
f"{platform.freedesktop_os_release().get('VERSION_ID')}" | ||
) | ||
except OSError as err: | ||
logger.debug( | ||
f"Unable to determine current Linux distribution. Trace: {err}." | ||
) | ||
linux_distribution_name = None | ||
linux_distribution_version = None | ||
|
||
return { | ||
"computer_network_name": platform.node(), | ||
"operating_system_code": opersys, | ||
"processor_architecture": platform.machine(), | ||
# custom Linux | ||
"linux_distribution_name": linux_distribution_name, | ||
"linux_distribution_version": linux_distribution_version, | ||
# custom Windows | ||
"windows_edition": platform.win32_edition(), | ||
} | ||
|
||
@property | ||
def _context_user(self) -> dict: | ||
"""Returns a dictionary containing user informations that can be used in QDT Rules | ||
context. | ||
Returns: | ||
dict: dict user information. | ||
""" | ||
return { | ||
"name": getuser(), | ||
"groups_local": get_user_local_groups(), | ||
"groups_domain": get_user_domain_groups(), | ||
} | ||
|
||
# -- EXPORT | ||
def to_dict(self) -> dict: | ||
"""Convert object into dictionary. | ||
Returns: | ||
dict: object as dictionary | ||
""" | ||
result = {} | ||
for attr in dir(self): | ||
if isinstance( | ||
getattr(self.__class__, attr, None), property | ||
) and attr.startswith("_context_"): | ||
result[attr.removeprefix("_context_")] = getattr(self, attr) | ||
return result | ||
|
||
def to_json(self, **kwargs) -> str: | ||
"""Supersedes json.dumps using the dictionary returned by to_dict(). | ||
kwargs are passed to json.dumps. | ||
Returns: | ||
str: object serialized as JSON string | ||
Example: | ||
.. code-block:: python | ||
from pathlib import Path | ||
rules_context = QdtRulesContext() | ||
# write into the file passing extra parameters to json.dumps | ||
with Path("qdt_rules_context.json").open("w", encoding="UTF8") as wf: | ||
wf.write(rules_context.to_json(indent=4, sort_keys=True)) | ||
""" | ||
obj_as_dict = self.to_dict() | ||
|
||
return json.dumps(obj_as_dict, **kwargs) |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#! python3 # noqa E265 | ||
|
||
""" | ||
Usage from the repo root folder: | ||
.. code-block:: bash | ||
# for whole tests | ||
python -m unittest tests.test_rules_context | ||
# for specific test | ||
python -m unittest tests.test_rules_context.testQdtRulesContext.test_rules_export_to_json | ||
""" | ||
|
||
|
||
# standard library | ||
import json | ||
import tempfile | ||
import unittest | ||
from pathlib import Path | ||
|
||
# project | ||
from qgis_deployment_toolbelt.profiles.rules_context import QdtRulesContext | ||
|
||
# ############################################################################ | ||
# ########## Classes ############# | ||
# ################################ | ||
|
||
|
||
class TestQdtRulesContext(unittest.TestCase): | ||
"""Test QDT rules context.""" | ||
|
||
def test_rules_export_to_json(self): | ||
"""Test export to JSON.""" | ||
|
||
rules_context = QdtRulesContext() | ||
|
||
with tempfile.TemporaryDirectory( | ||
prefix="qdt_test_rules_context" | ||
) as tmp_dir_name: | ||
context_json_path = Path(tmp_dir_name).joinpath("qdt_rules_context.json") | ||
|
||
# write into the file passing extra parameters to json.dumps | ||
with context_json_path.open("w", encoding="UTF8") as wf: | ||
wf.write(rules_context.to_json(indent=4, sort_keys=True)) | ||
|
||
# test reading | ||
with context_json_path.open(mode="r", encoding="utf8") as in_json: | ||
context_data = json.load(in_json) | ||
|
||
self.assertIsInstance(context_data, dict) | ||
self.assertIn("date", context_data) | ||
self.assertIn("environment", context_data) | ||
self.assertIn("user", context_data) | ||
|
||
|
||
# ############################################################################ | ||
# ####### Stand-alone run ######## | ||
# ################################ | ||
if __name__ == "__main__": | ||
unittest.main() |