Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb67ac80

Browse files
committed
Merge tag 'v8.7.0' into cpython
2 parents55c9652 +708dff4 commitb67ac80

File tree

11 files changed

+284
-118
lines changed

11 files changed

+284
-118
lines changed

‎Lib/importlib/metadata/__init__.py‎

Lines changed: 143 additions & 62 deletions
Large diffs are not rendered by default.

‎Lib/importlib/metadata/_adapters.py‎

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,58 @@
1+
importemail.message
2+
importemail.policy
13
importre
24
importtextwrap
3-
importemail.message
45

56
from ._textimportFoldedCase
67

78

9+
classRawPolicy(email.policy.EmailPolicy):
10+
deffold(self,name,value):
11+
folded=self.linesep.join(
12+
textwrap.indent(value,prefix=' '*8,predicate=lambdaline:True)
13+
.lstrip()
14+
.splitlines()
15+
)
16+
returnf'{name}:{folded}{self.linesep}'
17+
18+
819
classMessage(email.message.Message):
20+
r"""
21+
Specialized Message subclass to handle metadata naturally.
22+
23+
Reads values that may have newlines in them and converts the
24+
payload to the Description.
25+
26+
>>> msg_text = textwrap.dedent('''
27+
... Name: Foo
28+
... Version: 3.0
29+
... License: blah
30+
... de-blah
31+
... <BLANKLINE>
32+
... First line of description.
33+
... Second line of description.
34+
... <BLANKLINE>
35+
... Fourth line!
36+
... ''').lstrip().replace('<BLANKLINE>', '')
37+
>>> msg = Message(email.message_from_string(msg_text))
38+
>>> msg['Description']
39+
'First line of description.\nSecond line of description.\n\nFourth line!\n'
40+
41+
Message should render even if values contain newlines.
42+
43+
>>> print(msg)
44+
Name: Foo
45+
Version: 3.0
46+
License: blah
47+
de-blah
48+
Description: First line of description.
49+
Second line of description.
50+
<BLANKLINE>
51+
Fourth line!
52+
<BLANKLINE>
53+
<BLANKLINE>
54+
"""
55+
956
multiple_use_keys=set(
1057
map(
1158
FoldedCase,
@@ -57,15 +104,20 @@ def __getitem__(self, item):
57104
def_repair_headers(self):
58105
defredent(value):
59106
"Correct for RFC822 indentation"
60-
ifnotvalueor'\n'notinvalue:
107+
indent=' '*8
108+
ifnotvalueor'\n'+indentnotinvalue:
61109
returnvalue
62-
returntextwrap.dedent(' '*8+value)
110+
returntextwrap.dedent(indent+value)
63111

64112
headers= [(key,redent(value))forkey,valueinvars(self)['_headers']]
65113
ifself._payload:
66114
headers.append(('Description',self.get_payload()))
115+
self.set_payload('')
67116
returnheaders
68117

118+
defas_string(self):
119+
returnsuper().as_string(policy=RawPolicy())
120+
69121
@property
70122
defjson(self):
71123
"""

‎Lib/importlib/metadata/_collections.py‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
importcollections
2+
importtyping
23

34

45
# from jaraco.collections 3.3
@@ -24,7 +25,10 @@ def freeze(self):
2425
self._frozen=lambdakey:self.default_factory()
2526

2627

27-
classPair(collections.namedtuple('Pair','name value')):
28+
classPair(typing.NamedTuple):
29+
name:str
30+
value:str
31+
2832
@classmethod
2933
defparse(cls,text):
3034
returncls(*map(str.strip,text.split("=",1)))

‎Lib/importlib/metadata/_functools.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
importtypes
21
importfunctools
2+
importtypes
33

44

55
# from jaraco.functools 3.3

‎Lib/importlib/metadata/_meta.py‎

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
from __future__importannotations
22

33
importos
4-
fromtypingimportProtocol
5-
fromtypingimportAny,Dict,Iterator,List,Optional,TypeVar,Union,overload
6-
4+
fromcollections.abcimportIterator
5+
fromtypingimport (
6+
Any,
7+
Protocol,
8+
TypeVar,
9+
overload,
10+
)
711

812
_T=TypeVar("_T")
913

@@ -20,25 +24,25 @@ def __iter__(self) -> Iterator[str]: ... # pragma: no cover
2024
@overload
2125
defget(
2226
self,name:str,failobj:None=None
23-
)->Optional[str]: ...# pragma: no cover
27+
)->str|None: ...# pragma: no cover
2428

2529
@overload
26-
defget(self,name:str,failobj:_T)->Union[str,_T]: ...# pragma: no cover
30+
defget(self,name:str,failobj:_T)->str|_T: ...# pragma: no cover
2731

2832
# overload per python/importlib_metadata#435
2933
@overload
3034
defget_all(
3135
self,name:str,failobj:None=None
32-
)->Optional[List[Any]]: ...# pragma: no cover
36+
)->list[Any]|None: ...# pragma: no cover
3337

3438
@overload
35-
defget_all(self,name:str,failobj:_T)->Union[List[Any],_T]:
39+
defget_all(self,name:str,failobj:_T)->list[Any]|_T:
3640
"""
3741
Return all values associated with a possibly multi-valued key.
3842
"""
3943

4044
@property
41-
defjson(self)->Dict[str,Union[str,List[str]]]:
45+
defjson(self)->dict[str,str|list[str]]:
4246
"""
4347
A JSON-compatible form of the metadata.
4448
"""
@@ -50,11 +54,11 @@ class SimplePath(Protocol):
5054
"""
5155

5256
defjoinpath(
53-
self,other:Union[str,os.PathLike[str]]
57+
self,other:str|os.PathLike[str]
5458
)->SimplePath: ...# pragma: no cover
5559

5660
def__truediv__(
57-
self,other:Union[str,os.PathLike[str]]
61+
self,other:str|os.PathLike[str]
5862
)->SimplePath: ...# pragma: no cover
5963

6064
@property

‎Lib/importlib/metadata/_typing.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
importfunctools
2+
importtyping
3+
4+
from ._metaimportPackageMetadata
5+
6+
md_none=functools.partial(typing.cast,PackageMetadata)
7+
"""
8+
Suppress type errors for optional metadata.
9+
10+
Although Distribution.metadata can return None when metadata is corrupt
11+
and thus None, allow callers to assume it's not None and crash if
12+
that's the case.
13+
14+
# python/importlib_metadata#493
15+
"""

‎Lib/test/test_importlib/metadata/_path.py‎

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
# from jaraco.path 3.7
1+
# from jaraco.path 3.7.2
2+
3+
from __future__importannotations
24

35
importfunctools
46
importpathlib
5-
fromtypingimportDict,Protocol,Union
6-
fromtypingimportruntime_checkable
7+
fromcollections.abcimportMapping
8+
fromtypingimportTYPE_CHECKING,Protocol,Union,runtime_checkable
9+
10+
ifTYPE_CHECKING:
11+
fromtyping_extensionsimportSelf
712

813

914
classSymlink(str):
@@ -12,29 +17,25 @@ class Symlink(str):
1217
"""
1318

1419

15-
FilesSpec=Dict[str,Union[str,bytes,Symlink,'FilesSpec']]# type: ignore
20+
FilesSpec=Mapping[str,Union[str,bytes,Symlink,'FilesSpec']]
1621

1722

1823
@runtime_checkable
1924
classTreeMaker(Protocol):
20-
def__truediv__(self,*args,**kwargs): ...# pragma: no cover
21-
22-
defmkdir(self,**kwargs): ...# pragma: no cover
23-
24-
defwrite_text(self,content,**kwargs): ...# pragma: no cover
25-
26-
defwrite_bytes(self,content): ...# pragma: no cover
27-
28-
defsymlink_to(self,target): ...# pragma: no cover
25+
def__truediv__(self,other,/)->Self: ...
26+
defmkdir(self,*,exist_ok)->object: ...
27+
defwrite_text(self,content,/,*,encoding)->object: ...
28+
defwrite_bytes(self,content,/)->object: ...
29+
defsymlink_to(self,target,/)->object: ...
2930

3031

31-
def_ensure_tree_maker(obj:Union[str,TreeMaker])->TreeMaker:
32-
returnobjifisinstance(obj,TreeMaker)elsepathlib.Path(obj)# type: ignore
32+
def_ensure_tree_maker(obj:str|TreeMaker)->TreeMaker:
33+
returnobjifisinstance(obj,TreeMaker)elsepathlib.Path(obj)
3334

3435

3536
defbuild(
3637
spec:FilesSpec,
37-
prefix:Union[str,TreeMaker]=pathlib.Path(),# type: ignore
38+
prefix:str|TreeMaker=pathlib.Path(),
3839
):
3940
"""
4041
Build a set of files/directories, as described by the spec.
@@ -66,23 +67,24 @@ def build(
6667

6768

6869
@functools.singledispatch
69-
defcreate(content:Union[str,bytes,FilesSpec],path):
70+
defcreate(content:str|bytes|FilesSpec,path:TreeMaker)->None:
7071
path.mkdir(exist_ok=True)
71-
build(content,prefix=path)# type: ignore
72+
# Mypy only looks at the signature of the main singledispatch method. So it must contain the complete Union
73+
build(content,prefix=path)# type: ignore[arg-type] # python/mypy#11727
7274

7375

7476
@create.register
75-
def_(content:bytes,path):
77+
def_(content:bytes,path:TreeMaker)->None:
7678
path.write_bytes(content)
7779

7880

7981
@create.register
80-
def_(content:str,path):
82+
def_(content:str,path:TreeMaker)->None:
8183
path.write_text(content,encoding='utf-8')
8284

8385

8486
@create.register
85-
def_(content:Symlink,path):
87+
def_(content:Symlink,path:TreeMaker)->None:
8688
path.symlink_to(content)
8789

8890

‎Lib/test/test_importlib/metadata/fixtures.py‎

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
importsys
1+
importcontextlib
22
importcopy
3+
importfunctools
34
importjson
4-
importshutil
55
importpathlib
6+
importshutil
7+
importsys
68
importtextwrap
7-
importfunctools
8-
importcontextlib
99

1010
fromtest.supportimportimport_helper
1111
fromtest.supportimportos_helper
@@ -14,14 +14,10 @@
1414
from .import_path
1515
from ._pathimportFilesSpec
1616

17-
18-
try:
19-
fromimportlibimportresources# type: ignore
20-
21-
getattr(resources,'files')
22-
getattr(resources,'as_file')
23-
except (ImportError,AttributeError):
24-
importimportlib_resourcesasresources# type: ignore
17+
ifsys.version_info>= (3,9):
18+
fromimportlibimportresources
19+
else:
20+
importimportlib_resourcesasresources
2521

2622

2723
@contextlib.contextmanager

‎Lib/test/test_importlib/metadata/test_api.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1+
importimportlib
12
importre
23
importtextwrap
34
importunittest
4-
importimportlib
55

6-
from .importfixtures
76
fromimportlib.metadataimport (
87
Distribution,
98
PackageNotFoundError,
@@ -15,6 +14,8 @@
1514
version,
1615
)
1716

17+
from .importfixtures
18+
1819

1920
classAPITests(
2021
fixtures.EggInfoPkg,

‎Lib/test/test_importlib/metadata/test_main.py‎

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
1-
importre
1+
importimportlib
22
importpickle
3+
importre
34
importunittest
4-
importimportlib
5-
importimportlib.metadata
65
fromtest.supportimportos_helper
76

87
try:
98
importpyfakefs.fake_filesystem_unittestasffs
109
exceptImportError:
1110
from .stubsimportfake_filesystem_unittestasffs
1211

13-
from .importfixtures
14-
from ._pathimportSymlink
1512
fromimportlib.metadataimport (
1613
Distribution,
1714
EntryPoint,
@@ -24,6 +21,9 @@
2421
version,
2522
)
2623

24+
from .importfixtures
25+
from ._pathimportSymlink
26+
2727

2828
classBasicTests(fixtures.DistInfoPkg,unittest.TestCase):
2929
version_pattern=r'\d+\.\d+(\.\d)?'
@@ -157,6 +157,16 @@ def test_valid_dists_preferred(self):
157157
dist=Distribution.from_name('foo')
158158
assertdist.version=="1.0"
159159

160+
deftest_missing_metadata(self):
161+
"""
162+
Dists with a missing metadata file should return None.
163+
164+
Ref python/importlib_metadata#493.
165+
"""
166+
fixtures.build_files(self.make_pkg('foo-4.3',files={}),self.site_dir)
167+
assertDistribution.from_name('foo').metadataisNone
168+
assertmetadata('foo')isNone
169+
160170

161171
classNonASCIITests(fixtures.OnSysPath,fixtures.SiteDir,unittest.TestCase):
162172
@staticmethod

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp