Skip to content

Commit 122018b

Browse files
committed
Phase 3
Signed-off-by: Christian Vetter <christian.vetter@here.com>
1 parent 422dc50 commit 122018b

35 files changed

Lines changed: 380 additions & 286 deletions

flatdata-generator/flatdata/generator/app.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from flatdata.generator.tree.errors import FlatdataSyntaxError
2222

2323

24-
def _parse_command_line():
24+
def _parse_command_line() -> argparse.Namespace:
2525
parser = argparse.ArgumentParser(
2626
description="Generates code for a given flatdata schema file.")
2727
parser.add_argument("-s", "--schema", type=str, required=True,
@@ -39,7 +39,7 @@ def _parse_command_line():
3939
return parser.parse_args()
4040

4141

42-
def _setup_logging(args):
42+
def _setup_logging(args: argparse.Namespace) -> None:
4343
level = logging.WARNING
4444
if args.debug:
4545
level = logging.DEBUG
@@ -52,13 +52,13 @@ def _setup_logging(args):
5252
level=level)
5353

5454

55-
def _check_args(args):
55+
def _check_args(args: argparse.Namespace) -> None:
5656
if not os.path.isfile(args.schema):
5757
logging.fatal("Cannot find schema file at %s", args.schema)
5858
sys.exit(1)
5959

6060

61-
def _run(args):
61+
def _run(args: argparse.Namespace) -> None:
6262
_setup_logging(args)
6363
_check_args(args)
6464

@@ -86,6 +86,6 @@ def _run(args):
8686
logging.info("Code for %s is written to %s", args.gen, args.output_file)
8787

8888

89-
def main():
89+
def main() -> None:
9090
"""Entrypoint"""
9191
_run(_parse_command_line())

flatdata-generator/flatdata/generator/engine.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,20 @@
44
'''
55

66
import types
7+
from typing import Any
78

89
from flatdata.generator.tree.builder import build_ast
910
from flatdata.generator.tree.nodes.trivial.namespace import Namespace
1011
from flatdata.generator.tree.nodes.node import Node
12+
from flatdata.generator.tree.syntax_tree import SyntaxTree
1113

1214
from .generators.cpp import CppGenerator
1315
from .generators.dot import DotGenerator
1416
from .generators.go import GoGenerator
1517
from .generators.python import PythonGenerator
1618
from .generators.rust import RustGenerator
1719
from .generators.flatdata import FlatdataGenerator
20+
from .generators import BaseGenerator
1821

1922

2023
class Engine:
@@ -23,7 +26,7 @@ class Engine:
2326
Implements code generation from the given flatdata schema.
2427
"""
2528

26-
_GENERATORS = {
29+
_GENERATORS: dict[str, type[BaseGenerator]] = {
2730
"cpp": CppGenerator,
2831
"dot": DotGenerator,
2932
"go": GoGenerator,
@@ -33,21 +36,21 @@ class Engine:
3336
}
3437

3538
@classmethod
36-
def available_generators(cls):
39+
def available_generators(cls) -> list[str]:
3740
"""
3841
Lists names of available code generators.
3942
"""
4043
return list(cls._GENERATORS.keys())
4144

42-
def __init__(self, schema):
45+
def __init__(self, schema: str) -> None:
4346
"""
4447
Instantiates generator engine for a given schema.
4548
:raises FlatdataSyntaxError
4649
"""
4750
self.schema = schema
4851
self.tree = build_ast(schema)
4952

50-
def render(self, generator_name):
53+
def render(self, generator_name: str) -> str:
5154
"""
5255
Render schema with a given generator
5356
:param generator_name:
@@ -60,38 +63,38 @@ def render(self, generator_name):
6063
)
6164

6265
output_content = generator.render(self.tree)
63-
return output_content
66+
return str(output_content)
6467

65-
def render_python_module(self, module_name=None, archive_name=None, root_namespace=None):
68+
def render_python_module(self, module_name: str | None = None, archive_name: str | None = None, root_namespace: str | None = None) -> types.ModuleType | tuple[types.ModuleType, Any]:
6669
"""
6770
Render python module.
6871
:param module_name: Module name to use. If none, root namespace name is used.
6972
:param archive_name: Archive name to lookup,
7073
if specified, archive type is returned along with the model
7174
:param root_namespace: Root namespace to pick in case of multiple top level namespaces.
7275
"""
73-
root_namespace = self._find_root_namespace(self.tree, archive_name, root_namespace)
76+
ns = self._find_root_namespace(self.tree, archive_name, root_namespace)
7477
module_code = self.render("py")
75-
module = types.ModuleType(module_name if module_name is not None else root_namespace.name)
78+
module = types.ModuleType(module_name if module_name is not None else ns.name)
7679
#pylint: disable=exec-used
7780
exec(module_code, module.__dict__)
7881
if archive_name is None:
7982
return module
8083

81-
name = root_namespace.name + "_" + archive_name
84+
name = ns.name + "_" + archive_name
8285
archive_type = getattr(module, name) if archive_name else None
8386
return module, archive_type
8487

8588
@classmethod
86-
def _create_generator(cls, name):
89+
def _create_generator(cls, name: str) -> BaseGenerator | None:
8790
generator_type = cls._GENERATORS.get(name, None)
8891
if generator_type is None:
8992
return None
9093

91-
return generator_type() # type: ignore[abstract] # dict values are concrete subclasses
94+
return generator_type() # type: ignore[call-arg] # dict values are concrete subclasses with zero-arg __init__
9295

9396
@staticmethod
94-
def _find_root_namespace(tree, archive_name, root_namespace=None):
97+
def _find_root_namespace(tree: SyntaxTree, archive_name: str | None, root_namespace: str | None = None) -> Namespace:
9598
root_children = tree.root.children
9699
root_namespaces = [
97100
child for child in root_children

flatdata-generator/flatdata/generator/generators/__init__.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
'''
55

66
from abc import ABCMeta, abstractmethod
7+
from typing import Any
8+
79
from jinja2 import Environment, PackageLoader
810
from jinja2 import nodes
911
from jinja2.ext import Extension
@@ -21,21 +23,21 @@
2123
class BaseGenerator(metaclass=ABCMeta):
2224
"""Abstract base class for Flatdata generators"""
2325

24-
def __init__(self, template):
26+
def __init__(self, template: str) -> None:
2527
self._template = template
2628

2729
@abstractmethod
28-
def supported_nodes(self):
30+
def supported_nodes(self) -> list[type]:
2931
"""List of supported nodes by this generator"""
3032
raise RuntimeError(
3133
"Derived generators must implement _supported_nodes")
3234

3335
@abstractmethod
34-
def _populate_environment(self, env):
36+
def _populate_environment(self, env: Environment) -> None:
3537
raise RuntimeError(
3638
"Derived generators must implement _populate_filters")
3739

38-
def render(self, tree):
40+
def render(self, tree: Any) -> str:
3941
"""Generate the language implementation from the AST"""
4042
env = Environment(loader=PackageLoader('flatdata.generator', 'templates'), lstrip_blocks=True,
4143
trim_blocks=True, autoescape=False, extensions=[RaiseExtension])
@@ -71,7 +73,7 @@ class RaiseExtension(Extension):
7173

7274
tags = set(['raise'])
7375

74-
def parse(self, parser):
76+
def parse(self, parser: Any) -> nodes.CallBlock:
7577
"""The first token is the line number, followed by the expression"""
7678
lineno = next(parser.stream).lineno
7779
message_node = parser.parse_expression()
@@ -81,6 +83,6 @@ def parse(self, parser):
8183
)
8284

8385
#pylint: disable=no-self-use
84-
def _raise(self, msg, caller):
86+
def _raise(self, msg: str, caller: Any) -> str:
8587
"""Helper callback."""
8688
raise TemplateRuntimeError(msg)

flatdata-generator/flatdata/generator/generators/cpp.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
See the LICENSE file in the root of this project for license details.
44
'''
55

6+
from jinja2 import Environment
7+
68
from flatdata.generator.tree.nodes.resources import Vector, Multivector, Instance, RawData, BoundResource, \
79
ResourceBase, Archive as ArchiveResource
810
from flatdata.generator.tree.nodes.trivial import Structure, Enumeration, Constant, Field
@@ -13,13 +15,13 @@
1315
class CppGenerator(BaseGenerator):
1416
"""Flatdata to C++ header file generator"""
1517

16-
def __init__(self):
18+
def __init__(self) -> None:
1719
BaseGenerator.__init__(self, "cpp/cpp.jinja2")
1820

19-
def supported_nodes(self):
21+
def supported_nodes(self) -> list[type]:
2022
return [Structure, Archive, Constant, Enumeration]
2123

22-
def _populate_environment(self, env):
24+
def _populate_environment(self, env: Environment) -> None:
2325
env.filters["cpp_doc"] = lambda value: value
2426

2527
def _safe_cpp_string_line(value):

flatdata-generator/flatdata/generator/generators/dot.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,19 @@
66
from flatdata.generator.tree.nodes.archive import Archive
77
from . import BaseGenerator
88

9+
from jinja2 import Environment
10+
911
SCOPE_SEPARATOR = "__"
1012
DECORATION_BOUND = "__bound__"
1113

1214

1315
class DotGenerator(BaseGenerator):
1416
"""Flatdata to DOT (graph description language) generator"""
1517

16-
def __init__(self):
18+
def __init__(self) -> None:
1719
BaseGenerator.__init__(self, "dot/dot.jinja2")
1820

19-
def _populate_environment(self, env):
21+
def _populate_environment(self, env: Environment) -> None:
2022
env.autoescape = True
2123

2224
def _field_value_type(field):
@@ -31,5 +33,5 @@ def _field_value_type(field):
3133

3234
env.filters["field_value_type"] = _field_value_type
3335

34-
def supported_nodes(self):
36+
def supported_nodes(self) -> list[type]:
3537
return [Archive]

flatdata-generator/flatdata/generator/generators/flatdata.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
See the LICENSE file in the root of this project for license details.
44
'''
55

6+
from jinja2 import Environment
7+
68
from flatdata.generator.tree.nodes.resources import BoundResource
79
from flatdata.generator.tree.nodes.trivial import Structure, Enumeration, Constant
810
from flatdata.generator.tree.nodes.archive import Archive
@@ -13,13 +15,13 @@
1315
class FlatdataGenerator(BaseGenerator):
1416
"""Flatdata to Flatdata generator, used for debugging/testing"""
1517

16-
def __init__(self):
18+
def __init__(self) -> None:
1719
BaseGenerator.__init__(self, "flatdata/flatdata.jinja2")
1820

19-
def supported_nodes(self):
21+
def supported_nodes(self) -> list[type]:
2022
return [Structure, Archive, Constant, Enumeration]
2123

22-
def _populate_environment(self, env):
24+
def _populate_environment(self, env: Environment) -> None:
2325
def _is_builtin(node):
2426
for namespace in SyntaxTree.namespaces(node):
2527
if namespace.name == "_builtin":

flatdata-generator/flatdata/generator/generators/go.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Copyright (c) 2017 HERE Europe B.V.
33
See the LICENSE file in the root of this project for license details.
44
'''
5+
from jinja2 import Environment
6+
57
from flatdata.generator.tree.nodes.archive import Archive
68
from flatdata.generator.tree.nodes.node import Node
79
from flatdata.generator.tree.nodes.resources import Instance, Vector, Multivector, RawData
@@ -14,13 +16,13 @@
1416
class GoGenerator(BaseGenerator):
1517
"""Flatdata to Go generator"""
1618

17-
def __init__(self):
19+
def __init__(self) -> None:
1820
BaseGenerator.__init__(self, "go/go.jinja2")
1921

20-
def supported_nodes(self):
22+
def supported_nodes(self) -> list[type]:
2123
return [Structure, Archive, Constant]
2224

23-
def _populate_environment(self, env):
25+
def _populate_environment(self, env: Environment) -> None:
2426
def _decorate_archive_type(value):
2527
assert isinstance(value, Node)
2628
return value.name
@@ -70,7 +72,7 @@ def to_initializer(resource, tree):
7072
for t in resource.referenced_structures]
7173
))
7274
if isinstance(resource, ArchiveResource):
73-
return _decorate_archive_type(resource.children[0].node)
75+
return _decorate_archive_type(resource.children[0].node) # type: ignore[attr-defined] # child is an ArchiveReference which has .node
7476
if isinstance(resource, RawData):
7577
return "None"
7678
raise ValueError("Unknown resource type: %s" % (resource.__class__))

flatdata-generator/flatdata/generator/generators/python.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Copyright (c) 2017 HERE Europe B.V.
33
See the LICENSE file in the root of this project for license details.
44
'''
5+
from jinja2 import Environment
6+
57
from flatdata.generator.tree.nodes.resources import Instance, Vector, Multivector, RawData
68
from flatdata.generator.tree.nodes.resources.archive import Archive as ArchiveResource
79
from flatdata.generator.tree.nodes.trivial import Structure
@@ -13,13 +15,13 @@
1315
class PythonGenerator(BaseGenerator):
1416
"""Flatdata to Python generator"""
1517

16-
def __init__(self):
18+
def __init__(self) -> None:
1719
BaseGenerator.__init__(self, "py/python.jinja2")
1820

19-
def supported_nodes(self):
21+
def supported_nodes(self) -> list[type]:
2022
return [Structure, Archive]
2123

22-
def _populate_environment(self, env):
24+
def _populate_environment(self, env: Environment) -> None:
2325
def _decorate_archive_type(tree, value):
2426
assert isinstance(value, Node)
2527
return tree.namespace_path(value, "_") + "_" + value.name
@@ -54,7 +56,7 @@ def to_initializer(resource, tree):
5456
','.join([_decorate_archive_type(tree, t.node) for t in
5557
resource.referenced_structures]))
5658
if isinstance(resource, ArchiveResource):
57-
return _decorate_archive_type(tree, resource.children[0].node)
59+
return _decorate_archive_type(tree, resource.children[0].node) # type: ignore[attr-defined] # child is an ArchiveReference which has .node
5860
if isinstance(resource, RawData):
5961
return "None"
6062
raise ValueError("Unknown resource type: %s" % (resource.__class__))

flatdata-generator/flatdata/generator/generators/rust.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
'''
55
import re
66

7+
from jinja2 import Environment
8+
79
from flatdata.generator.tree.nodes.resources import (Vector, Multivector, Instance, RawData, BoundResource,
810
Archive as ArchiveResource)
911
from flatdata.generator.tree.nodes.trivial import Structure, Constant, Enumeration
@@ -23,14 +25,14 @@ class RustGenerator(BaseGenerator):
2325
"pure", "ref", "return", "self", "sizeof", "static", "struct", "super", "trait", "true",
2426
"type", "typeof", "unsafe", "unsized", "use", "virtual", "where", "while", "yield"]
2527

26-
def __init__(self):
28+
def __init__(self) -> None:
2729
BaseGenerator.__init__(self, "rust/rust.jinja2")
2830

29-
def supported_nodes(self):
31+
def supported_nodes(self) -> list[type]:
3032
return [Structure, Archive, Constant, Enumeration]
3133

3234
@staticmethod
33-
def _format_numeric_literal(value):
35+
def _format_numeric_literal(value: str) -> str:
3436
try:
3537
# only apply this to integer values
3638
number = int(value)
@@ -40,7 +42,7 @@ def _format_numeric_literal(value):
4042
except ValueError:
4143
return value
4244

43-
def _populate_environment(self, env):
45+
def _populate_environment(self, env: Environment) -> None:
4446
def _camel_to_snake_case(expr):
4547
step1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', expr)
4648
return re.sub('([a-z0-9])(A-Z)', r'\1_\2', step1).lower()

0 commit comments

Comments
 (0)