1
1
"""Routines related to PyPI, indexes"""
2
2
3
- from __future__ import annotations
4
-
5
3
import enum
6
4
import functools
7
5
import itertools
@@ -111,6 +109,7 @@ class LinkType(enum.Enum):
111
109
format_invalid = enum .auto ()
112
110
platform_mismatch = enum .auto ()
113
111
requires_python_mismatch = enum .auto ()
112
+ upload_too_late = enum .auto ()
114
113
115
114
116
115
class LinkEvaluator :
@@ -131,7 +130,8 @@ def __init__(
131
130
formats : frozenset [str ],
132
131
target_python : TargetPython ,
133
132
allow_yanked : bool ,
134
- ignore_requires_python : bool | None = None ,
133
+ ignore_requires_python : Optional [bool ] = None ,
134
+ upload_before : Optional [datetime .datetime ] = None ,
135
135
) -> None :
136
136
"""
137
137
:param project_name: The user supplied package name.
@@ -149,6 +149,7 @@ def __init__(
149
149
:param ignore_requires_python: Whether to ignore incompatible
150
150
PEP 503 "data-requires-python" values in HTML links. Defaults
151
151
to False.
152
+ :param upload_before: If set, only allow links prior to the given date.
152
153
"""
153
154
if ignore_requires_python is None :
154
155
ignore_requires_python = False
@@ -158,6 +159,7 @@ def __init__(
158
159
self ._ignore_requires_python = ignore_requires_python
159
160
self ._formats = formats
160
161
self ._target_python = target_python
162
+ self ._upload_before = upload_before
161
163
162
164
self .project_name = project_name
163
165
@@ -176,6 +178,11 @@ def evaluate_link(self, link: Link) -> tuple[LinkType, str]:
176
178
reason = link .yanked_reason or "<none given>"
177
179
return (LinkType .yanked , f"yanked for reason: { reason } " )
178
180
181
+ if link .upload_time is not None and self ._upload_before is not None :
182
+ if link .upload_time > self ._upload_before :
183
+ reason = f"Upload time { link .upload_time } after { self ._upload_before } "
184
+ return (LinkType .upload_too_late , reason )
185
+
179
186
if link .egg_fragment :
180
187
egg_info = link .egg_fragment
181
188
ext = link .ext
@@ -590,9 +597,10 @@ def __init__(
590
597
link_collector : LinkCollector ,
591
598
target_python : TargetPython ,
592
599
allow_yanked : bool ,
593
- format_control : FormatControl | None = None ,
594
- candidate_prefs : CandidatePreferences | None = None ,
595
- ignore_requires_python : bool | None = None ,
600
+ format_control : Optional [FormatControl ] = None ,
601
+ candidate_prefs : Optional [CandidatePreferences ] = None ,
602
+ ignore_requires_python : Optional [bool ] = None ,
603
+ upload_before : Optional [datetime .datetime ] = None ,
596
604
) -> None :
597
605
"""
598
606
This constructor is primarily meant to be used by the create() class
@@ -614,6 +622,7 @@ def __init__(
614
622
self ._ignore_requires_python = ignore_requires_python
615
623
self ._link_collector = link_collector
616
624
self ._target_python = target_python
625
+ self ._upload_before = upload_before
617
626
618
627
self .format_control = format_control
619
628
@@ -636,15 +645,17 @@ def create(
636
645
cls ,
637
646
link_collector : LinkCollector ,
638
647
selection_prefs : SelectionPreferences ,
639
- target_python : TargetPython | None = None ,
640
- ) -> PackageFinder :
648
+ target_python : Optional [TargetPython ] = None ,
649
+ upload_before : Optional [datetime .datetime ] = None ,
650
+ ) -> "PackageFinder" :
641
651
"""Create a PackageFinder.
642
652
643
653
:param selection_prefs: The candidate selection preferences, as a
644
654
SelectionPreferences object.
645
655
:param target_python: The target Python interpreter to use when
646
656
checking compatibility. If None (the default), a TargetPython
647
657
object will be constructed from the running Python.
658
+ :param upload_before: If set, only find links prior to the given date.
648
659
"""
649
660
if target_python is None :
650
661
target_python = TargetPython ()
@@ -661,6 +672,7 @@ def create(
661
672
allow_yanked = selection_prefs .allow_yanked ,
662
673
format_control = selection_prefs .format_control ,
663
674
ignore_requires_python = selection_prefs .ignore_requires_python ,
675
+ upload_before = upload_before ,
664
676
)
665
677
666
678
@property
@@ -739,6 +751,7 @@ def make_link_evaluator(self, project_name: str) -> LinkEvaluator:
739
751
target_python = self ._target_python ,
740
752
allow_yanked = self ._allow_yanked ,
741
753
ignore_requires_python = self ._ignore_requires_python ,
754
+ upload_before = self ._upload_before ,
742
755
)
743
756
744
757
def _sort_links (self , links : Iterable [Link ]) -> list [Link ]:
0 commit comments