5
5
6
6
from __future__ import annotations
7
7
8
+ import datetime
8
9
import functools
9
10
import re
10
11
import urllib .parse
18
19
import tomlkit
19
20
from packaging .requirements import Requirement
20
21
from packaging .specifiers import Specifier
22
+ from tomlkit .items import String
21
23
22
24
from .paths import PYPROJECT_PATH , STUBS_PATH , distribution_path
23
25
@@ -140,6 +142,13 @@ def read_stubtest_settings(distribution: str) -> StubtestSettings:
140
142
)
141
143
142
144
145
+ @final
146
+ @dataclass (frozen = True )
147
+ class ObsoleteMetadata :
148
+ since_version : Annotated [str , "A string representing a specific version" ]
149
+ since_date : Annotated [datetime .date , "A date when the package became obsolete" ]
150
+
151
+
143
152
@final
144
153
@dataclass (frozen = True )
145
154
class StubMetadata :
@@ -154,7 +163,7 @@ class StubMetadata:
154
163
extra_description : str | None
155
164
stub_distribution : Annotated [str , "The name under which the distribution is uploaded to PyPI" ]
156
165
upstream_repository : Annotated [str , "The URL of the upstream repository" ] | None
157
- obsolete_since : Annotated [str , "A string representing a specific version " ] | None
166
+ obsolete : Annotated [ObsoleteMetadata , "Metadata indicating when the stubs package became obsolete " ] | None
158
167
no_longer_updated : bool
159
168
uploaded_to_pypi : Annotated [bool , "Whether or not a distribution is uploaded to PyPI" ]
160
169
partial_stub : Annotated [bool , "Whether this is a partial type stub package as per PEP 561." ]
@@ -163,7 +172,7 @@ class StubMetadata:
163
172
164
173
@property
165
174
def is_obsolete (self ) -> bool :
166
- return self .obsolete_since is not None
175
+ return self .obsolete is not None
167
176
168
177
169
178
_KNOWN_METADATA_FIELDS : Final = frozenset (
@@ -269,7 +278,14 @@ def read_metadata(distribution: str) -> StubMetadata:
269
278
assert num_url_path_parts == 2 , bad_github_url_msg
270
279
271
280
obsolete_since : object = data .get ("obsolete_since" )
272
- assert isinstance (obsolete_since , (str , type (None )))
281
+ assert isinstance (obsolete_since , (String , type (None )))
282
+ if obsolete_since :
283
+ comment = obsolete_since .trivia .comment
284
+ since_date_string = comment .removeprefix ("# Released on " )
285
+ since_date = datetime .date .fromisoformat (since_date_string )
286
+ obsolete = ObsoleteMetadata (since_version = obsolete_since , since_date = since_date )
287
+ else :
288
+ obsolete = None
273
289
no_longer_updated : object = data .get ("no_longer_updated" , False )
274
290
assert type (no_longer_updated ) is bool
275
291
uploaded_to_pypi : object = data .get ("upload" , True )
@@ -308,7 +324,7 @@ def read_metadata(distribution: str) -> StubMetadata:
308
324
extra_description = extra_description ,
309
325
stub_distribution = stub_distribution ,
310
326
upstream_repository = upstream_repository ,
311
- obsolete_since = obsolete_since ,
327
+ obsolete = obsolete ,
312
328
no_longer_updated = no_longer_updated ,
313
329
uploaded_to_pypi = uploaded_to_pypi ,
314
330
partial_stub = partial_stub ,
0 commit comments