Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ output
venv
.devcontainer
.ruff_cache
.venv
42 changes: 39 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,48 @@ The documentation of betterproto is available online: https://betterproto.github

- Python (3.10 or higher)

- [poetry](https://python-poetry.org/docs/#installation)
*Needed to install dependencies in a virtual environment*
- [uv](https://docs.astral.sh/uv/getting-started/installation/)
*Modern Python package and project manager*

- [poethepoet](https://github.com/nat-n/poethepoet) for running development tasks as defined in pyproject.toml
- Can be installed to your host environment via `pip install poethepoet` then executed as simple `poe`
- or run from the poetry venv as `poetry run poe`
- or run from the uv environment as `uv run poe`

### Getting Started

This project uses a uv workspace with two packages:
- `betterproto2` - The main library
- `betterproto2_compiler` - The protoc plugin

```bash
# Install dependencies and sync the workspace
uv sync

# Build all packages
uv build --all-packages

# Set up test outputs (required before running tests)
# Note: This requires grpcio-tools to be installed
cd betterproto2_compiler && uv run poe generate
cd ../betterproto2 && uv run poe get-local-compiled-tests
cd ..

# Run tests (after setting up test outputs)
uv run poe test

# Format code using ruff directly
uv run ruff format betterproto2/src betterproto2/tests betterproto2_compiler/src betterproto2_compiler/tests

# Check code using ruff directly
uv run ruff check betterproto2/src betterproto2/tests betterproto2_compiler/src betterproto2_compiler/tests
```

### Notes

- The workspace-level poe tasks (format, check) reference directories that don't exist at the workspace root, so use the direct ruff commands shown above.
- The workspace-level `uv run poe test` command runs tests for both packages sequentially.
- Individual packages have their own specific tasks - check `uv run poe --help` from within each package directory for more options.
- Some tests may fail due to missing test data files (like in `test_streams.py`), but the core functionality tests should pass.

## License

Expand Down
100 changes: 6 additions & 94 deletions betterproto2/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,114 +25,26 @@ pydantic = ["pydantic>=2.11.5"]
protobuf = ["protobuf>=5.29.3"]
all = ["grpclib>=0.4.8", "grpcio>=1.72.1", "pydantic>=2.11.5", "protobuf>=5.29.3"]

[dependency-groups]
dev = [
"ipykernel>=6.29.5",
"mkdocs-material>=9.6.14",
"mkdocstrings[python]>=0.29.1",
"mypy>=1.16.0",
"pre-commit>=4.2.0,<5",
"pyright>=1.1.401",
# The Ruff version is pinned. To update it, also update it in .pre-commit-config.yaml
"ruff==0.9.3",
]
test = [
"cachelib>=0.13.0",
"poethepoet>=0.34.0",
"pytest>=8.4.0",
"pytest-asyncio>=1.0.0",
"pytest-cov>=6.1.1",
"pytest-mock>=3.14.1",
]

[tool.uv]
package = true
default-groups = "all"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
requires = ["uv_build>=0.8.22,<0.9.0"]
build-backend = "uv_build"

# Package-specific Ruff configuration (inherits from workspace)
[tool.ruff]
extend-exclude = ["tests/outputs", "src/betterproto2/internal_lib"]
target-version = "py310"
line-length = 120

[tool.ruff.lint]
select = [
"F401", # Unused imports
"F841", # Unused local variables
"F821", # Undefined names
"E501", # Line length violations

"SIM101", # Simplify unnecessary if-else blocks
"SIM102", # Simplify return or yield statements
"SIM103", # Simplify list/set/dict comprehensions

"UP",

"I",
]


[tool.ruff.lint.isort]
combine-as-imports = true

# Package-specific pytest configuration
[tool.pytest.ini_options]
python_files = "test_*.py"
python_classes = ""
norecursedirs = "**/output_*"
addopts = "-p no:warnings"

# Dev workflow tasks
# Package-specific tasks
[tool.poe.tasks.get-local-compiled-tests]
# task useful for local development. Copies the compiled test files from the compiler folder to the tests folder
shell = "rm -rf tests/outputs* && cp -r ../betterproto2_compiler/tests/outputs tests"

[tool.poe.tasks.test]
cmd = "pytest"
help = "Run tests"

[tool.poe.tasks.test-cov]
cmd = "pytest --cov=betterproto2 --cov-report=term --cov-report=html tests/"
help = "Run tests with code coverage report"

[tool.poe.tasks.typecheck]
cmd = "pyright src"
help = "Typecheck the code with Pyright"

[tool.poe.tasks.format]
sequence = ["_format", "_sort-imports"]
help = "Format the source code, and sort the imports"

[tool.poe.tasks.check]
sequence = ["_check-format", "_check"]
help = "Check that the source code is formatted and the imports sorted"

[tool.poe.tasks._format]
cmd = "ruff format src tests"
help = "Format the source code without sorting the imports"

[tool.poe.tasks._sort-imports]
cmd = "ruff check --select I --fix src tests"
help = "Sort the imports"

[tool.poe.tasks._check-format]
cmd = "ruff format --diff src tests"
help = "Check that the source code is formatted"

[tool.poe.tasks._check]
cmd = "ruff check src tests"
help = "Check the code"

[tool.poe.tasks.clean]
cmd = """
rm -rf .coverage .mypy_cache .pytest_cache
dist betterproto.egg-info **/__pycache__
testsoutput_*
"""
help = "Clean out generated files from the workspace"

[tool.poe.tasks.serve-docs]
cmd = "mkdocs serve"
help = "Serve the documentation locally"
shell = "rm -rf tests/outputs* && cp -r ../betterproto2_compiler/tests/outputs tests"
96 changes: 11 additions & 85 deletions betterproto2_compiler/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,65 +23,33 @@ dependencies = [
"strenum>=0.4.15,<0.5 ; python_version == '3.10'",
]

# [tool.uv.sources]
# betterproto2 = { path = "../betterproto2" }

[project.urls]
Documentation = "https://betterproto.github.io/python-betterproto2/"
Repository = "https://github.com/betterproto/python-betterproto2"

[project.scripts]
protoc-gen-python_betterproto2 = "betterproto2_compiler.plugin:main"

[dependency-groups]
dev = [
"pre-commit>=4.2.0,<5",
"grpcio-tools>=1.54.2,<2",
"poethepoet>=0.32.2,<0.33",
"pyright>=1.1.391,<2",
"ipykernel>=6.29.5,<7",
]
test = [
"pytest>=8.3.4,<9",
"protobuf>=5.29.3,<6",
]

[tool.uv]
package = true
default-groups = "all"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
requires = ["uv_build>=0.8.22,<0.9.0"]
build-backend = "uv_build"

# Package-specific Ruff configuration (inherits from workspace)
[tool.ruff]
extend-exclude = ["tests/outputs", "src/betterproto2_compiler/lib"]
target-version = "py310"
line-length = 120

[tool.ruff.lint]
select = [
"F401", # Unused imports
"F841", # Unused local variables
"F821", # Undefined names
"E501", # Line length violations

"SIM101", # Simplify unnecessary if-else blocks
"SIM102", # Simplify return or yield statements
"SIM103", # Simplify list/set/dict comprehensions

"UP",

"I",
]

[tool.ruff.lint.isort]
combine-as-imports = true

[tool.poe.tasks.test]
cmd = "pytest"
help = "Run tests"
# Package-specific pytest configuration
[tool.pytest.ini_options]
python_files = "test_*.py"
python_classes = ""
norecursedirs = "**/output_*"
addopts = "-p no:warnings"

# Package-specific tasks
[tool.poe.tasks.generate]
# sequence = ["_generate_tests", "_generate_tests_lib"]
sequence = ["_generate_tests"]
Expand Down Expand Up @@ -132,46 +100,4 @@ python -m grpc.tools.protoc \
google/protobuf/timestamp.proto \
google/protobuf/type.proto \
google/protobuf/wrappers.proto
"""

[tool.poe.tasks.typecheck]
cmd = "pyright src"
help = "Typecheck the code with Pyright"

[tool.poe.tasks.format]
sequence = ["_format", "_sort-imports"]
help = "Format the source code, and sort the imports"

[tool.poe.tasks.check]
sequence = ["_check-format", "_check-ruff-lint"]
help = "Check that the source code is formatted and the code passes the linter"

[tool.poe.tasks._format]
cmd = "ruff format src tests"
help = "Format the source code without sorting the imports"

[tool.poe.tasks._sort-imports]
cmd = "ruff check --select I --fix src tests"
help = "Sort the imports"

[tool.poe.tasks._check-format]
cmd = "ruff format --diff src tests"
help = "Check that the source code is formatted"

[tool.poe.tasks._check-ruff-lint]
cmd = "ruff check src tests"
help = "Check the code with the Ruff linter"

# python -m grpc.tools.protoc \
# --python_betterproto2_out=src/lib2 \
# google/protobuf/any.proto \
# google/protobuf/api.proto \
# google/protobuf/duration.proto \
# google/protobuf/empty.proto \
# google/protobuf/field_mask.proto \
# google/protobuf/source_context.proto \
# google/protobuf/struct.proto \
# google/protobuf/timestamp.proto \
# google/protobuf/type.proto \
# google/protobuf/wrappers.proto \
# google/protobuf/compiler/plugin.proto
"""
Loading
Loading