Skip to content
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

Cherry-pick latest updates from betterproto #10

Merged
merged 11 commits into from
Apr 30, 2024
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@ jobs:
os: [Ubuntu, MacOS, Windows]
python-version: ['3.9', '3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
run: echo "version=$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")" >> "$GITHUB_OUTPUT"

- name: Install poetry
shell: bash
Expand Down
13 changes: 7 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ repos:
additional_dependencies:
- toml

- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
rev: v2.10.0
hooks:
- id: pretty-format-java
args: [--autofix, --aosp]
files: ^.*\.java$
# Removing since aristaproto don't use the java code and this breaks CI.
# - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
# rev: v2.10.0
# hooks:
# - id: pretty-format-java
# args: [--autofix, --aosp]
# files: ^.*\.java$
33 changes: 23 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
# Arista Protobuf / Python gRPC bindings generator & library

This project is forked from <https://github.com/danielgtaylor/python-betterproto> @ [b8a091ae7055dd949d193695a06c9536ad51eea8](https://github.com/danielgtaylor/python-betterproto/commit/b8a091ae7055dd949d193695a06c9536ad51eea8)
This was originally forked from <https://github.com/danielgtaylor/python-betterproto> @ [b8a091ae7055dd949d193695a06c9536ad51eea8](https://github.com/danielgtaylor/python-betterproto/commit/b8a091ae7055dd949d193695a06c9536ad51eea8).

Afterwards commits up to `1f88b67eeb9871d33da154fd2c859b9d1aed62c1` on `python-betterproto` have been cherry-picked.

Changes in this project compared with the base project:

- Renamed to `aristaproto`.
- Cut support for Python < 3.9.
- Updating various CI actions and dependencies.
- Merged docs from multiple `rst` files to MarkDown.
- Keep nanosecond precision for `Timestamp`.
- Subclass `datetime` to store the original nano-second value when converting from `Timestamp` to `datetime`.
- On conversion from the subclass of `datetime` to `Timestamp` the original nano-second value is restored.
Expand All @@ -20,8 +26,6 @@ pip install "aristaproto[compiler]"
pip install aristaproto
```

*Betterproto* is under active development. To install the latest beta version, use `pip install --pre aristaproto`.

## Getting Started

### Compiling proto files
Expand Down Expand Up @@ -244,7 +248,22 @@ message Test {
}
```

You can use `aristaproto.which_one_of(message, group_name)` to determine which of the fields was set. It returns a tuple of the field name and value, or a blank string and `None` if unset.
On Python 3.10 and later, you can use a `match` statement to access the provided one-of field, which supports type-checking:

```py
test = Test()
match test:
case Test(on=value):
print(value) # value: bool
case Test(count=value):
print(value) # value: int
case Test(name=value):
print(value) # value: str
case _:
print("No value provided")
```

You can also use `aristaproto.which_one_of(message, group_name)` to determine which of the fields was set. It returns a tuple of the field name and value, or a blank string and `None` if unset.

```py
>>> test = Test()
Expand All @@ -259,17 +278,11 @@ You can use `aristaproto.which_one_of(message, group_name)` to determine which o
>>> test.count = 57
>>> aristaproto.which_one_of(test, "foo")
["count", 57]
>>> test.on
False

# Default (zero) values also work.
>>> test.name = ""
>>> aristaproto.which_one_of(test, "foo")
["name", ""]
>>> test.count
0
>>> test.on
False
```

Again this is a little different than the official Google code generator:
Expand Down
27 changes: 13 additions & 14 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "aristaproto"
version = "0.1.1"
version = "0.1.2"
description = "Arista Protobuf / Python gRPC bindings generator & library"
authors = ["Arista Networks <[email protected]>"]
readme = "README.md"
Expand All @@ -19,7 +19,7 @@ jinja2 = { version = ">=3.0.3", optional = true }
python-dateutil = "^2.8"
isort = {version = "^5.11.5", optional = true}
typing-extensions = "^4.7.1"
betterproto-rust-codec = { version = "0.1.0", optional = true }
betterproto-rust-codec = { version = "0.1.1", optional = true }

[tool.poetry.group.dev.dependencies]
asv = "^0.4.2"
Expand Down Expand Up @@ -94,11 +94,11 @@ cmd = """
protoc
--plugin=protoc-gen-custom=src/aristaproto/plugin/main.py
--custom_opt=INCLUDE_GOOGLE
--custom_out=src/aristaproto/lib
--custom_out=src/aristaproto/lib/std
-I /usr/local/include/
/usr/local/include/google/protobuf/**/*.proto
"""
help = "Regenerate the types in aristaproto.lib.google"
help = "Regenerate the types in aristaproto.lib.std.google"

# CI tasks

Expand Down
2 changes: 1 addition & 1 deletion src/aristaproto/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ def __post_init__(self) -> None:
group_current.setdefault(meta.group)

value = self.__raw_get(field_name)
if value != PLACEHOLDER and not (meta.optional and value is None):
if value is not PLACEHOLDER and not (meta.optional and value is None):
# Found a non-sentinel value
all_sentinel = False

Expand Down
11 changes: 9 additions & 2 deletions src/aristaproto/compile/importing.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ def parse_source_type_name(field_type_name: str) -> Tuple[str, str]:


def get_type_reference(
*, package: str, imports: set, source_type: str, unwrap: bool = True
*,
package: str,
imports: set,
source_type: str,
unwrap: bool = True,
pydantic: bool = False,
) -> str:
"""
Return a Python type name for a proto type reference. Adds the import if
Expand All @@ -69,7 +74,9 @@ def get_type_reference(
compiling_google_protobuf = current_package == ["google", "protobuf"]
importing_google_protobuf = py_package == ["google", "protobuf"]
if importing_google_protobuf and not compiling_google_protobuf:
py_package = ["aristaproto", "lib"] + py_package
py_package = (
["aristaproto", "lib"] + (["pydantic"] if pydantic else []) + py_package
)

if py_package[:1] == ["aristaproto"]:
return reference_absolute(imports, py_package, py_type)
Expand Down
6 changes: 6 additions & 0 deletions src/aristaproto/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@ def __delattr__(self, item: Any) -> Never:
f"{self.__class__.__name__} Cannot delete a member's attributes."
)

def __copy__(self) -> Self:
return self

def __deepcopy__(self, memo: Any) -> Self:
return self

@classmethod
def try_value(cls, value: int = 0) -> Self:
"""Return the value which corresponds to the value.
Expand Down
Loading
Loading