Coverage for gws-app/gws/__init__.py: 99%
2086 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-05 13:35 +0200
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-05 13:35 +0200
1"""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 excludePlugins: Optional[list[str]]
667 """Names of the core plugins that should be deactivated."""
668 plugins: Optional[list[ApplicationManifestPlugin]]
669 """Custom plugins."""
670 locales: list[str]
671 """Locale names supported by this application."""
672 tsConfig: list[str]
673 """Path to ``tsconfig.json``."""
674 withFallbackConfig: bool = False
675 """Use a minimal fallback configuration."""
676 withStrictConfig: bool = False
677 """Stop the application upon a configuration error."""
680class ExtObjectDescriptor(Data):
681 """Extension object descriptor."""
683 extName: str
684 """Full extension name like ``gws.ext.object.layer.wms``."""
685 extType: str
686 """Extension type like ``wms``."""
687 classPtr: type
688 """Class object."""
689 ident: str
690 """Identifier."""
691 modName: str
692 """Name of the module that contains the class."""
693 modPath: str
694 """Path to the module that contains the class."""
697class ExtCommandDescriptor(Data):
698 """Command descriptor, describes the action method that handles a command."""
700 extName: str
701 """Full command name like ``gws.ext.command.api.mapGetBox``."""
702 extType: str
703 """Command name like ``mapGetBox``."""
704 extCommandCategory: 'CommandCategory'
705 """Command category."""
706 methodName: str
707 """Name of the action method that handles the command."""
708 methodPtr: Callable
709 """Command method. Not set by ``SpecRuntime.command_descriptor``."""
710 request: 'Request'
711 """Request sent to the command. Not set by ``SpecRuntime.command_descriptor``."""
712 tArg: str
713 """Type uid of the command argument (the request)."""
714 tOwner: str
715 """Type uid of the action class that owns the command."""
716 owner: ExtObjectDescriptor
717 """Object descriptor of the action class that owns the command."""
720class SpecReadOption(Enum):
721 """Options for reading values with ``SpecRuntime.read``."""
723 acceptExtraProps = 'acceptExtraProps'
724 """Accept extra object properties."""
725 allowMissing = 'allowMissing'
726 """Allow otherwise required properties to be missing."""
727 caseInsensitive = 'caseInsensitive'
728 """Case insensitive search for properties."""
729 convertValues = 'convertValues'
730 """Try to convert values to specified types."""
731 ignoreExtraProps = 'ignoreExtraProps'
732 """Silently ignore extra object properties."""
733 verboseErrors = 'verboseErrors'
734 """Add the value and the location of an error to ``ReadError`` exceptions."""
737class CommandCategory(Enum):
738 """Command category."""
740 api = 'api'
741 """API command."""
742 cli = 'cli'
743 """CLI command."""
744 get = 'get'
745 """Web GET command."""
746 post = 'post'
747 """Web POST command."""
748 raw = 'raw'
749 """Raw Web command without preprocessing."""
752class SpecRuntime:
753 """Spec runtime.
755 Provides access to the generated specs: reading and validating values,
756 looking up extension objects and commands, and loading classes.
757 """
759 version: str
760 """Application version."""
761 manifest: ApplicationManifest
762 """Application manifest."""
763 appBundlePaths: list[str]
764 """Paths of the client bundles of all chunks."""
766 def read(self, value, type_name: str, path: str = '', options: set[SpecReadOption] = None):
767 """Read and validate a raw value according to a spec type.
769 Args:
770 value: Raw value from a config or a request.
771 type_name: Type uid or extension name.
772 path: Path of the config file, used to resolve relative paths and in error messages.
773 options: Read options.
775 Returns:
776 The parsed value. Objects are returned as ``gws.Data``.
778 Raises:
779 ``gws.spec.core.ReadError``: If the value does not match the type.
780 """
782 def object_descriptor(self, type_name: str) -> Optional[ExtObjectDescriptor]:
783 """Get an object descriptor.
785 Args:
786 type_name: Type uid or extension name.
788 Returns:
789 A descriptor or ``None`` if the type is not found.
790 """
792 def command_descriptor(self, command_category: CommandCategory, command_name: str) -> Optional[ExtCommandDescriptor]:
793 """Get a command descriptor.
795 Args:
796 command_category: Command category.
797 command_name: Command name.
799 Returns:
800 A descriptor or ``None`` if the command is not found.
801 """
803 def register_object(self, ext_name: ClassRef, obj_type: str, cls: type):
804 """Register an extension class at run time.
806 The class gets the ``extName`` and ``extType`` attributes.
808 Args:
809 ext_name: Extension category, like ``gws.ext.object.layer``.
810 obj_type: Extension type, like ``wms``.
811 cls: Class to register.
813 Raises:
814 ``gws.spec.core.Error``: If the class reference is invalid.
815 """
817 def get_class(self, classref: ClassRef, ext_type: Optional[str] = None) -> Optional[type]:
818 """Get a class object for a class reference.
820 The module defining the class is imported on demand.
822 Args:
823 classref: Class reference: a class, a class name or an extension name.
824 ext_type: Extension type, used when ``classref`` is an extension category name.
825 Defaults to ``default``.
827 Returns:
828 A class or ``None`` if the reference is not found.
830 Raises:
831 ``gws.spec.core.LoadError``: If the module cannot be imported.
832 """
834 def parse_classref(self, classref: ClassRef) -> tuple[Optional[type], str, str]:
835 """Parse a class reference.
837 Args:
838 classref: Class reference.
840 Returns:
841 A tuple ``(class object, class name, extension name)``, where only one element is set.
843 Raises:
844 ``gws.spec.core.Error``: If the class reference is invalid.
845 """
847 def get_config_types(self, lang: str) -> list[dict]:
848 """Get the configuration types as dictionaries.
850 Docstrings, titles and enum docs are taken from the strings in the given language.
852 Args:
853 lang: Language code.
855 Returns:
856 A list of type dictionaries.
857 """
858################################################################################
862################################################################################
863# /core/_tree.pyinc
866class Object:
867 """Basic GWS object.
869 An object has permissions and can provide properties for the client.
870 """
872 permissions: dict[Access, Acl]
873 """Mapping from an access mode to a list of ACL tuples."""
875 def props(self, user: 'User') -> Props:
876 """Generate a ``Props`` struct for this object.
878 Do not call this method directly, use ``gws.props_of`` instead, which also checks permissions.
880 Args:
881 user: The user for which the props should be generated.
883 Returns:
884 A ``Props`` object or a dict. Nested objects are converted to props as well.
885 """
887 def __init__(self):
888 self.permissions = {}
891from .core import tree_impl
893setattr(tree_impl, 'Access', Access)
894setattr(tree_impl, 'Error', Error)
895setattr(tree_impl, 'Data', Data)
896setattr(tree_impl, 'Props', Props)
897setattr(tree_impl, 'Object', Object)
899Object.__repr__ = tree_impl.object_repr
902class Node(Object):
903 """GWS object tree node.
905 Nodes are created by the ``Root`` or by their parent node. Configuration hooks
906 (``pre_configure``, ``configure``, ``post_configure``) are invoked for every class in the MRO
907 that defines them, base classes first, so they do not need to call ``super()``.
908 """
910 extName: str
911 """Full extension name like ``gws.ext.object.layer.wms``."""
912 extType: str
913 """Extension type like ``wms``."""
915 config: Config
916 """Configuration for this object."""
917 root: 'Root'
918 """Root object."""
919 parent: 'Node'
920 """Parent object."""
921 children: list['Node']
922 """Child objects."""
923 uid: str
924 """Unique ID."""
926 def initialize(self, config):
927 """Initialize the node.
929 Store the configuration, set up the permissions, then run ``pre_configure`` and ``configure``.
931 Args:
932 config: Configuration.
933 """
934 return tree_impl.node_initialize(self, config)
936 def pre_configure(self):
937 """Pre-configuration hook.
939 Called before ``configure``, when the node is initialized.
940 """
942 def configure(self):
943 """Configuration hook.
945 Called when the node is initialized. Raising an exception here aborts the creation of the node.
946 """
948 def post_configure(self):
949 """Post-configuration hook.
951 Called after the whole object tree has been created.
952 """
954 def activate(self):
955 """Activation hook.
957 Called by ``Root.activate`` after the configuration has been loaded.
958 """
960 def create_child(self, classref: ClassRef, config: Config = None, **kwargs) -> Optional['Node']:
961 """Create a child object.
963 Args:
964 classref: Class reference.
965 config: Configuration.
966 **kwargs: Additional configuration properties.
968 Returns:
969 A newly created object or ``None`` if the object cannot be initialized.
970 """
971 return tree_impl.node_create_child(self, classref, config, **kwargs)
973 def create_child_if_configured(self, classref: ClassRef, config=None, **kwargs) -> Optional['Node']:
974 """Create a child object if the configuration is not None.
976 Args:
977 classref: Class reference.
978 config: Configuration.
979 **kwargs: Additional configuration properties.
981 Returns:
982 A newly created object or ``None`` if the configuration is ``None`` or the object cannot be initialized.
983 """
984 return tree_impl.node_create_child_if_configured(self, classref, config, **kwargs)
986 def create_children(self, classref: ClassRef, configs: list[Config], **kwargs) -> list['Node']:
987 """Create a list of child objects from a list of configurations.
989 Args:
990 classref: Class reference.
991 configs: List of configurations.
992 **kwargs: Additional configuration properties.
994 Returns:
995 A list of newly created objects.
996 """
997 return tree_impl.node_create_children(self, classref, configs, **kwargs)
999 def cfg(self, key: str, default=None):
1000 """Fetch a configuration property.
1002 Args:
1003 key: Property key. If it contains dots, fetch nested properties.
1004 default: Default to return if the property is not found.
1006 Returns:
1007 A property value.
1008 """
1009 return tree_impl.node_cfg(self, key, default)
1011 def is_a(self, classref: ClassRef) -> bool:
1012 """Check if the node matches the class reference.
1014 Args:
1015 classref: Class reference.
1017 Returns:
1018 ``True`` if the node matches.
1019 """
1020 return tree_impl.is_a(self.root, self, classref)
1022 def find_all(self, classref: Optional[ClassRef] = None) -> list['Node']:
1023 """Find all direct children that match a specific class.
1025 Args:
1026 classref: Class reference. If omitted, all children are returned.
1028 Returns:
1029 A list of objects.
1030 """
1031 return tree_impl.node_find_all(self, classref)
1033 def find_first(self, classref: Optional[ClassRef] = None) -> Optional['Node']:
1034 """Find the first direct child that matches a specific class.
1036 Args:
1037 classref: Class reference. If omitted, the first child is returned.
1039 Returns:
1040 An object or ``None``.
1041 """
1042 return tree_impl.node_find_first(self, classref)
1044 def find_closest(self, classref: Optional[ClassRef] = None) -> Optional['Node']:
1045 """Find the closest node ancestor that matches a specific class.
1047 Args:
1048 classref: Class reference. If omitted, the parent is returned.
1050 Returns:
1051 An object or ``None``.
1052 """
1054 return tree_impl.node_find_closest(self, classref)
1056 def find_ancestors(self, classref: Optional[ClassRef] = None) -> list['Node']:
1057 """Find node ancestors that match a specific class.
1059 Args:
1060 classref: Class reference. If omitted, all ancestors are returned.
1062 Returns:
1063 A list of objects, from the parent upwards.
1064 """
1065 return tree_impl.node_find_ancestors(self, classref)
1067 def find_descendants(self, classref: Optional[ClassRef] = None) -> list['Node']:
1068 """Find node descendants that match a specific class.
1070 Args:
1071 classref: Class reference. If omitted, all descendants are returned.
1073 Returns:
1074 A list of objects in the depth-first order.
1075 """
1077 return tree_impl.node_find_descendants(self, classref)
1079 def enter_middleware(self, req: 'WebRequester') -> Optional['WebResponder']:
1080 """Begin middleware processing.
1082 Args:
1083 req: Requester object.
1085 Returns:
1086 A Responder object to end the request processing, or ``None`` to continue.
1087 """
1089 def exit_middleware(self, req: 'WebRequester', res: 'WebResponder'):
1090 """Finish middleware processing.
1092 Args:
1093 req: Requester object.
1094 res: Current responder object.
1095 """
1097 def periodic_task(self):
1098 """Periodic task hook.
1100 Called by the server monitor for nodes registered with ``register_periodic_task``.
1101 """
1104class Root:
1105 """Root node of the object tree."""
1107 app: 'Application'
1108 """Application object."""
1109 specs: 'SpecRuntime'
1110 """Specs runtime."""
1111 configErrors: list
1112 """List of configuration errors."""
1113 configWarnings: list
1114 """List of configuration warnings."""
1116 nodes: list['Node']
1117 """All nodes in the tree, in the order of creation."""
1118 uidMap: dict[str, 'Node']
1119 """Mapping from uids to nodes."""
1120 uidCount: int
1121 """Counter for generated uids."""
1122 configStack: list['Node']
1123 """Nodes being configured, from the outermost to the current one."""
1124 configPaths: list[str]
1125 """Paths of the configuration files."""
1127 def __init__(self, specs: 'SpecRuntime'):
1128 """Create an empty root.
1130 Args:
1131 specs: Specs runtime.
1132 """
1133 tree_impl.root_init(self, specs)
1135 def initialize(self, obj, config):
1136 """Initialize a node and record configuration errors.
1138 Args:
1139 obj: The node.
1140 config: Configuration.
1142 Returns:
1143 ``True`` if the node was initialized, ``False`` if it failed.
1144 """
1145 return tree_impl.root_initialize(self, obj, config)
1147 def post_initialize(self):
1148 """Run ``post_configure`` on all nodes, in the reverse order of creation.
1150 Errors are logged and recorded in ``configErrors``.
1151 """
1152 return tree_impl.root_post_initialize(self)
1154 def activate(self):
1155 """Run ``activate`` on all nodes."""
1156 return tree_impl.root_activate(self)
1158 def config_warning(self, message: str):
1159 """Register a configuration warning.
1161 The warning is logged immediately and reported again after the configuration is complete.
1162 The object stack is only available when called from ``configure`` or ``post_configure``.
1164 Args:
1165 message: Warning message.
1166 """
1167 return tree_impl.root_config_warning(self, message)
1169 def find_all(self, classref: Optional[ClassRef] = None) -> list['Node']:
1170 """Find all objects that match a specific class.
1172 Args:
1173 classref: Class reference.
1175 Returns:
1176 A list of objects.
1177 """
1178 return tree_impl.root_find_all(self, classref)
1180 def find_first(self, classref: Optional[ClassRef] = None) -> Optional['Node']:
1181 """Find the first object that matches a specific class.
1183 Args:
1184 classref: Class reference.
1186 Returns:
1187 An object or ``None``.
1188 """
1189 return tree_impl.root_find_first(self, classref)
1191 def get(self, uid: str = None, classref: Optional[ClassRef] = None) -> Optional['Node']:
1192 """Get an object by its unique ID.
1194 Args:
1195 uid: Object uid.
1196 classref: Class reference. If provided, ensures that the object matches the reference.
1198 Returns:
1199 An object or ``None``.
1200 """
1201 return tree_impl.root_get(self, uid, classref)
1203 def object_count(self) -> int:
1204 """Return the number of objects in the tree.
1206 Returns:
1207 The number of objects.
1208 """
1209 return tree_impl.root_object_count(self)
1211 def create(
1212 self,
1213 classref: ClassRef,
1214 parent: Optional['Node'] = None,
1215 config: Config = None,
1216 **kwargs,
1217 ) -> Optional['Node']:
1218 """Create an object.
1220 Args:
1221 classref: Class reference.
1222 parent: Parent object.
1223 config: Configuration.
1224 **kwargs: Additional configuration properties.
1226 Returns:
1227 A newly created object or ``None`` if the object cannot be initialized.
1228 """
1229 return tree_impl.root_create(self, classref, parent, config, **kwargs)
1231 def create_shared(self, classref: ClassRef, config: Config = None, **kwargs) -> Optional['Node']:
1232 """Create a shared object, attached directly to the root.
1234 If the config has no uid, it is computed from the class reference and the configuration.
1235 If an object with this uid already exists, it is returned instead of creating a new one.
1237 Args:
1238 classref: Class reference.
1239 config: Configuration.
1240 **kwargs: Additional configuration properties.
1242 Returns:
1243 A newly created object or ``None`` if the object cannot be initialized.
1244 """
1245 return tree_impl.root_create_shared(self, classref, config, **kwargs)
1247 def create_temporary(self, classref: ClassRef, config: Config = None, **kwargs) -> Optional['Node']:
1248 """Create a temporary object, not attached to the tree.
1250 Args:
1251 classref: Class reference.
1252 config: Configuration.
1253 **kwargs: Additional configuration properties.
1255 Returns:
1256 A newly created object or ``None`` if the object cannot be initialized.
1257 """
1258 return tree_impl.root_create_temporary(self, classref, config, **kwargs)
1260 def create_application(self, config: Config = None, **kwargs) -> 'Application':
1261 """Create the Application object.
1263 Args:
1264 config: Configuration.
1265 **kwargs: Additional configuration properties.
1267 Returns:
1268 The Application object.
1269 """
1270 return tree_impl.root_create_application(self, config, **kwargs)
1273def create_root(specs: 'SpecRuntime') -> Root:
1274 """Create a new root object.
1276 Args:
1277 specs: Specs runtime.
1279 Returns:
1280 The root object.
1281 """
1282 return Root(specs)
1285def save_root(root: Root, path: str = None) -> str:
1286 """Pickle the root object to a file.
1288 ``sys.path`` is pickled next to it, to ``<path>.syspath``, so that ``load_root`` can restore it.
1290 Args:
1291 root: The root object.
1292 path: File path. Defaults to ``config.pickle`` in the config directory.
1294 Returns:
1295 The file path.
1296 """
1297 return tree_impl.save_root(root, path)
1300def load_root(path: str = None) -> Root:
1301 """Load a pickled root object, activate it and make it the current root.
1303 ``sys.path`` is restored first, so that plugin modules can be imported.
1305 Args:
1306 path: File path. Defaults to ``config.pickle`` in the config directory.
1308 Returns:
1309 The root object.
1310 """
1311 return tree_impl.load_root(path)
1314def activate_root(root: Root) -> Root:
1315 """Activate the root object and make it the current root.
1317 Args:
1318 root: The root object.
1320 Returns:
1321 The root object.
1322 """
1323 return tree_impl.activate_root(root)
1326def deactivate_root():
1327 """Remove the current root."""
1328 return tree_impl.deactivate_root()
1331def get_root() -> Root:
1332 """Return the current root object.
1334 Returns:
1335 The root object set by ``activate_root`` or ``load_root``.
1337 Raises:
1338 Error: If there is no current root.
1339 """
1340 return tree_impl.get_root()
1343def props_of(obj: Object, user: 'User', *context) -> Optional['Props']:
1344 """Generate props for an object, if the user is allowed to use it.
1346 Nested objects the user cannot read are removed from the result.
1348 Args:
1349 obj: The object.
1350 user: The user.
1351 *context: Context objects for the permission check.
1353 Returns:
1354 A ``Props`` object, or ``None`` if the user cannot use the object.
1356 Raises:
1357 Error: If the object's ``props`` returns an invalid type.
1358 """
1359 return tree_impl.props_of(obj, user, *context)
1360################################################################################
1364################################################################################
1365# /lib/mapserver/types.pyinc
1368class MapServerLayerType(Enum):
1369 """MapServer layer type."""
1371 point = 'point'
1372 """Point layer."""
1373 line = 'line'
1374 """Line layer."""
1375 polygon = 'polygon'
1376 """Polygon layer."""
1377 raster = 'raster'
1378 """Raster layer."""
1380class MapServerLayerOptions(Data):
1381 """Options for a MapServer-based layer."""
1383 type: MapServerLayerType
1384 """Layer type."""
1385 path: str
1386 """Path to the data file, e.g. an image (layer DATA option)."""
1387 tileIndex: str
1388 """Path to the tile index SHP file."""
1389 crs: 'Crs'
1390 """Layer CRS."""
1391 connectionType: str
1392 """Type of connection, only ``postgres`` is supported."""
1393 connectionString: str
1394 """Connection string for the data source."""
1395 dataString: str
1396 """Layer DATA option, overrides ``path``."""
1397 style: 'StyleValues'
1398 """Style for the layer; only a part of the style values is supported."""
1399 processing: list[str]
1400 """Processing options for the layer."""
1401 transparentColor: str
1402 """Color to treat as transparent in the layer (OFFSITE)."""
1403 sldPath: str
1404 """Path to SLD file for styling the layer."""
1405 sldName: str
1406 """Name of an SLD NamedLayer to apply."""
1407################################################################################
1410################################################################################
1411# /lib/mime/types.pyinc
1414MimeType: TypeAlias = str
1415"""A MIME type or a file extension."""
1416################################################################################
1419################################################################################
1420# /lib/uom/types.pyinc
1423class Uom(Enum):
1424 """Unit of measure."""
1426 mi = 'mi'
1427 """Statute mile (EPSG 9093)."""
1428 us_ch = 'us-ch'
1429 """US survey chain (EPSG 9033)."""
1430 us_ft = 'us-ft'
1431 """US survey foot (EPSG 9003)."""
1432 us_in = 'us-in'
1433 """US survey inch."""
1434 us_mi = 'us-mi'
1435 """US survey mile (EPSG 9035)."""
1436 us_yd = 'us-yd'
1437 """US survey yard."""
1438 cm = 'cm'
1439 """Centimetre (EPSG 1033)."""
1440 ch = 'ch'
1441 """Chain (EPSG 9097)."""
1442 dm = 'dm'
1443 """Decimetre."""
1444 deg = 'deg'
1445 """Degree (EPSG 9102)."""
1446 fath = 'fath'
1447 """Fathom (EPSG 9014)."""
1448 ft = 'ft'
1449 """Foot (EPSG 9002)."""
1450 grad = 'grad'
1451 """Grad (EPSG 9105)."""
1452 inch = 'in'
1453 """Inch."""
1454 km = 'km'
1455 """Kilometre (EPSG 9036)."""
1456 link = 'link'
1457 """Link (EPSG 9098)."""
1458 m = 'm'
1459 """Metre (EPSG 9001)."""
1460 mm = 'mm'
1461 """Millimetre (EPSG 1025)."""
1462 kmi = 'kmi'
1463 """Nautical mile (EPSG 9030)."""
1464 rad = 'rad'
1465 """Radian (EPSG 9101)."""
1466 yd = 'yd'
1467 """Yard (EPSG 9096)."""
1468 px = 'px'
1469 """Pixel."""
1470 pt = 'pt'
1471 """Typographic point (1/72 inch)."""
1474UomValue: TypeAlias = tuple[float, Uom]
1475"""A value with a unit, like ``(5, Uom.mm)``."""
1477UomValueStr: TypeAlias = str
1478"""A value with a unit like ``5mm``."""
1480UomPoint: TypeAlias = tuple[float, float, Uom]
1481"""A point with a unit, like ``(1, 2, Uom.mm)``."""
1483UomPointStr: TypeAlias = list[str]
1484"""A point with a unit like ``["1mm", "2mm"]``."""
1486UomSize: TypeAlias = tuple[float, float, Uom]
1487"""A size with a unit, like ``(10, 20, Uom.mm)``."""
1489UomSizeStr: TypeAlias = list[str]
1490"""A size with a unit like ``["1mm", "2mm"]``."""
1492UomExtent: TypeAlias = tuple[float, float, float, float, Uom]
1493"""An extent with a unit, like ``(0, 0, 10, 20, Uom.mm)``."""
1495UomExtentStr: TypeAlias = list[str]
1496"""An extent with a unit like ``["1mm", "2mm", "3mm", "4mm"]``."""
1497################################################################################
1500################################################################################
1501# /lib/image/types.pyinc
1504class ImageFormat(Data):
1505 """Image format: MIME types and encoding options."""
1507 name: str
1508 """Name of the format."""
1509 mimeTypes: list[str]
1510 """MIME types for this format."""
1511 options: dict
1512 """Encoding options, as accepted by ``Image.to_bytes``."""
1515class Image:
1516 """Raster image.
1518 Manipulation methods change the image in place and return the image itself, so that calls can be chained.
1519 """
1521 def size(self) -> Size:
1522 """Get the image size.
1524 Returns:
1525 A tuple ``(width, height)`` in pixels.
1526 """
1528 def mode(self) -> str:
1529 """Get the image mode.
1531 Returns:
1532 PIL image mode, e.g. ``RGBA``.
1533 """
1535 def convert(self, mode: str) -> 'Image':
1536 """Convert the image to a mode.
1538 Args:
1539 mode: PIL image mode.
1541 Returns:
1542 The image.
1543 """
1545 def add_box(self, color=None) -> 'Image':
1546 """Draw a 1 pixel wide frame along the image edges.
1548 The image is converted to RGBA.
1550 Args:
1551 color: Line color, black by default.
1553 Returns:
1554 The image.
1555 """
1557 def add_text(self, text: str, x=0, y=0, color=None) -> 'Image':
1558 """Draw text on the image with the default font.
1560 The image is converted to RGBA.
1562 Args:
1563 text: Text, can contain multiple lines.
1564 x: X coordinate of the top left corner of the text.
1565 y: Y coordinate of the top left corner of the text.
1566 color: Text color, black by default.
1568 Returns:
1569 The image.
1570 """
1572 def compose(self, other: 'Image', opacity=1) -> 'Image':
1573 """Place another image on top of this one, using alpha composition.
1575 The other image is resized to the size of this one if needed.
1577 Args:
1578 other: Image to place on top.
1579 opacity: Opacity of the other image, from 0 to 1.
1581 Returns:
1582 The image.
1583 """
1585 def crop(self, box) -> 'Image':
1586 """Crop the image.
1588 Args:
1589 box: Crop rectangle ``(left, upper, right, lower)`` in pixels.
1591 Returns:
1592 The image.
1593 """
1595 def paste(self, other: 'Image', where=None) -> 'Image':
1596 """Paste another image into this one.
1598 Args:
1599 other: Image to paste.
1600 where: Position ``(x, y)`` of the upper left corner, or a box ``(left, upper, right, lower)``.
1601 By default, the image is pasted at ``(0, 0)``.
1603 Returns:
1604 The image.
1605 """
1607 def resize(self, size: Size, **kwargs) -> 'Image':
1608 """Resize the image to a size, without keeping the aspect ratio.
1610 Args:
1611 size: New size ``(width, height)``.
1612 **kwargs: Options for ``PIL.Image.resize``. The default resampling is bicubic.
1614 Returns:
1615 The image.
1616 """
1618 def resize_to(self, width: int = 0, height: int = 0, **kwargs) -> 'Image':
1619 """Resize the image to a width, a height or both.
1621 If only one dimension is given, the other is computed to keep the aspect ratio.
1622 If none is given, the image is not changed.
1624 Args:
1625 width: New width.
1626 height: New height.
1627 **kwargs: Options for ``PIL.Image.resize``.
1629 Returns:
1630 The image.
1631 """
1633 def rotate(self, angle: int, **kwargs) -> 'Image':
1634 """Rotate the image counter-clockwise.
1636 Args:
1637 angle: Angle in degrees.
1638 **kwargs: Options for ``PIL.Image.rotate``. The default resampling is bicubic.
1640 Returns:
1641 The image.
1642 """
1644 def to_bytes(self, mime_type: Optional[str] = None, options: Optional[dict] = None) -> bytes:
1645 """Encode the image.
1647 The ``options`` dict can contain any PIL save option
1648 (see https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html).
1650 An additional option ``mode`` is the image mode
1651 (see https://pillow.readthedocs.io/en/stable/handbook/concepts.html#concept-modes).
1652 If provided, the image is converted to that mode before saving, with an adaptive palette.
1654 An additional option ``background`` sets the color to replace the alpha channel with
1655 when an RGBA image is saved as JPEG (default is white).
1657 Args:
1658 mime_type: MIME type of the output, PNG by default.
1659 options: Encoding options.
1661 Returns:
1662 The encoded image.
1663 """
1665 def to_base64(self, mime_type: Optional[str] = None, options: Optional[dict] = None) -> str:
1666 """Encode the image as a base64 string.
1668 Args:
1669 mime_type: MIME type of the output, PNG by default.
1670 options: Encoding options, as in ``to_bytes``.
1672 Returns:
1673 The base64 encoded image.
1674 """
1676 def to_data_url(self, mime_type: Optional[str] = None, options: Optional[dict] = None) -> str:
1677 """Encode the image as a base64 data URL.
1679 Args:
1680 mime_type: MIME type of the output, PNG by default.
1681 options: Encoding options, as in ``to_bytes``.
1683 Returns:
1684 A ``data:`` URL.
1685 """
1687 def to_path(self, path: str, mime_type: Optional[str] = None, options: Optional[dict] = None) -> str:
1688 """Encode the image and save it to a file.
1690 Args:
1691 path: File path.
1692 mime_type: MIME type of the output, PNG by default.
1693 options: Encoding options, as in ``to_bytes``.
1695 Returns:
1696 The file path.
1697 """
1699 def to_array(self) -> 'numpy.typing.NDArray':
1700 """Convert the image to a numpy array.
1702 Returns:
1703 An array of shape ``(height, width)`` or ``(height, width, channels)``.
1704 """
1706 def compare_to(self, other: 'Image') -> float:
1707 """Compare this image to another one.
1709 Computes the mean squared difference of the RGBA channels over all pixels,
1710 normalized to the range 0 to 1. Both images must be RGBA and have the same size.
1712 Args:
1713 other: Image to compare to.
1715 Returns:
1716 ``0`` if the images are equal, larger values for larger differences.
1717 """
1718################################################################################
1721################################################################################
1722# /lib/intl/types.pyinc
1725LocaleUid: TypeAlias = str
1726"""Locale UID like ``de_DE``."""
1729class Locale(Data):
1730 """Locale data: language, territory, date and number conventions."""
1732 uid: str
1733 """Locale uid like ``de_DE``. A locale without a territory has the territory ``ZZ``."""
1734 dateFormatLong: str
1735 """Long date format pattern."""
1736 dateFormatMedium: str
1737 """Medium date format pattern."""
1738 dateFormatShort: str
1739 """Short date format pattern."""
1740 dateUnits: str
1741 """Narrow names of year, month and day, e.g. ``YMD`` for ``en``, ``JMT`` for ``de``."""
1742 dayNamesLong: list[str]
1743 """Full day names."""
1744 dayNamesShort: list[str]
1745 """Abbreviated day names."""
1746 dayNamesNarrow: list[str]
1747 """Narrow day names."""
1748 firstWeekDay: int
1749 """First day of the week, ``0`` is Monday."""
1751 language: str
1752 """Language code: ``de``."""
1753 language3: str
1754 """ISO 639 alpha-3 language code: ``deu``."""
1755 languageBib: str
1756 """ISO 639-2 bibliographic language code: ``ger``."""
1757 languageName: str
1758 """Native language name: ``Deutsch``."""
1759 languageNameEn: str
1760 """English language name: ``German``."""
1762 territory: str
1763 """Territory code: ``DE``."""
1764 territoryName: str
1765 """Native territory name: ``Deutschland``."""
1766 monthNamesLong: list[str]
1767 """Full month names."""
1768 monthNamesShort: list[str]
1769 """Abbreviated month names."""
1770 monthNamesNarrow: list[str]
1771 """Narrow month names."""
1772 numberDecimal: str
1773 """Decimal separator."""
1774 numberGroup: str
1775 """Group (thousands) separator."""
1778class DateTimeFormat(Enum):
1779 """Date or time format."""
1780 short = 'short'
1781 """Local short format."""
1782 medium = 'medium'
1783 """Local medium format."""
1784 long = 'long'
1785 """Local long format."""
1786 iso = 'iso'
1787 """ISO 8601 format."""
1790class NumberFormat(Enum):
1791 """Number format."""
1792 decimal = 'decimal'
1793 """Locale decimal format."""
1794 grouped = 'grouped'
1795 """Locale grouped format."""
1796 currency = 'currency'
1797 """Locale currency format."""
1798 percent = 'percent'
1799 """Locale percent format."""
1802class DateFormatter:
1803 """Locale-aware date formatter."""
1805 def format(self, fmt: DateTimeFormat | str, date: Optional[Union['datetime.date', str]] = None) -> str:
1806 """Format a date.
1808 Args:
1809 fmt: Format type, or a ``babel`` (CLDR) date pattern like ``dd.MM.yyyy``.
1810 date: Date or date string, the current date by default.
1812 Returns:
1813 The formatted date.
1815 Raises:
1816 ``Error``: If the date cannot be parsed.
1817 """
1819 def short(self, date=None) -> str:
1820 """Format a date in the short format of the locale, e.g. ``11.12.13``.
1822 Args:
1823 date: Date or date string, the current date by default.
1825 Returns:
1826 The formatted date.
1827 """
1829 def medium(self, date=None) -> str:
1830 """Format a date in the medium format of the locale, e.g. ``11.12.2013``.
1832 Args:
1833 date: Date or date string, the current date by default.
1835 Returns:
1836 The formatted date.
1837 """
1839 def long(self, date=None) -> str:
1840 """Format a date in the long format of the locale, e.g. ``11. Dezember 2013``.
1842 Args:
1843 date: Date or date string, the current date by default.
1845 Returns:
1846 The formatted date.
1847 """
1849 def iso(self, date=None) -> str:
1850 """Format a date in the ISO 8601 format, e.g. ``2013-12-11``.
1852 Args:
1853 date: Date or date string, the current date by default.
1855 Returns:
1856 The formatted date.
1857 """
1860class TimeFormatter:
1861 """Locale-aware time formatter."""
1863 def format(self, fmt: DateTimeFormat | str, time: Optional[Union['datetime.time', str]] = None) -> str:
1864 """Format a time.
1866 Args:
1867 fmt: Format type, or a ``babel`` (CLDR) time pattern like ``HH:mm``.
1868 time: Time, datetime or time string, the current time by default.
1870 Returns:
1871 The formatted time.
1873 Raises:
1874 ``Error``: If the time cannot be parsed.
1875 """
1877 def short(self, time=None) -> str:
1878 """Format a time in the short format of the locale, e.g. ``11:22``.
1880 Args:
1881 time: Time, datetime or time string, the current time by default.
1883 Returns:
1884 The formatted time.
1885 """
1887 def medium(self, time=None) -> str:
1888 """Format a time in the medium format of the locale, e.g. ``11:22:33``.
1890 Args:
1891 time: Time, datetime or time string, the current time by default.
1893 Returns:
1894 The formatted time.
1895 """
1897 def long(self, time=None) -> str:
1898 """Format a time in the long format of the locale, which usually includes the time zone.
1900 Args:
1901 time: Time, datetime or time string, the current time by default.
1903 Returns:
1904 The formatted time.
1905 """
1907 def iso(self, time=None) -> str:
1908 """Format a time in the ISO 8601 format, with the time zone offset, e.g. ``11:22:33+0100``.
1910 Args:
1911 time: Time, datetime or time string, the current time by default.
1913 Returns:
1914 The formatted time.
1915 """
1918class NumberFormatter:
1919 """Locale-aware number formatter."""
1921 def format(self, fmt: NumberFormat | str, n, *args, **kwargs) -> str:
1922 """Format a number.
1924 Args:
1925 fmt: Format type. For an unknown format, the number is converted with ``str``.
1926 n: Number.
1927 *args: Arguments for the format method, e.g. the currency for ``currency``.
1928 **kwargs: Keyword arguments for the format method.
1930 Returns:
1931 The formatted number.
1932 """
1934 def decimal(self, n, *args, **kwargs) -> str:
1935 """Format a number as a decimal without group separators.
1937 Args:
1938 n: Number.
1939 *args: Arguments for ``babel.numbers.format_decimal``.
1940 **kwargs: Keyword arguments for ``babel.numbers.format_decimal``.
1942 Returns:
1943 The formatted number.
1944 """
1946 def grouped(self, n, *args, **kwargs) -> str:
1947 """Format a number as a decimal with group separators.
1949 Args:
1950 n: Number.
1951 *args: Arguments for ``babel.numbers.format_decimal``.
1952 **kwargs: Keyword arguments for ``babel.numbers.format_decimal``.
1954 Returns:
1955 The formatted number.
1956 """
1958 def currency(self, n, currency: str, *args, **kwargs) -> str:
1959 """Format a number as a currency value.
1961 Args:
1962 n: Number.
1963 currency: Currency code like ``EUR``.
1964 *args: Arguments for ``babel.numbers.format_currency``.
1965 **kwargs: Keyword arguments for ``babel.numbers.format_currency``.
1967 Returns:
1968 The formatted value.
1969 """
1971 def percent(self, n, *args, **kwargs) -> str:
1972 """Format a number as a percentage, ``0.5`` is 50 percent.
1974 Args:
1975 n: Number.
1976 *args: Arguments for ``babel.numbers.format_percent``.
1977 **kwargs: Keyword arguments for ``babel.numbers.format_percent``.
1979 Returns:
1980 The formatted value.
1981 """
1982################################################################################
1985################################################################################
1986# /lib/style/types.pyinc
1989class StyleValues(Data):
1990 """Style values, as parsed by ``gws.lib.style.parser``."""
1992 fill: Color
1993 """Fill color."""
1995 stroke: Color
1996 """Stroke (line) color."""
1997 stroke_dasharray: list[int]
1998 """Dash pattern, as a list of dash and gap lengths."""
1999 stroke_dashoffset: int
2000 """Offset of the dash pattern."""
2001 stroke_linecap: Literal['butt', 'round', 'square']
2002 """Shape of line ends."""
2003 stroke_linejoin: Literal['bevel', 'round', 'miter']
2004 """Shape of line corners."""
2005 stroke_miterlimit: int
2006 """Limit for miter joins."""
2007 stroke_width: int
2008 """Stroke width in pixels."""
2010 marker: Literal['circle', 'square', 'arrow', 'cross']
2011 """Marker symbol drawn at the vertices of a geometry."""
2012 marker_fill: Color
2013 """Marker fill color."""
2014 marker_size: int
2015 """Marker size in pixels."""
2016 marker_stroke: Color
2017 """Marker stroke color."""
2018 marker_stroke_dasharray: list[int]
2019 """Marker dash pattern."""
2020 marker_stroke_dashoffset: int
2021 """Offset of the marker dash pattern."""
2022 marker_stroke_linecap: Literal['butt', 'round', 'square']
2023 """Shape of marker line ends."""
2024 marker_stroke_linejoin: Literal['bevel', 'round', 'miter']
2025 """Shape of marker line corners."""
2026 marker_stroke_miterlimit: int
2027 """Limit for marker miter joins."""
2028 marker_stroke_width: int
2029 """Marker stroke width in pixels."""
2031 with_geometry: Literal['all', 'none']
2032 """Draw the geometry (``all``) or not (``none``)."""
2033 with_label: Literal['all', 'none']
2034 """Draw the label (``all``) or not (``none``)."""
2036 label_align: Literal['left', 'right', 'center']
2037 """Horizontal text alignment of the label."""
2038 label_background: Color
2039 """Label background color."""
2040 label_fill: Color
2041 """Label text color."""
2042 label_font_family: str
2043 """Label font family."""
2044 label_font_size: int
2045 """Label font size in pixels."""
2046 label_font_style: Literal['normal', 'italic']
2047 """Label font style."""
2048 label_font_weight: Literal['normal', 'bold']
2049 """Label font weight."""
2050 label_line_height: int
2051 """Line spacing for multi-line labels."""
2052 label_max_scale: int
2053 """Maximal scale denominator at which the label is shown."""
2054 label_min_scale: int
2055 """Minimal scale denominator at which the label is shown."""
2056 label_offset_x: int
2057 """Horizontal label offset in pixels."""
2058 label_offset_y: int
2059 """Vertical label offset in pixels."""
2060 label_padding: list[int]
2061 """Label padding in pixels, as ``[top, right, bottom, left]``."""
2062 label_placement: Literal['start', 'end', 'middle']
2063 """Label position along the geometry: the first point, the last point or the centroid."""
2064 label_stroke: Color
2065 """Label text stroke color."""
2066 label_stroke_dasharray: list[int]
2067 """Label text dash pattern."""
2068 label_stroke_dashoffset: int
2069 """Offset of the label text dash pattern."""
2070 label_stroke_linecap: Literal['butt', 'round', 'square']
2071 """Shape of label text line ends."""
2072 label_stroke_linejoin: Literal['bevel', 'round', 'miter']
2073 """Shape of label text line corners."""
2074 label_stroke_miterlimit: int
2075 """Limit for label text miter joins."""
2076 label_stroke_width: int
2077 """Label text stroke width in pixels."""
2079 point_size: int
2080 """Diameter of point geometries in pixels."""
2081 icon: str
2082 """Icon for point geometries. After parsing, a ``gws.lib.style.icon.ParsedIcon`` object."""
2084 offset_x: int
2085 """Horizontal offset of the drawn geometry in pixels."""
2086 offset_y: int
2087 """Vertical offset of the drawn geometry in pixels."""
2090class StyleProps(Props):
2091 """CSS Style properties."""
2093 cssSelector: Optional[str]
2094 text: Optional[str]
2095 values: Optional[dict]
2098class Style:
2099 """Feature style."""
2101 cssSelector: str
2102 """CSS selector of the style."""
2103 text: str
2104 """Raw CSS text of the style."""
2105 values: StyleValues
2106 """Parsed style values."""
2107################################################################################
2110################################################################################
2111# /lib/xmlx/types.pyinc
2114class XmlNamespace(Data):
2115 """XML namespace."""
2117 prefix: str
2118 """Default prefix for this Namespace, empty for a default namespace declaration."""
2119 uri: Url
2120 """Namespace uri."""
2121 schemaLocation: Url
2122 """Namespace schema location."""
2123 extendsGml: bool
2124 """Namespace schema extends the GML3 schema."""
2127class XmlOptions(Data):
2128 """XML options for parsing and serialization."""
2130 removeNamespaces: bool = False
2131 """Strip namespaces when parsing: tags and attributes are local names, declarations are dropped."""
2133 customNamespacePrefixes: Optional[dict[str, str]] = None
2134 """Serialization: prefixes to use instead of the default ones (namespace uri -> prefix)."""
2136 defaultNamespace: Optional['XmlNamespace'] = None
2137 """Serialization: elements in this namespace are written without a prefix."""
2139 doctype: Optional[str] = None
2140 """Serialization: document type definition (DTD), written after the XML declaration."""
2142 compactWhitespace: bool = False
2143 """Collapse whitespace in text content (parsing and serialization)."""
2145 withNamespaceDeclarations: bool = False
2146 """Serialization: declare all namespaces used in the tree on the root element."""
2148 withSchemaLocations: bool = False
2149 """Serialization: add ``xsi:schemaLocation`` for declared namespaces that have a schema location."""
2151 withXmlDeclaration: bool = False
2152 """Serialization: write the ``<?xml ...?>`` declaration."""
2155class XmlElement(Iterable):
2156 """XML Element.
2158 Implements a subset of the ``ElementTree.Element`` API.
2160 ``tag`` is either a local name (``Point``) or a Clark name (``{http://www.opengis.net/gml/3.2}Point``);
2161 ``name`` is always the local name. Prefixed names never occur in a tree: ``tag()`` resolves ``ID:name``
2162 to a Clark name, the parser resolves prefixes against the document's declarations. The element itself
2163 (constructor, ``add()``, ``set()``) takes names as they are; it has no namespace map to resolve against.
2164 """
2166 tag: str
2167 """Tag name, local or Clark."""
2169 name: str
2170 """Element name (tag without a namespace)."""
2172 text: str
2173 """Text before first subelement."""
2175 tail: str
2176 """Text after this element's end tag."""
2178 attrib: dict
2179 """Dictionary of element attributes."""
2181 namespaces: list[XmlNamespace]
2182 """Namespaces declared on this element (``prefix == ''`` for the default namespace)."""
2184 def __len__(self) -> int: ...
2186 def __iter__(self) -> Iterator['XmlElement']: ...
2188 def __getitem__(self, item: int) -> 'XmlElement': ...
2190 def append(self, subelement: 'XmlElement'):
2191 """Add a child at the end of the list of children.
2193 Args:
2194 subelement: The element to add.
2195 """
2197 def clear(self):
2198 """Remove the attributes, namespace declarations, children, text and tail of this element."""
2200 def extend(self, subelements: Iterable['XmlElement']):
2201 """Add children at the end of the list of children.
2203 Args:
2204 subelements: The elements to add.
2205 """
2207 def find(self, path: str) -> Optional['XmlElement']:
2208 """Find the first matching subelement.
2210 Args:
2211 path: Tag name or path in ``ElementTree`` syntax, with local or Clark names.
2213 Returns:
2214 The element, or ``None`` if nothing matches.
2215 """
2217 def require(self, path: str) -> 'XmlElement':
2218 """Find the first matching subelement, which must exist.
2220 Args:
2221 path: Tag name or path in ``ElementTree`` syntax, with local or Clark names.
2223 Returns:
2224 The element.
2226 Raises:
2227 gws.lib.xmlx.Error: If nothing matches.
2228 """
2230 def findall(self, path: str) -> list['XmlElement']:
2231 """Find all matching subelements.
2233 Args:
2234 path: Tag name or path in ``ElementTree`` syntax, with local or Clark names.
2236 Returns:
2237 A list of elements in document order.
2238 """
2240 def findtext(self, path: str, default: str = '') -> str:
2241 """Find the text of the first matching subelement.
2243 Args:
2244 path: Tag name or path in ``ElementTree`` syntax, with local or Clark names.
2245 default: Value to return if nothing matches.
2247 Returns:
2248 The text of the element, or ``default``.
2249 """
2251 def get(self, key: str, default: str = '') -> str:
2252 """Get an attribute value.
2254 Args:
2255 key: Attribute name, local or Clark.
2256 default: Value to return if the attribute does not exist.
2258 Returns:
2259 The attribute value, or ``default``.
2260 """
2262 def insert(self, index: int, subelement: 'XmlElement'):
2263 """Insert a child at the given position.
2265 Args:
2266 index: Position in the list of children.
2267 subelement: The element to insert.
2268 """
2270 def items(self) -> Iterable[tuple[str, Any]]:
2271 """Get the attributes.
2273 Returns:
2274 The attributes as ``(name, value)`` pairs.
2275 """
2277 def iter(self, tag: Optional[str] = None) -> Iterable['XmlElement']:
2278 """Iterate over this element and all its descendants, depth-first.
2280 Args:
2281 tag: Only return elements with this tag; ``None`` or ``*`` returns all elements.
2283 Returns:
2284 An iterator of elements, starting with this element if it matches.
2285 """
2287 def iterfind(self, path: str) -> Iterable['XmlElement']:
2288 """Iterate over all matching subelements.
2290 Args:
2291 path: Tag name or path in ``ElementTree`` syntax, with local or Clark names.
2293 Returns:
2294 An iterator of elements in document order.
2295 """
2297 def itertext(self) -> Iterable[str]:
2298 """Iterate over the text content of this element and its descendants.
2300 Returns:
2301 An iterator of the non-empty texts and tails in document order, without the tail of this element.
2302 """
2304 def keys(self) -> Iterable[str]:
2305 """Get the attribute names.
2307 Returns:
2308 The attribute names.
2309 """
2311 def remove(self, other: 'XmlElement'):
2312 """Remove a child.
2314 Args:
2315 other: The child to remove.
2317 Raises:
2318 ValueError: If the element is not a child of this element.
2319 """
2321 def set(self, key: str, value: Any):
2322 """Set an attribute.
2324 Args:
2325 key: Attribute name, local or Clark.
2326 value: Attribute value.
2327 """
2329 # extensions
2331 def hasattr(self, key: str) -> bool:
2332 """Check if an attribute exists.
2334 Args:
2335 key: Attribute name, local or Clark.
2337 Returns:
2338 ``True`` if the attribute exists.
2339 """
2341 def isa(self, *names: str) -> bool:
2342 """Check if the local name of this element matches one of the given names, case-insensitively.
2344 Args:
2345 *names: Local names.
2347 Returns:
2348 ``True`` if the name matches.
2349 """
2351 def add(self, tag: str, attrib: Optional[dict] = None, **extra) -> 'XmlElement':
2352 """Create a new element and add it as a child.
2354 Names are taken as they are (local or Clark); ``ID:name`` resolution is done by ``tag()`` only.
2356 Args:
2357 tag: Tag name, local or Clark.
2358 attrib: Attributes.
2359 **extra: Additional attributes.
2361 Returns:
2362 The new element.
2363 """
2365 def children(self) -> list['XmlElement']:
2366 """Get the children of this element.
2368 Returns:
2369 The list of children. This is the internal list, not a copy.
2370 """
2372 def declare(self, *namespaces: XmlNamespace):
2373 """Add namespace declarations to this element.
2375 The declarations are written as ``xmlns`` attributes on output. Namespaces already declared
2376 with the same prefix and URI are skipped.
2378 Args:
2379 *namespaces: Namespaces to declare.
2380 """
2382 def findfirst(self, *paths) -> Optional['XmlElement']:
2383 """Find the first element that matches one of the given paths.
2385 Args:
2386 *paths: Tag names or paths in ``ElementTree`` syntax, tried in order.
2388 Returns:
2389 The first match, or ``None``. Without paths, the first child, or ``None`` if there are no children.
2390 """
2392 def textof(self, *paths) -> str:
2393 """Get the text of the first matching element that has text.
2395 Args:
2396 *paths: Tag names or paths in ``ElementTree`` syntax, tried in order.
2398 Returns:
2399 The text, or an empty string if no matching element has text.
2400 """
2402 def textlist(self, *paths, deep=False) -> list[str]:
2403 """Collect texts from subelements.
2405 Texts are stripped, empty texts are skipped.
2407 Args:
2408 *paths: Tag names or paths in ``ElementTree`` syntax. Without paths, the direct children are used.
2409 deep: If ``True``, also collect texts from all descendants of the found elements.
2411 Returns:
2412 A list of texts in document order.
2413 """
2415 def textdict(self, *paths, deep=False) -> dict[str, str]:
2416 """Collect texts from subelements, keyed by tag.
2418 Texts are stripped, empty texts are skipped. If several elements have the same tag, the last text wins.
2420 Args:
2421 *paths: Tag names or paths in ``ElementTree`` syntax. Without paths, the direct children are used.
2422 deep: If ``True``, also collect texts from all descendants of the found elements.
2424 Returns:
2425 A dict of tags (local or Clark) and texts.
2426 """
2428 def to_string(self, opts: Optional[XmlOptions] = None) -> str:
2429 """Serialize this element and its subtree.
2431 Args:
2432 opts: Serialization options.
2434 Returns:
2435 An XML string.
2437 Raises:
2438 gws.lib.xmlx.WriteError: If the tree contains an invalid or prefixed name.
2439 gws.lib.xmlx.NamespaceError: If a namespace is unknown, or one prefix is used for different URIs.
2440 """
2442 def to_dict(self) -> dict:
2443 """Convert the element tree to a dict.
2445 Returns:
2446 A dict with the keys ``tag``, ``attrib``, ``text``, ``tail`` and ``children``,
2447 where ``children`` is a list of such dicts.
2448 """
2449################################################################################
2453################################################################################
2454# /lib/crs/types.pyinc
2457CrsName: TypeAlias = int | str
2458"""A CRS code like ``EPSG:3857`` or a SRID like ``3857``."""
2461class CrsFormat(Enum):
2462 """CRS name format."""
2464 none = ''
2465 """No format."""
2466 crs = 'crs'
2467 """Like ``crs84``."""
2468 srid = 'srid'
2469 """Like ``3857``."""
2470 epsg = 'epsg'
2471 """Like ``EPSG:3857``."""
2472 url = 'url'
2473 """Like ``http://www.opengis.net/gml/srs/epsg.xml#3857``."""
2474 uri = 'uri'
2475 """Like ``http://www.opengis.net/def/crs/epsg/0/3857``."""
2476 urnx = 'urnx'
2477 """Like ``urn:x-ogc:def:crs:EPSG:3857``."""
2478 urn = 'urn'
2479 """Like ``urn:ogc:def:crs:EPSG::3857``."""
2482class Axis(Enum):
2483 """Axis orientation."""
2485 xy = 'xy'
2486 """XY (longitude/latitude) axis orientation."""
2487 yx = 'yx'
2488 """YX (latitude/longitude) axis orientation."""
2491class Bounds(Data):
2492 """Geo-referenced extent: an extent together with its CRS."""
2494 crs: 'Crs'
2495 """Coordinate reference system of the extent."""
2496 extent: Extent
2497 """Extent in the coordinates of ``crs``."""
2500class Crs:
2501 """Coordinate reference system."""
2503 axis: Axis
2504 """Axis orientation."""
2505 base: int
2506 """Base CRS code."""
2507 bounds: Bounds
2508 """CRS own Bounds."""
2509 coordinatePrecision: int
2510 """Preferred precision for coordinates in this CRS."""
2511 datum: str
2512 """Datum."""
2513 epsg: str
2514 """Name in the "epsg" format."""
2515 extent: Extent
2516 """CRS own Extent."""
2517 isGeographic: bool
2518 """This CRS is geographic."""
2519 isProjected: bool
2520 """This CRS is projected."""
2521 isYX: bool
2522 """This CRS has a lat/lon axis."""
2523 name: str
2524 """CRS name."""
2525 proj4text: str
2526 """Proj4 definition."""
2527 srid: int
2528 """CRS SRID."""
2529 uom: Uom
2530 """CRS unit."""
2531 uri: str
2532 """Name in the "uri" format."""
2533 url: str
2534 """Name in the "url" format."""
2535 urn: str
2536 """Name in the "urn" format."""
2537 urnx: str
2538 """Name in the "urnx" format."""
2539 wgsExtent: Extent
2540 """CRS Extent in the WGS projection."""
2541 wgsMaxExtent: Extent
2542 """Maximal extent that makes sense for this CRS, in the WGS projection."""
2543 wkt: str
2544 """WKT definition."""
2546 def axis_for_format(self, fmt: 'CrsFormat') -> Axis:
2547 """Get the axis orientation implied by a CRS name format.
2549 For CRSs with a lat/lon axis, the orientation depends on how the CRS is named.
2550 We adhere to the GeoServer convention: the ``srid``, ``epsg``, ``url`` and ``uri``
2551 formats imply XY, the ``urn`` and ``urnx`` formats imply YX
2552 (see https://docs.geoserver.org/latest/en/user/services/wfs/axis_order.html).
2553 For XY CRSs, the own axis is always returned.
2555 Args:
2556 fmt: CRS name format.
2558 Returns:
2559 The axis orientation.
2560 """
2562 def clip_wgs_extent(self, wgs_extent: Extent) -> Optional[Extent]:
2563 """Clip a WGS extent to the maximal extent of this CRS.
2565 Args:
2566 wgs_extent: Extent in the WGS projection.
2568 Returns:
2569 The clipped extent in the WGS projection, or ``None`` if there is no intersection.
2570 """
2572 def extent_size_in_meters(self, extent: Extent) -> Size:
2573 """Calculate the width and height of an extent in meters.
2575 For projected CRSs, the extent size is returned as is. For geographic CRSs,
2576 geodesic distances on the WGS84 ellipsoid are measured along the middle
2577 latitude and the middle longitude of the extent.
2579 Args:
2580 extent: Extent in this CRS.
2582 Returns:
2583 A ``(width, height)`` tuple in meters.
2585 Raises:
2586 ``gws.lib.crs.Error``: If this is a projected CRS with units other than meters.
2587 """
2589 def point_offset_in_meters(self, xy: Point, dist: float, az: int) -> Point:
2590 """Calculate a point at a given distance and direction from another point.
2592 Args:
2593 xy: Point in this CRS.
2594 dist: Distance in meters.
2595 az: Azimuth in degrees (0 = North, 90 = East, etc.).
2597 Returns:
2598 The offset point in this CRS.
2600 Raises:
2601 ``gws.lib.crs.Error``: If this is a projected CRS with units other than meters.
2602 """
2604 def to_geojson(self) -> dict:
2605 """Return a GeoJSON representation of the CRS.
2607 The CRS is represented as a "named CRS" with its ``urn`` name,
2608 as per the 2008 GeoJSON specification (https://geojson.org/geojson-spec#named-crs).
2610 Returns:
2611 A GeoJSON ``crs`` dict.
2612 """
2614 def to_string(self, fmt: Optional['CrsFormat'] = None) -> str:
2615 """Return the name of the CRS in a given format.
2617 Args:
2618 fmt: Format to use, ``CrsFormat.epsg`` by default.
2620 Returns:
2621 The CRS name, like ``EPSG:3857``.
2622 """
2624 def transform_extent(self, extent: Extent, crs_to: 'Crs') -> Extent:
2625 """Transform an Extent from this CRS to another.
2627 The transformation goes through WGS84. If the extent is very large
2628 (almost the whole world) and the target CRS has a limited area of use,
2629 the result is computed by sampling points, so that it stays finite.
2631 Args:
2632 extent: Extent in this CRS.
2633 crs_to: Target CRS.
2635 Returns:
2636 The transformed Extent, with min and max values in order.
2637 """
2639 def transform_resolution(self, extent: Extent, res: float, crs_to: 'Crs') -> float:
2640 """Transform a resolution over an extent from this CRS to another.
2642 The returned resolution is the finest one found at a set of sample points of the extent,
2643 so that the target resolution is never coarser than the source resolution anywhere in the extent.
2645 Args:
2646 extent: Extent in this CRS.
2647 res: Resolution in units of this CRS per pixel.
2648 crs_to: Target CRS.
2650 Returns:
2651 The resolution in units of the target CRS per pixel, or ``0.0`` if the transformation fails.
2652 """
2654 def transformer(self, crs_to: 'Crs') -> Callable:
2655 """Create a transformer function to another CRS.
2657 The function always uses the XY (easting/longitude first) axis order.
2659 Args:
2660 crs_to: Target CRS.
2662 Returns:
2663 A function that takes ``x, y`` and returns a transformed ``(x, y)`` tuple.
2664 """
2665################################################################################
2668################################################################################
2669# /lib/shape/types.pyinc
2672class ShapeProps(Props):
2673 """Shape properties."""
2675 crs: str
2676 geometry: dict
2679class Shape(Object):
2680 """Geo-referenced geometry."""
2682 type: GeometryType
2683 """Geometry type."""
2685 crs: 'Crs'
2686 """CRS of this shape."""
2688 x: Optional[float]
2689 """X-coordinate for Point geometries, None otherwise."""
2691 y: Optional[float]
2692 """Y-coordinate for Point geometries, None otherwise."""
2694 # common props
2696 def area(self) -> float:
2697 """Compute the area of the geometry.
2699 Returns:
2700 The area in CRS units, 0 for geometries without an area.
2701 """
2703 def bounds(self) -> Bounds:
2704 """Compute the bounds of this shape.
2706 Returns:
2707 A Bounds object in the CRS of this shape.
2708 """
2710 def centroid(self) -> 'Shape':
2711 """Compute the centroid of this shape.
2713 Returns:
2714 A Point shape.
2715 """
2717 def center(self) -> tuple[float, float]:
2718 """Compute the coordinates of the centroid.
2720 Returns:
2721 A tuple ``(x, y)``.
2722 """
2724 # formats
2726 def to_wkb(self) -> bytes:
2727 """Convert this shape to WKB.
2729 Returns:
2730 WKB bytes.
2731 """
2733 def to_wkb_hex(self) -> str:
2734 """Convert this shape to hex-encoded WKB.
2736 Returns:
2737 A hex string.
2738 """
2740 def to_ewkb(self) -> bytes:
2741 """Convert this shape to EWKB, which includes the SRID.
2743 Returns:
2744 EWKB bytes.
2745 """
2747 def to_ewkb_hex(self) -> str:
2748 """Convert this shape to hex-encoded EWKB, which includes the SRID.
2750 Returns:
2751 A hex string.
2752 """
2754 def to_wkt(self, trim=False, rounding_precision=-1, output_dimension=3) -> str:
2755 """Convert this shape to WKT.
2757 Whitespace around commas and parentheses is removed.
2759 Args:
2760 trim: Remove trailing zeros from the coordinates.
2761 rounding_precision: Number of decimal places, -1 for full precision.
2762 output_dimension: Max. number of dimensions to output.
2764 Returns:
2765 A WKT string.
2766 """
2768 def to_ewkt(self, trim=False, rounding_precision=-1, output_dimension=3) -> str:
2769 """Convert this shape to EWKT, which is WKT prefixed with ``SRID=<srid>;``.
2771 Args:
2772 trim: Remove trailing zeros from the coordinates.
2773 rounding_precision: Number of decimal places, -1 for full precision.
2774 output_dimension: Max. number of dimensions to output.
2776 Returns:
2777 An EWKT string.
2778 """
2780 def to_geojson(self, keep_crs=False) -> dict:
2781 """Convert this shape to a GeoJSON geometry dict.
2783 Args:
2784 keep_crs: Keep the CRS of this shape, otherwise transform the coordinates to WGS84.
2786 Returns:
2787 A GeoJSON geometry dict.
2788 """
2790 def to_precision(self, prec: int) -> 'Shape':
2791 """Create a copy of this shape with coordinates snapped to the given precision.
2793 Args:
2794 prec: Number of decimal places.
2796 Returns:
2797 A new shape.
2798 """
2800 def to_props(self) -> ShapeProps:
2801 """Convert this shape to props, with the EPSG code and a GeoJSON geometry in the CRS of this shape.
2803 Returns:
2804 Shape props.
2805 """
2807 # predicates (https://shapely.readthedocs.io/en/stable/manual.html#predicates-and-relationships)
2809 def is_empty(self) -> bool:
2810 """Check if this shape is empty.
2812 Returns:
2813 ``True`` if this shape is empty.
2814 """
2816 def is_ring(self) -> bool:
2817 """Check if this shape is a closed and simple line.
2819 Returns:
2820 ``True`` if this shape is a ring.
2821 """
2823 def is_simple(self) -> bool:
2824 """Check if this shape is simple, that is, has no self-intersections.
2826 Returns:
2827 ``True`` if this shape is simple.
2828 """
2830 def is_valid(self) -> bool:
2831 """Check if this shape is valid.
2833 Returns:
2834 ``True`` if this shape is valid.
2835 """
2837 def equals(self, other: 'Shape') -> bool:
2838 """Check if this shape is spatially equal to the other.
2840 The other shape is transformed to the CRS of this shape. The same applies to
2841 all binary predicates.
2843 Args:
2844 other: Another shape.
2846 Returns:
2847 ``True`` if the shapes are equal.
2848 """
2850 def contains(self, other: 'Shape') -> bool:
2851 """Check if this shape contains the other.
2853 Args:
2854 other: Another shape.
2856 Returns:
2857 ``True`` if this shape contains the other.
2858 """
2860 def covers(self, other: 'Shape') -> bool:
2861 """Check if this shape covers the other.
2863 Args:
2864 other: Another shape.
2866 Returns:
2867 ``True`` if this shape covers the other.
2868 """
2870 def covered_by(self, other: 'Shape') -> bool:
2871 """Check if this shape is covered by the other.
2873 Args:
2874 other: Another shape.
2876 Returns:
2877 ``True`` if this shape is covered by the other.
2878 """
2880 def crosses(self, other: 'Shape') -> bool:
2881 """Check if this shape crosses the other.
2883 Args:
2884 other: Another shape.
2886 Returns:
2887 ``True`` if this shape crosses the other.
2888 """
2890 def disjoint(self, other: 'Shape') -> bool:
2891 """Check if this shape does not intersect the other.
2893 Args:
2894 other: Another shape.
2896 Returns:
2897 ``True`` if the shapes have no point in common.
2898 """
2900 def intersects(self, other: 'Shape') -> bool:
2901 """Check if this shape intersects the other.
2903 Args:
2904 other: Another shape.
2906 Returns:
2907 ``True`` if the shapes have at least one point in common.
2908 """
2910 def overlaps(self, other: 'Shape') -> bool:
2911 """Check if this shape overlaps the other.
2913 Args:
2914 other: Another shape.
2916 Returns:
2917 ``True`` if this shape overlaps the other.
2918 """
2920 def touches(self, other: 'Shape') -> bool:
2921 """Check if this shape touches the other.
2923 Args:
2924 other: Another shape.
2926 Returns:
2927 ``True`` if this shape touches the other.
2928 """
2930 def within(self, other: 'Shape') -> bool:
2931 """Check if this shape is within the other.
2933 Args:
2934 other: Another shape.
2936 Returns:
2937 ``True`` if this shape is within the other.
2938 """
2940 # set operations
2942 def union(self, others: list['Shape']) -> 'Shape':
2943 """Compute the union of this shape and other shapes.
2945 Args:
2946 others: Other shapes, transformed to the CRS of this shape.
2948 Returns:
2949 A new shape, or this shape if ``others`` is empty.
2950 """
2952 def intersection(self, *others: 'Shape') -> 'Shape':
2953 """Compute the intersection of this shape and other shapes.
2955 Args:
2956 *others: Other shapes, transformed to the CRS of this shape.
2958 Returns:
2959 A new shape, or this shape if no others are given.
2960 """
2962 # convertors
2964 def to_multi(self) -> 'Shape':
2965 """Convert a single geometry shape to a multi-geometry one.
2967 Returns:
2968 A multi-geometry shape for a point, a line string or a polygon, otherwise this shape.
2969 """
2971 def to_type(self, new_type: 'GeometryType') -> 'Shape':
2972 """Convert this shape to another geometry type.
2974 Only the conversion from a single to the respective multi-geometry is supported.
2976 Args:
2977 new_type: Target geometry type. ``geometry`` and the current type return this shape.
2979 Returns:
2980 A converted shape.
2982 Raises:
2983 ``gws.Error``: If the conversion is not supported.
2984 """
2986 def to_2d(self) -> 'Shape':
2987 """Convert this shape to 2 dimensions.
2989 Returns:
2990 A 2D shape, or this shape if it is already 2D.
2991 """
2993 # misc
2995 def tolerance_polygon(self, tolerance=None, quad_segs=None) -> 'Shape':
2996 """Build a buffer polygon around this shape.
2998 Polygons without a tolerance are returned as is. Other shapes always get a
2999 buffer, with a small minimal radius if no tolerance is given. Shapes in a
3000 geographic CRS are buffered in Web Mercator.
3002 Args:
3003 tolerance: Buffer radius in CRS units, or in meters for geographic CRS.
3004 quad_segs: Number of segments per quarter circle.
3006 Returns:
3007 A polygon shape.
3008 """
3010 def transformed_to(self, crs: 'Crs') -> 'Shape':
3011 """Transform this shape to another CRS.
3013 Args:
3014 crs: Target CRS.
3016 Returns:
3017 A transformed shape, or this shape if the CRS is the same.
3018 """
3019################################################################################
3022################################################################################
3023# /lib/grid/types.pyinc
3026MapTile: TypeAlias = tuple[int, int, int]
3027"""Grid tile: ``(x, y, z)``."""
3029MapTileRange: TypeAlias = tuple[int, int, int, int, int]
3030"""Rectangle of tiles at one level: ``(min_x, min_y, max_x, max_y, z)``."""
3032class MapGrid(Data):
3033 """Fixed tile grid over a CRS, origin north-west.
3035 Level ``z`` has the resolution ``baseResolution / 2**z``. See ``gws.lib.grid``.
3036 """
3038 crs: Crs
3039 """Grid CRS."""
3040 extent: Extent
3041 """Frame extent; the origin is its north-west corner."""
3042 baseResolution: float
3043 """Resolution at level 0, in CRS units per pixel."""
3044 tileSize: int
3045 """Tile width and height in pixels."""
3048class TileMatrix(Data):
3049 """Tile matrix, one level of a tile matrix set, as in WMTS."""
3051 identifier: str
3052 """Matrix identifier."""
3053 scale: float
3054 """Scale denominator."""
3055 resolution: float
3056 """Resolution in CRS units per pixel."""
3057 x: float
3058 """X coordinate of the top left corner."""
3059 y: float
3060 """Y coordinate of the top left corner."""
3061 width: float
3062 """Matrix width in tiles."""
3063 height: float
3064 """Matrix height in tiles."""
3065 tileWidth: float
3066 """Tile width in pixels."""
3067 tileHeight: float
3068 """Tile height in pixels."""
3069 extent: Extent
3070 """Matrix extent."""
3073class TileMatrixSet(Data):
3074 """Tile matrix set, a pyramid of tile matrices, as in WMTS."""
3076 identifier: str
3077 """Matrix set identifier."""
3078 crs: 'Crs'
3079 """CRS of the matrices."""
3080 matrices: list[TileMatrix]
3081 """Matrices of the set."""
3082################################################################################
3085################################################################################
3086# /gis/cache/types.pyinc
3089class MapCache(Data):
3090 """Tile cache settings of a grabber."""
3092 name: str
3093 """Cache name, also the name of the cache directory."""
3094 maxAge: int
3095 """Max. age of cached tiles in seconds, 0 disables storing."""
3096 maxLevel: int
3097 """Finest zoom level to store."""
3098 requestBuffer: int
3099 """Pixel buffer around source requests."""
3100 requestTiles: int
3101 """Tiles per side of the block rendered in one source request."""
3104class TileStoreStats(Data):
3105 """Tile store statistics."""
3107 count: int
3108 """Number of stored tiles."""
3109 size: int
3110 """Total size of stored tiles in bytes."""
3111 range: Optional[MapTileRange]
3112 """Bounding tile range of the stored tiles, only for a single level."""
3115class TileStore:
3116 """Storage for encoded map tiles of one grid.
3118 Tiles are addressed by ``(x, y, z)``. A tile counts as stored only while it is younger than ``maxAge``.
3119 """
3121 baseDir: str
3122 """Base directory of the store."""
3123 maxAge: int
3124 """Max. age of stored tiles in seconds."""
3126 def stats(self) -> TileStoreStats:
3127 """Compute statistics for the whole store.
3129 Returns:
3130 Number and size of stored tiles. The tile range is not set.
3131 """
3133 def stats_for_level(self, z: int) -> TileStoreStats:
3134 """Compute statistics for a level.
3136 Args:
3137 z: Zoom level.
3139 Returns:
3140 Number, size and bounding tile range of the stored tiles of the level.
3141 """
3143 def path(self, mt: MapTile) -> str:
3144 """Return the file path of a tile.
3146 Args:
3147 mt: Tile.
3149 Returns:
3150 The file path, whether the tile exists or not.
3151 """
3153 def has(self, mt: MapTile) -> bool:
3154 """Check if a tile is stored.
3156 Args:
3157 mt: Tile.
3159 Returns:
3160 ``True`` if the tile is stored and younger than ``maxAge``.
3161 """
3163 def read(self, mt: MapTile) -> Optional[bytes]:
3164 """Read a stored tile.
3166 Args:
3167 mt: Tile.
3169 Returns:
3170 The tile content, or ``None`` if the tile is missing, stale or unreadable.
3171 """
3173 def write(self, mt: MapTile, blob: bytes):
3174 """Store a tile.
3176 Args:
3177 mt: Tile.
3178 blob: Encoded tile content.
3179 """
3181 def drop(self):
3182 """Remove the whole store."""
3184 def drop_level(self, z: int):
3185 """Remove all tiles of a level.
3187 Args:
3188 z: Zoom level.
3189 """
3191 def drop_range(self, mtr: MapTileRange):
3192 """Remove the tiles of a range.
3194 Args:
3195 mtr: Tile range.
3196 """
3197################################################################################
3200################################################################################
3201# /gis/render/types.pyinc
3204class MapView(Data):
3205 """Geometry of a rendered map."""
3207 bounds: Bounds
3208 """Bounds of the map, not rotated."""
3209 center: Point
3210 """Center point."""
3211 rotation: int
3212 """Rotation angle in degrees."""
3213 scale: int
3214 """Scale denominator."""
3215 mmSize: Size
3216 """Map size in mm."""
3217 pxSize: Size
3218 """Map size in pixels."""
3219 dpi: int
3220 """Resolution in dots per inch."""
3223class MapRenderInputPlaneType(Enum):
3224 """Type of a map render input plane."""
3226 features = 'features'
3227 """A list of features, rendered as SVG."""
3228 image = 'image'
3229 """A raster image."""
3230 imageLayer = 'imageLayer'
3231 """A layer, rendered as an image."""
3232 svgLayer = 'svgLayer'
3233 """A layer, rendered as SVG."""
3234 svgSoup = 'svgSoup'
3235 """An SVG soup, a resolution-independent drawing, see ``gws.lib.svg.soup_to_fragment``."""
3238class MapRenderInputPlane(Data):
3239 """A plane of a map to render."""
3241 type: MapRenderInputPlaneType
3242 """Plane type."""
3243 features: list['Feature']
3244 """Features, for the ``features`` type."""
3245 image: 'Image'
3246 """Image, for the ``image`` type."""
3247 layer: 'Layer'
3248 """Layer, for the ``imageLayer`` and ``svgLayer`` types."""
3249 opacity: float
3250 """Opacity from 0 to 1, defaults to the layer opacity or 1."""
3251 soupPoints: list[Point]
3252 """Points in map coordinates, for the ``svgSoup`` type."""
3253 soupTags: list[Any]
3254 """Tags that refer to the points, for the ``svgSoup`` type."""
3255 styles: list['Style']
3256 """Styles. For ``features``, matched by CSS selector; for ``svgLayer``, the first style is used."""
3257 compositeLayerUids: list[str]
3258 """Child layers to render in one composite image, for the ``imageLayer`` type."""
3261class MapRenderInput(Data):
3262 """Input of the map renderer."""
3264 backgroundColor: int
3265 """Background color of the first raster plane."""
3266 bbox: Extent
3267 """Bounding box of the map. If not set, ``center`` and ``scale`` are used."""
3268 center: Point
3269 """Center point of the map."""
3270 targetCrs: 'Crs'
3271 """CRS of the map."""
3272 dpi: int
3273 """Resolution of raster planes, for maps sized in mm."""
3274 mapSize: UomSize
3275 """Map size in mm or pixels."""
3276 notify: Callable
3277 """Callback, called with an event name and the plane before and after each plane is rendered."""
3278 planes: list['MapRenderInputPlane']
3279 """Planes to render, top to bottom."""
3280 project: 'Project'
3281 """Project of the map."""
3282 rotation: int
3283 """Rotation angle in degrees."""
3284 scale: int
3285 """Scale denominator, used with ``center``."""
3286 user: 'User'
3287 """User who requests the map."""
3288 visibleLayers: Optional[list['Layer']]
3289 """Visible layers of the map."""
3292class MapRenderOutputPlaneType(Enum):
3293 """Type of a map render output plane."""
3295 image = 'image'
3296 """A raster image."""
3297 path = 'path'
3298 """A path to an image file."""
3299 svg = 'svg'
3300 """A list of SVG elements."""
3303class MapRenderOutputPlane(Data):
3304 """A plane of a rendered map."""
3306 type: MapRenderOutputPlaneType
3307 """Plane type."""
3308 path: str
3309 """Image file path, for the ``path`` type."""
3310 elements: list[XmlElement]
3311 """SVG elements, for the ``svg`` type."""
3312 image: 'Image'
3313 """Image, for the ``image`` type."""
3316class MapRenderOutput(Data):
3317 """Output of the map renderer."""
3319 planes: list['MapRenderOutputPlane']
3320 """Rendered planes, bottom to top."""
3321 view: MapView
3322 """Map view of the vector planes."""
3325class LayerRenderInputType(Enum):
3326 """Type of a layer render request."""
3328 box = 'box'
3329 """Render an image of the view extent."""
3330 tile = 'tile'
3331 """Render a tile of the layer grid."""
3332 svg = 'svg'
3333 """Render SVG elements for the view."""
3336class LayerRenderInput(Data):
3337 """Input of a layer render request."""
3339 extraParams: dict
3340 """Additional request parameters, e.g. ``compositeLayerUids``."""
3341 renderParams: dict
3342 """Parameters set by the layer for its grabber. Non-empty params mark a dynamic, uncached request."""
3343 project: 'Project'
3344 """Project of the request."""
3345 style: 'Style'
3346 """Style for the ``svg`` type."""
3347 targetCrs: 'Crs'
3348 """CRS of the output."""
3349 type: LayerRenderInputType
3350 """Request type."""
3351 user: 'User'
3352 """User who requests the rendering."""
3353 view: MapView
3354 """Map view, for the ``box`` and ``svg`` types."""
3355 x: int
3356 """Tile column, for the ``tile`` type."""
3357 y: int
3358 """Tile row, for the ``tile`` type."""
3359 z: int
3360 """Zoom level, for the ``tile`` type."""
3363class LayerRenderOutput(Data):
3364 """Output of a layer render request."""
3366 content: bytes
3367 """Encoded image, for the ``box`` and ``tile`` types."""
3368 tags: list[XmlElement]
3369 """SVG elements, for the ``svg`` type."""
3370################################################################################
3373################################################################################
3374# /gis/source/types.pyinc
3377class SourceStyle(Data):
3378 """A style of a source layer, as listed in the capabilities of a service."""
3380 isDefault: bool
3381 """The style is the default style of the layer."""
3382 legendUrl: Url
3383 """URL of the legend image."""
3384 metadata: 'Metadata'
3385 """Style metadata."""
3386 name: str
3387 """Style name."""
3390class SourceLayer(Data):
3391 """A layer of an external source, such as a WMS, WFS or WMTS service or a QGIS project.
3393 Source layers are read from capabilities and form a tree. The ``a*`` properties
3394 are set by ``gws.gis.source.check_layers``.
3395 """
3397 aLevel: int
3398 """Depth in the layer tree, 1 for top-level layers."""
3399 aPath: str
3400 """Path of uids from the top of the tree, e.g. ``/root/roads``."""
3401 aUid: str
3402 """Uid derived from the name or title."""
3404 dataSource: dict
3405 """Parsed data source of a QGIS layer."""
3406 metadata: 'Metadata'
3407 """Layer metadata."""
3409 supportedCrs: list['Crs']
3410 """CRS supported by the source for this layer."""
3411 wgsExtent: Extent
3412 """Layer extent in WGS84."""
3414 isExpanded: bool
3415 """The layer is expanded in the source layer tree."""
3416 isGroup: bool
3417 """The layer is a group."""
3418 isImage: bool
3419 """The layer can be rendered as an image."""
3420 isQueryable: bool
3421 """The layer can be queried for features."""
3422 isVisible: bool
3423 """The layer is visible by default."""
3425 layers: list['SourceLayer']
3426 """Sub-layers."""
3428 name: str
3429 """Layer name, used in requests to the source."""
3430 title: str
3431 """Layer title."""
3433 legendUrl: Url
3434 """URL of the legend image."""
3435 opacity: float
3436 """Layer opacity from 0 to 1."""
3437 scaleRange: list[float]
3438 """Min. and max. scale denominators at which the layer is visible."""
3440 styles: list[SourceStyle]
3441 """Available styles."""
3442 defaultStyle: Optional[SourceStyle]
3443 """Default style."""
3445 tileMatrixIds: list[str]
3446 """Ids of the WMTS tile matrix sets the layer links to."""
3447 tileMatrixSets: list[TileMatrixSet]
3448 """WMTS tile matrix sets of the layer."""
3449 imageFormat: str
3450 """Image format for WMTS requests."""
3451 resourceUrls: dict
3452 """WMTS resource URL templates, keyed by resource type."""
3454 sourceId: str
3455 """Id of the layer in the source, e.g. the QGIS layer id."""
3456 properties: dict
3457 """Custom properties of a QGIS layer."""
3458################################################################################
3462################################################################################
3463# /config/types.pyinc
3466class ConfigLocation(Data):
3467 """Location in the configuration tree."""
3469 objectUid: str
3470 """UID of the object."""
3471 objectType: str
3472 """Type of the object."""
3473 objectName: str
3474 """Name of the object."""
3475 propName: str
3476 """Property of the parent this object is located at."""
3479class ConfigErrorInfo(Data):
3480 """Full information about a configuration error."""
3482 message: str
3483 """Error message."""
3484 path: str
3485 """Path to the configuration file."""
3486 line: int
3487 """Line number where the error occurred."""
3488 value: str
3489 """Value that caused the error."""
3490 stack: list[ConfigLocation]
3491 """Locations of the objects being configured when the error occurred, innermost first."""
3492 contextLines: list[str]
3493 """Source lines around the error, with line numbers, the error line is marked with ``>>>``."""
3494 cause: str
3495 """Representation of the exception that caused the error."""
3498class ConfigContext(Data):
3499 """Shared state for parsing and validating a configuration."""
3501 specs: SpecRuntime
3502 """Specs used to validate the configuration."""
3503 readOptions: set[SpecReadOption]
3504 """Options passed to the spec reader."""
3505 errors: list[ConfigErrorInfo]
3506 """Errors collected so far."""
3507 warnings: list[ConfigErrorInfo]
3508 """Warnings collected so far."""
3509 paths: set[str]
3510 """Paths of all configuration files that were read, including included files."""
3514class ConfigResult(Data):
3515 """Result of a configuration run."""
3517 root: Optional['Root']
3518 """Configured root object, or ``None`` if configuration failed or was not requested."""
3519 config: Optional['Config']
3520 """Parsed application configuration."""
3521 errors: list[ConfigErrorInfo]
3522 """Configuration errors."""
3523 warnings: list[ConfigErrorInfo]
3524 """Configuration warnings."""
3525 info: str
3526 """Summary with the number of objects, time and memory used."""
3527################################################################################
3530################################################################################
3531# /server/types.pyinc
3534class ServerManager(Node):
3535 """Server configuration manager.
3537 Holds the ``server`` configuration and creates the configuration files for
3538 the embedded servers and the server start script.
3539 """
3541 templates: list['Template']
3542 """Templates for the server configuration files and the start script."""
3544 def create_server_configs(self, target_dir: str, script_path: str, pid_paths: dict):
3545 """Create the server configuration files and the start script.
3547 Args:
3548 target_dir: Directory for the configuration files.
3549 script_path: Path of the start script.
3550 pid_paths: Paths of the pid files, keyed by server name (``web``, ``spool``, ``nginx``).
3551 """
3554class ServerMonitor(Node):
3555 """Server monitor.
3557 Watches configuration files and directories and reconfigures the server
3558 when they change, and runs periodic tasks of registered objects.
3559 """
3561 def watch_directory(self, path: str, pattern: 'Regex', recursive=False):
3562 """Add a directory to watch.
3564 Args:
3565 path: Directory path.
3566 pattern: Regex pattern for file names to watch.
3567 recursive: Also watch subdirectories.
3568 """
3570 def watch_file(self, path: str):
3571 """Add a file to watch.
3573 Args:
3574 path: File path.
3575 """
3577 def register_periodic_task(self, obj: Node, frequency: int = 0):
3578 """Register an object as a periodic task handler.
3580 Args:
3581 obj: A node with a ``periodic_task`` method.
3582 frequency: Interval between runs in seconds, the monitor default if 0.
3584 Raises:
3585 ``gws.Error``: If the object has no ``periodic_task`` method.
3586 """
3588 def schedule_reload(self, with_reconfigure: bool = False):
3589 """Schedule a reload of the web and spool backends.
3591 The reload is performed by the monitor on its next tick.
3593 Args:
3594 with_reconfigure: Reconfigure the server before reloading.
3595 """
3597 def start(self):
3598 """Start watching files and register the timer that drives the monitor.
3600 Must be called in a uWSGI process.
3601 """
3602################################################################################
3606################################################################################
3607# /base/metadata/types.pyinc
3610class MetadataLink(Data):
3611 """Link to a metadata document or another resource related to an object."""
3613 about: str
3614 """Aspect of the object the link describes."""
3615 description: str
3616 """Description of the linked resource."""
3617 format: str
3618 """Format of the linked resource."""
3619 formatVersion: str
3620 """Version of the format of the linked resource."""
3621 function: str
3622 """Function of the link."""
3623 mimeType: str
3624 """MIME type of the linked resource."""
3625 scheme: str
3626 """Link scheme or protocol."""
3627 title: str
3628 """Link title."""
3629 type: str
3630 """Link type."""
3631 url: str
3632 """Link URL."""
3635class Metadata(Data):
3636 """Metadata of an object, used in the client, in OWS services and in catalog records."""
3638 name: str
3639 """Object name."""
3640 title: str
3641 """Object title."""
3643 abstract: str
3644 """Abstract, a brief description of the object."""
3645 accessConstraints: str
3646 """Access constraints."""
3647 accessConstraintsType: str
3648 """Type of the access constraints."""
3649 attribution: str
3650 """Attribution text."""
3651 attributionUrl: str
3652 """URL of the attribution."""
3653 dateCreated: Optional['datetime.datetime']
3654 """Creation date."""
3655 dateUpdated: Optional['datetime.datetime']
3656 """Last update date."""
3657 fees: str
3658 """Fees for using the object."""
3659 image: str
3660 """Image URL or path associated with the object."""
3661 keywords: list[str]
3662 """Keywords, optionally prefixed with a vocabulary, e.g. ``gemet:river``."""
3663 license: str
3664 """License text."""
3665 licenseUrl: str
3666 """License URL."""
3668 contactAddress: str
3669 """Street address of the contact."""
3670 contactAddressType: str
3671 """Type of the contact address."""
3672 contactArea: str
3673 """Administrative area, state or province of the contact address."""
3674 contactCity: str
3675 """Contact city."""
3676 contactCountry: str
3677 """Contact country."""
3678 contactEmail: str
3679 """Contact email address."""
3680 contactFax: str
3681 """Contact fax number."""
3682 contactOrganization: str
3683 """Contact organization."""
3684 contactPerson: str
3685 """Contact person name."""
3686 contactPhone: str
3687 """Contact phone number."""
3688 contactPosition: str
3689 """Contact position or job title."""
3690 contactProviderName: str
3691 """Name of the service provider."""
3692 contactProviderSite: str
3693 """Website of the service provider."""
3694 contactRole: str
3695 """Role of the contact, an ISO ``CI_RoleCode`` value."""
3696 contactUrl: str
3697 """Website of the contact."""
3698 contactZip: str
3699 """Contact postal code."""
3701 authorityIdentifier: str
3702 """Identifier issued by the authority."""
3703 authorityName: str
3704 """Name of the authority that issues identifiers."""
3705 authorityUrl: str
3706 """URL of the authority that issues identifiers."""
3708 metaLinks: list[MetadataLink]
3709 """Links to metadata documents."""
3710 serviceMetadataURL: str
3711 """URL of the service metadata document."""
3713 catalogCitationUid: str
3714 """Identifier of the resource in catalog records."""
3715 catalogUid: str
3716 """Identifier of the metadata record."""
3718 language: str
3719 """Language as an ISO 639-1 code."""
3720 language3: str
3721 """Language as an ISO 639-2 three-letter code, derived from ``language``."""
3722 languageBib: str
3723 """Language as an ISO 639-2 bibliographic code, derived from ``language``."""
3724 languageName: str
3725 """Name of the language."""
3727 parentIdentifier: str
3728 """Identifier of the parent metadata record."""
3729 wgsExtent: Optional[Extent]
3730 """Geographic extent in WGS84."""
3731 crs: Optional['Crs']
3732 """Reference system of the data."""
3733 temporalBegin: Optional['datetime.datetime']
3734 """Start of the temporal extent."""
3735 temporalEnd: Optional['datetime.datetime']
3736 """End of the temporal extent."""
3738 inspireMandatoryKeyword: str
3739 """INSPIRE mandatory keyword (service type)."""
3740 inspireDegreeOfConformity: str
3741 """Degree of conformity with the INSPIRE implementing rules."""
3742 inspireResourceType: str
3743 """INSPIRE resource type."""
3744 inspireSpatialDataServiceType: str
3745 """INSPIRE spatial data service type."""
3746 inspireSpatialScope: str
3747 """INSPIRE spatial scope."""
3748 inspireSpatialScopeName: str
3749 """Display name of the INSPIRE spatial scope."""
3750 inspireTheme: str
3751 """INSPIRE data theme code."""
3753 inspireThemeNameLocal: str
3754 """Name of the INSPIRE theme in the metadata language, derived from ``inspireTheme``."""
3755 inspireThemeNameEn: str
3756 """English name of the INSPIRE theme, derived from ``inspireTheme``."""
3758 isoMaintenanceFrequencyCode: str
3759 """How often the data is updated."""
3760 isoQualityConformanceExplanation: str
3761 """Explanation of the conformance result."""
3762 isoQualityConformanceQualityPass: bool
3763 """The data passes the conformance test."""
3764 isoQualityConformanceSpecificationDate: str
3765 """Publication date of the conformance specification."""
3766 isoQualityConformanceSpecificationTitle: str
3767 """Title of the conformance specification."""
3768 isoQualityLineageSource: str
3769 """Description of the source data."""
3770 isoQualityLineageSourceScale: int
3771 """Scale denominator of the source data."""
3772 isoQualityLineageStatement: str
3773 """Statement on the lineage of the data."""
3774 isoRestrictionCode: str
3775 """Restrictions on access or use of the data."""
3776 isoServiceFunction: str
3777 """ISO service function."""
3778 isoScope: str
3779 """Scope of the metadata."""
3780 isoScopeName: str
3781 """Name of the scope."""
3782 isoSpatialRepresentationType: str
3783 """How the data is represented spatially."""
3784 isoTopicCategories: list[str]
3785 """ISO 19115 topic categories."""
3786 isoSpatialResolution: int
3787 """Spatial resolution as a scale denominator."""
3788################################################################################
3791################################################################################
3792# /base/feature/types.pyinc
3795FeatureUid: TypeAlias = str
3796"""Unique Feature id."""
3798class FeatureRecord(Data):
3799 """Raw data from a feature source."""
3801 attributes: dict
3802 """Attribute values as read from the source or as written to it."""
3803 meta: dict
3804 """Extra source information, e.g. ``layerName`` for features from OWS responses."""
3805 uid: Optional[str]
3806 """Feature id provided by the source."""
3807 shape: Optional['Shape']
3808 """Geometry provided by the source."""
3809 ewkt: str
3810 """Geometry as EWKT, provided by some sources."""
3813class FeatureProps(Props):
3814 """Feature Proprieties."""
3816 attributes: dict
3817 category: Optional[str]
3818 cssSelector: str
3819 errors: Optional[list['ModelValidationError']]
3820 createWithFeatures: Optional[list['FeatureProps']]
3821 isNew: bool
3822 modelUid: str
3823 uid: str
3824 views: dict
3827class Feature:
3828 """Feature object.
3830 A set of named attributes that belongs to a model. The model defines the
3831 uid attribute (``uidName``) and the geometry attribute (``geometryName``).
3832 """
3834 attributes: dict
3835 """Attribute values as python values."""
3836 category: str
3837 """Category for grouping features in the client, e.g. the source layer name."""
3838 cssSelector: str
3839 """CSS selector for the feature style in the client."""
3840 errors: list['ModelValidationError']
3841 """Validation errors."""
3842 isNew: bool
3843 """The feature is new and not yet saved."""
3844 model: 'Model'
3845 """Model the feature belongs to."""
3846 props: 'FeatureProps'
3847 """Data from or for the client."""
3848 record: 'FeatureRecord'
3849 """Raw data from or for the source."""
3850 views: dict
3851 """Rendered views, keyed by view name, e.g. ``title`` or ``label``."""
3852 createWithFeatures: list['Feature']
3853 """Related features a new feature is created with."""
3854 insertedPrimaryKey: Optional[int | str]
3855 """Primary key of the row inserted when the feature was created."""
3857 def get(self, name: str, default=None) -> Any:
3858 """Get an attribute value.
3860 Args:
3861 name: Attribute name.
3862 default: Value to return if the attribute does not exist.
3864 Returns:
3865 The attribute value, or ``default``.
3866 """
3868 def has(self, name: str) -> bool:
3869 """Check if an attribute exists.
3871 Args:
3872 name: Attribute name.
3874 Returns:
3875 ``True`` if the attribute exists.
3876 """
3878 def set(self, name: str, value: Any) -> 'Feature':
3879 """Set an attribute value.
3881 Args:
3882 name: Attribute name.
3883 value: Attribute value.
3885 Returns:
3886 The feature itself.
3887 """
3889 def raw(self, name: str) -> Any:
3890 """Get a raw attribute value from the record.
3892 Args:
3893 name: Attribute name.
3895 Returns:
3896 The value, or ``None`` if the record has no such attribute.
3897 """
3899 def render_views(self, templates: list['Template'], **kwargs) -> 'Feature':
3900 """Render feature views and store them in ``views``.
3902 Each template renders the view named after the last part of its subject,
3903 e.g. ``feature.title`` renders ``title``. The templates receive the
3904 feature attributes, ``feature`` and the extra arguments.
3906 Args:
3907 templates: Feature templates.
3908 **kwargs: Extra template arguments.
3910 Returns:
3911 The feature itself.
3912 """
3914 def shape(self) -> Optional['Shape']:
3915 """Get the feature geometry.
3917 Returns:
3918 The geometry, or ``None`` if the model has no geometry or the feature has no value.
3919 """
3921 def to_svg(self, view: 'MapView', label: Optional[str] = None, style: Optional['Style'] = None) -> list[XmlElement]:
3922 """Render the feature geometry as SVG fragments for a map view.
3924 Args:
3925 view: Map view. The geometry is transformed to its CRS.
3926 label: Label text.
3927 style: Style.
3929 Returns:
3930 A list of SVG elements, empty if the feature has no geometry.
3931 """
3933 def to_geojson(self, keep_crs=False) -> dict:
3934 """Convert the feature to a GeoJSON feature.
3936 The geometry is converted to WGS84 unless ``keep_crs`` is set. The uid
3937 is added as the ``id`` property.
3939 Args:
3940 keep_crs: Keep the geometry coordinates in the feature CRS.
3942 Returns:
3943 A GeoJSON feature dict.
3944 """
3946 def transform_to(self, crs: 'Crs') -> 'Feature':
3947 """Transform the feature geometry to another CRS, in place.
3949 Args:
3950 crs: Target CRS.
3952 Returns:
3953 The feature itself.
3954 """
3956 def uid(self) -> FeatureUid:
3957 """Get the unique id of the feature.
3959 Returns:
3960 The value of the uid attribute as a string, an empty string if the model
3961 has no uid attribute, or ``None`` if the feature has no value.
3962 """
3963################################################################################
3967################################################################################
3968# /base/action/types.pyinc
3971class ActionManager(Node):
3972 """Action manager.
3974 Locates actions in projects and the application and prepares command calls.
3975 """
3977 def actions_for_project(self, project: 'Project', user: 'User') -> list['Action']:
3978 """Get the actions a user can use in a project.
3980 Includes the project actions and the application actions, one action per type.
3981 A project action takes precedence over an application action of the same type.
3983 Args:
3984 project: The project.
3985 user: The user.
3987 Returns:
3988 A list of actions.
3989 """
3991 def find_action(self, project: Optional['Project'], ext_type: str, user: 'User') -> Optional['Action']:
3992 """Find an action by its type.
3994 Searches the project actions first, if a project is given, then the application actions.
3996 Args:
3997 project: The project, or ``None`` to search the application actions only.
3998 ext_type: Action type, for example ``map``.
3999 user: The user who wants to use the action.
4001 Returns:
4002 The action object, or ``None`` if not found.
4004 Raises:
4005 ForbiddenError: If the action is found but the user may not use it.
4006 """
4008 def prepare_action(
4009 self,
4010 command_category: CommandCategory,
4011 command_name: str,
4012 params: dict,
4013 path: str,
4014 user: 'User',
4015 read_options: Optional[set[SpecReadOption]]=None,
4016 ) -> tuple[Callable, Request]:
4017 """Prepare a command call.
4019 Parses the parameters into the command's request type, finds the action
4020 that owns the command (in the requested project, then in the application)
4021 and checks the user's access.
4023 Args:
4024 command_category: Command category.
4025 command_name: Command name, for example ``mapDescribeLayer``.
4026 params: Raw request parameters.
4027 path: Request path; for ``raw`` commands, the project uid can be given as a ``/projectUid/<uid>`` segment.
4028 user: The user who runs the command.
4029 read_options: Options for the spec reader.
4031 Returns:
4032 A tuple of the bound command method and the parsed request object.
4034 Raises:
4035 NotFoundError: If the command, the project or the action is not found.
4036 BadRequestError: If the parameters cannot be parsed.
4037 ForbiddenError: If the user may not use the project or the action.
4038 """
4041class Action(Node):
4042 """Server action.
4044 An action is a configurable object that provides server commands.
4045 """
4046################################################################################
4049################################################################################
4050# /base/auth/types.pyinc
4053class User(Object):
4054 """User.
4056 A user has a set of roles, which are checked against the permissions of
4057 objects to decide access.
4058 """
4060 isGuest: bool
4061 """The user is the guest user."""
4063 authProvider: 'AuthProvider'
4064 """The provider that created the user."""
4066 attributes: dict
4067 """Public user attributes, sent to the client."""
4068 data: dict
4069 """Private user data from the provider."""
4070 roles: set[str]
4071 """User roles."""
4072 uid: str
4073 """Global user uid, made of the provider uid and the local uid."""
4075 authToken: str
4076 """Token for the ``token`` authentication method."""
4077 displayName: str
4078 """User display name."""
4079 email: str
4080 """User email."""
4081 localUid: str
4082 """User uid within its provider."""
4083 loginName: str
4084 """User login name."""
4085 mfaUid: str
4086 """Uid of the multi-factor adapter for this user, empty if none."""
4087 mfaSecret: str
4088 """Secret for the multi-factor adapter."""
4090 def acl_bit(self, access: Access, obj: Object) -> Optional[int]:
4091 """Get the access decision for an object itself, without parents.
4093 Args:
4094 access: Access mode.
4095 obj: The object.
4097 Returns:
4098 ``gws.c.ALLOW`` or ``gws.c.DENY`` if the object's permissions decide
4099 for one of the user's roles, ``None`` otherwise.
4100 """
4102 def can(self, access: Access, obj: Object, *context) -> bool:
4103 """Check if the user can access an object.
4105 If the object's permissions do not decide, the context objects are
4106 checked in turn, then the parents of the last checked object.
4108 Args:
4109 access: Access mode.
4110 obj: The object.
4111 *context: Further objects to check, before the parents.
4113 Returns:
4114 ``True`` if access is granted.
4115 """
4117 def can_create(self, obj: Object, *context) -> bool:
4118 """Check if the user has the ``create`` permission on an object.
4120 Args:
4121 obj: The object.
4122 *context: Further objects to check, before the parents.
4124 Returns:
4125 ``True`` if access is granted.
4126 """
4128 def can_delete(self, obj: Object, *context) -> bool:
4129 """Check if the user has the ``delete`` permission on an object.
4131 Args:
4132 obj: The object.
4133 *context: Further objects to check, before the parents.
4135 Returns:
4136 ``True`` if access is granted.
4137 """
4139 def can_read(self, obj: Object, *context) -> bool:
4140 """Check if the user has the ``read`` permission on an object.
4142 Args:
4143 obj: The object.
4144 *context: Further objects to check, before the parents.
4146 Returns:
4147 ``True`` if access is granted.
4148 """
4150 def can_use(self, obj: Object, *context) -> bool:
4151 """Check if the user can use an object, which requires the ``read`` permission.
4153 Args:
4154 obj: The object.
4155 *context: Further objects to check, before the parents.
4157 Returns:
4158 ``True`` if access is granted.
4159 """
4161 def can_write(self, obj: Object, *context) -> bool:
4162 """Check if the user has the ``write`` permission on an object.
4164 Args:
4165 obj: The object.
4166 *context: Further objects to check, before the parents.
4168 Returns:
4169 ``True`` if access is granted.
4170 """
4172 def can_edit(self, obj: Object, *context) -> bool:
4173 """Check if the user has any of the ``write``, ``create`` or ``delete`` permissions on an object.
4175 Args:
4176 obj: The object.
4177 *context: Further objects to check, before the parents.
4179 Returns:
4180 ``True`` if access is granted.
4181 """
4183 def has_role(self, role: str) -> bool:
4184 """Check if the user has a role.
4186 Args:
4187 role: Role name.
4189 Returns:
4190 ``True`` if the user has the role.
4191 """
4193 def acquire(self, uid: str = None, classref: Optional[ClassRef] = None, access: Optional[Access] = None) -> Optional[Object]:
4194 """Get an object by uid, if the user can access it.
4196 Args:
4197 uid: Object uid.
4198 classref: Class reference. If provided, the object must match it.
4199 access: Access mode, ``Access.read`` if omitted.
4201 Returns:
4202 The object, or ``None`` if it does not exist or the user may not access it.
4203 """
4205 def require(self, uid: str = None, classref: Optional[ClassRef] = None, access: Optional[Access] = None) -> Object:
4206 """Get an object by uid and fail if it is not found or not accessible.
4208 Args:
4209 uid: Object uid.
4210 classref: Class reference. If provided, the object must match it.
4211 access: Access mode, ``Access.read`` if omitted.
4213 Returns:
4214 The object.
4216 Raises:
4217 NotFoundError: If the object does not exist.
4218 ForbiddenError: If the user may not access the object.
4219 """
4221 def require_project(self, uid: str = None) -> 'Project':
4222 """Get a project the user can read.
4224 Args:
4225 uid: Project uid.
4227 Returns:
4228 The project.
4230 Raises:
4231 NotFoundError: If the project does not exist.
4232 ForbiddenError: If the user may not read the project.
4233 """
4235 def require_layer(self, uid=None) -> 'Layer':
4236 """Get a layer the user can read.
4238 Args:
4239 uid: Layer uid.
4241 Returns:
4242 The layer.
4244 Raises:
4245 NotFoundError: If the layer does not exist.
4246 ForbiddenError: If the user may not read the layer.
4247 """
4250class AuthManager(Node):
4251 """Authorization manager.
4253 Holds the authentication methods, providers, multi-factor adapters and the
4254 session manager, authenticates users and opens a session for every web request.
4255 """
4257 guestSession: 'AuthSession'
4258 """Session of the guest user, used for requests without a session."""
4260 guestUser: 'User'
4261 """The guest user."""
4262 systemUser: 'User'
4263 """The system user, allowed everything."""
4265 providers: list['AuthProvider']
4266 """Authentication providers."""
4267 methods: list['AuthMethod']
4268 """Authentication methods."""
4269 mfAdapters: list['AuthMultiFactorAdapter']
4270 """Multi-factor adapters."""
4272 sessionMgr: 'AuthSessionManager'
4273 """Session manager."""
4275 def authenticate(self, method: 'AuthMethod', credentials: Data, req: 'WebRequester') -> Optional['User']:
4276 """Authenticate a user with the providers that allow the method.
4278 Args:
4279 method: The authentication method.
4280 credentials: The credentials, for example ``username`` and ``password``.
4281 req: The web request.
4283 Returns:
4284 The user, or ``None`` if no provider accepts the credentials.
4286 Raises:
4287 ForbiddenError: If a provider rejects the credentials.
4288 TooManyRequestsError: If the attempt is blocked by the throttle.
4289 """
4291 def create_transient_session(self, method: 'AuthMethod', user: 'User', data: Optional[dict] = None) -> 'AuthSession':
4292 """Create a session that lives only for the duration of the request.
4294 The session is not stored in the session manager.
4296 Args:
4297 method: The method that creates the session.
4298 user: The session user.
4299 data: Session data.
4301 Returns:
4302 A new session.
4303 """
4305 def get_user(self, user_uid: str) -> Optional['User']:
4306 """Get a user by its global uid.
4308 Args:
4309 user_uid: Global user uid.
4311 Returns:
4312 The user, or ``None`` if the provider is not found or does not return the user.
4313 """
4315 def add_provider(self, provider: 'AuthProvider'):
4316 """Add an authentication provider.
4318 Args:
4319 provider: The provider.
4320 """
4322 def add_method(self, method: 'AuthMethod'):
4323 """Add an authentication method.
4325 Args:
4326 method: The method.
4327 """
4329 def add_multi_factor_adapter(self, adapter: 'AuthMultiFactorAdapter'):
4330 """Add a multi-factor adapter.
4332 Args:
4333 adapter: The adapter.
4334 """
4336 def can_use_method(self, req: 'WebRequester', method: 'AuthMethod') -> bool:
4337 """Check if a method may be used for a request.
4339 A secure method can only be used on secure requests, or from the addresses
4340 listed in its ``allowInsecureFrom``.
4342 Args:
4343 req: The web request.
4344 method: The method.
4346 Returns:
4347 ``True`` if the method may be used.
4348 """
4350 def get_provider(self, uid: str) -> Optional['AuthProvider']:
4351 """Get an authentication provider by its uid.
4353 Args:
4354 uid: Provider uid.
4356 Returns:
4357 The provider, or ``None`` if not found.
4358 """
4360 def get_method(self, uid: str) -> Optional['AuthMethod']:
4361 """Get an authentication method by its uid.
4363 Args:
4364 uid: Method uid.
4366 Returns:
4367 The method, or ``None`` if not found.
4368 """
4370 def get_multi_factor_adapter(self, uid: str) -> Optional['AuthMultiFactorAdapter']:
4371 """Get a multi-factor adapter by its uid.
4373 Args:
4374 uid: Adapter uid.
4376 Returns:
4377 The adapter, or ``None`` if not found.
4378 """
4380 def serialize_user(self, user: 'User') -> str:
4381 """Serialize a user to a string, together with its provider uid.
4383 Args:
4384 user: The user.
4386 Returns:
4387 A JSON string.
4388 """
4390 def unserialize_user(self, ser: str) -> Optional['User']:
4391 """Restore a user serialized by ``serialize_user``.
4393 Args:
4394 ser: The serialized user.
4396 Returns:
4397 The user, or ``None`` if the provider is not found.
4398 """
4400 def is_public_object(self, obj: Object, *context) -> bool:
4401 """Check if the guest user can read an object.
4403 Args:
4404 obj: The object.
4405 *context: Further objects to check, before the parents.
4407 Returns:
4408 ``True`` if the object is public.
4409 """
4412class AuthMethod(Node):
4413 """Authentication method.
4415 Defines how credentials and sessions are passed between the client and the
4416 server, for example as a login form and a session cookie.
4417 """
4419 secure: bool
4420 """The method may only be used on secure (HTTPS) requests."""
4422 allowInsecureFrom: list[str]
4423 """IP addresses from which the method may be used without HTTPS."""
4425 def open_session(self, req: 'WebRequester') -> Optional['AuthSession']:
4426 """Try to open a session for a request.
4428 Called at the start of every web request.
4430 Args:
4431 req: The web request.
4433 Returns:
4434 A session, or ``None`` if the request has no session for this method.
4435 """
4437 def close_session(self, req: 'WebRequester', res: 'WebResponder') -> bool:
4438 """Close the session of a request.
4440 Called at the end of every web request whose session was opened by this
4441 method, for example to set or delete the session cookie.
4443 Args:
4444 req: The web request.
4445 res: The web response.
4447 Returns:
4448 ``True`` if the session was closed.
4449 """
4452class AuthMultiFactorState(Enum):
4453 """State of a multi-factor authentication transaction."""
4455 open = 'open'
4456 """The transaction is started and waits for verification."""
4457 ok = 'ok'
4458 """The verification was successful."""
4459 retry = 'retry'
4460 """The verification failed and can be retried."""
4461 failed = 'failed'
4462 """The transaction failed."""
4465class AuthMultiFactorTransaction(Data):
4466 """Multi-factor authentication transaction.
4468 Kept in the user's session from the login until the verification succeeds,
4469 fails or expires.
4470 """
4472 state: AuthMultiFactorState
4473 """Current state."""
4474 restartCount: int
4475 """Number of restarts."""
4476 verifyCount: int
4477 """Number of verification attempts."""
4478 secret: str
4479 """Secret for code generation."""
4480 startTime: int
4481 """Start time, as a Unix timestamp."""
4482 generateTime: int
4483 """Time when the code was last generated, as a Unix timestamp."""
4484 message: str
4485 """Message shown to the user."""
4486 adapter: 'AuthMultiFactorAdapter'
4487 """The adapter handling the transaction."""
4488 user: 'User'
4489 """The user who logs in."""
4492class AuthMultiFactorAdapter(Node):
4493 """Multi-factor authentication adapter.
4495 Provides the second verification step of a login, for example a code sent by
4496 email or generated by an authenticator app.
4497 """
4499 message: str
4500 """Message shown to the user during the verification step."""
4501 lifeTime: int
4502 """Time in seconds allowed to complete the verification."""
4503 maxRestarts: int
4504 """How often a transaction can be restarted."""
4505 maxVerifyAttempts: int
4506 """Number of verification attempts allowed."""
4508 def start(self, user: 'User') -> Optional[AuthMultiFactorTransaction]:
4509 """Start a transaction for a user.
4511 Args:
4512 user: The user who logs in.
4514 Returns:
4515 A new transaction, or ``None`` if the adapter cannot be used for this
4516 user, for example because a required user attribute is missing.
4517 """
4519 def verify(self, mfa: AuthMultiFactorTransaction, payload: dict) -> AuthMultiFactorTransaction:
4520 """Verify a payload submitted by the user.
4522 Args:
4523 mfa: The transaction.
4524 payload: The payload, for example ``{'code': '123456'}``.
4526 Returns:
4527 The transaction with an updated state.
4528 """
4530 def cancel(self, mfa: AuthMultiFactorTransaction):
4531 """Cancel a transaction.
4533 Args:
4534 mfa: The transaction.
4535 """
4537 def check_state(self, mfa: AuthMultiFactorTransaction) -> bool:
4538 """Check if a transaction is still valid, and mark it failed if not.
4540 Args:
4541 mfa: The transaction.
4543 Returns:
4544 ``True`` if the transaction is valid.
4545 """
4547 def check_restart(self, mfa: AuthMultiFactorTransaction) -> bool:
4548 """Check if a transaction can be restarted.
4550 Args:
4551 mfa: The transaction.
4553 Returns:
4554 ``True`` if a restart is allowed.
4555 """
4557 def restart(self, mfa: AuthMultiFactorTransaction) -> Optional[AuthMultiFactorTransaction]:
4558 """Restart a transaction, for example by sending a new code.
4560 Args:
4561 mfa: The transaction.
4563 Returns:
4564 A new transaction, or ``None`` if a restart is not possible.
4565 """
4567 def key_uri(self, secret: str | bytes, issuer_name: str, account_name: str) -> Optional[str]:
4568 """Generate a key URI for authenticator apps.
4570 Args:
4571 secret: The user's secret.
4572 issuer_name: Issuer name shown in the app.
4573 account_name: Account name shown in the app.
4575 Returns:
4576 An ``otpauth://`` URI, or ``None`` if the adapter does not support it.
4577 """
4580class AuthProvider(Node):
4581 """Authentication provider.
4583 A source of users, for example a file, an LDAP directory or a database table,
4584 which verifies credentials.
4585 """
4587 allowedMethods: list[str]
4588 """Method types this provider accepts, all methods if empty."""
4590 def get_user(self, local_uid: str) -> Optional['User']:
4591 """Get a user by its local uid.
4593 Args:
4594 local_uid: User uid within the provider.
4596 Returns:
4597 The user, or ``None`` if not found.
4598 """
4600 def authenticate(self, method: 'AuthMethod', credentials: Data) -> Optional['User']:
4601 """Authenticate a user.
4603 Args:
4604 method: The authentication method.
4605 credentials: The credentials, for example ``username`` and ``password``.
4607 Returns:
4608 The user, or ``None`` if the provider does not know the user.
4610 Raises:
4611 AuthenticationError: If the credentials are wrong or match more than one user.
4612 """
4614 def serialize_user(self, user: 'User') -> str:
4615 """Serialize a user to a string.
4617 Args:
4618 user: The user.
4620 Returns:
4621 The serialized user.
4622 """
4624 def unserialize_user(self, ser: str) -> Optional['User']:
4625 """Restore a user serialized by ``serialize_user``.
4627 Args:
4628 ser: The serialized user.
4630 Returns:
4631 The user, or ``None`` if it cannot be restored.
4632 """
4635class AuthSession:
4636 """Authentication session.
4638 Holds the user and arbitrary data between requests.
4639 """
4641 uid: str
4642 """Session uid."""
4643 method: Optional['AuthMethod']
4644 """The method that created the session, ``None`` for the guest session."""
4645 user: 'User'
4646 """The session user."""
4647 data: dict
4648 """Session data."""
4649 created: 'datetime.datetime'
4650 """Creation time."""
4651 updated: 'datetime.datetime'
4652 """Last update time."""
4653 isChanged: bool
4654 """The session data has changed since the session was loaded."""
4655 isTransient: bool
4656 """The session lives only for the duration of the request and is not stored."""
4658 def get(self, key: str, default=None):
4659 """Get a session data value.
4661 Args:
4662 key: Value name.
4663 default: Default value.
4665 Returns:
4666 The value, or the default if it is not set.
4667 """
4669 def set(self, key: str, value):
4670 """Set a session data value and mark the session as changed.
4672 Args:
4673 key: Value name.
4674 value: The value.
4675 """
4678class AuthSessionManager(Node):
4679 """Authentication session manager.
4681 Stores sessions persistently. A session is valid until ``lifeTime`` has passed
4682 since its last update, or ``maxLifeTime`` since its creation.
4683 """
4685 lifeTime: int
4686 """Session life time in seconds, counted from the last update."""
4688 maxLifeTime: int
4689 """Absolute session life time in seconds, counted from the creation, or 0 if not limited."""
4691 def create(self, method: 'AuthMethod', user: 'User', data: Optional[dict] = None) -> 'AuthSession':
4692 """Create and store a new session.
4694 Args:
4695 method: The method that creates the session.
4696 user: The session user.
4697 data: Session data.
4699 Returns:
4700 The new session.
4701 """
4703 def delete(self, sess: 'AuthSession'):
4704 """Delete a session.
4706 Args:
4707 sess: The session.
4708 """
4710 def delete_all(self):
4711 """Delete all sessions."""
4713 def get(self, uid: str) -> Optional['AuthSession']:
4714 """Get a valid session by its uid.
4716 Args:
4717 uid: Session uid.
4719 Returns:
4720 The session, or ``None`` if it does not exist or has expired.
4721 """
4723 def list_all(self) -> list['AuthSession']:
4724 """Get all stored sessions.
4726 Returns:
4727 A list of sessions.
4728 """
4730 def save(self, sess: 'AuthSession'):
4731 """Save the session data.
4733 Args:
4734 sess: The session.
4735 """
4737 def touch(self, sess: 'AuthSession'):
4738 """Update the last activity time of a session.
4740 Args:
4741 sess: The session.
4742 """
4744 def cleanup(self):
4745 """Remove expired sessions from the storage."""
4746################################################################################
4750################################################################################
4751# /base/layer/types.pyinc
4754class LayerDisplayMode(Enum):
4755 """How a layer is rendered."""
4757 box = 'box'
4758 """Render the map view as a single image."""
4759 tile = 'tile'
4760 """Render the layer as tiles of a grid."""
4761 client = 'client'
4762 """Let the client render the layer from its source."""
4765class FeatureLoadingStrategy(Enum):
4766 """When the client loads a layer's features."""
4768 all = 'all'
4769 """Load all features once, on first display."""
4770 bbox = 'bbox'
4771 """Reload features for the current map extent whenever it changes."""
4772 lazy = 'lazy'
4773 """Load features only when a search text is entered."""
4776class LayerOwsBinding(Node):
4777 """Binding of a layer to OWS services: access, names and models."""
4779 allowedServiceUids: list[str]
4780 """UIDs of services which can use this layer; empty means any."""
4781 deniedServiceUids: list[str]
4782 """UIDs of services which can not use this layer."""
4783 featureName: str
4784 """Name for features in this layer."""
4785 geometryName: str
4786 """Name for geometries in this layer."""
4787 layerName: str
4788 """Name for this layer in OWS services."""
4789 models: list['Model']
4790 """OWS-specific models."""
4791 xmlNamespace: Optional['XmlNamespace']
4792 """XML namespace for feature and layer names."""
4795class Layer(Node):
4796 """Layer object."""
4798 bounds: Bounds
4799 """Bounds in the map CRS: the WGS extent clipped to the parent extent and to the CRS."""
4800 canRenderBox: bool
4801 """The layer can render a single image for an arbitrary extent."""
4802 canRenderInClient: bool
4803 """The layer can be drawn by the client directly from its source (``display: client``)."""
4804 canRenderSvg: bool
4805 """The layer can render its features as SVG."""
4806 canRenderTile: bool
4807 """The layer can render tiles in a fixed grid."""
4808 cssSelector: str
4809 """CSS selector for feature styling."""
4810 displayMode: LayerDisplayMode
4811 """How the client displays the layer."""
4812 finders: list['Finder']
4813 """Search providers."""
4814 grabbers: dict[int, 'Grabber']
4815 """Grabbers by CRS code, one for each CRS the application supports."""
4816 hasLegend: bool
4817 """The layer has a legend."""
4818 imageFormat: ImageFormat
4819 """Image format for box and tile rendering."""
4820 isEnabledForOws: bool
4821 """The layer can be used by OWS services."""
4822 isGroup: bool
4823 """The layer is a group of other layers."""
4824 isSearchable: bool
4825 """The layer has at least one search provider."""
4826 layers: list['Layer']
4827 """Child layers."""
4828 legend: Optional['Legend']
4829 """Legend object."""
4830 loadingStrategy: FeatureLoadingStrategy
4831 """How the client loads features."""
4832 mapCrs: 'Crs'
4833 """CRS of the map this layer belongs to."""
4834 metadata: 'Metadata'
4835 """Layer metadata."""
4836 models: list['Model']
4837 """Data models."""
4838 opacity: float
4839 """Layer opacity, 0 to 1."""
4840 ows: 'LayerOwsBinding'
4841 """Binding to OWS services."""
4842 resolutions: list[float]
4843 """Resolutions the layer is visible at, in map units per pixel."""
4844 sourceLayers: list['SourceLayer']
4845 """Source layers this layer is built from."""
4846 templates: list['Template']
4847 """Layer templates."""
4848 title: str
4849 """Layer title."""
4850 wgsExtent: Extent
4851 """Layer extent in WGS84."""
4852 zoomBounds: Bounds
4853 """Bounds the client zooms to for this layer; defaults to ``bounds``."""
4855 def find_features(self, search: 'SearchQuery', user: 'User') -> list['Feature']:
4856 """Find features in the layer.
4858 Vector layers search in the first model the user can read; other
4859 layers return an empty list.
4861 Args:
4862 search: Search query.
4863 user: The user who searches.
4865 Returns:
4866 Found features.
4867 """
4869 def render(self, lri: LayerRenderInput) -> Optional['LayerRenderOutput']:
4870 """Render a box, a tile or an SVG fragment, depending on the input type.
4872 Args:
4873 lri: Render input.
4875 Returns:
4876 Render output with image content or SVG tags, or ``None`` if the
4877 layer has nothing to render.
4878 """
4880 def render_legend(self, args: Optional[dict | Data] = None) -> Optional['LegendRenderOutput']:
4881 """Render the layer legend.
4883 Without ``args`` the output is cached for the server lifetime.
4885 Args:
4886 args: Arguments passed to the legend renderer.
4888 Returns:
4889 Legend output, or ``None`` if the layer has no legend.
4890 """
4892 def url_path_for(self, kind: str) -> str:
4893 """Return the URL path for requests to this layer.
4895 Args:
4896 kind: ``box``, ``tile``, ``legend`` or ``features``. The ``tile``
4897 path contains ``{z}``, ``{x}`` and ``{y}`` placeholders.
4899 Returns:
4900 URL path.
4902 Raises:
4903 ``gws.Error``: If ``kind`` is not recognized.
4904 """
4905################################################################################
4908################################################################################
4909# /base/grabber/types.pyinc
4912class Grabber:
4913 """Raster grabber.
4915 Provides raster images for a layer: fetches them from a source, aligns them to a
4916 tile grid, stores and reads them back.
4917 """
4919 cache: MapCache
4920 """Cache settings; the name (``<layer cache name>_<srid>``) keys the tile store."""
4921 extent: Extent
4922 """Extent covered by this grabber, in the target CRS."""
4923 grid: MapGrid
4924 """The fixed target grid for the CRS."""
4925 imageFormat: ImageFormat
4926 """Format tiles are stored and returned in."""
4927 sourceCrs: Crs
4928 """Source CRS; defines the original CRS of the raster data."""
4929 store: 'TileStore'
4930 """Persistent tile store."""
4931 targetCrs: Crs
4932 """Target CRS; one grabber serves exactly one CRS."""
4934 def get_tile_as_bytes(self, mt: MapTile, params: Optional[dict] = None) -> bytes:
4935 """Return a single tile as an encoded image, composing and storing it if needed.
4937 A tile outside the layer's range is a transparent image.
4939 Args:
4940 mt: Tile.
4941 params: Dynamic request parameters. With ``params``, the persistent store is bypassed.
4943 Returns:
4944 The encoded tile.
4946 Raises:
4947 ``Exception``: Errors of the source request are passed through.
4948 """
4950 def get_tile_as_image(self, mt: MapTile, params: Optional[dict] = None) -> 'Image':
4951 """Return a single tile as an image, composing and storing it if needed.
4953 Same contract as ``get_tile_as_bytes``, decoded pixels instead of bytes.
4955 Args:
4956 mt: Tile.
4957 params: Dynamic request parameters. With ``params``, the persistent store is bypassed.
4959 Returns:
4960 The tile image.
4962 Raises:
4963 ``Exception``: Errors of the source request are passed through.
4964 """
4966 def get_tiles_as_bytes_dict(self, mtr: MapTileRange, params: Optional[dict] = None) -> dict[MapTile, bytes]:
4967 """Return a rectangular block of tiles as encoded images.
4969 Args:
4970 mtr: Tile range.
4971 params: Dynamic request parameters. With ``params``, the persistent store is bypassed.
4973 Returns:
4974 Encoded tiles, keyed by tile. Sparse: contains entries only for tiles present in the grid.
4976 Raises:
4977 ``Exception``: Errors of the source request are passed through.
4978 """
4980 def get_tiles_as_image_dict(self, mtr: MapTileRange, params: Optional[dict] = None) -> dict[MapTile, 'Image']:
4981 """Return a rectangular block of tiles as images.
4983 Same contract as ``get_tiles_as_bytes_dict``, decoded pixels instead of bytes.
4985 Args:
4986 mtr: Tile range.
4987 params: Dynamic request parameters. With ``params``, the persistent store is bypassed.
4989 Returns:
4990 Tile images, keyed by tile.
4992 Raises:
4993 ``Exception``: Errors of the source request are passed through.
4994 """
4996 def get_box_as_bytes(self, extent: Extent, w: int, h: int, params: Optional[dict] = None) -> bytes:
4997 """Return an encoded image for arbitrary extent and pixel size.
4999 A box overlapping no data is a transparent image.
5001 Args:
5002 extent: Extent in the target CRS.
5003 w: Width in pixels.
5004 h: Height in pixels.
5005 params: Dynamic request parameters. With ``params``, the persistent store is bypassed.
5007 Returns:
5008 The encoded image.
5010 Raises:
5011 ``Exception``: Errors of the source request are passed through.
5012 """
5014 def get_box_as_image(self, extent: Extent, w: int, h: int, params: Optional[dict] = None) -> 'Image':
5015 """Return an image for arbitrary extent and pixel size.
5017 Same contract as ``get_box_as_bytes``, decoded pixels instead of bytes.
5019 Args:
5020 extent: Extent in the target CRS.
5021 w: Width in pixels.
5022 h: Height in pixels.
5023 params: Dynamic request parameters. With ``params``, the persistent store is bypassed.
5025 Returns:
5026 The image.
5028 Raises:
5029 ``Exception``: Errors of the source request are passed through.
5030 """
5032 def levels(self) -> list[int]:
5033 """Return the levels this grabber supports.
5035 Returns:
5036 A list of levels.
5037 """
5039 def tile_range_for_level(self, z: int) -> MapTileRange:
5040 """Return the tile range covered by the grabber's extent at a level.
5042 Args:
5043 z: Level.
5045 Returns:
5046 The tile range in the grabber's grid.
5047 """
5048################################################################################
5051################################################################################
5052# /base/legend/types.pyinc
5055class LegendRenderOutput(Data):
5056 """Legend render output."""
5058 html: str
5059 """HTML representation of the legend; not set by the built-in legend types."""
5060 image: 'Image'
5061 """Legend image."""
5062 size: Size
5063 """Size of the legend image in pixels."""
5066class Legend(Node):
5067 """Legend object."""
5069 def render(self, args: Optional[dict | Data] = None) -> Optional[LegendRenderOutput]:
5070 """Render the legend.
5072 Args:
5073 args: Arguments for the renderer, for example template arguments.
5075 Returns:
5076 Legend output, or ``None`` if there is nothing to show.
5077 """
5078################################################################################
5081################################################################################
5082# /base/map/types.pyinc
5085class Map(Node):
5086 """Map object."""
5088 rootLayer: 'Layer'
5089 """Root group layer that holds the map layers."""
5091 bounds: Bounds
5092 """Map extent in the map CRS."""
5093 center: Point
5094 """Initial map center."""
5095 coordinatePrecision: int
5096 """Decimal places for coordinates."""
5097 initResolution: float
5098 """Initial resolution."""
5099 resolutions: list[float]
5100 """Resolutions the map can be displayed at, in map units per pixel."""
5101 title: str
5102 """Map title."""
5103 wgsExtent: Extent
5104 """Map extent in WGS84."""
5105################################################################################
5109################################################################################
5110# /base/model/types.pyinc
5113class ModelClientOptions(Data):
5114 """Client options for a model."""
5116 keepFormOpen: Optional[bool]
5117 """Keep the edit form open after saving."""
5120class ModelValidationError(Data):
5121 """Validation error of a feature field."""
5123 fieldName: str
5124 """Name of the field that failed validation."""
5125 message: str
5126 """Error message, or a message key for the client."""
5129class ModelOperation(Enum):
5130 """Model operation."""
5132 read = 'read'
5133 """Read features."""
5134 create = 'create'
5135 """Create new features."""
5136 update = 'update'
5137 """Update existing features."""
5138 delete = 'delete'
5139 """Delete features."""
5140 export = 'export'
5141 """Export features."""
5144class ModelReadTarget(Enum):
5145 """Target for the read operation."""
5147 map = 'map'
5148 """The feature is to be drawn on a map."""
5149 searchResults = 'searchResults'
5150 """The feature is to be displayed in the search results list."""
5151 list = 'list'
5152 """The feature is to be displayed in a list view."""
5153 editList = 'editList'
5154 """The feature is to be displayed in an editable list view."""
5155 editForm = 'editForm'
5156 """The feature is to be displayed in an edit form."""
5159class ModelSelectBuild(Data):
5160 """Parts of a database select statement, collected from the model fields."""
5162 columns: list['sqlalchemy.Column']
5163 """Columns to select."""
5164 geometryWhere: list
5165 """Conditions for the geometry search, combined with OR."""
5166 keywordWhere: list
5167 """Conditions for the keyword search, combined with OR."""
5168 where: list
5169 """Other conditions, combined with AND."""
5170 order: list
5171 """Sort expressions."""
5174class ModelContext(Data):
5175 """Context of a model operation."""
5177 op: ModelOperation
5178 """The operation."""
5179 target: ModelReadTarget
5180 """Where the features are to be displayed, for read operations."""
5181 user: 'User'
5182 """The user performing the operation."""
5183 project: Optional['Project']
5184 """The current project."""
5185 relDepth: int = 0
5186 """Current depth of related features."""
5187 maxDepth: int = 0
5188 """Maximum depth of related features to process."""
5189 search: 'SearchQuery'
5190 """The search query, for read operations."""
5191 dbSelect: ModelSelectBuild
5192 """The select statement being built, for database read operations."""
5195EmptyValue = object()
5196"""Special value for empty fields."""
5198ErrorValue = object()
5199"""Special value for invalid fields."""
5202class ModelWidget(Node):
5203 """Model widget.
5205 Describes how the client displays and edits a field value.
5206 """
5208 supportsTableView: bool = True
5209 """The widget can be used in the table view."""
5212class ModelValidator(Node):
5213 """Model validator.
5215 Checks the value of a field.
5216 """
5218 message: str
5219 """Error message, or a message key for the client."""
5220 ops: set[ModelOperation]
5221 """Operations the validator applies to."""
5223 def validate(self, field: 'ModelField', feature: 'Feature', mc: ModelContext) -> bool:
5224 """Check the value of a field in a feature.
5226 Args:
5227 field: The field.
5228 feature: The feature.
5229 mc: The model context.
5231 Returns:
5232 True if the value is valid.
5233 """
5236class ModelValue(Node):
5237 """Model value.
5239 Computes a value for a field.
5240 """
5242 isDefault: bool
5243 """The value is used only when the source provides no value."""
5244 ops: set[ModelOperation]
5245 """Operations the value applies to."""
5247 def compute(self, field: 'ModelField', feature: 'Feature', mc: 'ModelContext'):
5248 """Compute the value of a field.
5250 Args:
5251 field: The field.
5252 feature: The feature.
5253 mc: The model context.
5255 Returns:
5256 The computed value.
5257 """
5260class ModelField(Node):
5261 """Model field.
5263 Handles a subset of feature data. The model calls the field methods when it performs
5264 an operation; the methods read and write ``feature.attributes``, ``feature.record``
5265 and ``feature.props``.
5266 """
5268 name: str
5269 """Field name."""
5270 title: str
5271 """Field title."""
5273 attributeType: AttributeType
5274 """Type of the field value."""
5276 widget: Optional['ModelWidget'] = None
5277 """Widget for the client."""
5279 values: list['ModelValue']
5280 """Value objects."""
5281 validators: list['ModelValidator']
5282 """Validators."""
5284 isPrimaryKey: bool
5285 """The field is a primary key."""
5286 isRequired: bool
5287 """The field must not be empty."""
5288 isUnique: bool
5289 """The field is unique."""
5290 isAuto: bool
5291 """The value is set by the database and never written."""
5292 isHidden: bool
5293 """The field is not automatically displayed in the client."""
5295 supportsFilterSearch: bool = False
5296 """The field supports filter search."""
5297 supportsGeometrySearch: bool = False
5298 """The field supports geometry search."""
5299 supportsKeywordSearch: bool = False
5300 """The field supports keyword search."""
5302 model: 'Model'
5303 """The model of the field."""
5305 def before_select(self, mc: ModelContext):
5306 """Called before features are selected, adds columns and conditions to ``mc.dbSelect``.
5308 Args:
5309 mc: The model context.
5310 """
5312 def after_select(self, features: list['Feature'], mc: ModelContext):
5313 """Called after features are selected, sets the field value in the features.
5315 Args:
5316 features: The selected features.
5317 mc: The model context.
5318 """
5320 def before_create(self, feature: 'Feature', mc: ModelContext):
5321 """Called before a feature is inserted, writes the field value to ``feature.record``.
5323 Args:
5324 feature: The feature.
5325 mc: The model context.
5326 """
5328 def after_create(self, feature: 'Feature', mc: ModelContext):
5329 """Called after a feature is inserted.
5331 Args:
5332 feature: The feature.
5333 mc: The model context.
5334 """
5336 def before_create_related(self, dst_feature: 'Feature', mc: ModelContext):
5337 """Called before a feature of another model, created together with features of this model, is inserted.
5339 Args:
5340 dst_feature: The feature being created.
5341 mc: The model context.
5342 """
5344 def after_create_related(self, dst_feature: 'Feature', mc: ModelContext):
5345 """Called after a feature of another model, created together with features of this model, is inserted.
5347 Args:
5348 dst_feature: The created feature.
5349 mc: The model context.
5350 """
5352 def before_update(self, feature: 'Feature', mc: ModelContext):
5353 """Called before a feature is updated, writes the field value to ``feature.record``.
5355 Args:
5356 feature: The feature.
5357 mc: The model context.
5358 """
5360 def after_update(self, feature: 'Feature', mc: ModelContext):
5361 """Called after a feature is updated.
5363 Args:
5364 feature: The feature.
5365 mc: The model context.
5366 """
5368 def before_delete(self, feature: 'Feature', mc: ModelContext):
5369 """Called before a feature is deleted.
5371 Args:
5372 feature: The feature.
5373 mc: The model context.
5374 """
5376 def after_delete(self, feature: 'Feature', mc: ModelContext):
5377 """Called after a feature is deleted.
5379 Args:
5380 feature: The feature.
5381 mc: The model context.
5382 """
5384 def do_init(self, feature: 'Feature', mc: ModelContext):
5385 """Set the initial field value of a new feature.
5387 Args:
5388 feature: The feature.
5389 mc: The model context.
5390 """
5392 def do_init_related(self, dst_feature: 'Feature', mc: ModelContext):
5393 """Initialize a new feature of another model that is created together with features of this model.
5395 Args:
5396 dst_feature: The new feature.
5397 mc: The model context.
5398 """
5400 def do_validate(self, feature: 'Feature', mc: ModelContext):
5401 """Validate the field value and append errors to ``feature.errors``.
5403 Args:
5404 feature: The feature.
5405 mc: The model context.
5406 """
5408 def from_props(self, feature: 'Feature', mc: ModelContext):
5409 """Set the field value from ``feature.props``.
5411 Args:
5412 feature: The feature.
5413 mc: The model context.
5414 """
5416 def to_props(self, feature: 'Feature', mc: ModelContext):
5417 """Write the field value to ``feature.props``.
5419 Args:
5420 feature: The feature.
5421 mc: The model context.
5422 """
5424 def from_record(self, feature: 'Feature', mc: ModelContext):
5425 """Set the field value from ``feature.record``.
5427 Args:
5428 feature: The feature.
5429 mc: The model context.
5430 """
5432 def to_record(self, feature: 'Feature', mc: ModelContext):
5433 """Write the field value to ``feature.record``.
5435 Args:
5436 feature: The feature.
5437 mc: The model context.
5438 """
5440 def related_models(self) -> list['Model']:
5441 """Return the models related to this field.
5443 Returns:
5444 A list of models, empty for fields that are not related fields.
5445 """
5447 def find_relatable_features(self, search: 'SearchQuery', mc: ModelContext) -> list['Feature']:
5448 """Find features that can be linked by this field.
5450 Args:
5451 search: The search query.
5452 mc: The model context.
5454 Returns:
5455 The features found in the related models.
5456 """
5458 def raw_to_python(self, feature: 'Feature', value, mc: ModelContext):
5459 """Convert a raw source value to a python value.
5461 Args:
5462 feature: The feature.
5463 value: The value to convert.
5464 mc: The model context.
5466 Returns:
5467 The converted value.
5468 """
5470 def prop_to_python(self, feature: 'Feature', value, mc: ModelContext):
5471 """Convert a client props value to a python value.
5473 Args:
5474 feature: The feature.
5475 value: The value to convert.
5476 mc: The model context.
5478 Returns:
5479 The converted value.
5480 """
5482 def python_to_raw(self, feature: 'Feature', value, mc: ModelContext):
5483 """Convert a python value to a raw source value.
5485 Args:
5486 feature: The feature.
5487 value: The value to convert.
5488 mc: The model context.
5490 Returns:
5491 The converted value.
5492 """
5494 def python_to_prop(self, feature: 'Feature', value, mc: ModelContext):
5495 """Convert a python value to a client props value.
5497 Args:
5498 feature: The feature.
5499 value: The value to convert.
5500 mc: The model context.
5502 Returns:
5503 The converted value.
5504 """
5506 def describe(self) -> Optional['ColumnDescription']:
5507 """Return the description of the source column of this field.
5509 Returns:
5510 The column description, or None if the source has no such column.
5511 """
5514class Model(Node):
5515 """Data model.
5517 Reads features from a source, converts them to and from client props and,
5518 if editable, writes them back.
5519 """
5521 clientOptions: ModelClientOptions
5522 """Client options."""
5523 defaultSort: list['SearchSort']
5524 """Default sort order of features."""
5525 fields: list['ModelField']
5526 """Model fields."""
5527 geometryCrs: Optional['Crs']
5528 """CRS of the geometry field."""
5529 geometryName: str
5530 """Name of the geometry field."""
5531 geometryType: Optional[GeometryType]
5532 """Type of the geometry field."""
5533 isEditable: bool
5534 """Features of this model can be edited."""
5535 loadingStrategy: 'FeatureLoadingStrategy'
5536 """How the client loads features."""
5537 exportStrategy: 'FeatureExportStrategy'
5538 """How features are obtained for export."""
5539 title: str
5540 """Model title."""
5541 uidName: str
5542 """Name of the uid (primary key) field."""
5543 withTableView: bool
5544 """The table view of features is enabled in the client."""
5546 def find_features(self, search: 'SearchQuery', mc: ModelContext) -> list['Feature']:
5547 """Find features matching a search query.
5549 Args:
5550 search: The search query.
5551 mc: The model context.
5553 Returns:
5554 The features found.
5555 """
5557 def get_features(self, uids: Iterable[str | int], mc: ModelContext) -> list['Feature']:
5558 """Return features by uid.
5560 Args:
5561 uids: Feature uids.
5562 mc: The model context.
5564 Returns:
5565 The features found, empty if no uids are given.
5566 """
5568 def get_feature(self, uid: str | int, mc: ModelContext) -> Optional['Feature']:
5569 """Return a feature by uid.
5571 Args:
5572 uid: The feature uid.
5573 mc: The model context.
5575 Returns:
5576 The feature, or None if it is not found.
5577 """
5579 def init_feature(self, feature: 'Feature', mc: ModelContext):
5580 """Initialize a new feature with initial field values.
5582 Args:
5583 feature: The new feature.
5584 mc: The model context.
5586 Raises:
5587 gws.ForbiddenError: If the user cannot create features of this model.
5588 """
5590 def create_feature(self, feature: 'Feature', mc: ModelContext) -> FeatureUid:
5591 """Insert a new feature into the source.
5593 Args:
5594 feature: The feature.
5595 mc: The model context.
5597 Returns:
5598 The primary key of the inserted feature.
5600 Raises:
5601 gws.ForbiddenError: If the user cannot create features of this model.
5602 """
5604 def update_feature(self, feature: 'Feature', mc: ModelContext) -> FeatureUid:
5605 """Update an existing feature in the source.
5607 Args:
5608 feature: The feature.
5609 mc: The model context.
5611 Returns:
5612 The uid of the feature.
5614 Raises:
5615 gws.ForbiddenError: If the user cannot write to this model.
5616 """
5618 def delete_feature(self, feature: 'Feature', mc: ModelContext) -> FeatureUid:
5619 """Delete a feature from the source.
5621 Args:
5622 feature: The feature.
5623 mc: The model context.
5625 Returns:
5626 The uid of the feature.
5628 Raises:
5629 gws.ForbiddenError: If the user cannot delete features of this model.
5630 """
5632 def validate_feature(self, feature: 'Feature', mc: ModelContext) -> bool:
5633 """Validate a feature and store validation errors in ``feature.errors``.
5635 Args:
5636 feature: The feature.
5637 mc: The model context.
5639 Returns:
5640 True if the feature has no errors.
5641 """
5643 def feature_from_props(self, props: 'FeatureProps', mc: ModelContext) -> 'Feature':
5644 """Create a feature from client props.
5646 Args:
5647 props: The feature props.
5648 mc: The model context.
5650 Returns:
5651 A new feature.
5652 """
5654 def feature_to_props(self, feature: 'Feature', mc: ModelContext) -> 'FeatureProps':
5655 """Convert a feature to client props and store them in ``feature.props``.
5657 Args:
5658 feature: The feature.
5659 mc: The model context.
5661 Returns:
5662 The feature props.
5663 """
5665 def feature_to_view_props(self, feature: 'Feature', mc: ModelContext) -> 'FeatureProps':
5666 """Convert a feature to client props for viewing, with a reduced set of attributes.
5668 Args:
5669 feature: The feature.
5670 mc: The model context.
5672 Returns:
5673 The feature props.
5674 """
5676 def describe(self) -> Optional['DataSetDescription']:
5677 """Return the description of the model source.
5679 Returns:
5680 The dataset description, or None if the source cannot be described.
5681 """
5683 def field(self, name: str) -> Optional['ModelField']:
5684 """Return a field by name.
5686 Args:
5687 name: The field name.
5689 Returns:
5690 The field, or None if it is not found.
5691 """
5693 def related_models(self) -> list['Model']:
5694 """Return the models related to the fields of this model.
5696 Returns:
5697 A list of models without duplicates.
5698 """
5701class ModelManager(Node):
5702 """Model manager.
5704 Looks up models and provides the default model.
5705 """
5707 def get_model(self, uid: str, user: 'User' = None, access: Access = None) -> Optional['Model']:
5708 """Return a model by uid.
5710 Args:
5711 uid: The model uid.
5712 user: If given together with ``access``, the user must have this access to the model.
5713 access: The required access.
5715 Returns:
5716 The model, or None if it is not found or not accessible.
5717 """
5719 def find_model(self, *objects, user: 'User' = None, access: Access = None) -> Optional['Model']:
5720 """Return the first model of the given objects.
5722 Looks in the ``models`` attribute of each object in turn.
5724 Args:
5725 *objects: Objects with models, e.g. layers. None values are skipped.
5726 user: If given together with ``access``, the user must have this access to the model.
5727 access: The required access.
5729 Returns:
5730 The model, or None if none is found.
5731 """
5733 def editable_models(self, project: 'Project', user: 'User') -> list['Model']:
5734 """Return the models a user can edit in a project, together with their related models.
5736 Args:
5737 project: The project.
5738 user: The user.
5740 Returns:
5741 The models, sorted by title.
5742 """
5744 def default_model(self) -> 'Model':
5745 """Return the shared default model.
5747 Returns:
5748 The default model.
5749 """
5750################################################################################
5753################################################################################
5754# /base/database/types.pyinc
5757class DatabaseModel(Model):
5758 """Data model for a database table."""
5760 db: 'DatabaseProvider'
5761 """Database provider."""
5762 sqlFilter: str
5763 """Literal SQL condition applied when selecting rows."""
5764 tableName: str
5765 """Table name associated with this model."""
5767 def table(self) -> 'sqlalchemy.Table':
5768 """Return the SQLAlchemy ``Table`` object of the model table.
5770 Returns:
5771 The table object.
5773 Raises:
5774 ``sqlalchemy.exc.SQLAlchemyError``: If the table does not exist.
5775 """
5777 def column(self, column_name: str) -> 'sqlalchemy.Column':
5778 """Return the SQLAlchemy ``Column`` object of a column in the model table.
5780 Args:
5781 column_name: Column name.
5783 Returns:
5784 The column object.
5786 Raises:
5787 ``sqlalchemy.exc.SQLAlchemyError``: If the table or the column does not exist.
5788 """
5790 def uid_column(self) -> 'sqlalchemy.Column':
5791 """Return the SQLAlchemy ``Column`` object of the primary key column.
5793 Returns:
5794 The column object for ``uidName``.
5796 Raises:
5797 ``gws.Error``: If the model has no primary key or the key column does not exist.
5798 """
5800 def uid_equals(self, uid: FeatureUid | Iterable[FeatureUid]) -> 'sqlalchemy.ColumnElement[bool]':
5801 """Return a condition that matches features by uid.
5803 The values are bound with the type of the primary key column, so that
5804 string uids can be compared with columns of other types.
5806 Args:
5807 uid: A feature uid, or an iterable of uids.
5809 Returns:
5810 An ``=`` condition for a single uid, an ``IN`` condition for an iterable.
5812 Raises:
5813 ``gws.Error``: If the model has no primary key or the key column does not exist.
5814 """
5816 def fetch_features(self, select: 'sqlalchemy.Select') -> list['Feature']:
5817 """Run a SELECT statement and create a feature for each row.
5819 The row values become the attributes of the feature record.
5821 Args:
5822 select: SELECT statement.
5824 Returns:
5825 A list of features.
5826 """
5828 def build_select(self, mc: 'ModelContext') -> Optional['sqlalchemy.Select']:
5829 """Build a SELECT statement for a search.
5831 Combines the search query in ``mc.search``, the columns and conditions
5832 collected by the fields in ``mc.dbSelect`` and ``sqlFilter``.
5834 Args:
5835 mc: Model context with ``search`` and ``dbSelect`` set.
5837 Returns:
5838 The SELECT statement, or ``None`` if the search cannot match anything.
5839 """
5842class ColumnDescription(Data):
5843 """Description of a dataset column."""
5845 columnIndex: int
5846 """The index of the column within the table."""
5847 comment: str
5848 """Column comment or description provided in the database metadata."""
5849 default: str
5850 """The default value assigned to the column, if any."""
5851 geometrySrid: int
5852 """The Spatial Reference Identifier (SRID) for geometry columns."""
5853 geometryType: GeometryType
5854 """The type of geometry stored in the column (e.g., Point, Polygon)."""
5855 isAutoincrement: bool
5856 """Indicates if the column is auto-incremented."""
5857 isNullable: bool
5858 """Specifies if the column permits NULL values."""
5859 isPrimaryKey: bool
5860 """Specifies if the column is part of the primary key."""
5861 isUnique: bool
5862 """Indicates if the column has a unique constraint."""
5863 hasDefault: bool
5864 """Indicates if the column has a database-defined default value."""
5865 isIndexed: bool
5866 """Indicates if the column has an index."""
5867 name: str
5868 """The name of the column."""
5869 nativeType: str
5870 """The database-specific data type of the column."""
5871 options: dict
5872 """Additional options or configurations for the column, if any."""
5873 type: AttributeType
5874 """The abstract type of the column used in higher-level processing."""
5877class DataSetDescription(Data):
5878 """Description of a dataset, like a DB table or a GDAL data set."""
5880 columns: list[ColumnDescription]
5881 """A list of column descriptions."""
5882 columnMap: dict[str, ColumnDescription]
5883 """A dictionary mapping column names to their descriptions."""
5884 fullName: str
5885 """The full name of the dataset, including schema if applicable."""
5886 geometryName: str
5887 """The name of the geometry column, if any."""
5888 geometrySrid: int
5889 """The Spatial Reference Identifier (SRID) for the geometry."""
5890 geometryType: GeometryType
5891 """The type of geometry stored in the dataset."""
5892 name: str
5893 """The name of the dataset or table."""
5894 schema: str
5895 """The schema to which the dataset belongs."""
5898class DatabaseManager(Node):
5899 """Database manager."""
5901 providers: list['DatabaseProvider']
5902 """A list of database providers managed by this DatabaseManager."""
5904 def create_provider(self, cfg: Config, **kwargs) -> 'DatabaseProvider':
5905 """Create a database provider and add it to ``providers``.
5907 The provider is created as a shared object. A provider with the same uid
5908 that is already in ``providers`` is replaced.
5910 Args:
5911 cfg: Provider configuration.
5912 **kwargs: Extra configuration values.
5914 Returns:
5915 The provider.
5916 """
5918 def find_provider(self, uid: Optional[str] = None, ext_type: Optional[str] = None) -> Optional['DatabaseProvider']:
5919 """Find a database provider by uid or type.
5921 With ``uid``, returns the provider with this uid (and of type ``ext_type``,
5922 if given). With ``ext_type`` only, returns the first provider of this type.
5923 Without arguments, returns the first provider.
5925 Args:
5926 uid: Provider uid.
5927 ext_type: Provider type, e.g. ``postgres``.
5929 Returns:
5930 The provider, or ``None`` if none matches.
5931 """
5934DatabaseTableAlike: TypeAlias = Union['sqlalchemy.Table', str]
5935"""An SQLAlchemy ``Table`` object or a string table name."""
5938DatabaseStmt: TypeAlias = Union['sqlalchemy.Executable', str]
5939"""An Executable SQLAlchemy object or a string SQL statement."""
5942class DatabaseConnection:
5943 """Database connection.
5945 Wraps an SQLAlchemy ``Connection`` and provides some convenience methods.
5946 Returned by ``DatabaseProvider.connect`` and used as a context manager,
5947 which closes the connection on exit.
5949 Statements can be SQLAlchemy objects or SQL strings with ``:name`` bind
5950 parameters. The ``fetch_*`` methods roll back the transaction after reading.
5951 """
5953 saConn: 'sqlalchemy.Connection'
5954 """The underlying SQLAlchemy connection."""
5956 def __enter__(self) -> 'DatabaseConnection': ...
5958 def __exit__(self, exc_type, exc_value, traceback): ...
5960 def execute(self, stmt: 'sqlalchemy.Executable', params=None, execution_options: dict=None) -> 'sqlalchemy.CursorResult':
5961 """Execute an SQLAlchemy statement.
5963 Args:
5964 stmt: Statement.
5965 params: Bind parameters, a dict or a list of dicts.
5966 execution_options: SQLAlchemy execution options.
5968 Returns:
5969 The result.
5970 """
5972 def commit(self):
5973 """Commit the current transaction."""
5975 def rollback(self):
5976 """Roll back the current transaction."""
5978 def close(self):
5979 """Close the connection.
5981 The connection is shared by nested ``connect`` calls, and only the
5982 outermost ``close`` closes the SQLAlchemy connection.
5983 """
5985 def exec(self, stmt: 'DatabaseStmt', **params) -> 'sqlalchemy.CursorResult':
5986 """Execute a statement.
5988 Args:
5989 stmt: Statement or SQL string.
5990 **params: Bind parameters.
5992 Returns:
5993 The result.
5994 """
5996 def exec_commit(self, stmt: 'DatabaseStmt', **params) -> 'sqlalchemy.CursorResult':
5997 """Execute a statement and commit, or roll back on error.
5999 Args:
6000 stmt: Statement or SQL string.
6001 **params: Bind parameters.
6003 Returns:
6004 The result.
6006 Raises:
6007 ``Exception``: Any error from the execution is re-raised after the rollback.
6008 """
6010 def exec_rollback(self, stmt: 'DatabaseStmt', **params) -> 'sqlalchemy.CursorResult':
6011 """Execute a statement and roll back afterwards.
6013 Args:
6014 stmt: Statement or SQL string.
6015 **params: Bind parameters.
6017 Returns:
6018 The result.
6019 """
6021 def fetch_all(self, stmt: 'DatabaseStmt', **params) -> list[dict]:
6022 """Execute a statement and return all rows.
6024 Args:
6025 stmt: Statement or SQL string.
6026 **params: Bind parameters.
6028 Returns:
6029 A list of rows as dicts.
6030 """
6032 def fetch_first(self, stmt: 'DatabaseStmt', **params) -> dict | None:
6033 """Execute a statement and return the first row.
6035 Args:
6036 stmt: Statement or SQL string.
6037 **params: Bind parameters.
6039 Returns:
6040 The first row as a dict, or ``None`` if there are no rows.
6041 """
6043 def fetch_scalars(self, stmt: 'DatabaseStmt', **params) -> list:
6044 """Execute a statement and return the first column of all rows.
6046 Args:
6047 stmt: Statement or SQL string.
6048 **params: Bind parameters.
6050 Returns:
6051 A list of values.
6052 """
6054 def fetch_strings(self, stmt: 'DatabaseStmt', **params) -> list[str]:
6055 """Execute a statement and return the first column of all rows as strings.
6057 Args:
6058 stmt: Statement or SQL string.
6059 **params: Bind parameters.
6061 Returns:
6062 A list of strings, with ``NULL`` values as empty strings.
6063 """
6065 def fetch_ints(self, stmt: 'DatabaseStmt', **params) -> list[int]:
6066 """Execute a statement and return the first column of all rows as integers.
6068 Args:
6069 stmt: Statement or SQL string.
6070 **params: Bind parameters.
6072 Returns:
6073 A list of integers.
6075 Raises:
6076 ``ValueError``: If a value is not an integer.
6077 """
6079 def fetch_scalar(self, stmt: 'DatabaseStmt', **params) -> Any:
6080 """Execute a statement and return the first column of the first row.
6082 Args:
6083 stmt: Statement or SQL string.
6084 **params: Bind parameters.
6086 Returns:
6087 The value, or ``None`` if there are no rows.
6088 """
6090 def fetch_string(self, stmt: 'DatabaseStmt', **params) -> str | None:
6091 """Execute a statement and return the first column of the first row as a string.
6093 Args:
6094 stmt: Statement or SQL string.
6095 **params: Bind parameters.
6097 Returns:
6098 The string, or ``None`` if there are no rows or the value is ``NULL``.
6099 """
6101 def fetch_int(self, stmt: 'DatabaseStmt', **params) -> int | None:
6102 """Execute a statement and return the first column of the first row as an integer.
6104 Args:
6105 stmt: Statement or SQL string.
6106 **params: Bind parameters.
6108 Returns:
6109 The integer, or ``None`` if there are no rows or the value is ``NULL``.
6111 Raises:
6112 ``ValueError``: If the value is not an integer.
6113 """
6115class DatabaseInspectOptions(Data):
6116 """Options for database inspection."""
6118 refresh: bool = False
6119 """Whether to force inspection even if cached information is available."""
6120 cacheLifeTime: int = 0
6121 """Schema cache lifetime in seconds."""
6124class DatabaseProvider(Node):
6125 """Database provider.
6127 Wraps an SQLAlchemy ``Engine`` and hands out connections. Also reflects
6128 table structures and describes tables and columns.
6129 """
6131 def connect(self) -> 'DatabaseConnection':
6132 """Open a connection, to be used as a context manager.
6134 Calls can be nested. An inner call does not open a new connection, but
6135 returns a wrapper around the open one. Only the outermost connection is
6136 closed upon exit::
6138 with db.connect():
6139 ...
6140 with db.connect(): # no-op
6141 ...
6142 # connection remains open
6143 ...
6144 # connection closed
6146 Returns:
6147 The connection.
6148 """
6150 def engine_options(self, **kwargs):
6151 """Add defaults to the SQLAlchemy engine options.
6153 Args:
6154 **kwargs: Engine options. Options passed here take precedence over the defaults.
6156 Returns:
6157 The options dict.
6158 """
6160 def url(self) -> str:
6161 """Return the connection URL.
6163 Returns:
6164 An SQLAlchemy connection URL.
6165 """
6167 def engine(self) -> 'sqlalchemy.Engine':
6168 """Return the SQLAlchemy ``Engine`` object for this provider, creating it if needed.
6170 Returns:
6171 The engine.
6172 """
6174 def create_engine(self, **kwargs) -> 'sqlalchemy.Engine':
6175 """Create a new SQLAlchemy ``Engine`` object for this provider.
6177 Args:
6178 **kwargs: Engine options, see ``engine_options``.
6180 Returns:
6181 The engine.
6182 """
6184 def describe(self, table: DatabaseTableAlike) -> 'DataSetDescription':
6185 """Describe a table.
6187 Args:
6188 table: Table object or table name.
6190 Returns:
6191 The table description. The first geometry column becomes the primary geometry.
6193 Raises:
6194 ``sqlalchemy.exc.SQLAlchemyError``: If the table does not exist.
6195 """
6197 def describe_column(self, table: DatabaseTableAlike, column_name: str) -> ColumnDescription:
6198 """Describe a column in a table.
6200 Args:
6201 table: Table object or table name.
6202 column_name: Column name.
6204 Returns:
6205 The column description.
6207 Raises:
6208 ``sqlalchemy.exc.SQLAlchemyError``: If the table or the column does not exist.
6209 """
6211 def table(self, table: 'DatabaseTableAlike', **kwargs) -> 'sqlalchemy.Table':
6212 """Return the SQLAlchemy ``Table`` object for a table.
6214 Args:
6215 table: Table object or table name.
6216 **kwargs: Not used by the base provider.
6218 Returns:
6219 The table object.
6221 Raises:
6222 ``sqlalchemy.exc.SQLAlchemyError``: If the table does not exist.
6223 """
6225 def column(self, table: DatabaseTableAlike, column_name: str) -> 'sqlalchemy.Column':
6226 """Return the SQLAlchemy ``Column`` object for a column.
6228 Args:
6229 table: Table object or table name.
6230 column_name: Column name.
6232 Returns:
6233 The column object.
6235 Raises:
6236 ``sqlalchemy.exc.SQLAlchemyError``: If the table or the column does not exist.
6237 """
6239 def count(self, table: DatabaseTableAlike) -> int:
6240 """Return the number of rows in a table.
6242 Args:
6243 table: Table object or table name.
6245 Returns:
6246 The row count, or 0 if the table does not exist.
6247 """
6249 def has_schema(self, schema_name: str) -> bool:
6250 """Check if a schema exists.
6252 Args:
6253 schema_name: Schema name.
6255 Returns:
6256 ``True`` if the schema exists.
6257 """
6259 def has_table(self, table_name: str) -> bool:
6260 """Check if a table exists.
6262 Args:
6263 table_name: Table name, optionally schema-qualified.
6265 Returns:
6266 ``True`` if the table exists.
6267 """
6269 def has_column(self, table: DatabaseTableAlike, column_name: str) -> bool:
6270 """Check if a column exists.
6272 Args:
6273 table: Table object or table name.
6274 column_name: Column name.
6276 Returns:
6277 ``True`` if the table and the column exist.
6278 """
6280 def join_table_name(self, schema: str, name: str) -> str:
6281 """Create a full table name from the schema and table names.
6283 Args:
6284 schema: Schema name. If empty, the default schema is used.
6285 name: Table name.
6287 Returns:
6288 The schema-qualified table name.
6289 """
6291 def split_table_name(self, table_name: str) -> tuple[str, str]:
6292 """Split a full table name into the schema and table names.
6294 Args:
6295 table_name: Table name, optionally schema-qualified.
6297 Returns:
6298 A tuple of the schema name (the default schema if none is given) and the table name.
6299 """
6301 def table_bounds(self, table: DatabaseTableAlike) -> Optional[Bounds]:
6302 """Compute the bounding box of the primary geometry of a table.
6304 Args:
6305 table: Table object or table name.
6307 Returns:
6308 The bounds, or ``None`` if the table has no geometry or no data.
6309 """
6311 def select_text(self, sql: str, **kwargs) -> list[dict]:
6312 """Execute a textual SELECT statement.
6314 Args:
6315 sql: SQL statement with ``:name`` bind parameters.
6316 **kwargs: Bind parameters.
6318 Returns:
6319 A list of rows as dicts.
6321 Raises:
6322 ``sqlalchemy.exc.SQLAlchemyError``: On database errors, after a rollback.
6323 """
6325 def execute_text(self, sql: str, **kwargs) -> 'sqlalchemy.CursorResult':
6326 """Execute a textual statement and commit.
6328 Args:
6329 sql: SQL statement with ``:name`` bind parameters.
6330 **kwargs: Bind parameters.
6332 Returns:
6333 The result.
6335 Raises:
6336 ``sqlalchemy.exc.SQLAlchemyError``: On database errors, after a rollback.
6337 """
6339 def schema_names(self) -> list[str]:
6340 """Return the names of the schemas in the database.
6342 Returns:
6343 A list of schema names.
6344 """
6346 def inspect_schema(self, schema: str, options: Optional[DatabaseInspectOptions] = None):
6347 """Reflect the tables of a schema and keep the result.
6349 A schema that has already been reflected is not reflected again, unless
6350 ``options.refresh`` is set. The reflected metadata is cached for the
6351 configured schema cache lifetime. If ``options`` are given, their
6352 ``cacheLifeTime`` is used instead; 0 means no caching.
6354 Args:
6355 schema: Schema name.
6356 options: Inspection options.
6357 """
6358################################################################################
6362################################################################################
6363# /base/job/types.pyinc
6366class JobTerminated(Exception):
6367 """Raised in a worker when its job is no longer running, e.g. because it was cancelled."""
6369 pass
6372class JobState(Enum):
6373 """Background job state."""
6375 init = 'init'
6376 """The job is being created."""
6377 open = 'open'
6378 """The job is just created and waiting for start."""
6379 running = 'running'
6380 """The job is running."""
6381 complete = 'complete'
6382 """The job has been completed successfully."""
6383 error = 'error'
6384 """There was an error."""
6385 cancel = 'cancel'
6386 """The job was cancelled."""
6389class Job(Data):
6390 """Background job data."""
6392 uid: str
6393 """Job uid."""
6394 user: 'User'
6395 """User who created the job."""
6396 worker: str
6397 """Worker class, as ``<module path>:<class name>``."""
6398 state: JobState
6399 """Job state."""
6400 error: str
6401 """Error message, if the job failed."""
6402 numSteps: int
6403 """Total number of steps, for progress reporting."""
6404 step: int
6405 """Current step."""
6406 stepName: str
6407 """Name of the current step."""
6408 payload: dict
6409 """Input data for the worker."""
6410 result: dict
6411 """Result data from the worker."""
6412 timeCreated: datetime.datetime
6413 """Creation time."""
6414 timeUpdated: datetime.datetime
6415 """Time of the last update."""
6418class JobRequest(Request):
6419 """Request that refers to a job."""
6421 jobUid: str
6422 """Job uid."""
6425class JobStatusResponse(Response):
6426 """Job status."""
6428 jobUid: str
6429 """Job uid."""
6430 state: JobState
6431 """Job state."""
6432 progress: int
6433 """Progress in percent."""
6434 stepName: str
6435 """Name of the current step."""
6436 output: dict
6437 """Job-specific output, e.g. a download URL when the job is complete."""
6440class JobManager(Node):
6441 """Job manager."""
6443 def create_job(self, worker: type, user: User, payload: dict | Data = None) -> Job:
6444 """Create a job in the ``open`` state.
6446 Args:
6447 worker: Worker class. It must have a ``run(root, job)`` class method.
6448 user: User the job runs for.
6449 payload: Input data for the worker, must be JSON-serializable.
6451 Returns:
6452 The new job.
6453 """
6455 def get_job(self, job_uid: str, user: User = None, state: JobState = None) -> Optional[Job]:
6456 """Read a job.
6458 Args:
6459 job_uid: Job uid.
6460 user: If given, the job must belong to this user.
6461 state: If given, the job must be in this state.
6463 Returns:
6464 The job, or ``None`` if it does not exist or does not match. The reason is logged.
6465 """
6467 def update_job(self, job: Job, **kwargs) -> Optional[Job]:
6468 """Update fields of a job.
6470 Args:
6471 job: The job.
6472 **kwargs: Job fields to update.
6474 Returns:
6475 The updated job, or ``None`` if the job does not exist.
6476 """
6478 def run_job(self, job: Job) -> Optional[Job]:
6479 """Run an open job in the current process.
6481 Marks the job as running, so that it runs only once, and calls the
6482 ``run`` method of its worker. If the worker raises an exception, the
6483 job goes into the ``error`` state.
6485 Args:
6486 job: The job.
6488 Returns:
6489 The job after the run.
6491 Raises:
6492 ``gws.Error``: If the job is not open or is already taken by another process.
6493 """
6495 def cancel_job(self, job: Job) -> Optional[Job]:
6496 """Set a job to the ``cancel`` state.
6498 The worker notices the change on its next job update and stops.
6500 Args:
6501 job: The job.
6503 Returns:
6504 The updated job, or ``None`` if the job does not exist.
6505 """
6507 def remove_job(self, job: Job):
6508 """Delete a job record.
6510 Args:
6511 job: The job.
6512 """
6514 def schedule_job(self, job: Job) -> Job:
6515 """Start an open job.
6517 The job is passed to the uWSGI spooler if it is available, otherwise it
6518 runs at once in the current process.
6520 Args:
6521 job: The job.
6523 Returns:
6524 The job.
6526 Raises:
6527 ``gws.Error``: If the job is not open.
6528 """
6530 def require_job(self, req: 'WebRequester', p: JobRequest) -> Job:
6531 """Return the job of a request, if it belongs to the requesting user.
6533 Args:
6534 req: Web request.
6535 p: Job request.
6537 Returns:
6538 The job.
6540 Raises:
6541 ``gws.NotFoundError``: If the job does not exist or belongs to another user.
6542 """
6544 def require_result(self, req: 'WebRequester', p: JobRequest) -> dict:
6545 """Return the result of a completed job of the requesting user.
6547 Args:
6548 req: Web request.
6549 p: Job request.
6551 Returns:
6552 The job result.
6554 Raises:
6555 ``gws.NotFoundError``: If the job does not exist, belongs to another user,
6556 is not complete or has no result.
6557 """
6559 def handle_status_request(self, req: 'WebRequester', p: JobRequest) -> JobStatusResponse:
6560 """Return the status of a job of the requesting user.
6562 Args:
6563 req: Web request.
6564 p: Job request.
6566 Returns:
6567 The job status.
6569 Raises:
6570 ``gws.NotFoundError``: If the job does not exist or belongs to another user.
6571 """
6573 def handle_cancel_request(self, req: 'WebRequester', p: JobRequest) -> JobStatusResponse:
6574 """Cancel a job of the requesting user.
6576 Args:
6577 req: Web request.
6578 p: Job request.
6580 Returns:
6581 The job status after cancelling.
6583 Raises:
6584 ``gws.NotFoundError``: If the job does not exist or belongs to another user.
6585 """
6587 def job_status_response(self, job: Job, **kwargs) -> 'JobStatusResponse':
6588 """Create a status response for a job.
6590 Args:
6591 job: The job.
6592 **kwargs: Extra or overriding response fields.
6594 Returns:
6595 The status response.
6596 """
6597################################################################################
6600################################################################################
6601# /base/ows/types.pyinc
6604import gws
6607class OwsProtocol(Enum):
6608 """Supported OWS protocols."""
6610 WMS = 'WMS'
6611 WMTS = 'WMTS'
6612 WCS = 'WCS'
6613 WFS = 'WFS'
6614 CSW = 'CSW'
6617class OwsAuthorization(Data):
6618 """Credentials for accessing an OWS service."""
6620 type: str
6621 """Authorization type, only ``basic`` is supported."""
6622 username: str
6623 """User name."""
6624 password: str
6625 """Password."""
6628class OwsVerb(Enum):
6629 """OWS request type."""
6631 CreateStoredQuery = 'CreateStoredQuery'
6632 DescribeCoverage = 'DescribeCoverage'
6633 DescribeFeatureType = 'DescribeFeatureType'
6634 DescribeLayer = 'DescribeLayer'
6635 DescribeRecord = 'DescribeRecord'
6636 DescribeStoredQueries = 'DescribeStoredQueries'
6637 DropStoredQuery = 'DropStoredQuery'
6638 GetCapabilities = 'GetCapabilities'
6639 GetFeature = 'GetFeature'
6640 GetFeatureInfo = 'GetFeatureInfo'
6641 GetFeatureWithLock = 'GetFeatureWithLock'
6642 GetLegendGraphic = 'GetLegendGraphic'
6643 GetMap = 'GetMap'
6644 GetPrint = 'GetPrint'
6645 GetPropertyValue = 'GetPropertyValue'
6646 GetRecordById = 'GetRecordById'
6647 GetRecords = 'GetRecords'
6648 GetTile = 'GetTile'
6649 ListStoredQueries = 'ListStoredQueries'
6650 LockFeature = 'LockFeature'
6651 Transaction = 'Transaction'
6654class OwsOperation(Data):
6655 """OWS operation, as offered by a remote service or by our own service."""
6657 allowedParameters: dict[str, list[str]]
6658 """Allowed values for parameters, keyed by the upper-cased parameter name."""
6659 constraints: dict[str, list[str]]
6660 """Operation constraints."""
6661 formats: list[str]
6662 """Supported output formats."""
6663 handlerName: str
6664 """Name of the service method that handles this operation (server side)."""
6665 params: dict[str, str]
6666 """Extra parameters for GET requests (client side)."""
6667 postUrl: Url
6668 """URL for POST requests."""
6669 preferredFormat: str
6670 """Output format to use in requests (client side)."""
6671 url: Url
6672 """URL for GET requests."""
6673 verb: OwsVerb
6674 """Request type."""
6677class OwsCapabilities(Data):
6678 """Parsed capabilities of a remote OWS service."""
6680 metadata: 'Metadata'
6681 """Service metadata."""
6682 operations: list['OwsOperation']
6683 """Operations offered by the service."""
6684 sourceLayers: list['SourceLayer']
6685 """Layers or feature types of the service."""
6686 tileMatrixSets: list['TileMatrixSet']
6687 """Tile matrix sets (WMTS)."""
6688 version: str
6689 """Service version."""
6692class OwsService(Node):
6693 """OWS service provided by GBD WebSuite."""
6695 isRasterService: bool = False
6696 """Service provides raster services."""
6697 isVectorService: bool = False
6698 """Service provides vector services."""
6699 isOwsCommon: bool = False
6700 """Conforms to OGC Web Services Common Standard."""
6702 alwaysXY: bool
6703 """Force lon/lat order for geographic projections."""
6704 metadata: 'Metadata'
6705 """Service metadata."""
6706 name: str
6707 """Service name."""
6708 project: Optional['Project']
6709 """Project this service is configured for."""
6710 rootLayer: Optional['Layer']
6711 """Root layer of the service."""
6712 protocol: OwsProtocol
6713 """Supported protocol."""
6714 defaultFeatureCount: int
6715 """Default limit of features per page."""
6716 maxFeatureCount: int
6717 """Max limit of features per page."""
6718 searchTolerance: UomValue
6719 """Default tolerance for spatial search."""
6720 supportedBounds: list[Bounds]
6721 """Supported bounds."""
6722 supportedVersions: list[str]
6723 """Supported versions."""
6724 supportedOperations: list['OwsOperation']
6725 """Supported operations."""
6726 templates: list['Template']
6727 """Service templates."""
6728 imageFormats: list[ImageFormat]
6729 """Supported image formats."""
6730 updateSequence: str
6731 """Service update sequence."""
6732 withInspireMeta: bool
6733 """Include INSPIRE metadata."""
6734 withStrictParams: bool
6735 """Strict parameter checking."""
6737 def handle_request(self, req: 'WebRequester') -> ContentResponse:
6738 """Handle a service request.
6740 Errors are returned as OWS exception documents, not raised.
6742 Args:
6743 req: Web request.
6745 Returns:
6746 The service response.
6747 """
6749 def layer_is_compatible(self, layer: 'Layer') -> bool:
6750 """Check if a layer can be used in this service.
6752 Args:
6753 layer: Layer object.
6755 Returns:
6756 ``True`` if the layer can be published by this service.
6757 """
6760class OwsServiceProvider(Node):
6761 """Remote OWS service used as a data provider."""
6763 alwaysXY: bool
6764 """Force XY axis order for CRSs with lat/lon axis order."""
6765 authorization: Optional['OwsAuthorization']
6766 """Credentials for the service."""
6767 bounds: Optional[Bounds]
6768 """Service bounds, if known."""
6769 forceCrs: 'Crs'
6770 """CRS to use for requests, if configured."""
6771 maxRequests: int
6772 """Max. number of concurrent requests to the service."""
6773 metadata: 'Metadata'
6774 """Service metadata."""
6775 operations: list['OwsOperation']
6776 """Operations offered by the service."""
6777 protocol: 'OwsProtocol'
6778 """Service protocol."""
6779 sourceLayers: list['SourceLayer']
6780 """Layers or feature types of the service."""
6781 url: Url
6782 """Service URL."""
6783 version: str
6784 """Service version."""
6785 wgsExtent: Optional[Extent]
6786 """Service extent in WGS84, if known."""
6788 def get_operation(self, verb: 'OwsVerb', method: Optional['RequestMethod'] = None) -> Optional['OwsOperation']:
6789 """Find an operation by its verb.
6791 Args:
6792 verb: Request type.
6793 method: Request method. For ``POST``, the operation must have a POST URL,
6794 otherwise a GET URL.
6796 Returns:
6797 The operation, or ``None`` if the service does not support it.
6798 """
6800 def get_features(self, args: 'SearchQuery', source_layers: list['SourceLayer']) -> list['FeatureRecord']:
6801 """Search for features in the given source layers.
6803 Args:
6804 args: Search query.
6805 source_layers: Source layers to search.
6807 Returns:
6808 Found feature records.
6809 """
6810################################################################################
6813################################################################################
6814# /base/printer/types.pyinc
6817class PrintPlaneType(Enum):
6818 """Print plane type."""
6820 bitmap = 'bitmap'
6821 """Raw bitmap data."""
6822 url = 'url'
6823 """Image given as a data URL."""
6824 features = 'features'
6825 """Features sent by the client."""
6826 raster = 'raster'
6827 """Raster layer."""
6828 vector = 'vector'
6829 """Vector layer, rendered as SVG."""
6830 soup = 'soup'
6831 """SVG soup: points and SVG tags."""
6834class PrintPlane(Data):
6835 """Print plane, a single map layer in a print request."""
6837 type: PrintPlaneType
6838 """Plane type."""
6840 opacity: Optional[float]
6841 """Plane opacity, from 0 to 1."""
6842 cssSelector: Optional[str]
6843 """CSS selector of the style for vector layers and features."""
6845 bitmapData: Optional[bytes]
6846 """Raw pixel data, for bitmap planes."""
6847 bitmapMode: Optional[str]
6848 """Pixel mode of the bitmap, ``RGBA`` or ``RGB``."""
6849 bitmapWidth: Optional[int]
6850 """Bitmap width in pixels."""
6851 bitmapHeight: Optional[int]
6852 """Bitmap height in pixels."""
6854 url: Optional[str]
6855 """Data URL of the image, for url planes."""
6857 features: Optional[list['FeatureProps']]
6858 """Features, for features planes."""
6860 layerUid: Optional[str]
6861 """Layer uid, for raster and vector planes."""
6862 compositeLayerUids: Optional[list[str]]
6863 """Uids of the sub-layers to render, for composite raster layers."""
6865 soupPoints: Optional[list[Point]]
6866 """Points, for soup planes."""
6867 soupTags: Optional[list[Any]]
6868 """SVG tags, for soup planes."""
6871class PrintMap(Data):
6872 """Map properties for printing."""
6874 backgroundColor: Optional[int]
6875 """Background color."""
6876 bbox: Optional[Extent]
6877 """Map extent."""
6878 center: Optional[Point]
6879 """Map center."""
6880 planes: list[PrintPlane]
6881 """Map planes."""
6882 rotation: Optional[int]
6883 """Map rotation in degrees."""
6884 scale: int
6885 """Map scale denominator."""
6886 styles: Optional[list['StyleProps']]
6887 """Styles used by the planes."""
6888 visibleLayers: Optional[list[str]]
6889 """Uids of the visible layers."""
6892class PrintRequestType(Enum):
6893 """Type of the print request."""
6895 template = 'template'
6896 map = 'map'
6899class PrintRequest(Request):
6900 """Print request."""
6902 type: PrintRequestType
6903 """Request type."""
6905 args: Optional[dict]
6906 """Template arguments."""
6907 crs: Optional[CrsName]
6908 """CRS of the maps, the project CRS by default."""
6909 outputFormat: Optional[str]
6910 """Output format, ``pdf`` (default) or ``png``, or the mime type."""
6911 maps: Optional[list[PrintMap]]
6912 """Maps to print."""
6914 printerUid: Optional[str]
6915 """Printer uid, for template requests."""
6916 dpi: Optional[int]
6917 """Output resolution."""
6918 outputSize: Optional[Size]
6919 """Output size in screen pixels, for map requests."""
6922class PrintResult(Data):
6923 """Print result."""
6925 path: str
6926 """Path of the output file."""
6927 mimeType: str
6928 """Mime type of the output file."""
6931class Printer(Node):
6932 """Printer, a print template offered to users."""
6934 title: str
6935 """Printer title."""
6936 template: 'Template'
6937 """Template that renders the print output."""
6938 models: list['Model']
6939 """Models whose fields are shown as input fields in the print dialog."""
6940 qualityLevels: list['TemplateQualityLevel']
6941 """Quality levels users can choose from."""
6944class PrinterManager(Node):
6945 """Print manager."""
6947 def start_print_job(self, request: PrintRequest, user: 'User') -> 'JobStatusResponse':
6948 """Start a background print job.
6950 Args:
6951 request: Print request.
6952 user: User who requested the print.
6954 Returns:
6955 The status of the new job.
6956 """
6958 def exec_print(self, request: PrintRequest, out_path: str):
6959 """Execute a print request synchronously, as the system user.
6961 Args:
6962 request: Print request.
6963 out_path: Path to copy the output file to.
6964 """
6965################################################################################
6968################################################################################
6969# /base/project/types.pyinc
6972class Client(Node):
6973 """Settings for the browser client: UI elements and client options."""
6975 options: dict
6976 """Client options."""
6977 elements: list
6978 """Client UI elements."""
6981class Project(Node):
6982 """Project: a map application with its own map, actions, templates and services."""
6984 assetsRoot: Optional['WebDocumentRoot']
6985 """Project assets directory, checked before the global assets directory."""
6986 client: 'Client'
6987 """Project client settings, replacing the application client."""
6989 localeUids: list[str]
6990 """Locales of the project."""
6991 map: 'Map'
6992 """Main map of the project."""
6993 metadata: 'Metadata'
6994 """Project metadata."""
6995 title: str
6996 """Project title."""
6998 actions: list['Action']
6999 """Actions available only in this project."""
7000 finders: list['Finder']
7001 """Search providers of the project."""
7002 models: list['Model']
7003 """Data models of the project."""
7004 exporters: list['Exporter']
7005 """Exporters of the project."""
7006 printers: list['Printer']
7007 """Printers of the project."""
7008 templates: list['Template']
7009 """Templates of the project."""
7010 owsServices: list['OwsService']
7011 """OWS services published for the project."""
7013 vars: dict
7014 """Custom variables."""
7015################################################################################
7018################################################################################
7019# /base/search/types.pyinc
7022class SearchSort(Data):
7023 """Search sort specification."""
7025 fieldName: str
7026 """Field name to sort by."""
7027 reverse: bool
7028 """Sort in descending order."""
7031class SearchFilterOperator(Enum):
7032 """Search filter operator, as defined in OGC Filter Encoding 2.0."""
7034 And = 'And'
7035 """All sub-filters match."""
7036 Or = 'Or'
7037 """At least one sub-filter matches."""
7038 Not = 'Not'
7039 """The sub-filter does not match."""
7041 PropertyIsEqualTo = 'PropertyIsEqualTo'
7042 """Property is equal to the value."""
7043 PropertyIsNotEqualTo = 'PropertyIsNotEqualTo'
7044 """Property is not equal to the value."""
7045 PropertyIsLessThan = 'PropertyIsLessThan'
7046 """Property is less than the value."""
7047 PropertyIsGreaterThan = 'PropertyIsGreaterThan'
7048 """Property is greater than the value."""
7049 PropertyIsLessThanOrEqualTo = 'PropertyIsLessThanOrEqualTo'
7050 """Property is less than or equal to the value."""
7051 PropertyIsGreaterThanOrEqualTo = 'PropertyIsGreaterThanOrEqualTo'
7052 """Property is greater than or equal to the value."""
7053 PropertyIsLike = 'PropertyIsLike'
7054 """Property matches a pattern."""
7055 PropertyIsNull = 'PropertyIsNull'
7056 """Property is null."""
7057 PropertyIsNil = 'PropertyIsNil'
7058 """Property is nil."""
7059 PropertyIsBetween = 'PropertyIsBetween'
7060 """Property is between two values."""
7062 Equals = 'Equals'
7063 """Geometry is equal to the shape."""
7064 Disjoint = 'Disjoint'
7065 """Geometry does not intersect the shape."""
7066 Touches = 'Touches'
7067 """Geometry touches the shape."""
7068 Within = 'Within'
7069 """Geometry is within the shape."""
7070 Overlaps = 'Overlaps'
7071 """Geometry overlaps the shape."""
7072 Crosses = 'Crosses'
7073 """Geometry crosses the shape."""
7074 Intersects = 'Intersects'
7075 """Geometry intersects the shape."""
7076 Contains = 'Contains'
7077 """Geometry contains the shape."""
7078 DWithin = 'DWithin'
7079 """Geometry is within a distance of the shape."""
7080 Beyond = 'Beyond'
7081 """Geometry is beyond a distance of the shape."""
7082 BBOX = 'BBOX'
7083 """Geometry intersects the bounding box."""
7086class SearchFilterMatchAction(Enum):
7087 """How a filter is applied to a multi-valued property."""
7089 All = 'All'
7090 """All values must match."""
7091 Any = 'Any'
7092 """At least one value must match."""
7093 One = 'One'
7094 """Exactly one value must match."""
7097class SearchFilter(Data):
7098 """Search filter, a tree of filter operators."""
7100 operator: SearchFilterOperator
7101 """Filter operator."""
7102 property: str
7103 """Property name for comparison and spatial operators."""
7104 value: str
7105 """Value for comparison operators."""
7106 shape: 'Shape'
7107 """Shape for spatial operators."""
7108 subFilters: list['SearchFilter']
7109 """Operands of logical operators."""
7110 matchCase: bool
7111 """Compare strings case-sensitively."""
7112 matchAction: SearchFilterMatchAction
7113 """How to match multi-valued properties."""
7114 wildCard: str
7115 """Wildcard character for ``PropertyIsLike``."""
7116 singleChar: str
7117 """Single character placeholder for ``PropertyIsLike``."""
7118 escapeChar: str
7119 """Escape character for ``PropertyIsLike``."""
7122class SearchQuery(Data):
7123 """Search query."""
7125 bounds: Bounds
7126 """Search bounds."""
7127 extraArgs: dict
7128 """Extra arguments for custom searches."""
7129 extraColumns: list
7130 """Extra columns to select."""
7131 extraParams: dict
7132 """Extra parameters to pass to a provider."""
7133 extraWhere: list
7134 """Extra where clauses."""
7135 keyword: str
7136 """Keyword to search for."""
7137 layers: list['Layer']
7138 """Layers to search in."""
7139 limit: int
7140 """Limit the number of results."""
7141 filter: SearchFilter
7142 """Search filter."""
7143 project: 'Project'
7144 """Project to search in."""
7145 resolution: float
7146 """Pixel resolution for geometry search."""
7147 shape: 'Shape'
7148 """Shape to search in."""
7149 sort: list[SearchSort]
7150 """Sort options."""
7151 tolerance: 'UomValue'
7152 """Tolerance for geometry search."""
7153 uids: list[str]
7154 """UIDs to search for."""
7157class SearchResult(Data):
7158 """Search result."""
7160 feature: 'Feature'
7161 """Found feature."""
7162 layer: 'Layer'
7163 """Layer whose finder found the feature, or ``None`` for project and application finders."""
7164 finder: 'Finder'
7165 """Finder that found the feature."""
7168class TextSearchType(Enum):
7169 """Text search type."""
7171 exact = 'exact'
7172 """Match the whole string."""
7173 begin = 'begin'
7174 """Match the beginning of the string."""
7175 end = 'end'
7176 """Match the end of the string."""
7177 any = 'any'
7178 """Match any substring."""
7179 like = 'like'
7180 """Use the percent sign as a placeholder."""
7183class TextSearchOptions(Data):
7184 """How keywords are matched against a text field."""
7186 type: TextSearchType
7187 """Type of the search."""
7188 minLength: int = 0
7189 """Min. keyword length."""
7190 caseSensitive: bool = False
7191 """Use case-sensitive search."""
7194class SortOptions(Data):
7195 """Sort order for features."""
7197 fieldName: str
7198 """Field name to sort by."""
7199 reverse: bool = False
7200 """Sort in descending order."""
7203class SearchManager(Node):
7204 """Search manager, runs search queries through the finders."""
7206 def run_search(self, search: 'SearchQuery', user: 'User') -> list['SearchResult']:
7207 """Run a search query.
7209 Runs the finders of the query layers, the project finders and the application
7210 finders the user may use and which can run the query.
7212 Args:
7213 search: Search query.
7214 user: User running the search.
7216 Returns:
7217 Search results, at most ``search.limit`` if a limit is given.
7218 """
7221class Finder(Node):
7222 """Search provider, finds features for search queries."""
7224 title: str
7225 """Finder title."""
7226 category: str
7227 """Category assigned to the results."""
7229 supportsFilterSearch: bool = False
7230 """The finder supports filter searches."""
7231 supportsGeometrySearch: bool = False
7232 """The finder supports geometry searches."""
7233 supportsKeywordSearch: bool = False
7234 """The finder supports keyword searches."""
7236 withFilter: bool
7237 """Filter searches are enabled."""
7238 withGeometry: bool
7239 """Geometry searches are enabled."""
7240 withKeyword: bool
7241 """Keyword searches are enabled."""
7243 templates: list['Template']
7244 """Templates to format the found features."""
7245 models: list['Model']
7246 """Models used to read the features."""
7247 sourceLayers: list['SourceLayer']
7248 """Source layers to search in, for finders of OWS and QGIS sources."""
7250 tolerance: 'UomValue'
7251 """Tolerance for geometry searches."""
7253 def run(self, search: SearchQuery, user: 'User', layer: Optional['Layer'] = None) -> list['Feature']:
7254 """Run a search query.
7256 Args:
7257 search: Search query.
7258 user: User running the search.
7259 layer: Layer the finder belongs to, if any.
7261 Returns:
7262 Found features.
7263 """
7265 def can_run(self, search: SearchQuery, user: 'User') -> bool:
7266 """Check if the finder can run a search query.
7268 Args:
7269 search: Search query.
7270 user: User running the search.
7272 Returns:
7273 ``True`` if the finder can run the query.
7274 """
7275################################################################################
7278################################################################################
7279# /base/storage/types.pyinc
7282class StorageManager(Node):
7283 """Storage manager, holds the storage providers."""
7285 providers: list['StorageProvider']
7286 """Configured storage providers."""
7288 def create_provider(self, cfg: Config, **kwargs) -> 'StorageProvider':
7289 """Create a storage provider and add it to the manager.
7291 A provider with the same uid replaces the existing one.
7293 Args:
7294 cfg: Provider configuration.
7295 **kwargs: Extra configuration values.
7297 Returns:
7298 The new provider.
7299 """
7301 def find_provider(self, uid: Optional[str] = None) -> Optional['StorageProvider']:
7302 """Find a storage provider.
7304 Args:
7305 uid: Provider uid. If not given, the first provider is returned.
7307 Returns:
7308 The provider, or ``None`` if not found.
7309 """
7313class StorageRecord(Data):
7314 """Storage record."""
7316 name: str
7317 """Record name."""
7318 userUid: str
7319 """Uid of the user who last wrote the record."""
7320 data: str
7321 """Serialized record data."""
7322 created: 'datetime.datetime'
7323 """Record create time."""
7324 updated: 'datetime.datetime'
7325 """Record update time."""
7328class StorageProvider(Node):
7329 """Storage provider, stores named records grouped by category."""
7331 def list_names(self, category: str) -> list[str]:
7332 """List the record names in a category.
7334 Args:
7335 category: Category name.
7337 Returns:
7338 Record names.
7339 """
7341 def read(self, category: str, name: str) -> Optional['StorageRecord']:
7342 """Read a record.
7344 Args:
7345 category: Category name.
7346 name: Record name.
7348 Returns:
7349 The record, or ``None`` if not found.
7350 """
7352 def write(self, category: str, name: str, data: str, user_uid: str):
7353 """Create a record or update an existing one.
7355 Args:
7356 category: Category name.
7357 name: Record name.
7358 data: Serialized record data.
7359 user_uid: Uid of the user who writes the record.
7360 """
7362 def delete(self, category: str, name: str):
7363 """Delete a record.
7365 Args:
7366 category: Category name.
7367 name: Record name.
7368 """
7369################################################################################
7372################################################################################
7373# /base/template/types.pyinc
7376class TemplateArgs(Data):
7377 """Template arguments."""
7379 app: 'Application'
7380 """Application object."""
7381 locale: 'Locale'
7382 """Current locale."""
7383 date: 'DateFormatter'
7384 """Locale-aware date formatter."""
7385 time: 'TimeFormatter'
7386 """Locale-aware time formatter."""
7387 number: 'NumberFormatter'
7388 """Locale-aware number formatter."""
7391class TemplateRenderInput(Data):
7392 """Template render input."""
7394 args: dict | Data
7395 """Template arguments."""
7396 crs: 'Crs'
7397 """CRS for maps."""
7398 dpi: int
7399 """Output resolution in dots per inch."""
7400 locale: 'Locale'
7401 """Locale for the output."""
7402 maps: list[MapRenderInput]
7403 """Maps to render, for print templates."""
7404 mimeOut: str
7405 """Requested output MIME type."""
7406 notify: Callable
7407 """Callback for progress messages."""
7408 project: 'Project'
7409 """Current project."""
7410 user: 'User'
7411 """Current user."""
7414class TemplateQualityLevel(Config):
7415 """Print quality level users can choose."""
7417 name: str
7418 """Quality level name shown to users."""
7419 dpi: int
7420 """Print resolution in dots per inch."""
7423class Template(Node):
7424 """Template, generates content from data."""
7426 mapSize: UomSize
7427 """Default map size for the template."""
7428 mimeTypes: list[str]
7429 """MIME types the template can generate."""
7430 pageSize: UomSize
7431 """Default page size for printing."""
7432 pageMargin: UomExtent
7433 """Default page margin for printing."""
7434 subject: str
7435 """Template subject, the purpose the template serves, like ``feature.description``."""
7436 title: str
7437 """Template title."""
7439 def render(self, tri: TemplateRenderInput) -> ContentResponse:
7440 """Render the template.
7442 Args:
7443 tri: Render input.
7445 Returns:
7446 A response with the generated content.
7447 """
7450class TemplateManager(Node):
7451 """Template manager, finds templates by subject and creates them from files."""
7453 def find_templates(self, subjects: list[str], where: list[Node], user: 'User' = None, mime_type: str = None) -> list['Template']:
7454 """Find templates for several subjects.
7456 Args:
7457 subjects: Template subjects.
7458 where: Objects whose templates are searched, in this order.
7459 user: If given, only templates this user can use.
7460 mime_type: If given, only templates which can produce this MIME type.
7462 Returns:
7463 Found templates, one per subject at most.
7464 """
7466 def find_template(self, subject: str, where: list[Node], user: 'User' = None, mime_type: str = None) -> Optional['Template']:
7467 """Find a template for a subject.
7469 The templates of the objects in ``where`` are searched in the given order,
7470 then the application templates. A template without ``mimeTypes`` matches any
7471 MIME type.
7473 Args:
7474 subject: Template subject.
7475 where: Objects whose templates are searched, in this order.
7476 user: If given, only templates this user can use.
7477 mime_type: If given, only templates which can produce this MIME type.
7479 Returns:
7480 The first matching template, or ``None``.
7481 """
7483 def template_from_path(self, path: str) -> Optional['Template']:
7484 """Create a template from a file.
7486 The template type is derived from the file extension.
7488 Args:
7489 path: File path.
7491 Returns:
7492 A template, or ``None`` if the file is not a template.
7493 """
7494################################################################################
7497################################################################################
7498# /base/web/types.pyinc
7501class RequestMethod(Enum):
7502 """Web request method."""
7504 GET = 'GET'
7505 HEAD = 'HEAD'
7506 POST = 'POST'
7507 PUT = 'PUT'
7508 DELETE = 'DELETE'
7509 CONNECT = 'CONNECT'
7510 OPTIONS = 'OPTIONS'
7511 TRACE = 'TRACE'
7512 PATCH = 'PATCH'
7515class WebRequester:
7516 """Web requester, gives access to an incoming web request."""
7518 environ: dict
7519 """Request environment."""
7520 method: RequestMethod
7521 """Request method."""
7522 contentType: str
7523 """Request content type."""
7524 root: 'Root'
7525 """Object tree root."""
7526 site: 'WebSite'
7527 """Website the request is processed for."""
7529 session: 'AuthSession'
7530 """Current session."""
7531 user: 'User'
7532 """Current user."""
7534 isGet: bool
7535 """The request is a GET request."""
7536 isPost: bool
7537 """The request is a POST request."""
7538 isApi: bool
7539 """The request provides json data in the POST body."""
7540 isForm: bool
7541 """The request provides form data in the POST body."""
7542 isSecure: bool
7543 """The request is made over https."""
7545 scheme: str
7546 """Request scheme, http or https."""
7547 host: str
7548 """Request host name, without the port, empty if the host is invalid."""
7549 port: int
7550 """Request port, 0 if not given."""
7551 ip: str
7552 """Client address."""
7554 def parse(self):
7555 """Parse the request path, the parameters and the structured payload.
7557 Also determines the scheme, host, port and client address, taking proxy
7558 headers into account if the site has proxies.
7560 Raises:
7561 ``gws.base.web.error.HTTPException``: If the request path, the host or the payload is invalid.
7562 """
7564 def params(self) -> dict:
7565 """Return the GET parameters.
7567 Returns:
7568 Parameters from the query string and from the request path.
7569 """
7571 def query_params(self) -> dict:
7572 """Return the GET parameters from the query string.
7574 Returns:
7575 Query string parameters.
7576 """
7578 def path(self) -> str:
7579 """Return the request path after the command.
7581 Returns:
7582 The rest of the path after ``/_/<command>/``.
7583 """
7585 def struct(self) -> dict:
7586 """Return the structured payload of an API request.
7588 Returns:
7589 The decoded JSON or MessagePack payload.
7590 """
7592 def command(self) -> str:
7593 """Return the command name.
7595 Returns:
7596 The command from the path, or from the ``cmd`` parameter.
7597 """
7599 def data(self) -> bytes:
7600 """Return the raw POST data, unzipped if gzip-encoded.
7602 Returns:
7603 POST data, empty for non-POST requests.
7605 Raises:
7606 ``gws.base.web.error.HTTPException``: If the content length is invalid or too large, or the data cannot be unzipped.
7607 """
7609 def form(self) -> list[tuple[str, Any]]:
7610 """Return the POST form data.
7612 Returns:
7613 A list of ``(key, value)`` tuples, including uploaded files; empty if the request is not a form.
7615 Raises:
7616 ``gws.base.web.error.HTTPException``: If the form data cannot be decoded.
7617 """
7619 def text(self) -> str:
7620 """Return the POST data decoded to text, with the charset of the request.
7622 Returns:
7623 POST data as text.
7625 Raises:
7626 ``gws.base.web.error.HTTPException``: If the data cannot be decoded.
7627 """
7629 def cookie(self, key: str, default: str = '') -> str:
7630 """Get a cookie.
7632 Args:
7633 key: Cookie name.
7634 default: Default value.
7636 Returns:
7637 A cookie value.
7638 """
7640 def header(self, key: str, default: str = '') -> str:
7641 """Get a header.
7643 Args:
7644 key: Header name.
7645 default: Default value.
7647 Returns:
7648 A header value.
7649 """
7651 def has_param(self, key: str) -> bool:
7652 """Check if a GET parameter exists, ignoring case.
7654 Args:
7655 key: Parameter name.
7657 Returns:
7658 ``True`` if the parameter exists.
7659 """
7661 def param(self, key: str, default: str = '') -> str:
7662 """Get a GET parameter, ignoring case.
7664 Args:
7665 key: Parameter name.
7666 default: Default value.
7668 Returns:
7669 A parameter value.
7670 """
7672 def env(self, key: str, default: str = '') -> str:
7673 """Get a WSGI environment variable.
7675 Args:
7676 key: Variable name.
7677 default: Default value.
7679 Returns:
7680 A variable value.
7681 """
7683 def content_responder(self, response: ContentResponse) -> 'WebResponder':
7684 """Create a responder for a content response.
7686 Args:
7687 response: Response with literal content or a content path.
7689 Returns:
7690 A responder.
7691 """
7693 def redirect_responder(self, response: RedirectResponse) -> 'WebResponder':
7694 """Create a responder for a redirect response.
7696 Args:
7697 response: Redirect response.
7699 Returns:
7700 A responder.
7701 """
7703 def api_responder(self, response: Response) -> 'WebResponder':
7704 """Create a responder for an API (structured) response.
7706 The response is encoded as JSON or MessagePack, depending on the request.
7708 Args:
7709 response: Response object.
7711 Returns:
7712 A responder.
7713 """
7715 def error_responder(self, exc: Exception) -> 'WebResponder':
7716 """Create a responder for an exception.
7718 Args:
7719 exc: An exception; anything but an HTTP exception results in a 500 response.
7721 Returns:
7722 A responder.
7723 """
7725 def absolute_url_for(self, request_path: str, **params) -> str:
7726 """Create an absolute URL pointing to the requested host.
7728 Args:
7729 request_path: Request path.
7730 **params: Additional GET parameters.
7732 Returns:
7733 A URL.
7734 """
7736 def relative_url_for(self, request_path: str, **params) -> str:
7737 """Create a host-relative URL.
7739 Args:
7740 request_path: Request path.
7741 **params: Additional GET parameters.
7743 Returns:
7744 A URL.
7745 """
7747 def canonical_url_for(self, request_path: str, **params) -> str:
7748 """Create an absolute URL pointing to the canonical host.
7750 Args:
7751 request_path: Request path.
7752 **params: Additional GET parameters.
7754 Returns:
7755 A URL.
7756 """
7758 def set_session(self, session: 'AuthSession'):
7759 """Attach a session to the requester and set the user from it.
7761 Args:
7762 session: A session object.
7763 """
7766class WebResponder:
7767 """Web responder, builds and sends the response to a web request."""
7769 status: int
7770 """Response status."""
7772 def send_response(self, environ: dict, start_response: Callable):
7773 """Send the response to the client.
7775 Args:
7776 environ: WSGI environment.
7777 start_response: WSGI ``start_response`` function.
7779 Returns:
7780 The WSGI response iterable.
7781 """
7783 def set_cookie(self, key: str, value: str, **kwargs):
7784 """Set a cookie.
7786 Args:
7787 key: Cookie name.
7788 value: Cookie value.
7789 **kwargs: Cookie options.
7790 """
7792 def delete_cookie(self, key: str, **kwargs):
7793 """Delete a cookie.
7795 Args:
7796 key: Cookie name.
7797 **kwargs: Cookie options.
7798 """
7800 def set_status(self, status: int):
7801 """Set the response status.
7803 Args:
7804 status: HTTP status code.
7805 """
7807 def add_header(self, key: str, value: str):
7808 """Add a header.
7810 Args:
7811 key: Header name.
7812 value: Header value.
7813 """
7815 def set_body(self, body: str | bytes):
7816 """Set the response body.
7818 Args:
7819 body: New response body; strings are encoded as UTF-8.
7820 """
7823class WebDocumentRoot(Data):
7824 """Directory served over the web."""
7826 dir: DirPath
7827 """Local directory."""
7828 allowMime: list[str]
7829 """Allowed mime types."""
7830 denyMime: list[str]
7831 """Restricted mime types."""
7834class WebRewriteRule(Data):
7835 """URL rewrite rule."""
7837 pattern: Regex
7838 """URL matching pattern."""
7839 target: str
7840 """Rule target, with ``$1``, ``$2`` etc. placeholders for the pattern groups."""
7841 options: dict
7842 """Extra options."""
7843 reversed: bool
7844 """The rule rewrites URLs generated by the server, not incoming URLs."""
7847class WebCors(Data):
7848 """CORS options."""
7850 allowCredentials: bool
7851 """Allow credentials in cross-origin requests."""
7852 allowHeaders: str
7853 """Headers allowed in cross-origin requests."""
7854 allowMethods: str
7855 """Methods allowed in cross-origin requests."""
7856 allowOrigin: str
7857 """Origins allowed to make cross-origin requests."""
7860class WebManager(Node):
7861 """Web manager, holds the web site."""
7863 site: 'WebSite'
7864 """Configured web site."""
7867class WebSite(Node):
7868 """Web site the server responds to."""
7870 assetsRoot: Optional[WebDocumentRoot]
7871 """Root directory for assets."""
7872 canonicalHost: str
7873 """Host name for absolute canonical URLs."""
7874 corsOptions: WebCors
7875 """CORS options."""
7876 hostnames: list[str]
7877 """Host names this site responds to."""
7878 rewriteRules: list[WebRewriteRule]
7879 """URL rewrite rules."""
7880 proxyCount: int
7881 """Number of proxies in front of the server."""
7882 ssl: bool
7883 """The site is served over https."""
7884 staticRoot: WebDocumentRoot
7885 """Root directory for static files."""
7887 def url_for(self, req: 'WebRequester', path: str, mode: str, **params) -> str:
7888 """Create a URL for a request path, applying the reversed rewrite rules.
7890 If the path, or the rewritten path, is an absolute URL, only the parameters
7891 are added. In the ``absolute`` and ``canonical`` modes, the URL gets the scheme
7892 of the request. The host is the canonical host in the ``canonical`` mode, and
7893 the request host and port otherwise or if there is no canonical host.
7895 Args:
7896 req: Web requester.
7897 path: Request path.
7898 mode: ``absolute``, ``relative`` or ``canonical``.
7899 **params: Extra GET parameters.
7901 Returns:
7902 A URL.
7904 Raises:
7905 ``gws.BadRequestError``: If an absolute URL is requested and there is no host.
7906 """
7907################################################################################
7910################################################################################
7911# /base/exporter/types.pyinc
7914class ExportArgs(Data):
7915 """Arguments passed to ``Exporter.run``."""
7917 exporter: 'Exporter'
7918 """The exporter."""
7919 features: Optional[list['Feature']]
7920 """Features to export."""
7921 shape: Optional['Shape']
7922 """Shape from the export request."""
7923 project: 'Project'
7924 """Project of the export request."""
7925 user: 'User'
7926 """User the export runs for."""
7927 notify: Callable
7928 """Progress callback, called with an event name."""
7929 maxErrors: int = 100
7930 """Maximum number of errors collected in the result."""
7933class ExportTarget(Enum):
7934 """Export target."""
7936 file = 'file'
7937 """Save the export result to a file on the server."""
7938 download = 'download'
7939 """Return the export result for download."""
7942class ExportResult(Data):
7943 """Export result."""
7945 path: str
7946 """Path of the result file, empty if nothing was exported."""
7947 mimeType: str
7948 """Mime type of the result file."""
7949 numFiles: int
7950 """Number of files written."""
7951 numFeaturesTotal: int
7952 """Number of requested features."""
7953 numFeaturesExported: int
7954 """Number of exported features."""
7955 errors: list[str]
7956 """Error messages for features that were not exported."""
7959class FeatureExportStrategy(Enum):
7960 """How exported features are obtained."""
7962 load = 'load'
7963 """Load features by ids from the source model."""
7964 client = 'client'
7965 """Export features using properties as received from the client."""
7968class ExportRequestType(Enum):
7969 """Kind of data to export."""
7971 vector = 'vector'
7972 """Vector features."""
7973 raster = 'raster'
7974 """Raster data."""
7977class ExportRequest(Request):
7978 """Export request from the client."""
7980 type: ExportRequestType
7981 """Kind of data to export."""
7982 exporterUid: str
7983 """Uid of the exporter."""
7984 features: Optional[list['FeatureProps']]
7985 """Features to export."""
7986 shape: Optional['ShapeProps']
7987 """Shape passed to the exporter."""
7990class ExportResponse(Response):
7991 """Export response with the content of the result file."""
7993 content: str | bytes
7994 """File content."""
7995 contentFilename: str
7996 """File name."""
7997 mimeType: str
7998 """Mime type."""
8001class ExporterManager(Node):
8002 """Exporter manager."""
8004 def start_export_job(self, request: ExportRequest, user: 'User') -> 'JobStatusResponse':
8005 """Create and schedule a background export job.
8007 Args:
8008 request: Export request.
8009 user: User the export runs for.
8011 Returns:
8012 The status of the new job.
8013 """
8015 def exec_export(self, request: ExportRequest, out_path: str):
8016 """Run an export directly, as the system user, and copy the result file.
8018 Args:
8019 request: Export request.
8020 out_path: Path to copy the result file to.
8022 Returns:
8023 The export result.
8025 Raises:
8026 ``gws.Error``: If no features were exported.
8027 """
8029 def list_exporters(self, where: list['Node'], user: 'User') -> list['Exporter']:
8030 """List the exporters of the given objects that the user can use.
8032 Of several exporters with the same title, only the first one is listed.
8034 Args:
8035 where: Objects with an ``exporters`` list, e.g. a project and the application.
8036 ``None`` entries are ignored.
8037 user: User.
8039 Returns:
8040 A list of exporters.
8041 """
8043 def get_exporter(self, where: list['Node'], uid: str, user: 'User') -> Optional['Exporter']:
8044 """Find an exporter by uid among the exporters the user can use.
8046 Args:
8047 where: Objects with an ``exporters`` list, e.g. a project and the application.
8048 uid: Exporter uid.
8049 user: User.
8051 Returns:
8052 The exporter, or ``None`` if it is not found.
8053 """
8056class Exporter(Node):
8057 """Exporter.
8059 Writes features to files in a specific format.
8060 """
8062 title: str
8063 """Exporter title, shown in the client."""
8064 options: dict
8065 """Format-specific options, passed to the GDAL driver."""
8067 supportsVector: bool
8068 """The exporter can export vector features."""
8069 supportsRaster: bool
8070 """The exporter can export raster data."""
8071 supportsMultiLayer: bool
8072 """The format can hold several layers in one file."""
8074 withNoGeometry: bool
8075 """Export features without geometry instead of skipping them."""
8076 withMixedGeometry: bool
8077 """Allow different geometry types in one layer instead of skipping features."""
8078 withMixedCrs: bool
8079 """Allow different CRS in one layer instead of skipping features."""
8080 withMultiLayer: bool
8081 """Write all layers to one file."""
8083 supportedAttributeTypes: Optional[list[gws.AttributeType]]
8084 """Attribute types the exporter can write. If empty, the types supported by GDAL are used."""
8086 def run(self, ea: ExportArgs, er: ExportResult):
8087 """Export the features.
8089 Writes the result file and sets its path, the mime type, the counts
8090 and errors in the export result.
8092 Args:
8093 ea: Export arguments.
8094 er: Export result, filled by the exporter.
8095 """
8096################################################################################
8100################################################################################
8101# /base/application/types.pyinc
8104class MiddlewareManager(Node):
8105 """Middleware manager.
8107 Middleware objects process every web request: the web server calls
8108 ``enter_middleware`` on each of them in dependency order before the action,
8109 and ``exit_middleware`` in reverse order after it.
8110 """
8112 def register(self, obj: Node, name: str, depends_on: Optional[list[str]] = None):
8113 """Register an object as a middleware.
8115 Args:
8116 obj: The middleware object.
8117 name: Middleware name, for example ``db`` or ``auth``.
8118 depends_on: Names of middleware that must run before this one.
8119 """
8121 def objects(self) -> list[Node]:
8122 """Return the registered middleware objects in dependency order.
8124 Returns:
8125 A list of middleware objects, dependencies first.
8127 Raises:
8128 Error: If the dependencies are cyclic or refer to an unknown name.
8129 """
8132class TemplateOptions(Data):
8133 """Options for the built-in application and project home pages."""
8135 withLogin: bool = True
8136 """Show the login form on the home page."""
8137 footerText: Optional[str]
8138 """HTML text for the home page footer."""
8139 withGws: bool = True
8140 """Show the GWS logo in the home page footer."""
8141 homeResources: Optional[list[str]]
8142 """Extra resource URLs for the home page."""
8143 projectResources: Optional[list[str]]
8144 """Extra resource URLs for the project page."""
8147class Application(Node):
8148 """Application object.
8150 The top-level node of the configuration tree. It holds the managers, the
8151 global objects and the projects, and is available as ``root.app``.
8152 """
8154 client: 'Client'
8155 """Default client, used by projects without their own client configuration."""
8157 localeUids: list[str]
8158 """Default locale uids for all projects."""
8160 metadata: 'Metadata'
8161 """Application metadata."""
8163 monitor: 'ServerMonitor'
8164 """Server monitor, watches configuration files and runs periodic tasks."""
8166 templateOptions: TemplateOptions
8167 """Options for the built-in home page templates."""
8169 title: str
8170 """Application title."""
8172 vars: dict
8173 """Custom variables from the configuration."""
8175 version: str
8176 """Application version, for example ``8.5.3``."""
8178 versionString: str
8179 """Version string for display, with the revision if known."""
8181 def supported_crs(self) -> list['Crs']:
8182 """Return all CRS supported by the application.
8184 These are the CRS of all maps and the CRS supported by OWS services,
8185 plus the registered ones. The list is computed on the first call.
8187 Returns:
8188 A list of CRS objects, sorted by srid.
8189 """
8191 def register_supported_crs(self, crs: 'Crs'):
8192 """Register an additional supported CRS.
8194 Must be called during configuration.
8196 Args:
8197 crs: The CRS object.
8198 """
8200 defaultPrinter: 'Printer'
8201 """Default printer, used when no printer is configured."""
8203 actionMgr: 'ActionManager'
8204 """Action manager."""
8206 authMgr: 'AuthManager'
8207 """Authorization manager."""
8209 databaseMgr: 'DatabaseManager'
8210 """Database manager."""
8212 exporterMgr: 'ExporterManager'
8213 """Exporter manager."""
8215 jobMgr: 'JobManager'
8216 """Job manager."""
8218 middlewareMgr: 'MiddlewareManager'
8219 """Middleware manager."""
8221 modelMgr: 'ModelManager'
8222 """Model manager."""
8224 printerMgr: 'PrinterManager'
8225 """Printer manager."""
8227 searchMgr: 'SearchManager'
8228 """Search manager."""
8230 serverMgr: 'ServerManager'
8231 """Server manager."""
8233 storageMgr: 'StorageManager'
8234 """Storage manager."""
8236 templateMgr: 'TemplateManager'
8237 """Template manager."""
8239 webMgr: 'WebManager'
8240 """Web manager."""
8242 actions: list['Action']
8243 """Actions available in all projects."""
8245 projects: list['Project']
8246 """Configured projects."""
8248 exporters: list['Exporter']
8249 """Global exporters."""
8251 finders: list['Finder']
8252 """Finders available in all projects."""
8254 templates: list['Template']
8255 """Global templates, including the built-in ones."""
8257 printers: list['Printer']
8258 """Global printers."""
8260 models: list['Model']
8261 """Global models."""
8263 owsServices: list['OwsService']
8264 """OWS services provided by the server."""
8266 def project(self, uid: str) -> Optional['Project']:
8267 """Find a project by its uid.
8269 Args:
8270 uid: Project uid.
8272 Returns:
8273 The project, or ``None`` if not found.
8274 """
8276 def helper(self, ext_type: str) -> Optional['Node']:
8277 """Return a helper object by its type.
8279 A helper that is not configured is created with default options on the first call.
8281 Args:
8282 ext_type: Helper type, for example ``upload``.
8284 Returns:
8285 The helper object.
8287 Raises:
8288 Error: If the helper type does not exist.
8289 """
8291 def developer_option(self, key: str):
8292 """Return the value of a developer option.
8294 Developer options are configured in the ``developer`` property of the
8295 application config and are meant for development and debugging only.
8297 Args:
8298 key: Option name, for example ``template.always_reload``.
8300 Returns:
8301 The option value, or ``None`` if it is not set.
8302 """
8303################################################################################