Skip to content

Commit 85c2bb7

Browse files
revert: keep lib/ at src/agentex/lib (Option X); pyright can't see split namespace
Pyright fails reportMissingImports on intra-lib `agentex.lib.*` imports when lib/ lives in a sibling source tree (adk/src/agentex/lib/) because pyright analyzes statically and doesn't run pkgutil.extend_path. Even pointing pyright at the editable-install venv doesn't help — the static module resolver picks `src/agentex/` (which has __init__.py) and stops; it never discovers adk/src/agentex/lib/. This kills the file-move (Option Y) direction. Disabling reportMissingImports for lib loses meaningful static analysis; PEP-420 namespace (drop __init__.py) breaks `from agentex import Agentex`. Switching to Option X: lib/ stays at src/agentex/lib/ as it originally was. The two packages share the source tree: - Root pyproject's wheel target adds `exclude = ["src/agentex/lib/**"]` so the slim wheel doesn't ship lib code. - adk/pyproject.toml uses hatchling `force-include "../src/agentex/lib" = "agentex/lib"` to pull lib/* into the heavy wheel from the parent dir. - src/agentex/__init__.py reverts to its Stainless-natural form; no pkgutil.extend_path needed (single source tree, no namespace merge). Files reverted: - 350 lib files: adk/src/agentex/lib → src/agentex/lib - Test files moved earlier: adk/tests → tests (lib tests back at tests/lib) - Pytest config: testpaths back to ["tests"]; dropped --import-mode=importlib - Pyright config: removed extraPaths/include; restored exec-env root to src/agentex/lib; dropped adk/tests exec env - Mypy config: dropped mypy_path; removed adk/tests from exclude - Ruff per-file-ignores: removed adk/tests pattern - src/agentex/__init__.py: removed pkgutil.extend_path Kept: - Two-package structure (slim agentex-sdk-client at root, heavy agentex-sdk at adk/) — the install-time win - rye workspace so `rye sync` installs both packages' deps in the dev venv - bin/publish-pypi dual-build, release-please two-package mode, CI dual-build Verified locally: - pyright on src/agentex/lib/adk/__init__.py → 0 errors - pytest --collect-only → 2204 tests collect cleanly - Build slim → wheel excludes agentex/lib/ correctly - Build heavy → wheel contains only agentex/lib/* (347 files) - Dual install: from agentex import Agentex AND from agentex.lib.* both work - Single editable install (pip install -e . + pip install -e ./adk): heavy deps installed (ddtrace, temporalio, fastapi, etc.); imports work Trade-off documented in PR body: root pyproject's wheel `exclude` is a hand-edit to Stainless's emitted file that must survive 3-way merge. Manual edits to `dependencies = [...]` have survived historically; we're betting the same holds for `[tool.hatch.build.targets.wheel].exclude`. If Stainless clobbers it during a regen, options are (a) re-add manually, (b) move the exclude to `keep_files`-protected file via dashboard config, or (c) pivot back to file-move with pyright workarounds. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 0645fb0 commit 85c2bb7

391 files changed

Lines changed: 22 additions & 60 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

adk/pyproject.toml

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -81,30 +81,20 @@ agentex = "agentex.lib.cli.commands.main:app"
8181
requires = ["hatchling"]
8282
build-backend = "hatchling.build"
8383

84-
# Ship only agentex/lib/*. The rest of agentex.* (the Stainless-generated
85-
# client) ships from the sibling agentex-sdk-client package, which this
86-
# package pins as a runtime dep.
84+
# Ship only agentex/lib/*, pulled in from the parent repo's `src/agentex/lib`
85+
# tree. The rest of agentex.* (the Stainless-generated client) ships from the
86+
# sibling agentex-sdk-client package, which this package pins as a runtime dep.
87+
# Stainless explicitly preserves `src/agentex/lib/` across codegen (per
88+
# CONTRIBUTING.md), so it's safe to keep the source where it is.
8789
[tool.hatch.build.targets.wheel]
88-
only-include = ["src/agentex/lib"]
89-
sources = ["src"]
90-
# Don't ship internal test files in the wheel; CLI Jinja templates
91-
# (test_agent.py.j2 etc.) are preserved because they don't match these globs.
92-
exclude = [
93-
"src/agentex/lib/**/tests/**",
94-
"src/agentex/lib/**/test_*.py",
95-
"src/agentex/lib/**/conftest.py",
96-
"src/agentex/lib/**/pytest.ini",
97-
]
90+
bypass-selection = true
91+
92+
[tool.hatch.build.targets.wheel.force-include]
93+
"../src/agentex/lib" = "agentex/lib"
9894

9995
[tool.hatch.build.targets.sdist]
10096
include = [
10197
"/pyproject.toml",
10298
"/README.md",
103-
"/src/agentex/lib/**",
104-
]
105-
exclude = [
106-
"/src/agentex/lib/**/tests/**",
107-
"/src/agentex/lib/**/test_*.py",
108-
"/src/agentex/lib/**/conftest.py",
109-
"/src/agentex/lib/**/pytest.ini",
99+
"/../src/agentex/lib/**",
110100
]

adk/tests/lib/core/tracing/processors/__init__.py

Whitespace-only changes.

pyproject.toml

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,8 @@ dev = [
5757

5858
[tool.rye.workspace]
5959
# `rye sync` from the root installs both this slim package and the ADK
60-
# overlay editably. The two contribute disjoint files to the same agentex.*
61-
# namespace — see the pkgutil.extend_path call in src/agentex/__init__.py
62-
# which merges their __path__ entries at import time.
60+
# overlay editably. `src/agentex/lib/` is shared source: the slim wheel
61+
# excludes it; the heavy wheel includes it via hatchling force-include.
6362
members = ["adk"]
6463

6564
[tool.rye]
@@ -128,6 +127,12 @@ include = [
128127

129128
[tool.hatch.build.targets.wheel]
130129
packages = ["src/agentex"]
130+
# agentex/lib/* ships from the sibling agentex-sdk package (see adk/pyproject.toml).
131+
# Excluding it here keeps the slim wheel disjoint from the heavy wheel so both
132+
# can install into the same site-packages/agentex/ without file conflicts.
133+
exclude = [
134+
"src/agentex/lib/**",
135+
]
131136

132137
[tool.hatch.build.targets.sdist]
133138
# Basically everything except hidden files/directories (such as .github, .devcontainers, .python-version, etc)
@@ -156,14 +161,8 @@ pattern = '\[(.+?)\]\(((?!https?://)\S+?)\)'
156161
replacement = '[\1](https://github.com/scaleapi/scale-agentex-python/tree/main/\g<2>)'
157162

158163
[tool.pytest.ini_options]
159-
# Both `tests/` (client) and `adk/tests/` (ADK overlay) are collected; the ADK
160-
# tests resolve `agentex.lib.*` via the sibling agentex-sdk package installed
161-
# editably by scripts/bootstrap.
162-
testpaths = ["tests", "adk/tests"]
163-
# importlib mode avoids the "duplicate package name" collision that classic
164-
# import mode hits when both tests/ and adk/tests/ have __init__.py making
165-
# them both look like a top-level `tests` package.
166-
addopts = "--tb=short -n auto --import-mode=importlib"
164+
testpaths = ["tests"]
165+
addopts = "--tb=short -n auto"
167166
xfail_strict = true
168167
asyncio_mode = "auto"
169168
asyncio_default_fixture_loop_scope = "session"
@@ -177,12 +176,6 @@ filterwarnings = [
177176
typeCheckingMode = "basic"
178177
pythonVersion = "3.12"
179178

180-
# Both src/ (slim client) and adk/src/ (ADK overlay) contribute to the
181-
# agentex.* namespace. Pyright needs both as roots so cross-package imports
182-
# (e.g. agentex.lib.* code referencing agentex.types.*) resolve.
183-
include = ["src", "adk/src", "tests", "adk/tests", "examples", "scripts", "bin"]
184-
extraPaths = ["src", "adk/src"]
185-
186179
exclude = [
187180
"_dev",
188181
".venv",
@@ -210,34 +203,24 @@ reportUnknownVariableType = false
210203

211204
# Enable strict type checking only for hand-written code
212205
[[tool.pyright.executionEnvironments]]
213-
root = "adk/src/agentex/lib"
206+
root = "src/agentex/lib"
214207
typeCheckingMode = "strict"
215-
extraPaths = ["src", "adk/src"]
216208
# But allow some flexibility in OpenAI module for complex type boundaries
217209
reportArgumentType = false
218210

219211
[[tool.pyright.executionEnvironments]]
220212
root = "examples"
221213
typeCheckingMode = "strict"
222-
extraPaths = ["src", "adk/src"]
223214
# Allow type ignores in tutorials for readability
224215
reportUnnecessaryTypeIgnoreComment = false
225216

226217
[[tool.pyright.executionEnvironments]]
227218
root = "tests"
228219
typeCheckingMode = "basic"
229-
extraPaths = ["src", "adk/src"]
230220
# Be loose on typing in tests unless testing types specifically
231221
reportOptionalMemberAccess = false
232222
reportArgumentType = false
233223

234-
[[tool.pyright.executionEnvironments]]
235-
root = "adk/tests"
236-
typeCheckingMode = "basic"
237-
extraPaths = ["src", "adk/src"]
238-
reportOptionalMemberAccess = false
239-
reportArgumentType = false
240-
241224
[tool.mypy]
242225
pretty = true
243226
show_error_codes = true
@@ -248,8 +231,7 @@ show_error_codes = true
248231
#
249232
# We also exclude our `tests` as mypy doesn't always infer
250233
# types correctly and Pyright will still catch any type errors.
251-
exclude = ['src/agentex/_files.py', '_dev/.*.py', 'tests/.*', 'adk/tests/.*', 'examples/tutorials/.*']
252-
mypy_path = "src:adk/src"
234+
exclude = ['src/agentex/_files.py', '_dev/.*.py', 'tests/.*', 'examples/tutorials/.*']
253235

254236
strict_equality = true
255237
implicit_reexport = true
@@ -351,7 +333,6 @@ known-first-party = ["agentex", "tests"]
351333
"bin/**.py" = ["T201", "T203"]
352334
"scripts/**.py" = ["T201", "T203"]
353335
"tests/**.py" = ["T201", "T203", "ARG001", "ARG002", "ARG005"]
354-
"adk/tests/**.py" = ["T201", "T203", "ARG001", "ARG002", "ARG005"]
355336
"examples/**.py" = ["T201", "T203"]
356337
"examples/**.ipynb" = ["T201", "T203"]
357338
"examples/tutorials/**.py" = ["T201", "T203"]

src/agentex/__init__.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,5 @@
11
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
22

3-
# Make `agentex` a "split" package: the slim agentex-sdk-client ships this
4-
# __init__.py + the Stainless surface (resources/, types/, _*.py), while the
5-
# sibling agentex-sdk package ships agentex/lib/*. Both installs land in
6-
# site-packages/agentex/ in production (wheel install), but editable installs
7-
# split across two source trees — extend_path tells Python to merge them.
8-
from pkgutil import extend_path
9-
10-
__path__ = extend_path(__path__, __name__)
11-
123
import typing as _t
134

145
from . import types
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)