rkt-config-lib 1.4.0__tar.gz → 2.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rkt_config_lib-2.0.3/PKG-INFO +36 -0
- rkt_config_lib-2.0.3/README.md +22 -0
- rkt_config_lib-2.0.3/pyproject.toml +26 -0
- rkt_config_lib-2.0.3/src/config/__init__.py +1 -0
- rkt_config_lib-2.0.3/src/config/config.py +59 -0
- rkt_config_lib-2.0.3/src/rkt_config_lib.egg-info/PKG-INFO +36 -0
- rkt_config_lib-2.0.3/src/rkt_config_lib.egg-info/SOURCES.txt +10 -0
- {rkt_config_lib-1.4.0/rkt_lib_toolkit → rkt_config_lib-2.0.3/src}/rkt_config_lib.egg-info/requires.txt +1 -1
- rkt_config_lib-2.0.3/src/rkt_config_lib.egg-info/top_level.txt +1 -0
- rkt_config_lib-2.0.3/tests/test_config.py +66 -0
- rkt_config_lib-1.4.0/LICENSE +0 -21
- rkt_config_lib-1.4.0/PKG-INFO +0 -104
- rkt_config_lib-1.4.0/rkt_lib_toolkit/rkt_config_lib/Config.py +0 -53
- rkt_config_lib-1.4.0/rkt_lib_toolkit/rkt_config_lib/__init__.py +0 -1
- rkt_config_lib-1.4.0/rkt_lib_toolkit/rkt_config_lib.egg-info/PKG-INFO +0 -104
- rkt_config_lib-1.4.0/rkt_lib_toolkit/rkt_config_lib.egg-info/SOURCES.txt +0 -13
- rkt_config_lib-1.4.0/rkt_lib_toolkit/rkt_config_lib.egg-info/top_level.txt +0 -1
- rkt_config_lib-1.4.0/tests/test_AI.py +0 -189
- rkt_config_lib-1.4.0/tests/test_Config.py +0 -52
- rkt_config_lib-1.4.0/tests/test_Logger.py +0 -53
- rkt_config_lib-1.4.0/tests/test_Tool.py +0 -45
- {rkt_config_lib-1.4.0 → rkt_config_lib-2.0.3}/setup.cfg +0 -0
- {rkt_config_lib-1.4.0/rkt_lib_toolkit → rkt_config_lib-2.0.3/src}/rkt_config_lib.egg-info/dependency_links.txt +0 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rkt_config_lib
|
|
3
|
+
Version: 2.0.3
|
|
4
|
+
Summary: RootKit custom PyYaml Lib
|
|
5
|
+
Author-email: RootKit <rootkit@rootkit-lab.org>
|
|
6
|
+
License: MIT
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.7
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: PyYaml>=6.0.1
|
|
12
|
+
Requires-Dist: rkt_tool_lib
|
|
13
|
+
Requires-Dist: rkt_logger_lib
|
|
14
|
+
|
|
15
|
+
# rkt_config_lib
|
|
16
|
+
|
|
17
|
+
Centralized Configuration Management wrapper around PyYaml.
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
- **Singleton Pattern**: Ensures a single configuration state across your application.
|
|
21
|
+
- **Auto-Loading**: Automatically scans and loads all YAML files in a `config/` directory.
|
|
22
|
+
- **Safe Loading**: Uses `yaml.safe_load` by default to prevent arbitrary code execution vulnerabilities.
|
|
23
|
+
- **Integrated Logging**: Logs loading operations via `rkt_logger_lib`.
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from config import Config
|
|
29
|
+
|
|
30
|
+
conf = Config()
|
|
31
|
+
# Loads all .yml/.yaml files from ./config/ directory
|
|
32
|
+
conf.get_data()
|
|
33
|
+
|
|
34
|
+
# Access data (filename becomes the key)
|
|
35
|
+
my_settings = conf.data.get("settings")
|
|
36
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# rkt_config_lib
|
|
2
|
+
|
|
3
|
+
Centralized Configuration Management wrapper around PyYaml.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
- **Singleton Pattern**: Ensures a single configuration state across your application.
|
|
7
|
+
- **Auto-Loading**: Automatically scans and loads all YAML files in a `config/` directory.
|
|
8
|
+
- **Safe Loading**: Uses `yaml.safe_load` by default to prevent arbitrary code execution vulnerabilities.
|
|
9
|
+
- **Integrated Logging**: Logs loading operations via `rkt_logger_lib`.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from config import Config
|
|
15
|
+
|
|
16
|
+
conf = Config()
|
|
17
|
+
# Loads all .yml/.yaml files from ./config/ directory
|
|
18
|
+
conf.get_data()
|
|
19
|
+
|
|
20
|
+
# Access data (filename becomes the key)
|
|
21
|
+
my_settings = conf.data.get("settings")
|
|
22
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "rkt_config_lib"
|
|
7
|
+
version = "2.0.3"
|
|
8
|
+
description = "RootKit custom PyYaml Lib"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [
|
|
11
|
+
{ name="RootKit", email="rootkit@rootkit-lab.org" },
|
|
12
|
+
]
|
|
13
|
+
license = { text = "MIT" }
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Operating System :: OS Independent",
|
|
17
|
+
]
|
|
18
|
+
requires-python = ">=3.7"
|
|
19
|
+
dependencies = [
|
|
20
|
+
"PyYaml>=6.0.1",
|
|
21
|
+
"rkt_tool_lib",
|
|
22
|
+
"rkt_logger_lib",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[tool.setuptools.packages.find]
|
|
26
|
+
where = ["src"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .config import Config
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
import yaml
|
|
5
|
+
|
|
6
|
+
from logger import Logger
|
|
7
|
+
from tool import Singleton, Tool
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Config(metaclass=Singleton): # type: ignore[metaclass]
|
|
11
|
+
"""
|
|
12
|
+
Configuration manager wrapping PyYaml.
|
|
13
|
+
|
|
14
|
+
This class handles the loading of YAML configuration files from a specific directory.
|
|
15
|
+
It implements the Singleton pattern to ensure centralized configuration management.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
__slots__ = ["_me", "_logger", "_tool", "_skills_file", "data"]
|
|
19
|
+
|
|
20
|
+
def __init__(self) -> None:
|
|
21
|
+
self._me = self.__class__.__name__
|
|
22
|
+
self._logger = Logger(caller_class=self._me)
|
|
23
|
+
self._logger.set_logger(caller_class=self._me)
|
|
24
|
+
self._tool = Tool()
|
|
25
|
+
self.data: dict[str, Any] = {}
|
|
26
|
+
|
|
27
|
+
def get_data(self, needed_file: str = "", _config_dir: str = "config", create_if_not_exist: bool = False) -> None:
|
|
28
|
+
"""
|
|
29
|
+
Load configuration files from the config directory.
|
|
30
|
+
|
|
31
|
+
It scans the directory for YAML files and loads them into `self.data`.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
needed_file (str, optional): A specific file to load. If empty, loads all YAML files in the directory.
|
|
35
|
+
Defaults to "".
|
|
36
|
+
_config_dir (str, optional): Name of the configuration directory. Defaults to "config".
|
|
37
|
+
create_if_not_exist (bool, optional): Create the config directory if it doesn't exist. Defaults to False.
|
|
38
|
+
"""
|
|
39
|
+
config_dir = self._tool.get_dir(_config_dir)
|
|
40
|
+
|
|
41
|
+
if (not config_dir or not os.path.exists(config_dir)) and create_if_not_exist:
|
|
42
|
+
os.makedirs(_config_dir, exist_ok=True)
|
|
43
|
+
config_dir = self._tool.formatted_from_os(os.path.abspath(_config_dir))
|
|
44
|
+
|
|
45
|
+
if needed_file:
|
|
46
|
+
filename = os.path.basename(needed_file).split(".")[0]
|
|
47
|
+
with open(f"{config_dir}{needed_file}", encoding="utf8") as nf:
|
|
48
|
+
self._logger.add(level="info", caller=self._me, message=f"Load '{filename}' file ...")
|
|
49
|
+
self.data[filename] = yaml.safe_load(nf)
|
|
50
|
+
else:
|
|
51
|
+
for file in os.listdir(config_dir):
|
|
52
|
+
try:
|
|
53
|
+
(filename, ext) = os.path.basename(file).split(".")
|
|
54
|
+
except ValueError:
|
|
55
|
+
continue
|
|
56
|
+
if ext in ["yml", "yaml"] and filename not in self.data.keys():
|
|
57
|
+
with open(f"{config_dir}{file}", encoding="utf8") as f:
|
|
58
|
+
self._logger.add(level="info", caller=self._me, message=f"Load '{filename}' file ...")
|
|
59
|
+
self.data[filename] = yaml.safe_load(f)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rkt_config_lib
|
|
3
|
+
Version: 2.0.3
|
|
4
|
+
Summary: RootKit custom PyYaml Lib
|
|
5
|
+
Author-email: RootKit <rootkit@rootkit-lab.org>
|
|
6
|
+
License: MIT
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.7
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: PyYaml>=6.0.1
|
|
12
|
+
Requires-Dist: rkt_tool_lib
|
|
13
|
+
Requires-Dist: rkt_logger_lib
|
|
14
|
+
|
|
15
|
+
# rkt_config_lib
|
|
16
|
+
|
|
17
|
+
Centralized Configuration Management wrapper around PyYaml.
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
- **Singleton Pattern**: Ensures a single configuration state across your application.
|
|
21
|
+
- **Auto-Loading**: Automatically scans and loads all YAML files in a `config/` directory.
|
|
22
|
+
- **Safe Loading**: Uses `yaml.safe_load` by default to prevent arbitrary code execution vulnerabilities.
|
|
23
|
+
- **Integrated Logging**: Logs loading operations via `rkt_logger_lib`.
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from config import Config
|
|
29
|
+
|
|
30
|
+
conf = Config()
|
|
31
|
+
# Loads all .yml/.yaml files from ./config/ directory
|
|
32
|
+
conf.get_data()
|
|
33
|
+
|
|
34
|
+
# Access data (filename becomes the key)
|
|
35
|
+
my_settings = conf.data.get("settings")
|
|
36
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/config/__init__.py
|
|
4
|
+
src/config/config.py
|
|
5
|
+
src/rkt_config_lib.egg-info/PKG-INFO
|
|
6
|
+
src/rkt_config_lib.egg-info/SOURCES.txt
|
|
7
|
+
src/rkt_config_lib.egg-info/dependency_links.txt
|
|
8
|
+
src/rkt_config_lib.egg-info/requires.txt
|
|
9
|
+
src/rkt_config_lib.egg-info/top_level.txt
|
|
10
|
+
tests/test_config.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
config
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
from unittest import TestCase
|
|
5
|
+
from unittest.mock import patch
|
|
6
|
+
|
|
7
|
+
from yaml.scanner import ScannerError
|
|
8
|
+
|
|
9
|
+
from config import Config
|
|
10
|
+
from tool import Tool
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TestConfig(TestCase):
|
|
14
|
+
def get_dir_side_effect(self, folder: str, root: "Optional[str]" = None) -> "Optional[str]":
|
|
15
|
+
if folder in ["valid_config", "dummy_config", "missing_folder"]:
|
|
16
|
+
return str(Tool.formatted_from_os(os.path.join(os.path.dirname(__file__), "resources", folder)))
|
|
17
|
+
# Use the original method from the class, passing a new instance or self if relevant
|
|
18
|
+
# Accessing the original method requires unpatching or saving it.
|
|
19
|
+
# Simpler: just return None or duplicate logic for now since we don't expect other calls.
|
|
20
|
+
return None
|
|
21
|
+
|
|
22
|
+
@patch("tool.Tool.get_dir")
|
|
23
|
+
def test_get_data(self, mock_get_dir: "Any") -> None:
|
|
24
|
+
mock_get_dir.side_effect = self.get_dir_side_effect
|
|
25
|
+
config = Config()
|
|
26
|
+
config.data.clear()
|
|
27
|
+
config.get_data(_config_dir="valid_config")
|
|
28
|
+
|
|
29
|
+
assert config.data == {
|
|
30
|
+
"valid_config": {
|
|
31
|
+
"key1": {"sub_key": "value", "sub_key2": "value", "sub_key3": "value", "sub_key4": "value"}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@patch("tool.Tool.get_dir")
|
|
36
|
+
def test_get_data_dummy_data(self, mock_get_dir: "Any") -> None:
|
|
37
|
+
mock_get_dir.side_effect = self.get_dir_side_effect
|
|
38
|
+
config = Config()
|
|
39
|
+
config.data.clear()
|
|
40
|
+
try:
|
|
41
|
+
config.get_data(_config_dir="dummy_config")
|
|
42
|
+
self.fail("ScannerError expected here!")
|
|
43
|
+
except ScannerError:
|
|
44
|
+
assert config.data == {}
|
|
45
|
+
|
|
46
|
+
@patch("tool.Tool.get_dir")
|
|
47
|
+
def test_get_data_dummy_folder(self, mock_get_dir: "Any") -> None:
|
|
48
|
+
mock_get_dir.side_effect = self.get_dir_side_effect
|
|
49
|
+
config = Config()
|
|
50
|
+
config.data.clear()
|
|
51
|
+
config.get_data(_config_dir="missing_folder", create_if_not_exist=True)
|
|
52
|
+
assert os.path.exists("missing_folder")
|
|
53
|
+
shutil.rmtree("missing_folder")
|
|
54
|
+
|
|
55
|
+
@patch("tool.Tool.get_dir")
|
|
56
|
+
def test_get_data_from_specific_file(self, mock_get_dir: "Any") -> None:
|
|
57
|
+
mock_get_dir.side_effect = self.get_dir_side_effect
|
|
58
|
+
config = Config()
|
|
59
|
+
config.data.clear()
|
|
60
|
+
config.get_data(_config_dir="valid_config", needed_file="valid_config.yml")
|
|
61
|
+
|
|
62
|
+
assert config.data == {
|
|
63
|
+
"valid_config": {
|
|
64
|
+
"key1": {"sub_key": "value", "sub_key2": "value", "sub_key3": "value", "sub_key4": "value"}
|
|
65
|
+
}
|
|
66
|
+
}
|
rkt_config_lib-1.4.0/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
The MIT License (MIT)
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2016 Dabo Ross
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
rkt_config_lib-1.4.0/PKG-INFO
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.2
|
|
2
|
-
Name: rkt_config_lib
|
|
3
|
-
Version: 1.4.0
|
|
4
|
-
Summary: RootKit custom PyYaml Lib
|
|
5
|
-
Author: RootKit
|
|
6
|
-
Author-email: rootkit@rootkit-lab.org
|
|
7
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
8
|
-
Classifier: Intended Audience :: Developers
|
|
9
|
-
Classifier: Intended Audience :: End Users/Desktop
|
|
10
|
-
Classifier: Intended Audience :: Information Technology
|
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
-
Classifier: Natural Language :: English
|
|
13
|
-
Classifier: Natural Language :: French
|
|
14
|
-
Classifier: Operating System :: OS Independent
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
16
|
-
Classifier: Topic :: Utilities
|
|
17
|
-
Requires-Python: >=3.7
|
|
18
|
-
Description-Content-Type: text/markdown
|
|
19
|
-
License-File: LICENSE
|
|
20
|
-
Requires-Dist: PyYaml
|
|
21
|
-
Requires-Dist: rkt_tool_lib
|
|
22
|
-
Requires-Dist: rkt_logger_lib
|
|
23
|
-
Dynamic: author
|
|
24
|
-
Dynamic: author-email
|
|
25
|
-
Dynamic: classifier
|
|
26
|
-
Dynamic: description
|
|
27
|
-
Dynamic: description-content-type
|
|
28
|
-
Dynamic: requires-dist
|
|
29
|
-
Dynamic: requires-python
|
|
30
|
-
Dynamic: summary
|
|
31
|
-
|
|
32
|
-
# rkt_config_lib - Python library
|
|
33
|
-
|
|
34
|
-

|
|
35
|
-
|
|
36
|
-

|
|
37
|
-

|
|
38
|
-

|
|
39
|
-

|
|
40
|
-

|
|
41
|
-

|
|
42
|
-
|
|
43
|
-
This Python library is based only on built-in Python libraries and one (1) non-build-in library : [PyYaml](https://pypi.org/project/PyYAML/)
|
|
44
|
-
|
|
45
|
-
##### Python Version 3.7.2
|
|
46
|
-
##### PyYaml Version 5.4.1 (Released Jan 20, 2021)
|
|
47
|
-
|
|
48
|
-
----
|
|
49
|
-
|
|
50
|
-
## What is Python?
|
|
51
|
-
Python is an interpreted high-level general-purpose programming language. Python's design philosophy emphasizes code readability with its notable use of significant indentation. Its language constructs as well as its object-oriented approach aim to help programmers write clear, logical code for small and large-scale projects.
|
|
52
|
-
|
|
53
|
-
[source](https://en.wikipedia.org/wiki/Python_(programming_language))
|
|
54
|
-
## What is PyYaml?
|
|
55
|
-
YAML is a data serialization format designed for human readability and interaction with scripting languages. PyYAML is a YAML parser and emitter for Python.
|
|
56
|
-
|
|
57
|
-
PyYAML features a complete YAML 1.1 parser, Unicode support, pickle support, capable extension API, and sensible error messages. PyYAML supports standard YAML tags and provides Python-specific tags that allow to represent an arbitrary Python object.
|
|
58
|
-
|
|
59
|
-
PyYAML is applicable for a broad range of tasks from complex configuration files to object serialization and persistence.
|
|
60
|
-
|
|
61
|
-
[source](https://pypi.org/project/PyYAML/)
|
|
62
|
-
## Libraries
|
|
63
|
-
* Config: overlay of PyYaml library (read-only), use Tool and Logger library (rkt_tool_lib, rkt_logger_lib)
|
|
64
|
-
|
|
65
|
-
## Use it
|
|
66
|
-
### Install
|
|
67
|
-
```bash
|
|
68
|
-
(venv) my_project> pip install rkt_config_lib [--index-url https://gitlab.tprc.ovh/api/v4/groups/python/-/packages/pypi]
|
|
69
|
-
```
|
|
70
|
-
### Example
|
|
71
|
-
```python
|
|
72
|
-
from rkt_config_lib import Config
|
|
73
|
-
|
|
74
|
-
c = Config()
|
|
75
|
-
|
|
76
|
-
# by default search folder named "config" in root project folder
|
|
77
|
-
# for load all yaml files
|
|
78
|
-
c.get_data()
|
|
79
|
-
|
|
80
|
-
print(f"{c.data}")
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### Output (as file, sdtout or both)
|
|
84
|
-
```log
|
|
85
|
-
03/03/2022 16:44:09 :: [Logger] :: INFO :: Create logger for 'Config'
|
|
86
|
-
03/03/2022 16:44:09 :: [Logger] :: INFO :: add 'StreamHandler' in 'Config' logger
|
|
87
|
-
03/03/2022 16:44:09 :: [Logger] :: INFO :: add 'FileHandler' in 'Config' logger
|
|
88
|
-
03/03/2022 16:44:09 :: [Config] :: INFO :: Load 'database' file ...
|
|
89
|
-
```
|
|
90
|
-
```
|
|
91
|
-
{'database': {'connect_id': {'dbms': 'mariadb'}}}
|
|
92
|
-
^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
93
|
-
| |
|
|
94
|
-
| data: file content
|
|
95
|
-
file name without extension
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Contributing
|
|
99
|
-
|
|
100
|
-
If you find this library useful here's how you can help:
|
|
101
|
-
|
|
102
|
-
- Send a merge request with your kickass new features and bug fixes
|
|
103
|
-
- Help new users with [issues](https://gitlab.tprc.ovh/python/rkt_lib_toolkit/-/issues) they may encounter
|
|
104
|
-
- Support the development of this library and star this repo!
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import yaml
|
|
3
|
-
|
|
4
|
-
try:
|
|
5
|
-
from rkt_logger_lib.Logger import Logger
|
|
6
|
-
except ImportError:
|
|
7
|
-
from rkt_lib_toolkit.rkt_logger_lib.Logger import Logger
|
|
8
|
-
|
|
9
|
-
try:
|
|
10
|
-
from rkt_tool_lib.Tool import Tool, Singleton
|
|
11
|
-
except ImportError:
|
|
12
|
-
from rkt_lib_toolkit.rkt_tool_lib.Tool import Tool, Singleton
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class Config(metaclass=Singleton):
|
|
16
|
-
"""
|
|
17
|
-
Basic PyYaml wrapper
|
|
18
|
-
add custom logger, list of file need to be load
|
|
19
|
-
|
|
20
|
-
"""
|
|
21
|
-
__slots__ = ["_me", "_logger", "_tool", "_skills_file", "data"]
|
|
22
|
-
|
|
23
|
-
def __init__(self) -> None:
|
|
24
|
-
self._me = self.__class__.__name__
|
|
25
|
-
self._logger = Logger(caller_class=self._me)
|
|
26
|
-
self._logger.set_logger(caller_class=self._me)
|
|
27
|
-
self._tool = Tool()
|
|
28
|
-
self.data = {}
|
|
29
|
-
|
|
30
|
-
def get_data(self, needed_file: str = "", _config_dir: str = "config", create_if_not_exist: bool = False) -> None:
|
|
31
|
-
"""
|
|
32
|
-
Load all file in 'config_dir' and get data in dict formatted as : {"basename_1": <VALUE_1>, ...}
|
|
33
|
-
"""
|
|
34
|
-
config_dir = self._tool.get_dir(_config_dir)
|
|
35
|
-
|
|
36
|
-
if (not config_dir or not os.path.exists(config_dir)) and create_if_not_exist:
|
|
37
|
-
os.makedirs(_config_dir, exist_ok=True)
|
|
38
|
-
|
|
39
|
-
if needed_file:
|
|
40
|
-
filename = os.path.basename(needed_file).split(".")[0]
|
|
41
|
-
with open(f"{config_dir}{needed_file}", "r", encoding='utf8') as nf:
|
|
42
|
-
self._logger.add(level="info", caller=self._me, message=f"Load '{filename}' file ...")
|
|
43
|
-
self.data[filename] = yaml.load(nf, Loader=yaml.FullLoader)
|
|
44
|
-
else:
|
|
45
|
-
for file in os.listdir(config_dir):
|
|
46
|
-
try:
|
|
47
|
-
(filename, ext) = os.path.basename(file).split(".")
|
|
48
|
-
except ValueError:
|
|
49
|
-
continue
|
|
50
|
-
if ext in ["yml", "yaml"] and filename not in self.data.keys():
|
|
51
|
-
with open(f"{config_dir}{file}", "r", encoding='utf8') as f:
|
|
52
|
-
self._logger.add(level="info", caller=self._me, message=f"Load '{filename}' file ...")
|
|
53
|
-
self.data[filename] = yaml.load(f, Loader=yaml.FullLoader)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .Config import Config
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.2
|
|
2
|
-
Name: rkt_config_lib
|
|
3
|
-
Version: 1.4.0
|
|
4
|
-
Summary: RootKit custom PyYaml Lib
|
|
5
|
-
Author: RootKit
|
|
6
|
-
Author-email: rootkit@rootkit-lab.org
|
|
7
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
8
|
-
Classifier: Intended Audience :: Developers
|
|
9
|
-
Classifier: Intended Audience :: End Users/Desktop
|
|
10
|
-
Classifier: Intended Audience :: Information Technology
|
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
-
Classifier: Natural Language :: English
|
|
13
|
-
Classifier: Natural Language :: French
|
|
14
|
-
Classifier: Operating System :: OS Independent
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
16
|
-
Classifier: Topic :: Utilities
|
|
17
|
-
Requires-Python: >=3.7
|
|
18
|
-
Description-Content-Type: text/markdown
|
|
19
|
-
License-File: LICENSE
|
|
20
|
-
Requires-Dist: PyYaml
|
|
21
|
-
Requires-Dist: rkt_tool_lib
|
|
22
|
-
Requires-Dist: rkt_logger_lib
|
|
23
|
-
Dynamic: author
|
|
24
|
-
Dynamic: author-email
|
|
25
|
-
Dynamic: classifier
|
|
26
|
-
Dynamic: description
|
|
27
|
-
Dynamic: description-content-type
|
|
28
|
-
Dynamic: requires-dist
|
|
29
|
-
Dynamic: requires-python
|
|
30
|
-
Dynamic: summary
|
|
31
|
-
|
|
32
|
-
# rkt_config_lib - Python library
|
|
33
|
-
|
|
34
|
-

|
|
35
|
-
|
|
36
|
-

|
|
37
|
-

|
|
38
|
-

|
|
39
|
-

|
|
40
|
-

|
|
41
|
-

|
|
42
|
-
|
|
43
|
-
This Python library is based only on built-in Python libraries and one (1) non-build-in library : [PyYaml](https://pypi.org/project/PyYAML/)
|
|
44
|
-
|
|
45
|
-
##### Python Version 3.7.2
|
|
46
|
-
##### PyYaml Version 5.4.1 (Released Jan 20, 2021)
|
|
47
|
-
|
|
48
|
-
----
|
|
49
|
-
|
|
50
|
-
## What is Python?
|
|
51
|
-
Python is an interpreted high-level general-purpose programming language. Python's design philosophy emphasizes code readability with its notable use of significant indentation. Its language constructs as well as its object-oriented approach aim to help programmers write clear, logical code for small and large-scale projects.
|
|
52
|
-
|
|
53
|
-
[source](https://en.wikipedia.org/wiki/Python_(programming_language))
|
|
54
|
-
## What is PyYaml?
|
|
55
|
-
YAML is a data serialization format designed for human readability and interaction with scripting languages. PyYAML is a YAML parser and emitter for Python.
|
|
56
|
-
|
|
57
|
-
PyYAML features a complete YAML 1.1 parser, Unicode support, pickle support, capable extension API, and sensible error messages. PyYAML supports standard YAML tags and provides Python-specific tags that allow to represent an arbitrary Python object.
|
|
58
|
-
|
|
59
|
-
PyYAML is applicable for a broad range of tasks from complex configuration files to object serialization and persistence.
|
|
60
|
-
|
|
61
|
-
[source](https://pypi.org/project/PyYAML/)
|
|
62
|
-
## Libraries
|
|
63
|
-
* Config: overlay of PyYaml library (read-only), use Tool and Logger library (rkt_tool_lib, rkt_logger_lib)
|
|
64
|
-
|
|
65
|
-
## Use it
|
|
66
|
-
### Install
|
|
67
|
-
```bash
|
|
68
|
-
(venv) my_project> pip install rkt_config_lib [--index-url https://gitlab.tprc.ovh/api/v4/groups/python/-/packages/pypi]
|
|
69
|
-
```
|
|
70
|
-
### Example
|
|
71
|
-
```python
|
|
72
|
-
from rkt_config_lib import Config
|
|
73
|
-
|
|
74
|
-
c = Config()
|
|
75
|
-
|
|
76
|
-
# by default search folder named "config" in root project folder
|
|
77
|
-
# for load all yaml files
|
|
78
|
-
c.get_data()
|
|
79
|
-
|
|
80
|
-
print(f"{c.data}")
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### Output (as file, sdtout or both)
|
|
84
|
-
```log
|
|
85
|
-
03/03/2022 16:44:09 :: [Logger] :: INFO :: Create logger for 'Config'
|
|
86
|
-
03/03/2022 16:44:09 :: [Logger] :: INFO :: add 'StreamHandler' in 'Config' logger
|
|
87
|
-
03/03/2022 16:44:09 :: [Logger] :: INFO :: add 'FileHandler' in 'Config' logger
|
|
88
|
-
03/03/2022 16:44:09 :: [Config] :: INFO :: Load 'database' file ...
|
|
89
|
-
```
|
|
90
|
-
```
|
|
91
|
-
{'database': {'connect_id': {'dbms': 'mariadb'}}}
|
|
92
|
-
^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
93
|
-
| |
|
|
94
|
-
| data: file content
|
|
95
|
-
file name without extension
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Contributing
|
|
99
|
-
|
|
100
|
-
If you find this library useful here's how you can help:
|
|
101
|
-
|
|
102
|
-
- Send a merge request with your kickass new features and bug fixes
|
|
103
|
-
- Help new users with [issues](https://gitlab.tprc.ovh/python/rkt_lib_toolkit/-/issues) they may encounter
|
|
104
|
-
- Support the development of this library and star this repo!
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
LICENSE
|
|
2
|
-
README
|
|
3
|
-
rkt_lib_toolkit/rkt_config_lib/Config.py
|
|
4
|
-
rkt_lib_toolkit/rkt_config_lib/__init__.py
|
|
5
|
-
rkt_lib_toolkit/rkt_config_lib.egg-info/PKG-INFO
|
|
6
|
-
rkt_lib_toolkit/rkt_config_lib.egg-info/SOURCES.txt
|
|
7
|
-
rkt_lib_toolkit/rkt_config_lib.egg-info/dependency_links.txt
|
|
8
|
-
rkt_lib_toolkit/rkt_config_lib.egg-info/requires.txt
|
|
9
|
-
rkt_lib_toolkit/rkt_config_lib.egg-info/top_level.txt
|
|
10
|
-
tests/test_AI.py
|
|
11
|
-
tests/test_Config.py
|
|
12
|
-
tests/test_Logger.py
|
|
13
|
-
tests/test_Tool.py
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
rkt_config_lib
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
import os.path
|
|
2
|
-
import time
|
|
3
|
-
from unittest import TestCase
|
|
4
|
-
|
|
5
|
-
from pandas import DataFrame
|
|
6
|
-
|
|
7
|
-
from rkt_lib_toolkit import Logger, Config
|
|
8
|
-
from rkt_lib_toolkit.rkt_ai_lib import QLearning
|
|
9
|
-
|
|
10
|
-
MODEL = "tests/resources/qlearning/load/load_coverage.gzip"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class TestQLearning(TestCase):
|
|
14
|
-
def test_me_setter(self):
|
|
15
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
16
|
-
ql.me = 'me'
|
|
17
|
-
assert ql.me == 'me'
|
|
18
|
-
|
|
19
|
-
def test_me_getter(self):
|
|
20
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
21
|
-
assert ql.me == 'QLearning'
|
|
22
|
-
|
|
23
|
-
def test_logger_setter(self):
|
|
24
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
25
|
-
ql.logger = Logger(caller_class=ql.me)
|
|
26
|
-
assert isinstance(ql.logger, Logger)
|
|
27
|
-
|
|
28
|
-
def test_logger_getter(self):
|
|
29
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
30
|
-
logger = ql.logger
|
|
31
|
-
assert isinstance(logger, Logger)
|
|
32
|
-
|
|
33
|
-
def test_config_setter(self):
|
|
34
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
35
|
-
ql.config = Config()
|
|
36
|
-
assert isinstance(ql.config, Config)
|
|
37
|
-
|
|
38
|
-
def test_config_getter(self):
|
|
39
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
40
|
-
config = ql.config
|
|
41
|
-
assert isinstance(config, Config)
|
|
42
|
-
|
|
43
|
-
def test_learning_rate_setter(self):
|
|
44
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
45
|
-
original_lr = ql.learning_rate
|
|
46
|
-
ql.learning_rate = 1.0
|
|
47
|
-
assert ql.learning_rate != original_lr
|
|
48
|
-
|
|
49
|
-
def test_learning_rate_getter(self):
|
|
50
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
51
|
-
original_lr = ql.learning_rate
|
|
52
|
-
assert ql.learning_rate == original_lr
|
|
53
|
-
|
|
54
|
-
def test_discount_factor_setter(self):
|
|
55
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
56
|
-
original_df = ql.discount_factor
|
|
57
|
-
ql.discount_factor = 1.0
|
|
58
|
-
assert ql.discount_factor != original_df
|
|
59
|
-
|
|
60
|
-
def test_discount_factor_getter(self):
|
|
61
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
62
|
-
original_df = ql.discount_factor
|
|
63
|
-
assert ql.discount_factor == original_df
|
|
64
|
-
|
|
65
|
-
def test_qtable_setter(self):
|
|
66
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
67
|
-
assert isinstance(ql.qtable, DataFrame)
|
|
68
|
-
|
|
69
|
-
def test_qtable_getter(self):
|
|
70
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
71
|
-
qtable = ql.qtable
|
|
72
|
-
assert isinstance(qtable, DataFrame)
|
|
73
|
-
|
|
74
|
-
def test_previous_state_setter(self):
|
|
75
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
76
|
-
ql.previous_state = 's'
|
|
77
|
-
assert ql.previous_state == 's'
|
|
78
|
-
|
|
79
|
-
def test_previous_state_getter(self):
|
|
80
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
81
|
-
assert ql.previous_state == 'start'
|
|
82
|
-
|
|
83
|
-
def test_previous_action_setter(self):
|
|
84
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
85
|
-
ql.previous_action = 'a'
|
|
86
|
-
assert ql.previous_action == 'a'
|
|
87
|
-
|
|
88
|
-
def test_previous_action_getter(self):
|
|
89
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
90
|
-
assert ql.previous_action == 'do-nothing'
|
|
91
|
-
|
|
92
|
-
def test_available_actions_setter(self):
|
|
93
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
94
|
-
assert ql.available_actions == ['a', 'b', 'c']
|
|
95
|
-
|
|
96
|
-
def test_available_actions_getter(self):
|
|
97
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
98
|
-
actions_list = ql.available_actions
|
|
99
|
-
assert actions_list == ['a', 'b', 'c']
|
|
100
|
-
|
|
101
|
-
def test00_save(self):
|
|
102
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
103
|
-
ql.check_state_exist(state='s')
|
|
104
|
-
ql.previous_state = "new_action"
|
|
105
|
-
ql.check_state_exist(state='s1')
|
|
106
|
-
ql.save("tests/resources/qlearning/save/save_coverage.gzip")
|
|
107
|
-
ql.save(MODEL)
|
|
108
|
-
assert os.path.exists("tests/resources/qlearning/save/save_coverage.gzip")
|
|
109
|
-
|
|
110
|
-
def test01_load(self):
|
|
111
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
112
|
-
ql.load(do_load=True, file_to_load=MODEL)
|
|
113
|
-
assert isinstance(ql.qtable, DataFrame)
|
|
114
|
-
|
|
115
|
-
def test03_choose_action(self):
|
|
116
|
-
time.sleep(1.0)
|
|
117
|
-
ql = QLearning(actions=['a', 'b', 'c'], should_load=True,
|
|
118
|
-
qtable_file_to_load=MODEL)
|
|
119
|
-
|
|
120
|
-
action = ql.choose_action(state='s')
|
|
121
|
-
assert action in ['a', 'b', 'c']
|
|
122
|
-
|
|
123
|
-
def test_learn(self):
|
|
124
|
-
ql = QLearning(actions=['a', 'b', 'c'], should_load=True,
|
|
125
|
-
qtable_file_to_load=MODEL)
|
|
126
|
-
for i in range(2):
|
|
127
|
-
action = ql.choose_action(state=f's{i}')
|
|
128
|
-
ql.learn(state=f's{i}', action=action, reward=1.0)
|
|
129
|
-
assert ql.qtable.index.tolist() == ['start', 's1']
|
|
130
|
-
|
|
131
|
-
def test_check_state_exist(self):
|
|
132
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
133
|
-
ql.check_state_exist(state='s')
|
|
134
|
-
qtable_len = len(ql.qtable.index)
|
|
135
|
-
ql.check_state_exist(state='s')
|
|
136
|
-
qtable2_len = len(ql.qtable.index)
|
|
137
|
-
ql.previous_state = "new_action"
|
|
138
|
-
ql.check_state_exist(state='s1')
|
|
139
|
-
qtable3_len = len(ql.qtable.index)
|
|
140
|
-
assert qtable_len == qtable2_len and qtable_len != qtable3_len
|
|
141
|
-
|
|
142
|
-
def test_representation(self):
|
|
143
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
144
|
-
assert ql.__repr__() == f"QLearning(learning_rate={ql.learning_rate}, discount_factor={ql.discount_factor}, learning_method={ql._learning_method})"
|
|
145
|
-
|
|
146
|
-
def test_me_setter_error(self):
|
|
147
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
148
|
-
with self.assertRaises(TypeError):
|
|
149
|
-
ql.me = 1
|
|
150
|
-
|
|
151
|
-
def test_logger_setter_error(self):
|
|
152
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
153
|
-
with self.assertRaises(TypeError):
|
|
154
|
-
ql.logger = 1
|
|
155
|
-
|
|
156
|
-
def test_config_setter_error(self):
|
|
157
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
158
|
-
with self.assertRaises(TypeError):
|
|
159
|
-
ql.config = 1
|
|
160
|
-
|
|
161
|
-
def test_learning_rate_setter_error(self):
|
|
162
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
163
|
-
with self.assertRaises(TypeError):
|
|
164
|
-
ql.learning_rate = "0"
|
|
165
|
-
|
|
166
|
-
def test_discount_factor_setter_error(self):
|
|
167
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
168
|
-
with self.assertRaises(TypeError):
|
|
169
|
-
ql.discount_factor = "0"
|
|
170
|
-
|
|
171
|
-
def test_qtable_setter_error(self):
|
|
172
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
173
|
-
with self.assertRaises(TypeError):
|
|
174
|
-
ql.qtable = "0"
|
|
175
|
-
|
|
176
|
-
def test_previous_state_setter_error(self):
|
|
177
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
178
|
-
with self.assertRaises(TypeError):
|
|
179
|
-
ql.previous_state = 1
|
|
180
|
-
|
|
181
|
-
def test_previous_action_setter_error(self):
|
|
182
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
183
|
-
with self.assertRaises(TypeError):
|
|
184
|
-
ql.previous_action = 1
|
|
185
|
-
|
|
186
|
-
def test_available_actions_setter_error(self):
|
|
187
|
-
ql = QLearning(actions=['a', 'b', 'c'])
|
|
188
|
-
with self.assertRaises(TypeError):
|
|
189
|
-
ql.available_actions = 1
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import shutil
|
|
3
|
-
|
|
4
|
-
from unittest import TestCase
|
|
5
|
-
|
|
6
|
-
from yaml.scanner import ScannerError
|
|
7
|
-
from rkt_lib_toolkit.rkt_config_lib import Config
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class TestConfig(TestCase):
|
|
11
|
-
def test_get_data(self):
|
|
12
|
-
config = Config()
|
|
13
|
-
config.data.clear()
|
|
14
|
-
config.get_data(_config_dir="valid_config")
|
|
15
|
-
|
|
16
|
-
assert config.data == {
|
|
17
|
-
'valid_config': {'key1': {
|
|
18
|
-
'sub_key': 'value',
|
|
19
|
-
'sub_key2': 'value',
|
|
20
|
-
'sub_key3': 'value',
|
|
21
|
-
'sub_key4': 'value'
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
def test_get_data_dummy_data(self):
|
|
27
|
-
config = Config()
|
|
28
|
-
config.data.clear()
|
|
29
|
-
try:
|
|
30
|
-
config.get_data(_config_dir="dummy_config")
|
|
31
|
-
self.fail("ScannerError expected here!")
|
|
32
|
-
except ScannerError:
|
|
33
|
-
assert config.data == {}
|
|
34
|
-
|
|
35
|
-
def test_get_data_dummy_folder(self):
|
|
36
|
-
config = Config()
|
|
37
|
-
config.data.clear()
|
|
38
|
-
config.get_data(_config_dir="missing_folder", create_if_not_exist=True)
|
|
39
|
-
assert os.path.exists("missing_folder")
|
|
40
|
-
shutil.rmtree("missing_folder")
|
|
41
|
-
|
|
42
|
-
def test_get_data_from_specific_file(self):
|
|
43
|
-
config = Config()
|
|
44
|
-
config.data.clear()
|
|
45
|
-
config.get_data(_config_dir="valid_config", needed_file="valid_config.yml")
|
|
46
|
-
|
|
47
|
-
assert config.data == {
|
|
48
|
-
'valid_config': {'key1': {
|
|
49
|
-
'sub_key': 'value', 'sub_key2': 'value', 'sub_key3': 'value', 'sub_key4': 'value'
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import shutil
|
|
3
|
-
from datetime import datetime
|
|
4
|
-
from unittest import TestCase
|
|
5
|
-
|
|
6
|
-
from rkt_lib_toolkit.rkt_logger_lib import Logger
|
|
7
|
-
from rkt_lib_toolkit.rkt_exception_lib import InvalidLogLevelError, LogIsNotDirError
|
|
8
|
-
from rkt_lib_toolkit.rkt_tool_lib import Singleton, Tool
|
|
9
|
-
|
|
10
|
-
tool = Tool()
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class TestLogger(TestCase):
|
|
14
|
-
|
|
15
|
-
def test_logger_when_log_is_not_directory(self):
|
|
16
|
-
log = f"{tool.formatted_from_os(tool.get_cwd())}log_misstake"
|
|
17
|
-
if os.path.exists(log):
|
|
18
|
-
if os.path.isdir(log):
|
|
19
|
-
shutil.rmtree(log)
|
|
20
|
-
else:
|
|
21
|
-
os.remove(log)
|
|
22
|
-
|
|
23
|
-
open(log, "x").close()
|
|
24
|
-
Singleton._instances = {}
|
|
25
|
-
with self.assertRaises(LogIsNotDirError) as context:
|
|
26
|
-
logger = Logger("coverage", "log_misstake")
|
|
27
|
-
|
|
28
|
-
assert str(context.exception) == "\"log\" isn't a directory"
|
|
29
|
-
os.remove(log)
|
|
30
|
-
|
|
31
|
-
def test_add_without_exiting_log_level(self):
|
|
32
|
-
logger = Logger("coverage", "log")
|
|
33
|
-
logger.set_logger(caller_class="coverage", output="stream")
|
|
34
|
-
with self.assertRaises(InvalidLogLevelError):
|
|
35
|
-
logger.add("coverage", "tests coverage", 42)
|
|
36
|
-
|
|
37
|
-
def test_add_with_exiting_log_level(self):
|
|
38
|
-
logger = Logger("coverage", "log")
|
|
39
|
-
logger.set_logger(caller_class="coverage", output="stream")
|
|
40
|
-
assert logger.add("coverage", "tests coverage", 20) is None
|
|
41
|
-
|
|
42
|
-
def test_set_logger(self):
|
|
43
|
-
logger = Logger("coverage", "log")
|
|
44
|
-
logger.set_logger(caller_class="coverage", output="both", out_file="coverage", level=10)
|
|
45
|
-
logger.add("coverage", "test", 20)
|
|
46
|
-
excepted = f"{logger._tool.get_dir(folder='log')}coverage_{datetime.today().date()}.log"
|
|
47
|
-
obtained = logger.get_logger_file('coverage')
|
|
48
|
-
assert obtained == excepted, print(f"Expected: {excepted}\nObtained: {obtained}")
|
|
49
|
-
|
|
50
|
-
def test_no_logger_file(self):
|
|
51
|
-
logger = Logger("coverage", "log")
|
|
52
|
-
logger.set_logger(caller_class="coverage", output="both", out_file="coverage")
|
|
53
|
-
assert logger.get_logger_file('not_exist') is None
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
|
|
3
|
-
from rkt_lib_toolkit.rkt_tool_lib import Tool, Singleton
|
|
4
|
-
|
|
5
|
-
obj = Tool()
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class FakeClass(metaclass=Singleton):
|
|
9
|
-
def __init__(self):
|
|
10
|
-
self.name = "singleton"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class TestTool:
|
|
14
|
-
def test_formatted_from_os(self):
|
|
15
|
-
if os.name == "nt":
|
|
16
|
-
excepted = obj.formatted_from_os(os.getcwd()).endswith("\\")
|
|
17
|
-
else:
|
|
18
|
-
excepted = obj.formatted_from_os(os.getcwd()).endswith("/")
|
|
19
|
-
assert excepted
|
|
20
|
-
|
|
21
|
-
def test_get_cwd(self):
|
|
22
|
-
assert obj.get_cwd() == f"{os.getcwd()}\\" if os.name == "nt" else f"{os.getcwd()}/"
|
|
23
|
-
|
|
24
|
-
def test_get_dir_flat(self):
|
|
25
|
-
if os.name == "nt":
|
|
26
|
-
excepted = f"{os.getcwd()}\\tests\\"
|
|
27
|
-
else:
|
|
28
|
-
excepted = f"{os.getcwd()}/tests/"
|
|
29
|
-
assert obj.get_dir("tests") == excepted
|
|
30
|
-
|
|
31
|
-
def test_get_dir_recursive(self):
|
|
32
|
-
if os.name == "nt":
|
|
33
|
-
excepted = f"{os.getcwd()}\\tests\\resources\\"
|
|
34
|
-
else:
|
|
35
|
-
excepted = f"{os.getcwd()}/tests/resources/"
|
|
36
|
-
|
|
37
|
-
assert obj.get_dir("resources") == excepted
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class TestSingleton:
|
|
41
|
-
def test_singleton(self):
|
|
42
|
-
obj_1 = FakeClass()
|
|
43
|
-
obj_2 = FakeClass()
|
|
44
|
-
assert obj_1 == obj_2
|
|
45
|
-
|
|
File without changes
|
|
File without changes
|