typesync 0.0.1a1__tar.gz → 0.0.1a2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {typesync-0.0.1a1 → typesync-0.0.1a2}/PKG-INFO +5 -6
- {typesync-0.0.1a1 → typesync-0.0.1a2}/README.md +3 -5
- {typesync-0.0.1a1 → typesync-0.0.1a2}/pyproject.toml +8 -1
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync/__init__.py +3 -1
- typesync-0.0.1a2/typesync/annotations.py +27 -0
- typesync-0.0.1a2/typesync/argument_types.py +116 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync/cli.py +75 -23
- typesync-0.0.1a2/typesync/codegen/__init__.py +7 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync/codegen/extractor.py +122 -51
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync/codegen/inference.py +15 -5
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync/codegen/writer.py +101 -65
- typesync-0.0.1a2/typesync/misc.py +7 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync/type_translators/__init__.py +4 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync/type_translators/abstract.py +10 -3
- typesync-0.0.1a2/typesync/type_translators/annotations_translator.py +47 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync/type_translators/base_translator.py +14 -7
- typesync-0.0.1a2/typesync/type_translators/context.py +16 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync/type_translators/flask_translator.py +2 -7
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync/type_translators/type_node.py +28 -4
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync.egg-info/PKG-INFO +5 -6
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync.egg-info/SOURCES.txt +5 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync.egg-info/requires.txt +1 -0
- typesync-0.0.1a1/typesync/codegen/__init__.py +0 -7
- {typesync-0.0.1a1 → typesync-0.0.1a2}/LICENSE +0 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/setup.cfg +0 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/tests/test_arg_types.py +0 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/tests/test_inference.py +0 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/tests/test_nested_types.py +0 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/tests/test_return_types.py +0 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/tests/test_stubs.py +0 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/tests/test_typed_dict.py +0 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync/ts_types.py +0 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync/utils.py +0 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync.egg-info/dependency_links.txt +0 -0
- {typesync-0.0.1a1 → typesync-0.0.1a2}/typesync.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: typesync
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.1a2
|
|
4
4
|
Summary: Auto-generate TypeScript client code from Flask routes and Python type annotations.
|
|
5
5
|
Author-email: Francisco Rodrigues <francisco.rodrigues0908@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/ArmindoFlores/typesync
|
|
@@ -11,6 +11,7 @@ License-File: LICENSE
|
|
|
11
11
|
Requires-Dist: click
|
|
12
12
|
Requires-Dist: flask
|
|
13
13
|
Requires-Dist: inflection>=0.5.1
|
|
14
|
+
Requires-Dist: prettytable>=3.17.0
|
|
14
15
|
Dynamic: license-file
|
|
15
16
|
|
|
16
17
|
# Typesync
|
|
@@ -36,9 +37,9 @@ Some features are already implemented, others are planned.
|
|
|
36
37
|
- [x] Support for multiple HTTP methods (GET, POST, PUT, DELETE, etc.)
|
|
37
38
|
- [x] Support for JSON request bodies with typed parameters
|
|
38
39
|
- [ ] Support validators such as pydantic
|
|
39
|
-
- [
|
|
40
|
+
- [x] Support for `typing.Annotated` to:
|
|
40
41
|
- [ ] Ignore specific routes
|
|
41
|
-
- [
|
|
42
|
+
- [x] Customize generation behavior (naming, visibility, etc.)
|
|
42
43
|
- [ ] Improved error reporting for unsupported or ambiguous annotations
|
|
43
44
|
- [ ] Optional generation modes (types only, requests only)
|
|
44
45
|
- [ ] Configuration file support
|
|
@@ -52,9 +53,7 @@ Some features are already implemented, others are planned.
|
|
|
52
53
|
|
|
53
54
|
## Installation
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
Clone the repository and install dependencies:
|
|
56
|
+
You can install typesync using `pip install typesync`. Alternatively, you can do it directly from source, preferably using `uv`, by cloning the repository and installing dependencies:
|
|
58
57
|
|
|
59
58
|
```bash
|
|
60
59
|
git clone https://github.com/ArmindoFlores/typesync
|
|
@@ -21,9 +21,9 @@ Some features are already implemented, others are planned.
|
|
|
21
21
|
- [x] Support for multiple HTTP methods (GET, POST, PUT, DELETE, etc.)
|
|
22
22
|
- [x] Support for JSON request bodies with typed parameters
|
|
23
23
|
- [ ] Support validators such as pydantic
|
|
24
|
-
- [
|
|
24
|
+
- [x] Support for `typing.Annotated` to:
|
|
25
25
|
- [ ] Ignore specific routes
|
|
26
|
-
- [
|
|
26
|
+
- [x] Customize generation behavior (naming, visibility, etc.)
|
|
27
27
|
- [ ] Improved error reporting for unsupported or ambiguous annotations
|
|
28
28
|
- [ ] Optional generation modes (types only, requests only)
|
|
29
29
|
- [ ] Configuration file support
|
|
@@ -37,9 +37,7 @@ Some features are already implemented, others are planned.
|
|
|
37
37
|
|
|
38
38
|
## Installation
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
Clone the repository and install dependencies:
|
|
40
|
+
You can install typesync using `pip install typesync`. Alternatively, you can do it directly from source, preferably using `uv`, by cloning the repository and installing dependencies:
|
|
43
41
|
|
|
44
42
|
```bash
|
|
45
43
|
git clone https://github.com/ArmindoFlores/typesync
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[project]
|
|
2
|
-
version = "0.0.
|
|
2
|
+
version = "0.0.1a2"
|
|
3
3
|
name = "typesync"
|
|
4
4
|
description = "Auto-generate TypeScript client code from Flask routes and Python type annotations."
|
|
5
5
|
readme = "README.md"
|
|
@@ -8,6 +8,7 @@ dependencies = [
|
|
|
8
8
|
"click",
|
|
9
9
|
"flask",
|
|
10
10
|
"inflection>=0.5.1",
|
|
11
|
+
"prettytable>=3.17.0",
|
|
11
12
|
]
|
|
12
13
|
requires-python = ">= 3.12"
|
|
13
14
|
authors = [
|
|
@@ -36,6 +37,12 @@ dev = [
|
|
|
36
37
|
"ruff>=0.14.13",
|
|
37
38
|
]
|
|
38
39
|
|
|
40
|
+
[tool.ty.rules]
|
|
41
|
+
invalid-type-form = "ignore"
|
|
42
|
+
|
|
43
|
+
[tool.ty.src]
|
|
44
|
+
exclude = ["tests"]
|
|
45
|
+
|
|
39
46
|
[tool.ruff.lint]
|
|
40
47
|
extend-select = [
|
|
41
48
|
"E", # pycodestyle (errors)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
__all__ = [
|
|
2
|
+
"annotations",
|
|
2
3
|
"cli",
|
|
3
4
|
"extractor",
|
|
4
5
|
"ts_types",
|
|
@@ -6,8 +7,9 @@ __all__ = [
|
|
|
6
7
|
"utils",
|
|
7
8
|
]
|
|
8
9
|
|
|
9
|
-
from .
|
|
10
|
+
from . import annotations
|
|
10
11
|
from . import type_translators
|
|
11
12
|
from . import utils
|
|
12
13
|
from . import ts_types
|
|
13
14
|
from .cli import cli
|
|
15
|
+
from .codegen import extractor
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
from typesync.misc import HTTPMethod
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TypesyncAnnotation: ...
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TypesyncSkipGenerationAnnotation(TypesyncAnnotation): ...
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TypesyncHTTPMethodAnnotation(TypesyncAnnotation):
|
|
13
|
+
def __init__(self, methods: set[HTTPMethod]) -> None:
|
|
14
|
+
self.methods = methods
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
type SkipGeneration[T] = typing.Annotated[T, TypesyncSkipGenerationAnnotation()]
|
|
18
|
+
|
|
19
|
+
type ForHTTPGet[T] = typing.Annotated[T, TypesyncHTTPMethodAnnotation({"GET"})]
|
|
20
|
+
type ForHTTPHead[T] = typing.Annotated[T, TypesyncHTTPMethodAnnotation({"HEAD"})]
|
|
21
|
+
type ForHTTPPost[T] = typing.Annotated[T, TypesyncHTTPMethodAnnotation({"POST"})]
|
|
22
|
+
type ForHTTPPut[T] = typing.Annotated[T, TypesyncHTTPMethodAnnotation({"PUT"})]
|
|
23
|
+
type ForHTTPDelete[T] = typing.Annotated[T, TypesyncHTTPMethodAnnotation({"DELETE"})]
|
|
24
|
+
type ForHTTPConnect[T] = typing.Annotated[T, TypesyncHTTPMethodAnnotation({"CONNECT"})]
|
|
25
|
+
type ForHTTPOptions[T] = typing.Annotated[T, TypesyncHTTPMethodAnnotation({"OPTIONS"})]
|
|
26
|
+
type ForHTTPTrace[T] = typing.Annotated[T, TypesyncHTTPMethodAnnotation({"TRACE"})]
|
|
27
|
+
type ForHTTPPatch[T] = typing.Annotated[T, TypesyncHTTPMethodAnnotation({"PATCH"})]
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import importlib.util
|
|
3
|
+
import pathlib
|
|
4
|
+
import sys
|
|
5
|
+
import types
|
|
6
|
+
|
|
7
|
+
from click import ParamType
|
|
8
|
+
|
|
9
|
+
from .type_translators import Translator
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PythonModuleParamType(ParamType):
|
|
13
|
+
name = "python_module"
|
|
14
|
+
|
|
15
|
+
def convert(self, value, param, ctx) -> types.ModuleType:
|
|
16
|
+
if isinstance(value, types.ModuleType):
|
|
17
|
+
return value
|
|
18
|
+
|
|
19
|
+
if not isinstance(value, str):
|
|
20
|
+
return self.fail(f"{value!r} is not a valid value", param, ctx)
|
|
21
|
+
|
|
22
|
+
path = pathlib.Path(value).resolve()
|
|
23
|
+
|
|
24
|
+
if not path.exists:
|
|
25
|
+
return self.fail(f"file {value!r} does not exist", param, ctx)
|
|
26
|
+
|
|
27
|
+
if not path.is_file():
|
|
28
|
+
return self.fail(f"{value!r} is not a file", param, ctx)
|
|
29
|
+
|
|
30
|
+
mod_name = f"module_{hashlib.sha256(str(path).encode()).hexdigest()[:16]}"
|
|
31
|
+
spec = importlib.util.spec_from_file_location(mod_name, str(path))
|
|
32
|
+
if spec is None or spec.loader is None:
|
|
33
|
+
return self.fail(f"{value!r} is not a valid python module", param, ctx)
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
module = importlib.util.module_from_spec(spec)
|
|
37
|
+
except ModuleNotFoundError:
|
|
38
|
+
return self.fail(f"{value!r} is not a valid python module", param, ctx)
|
|
39
|
+
|
|
40
|
+
sys.modules[mod_name] = module
|
|
41
|
+
try:
|
|
42
|
+
spec.loader.exec_module(module)
|
|
43
|
+
except Exception as e:
|
|
44
|
+
del sys.modules[mod_name]
|
|
45
|
+
return self.fail(f"could not load module at {value!r} ({e})", param, ctx)
|
|
46
|
+
|
|
47
|
+
return module
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class TranslatorPluginParamType(ParamType):
|
|
51
|
+
name = "translator_plugin"
|
|
52
|
+
|
|
53
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
54
|
+
super().__init__(*args, **kwargs)
|
|
55
|
+
self.python_module_plugin_param_type = PythonModuleParamType()
|
|
56
|
+
|
|
57
|
+
def convert(self, value, param, ctx) -> type[Translator]:
|
|
58
|
+
module = self.python_module_plugin_param_type.convert(value, param, ctx)
|
|
59
|
+
|
|
60
|
+
translator_func = getattr(module, "translator", None)
|
|
61
|
+
if translator_func is None:
|
|
62
|
+
return self.fail(
|
|
63
|
+
f"{value!r} must define a function 'translator() -> type[Translator]'",
|
|
64
|
+
param,
|
|
65
|
+
ctx,
|
|
66
|
+
)
|
|
67
|
+
try:
|
|
68
|
+
translator = translator_func()
|
|
69
|
+
except Exception as e:
|
|
70
|
+
return self.fail(
|
|
71
|
+
f"failed to run the 'translator()' function defined by {value!r} ({e})",
|
|
72
|
+
param,
|
|
73
|
+
ctx,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
if not issubclass(translator, Translator):
|
|
77
|
+
return self.fail(
|
|
78
|
+
f"'translator()' function defined by {value!r} must return a class "
|
|
79
|
+
"that inherits from typesync.type_translators.Translator",
|
|
80
|
+
param,
|
|
81
|
+
ctx,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
return translator
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class TranslatorPriorityParamType(ParamType):
|
|
88
|
+
name = "translator_priority"
|
|
89
|
+
|
|
90
|
+
def convert(self, value, param, ctx) -> tuple[str, int]:
|
|
91
|
+
if isinstance(value, tuple):
|
|
92
|
+
return value
|
|
93
|
+
|
|
94
|
+
if not isinstance(value, str):
|
|
95
|
+
return self.fail(f"{value!r} is not a valid value", param, ctx)
|
|
96
|
+
|
|
97
|
+
id_and_priority = value.rsplit(":", 1)
|
|
98
|
+
if len(id_and_priority) != 2:
|
|
99
|
+
return self.fail(
|
|
100
|
+
f"must be of the form ID:PRIORITY (was {value!r})", param, ctx
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
id_, priority_str = id_and_priority
|
|
104
|
+
try:
|
|
105
|
+
priority = int(priority_str)
|
|
106
|
+
except ValueError:
|
|
107
|
+
return self.fail(
|
|
108
|
+
f"priority {priority_str!r} cannot be converted to an int", param, ctx
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
return id_, priority
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
PYTHON_MODULE = PythonModuleParamType()
|
|
115
|
+
TRANSLATOR_PLUGIN = TranslatorPluginParamType()
|
|
116
|
+
TRANSLATOR_PRIORITY = TranslatorPriorityParamType()
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import typing
|
|
2
3
|
|
|
3
4
|
import click
|
|
4
5
|
from flask import current_app
|
|
5
6
|
from flask.cli import AppGroup
|
|
7
|
+
from prettytable import PrettyTable
|
|
6
8
|
from werkzeug.routing.rules import Rule
|
|
7
9
|
|
|
8
|
-
from .
|
|
10
|
+
from . import argument_types
|
|
11
|
+
from .codegen import CodeWriter, RouteTypeExtractor
|
|
12
|
+
|
|
13
|
+
if typing.TYPE_CHECKING:
|
|
14
|
+
from .type_translators import Translator
|
|
9
15
|
|
|
10
16
|
|
|
11
17
|
cli = AppGroup("typesync")
|
|
@@ -14,12 +20,37 @@ cli = AppGroup("typesync")
|
|
|
14
20
|
@cli.command(help="Generate Typescript types based on Flask routes.")
|
|
15
21
|
@click.argument("out_dir", type=click.Path(file_okay=False, resolve_path=True))
|
|
16
22
|
@click.option("--endpoint", "-E", help="The base endpoint.", default="")
|
|
17
|
-
@click.option("--samefile", "-S", help="Write types and apis to the same file")
|
|
23
|
+
@click.option("--samefile", "-S", help="Write types and apis to the same file.")
|
|
24
|
+
@click.option(
|
|
25
|
+
"--translator",
|
|
26
|
+
"-t",
|
|
27
|
+
help=(
|
|
28
|
+
"Path to a python script containing a additional type translators. "
|
|
29
|
+
"May be used multiple times."
|
|
30
|
+
),
|
|
31
|
+
type=argument_types.TRANSLATOR_PLUGIN,
|
|
32
|
+
multiple=True,
|
|
33
|
+
)
|
|
34
|
+
@click.option(
|
|
35
|
+
"--translator-priority",
|
|
36
|
+
help=("Set the priority of a translator.May be used multiple times."),
|
|
37
|
+
type=argument_types.TRANSLATOR_PRIORITY,
|
|
38
|
+
multiple=True,
|
|
39
|
+
)
|
|
40
|
+
@click.option(
|
|
41
|
+
"--skip-unannotated",
|
|
42
|
+
type=bool,
|
|
43
|
+
default=True,
|
|
44
|
+
help=(
|
|
45
|
+
"Whether to skip code generation for routes whose annotations are not specified"
|
|
46
|
+
" and could not be inferred. Defaults to True."
|
|
47
|
+
),
|
|
48
|
+
)
|
|
18
49
|
@click.option(
|
|
19
50
|
"--inference",
|
|
20
51
|
"-i",
|
|
21
52
|
is_flag=True,
|
|
22
|
-
help="Whether to use inference when type annotations cannot be resolved",
|
|
53
|
+
help="Whether to use inference when type annotations cannot be resolved.",
|
|
23
54
|
)
|
|
24
55
|
@click.option(
|
|
25
56
|
"--inference-can-eval",
|
|
@@ -31,42 +62,42 @@ cli = AppGroup("typesync")
|
|
|
31
62
|
)
|
|
32
63
|
@click.option(
|
|
33
64
|
"--types-file",
|
|
34
|
-
help="Name of output file containing type definitions (defaults to 'types.ts')",
|
|
65
|
+
help="Name of output file containing type definitions (defaults to 'types.ts').",
|
|
35
66
|
default="types.ts",
|
|
36
67
|
)
|
|
37
68
|
@click.option(
|
|
38
69
|
"--apis-file",
|
|
39
|
-
help="Name of output file containing API functions (defaults to 'apis.ts')",
|
|
70
|
+
help="Name of output file containing API functions (defaults to 'apis.ts').",
|
|
40
71
|
default="apis.ts",
|
|
41
72
|
)
|
|
42
73
|
@click.option(
|
|
43
74
|
"--return-type-format",
|
|
44
|
-
default="{
|
|
75
|
+
default="{r_pc}{m_uc}ReturnType",
|
|
45
76
|
help=(
|
|
46
77
|
"Format string used to generate return type names from the route name. "
|
|
47
78
|
"Available placeholders are: "
|
|
48
|
-
"{
|
|
49
|
-
"{
|
|
50
|
-
"{
|
|
51
|
-
"{
|
|
52
|
-
"{
|
|
53
|
-
"{
|
|
54
|
-
"Defaults to: '{
|
|
79
|
+
"{r_d} or {m_d} (default route name or HTTP method), "
|
|
80
|
+
"{r_cc} or {m_cc} (camelCase), "
|
|
81
|
+
"{r_pc} or {m_pc} (PascalCase), "
|
|
82
|
+
"{r_uc} or {m_uc} (UPPERCASE), "
|
|
83
|
+
"{r_lc} or {m_lc} (lowercase), "
|
|
84
|
+
"{r_sc} or {m_sc} (snake_case). "
|
|
85
|
+
"Defaults to: '{r_pc}{m_uc}ReturnType'."
|
|
55
86
|
),
|
|
56
87
|
)
|
|
57
88
|
@click.option(
|
|
58
89
|
"--args-type-format",
|
|
59
|
-
default="{
|
|
90
|
+
default="{r_pc}{m_uc}ArgsType",
|
|
60
91
|
help=(
|
|
61
92
|
"Format string used to generate argument type names from the route name. "
|
|
62
93
|
"Available placeholders are: "
|
|
63
|
-
"{
|
|
64
|
-
"{
|
|
65
|
-
"{
|
|
66
|
-
"{
|
|
67
|
-
"{
|
|
68
|
-
"{
|
|
69
|
-
"Defaults to: '{
|
|
94
|
+
"{r_d} or {m_d} (default route name or HTTP method), "
|
|
95
|
+
"{r_cc} or {m_cc} (camelCase), "
|
|
96
|
+
"{r_pc} or {m_pc} (PascalCase), "
|
|
97
|
+
"{r_uc} or {m_uc} (UPPERCASE), "
|
|
98
|
+
"{r_lc} or {m_lc} (lowercase), "
|
|
99
|
+
"{r_sc} or {m_sc} (snake_case). "
|
|
100
|
+
"Defaults to: '{r_pc}{m_uc}ArgsType'."
|
|
70
101
|
),
|
|
71
102
|
)
|
|
72
103
|
@click.option(
|
|
@@ -81,14 +112,17 @@ cli = AppGroup("typesync")
|
|
|
81
112
|
"{r_uc} or {m_uc} (UPPERCASE), "
|
|
82
113
|
"{r_lc} or {m_lc} (lowercase), "
|
|
83
114
|
"{r_sc} or {m_sc} (snake_case). "
|
|
84
|
-
"Defaults to: '{m_lc}{r_pc}'"
|
|
115
|
+
"Defaults to: '{m_lc}{r_pc}'."
|
|
85
116
|
),
|
|
86
117
|
)
|
|
87
118
|
def generate(
|
|
88
119
|
out_dir: str,
|
|
89
120
|
endpoint: str,
|
|
121
|
+
translator: tuple[type["Translator"], ...],
|
|
122
|
+
translator_priority: tuple[tuple[str, int], ...],
|
|
90
123
|
inference: bool,
|
|
91
124
|
inference_can_eval: bool,
|
|
125
|
+
skip_unannotated: bool,
|
|
92
126
|
types_file: str,
|
|
93
127
|
apis_file: str,
|
|
94
128
|
return_type_format: str,
|
|
@@ -114,13 +148,31 @@ def generate(
|
|
|
114
148
|
endpoint,
|
|
115
149
|
)
|
|
116
150
|
result = code_writer.write(
|
|
117
|
-
|
|
151
|
+
RouteTypeExtractor(
|
|
118
152
|
current_app,
|
|
119
153
|
rule,
|
|
154
|
+
translators=translator,
|
|
155
|
+
translator_priorities=dict(translator_priority),
|
|
120
156
|
inference_enabled=inference,
|
|
121
157
|
inference_can_eval=inference_can_eval,
|
|
158
|
+
skip_unannotated=skip_unannotated,
|
|
122
159
|
)
|
|
123
160
|
for rule in rules
|
|
124
161
|
)
|
|
125
162
|
if not result:
|
|
126
163
|
click.secho("Errors occurred during file generation", fg="red")
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@cli.command(help="Show available translators and their default priorities.")
|
|
167
|
+
def list_translators():
|
|
168
|
+
translators = RouteTypeExtractor.sort_translators(
|
|
169
|
+
RouteTypeExtractor.default_translators(), {}
|
|
170
|
+
)
|
|
171
|
+
table = PrettyTable()
|
|
172
|
+
table.field_names = ["ID", "Priority"]
|
|
173
|
+
table.add_rows(
|
|
174
|
+
[[translator.ID, translator.DEFAULT_PRIORITY] for translator in translators]
|
|
175
|
+
)
|
|
176
|
+
table.align["ID"] = "l"
|
|
177
|
+
table.align["Priority"] = "r"
|
|
178
|
+
print(table)
|