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

1"""Specs: type metadata for configuration, requests and commands. 

2 

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. 

9 

10The package has two parts: the generator, which creates specs from the 

11sources, and the runtime, which loads them and works with them. 

12 

13Modules: 

14 

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``. 

30 

31Design 

32====== 

33 

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``). 

40 

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. 

48 

49Spec Data 

50========= 

51 

52``core.SpecData`` is the central data object produced by the generator and 

53consumed by the runtime. Its fields are: 

54 

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. 

63 

64Types 

65===== 

66 

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: 

70 

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. 

103 

104Type kinds, defined in ``core.c``: 

105 

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``. 

131 

132``EXPR`` marks unevaluated default expressions in the generator. ``COMMAND`` 

133and ``FUNCTION`` are declared, but the generator does not produce them. 

134 

135Example:: 

136 

137 import gws.spec.runtime 

138 

139 specs = gws.spec.runtime.create('/data/MANIFEST.json', read_cache=True, write_cache=True) 

140 

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 ) 

147 

148 cls = specs.get_class('gws.ext.object.layer', 'wms') 

149 desc = specs.command_descriptor(gws.CommandCategory.api, 'mapGetBox') 

150"""