gws.spec¶
Specs: type metadata for configuration, requests and commands.
Specs are metadata that describe the GWS configuration types, request and response types, extension objects and the command methods of actions. They are generated from the Python sources (classes, annotations and docstrings) and used at run time to read and validate configuration and request data, to look up extension classes and to dispatch commands. The client build and the documentation generators use the generated specs as well.
The package has two parts: the generator, which creates specs from the sources, and the runtime, which loads them and works with them.
Modules:
core: shared data structures: theTyperecord, the type kindsc, the generator constantsv,Chunk,SpecDataand the error classes.runtime: creates thegws.SpecRuntimeobject (runtime.create), which generates or loads the specs and provides reading, object and command lookups and class loading.reader: reads and validates raw values (config dicts, request payloads) against spec types. Used byruntime.Object.read.generator: the spec generator, see thegws.spec.generatorpackage.spec: command line tool that runs the generator on the developer system and writes the specs, the TypeScript API and the configuration references to an output directory.types.pyinc: the interfacesgws.SpecRuntime,gws.ApplicationManifest,gws.ExtObjectDescriptor,gws.ExtCommandDescriptor,gws.SpecReadOptionandgws.CommandCategory, included intogws/__init__.py.
Design¶
The generator parses the Python sources of the application and its plugins
into a dictionary of core.Type records keyed by uid. It then resolves
aliases, evaluates defaults, synthesizes variant types for gws.ext objects
and extracts the types the server needs at run time. The result is a
core.SpecData object, which can be cached as JSON and loaded again
(generator.main.to_path, generator.main.from_path).
The runtime wraps a SpecData object. read validates a value against a
type using a reader.Reader and returns the parsed value. get_class
resolves a class reference (a class, a class name or a gws.ext name) and
imports the defining module on demand. command_descriptor maps a command
category and name to the action method that handles it. Commands registered
in the raw category are found under any category. Object and command
descriptors are cached in the runtime object.
Spec Data¶
core.SpecData is the central data object produced by the generator and
consumed by the runtime. Its fields are:
meta: build-time metadata: the application version, the manifest path and the parsed manifest.chunks: source code chunks (the core packages and each plugin) with their source files grouped by kind.serverTypes: all types the server needs at run time: configuration types, request and response types, ext objects and command methods.strings: documentation strings keyed by language code (e.g.'en','de') and then by type uid.
Types¶
Each entry in serverTypes is a core.Type instance. The c field
(a core.TypeKind string) determines the kind of the type and which other
fields are populated. The fields are:
c: type kind, see below.uid: unique identifier, used as the key throughout the spec.name: qualified name of named types, e.g. classes and properties.ident: source code identifier, used in docs.constValue: value of aCONSTANT.defaultExpression: unevaluated default (a constant or enum reference), evaluated by the normalizer.defaultValue: literal default value.doc: docstring from the source.title: documentation title.enumDocs: forENUM, a{member name: docstring}dict.enumValues: forENUM, a{member name: value}dict.extName:gws.extname, set for extension types and commands.hasDefault:Truewhen a default exists.isConfig:Truefor types reachable from the applicationConfig.literalValues: forLITERAL, the list of allowed values.modName,modPath: module that defines the type.pos: source position (path:line).tArg: forMETHOD, uid of the last (request) argument.tArgs: forMETHOD, uids of the arguments in order.tItem: forLISTandSET, uid of the element type.tItems: forUNION,TUPLEandCALLABLE, uids of the member types.tKey,tValue: forDICT, uids of the key and value types.tMembers: forVARIANT, a{tag: uid}dict of members.tModule: uid of the module type that contains this type.tOwner: forPROPERTYandMETHOD, uid of the owning class.tProperties: forCLASS, a{name: uid}dict of properties, including inherited ones.tReturn: forMETHOD, uid of the return type.tSupers: forCLASS, uids of the base classes.tTarget: forTYPE,EXTandOPTIONAL, uid of the target type.tValue: forPROPERTY, uid of the value type.
Type kinds, defined in core.c:
ATOM: built-in type:any,bool,bytes,float,int,strand a few other builtins.CALLABLE: callable. UsestItems.CLASS: class, e.g. config, props, request and response objects. UsestProperties,tSupers.CONSTANT: module-level constant. UsesconstValue.DICT:dict[K, V]. UsestKey,tValue.ENUM:Enumsubclass. UsesenumValues,enumDocs.EXT: agws.extname pointing to a class. UsestTarget,extName.LIST:list[T]. UsestItem.LITERAL:Literal[v1, v2, ...]. UsesliteralValues.METHOD: a method. Command methods haveextNameset togws.ext.command.<category>.<name>. UsestArg,tArgs,tReturn,tOwner.MODULE: Python module.NONE: theNonetype.OPTIONAL:Optional[T]. UsestTarget.PROPERTY: a property of aCLASS. UsestOwner,tValue.SET:set[T]. UsestItem.TUPLE:tuple[T, ...]. UsestItems.TYPE: type alias (TypeAlias). UsestTarget.UNDEFINED: a type name that could not be resolved.UNION:Union[T1, T2, ...]orT1 | T2. UsestItems.VARIANT: union of thegws.extclasses of one category, discriminated by thetypeproperty. UsestMembers.
EXPR marks unevaluated default expressions in the generator. COMMAND
and FUNCTION are declared, but the generator does not produce them.
Example:
import gws.spec.runtime
specs = gws.spec.runtime.create('/data/MANIFEST.json', read_cache=True, write_cache=True)
cfg = specs.read(
{'type': 'wms', 'provider': {'url': 'https://example.com/wms'}},
'gws.ext.config.layer',
path='/data/config.json',
options={gws.SpecReadOption.verboseErrors},
)
cls = specs.get_class('gws.ext.object.layer', 'wms')
desc = specs.command_descriptor(gws.CommandCategory.api, 'mapGetBox')
Source code: gws.spec