Skip to content

Commit 51568a1

Browse files
committed
Add as_json function. Fixes #277.
1 parent 69f366c commit 51568a1

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

importlib_metadata/__init__.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import sys
66
import zipp
77
import email
8+
import string
89
import pathlib
910
import operator
1011
import textwrap
@@ -919,3 +920,43 @@ def packages_distributions() -> Mapping[str, List[str]]:
919920
for pkg in (dist.read_text('top_level.txt') or '').split():
920921
pkg_to_dist[pkg].append(dist.metadata['Name'])
921922
return dict(pkg_to_dist)
923+
924+
925+
def as_json(metadata: PackageMetadata):
926+
"""
927+
Convert PackageMetadata to a JSON-compatible format
928+
per PEP 0566.
929+
"""
930+
# TODO: Need to match case-insensitive
931+
multiple_use = {
932+
'Classifier',
933+
'Obsoletes-Dist',
934+
'Platform',
935+
'Project-URL',
936+
'Provides-Dist',
937+
'Provides-Extra',
938+
'Requires-Dist',
939+
'Requires-External',
940+
'Supported-Platform',
941+
}
942+
943+
def redent(value):
944+
"Correct for RFC822 indentation"
945+
if not value or '\n' not in value:
946+
return value
947+
return textwrap.dedent(' ' * 8 + value)
948+
949+
def transform(key):
950+
value = (
951+
metadata.get_all(key) if key in multiple_use else redent(metadata.get(key))
952+
)
953+
if key == 'Keywords':
954+
value = value.split(string.whitespace)
955+
if not value and key == 'Description':
956+
value = metadata.get_payload()
957+
tk = key.lower().replace('-', '_')
958+
return tk, value
959+
960+
desc = ['Description'] if metadata.get_payload() else [] # type: ignore
961+
keys = itertools.chain(metadata, desc) # type: ignore
962+
return dict(map(transform, keys)) # type: ignore

tests/test_api.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from importlib_metadata import (
99
Distribution,
1010
PackageNotFoundError,
11+
as_json,
1112
distribution,
1213
entry_points,
1314
files,
@@ -246,6 +247,18 @@ def test_more_complex_deps_requires_text(self):
246247

247248
assert deps == expected
248249

250+
def test_as_json(self):
251+
md = as_json(metadata('distinfo-pkg'))
252+
assert 'name' in md
253+
desc = md['description']
254+
assert desc.startswith('Once upon a time\nThere was')
255+
256+
def test_as_json_egg_info(self):
257+
md = as_json(metadata('egginfo-pkg'))
258+
assert 'name' in md
259+
desc = md['description']
260+
assert desc.startswith('Once upon a time\nThere was')
261+
249262

250263
class LegacyDots(fixtures.DistInfoPkgWithDotLegacy, unittest.TestCase):
251264
def test_name_normalization(self):

0 commit comments

Comments
 (0)