Option to resolve at a fixed timestamp with pip-compile --exclude-newer YYYY-MM-DD (#434)

This works by filtering out files with a more recent upload time, so if
the index you use does not provide upload times, the results might be
inaccurate. pypi provides upload times for all files. This is, the field
is non-nullable in the warehouse schema, but the simple API PEP does not
know this field.

If you have only pypi dependencies, this means deterministic,
reproducible(!) resolution. We could try doing the same for git repos
but it doesn't seem worth the effort, i'd recommend pinning commits
since git histories are arbitrarily malleable and also if you care about
reproducibility and such you such not use git dependencies but a custom
index.

Timestamps are given either as RFC 3339 timestamps such as
`2006-12-02T02:07:43Z` or as UTC dates in the same format such as
`2006-12-02`. Dates are interpreted as including this day, i.e. until
midnight UTC that day. Date only is required to make this ergonomic and
midnight seems like an ergonomic choice.

In action for `pandas`:

```console
$ target/debug/puffin pip-compile --exclude-newer 2023-11-16 target/pandas.in
Resolved 6 packages in 679ms
# This file was autogenerated by Puffin v0.0.1 via the following command:
#    target/debug/puffin pip-compile --exclude-newer 2023-11-16 target/pandas.in
numpy==1.26.2
    # via pandas
pandas==2.1.3
python-dateutil==2.8.2
    # via pandas
pytz==2023.3.post1
    # via pandas
six==1.16.0
    # via python-dateutil
tzdata==2023.3
    # via pandas
$ target/debug/puffin pip-compile --exclude-newer 2022-11-16 target/pandas.in
Resolved 5 packages in 655ms
# This file was autogenerated by Puffin v0.0.1 via the following command:
#    target/debug/puffin pip-compile --exclude-newer 2022-11-16 target/pandas.in
numpy==1.23.4
    # via pandas
pandas==1.5.1
python-dateutil==2.8.2
    # via pandas
pytz==2022.6
    # via pandas
six==1.16.0
    # via python-dateutil
$ target/debug/puffin pip-compile --exclude-newer 2021-11-16 target/pandas.in
Resolved 5 packages in 594ms
# This file was autogenerated by Puffin v0.0.1 via the following command:
#    target/debug/puffin pip-compile --exclude-newer 2021-11-16 target/pandas.in
numpy==1.21.4
    # via pandas
pandas==1.3.4
python-dateutil==2.8.2
    # via pandas
pytz==2021.3
    # via pandas
six==1.16.0
    # via python-dateutil
```
This commit is contained in:
konsti 2023-11-16 20:46:17 +01:00 committed by GitHub
parent 0d455ebd06
commit e41ec12239
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 218 additions and 38 deletions

View file

@ -94,6 +94,7 @@ async fn black() -> Result<()> {
ResolutionMode::default(),
PreReleaseMode::default(),
None,
None,
);
let resolution = resolve(manifest, &MARKERS_311, &TAGS_311).await?;
@ -114,6 +115,7 @@ async fn black_colorama() -> Result<()> {
ResolutionMode::default(),
PreReleaseMode::default(),
None,
None,
);
let resolution = resolve(manifest, &MARKERS_311, &TAGS_311).await?;
@ -134,6 +136,7 @@ async fn black_python_310() -> Result<()> {
ResolutionMode::default(),
PreReleaseMode::default(),
None,
None,
);
let resolution = resolve(manifest, &MARKERS_310, &TAGS_310).await?;
@ -156,6 +159,7 @@ async fn black_mypy_extensions() -> Result<()> {
ResolutionMode::default(),
PreReleaseMode::default(),
None,
None,
);
let resolution = resolve(manifest, &MARKERS_311, &TAGS_311).await?;
@ -178,6 +182,7 @@ async fn black_mypy_extensions_extra() -> Result<()> {
ResolutionMode::default(),
PreReleaseMode::default(),
None,
None,
);
let resolution = resolve(manifest, &MARKERS_311, &TAGS_311).await?;
@ -200,6 +205,7 @@ async fn black_flake8() -> Result<()> {
ResolutionMode::default(),
PreReleaseMode::default(),
None,
None,
);
let resolution = resolve(manifest, &MARKERS_311, &TAGS_311).await?;
@ -220,6 +226,7 @@ async fn black_lowest() -> Result<()> {
ResolutionMode::Lowest,
PreReleaseMode::default(),
None,
None,
);
let resolution = resolve(manifest, &MARKERS_311, &TAGS_311).await?;
@ -240,6 +247,7 @@ async fn black_lowest_direct() -> Result<()> {
ResolutionMode::LowestDirect,
PreReleaseMode::default(),
None,
None,
);
let resolution = resolve(manifest, &MARKERS_311, &TAGS_311).await?;
@ -260,6 +268,7 @@ async fn black_respect_preference() -> Result<()> {
ResolutionMode::default(),
PreReleaseMode::default(),
None,
None,
);
let resolution = resolve(manifest, &MARKERS_311, &TAGS_311).await?;
@ -280,6 +289,7 @@ async fn black_ignore_preference() -> Result<()> {
ResolutionMode::default(),
PreReleaseMode::default(),
None,
None,
);
let resolution = resolve(manifest, &MARKERS_311, &TAGS_311).await?;
@ -300,6 +310,7 @@ async fn black_disallow_prerelease() -> Result<()> {
ResolutionMode::default(),
PreReleaseMode::Disallow,
None,
None,
);
let err = resolve(manifest, &MARKERS_311, &TAGS_311)
@ -322,6 +333,7 @@ async fn black_allow_prerelease_if_necessary() -> Result<()> {
ResolutionMode::default(),
PreReleaseMode::IfNecessary,
None,
None,
);
let err = resolve(manifest, &MARKERS_311, &TAGS_311)
@ -344,6 +356,7 @@ async fn pylint_disallow_prerelease() -> Result<()> {
ResolutionMode::default(),
PreReleaseMode::Disallow,
None,
None,
);
let resolution = resolve(manifest, &MARKERS_311, &TAGS_311).await?;
@ -364,6 +377,7 @@ async fn pylint_allow_prerelease() -> Result<()> {
ResolutionMode::default(),
PreReleaseMode::Allow,
None,
None,
);
let resolution = resolve(manifest, &MARKERS_311, &TAGS_311).await?;
@ -387,6 +401,7 @@ async fn pylint_allow_explicit_prerelease_without_marker() -> Result<()> {
ResolutionMode::default(),
PreReleaseMode::Explicit,
None,
None,
);
let resolution = resolve(manifest, &MARKERS_311, &TAGS_311).await?;
@ -410,6 +425,7 @@ async fn pylint_allow_explicit_prerelease_with_marker() -> Result<()> {
ResolutionMode::default(),
PreReleaseMode::Explicit,
None,
None,
);
let resolution = resolve(manifest, &MARKERS_311, &TAGS_311).await?;