fix `either` feature conditional compilation, again (#3834)
* fix `either` feature conditional compilation, again * test feature powerset in CI * install `rust-src` for feature powerset tests * review: adamreichold feedback * Fix one more case of redundant imports. * just check feature powerset for now --------- Co-authored-by: Adam Reichold <adam.reichold@t-online.de>
This commit is contained in:
parent
5ddcd46980
commit
c4f66657c5
|
@ -480,6 +480,22 @@ jobs:
|
||||||
- run: python3 -m pip install --upgrade pip && pip install nox
|
- run: python3 -m pip install --upgrade pip && pip install nox
|
||||||
- run: python3 -m nox -s test-version-limits
|
- run: python3 -m nox -s test-version-limits
|
||||||
|
|
||||||
|
check-feature-powerset:
|
||||||
|
needs: [fmt]
|
||||||
|
if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || (github.event_name != 'pull_request' && github.ref != 'refs/heads/main') }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
continue-on-error: true
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
with:
|
||||||
|
components: rust-src
|
||||||
|
- uses: taiki-e/install-action@cargo-hack
|
||||||
|
- run: python3 -m pip install --upgrade pip && pip install nox
|
||||||
|
- run: python3 -m nox -s check-feature-powerset
|
||||||
|
|
||||||
conclusion:
|
conclusion:
|
||||||
needs:
|
needs:
|
||||||
- fmt
|
- fmt
|
||||||
|
@ -494,6 +510,7 @@ jobs:
|
||||||
- emscripten
|
- emscripten
|
||||||
- test-debug
|
- test-debug
|
||||||
- test-version-limits
|
- test-version-limits
|
||||||
|
- check-feature-powerset
|
||||||
if: always()
|
if: always()
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
|
17
Cargo.toml
17
Cargo.toml
|
@ -107,20 +107,21 @@ nightly = []
|
||||||
# This is mostly intended for testing purposes - activating *all* of these isn't particularly useful.
|
# This is mostly intended for testing purposes - activating *all* of these isn't particularly useful.
|
||||||
full = [
|
full = [
|
||||||
"macros",
|
"macros",
|
||||||
|
"gil-refs",
|
||||||
# "multiple-pymethods", # TODO re-add this when MSRV is greater than 1.62
|
# "multiple-pymethods", # TODO re-add this when MSRV is greater than 1.62
|
||||||
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
"chrono-tz",
|
"chrono-tz",
|
||||||
|
"either",
|
||||||
|
"experimental-inspect",
|
||||||
|
"eyre",
|
||||||
|
"hashbrown",
|
||||||
|
"indexmap",
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-complex",
|
"num-complex",
|
||||||
"hashbrown",
|
|
||||||
"smallvec",
|
|
||||||
"serde",
|
|
||||||
"indexmap",
|
|
||||||
"either",
|
|
||||||
"eyre",
|
|
||||||
"anyhow",
|
|
||||||
"experimental-inspect",
|
|
||||||
"rust_decimal",
|
"rust_decimal",
|
||||||
|
"serde",
|
||||||
|
"smallvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix compilation failure with `either` feature enabled without `experimental-inspect` enabled.
|
82
noxfile.py
82
noxfile.py
|
@ -13,6 +13,14 @@ from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple
|
||||||
import nox
|
import nox
|
||||||
import nox.command
|
import nox.command
|
||||||
|
|
||||||
|
try:
|
||||||
|
import tomllib as toml
|
||||||
|
except ImportError:
|
||||||
|
try:
|
||||||
|
import toml
|
||||||
|
except ImportError:
|
||||||
|
toml = None
|
||||||
|
|
||||||
nox.options.sessions = ["test", "clippy", "rustfmt", "ruff", "docs"]
|
nox.options.sessions = ["test", "clippy", "rustfmt", "ruff", "docs"]
|
||||||
|
|
||||||
|
|
||||||
|
@ -479,10 +487,8 @@ def check_changelog(session: nox.Session):
|
||||||
def set_minimal_package_versions(session: nox.Session):
|
def set_minimal_package_versions(session: nox.Session):
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
try:
|
if toml is None:
|
||||||
import tomllib as toml
|
session.error("requires Python 3.11 or `toml` to be installed")
|
||||||
except ImportError:
|
|
||||||
import toml
|
|
||||||
|
|
||||||
projects = (
|
projects = (
|
||||||
None,
|
None,
|
||||||
|
@ -593,6 +599,74 @@ def test_version_limits(session: nox.Session):
|
||||||
_run_cargo(session, "check", env=env, expect_error=True)
|
_run_cargo(session, "check", env=env, expect_error=True)
|
||||||
|
|
||||||
|
|
||||||
|
@nox.session(name="check-feature-powerset", venv_backend="none")
|
||||||
|
def check_feature_powerset(session: nox.Session):
|
||||||
|
if toml is None:
|
||||||
|
session.error("requires Python 3.11 or `toml` to be installed")
|
||||||
|
|
||||||
|
with (PYO3_DIR / "Cargo.toml").open("rb") as cargo_toml_file:
|
||||||
|
cargo_toml = toml.load(cargo_toml_file)
|
||||||
|
|
||||||
|
EXCLUDED_FROM_FULL = {
|
||||||
|
"nightly",
|
||||||
|
"extension-module",
|
||||||
|
"full",
|
||||||
|
"default",
|
||||||
|
"auto-initialize",
|
||||||
|
"generate-import-lib",
|
||||||
|
"multiple-pymethods", # TODO add this after MSRV 1.62
|
||||||
|
}
|
||||||
|
|
||||||
|
features = cargo_toml["features"]
|
||||||
|
|
||||||
|
full_feature = set(features["full"])
|
||||||
|
abi3_features = {feature for feature in features if feature.startswith("abi3")}
|
||||||
|
abi3_version_features = abi3_features - {"abi3"}
|
||||||
|
|
||||||
|
expected_full_feature = features.keys() - EXCLUDED_FROM_FULL - abi3_features
|
||||||
|
|
||||||
|
uncovered_features = expected_full_feature - full_feature
|
||||||
|
if uncovered_features:
|
||||||
|
session.error(
|
||||||
|
f"some features missing from `full` meta feature: {uncovered_features}"
|
||||||
|
)
|
||||||
|
|
||||||
|
experimental_features = {
|
||||||
|
feature for feature in features if feature.startswith("experimental-")
|
||||||
|
}
|
||||||
|
full_without_experimental = full_feature - experimental_features
|
||||||
|
|
||||||
|
if len(experimental_features) >= 2:
|
||||||
|
# justification: we always assume that feature within these groups are
|
||||||
|
# mutually exclusive to simplify CI
|
||||||
|
features_to_group = [
|
||||||
|
full_without_experimental,
|
||||||
|
experimental_features,
|
||||||
|
]
|
||||||
|
elif len(experimental_features) == 1:
|
||||||
|
# no need to make an experimental features group
|
||||||
|
features_to_group = [full_without_experimental]
|
||||||
|
else:
|
||||||
|
session.error("no experimental features exist; please simplify the noxfile")
|
||||||
|
|
||||||
|
features_to_skip = [
|
||||||
|
*EXCLUDED_FROM_FULL,
|
||||||
|
*abi3_version_features,
|
||||||
|
]
|
||||||
|
|
||||||
|
comma_join = ",".join
|
||||||
|
_run_cargo(
|
||||||
|
session,
|
||||||
|
"hack",
|
||||||
|
"--feature-powerset",
|
||||||
|
'--optional-deps=""',
|
||||||
|
f'--skip="{comma_join(features_to_skip)}"',
|
||||||
|
*(f"--group-features={comma_join(group)}" for group in features_to_group),
|
||||||
|
"check",
|
||||||
|
"--all-targets",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _build_docs_for_ffi_check(session: nox.Session) -> None:
|
def _build_docs_for_ffi_check(session: nox.Session) -> None:
|
||||||
# pyo3-ffi-check needs to scrape docs of pyo3-ffi
|
# pyo3-ffi-check needs to scrape docs of pyo3-ffi
|
||||||
_run_cargo(session, "doc", _FFI_CHECK, "-p", "pyo3-ffi", "--no-deps")
|
_run_cargo(session, "doc", _FFI_CHECK, "-p", "pyo3-ffi", "--no-deps")
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::{types::PyModule, Python};
|
|
||||||
|
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
struct Eq(i64);
|
struct Eq(i64);
|
||||||
|
|
|
@ -94,7 +94,13 @@ where
|
||||||
} else if let Ok(r) = obj.extract::<R>() {
|
} else if let Ok(r) = obj.extract::<R>() {
|
||||||
Ok(Either::Right(r))
|
Ok(Either::Right(r))
|
||||||
} else {
|
} else {
|
||||||
let err_msg = format!("failed to convert the value to '{}'", Self::type_input());
|
// TODO: it might be nice to use the `type_input()` name here once `type_input`
|
||||||
|
// is not experimental, rather than the Rust type names.
|
||||||
|
let err_msg = format!(
|
||||||
|
"failed to convert the value to 'Union[{}, {}]'",
|
||||||
|
std::any::type_name::<L>(),
|
||||||
|
std::any::type_name::<R>()
|
||||||
|
);
|
||||||
Err(PyTypeError::new_err(err_msg))
|
Err(PyTypeError::new_err(err_msg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,7 +140,7 @@ mod tests {
|
||||||
assert!(err.is_instance_of::<PyTypeError>(py));
|
assert!(err.is_instance_of::<PyTypeError>(py));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
err.to_string(),
|
err.to_string(),
|
||||||
"TypeError: failed to convert the value to 'Union[int, float]'"
|
"TypeError: failed to convert the value to 'Union[i32, f32]'"
|
||||||
);
|
);
|
||||||
|
|
||||||
let obj_i = 42.to_object(py);
|
let obj_i = 42.to_object(py);
|
||||||
|
|
Loading…
Reference in New Issue