Skip to content

[Python] Enhance object API __init__ with typed keyword arguments #8615

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 23, 2025

Conversation

crackcomm
Copy link
Contributor

This commit significantly improves the developer experience for the Python Object-Based API by overhauling the generated __init__ method for T-suffixed classes.

Previously, T objects had to be instantiated with an empty constructor, and their fields had to be populated manually one by one. This was verbose and not idiomatic Python.

This change modifies the Python code generator (GenInitialize) to produce __init__ methods that are:

  1. Keyword-Argument-Friendly: The constructor now accepts all table/struct fields as keyword arguments, allowing for concise, single-line object creation.

  2. Fully Typed: The signature of the __init__ method is now annotated with Python type hints. This provides immediate benefits for static analysis tools (like Mypy) and IDEs, enabling better autocompletion and type checking.

  3. Correctly Optional: The generator now correctly wraps types in Optional[...] if their default value is None. This applies to strings, vectors, and other nullable fields, ensuring strict type safety.

The new approach remains fully backward-compatible, as all arguments have default values. Existing code that uses the empty constructor will continue to work without modification.

Example of a Generated __init__

Before:

class KeyValueT(object):
    def __init__(self):
        self.key = None  # type: str
        self.value = None  # type: str

After:

class KeyValueT(object):
    def __init__(self, key: Optional[str] = None, value: Optional[str] = None):
        self.key = key
        self.value = value

Example of User Code

Before:

# Old, verbose way
kv = KeyValueT()
kv.key = "instrument"
kv.value = "EUR/USD"

After:

# New, Pythonic way
kv = KeyValueT(key="instrument", value="EUR/USD")

@github-actions github-actions bot added c++ codegen Involving generating code from schema python labels Jun 16, 2025
@crackcomm crackcomm force-pushed the push-uvkkkyywuuzy branch from 3df6969 to 2043352 Compare June 16, 2025 04:43
@fliiiix
Copy link
Contributor

fliiiix commented Jun 23, 2025

Nice, but im almost certain this will break Python 2 support

File "script.py", line 2
    def __init__(self, key: Optional[str] = None, value: Optional[str] = None):
                          ^
SyntaxError: invalid syntax

Some guarding against that would be probably useful version_.major == 3

@crackcomm crackcomm force-pushed the push-uvkkkyywuuzy branch 3 times, most recently from 45a426b to 0455d8c Compare July 14, 2025 07:59
This commit significantly improves the developer experience for the Python Object-Based API by overhauling the generated `__init__` method for `T`-suffixed classes.

Previously, `T` objects had to be instantiated with an empty constructor, and their fields had to be populated manually one by one. This was verbose and not idiomatic Python.

This change modifies the Python code generator (`GenInitialize`) to produce `__init__` methods that are:

1.  **Keyword-Argument-Friendly**: The constructor now accepts all table/struct fields as keyword arguments, allowing for concise, single-line object creation.

2.  **Fully Typed**: The signature of the `__init__` method is now annotated with Python type hints. This provides immediate benefits for static analysis tools (like Mypy) and IDEs, enabling better autocompletion and type checking.

3.  **Correctly Optional**: The generator now correctly wraps types in `Optional[...]` if their default value is `None`. This applies to strings, vectors, and other nullable fields, ensuring strict type safety.

The new approach remains **fully backward-compatible**, as all arguments have default values. Existing code that uses the empty constructor will continue to work without modification.

#### Example of a Generated `__init__`

**Before:**

```python
class KeyValueT(object):
    def __init__(self):
        self.key = None  # type: str
        self.value = None  # type: str
```

**After:**

```python
class KeyValueT(object):
    def __init__(self, key: Optional[str] = None, value: Optional[str] = None):
        self.key = key
        self.value = value
```

#### Example of User Code

**Before:**

```python
# Old, verbose way
kv = KeyValueT()
kv.key = "instrument"
kv.value = "EUR/USD"
```

**After:**

```python
# New, Pythonic way
kv = KeyValueT(key="instrument", value="EUR/USD")
```
@crackcomm crackcomm force-pushed the push-uvkkkyywuuzy branch from 0455d8c to c588585 Compare July 14, 2025 08:08
@crackcomm
Copy link
Contributor Author

The code was generated with ./tests/PythonTest.sh, I guess it's missing the flag from #8551? I used scripts/generate_code.py instead.

@fliiiix
Copy link
Contributor

fliiiix commented Jul 14, 2025

I guess it's missing the flag from #8551?

I guess this flag should not be part of scripts/generate_code.py? and maybe it should have a test

@fliiiix
Copy link
Contributor

fliiiix commented Jul 17, 2025

@aardappel I just tested this and it looks good to me 👍 if @akb825 has no more comments i guess this could be merged?

@fliiiix
Copy link
Contributor

fliiiix commented Jul 22, 2025

@aardappel i guess this can be merged?

@akb825
Copy link
Contributor

akb825 commented Jul 22, 2025

@aardappel I just tested this and it looks good to me 👍 if @akb825 has no more comments i guess this could be merged?

Sorry, I forgot to reply earlier, looks good on my end.

@aardappel aardappel merged commit c526cb6 into google:master Jul 23, 2025
51 checks passed
@aardappel
Copy link
Collaborator

thanks :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ codegen Involving generating code from schema python
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants