From 2adef37b006a3e8ace505e12ecfc6b6993c635fd Mon Sep 17 00:00:00 2001 From: Dag Brattli Date: Sun, 1 Mar 2026 09:09:01 +0100 Subject: [PATCH 1/3] Fix Python docs: correct Py.Decorator to Py.Decorate and fix examples - Rename Py.Decorator to Py.Decorate (the actual API name) - Replace record example with class example (records already compile to @dataclass automatically, and Py.Decorate cannot be used on records) - Remove function decorator example (Fable doesn't support attributes on functions, only on types) - Add single-argument form example for local decorators - Move Class Attributes section before Python Decorators since the decorator example references Py.ClassAttributes Co-Authored-By: Claude Opus 4.6 --- docs/docs/python/features.md | 62 ++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/docs/docs/python/features.md b/docs/docs/python/features.md index a39c159..4a5c1f5 100644 --- a/docs/docs/python/features.md +++ b/docs/docs/python/features.md @@ -458,73 +458,67 @@ def add(a: int32, b: int32) -> Any: `Py.python` executes as statements, so use `return` keyword to return values. -## Python Decorators +## Class Attributes

Added in v5.0.0-alpha

-`Py.Decorator` allows you to apply Python decorators to classes and functions. +`Py.ClassAttributes` controls how class members are generated in Python. ```fs open Fable.Core -[] -type User = - { Name: string - Age: int } +[] +type Config() = + member val Name = "default" with get, set + member val Port = 8080 with get, set ``` generates: ```py -@dataclasses.dataclass -class User: - name: str - age: int32 -``` - -You can also pass parameters to decorators: - -```fs -[] -let expensiveFunction x = x * 2 +class Config: + name: str = "default" + port: int = 8080 ``` -generates: - -```py -@functools.lru_cache(maxsize=128) -def expensive_function(x): - return x * 2 -``` +Without `ClassAttributes`, members would be generated as properties with instance backing. -## Class Attributes +## Python Decorators

Added in v5.0.0-alpha

-`Py.ClassAttributes` controls how class members are generated in Python. +`Py.Decorate` allows you to apply Python decorators to types. ```fs open Fable.Core -[] -type Config() = - member val Name = "default" with get, set - member val Port = 8080 with get, set +[] +[] +type DecoratedUser() = + member val Name: string = "" with get, set + member val Age: int = 0 with get, set ``` generates: ```py -class Config: - name: str = "default" - port: int = 8080 +@dataclass +class DecoratedUser: + Age: int32 = int32.ZERO + Name: str = "" ``` -Without `ClassAttributes`, members would be generated as properties with instance backing. +The single argument form can be used for local decorators where you don't need to import anything: + +```fs +[] +type MyClass() = + member val Value: int = 0 with get, set +``` ## `[]` From d3dba62e5f3dcb88ee1adff5188ec7c2b9ba0813 Mon Sep 17 00:00:00 2001 From: Dag Brattli Date: Sun, 1 Mar 2026 09:22:12 +0100 Subject: [PATCH 2/3] Add ClassAttributes options table and Py.DataClass shorthand to docs Explain the different style and init parameters for Py.ClassAttributes, and document Py.DataClass as a shorthand for frameworks like Pydantic. Co-Authored-By: Claude Opus 4.6 --- docs/docs/python/features.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/docs/python/features.md b/docs/docs/python/features.md index 4a5c1f5..70a598d 100644 --- a/docs/docs/python/features.md +++ b/docs/docs/python/features.md @@ -485,6 +485,25 @@ class Config: Without `ClassAttributes`, members would be generated as properties with instance backing. +| Parameter | Effect | +| -------------------- | ---------------------------------------------------------- | +| `style = Attributes` | Generate class-level type annotations | +| `style = Properties` | Generate properties with instance attribute backing | +| `init = false` | Don't generate `__init__` (Pydantic/dataclass provides it) | +| `init = true` | Generate `__init__` with attribute assignments | + +`Py.DataClass` is shorthand for `Py.ClassAttributes(style = Attributes, init = false)`. +This is useful when working with frameworks like Pydantic, dataclasses, and attrs that +expect class-level type annotations: + +```fs +[] +type User() = + inherit BaseModel() + member val Name: string = "" with get, set + member val Age: int = 0 with get, set +``` + ## Python Decorators

From d7cfa03b0f83de0820aa580f4bd7729c5afbc084 Mon Sep 17 00:00:00 2001 From: Dag Brattli Date: Sun, 1 Mar 2026 09:24:52 +0100 Subject: [PATCH 3/3] Add DecorateTemplate section for library authors Document Py.DecorateTemplate for creating reusable custom decorator attributes, with a web framework route decorator as an example. Co-Authored-By: Claude Opus 4.6 --- docs/docs/python/features.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/docs/python/features.md b/docs/docs/python/features.md index 70a598d..ea73eb8 100644 --- a/docs/docs/python/features.md +++ b/docs/docs/python/features.md @@ -539,6 +539,31 @@ type MyClass() = member val Value: int = 0 with get, set ``` +### DecorateTemplate for Library Authors + +When building a library, you can create custom decorator attributes that users +can apply without knowing the underlying Python syntax. Use `Py.DecorateTemplate`: + +```fs +/// Custom route decorator for a web framework +[] +[] +type GetRouteAttribute(path: string) = + inherit System.Attribute() +``` + +Now users of your library can simply write: + +```fs +[] +static member get_users() = ... +// Generates: @app.get('/users') +``` + +The template string uses `{0}`, `{1}`, etc. as placeholders for the attribute's +constructor arguments. The `[]` attribute prevents the attribute type +from being emitted to Python. + ## `[]` ### Erased unions