|
28 | 28 | from pip._internal.models.format_control import FormatControl |
29 | 29 | from pip._internal.models.index import PyPI |
30 | 30 | from pip._internal.models.target_python import TargetPython |
| 31 | +from pip._internal.utils.datetime import parse_iso_datetime |
31 | 32 | from pip._internal.utils.hashes import STRONG_HASHES |
32 | 33 | from pip._internal.utils.misc import strtobool |
33 | 34 |
|
@@ -833,31 +834,51 @@ def _handle_dependency_group( |
833 | 834 | ) |
834 | 835 |
|
835 | 836 |
|
836 | | -def _handle_upload_before( |
| 837 | +def _handle_uploaded_prior_to( |
837 | 838 | option: Option, opt: str, value: str, parser: OptionParser |
838 | 839 | ) -> None: |
839 | 840 | """ |
840 | | - Process a value provided for the --upload-before option. |
| 841 | + This is an optparse.Option callback for the --uploaded-prior-to option. |
841 | 842 |
|
842 | | - This is an optparse.Option callback for the --upload-before option. |
| 843 | + Parses an ISO 8601 datetime string. If no timezone is specified in the string, |
| 844 | + local timezone is used. |
| 845 | +
|
| 846 | + Note: This option only works with indexes that provide upload-time metadata |
| 847 | + as specified in the simple repository API: |
| 848 | + https://packaging.python.org/en/latest/specifications/simple-repository-api/ |
843 | 849 | """ |
844 | 850 | if value is None: |
845 | 851 | return None |
846 | | - upload_before = datetime.datetime.fromisoformat(value) |
847 | | - # Assume local timezone if no offset is given in the ISO string. |
848 | | - if upload_before.tzinfo is None: |
849 | | - upload_before = upload_before.astimezone() |
850 | | - parser.values.upload_before = upload_before |
| 852 | + |
| 853 | + try: |
| 854 | + uploaded_prior_to = parse_iso_datetime(value) |
| 855 | + # Use local timezone if no offset is given in the ISO string. |
| 856 | + if uploaded_prior_to.tzinfo is None: |
| 857 | + uploaded_prior_to = uploaded_prior_to.astimezone() |
| 858 | + parser.values.uploaded_prior_to = uploaded_prior_to |
| 859 | + except ValueError as exc: |
| 860 | + msg = ( |
| 861 | + f"invalid --uploaded-prior-to value: {value!r}: {exc}. " |
| 862 | + f"Expected an ISO 8601 datetime string, " |
| 863 | + f"e.g '2023-01-01' or '2023-01-01T00:00:00Z'" |
| 864 | + ) |
| 865 | + raise_option_error(parser, option=option, msg=msg) |
851 | 866 |
|
852 | 867 |
|
853 | | -upload_before: Callable[..., Option] = partial( |
| 868 | +uploaded_prior_to: Callable[..., Option] = partial( |
854 | 869 | Option, |
855 | | - "--upload-before", |
856 | | - dest="upload_before", |
| 870 | + "--uploaded-prior-to", |
| 871 | + dest="uploaded_prior_to", |
857 | 872 | metavar="datetime", |
858 | 873 | action="callback", |
859 | | - callback=_handle_upload_before, |
860 | | - help="Skip uploads after given time. This should be an ISO 8601 string.", |
| 874 | + callback=_handle_uploaded_prior_to, |
| 875 | + type="str", |
| 876 | + help=( |
| 877 | + "Only consider packages uploaded prior to the given date time. " |
| 878 | + "Accepts ISO 8601 strings (e.g., '2023-01-01T00:00:00Z'). " |
| 879 | + "Uses local timezone if none specified. Only effective when " |
| 880 | + "installing from indexes that provide upload-time metadata." |
| 881 | + ), |
861 | 882 | ) |
862 | 883 |
|
863 | 884 | no_build_isolation: Callable[..., Option] = partial( |
|
0 commit comments