Coverage for gws-app/gws/__init__.py: 99%
2083 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-23 20:06 +0200
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-23 20:06 +0200
1"""GBD WebSuite: basic types and interfaces.
3The ``gws`` package holds the types that all parts of GBD WebSuite share: the
4basic data containers, enums and type aliases, the error classes, the object
5tree interfaces, the base ``Config`` and ``Props`` classes, and the interfaces
6of all configurable objects (``gws.Layer``, ``gws.Map``, ``gws.Model``,
7``gws.Grabber``, ``gws.Project``, ``gws.Application`` and many more). Every GWS
8module imports it with ``import gws``.
10``gws/__init__.py`` is generated by ``app/_make_init.py`` from this file
11(``__init__.pyinc``). Each ``# @include`` line is replaced with the contents of
12a ``*.pyinc`` fragment, so the types defined in ``core/*.pyinc`` and in the
13``types.pyinc`` files of the other packages all end up in the ``gws``
14namespace. The package also re-exports these modules of ``gws.core`` under
15short names:
17- ``gws.u``: general utilities (``gws.core.util``),
18- ``gws.c``: constants (``gws.core.const``),
19- ``gws.log``: logging,
20- ``gws.debug``: debugging helpers,
21- ``gws.env``: environment variables,
23and ``gws.ext``, the decorators that register extension classes and command
24methods.
26Code base layout
27----------------
29- ``gws.core``: the lowest layer: basic types, the object tree, logging,
30 constants and general utilities.
31- ``gws.lib``: general purpose libraries (CRS, images, XML, networking, SVG,
32 styles and so on), independent of the GWS object tree.
33- ``gws.gis``: GIS functionality built on ``lib``: map rendering, zoom
34 levels, source layers and tile caches.
35- ``gws.base``: the base classes and managers of the configurable objects
36 (application, projects, maps, layers, models, actions, auth and others).
37- ``gws.plugin``: concrete implementations of the base classes (layer types,
38 auth providers, OWS services, templates, model fields and so on), each
39 registered with a ``gws.ext`` decorator.
40- ``gws.config``: configuration parsing and loading, which builds the object
41 tree from the configuration.
42- ``gws.spec``: the spec generator and runtime: type metadata used to read
43 configuration and requests and to find extension classes and commands.
44- ``gws.server``: configuration and control of the embedded servers (uWSGI,
45 NGINX, the spool server and the monitor).
46- ``gws.ext``: the extension decorators (``gws.ext.object.*``,
47 ``gws.ext.config.*``, ``gws.ext.props.*``, ``gws.ext.command.*``).
48 ``gws/ext/__init__.py`` is generated as well.
49- ``gws.test``: the test framework.
51The intended import hierarchy is ``core < lib < gis < base < plugin``: each
52layer imports only from the layers below it. ``config``, ``spec`` and
53``server`` import ``lib`` and each other, and ``base`` imports them. Nothing
54outside ``gws.plugin`` imports plugins; plugin classes are found through the
55specs and loaded on demand.
57Example::
59 import gws
60 import gws.base.layer
62 d = gws.Data(name='roads', crs='EPSG:3857')
63 d.name # 'roads'
64 d.title # None, missing attributes are None
65 gws.u.get({'a': {'b': 1}}, 'a.b') # 1
67 @gws.ext.config.layer('my')
68 class Config(gws.base.layer.Config):
69 pass
71 @gws.ext.object.layer('my')
72 class Object(gws.base.layer.Object):
73 def configure(self):
74 gws.log.info(f'configuring {self.uid}')
75"""
77from typing import (
78 TYPE_CHECKING,
79 TypeAlias,
80 cast,
81 Any,
82 Callable,
83 ContextManager,
84 Generator,
85 Iterable,
86 Iterator,
87 Literal,
88 Optional,
89 Protocol,
90 Union,
91)
93from collections.abc import (
94 Mapping,
95 Sequence,
96)
98import enum
99import datetime
101if TYPE_CHECKING:
102 import sqlalchemy
103 import numpy.typing
105# mypy: disable-error-code="empty-body"
108from . import ext
110from .core import (
111 log,
112 debug,
113 env,
114 const as c,
115 util as u,
116)
119################################################################################
120# /core/_data.pyinc
123# basic data type
125class Data:
126 """Basic data object.
128 This object can be instantiated by passing one or more ``dict`` or ``Data`` arguments
129 and/or keyword args. All keys and keywords become attributes of the object.
131 Accessing an undefined attribute returns ``None`` and no error is raised,
132 unless the attribute name starts with an underscore.
134 Example::
136 d = gws.Data({'a': 1}, b=2)
137 d.a # 1
138 d['b'] # 2
139 d.c # None
140 """
142 def __init__(self, *args, **kwargs):
143 """Create the object from dicts, ``Data`` objects and keyword args.
145 Args:
146 *args: Dicts, Mappings or ``Data`` objects. Other values are ignored.
147 **kwargs: Keyword args.
148 """
149 self.update(*args, **kwargs)
151 def __repr__(self):
152 """Return the ``repr`` of the attributes dict."""
153 return repr(vars(self))
155 def __getitem__(self, key):
156 """Return an attribute value or ``None`` if it is undefined."""
157 return vars(self).get(key)
159 def __setitem__(self, key, value):
160 """Set an attribute value."""
161 vars(self)[key] = value
163 # def __getattr__(self, attr):
164 # if attr.startswith('_'):
165 # # do not use None fallback for special props
166 # raise AttributeError(attr)
167 # return None
169 def get(self, key, default=None):
170 """Get an attribute value.
172 Args:
173 key: Attribute name.
174 default: Default value, returned if the attribute is undefined.
176 Returns:
177 The attribute value or the default.
178 """
179 return vars(self).get(key, default)
181 def setdefault(self, key, val):
182 """Set an attribute value if it is not already set.
184 Args:
185 key: Attribute name.
186 val: Attribute value.
188 Returns:
189 The current attribute value, existing or new.
190 """
191 return vars(self).setdefault(key, val)
193 def set(self, key, val):
194 """Set an attribute value.
196 Args:
197 key: Attribute name.
198 val: Attribute value.
199 """
200 vars(self)[key] = val
202 def update(self, *args, **kwargs):
203 """Update the object with keys and values from args and keywords.
205 Later values override earlier ones, keywords override args.
207 Args:
208 *args: Dicts, Mappings or ``Data`` objects. Other values are ignored.
209 **kwargs: Keyword args.
210 """
212 d = {}
213 for a in args:
214 if isinstance(a, Mapping):
215 d.update(a)
216 elif isinstance(a, Data):
217 d.update(vars(a))
218 d.update(kwargs)
219 vars(self).update(d)
222# getattr needs to be defined out of class, otherwise the type checker will accept any attribute
224def _data_getattr(self, attr):
225 """Return ``None`` for undefined attributes, raise ``AttributeError`` for names starting with an underscore."""
226 if attr.startswith('_'):
227 # do not use None fallback for special props
228 raise AttributeError(attr)
229 return None
232setattr(Data, '__getattr__', _data_getattr)
235def is_data_object(x):
236 """Check if the argument is a ``Data`` object.
238 Args:
239 x: A value.
241 Returns:
242 ``True`` if the value is a ``Data`` object.
243 """
244 return isinstance(x, Data)
247def to_data_object(x) -> 'Data':
248 """Convert a value to a ``Data`` object.
250 If the argument is already a ``Data`` object, simply return it.
251 If the argument is ``None``, an empty object is returned.
253 Args:
254 x: A ``Data`` object, a Mapping or ``None``.
256 Returns:
257 A ``Data`` object.
259 Raises:
260 ValueError: If the value cannot be converted.
261 """
263 if is_data_object(x):
264 return x
265 if isinstance(x, Mapping):
266 return Data(x)
267 if x is None:
268 return Data()
269 raise ValueError(f'cannot convert {x!r} to Data')
270################################################################################
274u.is_data_object = is_data_object
275u.to_data_object = to_data_object
279################################################################################
280# /core/_basic.pyinc
283class Enum(enum.Enum):
284 """Enumeration type.
286 Despite being declared as extending ``Enum`` (for IDE support), this class is actually just a simple object
287 and intended to be used as a collection of attributes. It doesn't provide any ``Enum``-specific utilities.
289 The rationale behind this is that we need ``Enum`` members (e.g. ``Color.RED``) to be scalars,
290 and not complex objects as in the standard ``Enum``.
291 """
292 pass
295# hack to make Enum a simple object
296globals()['Enum'] = type('Enum', (), {})
298Extent: TypeAlias = tuple[float, float, float, float]
299"""An array of 4 elements representing extent coordinates ``[min-x, min-y, max-x, max-y]``."""
301Point: TypeAlias = tuple[float, float]
302"""Point coordinates ``[x, y]``."""
304Size: TypeAlias = tuple[float, float]
305"""Size ``[width, height]``."""
308class Origin(Enum):
309 """Grid origin."""
311 nw = 'nw'
312 """North-west."""
313 sw = 'sw'
314 """South-west."""
315 ne = 'ne'
316 """North-east."""
317 se = 'se'
318 """South-east."""
319 lt = 'nw'
320 """Left top."""
321 lb = 'sw'
322 """Left bottom."""
323 rt = 'ne'
324 """Right top."""
325 rb = 'se'
326 """Right bottom."""
329FilePath: TypeAlias = str
330"""File path on the server."""
332DirPath: TypeAlias = str
333"""Directory path on the server."""
335Duration: TypeAlias = str
336"""Duration like ``1w 2d 3h 4m 5s`` or an integer number of seconds."""
338Color: TypeAlias = str
339"""CSS color name."""
341Regex: TypeAlias = str
342"""Regular expression, as used in Python."""
344FormatStr: TypeAlias = str
345"""Format string as used in Python."""
347DateStr: TypeAlias = str
348"""ISO date string like ``2019-01-30``."""
350DateTimeStr: TypeAlias = str
351"""ISO datetime string like ``2019-01-30 01:02:03``."""
353Url: TypeAlias = str
354"""URL."""
356ClassRef: TypeAlias = type | str
357"""Class reference: a type, an ``ext`` class or name like ``gws.ext.object.layer``, or a full class name."""
360class Config(Data):
361 """Object configuration."""
363 uid: str = ''
364 """Unique ID."""
367class Props(Data):
368 """Object properties."""
370 uid: str = ''
371 """Unique ID."""
374class Request(Data):
375 """Command request."""
377 projectUid: Optional[str]
378 """Unique ID of the project."""
379 localeUid: Optional[str]
380 """Locale ID for this request."""
383class EmptyRequest(Data):
384 """Empty command request."""
386 pass
389class ResponseError(Data):
390 """Response error."""
392 code: Optional[int]
393 """Error code."""
394 info: Optional[str]
395 """Information about the error."""
398class Response(Data):
399 """Command response."""
401 error: Optional[ResponseError]
402 """Response error."""
403 status: int
404 """Response status or exit code."""
407class ContentResponse(Response):
408 """Web response with literal content."""
410 content: bytes | str
411 """Response content."""
412 contentFilename: str
413 """File name for the attachment. If provided, the content is served as an attachment."""
414 contentPath: str
415 """Local path with the content."""
416 mimeType: str
417 """Response mime type."""
418 headers: dict
419 """Additional headers."""
422class RedirectResponse(Response):
423 """Web redirect response."""
425 location: str
426 """Redirect URL."""
427 headers: dict
428 """Additional headers."""
431class AttributeType(Enum):
432 """Feature attribute type."""
434 bool = 'bool'
435 """Boolean value."""
436 bytes = 'bytes'
437 """Binary data."""
438 date = 'date'
439 """Date value."""
440 datetime = 'datetime'
441 """Date and time value."""
442 feature = 'feature'
443 """Feature reference."""
444 featurelist = 'featurelist'
445 """List of features."""
446 file = 'file'
447 """File reference."""
448 float = 'float'
449 """Floating-point number."""
450 floatlist = 'floatlist'
451 """List of floating-point numbers."""
452 geometry = 'geometry'
453 """Geometry reference."""
454 int = 'int'
455 """Integer number."""
456 intlist = 'intlist'
457 """List of integer numbers."""
458 str = 'str'
459 """String value."""
460 strlist = 'strlist'
461 """List of strings."""
462 time = 'time'
463 """Time value."""
466class GeometryType(Enum):
467 """Feature geometry type.
469 OGC and SQL/MM geometry types.
471 References:
472 - OGC 06-103r4 (https://www.ogc.org/standards/sfa)
473 - https://postgis.net/docs/manual-3.3/using_postgis_dbmanagement.html
474 """
476 geometry = 'geometry'
477 """Any geometry."""
479 point = 'point'
480 """Point."""
481 curve = 'curve'
482 """Curve."""
483 surface = 'surface'
484 """Surface."""
486 geometrycollection = 'geometrycollection'
487 """Collection of geometries."""
489 linestring = 'linestring'
490 """Line string."""
491 line = 'line'
492 """Line."""
493 linearring = 'linearring'
494 """Linear ring."""
496 polygon = 'polygon'
497 """Polygon."""
498 triangle = 'triangle'
499 """Triangle."""
501 polyhedralsurface = 'polyhedralsurface'
502 """Polyhedral surface."""
503 tin = 'tin'
504 """Triangulated irregular network."""
506 multipoint = 'multipoint'
507 """Collection of points."""
508 multicurve = 'multicurve'
509 """Collection of curves."""
510 multilinestring = 'multilinestring'
511 """Collection of line strings."""
512 multipolygon = 'multipolygon'
513 """Collection of polygons."""
514 multisurface = 'multisurface'
515 """Collection of surfaces."""
517 circularstring = 'circularstring'
518 """Circular arc string."""
519 compoundcurve = 'compoundcurve'
520 """Curve composed of line strings and circular strings."""
521 curvepolygon = 'curvepolygon'
522 """Polygon with curved rings."""
525class CliParams(Data):
526 """Parameters of a command line command."""
527 pass
528################################################################################
531################################################################################
532# /core/_access.pyinc
535Acl: TypeAlias = list[tuple[int, str]]
536"""Access control list.
538A list of tuples ``(ACL bit, role-name)`` where ``ACL bit`` is ``1`` if the access is allowed and ``0`` otherwise.
539"""
541AclStr: TypeAlias = str
542"""Comma-separated rules ``allow <role>`` or ``deny <role>``."""
545class Access(Enum):
546 """Access mode."""
548 read = 'read'
549 """Permission to read the object."""
550 write = 'write'
551 """Permission to change the object."""
552 create = 'create'
553 """Permission to create new objects."""
554 delete = 'delete'
555 """Permission to delete objects."""
558class PermissionsConfig(Config):
559 """Access rules per operation."""
561 all: Optional[AclStr]
562 """Rules for read, write, create and delete at once."""
563 read: Optional[AclStr]
564 """Rules for reading or using the object."""
565 write: Optional[AclStr]
566 """Rules for changing existing objects."""
567 create: Optional[AclStr]
568 """Rules for creating new objects."""
569 delete: Optional[AclStr]
570 """Rules for deleting objects."""
571 edit: Optional[AclStr]
572 """Rules for write, create and delete at once."""
575class ConfigWithAccess(Config):
576 """Basic config with permissions."""
578 access: Optional[AclStr]
579 """Permission to read or use the object."""
580 permissions: Optional[PermissionsConfig]
581 """Access rules per operation."""
582################################################################################
585################################################################################
586# /core/_error.pyinc
589class Error(Exception):
590 """Generic GWS error.
592 Its ``repr`` is the first line of ``log.exception_backtrace``: the class name, the message and the location.
593 """
594 def __repr__(self):
595 return log.exception_backtrace(self)[0]
598class ConfigurationError(Error):
599 """GWS configuration error."""
600 pass
603class NotFoundError(Error):
604 """Generic 'object not found' error."""
605 pass
608class ForbiddenError(Error):
609 """Generic 'forbidden' error."""
610 pass
613class AuthenticationError(ForbiddenError):
614 """Credentials are missing, wrong or expired."""
615 pass
618class BadRequestError(Error):
619 """Generic 'bad request' error."""
620 pass
623class TooManyRequestsError(Error):
624 """Generic 'too many requests' error."""
626 retryAfter: int = 0
627 """Time in seconds after which the request can be repeated."""
630class ResponseTooLargeError(Error):
631 """Generic error when a response is too large."""
632 pass
635class ExternalServiceError(Error):
636 """Generic error when an external service fails."""
637 pass
640LockBusyError = u.LockBusyError
641"""Raised when a server lock cannot be acquired within the timeout."""
642################################################################################
646################################################################################
647# /spec/types.pyinc
650class ApplicationManifestPlugin(Data):
651 """Custom plugin entry in the application manifest."""
653 path: DirPath
654 """Path to the plugin directory; relative paths are resolved against the manifest location."""
656 name: str = ''
657 """Plugin name. When omitted, the directory name is used."""
660class ApplicationManifest(Data):
661 """Application manifest, read from a ``MANIFEST.json`` file.
663 The manifest is JSON; lines starting with ``//`` or ``#`` are ignored.
664 """
666 uid: Optional[str]
667 """Application identifier."""
668 release: Optional[str]
669 """Application release version."""
670 excludePlugins: Optional[list[str]]
671 """Names of the core plugins that should be deactivated."""
672 plugins: Optional[list[ApplicationManifestPlugin]]
673 """Custom plugins."""
674 locales: list[str]
675 """Locale names supported by this application."""
676 tsConfig: str
677 """Path to ``tsconfig.json``."""
678 withFallbackConfig: bool = False
679 """Use a minimal fallback configuration."""
680 withStrictConfig: bool = False
681 """Stop the application upon a configuration error."""
684class ExtObjectDescriptor(Data):
685 """Extension object descriptor."""
687 extName: str
688 """Full extension name like ``gws.ext.object.layer.wms``."""
689 extType: str
690 """Extension type like ``wms``."""
691 classPtr: type
692 """Class object."""
693 ident: str
694 """Identifier."""
695 modName: str
696 """Name of the module that contains the class."""
697 modPath: str
698 """Path to the module that contains the class."""
701class ExtCommandDescriptor(Data):
702 """Command descriptor, describes the action method that handles a command."""
704 extName: str
705 """Full command name like ``gws.ext.command.api.mapGetBox``."""
706 extType: str
707 """Command name like ``mapGetBox``."""
708 extCommandCategory: 'CommandCategory'
709 """Command category."""
710 methodName: str
711 """Name of the action method that handles the command."""
712 methodPtr: Callable
713 """Command method. Not set by ``SpecRuntime.command_descriptor``."""
714 request: 'Request'
715 """Request sent to the command. Not set by ``SpecRuntime.command_descriptor``."""
716 tArg: str
717 """Type uid of the command argument (the request)."""
718 tOwner: str
719 """Type uid of the action class that owns the command."""
720 owner: ExtObjectDescriptor
721 """Object descriptor of the action class that owns the command."""
724class SpecReadOption(Enum):
725 """Options for reading values with ``SpecRuntime.read``."""
727 acceptExtraProps = 'acceptExtraProps'
728 """Accept extra object properties."""
729 allowMissing = 'allowMissing'
730 """Allow otherwise required properties to be missing."""
731 caseInsensitive = 'caseInsensitive'
732 """Case insensitive search for properties."""
733 convertValues = 'convertValues'
734 """Try to convert values to specified types."""
735 ignoreExtraProps = 'ignoreExtraProps'
736 """Silently ignore extra object properties."""
737 verboseErrors = 'verboseErrors'
738 """Add the value and the location of an error to ``ReadError`` exceptions."""
741class CommandCategory(Enum):
742 """Command category."""
744 api = 'api'
745 """API command."""
746 cli = 'cli'
747 """CLI command."""
748 get = 'get'
749 """Web GET command."""
750 post = 'post'
751 """Web POST command."""
752 raw = 'raw'
753 """Raw Web command without preprocessing."""
756class SpecRuntime:
757 """Spec runtime.
759 Provides access to the generated specs: reading and validating values,
760 looking up extension objects and commands, and loading classes.
761 """
763 version: str
764 """Application version."""
765 manifest: ApplicationManifest
766 """Application manifest."""
767 appBundlePaths: list[str]
768 """Paths of the client bundles of all chunks."""
770 def read(self, value, type_name: str, path: str = '', options: set[SpecReadOption] = None):
771 """Read and validate a raw value according to a spec type.
773 Args:
774 value: Raw value from a config or a request.
775 type_name: Type uid or extension name.
776 path: Path of the config file, used to resolve relative paths and in error messages.
777 options: Read options.
779 Returns:
780 The parsed value. Objects are returned as ``gws.Data``.
782 Raises:
783 ``gws.spec.core.ReadError``: If the value does not match the type.
784 """
786 def object_descriptor(self, type_name: str) -> Optional[ExtObjectDescriptor]:
787 """Get an object descriptor.
789 Args:
790 type_name: Type uid or extension name.
792 Returns:
793 A descriptor or ``None`` if the type is not found.
794 """
796 def command_descriptor(self, command_category: CommandCategory, command_name: str) -> Optional[ExtCommandDescriptor]:
797 """Get a command descriptor.
799 Args:
800 command_category: Command category.
801 command_name: Command name.
803 Returns:
804 A descriptor or ``None`` if the command is not found.
805 """
807 def register_object(self, ext_name: ClassRef, obj_type: str, cls: type):
808 """Register an extension class at run time.
810 The class gets the ``extName`` and ``extType`` attributes.
812 Args:
813 ext_name: Extension category, like ``gws.ext.object.layer``.
814 obj_type: Extension type, like ``wms``.
815 cls: Class to register.
817 Raises:
818 ``gws.spec.core.Error``: If the class reference is invalid.
819 """
821 def get_class(self, classref: ClassRef, ext_type: Optional[str] = None) -> Optional[type]:
822 """Get a class object for a class reference.
824 The module defining the class is imported on demand.
826 Args:
827 classref: Class reference: a class, a class name or an extension name.
828 ext_type: Extension type, used when ``classref`` is an extension category name.
829 Defaults to ``default``.
831 Returns:
832 A class or ``None`` if the reference is not found.
834 Raises:
835 ``gws.spec.core.LoadError``: If the module cannot be imported.
836 """
838 def parse_classref(self, classref: ClassRef) -> tuple[Optional[type], str, str]:
839 """Parse a class reference.
841 Args:
842 classref: Class reference.
844 Returns:
845 A tuple ``(class object, class name, extension name)``, where only one element is set.
847 Raises:
848 ``gws.spec.core.Error``: If the class reference is invalid.
849 """
851 def get_config_types(self, lang: str) -> list[dict]:
852 """Get the configuration types as dictionaries.
854 Docstrings, titles and enum docs are taken from the strings in the given language.
856 Args:
857 lang: Language code.
859 Returns:
860 A list of type dictionaries.
861 """
862################################################################################
866################################################################################
867# /core/_tree.pyinc
870class Object:
871 """Basic GWS object.
873 An object has permissions and can provide properties for the client.
874 """
876 permissions: dict[Access, Acl]
877 """Mapping from an access mode to a list of ACL tuples."""
879 def props(self, user: 'User') -> Props:
880 """Generate a ``Props`` struct for this object.
882 Do not call this method directly, use ``gws.props_of`` instead, which also checks permissions.
884 Args:
885 user: The user for which the props should be generated.
887 Returns:
888 A ``Props`` object or a dict. Nested objects are converted to props as well.
889 """
891 def __init__(self):
892 self.permissions = {}
895from .core import tree_impl
897setattr(tree_impl, 'Access', Access)
898setattr(tree_impl, 'Error', Error)
899setattr(tree_impl, 'Data', Data)
900setattr(tree_impl, 'Props', Props)
901setattr(tree_impl, 'Object', Object)
903Object.__repr__ = tree_impl.object_repr
906class Node(Object):
907 """GWS object tree node.
909 Nodes are created by the ``Root`` or by their parent node. Configuration hooks
910 (``pre_configure``, ``configure``, ``post_configure``) are invoked for every class in the MRO
911 that defines them, base classes first, so they do not need to call ``super()``.
912 """
914 extName: str
915 """Full extension name like ``gws.ext.object.layer.wms``."""
916 extType: str
917 """Extension type like ``wms``."""
919 config: Config
920 """Configuration for this object."""
921 root: 'Root'
922 """Root object."""
923 parent: 'Node'
924 """Parent object."""
925 children: list['Node']
926 """Child objects."""
927 uid: str
928 """Unique ID."""
930 def initialize(self, config):
931 """Initialize the node.
933 Store the configuration, set up the permissions, then run ``pre_configure`` and ``configure``.
935 Args:
936 config: Configuration.
937 """
938 return tree_impl.node_initialize(self, config)
940 def pre_configure(self):
941 """Pre-configuration hook.
943 Called before ``configure``, when the node is initialized.
944 """
946 def configure(self):
947 """Configuration hook.
949 Called when the node is initialized. Raising an exception here aborts the creation of the node.
950 """
952 def post_configure(self):
953 """Post-configuration hook.
955 Called after the whole object tree has been created.
956 """
958 def activate(self):
959 """Activation hook.
961 Called by ``Root.activate`` after the configuration has been loaded.
962 """
964 def create_child(self, classref: ClassRef, config: Config = None, **kwargs) -> Optional['Node']:
965 """Create a child object.
967 Args:
968 classref: Class reference.
969 config: Configuration.
970 **kwargs: Additional configuration properties.
972 Returns:
973 A newly created object or ``None`` if the object cannot be initialized.
974 """
975 return tree_impl.node_create_child(self, classref, config, **kwargs)
977 def create_child_if_configured(self, classref: ClassRef, config=None, **kwargs) -> Optional['Node']:
978 """Create a child object if the configuration is not None.
980 Args:
981 classref: Class reference.
982 config: Configuration.
983 **kwargs: Additional configuration properties.
985 Returns:
986 A newly created object or ``None`` if the configuration is ``None`` or the object cannot be initialized.
987 """
988 return tree_impl.node_create_child_if_configured(self, classref, config, **kwargs)
990 def create_children(self, classref: ClassRef, configs: list[Config], **kwargs) -> list['Node']:
991 """Create a list of child objects from a list of configurations.
993 Args:
994 classref: Class reference.
995 configs: List of configurations.
996 **kwargs: Additional configuration properties.
998 Returns:
999 A list of newly created objects.
1000 """
1001 return tree_impl.node_create_children(self, classref, configs, **kwargs)
1003 def cfg(self, key: str, default=None):
1004 """Fetch a configuration property.
1006 Args:
1007 key: Property key. If it contains dots, fetch nested properties.
1008 default: Default to return if the property is not found.
1010 Returns:
1011 A property value.
1012 """
1013 return tree_impl.node_cfg(self, key, default)
1015 def is_a(self, classref: ClassRef) -> bool:
1016 """Check if the node matches the class reference.
1018 Args:
1019 classref: Class reference.
1021 Returns:
1022 ``True`` if the node matches.
1023 """
1024 return tree_impl.is_a(self.root, self, classref)
1026 def find_all(self, classref: Optional[ClassRef] = None) -> list['Node']:
1027 """Find all direct children that match a specific class.
1029 Args:
1030 classref: Class reference. If omitted, all children are returned.
1032 Returns:
1033 A list of objects.
1034 """
1035 return tree_impl.node_find_all(self, classref)
1037 def find_first(self, classref: Optional[ClassRef] = None) -> Optional['Node']:
1038 """Find the first direct child that matches a specific class.
1040 Args:
1041 classref: Class reference. If omitted, the first child is returned.
1043 Returns:
1044 An object or ``None``.
1045 """
1046 return tree_impl.node_find_first(self, classref)
1048 def find_closest(self, classref: Optional[ClassRef] = None) -> Optional['Node']:
1049 """Find the closest node ancestor that matches a specific class.
1051 Args:
1052 classref: Class reference. If omitted, the parent is returned.
1054 Returns:
1055 An object or ``None``.
1056 """
1058 return tree_impl.node_find_closest(self, classref)
1060 def find_ancestors(self, classref: Optional[ClassRef] = None) -> list['Node']:
1061 """Find node ancestors that match a specific class.
1063 Args:
1064 classref: Class reference. If omitted, all ancestors are returned.
1066 Returns:
1067 A list of objects, from the parent upwards.
1068 """
1069 return tree_impl.node_find_ancestors(self, classref)
1071 def find_descendants(self, classref: Optional[ClassRef] = None) -> list['Node']:
1072 """Find node descendants that match a specific class.
1074 Args:
1075 classref: Class reference. If omitted, all descendants are returned.
1077 Returns:
1078 A list of objects in the depth-first order.
1079 """
1081 return tree_impl.node_find_descendants(self, classref)
1083 def enter_middleware(self, req: 'WebRequester') -> Optional['WebResponder']:
1084 """Begin middleware processing.
1086 Args:
1087 req: Requester object.
1089 Returns:
1090 A Responder object to end the request processing, or ``None`` to continue.
1091 """
1093 def exit_middleware(self, req: 'WebRequester', res: 'WebResponder'):
1094 """Finish middleware processing.
1096 Args:
1097 req: Requester object.
1098 res: Current responder object.
1099 """
1101 def periodic_task(self):
1102 """Periodic task hook.
1104 Called by the server monitor for nodes registered with ``register_periodic_task``.
1105 """
1108class Root:
1109 """Root node of the object tree."""
1111 app: 'Application'
1112 """Application object."""
1113 specs: 'SpecRuntime'
1114 """Specs runtime."""
1115 configErrors: list
1116 """List of configuration errors."""
1117 configWarnings: list
1118 """List of configuration warnings."""
1120 nodes: list['Node']
1121 """All nodes in the tree, in the order of creation."""
1122 uidMap: dict[str, 'Node']
1123 """Mapping from uids to nodes."""
1124 uidCount: int
1125 """Counter for generated uids."""
1126 configStack: list['Node']
1127 """Nodes being configured, from the outermost to the current one."""
1128 configPaths: list[str]
1129 """Paths of the configuration files."""
1131 def __init__(self, specs: 'SpecRuntime'):
1132 """Create an empty root.
1134 Args:
1135 specs: Specs runtime.
1136 """
1137 tree_impl.root_init(self, specs)
1139 def initialize(self, obj, config):
1140 """Initialize a node and record configuration errors.
1142 Args:
1143 obj: The node.
1144 config: Configuration.
1146 Returns:
1147 ``True`` if the node was initialized, ``False`` if it failed.
1148 """
1149 return tree_impl.root_initialize(self, obj, config)
1151 def post_initialize(self):
1152 """Run ``post_configure`` on all nodes, in the reverse order of creation.
1154 Errors are logged and recorded in ``configErrors``.
1155 """
1156 return tree_impl.root_post_initialize(self)
1158 def activate(self):
1159 """Run ``activate`` on all nodes."""
1160 return tree_impl.root_activate(self)
1162 def config_warning(self, message: str):
1163 """Register a configuration warning.
1165 The warning is logged immediately and reported again after the configuration is complete.
1166 The object stack is only available when called from ``configure`` or ``post_configure``.
1168 Args:
1169 message: Warning message.
1170 """
1171 return tree_impl.root_config_warning(self, message)
1173 def find_all(self, classref: Optional[ClassRef] = None) -> list['Node']:
1174 """Find all objects that match a specific class.
1176 Args:
1177 classref: Class reference.
1179 Returns:
1180 A list of objects.
1181 """
1182 return tree_impl.root_find_all(self, classref)
1184 def find_first(self, classref: Optional[ClassRef] = None) -> Optional['Node']:
1185 """Find the first object that matches a specific class.
1187 Args:
1188 classref: Class reference.
1190 Returns:
1191 An object or ``None``.
1192 """
1193 return tree_impl.root_find_first(self, classref)
1195 def get(self, uid: str = None, classref: Optional[ClassRef] = None) -> Optional['Node']:
1196 """Get an object by its unique ID.
1198 Args:
1199 uid: Object uid.
1200 classref: Class reference. If provided, ensures that the object matches the reference.
1202 Returns:
1203 An object or ``None``.
1204 """
1205 return tree_impl.root_get(self, uid, classref)
1207 def object_count(self) -> int:
1208 """Return the number of objects in the tree.
1210 Returns:
1211 The number of objects.
1212 """
1213 return tree_impl.root_object_count(self)
1215 def create(
1216 self,
1217 classref: ClassRef,
1218 parent: Optional['Node'] = None,
1219 config: Config = None,
1220 **kwargs,
1221 ) -> Optional['Node']:
1222 """Create an object.
1224 Args:
1225 classref: Class reference.
1226 parent: Parent object.
1227 config: Configuration.
1228 **kwargs: Additional configuration properties.
1230 Returns:
1231 A newly created object or ``None`` if the object cannot be initialized.
1232 """
1233 return tree_impl.root_create(self, classref, parent, config, **kwargs)
1235 def create_shared(self, classref: ClassRef, config: Config = None, **kwargs) -> Optional['Node']:
1236 """Create a shared object, attached directly to the root.
1238 If the config has no uid, it is computed from the class reference and the configuration.
1239 If an object with this uid already exists, it is returned instead of creating a new one.
1241 Args:
1242 classref: Class reference.
1243 config: Configuration.
1244 **kwargs: Additional configuration properties.
1246 Returns:
1247 A newly created object or ``None`` if the object cannot be initialized.
1248 """
1249 return tree_impl.root_create_shared(self, classref, config, **kwargs)
1251 def create_temporary(self, classref: ClassRef, config: Config = None, **kwargs) -> Optional['Node']:
1252 """Create a temporary object, not attached to the tree.
1254 Args:
1255 classref: Class reference.
1256 config: Configuration.
1257 **kwargs: Additional configuration properties.
1259 Returns:
1260 A newly created object or ``None`` if the object cannot be initialized.
1261 """
1262 return tree_impl.root_create_temporary(self, classref, config, **kwargs)
1264 def create_application(self, config: Config = None, **kwargs) -> 'Application':
1265 """Create the Application object.
1267 Args:
1268 config: Configuration.
1269 **kwargs: Additional configuration properties.
1271 Returns:
1272 The Application object.
1273 """
1274 return tree_impl.root_create_application(self, config, **kwargs)
1277def create_root(specs: 'SpecRuntime') -> Root:
1278 """Create a new root object.
1280 Args:
1281 specs: Specs runtime.
1283 Returns:
1284 The root object.
1285 """
1286 return Root(specs)
1289def save_root(root: Root, path: str = None) -> str:
1290 """Pickle the root object to a file.
1292 ``sys.path`` is pickled next to it, to ``<path>.syspath``, so that ``load_root`` can restore it.
1294 Args:
1295 root: The root object.
1296 path: File path. Defaults to ``config.pickle`` in the config directory.
1298 Returns:
1299 The file path.
1300 """
1301 return tree_impl.save_root(root, path)
1304def load_root(path: str = None) -> Root:
1305 """Load a pickled root object, activate it and make it the current root.
1307 ``sys.path`` is restored first, so that plugin modules can be imported.
1309 Args:
1310 path: File path. Defaults to ``config.pickle`` in the config directory.
1312 Returns:
1313 The root object.
1314 """
1315 return tree_impl.load_root(path)
1318def activate_root(root: Root) -> Root:
1319 """Activate the root object and make it the current root.
1321 Args:
1322 root: The root object.
1324 Returns:
1325 The root object.
1326 """
1327 return tree_impl.activate_root(root)
1330def deactivate_root():
1331 """Remove the current root."""
1332 return tree_impl.deactivate_root()
1335def get_root() -> Root:
1336 """Return the current root object.
1338 Returns:
1339 The root object set by ``activate_root`` or ``load_root``.
1341 Raises:
1342 Error: If there is no current root.
1343 """
1344 return tree_impl.get_root()
1347def props_of(obj: Object, user: 'User', *context) -> Optional['Props']:
1348 """Generate props for an object, if the user is allowed to use it.
1350 Nested objects the user cannot read are removed from the result.
1352 Args:
1353 obj: The object.
1354 user: The user.
1355 *context: Context objects for the permission check.
1357 Returns:
1358 A ``Props`` object, or ``None`` if the user cannot use the object.
1360 Raises:
1361 Error: If the object's ``props`` returns an invalid type.
1362 """
1363 return tree_impl.props_of(obj, user, *context)
1364################################################################################
1368################################################################################
1369# /lib/mapserver/types.pyinc
1372class MapServerLayerType(Enum):
1373 """MapServer layer type."""
1375 point = 'point'
1376 """Point layer."""
1377 line = 'line'
1378 """Line layer."""
1379 polygon = 'polygon'
1380 """Polygon layer."""
1381 raster = 'raster'
1382 """Raster layer."""
1384class MapServerLayerOptions(Data):
1385 """Options for a MapServer-based layer."""
1387 type: MapServerLayerType
1388 """Layer type."""
1389 path: str
1390 """Path to the data file, e.g. an image (layer DATA option)."""
1391 tileIndex: str
1392 """Path to the tile index SHP file."""
1393 crs: 'Crs'
1394 """Layer CRS."""
1395 connectionType: str
1396 """Type of connection, only ``postgres`` is supported."""
1397 connectionString: str
1398 """Connection string for the data source."""
1399 dataString: str
1400 """Layer DATA option, overrides ``path``."""
1401 style: 'StyleValues'
1402 """Style for the layer; only a part of the style values is supported."""
1403 processing: list[str]
1404 """Processing options for the layer."""
1405 transparentColor: str
1406 """Color to treat as transparent in the layer (OFFSITE)."""
1407 sldPath: str
1408 """Path to SLD file for styling the layer."""
1409 sldName: str
1410 """Name of an SLD NamedLayer to apply."""
1411################################################################################
1414################################################################################
1415# /lib/mime/types.pyinc
1418MimeType: TypeAlias = str
1419"""A MIME type or a file extension."""
1420################################################################################
1423################################################################################
1424# /lib/uom/types.pyinc
1427class Uom(Enum):
1428 """Unit of measure."""
1430 mi = 'mi'
1431 """Statute mile (EPSG 9093)."""
1432 us_ch = 'us-ch'
1433 """US survey chain (EPSG 9033)."""
1434 us_ft = 'us-ft'
1435 """US survey foot (EPSG 9003)."""
1436 us_in = 'us-in'
1437 """US survey inch."""
1438 us_mi = 'us-mi'
1439 """US survey mile (EPSG 9035)."""
1440 us_yd = 'us-yd'
1441 """US survey yard."""
1442 cm = 'cm'
1443 """Centimetre (EPSG 1033)."""
1444 ch = 'ch'
1445 """Chain (EPSG 9097)."""
1446 dm = 'dm'
1447 """Decimetre."""
1448 deg = 'deg'
1449 """Degree (EPSG 9102)."""
1450 fath = 'fath'
1451 """Fathom (EPSG 9014)."""
1452 ft = 'ft'
1453 """Foot (EPSG 9002)."""
1454 grad = 'grad'
1455 """Grad (EPSG 9105)."""
1456 inch = 'in'
1457 """Inch."""
1458 km = 'km'
1459 """Kilometre (EPSG 9036)."""
1460 link = 'link'
1461 """Link (EPSG 9098)."""
1462 m = 'm'
1463 """Metre (EPSG 9001)."""
1464 mm = 'mm'
1465 """Millimetre (EPSG 1025)."""
1466 kmi = 'kmi'
1467 """Nautical mile (EPSG 9030)."""
1468 rad = 'rad'
1469 """Radian (EPSG 9101)."""
1470 yd = 'yd'
1471 """Yard (EPSG 9096)."""
1472 px = 'px'
1473 """Pixel."""
1474 pt = 'pt'
1475 """Typographic point (1/72 inch)."""
1478UomValue: TypeAlias = tuple[float, Uom]
1479"""A value with a unit, like ``(5, Uom.mm)``."""
1481UomValueStr: TypeAlias = str
1482"""A value with a unit like ``5mm``."""
1484UomPoint: TypeAlias = tuple[float, float, Uom]
1485"""A point with a unit, like ``(1, 2, Uom.mm)``."""
1487UomPointStr: TypeAlias = list[str]
1488"""A point with a unit like ``["1mm", "2mm"]``."""
1490UomSize: TypeAlias = tuple[float, float, Uom]
1491"""A size with a unit, like ``(10, 20, Uom.mm)``."""
1493UomSizeStr: TypeAlias = list[str]
1494"""A size with a unit like ``["1mm", "2mm"]``."""
1496UomExtent: TypeAlias = tuple[float, float, float, float, Uom]
1497"""An extent with a unit, like ``(0, 0, 10, 20, Uom.mm)``."""
1499UomExtentStr: TypeAlias = list[str]
1500"""An extent with a unit like ``["1mm", "2mm", "3mm", "4mm"]``."""
1501################################################################################
1504################################################################################
1505# /lib/image/types.pyinc
1508class ImageFormat(Data):
1509 """Image format: MIME types and encoding options."""
1511 name: str
1512 """Name of the format."""
1513 mimeTypes: list[str]
1514 """MIME types for this format."""
1515 options: dict
1516 """Encoding options, as accepted by ``Image.to_bytes``."""
1519class Image:
1520 """Raster image.
1522 Manipulation methods change the image in place and return the image itself, so that calls can be chained.
1523 """
1525 def size(self) -> Size:
1526 """Get the image size.
1528 Returns:
1529 A tuple ``(width, height)`` in pixels.
1530 """
1532 def mode(self) -> str:
1533 """Get the image mode.
1535 Returns:
1536 PIL image mode, e.g. ``RGBA``.
1537 """
1539 def convert(self, mode: str) -> 'Image':
1540 """Convert the image to a mode.
1542 Args:
1543 mode: PIL image mode.
1545 Returns:
1546 The image.
1547 """
1549 def add_box(self, color=None) -> 'Image':
1550 """Draw a 1 pixel wide frame along the image edges.
1552 The image is converted to RGBA.
1554 Args:
1555 color: Line color, black by default.
1557 Returns:
1558 The image.
1559 """
1561 def add_text(self, text: str, x=0, y=0, color=None) -> 'Image':
1562 """Draw text on the image with the default font.
1564 The image is converted to RGBA.
1566 Args:
1567 text: Text, can contain multiple lines.
1568 x: X coordinate of the top left corner of the text.
1569 y: Y coordinate of the top left corner of the text.
1570 color: Text color, black by default.
1572 Returns:
1573 The image.
1574 """
1576 def compose(self, other: 'Image', opacity=1) -> 'Image':
1577 """Place another image on top of this one, using alpha composition.
1579 The other image is resized to the size of this one if needed.
1581 Args:
1582 other: Image to place on top.
1583 opacity: Opacity of the other image, from 0 to 1.
1585 Returns:
1586 The image.
1587 """
1589 def crop(self, box) -> 'Image':
1590 """Crop the image.
1592 Args:
1593 box: Crop rectangle ``(left, upper, right, lower)`` in pixels.
1595 Returns:
1596 The image.
1597 """
1599 def paste(self, other: 'Image', where=None) -> 'Image':
1600 """Paste another image into this one.
1602 Args:
1603 other: Image to paste.
1604 where: Position ``(x, y)`` of the upper left corner, or a box ``(left, upper, right, lower)``.
1605 By default, the image is pasted at ``(0, 0)``.
1607 Returns:
1608 The image.
1609 """
1611 def resize(self, size: Size, **kwargs) -> 'Image':
1612 """Resize the image to a size, without keeping the aspect ratio.
1614 Args:
1615 size: New size ``(width, height)``.
1616 **kwargs: Options for ``PIL.Image.resize``. The default resampling is bicubic.
1618 Returns:
1619 The image.
1620 """
1622 def resize_to(self, width: int = 0, height: int = 0, **kwargs) -> 'Image':
1623 """Resize the image to a width, a height or both.
1625 If only one dimension is given, the other is computed to keep the aspect ratio.
1626 If none is given, the image is not changed.
1628 Args:
1629 width: New width.
1630 height: New height.
1631 **kwargs: Options for ``PIL.Image.resize``.
1633 Returns:
1634 The image.
1635 """
1637 def rotate(self, angle: int, **kwargs) -> 'Image':
1638 """Rotate the image counter-clockwise.
1640 Args:
1641 angle: Angle in degrees.
1642 **kwargs: Options for ``PIL.Image.rotate``. The default resampling is bicubic.
1644 Returns:
1645 The image.
1646 """
1648 def to_bytes(self, mime: MimeType = '', options: Optional[dict] = None) -> bytes:
1649 """Encode the image.
1651 The ``options`` dict can contain any PIL save option
1652 (see https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html).
1654 An additional option ``mode`` is the image mode
1655 (see https://pillow.readthedocs.io/en/stable/handbook/concepts.html#concept-modes).
1656 If provided, the image is converted to that mode before saving, with an adaptive palette.
1658 An additional option ``background`` sets the color to replace the alpha channel with
1659 when an RGBA image is saved as JPEG (default is white).
1661 Args:
1662 mime: MIME type of the output, PNG by default.
1663 options: Encoding options.
1665 Returns:
1666 The encoded image.
1667 """
1669 def to_base64(self, mime: MimeType = '', options: Optional[dict] = None) -> str:
1670 """Encode the image as a base64 string.
1672 Args:
1673 mime: MIME type of the output, PNG by default.
1674 options: Encoding options, as in ``to_bytes``.
1676 Returns:
1677 The base64 encoded image.
1678 """
1680 def to_data_url(self, mime: MimeType = '', options: Optional[dict] = None) -> str:
1681 """Encode the image as a base64 data URL.
1683 Args:
1684 mime: MIME type of the output, PNG by default.
1685 options: Encoding options, as in ``to_bytes``.
1687 Returns:
1688 A ``data:`` URL.
1689 """
1691 def to_path(self, path: str, mime: MimeType = '', options: Optional[dict] = None) -> str:
1692 """Encode the image and save it to a file.
1694 Args:
1695 path: File path.
1696 mime: MIME type of the output, PNG by default.
1697 options: Encoding options, as in ``to_bytes``.
1699 Returns:
1700 The file path.
1701 """
1703 def to_array(self) -> 'numpy.typing.NDArray':
1704 """Convert the image to a numpy array.
1706 Returns:
1707 An array of shape ``(height, width)`` or ``(height, width, channels)``.
1708 """
1710 def compare_to(self, other: 'Image') -> float:
1711 """Compare this image to another one.
1713 Computes the mean squared difference of the RGBA channels over all pixels,
1714 normalized to the range 0 to 1. Both images must be RGBA and have the same size.
1716 Args:
1717 other: Image to compare to.
1719 Returns:
1720 ``0`` if the images are equal, larger values for larger differences.
1721 """
1722################################################################################
1725################################################################################
1726# /lib/intl/types.pyinc
1729LocaleUid: TypeAlias = str
1730"""Locale UID like ``de_DE``."""
1733class Locale(Data):
1734 """Locale data: language, territory, date and number conventions."""
1736 uid: str
1737 """Locale uid like ``de_DE``. A locale without a territory has the territory ``ZZ``."""
1738 dateFormatLong: str
1739 """Long date format pattern."""
1740 dateFormatMedium: str
1741 """Medium date format pattern."""
1742 dateFormatShort: str
1743 """Short date format pattern."""
1744 dayNamesLong: list[str]
1745 """Full day names."""
1746 dayNamesShort: list[str]
1747 """Abbreviated day names."""
1748 dayNamesNarrow: list[str]
1749 """Narrow day names."""
1750 firstWeekDay: int
1751 """First day of the week, ``0`` is Monday."""
1753 language: str
1754 """Language code: ``de``."""
1755 language3: str
1756 """ISO 639 alpha-3 language code: ``deu``."""
1757 languageBib: str
1758 """ISO 639-2 bibliographic language code: ``ger``."""
1759 languageName: str
1760 """Native language name: ``Deutsch``."""
1761 languageNameEn: str
1762 """English language name: ``German``."""
1764 territory: str
1765 """Territory code: ``DE``."""
1766 territoryName: str
1767 """Native territory name: ``Deutschland``."""
1768 monthNamesLong: list[str]
1769 """Full month names."""
1770 monthNamesShort: list[str]
1771 """Abbreviated month names."""
1772 monthNamesNarrow: list[str]
1773 """Narrow month names."""
1774 numberDecimal: str
1775 """Decimal separator."""
1776 numberGroup: str
1777 """Group (thousands) separator."""
1780class DateTimeFormat(Enum):
1781 """Date or time format."""
1782 short = 'short'
1783 """Local short format."""
1784 medium = 'medium'
1785 """Local medium format."""
1786 long = 'long'
1787 """Local long format."""
1788 iso = 'iso'
1789 """ISO 8601 format."""
1792class NumberFormat(Enum):
1793 """Number format."""
1794 decimal = 'decimal'
1795 """Locale decimal format."""
1796 grouped = 'grouped'
1797 """Locale grouped format."""
1798 currency = 'currency'
1799 """Locale currency format."""
1800 percent = 'percent'
1801 """Locale percent format."""
1804class DateFormatter:
1805 """Locale-aware date formatter."""
1807 def format(self, fmt: DateTimeFormat | str, date: Optional[Union['datetime.date', str]] = None) -> str:
1808 """Format a date.
1810 Args:
1811 fmt: Format type, or a ``babel`` (CLDR) date pattern like ``dd.MM.yyyy``.
1812 date: Date or date string, the current date by default.
1814 Returns:
1815 The formatted date.
1817 Raises:
1818 ``Error``: If the date cannot be parsed.
1819 """
1821 def short(self, date=None) -> str:
1822 """Format a date in the short format of the locale, e.g. ``11.12.13``.
1824 Args:
1825 date: Date or date string, the current date by default.
1827 Returns:
1828 The formatted date.
1829 """
1831 def medium(self, date=None) -> str:
1832 """Format a date in the medium format of the locale, e.g. ``11.12.2013``.
1834 Args:
1835 date: Date or date string, the current date by default.
1837 Returns:
1838 The formatted date.
1839 """
1841 def long(self, date=None) -> str:
1842 """Format a date in the long format of the locale, e.g. ``11. Dezember 2013``.
1844 Args:
1845 date: Date or date string, the current date by default.
1847 Returns:
1848 The formatted date.
1849 """
1851 def iso(self, date=None) -> str:
1852 """Format a date in the ISO 8601 format, e.g. ``2013-12-11``.
1854 Args:
1855 date: Date or date string, the current date by default.
1857 Returns:
1858 The formatted date.
1859 """
1862class TimeFormatter:
1863 """Locale-aware time formatter."""
1865 def format(self, fmt: DateTimeFormat | str, time: Optional[Union['datetime.time', str]] = None) -> str:
1866 """Format a time.
1868 Args:
1869 fmt: Format type, or a ``babel`` (CLDR) time pattern like ``HH:mm``.
1870 time: Time, datetime or time string, the current time by default.
1872 Returns:
1873 The formatted time.
1875 Raises:
1876 ``Error``: If the time cannot be parsed.
1877 """
1879 def short(self, time=None) -> str:
1880 """Format a time in the short format of the locale, e.g. ``11:22``.
1882 Args:
1883 time: Time, datetime or time string, the current time by default.
1885 Returns:
1886 The formatted time.
1887 """
1889 def medium(self, time=None) -> str:
1890 """Format a time in the medium format of the locale, e.g. ``11:22:33``.
1892 Args:
1893 time: Time, datetime or time string, the current time by default.
1895 Returns:
1896 The formatted time.
1897 """
1899 def long(self, time=None) -> str:
1900 """Format a time in the long format of the locale, which usually includes the time zone.
1902 Args:
1903 time: Time, datetime or time string, the current time by default.
1905 Returns:
1906 The formatted time.
1907 """
1909 def iso(self, time=None) -> str:
1910 """Format a time in the ISO 8601 format, with the time zone offset, e.g. ``11:22:33+0100``.
1912 Args:
1913 time: Time, datetime or time string, the current time by default.
1915 Returns:
1916 The formatted time.
1917 """
1920class NumberFormatter:
1921 """Locale-aware number formatter."""
1923 def format(self, fmt: NumberFormat | str, n, *args, **kwargs) -> str:
1924 """Format a number.
1926 Args:
1927 fmt: Format type. For an unknown format, the number is converted with ``str``.
1928 n: Number.
1929 *args: Arguments for the format method, e.g. the currency for ``currency``.
1930 **kwargs: Keyword arguments for the format method.
1932 Returns:
1933 The formatted number.
1934 """
1936 def decimal(self, n, *args, **kwargs) -> str:
1937 """Format a number as a decimal without group separators.
1939 Args:
1940 n: Number.
1941 *args: Arguments for ``babel.numbers.format_decimal``.
1942 **kwargs: Keyword arguments for ``babel.numbers.format_decimal``.
1944 Returns:
1945 The formatted number.
1946 """
1948 def grouped(self, n, *args, **kwargs) -> str:
1949 """Format a number as a decimal with group separators.
1951 Args:
1952 n: Number.
1953 *args: Arguments for ``babel.numbers.format_decimal``.
1954 **kwargs: Keyword arguments for ``babel.numbers.format_decimal``.
1956 Returns:
1957 The formatted number.
1958 """
1960 def currency(self, n, currency: str, *args, **kwargs) -> str:
1961 """Format a number as a currency value.
1963 Args:
1964 n: Number.
1965 currency: Currency code like ``EUR``.
1966 *args: Arguments for ``babel.numbers.format_currency``.
1967 **kwargs: Keyword arguments for ``babel.numbers.format_currency``.
1969 Returns:
1970 The formatted value.
1971 """
1973 def percent(self, n, *args, **kwargs) -> str:
1974 """Format a number as a percentage, ``0.5`` is 50 percent.
1976 Args:
1977 n: Number.
1978 *args: Arguments for ``babel.numbers.format_percent``.
1979 **kwargs: Keyword arguments for ``babel.numbers.format_percent``.
1981 Returns:
1982 The formatted value.
1983 """
1984################################################################################
1987################################################################################
1988# /lib/style/types.pyinc
1991class StyleValues(Data):
1992 """Style values, as parsed by ``gws.lib.style.parser``."""
1994 fill: Color
1995 """Fill color."""
1997 stroke: Color
1998 """Stroke (line) color."""
1999 stroke_dasharray: list[int]
2000 """Dash pattern, as a list of dash and gap lengths."""
2001 stroke_dashoffset: int
2002 """Offset of the dash pattern."""
2003 stroke_linecap: Literal['butt', 'round', 'square']
2004 """Shape of line ends."""
2005 stroke_linejoin: Literal['bevel', 'round', 'miter']
2006 """Shape of line corners."""
2007 stroke_miterlimit: int
2008 """Limit for miter joins."""
2009 stroke_width: int
2010 """Stroke width in pixels."""
2012 marker: Literal['circle', 'square', 'arrow', 'cross']
2013 """Marker symbol drawn at the vertices of a geometry."""
2014 marker_fill: Color
2015 """Marker fill color."""
2016 marker_size: int
2017 """Marker size in pixels."""
2018 marker_stroke: Color
2019 """Marker stroke color."""
2020 marker_stroke_dasharray: list[int]
2021 """Marker dash pattern."""
2022 marker_stroke_dashoffset: int
2023 """Offset of the marker dash pattern."""
2024 marker_stroke_linecap: Literal['butt', 'round', 'square']
2025 """Shape of marker line ends."""
2026 marker_stroke_linejoin: Literal['bevel', 'round', 'miter']
2027 """Shape of marker line corners."""
2028 marker_stroke_miterlimit: int
2029 """Limit for marker miter joins."""
2030 marker_stroke_width: int
2031 """Marker stroke width in pixels."""
2033 with_geometry: Literal['all', 'none']
2034 """Draw the geometry (``all``) or not (``none``)."""
2035 with_label: Literal['all', 'none']
2036 """Draw the label (``all``) or not (``none``)."""
2038 label_align: Literal['left', 'right', 'center']
2039 """Horizontal text alignment of the label."""
2040 label_background: Color
2041 """Label background color."""
2042 label_fill: Color
2043 """Label text color."""
2044 label_font_family: str
2045 """Label font family."""
2046 label_font_size: int
2047 """Label font size in pixels."""
2048 label_font_style: Literal['normal', 'italic']
2049 """Label font style."""
2050 label_font_weight: Literal['normal', 'bold']
2051 """Label font weight."""
2052 label_line_height: int
2053 """Line spacing for multi-line labels."""
2054 label_max_scale: int
2055 """Maximal scale denominator at which the label is shown."""
2056 label_min_scale: int
2057 """Minimal scale denominator at which the label is shown."""
2058 label_offset_x: int
2059 """Horizontal label offset in pixels."""
2060 label_offset_y: int
2061 """Vertical label offset in pixels."""
2062 label_padding: list[int]
2063 """Label padding in pixels, as ``[top, right, bottom, left]``."""
2064 label_placement: Literal['start', 'end', 'middle']
2065 """Label position along the geometry: the first point, the last point or the centroid."""
2066 label_stroke: Color
2067 """Label text stroke color."""
2068 label_stroke_dasharray: list[int]
2069 """Label text dash pattern."""
2070 label_stroke_dashoffset: int
2071 """Offset of the label text dash pattern."""
2072 label_stroke_linecap: Literal['butt', 'round', 'square']
2073 """Shape of label text line ends."""
2074 label_stroke_linejoin: Literal['bevel', 'round', 'miter']
2075 """Shape of label text line corners."""
2076 label_stroke_miterlimit: int
2077 """Limit for label text miter joins."""
2078 label_stroke_width: int
2079 """Label text stroke width in pixels."""
2081 point_size: int
2082 """Diameter of point geometries in pixels."""
2083 icon: Optional['XmlElement']
2084 """Icon for point geometries, the normalized SVG element."""
2086 offset_x: int
2087 """Horizontal offset of the drawn geometry in pixels."""
2088 offset_y: int
2089 """Vertical offset of the drawn geometry in pixels."""
2092class StyleProps(Props):
2093 """CSS Style properties."""
2095 cssSelector: Optional[str]
2096 text: Optional[str]
2097 values: Optional[dict]
2100class Style:
2101 """Feature style."""
2103 cssSelector: str
2104 """CSS selector of the style."""
2105 text: str
2106 """Raw CSS text of the style."""
2107 values: StyleValues
2108 """Parsed style values."""
2109################################################################################
2112################################################################################
2113# /lib/xmlx/types.pyinc
2116class XmlNamespace(Data):
2117 """XML namespace."""
2119 prefix: str
2120 """Default prefix for this Namespace, empty for a default namespace declaration."""
2121 uri: Url
2122 """Namespace uri."""
2123 schemaLocation: Url
2124 """Namespace schema location."""
2125 extendsGml: bool
2126 """Namespace schema extends the GML3 schema."""
2129class XmlOptions(Data):
2130 """XML options for parsing and serialization."""
2132 removeNamespaces: bool = False
2133 """Strip namespaces when parsing: tags and attributes are local names, declarations are dropped."""
2135 customNamespacePrefixes: Optional[dict[str, str]] = None
2136 """Serialization: prefixes to use instead of the default ones (namespace uri -> prefix)."""
2138 defaultNamespace: Optional['XmlNamespace'] = None
2139 """Serialization: elements in this namespace are written without a prefix."""
2141 doctype: Optional[str] = None
2142 """Serialization: document type definition (DTD), written after the XML declaration."""
2144 compactWhitespace: bool = False
2145 """Collapse whitespace in text content (parsing and serialization)."""
2147 withNamespaceDeclarations: bool = False
2148 """Serialization: declare all namespaces used in the tree on the root element."""
2150 withSchemaLocations: bool = False
2151 """Serialization: add ``xsi:schemaLocation`` for declared namespaces that have a schema location."""
2153 withXmlDeclaration: bool = False
2154 """Serialization: write the ``<?xml ...?>`` declaration."""
2157class XmlElement(Iterable):
2158 """XML Element.
2160 Implements a subset of the ``ElementTree.Element`` API.
2162 ``tag`` is either a local name (``Point``) or a Clark name (``{http://www.opengis.net/gml/3.2}Point``);
2163 ``name`` is always the local name. Prefixed names never occur in a tree: ``tag()`` resolves ``ID:name``
2164 to a Clark name, the parser resolves prefixes against the document's declarations. The element itself
2165 (constructor, ``add()``, ``set()``) takes names as they are; it has no namespace map to resolve against.
2166 """
2168 tag: str
2169 """Tag name, local or Clark."""
2171 name: str
2172 """Element name (tag without a namespace)."""
2174 text: str
2175 """Text before first subelement."""
2177 tail: str
2178 """Text after this element's end tag."""
2180 attrib: dict
2181 """Dictionary of element attributes."""
2183 namespaces: list[XmlNamespace]
2184 """Namespaces declared on this element (``prefix == ''`` for the default namespace)."""
2186 def __len__(self) -> int: ...
2188 def __iter__(self) -> Iterator['XmlElement']: ...
2190 def __getitem__(self, item: int) -> 'XmlElement': ...
2192 def append(self, subelement: 'XmlElement'):
2193 """Add a child at the end of the list of children.
2195 Args:
2196 subelement: The element to add.
2197 """
2199 def clear(self):
2200 """Remove the attributes, namespace declarations, children, text and tail of this element."""
2202 def extend(self, subelements: Iterable['XmlElement']):
2203 """Add children at the end of the list of children.
2205 Args:
2206 subelements: The elements to add.
2207 """
2209 def find(self, path: str) -> Optional['XmlElement']:
2210 """Find the first matching subelement.
2212 Args:
2213 path: Tag name or path in ``ElementTree`` syntax, with local or Clark names.
2215 Returns:
2216 The element, or ``None`` if nothing matches.
2217 """
2219 def require(self, path: str) -> 'XmlElement':
2220 """Find the first matching subelement, which must exist.
2222 Args:
2223 path: Tag name or path in ``ElementTree`` syntax, with local or Clark names.
2225 Returns:
2226 The element.
2228 Raises:
2229 gws.lib.xmlx.Error: If nothing matches.
2230 """
2232 def findall(self, path: str) -> list['XmlElement']:
2233 """Find all matching subelements.
2235 Args:
2236 path: Tag name or path in ``ElementTree`` syntax, with local or Clark names.
2238 Returns:
2239 A list of elements in document order.
2240 """
2242 def findtext(self, path: str, default: str = '') -> str:
2243 """Find the text of the first matching subelement.
2245 Args:
2246 path: Tag name or path in ``ElementTree`` syntax, with local or Clark names.
2247 default: Value to return if nothing matches.
2249 Returns:
2250 The text of the element, or ``default``.
2251 """
2253 def get(self, key: str, default: str = '') -> str:
2254 """Get an attribute value.
2256 Args:
2257 key: Attribute name, local or Clark.
2258 default: Value to return if the attribute does not exist.
2260 Returns:
2261 The attribute value, or ``default``.
2262 """
2264 def insert(self, index: int, subelement: 'XmlElement'):
2265 """Insert a child at the given position.
2267 Args:
2268 index: Position in the list of children.
2269 subelement: The element to insert.
2270 """
2272 def items(self) -> Iterable[tuple[str, Any]]:
2273 """Get the attributes.
2275 Returns:
2276 The attributes as ``(name, value)`` pairs.
2277 """
2279 def iter(self, tag: Optional[str] = None) -> Iterable['XmlElement']:
2280 """Iterate over this element and all its descendants, depth-first.
2282 Args:
2283 tag: Only return elements with this tag; ``None`` or ``*`` returns all elements.
2285 Returns:
2286 An iterator of elements, starting with this element if it matches.
2287 """
2289 def iterfind(self, path: str) -> Iterable['XmlElement']:
2290 """Iterate over all matching subelements.
2292 Args:
2293 path: Tag name or path in ``ElementTree`` syntax, with local or Clark names.
2295 Returns:
2296 An iterator of elements in document order.
2297 """
2299 def itertext(self) -> Iterable[str]:
2300 """Iterate over the text content of this element and its descendants.
2302 Returns:
2303 An iterator of the non-empty texts and tails in document order, without the tail of this element.
2304 """
2306 def keys(self) -> Iterable[str]:
2307 """Get the attribute names.
2309 Returns:
2310 The attribute names.
2311 """
2313 def remove(self, other: 'XmlElement'):
2314 """Remove a child.
2316 Args:
2317 other: The child to remove.
2319 Raises:
2320 ValueError: If the element is not a child of this element.
2321 """
2323 def set(self, key: str, value: Any):
2324 """Set an attribute.
2326 Args:
2327 key: Attribute name, local or Clark.
2328 value: Attribute value.
2329 """
2331 # extensions
2333 def hasattr(self, key: str) -> bool:
2334 """Check if an attribute exists.
2336 Args:
2337 key: Attribute name, local or Clark.
2339 Returns:
2340 ``True`` if the attribute exists.
2341 """
2343 def isa(self, *names: str) -> bool:
2344 """Check if the local name of this element matches one of the given names, case-insensitively.
2346 Args:
2347 *names: Local names.
2349 Returns:
2350 ``True`` if the name matches.
2351 """
2353 def add(self, tag: str, attrib: Optional[dict] = None, **extra) -> 'XmlElement':
2354 """Create a new element and add it as a child.
2356 Names are taken as they are (local or Clark); ``ID:name`` resolution is done by ``tag()`` only.
2358 Args:
2359 tag: Tag name, local or Clark.
2360 attrib: Attributes.
2361 **extra: Additional attributes.
2363 Returns:
2364 The new element.
2365 """
2367 def children(self) -> list['XmlElement']:
2368 """Get the children of this element.
2370 Returns:
2371 The list of children. This is the internal list, not a copy.
2372 """
2374 def declare(self, *namespaces: XmlNamespace):
2375 """Add namespace declarations to this element.
2377 The declarations are written as ``xmlns`` attributes on output. Namespaces already declared
2378 with the same prefix and URI are skipped.
2380 Args:
2381 *namespaces: Namespaces to declare.
2382 """
2384 def findfirst(self, *paths) -> Optional['XmlElement']:
2385 """Find the first element that matches one of the given paths.
2387 Args:
2388 *paths: Tag names or paths in ``ElementTree`` syntax, tried in order.
2390 Returns:
2391 The first match, or ``None``. Without paths, the first child, or ``None`` if there are no children.
2392 """
2394 def textof(self, *paths) -> str:
2395 """Get the text of the first matching element that has text.
2397 Args:
2398 *paths: Tag names or paths in ``ElementTree`` syntax, tried in order.
2400 Returns:
2401 The text, or an empty string if no matching element has text.
2402 """
2404 def textlist(self, *paths, deep=False) -> list[str]:
2405 """Collect texts from subelements.
2407 Texts are stripped, empty texts are skipped.
2409 Args:
2410 *paths: Tag names or paths in ``ElementTree`` syntax. Without paths, the direct children are used.
2411 deep: If ``True``, also collect texts from all descendants of the found elements.
2413 Returns:
2414 A list of texts in document order.
2415 """
2417 def textdict(self, *paths, deep=False) -> dict[str, str]:
2418 """Collect texts from subelements, keyed by tag.
2420 Texts are stripped, empty texts are skipped. If several elements have the same tag, the last text wins.
2422 Args:
2423 *paths: Tag names or paths in ``ElementTree`` syntax. Without paths, the direct children are used.
2424 deep: If ``True``, also collect texts from all descendants of the found elements.
2426 Returns:
2427 A dict of tags (local or Clark) and texts.
2428 """
2430 def to_string(self, opts: Optional[XmlOptions] = None) -> str:
2431 """Serialize this element and its subtree.
2433 Args:
2434 opts: Serialization options.
2436 Returns:
2437 An XML string.
2439 Raises:
2440 gws.lib.xmlx.WriteError: If the tree contains an invalid or prefixed name.
2441 gws.lib.xmlx.NamespaceError: If a namespace is unknown, or one prefix is used for different URIs.
2442 """
2444 def to_dict(self) -> dict:
2445 """Convert the element tree to a dict.
2447 Returns:
2448 A dict with the keys ``tag``, ``attrib``, ``text``, ``tail`` and ``children``,
2449 where ``children`` is a list of such dicts.
2450 """
2451################################################################################
2455################################################################################
2456# /lib/crs/types.pyinc
2459CrsName: TypeAlias = int | str
2460"""A CRS code like ``EPSG:3857`` or a SRID like ``3857``."""
2463class CrsFormat(Enum):
2464 """CRS name format."""
2466 none = ''
2467 """No format."""
2468 crs = 'crs'
2469 """Like ``crs84``."""
2470 srid = 'srid'
2471 """Like ``3857``."""
2472 epsg = 'epsg'
2473 """Like ``EPSG:3857``."""
2474 url = 'url'
2475 """Like ``http://www.opengis.net/gml/srs/epsg.xml#3857``."""
2476 uri = 'uri'
2477 """Like ``http://www.opengis.net/def/crs/epsg/0/3857``."""
2478 urnx = 'urnx'
2479 """Like ``urn:x-ogc:def:crs:EPSG:3857``."""
2480 urn = 'urn'
2481 """Like ``urn:ogc:def:crs:EPSG::3857``."""
2484class Axis(Enum):
2485 """Axis orientation."""
2487 xy = 'xy'
2488 """XY (longitude/latitude) axis orientation."""
2489 yx = 'yx'
2490 """YX (latitude/longitude) axis orientation."""
2493class Bounds(Data):
2494 """Geo-referenced extent: an extent together with its CRS."""
2496 crs: 'Crs'
2497 """Coordinate reference system of the extent."""
2498 extent: Extent
2499 """Extent in the coordinates of ``crs``."""
2502class Crs:
2503 """Coordinate reference system."""
2505 axis: Axis
2506 """Axis orientation."""
2507 base: int
2508 """Base CRS code."""
2509 bounds: Bounds
2510 """CRS own Bounds."""
2511 coordinatePrecision: int
2512 """Preferred precision for coordinates in this CRS."""
2513 datum: str
2514 """Datum."""
2515 epsg: str
2516 """Name in the "epsg" format."""
2517 extent: Extent
2518 """CRS own Extent."""
2519 isGeographic: bool
2520 """This CRS is geographic."""
2521 isProjected: bool
2522 """This CRS is projected."""
2523 isYX: bool
2524 """This CRS has a lat/lon axis."""
2525 name: str
2526 """CRS name."""
2527 proj4text: str
2528 """Proj4 definition."""
2529 srid: int
2530 """CRS SRID."""
2531 uom: Uom
2532 """CRS unit."""
2533 uri: str
2534 """Name in the "uri" format."""
2535 url: str
2536 """Name in the "url" format."""
2537 urn: str
2538 """Name in the "urn" format."""
2539 urnx: str
2540 """Name in the "urnx" format."""
2541 wgsExtent: Extent
2542 """CRS Extent in the WGS projection."""
2543 wgsMaxExtent: Extent
2544 """Maximal extent that makes sense for this CRS, in the WGS projection."""
2545 wkt: str
2546 """WKT definition."""
2548 def axis_for_format(self, fmt: 'CrsFormat') -> Axis:
2549 """Get the axis orientation implied by a CRS name format.
2551 For CRSs with a lat/lon axis, the orientation depends on how the CRS is named.
2552 We adhere to the GeoServer convention: the ``srid``, ``epsg``, ``url`` and ``uri``
2553 formats imply XY, the ``urn`` and ``urnx`` formats imply YX
2554 (see https://docs.geoserver.org/latest/en/user/services/wfs/axis_order.html).
2555 For XY CRSs, the own axis is always returned.
2557 Args:
2558 fmt: CRS name format.
2560 Returns:
2561 The axis orientation.
2562 """
2564 def clip_wgs_extent(self, wgs_extent: Extent) -> Optional[Extent]:
2565 """Clip a WGS extent to the maximal extent of this CRS.
2567 Args:
2568 wgs_extent: Extent in the WGS projection.
2570 Returns:
2571 The clipped extent in the WGS projection, or ``None`` if there is no intersection.
2572 """
2574 def extent_size_in_meters(self, extent: Extent) -> Size:
2575 """Calculate the width and height of an extent in meters.
2577 For projected CRSs, the extent size is returned as is. For geographic CRSs,
2578 geodesic distances on the WGS84 ellipsoid are measured along the middle
2579 latitude and the middle longitude of the extent.
2581 Args:
2582 extent: Extent in this CRS.
2584 Returns:
2585 A ``(width, height)`` tuple in meters.
2587 Raises:
2588 ``gws.lib.crs.Error``: If this is a projected CRS with units other than meters.
2589 """
2591 def point_offset_in_meters(self, xy: Point, dist: float, az: int) -> Point:
2592 """Calculate a point at a given distance and direction from another point.
2594 Args:
2595 xy: Point in this CRS.
2596 dist: Distance in meters.
2597 az: Azimuth in degrees (0 = North, 90 = East, etc.).
2599 Returns:
2600 The offset point in this CRS.
2602 Raises:
2603 ``gws.lib.crs.Error``: If this is a projected CRS with units other than meters.
2604 """
2606 def to_geojson(self) -> dict:
2607 """Return a GeoJSON representation of the CRS.
2609 The CRS is represented as a "named CRS" with its ``urn`` name,
2610 as per the 2008 GeoJSON specification (https://geojson.org/geojson-spec#named-crs).
2612 Returns:
2613 A GeoJSON ``crs`` dict.
2614 """
2616 def to_string(self, fmt: Optional['CrsFormat'] = None) -> str:
2617 """Return the name of the CRS in a given format.
2619 Args:
2620 fmt: Format to use, ``CrsFormat.epsg`` by default.
2622 Returns:
2623 The CRS name, like ``EPSG:3857``.
2624 """
2626 def transform_extent(self, extent: Extent, crs_to: 'Crs') -> Extent:
2627 """Transform an Extent from this CRS to another.
2629 The transformation goes through WGS84. If the extent is very large
2630 (almost the whole world) and the target CRS has a limited area of use,
2631 the result is computed by sampling points, so that it stays finite.
2633 Args:
2634 extent: Extent in this CRS.
2635 crs_to: Target CRS.
2637 Returns:
2638 The transformed Extent, with min and max values in order.
2639 """
2641 def transform_resolution(self, extent: Extent, res: float, crs_to: 'Crs') -> float:
2642 """Transform a resolution over an extent from this CRS to another.
2644 The returned resolution is the finest one found at a set of sample points of the extent,
2645 so that the target resolution is never coarser than the source resolution anywhere in the extent.
2647 Args:
2648 extent: Extent in this CRS.
2649 res: Resolution in units of this CRS per pixel.
2650 crs_to: Target CRS.
2652 Returns:
2653 The resolution in units of the target CRS per pixel, or ``0.0`` if the transformation fails.
2654 """
2656 def transformer(self, crs_to: 'Crs') -> Callable:
2657 """Create a transformer function to another CRS.
2659 The function always uses the XY (easting/longitude first) axis order.
2661 Args:
2662 crs_to: Target CRS.
2664 Returns:
2665 A function that takes ``x, y`` and returns a transformed ``(x, y)`` tuple.
2666 """
2667################################################################################
2670################################################################################
2671# /lib/shape/types.pyinc
2674class ShapeProps(Props):
2675 """Shape properties."""
2677 crs: str
2678 geometry: dict
2681class Shape(Object):
2682 """Geo-referenced geometry."""
2684 type: GeometryType
2685 """Geometry type."""
2687 crs: 'Crs'
2688 """CRS of this shape."""
2690 x: Optional[float]
2691 """X-coordinate for Point geometries, None otherwise."""
2693 y: Optional[float]
2694 """Y-coordinate for Point geometries, None otherwise."""
2696 # common props
2698 def area(self) -> float:
2699 """Compute the area of the geometry.
2701 Returns:
2702 The area in CRS units, 0 for geometries without an area.
2703 """
2705 def bounds(self) -> Bounds:
2706 """Compute the bounds of this shape.
2708 Returns:
2709 A Bounds object in the CRS of this shape.
2710 """
2712 def centroid(self) -> 'Shape':
2713 """Compute the centroid of this shape.
2715 Returns:
2716 A Point shape.
2717 """
2719 def center(self) -> tuple[float, float]:
2720 """Compute the coordinates of the centroid.
2722 Returns:
2723 A tuple ``(x, y)``.
2724 """
2726 # formats
2728 def to_wkb(self) -> bytes:
2729 """Convert this shape to WKB.
2731 Returns:
2732 WKB bytes.
2733 """
2735 def to_wkb_hex(self) -> str:
2736 """Convert this shape to hex-encoded WKB.
2738 Returns:
2739 A hex string.
2740 """
2742 def to_ewkb(self) -> bytes:
2743 """Convert this shape to EWKB, which includes the SRID.
2745 Returns:
2746 EWKB bytes.
2747 """
2749 def to_ewkb_hex(self) -> str:
2750 """Convert this shape to hex-encoded EWKB, which includes the SRID.
2752 Returns:
2753 A hex string.
2754 """
2756 def to_wkt(self, trim=False, rounding_precision=-1, output_dimension=3) -> str:
2757 """Convert this shape to WKT.
2759 Whitespace around commas and parentheses is removed.
2761 Args:
2762 trim: Remove trailing zeros from the coordinates.
2763 rounding_precision: Number of decimal places, -1 for full precision.
2764 output_dimension: Max. number of dimensions to output.
2766 Returns:
2767 A WKT string.
2768 """
2770 def to_ewkt(self, trim=False, rounding_precision=-1, output_dimension=3) -> str:
2771 """Convert this shape to EWKT, which is WKT prefixed with ``SRID=<srid>;``.
2773 Args:
2774 trim: Remove trailing zeros from the coordinates.
2775 rounding_precision: Number of decimal places, -1 for full precision.
2776 output_dimension: Max. number of dimensions to output.
2778 Returns:
2779 An EWKT string.
2780 """
2782 def to_geojson(self, keep_crs=False) -> dict:
2783 """Convert this shape to a GeoJSON geometry dict.
2785 Args:
2786 keep_crs: Keep the CRS of this shape, otherwise transform the coordinates to WGS84.
2788 Returns:
2789 A GeoJSON geometry dict.
2790 """
2792 def to_precision(self, prec: int) -> 'Shape':
2793 """Create a copy of this shape with coordinates snapped to the given precision.
2795 Args:
2796 prec: Number of decimal places.
2798 Returns:
2799 A new shape.
2800 """
2802 def to_props(self) -> ShapeProps:
2803 """Convert this shape to props, with the EPSG code and a GeoJSON geometry in the CRS of this shape.
2805 Returns:
2806 Shape props.
2807 """
2809 # predicates (https://shapely.readthedocs.io/en/stable/manual.html#predicates-and-relationships)
2811 def is_empty(self) -> bool:
2812 """Check if this shape is empty.
2814 Returns:
2815 ``True`` if this shape is empty.
2816 """
2818 def is_ring(self) -> bool:
2819 """Check if this shape is a closed and simple line.
2821 Returns:
2822 ``True`` if this shape is a ring.
2823 """
2825 def is_simple(self) -> bool:
2826 """Check if this shape is simple, that is, has no self-intersections.
2828 Returns:
2829 ``True`` if this shape is simple.
2830 """
2832 def is_valid(self) -> bool:
2833 """Check if this shape is valid.
2835 Returns:
2836 ``True`` if this shape is valid.
2837 """
2839 def equals(self, other: 'Shape') -> bool:
2840 """Check if this shape is spatially equal to the other.
2842 The other shape is transformed to the CRS of this shape. The same applies to
2843 all binary predicates.
2845 Args:
2846 other: Another shape.
2848 Returns:
2849 ``True`` if the shapes are equal.
2850 """
2852 def contains(self, other: 'Shape') -> bool:
2853 """Check if this shape contains the other.
2855 Args:
2856 other: Another shape.
2858 Returns:
2859 ``True`` if this shape contains the other.
2860 """
2862 def covers(self, other: 'Shape') -> bool:
2863 """Check if this shape covers the other.
2865 Args:
2866 other: Another shape.
2868 Returns:
2869 ``True`` if this shape covers the other.
2870 """
2872 def covered_by(self, other: 'Shape') -> bool:
2873 """Check if this shape is covered by the other.
2875 Args:
2876 other: Another shape.
2878 Returns:
2879 ``True`` if this shape is covered by the other.
2880 """
2882 def crosses(self, other: 'Shape') -> bool:
2883 """Check if this shape crosses the other.
2885 Args:
2886 other: Another shape.
2888 Returns:
2889 ``True`` if this shape crosses the other.
2890 """
2892 def disjoint(self, other: 'Shape') -> bool:
2893 """Check if this shape does not intersect the other.
2895 Args:
2896 other: Another shape.
2898 Returns:
2899 ``True`` if the shapes have no point in common.
2900 """
2902 def intersects(self, other: 'Shape') -> bool:
2903 """Check if this shape intersects the other.
2905 Args:
2906 other: Another shape.
2908 Returns:
2909 ``True`` if the shapes have at least one point in common.
2910 """
2912 def overlaps(self, other: 'Shape') -> bool:
2913 """Check if this shape overlaps the other.
2915 Args:
2916 other: Another shape.
2918 Returns:
2919 ``True`` if this shape overlaps the other.
2920 """
2922 def touches(self, other: 'Shape') -> bool:
2923 """Check if this shape touches the other.
2925 Args:
2926 other: Another shape.
2928 Returns:
2929 ``True`` if this shape touches the other.
2930 """
2932 def within(self, other: 'Shape') -> bool:
2933 """Check if this shape is within the other.
2935 Args:
2936 other: Another shape.
2938 Returns:
2939 ``True`` if this shape is within the other.
2940 """
2942 # set operations
2944 def union(self, others: list['Shape']) -> 'Shape':
2945 """Compute the union of this shape and other shapes.
2947 Args:
2948 others: Other shapes, transformed to the CRS of this shape.
2950 Returns:
2951 A new shape, or this shape if ``others`` is empty.
2952 """
2954 def intersection(self, *others: 'Shape') -> 'Shape':
2955 """Compute the intersection of this shape and other shapes.
2957 Args:
2958 *others: Other shapes, transformed to the CRS of this shape.
2960 Returns:
2961 A new shape, or this shape if no others are given.
2962 """
2964 # convertors
2966 def to_multi(self) -> 'Shape':
2967 """Convert a single geometry shape to a multi-geometry one.
2969 Returns:
2970 A multi-geometry shape for a point, a line string or a polygon, otherwise this shape.
2971 """
2973 def to_type(self, new_type: 'GeometryType') -> 'Shape':
2974 """Convert this shape to another geometry type.
2976 Only the conversion from a single to the respective multi-geometry is supported.
2978 Args:
2979 new_type: Target geometry type. ``geometry`` and the current type return this shape.
2981 Returns:
2982 A converted shape.
2984 Raises:
2985 ``gws.Error``: If the conversion is not supported.
2986 """
2988 def to_2d(self) -> 'Shape':
2989 """Convert this shape to 2 dimensions.
2991 Returns:
2992 A 2D shape, or this shape if it is already 2D.
2993 """
2995 # misc
2997 def tolerance_polygon(self, tolerance=None, quad_segs=None) -> 'Shape':
2998 """Build a buffer polygon around this shape.
3000 Polygons without a tolerance are returned as is. Other shapes always get a
3001 buffer, with a small minimal radius if no tolerance is given. Shapes in a
3002 geographic CRS are buffered in Web Mercator.
3004 Args:
3005 tolerance: Buffer radius in CRS units, or in meters for geographic CRS.
3006 quad_segs: Number of segments per quarter circle.
3008 Returns:
3009 A polygon shape.
3010 """
3012 def transformed_to(self, crs: 'Crs') -> 'Shape':
3013 """Transform this shape to another CRS.
3015 Args:
3016 crs: Target CRS.
3018 Returns:
3019 A transformed shape, or this shape if the CRS is the same.
3020 """
3021################################################################################
3024################################################################################
3025# /lib/grid/types.pyinc
3028MapTile: TypeAlias = tuple[int, int, int]
3029"""Grid tile: ``(x, y, z)``."""
3031MapTileRange: TypeAlias = tuple[int, int, int, int, int]
3032"""Rectangle of tiles at one level: ``(min_x, min_y, max_x, max_y, z)``."""
3034class MapGrid(Data):
3035 """Fixed tile grid over a CRS, origin north-west.
3037 Level ``z`` has the resolution ``baseResolution / 2**z``. See ``gws.lib.grid``.
3038 """
3040 crs: Crs
3041 """Grid CRS."""
3042 extent: Extent
3043 """Frame extent; the origin is its north-west corner."""
3044 baseResolution: float
3045 """Resolution at level 0, in CRS units per pixel."""
3046 tileSize: int
3047 """Tile width and height in pixels."""
3050class TileMatrix(Data):
3051 """Tile matrix, one level of a tile matrix set, as in WMTS."""
3053 identifier: str
3054 """Matrix identifier."""
3055 scale: float
3056 """Scale denominator."""
3057 resolution: float
3058 """Resolution in CRS units per pixel."""
3059 x: float
3060 """X coordinate of the top left corner."""
3061 y: float
3062 """Y coordinate of the top left corner."""
3063 width: float
3064 """Matrix width in tiles."""
3065 height: float
3066 """Matrix height in tiles."""
3067 tileWidth: float
3068 """Tile width in pixels."""
3069 tileHeight: float
3070 """Tile height in pixels."""
3071 extent: Extent
3072 """Matrix extent."""
3075class TileMatrixSet(Data):
3076 """Tile matrix set, a pyramid of tile matrices, as in WMTS."""
3078 identifier: str
3079 """Matrix set identifier."""
3080 crs: 'Crs'
3081 """CRS of the matrices."""
3082 matrices: list[TileMatrix]
3083 """Matrices of the set."""
3084################################################################################
3087################################################################################
3088# /gis/cache/types.pyinc
3091class MapCache(Data):
3092 """Tile cache settings of a grabber."""
3094 name: str
3095 """Cache name, also the name of the cache directory."""
3096 maxAge: int
3097 """Max. age of cached tiles in seconds, 0 disables storing."""
3098 maxLevel: int
3099 """Finest zoom level to store."""
3100 requestBuffer: int
3101 """Pixel buffer around source requests."""
3102 requestTiles: int
3103 """Tiles per side of the block rendered in one source request."""
3106class TileStoreStats(Data):
3107 """Tile store statistics."""
3109 count: int
3110 """Number of stored tiles."""
3111 size: int
3112 """Total size of stored tiles in bytes."""
3113 range: Optional[MapTileRange]
3114 """Bounding tile range of the stored tiles, only for a single level."""
3117class TileStore:
3118 """Storage for encoded map tiles of one grid.
3120 Tiles are addressed by ``(x, y, z)``. A tile counts as stored only while it is younger than ``maxAge``.
3121 """
3123 baseDir: str
3124 """Base directory of the store."""
3125 maxAge: int
3126 """Max. age of stored tiles in seconds."""
3128 def stats(self) -> TileStoreStats:
3129 """Compute statistics for the whole store.
3131 Returns:
3132 Number and size of stored tiles. The tile range is not set.
3133 """
3135 def stats_for_level(self, z: int) -> TileStoreStats:
3136 """Compute statistics for a level.
3138 Args:
3139 z: Zoom level.
3141 Returns:
3142 Number, size and bounding tile range of the stored tiles of the level.
3143 """
3145 def path(self, mt: MapTile) -> str:
3146 """Return the file path of a tile.
3148 Args:
3149 mt: Tile.
3151 Returns:
3152 The file path, whether the tile exists or not.
3153 """
3155 def has(self, mt: MapTile) -> bool:
3156 """Check if a tile is stored.
3158 Args:
3159 mt: Tile.
3161 Returns:
3162 ``True`` if the tile is stored and younger than ``maxAge``.
3163 """
3165 def read(self, mt: MapTile) -> Optional[bytes]:
3166 """Read a stored tile.
3168 Args:
3169 mt: Tile.
3171 Returns:
3172 The tile content, or ``None`` if the tile is missing, stale or unreadable.
3173 """
3175 def write(self, mt: MapTile, blob: bytes):
3176 """Store a tile.
3178 Args:
3179 mt: Tile.
3180 blob: Encoded tile content.
3181 """
3183 def drop(self):
3184 """Remove the whole store."""
3186 def drop_level(self, z: int):
3187 """Remove all tiles of a level.
3189 Args:
3190 z: Zoom level.
3191 """
3193 def drop_range(self, mtr: MapTileRange):
3194 """Remove the tiles of a range.
3196 Args:
3197 mtr: Tile range.
3198 """
3199################################################################################
3202################################################################################
3203# /gis/render/types.pyinc
3206class MapView(Data):
3207 """Geometry of a rendered map."""
3209 bounds: Bounds
3210 """Bounds of the map, not rotated."""
3211 center: Point
3212 """Center point."""
3213 rotation: int
3214 """Rotation angle in degrees."""
3215 scale: int
3216 """Scale denominator."""
3217 mmSize: Size
3218 """Map size in mm."""
3219 pxSize: Size
3220 """Map size in pixels."""
3221 dpi: int
3222 """Resolution in dots per inch."""
3225class MapRenderInputPlaneType(Enum):
3226 """Type of a map render input plane."""
3228 features = 'features'
3229 """A list of features, rendered as SVG."""
3230 image = 'image'
3231 """A raster image."""
3232 imageLayer = 'imageLayer'
3233 """A layer, rendered as an image."""
3234 svgLayer = 'svgLayer'
3235 """A layer, rendered as SVG."""
3236 svgSoup = 'svgSoup'
3237 """An SVG soup, a resolution-independent drawing, see ``gws.lib.svg.soup_to_fragment``."""
3240class MapRenderInputPlane(Data):
3241 """A plane of a map to render."""
3243 type: MapRenderInputPlaneType
3244 """Plane type."""
3245 features: list['Feature']
3246 """Features, for the ``features`` type."""
3247 image: 'Image'
3248 """Image, for the ``image`` type."""
3249 layer: 'Layer'
3250 """Layer, for the ``imageLayer`` and ``svgLayer`` types."""
3251 opacity: float
3252 """Opacity from 0 to 1, defaults to the layer opacity or 1."""
3253 soupPoints: list[Point]
3254 """Points in map coordinates, for the ``svgSoup`` type."""
3255 soupTags: list[Any]
3256 """Tags that refer to the points, for the ``svgSoup`` type."""
3257 styles: list['Style']
3258 """Styles. For ``features``, matched by CSS selector; for ``svgLayer``, the first style is used."""
3259 compositeLayerUids: list[str]
3260 """Child layers to render in one composite image, for the ``imageLayer`` type."""
3263class MapRenderInput(Data):
3264 """Input of the map renderer."""
3266 backgroundColor: int
3267 """Background color of the first raster plane."""
3268 bbox: Extent
3269 """Bounding box of the map. If not set, ``center`` and ``scale`` are used."""
3270 center: Point
3271 """Center point of the map."""
3272 targetCrs: 'Crs'
3273 """CRS of the map."""
3274 dpi: int
3275 """Resolution of raster planes, for maps sized in mm."""
3276 mapSize: UomSize
3277 """Map size in mm or pixels."""
3278 notify: Callable
3279 """Callback, called with an event name and the plane before and after each plane is rendered."""
3280 planes: list['MapRenderInputPlane']
3281 """Planes to render, top to bottom."""
3282 project: 'Project'
3283 """Project of the map."""
3284 rotation: int
3285 """Rotation angle in degrees."""
3286 scale: int
3287 """Scale denominator, used with ``center``."""
3288 user: 'User'
3289 """User who requests the map."""
3290 visibleLayers: Optional[list['Layer']]
3291 """Visible layers of the map."""
3294class MapRenderOutputPlaneType(Enum):
3295 """Type of a map render output plane."""
3297 image = 'image'
3298 """A raster image."""
3299 path = 'path'
3300 """A path to an image file."""
3301 svg = 'svg'
3302 """A list of SVG elements."""
3305class MapRenderOutputPlane(Data):
3306 """A plane of a rendered map."""
3308 type: MapRenderOutputPlaneType
3309 """Plane type."""
3310 path: str
3311 """Image file path, for the ``path`` type."""
3312 elements: list[XmlElement]
3313 """SVG elements, for the ``svg`` type."""
3314 image: 'Image'
3315 """Image, for the ``image`` type."""
3318class MapRenderOutput(Data):
3319 """Output of the map renderer."""
3321 planes: list['MapRenderOutputPlane']
3322 """Rendered planes, bottom to top."""
3323 view: MapView
3324 """Map view of the vector planes."""
3327class LayerRenderInputType(Enum):
3328 """Type of a layer render request."""
3330 box = 'box'
3331 """Render an image of the view extent."""
3332 tile = 'tile'
3333 """Render a tile of the layer grid."""
3334 svg = 'svg'
3335 """Render SVG elements for the view."""
3338class LayerRenderInput(Data):
3339 """Input of a layer render request."""
3341 extraParams: dict
3342 """Additional request parameters, e.g. ``compositeLayerUids``."""
3343 renderParams: dict
3344 """Parameters set by the layer for its grabber. Non-empty params mark a dynamic, uncached request."""
3345 project: 'Project'
3346 """Project of the request."""
3347 style: 'Style'
3348 """Style for the ``svg`` type."""
3349 targetCrs: 'Crs'
3350 """CRS of the output."""
3351 type: LayerRenderInputType
3352 """Request type."""
3353 user: 'User'
3354 """User who requests the rendering."""
3355 view: MapView
3356 """Map view, for the ``box`` and ``svg`` types."""
3357 x: int
3358 """Tile column, for the ``tile`` type."""
3359 y: int
3360 """Tile row, for the ``tile`` type."""
3361 z: int
3362 """Zoom level, for the ``tile`` type."""
3365class LayerRenderOutput(Data):
3366 """Output of a layer render request."""
3368 content: bytes
3369 """Encoded image, for the ``box`` and ``tile`` types."""
3370 tags: list[XmlElement]
3371 """SVG elements, for the ``svg`` type."""
3372################################################################################
3375################################################################################
3376# /gis/source/types.pyinc
3379class SourceStyle(Data):
3380 """A style of a source layer, as listed in the capabilities of a service."""
3382 isDefault: bool
3383 """The style is the default style of the layer."""
3384 legendUrl: Url
3385 """URL of the legend image."""
3386 metadata: 'Metadata'
3387 """Style metadata."""
3388 name: str
3389 """Style name."""
3392class SourceLayer(Data):
3393 """A layer of an external source, such as a WMS, WFS or WMTS service or a QGIS project.
3395 Source layers are read from capabilities and form a tree. The ``a*`` properties
3396 are set by ``gws.gis.source.check_layers``.
3397 """
3399 aLevel: int
3400 """Depth in the layer tree, 1 for top-level layers."""
3401 aPath: str
3402 """Path of uids from the top of the tree, e.g. ``/root/roads``."""
3403 aUid: str
3404 """Uid derived from the name or title."""
3406 dataSource: dict
3407 """Parsed data source of a QGIS layer."""
3408 metadata: 'Metadata'
3409 """Layer metadata."""
3411 supportedCrs: list['Crs']
3412 """CRS supported by the source for this layer."""
3413 wgsExtent: Extent
3414 """Layer extent in WGS84."""
3416 isExpanded: bool
3417 """The layer is expanded in the source layer tree."""
3418 isGroup: bool
3419 """The layer is a group."""
3420 isImage: bool
3421 """The layer can be rendered as an image."""
3422 isQueryable: bool
3423 """The layer can be queried for features."""
3424 isReadOnly: bool
3425 """The layer has the readOnly flag set."""
3426 isVisible: bool
3427 """The layer is visible by default."""
3429 layers: list['SourceLayer']
3430 """Sub-layers."""
3432 name: str
3433 """Layer name, used in requests to the source."""
3434 title: str
3435 """Layer title."""
3437 legendUrl: Url
3438 """URL of the legend image."""
3439 opacity: float
3440 """Layer opacity from 0 to 1."""
3441 scaleRange: list[float]
3442 """Min. and max. scale denominators at which the layer is visible."""
3444 styles: list[SourceStyle]
3445 """Available styles."""
3446 defaultStyle: Optional[SourceStyle]
3447 """Default style."""
3449 tileMatrixIds: list[str]
3450 """Ids of the WMTS tile matrix sets the layer links to."""
3451 tileMatrixSets: list[TileMatrixSet]
3452 """WMTS tile matrix sets of the layer."""
3453 imageFormat: str
3454 """Image format for WMTS requests."""
3455 resourceUrls: dict
3456 """WMTS resource URL templates, keyed by resource type."""
3458 sourceId: str
3459 """Id of the layer in the source, e.g. the QGIS layer id."""
3460 properties: dict
3461 """Custom properties of a QGIS layer."""
3462################################################################################
3466################################################################################
3467# /config/types.pyinc
3470class ConfigLocation(Data):
3471 """Location in the configuration tree."""
3473 objectUid: str
3474 """UID of the object."""
3475 objectType: str
3476 """Type of the object."""
3477 objectName: str
3478 """Name of the object."""
3479 propName: str
3480 """Property of the parent this object is located at."""
3483class ConfigErrorInfo(Data):
3484 """Full information about a configuration error."""
3486 message: str
3487 """Error message."""
3488 path: str
3489 """Path to the configuration file."""
3490 line: int
3491 """Line number where the error occurred."""
3492 value: str
3493 """Value that caused the error."""
3494 stack: list[ConfigLocation]
3495 """Locations of the objects being configured when the error occurred, innermost first."""
3496 contextLines: list[str]
3497 """Source lines around the error, with line numbers, the error line is marked with ``>>>``."""
3498 cause: str
3499 """Representation of the exception that caused the error."""
3502class ConfigContext(Data):
3503 """Shared state for parsing and validating a configuration."""
3505 specs: SpecRuntime
3506 """Specs used to validate the configuration."""
3507 readOptions: set[SpecReadOption]
3508 """Options passed to the spec reader."""
3509 errors: list[ConfigErrorInfo]
3510 """Errors collected so far."""
3511 warnings: list[ConfigErrorInfo]
3512 """Warnings collected so far."""
3513 paths: set[str]
3514 """Paths of all configuration files that were read, including included files."""
3518class ConfigResult(Data):
3519 """Result of a configuration run."""
3521 root: Optional['Root']
3522 """Configured root object, or ``None`` if configuration failed or was not requested."""
3523 config: Optional['Config']
3524 """Parsed application configuration."""
3525 errors: list[ConfigErrorInfo]
3526 """Configuration errors."""
3527 warnings: list[ConfigErrorInfo]
3528 """Configuration warnings."""
3529 info: str
3530 """Summary with the number of objects, time and memory used."""
3531################################################################################
3534################################################################################
3535# /server/types.pyinc
3538class ServerManager(Node):
3539 """Server configuration manager.
3541 Holds the ``server`` configuration and creates the configuration files for
3542 the embedded servers and the server start script.
3543 """
3545 templates: list['Template']
3546 """Templates for the server configuration files and the start script."""
3548 def create_server_configs(self, target_dir: str, script_path: str, pid_paths: dict):
3549 """Create the server configuration files and the start script.
3551 Args:
3552 target_dir: Directory for the configuration files.
3553 script_path: Path of the start script.
3554 pid_paths: Paths of the pid files, keyed by server name (``web``, ``spool``, ``nginx``).
3555 """
3558class ServerMonitor(Node):
3559 """Server monitor.
3561 Watches configuration files and directories and reconfigures the server
3562 when they change, and runs periodic tasks of registered objects.
3563 """
3565 def watch_directory(self, path: str, pattern: 'Regex', recursive=False):
3566 """Add a directory to watch.
3568 Args:
3569 path: Directory path.
3570 pattern: Regex pattern for file names to watch.
3571 recursive: Also watch subdirectories.
3572 """
3574 def watch_file(self, path: str):
3575 """Add a file to watch.
3577 Args:
3578 path: File path.
3579 """
3581 def register_periodic_task(self, obj: Node, frequency: int = 0):
3582 """Register an object as a periodic task handler.
3584 Args:
3585 obj: A node with a ``periodic_task`` method.
3586 frequency: Interval between runs in seconds, the monitor default if 0.
3588 Raises:
3589 ``gws.Error``: If the object has no ``periodic_task`` method.
3590 """
3592 def schedule_reload(self, with_reconfigure: bool = False):
3593 """Schedule a reload of the web and spool backends.
3595 The reload is performed by the monitor on its next tick.
3597 Args:
3598 with_reconfigure: Reconfigure the server before reloading.
3599 """
3601 def start(self):
3602 """Start watching files and register the timer that drives the monitor.
3604 Must be called in a uWSGI process.
3605 """
3606################################################################################
3610################################################################################
3611# /base/metadata/types.pyinc
3614class MetadataLink(Data):
3615 """Link to a metadata document or another resource related to an object."""
3617 about: str
3618 """Aspect of the object the link describes."""
3619 description: str
3620 """Description of the linked resource."""
3621 format: str
3622 """Format of the linked resource."""
3623 formatVersion: str
3624 """Version of the format of the linked resource."""
3625 function: str
3626 """Function of the link."""
3627 mimeType: str
3628 """MIME type of the linked resource."""
3629 scheme: str
3630 """Link scheme or protocol."""
3631 title: str
3632 """Link title."""
3633 type: str
3634 """Link type."""
3635 url: str
3636 """Link URL."""
3639class Metadata(Data):
3640 """Metadata of an object, used in the client, in OWS services and in catalog records."""
3642 name: str
3643 """Object name."""
3644 title: str
3645 """Object title."""
3647 abstract: str
3648 """Abstract, a brief description of the object."""
3649 accessConstraints: str
3650 """Access constraints."""
3651 accessConstraintsType: str
3652 """Type of the access constraints."""
3653 attribution: str
3654 """Attribution text."""
3655 attributionUrl: str
3656 """URL of the attribution."""
3657 dateCreated: Optional['datetime.datetime']
3658 """Creation date."""
3659 dateUpdated: Optional['datetime.datetime']
3660 """Last update date."""
3661 fees: str
3662 """Fees for using the object."""
3663 image: str
3664 """Image URL or path associated with the object."""
3665 keywords: list[str]
3666 """Keywords, optionally prefixed with a vocabulary, e.g. ``gemet:river``."""
3667 license: str
3668 """License text."""
3669 licenseUrl: str
3670 """License URL."""
3672 contactAddress: str
3673 """Street address of the contact."""
3674 contactAddressType: str
3675 """Type of the contact address."""
3676 contactArea: str
3677 """Administrative area, state or province of the contact address."""
3678 contactCity: str
3679 """Contact city."""
3680 contactCountry: str
3681 """Contact country."""
3682 contactEmail: str
3683 """Contact email address."""
3684 contactFax: str
3685 """Contact fax number."""
3686 contactOrganization: str
3687 """Contact organization."""
3688 contactPerson: str
3689 """Contact person name."""
3690 contactPhone: str
3691 """Contact phone number."""
3692 contactPosition: str
3693 """Contact position or job title."""
3694 contactProviderName: str
3695 """Name of the service provider."""
3696 contactProviderSite: str
3697 """Website of the service provider."""
3698 contactRole: str
3699 """Role of the contact, an ISO ``CI_RoleCode`` value."""
3700 contactUrl: str
3701 """Website of the contact."""
3702 contactZip: str
3703 """Contact postal code."""
3705 authorityIdentifier: str
3706 """Identifier issued by the authority."""
3707 authorityName: str
3708 """Name of the authority that issues identifiers."""
3709 authorityUrl: str
3710 """URL of the authority that issues identifiers."""
3712 metaLinks: list[MetadataLink]
3713 """Links to metadata documents."""
3714 serviceMetadataURL: str
3715 """URL of the service metadata document."""
3717 catalogCitationUid: str
3718 """Identifier of the resource in catalog records."""
3719 catalogUid: str
3720 """Identifier of the metadata record."""
3722 language: str
3723 """Language as an ISO 639-1 code."""
3724 language3: str
3725 """Language as an ISO 639-2 three-letter code, derived from ``language``."""
3726 languageBib: str
3727 """Language as an ISO 639-2 bibliographic code, derived from ``language``."""
3728 languageName: str
3729 """Name of the language."""
3731 parentIdentifier: str
3732 """Identifier of the parent metadata record."""
3733 wgsExtent: Optional[Extent]
3734 """Geographic extent in WGS84."""
3735 crs: Optional['Crs']
3736 """Reference system of the data."""
3737 temporalBegin: Optional['datetime.datetime']
3738 """Start of the temporal extent."""
3739 temporalEnd: Optional['datetime.datetime']
3740 """End of the temporal extent."""
3742 inspireMandatoryKeyword: str
3743 """INSPIRE mandatory keyword (service type)."""
3744 inspireDegreeOfConformity: str
3745 """Degree of conformity with the INSPIRE implementing rules."""
3746 inspireResourceType: str
3747 """INSPIRE resource type."""
3748 inspireSpatialDataServiceType: str
3749 """INSPIRE spatial data service type."""
3750 inspireSpatialScope: str
3751 """INSPIRE spatial scope."""
3752 inspireSpatialScopeName: str
3753 """Display name of the INSPIRE spatial scope."""
3754 inspireTheme: str
3755 """INSPIRE data theme code."""
3757 inspireThemeNameLocal: str
3758 """Name of the INSPIRE theme in the metadata language, derived from ``inspireTheme``."""
3759 inspireThemeNameEn: str
3760 """English name of the INSPIRE theme, derived from ``inspireTheme``."""
3762 isoMaintenanceFrequencyCode: str
3763 """How often the data is updated."""
3764 isoQualityConformanceExplanation: str
3765 """Explanation of the conformance result."""
3766 isoQualityConformanceQualityPass: bool
3767 """The data passes the conformance test."""
3768 isoQualityConformanceSpecificationDate: str
3769 """Publication date of the conformance specification."""
3770 isoQualityConformanceSpecificationTitle: str
3771 """Title of the conformance specification."""
3772 isoQualityLineageSource: str
3773 """Description of the source data."""
3774 isoQualityLineageSourceScale: int
3775 """Scale denominator of the source data."""
3776 isoQualityLineageStatement: str
3777 """Statement on the lineage of the data."""
3778 isoRestrictionCode: str
3779 """Restrictions on access or use of the data."""
3780 isoServiceFunction: str
3781 """ISO service function."""
3782 isoScope: str
3783 """Scope of the metadata."""
3784 isoScopeName: str
3785 """Name of the scope."""
3786 isoSpatialRepresentationType: str
3787 """How the data is represented spatially."""
3788 isoTopicCategories: list[str]
3789 """ISO 19115 topic categories."""
3790 isoSpatialResolution: int
3791 """Spatial resolution as a scale denominator."""
3792################################################################################
3795################################################################################
3796# /base/feature/types.pyinc
3799FeatureUid: TypeAlias = str
3800"""Unique Feature id."""
3802class FeatureRecord(Data):
3803 """Raw data from a feature source."""
3805 attributes: dict
3806 """Attribute values as read from the source or as written to it."""
3807 meta: dict
3808 """Extra source information, e.g. ``layerName`` for features from OWS responses."""
3809 uid: Optional[str]
3810 """Feature id provided by the source."""
3811 shape: Optional['Shape']
3812 """Geometry provided by the source."""
3813 ewkt: str
3814 """Geometry as EWKT, provided by some sources."""
3817class FeatureProps(Props):
3818 """Feature Proprieties."""
3820 attributes: dict
3821 category: Optional[str]
3822 cssSelector: str
3823 errors: Optional[list['ModelValidationError']]
3824 createWithFeatures: Optional[list['FeatureProps']]
3825 isNew: bool
3826 modelUid: str
3827 uid: str
3828 views: dict
3831class Feature:
3832 """Feature object.
3834 A set of named attributes that belongs to a model. The model defines the
3835 uid attribute (``uidName``) and the geometry attribute (``geometryName``).
3836 """
3838 attributes: dict
3839 """Attribute values as python values."""
3840 category: str
3841 """Category for grouping features in the client, e.g. the source layer name."""
3842 cssSelector: str
3843 """CSS selector for the feature style in the client."""
3844 errors: list['ModelValidationError']
3845 """Validation errors."""
3846 isNew: bool
3847 """The feature is new and not yet saved."""
3848 model: 'Model'
3849 """Model the feature belongs to."""
3850 props: 'FeatureProps'
3851 """Data from or for the client."""
3852 record: 'FeatureRecord'
3853 """Raw data from or for the source."""
3854 views: dict
3855 """Rendered views, keyed by view name, e.g. ``title`` or ``label``."""
3856 createWithFeatures: list['Feature']
3857 """Related features a new feature is created with."""
3858 insertedPrimaryKey: Optional[int | str]
3859 """Primary key of the row inserted when the feature was created."""
3861 def get(self, name: str, default=None) -> Any:
3862 """Get an attribute value.
3864 Args:
3865 name: Attribute name.
3866 default: Value to return if the attribute does not exist.
3868 Returns:
3869 The attribute value, or ``default``.
3870 """
3872 def has(self, name: str) -> bool:
3873 """Check if an attribute exists.
3875 Args:
3876 name: Attribute name.
3878 Returns:
3879 ``True`` if the attribute exists.
3880 """
3882 def set(self, name: str, value: Any) -> 'Feature':
3883 """Set an attribute value.
3885 Args:
3886 name: Attribute name.
3887 value: Attribute value.
3889 Returns:
3890 The feature itself.
3891 """
3893 def raw(self, name: str) -> Any:
3894 """Get a raw attribute value from the record.
3896 Args:
3897 name: Attribute name.
3899 Returns:
3900 The value, or ``None`` if the record has no such attribute.
3901 """
3903 def render_views(self, templates: list['Template'], **kwargs) -> 'Feature':
3904 """Render feature views and store them in ``views``.
3906 Each template renders the view named after the last part of its subject,
3907 e.g. ``feature.title`` renders ``title``. The templates receive the
3908 feature attributes, ``feature`` and the extra arguments.
3910 Args:
3911 templates: Feature templates.
3912 **kwargs: Extra template arguments.
3914 Returns:
3915 The feature itself.
3916 """
3918 def shape(self) -> Optional['Shape']:
3919 """Get the feature geometry.
3921 Returns:
3922 The geometry, or ``None`` if the model has no geometry or the feature has no value.
3923 """
3925 def to_svg(self, view: 'MapView', label: Optional[str] = None, style: Optional['Style'] = None) -> list[XmlElement]:
3926 """Render the feature geometry as SVG fragments for a map view.
3928 Args:
3929 view: Map view. The geometry is transformed to its CRS.
3930 label: Label text.
3931 style: Style.
3933 Returns:
3934 A list of SVG elements, empty if the feature has no geometry.
3935 """
3937 def to_geojson(self, keep_crs=False) -> dict:
3938 """Convert the feature to a GeoJSON feature.
3940 The geometry is converted to WGS84 unless ``keep_crs`` is set. The uid
3941 is added as the ``id`` property.
3943 Args:
3944 keep_crs: Keep the geometry coordinates in the feature CRS.
3946 Returns:
3947 A GeoJSON feature dict.
3948 """
3950 def transform_to(self, crs: 'Crs') -> 'Feature':
3951 """Transform the feature geometry to another CRS, in place.
3953 Args:
3954 crs: Target CRS.
3956 Returns:
3957 The feature itself.
3958 """
3960 def uid(self) -> FeatureUid:
3961 """Get the unique id of the feature.
3963 Returns:
3964 The value of the uid attribute as a string, an empty string if the model
3965 has no uid attribute, or ``None`` if the feature has no value.
3966 """
3967################################################################################
3971################################################################################
3972# /base/action/types.pyinc
3975class ActionManager(Node):
3976 """Action manager.
3978 Locates actions in projects and the application and prepares command calls.
3979 """
3981 def actions_for_project(self, project: 'Project', user: 'User') -> list['Action']:
3982 """Get the actions a user can use in a project.
3984 Includes the project actions and the application actions, one action per type.
3985 A project action takes precedence over an application action of the same type.
3987 Args:
3988 project: The project.
3989 user: The user.
3991 Returns:
3992 A list of actions.
3993 """
3995 def find_action(self, project: Optional['Project'], ext_type: str, user: 'User') -> Optional['Action']:
3996 """Find an action by its type.
3998 Searches the project actions first, if a project is given, then the application actions.
4000 Args:
4001 project: The project, or ``None`` to search the application actions only.
4002 ext_type: Action type, for example ``map``.
4003 user: The user who wants to use the action.
4005 Returns:
4006 The action object, or ``None`` if not found.
4008 Raises:
4009 ForbiddenError: If the action is found but the user may not use it.
4010 """
4012 def prepare_action(
4013 self,
4014 command_category: CommandCategory,
4015 command_name: str,
4016 params: dict,
4017 path: str,
4018 user: 'User',
4019 read_options: Optional[set[SpecReadOption]]=None,
4020 ) -> tuple[Callable, Request]:
4021 """Prepare a command call.
4023 Parses the parameters into the command's request type, finds the action
4024 that owns the command (in the requested project, then in the application)
4025 and checks the user's access.
4027 Args:
4028 command_category: Command category.
4029 command_name: Command name, for example ``mapDescribeLayer``.
4030 params: Raw request parameters.
4031 path: Request path; for ``raw`` commands, the project uid can be given as a ``/projectUid/<uid>`` segment.
4032 user: The user who runs the command.
4033 read_options: Options for the spec reader.
4035 Returns:
4036 A tuple of the bound command method and the parsed request object.
4038 Raises:
4039 NotFoundError: If the command, the project or the action is not found.
4040 BadRequestError: If the parameters cannot be parsed.
4041 ForbiddenError: If the user may not use the project or the action.
4042 """
4045class Action(Node):
4046 """Server action.
4048 An action is a configurable object that provides server commands.
4049 """
4050################################################################################
4053################################################################################
4054# /base/auth/types.pyinc
4057class User(Object):
4058 """User.
4060 A user has a set of roles, which are checked against the permissions of
4061 objects to decide access.
4062 """
4064 isGuest: bool
4065 """The user is the guest user."""
4067 authProvider: 'AuthProvider'
4068 """The provider that created the user."""
4070 attributes: dict
4071 """Public user attributes, sent to the client."""
4072 data: dict
4073 """Private user data from the provider."""
4074 roles: set[str]
4075 """User roles."""
4076 uid: str
4077 """Global user uid, made of the provider uid and the local uid."""
4079 authToken: str
4080 """Token for the ``token`` authentication method."""
4081 displayName: str
4082 """User display name."""
4083 email: str
4084 """User email."""
4085 localUid: str
4086 """User uid within its provider."""
4087 loginName: str
4088 """User login name."""
4089 mfaUid: str
4090 """Uid of the multi-factor adapter for this user, empty if none."""
4091 mfaSecret: str
4092 """Secret for the multi-factor adapter."""
4094 def acl_bit(self, access: Access, obj: Object) -> Optional[int]:
4095 """Get the access decision for an object itself, without parents.
4097 Args:
4098 access: Access mode.
4099 obj: The object.
4101 Returns:
4102 ``gws.c.ALLOW`` or ``gws.c.DENY`` if the object's permissions decide
4103 for one of the user's roles, ``None`` otherwise.
4104 """
4106 def can(self, access: Access, obj: Object, *context) -> bool:
4107 """Check if the user can access an object.
4109 If the object's permissions do not decide, the context objects are
4110 checked in turn, then the parents of the last checked object.
4112 Args:
4113 access: Access mode.
4114 obj: The object.
4115 *context: Further objects to check, before the parents.
4117 Returns:
4118 ``True`` if access is granted.
4119 """
4121 def can_create(self, obj: Object, *context) -> bool:
4122 """Check if the user has the ``create`` permission on an object.
4124 Args:
4125 obj: The object.
4126 *context: Further objects to check, before the parents.
4128 Returns:
4129 ``True`` if access is granted.
4130 """
4132 def can_delete(self, obj: Object, *context) -> bool:
4133 """Check if the user has the ``delete`` permission on an object.
4135 Args:
4136 obj: The object.
4137 *context: Further objects to check, before the parents.
4139 Returns:
4140 ``True`` if access is granted.
4141 """
4143 def can_read(self, obj: Object, *context) -> bool:
4144 """Check if the user has the ``read`` permission on an object.
4146 Args:
4147 obj: The object.
4148 *context: Further objects to check, before the parents.
4150 Returns:
4151 ``True`` if access is granted.
4152 """
4154 def can_use(self, obj: Object, *context) -> bool:
4155 """Check if the user can use an object, which requires the ``read`` permission.
4157 Args:
4158 obj: The object.
4159 *context: Further objects to check, before the parents.
4161 Returns:
4162 ``True`` if access is granted.
4163 """
4165 def can_write(self, obj: Object, *context) -> bool:
4166 """Check if the user has the ``write`` permission on an object.
4168 Args:
4169 obj: The object.
4170 *context: Further objects to check, before the parents.
4172 Returns:
4173 ``True`` if access is granted.
4174 """
4176 def can_edit(self, obj: Object, *context) -> bool:
4177 """Check if the user has any of the ``write``, ``create`` or ``delete`` permissions on an object.
4179 Args:
4180 obj: The object.
4181 *context: Further objects to check, before the parents.
4183 Returns:
4184 ``True`` if access is granted.
4185 """
4187 def has_role(self, role: str) -> bool:
4188 """Check if the user has a role.
4190 Args:
4191 role: Role name.
4193 Returns:
4194 ``True`` if the user has the role.
4195 """
4197 def acquire(self, uid: str = None, classref: Optional[ClassRef] = None, access: Optional[Access] = None) -> Optional[Object]:
4198 """Get an object by uid, if the user can access it.
4200 Args:
4201 uid: Object uid.
4202 classref: Class reference. If provided, the object must match it.
4203 access: Access mode, ``Access.read`` if omitted.
4205 Returns:
4206 The object, or ``None`` if it does not exist or the user may not access it.
4207 """
4209 def require(self, uid: str = None, classref: Optional[ClassRef] = None, access: Optional[Access] = None) -> Object:
4210 """Get an object by uid and fail if it is not found or not accessible.
4212 Args:
4213 uid: Object uid.
4214 classref: Class reference. If provided, the object must match it.
4215 access: Access mode, ``Access.read`` if omitted.
4217 Returns:
4218 The object.
4220 Raises:
4221 NotFoundError: If the object does not exist.
4222 ForbiddenError: If the user may not access the object.
4223 """
4225 def require_project(self, uid: str = None) -> 'Project':
4226 """Get a project the user can read.
4228 Args:
4229 uid: Project uid.
4231 Returns:
4232 The project.
4234 Raises:
4235 NotFoundError: If the project does not exist.
4236 ForbiddenError: If the user may not read the project.
4237 """
4239 def require_layer(self, uid=None) -> 'Layer':
4240 """Get a layer the user can read.
4242 Args:
4243 uid: Layer uid.
4245 Returns:
4246 The layer.
4248 Raises:
4249 NotFoundError: If the layer does not exist.
4250 ForbiddenError: If the user may not read the layer.
4251 """
4254class AuthManager(Node):
4255 """Authorization manager.
4257 Holds the authentication methods, providers, multi-factor adapters and the
4258 session manager, authenticates users and opens a session for every web request.
4259 """
4261 guestSession: 'AuthSession'
4262 """Session of the guest user, used for requests without a session."""
4264 guestUser: 'User'
4265 """The guest user."""
4266 systemUser: 'User'
4267 """The system user, allowed everything."""
4269 providers: list['AuthProvider']
4270 """Authentication providers."""
4271 methods: list['AuthMethod']
4272 """Authentication methods."""
4273 mfAdapters: list['AuthMultiFactorAdapter']
4274 """Multi-factor adapters."""
4276 sessionMgr: 'AuthSessionManager'
4277 """Session manager."""
4279 def authenticate(self, method: 'AuthMethod', credentials: Data, req: 'WebRequester') -> Optional['User']:
4280 """Authenticate a user with the providers that allow the method.
4282 Args:
4283 method: The authentication method.
4284 credentials: The credentials, for example ``username`` and ``password``.
4285 req: The web request.
4287 Returns:
4288 The user, or ``None`` if no provider accepts the credentials.
4290 Raises:
4291 ForbiddenError: If a provider rejects the credentials.
4292 TooManyRequestsError: If the attempt is blocked by the throttle.
4293 """
4295 def create_transient_session(self, method: 'AuthMethod', user: 'User', data: Optional[dict] = None) -> 'AuthSession':
4296 """Create a session that lives only for the duration of the request.
4298 The session is not stored in the session manager.
4300 Args:
4301 method: The method that creates the session.
4302 user: The session user.
4303 data: Session data.
4305 Returns:
4306 A new session.
4307 """
4309 def get_user(self, user_uid: str) -> Optional['User']:
4310 """Get a user by its global uid.
4312 Args:
4313 user_uid: Global user uid.
4315 Returns:
4316 The user, or ``None`` if the provider is not found or does not return the user.
4317 """
4319 def add_provider(self, provider: 'AuthProvider'):
4320 """Add an authentication provider.
4322 Args:
4323 provider: The provider.
4324 """
4326 def add_method(self, method: 'AuthMethod'):
4327 """Add an authentication method.
4329 Args:
4330 method: The method.
4331 """
4333 def add_multi_factor_adapter(self, adapter: 'AuthMultiFactorAdapter'):
4334 """Add a multi-factor adapter.
4336 Args:
4337 adapter: The adapter.
4338 """
4340 def can_use_method(self, req: 'WebRequester', method: 'AuthMethod') -> bool:
4341 """Check if a method may be used for a request.
4343 A secure method can only be used on secure requests, or from the addresses
4344 listed in its ``allowInsecureFrom``.
4346 Args:
4347 req: The web request.
4348 method: The method.
4350 Returns:
4351 ``True`` if the method may be used.
4352 """
4354 def get_provider(self, uid: str) -> Optional['AuthProvider']:
4355 """Get an authentication provider by its uid.
4357 Args:
4358 uid: Provider uid.
4360 Returns:
4361 The provider, or ``None`` if not found.
4362 """
4364 def get_method(self, uid: str) -> Optional['AuthMethod']:
4365 """Get an authentication method by its uid.
4367 Args:
4368 uid: Method uid.
4370 Returns:
4371 The method, or ``None`` if not found.
4372 """
4374 def get_multi_factor_adapter(self, uid: str) -> Optional['AuthMultiFactorAdapter']:
4375 """Get a multi-factor adapter by its uid.
4377 Args:
4378 uid: Adapter uid.
4380 Returns:
4381 The adapter, or ``None`` if not found.
4382 """
4384 def serialize_user(self, user: 'User') -> str:
4385 """Serialize a user to a string, together with its provider uid.
4387 Args:
4388 user: The user.
4390 Returns:
4391 A JSON string.
4392 """
4394 def unserialize_user(self, ser: str) -> Optional['User']:
4395 """Restore a user serialized by ``serialize_user``.
4397 Args:
4398 ser: The serialized user.
4400 Returns:
4401 The user, or ``None`` if the provider is not found.
4402 """
4404 def is_public_object(self, obj: Object, *context) -> bool:
4405 """Check if the guest user can read an object.
4407 Args:
4408 obj: The object.
4409 *context: Further objects to check, before the parents.
4411 Returns:
4412 ``True`` if the object is public.
4413 """
4416class AuthMethod(Node):
4417 """Authentication method.
4419 Defines how credentials and sessions are passed between the client and the
4420 server, for example as a login form and a session cookie.
4421 """
4423 secure: bool
4424 """The method may only be used on secure (HTTPS) requests."""
4426 allowInsecureFrom: list[str]
4427 """IP addresses from which the method may be used without HTTPS."""
4429 def open_session(self, req: 'WebRequester') -> Optional['AuthSession']:
4430 """Try to open a session for a request.
4432 Called at the start of every web request.
4434 Args:
4435 req: The web request.
4437 Returns:
4438 A session, or ``None`` if the request has no session for this method.
4439 """
4441 def close_session(self, req: 'WebRequester', res: 'WebResponder') -> None:
4442 """Close the session of a request.
4444 Called at the end of every web request whose session was opened by this
4445 method, for example to set or delete the session cookie.
4447 Args:
4448 req: The web request.
4449 res: The web response.
4450 """
4453class AuthMultiFactorState(Enum):
4454 """State of a multi-factor authentication transaction."""
4456 open = 'open'
4457 """The transaction is started and waits for verification."""
4458 ok = 'ok'
4459 """The verification was successful."""
4460 retry = 'retry'
4461 """The verification failed and can be retried."""
4462 failed = 'failed'
4463 """The transaction failed."""
4466class AuthMultiFactorTransaction(Data):
4467 """Multi-factor authentication transaction.
4469 Kept in the user's session from the login until the verification succeeds,
4470 fails or expires.
4471 """
4473 state: AuthMultiFactorState
4474 """Current state."""
4475 restartCount: int
4476 """Number of restarts."""
4477 verifyCount: int
4478 """Number of verification attempts."""
4479 secret: str
4480 """Secret for code generation."""
4481 startTime: int
4482 """Start time, as a Unix timestamp."""
4483 generateTime: int
4484 """Time when the code was last generated, as a Unix timestamp."""
4485 message: str
4486 """Message shown to the user."""
4487 adapter: 'AuthMultiFactorAdapter'
4488 """The adapter handling the transaction."""
4489 user: 'User'
4490 """The user who logs in."""
4493class AuthMultiFactorAdapter(Node):
4494 """Multi-factor authentication adapter.
4496 Provides the second verification step of a login, for example a code sent by
4497 email or generated by an authenticator app.
4498 """
4500 message: str
4501 """Message shown to the user during the verification step."""
4502 lifeTime: int
4503 """Time in seconds allowed to complete the verification."""
4504 maxRestarts: int
4505 """How often a transaction can be restarted."""
4506 maxVerifyAttempts: int
4507 """Number of verification attempts allowed."""
4509 def start(self, user: 'User') -> Optional[AuthMultiFactorTransaction]:
4510 """Start a transaction for a user.
4512 Args:
4513 user: The user who logs in.
4515 Returns:
4516 A new transaction, or ``None`` if the adapter cannot be used for this
4517 user, for example because a required user attribute is missing.
4518 """
4520 def verify(self, mfa: AuthMultiFactorTransaction, payload: dict) -> AuthMultiFactorTransaction:
4521 """Verify a payload submitted by the user.
4523 Args:
4524 mfa: The transaction.
4525 payload: The payload, for example ``{'code': '123456'}``.
4527 Returns:
4528 The transaction with an updated state.
4529 """
4531 def check_state(self, mfa: AuthMultiFactorTransaction) -> bool:
4532 """Check if a transaction is still valid, and mark it failed if not.
4534 Args:
4535 mfa: The transaction.
4537 Returns:
4538 ``True`` if the transaction is valid.
4539 """
4541 def check_restart(self, mfa: AuthMultiFactorTransaction) -> bool:
4542 """Check if a transaction can be restarted.
4544 Args:
4545 mfa: The transaction.
4547 Returns:
4548 ``True`` if a restart is allowed.
4549 """
4551 def restart(self, mfa: AuthMultiFactorTransaction) -> Optional[AuthMultiFactorTransaction]:
4552 """Restart a transaction, for example by sending a new code.
4554 Args:
4555 mfa: The transaction.
4557 Returns:
4558 A new transaction, or ``None`` if a restart is not possible.
4559 """
4561 def key_uri(self, secret: str | bytes, issuer_name: str, account_name: str) -> Optional[str]:
4562 """Generate a key URI for authenticator apps.
4564 Args:
4565 secret: The user's secret.
4566 issuer_name: Issuer name shown in the app.
4567 account_name: Account name shown in the app.
4569 Returns:
4570 An ``otpauth://`` URI, or ``None`` if the adapter does not support it.
4571 """
4574class AuthProvider(Node):
4575 """Authentication provider.
4577 A source of users, for example a file, an LDAP directory or a database table,
4578 which verifies credentials.
4579 """
4581 allowedMethods: list[str]
4582 """Method types this provider accepts, all methods if empty."""
4584 def get_user(self, local_uid: str) -> Optional['User']:
4585 """Get a user by its local uid.
4587 Args:
4588 local_uid: User uid within the provider.
4590 Returns:
4591 The user, or ``None`` if not found.
4592 """
4594 def authenticate(self, method: 'AuthMethod', credentials: Data) -> Optional['User']:
4595 """Authenticate a user.
4597 Args:
4598 method: The authentication method.
4599 credentials: The credentials, for example ``username`` and ``password``.
4601 Returns:
4602 The user, or ``None`` if the provider does not know the user.
4604 Raises:
4605 AuthenticationError: If the credentials are wrong or match more than one user.
4606 """
4608 def serialize_user(self, user: 'User') -> str:
4609 """Serialize a user to a string.
4611 Args:
4612 user: The user.
4614 Returns:
4615 The serialized user.
4616 """
4618 def unserialize_user(self, ser: str) -> Optional['User']:
4619 """Restore a user serialized by ``serialize_user``.
4621 Args:
4622 ser: The serialized user.
4624 Returns:
4625 The user, or ``None`` if it cannot be restored.
4626 """
4629class AuthSession:
4630 """Authentication session.
4632 Holds the user and arbitrary data between requests.
4633 """
4635 uid: str
4636 """Session uid."""
4637 method: Optional['AuthMethod']
4638 """The method that created the session, ``None`` for the guest session."""
4639 user: 'User'
4640 """The session user."""
4641 data: dict
4642 """Session data."""
4643 created: 'datetime.datetime'
4644 """Creation time."""
4645 updated: 'datetime.datetime'
4646 """Last update time."""
4647 isChanged: bool
4648 """The session data has changed since the session was loaded."""
4649 isTransient: bool
4650 """The session lives only for the duration of the request and is not stored."""
4652 def get(self, key: str, default=None):
4653 """Get a session data value.
4655 Args:
4656 key: Value name.
4657 default: Default value.
4659 Returns:
4660 The value, or the default if it is not set.
4661 """
4663 def set(self, key: str, value):
4664 """Set a session data value and mark the session as changed.
4666 Args:
4667 key: Value name.
4668 value: The value.
4669 """
4672class AuthSessionManager(Node):
4673 """Authentication session manager.
4675 Stores sessions persistently. A session is valid until ``lifeTime`` has passed
4676 since its last update, or ``maxLifeTime`` since its creation.
4677 """
4679 lifeTime: int
4680 """Session life time in seconds, counted from the last update."""
4682 maxLifeTime: int
4683 """Absolute session life time in seconds, counted from the creation, or 0 if not limited."""
4685 def create(self, method: 'AuthMethod', user: 'User', data: Optional[dict] = None) -> 'AuthSession':
4686 """Create and store a new session.
4688 Args:
4689 method: The method that creates the session.
4690 user: The session user.
4691 data: Session data.
4693 Returns:
4694 The new session.
4695 """
4697 def delete(self, sess: 'AuthSession'):
4698 """Delete a session.
4700 Args:
4701 sess: The session.
4702 """
4704 def delete_all(self):
4705 """Delete all sessions."""
4707 def get(self, uid: str) -> Optional['AuthSession']:
4708 """Get a valid session by its uid.
4710 Args:
4711 uid: Session uid.
4713 Returns:
4714 The session, or ``None`` if it does not exist or has expired.
4715 """
4717 def list_all(self) -> list['AuthSession']:
4718 """Get all stored sessions.
4720 Returns:
4721 A list of sessions.
4722 """
4724 def save(self, sess: 'AuthSession'):
4725 """Save the session data.
4727 Args:
4728 sess: The session.
4729 """
4731 def touch(self, sess: 'AuthSession'):
4732 """Update the last activity time of a session.
4734 Args:
4735 sess: The session.
4736 """
4738 def cleanup(self):
4739 """Remove expired sessions from the storage."""
4740################################################################################
4744################################################################################
4745# /base/layer/types.pyinc
4748class LayerDisplayMode(Enum):
4749 """How a layer is rendered."""
4751 box = 'box'
4752 """Render the map view as a single image."""
4753 tile = 'tile'
4754 """Render the layer as tiles of a grid."""
4755 client = 'client'
4756 """Let the client render the layer from its source."""
4759class FeatureLoadingStrategy(Enum):
4760 """When the client loads a layer's features."""
4762 all = 'all'
4763 """Load all features once, on first display."""
4764 bbox = 'bbox'
4765 """Reload features for the current map extent whenever it changes."""
4766 lazy = 'lazy'
4767 """Load features only when a search text is entered."""
4770class LayerOwsBinding(Node):
4771 """Binding of a layer to OWS services: access, names and models."""
4773 allowedServiceUids: list[str]
4774 """UIDs of services which can use this layer; empty means any."""
4775 deniedServiceUids: list[str]
4776 """UIDs of services which can not use this layer."""
4777 featureName: str
4778 """Name for features in this layer."""
4779 geometryName: str
4780 """Name for geometries in this layer."""
4781 layerName: str
4782 """Name for this layer in OWS services."""
4783 models: list['Model']
4784 """OWS-specific models."""
4785 xmlNamespace: Optional['XmlNamespace']
4786 """XML namespace for feature and layer names."""
4789class Layer(Node):
4790 """Layer object."""
4792 bounds: Bounds
4793 """Bounds in the map CRS: the WGS extent clipped to the parent extent and to the CRS."""
4794 canRenderBox: bool
4795 """The layer can render a single image for an arbitrary extent."""
4796 canRenderInClient: bool
4797 """The layer can be drawn by the client directly from its source (``display: client``)."""
4798 canRenderSvg: bool
4799 """The layer can render its features as SVG."""
4800 canRenderTile: bool
4801 """The layer can render tiles in a fixed grid."""
4802 cssSelector: str
4803 """CSS selector for feature styling."""
4804 displayMode: LayerDisplayMode
4805 """How the client displays the layer."""
4806 finders: list['Finder']
4807 """Search providers."""
4808 grabbers: dict[int, 'Grabber']
4809 """Grabbers by CRS code, one for each CRS the application supports."""
4810 hasLegend: bool
4811 """The layer has a legend."""
4812 imageFormat: ImageFormat
4813 """Image format for box and tile rendering."""
4814 isEnabledForOws: bool
4815 """The layer can be used by OWS services."""
4816 isGroup: bool
4817 """The layer is a group of other layers."""
4818 isSearchable: bool
4819 """The layer has at least one search provider."""
4820 layers: list['Layer']
4821 """Child layers."""
4822 legend: Optional['Legend']
4823 """Legend object."""
4824 loadingStrategy: FeatureLoadingStrategy
4825 """How the client loads features."""
4826 mapCrs: 'Crs'
4827 """CRS of the map this layer belongs to."""
4828 metadata: 'Metadata'
4829 """Layer metadata."""
4830 models: list['Model']
4831 """Data models."""
4832 opacity: float
4833 """Layer opacity, 0 to 1."""
4834 ows: 'LayerOwsBinding'
4835 """Binding to OWS services."""
4836 resolutions: list[float]
4837 """Resolutions the layer is visible at, in map units per pixel."""
4838 sourceLayers: list['SourceLayer']
4839 """Source layers this layer is built from."""
4840 templates: list['Template']
4841 """Layer templates."""
4842 title: str
4843 """Layer title."""
4844 wgsExtent: Extent
4845 """Layer extent in WGS84."""
4846 zoomBounds: Bounds
4847 """Bounds the client zooms to for this layer; defaults to ``bounds``."""
4849 def find_features(self, search: 'SearchQuery', user: 'User') -> list['Feature']:
4850 """Find features in the layer.
4852 Vector layers search in the first model the user can read; other
4853 layers return an empty list.
4855 Args:
4856 search: Search query.
4857 user: The user who searches.
4859 Returns:
4860 Found features.
4861 """
4863 def render(self, lri: LayerRenderInput) -> Optional['LayerRenderOutput']:
4864 """Render a box, a tile or an SVG fragment, depending on the input type.
4866 Args:
4867 lri: Render input.
4869 Returns:
4870 Render output with image content or SVG tags, or ``None`` if the
4871 layer has nothing to render.
4872 """
4874 def render_legend(self, args: Optional[dict | Data] = None) -> Optional['LegendRenderOutput']:
4875 """Render the layer legend.
4877 Without ``args`` the output is cached for the server lifetime.
4879 Args:
4880 args: Arguments passed to the legend renderer.
4882 Returns:
4883 Legend output, or ``None`` if the layer has no legend.
4884 """
4886 def url_path_for(self, kind: str) -> str:
4887 """Return the URL path for requests to this layer.
4889 Args:
4890 kind: ``box``, ``tile``, ``legend`` or ``features``. The ``tile``
4891 path contains ``{z}``, ``{x}`` and ``{y}`` placeholders.
4893 Returns:
4894 URL path.
4896 Raises:
4897 ``gws.Error``: If ``kind`` is not recognized.
4898 """
4899################################################################################
4902################################################################################
4903# /base/grabber/types.pyinc
4906class Grabber:
4907 """Raster grabber.
4909 Provides raster images for a layer: fetches them from a source, aligns them to a
4910 tile grid, stores and reads them back.
4911 """
4913 cache: MapCache
4914 """Cache settings; the name (``<layer cache name>_<srid>``) keys the tile store."""
4915 extent: Extent
4916 """Extent covered by this grabber, in the target CRS."""
4917 grid: MapGrid
4918 """The fixed target grid for the CRS."""
4919 imageFormat: ImageFormat
4920 """Format tiles are stored and returned in."""
4921 sourceCrs: Crs
4922 """Source CRS; defines the original CRS of the raster data."""
4923 store: 'TileStore'
4924 """Persistent tile store."""
4925 targetCrs: Crs
4926 """Target CRS; one grabber serves exactly one CRS."""
4928 def get_tile_as_bytes(self, mt: MapTile, params: Optional[dict] = None) -> bytes:
4929 """Return a single tile as an encoded image, composing and storing it if needed.
4931 A tile outside the layer's range is a transparent image.
4933 Args:
4934 mt: Tile.
4935 params: Dynamic request parameters. With ``params``, the persistent store is bypassed.
4937 Returns:
4938 The encoded tile.
4940 Raises:
4941 ``Exception``: Errors of the source request are passed through.
4942 """
4944 def get_tile_as_image(self, mt: MapTile, params: Optional[dict] = None) -> 'Image':
4945 """Return a single tile as an image, composing and storing it if needed.
4947 Same contract as ``get_tile_as_bytes``, decoded pixels instead of bytes.
4949 Args:
4950 mt: Tile.
4951 params: Dynamic request parameters. With ``params``, the persistent store is bypassed.
4953 Returns:
4954 The tile image.
4956 Raises:
4957 ``Exception``: Errors of the source request are passed through.
4958 """
4960 def get_tiles_as_bytes_dict(self, mtr: MapTileRange, params: Optional[dict] = None) -> dict[MapTile, bytes]:
4961 """Return a rectangular block of tiles as encoded images.
4963 Args:
4964 mtr: Tile range.
4965 params: Dynamic request parameters. With ``params``, the persistent store is bypassed.
4967 Returns:
4968 Encoded tiles, keyed by tile. Sparse: contains entries only for tiles present in the grid.
4970 Raises:
4971 ``Exception``: Errors of the source request are passed through.
4972 """
4974 def get_tiles_as_image_dict(self, mtr: MapTileRange, params: Optional[dict] = None) -> dict[MapTile, 'Image']:
4975 """Return a rectangular block of tiles as images.
4977 Same contract as ``get_tiles_as_bytes_dict``, decoded pixels instead of bytes.
4979 Args:
4980 mtr: Tile range.
4981 params: Dynamic request parameters. With ``params``, the persistent store is bypassed.
4983 Returns:
4984 Tile images, keyed by tile.
4986 Raises:
4987 ``Exception``: Errors of the source request are passed through.
4988 """
4990 def get_box_as_bytes(self, extent: Extent, w: int, h: int, params: Optional[dict] = None) -> bytes:
4991 """Return an encoded image for arbitrary extent and pixel size.
4993 A box overlapping no data is a transparent image.
4995 Args:
4996 extent: Extent in the target CRS.
4997 w: Width in pixels.
4998 h: Height in pixels.
4999 params: Dynamic request parameters. With ``params``, the persistent store is bypassed.
5001 Returns:
5002 The encoded image.
5004 Raises:
5005 ``Exception``: Errors of the source request are passed through.
5006 """
5008 def get_box_as_image(self, extent: Extent, w: int, h: int, params: Optional[dict] = None) -> 'Image':
5009 """Return an image for arbitrary extent and pixel size.
5011 Same contract as ``get_box_as_bytes``, decoded pixels instead of bytes.
5013 Args:
5014 extent: Extent in the target CRS.
5015 w: Width in pixels.
5016 h: Height in pixels.
5017 params: Dynamic request parameters. With ``params``, the persistent store is bypassed.
5019 Returns:
5020 The image.
5022 Raises:
5023 ``Exception``: Errors of the source request are passed through.
5024 """
5026 def levels(self) -> list[int]:
5027 """Return the levels this grabber supports.
5029 Returns:
5030 A list of levels.
5031 """
5033 def tile_range_for_level(self, z: int) -> MapTileRange:
5034 """Return the tile range covered by the grabber's extent at a level.
5036 Args:
5037 z: Level.
5039 Returns:
5040 The tile range in the grabber's grid.
5041 """
5042################################################################################
5045################################################################################
5046# /base/legend/types.pyinc
5049class LegendRenderOutput(Data):
5050 """Legend render output."""
5052 html: str
5053 """HTML representation of the legend; not set by the built-in legend types."""
5054 image: 'Image'
5055 """Legend image."""
5056 size: Size
5057 """Size of the legend image in pixels."""
5060class Legend(Node):
5061 """Legend object."""
5063 def render(self, args: Optional[dict | Data] = None) -> Optional[LegendRenderOutput]:
5064 """Render the legend.
5066 Args:
5067 args: Arguments for the renderer, for example template arguments.
5069 Returns:
5070 Legend output, or ``None`` if there is nothing to show.
5071 """
5072################################################################################
5075################################################################################
5076# /base/map/types.pyinc
5079class Map(Node):
5080 """Map object."""
5082 rootLayer: 'Layer'
5083 """Root group layer that holds the map layers."""
5085 bounds: Bounds
5086 """Map extent in the map CRS."""
5087 center: Point
5088 """Initial map center."""
5089 coordinatePrecision: int
5090 """Decimal places for coordinates."""
5091 initResolution: float
5092 """Initial resolution."""
5093 resolutions: list[float]
5094 """Resolutions the map can be displayed at, in map units per pixel."""
5095 title: str
5096 """Map title."""
5097 wgsExtent: Extent
5098 """Map extent in WGS84."""
5099################################################################################
5103################################################################################
5104# /base/model/types.pyinc
5107class ModelClientOptions(Data):
5108 """Client options for a model."""
5110 keepFormOpen: Optional[bool]
5111 """Keep the edit form open after saving."""
5114class ModelValidationError(Data):
5115 """Validation error of a feature field."""
5117 fieldName: str
5118 """Name of the field that failed validation."""
5119 message: str
5120 """Error message, or a message key for the client."""
5123class ModelOperation(Enum):
5124 """Model operation."""
5126 read = 'read'
5127 """Read features."""
5128 create = 'create'
5129 """Create new features."""
5130 update = 'update'
5131 """Update existing features."""
5132 delete = 'delete'
5133 """Delete features."""
5134 export = 'export'
5135 """Export features."""
5138class ModelReadTarget(Enum):
5139 """Target for the read operation."""
5141 map = 'map'
5142 """The feature is to be drawn on a map."""
5143 searchResults = 'searchResults'
5144 """The feature is to be displayed in the search results list."""
5145 list = 'list'
5146 """The feature is to be displayed in a list view."""
5147 editList = 'editList'
5148 """The feature is to be displayed in an editable list view."""
5149 editForm = 'editForm'
5150 """The feature is to be displayed in an edit form."""
5153class ModelSelectBuild(Data):
5154 """Parts of a database select statement, collected from the model fields."""
5156 columns: list['sqlalchemy.Column']
5157 """Columns to select."""
5158 geometryWhere: list
5159 """Conditions for the geometry search, combined with OR."""
5160 keywordWhere: list
5161 """Conditions for the keyword search, combined with OR."""
5162 where: list
5163 """Other conditions, combined with AND."""
5164 order: list
5165 """Sort expressions."""
5168class ModelContext(Data):
5169 """Context of a model operation."""
5171 op: ModelOperation
5172 """The operation."""
5173 target: ModelReadTarget
5174 """Where the features are to be displayed, for read operations."""
5175 user: 'User'
5176 """The user performing the operation."""
5177 project: Optional['Project']
5178 """The current project."""
5179 relDepth: int = 0
5180 """Current depth of related features."""
5181 maxDepth: int = 0
5182 """Maximum depth of related features to process."""
5183 search: 'SearchQuery'
5184 """The search query, for read operations."""
5185 dbSelect: ModelSelectBuild
5186 """The select statement being built, for database read operations."""
5189EmptyValue = object()
5190"""Special value for empty fields."""
5192ErrorValue = object()
5193"""Special value for invalid fields."""
5196class ModelWidget(Node):
5197 """Model widget.
5199 Describes how the client displays and edits a field value.
5200 """
5202 supportsTableView: bool = True
5203 """The widget can be used in the table view."""
5206class ModelValidator(Node):
5207 """Model validator.
5209 Checks the value of a field.
5210 """
5212 message: str
5213 """Error message, or a message key for the client."""
5214 ops: set[ModelOperation]
5215 """Operations the validator applies to."""
5217 def validate(self, field: 'ModelField', feature: 'Feature', mc: ModelContext) -> bool:
5218 """Check the value of a field in a feature.
5220 Args:
5221 field: The field.
5222 feature: The feature.
5223 mc: The model context.
5225 Returns:
5226 True if the value is valid.
5227 """
5230class ModelValue(Node):
5231 """Model value.
5233 Computes a value for a field.
5234 """
5236 isDefault: bool
5237 """The value is used only when the source provides no value."""
5238 ops: set[ModelOperation]
5239 """Operations the value applies to."""
5241 def compute(self, field: 'ModelField', feature: 'Feature', mc: 'ModelContext'):
5242 """Compute the value of a field.
5244 Args:
5245 field: The field.
5246 feature: The feature.
5247 mc: The model context.
5249 Returns:
5250 The computed value.
5251 """
5254class ModelField(Node):
5255 """Model field.
5257 Handles a subset of feature data. The model calls the field methods when it performs
5258 an operation; the methods read and write ``feature.attributes``, ``feature.record``
5259 and ``feature.props``.
5260 """
5262 name: str
5263 """Field name."""
5264 title: str
5265 """Field title."""
5267 attributeType: AttributeType
5268 """Type of the field value."""
5270 widget: Optional['ModelWidget'] = None
5271 """Widget for the client."""
5273 values: list['ModelValue']
5274 """Value objects."""
5275 validators: list['ModelValidator']
5276 """Validators."""
5278 isPrimaryKey: bool
5279 """The field is a primary key."""
5280 isRequired: bool
5281 """The field must not be empty."""
5282 isUnique: bool
5283 """The field is unique."""
5284 isAuto: bool
5285 """The value is set by the database and never written."""
5286 isHidden: bool
5287 """The field is not automatically displayed in the client."""
5289 supportsFilterSearch: bool = False
5290 """The field supports filter search."""
5291 supportsGeometrySearch: bool = False
5292 """The field supports geometry search."""
5293 supportsKeywordSearch: bool = False
5294 """The field supports keyword search."""
5296 model: 'Model'
5297 """The model of the field."""
5299 def before_select(self, mc: ModelContext):
5300 """Called before features are selected, adds columns and conditions to ``mc.dbSelect``.
5302 Args:
5303 mc: The model context.
5304 """
5306 def after_select(self, features: list['Feature'], mc: ModelContext):
5307 """Called after features are selected, sets the field value in the features.
5309 Args:
5310 features: The selected features.
5311 mc: The model context.
5312 """
5314 def before_create(self, feature: 'Feature', mc: ModelContext):
5315 """Called before a feature is inserted, writes the field value to ``feature.record``.
5317 Args:
5318 feature: The feature.
5319 mc: The model context.
5320 """
5322 def after_create(self, feature: 'Feature', mc: ModelContext):
5323 """Called after a feature is inserted.
5325 Args:
5326 feature: The feature.
5327 mc: The model context.
5328 """
5330 def before_create_related(self, dst_feature: 'Feature', mc: ModelContext):
5331 """Called before a feature of another model, created together with features of this model, is inserted.
5333 Args:
5334 dst_feature: The feature being created.
5335 mc: The model context.
5336 """
5338 def after_create_related(self, dst_feature: 'Feature', mc: ModelContext):
5339 """Called after a feature of another model, created together with features of this model, is inserted.
5341 Args:
5342 dst_feature: The created feature.
5343 mc: The model context.
5344 """
5346 def before_update(self, feature: 'Feature', mc: ModelContext):
5347 """Called before a feature is updated, writes the field value to ``feature.record``.
5349 Args:
5350 feature: The feature.
5351 mc: The model context.
5352 """
5354 def after_update(self, feature: 'Feature', mc: ModelContext):
5355 """Called after a feature is updated.
5357 Args:
5358 feature: The feature.
5359 mc: The model context.
5360 """
5362 def before_delete(self, feature: 'Feature', mc: ModelContext):
5363 """Called before a feature is deleted.
5365 Args:
5366 feature: The feature.
5367 mc: The model context.
5368 """
5370 def after_delete(self, feature: 'Feature', mc: ModelContext):
5371 """Called after a feature is deleted.
5373 Args:
5374 feature: The feature.
5375 mc: The model context.
5376 """
5378 def do_init(self, feature: 'Feature', mc: ModelContext):
5379 """Set the initial field value of a new feature.
5381 Args:
5382 feature: The feature.
5383 mc: The model context.
5384 """
5386 def do_init_related(self, dst_feature: 'Feature', mc: ModelContext):
5387 """Initialize a new feature of another model that is created together with features of this model.
5389 Args:
5390 dst_feature: The new feature.
5391 mc: The model context.
5392 """
5394 def do_validate(self, feature: 'Feature', mc: ModelContext):
5395 """Validate the field value and append errors to ``feature.errors``.
5397 Args:
5398 feature: The feature.
5399 mc: The model context.
5400 """
5402 def from_props(self, feature: 'Feature', mc: ModelContext):
5403 """Set the field value from ``feature.props``.
5405 Args:
5406 feature: The feature.
5407 mc: The model context.
5408 """
5410 def to_props(self, feature: 'Feature', mc: ModelContext):
5411 """Write the field value to ``feature.props``.
5413 Args:
5414 feature: The feature.
5415 mc: The model context.
5416 """
5418 def from_record(self, feature: 'Feature', mc: ModelContext):
5419 """Set the field value from ``feature.record``.
5421 Args:
5422 feature: The feature.
5423 mc: The model context.
5424 """
5426 def to_record(self, feature: 'Feature', mc: ModelContext):
5427 """Write the field value to ``feature.record``.
5429 Args:
5430 feature: The feature.
5431 mc: The model context.
5432 """
5434 def related_models(self) -> list['Model']:
5435 """Return the models related to this field.
5437 Returns:
5438 A list of models, empty for fields that are not related fields.
5439 """
5441 def find_relatable_features(self, search: 'SearchQuery', mc: ModelContext) -> list['Feature']:
5442 """Find features that can be linked by this field.
5444 Args:
5445 search: The search query.
5446 mc: The model context.
5448 Returns:
5449 The features found in the related models.
5450 """
5452 def raw_to_python(self, feature: 'Feature', value, mc: ModelContext):
5453 """Convert a raw source value to a python value.
5455 Args:
5456 feature: The feature.
5457 value: The value to convert.
5458 mc: The model context.
5460 Returns:
5461 The converted value.
5462 """
5464 def prop_to_python(self, feature: 'Feature', value, mc: ModelContext):
5465 """Convert a client props value to a python value.
5467 Args:
5468 feature: The feature.
5469 value: The value to convert.
5470 mc: The model context.
5472 Returns:
5473 The converted value.
5474 """
5476 def python_to_raw(self, feature: 'Feature', value, mc: ModelContext):
5477 """Convert a python value to a raw source value.
5479 Args:
5480 feature: The feature.
5481 value: The value to convert.
5482 mc: The model context.
5484 Returns:
5485 The converted value.
5486 """
5488 def python_to_prop(self, feature: 'Feature', value, mc: ModelContext):
5489 """Convert a python value to a client props value.
5491 Args:
5492 feature: The feature.
5493 value: The value to convert.
5494 mc: The model context.
5496 Returns:
5497 The converted value.
5498 """
5500 def describe(self) -> Optional['ColumnDescription']:
5501 """Return the description of the source column of this field.
5503 Returns:
5504 The column description, or None if the source has no such column.
5505 """
5508class Model(Node):
5509 """Data model.
5511 Reads features from a source, converts them to and from client props and,
5512 if editable, writes them back.
5513 """
5515 clientOptions: ModelClientOptions
5516 """Client options."""
5517 defaultSort: list['SearchSort']
5518 """Default sort order of features."""
5519 fields: list['ModelField']
5520 """Model fields."""
5521 geometryCrs: Optional['Crs']
5522 """CRS of the geometry field."""
5523 geometryName: str
5524 """Name of the geometry field."""
5525 geometryType: Optional[GeometryType]
5526 """Type of the geometry field."""
5527 isEditable: bool
5528 """Features of this model can be edited."""
5529 loadingStrategy: 'FeatureLoadingStrategy'
5530 """How the client loads features."""
5531 exportStrategy: 'FeatureExportStrategy'
5532 """How features are obtained for export."""
5533 title: str
5534 """Model title."""
5535 uidName: str
5536 """Name of the uid (primary key) field."""
5537 withTableView: bool
5538 """The table view of features is enabled in the client."""
5540 def find_features(self, search: 'SearchQuery', mc: ModelContext) -> list['Feature']:
5541 """Find features matching a search query.
5543 Args:
5544 search: The search query.
5545 mc: The model context.
5547 Returns:
5548 The features found.
5549 """
5551 def get_features(self, uids: Iterable[str | int], mc: ModelContext) -> list['Feature']:
5552 """Return features by uid.
5554 Args:
5555 uids: Feature uids.
5556 mc: The model context.
5558 Returns:
5559 The features found, empty if no uids are given.
5560 """
5562 def get_feature(self, uid: str | int, mc: ModelContext) -> Optional['Feature']:
5563 """Return a feature by uid.
5565 Args:
5566 uid: The feature uid.
5567 mc: The model context.
5569 Returns:
5570 The feature, or None if it is not found.
5571 """
5573 def init_feature(self, feature: 'Feature', mc: ModelContext):
5574 """Initialize a new feature with initial field values.
5576 Args:
5577 feature: The new feature.
5578 mc: The model context.
5580 Raises:
5581 gws.ForbiddenError: If the user cannot create features of this model.
5582 """
5584 def create_feature(self, feature: 'Feature', mc: ModelContext) -> FeatureUid:
5585 """Insert a new feature into the source.
5587 Args:
5588 feature: The feature.
5589 mc: The model context.
5591 Returns:
5592 The primary key of the inserted feature.
5594 Raises:
5595 gws.ForbiddenError: If the user cannot create features of this model.
5596 """
5598 def update_feature(self, feature: 'Feature', mc: ModelContext) -> FeatureUid:
5599 """Update an existing feature in the source.
5601 Args:
5602 feature: The feature.
5603 mc: The model context.
5605 Returns:
5606 The uid of the feature.
5608 Raises:
5609 gws.ForbiddenError: If the user cannot write to this model.
5610 """
5612 def delete_feature(self, feature: 'Feature', mc: ModelContext) -> FeatureUid:
5613 """Delete a feature from the source.
5615 Args:
5616 feature: The feature.
5617 mc: The model context.
5619 Returns:
5620 The uid of the feature.
5622 Raises:
5623 gws.ForbiddenError: If the user cannot delete features of this model.
5624 """
5626 def validate_feature(self, feature: 'Feature', mc: ModelContext) -> bool:
5627 """Validate a feature and store validation errors in ``feature.errors``.
5629 Args:
5630 feature: The feature.
5631 mc: The model context.
5633 Returns:
5634 True if the feature has no errors.
5635 """
5637 def feature_from_props(self, props: 'FeatureProps', mc: ModelContext) -> 'Feature':
5638 """Create a feature from client props.
5640 Args:
5641 props: The feature props.
5642 mc: The model context.
5644 Returns:
5645 A new feature.
5646 """
5648 def feature_to_props(self, feature: 'Feature', mc: ModelContext) -> 'FeatureProps':
5649 """Convert a feature to client props and store them in ``feature.props``.
5651 Args:
5652 feature: The feature.
5653 mc: The model context.
5655 Returns:
5656 The feature props.
5657 """
5659 def feature_to_view_props(self, feature: 'Feature', mc: ModelContext) -> 'FeatureProps':
5660 """Convert a feature to client props for viewing, with a reduced set of attributes.
5662 Args:
5663 feature: The feature.
5664 mc: The model context.
5666 Returns:
5667 The feature props.
5668 """
5670 def describe(self) -> Optional['DataSetDescription']:
5671 """Return the description of the model source.
5673 Returns:
5674 The dataset description, or None if the source cannot be described.
5675 """
5677 def field(self, name: str) -> Optional['ModelField']:
5678 """Return a field by name.
5680 Args:
5681 name: The field name.
5683 Returns:
5684 The field, or None if it is not found.
5685 """
5687 def related_models(self) -> list['Model']:
5688 """Return the models related to the fields of this model.
5690 Returns:
5691 A list of models without duplicates.
5692 """
5695class ModelManager(Node):
5696 """Model manager.
5698 Looks up models and provides the default model.
5699 """
5701 def get_model(self, uid: str, user: 'User' = None, access: Access = None) -> Optional['Model']:
5702 """Return a model by uid.
5704 Args:
5705 uid: The model uid.
5706 user: If given together with ``access``, the user must have this access to the model.
5707 access: The required access.
5709 Returns:
5710 The model, or None if it is not found or not accessible.
5711 """
5713 def find_model(self, *objects, user: 'User' = None, access: Access = None) -> Optional['Model']:
5714 """Return the first model of the given objects.
5716 Looks in the ``models`` attribute of each object in turn.
5718 Args:
5719 *objects: Objects with models, e.g. layers. None values are skipped.
5720 user: If given together with ``access``, the user must have this access to the model.
5721 access: The required access.
5723 Returns:
5724 The model, or None if none is found.
5725 """
5727 def editable_models(self, project: 'Project', user: 'User') -> list['Model']:
5728 """Return the models a user can edit in a project, together with their related models.
5730 Args:
5731 project: The project.
5732 user: The user.
5734 Returns:
5735 The models, sorted by title.
5736 """
5738 def default_model(self) -> 'Model':
5739 """Return the shared default model.
5741 Returns:
5742 The default model.
5743 """
5744################################################################################
5747################################################################################
5748# /base/database/types.pyinc
5751class DatabaseModel(Model):
5752 """Data model for a database table."""
5754 db: 'DatabaseProvider'
5755 """Database provider."""
5756 sqlFilter: str
5757 """Literal SQL condition applied when selecting rows."""
5758 tableName: str
5759 """Table name associated with this model."""
5761 def table(self) -> 'sqlalchemy.Table':
5762 """Return the SQLAlchemy ``Table`` object of the model table.
5764 Returns:
5765 The table object.
5767 Raises:
5768 ``sqlalchemy.exc.SQLAlchemyError``: If the table does not exist.
5769 """
5771 def column(self, column_name: str) -> 'sqlalchemy.Column':
5772 """Return the SQLAlchemy ``Column`` object of a column in the model table.
5774 Args:
5775 column_name: Column name.
5777 Returns:
5778 The column object.
5780 Raises:
5781 ``sqlalchemy.exc.SQLAlchemyError``: If the table or the column does not exist.
5782 """
5784 def uid_column(self) -> 'sqlalchemy.Column':
5785 """Return the SQLAlchemy ``Column`` object of the primary key column.
5787 Returns:
5788 The column object for ``uidName``.
5790 Raises:
5791 ``gws.Error``: If the model has no primary key or the key column does not exist.
5792 """
5794 def uid_equals(self, uid: FeatureUid | Iterable[FeatureUid]) -> 'sqlalchemy.ColumnElement[bool]':
5795 """Return a condition that matches features by uid.
5797 The values are bound with the type of the primary key column, so that
5798 string uids can be compared with columns of other types.
5800 Args:
5801 uid: A feature uid, or an iterable of uids.
5803 Returns:
5804 An ``=`` condition for a single uid, an ``IN`` condition for an iterable.
5806 Raises:
5807 ``gws.Error``: If the model has no primary key or the key column does not exist.
5808 """
5810 def fetch_features(self, select: 'sqlalchemy.Select') -> list['Feature']:
5811 """Run a SELECT statement and create a feature for each row.
5813 The row values become the attributes of the feature record.
5815 Args:
5816 select: SELECT statement.
5818 Returns:
5819 A list of features.
5820 """
5822 def build_select(self, mc: 'ModelContext') -> Optional['sqlalchemy.Select']:
5823 """Build a SELECT statement for a search.
5825 Combines the search query in ``mc.search``, the columns and conditions
5826 collected by the fields in ``mc.dbSelect`` and ``sqlFilter``.
5828 Args:
5829 mc: Model context with ``search`` and ``dbSelect`` set.
5831 Returns:
5832 The SELECT statement, or ``None`` if the search cannot match anything.
5833 """
5836class ColumnDescription(Data):
5837 """Description of a dataset column."""
5839 columnIndex: int
5840 """The index of the column within the table."""
5841 comment: str
5842 """Column comment or description provided in the database metadata."""
5843 geometrySrid: int
5844 """The Spatial Reference Identifier (SRID) for geometry columns."""
5845 geometryType: GeometryType
5846 """The type of geometry stored in the column (e.g., Point, Polygon)."""
5847 isAutoincrement: bool
5848 """Indicates if the column is auto-incremented."""
5849 isNullable: bool
5850 """Specifies if the column permits NULL values."""
5851 isPrimaryKey: bool
5852 """Specifies if the column is part of the primary key."""
5853 isUnique: bool
5854 """Indicates if the column has a unique constraint."""
5855 hasDefault: bool
5856 """Indicates if the column has a database-defined default value."""
5857 isIndexed: bool
5858 """Indicates if the column has an index."""
5859 name: str
5860 """The name of the column."""
5861 nativeType: str
5862 """The database-specific data type of the column."""
5863 options: dict
5864 """Additional options or configurations for the column, if any."""
5865 type: AttributeType
5866 """The abstract type of the column used in higher-level processing."""
5869class DataSetDescription(Data):
5870 """Description of a dataset, like a DB table or a GDAL data set."""
5872 columns: list[ColumnDescription]
5873 """A list of column descriptions."""
5874 columnMap: dict[str, ColumnDescription]
5875 """A dictionary mapping column names to their descriptions."""
5876 fullName: str
5877 """The full name of the dataset, including schema if applicable."""
5878 geometryName: str
5879 """The name of the geometry column, if any."""
5880 geometrySrid: int
5881 """The Spatial Reference Identifier (SRID) for the geometry."""
5882 geometryType: GeometryType
5883 """The type of geometry stored in the dataset."""
5884 name: str
5885 """The name of the dataset or table."""
5886 schema: str
5887 """The schema to which the dataset belongs."""
5890class DatabaseManager(Node):
5891 """Database manager."""
5893 providers: list['DatabaseProvider']
5894 """A list of database providers managed by this DatabaseManager."""
5896 def create_provider(self, cfg: Config, **kwargs) -> 'DatabaseProvider':
5897 """Create a database provider and add it to ``providers``.
5899 The provider is created as a shared object. A provider with the same uid
5900 that is already in ``providers`` is replaced.
5902 Args:
5903 cfg: Provider configuration.
5904 **kwargs: Extra configuration values.
5906 Returns:
5907 The provider.
5908 """
5910 def find_provider(self, uid: Optional[str] = None, ext_type: Optional[str] = None) -> Optional['DatabaseProvider']:
5911 """Find a database provider by uid or type.
5913 With ``uid``, returns the provider with this uid (and of type ``ext_type``,
5914 if given). With ``ext_type`` only, returns the first provider of this type.
5915 Without arguments, returns the first provider.
5917 Args:
5918 uid: Provider uid.
5919 ext_type: Provider type, e.g. ``postgres``.
5921 Returns:
5922 The provider, or ``None`` if none matches.
5923 """
5926DatabaseTableAlike: TypeAlias = Union['sqlalchemy.Table', str]
5927"""An SQLAlchemy ``Table`` object or a string table name."""
5930DatabaseStmt: TypeAlias = Union['sqlalchemy.Executable', str]
5931"""An Executable SQLAlchemy object or a string SQL statement."""
5934class DatabaseConnection:
5935 """Database connection.
5937 Wraps an SQLAlchemy ``Connection`` and provides some convenience methods.
5938 Returned by ``DatabaseProvider.begin``. The connection does not control
5939 the transaction: it is committed or rolled back by ``begin``.
5941 Statements can be SQLAlchemy objects or SQL strings with ``:name`` bind
5942 parameters.
5943 """
5945 saConn: 'sqlalchemy.Connection'
5946 """The underlying SQLAlchemy connection."""
5948 def execute(self, stmt: 'DatabaseStmt', params=None, execution_options: dict=None) -> 'sqlalchemy.CursorResult':
5949 """Execute a statement.
5951 Args:
5952 stmt: Statement or SQL string.
5953 params: Bind parameters, a dict or a list of dicts.
5954 execution_options: SQLAlchemy execution options.
5956 Returns:
5957 The result.
5958 """
5960 def fetch_all(self, stmt: 'DatabaseStmt', **params) -> list[dict]:
5961 """Execute a statement and return all rows.
5963 Args:
5964 stmt: Statement or SQL string.
5965 **params: Bind parameters.
5967 Returns:
5968 A list of rows as dicts.
5969 """
5971 def fetch_first(self, stmt: 'DatabaseStmt', **params) -> dict | None:
5972 """Execute a statement and return the first row.
5974 Args:
5975 stmt: Statement or SQL string.
5976 **params: Bind parameters.
5978 Returns:
5979 The first row as a dict, or ``None`` if there are no rows.
5980 """
5982 def fetch_scalars(self, stmt: 'DatabaseStmt', **params) -> list:
5983 """Execute a statement and return the first column of all rows.
5985 Args:
5986 stmt: Statement or SQL string.
5987 **params: Bind parameters.
5989 Returns:
5990 A list of values.
5991 """
5993 def fetch_strings(self, stmt: 'DatabaseStmt', **params) -> list[str]:
5994 """Execute a statement and return the first column of all rows as strings.
5996 Args:
5997 stmt: Statement or SQL string.
5998 **params: Bind parameters.
6000 Returns:
6001 A list of strings, with ``NULL`` values as empty strings.
6002 """
6004 def fetch_ints(self, stmt: 'DatabaseStmt', **params) -> list[int]:
6005 """Execute a statement and return the first column of all rows as integers.
6007 Args:
6008 stmt: Statement or SQL string.
6009 **params: Bind parameters.
6011 Returns:
6012 A list of integers.
6014 Raises:
6015 ``ValueError``: If a value is not an integer.
6016 """
6018 def fetch_scalar(self, stmt: 'DatabaseStmt', **params) -> Any:
6019 """Execute a statement and return the first column of the first row.
6021 Args:
6022 stmt: Statement or SQL string.
6023 **params: Bind parameters.
6025 Returns:
6026 The value, or ``None`` if there are no rows.
6027 """
6029 def fetch_string(self, stmt: 'DatabaseStmt', **params) -> str | None:
6030 """Execute a statement and return the first column of the first row as a string.
6032 Args:
6033 stmt: Statement or SQL string.
6034 **params: Bind parameters.
6036 Returns:
6037 The string, or ``None`` if there are no rows or the value is ``NULL``.
6038 """
6040 def fetch_int(self, stmt: 'DatabaseStmt', **params) -> int | None:
6041 """Execute a statement and return the first column of the first row as an integer.
6043 Args:
6044 stmt: Statement or SQL string.
6045 **params: Bind parameters.
6047 Returns:
6048 The integer, or ``None`` if there are no rows or the value is ``NULL``.
6050 Raises:
6051 ``ValueError``: If the value is not an integer.
6052 """
6054class DatabaseInspectOptions(Data):
6055 """Options for database inspection."""
6057 refresh: bool = False
6058 """Whether to force inspection even if cached information is available."""
6059 cacheLifeTime: int = 0
6060 """Schema cache lifetime in seconds."""
6063class DatabaseProvider(Node):
6064 """Database provider.
6066 Wraps an SQLAlchemy ``Engine`` and hands out connections. Also reflects
6067 table structures and describes tables and columns.
6068 """
6070 def begin(self, nested: bool = False) -> ContextManager['DatabaseConnection']:
6071 """Begin a transaction, to be used as a context manager.
6073 The outermost call opens a connection and begins a transaction, which
6074 is committed on normal exit and rolled back on an exception. Inner
6075 calls in the same thread join the open transaction, or create a
6076 savepoint if ``nested`` is set::
6078 with db.begin() as conn:
6079 conn.execute('INSERT ...')
6080 with db.begin() as conn2: # same connection and transaction
6081 rows = conn2.fetch_all('SELECT ...')
6082 with db.begin(nested=True) as conn3: # savepoint
6083 conn3.execute('UPDATE ...')
6084 # committed, connection closed
6086 Unlike SQLAlchemy ``Engine.begin``, an inner call does not open a new
6087 connection. Each provider keeps its own connection per thread.
6089 Args:
6090 nested: Create a savepoint when joining an open transaction. An
6091 exception inside the block then rolls back to the savepoint
6092 only. Has no effect on the outermost call.
6094 Returns:
6095 A context manager that yields the connection.
6096 """
6098 def connect(self) -> ContextManager['DatabaseConnection']:
6099 """Deprecated, same as ``begin``."""
6101 def autocommit_connection(self) -> ContextManager['DatabaseConnection']:
6102 """Open a separate connection in autocommit mode, to be used as a context manager.
6104 For statements that cannot run inside a transaction, like ``VACUUM``.
6105 The connection is not shared with ``begin``.
6107 Returns:
6108 A context manager that yields the connection.
6110 Raises:
6111 ``gws.Error``: If a transaction of this provider is open in the current thread.
6112 """
6114 def engine_options(self, **kwargs):
6115 """Add defaults to the SQLAlchemy engine options.
6117 Args:
6118 **kwargs: Engine options. Options passed here take precedence over the defaults.
6120 Returns:
6121 The options dict.
6122 """
6124 def url(self) -> str:
6125 """Return the connection URL.
6127 Returns:
6128 An SQLAlchemy connection URL.
6129 """
6131 def engine(self) -> 'sqlalchemy.Engine':
6132 """Return the SQLAlchemy ``Engine`` object for this provider, creating it if needed.
6134 Returns:
6135 The engine.
6136 """
6138 def create_engine(self, **kwargs) -> 'sqlalchemy.Engine':
6139 """Create a new SQLAlchemy ``Engine`` object for this provider.
6141 Args:
6142 **kwargs: Engine options, see ``engine_options``.
6144 Returns:
6145 The engine.
6146 """
6148 def describe(self, table: DatabaseTableAlike) -> 'DataSetDescription':
6149 """Describe a table.
6151 Args:
6152 table: Table object or table name.
6154 Returns:
6155 The table description. The first geometry column becomes the primary geometry.
6157 Raises:
6158 ``sqlalchemy.exc.SQLAlchemyError``: If the table does not exist.
6159 """
6161 def describe_column(self, table: DatabaseTableAlike, column_name: str) -> ColumnDescription:
6162 """Describe a column in a table.
6164 Args:
6165 table: Table object or table name.
6166 column_name: Column name.
6168 Returns:
6169 The column description.
6171 Raises:
6172 ``sqlalchemy.exc.SQLAlchemyError``: If the table or the column does not exist.
6173 """
6175 def table(self, table: 'DatabaseTableAlike', **kwargs) -> 'sqlalchemy.Table':
6176 """Return the SQLAlchemy ``Table`` object for a table.
6178 Args:
6179 table: Table object or table name.
6180 **kwargs: Not used by the base provider.
6182 Returns:
6183 The table object.
6185 Raises:
6186 ``sqlalchemy.exc.SQLAlchemyError``: If the table does not exist.
6187 """
6189 def column(self, table: DatabaseTableAlike, column_name: str) -> 'sqlalchemy.Column':
6190 """Return the SQLAlchemy ``Column`` object for a column.
6192 Args:
6193 table: Table object or table name.
6194 column_name: Column name.
6196 Returns:
6197 The column object.
6199 Raises:
6200 ``sqlalchemy.exc.SQLAlchemyError``: If the table or the column does not exist.
6201 """
6203 def count(self, table: DatabaseTableAlike) -> int:
6204 """Return the number of rows in a table.
6206 Args:
6207 table: Table object or table name.
6209 Returns:
6210 The row count, or 0 if the table does not exist.
6211 """
6213 def has_schema(self, schema_name: str) -> bool:
6214 """Check if a schema exists.
6216 Args:
6217 schema_name: Schema name.
6219 Returns:
6220 ``True`` if the schema exists.
6221 """
6223 def has_table(self, table_name: str) -> bool:
6224 """Check if a table exists.
6226 Args:
6227 table_name: Table name, optionally schema-qualified.
6229 Returns:
6230 ``True`` if the table exists.
6231 """
6233 def has_column(self, table: DatabaseTableAlike, column_name: str) -> bool:
6234 """Check if a column exists.
6236 Args:
6237 table: Table object or table name.
6238 column_name: Column name.
6240 Returns:
6241 ``True`` if the table and the column exist.
6242 """
6244 def join_table_name(self, schema: str, name: str) -> str:
6245 """Create a full table name from the schema and table names.
6247 Args:
6248 schema: Schema name. If empty, the default schema is used.
6249 name: Table name.
6251 Returns:
6252 The schema-qualified table name.
6253 """
6255 def split_table_name(self, table_name: str) -> tuple[str, str]:
6256 """Split a full table name into the schema and table names.
6258 Args:
6259 table_name: Table name, optionally schema-qualified.
6261 Returns:
6262 A tuple of the schema name (the default schema if none is given) and the table name.
6263 """
6265 def table_bounds(self, table: DatabaseTableAlike) -> Optional[Bounds]:
6266 """Compute the bounding box of the primary geometry of a table.
6268 Args:
6269 table: Table object or table name.
6271 Returns:
6272 The bounds, or ``None`` if the table has no geometry or no data.
6273 """
6275 def schema_names(self) -> list[str]:
6276 """Return the names of the schemas in the database.
6278 Returns:
6279 A list of schema names.
6280 """
6282 def inspect_schema(self, schema: str, options: Optional[DatabaseInspectOptions] = None):
6283 """Reflect the tables of a schema and keep the result.
6285 A schema that has already been reflected is not reflected again, unless
6286 ``options.refresh`` is set. The reflected metadata is cached for the
6287 configured schema cache lifetime. If ``options`` are given, their
6288 ``cacheLifeTime`` is used instead; 0 means no caching.
6290 Args:
6291 schema: Schema name.
6292 options: Inspection options.
6293 """
6294################################################################################
6298################################################################################
6299# /base/job/types.pyinc
6302class JobTerminated(Exception):
6303 """Raised in a worker when its job is no longer running, e.g. because it was cancelled."""
6305 pass
6308class JobState(Enum):
6309 """Background job state."""
6311 init = 'init'
6312 """The job is being created."""
6313 open = 'open'
6314 """The job is just created and waiting for start."""
6315 running = 'running'
6316 """The job is running."""
6317 complete = 'complete'
6318 """The job has been completed successfully."""
6319 error = 'error'
6320 """There was an error."""
6321 cancel = 'cancel'
6322 """The job was cancelled."""
6325class Job(Data):
6326 """Background job data."""
6328 uid: str
6329 """Job uid."""
6330 user: 'User'
6331 """User who created the job."""
6332 worker: str
6333 """Worker class, as ``<module path>:<class name>``."""
6334 state: JobState
6335 """Job state."""
6336 error: str
6337 """Error message, if the job failed."""
6338 numSteps: int
6339 """Total number of steps, for progress reporting."""
6340 step: int
6341 """Current step."""
6342 stepName: str
6343 """Name of the current step."""
6344 payload: dict
6345 """Input data for the worker."""
6346 result: dict
6347 """Result data from the worker."""
6348 timeCreated: datetime.datetime
6349 """Creation time."""
6350 timeUpdated: datetime.datetime
6351 """Time of the last update."""
6354class JobRequest(Request):
6355 """Request that refers to a job."""
6357 jobUid: str
6358 """Job uid."""
6361class JobStatusResponse(Response):
6362 """Job status."""
6364 jobUid: str
6365 """Job uid."""
6366 state: JobState
6367 """Job state."""
6368 progress: int
6369 """Progress in percent."""
6370 stepName: str
6371 """Name of the current step."""
6372 output: dict
6373 """Job-specific output, e.g. a download URL when the job is complete."""
6376class JobManager(Node):
6377 """Job manager."""
6379 def create_job(self, worker: type, user: User, payload: dict | Data = None) -> Job:
6380 """Create a job in the ``open`` state.
6382 Args:
6383 worker: Worker class. It must have a ``run(root, job)`` class method.
6384 user: User the job runs for.
6385 payload: Input data for the worker, must be JSON-serializable.
6387 Returns:
6388 The new job.
6389 """
6391 def get_job(self, job_uid: str, user: User = None, state: JobState = None) -> Optional[Job]:
6392 """Read a job.
6394 Args:
6395 job_uid: Job uid.
6396 user: If given, the job must belong to this user.
6397 state: If given, the job must be in this state.
6399 Returns:
6400 The job, or ``None`` if it does not exist or does not match. The reason is logged.
6401 """
6403 def update_job(self, job: Job, **kwargs) -> Optional[Job]:
6404 """Update fields of a job.
6406 Args:
6407 job: The job.
6408 **kwargs: Job fields to update.
6410 Returns:
6411 The updated job, or ``None`` if the job does not exist.
6412 """
6414 def run_job(self, job: Job) -> Optional[Job]:
6415 """Run an open job in the current process.
6417 Marks the job as running, so that it runs only once, and calls the
6418 ``run`` method of its worker. If the worker raises an exception, the
6419 job goes into the ``error`` state.
6421 Args:
6422 job: The job.
6424 Returns:
6425 The job after the run.
6427 Raises:
6428 ``gws.Error``: If the job is not open or is already taken by another process.
6429 """
6431 def cancel_job(self, job: Job) -> Optional[Job]:
6432 """Set a job to the ``cancel`` state.
6434 The worker notices the change on its next job update and stops.
6436 Args:
6437 job: The job.
6439 Returns:
6440 The updated job, or ``None`` if the job does not exist.
6441 """
6443 def remove_job(self, job: Job):
6444 """Delete a job record.
6446 Args:
6447 job: The job.
6448 """
6450 def schedule_job(self, job: Job) -> Job:
6451 """Start an open job.
6453 The job is passed to the uWSGI spooler if it is available, otherwise it
6454 runs at once in the current process.
6456 Args:
6457 job: The job.
6459 Returns:
6460 The job.
6462 Raises:
6463 ``gws.Error``: If the job is not open.
6464 """
6466 def require_job(self, req: 'WebRequester', p: JobRequest) -> Job:
6467 """Return the job of a request, if it belongs to the requesting user.
6469 Args:
6470 req: Web request.
6471 p: Job request.
6473 Returns:
6474 The job.
6476 Raises:
6477 ``gws.NotFoundError``: If the job does not exist or belongs to another user.
6478 """
6480 def require_result(self, req: 'WebRequester', p: JobRequest) -> dict:
6481 """Return the result of a completed job of the requesting user.
6483 Args:
6484 req: Web request.
6485 p: Job request.
6487 Returns:
6488 The job result.
6490 Raises:
6491 ``gws.NotFoundError``: If the job does not exist, belongs to another user,
6492 is not complete or has no result.
6493 """
6495 def handle_status_request(self, req: 'WebRequester', p: JobRequest) -> JobStatusResponse:
6496 """Return the status of a job of the requesting user.
6498 Args:
6499 req: Web request.
6500 p: Job request.
6502 Returns:
6503 The job status.
6505 Raises:
6506 ``gws.NotFoundError``: If the job does not exist or belongs to another user.
6507 """
6509 def handle_cancel_request(self, req: 'WebRequester', p: JobRequest) -> JobStatusResponse:
6510 """Cancel a job of the requesting user.
6512 Args:
6513 req: Web request.
6514 p: Job request.
6516 Returns:
6517 The job status after cancelling.
6519 Raises:
6520 ``gws.NotFoundError``: If the job does not exist or belongs to another user.
6521 """
6523 def job_status_response(self, job: Job, **kwargs) -> 'JobStatusResponse':
6524 """Create a status response for a job.
6526 Args:
6527 job: The job.
6528 **kwargs: Extra or overriding response fields.
6530 Returns:
6531 The status response.
6532 """
6533################################################################################
6536################################################################################
6537# /base/ows/types.pyinc
6540import gws
6543class OwsProtocol(Enum):
6544 """Supported OWS protocols."""
6546 WMS = 'WMS'
6547 WMTS = 'WMTS'
6548 WCS = 'WCS'
6549 WFS = 'WFS'
6550 CSW = 'CSW'
6553class OwsAuthorization(Data):
6554 """Credentials for accessing an OWS service."""
6556 type: str
6557 """Authorization type, ``basic`` or ``token``."""
6558 username: str
6559 """User name."""
6560 password: str
6561 """Password."""
6562 header: str
6563 """HTTP header that carries the token."""
6564 prefix: str
6565 """Prefix expected before the token in the header value."""
6566 token: str
6567 """Authorization token."""
6571class OwsVerb(Enum):
6572 """OWS request type."""
6574 CreateStoredQuery = 'CreateStoredQuery'
6575 DescribeCoverage = 'DescribeCoverage'
6576 DescribeFeatureType = 'DescribeFeatureType'
6577 DescribeLayer = 'DescribeLayer'
6578 DescribeRecord = 'DescribeRecord'
6579 DescribeStoredQueries = 'DescribeStoredQueries'
6580 DropStoredQuery = 'DropStoredQuery'
6581 GetCapabilities = 'GetCapabilities'
6582 GetFeature = 'GetFeature'
6583 GetFeatureInfo = 'GetFeatureInfo'
6584 GetFeatureWithLock = 'GetFeatureWithLock'
6585 GetLegendGraphic = 'GetLegendGraphic'
6586 GetMap = 'GetMap'
6587 GetPrint = 'GetPrint'
6588 GetPropertyValue = 'GetPropertyValue'
6589 GetRecordById = 'GetRecordById'
6590 GetRecords = 'GetRecords'
6591 GetTile = 'GetTile'
6592 ListStoredQueries = 'ListStoredQueries'
6593 LockFeature = 'LockFeature'
6594 Transaction = 'Transaction'
6597class OwsOperation(Data):
6598 """OWS operation, as offered by a remote service or by our own service."""
6600 allowedParameters: dict[str, list[str]]
6601 """Allowed values for parameters, keyed by the upper-cased parameter name."""
6602 constraints: dict[str, list[str]]
6603 """Operation constraints."""
6604 defaultMimeType: str
6605 """Output MIME type to use in requests that do not specify one (client side)."""
6606 handlerName: str
6607 """Name of the service method that handles this operation (server side)."""
6608 mimeTypeMap: dict[str, str]
6609 """Normalized MIME types mapped to the spelling of the remote service, if it differs (client side)."""
6610 mimeTypes: list[str]
6611 """Supported output MIME types, normalized."""
6612 params: dict[str, str]
6613 """Extra parameters for GET requests (client side)."""
6614 postUrl: Url
6615 """URL for POST requests."""
6616 url: Url
6617 """URL for GET requests."""
6618 verb: OwsVerb
6619 """Request type."""
6622class OwsCapabilities(Data):
6623 """Parsed capabilities of a remote OWS service."""
6625 metadata: 'Metadata'
6626 """Service metadata."""
6627 operations: list['OwsOperation']
6628 """Operations offered by the service."""
6629 sourceLayers: list['SourceLayer']
6630 """Layers or feature types of the service."""
6631 tileMatrixSets: list['TileMatrixSet']
6632 """Tile matrix sets (WMTS)."""
6633 version: str
6634 """Service version."""
6637class OwsService(Node):
6638 """OWS service provided by GBD WebSuite."""
6640 isRasterService: bool = False
6641 """Service provides raster services."""
6642 isVectorService: bool = False
6643 """Service provides vector services."""
6644 isOwsCommon: bool = False
6645 """Conforms to OGC Web Services Common Standard."""
6647 alwaysXY: bool
6648 """Force lon/lat order for geographic projections."""
6649 metadata: 'Metadata'
6650 """Service metadata."""
6651 name: str
6652 """Service name."""
6653 project: Optional['Project']
6654 """Project this service is configured for."""
6655 rootLayer: Optional['Layer']
6656 """Root layer of the service."""
6657 protocol: OwsProtocol
6658 """Supported protocol."""
6659 defaultFeatureCount: int
6660 """Default limit of features per page."""
6661 maxFeatureCount: int
6662 """Max limit of features per page."""
6663 searchTolerance: UomValue
6664 """Default tolerance for spatial search."""
6665 supportedBounds: list[Bounds]
6666 """Supported bounds."""
6667 supportedVersions: list[str]
6668 """Supported versions."""
6669 supportedOperations: list['OwsOperation']
6670 """Supported operations."""
6671 templates: list['Template']
6672 """Service templates."""
6673 imageFormats: list[ImageFormat]
6674 """Supported image formats."""
6675 updateSequence: str
6676 """Service update sequence."""
6677 withInspireMeta: bool
6678 """Include INSPIRE metadata."""
6679 withStrictParams: bool
6680 """Strict parameter checking."""
6682 def handle_request(self, req: 'WebRequester') -> ContentResponse:
6683 """Handle a service request.
6685 Errors are returned as OWS exception documents, not raised.
6687 Args:
6688 req: Web request.
6690 Returns:
6691 The service response.
6692 """
6694 def layer_is_compatible(self, layer: 'Layer') -> bool:
6695 """Check if a layer can be used in this service.
6697 Args:
6698 layer: Layer object.
6700 Returns:
6701 ``True`` if the layer can be published by this service.
6702 """
6705class OwsServiceProvider(Node):
6706 """Remote OWS service used as a data provider."""
6708 alwaysXY: bool
6709 """Force XY axis order for CRSs with lat/lon axis order."""
6710 authorization: Optional['OwsAuthorization']
6711 """Credentials for the service."""
6712 bounds: Optional[Bounds]
6713 """Service bounds, if known."""
6714 forceCrs: 'Crs'
6715 """CRS to use for requests, if configured."""
6716 maxRequests: int
6717 """Max. number of concurrent requests to the service."""
6718 metadata: 'Metadata'
6719 """Service metadata."""
6720 operations: list['OwsOperation']
6721 """Operations offered by the service."""
6722 protocol: 'OwsProtocol'
6723 """Service protocol."""
6724 sourceLayers: list['SourceLayer']
6725 """Layers or feature types of the service."""
6726 url: Url
6727 """Service URL."""
6728 version: str
6729 """Service version."""
6730 wgsExtent: Optional[Extent]
6731 """Service extent in WGS84, if known."""
6733 def get_operation(self, verb: 'OwsVerb', method: Optional['RequestMethod'] = None) -> Optional['OwsOperation']:
6734 """Find an operation by its verb.
6736 Args:
6737 verb: Request type.
6738 method: Request method. For ``POST``, the operation must have a POST URL,
6739 otherwise a GET URL.
6741 Returns:
6742 The operation, or ``None`` if the service does not support it.
6743 """
6745 def get_features(self, args: 'SearchQuery', source_layers: list['SourceLayer'], mime: MimeType = '') -> list['FeatureRecord']:
6746 """Search for features in the given source layers.
6748 Args:
6749 args: Search query.
6750 source_layers: Source layers to search.
6751 mime: Response MIME type to request, the default of the operation if empty.
6753 Returns:
6754 Found feature records.
6755 """
6756################################################################################
6759################################################################################
6760# /base/printer/types.pyinc
6763class PrintPlaneType(Enum):
6764 """Print plane type."""
6766 bitmap = 'bitmap'
6767 """Raw bitmap data."""
6768 url = 'url'
6769 """Image given as a data URL."""
6770 features = 'features'
6771 """Features sent by the client."""
6772 raster = 'raster'
6773 """Raster layer."""
6774 vector = 'vector'
6775 """Vector layer, rendered as SVG."""
6776 soup = 'soup'
6777 """SVG soup: points and SVG tags."""
6780class PrintPlane(Data):
6781 """Print plane, a single map layer in a print request."""
6783 type: PrintPlaneType
6784 """Plane type."""
6786 opacity: Optional[float]
6787 """Plane opacity, from 0 to 1."""
6788 cssSelector: Optional[str]
6789 """CSS selector of the style for vector layers and features."""
6791 bitmapData: Optional[bytes]
6792 """Raw pixel data, for bitmap planes."""
6793 bitmapMode: Optional[str]
6794 """Pixel mode of the bitmap, ``RGBA`` or ``RGB``."""
6795 bitmapWidth: Optional[int]
6796 """Bitmap width in pixels."""
6797 bitmapHeight: Optional[int]
6798 """Bitmap height in pixels."""
6800 url: Optional[str]
6801 """Data URL of the image, for url planes."""
6803 features: Optional[list['FeatureProps']]
6804 """Features, for features planes."""
6806 layerUid: Optional[str]
6807 """Layer uid, for raster and vector planes."""
6808 compositeLayerUids: Optional[list[str]]
6809 """Uids of the sub-layers to render, for composite raster layers."""
6811 soupPoints: Optional[list[Point]]
6812 """Points, for soup planes."""
6813 soupTags: Optional[list[Any]]
6814 """SVG tags, for soup planes."""
6817class PrintMap(Data):
6818 """Map properties for printing."""
6820 backgroundColor: Optional[int]
6821 """Background color."""
6822 bbox: Optional[Extent]
6823 """Map extent."""
6824 center: Optional[Point]
6825 """Map center."""
6826 planes: list[PrintPlane]
6827 """Map planes."""
6828 rotation: Optional[int]
6829 """Map rotation in degrees."""
6830 scale: int
6831 """Map scale denominator."""
6832 styles: Optional[list['StyleProps']]
6833 """Styles used by the planes."""
6834 visibleLayers: Optional[list[str]]
6835 """Uids of the visible layers."""
6838class PrintRequestType(Enum):
6839 """Type of the print request."""
6841 template = 'template'
6842 map = 'map'
6845class PrintRequest(Request):
6846 """Print request."""
6848 type: PrintRequestType
6849 """Request type."""
6851 args: Optional[dict]
6852 """Template arguments."""
6853 crs: Optional[CrsName]
6854 """CRS of the maps, the project CRS by default."""
6855 outputFormat: Optional[str]
6856 """Output format, ``pdf`` (default) or ``png``, or the mime type."""
6857 maps: Optional[list[PrintMap]]
6858 """Maps to print."""
6860 printerUid: Optional[str]
6861 """Printer uid, for template requests."""
6862 dpi: Optional[int]
6863 """Output resolution."""
6864 outputSize: Optional[Size]
6865 """Output size in screen pixels, for map requests."""
6868class PrintResult(Data):
6869 """Print result."""
6871 path: str
6872 """Path of the output file."""
6873 mimeType: str
6874 """Mime type of the output file."""
6877class Printer(Node):
6878 """Printer, a print template offered to users."""
6880 title: str
6881 """Printer title."""
6882 template: 'Template'
6883 """Template that renders the print output."""
6884 models: list['Model']
6885 """Models whose fields are shown as input fields in the print dialog."""
6886 qualityLevels: list['TemplateQualityLevel']
6887 """Quality levels users can choose from."""
6890class PrinterManager(Node):
6891 """Print manager."""
6893 def start_print_job(self, request: PrintRequest, user: 'User') -> 'JobStatusResponse':
6894 """Start a background print job.
6896 Args:
6897 request: Print request.
6898 user: User who requested the print.
6900 Returns:
6901 The status of the new job.
6902 """
6904 def exec_print(self, request: PrintRequest, out_path: str):
6905 """Execute a print request synchronously, as the system user.
6907 Args:
6908 request: Print request.
6909 out_path: Path to copy the output file to.
6910 """
6911################################################################################
6914################################################################################
6915# /base/project/types.pyinc
6918class Client(Node):
6919 """Settings for the browser client: UI elements and client options."""
6921 options: dict
6922 """Client options."""
6923 elements: list
6924 """Client UI elements."""
6927class Project(Node):
6928 """Project: a map application with its own map, actions, templates and services."""
6930 assetsRoot: Optional['WebDocumentRoot']
6931 """Project assets directory, checked before the global assets directory."""
6932 client: 'Client'
6933 """Project client settings, replacing the application client."""
6935 localeUids: list[str]
6936 """Locales of the project."""
6937 map: 'Map'
6938 """Main map of the project."""
6939 metadata: 'Metadata'
6940 """Project metadata."""
6941 title: str
6942 """Project title."""
6944 actions: list['Action']
6945 """Actions available only in this project."""
6946 finders: list['Finder']
6947 """Search providers of the project."""
6948 models: list['Model']
6949 """Data models of the project."""
6950 exporters: list['Exporter']
6951 """Exporters of the project."""
6952 printers: list['Printer']
6953 """Printers of the project."""
6954 templates: list['Template']
6955 """Templates of the project."""
6956 owsServices: list['OwsService']
6957 """OWS services published for the project."""
6959 vars: dict
6960 """Custom variables."""
6961################################################################################
6964################################################################################
6965# /base/search/types.pyinc
6968class SearchSort(Data):
6969 """Search sort specification."""
6971 fieldName: str
6972 """Field name to sort by."""
6973 reverse: bool
6974 """Sort in descending order."""
6977class SearchFilterOperator(Enum):
6978 """Search filter operator, as defined in OGC Filter Encoding 2.0."""
6980 And = 'And'
6981 """All sub-filters match."""
6982 Or = 'Or'
6983 """At least one sub-filter matches."""
6984 Not = 'Not'
6985 """The sub-filter does not match."""
6987 PropertyIsEqualTo = 'PropertyIsEqualTo'
6988 """Property is equal to the value."""
6989 PropertyIsNotEqualTo = 'PropertyIsNotEqualTo'
6990 """Property is not equal to the value."""
6991 PropertyIsLessThan = 'PropertyIsLessThan'
6992 """Property is less than the value."""
6993 PropertyIsGreaterThan = 'PropertyIsGreaterThan'
6994 """Property is greater than the value."""
6995 PropertyIsLessThanOrEqualTo = 'PropertyIsLessThanOrEqualTo'
6996 """Property is less than or equal to the value."""
6997 PropertyIsGreaterThanOrEqualTo = 'PropertyIsGreaterThanOrEqualTo'
6998 """Property is greater than or equal to the value."""
6999 PropertyIsLike = 'PropertyIsLike'
7000 """Property matches a pattern."""
7001 PropertyIsNull = 'PropertyIsNull'
7002 """Property is null."""
7003 PropertyIsNil = 'PropertyIsNil'
7004 """Property is nil."""
7005 PropertyIsBetween = 'PropertyIsBetween'
7006 """Property is between two values."""
7008 Equals = 'Equals'
7009 """Geometry is equal to the shape."""
7010 Disjoint = 'Disjoint'
7011 """Geometry does not intersect the shape."""
7012 Touches = 'Touches'
7013 """Geometry touches the shape."""
7014 Within = 'Within'
7015 """Geometry is within the shape."""
7016 Overlaps = 'Overlaps'
7017 """Geometry overlaps the shape."""
7018 Crosses = 'Crosses'
7019 """Geometry crosses the shape."""
7020 Intersects = 'Intersects'
7021 """Geometry intersects the shape."""
7022 Contains = 'Contains'
7023 """Geometry contains the shape."""
7024 DWithin = 'DWithin'
7025 """Geometry is within a distance of the shape."""
7026 Beyond = 'Beyond'
7027 """Geometry is beyond a distance of the shape."""
7028 BBOX = 'BBOX'
7029 """Geometry intersects the bounding box."""
7032class SearchFilterMatchAction(Enum):
7033 """How a filter is applied to a multi-valued property."""
7035 All = 'All'
7036 """All values must match."""
7037 Any = 'Any'
7038 """At least one value must match."""
7039 One = 'One'
7040 """Exactly one value must match."""
7043class SearchFilter(Data):
7044 """Search filter, a tree of filter operators."""
7046 operator: SearchFilterOperator
7047 """Filter operator."""
7048 property: str
7049 """Property name for comparison and spatial operators."""
7050 value: str
7051 """Value for comparison operators."""
7052 shape: 'Shape'
7053 """Shape for spatial operators."""
7054 subFilters: list['SearchFilter']
7055 """Operands of logical operators."""
7056 matchCase: bool
7057 """Compare strings case-sensitively."""
7058 matchAction: SearchFilterMatchAction
7059 """How to match multi-valued properties."""
7060 wildCard: str
7061 """Wildcard character for ``PropertyIsLike``."""
7062 singleChar: str
7063 """Single character placeholder for ``PropertyIsLike``."""
7064 escapeChar: str
7065 """Escape character for ``PropertyIsLike``."""
7068class SearchQuery(Data):
7069 """Search query."""
7071 bounds: Bounds
7072 """Search bounds."""
7073 extraArgs: dict
7074 """Extra arguments for custom searches."""
7075 extraColumns: list
7076 """Extra columns to select."""
7077 extraParams: dict
7078 """Extra parameters to pass to a provider."""
7079 extraWhere: list
7080 """Extra where clauses."""
7081 keyword: str
7082 """Keyword to search for."""
7083 layers: list['Layer']
7084 """Layers to search in."""
7085 limit: int
7086 """Limit the number of results."""
7087 filter: SearchFilter
7088 """Search filter."""
7089 project: 'Project'
7090 """Project to search in."""
7091 resolution: float
7092 """Pixel resolution for geometry search."""
7093 shape: 'Shape'
7094 """Shape to search in."""
7095 sort: list[SearchSort]
7096 """Sort options."""
7097 tolerance: 'UomValue'
7098 """Tolerance for geometry search."""
7099 uids: list[str]
7100 """UIDs to search for."""
7103class SearchResult(Data):
7104 """Search result."""
7106 feature: 'Feature'
7107 """Found feature."""
7108 layer: 'Layer'
7109 """Layer whose finder found the feature, or ``None`` for project and application finders."""
7110 finder: 'Finder'
7111 """Finder that found the feature."""
7114class TextSearchType(Enum):
7115 """Text search type."""
7117 exact = 'exact'
7118 """Match the whole string."""
7119 begin = 'begin'
7120 """Match the beginning of the string."""
7121 end = 'end'
7122 """Match the end of the string."""
7123 any = 'any'
7124 """Match any substring."""
7125 like = 'like'
7126 """Use the percent sign as a placeholder."""
7129class TextSearchOptions(Data):
7130 """How keywords are matched against a text field."""
7132 type: TextSearchType
7133 """Type of the search."""
7134 minLength: int = 0
7135 """Min. keyword length."""
7136 caseSensitive: bool = False
7137 """Use case-sensitive search."""
7140class SortOptions(Data):
7141 """Sort order for features."""
7143 fieldName: str
7144 """Field name to sort by."""
7145 reverse: bool = False
7146 """Sort in descending order."""
7149class SearchManager(Node):
7150 """Search manager, runs search queries through the finders."""
7152 def run_search(self, search: 'SearchQuery', user: 'User') -> list['SearchResult']:
7153 """Run a search query.
7155 Runs the finders of the query layers, the project finders and the application
7156 finders the user may use and which can run the query.
7158 Args:
7159 search: Search query.
7160 user: User running the search.
7162 Returns:
7163 Search results, at most ``search.limit`` if a limit is given.
7164 """
7167class Finder(Node):
7168 """Search provider, finds features for search queries."""
7170 title: str
7171 """Finder title."""
7172 category: str
7173 """Category assigned to the results."""
7175 supportsFilterSearch: bool = False
7176 """The finder supports filter searches."""
7177 supportsGeometrySearch: bool = False
7178 """The finder supports geometry searches."""
7179 supportsKeywordSearch: bool = False
7180 """The finder supports keyword searches."""
7182 withFilter: bool
7183 """Filter searches are enabled."""
7184 withGeometry: bool
7185 """Geometry searches are enabled."""
7186 withKeyword: bool
7187 """Keyword searches are enabled."""
7189 templates: list['Template']
7190 """Templates to format the found features."""
7191 models: list['Model']
7192 """Models used to read the features."""
7193 sourceLayers: list['SourceLayer']
7194 """Source layers to search in, for finders of OWS and QGIS sources."""
7196 tolerance: 'UomValue'
7197 """Tolerance for geometry searches."""
7199 def run(self, search: SearchQuery, user: 'User', layer: Optional['Layer'] = None) -> list['Feature']:
7200 """Run a search query.
7202 Args:
7203 search: Search query.
7204 user: User running the search.
7205 layer: Layer the finder belongs to, if any.
7207 Returns:
7208 Found features.
7209 """
7211 def can_run(self, search: SearchQuery, user: 'User') -> bool:
7212 """Check if the finder can run a search query.
7214 Args:
7215 search: Search query.
7216 user: User running the search.
7218 Returns:
7219 ``True`` if the finder can run the query.
7220 """
7221################################################################################
7224################################################################################
7225# /base/storage/types.pyinc
7228class StorageManager(Node):
7229 """Storage manager, holds the storage providers."""
7231 providers: list['StorageProvider']
7232 """Configured storage providers."""
7234 def create_provider(self, cfg: Config, **kwargs) -> 'StorageProvider':
7235 """Create a storage provider and add it to the manager.
7237 A provider with the same uid replaces the existing one.
7239 Args:
7240 cfg: Provider configuration.
7241 **kwargs: Extra configuration values.
7243 Returns:
7244 The new provider.
7245 """
7247 def find_provider(self, uid: Optional[str] = None) -> Optional['StorageProvider']:
7248 """Find a storage provider.
7250 Args:
7251 uid: Provider uid. If not given, the first provider is returned.
7253 Returns:
7254 The provider, or ``None`` if not found.
7255 """
7259class StorageRecord(Data):
7260 """Storage record."""
7262 name: str
7263 """Record name."""
7264 userUid: str
7265 """Uid of the user who last wrote the record."""
7266 data: str
7267 """Serialized record data."""
7268 created: 'datetime.datetime'
7269 """Record create time."""
7270 updated: 'datetime.datetime'
7271 """Record update time."""
7274class StorageProvider(Node):
7275 """Storage provider, stores named records grouped by category."""
7277 def list_names(self, category: str) -> list[str]:
7278 """List the record names in a category.
7280 Args:
7281 category: Category name.
7283 Returns:
7284 Record names.
7285 """
7287 def read(self, category: str, name: str) -> Optional['StorageRecord']:
7288 """Read a record.
7290 Args:
7291 category: Category name.
7292 name: Record name.
7294 Returns:
7295 The record, or ``None`` if not found.
7296 """
7298 def write(self, category: str, name: str, data: str, user_uid: str):
7299 """Create a record or update an existing one.
7301 Args:
7302 category: Category name.
7303 name: Record name.
7304 data: Serialized record data.
7305 user_uid: Uid of the user who writes the record.
7306 """
7308 def delete(self, category: str, name: str):
7309 """Delete a record.
7311 Args:
7312 category: Category name.
7313 name: Record name.
7314 """
7315################################################################################
7318################################################################################
7319# /base/template/types.pyinc
7322class TemplateArgs(Data):
7323 """Template arguments."""
7325 app: 'Application'
7326 """Application object."""
7327 locale: 'Locale'
7328 """Current locale."""
7329 date: 'DateFormatter'
7330 """Locale-aware date formatter."""
7331 time: 'TimeFormatter'
7332 """Locale-aware time formatter."""
7333 number: 'NumberFormatter'
7334 """Locale-aware number formatter."""
7337class TemplateRenderInput(Data):
7338 """Template render input."""
7340 args: dict | Data
7341 """Template arguments."""
7342 crs: 'Crs'
7343 """CRS for maps."""
7344 dpi: int
7345 """Output resolution in dots per inch."""
7346 locale: 'Locale'
7347 """Locale for the output."""
7348 maps: list[MapRenderInput]
7349 """Maps to render, for print templates."""
7350 mimeOut: str
7351 """Requested output MIME type."""
7352 notify: Callable
7353 """Callback for progress messages."""
7354 project: 'Project'
7355 """Current project."""
7356 user: 'User'
7357 """Current user."""
7360class TemplateQualityLevel(Config):
7361 """Print quality level users can choose."""
7363 name: str
7364 """Quality level name shown to users."""
7365 dpi: int
7366 """Print resolution in dots per inch."""
7369class Template(Node):
7370 """Template, generates content from data."""
7372 mapSize: UomSize
7373 """Default map size for the template."""
7374 mimeTypes: list[str]
7375 """MIME types the template can generate."""
7376 pageSize: UomSize
7377 """Default page size for printing."""
7378 pageMargin: UomExtent
7379 """Default page margin for printing."""
7380 subject: str
7381 """Template subject, the purpose the template serves, like ``feature.description``."""
7382 title: str
7383 """Template title."""
7385 def render(self, tri: TemplateRenderInput) -> ContentResponse:
7386 """Render the template.
7388 Args:
7389 tri: Render input.
7391 Returns:
7392 A response with the generated content.
7393 """
7396class TemplateManager(Node):
7397 """Template manager, finds templates by subject and creates them from files."""
7399 def find_templates(self, subjects: list[str], where: list[Node], user: 'User' = None, mime: MimeType = None) -> list['Template']:
7400 """Find templates for several subjects.
7402 Args:
7403 subjects: Template subjects.
7404 where: Objects whose templates are searched, in this order.
7405 user: If given, only templates this user can use.
7406 mime: If given, only templates which can produce this MIME type.
7408 Returns:
7409 Found templates, one per subject at most.
7410 """
7412 def find_template(self, subject: str, where: list[Node], user: 'User' = None, mime: MimeType = None) -> Optional['Template']:
7413 """Find a template for a subject.
7415 The templates of the objects in ``where`` are searched in the given order,
7416 then the application templates. A template without ``mimeTypes`` matches any
7417 MIME type.
7419 Args:
7420 subject: Template subject.
7421 where: Objects whose templates are searched, in this order.
7422 user: If given, only templates this user can use.
7423 mime: If given, only templates which can produce this MIME type.
7425 Returns:
7426 The first matching template, or ``None``.
7427 """
7429 def template_from_path(self, path: str) -> Optional['Template']:
7430 """Create a template from a file.
7432 The template type is derived from the file extension.
7434 Args:
7435 path: File path.
7437 Returns:
7438 A template, or ``None`` if the file is not a template.
7439 """
7440################################################################################
7443################################################################################
7444# /base/web/types.pyinc
7447class RequestMethod(Enum):
7448 """Web request method."""
7450 GET = 'GET'
7451 HEAD = 'HEAD'
7452 POST = 'POST'
7453 PUT = 'PUT'
7454 DELETE = 'DELETE'
7455 CONNECT = 'CONNECT'
7456 OPTIONS = 'OPTIONS'
7457 TRACE = 'TRACE'
7458 PATCH = 'PATCH'
7461class WebRequester:
7462 """Web requester, gives access to an incoming web request."""
7464 environ: dict
7465 """Request environment."""
7466 method: RequestMethod
7467 """Request method."""
7468 contentType: str
7469 """Request content type."""
7470 root: 'Root'
7471 """Object tree root."""
7472 site: 'WebSite'
7473 """Website the request is processed for."""
7475 session: 'AuthSession'
7476 """Current session."""
7477 user: 'User'
7478 """Current user."""
7480 isGet: bool
7481 """The request is a GET request."""
7482 isPost: bool
7483 """The request is a POST request."""
7484 isApi: bool
7485 """The request provides json data in the POST body."""
7486 isForm: bool
7487 """The request provides form data in the POST body."""
7488 isSecure: bool
7489 """The request is made over https."""
7491 scheme: str
7492 """Request scheme, http or https."""
7493 host: str
7494 """Request host name, without the port, empty if the host is invalid."""
7495 port: int
7496 """Request port, 0 if not given."""
7497 ip: str
7498 """Client address."""
7500 def parse(self):
7501 """Parse the request path, the parameters and the structured payload.
7503 Also determines the scheme, host, port and client address, taking proxy
7504 headers into account if the site has proxies.
7506 Raises:
7507 ``gws.base.web.error.HTTPException``: If the request path, the host or the payload is invalid.
7508 """
7510 def params(self) -> dict:
7511 """Return the GET parameters.
7513 Returns:
7514 Parameters from the query string and from the request path.
7515 """
7517 def query_params(self) -> dict:
7518 """Return the GET parameters from the query string.
7520 Returns:
7521 Query string parameters.
7522 """
7524 def path(self) -> str:
7525 """Return the request path after the command.
7527 Returns:
7528 The rest of the path after ``/_/<command>/``.
7529 """
7531 def struct(self) -> dict:
7532 """Return the structured payload of an API request.
7534 Returns:
7535 The decoded JSON or MessagePack payload.
7536 """
7538 def command(self) -> str:
7539 """Return the command name.
7541 Returns:
7542 The command from the path, or from the ``cmd`` parameter.
7543 """
7545 def data(self) -> bytes:
7546 """Return the raw POST data, unzipped if gzip-encoded.
7548 Returns:
7549 POST data, empty for non-POST requests.
7551 Raises:
7552 ``gws.base.web.error.HTTPException``: If the content length is invalid or too large, or the data cannot be unzipped.
7553 """
7555 def form(self) -> list[tuple[str, Any]]:
7556 """Return the POST form data.
7558 Returns:
7559 A list of ``(key, value)`` tuples, including uploaded files; empty if the request is not a form.
7561 Raises:
7562 ``gws.base.web.error.HTTPException``: If the form data cannot be decoded.
7563 """
7565 def text(self) -> str:
7566 """Return the POST data decoded to text, with the charset of the request.
7568 Returns:
7569 POST data as text.
7571 Raises:
7572 ``gws.base.web.error.HTTPException``: If the data cannot be decoded.
7573 """
7575 def cookie(self, key: str, default: str = '') -> str:
7576 """Get a cookie.
7578 Args:
7579 key: Cookie name.
7580 default: Default value.
7582 Returns:
7583 A cookie value.
7584 """
7586 def header(self, key: str, default: str = '') -> str:
7587 """Get a header.
7589 Args:
7590 key: Header name.
7591 default: Default value.
7593 Returns:
7594 A header value.
7595 """
7597 def has_param(self, key: str) -> bool:
7598 """Check if a GET parameter exists, ignoring case.
7600 Args:
7601 key: Parameter name.
7603 Returns:
7604 ``True`` if the parameter exists.
7605 """
7607 def param(self, key: str, default: str = '') -> str:
7608 """Get a GET parameter, ignoring case.
7610 Args:
7611 key: Parameter name.
7612 default: Default value.
7614 Returns:
7615 A parameter value.
7616 """
7618 def env(self, key: str, default: str = '') -> str:
7619 """Get a WSGI environment variable.
7621 Args:
7622 key: Variable name.
7623 default: Default value.
7625 Returns:
7626 A variable value.
7627 """
7629 def content_responder(self, response: ContentResponse) -> 'WebResponder':
7630 """Create a responder for a content response.
7632 Args:
7633 response: Response with literal content or a content path.
7635 Returns:
7636 A responder.
7637 """
7639 def redirect_responder(self, response: RedirectResponse) -> 'WebResponder':
7640 """Create a responder for a redirect response.
7642 Args:
7643 response: Redirect response.
7645 Returns:
7646 A responder.
7647 """
7649 def api_responder(self, response: Response) -> 'WebResponder':
7650 """Create a responder for an API (structured) response.
7652 The response is encoded as JSON or MessagePack, depending on the request.
7654 Args:
7655 response: Response object.
7657 Returns:
7658 A responder.
7659 """
7661 def error_responder(self, exc: Exception) -> 'WebResponder':
7662 """Create a responder for an exception.
7664 Args:
7665 exc: An exception; anything but an HTTP exception results in a 500 response.
7667 Returns:
7668 A responder.
7669 """
7671 def absolute_url_for(self, request_path: str, **params) -> str:
7672 """Create an absolute URL pointing to the requested host.
7674 Args:
7675 request_path: Request path.
7676 **params: Additional GET parameters.
7678 Returns:
7679 A URL.
7680 """
7682 def relative_url_for(self, request_path: str, **params) -> str:
7683 """Create a host-relative URL.
7685 Args:
7686 request_path: Request path.
7687 **params: Additional GET parameters.
7689 Returns:
7690 A URL.
7691 """
7693 def canonical_url_for(self, request_path: str, **params) -> str:
7694 """Create an absolute URL pointing to the canonical host.
7696 Args:
7697 request_path: Request path.
7698 **params: Additional GET parameters.
7700 Returns:
7701 A URL.
7702 """
7704 def set_session(self, session: 'AuthSession'):
7705 """Attach a session to the requester and set the user from it.
7707 Args:
7708 session: A session object.
7709 """
7712class WebResponder:
7713 """Web responder, builds and sends the response to a web request."""
7715 status: int
7716 """Response status."""
7718 def send_response(self, environ: dict, start_response: Callable):
7719 """Send the response to the client.
7721 Args:
7722 environ: WSGI environment.
7723 start_response: WSGI ``start_response`` function.
7725 Returns:
7726 The WSGI response iterable.
7727 """
7729 def set_cookie(self, key: str, value: str, **kwargs):
7730 """Set a cookie.
7732 Args:
7733 key: Cookie name.
7734 value: Cookie value.
7735 **kwargs: Cookie options.
7736 """
7738 def delete_cookie(self, key: str, **kwargs):
7739 """Delete a cookie.
7741 Args:
7742 key: Cookie name.
7743 **kwargs: Cookie options.
7744 """
7746 def set_status(self, status: int):
7747 """Set the response status.
7749 Args:
7750 status: HTTP status code.
7751 """
7753 def add_header(self, key: str, value: str):
7754 """Add a header.
7756 Args:
7757 key: Header name.
7758 value: Header value.
7759 """
7761 def set_body(self, body: str | bytes):
7762 """Set the response body.
7764 Args:
7765 body: New response body; strings are encoded as UTF-8.
7766 """
7769class WebDocumentRoot(Data):
7770 """Directory served over the web."""
7772 dir: DirPath
7773 """Local directory."""
7774 allowMime: list[str]
7775 """Allowed mime types."""
7776 denyMime: list[str]
7777 """Restricted mime types."""
7780class WebRewriteRule(Data):
7781 """URL rewrite rule."""
7783 pattern: Regex
7784 """URL matching pattern."""
7785 target: str
7786 """Rule target, with ``$1``, ``$2`` etc. placeholders for the pattern groups."""
7787 reversed: bool
7788 """The rule rewrites URLs generated by the server, not incoming URLs."""
7791class WebCors(Data):
7792 """CORS options."""
7794 allowCredentials: bool
7795 """Allow credentials in cross-origin requests."""
7796 allowHeaders: str
7797 """Headers allowed in cross-origin requests."""
7798 allowMethods: str
7799 """Methods allowed in cross-origin requests."""
7800 allowOrigin: str
7801 """Origins allowed to make cross-origin requests."""
7804class WebManager(Node):
7805 """Web manager, holds the web site."""
7807 site: 'WebSite'
7808 """Configured web site."""
7811class WebSite(Node):
7812 """Web site the server responds to."""
7814 assetsRoot: Optional[WebDocumentRoot]
7815 """Root directory for assets."""
7816 canonicalHost: str
7817 """Host name for absolute canonical URLs."""
7818 corsOptions: WebCors
7819 """CORS options."""
7820 hostnames: list[str]
7821 """Host names this site responds to."""
7822 rewriteRules: list[WebRewriteRule]
7823 """URL rewrite rules."""
7824 proxyCount: int
7825 """Number of proxies in front of the server."""
7826 ssl: bool
7827 """The site is served over https."""
7828 staticRoot: WebDocumentRoot
7829 """Root directory for static files."""
7831 def url_for(self, req: 'WebRequester', path: str, mode: str, **params) -> str:
7832 """Create a URL for a request path, applying the reversed rewrite rules.
7834 If the path, or the rewritten path, is an absolute URL, only the parameters
7835 are added. In the ``absolute`` and ``canonical`` modes, the URL gets the scheme
7836 of the request. The host is the canonical host in the ``canonical`` mode, and
7837 the request host and port otherwise or if there is no canonical host.
7839 Args:
7840 req: Web requester.
7841 path: Request path.
7842 mode: ``absolute``, ``relative`` or ``canonical``.
7843 **params: Extra GET parameters.
7845 Returns:
7846 A URL.
7848 Raises:
7849 ``gws.BadRequestError``: If an absolute URL is requested and there is no host.
7850 """
7851################################################################################
7854################################################################################
7855# /base/exporter/types.pyinc
7858class ExportArgs(Data):
7859 """Arguments passed to ``Exporter.run``."""
7861 exporter: 'Exporter'
7862 """The exporter."""
7863 features: Optional[list['Feature']]
7864 """Features to export."""
7865 shape: Optional['Shape']
7866 """Shape from the export request."""
7867 project: 'Project'
7868 """Project of the export request."""
7869 user: 'User'
7870 """User the export runs for."""
7871 notify: Callable
7872 """Progress callback, called with an event name."""
7873 maxErrors: int = 100
7874 """Maximum number of errors collected in the result."""
7877class ExportTarget(Enum):
7878 """Export target."""
7880 file = 'file'
7881 """Save the export result to a file on the server."""
7882 download = 'download'
7883 """Return the export result for download."""
7886class ExportResult(Data):
7887 """Export result."""
7889 path: str
7890 """Path of the result file, empty if nothing was exported."""
7891 mimeType: str
7892 """Mime type of the result file."""
7893 numFiles: int
7894 """Number of files written."""
7895 numFeaturesTotal: int
7896 """Number of requested features."""
7897 numFeaturesExported: int
7898 """Number of exported features."""
7899 errors: list[str]
7900 """Error messages for features that were not exported."""
7903class FeatureExportStrategy(Enum):
7904 """How exported features are obtained."""
7906 load = 'load'
7907 """Load features by ids from the source model."""
7908 client = 'client'
7909 """Export features using properties as received from the client."""
7912class ExportRequestType(Enum):
7913 """Kind of data to export."""
7915 vector = 'vector'
7916 """Vector features."""
7917 raster = 'raster'
7918 """Raster data."""
7921class ExportRequest(Request):
7922 """Export request from the client."""
7924 type: ExportRequestType
7925 """Kind of data to export."""
7926 exporterUid: str
7927 """Uid of the exporter."""
7928 features: Optional[list['FeatureProps']]
7929 """Features to export."""
7930 shape: Optional['ShapeProps']
7931 """Shape passed to the exporter."""
7934class ExportResponse(Response):
7935 """Export response with the content of the result file."""
7937 content: str | bytes
7938 """File content."""
7939 contentFilename: str
7940 """File name."""
7941 mimeType: str
7942 """Mime type."""
7945class ExporterManager(Node):
7946 """Exporter manager."""
7948 def start_export_job(self, request: ExportRequest, user: 'User') -> 'JobStatusResponse':
7949 """Create and schedule a background export job.
7951 Args:
7952 request: Export request.
7953 user: User the export runs for.
7955 Returns:
7956 The status of the new job.
7957 """
7959 def exec_export(self, request: ExportRequest, out_path: str):
7960 """Run an export directly, as the system user, and copy the result file.
7962 Args:
7963 request: Export request.
7964 out_path: Path to copy the result file to.
7966 Returns:
7967 The export result.
7969 Raises:
7970 ``gws.Error``: If no features were exported.
7971 """
7973 def list_exporters(self, where: list['Node'], user: 'User') -> list['Exporter']:
7974 """List the exporters of the given objects that the user can use.
7976 Of several exporters with the same title, only the first one is listed.
7978 Args:
7979 where: Objects with an ``exporters`` list, e.g. a project and the application.
7980 ``None`` entries are ignored.
7981 user: User.
7983 Returns:
7984 A list of exporters.
7985 """
7987 def get_exporter(self, where: list['Node'], uid: str, user: 'User') -> Optional['Exporter']:
7988 """Find an exporter by uid among the exporters the user can use.
7990 Args:
7991 where: Objects with an ``exporters`` list, e.g. a project and the application.
7992 uid: Exporter uid.
7993 user: User.
7995 Returns:
7996 The exporter, or ``None`` if it is not found.
7997 """
8000class Exporter(Node):
8001 """Exporter.
8003 Writes features to files in a specific format.
8004 """
8006 title: str
8007 """Exporter title, shown in the client."""
8008 options: dict
8009 """Format-specific options, passed to the GDAL driver."""
8011 supportsVector: bool
8012 """The exporter can export vector features."""
8013 supportsRaster: bool
8014 """The exporter can export raster data."""
8015 supportsMultiLayer: bool
8016 """The format can hold several layers in one file."""
8018 withNoGeometry: bool
8019 """Export features without geometry instead of skipping them."""
8020 withMixedGeometry: bool
8021 """Allow different geometry types in one layer instead of skipping features."""
8022 withMixedCrs: bool
8023 """Allow different CRS in one layer instead of skipping features."""
8024 withMultiLayer: bool
8025 """Write all layers to one file."""
8027 supportedAttributeTypes: Optional[list[gws.AttributeType]]
8028 """Attribute types the exporter can write. If empty, the types supported by GDAL are used."""
8030 def run(self, ea: ExportArgs, er: ExportResult):
8031 """Export the features.
8033 Writes the result file and sets its path, the mime type, the counts
8034 and errors in the export result.
8036 Args:
8037 ea: Export arguments.
8038 er: Export result, filled by the exporter.
8039 """
8040################################################################################
8044################################################################################
8045# /base/application/types.pyinc
8048class MiddlewareManager(Node):
8049 """Middleware manager.
8051 Middleware objects process every web request: the web server calls
8052 ``enter_middleware`` on each of them in dependency order before the action,
8053 and ``exit_middleware`` in reverse order after it.
8054 """
8056 def register(self, obj: Node, name: str, depends_on: Optional[list[str]] = None):
8057 """Register an object as a middleware.
8059 Args:
8060 obj: The middleware object.
8061 name: Middleware name, for example ``db`` or ``auth``.
8062 depends_on: Names of middleware that must run before this one.
8063 """
8065 def objects(self) -> list[Node]:
8066 """Return the registered middleware objects in dependency order.
8068 Returns:
8069 A list of middleware objects, dependencies first.
8071 Raises:
8072 Error: If the dependencies are cyclic or refer to an unknown name.
8073 """
8076class TemplateOptions(Data):
8077 """Options for the built-in application and project home pages."""
8079 withLogin: bool = True
8080 """Show the login form on the home page."""
8081 footerText: Optional[str]
8082 """HTML text for the home page footer."""
8083 withGws: bool = True
8084 """Show the GWS logo in the home page footer."""
8085 homeResources: Optional[list[str]]
8086 """Extra resource URLs for the home page."""
8087 projectResources: Optional[list[str]]
8088 """Extra resource URLs for the project page."""
8091class Application(Node):
8092 """Application object.
8094 The top-level node of the configuration tree. It holds the managers, the
8095 global objects and the projects, and is available as ``root.app``.
8096 """
8098 client: 'Client'
8099 """Default client, used by projects without their own client configuration."""
8101 localeUids: list[str]
8102 """Default locale uids for all projects."""
8104 metadata: 'Metadata'
8105 """Application metadata."""
8107 monitor: 'ServerMonitor'
8108 """Server monitor, watches configuration files and runs periodic tasks."""
8110 templateOptions: TemplateOptions
8111 """Options for the built-in home page templates."""
8113 title: str
8114 """Application title."""
8116 vars: dict
8117 """Custom variables from the configuration."""
8119 version: str
8120 """Application version, for example ``8.5.3``."""
8122 versionString: str
8123 """Version string for display, with the revision if known."""
8125 def supported_crs(self) -> list['Crs']:
8126 """Return all CRS supported by the application.
8128 These are the CRS of all maps and the CRS supported by OWS services,
8129 plus the registered ones. The list is computed on the first call.
8131 Returns:
8132 A list of CRS objects, sorted by srid.
8133 """
8135 def register_supported_crs(self, crs: 'Crs'):
8136 """Register an additional supported CRS.
8138 Must be called during configuration.
8140 Args:
8141 crs: The CRS object.
8142 """
8144 defaultPrinter: 'Printer'
8145 """Default printer, used when no printer is configured."""
8147 actionMgr: 'ActionManager'
8148 """Action manager."""
8150 authMgr: 'AuthManager'
8151 """Authorization manager."""
8153 databaseMgr: 'DatabaseManager'
8154 """Database manager."""
8156 exporterMgr: 'ExporterManager'
8157 """Exporter manager."""
8159 jobMgr: 'JobManager'
8160 """Job manager."""
8162 middlewareMgr: 'MiddlewareManager'
8163 """Middleware manager."""
8165 modelMgr: 'ModelManager'
8166 """Model manager."""
8168 printerMgr: 'PrinterManager'
8169 """Printer manager."""
8171 searchMgr: 'SearchManager'
8172 """Search manager."""
8174 serverMgr: 'ServerManager'
8175 """Server manager."""
8177 storageMgr: 'StorageManager'
8178 """Storage manager."""
8180 templateMgr: 'TemplateManager'
8181 """Template manager."""
8183 webMgr: 'WebManager'
8184 """Web manager."""
8186 actions: list['Action']
8187 """Actions available in all projects."""
8189 projects: list['Project']
8190 """Configured projects."""
8192 exporters: list['Exporter']
8193 """Global exporters."""
8195 finders: list['Finder']
8196 """Finders available in all projects."""
8198 templates: list['Template']
8199 """Global templates, including the built-in ones."""
8201 printers: list['Printer']
8202 """Global printers."""
8204 models: list['Model']
8205 """Global models."""
8207 owsServices: list['OwsService']
8208 """OWS services provided by the server."""
8210 def project(self, uid: str) -> Optional['Project']:
8211 """Find a project by its uid.
8213 Args:
8214 uid: Project uid.
8216 Returns:
8217 The project, or ``None`` if not found.
8218 """
8220 def helper(self, ext_type: str) -> Optional['Node']:
8221 """Return a helper object by its type.
8223 A helper that is not configured is created with default options on the first call.
8225 Args:
8226 ext_type: Helper type, for example ``upload``.
8228 Returns:
8229 The helper object.
8231 Raises:
8232 Error: If the helper type does not exist.
8233 """
8235 def developer_option(self, key: str):
8236 """Return the value of a developer option.
8238 Developer options are configured in the ``developer`` property of the
8239 application config and are meant for development and debugging only.
8241 Args:
8242 key: Option name, for example ``template.always_reload``.
8244 Returns:
8245 The option value, or ``None`` if it is not set.
8246 """
8247################################################################################