pkn 0.1.2__py3-none-any.whl → 0.1.4__py3-none-any.whl

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.
pkn/__init__.py CHANGED
@@ -1,3 +1,4 @@
1
+ from .logging import *
1
2
  from .pydantic import *
2
3
 
3
- __version__ = "0.1.2"
4
+ __version__ = "0.1.4"
@@ -0,0 +1,59 @@
1
+ from importlib.machinery import ModuleSpec, SourceFileLoader
2
+ from inspect import currentframe
3
+ from logging import Logger, getLogger as baseGetLogger
4
+ from logging.config import dictConfig
5
+ from typing import Literal, Union
6
+
7
+ __all__ = ("default", "getLogger")
8
+
9
+ LogLevelStr = Literal["CRITICAL", "FATAL", "ERROR", "WARNING", "WARN", "INFO", "DEBUG", "NOTSET"]
10
+ LogLevelInt = Literal[50, 40, 30, 20, 10, 0]
11
+ LogLevel = Union[LogLevelStr, LogLevelInt]
12
+
13
+
14
+ def default(
15
+ file: str = "output.log",
16
+ console_level: LogLevel = "INFO",
17
+ file_level: LogLevel = "DEBUG",
18
+ ) -> None:
19
+ config = dict(
20
+ version=1,
21
+ disable_existing_loggers=False,
22
+ formatters={
23
+ "simple": {"format": "[%(asctime)s][%(threadName)s][%(name)s][%(levelname)s]: %(message)s"},
24
+ "colorlog": {
25
+ "()": "colorlog.ColoredFormatter",
26
+ "format": "[%(cyan)s%(asctime)s%(reset)s][%(threadName)s][%(blue)s%(name)s%(reset)s][%(log_color)s%(levelname)s%(reset)s]: %(message)s",
27
+ "log_colors": {
28
+ "DEBUG": "white",
29
+ "INFO": "green",
30
+ "WARNING": "yellow",
31
+ "ERROR": "red",
32
+ "CRITICAL": "red",
33
+ },
34
+ },
35
+ "whenAndWhere": {"format": "[%(asctime)s][%(threadName)s][%(name)s][%(filename)s:%(lineno)d][%(levelname)s]: %(message)s"},
36
+ },
37
+ handlers={
38
+ "console": {"level": console_level, "class": "ccflow.utils.logging.StreamHandler", "formatter": "colorlog", "stream": "ext://sys.stdout"},
39
+ },
40
+ root={"handlers": ["console"], "level": "DEBUG"},
41
+ )
42
+ if file:
43
+ config["handlers"]["file"] = {"level": file_level, "class": "ccflow.FileHandler", "formatter": "whenAndWhere", "filename": file}
44
+ dictConfig(config)
45
+
46
+
47
+ def getLogger() -> Logger:
48
+ # Get fully qualified module name of parent caller
49
+ cur_frame = currentframe()
50
+ caller_frame = cur_frame.f_back
51
+
52
+ spec = caller_frame.f_globals["__spec__"]
53
+ loader = caller_frame.f_globals["__loader__"] or spec
54
+
55
+ if isinstance(loader, SourceFileLoader):
56
+ module_name = loader.name
57
+ elif spec and isinstance(spec, ModuleSpec):
58
+ module_name = spec.name
59
+ return baseGetLogger(module_name)
pkn/pydantic/__init__.py CHANGED
@@ -1 +1,3 @@
1
+ from .generic import *
2
+ from .paths import *
1
3
  from .roots import *
pkn/pydantic/paths.py ADDED
@@ -0,0 +1,41 @@
1
+ from importlib import import_module
2
+ from types import FunctionType, MethodType
3
+ from typing import Annotated, Optional
4
+
5
+ from pydantic import BeforeValidator, PlainSerializer
6
+
7
+ __all__ = (
8
+ "get_import_path",
9
+ "serialize_path_as_string",
10
+ "ImportPath",
11
+ "CallablePath",
12
+ )
13
+
14
+
15
+ def get_import_path(path: str) -> type:
16
+ if isinstance(path, type):
17
+ return path
18
+ elif isinstance(path, (FunctionType, MethodType)):
19
+ return path
20
+ if not isinstance(path, str):
21
+ raise TypeError(path)
22
+ module, call = path.rsplit(".", 1)
23
+ return getattr(import_module(module), call)
24
+
25
+
26
+ def serialize_path_as_string(value: type) -> Optional[str]:
27
+ if value is None:
28
+ return None
29
+ if hasattr(value, "__module__") and hasattr(value, "__qualname__"):
30
+ return f"{value.__module__}.{value.__qualname__}"
31
+ if hasattr(value, "__name__"):
32
+ return f"{value.__module__}.{value.__name__}"
33
+ if hasattr(value, "__class__") and hasattr(value.__class__, "__name__"):
34
+ return f"{value.__class__.__module__}.{value.__class__.__name__}"
35
+ if hasattr(value, "__class__") and hasattr(value.__class__, "__qualname__"):
36
+ return f"{value.__class__.__module__}.{value.__class__.__qualname__}"
37
+ raise TypeError(f"Could not derive module and name for {value}")
38
+
39
+
40
+ ImportPath = Annotated[type, BeforeValidator(get_import_path), PlainSerializer(serialize_path_as_string, when_used="json", return_type=str)]
41
+ CallablePath = Annotated[object, BeforeValidator(get_import_path), PlainSerializer(serialize_path_as_string, when_used="json", return_type=str)]
pkn/tests/__init__.py ADDED
File without changes
File without changes
@@ -0,0 +1,21 @@
1
+ from unittest.mock import patch
2
+
3
+ from pkn import default, getLogger
4
+
5
+
6
+ def test():
7
+ default()
8
+ logger = getLogger()
9
+ logger.critical("This is a test log message.")
10
+
11
+
12
+ class TestLogger:
13
+ def test_logging(self):
14
+ # Patch standard out and look at log message
15
+ with patch("sys.stdout") as mock_stdout:
16
+ default()
17
+ logger = getLogger()
18
+ logger.critical("This is a test log message.")
19
+ assert mock_stdout.write.call_args[0][0].endswith(
20
+ "\x1b[0m][MainThread][\x1b[34mpkn.tests.logging.test_logging\x1b[0m][\x1b[31mCRITICAL\x1b[0m]: This is a test log message.\x1b[0m\n"
21
+ )
File without changes
@@ -0,0 +1,36 @@
1
+ from pydantic import BaseModel
2
+
3
+ from pkn.pydantic import CallablePath, ImportPath
4
+
5
+
6
+ def foo():
7
+ return "foo"
8
+
9
+
10
+ class MyType: ...
11
+
12
+
13
+ class MyModel(BaseModel):
14
+ typ: ImportPath
15
+ foo: CallablePath
16
+
17
+
18
+ def test_get_import_path_inst():
19
+ m = MyModel(typ=MyType, foo=foo)
20
+ assert m.typ == MyType
21
+ assert m.foo == foo
22
+
23
+
24
+ def test_get_import_path_string():
25
+ m = MyModel(typ="pkn.tests.pydantic.test_paths.MyType", foo="pkn.tests.pydantic.test_paths.foo")
26
+ assert m.typ == MyType
27
+ assert m.foo == foo
28
+
29
+
30
+ def test_serialize():
31
+ m = MyModel(typ="pkn.tests.pydantic.test_paths.MyType", foo="pkn.tests.pydantic.test_paths.foo")
32
+ assert m.model_dump() == {
33
+ "typ": MyType,
34
+ "foo": foo,
35
+ }
36
+ assert m.model_dump_json() == ('{"typ":"pkn.tests.pydantic.test_paths.MyType","foo":"pkn.tests.pydantic.test_paths.foo"}')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pkn
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: My Pocket Knife
5
5
  Project-URL: Repository, https://github.com/1kbgz/pkn
6
6
  Project-URL: Homepage, https://github.com/1kbgz/pkn
@@ -15,15 +15,21 @@ Classifier: Programming Language :: Python :: 3.10
15
15
  Classifier: Programming Language :: Python :: 3.11
16
16
  Classifier: Programming Language :: Python :: 3.12
17
17
  Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
18
19
  Classifier: Programming Language :: Python :: Implementation :: CPython
19
20
  Classifier: Programming Language :: Python :: Implementation :: PyPy
20
21
  Requires-Python: >=3.9
22
+ Requires-Dist: ccflow
23
+ Requires-Dist: colorlog
21
24
  Requires-Dist: pydantic
22
25
  Provides-Extra: develop
23
26
  Requires-Dist: build; extra == 'develop'
24
27
  Requires-Dist: bump-my-version; extra == 'develop'
25
28
  Requires-Dist: check-manifest; extra == 'develop'
29
+ Requires-Dist: codespell<2.5,>=2.4; extra == 'develop'
26
30
  Requires-Dist: hatchling; extra == 'develop'
31
+ Requires-Dist: mdformat-tables>=1; extra == 'develop'
32
+ Requires-Dist: mdformat<0.8,>=0.7.22; extra == 'develop'
27
33
  Requires-Dist: pytest; extra == 'develop'
28
34
  Requires-Dist: pytest-cov; extra == 'develop'
29
35
  Requires-Dist: ruff; extra == 'develop'
@@ -36,13 +42,12 @@ Description-Content-Type: text/markdown
36
42
 
37
43
  My Pocket Knife
38
44
 
39
- [![Build Status](https://github.com/1kbgz/pkn/actions/workflows/build.yml/badge.svg?branch=main&event=push)](https://github.com/1kbgz/pkn/actions/workflows/build.yml)
45
+ [![Build Status](https://github.com/1kbgz/pkn/actions/workflows/build.yaml/badge.svg?branch=main&event=push)](https://github.com/1kbgz/pkn/actions/workflows/build.yaml)
40
46
  [![codecov](https://codecov.io/gh/1kbgz/pkn/branch/main/graph/badge.svg)](https://codecov.io/gh/1kbgz/pkn)
41
47
  [![License](https://img.shields.io/github/license/1kbgz/pkn)](https://github.com/1kbgz/pkn)
42
48
  [![PyPI](https://img.shields.io/pypi/v/pkn.svg)](https://pypi.python.org/pypi/pkn)
43
49
 
44
50
  ## Overview
45
51
 
46
-
47
52
  > [!NOTE]
48
53
  > This library was generated using [copier](https://copier.readthedocs.io/en/stable/) from the [Base Python Project Template repository](https://github.com/python-project-templates/base).
@@ -0,0 +1,24 @@
1
+ pkn/__init__.py,sha256=HLejGA44I1BeeTOoK-TsvGlbO7Xhu7uY062dBRAEXBE,70
2
+ pkn/infra/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ pkn/infra/at.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ pkn/infra/common.py,sha256=Ymsc6F60EUJoCxGNUbj2xQ4OwsVh5IwcOXFnn_mRGYE,744
5
+ pkn/infra/journalctl.py,sha256=ZbmEAcqJG3IoLUTy8Uwkx341ga0t-56SXl4Wa-ls1DY,287
6
+ pkn/infra/launchctl.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ pkn/infra/reboot.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ pkn/infra/systemctl.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ pkn/logging/__init__.py,sha256=eCiigtI7nSCpH2nBAOgq2Dy57c99ShxwHYGyfWRMUVc,2284
10
+ pkn/pydantic/__init__.py,sha256=KQVHgirlymnu4lpOW_MxxfchnE2c2A_f9xGdS4UxAIc,65
11
+ pkn/pydantic/generic.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ pkn/pydantic/paths.py,sha256=aQ5kfYVjtVQrSbE9wJ0cCMqWFNM81V8ivTkLa6kLypU,1590
13
+ pkn/pydantic/roots.py,sha256=2jt5fbGGMDu7kEi6EYci21FFkLwxtEse1ldrAehTYyw,2575
14
+ pkn/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ pkn/tests/test_all.py,sha256=7jewXmZqf4xpkDjN1yc17oxTCHQIlxqWqgmm_l96kSI,60
16
+ pkn/tests/logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ pkn/tests/logging/test_logging.py,sha256=4CfAK2L4qyqWDdNfNmItWnRjm5pqCXETMlV1v8T6S1I,662
18
+ pkn/tests/pydantic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ pkn/tests/pydantic/test_paths.py,sha256=SBQPMRw8xFlgt0LRFtxOL8ZC_YRyR1HyduqeggknLB0,846
20
+ pkn/tests/pydantic/test_roots.py,sha256=uNfzA5jqIDK8WVD-yIJdwTJOdec7HwmCwI677rbi86I,1377
21
+ pkn-0.1.4.dist-info/METADATA,sha256=oRefiNhEjqFaV60HQsaBT6Oy47Pb0ANNkYBkp-qQJjY,2300
22
+ pkn-0.1.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ pkn-0.1.4.dist-info/licenses/LICENSE,sha256=RcPqVYf2JyhlV4FlBQud0104R3fT1_-7XbT-vp4eLyE,11335
24
+ pkn-0.1.4.dist-info/RECORD,,
@@ -186,7 +186,7 @@
186
186
  same "printed page" as the copyright notice for easier
187
187
  identification within third-party archives.
188
188
 
189
- Copyright 2024 the pkn authors
189
+ Copyright 2025 1kbgz
190
190
 
191
191
  Licensed under the Apache License, Version 2.0 (the "License");
192
192
  you may not use this file except in compliance with the License.
@@ -1,17 +0,0 @@
1
- pkn/__init__.py,sha256=8KXL-9bF0pEahj6yBE3dQ2NqHbFoMSaPgJ_GxCzk3wI,47
2
- pkn/infra/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- pkn/infra/at.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- pkn/infra/common.py,sha256=Ymsc6F60EUJoCxGNUbj2xQ4OwsVh5IwcOXFnn_mRGYE,744
5
- pkn/infra/journalctl.py,sha256=ZbmEAcqJG3IoLUTy8Uwkx341ga0t-56SXl4Wa-ls1DY,287
6
- pkn/infra/launchctl.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- pkn/infra/reboot.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- pkn/infra/systemctl.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- pkn/pydantic/__init__.py,sha256=M-lKT4BNEjAX0098TvC4U8CVnDTn4smN-fkMK9haopM,21
10
- pkn/pydantic/generic.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- pkn/pydantic/roots.py,sha256=2jt5fbGGMDu7kEi6EYci21FFkLwxtEse1ldrAehTYyw,2575
12
- pkn/tests/test_all.py,sha256=7jewXmZqf4xpkDjN1yc17oxTCHQIlxqWqgmm_l96kSI,60
13
- pkn/tests/pydantic/test_roots.py,sha256=uNfzA5jqIDK8WVD-yIJdwTJOdec7HwmCwI677rbi86I,1377
14
- pkn-0.1.2.dist-info/METADATA,sha256=6jFvA6_OYXNtxS75OFNnYB7t3MnHT4e_BzL_Hdild3A,2036
15
- pkn-0.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
- pkn-0.1.2.dist-info/licenses/LICENSE,sha256=88kGYCLkpYJl18wjFE_ggvtjqnPAm2zhiIgX12fG_ug,11345
17
- pkn-0.1.2.dist-info/RECORD,,
File without changes