Skip to content

feat(python): add PackageData.from_rez(pkg) convenience#79

Merged
doubleailes merged 1 commit into
mainfrom
packagedata-from-rez
May 15, 2026
Merged

feat(python): add PackageData.from_rez(pkg) convenience#79
doubleailes merged 1 commit into
mainfrom
packagedata-from-rez

Conversation

@doubleailes
Copy link
Copy Markdown
Owner

Summary

Follow-up to #78. The integration site for rez was eight lines of boilerplate per package:

```python
pyrer.PackageData(
name=fam.name,
version=str(pkg.version),
requires=[str(r) for r in (pkg.requires or [])],
variants=[[str(r) for r in v] for v in (pkg.variants or [])],
)
```

Same body every time. Ship it as a classmethod on `PackageData` so the call site collapses to one line:

```python
pyrer.PackageData.from_rez(pkg)
```

Implementation

`#[classmethod] from_rez(cls, pkg: &Bound<', PyAny>)` reads four attributes off `pkg` via PyO3 duck typing — `pyrer` still does not import `rez`, so any object exposing `name` / `version` / `requires` / `variants` works (tests use plain Python classes, no rez install needed).

Handles in one place:

  • `version` → `str(version)` (rez's `Version` is not a `str`).
  • Each `Requirement` in `requires` and inside each `variants` entry → `str(req)`.
  • `requires is None` / `variants is None` → empty list (rez models "no requires" as `None`).
  • Missing one of the four attributes → `AttributeError` from PyO3 surfaces naturally.

Two small private helpers (`read_requirement_list`, `read_variants_list`) share the iteration logic.

Tests

Six new cases in `tests/test_rich_api.py`:

  • plain attribute access (string fields, list-of-string requires)
  • `requires`/`variants` is `None` → empty
  • requirement-object `str` is honoured
  • version-object `str` is honoured
  • missing attribute raises `AttributeError`
  • end-to-end: `from_rez` → `solve` produces the same result as the four-field constructor

72 / 72 Python tests pass (7 + 58 + 14).

Docs

`README.md` and `rez-integration.md` integration recipes shrink from eight lines of conversion to a one-line `PackageData.from_rez(pkg)` call. The `pyrer`-doesn't-import-rez note stays so users on non-rez pipelines know the constructor is still available for them.

🤖 Generated with Claude Code

The integration site for rez was eight lines of boilerplate per
package — `pyrer.PackageData(name=..., version=str(pkg.version),
requires=[str(r) for r in (pkg.requires or [])], variants=[[str(r)
for r in v] for v in (pkg.variants or [])])`. Same body every time.
Ship that as a classmethod on `PackageData` so the call site is one
line:

    pkg_data = pyrer.PackageData.from_rez(pkg)

## Implementation

`#[classmethod] from_rez(_cls, pkg: &Bound<'_, PyAny>)` reads four
attributes off `pkg` via PyO3 duck typing — `pyrer` still does not
import `rez`, so any object exposing `name` / `version` / `requires`
/ `variants` works (tests use plain Python classes, no rez install
needed).

Handles, in one place:

- `version` → `str(version)` (rez's `Version` is not a `str`).
- Each `Requirement` in `requires` and inside each `variants` entry
  → `str(req)` (rez's `Requirement` likewise renders via `__str__`).
- `requires is None` and `variants is None` → empty list (rez models
  "no requires" as `None`, not `[]`).
- Missing one of the four attributes → `AttributeError` from PyO3
  surfaces naturally; the user knows immediately which object is
  wrong.

Two small private helpers (`read_requirement_list`,
`read_variants_list`) share the iteration logic so both the top-level
`requires` and each variant entry go through the same code.

## Tests

Six new cases in `tests/test_rich_api.py`:

- plain attribute access (str fields, list-of-str requires)
- `requires`/`variants` is `None` → empty
- requirement-object `__str__` is honoured
- version-object `__str__` is honoured
- missing attribute raises `AttributeError`
- end-to-end: `from_rez` → `solve` produces the same result as the
  four-field constructor

All 72 Python tests (7 + 58 + 14) pass.

## Docs

`README.md` and `rez-integration.md` integration recipes shrink from
8 lines of conversion to a one-line `PackageData.from_rez(pkg)` call.
The `pyrer`-doesn't-import-rez note is kept so users on non-rez
pipelines know the constructor is still there for them.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@qodo-code-review
Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@doubleailes doubleailes merged commit 95662d8 into main May 15, 2026
22 checks passed
@doubleailes doubleailes deleted the packagedata-from-rez branch May 15, 2026 20:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant