Metadata-Version: 2.1
Name: wexample-wex-addon-dev-python
Version: 13.2.0
Summary: Extends wex with commands to format, lint, and rename Python symbols, plus workdir types for Python packages and suites
Author-Email: weeger <contact@wexample.com>
License: MIT
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Project-URL: homepage, https://github.com/wexample/python-wex-dev-python
Requires-Python: >=3.10
Requires-Dist: attrs>=23.1.0
Requires-Dist: cattrs>=23.1.0
Requires-Dist: griffe>=2.0.2
Requires-Dist: networkx
Requires-Dist: pylint
Requires-Dist: pyright
Requires-Dist: wexample-api>=6.8.0
Requires-Dist: wexample-filestate-python>=9.0.0
Requires-Dist: wexample-wex-addon-ai>=13.0.0
Requires-Dist: wexample-wex-addon-app>=30.0.0
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Description-Content-Type: text/markdown

# wex_addon_dev_python

Version: 13.2.0

`wex_addon_dev_python` extends the wex CLI with a `python::` command group that formats source files with isort and black (`python::code/format`), checks them with mypy, pylint, and pyright (`python::code/check`), and renames Python symbols — packages, modules, classes, functions, constants — while propagating every affected import statement across the workdir (`python::code/rename`). It also ships `PythonPackageWorkdir` and `PythonPackagesSuiteWorkdir`, two workdir types that let wex manage a single PDM-based package or a multi-package suite as a first-class project structure. The intended users are wex operators who develop and maintain Python packages within the wexample ecosystem.

## Table of Contents

- [Installation](#installation)
- [Quickstart](#quickstart)
- [Tests](#tests)
- [Architecture](#architecture)
- [Integration in the Suite](#integration-in-the-suite)
- [Dependencies](#dependencies)
- [Versioning & Compatibility Policy](#versioning--compatibility-policy)
- [License](#license)
- [About us](#about-us)
- [Known Limitations & Roadmap](#known-limitations--roadmap)
- [Status & Compatibility](#status--compatibility)
- [Useful Links](#useful-links)
- [Migration Notes](#migration-notes)

## Installation

```bash
pip install wexample-wex-addon-dev-python
```

Requires Python >=3.10.

## Quickstart

Install from PyPI:

```bash
pip install wexample-wex-addon-dev-python
```

That makes the `python::` command group available to wex. Pass any file or directory to `--file`; the middleware expands globs and recurses automatically.

Format a source tree — isort sorts imports, black reformats the rest:

```bash
wex python::code/format --file src/mypackage/
```

Run the three static-analysis tools (mypy, pylint, pyright) against the same tree:

```bash
wex python::code/check --file src/mypackage/
```

Rename a Python symbol and rewrite every import statement that references it across the workdir. The `--dry_run` flag prints which files would change without touching them:

```bash
wex python::code/rename \
  --source mylib.helpers \
  --target mylib.helper \
  --kind package \
  --dry_run
```

Drop `--dry_run` to apply. Valid `--kind` values are `package`, `module`, `class`, `function`, and `constant`.

## Tests

This project uses `pytest` for testing and `pytest-cov` for code coverage analysis.

### Installation

First, install the required testing dependencies:
```bash
.venv/bin/python -m pip install pytest pytest-cov
```

### Basic Usage

Run all tests with coverage:
```bash
.venv/bin/python -m pytest --cov --cov-report=html
```

### Common Commands
```bash
# Run tests with coverage for a specific module
.venv/bin/python -m pytest --cov=your_module

# Show which lines are not covered
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing

# Generate an HTML coverage report
.venv/bin/python -m pytest --cov=your_module --cov-report=html

# Combine terminal and HTML reports
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html

# Run specific test file with coverage
.venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing
```

### Viewing HTML Reports

After generating an HTML report, open `htmlcov/index.html` in your browser to view detailed line-by-line coverage information.

### Coverage Threshold

To enforce a minimum coverage percentage:
```bash
.venv/bin/python -m pytest --cov=your_module --cov-fail-under=80
```

This will cause the test suite to fail if coverage drops below 80%.

## Architecture

The package is a wex addon. Its single registration point is src/wexample_wex_addon_dev_python/python_addon_manager.py — a `PythonAddonManager` that inherits `AbstractAddonManager` and declares four contributions:

- **middlewares** — `EachPythonFileMiddleware`
- **selections** — `PythonCodePerformanceSelection`
- **workdir types** — `python`, `python-package`, `python-packages-suite`
- **configurable keys** — `PDM_BIN_DIR`, detected and applied by src/wexample_wex_addon_dev_python/helper/pdm.py

Everything else in the package implements one of those four surfaces.

### Middleware

src/wexample_wex_addon_dev_python/middleware/each_python_file_middleware.py extends `EachFileMiddleware`. It filters `.py` files by extension and refuses to recurse into `__pycache__`, `.git`, `.venv`, `.mypy_cache`, and similar directories. Commands that operate file-by-file declare `@middleware(name="each_python_file")` to let the kernel expand a path argument into individual files before calling the command function.

### Commands

All three live under `src/wexample_wex_addon_dev_python/commands/code/`.

**Format** — src/wexample_wex_addon_dev_python/commands/code/format.py runs isort then black in that order on one file. An optional `--tool` flag restricts execution to a single tool. The command returns `False` on the first failure when `--stop_on_failure` is set.

**Check** — src/wexample_wex_addon_dev_python/commands/code/check.py runs mypy, pylint, and pyright in sequence. Pylint is invoked with `--output-format=json`; only messages of type `error` or `fatal` cause a `False` return; warnings and conventions are reported but do not fail the check.

**Rename** — src/wexample_wex_addon_dev_python/commands/code/rename.py accepts `--source`, `--target`, and `--kind`. It resolves the `SymbolKind` enum, picks a handler class, delegates to `handler.run()`, and returns a `TableResponse` listing the changed files. A `--dry_run` flag stops the handler after the plan phase, touching nothing on disk.

### Refactor subsystem

The refactor package implements a three-phase rename pipeline.

src/wexample_wex_addon_dev_python/refactor/abstract_python_rename_handler.py defines the pipeline: `compute_plan()` (scan only, no writes) → `preflight()` (detect permission errors and missing parents) → `apply()` (hand the plan to a `RenameApplier`). Subclasses implement `compute_plan` and `_build_report`.

src/wexample_wex_addon_dev_python/refactor/rename_plan.py is the data structure. It carries:
- `rewrites` — per-file new source text
- `path_renames` — `(old, new)` pairs for files or directories
- `directories_to_create` — dirs that must exist before rewrites run
- `files_to_delete`, `directories_to_remove`, `directories_to_purge` — cleanup after moves

src/wexample_wex_addon_dev_python/refactor/applier.py defines `RenameApplier` (abstract strategy) and `NaiveRenameApplier` (direct `os`/`shutil` calls). The sequencing is: create dirs → write files → rename paths → delete files → purge artefact dirs → remove empty dirs.

src/wexample_wex_addon_dev_python/refactor/symbol_kind.py lists the supported kinds: `package`, `module`, `class`, `function`, `constant`. `method` is declared in the enum but not implemented; the comment explains why (dynamic typing makes safe method-rename impossible without a full type-inference pipeline).

The package handler adds merge logic: when the target directory already exists, each child of the source is moved in, identical `__init__.py` files are dropped, and the empty source dir is removed. Non-identical file conflicts abort with a descriptive error.

### Workdir hierarchy

**`PythonWorkdir`** — src/wexample_wex_addon_dev_python/workdir/python_workdir.py is the base for every Python project. It mixes in `WithAiWorkdirMixin`, `WithProfilingPythonWorkdirMixin`, and `CodeBaseWorkdir`. Responsibilities:

- venv path resolution (local `.venv` or a suite-level `python.venv_path` from runtime config)
- `app_install` — creates the venv, then calls `_install_dependencies_in_venv`
- test execution via `test_run` / `test_get_command` (pytest + pytest-cov, JSON report stored in `.wex/local/`)
- filestate layout declaration in `prepare_value`: `src/{vendor}_{name}/`, `tests/`, `helpers/`, plus the full set of Python file options (future annotations, sort imports, modernize typing, order class members, format, …)
- `get_app_config_file` — returns the managed `PythonPyprojectTomlFile`
- `update_dependencies` — updates `pyproject.toml` then re-pins `requirements.txt` via `uv pip compile` with retry logic for PyPI propagation races

**`PythonPackageWorkdir`** — src/wexample_wex_addon_dev_python/workdir/python_package_workdir.py extends `PythonWorkdir` for distributable packages. Additional responsibilities:

- publish via `pdm publish` (PyPI) or a git tag push (private GitLab registry when `pdm.repository.url` is set)
- `_wait_for_registry` — polls the PEP 503 Simple index through `PypiRegistryGateway` until the new version appears
- `_classify_version_bump` — uses `griffe` to compare the current AST against the previous git tag and determine major vs. intermediate bump
- suite-aware install in local env: external deps are pip-installed normally; suite packages are installed in editable mode, leaf-to-trunk order, skipping packages already editable at the right path
- `get_required_knowledge_pages` adds `usage/quickstart` to the pages the workdir expects to exist

**`PythonPackagesSuiteWorkdir`** — src/wexample_wex_addon_dev_python/workdir/python_packages_suite_workdir.py extends `FrameworkPackageSuiteWorkdir`. It treats any subdirectory of `pip/` that contains a `pyproject.toml` as a package. `build_dependencies_stack` builds a `networkx` directed graph from the local dependency map and returns the shortest path from one package to another as concrete `PythonPackageWorkdir` objects.

**`WithProfilingPythonWorkdirMixin`** — src/wexample_wex_addon_dev_python/workdir/mixin/with_profiling_python_workdir_mixin.py runs `pytest --benchmark-only` in the project's venv, writes a temporary JSON report, parses benchmark stats (min, mean, median, max in ms, rounds), and returns the result as a structured dict.

### File objects

src/wexample_wex_addon_dev_python/file/python_pyproject_toml_file.py wraps `pyproject.toml` as a managed filestate object. Its `dumps` method enforces canonical structure on every write: build-system pinned to `pdm-backend`, PDM build config derived from the workdir's `get_src_import_name()`, project metadata from wex config, dependencies sorted, dev group always containing `pytest` and `pytest-cov`, pytest and coverage tool config injected, and sections reordered (`build-system` → `project` → `tool`).

### Selection

src/wexample_wex_addon_dev_python/selection/abstract_python_code_selection.py establishes the Python-file baseline for AI agent selections: `.py` extension only, skip `__init__.py`, skip `__pycache__` / `/tests/` / `/build/` / `/dist/` / `/.venv/` / `/.pdm-build/`, 50-byte minimum.

src/wexample_wex_addon_dev_python/selection/python_code_performance_selection.py inherits that baseline and adds two constraints: the file must be under `/src/`, and its AST must contain at least one non-trivial function. Trivial is defined as: `pass`, `...`, docstring-only, `raise NotImplementedError`, a same-name `super()` pass-through, or any `@abstractmethod`.

### Supporting pieces

src/wexample_wex_addon_dev_python/common/pypi_registry_gateway.py is a thin HTTP client over the PEP 503 Simple index. It accepts optional Basic auth (`username` + `token`) and exposes `has_version(package, version) -> bool`.

src/wexample_wex_addon_dev_python/operation/generated_description_operation.py is a filestate operation that invokes a `ClaudeAgent` to produce a one-sentence `global.description` and writes it to the app config. The model is called only during `apply_operation`, not during dry-run, so a preview is always offline. Failures (network, model, length over 200 chars) leave the key unset and log a warning rather than aborting the rectification.

src/wexample_wex_addon_dev_python/services/python/app_service.py contributes the initial `pyproject.toml` and `src/app/` scaffolding when a new Python app service is set up.

src/wexample_wex_addon_dev_python/const/tags.py declares the `DomainTag` constants (`domain:format`, `domain:language-python`, `domain:lint`, `domain:service`) used in command `@command(tags=[…])` decorators.

### Call path for a rename

1. `python__code__rename` validates `--kind`, selects a handler class, calls `app_workdir.get_code_scope_paths(kernel)` for the set of roots.
2. The handler's `__attrs_post_init__` splits the dotted names and validates they are non-empty.
3. `handler.run()` calls `compute_plan()` — the handler scans every root for the source pattern, builds a `RenamePlan` (rewrites + path moves), returns it.
4. If not `dry_run`, `plan.preflight()` checks writability and parent existence. Any problem raises `RuntimeError` before a single file is touched.
5. `NaiveRenameApplier().apply(plan)` executes the six steps in sequence.
6. The command formats the report into a `TableResponse`.

## Integration in the Suite

This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.

### Related Packages

The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.

Visit the [Wexample Suite documentation](https://docs.wexample.com) for the complete package ecosystem.

## Dependencies

- attrs: >=23.1.0
- cattrs: >=23.1.0
- griffe: >=2.0.2
- networkx: 
- pylint: 
- pyright: 
- wexample-api: >=6.8.0
- wexample-filestate-python: >=9.0.0
- wexample-wex-addon-ai: >=13.0.0
- wexample-wex-addon-app: >=30.0.0

## Versioning & Compatibility Policy

Wexample packages follow **Semantic Versioning** (SemVer):

- **MAJOR**: Breaking changes
- **MINOR**: New features, backward compatible
- **PATCH**: Bug fixes, backward compatible

We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

Free to use in both personal and commercial projects.

## About us

[Wexample](https://wexample.com) stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.

This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.

Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.

## Known Limitations & Roadmap

Current limitations and planned features are tracked in the GitHub issues.

See the [project roadmap](https://github.com/wexample/python-wex_addon_dev_python/issues) for upcoming features and improvements.

## Status & Compatibility

**Maturity**: Production-ready

**Python Support**: >=3.10

**OS Support**: Linux, macOS, Windows

**Status**: Actively maintained

## Useful Links

- **Homepage**: https://github.com/wexample/python-wex-addon-dev-python
- **Documentation**: [docs.wexample.com](https://docs.wexample.com)
- **Issue Tracker**: https://github.com/wexample/python-wex-addon-dev-python/issues
- **Discussions**: https://github.com/wexample/python-wex-addon-dev-python/discussions
- **PyPI**: [pypi.org/project/wexample-wex-addon-dev-python](https://pypi.org/project/wexample-wex-addon-dev-python/)

## Migration Notes

When upgrading between major versions, refer to the migration guides in the documentation.

Breaking changes are clearly documented with upgrade paths and examples.
