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 a348347 commit 5d36313
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 9 deletions.
18 changes: 9 additions & 9 deletions .github/workflows/build-binaries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,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 +71,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 +116,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 +171,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 +219,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 @@ -302,12 +302,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: manylinux2018
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 +366,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 +429,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
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 5d36313

Please sign in to comment.