mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00
Use local versions of PEP 440 and PEP 508 crates (#32)
This PR modifies the PEP 440 and PEP 508 crates to pass CI, primarily by fixing all lint violations. We're also now using these crates in the workspace via `path`. (Previously, we were still fetching them from Cargo.)
This commit is contained in:
parent
4fcdb3c045
commit
c8477991a9
22 changed files with 359 additions and 1596 deletions
154
Cargo.lock
generated
154
Cargo.lock
generated
|
@ -127,6 +127,12 @@ version = "1.0.75"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arc-swap"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-compression"
|
name = "async-compression"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
|
@ -149,7 +155,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -392,7 +398,7 @@ dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -773,7 +779,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1077,6 +1083,18 @@ dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indoc"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indoc"
|
||||||
|
version = "2.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "insta"
|
name = "insta"
|
||||||
version = "1.33.0"
|
version = "1.33.0"
|
||||||
|
@ -1292,7 +1310,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1422,7 +1440,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1483,25 +1501,30 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pep440_rs"
|
name = "pep440_rs"
|
||||||
version = "0.3.12"
|
version = "0.3.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "887f66cc62717ea72caac4f1eb4e6f392224da3ffff3f40ec13ab427802746d6"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"indoc 2.0.4",
|
||||||
|
"once_cell",
|
||||||
|
"pyo3",
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
|
"tracing",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pep508_rs"
|
name = "pep508_rs"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e4516b53d9ea6112ebb38b4af08d5707d30b994fb7f98ff133c5dcf7ed8fa854"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"indoc 2.0.4",
|
||||||
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"pep440_rs",
|
"pep440_rs",
|
||||||
|
"pyo3",
|
||||||
|
"pyo3-log",
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"testing_logger",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tracing",
|
"tracing",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
|
@ -1734,6 +1757,77 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyo3"
|
||||||
|
version = "0.19.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e681a6cfdc4adcc93b4d3cf993749a4552018ee0a9b65fc0ccfad74352c72a38"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"indoc 1.0.9",
|
||||||
|
"libc",
|
||||||
|
"memoffset",
|
||||||
|
"parking_lot",
|
||||||
|
"pyo3-build-config",
|
||||||
|
"pyo3-ffi",
|
||||||
|
"pyo3-macros",
|
||||||
|
"unindent",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyo3-build-config"
|
||||||
|
version = "0.19.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "076c73d0bc438f7a4ef6fdd0c3bb4732149136abd952b110ac93e4edb13a6ba5"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"target-lexicon",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyo3-ffi"
|
||||||
|
version = "0.19.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e53cee42e77ebe256066ba8aa77eff722b3bb91f3419177cf4cd0f304d3284d9"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"pyo3-build-config",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyo3-log"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f47b0777feb17f61eea78667d61103758b243a871edc09a7786500a50467b605"
|
||||||
|
dependencies = [
|
||||||
|
"arc-swap",
|
||||||
|
"log",
|
||||||
|
"pyo3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyo3-macros"
|
||||||
|
version = "0.19.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dfeb4c99597e136528c6dd7d5e3de5434d1ceaf487436a3f03b2d56b6fc9efd1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"pyo3-macros-backend",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyo3-macros-backend"
|
||||||
|
version = "0.19.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "947dc12175c254889edc0c02e399476c2f652b4b9ebd123aa655c224de259536"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-xml"
|
name = "quick-xml"
|
||||||
version = "0.29.0"
|
version = "0.29.0"
|
||||||
|
@ -2069,7 +2163,7 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2112,7 +2206,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2257,6 +2351,17 @@ version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.38"
|
version = "2.0.38"
|
||||||
|
@ -2317,6 +2422,15 @@ dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "testing_logger"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d92b727cb45d33ae956f7f46b966b25f1bc712092aeef9dba5ac798fc89f720"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.49"
|
version = "1.0.49"
|
||||||
|
@ -2334,7 +2448,7 @@ checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2425,7 +2539,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2491,7 +2605,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2593,6 +2707,12 @@ version = "0.1.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unindent"
|
||||||
|
version = "0.1.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
version = "2.4.1"
|
version = "2.4.1"
|
||||||
|
@ -2675,7 +2795,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.38",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2709,7 +2829,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.38",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
|
@ -25,8 +25,6 @@ install-wheel-rs = { version = "0.0.1" }
|
||||||
mailparse = { version = "0.14.0" }
|
mailparse = { version = "0.14.0" }
|
||||||
memchr = { version = "2.6.4" }
|
memchr = { version = "2.6.4" }
|
||||||
once_cell = { version = "1.18.0" }
|
once_cell = { version = "1.18.0" }
|
||||||
pep440_rs = { version = "0.3.12" }
|
|
||||||
pep508_rs = { version = "0.2.3" }
|
|
||||||
platform-info = { version = "2.0.2" }
|
platform-info = { version = "2.0.2" }
|
||||||
plist = { version = "1.5.0" }
|
plist = { version = "1.5.0" }
|
||||||
regex = { version = "1.9.6" }
|
regex = { version = "1.9.6" }
|
||||||
|
@ -44,4 +42,5 @@ tokio-util = { version = "0.7.9", features = ["compat"] }
|
||||||
tracing = { version = "0.1.37" }
|
tracing = { version = "0.1.37" }
|
||||||
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
||||||
tracing-tree = { version = "0.2.5" }
|
tracing-tree = { version = "0.2.5" }
|
||||||
|
unicode-width = { version = "0.1.8" }
|
||||||
url = { version = "2.4.1" }
|
url = { version = "2.4.1" }
|
||||||
|
|
|
@ -4,7 +4,6 @@ version = "0.3.12"
|
||||||
description = "A library for python version numbers and specifiers, implementing PEP 440"
|
description = "A library for python version numbers and specifiers, implementing PEP 440"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
include = ["/src", "Changelog.md", "License-Apache", "License-BSD", "Readme.md", "pyproject.toml"]
|
include = ["/src", "Changelog.md", "License-Apache", "License-BSD", "Readme.md", "pyproject.toml"]
|
||||||
# Same license as pypa/packaging where the tests are from
|
|
||||||
license = "Apache-2.0 OR BSD-2-Clause"
|
license = "Apache-2.0 OR BSD-2-Clause"
|
||||||
repository = "https://github.com/konstin/pep440-rs"
|
repository = "https://github.com/konstin/pep440-rs"
|
||||||
readme = "Readme.md"
|
readme = "Readme.md"
|
||||||
|
@ -14,12 +13,13 @@ name = "pep440_rs"
|
||||||
crate-type = ["rlib", "cdylib"]
|
crate-type = ["rlib", "cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lazy_static = "1.4.0"
|
once_cell = { workspace = true }
|
||||||
|
regex = { workspace = true }
|
||||||
|
serde = { workspace = true, features = ["derive"], optional = true }
|
||||||
|
tracing = { workspace = true, optional = true }
|
||||||
|
unicode-width = { workspace = true }
|
||||||
|
|
||||||
pyo3 = { version = "0.19", optional = true, features = ["extension-module", "abi3-py37"] }
|
pyo3 = { version = "0.19", optional = true, features = ["extension-module", "abi3-py37"] }
|
||||||
regex = { version = "1.8.1", default-features = false, features = ["std", "perf", "unicode-case", "unicode-perl"] }
|
|
||||||
serde = { version = "1.0.162", features = ["derive"], optional = true }
|
|
||||||
tracing = { version = "0.1.37", optional = true }
|
|
||||||
unicode-width = "0.1.10"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
indoc = "2.0.1"
|
indoc = "2.0.1"
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
[project]
|
|
||||||
name = "pep440_rs"
|
|
||||||
readme = "python/Readme.md"
|
|
||||||
|
|
||||||
[build-system]
|
|
||||||
requires = ["maturin>=1.0.0,<2.0.0"]
|
|
||||||
build-backend = "maturin"
|
|
||||||
|
|
||||||
[tool.maturin]
|
|
||||||
features = ["pyo3"]
|
|
||||||
python-source = "python"
|
|
||||||
module-name = "pep440_rs._pep440_rs"
|
|
||||||
|
|
||||||
[tool.ruff.per-file-ignores]
|
|
||||||
"python/pep440_rs/__init__.py" = ["F403", "F405"]
|
|
|
@ -1,4 +1,4 @@
|
||||||
use lazy_static::lazy_static;
|
use once_cell::sync::Lazy;
|
||||||
#[cfg(feature = "pyo3")]
|
#[cfg(feature = "pyo3")]
|
||||||
use pyo3::{
|
use pyo3::{
|
||||||
basic::CompareOp, exceptions::PyValueError, pyclass, pymethods, FromPyObject, IntoPy, PyAny,
|
basic::CompareOp, exceptions::PyValueError, pyclass, pymethods, FromPyObject, IntoPy, PyAny,
|
||||||
|
@ -53,12 +53,9 @@ pub(crate) const VERSION_RE_INNER: &str = r"
|
||||||
(?P<trailing_dot_star>\.\*)? # allow for version matching `.*`
|
(?P<trailing_dot_star>\.\*)? # allow for version matching `.*`
|
||||||
";
|
";
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
/// Matches a python version, such as `1.19.a1`. Based on the PEP 440 regex
|
/// Matches a python version, such as `1.19.a1`. Based on the PEP 440 regex
|
||||||
static ref VERSION_RE: Regex = Regex::new(&format!(
|
static VERSION_RE: Lazy<Regex> =
|
||||||
r#"(?xi)^(?:\s*){}(?:\s*)$"#, VERSION_RE_INNER
|
Lazy::new(|| Regex::new(&format!(r#"(?xi)^(?:\s*){VERSION_RE_INNER}(?:\s*)$"#)).unwrap());
|
||||||
)).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// One of `~=` `==` `!=` `<=` `>=` `<` `>` `===`
|
/// One of `~=` `==` `!=` `<=` `>=` `<` `>` `===`
|
||||||
#[derive(Eq, PartialEq, Debug, Hash, Clone)]
|
#[derive(Eq, PartialEq, Debug, Hash, Clone)]
|
||||||
|
@ -115,8 +112,7 @@ impl FromStr for Operator {
|
||||||
// Should be forbidden by the regex if called from normal parsing
|
// Should be forbidden by the regex if called from normal parsing
|
||||||
other => {
|
other => {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"No such comparison operator '{}', must be one of ~= == != <= >= < > ===",
|
"No such comparison operator '{other}', must be one of ~= == != <= >= < > ===",
|
||||||
other
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -125,7 +121,7 @@ impl FromStr for Operator {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Operator {
|
impl Display for Operator {
|
||||||
/// Note the EqualStar is also `==`
|
/// Note the `EqualStar` is also `==`.
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
let operator = match self {
|
let operator = match self {
|
||||||
Operator::Equal => "==",
|
Operator::Equal => "==",
|
||||||
|
@ -142,7 +138,7 @@ impl Display for Operator {
|
||||||
Operator::GreaterThanEqual => ">=",
|
Operator::GreaterThanEqual => ">=",
|
||||||
};
|
};
|
||||||
|
|
||||||
write!(f, "{}", operator)
|
write!(f, "{operator}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,8 +177,7 @@ impl FromStr for PreRelease {
|
||||||
"b" | "beta" => Ok(Self::Beta),
|
"b" | "beta" => Ok(Self::Beta),
|
||||||
"c" | "rc" | "pre" | "preview" => Ok(Self::Rc),
|
"c" | "rc" | "pre" | "preview" => Ok(Self::Rc),
|
||||||
_ => Err(format!(
|
_ => Err(format!(
|
||||||
"'{}' isn't recognized as alpha, beta or release candidate",
|
"'{prerelease}' isn't recognized as alpha, beta or release candidate",
|
||||||
prerelease
|
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,7 +207,7 @@ impl Display for PreRelease {
|
||||||
/// > shorter local version’s segments match the beginning of the longer local version’s segments
|
/// > shorter local version’s segments match the beginning of the longer local version’s segments
|
||||||
/// > exactly.
|
/// > exactly.
|
||||||
///
|
///
|
||||||
/// Luckily the default Ord impl for Vec<LocalSegment> matches the PEP 440 rules
|
/// Luckily the default `Ord` implementation for `Vec<LocalSegment>` matches the PEP 440 rules.
|
||||||
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
|
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
|
||||||
pub enum LocalSegment {
|
pub enum LocalSegment {
|
||||||
/// Not-parseable as integer segment of local version
|
/// Not-parseable as integer segment of local version
|
||||||
|
@ -224,8 +219,8 @@ pub enum LocalSegment {
|
||||||
impl Display for LocalSegment {
|
impl Display for LocalSegment {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::String(string) => write!(f, "{}", string),
|
Self::String(string) => write!(f, "{string}"),
|
||||||
Self::Number(number) => write!(f, "{}", number),
|
Self::Number(number) => write!(f, "{number}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,9 +249,9 @@ impl FromStr for LocalSegment {
|
||||||
///
|
///
|
||||||
/// Beware that the sorting implemented with [Ord] and [Eq] is not consistent with the operators
|
/// Beware that the sorting implemented with [Ord] and [Eq] is not consistent with the operators
|
||||||
/// from PEP 440, i.e. compare two versions in rust with `>` gives a different result than a
|
/// from PEP 440, i.e. compare two versions in rust with `>` gives a different result than a
|
||||||
/// VersionSpecifier with `>` as operator.
|
/// `VersionSpecifier` with `>` as operator.
|
||||||
///
|
///
|
||||||
/// Parse with [Version::from_str]:
|
/// Parse with [`Version::from_str`]:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use std::str::FromStr;
|
/// use std::str::FromStr;
|
||||||
|
@ -360,25 +355,25 @@ impl PyVersion {
|
||||||
#[getter]
|
#[getter]
|
||||||
#[allow(clippy::get_first)]
|
#[allow(clippy::get_first)]
|
||||||
pub fn major(&self) -> usize {
|
pub fn major(&self) -> usize {
|
||||||
self.release().get(0).cloned().unwrap_or_default()
|
self.release().get(0).copied().unwrap_or_default()
|
||||||
}
|
}
|
||||||
/// The second item of release or 0 if unavailable.
|
/// The second item of release or 0 if unavailable.
|
||||||
#[getter]
|
#[getter]
|
||||||
pub fn minor(&self) -> usize {
|
pub fn minor(&self) -> usize {
|
||||||
self.release().get(1).cloned().unwrap_or_default()
|
self.release().get(1).copied().unwrap_or_default()
|
||||||
}
|
}
|
||||||
/// The third item of release or 0 if unavailable.
|
/// The third item of release or 0 if unavailable.
|
||||||
#[getter]
|
#[getter]
|
||||||
pub fn micro(&self) -> usize {
|
pub fn micro(&self) -> usize {
|
||||||
self.release().get(2).cloned().unwrap_or_default()
|
self.release().get(2).copied().unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a PEP 440 version string
|
/// Parses a PEP 440 version string
|
||||||
#[cfg(feature = "pyo3")]
|
#[cfg(feature = "pyo3")]
|
||||||
#[new]
|
#[new]
|
||||||
pub fn parse(version: String) -> PyResult<Self> {
|
pub fn parse(version: &str) -> PyResult<Self> {
|
||||||
Ok(Self(
|
Ok(Self(
|
||||||
Version::from_str(&version).map_err(PyValueError::new_err)?,
|
Version::from_str(version).map_err(PyValueError::new_err)?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,8 +381,8 @@ impl PyVersion {
|
||||||
/// Parse a PEP 440 version optionally ending with `.*`
|
/// Parse a PEP 440 version optionally ending with `.*`
|
||||||
#[cfg(feature = "pyo3")]
|
#[cfg(feature = "pyo3")]
|
||||||
#[staticmethod]
|
#[staticmethod]
|
||||||
pub fn parse_star(version_specifier: String) -> PyResult<(Self, bool)> {
|
pub fn parse_star(version_specifier: &str) -> PyResult<(Self, bool)> {
|
||||||
Version::from_str_star(&version_specifier)
|
Version::from_str_star(version_specifier)
|
||||||
.map_err(PyValueError::new_err)
|
.map_err(PyValueError::new_err)
|
||||||
.map(|(version, star)| (Self(version), star))
|
.map(|(version, star)| (Self(version), star))
|
||||||
}
|
}
|
||||||
|
@ -422,7 +417,7 @@ impl PyVersion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://github.com/serde-rs/serde/issues/1316#issue-332908452
|
/// <https://github.com/serde-rs/serde/issues/1316#issue-332908452>
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
impl<'de> Deserialize<'de> for Version {
|
impl<'de> Deserialize<'de> for Version {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
@ -434,7 +429,7 @@ impl<'de> Deserialize<'de> for Version {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://github.com/serde-rs/serde/issues/1316#issue-332908452
|
/// <https://github.com/serde-rs/serde/issues/1316#issue-332908452>
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
impl Serialize for Version {
|
impl Serialize for Version {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
@ -500,29 +495,26 @@ impl Version {
|
||||||
impl Display for Version {
|
impl Display for Version {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
let epoch = if self.epoch == 0 {
|
let epoch = if self.epoch == 0 {
|
||||||
"".to_string()
|
String::new()
|
||||||
} else {
|
} else {
|
||||||
format!("{}!", self.epoch)
|
format!("{}!", self.epoch)
|
||||||
};
|
};
|
||||||
let release = self
|
let release = self
|
||||||
.release
|
.release
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| x.to_string())
|
.map(ToString::to_string)
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(".");
|
.join(".");
|
||||||
let pre = self
|
let pre = self
|
||||||
.pre
|
.pre
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|(pre_kind, pre_version)| format!("{}{}", pre_kind, pre_version))
|
.map(|(pre_kind, pre_version)| format!("{pre_kind}{pre_version}"))
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let post = self
|
let post = self
|
||||||
.post
|
.post
|
||||||
.map(|post| format!(".post{}", post))
|
.map(|post| format!(".post{post}"))
|
||||||
.unwrap_or_default();
|
|
||||||
let dev = self
|
|
||||||
.dev
|
|
||||||
.map(|dev| format!(".dev{}", dev))
|
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
let dev = self.dev.map(|dev| format!(".dev{dev}")).unwrap_or_default();
|
||||||
let local = self
|
let local = self
|
||||||
.local
|
.local
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -531,19 +523,19 @@ impl Display for Version {
|
||||||
"+{}",
|
"+{}",
|
||||||
segments
|
segments
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| x.to_string())
|
.map(std::string::ToString::to_string)
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(".")
|
.join(".")
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
write!(f, "{}{}{}{}{}{}", epoch, release, pre, post, dev, local)
|
write!(f, "{epoch}{release}{pre}{post}{dev}{local}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare the release parts of two versions, e.g. `4.3.1` > `4.2`, `1.1.0` == `1.1` and
|
/// Compare the release parts of two versions, e.g. `4.3.1` > `4.2`, `1.1.0` == `1.1` and
|
||||||
/// `1.16` < `1.19`
|
/// `1.16` < `1.19`
|
||||||
pub fn compare_release(this: &[usize], other: &[usize]) -> Ordering {
|
pub(crate) fn compare_release(this: &[usize], other: &[usize]) -> Ordering {
|
||||||
// "When comparing release segments with different numbers of components, the shorter segment
|
// "When comparing release segments with different numbers of components, the shorter segment
|
||||||
// is padded out with additional zeros as necessary"
|
// is padded out with additional zeros as necessary"
|
||||||
let iterator: Vec<(&usize, &usize)> = if this.len() < other.len() {
|
let iterator: Vec<(&usize, &usize)> = if this.len() < other.len() {
|
||||||
|
@ -632,7 +624,7 @@ impl PartialEq<Self> for Version {
|
||||||
impl Eq for Version {}
|
impl Eq for Version {}
|
||||||
|
|
||||||
impl Hash for Version {
|
impl Hash for Version {
|
||||||
/// Custom implementation to ignoring trailing zero because PartialEq zero pads
|
/// Custom implementation to ignoring trailing zero because `PartialEq` zero pads
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
self.epoch.hash(state);
|
self.epoch.hash(state);
|
||||||
// Skip trailing zeros
|
// Skip trailing zeros
|
||||||
|
@ -693,11 +685,11 @@ impl FromStr for Version {
|
||||||
/// Parses a version such as `1.19`, `1.0a1`,`1.0+abc.5` or `1!2012.2`
|
/// Parses a version such as `1.19`, `1.0a1`,`1.0+abc.5` or `1!2012.2`
|
||||||
///
|
///
|
||||||
/// Note that this variant doesn't allow the version to end with a star, see
|
/// Note that this variant doesn't allow the version to end with a star, see
|
||||||
/// [Self::from_str_star] if you want to parse versions for specifiers
|
/// [`Self::from_str_star`] if you want to parse versions for specifiers
|
||||||
fn from_str(version: &str) -> Result<Self, Self::Err> {
|
fn from_str(version: &str) -> Result<Self, Self::Err> {
|
||||||
let captures = VERSION_RE
|
let captures = VERSION_RE
|
||||||
.captures(version)
|
.captures(version)
|
||||||
.ok_or_else(|| format!("Version `{}` doesn't match PEP 440 rules", version))?;
|
.ok_or_else(|| format!("Version `{version}` doesn't match PEP 440 rules"))?;
|
||||||
let (version, star) = Version::parse_impl(&captures)?;
|
let (version, star) = Version::parse_impl(&captures)?;
|
||||||
if star {
|
if star {
|
||||||
return Err("A star (`*`) must not be used in a fixed version (use `Version::from_string_star` otherwise)".to_string());
|
return Err("A star (`*`) must not be used in a fixed version (use `Version::from_string_star` otherwise)".to_string());
|
||||||
|
@ -707,7 +699,7 @@ impl FromStr for Version {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Version {
|
impl Version {
|
||||||
/// Like [Self::from_str], but also allows the version to end with a star and returns whether it
|
/// Like [`Self::from_str`], but also allows the version to end with a star and returns whether it
|
||||||
/// did. This variant is for use in specifiers.
|
/// did. This variant is for use in specifiers.
|
||||||
/// * `1.2.3` -> false
|
/// * `1.2.3` -> false
|
||||||
/// * `1.2.3.*` -> true
|
/// * `1.2.3.*` -> true
|
||||||
|
@ -716,7 +708,7 @@ impl Version {
|
||||||
pub fn from_str_star(version: &str) -> Result<(Self, bool), String> {
|
pub fn from_str_star(version: &str) -> Result<(Self, bool), String> {
|
||||||
let captures = VERSION_RE
|
let captures = VERSION_RE
|
||||||
.captures(version)
|
.captures(version)
|
||||||
.ok_or_else(|| format!("Version `{}` doesn't match PEP 440 rules", version))?;
|
.ok_or_else(|| format!("Version `{version}` doesn't match PEP 440 rules"))?;
|
||||||
let (version, star) = Version::parse_impl(&captures)?;
|
let (version, star) = Version::parse_impl(&captures)?;
|
||||||
Ok((version, star))
|
Ok((version, star))
|
||||||
}
|
}
|
||||||
|
@ -895,7 +887,7 @@ mod test {
|
||||||
];
|
];
|
||||||
for version in versions {
|
for version in versions {
|
||||||
Version::from_str(version).unwrap();
|
Version::from_str(version).unwrap();
|
||||||
VersionSpecifier::from_str(&format!("=={}", version)).unwrap();
|
VersionSpecifier::from_str(&format!("=={version}")).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -915,14 +907,11 @@ mod test {
|
||||||
for version in versions {
|
for version in versions {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Version::from_str(version).unwrap_err(),
|
Version::from_str(version).unwrap_err(),
|
||||||
format!("Version `{}` doesn't match PEP 440 rules", version)
|
format!("Version `{version}` doesn't match PEP 440 rules")
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
VersionSpecifier::from_str(&format!("=={}", version)).unwrap_err(),
|
VersionSpecifier::from_str(&format!("=={version}")).unwrap_err(),
|
||||||
format!(
|
format!("Version specifier `=={version}` doesn't match PEP 440 rules")
|
||||||
"Version specifier `=={}` doesn't match PEP 440 rules",
|
|
||||||
version
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1048,19 +1037,17 @@ mod test {
|
||||||
let version = Version::from_str(version_str).unwrap();
|
let version = Version::from_str(version_str).unwrap();
|
||||||
let normalized = Version::from_str(normalized_str).unwrap();
|
let normalized = Version::from_str(normalized_str).unwrap();
|
||||||
// Just test version parsing again
|
// Just test version parsing again
|
||||||
assert_eq!(version, normalized, "{} {}", version_str, normalized_str);
|
assert_eq!(version, normalized, "{version_str} {normalized_str}");
|
||||||
// Test version normalization
|
// Test version normalization
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
version.to_string(),
|
version.to_string(),
|
||||||
normalized.to_string(),
|
normalized.to_string(),
|
||||||
"{} {}",
|
"{version_str} {normalized_str}"
|
||||||
version_str,
|
|
||||||
normalized_str
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://github.com/pypa/packaging/blob/237ff3aa348486cf835a980592af3a59fccd6101/tests/test_version.py#L229-L277
|
/// <https://github.com/pypa/packaging/blob/237ff3aa348486cf835a980592af3a59fccd6101/tests/test_version.py#L229-L277>
|
||||||
#[test]
|
#[test]
|
||||||
fn test_equality_and_normalization2() {
|
fn test_equality_and_normalization2() {
|
||||||
let versions = [
|
let versions = [
|
||||||
|
@ -1115,22 +1102,18 @@ mod test {
|
||||||
for (version_str, normalized_str) in versions {
|
for (version_str, normalized_str) in versions {
|
||||||
let version = Version::from_str(version_str).unwrap();
|
let version = Version::from_str(version_str).unwrap();
|
||||||
let normalized = Version::from_str(normalized_str).unwrap();
|
let normalized = Version::from_str(normalized_str).unwrap();
|
||||||
assert_eq!(version, normalized, "{} {}", version_str, normalized_str);
|
assert_eq!(version, normalized, "{version_str} {normalized_str}");
|
||||||
// Test version normalization
|
// Test version normalization
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
version.to_string(),
|
version.to_string(),
|
||||||
normalized_str,
|
normalized_str,
|
||||||
"{} {}",
|
"{version_str} {normalized_str}"
|
||||||
version_str,
|
|
||||||
normalized_str
|
|
||||||
);
|
);
|
||||||
// Since we're already at it
|
// Since we're already at it
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
version.to_string(),
|
version.to_string(),
|
||||||
normalized.to_string(),
|
normalized.to_string(),
|
||||||
"{} {}",
|
"{version_str} {normalized_str}"
|
||||||
version_str,
|
|
||||||
normalized_str
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
use crate::version::PyVersion;
|
use crate::version::PyVersion;
|
||||||
use crate::version::VERSION_RE_INNER;
|
use crate::version::VERSION_RE_INNER;
|
||||||
use crate::{version, Operator, Pep440Error, Version};
|
use crate::{version, Operator, Pep440Error, Version};
|
||||||
use lazy_static::lazy_static;
|
use once_cell::sync::Lazy;
|
||||||
#[cfg(feature = "pyo3")]
|
#[cfg(feature = "pyo3")]
|
||||||
use pyo3::{
|
use pyo3::{
|
||||||
exceptions::{PyIndexError, PyNotImplementedError, PyValueError},
|
exceptions::{PyIndexError, PyNotImplementedError, PyValueError},
|
||||||
|
@ -27,14 +27,14 @@ use unicode_width::UnicodeWidthStr;
|
||||||
#[cfg(feature = "tracing")]
|
#[cfg(feature = "tracing")]
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
/// Matches a python version specifier, such as `>=1.19.a1` or `4.1.*`. Extends the PEP 440
|
/// Matches a python version specifier, such as `>=1.19.a1` or `4.1.*`. Extends the PEP 440
|
||||||
/// version regex to version specifiers
|
/// version regex to version specifiers
|
||||||
static ref VERSION_SPECIFIER_RE: Regex = Regex::new(&format!(
|
static VERSION_SPECIFIER_RE: Lazy<Regex> = Lazy::new(|| {
|
||||||
r#"(?xi)^(?:\s*)(?P<operator>(~=|==|!=|<=|>=|<|>|===))(?:\s*){}(?:\s*)$"#,
|
Regex::new(&format!(
|
||||||
VERSION_RE_INNER
|
r#"(?xi)^(?:\s*)(?P<operator>(~=|==|!=|<=|>=|<|>|===))(?:\s*){VERSION_RE_INNER}(?:\s*)$"#,
|
||||||
)).unwrap();
|
))
|
||||||
}
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
/// A thin wrapper around `Vec<VersionSpecifier>` with a serde implementation
|
/// A thin wrapper around `Vec<VersionSpecifier>` with a serde implementation
|
||||||
///
|
///
|
||||||
|
@ -91,10 +91,10 @@ impl Display for VersionSpecifiers {
|
||||||
for (idx, version_specifier) in self.0.iter().enumerate() {
|
for (idx, version_specifier) in self.0.iter().enumerate() {
|
||||||
// Separate version specifiers by comma, but we need one comma less than there are
|
// Separate version specifiers by comma, but we need one comma less than there are
|
||||||
// specifiers
|
// specifiers
|
||||||
if idx != 0 {
|
if idx == 0 {
|
||||||
write!(f, ", {}", version_specifier)?;
|
write!(f, "{version_specifier}")?;
|
||||||
} else {
|
} else {
|
||||||
write!(f, "{}", version_specifier)?;
|
write!(f, ", {version_specifier}")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -125,8 +125,8 @@ impl VersionSpecifiersIter {
|
||||||
impl VersionSpecifiers {
|
impl VersionSpecifiers {
|
||||||
/// PEP 440 parsing
|
/// PEP 440 parsing
|
||||||
#[new]
|
#[new]
|
||||||
pub fn __new__(version_specifiers: String) -> PyResult<Self> {
|
pub fn __new__(version_specifiers: &str) -> PyResult<Self> {
|
||||||
Self::from_str(&version_specifiers).map_err(|err| PyValueError::new_err(err.to_string()))
|
Self::from_str(version_specifiers).map_err(|err| PyValueError::new_err(err.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PEP 440 serialization
|
/// PEP 440 serialization
|
||||||
|
@ -150,6 +150,7 @@ impl VersionSpecifiers {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
fn __iter__(slf: PyRef<'_, Self>) -> PyResult<Py<VersionSpecifiersIter>> {
|
fn __iter__(slf: PyRef<'_, Self>) -> PyResult<Py<VersionSpecifiersIter>> {
|
||||||
let iter = VersionSpecifiersIter {
|
let iter = VersionSpecifiersIter {
|
||||||
inner: slf.0.clone().into_iter(),
|
inner: slf.0.clone().into_iter(),
|
||||||
|
@ -207,8 +208,8 @@ impl Serialize for VersionSpecifiers {
|
||||||
/// let version_specifier = VersionSpecifier::from_str("== 1.*").unwrap();
|
/// let version_specifier = VersionSpecifier::from_str("== 1.*").unwrap();
|
||||||
/// assert!(version_specifier.contains(&version));
|
/// assert!(version_specifier.contains(&version));
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg_attr(feature = "pyo3", pyclass(get_all))]
|
|
||||||
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
|
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
|
||||||
|
#[cfg_attr(feature = "pyo3", pyclass(get_all))]
|
||||||
pub struct VersionSpecifier {
|
pub struct VersionSpecifier {
|
||||||
/// ~=|==|!=|<=|>=|<|>|===, plus whether the version ended with a star
|
/// ~=|==|!=|<=|>=|<|>|===, plus whether the version ended with a star
|
||||||
pub(crate) operator: Operator,
|
pub(crate) operator: Operator,
|
||||||
|
@ -222,8 +223,8 @@ impl VersionSpecifier {
|
||||||
// Since we don't bring FromStr to python
|
// Since we don't bring FromStr to python
|
||||||
/// Parse a PEP 440 version
|
/// Parse a PEP 440 version
|
||||||
#[new]
|
#[new]
|
||||||
pub fn parse(version_specifier: String) -> PyResult<Self> {
|
pub fn parse(version_specifier: &str) -> PyResult<Self> {
|
||||||
Self::from_str(&version_specifier).map_err(PyValueError::new_err)
|
Self::from_str(version_specifier).map_err(PyValueError::new_err)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See [VersionSpecifier::contains]
|
/// See [VersionSpecifier::contains]
|
||||||
|
@ -244,7 +245,7 @@ impl VersionSpecifier {
|
||||||
|
|
||||||
/// Returns the normalized representation
|
/// Returns the normalized representation
|
||||||
pub fn __repr__(&self) -> String {
|
pub fn __repr__(&self) -> String {
|
||||||
format!(r#"<VersionSpecifier("{}")>"#, self)
|
format!(r#"<VersionSpecifier("{self}")>"#)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult<bool> {
|
fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult<bool> {
|
||||||
|
@ -265,7 +266,7 @@ impl VersionSpecifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://github.com/serde-rs/serde/issues/1316#issue-332908452
|
/// <https://github.com/serde-rs/serde/issues/1316#issue-332908452>
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
impl<'de> Deserialize<'de> for VersionSpecifier {
|
impl<'de> Deserialize<'de> for VersionSpecifier {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
@ -277,7 +278,7 @@ impl<'de> Deserialize<'de> for VersionSpecifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://github.com/serde-rs/serde/issues/1316#issue-332908452
|
/// <https://github.com/serde-rs/serde/issues/1316#issue-332908452>
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
impl Serialize for VersionSpecifier {
|
impl Serialize for VersionSpecifier {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
@ -309,7 +310,7 @@ impl VersionSpecifier {
|
||||||
operator,
|
operator,
|
||||||
local
|
local
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| x.to_string())
|
.map(std::string::ToString::to_string)
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(".")
|
.join(".")
|
||||||
));
|
));
|
||||||
|
@ -323,8 +324,7 @@ impl VersionSpecifier {
|
||||||
Operator::NotEqual => Operator::NotEqualStar,
|
Operator::NotEqual => Operator::NotEqualStar,
|
||||||
other => {
|
other => {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"Operator {} must not be used in version ending with a star",
|
"Operator {other} must not be used in version ending with a star"
|
||||||
other
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -489,7 +489,7 @@ impl FromStr for VersionSpecifier {
|
||||||
fn from_str(spec: &str) -> Result<Self, Self::Err> {
|
fn from_str(spec: &str) -> Result<Self, Self::Err> {
|
||||||
let captures = VERSION_SPECIFIER_RE
|
let captures = VERSION_SPECIFIER_RE
|
||||||
.captures(spec)
|
.captures(spec)
|
||||||
.ok_or_else(|| format!("Version specifier `{}` doesn't match PEP 440 rules", spec))?;
|
.ok_or_else(|| format!("Version specifier `{spec}` doesn't match PEP 440 rules"))?;
|
||||||
let (version, star) = Version::parse_impl(&captures)?;
|
let (version, star) = Version::parse_impl(&captures)?;
|
||||||
// operator but we don't know yet if it has a star
|
// operator but we don't know yet if it has a star
|
||||||
let operator = Operator::from_str(&captures["operator"])?;
|
let operator = Operator::from_str(&captures["operator"])?;
|
||||||
|
@ -509,7 +509,7 @@ impl Display for VersionSpecifier {
|
||||||
|
|
||||||
/// Parses a list of specifiers such as `>= 1.0, != 1.3.*, < 2.0`.
|
/// Parses a list of specifiers such as `>= 1.0, != 1.3.*, < 2.0`.
|
||||||
///
|
///
|
||||||
/// I recommend using [VersionSpecifiers::from_str] instead.
|
/// I recommend using [`VersionSpecifiers::from_str`] instead.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use std::str::FromStr;
|
/// use std::str::FromStr;
|
||||||
|
@ -625,8 +625,8 @@ mod test {
|
||||||
"1!1.2.rev33+123456",
|
"1!1.2.rev33+123456",
|
||||||
];
|
];
|
||||||
|
|
||||||
/// https://github.com/pypa/packaging/blob/237ff3aa348486cf835a980592af3a59fccd6101/tests/test_version.py#L666-L707
|
/// <https://github.com/pypa/packaging/blob/237ff3aa348486cf835a980592af3a59fccd6101/tests/test_version.py#L666-L707>
|
||||||
/// https://github.com/pypa/packaging/blob/237ff3aa348486cf835a980592af3a59fccd6101/tests/test_version.py#L709-L750
|
/// <https://github.com/pypa/packaging/blob/237ff3aa348486cf835a980592af3a59fccd6101/tests/test_version.py#L709-L750>
|
||||||
///
|
///
|
||||||
/// These tests are a lot shorter than the pypa/packaging version since we implement all
|
/// These tests are a lot shorter than the pypa/packaging version since we implement all
|
||||||
/// comparisons through one method
|
/// comparisons through one method
|
||||||
|
@ -667,7 +667,7 @@ mod test {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
for (a, b, ordering) in operations {
|
for (a, b, ordering) in operations {
|
||||||
assert_eq!(a.cmp(b), ordering, "{} {:?} {}", a, ordering, b);
|
assert_eq!(a.cmp(b), ordering, "{a} {ordering:?} {b}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -792,7 +792,7 @@ mod test {
|
||||||
|
|
||||||
/// Test for tilde equal (~=) and star equal (== x.y.*) recorded from pypa/packaging
|
/// Test for tilde equal (~=) and star equal (== x.y.*) recorded from pypa/packaging
|
||||||
///
|
///
|
||||||
/// Well, except for https://github.com/pypa/packaging/issues/617
|
/// Well, except for <https://github.com/pypa/packaging/issues/617>
|
||||||
#[test]
|
#[test]
|
||||||
fn test_operators_other() {
|
fn test_operators_other() {
|
||||||
let versions: Vec<Version> = VERSIONS_0
|
let versions: Vec<Version> = VERSIONS_0
|
||||||
|
@ -809,9 +809,10 @@ mod test {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|specifier| specifier.contains(version))
|
.map(|specifier| specifier.contains(version))
|
||||||
.collect::<Vec<bool>>();
|
.collect::<Vec<bool>>();
|
||||||
for ((actual, expected), specifier) in actual.iter().zip(expected).zip(SPECIFIERS_OTHER)
|
for ((actual, expected), _specifier) in
|
||||||
|
actual.iter().zip(expected).zip(SPECIFIERS_OTHER)
|
||||||
{
|
{
|
||||||
assert_eq!(actual, expected, "{} {}", version, specifier);
|
assert_eq!(actual, expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -924,9 +925,7 @@ mod test {
|
||||||
VersionSpecifier::from_str(specifier)
|
VersionSpecifier::from_str(specifier)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.contains(&Version::from_str(version).unwrap()),
|
.contains(&Version::from_str(version).unwrap()),
|
||||||
"{} {}",
|
"{version} {specifier}"
|
||||||
version,
|
|
||||||
specifier
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1027,9 +1026,7 @@ mod test {
|
||||||
!VersionSpecifier::from_str(specifier)
|
!VersionSpecifier::from_str(specifier)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.contains(&Version::from_str(version).unwrap()),
|
.contains(&Version::from_str(version).unwrap()),
|
||||||
"{} {}",
|
"{version} {specifier}"
|
||||||
version,
|
|
||||||
specifier
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1246,15 +1243,12 @@ mod test {
|
||||||
];
|
];
|
||||||
for (specifier, error) in specifiers {
|
for (specifier, error) in specifiers {
|
||||||
if let Some(error) = error {
|
if let Some(error) = error {
|
||||||
assert_eq!(VersionSpecifier::from_str(specifier).unwrap_err(), error)
|
assert_eq!(VersionSpecifier::from_str(specifier).unwrap_err(), error);
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
VersionSpecifier::from_str(specifier).unwrap_err(),
|
VersionSpecifier::from_str(specifier).unwrap_err(),
|
||||||
format!(
|
format!("Version specifier `{specifier}` doesn't match PEP 440 rules",)
|
||||||
"Version specifier `{}` doesn't match PEP 440 rules",
|
);
|
||||||
specifier
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
177
crates/pep508-rs/.github/workflows/release.yml
vendored
177
crates/pep508-rs/.github/workflows/release.yml
vendored
|
@ -1,177 +0,0 @@
|
||||||
name: Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- v*
|
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
crates-io:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
- name: Push to crates.io
|
|
||||||
env:
|
|
||||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
|
||||||
run: cargo publish
|
|
||||||
|
|
||||||
macos:
|
|
||||||
runs-on: macos-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-python@v4
|
|
||||||
with:
|
|
||||||
python-version: 3.9
|
|
||||||
architecture: x64
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
- name: Build wheels - x86_64
|
|
||||||
uses: PyO3/maturin-action@v1
|
|
||||||
with:
|
|
||||||
target: x86_64
|
|
||||||
args: --release --strip --out dist --sdist
|
|
||||||
env:
|
|
||||||
RUSTFLAGS: "-C link-arg=-undefined -C link-arg=dynamic_lookup"
|
|
||||||
- name: Build wheels - universal2
|
|
||||||
uses: PyO3/maturin-action@v1
|
|
||||||
with:
|
|
||||||
args: --release --strip --target --target universal2-apple-darwin --out dist
|
|
||||||
env:
|
|
||||||
RUSTFLAGS: "-C link-arg=-undefined -C link-arg=dynamic_lookup"
|
|
||||||
- name: Upload wheels
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: wheels
|
|
||||||
path: dist
|
|
||||||
|
|
||||||
windows:
|
|
||||||
runs-on: windows-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-python@v4
|
|
||||||
with:
|
|
||||||
python-version: 3.9
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
- name: Build wheels
|
|
||||||
uses: PyO3/maturin-action@v1
|
|
||||||
with:
|
|
||||||
args: --release --strip --out dist
|
|
||||||
- name: Upload wheels
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: wheels
|
|
||||||
path: dist
|
|
||||||
|
|
||||||
linux:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
target: [ x86_64 ]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-python@v4
|
|
||||||
with:
|
|
||||||
python-version: 3.9
|
|
||||||
architecture: x64
|
|
||||||
- name: Build wheels
|
|
||||||
uses: PyO3/maturin-action@v1
|
|
||||||
with:
|
|
||||||
target: ${{ matrix.target }}
|
|
||||||
args: --release --strip --out dist
|
|
||||||
- name: Upload wheels
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: wheels
|
|
||||||
path: dist
|
|
||||||
|
|
||||||
linux-cross:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
target: [ aarch64, armv7, s390x, ppc64le, ppc64 ]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-python@v4
|
|
||||||
with:
|
|
||||||
python-version: 3.9
|
|
||||||
- name: Build wheels
|
|
||||||
uses: PyO3/maturin-action@v1
|
|
||||||
with:
|
|
||||||
rust-toolchain: nightly
|
|
||||||
target: ${{ matrix.target }}
|
|
||||||
args: --release --strip --out dist
|
|
||||||
- name: Upload wheels
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: wheels
|
|
||||||
path: dist
|
|
||||||
|
|
||||||
musllinux:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
target:
|
|
||||||
- x86_64-unknown-linux-musl
|
|
||||||
- i686-unknown-linux-musl
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-python@v4
|
|
||||||
with:
|
|
||||||
python-version: 3.9
|
|
||||||
architecture: x64
|
|
||||||
- name: Build wheels
|
|
||||||
uses: PyO3/maturin-action@v1
|
|
||||||
with:
|
|
||||||
target: ${{ matrix.target }}
|
|
||||||
manylinux: musllinux_1_2
|
|
||||||
args: --release --strip --out dist
|
|
||||||
- name: Upload wheels
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: wheels
|
|
||||||
path: dist
|
|
||||||
|
|
||||||
musllinux-cross:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
platform:
|
|
||||||
- target: aarch64-unknown-linux-musl
|
|
||||||
arch: aarch64
|
|
||||||
- target: armv7-unknown-linux-musleabihf
|
|
||||||
arch: armv7
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-python@v4
|
|
||||||
with:
|
|
||||||
python-version: 3.9
|
|
||||||
- name: Build wheels
|
|
||||||
uses: PyO3/maturin-action@v1
|
|
||||||
with:
|
|
||||||
rust-toolchain: nightly
|
|
||||||
target: ${{ matrix.platform.target }}
|
|
||||||
manylinux: musllinux_1_2
|
|
||||||
args: --release --strip --out dist
|
|
||||||
- name: Upload wheels
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: wheels
|
|
||||||
path: dist
|
|
||||||
|
|
||||||
release:
|
|
||||||
name: Release
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [ macos, windows, linux, linux-cross, musllinux, musllinux-cross ]
|
|
||||||
environment: release
|
|
||||||
permissions:
|
|
||||||
id-token: write
|
|
||||||
steps:
|
|
||||||
- uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: wheels
|
|
||||||
- name: Publish to PyPI
|
|
||||||
uses: PyO3/maturin-action@v1
|
|
||||||
with:
|
|
||||||
command: upload
|
|
||||||
args: --skip-existing *
|
|
38
crates/pep508-rs/.github/workflows/test.yml
vendored
38
crates/pep508-rs/.github/workflows/test.yml
vendored
|
@ -1,38 +0,0 @@
|
||||||
name: test
|
|
||||||
|
|
||||||
on: [ push, pull_request ]
|
|
||||||
|
|
||||||
env:
|
|
||||||
CARGO_TERM_COLOR: always
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest, windows-latest, macos-latest ]
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- run: rustup toolchain install stable --profile minimal
|
|
||||||
- uses: Swatinem/rust-cache@v2
|
|
||||||
- name: Run tests
|
|
||||||
run: cargo test
|
|
||||||
|
|
||||||
lint:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
with:
|
|
||||||
components: clippy, rustfmt
|
|
||||||
- uses: Swatinem/rust-cache@v2
|
|
||||||
- name: Ruff
|
|
||||||
run: pipx run ruff check --format github .
|
|
||||||
- name: black
|
|
||||||
run: pipx run black --check .
|
|
||||||
- name: Rustfmt
|
|
||||||
run: cargo fmt --all -- --check
|
|
||||||
- name: Clippy (pure rust)
|
|
||||||
run: cargo clippy --tests -- -D warnings
|
|
||||||
- name: Clippy (pyo3)
|
|
||||||
run: cargo clippy --tests --all-features -- -D warnings
|
|
6
crates/pep508-rs/.gitignore
vendored
6
crates/pep508-rs/.gitignore
vendored
|
@ -1,6 +0,0 @@
|
||||||
.ipynb_checkpoints
|
|
||||||
.venv
|
|
||||||
/pypi_analysis/pipy_requires_dist.ndjson
|
|
||||||
/pypi_analysis/pypi_all.ndjson
|
|
||||||
__pycache__
|
|
||||||
target
|
|
|
@ -4,25 +4,28 @@ version = "0.2.3"
|
||||||
description = "A library for python dependency specifiers, better known as PEP 508"
|
description = "A library for python dependency specifiers, better known as PEP 508"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
include = ["/src", "Changelog.md", "License-Apache", "License-BSD", "Readme.md", "pyproject.toml"]
|
include = ["/src", "Changelog.md", "License-Apache", "License-BSD", "Readme.md", "pyproject.toml"]
|
||||||
# Same license as pypa/packaging where the tests are from
|
|
||||||
license = "Apache-2.0 OR BSD-2-Clause"
|
license = "Apache-2.0 OR BSD-2-Clause"
|
||||||
readme = "Readme.md"
|
readme = "Readme.md"
|
||||||
repository = "https://github.com/konstin/pep508_rs"
|
repository = "https://github.com/konstin/pep508_rs"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "pep508_rs"
|
||||||
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = { version = "1.0.75", optional = true }
|
pep440_rs = { path = "../pep440-rs" }
|
||||||
once_cell = "1.18.0"
|
|
||||||
pep440_rs = "0.3.11"
|
once_cell = { workspace = true }
|
||||||
|
regex = { workspace = true }
|
||||||
|
serde = { workspace = true, features = ["derive"], optional = true }
|
||||||
|
serde_json = { workspace = true, optional = true }
|
||||||
|
thiserror = { workspace = true }
|
||||||
|
tracing = { workspace = true, features = ["log"] }
|
||||||
|
unicode-width = { workspace = true }
|
||||||
|
url = { workspace = true, features = ["serde"] }
|
||||||
|
|
||||||
pyo3 = { version = "0.19.2", optional = true, features = ["abi3", "extension-module"] }
|
pyo3 = { version = "0.19.2", optional = true, features = ["abi3", "extension-module"] }
|
||||||
pyo3-log = { version = "0.8.3", optional = true }
|
pyo3-log = { version = "0.8.3", optional = true }
|
||||||
regex = { version = "1.9.5", default-features = false, features = ["std"] }
|
|
||||||
serde = { version = "1.0.188", features = ["derive"], optional = true }
|
|
||||||
serde_json = { version = "1.0.107", optional = true }
|
|
||||||
thiserror = "1.0.49"
|
|
||||||
toml = { version = "0.8.1", optional = true }
|
|
||||||
tracing = { version = "0.1.37", features = ["log"] }
|
|
||||||
unicode-width = "0.1.11"
|
|
||||||
url = { version = "2.4.1", features = ["serde"] }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
indoc = "2.0.4"
|
indoc = "2.0.4"
|
||||||
|
@ -33,17 +36,4 @@ serde_json = "1.0.107"
|
||||||
[features]
|
[features]
|
||||||
pyo3 = ["dep:pyo3", "pep440_rs/pyo3", "pyo3-log"]
|
pyo3 = ["dep:pyo3", "pep440_rs/pyo3", "pyo3-log"]
|
||||||
serde = ["dep:serde", "pep440_rs/serde"]
|
serde = ["dep:serde", "pep440_rs/serde"]
|
||||||
modern = ["serde", "toml", "anyhow"]
|
|
||||||
default = []
|
default = []
|
||||||
|
|
||||||
[lib]
|
|
||||||
name = "pep508_rs"
|
|
||||||
crate-type = ["cdylib", "rlib"]
|
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
debug = true
|
|
||||||
|
|
||||||
[profile.maturin]
|
|
||||||
inherits = "release"
|
|
||||||
strip = true
|
|
||||||
|
|
||||||
|
|
580
crates/pep508-rs/poetry.lock
generated
580
crates/pep508-rs/poetry.lock
generated
|
@ -1,580 +0,0 @@
|
||||||
# This file is automatically @generated by Poetry 1.5.0 and should not be changed by hand.
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "appnope"
|
|
||||||
version = "0.1.3"
|
|
||||||
description = "Disable App Nap on macOS >= 10.9"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"},
|
|
||||||
{file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "backcall"
|
|
||||||
version = "0.2.0"
|
|
||||||
description = "Specifications for callback functions passed in to an API"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"},
|
|
||||||
{file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "black"
|
|
||||||
version = "23.3.0"
|
|
||||||
description = "The uncompromising code formatter."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"},
|
|
||||||
{file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"},
|
|
||||||
{file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"},
|
|
||||||
{file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"},
|
|
||||||
{file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"},
|
|
||||||
{file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"},
|
|
||||||
{file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"},
|
|
||||||
{file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"},
|
|
||||||
{file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"},
|
|
||||||
{file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"},
|
|
||||||
{file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"},
|
|
||||||
{file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"},
|
|
||||||
{file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"},
|
|
||||||
{file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"},
|
|
||||||
{file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"},
|
|
||||||
{file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"},
|
|
||||||
{file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"},
|
|
||||||
{file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"},
|
|
||||||
{file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"},
|
|
||||||
{file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"},
|
|
||||||
{file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"},
|
|
||||||
{file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"},
|
|
||||||
{file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"},
|
|
||||||
{file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"},
|
|
||||||
{file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
click = ">=8.0.0"
|
|
||||||
ipython = {version = ">=7.8.0", optional = true, markers = "extra == \"jupyter\""}
|
|
||||||
mypy-extensions = ">=0.4.3"
|
|
||||||
packaging = ">=22.0"
|
|
||||||
pathspec = ">=0.9.0"
|
|
||||||
platformdirs = ">=2"
|
|
||||||
tokenize-rt = {version = ">=3.2.0", optional = true, markers = "extra == \"jupyter\""}
|
|
||||||
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
|
|
||||||
typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""}
|
|
||||||
typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
colorama = ["colorama (>=0.4.3)"]
|
|
||||||
d = ["aiohttp (>=3.7.4)"]
|
|
||||||
jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
|
|
||||||
uvloop = ["uvloop (>=0.15.2)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "click"
|
|
||||||
version = "8.1.3"
|
|
||||||
description = "Composable command line interface toolkit"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
|
|
||||||
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
|
||||||
importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "colorama"
|
|
||||||
version = "0.4.6"
|
|
||||||
description = "Cross-platform colored terminal text."
|
|
||||||
optional = false
|
|
||||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
|
||||||
files = [
|
|
||||||
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
|
||||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "decorator"
|
|
||||||
version = "5.1.1"
|
|
||||||
description = "Decorators for Humans"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.5"
|
|
||||||
files = [
|
|
||||||
{file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"},
|
|
||||||
{file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "exceptiongroup"
|
|
||||||
version = "1.1.1"
|
|
||||||
description = "Backport of PEP 654 (exception groups)"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"},
|
|
||||||
{file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
test = ["pytest (>=6)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "importlib-metadata"
|
|
||||||
version = "6.6.0"
|
|
||||||
description = "Read metadata from Python packages"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"},
|
|
||||||
{file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
|
|
||||||
zipp = ">=0.5"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
|
||||||
perf = ["ipython"]
|
|
||||||
testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "iniconfig"
|
|
||||||
version = "2.0.0"
|
|
||||||
description = "brain-dead simple config-ini parsing"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
|
|
||||||
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ipython"
|
|
||||||
version = "7.34.0"
|
|
||||||
description = "IPython: Productive Interactive Computing"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "ipython-7.34.0-py3-none-any.whl", hash = "sha256:c175d2440a1caff76116eb719d40538fbb316e214eda85c5515c303aacbfb23e"},
|
|
||||||
{file = "ipython-7.34.0.tar.gz", hash = "sha256:af3bdb46aa292bce5615b1b2ebc76c2080c5f77f54bda2ec72461317273e7cd6"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
appnope = {version = "*", markers = "sys_platform == \"darwin\""}
|
|
||||||
backcall = "*"
|
|
||||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
|
||||||
decorator = "*"
|
|
||||||
jedi = ">=0.16"
|
|
||||||
matplotlib-inline = "*"
|
|
||||||
pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""}
|
|
||||||
pickleshare = "*"
|
|
||||||
prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0"
|
|
||||||
pygments = "*"
|
|
||||||
setuptools = ">=18.5"
|
|
||||||
traitlets = ">=4.2"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
all = ["Sphinx (>=1.3)", "ipykernel", "ipyparallel", "ipywidgets", "nbconvert", "nbformat", "nose (>=0.10.1)", "notebook", "numpy (>=1.17)", "pygments", "qtconsole", "requests", "testpath"]
|
|
||||||
doc = ["Sphinx (>=1.3)"]
|
|
||||||
kernel = ["ipykernel"]
|
|
||||||
nbconvert = ["nbconvert"]
|
|
||||||
nbformat = ["nbformat"]
|
|
||||||
notebook = ["ipywidgets", "notebook"]
|
|
||||||
parallel = ["ipyparallel"]
|
|
||||||
qtconsole = ["qtconsole"]
|
|
||||||
test = ["ipykernel", "nbformat", "nose (>=0.10.1)", "numpy (>=1.17)", "pygments", "requests", "testpath"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "jedi"
|
|
||||||
version = "0.18.2"
|
|
||||||
description = "An autocompletion tool for Python that can be used for text editors."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "jedi-0.18.2-py2.py3-none-any.whl", hash = "sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e"},
|
|
||||||
{file = "jedi-0.18.2.tar.gz", hash = "sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
parso = ">=0.8.0,<0.9.0"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"]
|
|
||||||
qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
|
|
||||||
testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "matplotlib-inline"
|
|
||||||
version = "0.1.6"
|
|
||||||
description = "Inline Matplotlib backend for Jupyter"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.5"
|
|
||||||
files = [
|
|
||||||
{file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"},
|
|
||||||
{file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
traitlets = "*"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "maturin"
|
|
||||||
version = "1.0.1"
|
|
||||||
description = "Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "maturin-1.0.1-py3-none-linux_armv6l.whl", hash = "sha256:10097e2602330c0b9db16d7dfd002476f5e5cf99df58ba2f3abc6de64a69e9a6"},
|
|
||||||
{file = "maturin-1.0.1-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:9ecebccb111c9c870fb2f5eee17518fe106f676227bb16f204a51e7a162aceec"},
|
|
||||||
{file = "maturin-1.0.1-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:b39f9a42b3c8242e3f3ab990bd03ba989c6c07e4de9e21fcf877a2418119d445"},
|
|
||||||
{file = "maturin-1.0.1-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:c0b1efa47f8b7d15bc5945159764ce57316f9d1bfb7c8caa07cebdd41318359b"},
|
|
||||||
{file = "maturin-1.0.1-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:d392ec0578d9e6f03914837cef7bbb264d5708807e0b48176b6ff0b50083ba7c"},
|
|
||||||
{file = "maturin-1.0.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:d271b24febbfc020561984b1acdfc39b132df21f4e42d7af0fe274ea738c8000"},
|
|
||||||
{file = "maturin-1.0.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:8d88d1595d7514c27df96d5f4fe3dc5f24288528a746439403f27c3b448fca16"},
|
|
||||||
{file = "maturin-1.0.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:04c0279dd0d6ccd317018bd1a43f52cbda715822537ae1a68015c9171f18b2fd"},
|
|
||||||
{file = "maturin-1.0.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:787bb56c80eda482ece2dd4788d479dbd0e74d981b2e2c538228365c19290fb7"},
|
|
||||||
{file = "maturin-1.0.1-py3-none-win32.whl", hash = "sha256:6d9b4ff7c2d501e91886b859296f5c0478fc08bc7d537a72f98a69d51ff4f519"},
|
|
||||||
{file = "maturin-1.0.1-py3-none-win_amd64.whl", hash = "sha256:2907b345186a83db4bbe5571830509b3031784d08958b32d2ffa7857bd473725"},
|
|
||||||
{file = "maturin-1.0.1-py3-none-win_arm64.whl", hash = "sha256:6b020b9abbd1e9fef468c171216dc4be053834b5bf638075264ee090a993b0b0"},
|
|
||||||
{file = "maturin-1.0.1.tar.gz", hash = "sha256:71fdb2dbbd5bcc60bd91ddcbe34dba9f04cc53c2add089a95a79d0d8fc8337b8"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
patchelf = ["patchelf"]
|
|
||||||
zig = ["ziglang (>=0.10.0,<0.11.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "mypy-extensions"
|
|
||||||
version = "1.0.0"
|
|
||||||
description = "Type system extensions for programs checked with the mypy type checker."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.5"
|
|
||||||
files = [
|
|
||||||
{file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
|
|
||||||
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "packaging"
|
|
||||||
version = "23.1"
|
|
||||||
description = "Core utilities for Python packages"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
|
|
||||||
{file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parso"
|
|
||||||
version = "0.8.3"
|
|
||||||
description = "A Python Parser"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"},
|
|
||||||
{file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
|
|
||||||
testing = ["docopt", "pytest (<6.0.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pathspec"
|
|
||||||
version = "0.11.1"
|
|
||||||
description = "Utility library for gitignore style pattern matching of file paths."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"},
|
|
||||||
{file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pexpect"
|
|
||||||
version = "4.8.0"
|
|
||||||
description = "Pexpect allows easy control of interactive console applications."
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"},
|
|
||||||
{file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
ptyprocess = ">=0.5"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pickleshare"
|
|
||||||
version = "0.7.5"
|
|
||||||
description = "Tiny 'shelve'-like database with concurrency support"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"},
|
|
||||||
{file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "platformdirs"
|
|
||||||
version = "3.5.1"
|
|
||||||
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"},
|
|
||||||
{file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
typing-extensions = {version = ">=4.5", markers = "python_version < \"3.8\""}
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
|
|
||||||
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pluggy"
|
|
||||||
version = "1.0.0"
|
|
||||||
description = "plugin and hook calling mechanisms for python"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
|
|
||||||
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
dev = ["pre-commit", "tox"]
|
|
||||||
testing = ["pytest", "pytest-benchmark"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "prompt-toolkit"
|
|
||||||
version = "3.0.38"
|
|
||||||
description = "Library for building powerful interactive command lines in Python"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7.0"
|
|
||||||
files = [
|
|
||||||
{file = "prompt_toolkit-3.0.38-py3-none-any.whl", hash = "sha256:45ea77a2f7c60418850331366c81cf6b5b9cf4c7fd34616f733c5427e6abbb1f"},
|
|
||||||
{file = "prompt_toolkit-3.0.38.tar.gz", hash = "sha256:23ac5d50538a9a38c8bde05fecb47d0b403ecd0662857a86f886f798563d5b9b"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
wcwidth = "*"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ptyprocess"
|
|
||||||
version = "0.7.0"
|
|
||||||
description = "Run a subprocess in a pseudo terminal"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"},
|
|
||||||
{file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pygments"
|
|
||||||
version = "2.15.1"
|
|
||||||
description = "Pygments is a syntax highlighting package written in Python."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"},
|
|
||||||
{file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
plugins = ["importlib-metadata"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pytest"
|
|
||||||
version = "7.3.1"
|
|
||||||
description = "pytest: simple powerful testing with Python"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"},
|
|
||||||
{file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
|
||||||
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
|
|
||||||
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
|
|
||||||
iniconfig = "*"
|
|
||||||
packaging = "*"
|
|
||||||
pluggy = ">=0.12,<2.0"
|
|
||||||
tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ruff"
|
|
||||||
version = "0.0.270"
|
|
||||||
description = "An extremely fast Python linter, written in Rust."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "ruff-0.0.270-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:f74c4d550f7b8e808455ac77bbce38daafc458434815ba0bc21ae4bdb276509b"},
|
|
||||||
{file = "ruff-0.0.270-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:643de865fd35cb76c4f0739aea5afe7b8e4d40d623df7e9e6ea99054e5cead0a"},
|
|
||||||
{file = "ruff-0.0.270-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eca02e709b3308eb7255b5f74e779be23b5980fca3862eae28bb23069cd61ae4"},
|
|
||||||
{file = "ruff-0.0.270-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3ed3b198768d2b3a2300fb18f730cd39948a5cc36ba29ae9d4639a11040880be"},
|
|
||||||
{file = "ruff-0.0.270-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:739495d2dbde87cf4e3110c8d27bc20febf93112539a968a4e02c26f0deccd1d"},
|
|
||||||
{file = "ruff-0.0.270-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:08188f8351f4c0b6216e8463df0a76eb57894ca59a3da65e4ed205db980fd3ae"},
|
|
||||||
{file = "ruff-0.0.270-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0827b074635d37984fc98d99316bfab5c8b1231bb83e60dacc83bd92883eedb4"},
|
|
||||||
{file = "ruff-0.0.270-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d61ae4841313f6eeb8292dc349bef27b4ce426e62c36e80ceedc3824e408734"},
|
|
||||||
{file = "ruff-0.0.270-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0eb412f20e77529a01fb94d578b19dcb8331b56f93632aa0cce4a2ea27b7aeba"},
|
|
||||||
{file = "ruff-0.0.270-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b775e2c5fc869359daf8c8b8aa0fd67240201ab2e8d536d14a0edf279af18786"},
|
|
||||||
{file = "ruff-0.0.270-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:21f00e47ab2308617c44435c8dfd9e2e03897461c9e647ec942deb2a235b4cfd"},
|
|
||||||
{file = "ruff-0.0.270-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0bbfbf6fd2436165566ca85f6e57be03ed2f0a994faf40180cfbb3604c9232ef"},
|
|
||||||
{file = "ruff-0.0.270-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8af391ef81f7be960be10886a3c1aac0b298bde7cb9a86ec2b05faeb2081ce6b"},
|
|
||||||
{file = "ruff-0.0.270-py3-none-win32.whl", hash = "sha256:b4c037fe2f75bcd9aed0c89c7c507cb7fa59abae2bd4c8b6fc331a28178655a4"},
|
|
||||||
{file = "ruff-0.0.270-py3-none-win_amd64.whl", hash = "sha256:0012f9b7dc137ab7f1f0355e3c4ca49b562baf6c9fa1180948deeb6648c52957"},
|
|
||||||
{file = "ruff-0.0.270-py3-none-win_arm64.whl", hash = "sha256:9613456b0b375766244c25045e353bc8890c856431cd97893c97b10cc93bd28d"},
|
|
||||||
{file = "ruff-0.0.270.tar.gz", hash = "sha256:95db07b7850b30ebf32b27fe98bc39e0ab99db3985edbbf0754d399eb2f0e690"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "setuptools"
|
|
||||||
version = "67.8.0"
|
|
||||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "setuptools-67.8.0-py3-none-any.whl", hash = "sha256:5df61bf30bb10c6f756eb19e7c9f3b473051f48db77fddbe06ff2ca307df9a6f"},
|
|
||||||
{file = "setuptools-67.8.0.tar.gz", hash = "sha256:62642358adc77ffa87233bc4d2354c4b2682d214048f500964dbe760ccedf102"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
|
|
||||||
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
|
|
||||||
testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokenize-rt"
|
|
||||||
version = "5.0.0"
|
|
||||||
description = "A wrapper around the stdlib `tokenize` which roundtrips."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "tokenize_rt-5.0.0-py2.py3-none-any.whl", hash = "sha256:c67772c662c6b3dc65edf66808577968fb10badfc2042e3027196bed4daf9e5a"},
|
|
||||||
{file = "tokenize_rt-5.0.0.tar.gz", hash = "sha256:3160bc0c3e8491312d0485171dea861fc160a240f5f5766b72a1165408d10740"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tomli"
|
|
||||||
version = "2.0.1"
|
|
||||||
description = "A lil' TOML parser"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
|
|
||||||
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "traitlets"
|
|
||||||
version = "5.9.0"
|
|
||||||
description = "Traitlets Python configuration system"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "traitlets-5.9.0-py3-none-any.whl", hash = "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8"},
|
|
||||||
{file = "traitlets-5.9.0.tar.gz", hash = "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"]
|
|
||||||
test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typed-ast"
|
|
||||||
version = "1.5.4"
|
|
||||||
description = "a fork of Python 2 and 3 ast modules with type comment support"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "typed_ast-1.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4"},
|
|
||||||
{file = "typed_ast-1.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:211260621ab1cd7324e0798d6be953d00b74e0428382991adfddb352252f1d62"},
|
|
||||||
{file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:267e3f78697a6c00c689c03db4876dd1efdfea2f251a5ad6555e82a26847b4ac"},
|
|
||||||
{file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c542eeda69212fa10a7ada75e668876fdec5f856cd3d06829e6aa64ad17c8dfe"},
|
|
||||||
{file = "typed_ast-1.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:a9916d2bb8865f973824fb47436fa45e1ebf2efd920f2b9f99342cb7fab93f72"},
|
|
||||||
{file = "typed_ast-1.5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79b1e0869db7c830ba6a981d58711c88b6677506e648496b1f64ac7d15633aec"},
|
|
||||||
{file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a94d55d142c9265f4ea46fab70977a1944ecae359ae867397757d836ea5a3f47"},
|
|
||||||
{file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:183afdf0ec5b1b211724dfef3d2cad2d767cbefac291f24d69b00546c1837fb6"},
|
|
||||||
{file = "typed_ast-1.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:639c5f0b21776605dd6c9dbe592d5228f021404dafd377e2b7ac046b0349b1a1"},
|
|
||||||
{file = "typed_ast-1.5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf4afcfac006ece570e32d6fa90ab74a17245b83dfd6655a6f68568098345ff6"},
|
|
||||||
{file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed855bbe3eb3715fca349c80174cfcfd699c2f9de574d40527b8429acae23a66"},
|
|
||||||
{file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6778e1b2f81dfc7bc58e4b259363b83d2e509a65198e85d5700dfae4c6c8ff1c"},
|
|
||||||
{file = "typed_ast-1.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:0261195c2062caf107831e92a76764c81227dae162c4f75192c0d489faf751a2"},
|
|
||||||
{file = "typed_ast-1.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2efae9db7a8c05ad5547d522e7dbe62c83d838d3906a3716d1478b6c1d61388d"},
|
|
||||||
{file = "typed_ast-1.5.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7d5d014b7daa8b0bf2eaef684295acae12b036d79f54178b92a2b6a56f92278f"},
|
|
||||||
{file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:370788a63915e82fd6f212865a596a0fefcbb7d408bbbb13dea723d971ed8bdc"},
|
|
||||||
{file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4e964b4ff86550a7a7d56345c7864b18f403f5bd7380edf44a3c1fb4ee7ac6c6"},
|
|
||||||
{file = "typed_ast-1.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:683407d92dc953c8a7347119596f0b0e6c55eb98ebebd9b23437501b28dcbb8e"},
|
|
||||||
{file = "typed_ast-1.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4879da6c9b73443f97e731b617184a596ac1235fe91f98d279a7af36c796da35"},
|
|
||||||
{file = "typed_ast-1.5.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e123d878ba170397916557d31c8f589951e353cc95fb7f24f6bb69adc1a8a97"},
|
|
||||||
{file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebd9d7f80ccf7a82ac5f88c521115cc55d84e35bf8b446fcd7836eb6b98929a3"},
|
|
||||||
{file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98f80dee3c03455e92796b58b98ff6ca0b2a6f652120c263efdba4d6c5e58f72"},
|
|
||||||
{file = "typed_ast-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1"},
|
|
||||||
{file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typing-extensions"
|
|
||||||
version = "4.6.2"
|
|
||||||
description = "Backported and Experimental Type Hints for Python 3.7+"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "typing_extensions-4.6.2-py3-none-any.whl", hash = "sha256:3a8b36f13dd5fdc5d1b16fe317f5668545de77fa0b8e02006381fd49d731ab98"},
|
|
||||||
{file = "typing_extensions-4.6.2.tar.gz", hash = "sha256:06006244c70ac8ee83fa8282cb188f697b8db25bc8b4df07be1873c43897060c"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wcwidth"
|
|
||||||
version = "0.2.6"
|
|
||||||
description = "Measures the displayed width of unicode strings in a terminal"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"},
|
|
||||||
{file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zipp"
|
|
||||||
version = "3.15.0"
|
|
||||||
description = "Backport of pathlib-compatible object wrapper for zip files"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"},
|
|
||||||
{file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
|
||||||
testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
|
|
||||||
|
|
||||||
[metadata]
|
|
||||||
lock-version = "2.0"
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
content-hash = "f64653737d40fcf3c7b9f9fea186e98322fea9e7ee1889b8f8ee181570b26e17"
|
|
|
@ -1,32 +0,0 @@
|
||||||
[project]
|
|
||||||
name = "pep508_rs"
|
|
||||||
version = "0.2.2"
|
|
||||||
description = "A library for python dependency specifiers, better known as PEP 508"
|
|
||||||
readme = "Readme.md"
|
|
||||||
|
|
||||||
[tool.poetry]
|
|
||||||
name = "pep508_rs"
|
|
||||||
version = "0.1.1"
|
|
||||||
description = ""
|
|
||||||
authors = ["konstin <konstin@mailbox.org>"]
|
|
||||||
readme = "Readme.md"
|
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
|
||||||
python = ">=3.7"
|
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
|
||||||
black = { extras = ["jupyter"], version = "^23.1.0" }
|
|
||||||
maturin = "^1.0.0"
|
|
||||||
pytest = "^7.2.0"
|
|
||||||
ruff = "^0.0.270"
|
|
||||||
|
|
||||||
[tool.maturin]
|
|
||||||
features = ["pyo3"]
|
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
|
||||||
minversion = "7.2.0"
|
|
||||||
addopts = "--tb=short"
|
|
||||||
|
|
||||||
[build-system]
|
|
||||||
requires = ["maturin>=1.0,<2.0"]
|
|
||||||
build-backend = "maturin"
|
|
|
@ -16,8 +16,6 @@
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
mod marker;
|
mod marker;
|
||||||
#[cfg(feature = "modern")]
|
|
||||||
pub mod modern;
|
|
||||||
|
|
||||||
pub use marker::{
|
pub use marker::{
|
||||||
MarkerEnvironment, MarkerExpression, MarkerOperator, MarkerTree, MarkerValue,
|
MarkerEnvironment, MarkerExpression, MarkerOperator, MarkerTree, MarkerValue,
|
||||||
|
@ -125,8 +123,8 @@ create_exception!(
|
||||||
);
|
);
|
||||||
|
|
||||||
/// A PEP 508 dependency specification
|
/// A PEP 508 dependency specification
|
||||||
#[cfg_attr(feature = "pyo3", pyclass(module = "pep508"))]
|
|
||||||
#[derive(Hash, Debug, Clone, Eq, PartialEq)]
|
#[derive(Hash, Debug, Clone, Eq, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "pyo3", pyclass(module = "pep508"))]
|
||||||
pub struct Requirement {
|
pub struct Requirement {
|
||||||
/// The distribution name such as `numpy` in
|
/// The distribution name such as `numpy` in
|
||||||
/// `requests [security,tests] >= 2.8.1, == 2.8.* ; python_version > "3.8"`
|
/// `requests [security,tests] >= 2.8.1, == 2.8.* ; python_version > "3.8"`
|
||||||
|
@ -159,18 +157,18 @@ impl Display for Requirement {
|
||||||
}
|
}
|
||||||
VersionOrUrl::Url(url) => {
|
VersionOrUrl::Url(url) => {
|
||||||
// We add the space for markers later if necessary
|
// We add the space for markers later if necessary
|
||||||
write!(f, " @ {}", url)?;
|
write!(f, " @ {url}")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(marker) = &self.marker {
|
if let Some(marker) = &self.marker {
|
||||||
write!(f, " ; {}", marker)?;
|
write!(f, " ; {marker}")?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://github.com/serde-rs/serde/issues/908#issuecomment-298027413
|
/// <https://github.com/serde-rs/serde/issues/908#issuecomment-298027413>
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
impl<'de> Deserialize<'de> for Requirement {
|
impl<'de> Deserialize<'de> for Requirement {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
@ -182,7 +180,7 @@ impl<'de> Deserialize<'de> for Requirement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://github.com/serde-rs/serde/issues/1316#issue-332908452
|
/// <https://github.com/serde-rs/serde/issues/1316#issue-332908452>
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
impl Serialize for Requirement {
|
impl Serialize for Requirement {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
@ -214,7 +212,7 @@ impl Requirement {
|
||||||
/// `requests [security,tests] >= 2.8.1, == 2.8.* ; python_version > "3.8"`
|
/// `requests [security,tests] >= 2.8.1, == 2.8.* ; python_version > "3.8"`
|
||||||
#[getter]
|
#[getter]
|
||||||
pub fn marker(&self) -> Option<String> {
|
pub fn marker(&self) -> Option<String> {
|
||||||
self.marker.as_ref().map(|m| m.to_string())
|
self.marker.as_ref().map(std::string::ToString::to_string)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a PEP 440 string
|
/// Parses a PEP 440 string
|
||||||
|
@ -241,7 +239,7 @@ impl Requirement {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __repr__(&self) -> String {
|
fn __repr__(&self) -> String {
|
||||||
format!(r#""{}""#, self)
|
format!(r#""{self}""#)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult<bool> {
|
fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult<bool> {
|
||||||
|
@ -263,9 +261,10 @@ impl Requirement {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether the markers apply for the given environment
|
/// Returns whether the markers apply for the given environment
|
||||||
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
#[pyo3(name = "evaluate_markers")]
|
#[pyo3(name = "evaluate_markers")]
|
||||||
pub fn py_evaluate_markers(&self, env: &MarkerEnvironment, extras: Vec<String>) -> bool {
|
pub fn py_evaluate_markers(&self, env: &MarkerEnvironment, extras: Vec<String>) -> bool {
|
||||||
self.evaluate_markers(env, extras)
|
self.evaluate_markers(env, &extras)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether the requirement would be satisfied, independent of environment markers, i.e.
|
/// Returns whether the requirement would be satisfied, independent of environment markers, i.e.
|
||||||
|
@ -274,6 +273,7 @@ impl Requirement {
|
||||||
/// Note that unlike [Self::evaluate_markers] this does not perform any checks for bogus
|
/// Note that unlike [Self::evaluate_markers] this does not perform any checks for bogus
|
||||||
/// expressions but will simply return true. As caller you should separately perform a check
|
/// expressions but will simply return true. As caller you should separately perform a check
|
||||||
/// with an environment and forward all warnings.
|
/// with an environment and forward all warnings.
|
||||||
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
#[pyo3(name = "evaluate_extras_and_python_version")]
|
#[pyo3(name = "evaluate_extras_and_python_version")]
|
||||||
pub fn py_evaluate_extras_and_python_version(
|
pub fn py_evaluate_extras_and_python_version(
|
||||||
&self,
|
&self,
|
||||||
|
@ -281,28 +281,29 @@ impl Requirement {
|
||||||
python_versions: Vec<PyVersion>,
|
python_versions: Vec<PyVersion>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
self.evaluate_extras_and_python_version(
|
self.evaluate_extras_and_python_version(
|
||||||
extras,
|
&extras,
|
||||||
python_versions
|
&python_versions
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|py_version| py_version.0)
|
.map(|py_version| py_version.0)
|
||||||
.collect(),
|
.collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether the markers apply for the given environment
|
/// Returns whether the markers apply for the given environment
|
||||||
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
#[pyo3(name = "evaluate_markers_and_report")]
|
#[pyo3(name = "evaluate_markers_and_report")]
|
||||||
pub fn py_evaluate_markers_and_report(
|
pub fn py_evaluate_markers_and_report(
|
||||||
&self,
|
&self,
|
||||||
env: &MarkerEnvironment,
|
env: &MarkerEnvironment,
|
||||||
extras: Vec<String>,
|
extras: Vec<String>,
|
||||||
) -> (bool, Vec<(MarkerWarningKind, String, String)>) {
|
) -> (bool, Vec<(MarkerWarningKind, String, String)>) {
|
||||||
self.evaluate_markers_and_report(env, extras)
|
self.evaluate_markers_and_report(env, &extras)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Requirement {
|
impl Requirement {
|
||||||
/// Returns whether the markers apply for the given environment
|
/// Returns whether the markers apply for the given environment
|
||||||
pub fn evaluate_markers(&self, env: &MarkerEnvironment, extras: Vec<String>) -> bool {
|
pub fn evaluate_markers(&self, env: &MarkerEnvironment, extras: &[String]) -> bool {
|
||||||
if let Some(marker) = &self.marker {
|
if let Some(marker) = &self.marker {
|
||||||
marker.evaluate(
|
marker.evaluate(
|
||||||
env,
|
env,
|
||||||
|
@ -316,16 +317,16 @@ impl Requirement {
|
||||||
/// Returns whether the requirement would be satisfied, independent of environment markers, i.e.
|
/// Returns whether the requirement would be satisfied, independent of environment markers, i.e.
|
||||||
/// if there is potentially an environment that could activate this requirement.
|
/// if there is potentially an environment that could activate this requirement.
|
||||||
///
|
///
|
||||||
/// Note that unlike [Self::evaluate_markers] this does not perform any checks for bogus
|
/// Note that unlike [`Self::evaluate_markers`] this does not perform any checks for bogus
|
||||||
/// expressions but will simply return true. As caller you should separately perform a check
|
/// expressions but will simply return true. As caller you should separately perform a check
|
||||||
/// with an environment and forward all warnings.
|
/// with an environment and forward all warnings.
|
||||||
pub fn evaluate_extras_and_python_version(
|
pub fn evaluate_extras_and_python_version(
|
||||||
&self,
|
&self,
|
||||||
extras: HashSet<String>,
|
extras: &HashSet<String>,
|
||||||
python_versions: Vec<Version>,
|
python_versions: &[Version],
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if let Some(marker) = &self.marker {
|
if let Some(marker) = &self.marker {
|
||||||
marker.evaluate_extras_and_python_version(&extras, &python_versions)
|
marker.evaluate_extras_and_python_version(extras, python_versions)
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -335,12 +336,15 @@ impl Requirement {
|
||||||
pub fn evaluate_markers_and_report(
|
pub fn evaluate_markers_and_report(
|
||||||
&self,
|
&self,
|
||||||
env: &MarkerEnvironment,
|
env: &MarkerEnvironment,
|
||||||
extras: Vec<String>,
|
extras: &[String],
|
||||||
) -> (bool, Vec<(MarkerWarningKind, String, String)>) {
|
) -> (bool, Vec<(MarkerWarningKind, String, String)>) {
|
||||||
if let Some(marker) = &self.marker {
|
if let Some(marker) = &self.marker {
|
||||||
marker.evaluate_collect_warnings(
|
marker.evaluate_collect_warnings(
|
||||||
env,
|
env,
|
||||||
&extras.iter().map(|x| x.as_str()).collect::<Vec<&str>>(),
|
&extras
|
||||||
|
.iter()
|
||||||
|
.map(std::string::String::as_str)
|
||||||
|
.collect::<Vec<&str>>(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(true, Vec::new())
|
(true, Vec::new())
|
||||||
|
@ -448,12 +452,12 @@ impl<'a> CharIter<'a> {
|
||||||
while let Some(char) = self.peek_char() {
|
while let Some(char) = self.peek_char() {
|
||||||
if !condition(char) {
|
if !condition(char) {
|
||||||
break;
|
break;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
substring.push(char);
|
substring.push(char);
|
||||||
self.next();
|
self.next();
|
||||||
len += 1;
|
len += 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
(substring, start, len)
|
(substring, start, len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,8 +465,7 @@ impl<'a> CharIter<'a> {
|
||||||
match self.next() {
|
match self.next() {
|
||||||
None => Err(Pep508Error {
|
None => Err(Pep508Error {
|
||||||
message: Pep508ErrorSource::String(format!(
|
message: Pep508ErrorSource::String(format!(
|
||||||
"Expected '{}', found end of dependency specification",
|
"Expected '{expected}', found end of dependency specification"
|
||||||
expected
|
|
||||||
)),
|
)),
|
||||||
start: span_start,
|
start: span_start,
|
||||||
len: 1,
|
len: 1,
|
||||||
|
@ -471,8 +474,7 @@ impl<'a> CharIter<'a> {
|
||||||
Some((_, value)) if value == expected => Ok(()),
|
Some((_, value)) if value == expected => Ok(()),
|
||||||
Some((pos, other)) => Err(Pep508Error {
|
Some((pos, other)) => Err(Pep508Error {
|
||||||
message: Pep508ErrorSource::String(format!(
|
message: Pep508ErrorSource::String(format!(
|
||||||
"Expected '{}', found '{}'",
|
"Expected '{expected}', found '{other}'"
|
||||||
expected, other
|
|
||||||
)),
|
)),
|
||||||
start: pos,
|
start: pos,
|
||||||
len: 1,
|
len: 1,
|
||||||
|
@ -502,8 +504,7 @@ fn parse_name(chars: &mut CharIter) -> Result<String, Pep508Error> {
|
||||||
} else {
|
} else {
|
||||||
return Err(Pep508Error {
|
return Err(Pep508Error {
|
||||||
message: Pep508ErrorSource::String(format!(
|
message: Pep508ErrorSource::String(format!(
|
||||||
"Expected package name starting with an alphanumeric character, found '{}'",
|
"Expected package name starting with an alphanumeric character, found '{char}'"
|
||||||
char
|
|
||||||
)),
|
)),
|
||||||
start: index,
|
start: index,
|
||||||
len: 1,
|
len: 1,
|
||||||
|
@ -528,8 +529,7 @@ fn parse_name(chars: &mut CharIter) -> Result<String, Pep508Error> {
|
||||||
if chars.peek().is_none() && matches!(char, '.' | '-' | '_') {
|
if chars.peek().is_none() && matches!(char, '.' | '-' | '_') {
|
||||||
return Err(Pep508Error {
|
return Err(Pep508Error {
|
||||||
message: Pep508ErrorSource::String(format!(
|
message: Pep508ErrorSource::String(format!(
|
||||||
"Package name must end with an alphanumeric character, not '{}'",
|
"Package name must end with an alphanumeric character, not '{char}'"
|
||||||
char
|
|
||||||
)),
|
)),
|
||||||
start: index,
|
start: index,
|
||||||
len: 1,
|
len: 1,
|
||||||
|
@ -544,9 +544,8 @@ fn parse_name(chars: &mut CharIter) -> Result<String, Pep508Error> {
|
||||||
|
|
||||||
/// parses extras in the `[extra1,extra2] format`
|
/// parses extras in the `[extra1,extra2] format`
|
||||||
fn parse_extras(chars: &mut CharIter) -> Result<Option<Vec<String>>, Pep508Error> {
|
fn parse_extras(chars: &mut CharIter) -> Result<Option<Vec<String>>, Pep508Error> {
|
||||||
let bracket_pos = match chars.eat('[') {
|
let Some(bracket_pos) = chars.eat('[') else {
|
||||||
Some(pos) => pos,
|
return Ok(None);
|
||||||
None => return Ok(None),
|
|
||||||
};
|
};
|
||||||
let mut extras = Vec::new();
|
let mut extras = Vec::new();
|
||||||
|
|
||||||
|
@ -568,13 +567,12 @@ fn parse_extras(chars: &mut CharIter) -> Result<Option<Vec<String>>, Pep508Error
|
||||||
match chars.next() {
|
match chars.next() {
|
||||||
// letterOrDigit
|
// letterOrDigit
|
||||||
Some((_, alphanumeric @ ('a'..='z' | 'A'..='Z' | '0'..='9'))) => {
|
Some((_, alphanumeric @ ('a'..='z' | 'A'..='Z' | '0'..='9'))) => {
|
||||||
buffer.push(alphanumeric)
|
buffer.push(alphanumeric);
|
||||||
}
|
}
|
||||||
Some((pos, other)) => {
|
Some((pos, other)) => {
|
||||||
return Err(Pep508Error {
|
return Err(Pep508Error {
|
||||||
message: Pep508ErrorSource::String(format!(
|
message: Pep508ErrorSource::String(format!(
|
||||||
"Expected an alphanumeric character starting the extra name, found '{}'",
|
"Expected an alphanumeric character starting the extra name, found '{other}'"
|
||||||
other
|
|
||||||
)),
|
)),
|
||||||
start: pos,
|
start: pos,
|
||||||
len: 1,
|
len: 1,
|
||||||
|
@ -598,7 +596,7 @@ fn parse_extras(chars: &mut CharIter) -> Result<Option<Vec<String>>, Pep508Error
|
||||||
Some((pos, char)) if char != ',' && char != ']' && !char.is_whitespace() => {
|
Some((pos, char)) if char != ',' && char != ']' && !char.is_whitespace() => {
|
||||||
return Err(Pep508Error {
|
return Err(Pep508Error {
|
||||||
message: Pep508ErrorSource::String(format!(
|
message: Pep508ErrorSource::String(format!(
|
||||||
"Invalid character in extras name, expected an alphanumeric character, '-', '_', '.', ',' or ']', found '{}'", char
|
"Invalid character in extras name, expected an alphanumeric character, '-', '_', '.', ',' or ']', found '{char}'"
|
||||||
)),
|
)),
|
||||||
start: pos,
|
start: pos,
|
||||||
len: 1,
|
len: 1,
|
||||||
|
@ -786,8 +784,7 @@ fn parse(chars: &mut CharIter) -> Result<Requirement, Pep508Error> {
|
||||||
Some(other) => {
|
Some(other) => {
|
||||||
return Err(Pep508Error {
|
return Err(Pep508Error {
|
||||||
message: Pep508ErrorSource::String(format!(
|
message: Pep508ErrorSource::String(format!(
|
||||||
"Expected one of `@`, `(`, `<`, `=`, `>`, `~`, `!`, `;`, found `{}`",
|
"Expected one of `@`, `(`, `<`, `=`, `>`, `~`, `!`, `;`, found `{other}`"
|
||||||
other
|
|
||||||
)),
|
)),
|
||||||
start: chars.get_pos(),
|
start: chars.get_pos(),
|
||||||
len: 1,
|
len: 1,
|
||||||
|
@ -811,9 +808,9 @@ fn parse(chars: &mut CharIter) -> Result<Requirement, Pep508Error> {
|
||||||
if let Some((pos, char)) = chars.next() {
|
if let Some((pos, char)) = chars.next() {
|
||||||
return Err(Pep508Error {
|
return Err(Pep508Error {
|
||||||
message: Pep508ErrorSource::String(if marker.is_none() {
|
message: Pep508ErrorSource::String(if marker.is_none() {
|
||||||
format!(r#"Expected end of input or ';', found '{}'"#, char)
|
format!(r#"Expected end of input or ';', found '{char}'"#)
|
||||||
} else {
|
} else {
|
||||||
format!(r#"Expected end of input, found '{}'"#, char)
|
format!(r#"Expected end of input, found '{char}'"#)
|
||||||
}),
|
}),
|
||||||
start: pos,
|
start: pos,
|
||||||
len: 1,
|
len: 1,
|
||||||
|
@ -854,7 +851,7 @@ pub fn python_module(py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Half of these tests are copied from https://github.com/pypa/packaging/pull/624
|
/// Half of these tests are copied from <https://github.com/pypa/packaging/pull/624>
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::marker::{
|
use crate::marker::{
|
||||||
|
|
|
@ -24,8 +24,8 @@ use std::str::FromStr;
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
/// Ways in which marker evaluation can fail
|
/// Ways in which marker evaluation can fail
|
||||||
#[cfg_attr(feature = "pyo3", pyclass(module = "pep508"))]
|
|
||||||
#[derive(Debug, Eq, Hash, Ord, PartialOrd, PartialEq, Clone, Copy)]
|
#[derive(Debug, Eq, Hash, Ord, PartialOrd, PartialEq, Clone, Copy)]
|
||||||
|
#[cfg_attr(feature = "pyo3", pyclass(module = "pep508"))]
|
||||||
pub enum MarkerWarningKind {
|
pub enum MarkerWarningKind {
|
||||||
/// Using an old name from PEP 345 instead of the modern equivalent
|
/// Using an old name from PEP 345 instead of the modern equivalent
|
||||||
/// <https://peps.python.org/pep-0345/#environment-markers>
|
/// <https://peps.python.org/pep-0345/#environment-markers>
|
||||||
|
@ -46,12 +46,14 @@ pub enum MarkerWarningKind {
|
||||||
#[cfg(feature = "pyo3")]
|
#[cfg(feature = "pyo3")]
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl MarkerWarningKind {
|
impl MarkerWarningKind {
|
||||||
|
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||||
fn __hash__(&self) -> u8 {
|
fn __hash__(&self) -> u8 {
|
||||||
*self as u8
|
*self as u8
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool {
|
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||||
op.matches(self.cmp(other))
|
fn __richcmp__(&self, other: Self, op: CompareOp) -> bool {
|
||||||
|
op.matches(self.cmp(&other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,15 +86,15 @@ pub enum MarkerValueString {
|
||||||
ImplementationName,
|
ImplementationName,
|
||||||
/// `os_name`
|
/// `os_name`
|
||||||
OsName,
|
OsName,
|
||||||
/// /// Deprecated `os.name` from https://peps.python.org/pep-0345/#environment-markers
|
/// Deprecated `os.name` from <https://peps.python.org/pep-0345/#environment-markers>
|
||||||
OsNameDeprecated,
|
OsNameDeprecated,
|
||||||
/// `platform_machine`
|
/// `platform_machine`
|
||||||
PlatformMachine,
|
PlatformMachine,
|
||||||
/// /// Deprecated `platform.machine` from https://peps.python.org/pep-0345/#environment-markers
|
/// Deprecated `platform.machine` from <https://peps.python.org/pep-0345/#environment-markers>
|
||||||
PlatformMachineDeprecated,
|
PlatformMachineDeprecated,
|
||||||
/// `platform_python_implementation`
|
/// `platform_python_implementation`
|
||||||
PlatformPythonImplementation,
|
PlatformPythonImplementation,
|
||||||
/// /// Deprecated `platform.python_implementation` from https://peps.python.org/pep-0345/#environment-markers
|
/// Deprecated `platform.python_implementation` from <https://peps.python.org/pep-0345/#environment-markers>
|
||||||
PlatformPythonImplementationDeprecated,
|
PlatformPythonImplementationDeprecated,
|
||||||
/// `platform_release`
|
/// `platform_release`
|
||||||
PlatformRelease,
|
PlatformRelease,
|
||||||
|
@ -100,11 +102,11 @@ pub enum MarkerValueString {
|
||||||
PlatformSystem,
|
PlatformSystem,
|
||||||
/// `platform_version`
|
/// `platform_version`
|
||||||
PlatformVersion,
|
PlatformVersion,
|
||||||
/// /// Deprecated `platform.version` from https://peps.python.org/pep-0345/#environment-markers
|
/// Deprecated `platform.version` from <https://peps.python.org/pep-0345/#environment-markers>
|
||||||
PlatformVersionDeprecated,
|
PlatformVersionDeprecated,
|
||||||
/// `sys_platform`
|
/// `sys_platform`
|
||||||
SysPlatform,
|
SysPlatform,
|
||||||
/// /// Deprecated `sys.platform` from https://peps.python.org/pep-0345/#environment-markers
|
/// Deprecated `sys.platform` from <https://peps.python.org/pep-0345/#environment-markers>
|
||||||
SysPlatformDeprecated,
|
SysPlatformDeprecated,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +186,7 @@ impl FromStr for MarkerValue {
|
||||||
"sys_platform" => Self::MarkerEnvString(MarkerValueString::SysPlatform),
|
"sys_platform" => Self::MarkerEnvString(MarkerValueString::SysPlatform),
|
||||||
"sys.platform" => Self::MarkerEnvString(MarkerValueString::SysPlatformDeprecated),
|
"sys.platform" => Self::MarkerEnvString(MarkerValueString::SysPlatformDeprecated),
|
||||||
"extra" => Self::Extra,
|
"extra" => Self::Extra,
|
||||||
_ => return Err(format!("Invalid key: {}", s)),
|
_ => return Err(format!("Invalid key: {s}")),
|
||||||
};
|
};
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
@ -196,7 +198,7 @@ impl Display for MarkerValue {
|
||||||
Self::MarkerEnvVersion(marker_value_version) => marker_value_version.fmt(f),
|
Self::MarkerEnvVersion(marker_value_version) => marker_value_version.fmt(f),
|
||||||
Self::MarkerEnvString(marker_value_string) => marker_value_string.fmt(f),
|
Self::MarkerEnvString(marker_value_string) => marker_value_string.fmt(f),
|
||||||
Self::Extra => f.write_str("extra"),
|
Self::Extra => f.write_str("extra"),
|
||||||
Self::QuotedString(value) => write!(f, "'{}'", value),
|
Self::QuotedString(value) => write!(f, "'{value}'"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,7 +269,7 @@ impl FromStr for MarkerOperator {
|
||||||
{
|
{
|
||||||
Self::NotIn
|
Self::NotIn
|
||||||
}
|
}
|
||||||
other => return Err(format!("Invalid comparator: {}", other)),
|
other => return Err(format!("Invalid comparator: {other}")),
|
||||||
};
|
};
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
@ -290,8 +292,8 @@ impl Display for MarkerOperator {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper type with a [Version] and its original text
|
/// Helper type with a [Version] and its original text
|
||||||
#[cfg_attr(feature = "pyo3", pyclass(get_all, module = "pep508"))]
|
|
||||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "pyo3", pyclass(get_all, module = "pep508"))]
|
||||||
pub struct StringVersion {
|
pub struct StringVersion {
|
||||||
/// Original unchanged string
|
/// Original unchanged string
|
||||||
pub string: String,
|
pub string: String,
|
||||||
|
@ -344,7 +346,7 @@ impl Deref for StringVersion {
|
||||||
/// <https://packaging.python.org/en/latest/specifications/dependency-specifiers/#environment-markers>
|
/// <https://packaging.python.org/en/latest/specifications/dependency-specifiers/#environment-markers>
|
||||||
///
|
///
|
||||||
/// Some are `(String, Version)` because we have to support version comparison
|
/// Some are `(String, Version)` because we have to support version comparison
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs, clippy::unsafe_derive_deserialize)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "pyo3", pyclass(get_all, module = "pep508"))]
|
#[cfg_attr(feature = "pyo3", pyclass(get_all, module = "pep508"))]
|
||||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||||
|
@ -431,20 +433,17 @@ impl MarkerEnvironment {
|
||||||
let implementation_version =
|
let implementation_version =
|
||||||
StringVersion::from_str(implementation_version).map_err(|err| {
|
StringVersion::from_str(implementation_version).map_err(|err| {
|
||||||
PyValueError::new_err(format!(
|
PyValueError::new_err(format!(
|
||||||
"implementation_version is not a valid PEP440 version: {}",
|
"implementation_version is not a valid PEP440 version: {err}"
|
||||||
err
|
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
let python_full_version = StringVersion::from_str(python_full_version).map_err(|err| {
|
let python_full_version = StringVersion::from_str(python_full_version).map_err(|err| {
|
||||||
PyValueError::new_err(format!(
|
PyValueError::new_err(format!(
|
||||||
"python_full_version is not a valid PEP440 version: {}",
|
"python_full_version is not a valid PEP440 version: {err}"
|
||||||
err
|
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
let python_version = StringVersion::from_str(python_version).map_err(|err| {
|
let python_version = StringVersion::from_str(python_version).map_err(|err| {
|
||||||
PyValueError::new_err(format!(
|
PyValueError::new_err(format!(
|
||||||
"python_version is not a valid PEP440 version: {}",
|
"python_version is not a valid PEP440 version: {err}"
|
||||||
err
|
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
@ -483,10 +482,10 @@ impl MarkerEnvironment {
|
||||||
info.getattr("major")?.extract::<usize>()?,
|
info.getattr("major")?.extract::<usize>()?,
|
||||||
info.getattr("minor")?.extract::<usize>()?,
|
info.getattr("minor")?.extract::<usize>()?,
|
||||||
info.getattr("micro")?.extract::<usize>()?,
|
info.getattr("micro")?.extract::<usize>()?,
|
||||||
if kind != "final" {
|
if kind == "final" {
|
||||||
format!("{}{}", kind, info.getattr("serial")?.extract::<usize>()?)
|
String::new()
|
||||||
} else {
|
} else {
|
||||||
"".to_string()
|
format!("{}{}", kind, info.getattr("serial")?.extract::<usize>()?)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
let python_full_version: String = platform.getattr("python_version")?.call0()?.extract()?;
|
let python_full_version: String = platform.getattr("python_version")?.call0()?.extract()?;
|
||||||
|
@ -496,20 +495,17 @@ impl MarkerEnvironment {
|
||||||
let implementation_version =
|
let implementation_version =
|
||||||
StringVersion::from_str(&implementation_version).map_err(|err| {
|
StringVersion::from_str(&implementation_version).map_err(|err| {
|
||||||
PyValueError::new_err(format!(
|
PyValueError::new_err(format!(
|
||||||
"Broken python implementation, implementation_version is not a valid PEP440 version: {}",
|
"Broken python implementation, implementation_version is not a valid PEP440 version: {err}"
|
||||||
err
|
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
let python_full_version = StringVersion::from_str(&python_full_version).map_err(|err| {
|
let python_full_version = StringVersion::from_str(&python_full_version).map_err(|err| {
|
||||||
PyValueError::new_err(format!(
|
PyValueError::new_err(format!(
|
||||||
"Broken python implementation, python_full_version is not a valid PEP440 version: {}",
|
"Broken python implementation, python_full_version is not a valid PEP440 version: {err}"
|
||||||
err
|
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
let python_version = StringVersion::from_str(&python_version).map_err(|err| {
|
let python_version = StringVersion::from_str(&python_version).map_err(|err| {
|
||||||
PyValueError::new_err(format!(
|
PyValueError::new_err(format!(
|
||||||
"Broken python implementation, python_version is not a valid PEP440 version: {}",
|
"Broken python implementation, python_version is not a valid PEP440 version: {err}"
|
||||||
err
|
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
@ -546,7 +542,7 @@ pub struct MarkerExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MarkerExpression {
|
impl MarkerExpression {
|
||||||
/// Evaluate a <marker_value> <marker_op> <marker_value> expression
|
/// Evaluate a <`marker_value`> <`marker_op`> <`marker_value`> expression
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
&self,
|
&self,
|
||||||
env: &MarkerEnvironment,
|
env: &MarkerEnvironment,
|
||||||
|
@ -592,7 +588,7 @@ impl MarkerExpression {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
reporter(
|
reporter(
|
||||||
MarkerWarningKind::Pep440Error,
|
MarkerWarningKind::Pep440Error,
|
||||||
format!("Invalid operator/version combination: {}", err),
|
format!("Invalid operator/version combination: {err}"),
|
||||||
self,
|
self,
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
|
@ -664,7 +660,7 @@ impl MarkerExpression {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
reporter(
|
reporter(
|
||||||
MarkerWarningKind::Pep440Error,
|
MarkerWarningKind::Pep440Error,
|
||||||
format!("Invalid operator/version combination: {}", err),
|
format!("Invalid operator/version combination: {err}"),
|
||||||
self,
|
self,
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
|
@ -685,8 +681,7 @@ impl MarkerExpression {
|
||||||
// Not even pypa/packaging 22.0 supports this
|
// Not even pypa/packaging 22.0 supports this
|
||||||
// https://github.com/pypa/packaging/issues/632
|
// https://github.com/pypa/packaging/issues/632
|
||||||
reporter(MarkerWarningKind::StringStringComparison, format!(
|
reporter(MarkerWarningKind::StringStringComparison, format!(
|
||||||
"Comparing two quoted strings with each other doesn't make sense: {}, evaluating to false",
|
"Comparing two quoted strings with each other doesn't make sense: {self}, evaluating to false"
|
||||||
self
|
|
||||||
), self);
|
), self);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -703,7 +698,7 @@ impl MarkerExpression {
|
||||||
/// `python_version <pep PEP 440 operator> '...'` and
|
/// `python_version <pep PEP 440 operator> '...'` and
|
||||||
/// `'...' <pep PEP 440 operator> python_version`.
|
/// `'...' <pep PEP 440 operator> python_version`.
|
||||||
///
|
///
|
||||||
/// Note that unlike [Self::evaluate] this does not perform any checks for bogus expressions but
|
/// Note that unlike [`Self::evaluate`] this does not perform any checks for bogus expressions but
|
||||||
/// will simply return true.
|
/// will simply return true.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
@ -809,7 +804,7 @@ impl MarkerExpression {
|
||||||
MarkerOperator::GreaterThan => {
|
MarkerOperator::GreaterThan => {
|
||||||
reporter(
|
reporter(
|
||||||
MarkerWarningKind::LexicographicComparison,
|
MarkerWarningKind::LexicographicComparison,
|
||||||
format!("Comparing {} and {} lexicographically", l_string, r_string),
|
format!("Comparing {l_string} and {r_string} lexicographically"),
|
||||||
self,
|
self,
|
||||||
);
|
);
|
||||||
l_string > r_string
|
l_string > r_string
|
||||||
|
@ -817,7 +812,7 @@ impl MarkerExpression {
|
||||||
MarkerOperator::GreaterEqual => {
|
MarkerOperator::GreaterEqual => {
|
||||||
reporter(
|
reporter(
|
||||||
MarkerWarningKind::LexicographicComparison,
|
MarkerWarningKind::LexicographicComparison,
|
||||||
format!("Comparing {} and {} lexicographically", l_string, r_string),
|
format!("Comparing {l_string} and {r_string} lexicographically"),
|
||||||
self,
|
self,
|
||||||
);
|
);
|
||||||
l_string >= r_string
|
l_string >= r_string
|
||||||
|
@ -825,7 +820,7 @@ impl MarkerExpression {
|
||||||
MarkerOperator::LessThan => {
|
MarkerOperator::LessThan => {
|
||||||
reporter(
|
reporter(
|
||||||
MarkerWarningKind::LexicographicComparison,
|
MarkerWarningKind::LexicographicComparison,
|
||||||
format!("Comparing {} and {} lexicographically", l_string, r_string),
|
format!("Comparing {l_string} and {r_string} lexicographically"),
|
||||||
self,
|
self,
|
||||||
);
|
);
|
||||||
l_string < r_string
|
l_string < r_string
|
||||||
|
@ -833,7 +828,7 @@ impl MarkerExpression {
|
||||||
MarkerOperator::LessEqual => {
|
MarkerOperator::LessEqual => {
|
||||||
reporter(
|
reporter(
|
||||||
MarkerWarningKind::LexicographicComparison,
|
MarkerWarningKind::LexicographicComparison,
|
||||||
format!("Comparing {} and {} lexicographically", l_string, r_string),
|
format!("Comparing {l_string} and {r_string} lexicographically"),
|
||||||
self,
|
self,
|
||||||
);
|
);
|
||||||
l_string <= r_string
|
l_string <= r_string
|
||||||
|
@ -841,7 +836,7 @@ impl MarkerExpression {
|
||||||
MarkerOperator::TildeEqual => {
|
MarkerOperator::TildeEqual => {
|
||||||
reporter(
|
reporter(
|
||||||
MarkerWarningKind::LexicographicComparison,
|
MarkerWarningKind::LexicographicComparison,
|
||||||
format!("Can't compare {} and {} with `~=`", l_string, r_string),
|
format!("Can't compare {l_string} and {r_string} with `~=`"),
|
||||||
self,
|
self,
|
||||||
);
|
);
|
||||||
false
|
false
|
||||||
|
@ -880,8 +875,7 @@ impl FromStr for MarkerExpression {
|
||||||
if let Some((pos, unexpected)) = chars.next() {
|
if let Some((pos, unexpected)) = chars.next() {
|
||||||
return Err(Pep508Error {
|
return Err(Pep508Error {
|
||||||
message: Pep508ErrorSource::String(format!(
|
message: Pep508ErrorSource::String(format!(
|
||||||
"Unexpected character '{}', expected end of input",
|
"Unexpected character '{unexpected}', expected end of input"
|
||||||
unexpected
|
|
||||||
)),
|
)),
|
||||||
start: pos,
|
start: pos,
|
||||||
len: chars.chars.clone().count(),
|
len: chars.chars.clone().count(),
|
||||||
|
@ -937,7 +931,7 @@ impl MarkerTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Same as [Self::evaluate], but instead of using logging to warn, you can pass your own
|
/// Same as [`Self::evaluate`], but instead of using logging to warn, you can pass your own
|
||||||
/// handler for warnings
|
/// handler for warnings
|
||||||
pub fn evaluate_reporter(
|
pub fn evaluate_reporter(
|
||||||
&self,
|
&self,
|
||||||
|
@ -971,7 +965,7 @@ impl MarkerTree {
|
||||||
/// environment markers, i.e. if there is potentially an environment that could activate this
|
/// environment markers, i.e. if there is potentially an environment that could activate this
|
||||||
/// requirement.
|
/// requirement.
|
||||||
///
|
///
|
||||||
/// Note that unlike [Self::evaluate] this does not perform any checks for bogus expressions but
|
/// Note that unlike [`Self::evaluate`] this does not perform any checks for bogus expressions but
|
||||||
/// will simply return true. As caller you should separately perform a check with an environment
|
/// will simply return true. As caller you should separately perform a check with an environment
|
||||||
/// and forward all warnings.
|
/// and forward all warnings.
|
||||||
pub fn evaluate_extras_and_python_version(
|
pub fn evaluate_extras_and_python_version(
|
||||||
|
@ -992,7 +986,7 @@ impl MarkerTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Same as [Self::evaluate], but instead of using logging to warn, you get a Vec with all
|
/// Same as [`Self::evaluate`], but instead of using logging to warn, you get a Vec with all
|
||||||
/// warnings collected
|
/// warnings collected
|
||||||
pub fn evaluate_collect_warnings(
|
pub fn evaluate_collect_warnings(
|
||||||
&self,
|
&self,
|
||||||
|
@ -1001,7 +995,7 @@ impl MarkerTree {
|
||||||
) -> (bool, Vec<(MarkerWarningKind, String, String)>) {
|
) -> (bool, Vec<(MarkerWarningKind, String, String)>) {
|
||||||
let mut warnings = Vec::new();
|
let mut warnings = Vec::new();
|
||||||
let mut reporter = |kind, warning, marker: &MarkerExpression| {
|
let mut reporter = |kind, warning, marker: &MarkerExpression| {
|
||||||
warnings.push((kind, warning, marker.to_string()))
|
warnings.push((kind, warning, marker.to_string()));
|
||||||
};
|
};
|
||||||
self.report_deprecated_options(&mut reporter);
|
self.report_deprecated_options(&mut reporter);
|
||||||
let result = self.evaluate_reporter_impl(env, extras, &mut reporter);
|
let result = self.evaluate_reporter_impl(env, extras, &mut reporter);
|
||||||
|
@ -1066,12 +1060,12 @@ impl MarkerTree {
|
||||||
}
|
}
|
||||||
MarkerTree::And(expressions) => {
|
MarkerTree::And(expressions) => {
|
||||||
for expression in expressions {
|
for expression in expressions {
|
||||||
expression.report_deprecated_options(reporter)
|
expression.report_deprecated_options(reporter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MarkerTree::Or(expressions) => {
|
MarkerTree::Or(expressions) => {
|
||||||
for expression in expressions {
|
for expression in expressions {
|
||||||
expression.report_deprecated_options(reporter)
|
expression.report_deprecated_options(reporter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1082,13 +1076,13 @@ impl Display for MarkerTree {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
let format_inner = |expression: &MarkerTree| {
|
let format_inner = |expression: &MarkerTree| {
|
||||||
if matches!(expression, MarkerTree::Expression(_)) {
|
if matches!(expression, MarkerTree::Expression(_)) {
|
||||||
format!("{}", expression)
|
format!("{expression}")
|
||||||
} else {
|
} else {
|
||||||
format!("({})", expression)
|
format!("({expression})")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match self {
|
match self {
|
||||||
MarkerTree::Expression(expression) => write!(f, "{}", expression),
|
MarkerTree::Expression(expression) => write!(f, "{expression}"),
|
||||||
MarkerTree::And(and_list) => f.write_str(
|
MarkerTree::And(and_list) => f.write_str(
|
||||||
&and_list
|
&and_list
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -1131,8 +1125,7 @@ fn parse_marker_operator(chars: &mut CharIter) -> Result<MarkerOperator, Pep508E
|
||||||
Some((pos, other)) => {
|
Some((pos, other)) => {
|
||||||
return Err(Pep508Error {
|
return Err(Pep508Error {
|
||||||
message: Pep508ErrorSource::String(format!(
|
message: Pep508ErrorSource::String(format!(
|
||||||
"Expected whitespace after 'not', found '{}'",
|
"Expected whitespace after 'not', found '{other}'"
|
||||||
other
|
|
||||||
)),
|
)),
|
||||||
start: pos,
|
start: pos,
|
||||||
len: 1,
|
len: 1,
|
||||||
|
@ -1147,8 +1140,7 @@ fn parse_marker_operator(chars: &mut CharIter) -> Result<MarkerOperator, Pep508E
|
||||||
}
|
}
|
||||||
MarkerOperator::from_str(&operator).map_err(|_| Pep508Error {
|
MarkerOperator::from_str(&operator).map_err(|_| Pep508Error {
|
||||||
message: Pep508ErrorSource::String(format!(
|
message: Pep508ErrorSource::String(format!(
|
||||||
"Expected a valid marker operator (such as '>=' or 'not in'), found '{}'",
|
"Expected a valid marker operator (such as '>=' or 'not in'), found '{operator}'"
|
||||||
operator
|
|
||||||
)),
|
)),
|
||||||
start,
|
start,
|
||||||
len,
|
len,
|
||||||
|
@ -1156,10 +1148,10 @@ fn parse_marker_operator(chars: &mut CharIter) -> Result<MarkerOperator, Pep508E
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Either a single or double quoted string or one of 'python_version', 'python_full_version',
|
/// Either a single or double quoted string or one of '`python_version`', '`python_full_version`',
|
||||||
/// 'os_name', 'sys_platform', 'platform_release', 'platform_system', 'platform_version',
|
/// '`os_name`', '`sys_platform`', '`platform_release`', '`platform_system`', '`platform_version`',
|
||||||
/// 'platform_machine', 'platform_python_implementation', 'implementation_name',
|
/// '`platform_machine`', '`platform_python_implementation`', '`implementation_name`',
|
||||||
/// 'implementation_version', 'extra'
|
/// '`implementation_version`', 'extra'
|
||||||
fn parse_marker_value(chars: &mut CharIter) -> Result<MarkerValue, Pep508Error> {
|
fn parse_marker_value(chars: &mut CharIter) -> Result<MarkerValue, Pep508Error> {
|
||||||
// > User supplied constants are always encoded as strings with either ' or " quote marks. Note
|
// > User supplied constants are always encoded as strings with either ' or " quote marks. Note
|
||||||
// > that backslash escapes are not defined, but existing implementations do support them. They
|
// > that backslash escapes are not defined, but existing implementations do support them. They
|
||||||
|
@ -1189,8 +1181,7 @@ fn parse_marker_value(chars: &mut CharIter) -> Result<MarkerValue, Pep508Error>
|
||||||
});
|
});
|
||||||
MarkerValue::from_str(&key).map_err(|_| Pep508Error {
|
MarkerValue::from_str(&key).map_err(|_| Pep508Error {
|
||||||
message: Pep508ErrorSource::String(format!(
|
message: Pep508ErrorSource::String(format!(
|
||||||
"Expected a valid marker name, found '{}'",
|
"Expected a valid marker name, found '{key}'"
|
||||||
key
|
|
||||||
)),
|
)),
|
||||||
start,
|
start,
|
||||||
len,
|
len,
|
||||||
|
@ -1303,8 +1294,7 @@ pub(crate) fn parse_markers_impl(chars: &mut CharIter) -> Result<MarkerTree, Pep
|
||||||
// character was neither "and" nor "or"
|
// character was neither "and" nor "or"
|
||||||
return Err(Pep508Error {
|
return Err(Pep508Error {
|
||||||
message: Pep508ErrorSource::String(format!(
|
message: Pep508ErrorSource::String(format!(
|
||||||
"Unexpected character '{}', expected 'and', 'or' or end of input",
|
"Unexpected character '{unexpected}', expected 'and', 'or' or end of input"
|
||||||
unexpected
|
|
||||||
)),
|
)),
|
||||||
start: pos,
|
start: pos,
|
||||||
len: chars.chars.clone().count(),
|
len: chars.chars.clone().count(),
|
||||||
|
@ -1337,14 +1327,14 @@ mod test {
|
||||||
let v37 = StringVersion::from_str("3.7").unwrap();
|
let v37 = StringVersion::from_str("3.7").unwrap();
|
||||||
|
|
||||||
MarkerEnvironment {
|
MarkerEnvironment {
|
||||||
implementation_name: "".to_string(),
|
implementation_name: String::new(),
|
||||||
implementation_version: v37.clone(),
|
implementation_version: v37.clone(),
|
||||||
os_name: "linux".to_string(),
|
os_name: "linux".to_string(),
|
||||||
platform_machine: "".to_string(),
|
platform_machine: String::new(),
|
||||||
platform_python_implementation: "".to_string(),
|
platform_python_implementation: String::new(),
|
||||||
platform_release: "".to_string(),
|
platform_release: String::new(),
|
||||||
platform_system: "".to_string(),
|
platform_system: String::new(),
|
||||||
platform_version: "".to_string(),
|
platform_version: String::new(),
|
||||||
python_full_version: v37.clone(),
|
python_full_version: v37.clone(),
|
||||||
python_version: v37,
|
python_version: v37,
|
||||||
sys_platform: "linux".to_string(),
|
sys_platform: "linux".to_string(),
|
||||||
|
@ -1383,9 +1373,7 @@ mod test {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
MarkerTree::from_str(a).unwrap(),
|
MarkerTree::from_str(a).unwrap(),
|
||||||
MarkerTree::from_str(b).unwrap(),
|
MarkerTree::from_str(b).unwrap(),
|
||||||
"{} {}",
|
"{a} {b}"
|
||||||
a,
|
|
||||||
b
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1394,14 +1382,14 @@ mod test {
|
||||||
fn test_marker_evaluation() {
|
fn test_marker_evaluation() {
|
||||||
let v27 = StringVersion::from_str("2.7").unwrap();
|
let v27 = StringVersion::from_str("2.7").unwrap();
|
||||||
let env27 = MarkerEnvironment {
|
let env27 = MarkerEnvironment {
|
||||||
implementation_name: "".to_string(),
|
implementation_name: String::new(),
|
||||||
implementation_version: v27.clone(),
|
implementation_version: v27.clone(),
|
||||||
os_name: "linux".to_string(),
|
os_name: "linux".to_string(),
|
||||||
platform_machine: "".to_string(),
|
platform_machine: String::new(),
|
||||||
platform_python_implementation: "".to_string(),
|
platform_python_implementation: String::new(),
|
||||||
platform_release: "".to_string(),
|
platform_release: String::new(),
|
||||||
platform_system: "".to_string(),
|
platform_system: String::new(),
|
||||||
platform_version: "".to_string(),
|
platform_version: String::new(),
|
||||||
python_full_version: v27.clone(),
|
python_full_version: v27.clone(),
|
||||||
python_version: v27,
|
python_version: v27,
|
||||||
sys_platform: "linux".to_string(),
|
sys_platform: "linux".to_string(),
|
||||||
|
|
|
@ -1,362 +0,0 @@
|
||||||
//! WIP Draft for a poetry/cargo like, modern dependency specification
|
|
||||||
//!
|
|
||||||
//! This still needs
|
|
||||||
//! * Better VersionSpecifier (e.g. allowing `^1.19`) and it's sentry integration
|
|
||||||
//! * PEP 440/PEP 508 translation
|
|
||||||
//! * a json schema
|
|
||||||
|
|
||||||
#![cfg(feature = "modern")]
|
|
||||||
|
|
||||||
use crate::MarkerValue::QuotedString;
|
|
||||||
use crate::{MarkerExpression, MarkerOperator, MarkerTree, MarkerValue, Requirement, VersionOrUrl};
|
|
||||||
use anyhow::{bail, format_err, Context};
|
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use pep440_rs::{Operator, Pep440Error, Version, VersionSpecifier, VersionSpecifiers};
|
|
||||||
use regex::Regex;
|
|
||||||
use serde::{de, Deserialize, Deserializer, Serialize};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::str::FromStr;
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
/// Shared fields for version/git/file/path/url dependencies (`optional`, `extras`, `markers`)
|
|
||||||
#[derive(Eq, PartialEq, Debug, Clone, Deserialize, Serialize)]
|
|
||||||
pub struct RequirementModernCommon {
|
|
||||||
/// Whether this is an optional dependency. This is inverted from PEP 508 extras where the
|
|
||||||
/// requirements has the extras attached, as here the extras has a table where each extra
|
|
||||||
/// says which optional dependencies it activates
|
|
||||||
#[serde(default)]
|
|
||||||
pub optional: bool,
|
|
||||||
/// The list of extras <https://packaging.python.org/en/latest/tutorials/installing-packages/#installing-extras>
|
|
||||||
pub extras: Option<Vec<String>>,
|
|
||||||
/// The list of markers <https://peps.python.org/pep-0508/#environment-markers>.
|
|
||||||
/// Note that this will not accept extras.
|
|
||||||
///
|
|
||||||
/// TODO: Deserialize into `MarkerTree` that does not accept the extras key
|
|
||||||
pub markers: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Instead of only PEP 440 specifier, you can also set a single version (exact) or TODO use
|
|
||||||
/// the semver caret
|
|
||||||
#[derive(Eq, PartialEq, Debug, Clone, Serialize)]
|
|
||||||
pub enum VersionSpecifierModern {
|
|
||||||
/// e.g. `4.12.1-beta.1`
|
|
||||||
Version(Version),
|
|
||||||
/// e.g. `== 4.12.1-beta.1` or `>=3.8,<4.0`
|
|
||||||
VersionSpecifier(VersionSpecifiers),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VersionSpecifierModern {
|
|
||||||
/// `4.12.1-beta.1` -> `== 4.12.1-beta.1`
|
|
||||||
/// `== 4.12.1-beta.1` -> `== 4.12.1-beta.1`
|
|
||||||
/// `>=3.8,<4.0` -> `>=3.8,<4.0`
|
|
||||||
/// TODO: `^1.19` -> `>=1.19,<2.0`
|
|
||||||
pub fn to_pep508_specifier(&self) -> VersionSpecifiers {
|
|
||||||
match self {
|
|
||||||
// unwrapping is safe here because we're using Operator::Equal
|
|
||||||
VersionSpecifierModern::Version(version) => {
|
|
||||||
[VersionSpecifier::new(Operator::Equal, version.clone(), false).unwrap()]
|
|
||||||
.into_iter()
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
VersionSpecifierModern::VersionSpecifier(version_specifiers) => {
|
|
||||||
version_specifiers.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for VersionSpecifierModern {
|
|
||||||
/// TODO: Modern needs it's own error type
|
|
||||||
type Err = Pep440Error;
|
|
||||||
|
|
||||||
/// dispatching between just a version and a version specifier set
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
// If it starts with
|
|
||||||
if s.trim_start().starts_with(|x: char| x.is_ascii_digit()) {
|
|
||||||
Ok(Self::Version(Version::from_str(s).map_err(|err| {
|
|
||||||
// TODO: Fix this in pep440_rs
|
|
||||||
Pep440Error {
|
|
||||||
message: err,
|
|
||||||
line: s.to_string(),
|
|
||||||
start: 0,
|
|
||||||
width: 1,
|
|
||||||
}
|
|
||||||
})?))
|
|
||||||
} else if s.starts_with('^') {
|
|
||||||
todo!("TODO caret operator is not supported yet");
|
|
||||||
} else {
|
|
||||||
Ok(Self::VersionSpecifier(VersionSpecifiers::from_str(s)?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// https://github.com/serde-rs/serde/issues/908#issuecomment-298027413
|
|
||||||
impl<'de> Deserialize<'de> for VersionSpecifierModern {
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let s = String::deserialize(deserializer)?;
|
|
||||||
FromStr::from_str(&s).map_err(de::Error::custom)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// WIP Draft for a poetry/cargo like, modern dependency specification
|
|
||||||
#[derive(Eq, PartialEq, Debug, Clone, Deserialize, Serialize)]
|
|
||||||
#[serde(untagged)]
|
|
||||||
pub enum RequirementModern {
|
|
||||||
/// e.g. `numpy = "1.24.1"`
|
|
||||||
Dependency(VersionSpecifierModern),
|
|
||||||
/// e.g. `numpy = { version = "1.24.1" }` or `django-anymail = { version = "1.24.1", extras = ["sendgrid"], optional = true }`
|
|
||||||
LongDependency {
|
|
||||||
/// e.g. `1.2.3.beta1`
|
|
||||||
version: VersionSpecifierModern,
|
|
||||||
#[serde(flatten)]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
common: RequirementModernCommon,
|
|
||||||
},
|
|
||||||
/// e.g. `tqdm = { git = "https://github.com/tqdm/tqdm", rev = "0bb91857eca0d4aea08f66cf1c8949abe0cd6b7a" }`
|
|
||||||
GitDependency {
|
|
||||||
/// URL of the git repository e.g. `https://github.com/tqdm/tqdm`
|
|
||||||
git: Url,
|
|
||||||
/// The git branch to use
|
|
||||||
branch: Option<String>,
|
|
||||||
/// The git revision to use. Can be the short revision (`0bb9185`) or the long revision
|
|
||||||
/// (`0bb91857eca0d4aea08f66cf1c8949abe0cd6b7a`)
|
|
||||||
rev: Option<String>,
|
|
||||||
#[serde(flatten)]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
common: RequirementModernCommon,
|
|
||||||
},
|
|
||||||
/// e.g. `tqdm = { file = "tqdm-4.65.0-py3-none-any.whl" }`
|
|
||||||
FileDependency {
|
|
||||||
/// Path to a source distribution (e.g. `tqdm-4.65.0.tar.gz`) or wheel (e.g. `tqdm-4.65.0-py3-none-any.whl`)
|
|
||||||
file: String,
|
|
||||||
#[serde(flatten)]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
common: RequirementModernCommon,
|
|
||||||
},
|
|
||||||
/// Path to a directory with source distributions and/or wheels e.g.
|
|
||||||
/// `scilib_core = { path = "build_wheels/scilib_core/" }`.
|
|
||||||
///
|
|
||||||
/// Use this option if you e.g. have multiple platform platform dependent wheels or want to
|
|
||||||
/// have a fallback to a source distribution for you wheel.
|
|
||||||
PathDependency {
|
|
||||||
/// e.g. `dist/`, `target/wheels` or `vendored`
|
|
||||||
path: String,
|
|
||||||
#[serde(flatten)]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
common: RequirementModernCommon,
|
|
||||||
},
|
|
||||||
/// e.g. `jax = { url = "https://storage.googleapis.com/jax-releases/cuda112/jaxlib-0.1.64+cuda112-cp39-none-manylinux2010_x86_64.whl" }`
|
|
||||||
UrlDependency {
|
|
||||||
/// URL to a source distribution or wheel. The file available there must be named
|
|
||||||
/// appropriately for a source distribution or a wheel.
|
|
||||||
url: Url,
|
|
||||||
#[serde(flatten)]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
common: RequirementModernCommon,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adopted from the grammar at <https://peps.python.org/pep-0508/#extras>
|
|
||||||
static EXTRA_REGEX: Lazy<Regex> =
|
|
||||||
Lazy::new(|| Regex::new(r"^[a-zA-Z0-9]([-_.]*[a-zA-Z0-9])*$").unwrap());
|
|
||||||
|
|
||||||
impl RequirementModern {
|
|
||||||
/// Check the things that serde doesn't check, namely that extra names are valid
|
|
||||||
pub fn check(&self) -> anyhow::Result<()> {
|
|
||||||
match self {
|
|
||||||
Self::LongDependency { common, .. }
|
|
||||||
| Self::GitDependency { common, .. }
|
|
||||||
| Self::FileDependency { common, .. }
|
|
||||||
| Self::PathDependency { common, .. }
|
|
||||||
| Self::UrlDependency { common, .. } => {
|
|
||||||
if let Some(extras) = &common.extras {
|
|
||||||
for extra in extras {
|
|
||||||
if !EXTRA_REGEX.is_match(extra) {
|
|
||||||
bail!("Not a valid extra name: '{}'", extra)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// WIP Converts the modern format to PEP 508
|
|
||||||
pub fn to_pep508(
|
|
||||||
&self,
|
|
||||||
name: &str,
|
|
||||||
extras: &HashMap<String, Vec<String>>,
|
|
||||||
) -> Result<Requirement, anyhow::Error> {
|
|
||||||
let default = RequirementModernCommon {
|
|
||||||
optional: false,
|
|
||||||
extras: None,
|
|
||||||
markers: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let common = match self {
|
|
||||||
RequirementModern::Dependency(..) => &default,
|
|
||||||
RequirementModern::LongDependency { common, .. }
|
|
||||||
| RequirementModern::GitDependency { common, .. }
|
|
||||||
| RequirementModern::FileDependency { common, .. }
|
|
||||||
| RequirementModern::PathDependency { common, .. }
|
|
||||||
| RequirementModern::UrlDependency { common, .. } => common,
|
|
||||||
};
|
|
||||||
|
|
||||||
let marker = if common.optional {
|
|
||||||
// invert the extras table from the modern format
|
|
||||||
// extra1 -> optional_dep1, optional_dep2, ...
|
|
||||||
// to the PEP 508 format
|
|
||||||
// optional_dep1; extra == "extra1" or extra == "extra2"
|
|
||||||
let dep_markers = extras
|
|
||||||
.iter()
|
|
||||||
.filter(|(_marker, dependencies)| dependencies.contains(&name.to_string()))
|
|
||||||
.map(|(marker, _dependencies)| {
|
|
||||||
MarkerTree::Expression(MarkerExpression {
|
|
||||||
l_value: MarkerValue::Extra,
|
|
||||||
operator: MarkerOperator::Equal,
|
|
||||||
r_value: QuotedString(marker.to_string()),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
// any of these extras activates the dependency -> or clause
|
|
||||||
let dep_markers = MarkerTree::Or(dep_markers);
|
|
||||||
let joined_marker = if let Some(user_markers) = &common.markers {
|
|
||||||
let user_markers = MarkerTree::from_str(user_markers)
|
|
||||||
.context("TODO: parse this in serde already")?;
|
|
||||||
// but the dependency needs to be activated and match the other markers
|
|
||||||
// -> and clause
|
|
||||||
MarkerTree::And(vec![user_markers, dep_markers])
|
|
||||||
} else {
|
|
||||||
dep_markers
|
|
||||||
};
|
|
||||||
Some(joined_marker)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(extras) = &common.extras {
|
|
||||||
debug_assert!(extras.iter().all(|extra| EXTRA_REGEX.is_match(extra)));
|
|
||||||
}
|
|
||||||
|
|
||||||
let version_or_url = match self {
|
|
||||||
RequirementModern::Dependency(version) => {
|
|
||||||
VersionOrUrl::VersionSpecifier(version.to_pep508_specifier())
|
|
||||||
}
|
|
||||||
RequirementModern::LongDependency { version, .. } => {
|
|
||||||
VersionOrUrl::VersionSpecifier(version.to_pep508_specifier())
|
|
||||||
}
|
|
||||||
RequirementModern::GitDependency {
|
|
||||||
git, branch, rev, ..
|
|
||||||
} => {
|
|
||||||
// TODO: Read https://peps.python.org/pep-0440/#direct-references properly
|
|
||||||
// set_scheme doesn't like us adding `git+` to https, therefore this hack
|
|
||||||
let mut url =
|
|
||||||
Url::parse(&format!("git+{}", git)).expect("TODO: Better url validation");
|
|
||||||
match (branch, rev) {
|
|
||||||
(Some(_branch), Some(_rev)) => {
|
|
||||||
bail!("You can set both branch and rev (for {})", name)
|
|
||||||
}
|
|
||||||
(Some(branch), None) => url.set_path(&format!("{}@{}", url.path(), branch)),
|
|
||||||
(None, Some(rev)) => url.set_path(&format!("{}@{}", url.path(), rev)),
|
|
||||||
(None, None) => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
VersionOrUrl::Url(url)
|
|
||||||
}
|
|
||||||
RequirementModern::FileDependency { file, .. } => VersionOrUrl::Url(
|
|
||||||
Url::from_file_path(file)
|
|
||||||
.map_err(|()| format_err!("File must be absolute (for {})", name))?,
|
|
||||||
),
|
|
||||||
RequirementModern::PathDependency { path, .. } => VersionOrUrl::Url(
|
|
||||||
Url::from_directory_path(path)
|
|
||||||
.map_err(|()| format_err!("Path must be absolute (for {})", name))?,
|
|
||||||
),
|
|
||||||
RequirementModern::UrlDependency { url, .. } => VersionOrUrl::Url(url.clone()),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Requirement {
|
|
||||||
name: name.to_string(),
|
|
||||||
extras: common.extras.clone(),
|
|
||||||
version_or_url: Some(version_or_url),
|
|
||||||
marker,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use crate::modern::{RequirementModern, VersionSpecifierModern};
|
|
||||||
use crate::Requirement;
|
|
||||||
use indoc::indoc;
|
|
||||||
use pep440_rs::VersionSpecifiers;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use std::collections::{BTreeMap, HashMap};
|
|
||||||
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_basic() {
|
|
||||||
let deps: HashMap<String, RequirementModern> =
|
|
||||||
toml::from_str(r#"numpy = "==1.19""#).unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
deps["numpy"],
|
|
||||||
RequirementModern::Dependency(VersionSpecifierModern::VersionSpecifier(
|
|
||||||
VersionSpecifiers::from_str("==1.19").unwrap()
|
|
||||||
))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
deps["numpy"].to_pep508("numpy", &HashMap::new()).unwrap(),
|
|
||||||
Requirement::from_str("numpy== 1.19").unwrap()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_conversion() {
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct PyprojectToml {
|
|
||||||
// BTreeMap to keep the order
|
|
||||||
#[serde(rename = "modern-dependencies")]
|
|
||||||
modern_dependencies: BTreeMap<String, RequirementModern>,
|
|
||||||
extras: HashMap<String, Vec<String>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
let pyproject_toml = indoc! {r#"
|
|
||||||
[modern-dependencies]
|
|
||||||
pydantic = "1.10.5"
|
|
||||||
numpy = ">=1.24.2, <2.0.0"
|
|
||||||
pandas = { version = ">=1.5.3, <2.0.0" }
|
|
||||||
flask = { version = "2.2.3 ", extras = ["dotenv"], optional = true }
|
|
||||||
tqdm = { git = "https://github.com/tqdm/tqdm", rev = "0bb91857eca0d4aea08f66cf1c8949abe0cd6b7a" }
|
|
||||||
jax = { url = "https://storage.googleapis.com/jax-releases/cuda112/jaxlib-0.1.64+cuda112-cp39-none-manylinux2010_x86_64.whl" }
|
|
||||||
zstandard = { file = "/home/ferris/wheels/zstandard/zstandard-0.20.0.tar.gz" }
|
|
||||||
h5py = { path = "/home/ferris/wheels/h5py/" }
|
|
||||||
|
|
||||||
[extras]
|
|
||||||
internet = ["flask"]
|
|
||||||
"#
|
|
||||||
};
|
|
||||||
|
|
||||||
let deps: PyprojectToml = toml::from_str(pyproject_toml).unwrap();
|
|
||||||
|
|
||||||
let actual: Vec<String> = deps
|
|
||||||
.modern_dependencies
|
|
||||||
.iter()
|
|
||||||
.map(|(name, spec)| spec.to_pep508(name, &deps.extras).unwrap().to_string())
|
|
||||||
.collect();
|
|
||||||
let expected: Vec<String> = vec![
|
|
||||||
"flask[dotenv] ==2.2.3 ; extra == 'internet'".to_string(),
|
|
||||||
"h5py @ file:///home/ferris/wheels/h5py/".to_string(),
|
|
||||||
"jax @ https://storage.googleapis.com/jax-releases/cuda112/jaxlib-0.1.64+cuda112-cp39-none-manylinux2010_x86_64.whl".to_string(),
|
|
||||||
"numpy >=1.24.2, <2.0.0".to_string(),
|
|
||||||
"pandas >=1.5.3, <2.0.0".to_string(),
|
|
||||||
"pydantic ==1.10.5".to_string(),
|
|
||||||
"tqdm @ git+https://github.com/tqdm/tqdm@0bb91857eca0d4aea08f66cf1c8949abe0cd6b7a".to_string(),
|
|
||||||
"zstandard @ file:///home/ferris/wheels/zstandard/zstandard-0.20.0.tar.gz".to_string()
|
|
||||||
];
|
|
||||||
assert_eq!(actual, expected)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,97 +0,0 @@
|
||||||
from collections import namedtuple
|
|
||||||
from unittest import mock
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
from pep508_rs import Requirement, MarkerEnvironment, Pep508Error, VersionSpecifier
|
|
||||||
|
|
||||||
|
|
||||||
def test_pep508():
|
|
||||||
req = Requirement("numpy; python_version >= '3.7'")
|
|
||||||
assert req.name == "numpy"
|
|
||||||
env = MarkerEnvironment.current()
|
|
||||||
assert req.evaluate_markers(env, [])
|
|
||||||
req2 = Requirement("numpy; python_version < '3.7'")
|
|
||||||
assert not req2.evaluate_markers(env, [])
|
|
||||||
|
|
||||||
requests = Requirement(
|
|
||||||
'requests [security,tests] >=2.8.1, ==2.8.* ; python_version > "3.8"'
|
|
||||||
)
|
|
||||||
assert requests.name == "requests"
|
|
||||||
assert requests.extras == ["security", "tests"]
|
|
||||||
assert requests.version_or_url == [
|
|
||||||
VersionSpecifier(">=2.8.1"),
|
|
||||||
VersionSpecifier("==2.8.*"),
|
|
||||||
]
|
|
||||||
assert requests.marker == "python_version > '3.8'"
|
|
||||||
|
|
||||||
|
|
||||||
def test_marker():
|
|
||||||
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"])
|
|
||||||
|
|
||||||
|
|
||||||
class FakeVersionInfo(
|
|
||||||
namedtuple("FakeVersionInfo", ["major", "minor", "micro", "releaselevel", "serial"])
|
|
||||||
):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
("version", "version_str"),
|
|
||||||
[
|
|
||||||
(FakeVersionInfo(3, 10, 11, "final", 0), "3.10.11"),
|
|
||||||
(FakeVersionInfo(3, 10, 11, "rc", 1), "3.10.11rc1"),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_marker_values(version, version_str):
|
|
||||||
with mock.patch("sys.implementation.version", version):
|
|
||||||
env = MarkerEnvironment.current()
|
|
||||||
assert str(env.implementation_version.version) == version_str
|
|
||||||
|
|
||||||
|
|
||||||
def test_marker_values_current_platform():
|
|
||||||
MarkerEnvironment.current()
|
|
||||||
|
|
||||||
|
|
||||||
def test_errors():
|
|
||||||
with pytest.raises(
|
|
||||||
Pep508Error,
|
|
||||||
match="Expected an alphanumeric character starting the extra name, found 'ö'",
|
|
||||||
):
|
|
||||||
Requirement("numpy[ö]; python_version < '3.7'")
|
|
||||||
|
|
||||||
|
|
||||||
def test_warnings(caplog):
|
|
||||||
env = MarkerEnvironment.current()
|
|
||||||
assert not Requirement("numpy; '3.6' < '3.7'").evaluate_markers(env, [])
|
|
||||||
assert caplog.messages == [
|
|
||||||
"Comparing two quoted strings with each other doesn't make sense: "
|
|
||||||
"'3.6' < '3.7', evaluating to false"
|
|
||||||
]
|
|
||||||
caplog.clear()
|
|
||||||
assert not Requirement("numpy; 'a' < 'b'").evaluate_markers(env, [])
|
|
||||||
assert caplog.messages == [
|
|
||||||
"Comparing two quoted strings with each other doesn't make sense: "
|
|
||||||
"'a' < 'b', evaluating to false"
|
|
||||||
]
|
|
||||||
caplog.clear()
|
|
||||||
Requirement("numpy; python_version >= '3.9.'").evaluate_markers(env, [])
|
|
||||||
assert caplog.messages == [
|
|
||||||
"Expected PEP 440 version to compare with python_version, found '3.9.', "
|
|
||||||
"evaluating to false: Version `3.9.` doesn't match PEP 440 rules"
|
|
||||||
]
|
|
||||||
caplog.clear()
|
|
||||||
# pickleshare 0.7.5
|
|
||||||
Requirement("numpy; python_version in '2.6 2.7 3.2 3.3'").evaluate_markers(env, [])
|
|
||||||
assert caplog.messages == [
|
|
||||||
"Expected PEP 440 version to compare with python_version, "
|
|
||||||
"found '2.6 2.7 3.2 3.3', "
|
|
||||||
"evaluating to false: Version `2.6 2.7 3.2 3.3` doesn't match PEP 440 rules"
|
|
||||||
]
|
|
|
@ -17,8 +17,8 @@ colored = { workspace = true }
|
||||||
directories = { workspace = true }
|
directories = { workspace = true }
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
install-wheel-rs = { workspace = true }
|
install-wheel-rs = { workspace = true }
|
||||||
pep508_rs = { workspace = true }
|
pep508_rs = { path = "../pep508-rs" }
|
||||||
pep440_rs = { workspace = true }
|
pep440_rs = { path = "../pep440-rs" }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
tracing-tree = { workspace = true }
|
tracing-tree = { workspace = true }
|
||||||
tracing-subscriber = { workspace = true }
|
tracing-subscriber = { workspace = true }
|
||||||
|
|
|
@ -10,10 +10,10 @@ authors.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
pep440_rs = { path = "../pep440-rs" }
|
||||||
|
pep508_rs = { path = "../pep508-rs" }
|
||||||
puffin-platform = { path = "../puffin-platform" }
|
puffin-platform = { path = "../puffin-platform" }
|
||||||
|
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
pep440_rs = { workspace = true }
|
|
||||||
pep508_rs = { workspace = true }
|
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
|
|
|
@ -4,14 +4,14 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
pep440_rs = { path = "../pep440-rs", features = ["serde"] }
|
||||||
|
pep508_rs = { path = "../pep508-rs", features = ["serde"] }
|
||||||
puffin-platform = { path = "../puffin-platform" }
|
puffin-platform = { path = "../puffin-platform" }
|
||||||
|
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
mailparse = { workspace = true }
|
mailparse = { workspace = true }
|
||||||
memchr = { workspace = true }
|
memchr = { workspace = true }
|
||||||
once_cell = { workspace = true }
|
once_cell = { workspace = true }
|
||||||
pep440_rs = { workspace = true, features = ["serde"] }
|
|
||||||
pep508_rs = { workspace = true, features = ["serde"] }
|
|
||||||
regex = { workspace = true }
|
regex = { workspace = true }
|
||||||
rfc2047-decoder = { workspace = true }
|
rfc2047-decoder = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
|
|
|
@ -12,7 +12,7 @@ license.workspace = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
glibc_version = { workspace = true }
|
glibc_version = { workspace = true }
|
||||||
goblin = { workspace = true }
|
goblin = { workspace = true }
|
||||||
pep440_rs = { workspace = true }
|
pep440_rs = { path = "../pep440-rs" }
|
||||||
platform-info = { workspace = true }
|
platform-info = { workspace = true }
|
||||||
plist = { workspace = true }
|
plist = { workspace = true }
|
||||||
regex = { workspace = true }
|
regex = { workspace = true }
|
||||||
|
|
|
@ -17,6 +17,6 @@ puffin-package = { path = "../puffin-package" }
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
bitflags = { workspace = true }
|
bitflags = { workspace = true }
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
pep440_rs = { workspace = true }
|
pep440_rs = { path = "../pep440-rs" }
|
||||||
pep508_rs = { workspace = true }
|
pep508_rs = { path = "../pep508-rs" }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
|
|
|
@ -156,8 +156,7 @@ pub async fn resolve(
|
||||||
for dependency in metadata.requires_dist {
|
for dependency in metadata.requires_dist {
|
||||||
if !dependency.evaluate_markers(
|
if !dependency.evaluate_markers(
|
||||||
markers,
|
markers,
|
||||||
// TODO(charlie): Remove this clone.
|
requirement.extras.as_ref().map_or(&[], Vec::as_slice),
|
||||||
requirement.extras.clone().unwrap_or_default(),
|
|
||||||
) {
|
) {
|
||||||
debug!("--> ignoring {dependency} due to environment mismatch");
|
debug!("--> ignoring {dependency} due to environment mismatch");
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue