Python (Pydantic) classes generated from the BHoM C# object model (oM), the Python counterpart of BHoM_JSONSchema.
src/bhom_schema/: the generated Python package (bhom_schema.<Assembly>.<Namespace>.<Type>)..ci/generation/PythonSchemaGeneration*: the C# to Python converter (reads the compiled oM assemblies)..ci/generation/py2cs: the Python to C# converter, used by the linked-PR workflow to draft aligned C#..ci/unit-tests: NUnit and pytest tests, plusrun-all.ps1that runs everything..github/workflows: the weekly generation, the PR checks and the linked C# pull request. See docs/Workflows.md.docs/: research notes and the coding plan.
Prerequisites: .NET 8 SDK, Python 3.12, and the BHoM assemblies installed in %ProgramData%\BHoM\Assemblies
(build the repositories in Included-repositories.txt: BHoM, BHoM_Engine, JSONSchema_Toolkit and CSharpSchema_Test). The generator tests use their own small test classes in .ci/unit-tests/csharp/Fixtures, so they need no other repository.
python -m venv .venv
.venv\Scripts\python -m pip install -e ".[dev]"
.ci\unit-tests\run-all.ps1run-all.ps1 starts with a preflight that reports missing assemblies. It never builds a repo for you.
The version of the package is the BHoM version of its classes: bhom_schema.__bhom_version__ is 10.0 and bhom_schema.__version__ is
10.0.0 for a release. develop is regenerated every week and is 10.0.0.dev0. A release is made by hand, like BHoM_JSONSchema's: the
Release workflow makes the branch v10.0 and the tag v10.0.0, and attaches the wheel and the release notes (with a "Breaking changes"
section) to a GitHub Release. The wheel is also published to TestPyPI:
pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ bhom-schemaTo upgrade, read the release notes first. See docs/Workflows.md for how a release is made.
The classes read and write the JSON that BHoM_JSONSchema describes, the same as BHoM in C#:
from bhom_schema.FixtureAlpha_oM.GeometryHolder import GeometryHolder
text = holder.model_dump_json() # every object carries "_t", its C# class name
GeometryHolder.model_validate_json(text) # an interface field (Geometry: IGeometryLike) loads the class that "_t" names
GeometryHolder.model_json_schema() # the JSON Schema of the classA value in an interface field needs _t, and only classes that are in bhom_schema are accepted. Enums are written by name. See
docs/audit-1/Fix-Plan.md (step 5) for the rules and their limits.
A change to src/bhom_schema in a pull request is turned into a draft C# pull request by py2cs. It reads the Python
without running it, so it only understands these rules:
- One class per file, in
src/bhom_schema/<Assembly>/<namespace folders>/<ClassName>.py, inside an assembly folder that already exists (for exampleStructure_oM/Elements/Bar.pyforBH.oM.Structure.Elements.Bar). - A new class needs no
__bhom__marker: its C# name, namespace and repository are worked out from the folder and the generated classes next to it, and the PR report says so. - Every field has a default where C# would have one:
Name: str = "",Stage: int = Field(0, description="..."),Tags: list[str] = Field(default_factory=list). A field without a default becomes a C# property without an initial value. - Every class and field has a description: a docstring on the class,
Field(description="...")on a field. - Supported types:
str,int,float,bool,Decimal,datetime,timedelta,UUID,Any,list[...],dict[...],set[...],tuple[...],X | None(orOptional[X]), and otherbhom_schemaclasses. UseAnnotated[int, ClrType("long")]when the C# type is not the usual one, andQuantity("Length", "m")for physical quantities. - Existing C# files are changed member by member: only the properties that changed in Python are touched.
docs/templates/NewClass.py is a class to copy. Check your change before pushing:
$env:PYTHONPATH = ".ci/generation"
.venv\Scripts\python -m py2cs check --root src/bhom_schemaThe C# is the source of truth. A Python pull request is a proposal, and it is linked to a C# pull request in the repository that owns the class.
- Open the Python PR.
py2csdrafts the linked C# PR (a draft, with a report). The Python PR is never merged before its C# PR. - The C# PR is reviewed and merged in its own repository, as usual. Reviewers may change it.
- Before the Python PR can be merged, the alignment check must pass. It generates the Python from the merged C# and compares it with the PR. If they differ, change the Python PR to match what was merged. Or close the Python PR and let the next weekly generation bring in the same change; both give the same files.
- If the C# PR is closed without merging, close the Python PR too, with a comment saying why. Otherwise the next weekly generation removes the change from the Python again.
# After the C# is merged and built (the folder holds the built oM dlls)
.venv\Scripts\python -m py2cs align --base-root <Python before the PR> --head-root src/bhom_schema --assemblies <folder with the oM dlls>It exits with 0 when they match, and lists every difference otherwise (the first value is from the C#, the second from your PR).
Breaking changes are listed in their own section of the C# PR, which also gets the breaking-change label. They are:
a property removed or renamed, a property whose type changed, an enum member removed or renumbered, a class removed, and a base
class or interface removed. BHoM needs an upgrade in Versioning_Toolkit for these so old files still open. Nothing is blocked
automatically; the reviewer decides.
The weekly generation writes the Python straight from the C# and commits it to develop. It is not a pull request, so it never
raises a C# PR.