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

feat: add json_to_app method with support custom classes #112

Merged
merged 1 commit into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions idf_build_apps/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0

"""
Expand Down Expand Up @@ -28,6 +28,7 @@
from .main import (
build_apps,
find_apps,
json_to_app,
)

__all__ = [
Expand All @@ -37,6 +38,6 @@
'MakeApp',
'find_apps',
'build_apps',
'json_to_app',
'setup_logging',
'SESSION_ARGS',
]
5 changes: 2 additions & 3 deletions idf_build_apps/app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0

import functools
Expand All @@ -25,10 +25,9 @@
computed_field,
)

from idf_build_apps import (
from . import (
SESSION_ARGS,
)

from .build_apps_args import (
BuildAppsArgs,
)
Expand Down
42 changes: 41 additions & 1 deletion idf_build_apps/main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0

import argparse
Expand All @@ -11,11 +11,17 @@
import textwrap
import typing as t

from pydantic import (
Field,
create_model,
)

from . import (
SESSION_ARGS,
)
from .app import (
App,
AppDeserializer,
CMakeApp,
MakeApp,
)
Expand Down Expand Up @@ -791,3 +797,37 @@ def main():
print(f' {app}')

sys.exit(res)


def json_to_app(json_str: str, extra_classes: t.Optional[t.List[t.Type[App]]] = None) -> App:
"""
Deserialize json string to App object

.. note::

You can pass extra_cls to support custom App class. A custom App class must be a subclass of App, and have a
different value of `build_system`. For example, a custom CMake app

>>> class CustomApp(CMakeApp):
>>> build_system: Literal['custom_cmake'] = 'custom_cmake'

Then you can pass the CustomApp class to the `extra_cls` argument

>>> json_str = CustomApp('.', 'esp32').to_json()
>>> json_to_app(json_str, extra_classes=[CustomApp])

:param json_str: json string
:param extra_classes: extra App class
:return: App object
"""
types = [App, CMakeApp, MakeApp]
if extra_classes:
types.extend(extra_classes)

custom_deserializer = create_model(
'_CustomDeserializer',
app=(t.Union[tuple(types)], Field(discriminator='build_system')),
__base__=AppDeserializer,
)

return custom_deserializer.from_json(json_str)
39 changes: 39 additions & 0 deletions tests/test_app.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0

import sys

import pytest
from pydantic import (
ValidationError,
)

from idf_build_apps import (
AppDeserializer,
CMakeApp,
MakeApp,
)
from idf_build_apps.main import (
json_to_app,
)

if sys.version_info < (3, 8):
from typing_extensions import (
Literal,
)
else:
from typing import (
Literal,
)


def test_serialization():
Expand Down Expand Up @@ -54,3 +71,25 @@ def test_app_sorting():
assert d == e
assert not d < e
assert not d > e


def test_app_deserializer():
a = CMakeApp('foo', 'esp32')
b = MakeApp('foo', 'esp32')

class CustomApp(CMakeApp):
build_system: Literal['custom'] = 'custom' # type: ignore

c = CustomApp('foo', 'esp32')

assert json_to_app(a.to_json()) == a
assert json_to_app(b.to_json()) == b

with pytest.raises(
ValidationError,
match="Input tag 'custom' found using 'build_system' does not match "
"any of the expected tags: 'unknown', 'cmake', 'make'",
):
assert json_to_app(c.to_json()) == c

assert json_to_app(c.to_json(), extra_classes=[CustomApp]) == c
Loading