Skip to content

Conversation

@dbrattli
Copy link
Collaborator

@dbrattli dbrattli commented Dec 6, 2025

This PR enables library authors to create ergonomic decorator and class attributes that generate proper Python code at compile time, without users needing to know the underlying Python syntax.

New Attributes

Py.DecorateTemplateAttribute - Allows library authors to define custom decorator attributes:

// Library defines:
[<Erase; Py.DecorateTemplate("""app.get("{0}")""")>]
type GetAttribute(path: string) = inherit Attribute()

// User writes:
[<Get("/users")>]
static member get_users() = ...

Generates:

@app.get("/users")
@staticmethod
def get_users(): ...

Py.ClassAttributesTemplateAttribute - Allows library authors to define custom class attribute shortcuts:

// Library defines:
[<Erase; Py.ClassAttributesTemplate(Py.ClassAttributeStyle.Attributes, init = false)>]
type APIClassAttribute() = inherit Attribute()

// User writes:
[<APIClass>]
type API() = ...

Py.DataClassAttribute - Built-in shorthand for the common case (style = Attributes, init = false):

[<Py.DataClass>]
type User(name: string, age: int) = ...

Changes

  • Adds Py.DecorateTemplateAttribute to Fable.Core
  • Adds Py.ClassAttributesTemplateAttribute to Fable.Core
  • Adds Py.DataClassAttribute as a built-in shorthand
  • Detects template attributes and formats them with constructor arguments during code generation
  • Extends [<Erase>] support to regular types (previously limited to unions/interfaces)
  • Relocates test files to tests/Python/py/

@dbrattli
Copy link
Collaborator Author

dbrattli commented Dec 6, 2025

This PR enables us to write code for Fable.Python that looks like this:

  open Fable.Python.FastAPI

  let app = FastAPI()

  [<APIClass>]
  type API() =
      [<Get("/")>]
      static member root() = {| message = "Hello World" |}

      [<Get("/items/{item_id}")>]
      static member get_item(item_id: int) = {| item_id = item_id |}

      [<Post("/items")>]
      static member create_item(item: Item) = {| status = "created" |}

      [<Put("/items/{item_id}")>]
      static member update_item(item_id: int, item: Item) = {| updated = true |}

      [<Delete("/items/{item_id}")>]
      static member delete_item(item_id: int) = {| deleted = item_id |}

@dbrattli dbrattli changed the title [Python] Add decorateTemplateAttribute [Python] Add DecorateTemplate and ClassAttributesTemplate for library authors Dec 6, 2025
@dbrattli dbrattli merged commit 27cf959 into main Dec 6, 2025
22 checks passed
@dbrattli dbrattli deleted the python-decorate-template branch December 6, 2025 12:18
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.

2 participants