pkg-about 2.0.4__tar.gz → 2.0.7__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.
- {pkg_about-2.0.4 → pkg_about-2.0.7}/CHANGES.rst +4 -1
- {pkg_about-2.0.4 → pkg_about-2.0.7}/PKG-INFO +7 -4
- {pkg_about-2.0.4 → pkg_about-2.0.7}/pyproject.toml +4 -4
- {pkg_about-2.0.4 → pkg_about-2.0.7}/src/pkg_about/_about.py +34 -11
- {pkg_about-2.0.4 → pkg_about-2.0.7}/src/pkg_about.egg-info/PKG-INFO +7 -4
- {pkg_about-2.0.4 → pkg_about-2.0.7}/src/pkg_about.egg-info/requires.txt +2 -2
- {pkg_about-2.0.4 → pkg_about-2.0.7}/tests/test_main.py +75 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/.readthedocs.yml +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/LICENSE +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/MANIFEST.in +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/README.rst +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/docs/CHANGES.rst +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/docs/README.rst +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/docs/_static/.keep +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/docs/_templates/.keep +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/docs/conf.py +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/docs/index.rst +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/setup.cfg +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/src/pkg_about/__about__.py +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/src/pkg_about/__init__.py +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/src/pkg_about/py.typed +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/src/pkg_about.egg-info/SOURCES.txt +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/src/pkg_about.egg-info/dependency_links.txt +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/src/pkg_about.egg-info/top_level.txt +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/src/pkg_about.egg-info/zip-safe +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/tests/__init__.py +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/tests/__main__.py +0 -0
- {pkg_about-2.0.4 → pkg_about-2.0.7}/tests/data/setup.cfg +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
-
2.0.
|
|
4
|
+
2.0.7 (2025-11-27)
|
|
5
5
|
------------------
|
|
6
6
|
- | Now about() and about_from_setup() return an instance of the adict
|
|
7
7
|
| dictionary with about info (but backward compatibility is preserved).
|
|
@@ -10,6 +10,9 @@ Changelog
|
|
|
10
10
|
- | Workaround for the tox error when pyproject.toml and setup.cfg
|
|
11
11
|
| files coexist.
|
|
12
12
|
- Better parsing of newer metadata versions.
|
|
13
|
+
- | Fixed a bug concerning the 'strict' parameter for the methods
|
|
14
|
+
| email.utils.getaddresses() and email.utils.parseaddr().
|
|
15
|
+
| Thank you! https://github.com/hedesandxlii
|
|
13
16
|
- Mark the package as typed.
|
|
14
17
|
- Add tox's tool.tox.env.cleanup testenv.
|
|
15
18
|
- Setup (dependencies) update.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pkg_about
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.7
|
|
4
4
|
Summary: Shares Python package metadata at runtime.
|
|
5
5
|
Author-email: Adam Karpierz <adam@karpierz.net>
|
|
6
6
|
Maintainer-email: Adam Karpierz <adam@karpierz.net>
|
|
@@ -41,8 +41,8 @@ Requires-Dist: sphinx-toolbox>=4.0.0; extra == "doc"
|
|
|
41
41
|
Requires-Dist: sphinx-tabs>=3.4.5; extra == "doc"
|
|
42
42
|
Requires-Dist: sphinx-copybutton>=0.5.2; extra == "doc"
|
|
43
43
|
Requires-Dist: sphinxcontrib-spelling>=8.0.1; extra == "doc"
|
|
44
|
-
Requires-Dist: sphinx-lint>=1.0.
|
|
45
|
-
Requires-Dist: restructuredtext-lint>=
|
|
44
|
+
Requires-Dist: sphinx-lint>=1.0.2; extra == "doc"
|
|
45
|
+
Requires-Dist: restructuredtext-lint>=2.0.2; extra == "doc"
|
|
46
46
|
Requires-Dist: nbsphinx>=0.9.7; extra == "doc"
|
|
47
47
|
Provides-Extra: test
|
|
48
48
|
Requires-Dist: deepdiff>=8.6.1; extra == "test"
|
|
@@ -144,7 +144,7 @@ Authors
|
|
|
144
144
|
Changelog
|
|
145
145
|
=========
|
|
146
146
|
|
|
147
|
-
2.0.
|
|
147
|
+
2.0.7 (2025-11-27)
|
|
148
148
|
------------------
|
|
149
149
|
- | Now about() and about_from_setup() return an instance of the adict
|
|
150
150
|
| dictionary with about info (but backward compatibility is preserved).
|
|
@@ -153,6 +153,9 @@ Changelog
|
|
|
153
153
|
- | Workaround for the tox error when pyproject.toml and setup.cfg
|
|
154
154
|
| files coexist.
|
|
155
155
|
- Better parsing of newer metadata versions.
|
|
156
|
+
- | Fixed a bug concerning the 'strict' parameter for the methods
|
|
157
|
+
| email.utils.getaddresses() and email.utils.parseaddr().
|
|
158
|
+
| Thank you! https://github.com/hedesandxlii
|
|
156
159
|
- Mark the package as typed.
|
|
157
160
|
- Add tox's tool.tox.env.cleanup testenv.
|
|
158
161
|
- Setup (dependencies) update.
|
|
@@ -7,7 +7,7 @@ requires = ['setuptools>=80.9.0', 'packaging>=25.0.0', 'tox>=4.32.0']
|
|
|
7
7
|
|
|
8
8
|
[project]
|
|
9
9
|
name = 'pkg_about'
|
|
10
|
-
version = '2.0.
|
|
10
|
+
version = '2.0.7'
|
|
11
11
|
description = 'Shares Python package metadata at runtime.'
|
|
12
12
|
authors = [
|
|
13
13
|
{ name = 'Adam Karpierz', email = 'adam@karpierz.net' },
|
|
@@ -57,8 +57,8 @@ optional-dependencies.'doc' = [
|
|
|
57
57
|
'sphinx-tabs>=3.4.5', # don't touch! sphinx-toolbox requires <3.4.7
|
|
58
58
|
'sphinx-copybutton>=0.5.2',
|
|
59
59
|
'sphinxcontrib-spelling>=8.0.1',
|
|
60
|
-
'sphinx-lint>=1.0.
|
|
61
|
-
'restructuredtext-lint>=
|
|
60
|
+
'sphinx-lint>=1.0.2',
|
|
61
|
+
'restructuredtext-lint>=2.0.2',
|
|
62
62
|
'nbsphinx>=0.9.7',
|
|
63
63
|
]
|
|
64
64
|
optional-dependencies.'test' = [
|
|
@@ -252,7 +252,7 @@ commands = [
|
|
|
252
252
|
]
|
|
253
253
|
deps = [
|
|
254
254
|
{replace='ref',of=['tool','tox','env_run_base','deps'],extend=true},
|
|
255
|
-
'coverage>=7.
|
|
255
|
+
'coverage>=7.12.0',
|
|
256
256
|
'covdefaults>=2.3.0',
|
|
257
257
|
'diff-cover>=9.7.1',
|
|
258
258
|
]
|
|
@@ -10,37 +10,56 @@ from collections import namedtuple
|
|
|
10
10
|
from functools import partial
|
|
11
11
|
from email.utils import getaddresses, parseaddr
|
|
12
12
|
|
|
13
|
-
if sys.version_info >= (3, 12):
|
|
13
|
+
if sys.version_info >= (3, 12, 6):
|
|
14
14
|
getaddresses = partial(getaddresses, strict=False)
|
|
15
15
|
parseaddr = partial(parseaddr, strict=False)
|
|
16
16
|
else: pass # pragma: no cover
|
|
17
17
|
|
|
18
18
|
version_info = namedtuple("version_info",
|
|
19
19
|
["major", "minor", "micro", "releaselevel", "serial"],
|
|
20
|
-
module=
|
|
20
|
+
module=__package__)
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
class
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
class adict(dict[str, Any]):
|
|
24
|
+
|
|
25
|
+
__module__ = __package__
|
|
26
|
+
|
|
27
|
+
def __getattr__(self, name: str) -> Any:
|
|
28
|
+
try:
|
|
29
|
+
return self.__getitem__(name)
|
|
30
|
+
except KeyError as exc:
|
|
31
|
+
raise AttributeError(*exc.args) from None
|
|
32
|
+
|
|
33
|
+
def __setattr__(self, name: str, value: Any) -> None:
|
|
34
|
+
try:
|
|
35
|
+
self.__setitem__(name, value)
|
|
36
|
+
except KeyError as exc: # pragma: no cover
|
|
37
|
+
raise AttributeError(*exc.args) from None
|
|
38
|
+
|
|
39
|
+
def __delattr__(self, name: str) -> None:
|
|
40
|
+
try:
|
|
41
|
+
self.__delitem__(name)
|
|
42
|
+
except KeyError as exc:
|
|
43
|
+
raise AttributeError(*exc.args) from None
|
|
44
|
+
|
|
27
45
|
copy = __copy__ = lambda self: self.__class__(self)
|
|
28
46
|
|
|
29
47
|
|
|
30
|
-
def about(package: str | None = None) ->
|
|
48
|
+
def about(package: str | None = None) -> adict:
|
|
31
49
|
import sys
|
|
32
50
|
from packaging.version import parse as parse_version
|
|
33
51
|
from importlib.metadata import metadata as get_metadata
|
|
52
|
+
from importlib.metadata import version as get_version
|
|
34
53
|
pkg_globals = sys._getframe(1).f_globals
|
|
35
54
|
pkg_globals.pop("__builtins__", None)
|
|
36
55
|
pkg_globals.pop("__cached__", None)
|
|
37
56
|
if package is None: package = pkg_globals["__package__"]
|
|
38
57
|
metadata = get_metadata(package)
|
|
39
|
-
version = parse_version(
|
|
58
|
+
version = parse_version(get_version(package))
|
|
40
59
|
project_urls = {item.partition(",")[0].strip():
|
|
41
60
|
item.partition(",")[2].lstrip()
|
|
42
61
|
for item in metadata.get_all("Project-URL") or []}
|
|
43
|
-
|
|
62
|
+
release_levels = __release_levels
|
|
44
63
|
metadata_get = metadata.get # type: ignore[attr-defined]
|
|
45
64
|
|
|
46
65
|
pkg_metadata = adict(
|
|
@@ -65,11 +84,13 @@ def about(package: str | None = None) -> __adict:
|
|
|
65
84
|
or project_urls.get("Homepage")
|
|
66
85
|
or project_urls.get("Home")),
|
|
67
86
|
__author__ = metadata_get("Author"),
|
|
87
|
+
__email__ = None,
|
|
68
88
|
__author_email__ = metadata_get("Author-email"),
|
|
69
89
|
__maintainer__ = metadata_get("Maintainer"),
|
|
70
90
|
__maintainer_email__ = metadata_get("Maintainer-email"),
|
|
71
91
|
__license__ = (metadata_get("License-Expression")
|
|
72
92
|
or metadata_get("License")),
|
|
93
|
+
__copyright__ = None,
|
|
73
94
|
)
|
|
74
95
|
email = pkg_metadata["__author_email__"] or ""
|
|
75
96
|
names = ", ".join(name for name, _ in getaddresses([email]) if name)
|
|
@@ -94,7 +115,7 @@ def about(package: str | None = None) -> __adict:
|
|
|
94
115
|
return pkg_metadata
|
|
95
116
|
|
|
96
117
|
|
|
97
|
-
def about_from_setup(package_path: Path | str | None = None) ->
|
|
118
|
+
def about_from_setup(package_path: Path | str | None = None) -> adict:
|
|
98
119
|
import sys
|
|
99
120
|
from pathlib import Path
|
|
100
121
|
from packaging.version import parse as parse_version
|
|
@@ -129,7 +150,7 @@ def about_from_setup(package_path: Path | str | None = None) -> __adict:
|
|
|
129
150
|
with pyproject_path.open("rb") as file:
|
|
130
151
|
metadata.update(tomllib.load(file).get("project", {}))
|
|
131
152
|
version = parse_version(metadata["version"])
|
|
132
|
-
|
|
153
|
+
get, release_levels = __get, __release_levels
|
|
133
154
|
|
|
134
155
|
authors = get(metadata, "authors") or []
|
|
135
156
|
maintainers = get(metadata, "maintainers") or []
|
|
@@ -158,6 +179,7 @@ def about_from_setup(package_path: Path | str | None = None) -> __adict:
|
|
|
158
179
|
__author__ = (", ".join(item["name"] for item in authors
|
|
159
180
|
if item and "name" in item)
|
|
160
181
|
or get(metadata, "author")),
|
|
182
|
+
__email__ = None,
|
|
161
183
|
__author_email__ = (", ".join((f"{item['name']} <{item['email']}>"
|
|
162
184
|
if "name" in item and not parseaddr(
|
|
163
185
|
item["email"])[0]
|
|
@@ -177,6 +199,7 @@ def about_from_setup(package_path: Path | str | None = None) -> __adict:
|
|
|
177
199
|
or get(metadata, "maintainer_email")),
|
|
178
200
|
__license__ = (get(metadata, "license", "text")
|
|
179
201
|
or get(metadata, "license")),
|
|
202
|
+
__copyright__ = None,
|
|
180
203
|
)
|
|
181
204
|
pkg_metadata["__email__"] = pkg_metadata["__author_email__"]
|
|
182
205
|
pkg_metadata["__copyright__"] = pkg_metadata["__author__"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pkg_about
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.7
|
|
4
4
|
Summary: Shares Python package metadata at runtime.
|
|
5
5
|
Author-email: Adam Karpierz <adam@karpierz.net>
|
|
6
6
|
Maintainer-email: Adam Karpierz <adam@karpierz.net>
|
|
@@ -41,8 +41,8 @@ Requires-Dist: sphinx-toolbox>=4.0.0; extra == "doc"
|
|
|
41
41
|
Requires-Dist: sphinx-tabs>=3.4.5; extra == "doc"
|
|
42
42
|
Requires-Dist: sphinx-copybutton>=0.5.2; extra == "doc"
|
|
43
43
|
Requires-Dist: sphinxcontrib-spelling>=8.0.1; extra == "doc"
|
|
44
|
-
Requires-Dist: sphinx-lint>=1.0.
|
|
45
|
-
Requires-Dist: restructuredtext-lint>=
|
|
44
|
+
Requires-Dist: sphinx-lint>=1.0.2; extra == "doc"
|
|
45
|
+
Requires-Dist: restructuredtext-lint>=2.0.2; extra == "doc"
|
|
46
46
|
Requires-Dist: nbsphinx>=0.9.7; extra == "doc"
|
|
47
47
|
Provides-Extra: test
|
|
48
48
|
Requires-Dist: deepdiff>=8.6.1; extra == "test"
|
|
@@ -144,7 +144,7 @@ Authors
|
|
|
144
144
|
Changelog
|
|
145
145
|
=========
|
|
146
146
|
|
|
147
|
-
2.0.
|
|
147
|
+
2.0.7 (2025-11-27)
|
|
148
148
|
------------------
|
|
149
149
|
- | Now about() and about_from_setup() return an instance of the adict
|
|
150
150
|
| dictionary with about info (but backward compatibility is preserved).
|
|
@@ -153,6 +153,9 @@ Changelog
|
|
|
153
153
|
- | Workaround for the tox error when pyproject.toml and setup.cfg
|
|
154
154
|
| files coexist.
|
|
155
155
|
- Better parsing of newer metadata versions.
|
|
156
|
+
- | Fixed a bug concerning the 'strict' parameter for the methods
|
|
157
|
+
| email.utils.getaddresses() and email.utils.parseaddr().
|
|
158
|
+
| Thank you! https://github.com/hedesandxlii
|
|
156
159
|
- Mark the package as typed.
|
|
157
160
|
- Add tox's tool.tox.env.cleanup testenv.
|
|
158
161
|
- Setup (dependencies) update.
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import unittest
|
|
5
5
|
import sys
|
|
6
6
|
import os
|
|
7
|
+
import copy
|
|
7
8
|
import stat
|
|
8
9
|
import shutil
|
|
9
10
|
from pathlib import Path
|
|
@@ -11,6 +12,7 @@ from pathlib import Path
|
|
|
11
12
|
from . import test_dir
|
|
12
13
|
|
|
13
14
|
import pkg_about
|
|
15
|
+
from pkg_about._about import adict
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
class MainTestCase(unittest.TestCase):
|
|
@@ -131,3 +133,76 @@ class MainTestCase(unittest.TestCase):
|
|
|
131
133
|
self.assertEqual(about.__license__, "MIT")
|
|
132
134
|
self.assertIs(__copyright__, about.__copyright__)
|
|
133
135
|
self.assertEqual(about.__copyright__, __author__)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class TestAdict(unittest.TestCase):
|
|
139
|
+
|
|
140
|
+
def test_item_assignment(self):
|
|
141
|
+
d = adict()
|
|
142
|
+
self.assertNotIn("x", d)
|
|
143
|
+
d["x"] = 10
|
|
144
|
+
self.assertEqual(d.x, 10)
|
|
145
|
+
self.assertEqual(d["x"], 10)
|
|
146
|
+
|
|
147
|
+
def test_attribute_assignment(self):
|
|
148
|
+
d = adict()
|
|
149
|
+
self.assertNotIn("x", d)
|
|
150
|
+
d.x = 20
|
|
151
|
+
self.assertEqual(d["x"], 20)
|
|
152
|
+
self.assertEqual(d.x, 20)
|
|
153
|
+
|
|
154
|
+
def test_missing_item_raises(self):
|
|
155
|
+
d = adict()
|
|
156
|
+
with self.assertRaises(KeyError):
|
|
157
|
+
_ = d["missing"]
|
|
158
|
+
|
|
159
|
+
def test_missing_attribute_raises(self):
|
|
160
|
+
d = adict()
|
|
161
|
+
with self.assertRaises(AttributeError):
|
|
162
|
+
_ = d.missing
|
|
163
|
+
|
|
164
|
+
def test_item_deletion(self):
|
|
165
|
+
d = adict(x=5)
|
|
166
|
+
self.assertIn("x", d)
|
|
167
|
+
del d["x"]
|
|
168
|
+
self.assertNotIn("x", d)
|
|
169
|
+
|
|
170
|
+
def test_attribute_deletion(self):
|
|
171
|
+
d = adict(x=5)
|
|
172
|
+
self.assertIn("x", d)
|
|
173
|
+
del d.x
|
|
174
|
+
self.assertNotIn("x", d)
|
|
175
|
+
|
|
176
|
+
def test_missing_item_deletion_raises(self):
|
|
177
|
+
d = adict()
|
|
178
|
+
with self.assertRaises(KeyError):
|
|
179
|
+
del d["missing"]
|
|
180
|
+
|
|
181
|
+
def test_missing_attribute_deletion_raises(self):
|
|
182
|
+
d = adict()
|
|
183
|
+
with self.assertRaises(AttributeError):
|
|
184
|
+
del d.missing
|
|
185
|
+
|
|
186
|
+
def test_self_copy_returns_new_instance(self):
|
|
187
|
+
d1 = adict(a=1, b=2)
|
|
188
|
+
d2 = d1.copy()
|
|
189
|
+
self.assertIsInstance(d1, adict)
|
|
190
|
+
self.assertIsInstance(d2, adict)
|
|
191
|
+
self.assertEqual(d2, d1)
|
|
192
|
+
self.assertIsNot(d1, d2)
|
|
193
|
+
|
|
194
|
+
def test_copy_returns_new_instance(self):
|
|
195
|
+
d1 = adict(a=1, b=2)
|
|
196
|
+
d2 = copy.copy(d1)
|
|
197
|
+
self.assertIsInstance(d1, adict)
|
|
198
|
+
self.assertIsInstance(d2, adict)
|
|
199
|
+
self.assertEqual(d2, d1)
|
|
200
|
+
self.assertIsNot(d1, d2)
|
|
201
|
+
|
|
202
|
+
def test_fromkeys_creates_instance(self):
|
|
203
|
+
d = adict.fromkeys(["a", "b"], 0)
|
|
204
|
+
self.assertIsInstance(d, adict)
|
|
205
|
+
self.assertEqual(d["a"], 0)
|
|
206
|
+
self.assertEqual(d.a, 0)
|
|
207
|
+
self.assertEqual(d["b"], 0)
|
|
208
|
+
self.assertEqual(d.b, 0)
|
|
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
|
|
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
|
|
File without changes
|