pkn 0.1.2__tar.gz → 0.1.4__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.
@@ -4,8 +4,12 @@ __pycache__/
4
4
  *$py.class
5
5
 
6
6
  # C extensions
7
+ *.a
7
8
  *.so
9
+ *.obj
8
10
  *.dll
11
+ *.exp
12
+ *.lib
9
13
 
10
14
  # Distribution / packaging
11
15
  .Python
@@ -29,8 +33,6 @@ share/python-wheels/
29
33
  MANIFEST
30
34
 
31
35
  # PyInstaller
32
- # Usually these files are written by a python script from a template
33
- # before PyInstaller builds the exe, so as to inject date/other infos into it.
34
36
  *.manifest
35
37
  *.spec
36
38
 
@@ -81,11 +83,7 @@ ipython_config.py
81
83
  .python-version
82
84
 
83
85
  # pipenv
84
- # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
85
- # However, in case of collaboration, if having platform-specific dependencies or dependencies
86
- # having no cross-platform support, pipenv may install dependencies that don't work, or not
87
- # install all needed dependencies.
88
- #Pipfile.lock
86
+ Pipfile.lock
89
87
 
90
88
  # PEP 582; used by e.g. github.com/David-OConnor/pyflow
91
89
  __pypackages__/
@@ -125,19 +123,36 @@ dmypy.json
125
123
  .pyre/
126
124
 
127
125
  # Documentation
128
- docs/_build/
129
126
  /site
127
+ index.md
128
+ docs/_build/
129
+ docs/src/_build/
130
130
  docs/api
131
131
  docs/index.md
132
- _template/labextension
132
+ docs/html
133
+ docs/jupyter_execute
134
+ index.md
135
+
136
+ # JS
137
+ js/coverage
138
+ js/dist
139
+ js/lib
140
+ js/node_modules
141
+ js/test-results
142
+ js/playwright-report
143
+ js/*.tgz
144
+ pkn/extension
133
145
 
134
146
  # Jupyter
135
147
  .ipynb_checkpoints
136
148
  .autoversion
149
+ !pkn/extension/pkn.json
150
+ !pkn/extension/install.json
151
+ pkn/nbextension
152
+ pkn/labextension
137
153
 
138
154
  # Mac
139
155
  .DS_Store
140
156
 
141
157
  # Rust
142
158
  target
143
-
@@ -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,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).
@@ -2,13 +2,12 @@
2
2
 
3
3
  My Pocket Knife
4
4
 
5
- [![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)
5
+ [![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)
6
6
  [![codecov](https://codecov.io/gh/1kbgz/pkn/branch/main/graph/badge.svg)](https://codecov.io/gh/1kbgz/pkn)
7
7
  [![License](https://img.shields.io/github/license/1kbgz/pkn)](https://github.com/1kbgz/pkn)
8
8
  [![PyPI](https://img.shields.io/pypi/v/pkn.svg)](https://pypi.python.org/pypi/pkn)
9
9
 
10
10
  ## Overview
11
11
 
12
-
13
12
  > [!NOTE]
14
13
  > 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,4 @@
1
+ from .logging import *
2
+ from .pydantic import *
3
+
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)
@@ -0,0 +1,3 @@
1
+ from .generic import *
2
+ from .paths import *
3
+ from .roots import *
@@ -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)]
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"}')
@@ -8,7 +8,7 @@ authors = [{name = "the pkn authors", email = "t.paine154@gmail.com"}]
8
8
  description = "My Pocket Knife"
9
9
  readme = "README.md"
10
10
  license = { text = "Apache-2.0" }
11
- version = "0.1.2"
11
+ version = "0.1.4"
12
12
  requires-python = ">=3.9"
13
13
  keywords = []
14
14
 
@@ -23,9 +23,12 @@ classifiers = [
23
23
  "Programming Language :: Python :: 3.11",
24
24
  "Programming Language :: Python :: 3.12",
25
25
  "Programming Language :: Python :: 3.13",
26
+ "Programming Language :: Python :: 3.14",
26
27
  ]
27
28
 
28
29
  dependencies = [
30
+ "ccflow",
31
+ "colorlog",
29
32
  "pydantic",
30
33
  ]
31
34
 
@@ -34,7 +37,10 @@ develop = [
34
37
  "build",
35
38
  "bump-my-version",
36
39
  "check-manifest",
40
+ "codespell>=2.4,<2.5",
37
41
  "hatchling",
42
+ "mdformat>=0.7.22,<0.8",
43
+ "mdformat-tables>=1",
38
44
  "pytest",
39
45
  "pytest-cov",
40
46
  "ruff",
@@ -50,9 +56,10 @@ Repository = "https://github.com/1kbgz/pkn"
50
56
  Homepage = "https://github.com/1kbgz/pkn"
51
57
 
52
58
  [tool.bumpversion]
53
- current_version = "0.1.2"
59
+ current_version = "0.1.4"
54
60
  commit = true
55
61
  tag = true
62
+ commit_args = "-s"
56
63
 
57
64
  [[tool.bumpversion.files]]
58
65
  filename = "pkn/__init__.py"
@@ -66,7 +73,7 @@ replace = 'version = "{new_version}"'
66
73
 
67
74
  [tool.check-manifest]
68
75
  ignore = [
69
- ".copier-answers.yml",
76
+ ".copier-answers.yaml",
70
77
  "Makefile",
71
78
  "docs/**/*",
72
79
  ]
pkn-0.1.2/pkn/__init__.py DELETED
@@ -1,3 +0,0 @@
1
- from .pydantic import *
2
-
3
- __version__ = "0.1.2"
@@ -1 +0,0 @@
1
- from .roots import *
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes