Skip to content

Commit b225486

Browse files
committed
Rename uneval to pycodify
1 parent 157365a commit b225486

File tree

16 files changed

+275
-39
lines changed

16 files changed

+275
-39
lines changed

.github/workflows/ci.yml

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main, master, claude/**]
6+
pull_request:
7+
branches: [main, master]
8+
workflow_dispatch:
9+
10+
jobs:
11+
# Test across Python versions and OSes
12+
test:
13+
runs-on: ${{ matrix.os }}
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
python-version: ["3.10", "3.11", "3.12", "3.13"]
18+
os: [ubuntu-latest, windows-latest, macos-latest]
19+
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
24+
- name: Setup Python ${{ matrix.python-version }}
25+
uses: actions/setup-python@v5
26+
with:
27+
python-version: ${{ matrix.python-version }}
28+
29+
- name: Install dependencies
30+
run: |
31+
python -m pip install --upgrade pip
32+
pip install -e ".[dev]"
33+
34+
- name: Run tests with coverage
35+
run: |
36+
pytest --cov=src/pycodify --cov-report=xml --cov-report=html --cov-report=term-missing -v
37+
38+
- name: Upload coverage to Codecov
39+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'
40+
uses: codecov/codecov-action@v3
41+
with:
42+
file: ./coverage.xml
43+
fail_ci_if_error: false
44+
45+
# Code quality checks
46+
code-quality:
47+
runs-on: ubuntu-latest
48+
49+
steps:
50+
- name: Checkout
51+
uses: actions/checkout@v4
52+
53+
- name: Setup Python
54+
uses: actions/setup-python@v5
55+
with:
56+
python-version: "3.12"
57+
58+
- name: Install dependencies
59+
run: |
60+
python -m pip install --upgrade pip
61+
pip install ruff black mypy
62+
63+
- name: Run ruff (linting)
64+
run: |
65+
ruff check src/ --output-format=github
66+
67+
- name: Run black (formatting check)
68+
run: |
69+
black --check src/
70+
71+
- name: Run mypy (type checking)
72+
run: |
73+
mypy src/ --ignore-missing-imports
74+
75+
# Documentation build check
76+
docs:
77+
runs-on: ubuntu-latest
78+
79+
steps:
80+
- name: Checkout
81+
uses: actions/checkout@v4
82+
83+
- name: Setup Python
84+
uses: actions/setup-python@v5
85+
with:
86+
python-version: "3.12"
87+
88+
- name: Install dependencies
89+
run: |
90+
python -m pip install --upgrade pip
91+
pip install -e ".[docs]"
92+
93+
- name: Build documentation
94+
run: |
95+
cd docs
96+
make html
97+
98+
- name: Check for build warnings
99+
run: |
100+
cd docs
101+
make html SPHINXOPTS="-W --keep-going"
102+

CONTRIBUTING.md

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Contributing to pycodify
2+
3+
Thank you for your interest in contributing to pycodify! This document provides guidelines for development, testing, and submission.
4+
5+
## Development Setup
6+
7+
### Prerequisites
8+
- Python 3.10+
9+
- Git
10+
11+
### Installation
12+
13+
```bash
14+
# Clone the repository
15+
git clone https://github.com/OpenHCSDev/pycodify.git
16+
cd pycodify
17+
18+
# Create virtual environment
19+
python -m venv venv
20+
source venv/bin/activate # On Windows: venv\Scripts\activate
21+
22+
# Install in development mode with all dependencies
23+
pip install -e ".[dev,docs]"
24+
```
25+
26+
## Code Style
27+
28+
pycodify follows strict code quality standards:
29+
30+
### Formatting
31+
- **Black**: Code formatting (line length: 100)
32+
- **Ruff**: Linting and import sorting
33+
- **MyPy**: Static type checking
34+
35+
```bash
36+
# Format code
37+
black src/ tests/
38+
39+
# Lint
40+
ruff check src/ tests/
41+
42+
# Type check
43+
mypy src/
44+
```
45+
46+
### Docstrings
47+
- Use Google-style docstrings
48+
- Include type hints in function signatures
49+
- Document all public APIs
50+
51+
## Testing
52+
53+
### Running Tests
54+
55+
```bash
56+
# Run all tests
57+
pytest tests/ -v
58+
59+
# Run with coverage
60+
pytest tests/ --cov=src/pycodify --cov-report=html
61+
62+
# Run specific test file
63+
pytest tests/test_core.py -v
64+
```
65+
66+
### Test Requirements
67+
- Minimum 80% code coverage
68+
- All tests must pass before submission
69+
- Use pytest fixtures for setup/teardown
70+
- Test both collection and regeneration passes
71+
72+
## Submitting Changes
73+
74+
### Before Submitting
75+
1. Ensure all tests pass: `pytest tests/`
76+
2. Format code: `black src/ tests/`
77+
3. Run linter: `ruff check src/ tests/`
78+
4. Type check: `mypy src/`
79+
5. Update documentation if needed
80+
81+
### Pull Request Process
82+
1. Create a feature branch: `git checkout -b feature/your-feature`
83+
2. Make your changes with clear commit messages
84+
3. Push to your fork and create a Pull Request
85+
4. Ensure CI/CD checks pass
86+
5. Request review from maintainers
87+
88+
### Commit Message Format
89+
```
90+
<type>: <subject>
91+
92+
<body>
93+
94+
<footer>
95+
```
96+
97+
Types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`
98+
99+
## Documentation
100+
101+
### Building Docs Locally
102+
103+
```bash
104+
cd docs
105+
make html
106+
# Open build/html/index.html in browser
107+
```
108+
109+
### Documentation Standards
110+
- Update README.md for user-facing changes
111+
- Update docstrings for API changes
112+
- Add examples for new features
113+
- Document the two-pass algorithm for custom formatters
114+
115+
## Architecture Notes
116+
117+
pycodify uses a two-pass algorithm:
118+
1. **Collection Pass**: Traverse object, emit code fragments, collect imports
119+
2. **Resolution Pass**: Detect collisions, generate aliases, regenerate code
120+
121+
Custom formatters should inherit from `SourceFormatter` and implement:
122+
- `can_format(value)`: Check if formatter handles this type
123+
- `format(value, context)`: Return SourceFragment with code and imports
124+
125+
## Questions?
126+
127+
- Open an issue for bugs or feature requests
128+
- Check existing issues before creating new ones
129+
- Use discussions for questions
130+
131+
## License
132+
133+
By contributing, you agree that your contributions will be licensed under the MIT License.
134+

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
# uneval
1+
# pycodify
22

33
Python source code as a serialization format with automatic import resolution.
44

55
## Quick Start
66

77
```python
8-
from uneval import Assignment, generate_python_source
8+
from pycodify import Assignment, generate_python_source
99
from dataclasses import dataclass
1010

1111
@dataclass
@@ -41,12 +41,12 @@ Binary formats like `pickle` cannot be diffed, inspected, or edited. Text format
4141

4242
## Documentation
4343

44-
Full documentation available at [uneval.readthedocs.io](https://uneval.readthedocs.io)
44+
Full documentation available at [pycodify.readthedocs.io](https://pycodify.readthedocs.io)
4545

4646
## Installation
4747

4848
```bash
49-
pip install uneval
49+
pip install pycodify
5050
```
5151

5252
## License

docs/api.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,23 @@ API Reference
44
Core API
55
--------
66

7-
.. automodule:: uneval.core
7+
.. automodule:: pycodify.core
88
:members:
99
:undoc-members:
1010
:show-inheritance:
1111

1212
Formatters
1313
----------
1414

15-
.. automodule:: uneval.formatters
15+
.. automodule:: pycodify.formatters
1616
:members:
1717
:undoc-members:
1818
:show-inheritance:
1919

2020
Import Resolution
2121
-----------------
2222

23-
.. automodule:: uneval.imports
23+
.. automodule:: pycodify.imports
2424
:members:
2525
:undoc-members:
2626
:show-inheritance:
@@ -43,7 +43,7 @@ Main Functions
4343

4444
.. code-block:: python
4545
46-
from uneval import Assignment, generate_python_source
46+
from pycodify import Assignment, generate_python_source
4747
from dataclasses import dataclass
4848
4949
@dataclass

docs/architecture.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Two-Pass Algorithm
66

77
Generating executable source requires knowing import aliases before emitting code. But aliases depend on detecting collisions, which requires visiting all types first. This creates a dependency: code generation requires alias resolution, but alias resolution requires traversing the object graph.
88

9-
uneval solves this with two passes:
9+
pycodify solves this with two passes:
1010

1111
1. **Collection Pass**: Traverse the object, emit code fragments, collect ``(module, name)`` import pairs
1212
2. **Resolution**: Detect collisions (same name, different modules), generate deterministic aliases

docs/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
"""Sphinx configuration for uneval."""
1+
"""Sphinx configuration for pycodify."""
22
import os
33
import sys
44

55
# Add source to path
66
sys.path.insert(0, os.path.abspath("../src"))
77

88
# Project information
9-
project = "uneval"
9+
project = "pycodify"
1010
copyright = "2024, Tristan Simas"
1111
author = "Tristan Simas"
1212
version = "0.1.0"

docs/index.rst

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
uneval Documentation
2-
====================
1+
pycodify Documentation
2+
======================
33

4-
**uneval** serializes Python objects to executable Python source code with automatic import resolution.
4+
**pycodify** serializes Python objects to executable Python source code with automatic import resolution.
55

6-
The key insight: **Python source code is a serialization format.** Rather than inventing a format and writing loaders, uneval emits code that Python itself interprets. The import system becomes the deserializer.
6+
The key insight: **Python source code is a serialization format.** Rather than inventing a format and writing loaders, pycodify emits code that Python itself interprets. The import system becomes the deserializer.
77

88
Quick Start
99
-----------
1010

1111
.. code-block:: python
1212
13-
from uneval import Assignment, generate_python_source
13+
from pycodify import Assignment, generate_python_source
1414
from dataclasses import dataclass
1515
1616
@dataclass
@@ -59,9 +59,9 @@ API Reference
5959
.. autosummary::
6060
:toctree: _autosummary
6161

62-
uneval.core
63-
uneval.formatters
64-
uneval.imports
62+
pycodify.core
63+
pycodify.formatters
64+
pycodify.imports
6565

6666
Indices and Tables
6767
------------------

docs/usage.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ Usage Guide
44
Basic Usage
55
-----------
66

7-
The simplest way to use uneval is to generate source code for an object:
7+
The simplest way to use pycodify is to generate source code for an object:
88

99
.. code-block:: python
1010
11-
from uneval import Assignment, generate_python_source
11+
from pycodify import Assignment, generate_python_source
1212
from dataclasses import dataclass
1313
1414
@dataclass
@@ -77,14 +77,14 @@ Enums are serialized with their full qualified names:
7777
Handling Import Collisions
7878
---------------------------
7979

80-
When multiple modules have classes with the same name, uneval automatically aliases them:
80+
When multiple modules have classes with the same name, pycodify automatically aliases them:
8181

8282
.. code-block:: python
8383
8484
from module_a import Config as ConfigA
8585
from module_b import Config as ConfigB
8686
87-
# uneval detects the collision and generates:
87+
# pycodify detects the collision and generates:
8888
# from module_a import Config as Config_1
8989
# from module_b import Config as Config_2
9090
# obj = Config_1(...)

0 commit comments

Comments
 (0)