pkg-about 2.0.2__tar.gz → 2.0.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.
Files changed (28) hide show
  1. {pkg_about-2.0.2 → pkg_about-2.0.4}/CHANGES.rst +2 -1
  2. {pkg_about-2.0.2 → pkg_about-2.0.4}/PKG-INFO +6 -6
  3. {pkg_about-2.0.2 → pkg_about-2.0.4}/pyproject.toml +5 -6
  4. {pkg_about-2.0.2 → pkg_about-2.0.4}/src/pkg_about/_about.py +47 -13
  5. {pkg_about-2.0.2 → pkg_about-2.0.4}/src/pkg_about.egg-info/PKG-INFO +6 -6
  6. {pkg_about-2.0.2 → pkg_about-2.0.4}/src/pkg_about.egg-info/requires.txt +1 -0
  7. {pkg_about-2.0.2 → pkg_about-2.0.4}/tests/test_main.py +40 -6
  8. {pkg_about-2.0.2 → pkg_about-2.0.4}/.readthedocs.yml +0 -0
  9. {pkg_about-2.0.2 → pkg_about-2.0.4}/LICENSE +0 -0
  10. {pkg_about-2.0.2 → pkg_about-2.0.4}/MANIFEST.in +0 -0
  11. {pkg_about-2.0.2 → pkg_about-2.0.4}/README.rst +0 -0
  12. {pkg_about-2.0.2 → pkg_about-2.0.4}/docs/CHANGES.rst +0 -0
  13. {pkg_about-2.0.2 → pkg_about-2.0.4}/docs/README.rst +0 -0
  14. {pkg_about-2.0.2 → pkg_about-2.0.4}/docs/_static/.keep +0 -0
  15. {pkg_about-2.0.2 → pkg_about-2.0.4}/docs/_templates/.keep +0 -0
  16. {pkg_about-2.0.2 → pkg_about-2.0.4}/docs/conf.py +0 -0
  17. {pkg_about-2.0.2 → pkg_about-2.0.4}/docs/index.rst +0 -0
  18. {pkg_about-2.0.2 → pkg_about-2.0.4}/setup.cfg +0 -0
  19. {pkg_about-2.0.2 → pkg_about-2.0.4}/src/pkg_about/__about__.py +0 -0
  20. {pkg_about-2.0.2 → pkg_about-2.0.4}/src/pkg_about/__init__.py +0 -0
  21. {pkg_about-2.0.2 → pkg_about-2.0.4}/src/pkg_about/py.typed +0 -0
  22. {pkg_about-2.0.2 → pkg_about-2.0.4}/src/pkg_about.egg-info/SOURCES.txt +0 -0
  23. {pkg_about-2.0.2 → pkg_about-2.0.4}/src/pkg_about.egg-info/dependency_links.txt +0 -0
  24. {pkg_about-2.0.2 → pkg_about-2.0.4}/src/pkg_about.egg-info/top_level.txt +0 -0
  25. {pkg_about-2.0.2 → pkg_about-2.0.4}/src/pkg_about.egg-info/zip-safe +0 -0
  26. {pkg_about-2.0.2 → pkg_about-2.0.4}/tests/__init__.py +0 -0
  27. {pkg_about-2.0.2 → pkg_about-2.0.4}/tests/__main__.py +0 -0
  28. {pkg_about-2.0.2 → pkg_about-2.0.4}/tests/data/setup.cfg +0 -0
@@ -1,7 +1,7 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
- 2.0.2 (2025-10-10)
4
+ 2.0.4 (2025-11-08)
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).
@@ -9,6 +9,7 @@ Changelog
9
9
  | instead of a class (but backward compatibility is preserved).
10
10
  - | Workaround for the tox error when pyproject.toml and setup.cfg
11
11
  | files coexist.
12
+ - Better parsing of newer metadata versions.
12
13
  - Mark the package as typed.
13
14
  - Add tox's tool.tox.env.cleanup testenv.
14
15
  - Setup (dependencies) update.
@@ -1,11 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pkg_about
3
- Version: 2.0.2
3
+ Version: 2.0.4
4
4
  Summary: Shares Python package metadata at runtime.
5
- Author: Adam Karpierz
6
- Author-email: adam@karpierz.net
7
- Maintainer: Adam Karpierz
8
- Maintainer-email: adam@karpierz.net
5
+ Author-email: Adam Karpierz <adam@karpierz.net>
6
+ Maintainer-email: Adam Karpierz <adam@karpierz.net>
9
7
  License-Expression: Zlib
10
8
  Project-URL: Homepage, https://pypi.org/project/pkg-about/
11
9
  Project-URL: Documentation, https://pkg-about.readthedocs.io/
@@ -49,6 +47,7 @@ Requires-Dist: nbsphinx>=0.9.7; extra == "doc"
49
47
  Provides-Extra: test
50
48
  Requires-Dist: deepdiff>=8.6.1; extra == "test"
51
49
  Requires-Dist: rich>=14.2.0; extra == "test"
50
+ Requires-Dist: appdirs==1.4.4; extra == "test"
52
51
  Dynamic: license-file
53
52
 
54
53
  pkg_about
@@ -145,7 +144,7 @@ Authors
145
144
  Changelog
146
145
  =========
147
146
 
148
- 2.0.2 (2025-10-10)
147
+ 2.0.4 (2025-11-08)
149
148
  ------------------
150
149
  - | Now about() and about_from_setup() return an instance of the adict
151
150
  | dictionary with about info (but backward compatibility is preserved).
@@ -153,6 +152,7 @@ Changelog
153
152
  | instead of a class (but backward compatibility is preserved).
154
153
  - | Workaround for the tox error when pyproject.toml and setup.cfg
155
154
  | files coexist.
155
+ - Better parsing of newer metadata versions.
156
156
  - Mark the package as typed.
157
157
  - Add tox's tool.tox.env.cleanup testenv.
158
158
  - Setup (dependencies) update.
@@ -7,15 +7,13 @@ 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.2'
10
+ version = '2.0.4'
11
11
  description = 'Shares Python package metadata at runtime.'
12
12
  authors = [
13
- { name = 'Adam Karpierz' },
14
- { email = 'adam@karpierz.net' },
13
+ { name = 'Adam Karpierz', email = 'adam@karpierz.net' },
15
14
  ]
16
15
  maintainers = [
17
- { name = 'Adam Karpierz' },
18
- { email = 'adam@karpierz.net' },
16
+ { name = 'Adam Karpierz', email = 'adam@karpierz.net' },
19
17
  ]
20
18
  license = 'Zlib'
21
19
  license-files = ['LICENSE']
@@ -66,6 +64,7 @@ optional-dependencies.'doc' = [
66
64
  optional-dependencies.'test' = [
67
65
  'deepdiff>=8.6.1',
68
66
  'rich>=14.2.0',
67
+ 'appdirs==1.4.4',
69
68
  ]
70
69
 
71
70
  [project.scripts]
@@ -253,7 +252,7 @@ commands = [
253
252
  ]
254
253
  deps = [
255
254
  {replace='ref',of=['tool','tox','env_run_base','deps'],extend=true},
256
- 'coverage>=7.11.0',
255
+ 'coverage>=7.11.1',
257
256
  'covdefaults>=2.3.0',
258
257
  'diff-cover>=9.7.1',
259
258
  ]
@@ -3,9 +3,17 @@
3
3
 
4
4
  __all__ = ('about', 'about_from_setup')
5
5
 
6
+ import sys
6
7
  from typing import Any
7
8
  from pathlib import Path
8
9
  from collections import namedtuple
10
+ from functools import partial
11
+ from email.utils import getaddresses, parseaddr
12
+
13
+ if sys.version_info >= (3, 12):
14
+ getaddresses = partial(getaddresses, strict=False)
15
+ parseaddr = partial(parseaddr, strict=False)
16
+ else: pass # pragma: no cover
9
17
 
10
18
  version_info = namedtuple("version_info",
11
19
  ["major", "minor", "micro", "releaselevel", "serial"],
@@ -16,8 +24,7 @@ class __adict(dict[str, Any]):
16
24
  __getattr__ = dict.__getitem__
17
25
  __setattr__ = dict.__setitem__
18
26
  __delattr__ = dict.__delitem__
19
- __copy__ = lambda self: self.__class__(self)
20
- copy = lambda self: self.copy()
27
+ copy = __copy__ = lambda self: self.__class__(self)
21
28
 
22
29
 
23
30
  def about(package: str | None = None) -> __adict:
@@ -58,14 +65,28 @@ def about(package: str | None = None) -> __adict:
58
65
  or project_urls.get("Homepage")
59
66
  or project_urls.get("Home")),
60
67
  __author__ = metadata_get("Author"),
61
- __email__ = metadata_get("Author-email"),
62
68
  __author_email__ = metadata_get("Author-email"),
63
69
  __maintainer__ = metadata_get("Maintainer"),
64
70
  __maintainer_email__ = metadata_get("Maintainer-email"),
65
71
  __license__ = (metadata_get("License-Expression")
66
72
  or metadata_get("License")),
67
- __copyright__ = metadata_get("Author"),
68
73
  )
74
+ email = pkg_metadata["__author_email__"] or ""
75
+ names = ", ".join(name for name, _ in getaddresses([email]) if name)
76
+ if names:
77
+ if not pkg_metadata["__author__"]:
78
+ pkg_metadata["__author__"] = names
79
+ else: # pragma: no cover
80
+ pkg_metadata["__author__"] += ", " + names
81
+ email = pkg_metadata["__maintainer_email__"] or ""
82
+ names = ", ".join(name for name, _ in getaddresses([email]) if name)
83
+ if names:
84
+ if not pkg_metadata["__maintainer__"]:
85
+ pkg_metadata["__maintainer__"] = names
86
+ else: # pragma: no cover
87
+ pkg_metadata["__maintainer__"] += ", " + names
88
+ pkg_metadata["__email__"] = pkg_metadata["__author_email__"]
89
+ pkg_metadata["__copyright__"] = pkg_metadata["__author__"]
69
90
 
70
91
  pkg_globals.update(pkg_metadata)
71
92
  pkg_globals.setdefault("__all__", [])
@@ -110,6 +131,9 @@ def about_from_setup(package_path: Path | str | None = None) -> __adict:
110
131
  version = parse_version(metadata["version"])
111
132
  adict, get, release_levels = __adict, __get, __release_levels
112
133
 
134
+ authors = get(metadata, "authors") or []
135
+ maintainers = get(metadata, "maintainers") or []
136
+
113
137
  pkg_metadata = adict(
114
138
  __title__ = metadata["name"],
115
139
  __version__ = str(version),
@@ -131,21 +155,31 @@ def about_from_setup(package_path: Path | str | None = None) -> __adict:
131
155
  or get(metadata, "urls", "Homepage")
132
156
  or get(metadata, "urls", "Home")
133
157
  or get(metadata, "url")),
134
- __author__ = (get(metadata, "authors", 0, "name")
158
+ __author__ = (", ".join(item["name"] for item in authors
159
+ if item and "name" in item)
135
160
  or get(metadata, "author")),
136
- __email__ = (get(metadata, "authors", 1, "email")
137
- or get(metadata, "author_email")),
138
- __author_email__ = (get(metadata, "authors", 1, "email")
161
+ __author_email__ = (", ".join((f"{item['name']} <{item['email']}>"
162
+ if "name" in item and not parseaddr(
163
+ item["email"])[0]
164
+ else item["email"])
165
+ for item in authors
166
+ if item and "email" in item)
139
167
  or get(metadata, "author_email")),
140
- __maintainer__ = (get(metadata, "maintainers", 0, "name")
141
- or get(metadata, "maintainer")),
142
- __maintainer_email__ = (get(metadata, "maintainers", 1, "email")
168
+ __maintainer__ = (", ".join(item["name"] for item in maintainers
169
+ if item and "name" in item)
170
+ or get(metadata, "maintainer")),
171
+ __maintainer_email__ = (", ".join((f"{item['name']} <{item['email']}>"
172
+ if "name" in item and not parseaddr(
173
+ item["email"])[0]
174
+ else item["email"])
175
+ for item in maintainers
176
+ if item and "email" in item)
143
177
  or get(metadata, "maintainer_email")),
144
178
  __license__ = (get(metadata, "license", "text")
145
179
  or get(metadata, "license")),
146
- __copyright__ = (get(metadata, "authors", 0, "name")
147
- or get(metadata, "author")),
148
180
  )
181
+ pkg_metadata["__email__"] = pkg_metadata["__author_email__"]
182
+ pkg_metadata["__copyright__"] = pkg_metadata["__author__"]
149
183
 
150
184
  pkg_globals["about"] = pkg_metadata
151
185
  pkg_globals.setdefault("__all__", [])
@@ -1,11 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pkg_about
3
- Version: 2.0.2
3
+ Version: 2.0.4
4
4
  Summary: Shares Python package metadata at runtime.
5
- Author: Adam Karpierz
6
- Author-email: adam@karpierz.net
7
- Maintainer: Adam Karpierz
8
- Maintainer-email: adam@karpierz.net
5
+ Author-email: Adam Karpierz <adam@karpierz.net>
6
+ Maintainer-email: Adam Karpierz <adam@karpierz.net>
9
7
  License-Expression: Zlib
10
8
  Project-URL: Homepage, https://pypi.org/project/pkg-about/
11
9
  Project-URL: Documentation, https://pkg-about.readthedocs.io/
@@ -49,6 +47,7 @@ Requires-Dist: nbsphinx>=0.9.7; extra == "doc"
49
47
  Provides-Extra: test
50
48
  Requires-Dist: deepdiff>=8.6.1; extra == "test"
51
49
  Requires-Dist: rich>=14.2.0; extra == "test"
50
+ Requires-Dist: appdirs==1.4.4; extra == "test"
52
51
  Dynamic: license-file
53
52
 
54
53
  pkg_about
@@ -145,7 +144,7 @@ Authors
145
144
  Changelog
146
145
  =========
147
146
 
148
- 2.0.2 (2025-10-10)
147
+ 2.0.4 (2025-11-08)
149
148
  ------------------
150
149
  - | Now about() and about_from_setup() return an instance of the adict
151
150
  | dictionary with about info (but backward compatibility is preserved).
@@ -153,6 +152,7 @@ Changelog
153
152
  | instead of a class (but backward compatibility is preserved).
154
153
  - | Workaround for the tox error when pyproject.toml and setup.cfg
155
154
  | files coexist.
155
+ - Better parsing of newer metadata versions.
156
156
  - Mark the package as typed.
157
157
  - Add tox's tool.tox.env.cleanup testenv.
158
158
  - Setup (dependencies) update.
@@ -18,3 +18,4 @@ nbsphinx>=0.9.7
18
18
  [test]
19
19
  deepdiff>=8.6.1
20
20
  rich>=14.2.0
21
+ appdirs==1.4.4
@@ -58,13 +58,13 @@ class MainTestCase(unittest.TestCase):
58
58
  self.assertIs(__author__, about.__author__)
59
59
  self.assertEqual(about.__author__, "Adam Karpierz")
60
60
  self.assertIs(__email__, about.__email__)
61
- self.assertEqual(about.__email__, "adam@karpierz.net")
61
+ self.assertEqual(about.__email__, about.__author_email__)
62
62
  self.assertIs(__author_email__, about.__author_email__)
63
- self.assertEqual(about.__author_email__, "adam@karpierz.net")
63
+ self.assertEqual(about.__author_email__, "Adam Karpierz <adam@karpierz.net>")
64
64
  self.assertIs(__maintainer__, about.__maintainer__)
65
65
  self.assertEqual(about.__maintainer__, "Adam Karpierz")
66
66
  self.assertIs(__maintainer_email__, about.__maintainer_email__)
67
- self.assertEqual(about.__maintainer_email__, "adam@karpierz.net")
67
+ self.assertEqual(about.__maintainer_email__, "Adam Karpierz <adam@karpierz.net>")
68
68
  self.assertIs(__license__, about.__license__)
69
69
  self.assertEqual(about.__license__, "Zlib")
70
70
  self.assertIs(__copyright__, about.__copyright__)
@@ -88,12 +88,46 @@ class MainTestCase(unittest.TestCase):
88
88
  self.assertEqual(about.__summary__, "Shares Python package metadata at runtime.")
89
89
  self.assertEqual(about.__uri__, "https://pypi.org/project/pkg-about/")
90
90
  self.assertEqual(about.__author__, "Adam Karpierz")
91
- self.assertEqual(about.__email__, "adam@karpierz.net")
92
- self.assertEqual(about.__author_email__, "adam@karpierz.net")
91
+ self.assertEqual(about.__email__, about.__author_email__)
92
+ self.assertEqual(about.__author_email__, "Adam Karpierz <adam@karpierz.net>")
93
93
  self.assertEqual(about.__maintainer__, "Adam Karpierz")
94
- self.assertEqual(about.__maintainer_email__, "adam@karpierz.net")
94
+ self.assertEqual(about.__maintainer_email__, "Adam Karpierz <adam@karpierz.net>")
95
95
  self.assertEqual(about.__license__, "Zlib")
96
96
  self.assertEqual(about.__copyright__, about.__author__)
97
97
  finally:
98
98
  os.chmod(setup_cfg, stat.S_IWRITE)
99
99
  setup_cfg.unlink()
100
+
101
+ def test_about_appdirs(self):
102
+ about = pkg_about.about("appdirs")
103
+ self.assertIsInstance(about, dict)
104
+ self.assertIs(__title__, about.__title__)
105
+ self.assertEqual(about.__title__, "appdirs")
106
+ self.assertIs(__version__, about.__version__)
107
+ self.assertEqual(about.__version__, "1.4.4")
108
+ self.assertIs(__version_info__, about.__version_info__)
109
+ self.assertTrue(self.is_namedtuple_instance(about.__version_info__))
110
+ self.assertEqual(about.__version_info__.major, 1)
111
+ self.assertEqual(about.__version_info__.minor, 4)
112
+ self.assertEqual(about.__version_info__.micro, 4)
113
+ self.assertEqual(about.__version_info__.releaselevel, "final")
114
+ self.assertEqual(about.__version_info__.serial, 0)
115
+ self.assertIs(__summary__, about.__summary__)
116
+ self.assertEqual(about.__summary__, ('A small Python module for determining appropriate'
117
+ ' platform-specific dirs, e.g. a "user data dir".'))
118
+ self.assertIs(__uri__, about.__uri__)
119
+ self.assertEqual(about.__uri__, "http://github.com/ActiveState/appdirs")
120
+ self.assertIs(__author__, about.__author__)
121
+ self.assertEqual(about.__author__, "Trent Mick")
122
+ self.assertIs(__email__, about.__email__)
123
+ self.assertEqual(about.__email__, about.__author_email__)
124
+ self.assertIs(__author_email__, about.__author_email__)
125
+ self.assertEqual(about.__author_email__, "trentm@gmail.com")
126
+ self.assertIs(__maintainer__, about.__maintainer__)
127
+ self.assertEqual(about.__maintainer__, "Jeff Rouse")
128
+ self.assertIs(__maintainer_email__, about.__maintainer_email__)
129
+ self.assertEqual(about.__maintainer_email__, "jr@its.to")
130
+ self.assertIs(__license__, about.__license__)
131
+ self.assertEqual(about.__license__, "MIT")
132
+ self.assertIs(__copyright__, about.__copyright__)
133
+ self.assertEqual(about.__copyright__, __author__)
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