Skip to content

Commit db67117

Browse files
committed
bump pyo3
1 parent a6e32ed commit db67117

File tree

14 files changed

+340
-63
lines changed

14 files changed

+340
-63
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,6 @@ profile.json
186186

187187
# Scratchpad
188188
.scratch/
189+
190+
# pyprojectx
191+
.pyprojectx

Cargo.lock

Lines changed: 12 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ crate-type = ["cdylib", "lib"]
99
bench = false
1010

1111
[dependencies]
12-
pyo3 = { version = "0.22.5", features = ["abi3-py37", "auto-initialize"] }
12+
pyo3 = { version = "0.26.0", features = ["abi3-py37", "auto-initialize"] }
1313
regex = "1.11.1"
1414
once_cell = "1.21.3"
1515
ruff_python_ast = { git = "https://github.com/astral-sh/ruff.git", tag = "0.9.3" }

Makefile

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ endif
1515

1616
.PHONY: deps
1717
deps: ## Install dependencies
18-
python -m pip install --upgrade uv
19-
2018
@if [ ! -d "$(VENV)" ]; then \
2119
uv venv $(VENV); \
2220
echo "Virtual environment created at $(VENV)"; \

pw

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
#!/usr/bin/env python3
2+
3+
##################################################################################
4+
# Pyprojectx wrapper script #
5+
# https://github.com/pyprojectx/pyprojectx #
6+
# #
7+
# Copyright (c) 2021 Ivo Houbrechts #
8+
# #
9+
# Licensed under the MIT license #
10+
##################################################################################
11+
import argparse
12+
import os
13+
import subprocess
14+
import sys
15+
import sysconfig
16+
import zipfile
17+
from pathlib import Path
18+
from urllib import request
19+
20+
try:
21+
from venv import EnvBuilder
22+
except ImportError:
23+
EnvBuilder = None
24+
25+
26+
VERSION = "3.2.9"
27+
UV_VERSION = "0.8.8"
28+
29+
PYPROJECTX_INSTALL_DIR_ENV_VAR = "PYPROJECTX_INSTALL_DIR"
30+
PYPROJECTX_PACKAGE_ENV_VAR = "PYPROJECTX_PACKAGE"
31+
PYPROJECTX_USE_UV_ENV_VAR = "PYPROJECTX_USE_UV"
32+
PYPROJECT_TOML = "pyproject.toml"
33+
DEFAULT_INSTALL_DIR = ".pyprojectx"
34+
SCRIPTS_DIR = Path(sysconfig.get_path("scripts")).name
35+
EXE = sysconfig.get_config_var("EXE")
36+
37+
CYAN = "\033[96m"
38+
BLUE = "\033[94m"
39+
RED = "\033[91m"
40+
RESET = "\033[0m"
41+
if sys.platform.startswith("win"):
42+
os.system("color")
43+
44+
45+
def run(args):
46+
try:
47+
options = get_options(args)
48+
if options.upgrade:
49+
download_wrappers()
50+
return
51+
52+
pyprojectx_script = ensure_pyprojectx(options)
53+
explicit_options = []
54+
if not options.toml:
55+
explicit_options += ["--toml", str(options.toml_path)]
56+
if not options.install_dir:
57+
explicit_options += ["--install-dir", str(options.install_path)]
58+
59+
subprocess.run([str(pyprojectx_script), *explicit_options, *args], check=True)
60+
except subprocess.CalledProcessError as e:
61+
raise SystemExit(e.returncode) from e
62+
63+
64+
def get_options(args):
65+
options = arg_parser().parse_args(args)
66+
options.install_path = Path(
67+
options.install_dir
68+
or os.environ.get(PYPROJECTX_INSTALL_DIR_ENV_VAR, Path(__file__).with_name(DEFAULT_INSTALL_DIR))
69+
)
70+
options.toml_path = Path(options.toml) if options.toml else Path(__file__).with_name(PYPROJECT_TOML)
71+
if os.environ.get(PYPROJECTX_PACKAGE_ENV_VAR):
72+
options.version = "development"
73+
options.pyprojectx_package = os.environ.get(PYPROJECTX_PACKAGE_ENV_VAR)
74+
else:
75+
options.version = VERSION
76+
options.pyprojectx_package = f"pyprojectx=={VERSION}"
77+
options.verbosity = 0 if options.quiet or not options.verbosity else options.verbosity
78+
return options
79+
80+
81+
def arg_parser():
82+
parser = argparse.ArgumentParser(
83+
description="Execute commands or aliases defined in the [tool.pyprojectx] section of pyproject.toml. "
84+
"Use the -i or --info option to see available tools and aliases.",
85+
allow_abbrev=False,
86+
)
87+
parser.add_argument("--version", action="version", version=VERSION)
88+
parser.add_argument(
89+
"--toml",
90+
"-t",
91+
action="store",
92+
help="The toml config file. Defaults to 'pyproject.toml' in the same directory as the pw script.",
93+
)
94+
parser.add_argument(
95+
"--install-dir",
96+
action="store",
97+
help=f"The directory where all tools (including pyprojectx) are installed; defaults to the "
98+
f"{PYPROJECTX_INSTALL_DIR_ENV_VAR} environment value if set, else '.pyprojectx' "
99+
f"in the same directory as the invoked pw script.",
100+
)
101+
parser.add_argument(
102+
"--force-install",
103+
"-f",
104+
action="store_true",
105+
help="Force clean installation of the virtual environment used to run cmd, if any.",
106+
)
107+
parser.add_argument(
108+
"--clean",
109+
"-c",
110+
action="store_true",
111+
help="Clean .pyprojectx directory by removing all but the current versions "
112+
"of pyprojectx and context virtual environments.",
113+
)
114+
parser.add_argument(
115+
"--install-context",
116+
action="store",
117+
metavar="tool-context",
118+
help="Install a tool context without actually running any command.",
119+
)
120+
parser.add_argument(
121+
"--verbose",
122+
"-v",
123+
action="count",
124+
dest="verbosity",
125+
help="Give more output. This option is additive and can be used up to 2 times.",
126+
)
127+
parser.add_argument(
128+
"--quiet",
129+
"-q",
130+
action="store_true",
131+
help="Suppress output.",
132+
)
133+
parser.add_argument(
134+
"--info",
135+
"-i",
136+
action="store_true",
137+
help="Show the configuration details of a command instead of running it. "
138+
"If no command is specified, a list with all available tools and aliases is shown.",
139+
)
140+
parser.add_argument(
141+
"--add",
142+
action="store",
143+
metavar="[context:]<package>,<package>...",
144+
help="Add one or more packages to a tool context. "
145+
"If no context is specified, the packages are added to the main context. "
146+
"Packages can be specified as in 'pip install', except that a ',' can't be used in the version specification.",
147+
)
148+
parser.add_argument(
149+
"--lock",
150+
action="store_true",
151+
help="Write all dependencies of all tool contexts to 'pw.lock' to guarantee reproducible outcomes.",
152+
)
153+
parser.add_argument(
154+
"--install-px", action="store_true", help="Install the px and pxg scripts in your home directory."
155+
)
156+
parser.add_argument(
157+
"--upgrade",
158+
action="store_true",
159+
help="Download the latest pyprojectx wrapper scripts.",
160+
)
161+
parser.add_argument(
162+
"command", nargs=argparse.REMAINDER, help="The command/alias with optional arguments to execute."
163+
)
164+
return parser
165+
166+
167+
def ensure_pyprojectx(options): # noqa: C901
168+
venv_dir = (
169+
options.install_path / "pyprojectx" / f"{options.version}-py{sys.version_info.major}.{sys.version_info.minor}"
170+
)
171+
pyprojectx_script = venv_dir / SCRIPTS_DIR / f"pyprojectx{EXE}"
172+
173+
if not pyprojectx_script.is_file():
174+
if options.quiet:
175+
out = subprocess.DEVNULL
176+
else:
177+
out = sys.stderr
178+
print(f"{CYAN}creating pyprojectx venv in {BLUE}{venv_dir}{RESET}", file=sys.stderr)
179+
180+
use_uv_install_script = not EnvBuilder or os.environ.get(PYPROJECTX_USE_UV_ENV_VAR)
181+
if not use_uv_install_script:
182+
env_builder = EnvBuilder(with_pip=True)
183+
env_context = env_builder.ensure_directories(venv_dir)
184+
try:
185+
env_builder.create(venv_dir)
186+
except (SystemExit, subprocess.CalledProcessError) as e:
187+
print(f"failed to create virtualenv, falling back to uv install script ({e})")
188+
use_uv_install_script = True
189+
else:
190+
pip_cmd = [env_context.env_exe, "-m", "pip", "install", "--pre"]
191+
subprocess.run(
192+
[*pip_cmd, "--upgrade", "pip"],
193+
stdout=out,
194+
check=True,
195+
)
196+
if use_uv_install_script: # download and use uv to create the pyprojectx venv
197+
uv_dir = Path(options.install_path) / f"uv-{UV_VERSION}"
198+
release_base_url = (
199+
"https://github.com/astral-sh/uv/releases/latest/download"
200+
if UV_VERSION == "__uv_version__"
201+
else f"https://github.com/astral-sh/uv/releases/download/{UV_VERSION}"
202+
)
203+
if sys.platform == "win32":
204+
# https://github.com/PowerShell/PowerShell/issues/18530#issuecomment-1325691850
205+
os.environ["PSMODULEPATH"] = ""
206+
install_uv_cmd = (
207+
f'powershell -ExecutionPolicy Bypass -c "irm {release_base_url}/uv-installer.ps1 | iex"'
208+
)
209+
else:
210+
install_uv_cmd = f"curl --proto '=https' --tlsv1.2 -LsSf irm {release_base_url}/uv-installer.sh | sh"
211+
subprocess.run(
212+
install_uv_cmd,
213+
stdout=out,
214+
check=True,
215+
shell=True,
216+
env={**os.environ, "UV_BUILD_UNMANAGED_INSTALL": str(uv_dir), "UV_UNMANAGED_INSTALL": str(uv_dir)},
217+
)
218+
uv = uv_dir / f"uv{EXE}"
219+
subprocess.run(
220+
[uv, "venv", str(venv_dir), "--python", sys.executable, "--clear"],
221+
stdout=out,
222+
check=True,
223+
)
224+
pip_cmd = [uv, "pip", "install", "--pre", "--python", str(venv_dir / SCRIPTS_DIR / f"python{EXE}")]
225+
226+
if not options.quiet:
227+
print(
228+
f"{CYAN}installing pyprojectx {BLUE}{options.version}: {options.pyprojectx_package} {RESET}",
229+
file=sys.stderr,
230+
)
231+
if options.version == "development":
232+
if not options.quiet:
233+
print(
234+
f"{RED}WARNING: {options.pyprojectx_package} is installed in editable mode{RESET}",
235+
file=sys.stderr,
236+
)
237+
pip_cmd.append("-e")
238+
subprocess.run([*pip_cmd, options.pyprojectx_package], stdout=out, check=True)
239+
240+
return pyprojectx_script
241+
242+
243+
def download_wrappers():
244+
latest = "https://github.com/pyprojectx/pyprojectx/releases/latest/download/wrappers.zip"
245+
zip_file, _ = request.urlretrieve(latest) # noqa: S310
246+
with zipfile.ZipFile(zip_file, "r") as zip_ref:
247+
zip_ref.extractall(Path(__file__).parent)
248+
249+
250+
if __name__ == "__main__":
251+
try:
252+
run(sys.argv[1:])
253+
except KeyboardInterrupt:
254+
sys.tracebacklimit = -1
255+
raise

pw.bat

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@echo off
2+
python "%~dp0pw" %*

pw.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[main]
2+
requirements = ["uv==0.9.0"]
3+
hash = "45210da832f9626829457a65e9e7c4d0"

src/commands/check/check_external.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ struct CheckExternalMetadata {
133133
/// Get metadata for checking external dependencies.
134134
fn get_check_external_metadata(project_config: &ProjectConfig) -> Result<CheckExternalMetadata> {
135135
Python::with_gil(|py| {
136-
let external_utils = PyModule::import_bound(py, "tach.utils.external")
136+
let external_utils = PyModule::import(py, "tach.utils.external")
137137
.expect("Failed to import tach.utils.external");
138138
let mut module_mappings: HashMap<String, Vec<String>> = external_utils
139139
.getattr("get_module_mappings")

src/commands/helpers/import.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@ pub struct PythonImport {
1616
pub line_number: usize,
1717
}
1818

19-
impl IntoPy<PyObject> for LocatedImport {
20-
fn into_py(self, py: Python<'_>) -> PyObject {
19+
impl<'py> IntoPyObject<'py> for LocatedImport {
20+
type Target = PythonImport;
21+
type Output = Bound<'py, Self::Target>;
22+
type Error = pyo3::PyErr;
23+
fn into_pyobject(self, py: Python<'py>) -> std::result::Result<Self::Output, Self::Error> {
2124
PythonImport {
2225
module_path: self.import.module_path,
2326
line_number: self.alias_line_number,
2427
}
25-
.into_py(py)
28+
.into_pyobject(py)
2629
}
2730
}
2831

0 commit comments

Comments
 (0)