Skip to content

Commit

Permalink
Revert "Try to remove READMEs"
Browse files Browse the repository at this point in the history
This reverts commit a348347.
  • Loading branch information
charliermarsh committed Jan 18, 2024
1 parent df2e591 commit 410fc5b
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 11 deletions.
22 changes: 12 additions & 10 deletions .github/workflows/build-binaries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ env:

jobs:
sdist:
# TODO(charlie): Enable source distribution builds.
if: false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -43,7 +45,7 @@ jobs:
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: "Prep README.md"
run: rm README.md
run: echo "# Puffin" > README.md
- name: "Build sdist"
uses: PyO3/maturin-action@v1
with:
Expand Down Expand Up @@ -71,7 +73,7 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: "Prep README.md"
run: rm README.md
run: echo "# Puffin" > README.md
- name: "Build wheels - x86_64"
uses: PyO3/maturin-action@v1
with:
Expand Down Expand Up @@ -116,7 +118,7 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: "Prep README.md"
run: rm README.md
run: echo "# Puffin" > README.md
- name: "Build wheels - universal2"
uses: PyO3/maturin-action@v1
with:
Expand Down Expand Up @@ -171,7 +173,7 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}
architecture: ${{ matrix.platform.arch }}
- name: "Prep README.md"
run: rm README.md
run: echo "# Puffin" > README.md
- name: "Build wheels"
uses: PyO3/maturin-action@v1
with:
Expand Down Expand Up @@ -219,7 +221,7 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: "Prep README.md"
run: rm README.md
run: echo "# Puffin" > README.md
- name: "Build wheels"
uses: PyO3/maturin-action@v1
with:
Expand Down Expand Up @@ -275,7 +277,7 @@ jobs:
linux-cross:
# TODO(charlie): Enable cross-compilation.
# if: false
if: false
runs-on: ubuntu-latest
strategy:
matrix:
Expand All @@ -302,12 +304,12 @@ jobs:
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: "Prep README.md"
run: rm README.md
run: echo "# Puffin" > README.md
- name: "Build wheels"
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
manylinux: manylinux2014
manylinux: auto
docker-options: ${{ matrix.platform.maturin_docker_options }}
args: --release --locked --out dist
- uses: uraimo/run-on-arch-action@v2
Expand Down Expand Up @@ -366,7 +368,7 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: "Prep README.md"
run: rm README.md
run: echo "# Puffin" > README.md
- name: "Build wheels"
uses: PyO3/maturin-action@v1
with:
Expand Down Expand Up @@ -429,7 +431,7 @@ jobs:
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: "Prep README.md"
run: rm README.md
run: echo "# Puffin" > README.md
- name: "Build wheels"
uses: PyO3/maturin-action@v1
with:
Expand Down
20 changes: 20 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ dirs = { version = "5.0.1" }
# This tells flate2 (and all libraries that depend on it, including async_compression
# and async_zip) to use zlib-ng, which about 2x faster than the default flate2 backend
# at decompression. See https://github.com/rust-lang/flate2-rs#backends
flate2 = { version = "1.0.28" }
flate2 = { version = "1.0.28", features = ["zlib-ng"], default-features = false }
fs-err = { version = "2.11.0" }
fs2 = { version = "0.4.3" }
futures = { version = "0.3.30" }
Expand Down
1 change: 1 addition & 0 deletions crates/pep440-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name = "pep440_rs"
version = "0.3.12"
description = "A library for python version numbers and specifiers, implementing PEP 440"
license = "Apache-2.0 OR BSD-2-Clause"
include = ["/src", "Changelog.md", "License-Apache", "License-BSD", "README.md", "pyproject.toml"]

edition = { workspace = true }
rust-version = { workspace = true }
Expand Down
56 changes: 56 additions & 0 deletions crates/pep440-rs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# PEP440 in rust

[![Crates.io](https://img.shields.io/crates/v/pep440_rs.svg?logo=rust&style=flat-square)](https://crates.io/crates/pep440_rs)
[![PyPI](https://img.shields.io/pypi/v/pep440_rs.svg?logo=python&style=flat-square)](https://pypi.org/project/pep440_rs)

A library for python version numbers and specifiers, implementing
[PEP 440](https://peps.python.org/pep-0440). See [Reimplementing PEP 440](https://cohost.org/konstin/post/514863-reimplementing-pep-4) for some background.

Higher level bindings to the requirements syntax are available in [pep508_rs](https://github.com/konstin/pep508_rs).

```rust
use std::str::FromStr;
use pep440_rs::{parse_version_specifiers, Version, VersionSpecifier};

let version = Version::from_str("1.19").unwrap();
let version_specifier = VersionSpecifier::from_str("==1.*").unwrap();
assert!(version_specifier.contains(&version));
let version_specifiers = parse_version_specifiers(">=1.16, <2.0").unwrap();
assert!(version_specifiers.iter().all(|specifier| specifier.contains(&version)));
```

In python (`pip install pep440_rs`):

```python
from pep440_rs import Version, VersionSpecifier

assert Version("1.1a1").any_prerelease()
assert Version("1.1.dev2").any_prerelease()
assert not Version("1.1").any_prerelease()
assert VersionSpecifier(">=1.0").contains(Version("1.1a1"))
assert not VersionSpecifier(">=1.1").contains(Version("1.1a1"))
# Note that python comparisons are the version ordering, not the version specifiers operators
assert Version("1.1") >= Version("1.1a1")
assert Version("2.0") in VersionSpecifier("==2")
```

PEP 440 has a lot of unintuitive features, including:

* An epoch that you can prefix the version which, e.g. `1!1.2.3`. Lower epoch always means lower
version (`1.0 <=2!0.1`)
* post versions, which can be attached to both stable releases and prereleases
* dev versions, which can be attached to sbpth table releases and prereleases. When attached to a
prerelease the dev version is ordered just below the normal prerelease, however when attached
to a stable version, the dev version is sorted before a prereleases
* prerelease handling is a mess: "Pre-releases of any kind, including developmental releases,
are implicitly excluded from all version specifiers, unless they are already present on the
system, explicitly requested by the user, or if the only available version that satisfies
the version specifier is a pre-release.". This means that we can't say whether a specifier
matches without also looking at the environment
* prelease vs. prerelease incl. dev is fuzzy
* local versions on top of all the others, which are added with a + and have implicitly typed
string and number segments
* no semver-caret (`^`), but a pseudo-semver tilde (`~=`)
* ordering contradicts matching: We have e.g. `1.0+local > 1.0` when sorting,
but `==1.0` matches `1.0+local`. While the ordering of versions itself is a total order
the version matching needs to catch all sorts of special cases
1 change: 1 addition & 0 deletions crates/pep508-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "pep508_rs"
version = "0.2.3"
description = "A library for python dependency specifiers, better known as PEP 508"
include = ["/src", "Changelog.md", "License-Apache", "License-BSD", "Readme.md", "pyproject.toml"]
license = "Apache-2.0 OR BSD-2-Clause"

edition = { workspace = true }
Expand Down
68 changes: 68 additions & 0 deletions crates/pep508-rs/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Dependency specifiers (PEP 508) in Rust

[![Crates.io](https://img.shields.io/crates/v/pep508_rs.svg?logo=rust&style=flat-square)](https://crates.io/crates/pep508_rs)
[![PyPI](https://img.shields.io/pypi/v/pep508_rs.svg?logo=python&style=flat-square)](https://pypi.org/project/pep508_rs)

A library for python [dependency specifiers](https://packaging.python.org/en/latest/specifications/dependency-specifiers/), better known as [PEP 508](https://peps.python.org/pep-0508/).

## Usage

**In Rust**

```rust
use std::str::FromStr;
use pep508_rs::Requirement;

let marker = r#"requests [security,tests] >= 2.8.1, == 2.8.* ; python_version > "3.8""#;
let dependency_specification = Requirement::from_str(marker).unwrap();
assert_eq!(dependency_specification.name, "requests");
assert_eq!(dependency_specification.extras, Some(vec!["security".to_string(), "tests".to_string()]));
```

**In Python**

```python
from pep508_rs import Requirement

requests = Requirement(
'requests [security,tests] >= 2.8.1, == 2.8.* ; python_version > "3.8"'
)
assert requests.name == "requests"
assert requests.extras == ["security", "tests"]
assert [str(i) for i in requests.version_or_url] == [">= 2.8.1", "== 2.8.*"]
```

Python bindings are built with [maturin](https://github.com/PyO3/maturin), but you can also use the normal `pip install .`

`Version` and `VersionSpecifier` from [pep440_rs](https://github.com/konstin/pep440-rs) are reexported to avoid type mismatches.

## Markers

Markers allow you to install dependencies only in specific environments (python version, operating system, architecture, etc.) or when a specific feature is activated. E.g. you can say `importlib-metadata ; python_version < "3.8"` or `itsdangerous (>=1.1.0) ; extra == 'security'`. Unfortunately, the marker grammar has some oversights (e.g. <https://github.com/pypa/packaging.python.org/pull/1181>) and the design of comparisons (PEP 440 comparisons with lexicographic fallback) leads to confusing outcomes. This implementation tries to carefully validate everything and emit warnings whenever bogus comparisons with unintended semantics are made.

In python, warnings are by default sent to the normal python logging infrastructure:

```python
from pep508_rs import Requirement, MarkerEnvironment

env = MarkerEnvironment.current()
assert not Requirement("numpy; extra == 'science'").evaluate_markers(env, [])
assert Requirement("numpy; extra == 'science'").evaluate_markers(env, ["science"])
assert not Requirement(
"numpy; extra == 'science' and extra == 'arrays'"
).evaluate_markers(env, ["science"])
assert Requirement(
"numpy; extra == 'science' or extra == 'arrays'"
).evaluate_markers(env, ["science"])
```


```python
from pep508_rs import Requirement, MarkerEnvironment

env = MarkerEnvironment.current()
Requirement("numpy; python_version >= '3.9.'").evaluate_markers(env, [])
# This will log:
# "Expected PEP 440 version to compare with python_version, found '3.9.', "
# "evaluating to false: Version `3.9.` doesn't match PEP 440 rules"
```
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ authors = [{ name = "Puffin" }]
requires-python = ">=3.7"
keywords = []
classifiers = []
readme = "README.md"

[tool.maturin]
bindings = "bin"
Expand Down

0 comments on commit 410fc5b

Please sign in to comment.