Coverage for gws-app/gws/spec/__init__.py: 100%
0 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-05 13:35 +0200
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-05 13:35 +0200
1"""Specs: type metadata for configuration, requests and commands.
3Specs are metadata that describe the GWS configuration types, request and
4response types, extension objects and the command methods of actions. They are
5generated from the Python sources (classes, annotations and docstrings) and
6used at run time to read and validate configuration and request data, to look
7up extension classes and to dispatch commands. The client build and the
8documentation generators use the generated specs as well.
10The package has two parts: the generator, which creates specs from the
11sources, and the runtime, which loads them and works with them.
13Modules:
15- ``core``: shared data structures: the ``Type`` record, the type kinds ``c``,
16 the generator constants ``v``, ``Chunk``, ``SpecData`` and the error classes.
17- ``runtime``: creates the ``gws.SpecRuntime`` object (``runtime.create``),
18 which generates or loads the specs and provides reading, object and command
19 lookups and class loading.
20- ``reader``: reads and validates raw values (config dicts, request payloads)
21 against spec types. Used by ``runtime.Object.read``.
22- ``generator``: the spec generator, see the ``gws.spec.generator`` package.
23- ``spec``: command line tool that runs the generator on the developer system
24 and writes the specs, the TypeScript API and the configuration references
25 to an output directory.
26- ``types.pyinc``: the interfaces ``gws.SpecRuntime``,
27 ``gws.ApplicationManifest``, ``gws.ExtObjectDescriptor``,
28 ``gws.ExtCommandDescriptor``, ``gws.SpecReadOption`` and
29 ``gws.CommandCategory``, included into ``gws/__init__.py``.
31Design
32======
34The generator parses the Python sources of the application and its plugins
35into a dictionary of ``core.Type`` records keyed by uid. It then resolves
36aliases, evaluates defaults, synthesizes variant types for ``gws.ext`` objects
37and extracts the types the server needs at run time. The result is a
38``core.SpecData`` object, which can be cached as JSON and loaded again
39(``generator.main.to_path``, ``generator.main.from_path``).
41The runtime wraps a ``SpecData`` object. ``read`` validates a value against a
42type using a ``reader.Reader`` and returns the parsed value. ``get_class``
43resolves a class reference (a class, a class name or a ``gws.ext`` name) and
44imports the defining module on demand. ``command_descriptor`` maps a command
45category and name to the action method that handles it. Commands registered
46in the ``raw`` category are found under any category. Object and command
47descriptors are cached in the runtime object.
49Spec Data
50=========
52``core.SpecData`` is the central data object produced by the generator and
53consumed by the runtime. Its fields are:
55- ``meta``: build-time metadata: the application version, the manifest path
56 and the parsed manifest.
57- ``chunks``: source code chunks (the core packages and each plugin) with
58 their source files grouped by kind.
59- ``serverTypes``: all types the server needs at run time: configuration
60 types, request and response types, ext objects and command methods.
61- ``strings``: documentation strings keyed by language code (e.g. ``'en'``,
62 ``'de'``) and then by type uid.
64Types
65=====
67Each entry in ``serverTypes`` is a ``core.Type`` instance. The ``c`` field
68(a ``core.TypeKind`` string) determines the kind of the type and which other
69fields are populated. The fields are:
71- ``c``: type kind, see below.
72- ``uid``: unique identifier, used as the key throughout the spec.
73- ``name``: qualified name of named types, e.g. classes and properties.
74- ``ident``: source code identifier, used in docs.
75- ``constValue``: value of a ``CONSTANT``.
76- ``defaultExpression``: unevaluated default (a constant or enum reference),
77 evaluated by the normalizer.
78- ``defaultValue``: literal default value.
79- ``doc``: docstring from the source.
80- ``title``: documentation title.
81- ``enumDocs``: for ``ENUM``, a ``{member name: docstring}`` dict.
82- ``enumValues``: for ``ENUM``, a ``{member name: value}`` dict.
83- ``extName``: ``gws.ext`` name, set for extension types and commands.
84- ``hasDefault``: ``True`` when a default exists.
85- ``isConfig``: ``True`` for types reachable from the application ``Config``.
86- ``literalValues``: for ``LITERAL``, the list of allowed values.
87- ``modName``, ``modPath``: module that defines the type.
88- ``pos``: source position (``path:line``).
89- ``tArg``: for ``METHOD``, uid of the last (request) argument.
90- ``tArgs``: for ``METHOD``, uids of the arguments in order.
91- ``tItem``: for ``LIST`` and ``SET``, uid of the element type.
92- ``tItems``: for ``UNION``, ``TUPLE`` and ``CALLABLE``, uids of the member types.
93- ``tKey``, ``tValue``: for ``DICT``, uids of the key and value types.
94- ``tMembers``: for ``VARIANT``, a ``{tag: uid}`` dict of members.
95- ``tModule``: uid of the module type that contains this type.
96- ``tOwner``: for ``PROPERTY`` and ``METHOD``, uid of the owning class.
97- ``tProperties``: for ``CLASS``, a ``{name: uid}`` dict of properties,
98 including inherited ones.
99- ``tReturn``: for ``METHOD``, uid of the return type.
100- ``tSupers``: for ``CLASS``, uids of the base classes.
101- ``tTarget``: for ``TYPE``, ``EXT`` and ``OPTIONAL``, uid of the target type.
102- ``tValue``: for ``PROPERTY``, uid of the value type.
104Type kinds, defined in ``core.c``:
106- ``ATOM``: built-in type: ``any``, ``bool``, ``bytes``, ``float``, ``int``,
107 ``str`` and a few other builtins.
108- ``CALLABLE``: callable. Uses ``tItems``.
109- ``CLASS``: class, e.g. config, props, request and response objects. Uses
110 ``tProperties``, ``tSupers``.
111- ``CONSTANT``: module-level constant. Uses ``constValue``.
112- ``DICT``: ``dict[K, V]``. Uses ``tKey``, ``tValue``.
113- ``ENUM``: ``Enum`` subclass. Uses ``enumValues``, ``enumDocs``.
114- ``EXT``: a ``gws.ext`` name pointing to a class. Uses ``tTarget``, ``extName``.
115- ``LIST``: ``list[T]``. Uses ``tItem``.
116- ``LITERAL``: ``Literal[v1, v2, ...]``. Uses ``literalValues``.
117- ``METHOD``: a method. Command methods have ``extName`` set to
118 ``gws.ext.command.<category>.<name>``. Uses ``tArg``, ``tArgs``,
119 ``tReturn``, ``tOwner``.
120- ``MODULE``: Python module.
121- ``NONE``: the ``None`` type.
122- ``OPTIONAL``: ``Optional[T]``. Uses ``tTarget``.
123- ``PROPERTY``: a property of a ``CLASS``. Uses ``tOwner``, ``tValue``.
124- ``SET``: ``set[T]``. Uses ``tItem``.
125- ``TUPLE``: ``tuple[T, ...]``. Uses ``tItems``.
126- ``TYPE``: type alias (``TypeAlias``). Uses ``tTarget``.
127- ``UNDEFINED``: a type name that could not be resolved.
128- ``UNION``: ``Union[T1, T2, ...]`` or ``T1 | T2``. Uses ``tItems``.
129- ``VARIANT``: union of the ``gws.ext`` classes of one category, discriminated
130 by the ``type`` property. Uses ``tMembers``.
132``EXPR`` marks unevaluated default expressions in the generator. ``COMMAND``
133and ``FUNCTION`` are declared, but the generator does not produce them.
135Example::
137 import gws.spec.runtime
139 specs = gws.spec.runtime.create('/data/MANIFEST.json', read_cache=True, write_cache=True)
141 cfg = specs.read(
142 {'type': 'wms', 'provider': {'url': 'https://example.com/wms'}},
143 'gws.ext.config.layer',
144 path='/data/config.json',
145 options={gws.SpecReadOption.verboseErrors},
146 )
148 cls = specs.get_class('gws.ext.object.layer', 'wms')
149 desc = specs.command_descriptor(gws.CommandCategory.api, 'mapGetBox')
150"""