Skip to content

Commit

Permalink
Refactor constants and allow exporting enums (#300)
Browse files Browse the repository at this point in the history
  • Loading branch information
silviogutierrez authored Nov 9, 2023
1 parent ce9373c commit 4a68b89
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 9 deletions.
2 changes: 2 additions & 0 deletions packages/reactivated/src/generator.mts
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,8 @@ import createContext from "reactivated/dist/context";
import * as forms from "reactivated/dist/forms";
import * as generated from "reactivated/dist/generated";
import * as rpcUtils from "reactivated/dist/rpc";
import {constants} from "./constants";
export {constants};
// Note: this needs strict function types to behave correctly with excess properties etc.
export type Checker<P, U extends (React.FunctionComponent<P> | React.ComponentClass<P>)> = {};
Expand Down
22 changes: 21 additions & 1 deletion packages/reactivated/src/generator/constants.mts
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,36 @@ const interfaces = project.createSourceFile("");
const {urls, templates, types, values} = schema;

for (const name of Object.keys(values)) {
// Top level constants are deprecated.
// Because enums and classes will often have dots and the like.
if (name.includes(".")) {
continue;
}

interfaces.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
isExported: true,
declarations: [
{
name,
initializer: Writers.assertion(JSON.stringify(values[name]), "const"),
initializer: Writers.assertion(
JSON.stringify(values[name], null, 4),
"const",
),
},
],
});
}

interfaces.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
isExported: true,
declarations: [
{
name: "constants",
initializer: Writers.assertion(JSON.stringify(values, null, 4), "const"),
},
],
});

process.stdout.write(interfaces.getText());
8 changes: 7 additions & 1 deletion reactivated/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import abc
import enum
import inspect
from typing import (
Any,
Expand Down Expand Up @@ -36,11 +37,16 @@


def export(var: Any) -> None:
if inspect.isclass(var) and issubclass(var, enum.Enum):
name = f"{var.__module__}.{var.__qualname__}"
registry.value_registry.update({name: (var, "enum")})
return

"""See: https://stackoverflow.com/a/18425523"""
callers_local_vars = inspect.currentframe().f_back.f_locals.items() # type: ignore[union-attr]
name = [var_name for var_name, var_val in callers_local_vars if var_val is var][0]

registry.value_registry.update({name: (var, True)})
registry.value_registry.update({name: (var, "primitive")})


# def export_type(var: Any) -> None:
Expand Down
7 changes: 5 additions & 2 deletions reactivated/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import logging
import os
import subprocess
from typing import Any, Dict, NamedTuple, Tuple
from typing import Any, Dict, NamedTuple, Tuple, Type

from django.apps import AppConfig
from django.conf import settings
Expand Down Expand Up @@ -129,8 +129,11 @@ def get_values() -> Dict[str, Any]:
serialized = {}

for key, (value, serialize_as_is) in value_registry.items():
if serialize_as_is is True:
if serialize_as_is == "primitive":
serialized[key] = value
elif serialize_as_is == "enum":
generated_schema = create_schema(Type[value], {})
serialized[key] = serialize(value, generated_schema)
else:
generated_schema = create_schema(value, {})
generated_schema.definitions["is_static_context"] = True # type: ignore[index]
Expand Down
4 changes: 2 additions & 2 deletions reactivated/rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ def wrapped_view(request: THttpRequest, *args: Any, **kwargs: Any) -> Any:

if not is_empty_form:
input_name = f"{url_name}_input"
registry.value_registry[input_name] = (form_class, False)
registry.value_registry[input_name] = (form_class, "class")
registry.type_registry[input_name] = form_class # type: ignore[assignment]
else:
input_name = None # type: ignore[assignment]
Expand Down Expand Up @@ -453,7 +453,7 @@ def wrapped_view(request: THttpRequest, *args: Any, **kwargs: Any) -> Any:
if not is_empty_form:
input_name = f"{url_name}_input"
registry.type_registry[input_name] = form_type # type: ignore[assignment]
registry.value_registry[input_name] = (form_class, False)
registry.value_registry[input_name] = (form_class, "class")
else:
input_name = None # type: ignore[assignment]

Expand Down
3 changes: 2 additions & 1 deletion reactivated/serialization/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Any,
Callable,
Dict,
Literal,
Mapping,
NamedTuple,
Optional,
Expand All @@ -22,7 +23,7 @@
}
template_registry: Dict[str, Tuple[Any]] = {}
interface_registry: Dict[str, Tuple[Any]] = {}
value_registry: Dict[str, Tuple[Any, bool]] = {}
value_registry: Dict[str, Tuple[Any, Literal["primitive", "class", "enum"]]] = {}
definitions_registry: Dict[Any, Any] = {}
rpc_registry: types.RPCRegistry = {}

Expand Down
36 changes: 34 additions & 2 deletions tests/exports.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
import enum
from typing import NamedTuple

from django import forms

from reactivated import export, serialization
from reactivated.apps import get_values
from reactivated.serialization.registry import value_registry


class SimpleEnum(enum.Enum):
FIRST = "First"
SECOND = "Second"


class ComplexMember(NamedTuple):
ranking: int


class ComplexEnum(enum.Enum):
FIRST = ComplexMember(ranking=1)
SECOND = ComplexMember(ranking=2)


class SimpleForm(forms.Form):
some_field = forms.CharField()

Expand All @@ -17,8 +34,8 @@ def test_export_registry():

export(BAR)

assert value_registry["FOO"] == (1, True)
assert value_registry["BAR"] == (2, True)
assert value_registry["FOO"] == (1, "primitive")
assert value_registry["BAR"] == (2, "primitive")


def test_export_complex_types():
Expand All @@ -29,3 +46,18 @@ def test_export_complex_types():
)

del value_registry["SimpleForm"]


def test_export_enum():
export(SimpleEnum)
# generated_schema = serialization.create_schema(Type[SimpleEnum], {})
assert get_values()["tests.exports.SimpleEnum"] == {
"FIRST": "First",
"SECOND": "Second",
}

export(ComplexEnum)
assert get_values()["tests.exports.ComplexEnum"] == {
"FIRST": {"ranking": 1},
"SECOND": {"ranking": 2},
}

0 comments on commit 4a68b89

Please sign in to comment.