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

1"""GBD WebSuite: basic types and interfaces. 

2 

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

9 

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: 

16 

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, 

22 

23and ``gws.ext``, the decorators that register extension classes and command 

24methods. 

25 

26Code base layout 

27---------------- 

28 

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. 

50 

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. 

56 

57Example:: 

58 

59 import gws 

60 import gws.base.layer 

61 

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 

66 

67 @gws.ext.config.layer('my') 

68 class Config(gws.base.layer.Config): 

69 pass 

70 

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""" 

76 

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) 

92 

93from collections.abc import ( 

94 Mapping, 

95 Sequence, 

96) 

97 

98import enum 

99import datetime 

100 

101if TYPE_CHECKING: 

102 import sqlalchemy 

103 import numpy.typing 

104 

105# mypy: disable-error-code="empty-body" 

106 

107 

108from . import ext 

109 

110from .core import ( 

111 log, 

112 debug, 

113 env, 

114 const as c, 

115 util as u, 

116) 

117 

118 

119################################################################################ 

120# /core/_data.pyinc 

121 

122 

123# basic data type 

124 

125class Data: 

126 """Basic data object. 

127 

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. 

130 

131 Accessing an undefined attribute returns ``None`` and no error is raised, 

132 unless the attribute name starts with an underscore. 

133 

134 Example:: 

135 

136 d = gws.Data({'a': 1}, b=2) 

137 d.a # 1 

138 d['b'] # 2 

139 d.c # None 

140 """ 

141 

142 def __init__(self, *args, **kwargs): 

143 """Create the object from dicts, ``Data`` objects and keyword args. 

144 

145 Args: 

146 *args: Dicts, Mappings or ``Data`` objects. Other values are ignored. 

147 **kwargs: Keyword args. 

148 """ 

149 self.update(*args, **kwargs) 

150 

151 def __repr__(self): 

152 """Return the ``repr`` of the attributes dict.""" 

153 return repr(vars(self)) 

154 

155 def __getitem__(self, key): 

156 """Return an attribute value or ``None`` if it is undefined.""" 

157 return vars(self).get(key) 

158 

159 def __setitem__(self, key, value): 

160 """Set an attribute value.""" 

161 vars(self)[key] = value 

162 

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 

168 

169 def get(self, key, default=None): 

170 """Get an attribute value. 

171 

172 Args: 

173 key: Attribute name. 

174 default: Default value, returned if the attribute is undefined. 

175 

176 Returns: 

177 The attribute value or the default. 

178 """ 

179 return vars(self).get(key, default) 

180 

181 def setdefault(self, key, val): 

182 """Set an attribute value if it is not already set. 

183 

184 Args: 

185 key: Attribute name. 

186 val: Attribute value. 

187 

188 Returns: 

189 The current attribute value, existing or new. 

190 """ 

191 return vars(self).setdefault(key, val) 

192 

193 def set(self, key, val): 

194 """Set an attribute value. 

195 

196 Args: 

197 key: Attribute name. 

198 val: Attribute value. 

199 """ 

200 vars(self)[key] = val 

201 

202 def update(self, *args, **kwargs): 

203 """Update the object with keys and values from args and keywords. 

204 

205 Later values override earlier ones, keywords override args. 

206 

207 Args: 

208 *args: Dicts, Mappings or ``Data`` objects. Other values are ignored. 

209 **kwargs: Keyword args. 

210 """ 

211 

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) 

220 

221 

222# getattr needs to be defined out of class, otherwise the type checker will accept any attribute 

223 

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 

230 

231 

232setattr(Data, '__getattr__', _data_getattr) 

233 

234 

235def is_data_object(x): 

236 """Check if the argument is a ``Data`` object. 

237 

238 Args: 

239 x: A value. 

240 

241 Returns: 

242 ``True`` if the value is a ``Data`` object. 

243 """ 

244 return isinstance(x, Data) 

245 

246 

247def to_data_object(x) -> 'Data': 

248 """Convert a value to a ``Data`` object. 

249 

250 If the argument is already a ``Data`` object, simply return it. 

251 If the argument is ``None``, an empty object is returned. 

252 

253 Args: 

254 x: A ``Data`` object, a Mapping or ``None``. 

255 

256 Returns: 

257 A ``Data`` object. 

258 

259 Raises: 

260 ValueError: If the value cannot be converted. 

261 """ 

262 

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################################################################################ 

271 

272 

273 

274u.is_data_object = is_data_object 

275u.to_data_object = to_data_object 

276 

277 

278 

279################################################################################ 

280# /core/_basic.pyinc 

281 

282 

283class Enum(enum.Enum): 

284 """Enumeration type. 

285 

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. 

288 

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 

293 

294 

295# hack to make Enum a simple object 

296globals()['Enum'] = type('Enum', (), {}) 

297 

298Extent: TypeAlias = tuple[float, float, float, float] 

299"""An array of 4 elements representing extent coordinates ``[min-x, min-y, max-x, max-y]``.""" 

300 

301Point: TypeAlias = tuple[float, float] 

302"""Point coordinates ``[x, y]``.""" 

303 

304Size: TypeAlias = tuple[float, float] 

305"""Size ``[width, height]``.""" 

306 

307 

308class Origin(Enum): 

309 """Grid origin.""" 

310 

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

327 

328 

329FilePath: TypeAlias = str 

330"""File path on the server.""" 

331 

332DirPath: TypeAlias = str 

333"""Directory path on the server.""" 

334 

335Duration: TypeAlias = str 

336"""Duration like ``1w 2d 3h 4m 5s`` or an integer number of seconds.""" 

337 

338Color: TypeAlias = str 

339"""CSS color name.""" 

340 

341Regex: TypeAlias = str 

342"""Regular expression, as used in Python.""" 

343 

344FormatStr: TypeAlias = str 

345"""Format string as used in Python.""" 

346 

347DateStr: TypeAlias = str 

348"""ISO date string like ``2019-01-30``.""" 

349 

350DateTimeStr: TypeAlias = str 

351"""ISO datetime string like ``2019-01-30 01:02:03``.""" 

352 

353Url: TypeAlias = str 

354"""URL.""" 

355 

356ClassRef: TypeAlias = type | str 

357"""Class reference: a type, an ``ext`` class or name like ``gws.ext.object.layer``, or a full class name.""" 

358 

359 

360class Config(Data): 

361 """Object configuration.""" 

362 

363 uid: str = '' 

364 """Unique ID.""" 

365 

366 

367class Props(Data): 

368 """Object properties.""" 

369 

370 uid: str = '' 

371 """Unique ID.""" 

372 

373 

374class Request(Data): 

375 """Command request.""" 

376 

377 projectUid: Optional[str] 

378 """Unique ID of the project.""" 

379 localeUid: Optional[str] 

380 """Locale ID for this request.""" 

381 

382 

383class EmptyRequest(Data): 

384 """Empty command request.""" 

385 

386 pass 

387 

388 

389class ResponseError(Data): 

390 """Response error.""" 

391 

392 code: Optional[int] 

393 """Error code.""" 

394 info: Optional[str] 

395 """Information about the error.""" 

396 

397 

398class Response(Data): 

399 """Command response.""" 

400 

401 error: Optional[ResponseError] 

402 """Response error.""" 

403 status: int 

404 """Response status or exit code.""" 

405 

406 

407class ContentResponse(Response): 

408 """Web response with literal content.""" 

409 

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

420 

421 

422class RedirectResponse(Response): 

423 """Web redirect response.""" 

424 

425 location: str 

426 """Redirect URL.""" 

427 headers: dict 

428 """Additional headers.""" 

429 

430 

431class AttributeType(Enum): 

432 """Feature attribute type.""" 

433 

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

464 

465 

466class GeometryType(Enum): 

467 """Feature geometry type. 

468 

469 OGC and SQL/MM geometry types. 

470 

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 """ 

475 

476 geometry = 'geometry' 

477 """Any geometry.""" 

478 

479 point = 'point' 

480 """Point.""" 

481 curve = 'curve' 

482 """Curve.""" 

483 surface = 'surface' 

484 """Surface.""" 

485 

486 geometrycollection = 'geometrycollection' 

487 """Collection of geometries.""" 

488 

489 linestring = 'linestring' 

490 """Line string.""" 

491 line = 'line' 

492 """Line.""" 

493 linearring = 'linearring' 

494 """Linear ring.""" 

495 

496 polygon = 'polygon' 

497 """Polygon.""" 

498 triangle = 'triangle' 

499 """Triangle.""" 

500 

501 polyhedralsurface = 'polyhedralsurface' 

502 """Polyhedral surface.""" 

503 tin = 'tin' 

504 """Triangulated irregular network.""" 

505 

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

516 

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

523 

524 

525class CliParams(Data): 

526 """Parameters of a command line command.""" 

527 pass 

528################################################################################ 

529 

530 

531################################################################################ 

532# /core/_access.pyinc 

533 

534 

535Acl: TypeAlias = list[tuple[int, str]] 

536"""Access control list. 

537 

538A list of tuples ``(ACL bit, role-name)`` where ``ACL bit`` is ``1`` if the access is allowed and ``0`` otherwise. 

539""" 

540 

541AclStr: TypeAlias = str 

542"""Comma-separated rules ``allow <role>`` or ``deny <role>``.""" 

543 

544 

545class Access(Enum): 

546 """Access mode.""" 

547 

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

556 

557 

558class PermissionsConfig(Config): 

559 """Access rules per operation.""" 

560 

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

573 

574 

575class ConfigWithAccess(Config): 

576 """Basic config with permissions.""" 

577 

578 access: Optional[AclStr] 

579 """Permission to read or use the object.""" 

580 permissions: Optional[PermissionsConfig] 

581 """Access rules per operation.""" 

582################################################################################ 

583 

584 

585################################################################################ 

586# /core/_error.pyinc 

587 

588 

589class Error(Exception): 

590 """Generic GWS error. 

591 

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] 

596 

597 

598class ConfigurationError(Error): 

599 """GWS configuration error.""" 

600 pass 

601 

602 

603class NotFoundError(Error): 

604 """Generic 'object not found' error.""" 

605 pass 

606 

607 

608class ForbiddenError(Error): 

609 """Generic 'forbidden' error.""" 

610 pass 

611 

612 

613class AuthenticationError(ForbiddenError): 

614 """Credentials are missing, wrong or expired.""" 

615 pass 

616 

617 

618class BadRequestError(Error): 

619 """Generic 'bad request' error.""" 

620 pass 

621 

622 

623class TooManyRequestsError(Error): 

624 """Generic 'too many requests' error.""" 

625 

626 retryAfter: int = 0 

627 """Time in seconds after which the request can be repeated.""" 

628 

629 

630class ResponseTooLargeError(Error): 

631 """Generic error when a response is too large.""" 

632 pass 

633 

634 

635class ExternalServiceError(Error): 

636 """Generic error when an external service fails.""" 

637 pass 

638 

639 

640LockBusyError = u.LockBusyError 

641"""Raised when a server lock cannot be acquired within the timeout.""" 

642################################################################################ 

643 

644 

645 

646################################################################################ 

647# /spec/types.pyinc 

648 

649 

650class ApplicationManifestPlugin(Data): 

651 """Custom plugin entry in the application manifest.""" 

652 

653 path: DirPath 

654 """Path to the plugin directory; relative paths are resolved against the manifest location.""" 

655 

656 name: str = '' 

657 """Plugin name. When omitted, the directory name is used.""" 

658 

659 

660class ApplicationManifest(Data): 

661 """Application manifest, read from a ``MANIFEST.json`` file. 

662 

663 The manifest is JSON; lines starting with ``//`` or ``#`` are ignored. 

664 """ 

665 

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

678 

679 

680class ExtObjectDescriptor(Data): 

681 """Extension object descriptor.""" 

682 

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

695 

696 

697class ExtCommandDescriptor(Data): 

698 """Command descriptor, describes the action method that handles a command.""" 

699 

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

718 

719 

720class SpecReadOption(Enum): 

721 """Options for reading values with ``SpecRuntime.read``.""" 

722 

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

735 

736 

737class CommandCategory(Enum): 

738 """Command category.""" 

739 

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

750 

751 

752class SpecRuntime: 

753 """Spec runtime. 

754 

755 Provides access to the generated specs: reading and validating values, 

756 looking up extension objects and commands, and loading classes. 

757 """ 

758 

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

765 

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. 

768 

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. 

774 

775 Returns: 

776 The parsed value. Objects are returned as ``gws.Data``. 

777 

778 Raises: 

779 ``gws.spec.core.ReadError``: If the value does not match the type. 

780 """ 

781 

782 def object_descriptor(self, type_name: str) -> Optional[ExtObjectDescriptor]: 

783 """Get an object descriptor. 

784 

785 Args: 

786 type_name: Type uid or extension name. 

787 

788 Returns: 

789 A descriptor or ``None`` if the type is not found. 

790 """ 

791 

792 def command_descriptor(self, command_category: CommandCategory, command_name: str) -> Optional[ExtCommandDescriptor]: 

793 """Get a command descriptor. 

794 

795 Args: 

796 command_category: Command category. 

797 command_name: Command name. 

798 

799 Returns: 

800 A descriptor or ``None`` if the command is not found. 

801 """ 

802 

803 def register_object(self, ext_name: ClassRef, obj_type: str, cls: type): 

804 """Register an extension class at run time. 

805 

806 The class gets the ``extName`` and ``extType`` attributes. 

807 

808 Args: 

809 ext_name: Extension category, like ``gws.ext.object.layer``. 

810 obj_type: Extension type, like ``wms``. 

811 cls: Class to register. 

812 

813 Raises: 

814 ``gws.spec.core.Error``: If the class reference is invalid. 

815 """ 

816 

817 def get_class(self, classref: ClassRef, ext_type: Optional[str] = None) -> Optional[type]: 

818 """Get a class object for a class reference. 

819 

820 The module defining the class is imported on demand. 

821 

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

826 

827 Returns: 

828 A class or ``None`` if the reference is not found. 

829 

830 Raises: 

831 ``gws.spec.core.LoadError``: If the module cannot be imported. 

832 """ 

833 

834 def parse_classref(self, classref: ClassRef) -> tuple[Optional[type], str, str]: 

835 """Parse a class reference. 

836 

837 Args: 

838 classref: Class reference. 

839 

840 Returns: 

841 A tuple ``(class object, class name, extension name)``, where only one element is set. 

842 

843 Raises: 

844 ``gws.spec.core.Error``: If the class reference is invalid. 

845 """ 

846 

847 def get_config_types(self, lang: str) -> list[dict]: 

848 """Get the configuration types as dictionaries. 

849 

850 Docstrings, titles and enum docs are taken from the strings in the given language. 

851 

852 Args: 

853 lang: Language code. 

854 

855 Returns: 

856 A list of type dictionaries. 

857 """ 

858################################################################################ 

859 

860 

861 

862################################################################################ 

863# /core/_tree.pyinc 

864 

865 

866class Object: 

867 """Basic GWS object. 

868 

869 An object has permissions and can provide properties for the client. 

870 """ 

871 

872 permissions: dict[Access, Acl] 

873 """Mapping from an access mode to a list of ACL tuples.""" 

874 

875 def props(self, user: 'User') -> Props: 

876 """Generate a ``Props`` struct for this object. 

877 

878 Do not call this method directly, use ``gws.props_of`` instead, which also checks permissions. 

879 

880 Args: 

881 user: The user for which the props should be generated. 

882 

883 Returns: 

884 A ``Props`` object or a dict. Nested objects are converted to props as well. 

885 """ 

886 

887 def __init__(self): 

888 self.permissions = {} 

889 

890 

891from .core import tree_impl 

892 

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) 

898 

899Object.__repr__ = tree_impl.object_repr 

900 

901 

902class Node(Object): 

903 """GWS object tree node. 

904 

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 """ 

909 

910 extName: str 

911 """Full extension name like ``gws.ext.object.layer.wms``.""" 

912 extType: str 

913 """Extension type like ``wms``.""" 

914 

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

925 

926 def initialize(self, config): 

927 """Initialize the node. 

928 

929 Store the configuration, set up the permissions, then run ``pre_configure`` and ``configure``. 

930 

931 Args: 

932 config: Configuration. 

933 """ 

934 return tree_impl.node_initialize(self, config) 

935 

936 def pre_configure(self): 

937 """Pre-configuration hook. 

938 

939 Called before ``configure``, when the node is initialized. 

940 """ 

941 

942 def configure(self): 

943 """Configuration hook. 

944 

945 Called when the node is initialized. Raising an exception here aborts the creation of the node. 

946 """ 

947 

948 def post_configure(self): 

949 """Post-configuration hook. 

950 

951 Called after the whole object tree has been created. 

952 """ 

953 

954 def activate(self): 

955 """Activation hook. 

956 

957 Called by ``Root.activate`` after the configuration has been loaded. 

958 """ 

959 

960 def create_child(self, classref: ClassRef, config: Config = None, **kwargs) -> Optional['Node']: 

961 """Create a child object. 

962 

963 Args: 

964 classref: Class reference. 

965 config: Configuration. 

966 **kwargs: Additional configuration properties. 

967 

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) 

972 

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. 

975 

976 Args: 

977 classref: Class reference. 

978 config: Configuration. 

979 **kwargs: Additional configuration properties. 

980 

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) 

985 

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. 

988 

989 Args: 

990 classref: Class reference. 

991 configs: List of configurations. 

992 **kwargs: Additional configuration properties. 

993 

994 Returns: 

995 A list of newly created objects. 

996 """ 

997 return tree_impl.node_create_children(self, classref, configs, **kwargs) 

998 

999 def cfg(self, key: str, default=None): 

1000 """Fetch a configuration property. 

1001 

1002 Args: 

1003 key: Property key. If it contains dots, fetch nested properties. 

1004 default: Default to return if the property is not found. 

1005 

1006 Returns: 

1007 A property value. 

1008 """ 

1009 return tree_impl.node_cfg(self, key, default) 

1010 

1011 def is_a(self, classref: ClassRef) -> bool: 

1012 """Check if the node matches the class reference. 

1013 

1014 Args: 

1015 classref: Class reference. 

1016 

1017 Returns: 

1018 ``True`` if the node matches. 

1019 """ 

1020 return tree_impl.is_a(self.root, self, classref) 

1021 

1022 def find_all(self, classref: Optional[ClassRef] = None) -> list['Node']: 

1023 """Find all direct children that match a specific class. 

1024 

1025 Args: 

1026 classref: Class reference. If omitted, all children are returned. 

1027 

1028 Returns: 

1029 A list of objects. 

1030 """ 

1031 return tree_impl.node_find_all(self, classref) 

1032 

1033 def find_first(self, classref: Optional[ClassRef] = None) -> Optional['Node']: 

1034 """Find the first direct child that matches a specific class. 

1035 

1036 Args: 

1037 classref: Class reference. If omitted, the first child is returned. 

1038 

1039 Returns: 

1040 An object or ``None``. 

1041 """ 

1042 return tree_impl.node_find_first(self, classref) 

1043 

1044 def find_closest(self, classref: Optional[ClassRef] = None) -> Optional['Node']: 

1045 """Find the closest node ancestor that matches a specific class. 

1046 

1047 Args: 

1048 classref: Class reference. If omitted, the parent is returned. 

1049 

1050 Returns: 

1051 An object or ``None``. 

1052 """ 

1053 

1054 return tree_impl.node_find_closest(self, classref) 

1055 

1056 def find_ancestors(self, classref: Optional[ClassRef] = None) -> list['Node']: 

1057 """Find node ancestors that match a specific class. 

1058 

1059 Args: 

1060 classref: Class reference. If omitted, all ancestors are returned. 

1061 

1062 Returns: 

1063 A list of objects, from the parent upwards. 

1064 """ 

1065 return tree_impl.node_find_ancestors(self, classref) 

1066 

1067 def find_descendants(self, classref: Optional[ClassRef] = None) -> list['Node']: 

1068 """Find node descendants that match a specific class. 

1069 

1070 Args: 

1071 classref: Class reference. If omitted, all descendants are returned. 

1072 

1073 Returns: 

1074 A list of objects in the depth-first order. 

1075 """ 

1076 

1077 return tree_impl.node_find_descendants(self, classref) 

1078 

1079 def enter_middleware(self, req: 'WebRequester') -> Optional['WebResponder']: 

1080 """Begin middleware processing. 

1081 

1082 Args: 

1083 req: Requester object. 

1084 

1085 Returns: 

1086 A Responder object to end the request processing, or ``None`` to continue. 

1087 """ 

1088 

1089 def exit_middleware(self, req: 'WebRequester', res: 'WebResponder'): 

1090 """Finish middleware processing. 

1091 

1092 Args: 

1093 req: Requester object. 

1094 res: Current responder object. 

1095 """ 

1096 

1097 def periodic_task(self): 

1098 """Periodic task hook. 

1099 

1100 Called by the server monitor for nodes registered with ``register_periodic_task``. 

1101 """ 

1102 

1103 

1104class Root: 

1105 """Root node of the object tree.""" 

1106 

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

1115 

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

1126 

1127 def __init__(self, specs: 'SpecRuntime'): 

1128 """Create an empty root. 

1129 

1130 Args: 

1131 specs: Specs runtime. 

1132 """ 

1133 tree_impl.root_init(self, specs) 

1134 

1135 def initialize(self, obj, config): 

1136 """Initialize a node and record configuration errors. 

1137 

1138 Args: 

1139 obj: The node. 

1140 config: Configuration. 

1141 

1142 Returns: 

1143 ``True`` if the node was initialized, ``False`` if it failed. 

1144 """ 

1145 return tree_impl.root_initialize(self, obj, config) 

1146 

1147 def post_initialize(self): 

1148 """Run ``post_configure`` on all nodes, in the reverse order of creation. 

1149 

1150 Errors are logged and recorded in ``configErrors``. 

1151 """ 

1152 return tree_impl.root_post_initialize(self) 

1153 

1154 def activate(self): 

1155 """Run ``activate`` on all nodes.""" 

1156 return tree_impl.root_activate(self) 

1157 

1158 def config_warning(self, message: str): 

1159 """Register a configuration warning. 

1160 

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

1163 

1164 Args: 

1165 message: Warning message. 

1166 """ 

1167 return tree_impl.root_config_warning(self, message) 

1168 

1169 def find_all(self, classref: Optional[ClassRef] = None) -> list['Node']: 

1170 """Find all objects that match a specific class. 

1171 

1172 Args: 

1173 classref: Class reference. 

1174 

1175 Returns: 

1176 A list of objects. 

1177 """ 

1178 return tree_impl.root_find_all(self, classref) 

1179 

1180 def find_first(self, classref: Optional[ClassRef] = None) -> Optional['Node']: 

1181 """Find the first object that matches a specific class. 

1182 

1183 Args: 

1184 classref: Class reference. 

1185 

1186 Returns: 

1187 An object or ``None``. 

1188 """ 

1189 return tree_impl.root_find_first(self, classref) 

1190 

1191 def get(self, uid: str = None, classref: Optional[ClassRef] = None) -> Optional['Node']: 

1192 """Get an object by its unique ID. 

1193 

1194 Args: 

1195 uid: Object uid. 

1196 classref: Class reference. If provided, ensures that the object matches the reference. 

1197 

1198 Returns: 

1199 An object or ``None``. 

1200 """ 

1201 return tree_impl.root_get(self, uid, classref) 

1202 

1203 def object_count(self) -> int: 

1204 """Return the number of objects in the tree. 

1205 

1206 Returns: 

1207 The number of objects. 

1208 """ 

1209 return tree_impl.root_object_count(self) 

1210 

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. 

1219 

1220 Args: 

1221 classref: Class reference. 

1222 parent: Parent object. 

1223 config: Configuration. 

1224 **kwargs: Additional configuration properties. 

1225 

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) 

1230 

1231 def create_shared(self, classref: ClassRef, config: Config = None, **kwargs) -> Optional['Node']: 

1232 """Create a shared object, attached directly to the root. 

1233 

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. 

1236 

1237 Args: 

1238 classref: Class reference. 

1239 config: Configuration. 

1240 **kwargs: Additional configuration properties. 

1241 

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) 

1246 

1247 def create_temporary(self, classref: ClassRef, config: Config = None, **kwargs) -> Optional['Node']: 

1248 """Create a temporary object, not attached to the tree. 

1249 

1250 Args: 

1251 classref: Class reference. 

1252 config: Configuration. 

1253 **kwargs: Additional configuration properties. 

1254 

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) 

1259 

1260 def create_application(self, config: Config = None, **kwargs) -> 'Application': 

1261 """Create the Application object. 

1262 

1263 Args: 

1264 config: Configuration. 

1265 **kwargs: Additional configuration properties. 

1266 

1267 Returns: 

1268 The Application object. 

1269 """ 

1270 return tree_impl.root_create_application(self, config, **kwargs) 

1271 

1272 

1273def create_root(specs: 'SpecRuntime') -> Root: 

1274 """Create a new root object. 

1275 

1276 Args: 

1277 specs: Specs runtime. 

1278 

1279 Returns: 

1280 The root object. 

1281 """ 

1282 return Root(specs) 

1283 

1284 

1285def save_root(root: Root, path: str = None) -> str: 

1286 """Pickle the root object to a file. 

1287 

1288 ``sys.path`` is pickled next to it, to ``<path>.syspath``, so that ``load_root`` can restore it. 

1289 

1290 Args: 

1291 root: The root object. 

1292 path: File path. Defaults to ``config.pickle`` in the config directory. 

1293 

1294 Returns: 

1295 The file path. 

1296 """ 

1297 return tree_impl.save_root(root, path) 

1298 

1299 

1300def load_root(path: str = None) -> Root: 

1301 """Load a pickled root object, activate it and make it the current root. 

1302 

1303 ``sys.path`` is restored first, so that plugin modules can be imported. 

1304 

1305 Args: 

1306 path: File path. Defaults to ``config.pickle`` in the config directory. 

1307 

1308 Returns: 

1309 The root object. 

1310 """ 

1311 return tree_impl.load_root(path) 

1312 

1313 

1314def activate_root(root: Root) -> Root: 

1315 """Activate the root object and make it the current root. 

1316 

1317 Args: 

1318 root: The root object. 

1319 

1320 Returns: 

1321 The root object. 

1322 """ 

1323 return tree_impl.activate_root(root) 

1324 

1325 

1326def deactivate_root(): 

1327 """Remove the current root.""" 

1328 return tree_impl.deactivate_root() 

1329 

1330 

1331def get_root() -> Root: 

1332 """Return the current root object. 

1333 

1334 Returns: 

1335 The root object set by ``activate_root`` or ``load_root``. 

1336 

1337 Raises: 

1338 Error: If there is no current root. 

1339 """ 

1340 return tree_impl.get_root() 

1341 

1342 

1343def props_of(obj: Object, user: 'User', *context) -> Optional['Props']: 

1344 """Generate props for an object, if the user is allowed to use it. 

1345 

1346 Nested objects the user cannot read are removed from the result. 

1347 

1348 Args: 

1349 obj: The object. 

1350 user: The user. 

1351 *context: Context objects for the permission check. 

1352 

1353 Returns: 

1354 A ``Props`` object, or ``None`` if the user cannot use the object. 

1355 

1356 Raises: 

1357 Error: If the object's ``props`` returns an invalid type. 

1358 """ 

1359 return tree_impl.props_of(obj, user, *context) 

1360################################################################################ 

1361 

1362 

1363 

1364################################################################################ 

1365# /lib/mapserver/types.pyinc 

1366 

1367 

1368class MapServerLayerType(Enum): 

1369 """MapServer layer type.""" 

1370 

1371 point = 'point' 

1372 """Point layer.""" 

1373 line = 'line' 

1374 """Line layer.""" 

1375 polygon = 'polygon' 

1376 """Polygon layer.""" 

1377 raster = 'raster' 

1378 """Raster layer.""" 

1379 

1380class MapServerLayerOptions(Data): 

1381 """Options for a MapServer-based layer.""" 

1382 

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################################################################################ 

1408 

1409 

1410################################################################################ 

1411# /lib/mime/types.pyinc 

1412 

1413 

1414MimeType: TypeAlias = str 

1415"""A MIME type or a file extension.""" 

1416################################################################################ 

1417 

1418 

1419################################################################################ 

1420# /lib/uom/types.pyinc 

1421 

1422 

1423class Uom(Enum): 

1424 """Unit of measure.""" 

1425 

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

1472 

1473 

1474UomValue: TypeAlias = tuple[float, Uom] 

1475"""A value with a unit, like ``(5, Uom.mm)``.""" 

1476 

1477UomValueStr: TypeAlias = str 

1478"""A value with a unit like ``5mm``.""" 

1479 

1480UomPoint: TypeAlias = tuple[float, float, Uom] 

1481"""A point with a unit, like ``(1, 2, Uom.mm)``.""" 

1482 

1483UomPointStr: TypeAlias = list[str] 

1484"""A point with a unit like ``["1mm", "2mm"]``.""" 

1485 

1486UomSize: TypeAlias = tuple[float, float, Uom] 

1487"""A size with a unit, like ``(10, 20, Uom.mm)``.""" 

1488 

1489UomSizeStr: TypeAlias = list[str] 

1490"""A size with a unit like ``["1mm", "2mm"]``.""" 

1491 

1492UomExtent: TypeAlias = tuple[float, float, float, float, Uom] 

1493"""An extent with a unit, like ``(0, 0, 10, 20, Uom.mm)``.""" 

1494 

1495UomExtentStr: TypeAlias = list[str] 

1496"""An extent with a unit like ``["1mm", "2mm", "3mm", "4mm"]``.""" 

1497################################################################################ 

1498 

1499 

1500################################################################################ 

1501# /lib/image/types.pyinc 

1502 

1503 

1504class ImageFormat(Data): 

1505 """Image format: MIME types and encoding options.""" 

1506 

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

1513 

1514 

1515class Image: 

1516 """Raster image. 

1517 

1518 Manipulation methods change the image in place and return the image itself, so that calls can be chained. 

1519 """ 

1520 

1521 def size(self) -> Size: 

1522 """Get the image size. 

1523 

1524 Returns: 

1525 A tuple ``(width, height)`` in pixels. 

1526 """ 

1527 

1528 def mode(self) -> str: 

1529 """Get the image mode. 

1530 

1531 Returns: 

1532 PIL image mode, e.g. ``RGBA``. 

1533 """ 

1534 

1535 def convert(self, mode: str) -> 'Image': 

1536 """Convert the image to a mode. 

1537 

1538 Args: 

1539 mode: PIL image mode. 

1540 

1541 Returns: 

1542 The image. 

1543 """ 

1544 

1545 def add_box(self, color=None) -> 'Image': 

1546 """Draw a 1 pixel wide frame along the image edges. 

1547 

1548 The image is converted to RGBA. 

1549 

1550 Args: 

1551 color: Line color, black by default. 

1552 

1553 Returns: 

1554 The image. 

1555 """ 

1556 

1557 def add_text(self, text: str, x=0, y=0, color=None) -> 'Image': 

1558 """Draw text on the image with the default font. 

1559 

1560 The image is converted to RGBA. 

1561 

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. 

1567 

1568 Returns: 

1569 The image. 

1570 """ 

1571 

1572 def compose(self, other: 'Image', opacity=1) -> 'Image': 

1573 """Place another image on top of this one, using alpha composition. 

1574 

1575 The other image is resized to the size of this one if needed. 

1576 

1577 Args: 

1578 other: Image to place on top. 

1579 opacity: Opacity of the other image, from 0 to 1. 

1580 

1581 Returns: 

1582 The image. 

1583 """ 

1584 

1585 def crop(self, box) -> 'Image': 

1586 """Crop the image. 

1587 

1588 Args: 

1589 box: Crop rectangle ``(left, upper, right, lower)`` in pixels. 

1590 

1591 Returns: 

1592 The image. 

1593 """ 

1594 

1595 def paste(self, other: 'Image', where=None) -> 'Image': 

1596 """Paste another image into this one. 

1597 

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

1602 

1603 Returns: 

1604 The image. 

1605 """ 

1606 

1607 def resize(self, size: Size, **kwargs) -> 'Image': 

1608 """Resize the image to a size, without keeping the aspect ratio. 

1609 

1610 Args: 

1611 size: New size ``(width, height)``. 

1612 **kwargs: Options for ``PIL.Image.resize``. The default resampling is bicubic. 

1613 

1614 Returns: 

1615 The image. 

1616 """ 

1617 

1618 def resize_to(self, width: int = 0, height: int = 0, **kwargs) -> 'Image': 

1619 """Resize the image to a width, a height or both. 

1620 

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. 

1623 

1624 Args: 

1625 width: New width. 

1626 height: New height. 

1627 **kwargs: Options for ``PIL.Image.resize``. 

1628 

1629 Returns: 

1630 The image. 

1631 """ 

1632 

1633 def rotate(self, angle: int, **kwargs) -> 'Image': 

1634 """Rotate the image counter-clockwise. 

1635 

1636 Args: 

1637 angle: Angle in degrees. 

1638 **kwargs: Options for ``PIL.Image.rotate``. The default resampling is bicubic. 

1639 

1640 Returns: 

1641 The image. 

1642 """ 

1643 

1644 def to_bytes(self, mime_type: Optional[str] = None, options: Optional[dict] = None) -> bytes: 

1645 """Encode the image. 

1646 

1647 The ``options`` dict can contain any PIL save option 

1648 (see https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html). 

1649 

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. 

1653 

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

1656 

1657 Args: 

1658 mime_type: MIME type of the output, PNG by default. 

1659 options: Encoding options. 

1660 

1661 Returns: 

1662 The encoded image. 

1663 """ 

1664 

1665 def to_base64(self, mime_type: Optional[str] = None, options: Optional[dict] = None) -> str: 

1666 """Encode the image as a base64 string. 

1667 

1668 Args: 

1669 mime_type: MIME type of the output, PNG by default. 

1670 options: Encoding options, as in ``to_bytes``. 

1671 

1672 Returns: 

1673 The base64 encoded image. 

1674 """ 

1675 

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. 

1678 

1679 Args: 

1680 mime_type: MIME type of the output, PNG by default. 

1681 options: Encoding options, as in ``to_bytes``. 

1682 

1683 Returns: 

1684 A ``data:`` URL. 

1685 """ 

1686 

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. 

1689 

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

1694 

1695 Returns: 

1696 The file path. 

1697 """ 

1698 

1699 def to_array(self) -> 'numpy.typing.NDArray': 

1700 """Convert the image to a numpy array. 

1701 

1702 Returns: 

1703 An array of shape ``(height, width)`` or ``(height, width, channels)``. 

1704 """ 

1705 

1706 def compare_to(self, other: 'Image') -> float: 

1707 """Compare this image to another one. 

1708 

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. 

1711 

1712 Args: 

1713 other: Image to compare to. 

1714 

1715 Returns: 

1716 ``0`` if the images are equal, larger values for larger differences. 

1717 """ 

1718################################################################################ 

1719 

1720 

1721################################################################################ 

1722# /lib/intl/types.pyinc 

1723 

1724 

1725LocaleUid: TypeAlias = str 

1726"""Locale UID like ``de_DE``.""" 

1727 

1728 

1729class Locale(Data): 

1730 """Locale data: language, territory, date and number conventions.""" 

1731 

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

1750 

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

1761 

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

1776 

1777 

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

1788 

1789 

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

1800 

1801 

1802class DateFormatter: 

1803 """Locale-aware date formatter.""" 

1804 

1805 def format(self, fmt: DateTimeFormat | str, date: Optional[Union['datetime.date', str]] = None) -> str: 

1806 """Format a date. 

1807 

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. 

1811 

1812 Returns: 

1813 The formatted date. 

1814 

1815 Raises: 

1816 ``Error``: If the date cannot be parsed. 

1817 """ 

1818 

1819 def short(self, date=None) -> str: 

1820 """Format a date in the short format of the locale, e.g. ``11.12.13``. 

1821 

1822 Args: 

1823 date: Date or date string, the current date by default. 

1824 

1825 Returns: 

1826 The formatted date. 

1827 """ 

1828 

1829 def medium(self, date=None) -> str: 

1830 """Format a date in the medium format of the locale, e.g. ``11.12.2013``. 

1831 

1832 Args: 

1833 date: Date or date string, the current date by default. 

1834 

1835 Returns: 

1836 The formatted date. 

1837 """ 

1838 

1839 def long(self, date=None) -> str: 

1840 """Format a date in the long format of the locale, e.g. ``11. Dezember 2013``. 

1841 

1842 Args: 

1843 date: Date or date string, the current date by default. 

1844 

1845 Returns: 

1846 The formatted date. 

1847 """ 

1848 

1849 def iso(self, date=None) -> str: 

1850 """Format a date in the ISO 8601 format, e.g. ``2013-12-11``. 

1851 

1852 Args: 

1853 date: Date or date string, the current date by default. 

1854 

1855 Returns: 

1856 The formatted date. 

1857 """ 

1858 

1859 

1860class TimeFormatter: 

1861 """Locale-aware time formatter.""" 

1862 

1863 def format(self, fmt: DateTimeFormat | str, time: Optional[Union['datetime.time', str]] = None) -> str: 

1864 """Format a time. 

1865 

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. 

1869 

1870 Returns: 

1871 The formatted time. 

1872 

1873 Raises: 

1874 ``Error``: If the time cannot be parsed. 

1875 """ 

1876 

1877 def short(self, time=None) -> str: 

1878 """Format a time in the short format of the locale, e.g. ``11:22``. 

1879 

1880 Args: 

1881 time: Time, datetime or time string, the current time by default. 

1882 

1883 Returns: 

1884 The formatted time. 

1885 """ 

1886 

1887 def medium(self, time=None) -> str: 

1888 """Format a time in the medium format of the locale, e.g. ``11:22:33``. 

1889 

1890 Args: 

1891 time: Time, datetime or time string, the current time by default. 

1892 

1893 Returns: 

1894 The formatted time. 

1895 """ 

1896 

1897 def long(self, time=None) -> str: 

1898 """Format a time in the long format of the locale, which usually includes the time zone. 

1899 

1900 Args: 

1901 time: Time, datetime or time string, the current time by default. 

1902 

1903 Returns: 

1904 The formatted time. 

1905 """ 

1906 

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

1909 

1910 Args: 

1911 time: Time, datetime or time string, the current time by default. 

1912 

1913 Returns: 

1914 The formatted time. 

1915 """ 

1916 

1917 

1918class NumberFormatter: 

1919 """Locale-aware number formatter.""" 

1920 

1921 def format(self, fmt: NumberFormat | str, n, *args, **kwargs) -> str: 

1922 """Format a number. 

1923 

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. 

1929 

1930 Returns: 

1931 The formatted number. 

1932 """ 

1933 

1934 def decimal(self, n, *args, **kwargs) -> str: 

1935 """Format a number as a decimal without group separators. 

1936 

1937 Args: 

1938 n: Number. 

1939 *args: Arguments for ``babel.numbers.format_decimal``. 

1940 **kwargs: Keyword arguments for ``babel.numbers.format_decimal``. 

1941 

1942 Returns: 

1943 The formatted number. 

1944 """ 

1945 

1946 def grouped(self, n, *args, **kwargs) -> str: 

1947 """Format a number as a decimal with group separators. 

1948 

1949 Args: 

1950 n: Number. 

1951 *args: Arguments for ``babel.numbers.format_decimal``. 

1952 **kwargs: Keyword arguments for ``babel.numbers.format_decimal``. 

1953 

1954 Returns: 

1955 The formatted number. 

1956 """ 

1957 

1958 def currency(self, n, currency: str, *args, **kwargs) -> str: 

1959 """Format a number as a currency value. 

1960 

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

1966 

1967 Returns: 

1968 The formatted value. 

1969 """ 

1970 

1971 def percent(self, n, *args, **kwargs) -> str: 

1972 """Format a number as a percentage, ``0.5`` is 50 percent. 

1973 

1974 Args: 

1975 n: Number. 

1976 *args: Arguments for ``babel.numbers.format_percent``. 

1977 **kwargs: Keyword arguments for ``babel.numbers.format_percent``. 

1978 

1979 Returns: 

1980 The formatted value. 

1981 """ 

1982################################################################################ 

1983 

1984 

1985################################################################################ 

1986# /lib/style/types.pyinc 

1987 

1988 

1989class StyleValues(Data): 

1990 """Style values, as parsed by ``gws.lib.style.parser``.""" 

1991 

1992 fill: Color 

1993 """Fill color.""" 

1994 

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

2009 

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

2030 

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

2035 

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

2078 

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

2083 

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

2088 

2089 

2090class StyleProps(Props): 

2091 """CSS Style properties.""" 

2092 

2093 cssSelector: Optional[str] 

2094 text: Optional[str] 

2095 values: Optional[dict] 

2096 

2097 

2098class Style: 

2099 """Feature style.""" 

2100 

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################################################################################ 

2108 

2109 

2110################################################################################ 

2111# /lib/xmlx/types.pyinc 

2112 

2113 

2114class XmlNamespace(Data): 

2115 """XML namespace.""" 

2116 

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

2125 

2126 

2127class XmlOptions(Data): 

2128 """XML options for parsing and serialization.""" 

2129 

2130 removeNamespaces: bool = False 

2131 """Strip namespaces when parsing: tags and attributes are local names, declarations are dropped.""" 

2132 

2133 customNamespacePrefixes: Optional[dict[str, str]] = None 

2134 """Serialization: prefixes to use instead of the default ones (namespace uri -> prefix).""" 

2135 

2136 defaultNamespace: Optional['XmlNamespace'] = None 

2137 """Serialization: elements in this namespace are written without a prefix.""" 

2138 

2139 doctype: Optional[str] = None 

2140 """Serialization: document type definition (DTD), written after the XML declaration.""" 

2141 

2142 compactWhitespace: bool = False 

2143 """Collapse whitespace in text content (parsing and serialization).""" 

2144 

2145 withNamespaceDeclarations: bool = False 

2146 """Serialization: declare all namespaces used in the tree on the root element.""" 

2147 

2148 withSchemaLocations: bool = False 

2149 """Serialization: add ``xsi:schemaLocation`` for declared namespaces that have a schema location.""" 

2150 

2151 withXmlDeclaration: bool = False 

2152 """Serialization: write the ``<?xml ...?>`` declaration.""" 

2153 

2154 

2155class XmlElement(Iterable): 

2156 """XML Element. 

2157 

2158 Implements a subset of the ``ElementTree.Element`` API. 

2159 

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 """ 

2165 

2166 tag: str 

2167 """Tag name, local or Clark.""" 

2168 

2169 name: str 

2170 """Element name (tag without a namespace).""" 

2171 

2172 text: str 

2173 """Text before first subelement.""" 

2174 

2175 tail: str 

2176 """Text after this element's end tag.""" 

2177 

2178 attrib: dict 

2179 """Dictionary of element attributes.""" 

2180 

2181 namespaces: list[XmlNamespace] 

2182 """Namespaces declared on this element (``prefix == ''`` for the default namespace).""" 

2183 

2184 def __len__(self) -> int: ... 

2185 

2186 def __iter__(self) -> Iterator['XmlElement']: ... 

2187 

2188 def __getitem__(self, item: int) -> 'XmlElement': ... 

2189 

2190 def append(self, subelement: 'XmlElement'): 

2191 """Add a child at the end of the list of children. 

2192 

2193 Args: 

2194 subelement: The element to add. 

2195 """ 

2196 

2197 def clear(self): 

2198 """Remove the attributes, namespace declarations, children, text and tail of this element.""" 

2199 

2200 def extend(self, subelements: Iterable['XmlElement']): 

2201 """Add children at the end of the list of children. 

2202 

2203 Args: 

2204 subelements: The elements to add. 

2205 """ 

2206 

2207 def find(self, path: str) -> Optional['XmlElement']: 

2208 """Find the first matching subelement. 

2209 

2210 Args: 

2211 path: Tag name or path in ``ElementTree`` syntax, with local or Clark names. 

2212 

2213 Returns: 

2214 The element, or ``None`` if nothing matches. 

2215 """ 

2216 

2217 def require(self, path: str) -> 'XmlElement': 

2218 """Find the first matching subelement, which must exist. 

2219 

2220 Args: 

2221 path: Tag name or path in ``ElementTree`` syntax, with local or Clark names. 

2222 

2223 Returns: 

2224 The element. 

2225 

2226 Raises: 

2227 gws.lib.xmlx.Error: If nothing matches. 

2228 """ 

2229 

2230 def findall(self, path: str) -> list['XmlElement']: 

2231 """Find all matching subelements. 

2232 

2233 Args: 

2234 path: Tag name or path in ``ElementTree`` syntax, with local or Clark names. 

2235 

2236 Returns: 

2237 A list of elements in document order. 

2238 """ 

2239 

2240 def findtext(self, path: str, default: str = '') -> str: 

2241 """Find the text of the first matching subelement. 

2242 

2243 Args: 

2244 path: Tag name or path in ``ElementTree`` syntax, with local or Clark names. 

2245 default: Value to return if nothing matches. 

2246 

2247 Returns: 

2248 The text of the element, or ``default``. 

2249 """ 

2250 

2251 def get(self, key: str, default: str = '') -> str: 

2252 """Get an attribute value. 

2253 

2254 Args: 

2255 key: Attribute name, local or Clark. 

2256 default: Value to return if the attribute does not exist. 

2257 

2258 Returns: 

2259 The attribute value, or ``default``. 

2260 """ 

2261 

2262 def insert(self, index: int, subelement: 'XmlElement'): 

2263 """Insert a child at the given position. 

2264 

2265 Args: 

2266 index: Position in the list of children. 

2267 subelement: The element to insert. 

2268 """ 

2269 

2270 def items(self) -> Iterable[tuple[str, Any]]: 

2271 """Get the attributes. 

2272 

2273 Returns: 

2274 The attributes as ``(name, value)`` pairs. 

2275 """ 

2276 

2277 def iter(self, tag: Optional[str] = None) -> Iterable['XmlElement']: 

2278 """Iterate over this element and all its descendants, depth-first. 

2279 

2280 Args: 

2281 tag: Only return elements with this tag; ``None`` or ``*`` returns all elements. 

2282 

2283 Returns: 

2284 An iterator of elements, starting with this element if it matches. 

2285 """ 

2286 

2287 def iterfind(self, path: str) -> Iterable['XmlElement']: 

2288 """Iterate over all matching subelements. 

2289 

2290 Args: 

2291 path: Tag name or path in ``ElementTree`` syntax, with local or Clark names. 

2292 

2293 Returns: 

2294 An iterator of elements in document order. 

2295 """ 

2296 

2297 def itertext(self) -> Iterable[str]: 

2298 """Iterate over the text content of this element and its descendants. 

2299 

2300 Returns: 

2301 An iterator of the non-empty texts and tails in document order, without the tail of this element. 

2302 """ 

2303 

2304 def keys(self) -> Iterable[str]: 

2305 """Get the attribute names. 

2306 

2307 Returns: 

2308 The attribute names. 

2309 """ 

2310 

2311 def remove(self, other: 'XmlElement'): 

2312 """Remove a child. 

2313 

2314 Args: 

2315 other: The child to remove. 

2316 

2317 Raises: 

2318 ValueError: If the element is not a child of this element. 

2319 """ 

2320 

2321 def set(self, key: str, value: Any): 

2322 """Set an attribute. 

2323 

2324 Args: 

2325 key: Attribute name, local or Clark. 

2326 value: Attribute value. 

2327 """ 

2328 

2329 # extensions 

2330 

2331 def hasattr(self, key: str) -> bool: 

2332 """Check if an attribute exists. 

2333 

2334 Args: 

2335 key: Attribute name, local or Clark. 

2336 

2337 Returns: 

2338 ``True`` if the attribute exists. 

2339 """ 

2340 

2341 def isa(self, *names: str) -> bool: 

2342 """Check if the local name of this element matches one of the given names, case-insensitively. 

2343 

2344 Args: 

2345 *names: Local names. 

2346 

2347 Returns: 

2348 ``True`` if the name matches. 

2349 """ 

2350 

2351 def add(self, tag: str, attrib: Optional[dict] = None, **extra) -> 'XmlElement': 

2352 """Create a new element and add it as a child. 

2353 

2354 Names are taken as they are (local or Clark); ``ID:name`` resolution is done by ``tag()`` only. 

2355 

2356 Args: 

2357 tag: Tag name, local or Clark. 

2358 attrib: Attributes. 

2359 **extra: Additional attributes. 

2360 

2361 Returns: 

2362 The new element. 

2363 """ 

2364 

2365 def children(self) -> list['XmlElement']: 

2366 """Get the children of this element. 

2367 

2368 Returns: 

2369 The list of children. This is the internal list, not a copy. 

2370 """ 

2371 

2372 def declare(self, *namespaces: XmlNamespace): 

2373 """Add namespace declarations to this element. 

2374 

2375 The declarations are written as ``xmlns`` attributes on output. Namespaces already declared 

2376 with the same prefix and URI are skipped. 

2377 

2378 Args: 

2379 *namespaces: Namespaces to declare. 

2380 """ 

2381 

2382 def findfirst(self, *paths) -> Optional['XmlElement']: 

2383 """Find the first element that matches one of the given paths. 

2384 

2385 Args: 

2386 *paths: Tag names or paths in ``ElementTree`` syntax, tried in order. 

2387 

2388 Returns: 

2389 The first match, or ``None``. Without paths, the first child, or ``None`` if there are no children. 

2390 """ 

2391 

2392 def textof(self, *paths) -> str: 

2393 """Get the text of the first matching element that has text. 

2394 

2395 Args: 

2396 *paths: Tag names or paths in ``ElementTree`` syntax, tried in order. 

2397 

2398 Returns: 

2399 The text, or an empty string if no matching element has text. 

2400 """ 

2401 

2402 def textlist(self, *paths, deep=False) -> list[str]: 

2403 """Collect texts from subelements. 

2404 

2405 Texts are stripped, empty texts are skipped. 

2406 

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. 

2410 

2411 Returns: 

2412 A list of texts in document order. 

2413 """ 

2414 

2415 def textdict(self, *paths, deep=False) -> dict[str, str]: 

2416 """Collect texts from subelements, keyed by tag. 

2417 

2418 Texts are stripped, empty texts are skipped. If several elements have the same tag, the last text wins. 

2419 

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. 

2423 

2424 Returns: 

2425 A dict of tags (local or Clark) and texts. 

2426 """ 

2427 

2428 def to_string(self, opts: Optional[XmlOptions] = None) -> str: 

2429 """Serialize this element and its subtree. 

2430 

2431 Args: 

2432 opts: Serialization options. 

2433 

2434 Returns: 

2435 An XML string. 

2436 

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 """ 

2441 

2442 def to_dict(self) -> dict: 

2443 """Convert the element tree to a dict. 

2444 

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################################################################################ 

2450 

2451 

2452 

2453################################################################################ 

2454# /lib/crs/types.pyinc 

2455 

2456 

2457CrsName: TypeAlias = int | str 

2458"""A CRS code like ``EPSG:3857`` or a SRID like ``3857``.""" 

2459 

2460 

2461class CrsFormat(Enum): 

2462 """CRS name format.""" 

2463 

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

2480 

2481 

2482class Axis(Enum): 

2483 """Axis orientation.""" 

2484 

2485 xy = 'xy' 

2486 """XY (longitude/latitude) axis orientation.""" 

2487 yx = 'yx' 

2488 """YX (latitude/longitude) axis orientation.""" 

2489 

2490 

2491class Bounds(Data): 

2492 """Geo-referenced extent: an extent together with its CRS.""" 

2493 

2494 crs: 'Crs' 

2495 """Coordinate reference system of the extent.""" 

2496 extent: Extent 

2497 """Extent in the coordinates of ``crs``.""" 

2498 

2499 

2500class Crs: 

2501 """Coordinate reference system.""" 

2502 

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

2545 

2546 def axis_for_format(self, fmt: 'CrsFormat') -> Axis: 

2547 """Get the axis orientation implied by a CRS name format. 

2548 

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. 

2554 

2555 Args: 

2556 fmt: CRS name format. 

2557 

2558 Returns: 

2559 The axis orientation. 

2560 """ 

2561 

2562 def clip_wgs_extent(self, wgs_extent: Extent) -> Optional[Extent]: 

2563 """Clip a WGS extent to the maximal extent of this CRS. 

2564 

2565 Args: 

2566 wgs_extent: Extent in the WGS projection. 

2567 

2568 Returns: 

2569 The clipped extent in the WGS projection, or ``None`` if there is no intersection. 

2570 """ 

2571 

2572 def extent_size_in_meters(self, extent: Extent) -> Size: 

2573 """Calculate the width and height of an extent in meters. 

2574 

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. 

2578 

2579 Args: 

2580 extent: Extent in this CRS. 

2581 

2582 Returns: 

2583 A ``(width, height)`` tuple in meters. 

2584 

2585 Raises: 

2586 ``gws.lib.crs.Error``: If this is a projected CRS with units other than meters. 

2587 """ 

2588 

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. 

2591 

2592 Args: 

2593 xy: Point in this CRS. 

2594 dist: Distance in meters. 

2595 az: Azimuth in degrees (0 = North, 90 = East, etc.). 

2596 

2597 Returns: 

2598 The offset point in this CRS. 

2599 

2600 Raises: 

2601 ``gws.lib.crs.Error``: If this is a projected CRS with units other than meters. 

2602 """ 

2603 

2604 def to_geojson(self) -> dict: 

2605 """Return a GeoJSON representation of the CRS. 

2606 

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

2609 

2610 Returns: 

2611 A GeoJSON ``crs`` dict. 

2612 """ 

2613 

2614 def to_string(self, fmt: Optional['CrsFormat'] = None) -> str: 

2615 """Return the name of the CRS in a given format. 

2616 

2617 Args: 

2618 fmt: Format to use, ``CrsFormat.epsg`` by default. 

2619 

2620 Returns: 

2621 The CRS name, like ``EPSG:3857``. 

2622 """ 

2623 

2624 def transform_extent(self, extent: Extent, crs_to: 'Crs') -> Extent: 

2625 """Transform an Extent from this CRS to another. 

2626 

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. 

2630 

2631 Args: 

2632 extent: Extent in this CRS. 

2633 crs_to: Target CRS. 

2634 

2635 Returns: 

2636 The transformed Extent, with min and max values in order. 

2637 """ 

2638 

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. 

2641 

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. 

2644 

2645 Args: 

2646 extent: Extent in this CRS. 

2647 res: Resolution in units of this CRS per pixel. 

2648 crs_to: Target CRS. 

2649 

2650 Returns: 

2651 The resolution in units of the target CRS per pixel, or ``0.0`` if the transformation fails. 

2652 """ 

2653 

2654 def transformer(self, crs_to: 'Crs') -> Callable: 

2655 """Create a transformer function to another CRS. 

2656 

2657 The function always uses the XY (easting/longitude first) axis order. 

2658 

2659 Args: 

2660 crs_to: Target CRS. 

2661 

2662 Returns: 

2663 A function that takes ``x, y`` and returns a transformed ``(x, y)`` tuple. 

2664 """ 

2665################################################################################ 

2666 

2667 

2668################################################################################ 

2669# /lib/shape/types.pyinc 

2670 

2671 

2672class ShapeProps(Props): 

2673 """Shape properties.""" 

2674 

2675 crs: str 

2676 geometry: dict 

2677 

2678 

2679class Shape(Object): 

2680 """Geo-referenced geometry.""" 

2681 

2682 type: GeometryType 

2683 """Geometry type.""" 

2684 

2685 crs: 'Crs' 

2686 """CRS of this shape.""" 

2687 

2688 x: Optional[float] 

2689 """X-coordinate for Point geometries, None otherwise.""" 

2690 

2691 y: Optional[float] 

2692 """Y-coordinate for Point geometries, None otherwise.""" 

2693 

2694 # common props 

2695 

2696 def area(self) -> float: 

2697 """Compute the area of the geometry. 

2698 

2699 Returns: 

2700 The area in CRS units, 0 for geometries without an area. 

2701 """ 

2702 

2703 def bounds(self) -> Bounds: 

2704 """Compute the bounds of this shape. 

2705 

2706 Returns: 

2707 A Bounds object in the CRS of this shape. 

2708 """ 

2709 

2710 def centroid(self) -> 'Shape': 

2711 """Compute the centroid of this shape. 

2712 

2713 Returns: 

2714 A Point shape. 

2715 """ 

2716 

2717 def center(self) -> tuple[float, float]: 

2718 """Compute the coordinates of the centroid. 

2719 

2720 Returns: 

2721 A tuple ``(x, y)``. 

2722 """ 

2723 

2724 # formats 

2725 

2726 def to_wkb(self) -> bytes: 

2727 """Convert this shape to WKB. 

2728 

2729 Returns: 

2730 WKB bytes. 

2731 """ 

2732 

2733 def to_wkb_hex(self) -> str: 

2734 """Convert this shape to hex-encoded WKB. 

2735 

2736 Returns: 

2737 A hex string. 

2738 """ 

2739 

2740 def to_ewkb(self) -> bytes: 

2741 """Convert this shape to EWKB, which includes the SRID. 

2742 

2743 Returns: 

2744 EWKB bytes. 

2745 """ 

2746 

2747 def to_ewkb_hex(self) -> str: 

2748 """Convert this shape to hex-encoded EWKB, which includes the SRID. 

2749 

2750 Returns: 

2751 A hex string. 

2752 """ 

2753 

2754 def to_wkt(self, trim=False, rounding_precision=-1, output_dimension=3) -> str: 

2755 """Convert this shape to WKT. 

2756 

2757 Whitespace around commas and parentheses is removed. 

2758 

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. 

2763 

2764 Returns: 

2765 A WKT string. 

2766 """ 

2767 

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

2770 

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. 

2775 

2776 Returns: 

2777 An EWKT string. 

2778 """ 

2779 

2780 def to_geojson(self, keep_crs=False) -> dict: 

2781 """Convert this shape to a GeoJSON geometry dict. 

2782 

2783 Args: 

2784 keep_crs: Keep the CRS of this shape, otherwise transform the coordinates to WGS84. 

2785 

2786 Returns: 

2787 A GeoJSON geometry dict. 

2788 """ 

2789 

2790 def to_precision(self, prec: int) -> 'Shape': 

2791 """Create a copy of this shape with coordinates snapped to the given precision. 

2792 

2793 Args: 

2794 prec: Number of decimal places. 

2795 

2796 Returns: 

2797 A new shape. 

2798 """ 

2799 

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. 

2802 

2803 Returns: 

2804 Shape props. 

2805 """ 

2806 

2807 # predicates (https://shapely.readthedocs.io/en/stable/manual.html#predicates-and-relationships) 

2808 

2809 def is_empty(self) -> bool: 

2810 """Check if this shape is empty. 

2811 

2812 Returns: 

2813 ``True`` if this shape is empty. 

2814 """ 

2815 

2816 def is_ring(self) -> bool: 

2817 """Check if this shape is a closed and simple line. 

2818 

2819 Returns: 

2820 ``True`` if this shape is a ring. 

2821 """ 

2822 

2823 def is_simple(self) -> bool: 

2824 """Check if this shape is simple, that is, has no self-intersections. 

2825 

2826 Returns: 

2827 ``True`` if this shape is simple. 

2828 """ 

2829 

2830 def is_valid(self) -> bool: 

2831 """Check if this shape is valid. 

2832 

2833 Returns: 

2834 ``True`` if this shape is valid. 

2835 """ 

2836 

2837 def equals(self, other: 'Shape') -> bool: 

2838 """Check if this shape is spatially equal to the other. 

2839 

2840 The other shape is transformed to the CRS of this shape. The same applies to 

2841 all binary predicates. 

2842 

2843 Args: 

2844 other: Another shape. 

2845 

2846 Returns: 

2847 ``True`` if the shapes are equal. 

2848 """ 

2849 

2850 def contains(self, other: 'Shape') -> bool: 

2851 """Check if this shape contains the other. 

2852 

2853 Args: 

2854 other: Another shape. 

2855 

2856 Returns: 

2857 ``True`` if this shape contains the other. 

2858 """ 

2859 

2860 def covers(self, other: 'Shape') -> bool: 

2861 """Check if this shape covers the other. 

2862 

2863 Args: 

2864 other: Another shape. 

2865 

2866 Returns: 

2867 ``True`` if this shape covers the other. 

2868 """ 

2869 

2870 def covered_by(self, other: 'Shape') -> bool: 

2871 """Check if this shape is covered by the other. 

2872 

2873 Args: 

2874 other: Another shape. 

2875 

2876 Returns: 

2877 ``True`` if this shape is covered by the other. 

2878 """ 

2879 

2880 def crosses(self, other: 'Shape') -> bool: 

2881 """Check if this shape crosses the other. 

2882 

2883 Args: 

2884 other: Another shape. 

2885 

2886 Returns: 

2887 ``True`` if this shape crosses the other. 

2888 """ 

2889 

2890 def disjoint(self, other: 'Shape') -> bool: 

2891 """Check if this shape does not intersect the other. 

2892 

2893 Args: 

2894 other: Another shape. 

2895 

2896 Returns: 

2897 ``True`` if the shapes have no point in common. 

2898 """ 

2899 

2900 def intersects(self, other: 'Shape') -> bool: 

2901 """Check if this shape intersects the other. 

2902 

2903 Args: 

2904 other: Another shape. 

2905 

2906 Returns: 

2907 ``True`` if the shapes have at least one point in common. 

2908 """ 

2909 

2910 def overlaps(self, other: 'Shape') -> bool: 

2911 """Check if this shape overlaps the other. 

2912 

2913 Args: 

2914 other: Another shape. 

2915 

2916 Returns: 

2917 ``True`` if this shape overlaps the other. 

2918 """ 

2919 

2920 def touches(self, other: 'Shape') -> bool: 

2921 """Check if this shape touches the other. 

2922 

2923 Args: 

2924 other: Another shape. 

2925 

2926 Returns: 

2927 ``True`` if this shape touches the other. 

2928 """ 

2929 

2930 def within(self, other: 'Shape') -> bool: 

2931 """Check if this shape is within the other. 

2932 

2933 Args: 

2934 other: Another shape. 

2935 

2936 Returns: 

2937 ``True`` if this shape is within the other. 

2938 """ 

2939 

2940 # set operations 

2941 

2942 def union(self, others: list['Shape']) -> 'Shape': 

2943 """Compute the union of this shape and other shapes. 

2944 

2945 Args: 

2946 others: Other shapes, transformed to the CRS of this shape. 

2947 

2948 Returns: 

2949 A new shape, or this shape if ``others`` is empty. 

2950 """ 

2951 

2952 def intersection(self, *others: 'Shape') -> 'Shape': 

2953 """Compute the intersection of this shape and other shapes. 

2954 

2955 Args: 

2956 *others: Other shapes, transformed to the CRS of this shape. 

2957 

2958 Returns: 

2959 A new shape, or this shape if no others are given. 

2960 """ 

2961 

2962 # convertors 

2963 

2964 def to_multi(self) -> 'Shape': 

2965 """Convert a single geometry shape to a multi-geometry one. 

2966 

2967 Returns: 

2968 A multi-geometry shape for a point, a line string or a polygon, otherwise this shape. 

2969 """ 

2970 

2971 def to_type(self, new_type: 'GeometryType') -> 'Shape': 

2972 """Convert this shape to another geometry type. 

2973 

2974 Only the conversion from a single to the respective multi-geometry is supported. 

2975 

2976 Args: 

2977 new_type: Target geometry type. ``geometry`` and the current type return this shape. 

2978 

2979 Returns: 

2980 A converted shape. 

2981 

2982 Raises: 

2983 ``gws.Error``: If the conversion is not supported. 

2984 """ 

2985 

2986 def to_2d(self) -> 'Shape': 

2987 """Convert this shape to 2 dimensions. 

2988 

2989 Returns: 

2990 A 2D shape, or this shape if it is already 2D. 

2991 """ 

2992 

2993 # misc 

2994 

2995 def tolerance_polygon(self, tolerance=None, quad_segs=None) -> 'Shape': 

2996 """Build a buffer polygon around this shape. 

2997 

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. 

3001 

3002 Args: 

3003 tolerance: Buffer radius in CRS units, or in meters for geographic CRS. 

3004 quad_segs: Number of segments per quarter circle. 

3005 

3006 Returns: 

3007 A polygon shape. 

3008 """ 

3009 

3010 def transformed_to(self, crs: 'Crs') -> 'Shape': 

3011 """Transform this shape to another CRS. 

3012 

3013 Args: 

3014 crs: Target CRS. 

3015 

3016 Returns: 

3017 A transformed shape, or this shape if the CRS is the same. 

3018 """ 

3019################################################################################ 

3020 

3021 

3022################################################################################ 

3023# /lib/grid/types.pyinc 

3024 

3025 

3026MapTile: TypeAlias = tuple[int, int, int] 

3027"""Grid tile: ``(x, y, z)``.""" 

3028 

3029MapTileRange: TypeAlias = tuple[int, int, int, int, int] 

3030"""Rectangle of tiles at one level: ``(min_x, min_y, max_x, max_y, z)``.""" 

3031 

3032class MapGrid(Data): 

3033 """Fixed tile grid over a CRS, origin north-west. 

3034 

3035 Level ``z`` has the resolution ``baseResolution / 2**z``. See ``gws.lib.grid``. 

3036 """ 

3037 

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

3046 

3047 

3048class TileMatrix(Data): 

3049 """Tile matrix, one level of a tile matrix set, as in WMTS.""" 

3050 

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

3071 

3072 

3073class TileMatrixSet(Data): 

3074 """Tile matrix set, a pyramid of tile matrices, as in WMTS.""" 

3075 

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################################################################################ 

3083 

3084 

3085################################################################################ 

3086# /gis/cache/types.pyinc 

3087 

3088 

3089class MapCache(Data): 

3090 """Tile cache settings of a grabber.""" 

3091 

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

3102 

3103 

3104class TileStoreStats(Data): 

3105 """Tile store statistics.""" 

3106 

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

3113 

3114 

3115class TileStore: 

3116 """Storage for encoded map tiles of one grid. 

3117 

3118 Tiles are addressed by ``(x, y, z)``. A tile counts as stored only while it is younger than ``maxAge``. 

3119 """ 

3120 

3121 baseDir: str 

3122 """Base directory of the store.""" 

3123 maxAge: int 

3124 """Max. age of stored tiles in seconds.""" 

3125 

3126 def stats(self) -> TileStoreStats: 

3127 """Compute statistics for the whole store. 

3128 

3129 Returns: 

3130 Number and size of stored tiles. The tile range is not set. 

3131 """ 

3132 

3133 def stats_for_level(self, z: int) -> TileStoreStats: 

3134 """Compute statistics for a level. 

3135 

3136 Args: 

3137 z: Zoom level. 

3138 

3139 Returns: 

3140 Number, size and bounding tile range of the stored tiles of the level. 

3141 """ 

3142 

3143 def path(self, mt: MapTile) -> str: 

3144 """Return the file path of a tile. 

3145 

3146 Args: 

3147 mt: Tile. 

3148 

3149 Returns: 

3150 The file path, whether the tile exists or not. 

3151 """ 

3152 

3153 def has(self, mt: MapTile) -> bool: 

3154 """Check if a tile is stored. 

3155 

3156 Args: 

3157 mt: Tile. 

3158 

3159 Returns: 

3160 ``True`` if the tile is stored and younger than ``maxAge``. 

3161 """ 

3162 

3163 def read(self, mt: MapTile) -> Optional[bytes]: 

3164 """Read a stored tile. 

3165 

3166 Args: 

3167 mt: Tile. 

3168 

3169 Returns: 

3170 The tile content, or ``None`` if the tile is missing, stale or unreadable. 

3171 """ 

3172 

3173 def write(self, mt: MapTile, blob: bytes): 

3174 """Store a tile. 

3175 

3176 Args: 

3177 mt: Tile. 

3178 blob: Encoded tile content. 

3179 """ 

3180 

3181 def drop(self): 

3182 """Remove the whole store.""" 

3183 

3184 def drop_level(self, z: int): 

3185 """Remove all tiles of a level. 

3186 

3187 Args: 

3188 z: Zoom level. 

3189 """ 

3190 

3191 def drop_range(self, mtr: MapTileRange): 

3192 """Remove the tiles of a range. 

3193 

3194 Args: 

3195 mtr: Tile range. 

3196 """ 

3197################################################################################ 

3198 

3199 

3200################################################################################ 

3201# /gis/render/types.pyinc 

3202 

3203 

3204class MapView(Data): 

3205 """Geometry of a rendered map.""" 

3206 

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

3221 

3222 

3223class MapRenderInputPlaneType(Enum): 

3224 """Type of a map render input plane.""" 

3225 

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

3236 

3237 

3238class MapRenderInputPlane(Data): 

3239 """A plane of a map to render.""" 

3240 

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

3259 

3260 

3261class MapRenderInput(Data): 

3262 """Input of the map renderer.""" 

3263 

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

3290 

3291 

3292class MapRenderOutputPlaneType(Enum): 

3293 """Type of a map render output plane.""" 

3294 

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

3301 

3302 

3303class MapRenderOutputPlane(Data): 

3304 """A plane of a rendered map.""" 

3305 

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

3314 

3315 

3316class MapRenderOutput(Data): 

3317 """Output of the map renderer.""" 

3318 

3319 planes: list['MapRenderOutputPlane'] 

3320 """Rendered planes, bottom to top.""" 

3321 view: MapView 

3322 """Map view of the vector planes.""" 

3323 

3324 

3325class LayerRenderInputType(Enum): 

3326 """Type of a layer render request.""" 

3327 

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

3334 

3335 

3336class LayerRenderInput(Data): 

3337 """Input of a layer render request.""" 

3338 

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

3361 

3362 

3363class LayerRenderOutput(Data): 

3364 """Output of a layer render request.""" 

3365 

3366 content: bytes 

3367 """Encoded image, for the ``box`` and ``tile`` types.""" 

3368 tags: list[XmlElement] 

3369 """SVG elements, for the ``svg`` type.""" 

3370################################################################################ 

3371 

3372 

3373################################################################################ 

3374# /gis/source/types.pyinc 

3375 

3376 

3377class SourceStyle(Data): 

3378 """A style of a source layer, as listed in the capabilities of a service.""" 

3379 

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

3388 

3389 

3390class SourceLayer(Data): 

3391 """A layer of an external source, such as a WMS, WFS or WMTS service or a QGIS project. 

3392 

3393 Source layers are read from capabilities and form a tree. The ``a*`` properties 

3394 are set by ``gws.gis.source.check_layers``. 

3395 """ 

3396 

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

3403 

3404 dataSource: dict 

3405 """Parsed data source of a QGIS layer.""" 

3406 metadata: 'Metadata' 

3407 """Layer metadata.""" 

3408 

3409 supportedCrs: list['Crs'] 

3410 """CRS supported by the source for this layer.""" 

3411 wgsExtent: Extent 

3412 """Layer extent in WGS84.""" 

3413 

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

3424 

3425 layers: list['SourceLayer'] 

3426 """Sub-layers.""" 

3427 

3428 name: str 

3429 """Layer name, used in requests to the source.""" 

3430 title: str 

3431 """Layer title.""" 

3432 

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

3439 

3440 styles: list[SourceStyle] 

3441 """Available styles.""" 

3442 defaultStyle: Optional[SourceStyle] 

3443 """Default style.""" 

3444 

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

3453 

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################################################################################ 

3459 

3460 

3461 

3462################################################################################ 

3463# /config/types.pyinc 

3464 

3465 

3466class ConfigLocation(Data): 

3467 """Location in the configuration tree.""" 

3468 

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

3477 

3478 

3479class ConfigErrorInfo(Data): 

3480 """Full information about a configuration error.""" 

3481 

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

3496 

3497 

3498class ConfigContext(Data): 

3499 """Shared state for parsing and validating a configuration.""" 

3500 

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

3511 

3512 

3513 

3514class ConfigResult(Data): 

3515 """Result of a configuration run.""" 

3516 

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################################################################################ 

3528 

3529 

3530################################################################################ 

3531# /server/types.pyinc 

3532 

3533 

3534class ServerManager(Node): 

3535 """Server configuration manager. 

3536 

3537 Holds the ``server`` configuration and creates the configuration files for 

3538 the embedded servers and the server start script. 

3539 """ 

3540 

3541 templates: list['Template'] 

3542 """Templates for the server configuration files and the start script.""" 

3543 

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. 

3546 

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 """ 

3552 

3553 

3554class ServerMonitor(Node): 

3555 """Server monitor. 

3556 

3557 Watches configuration files and directories and reconfigures the server 

3558 when they change, and runs periodic tasks of registered objects. 

3559 """ 

3560 

3561 def watch_directory(self, path: str, pattern: 'Regex', recursive=False): 

3562 """Add a directory to watch. 

3563 

3564 Args: 

3565 path: Directory path. 

3566 pattern: Regex pattern for file names to watch. 

3567 recursive: Also watch subdirectories. 

3568 """ 

3569 

3570 def watch_file(self, path: str): 

3571 """Add a file to watch. 

3572 

3573 Args: 

3574 path: File path. 

3575 """ 

3576 

3577 def register_periodic_task(self, obj: Node, frequency: int = 0): 

3578 """Register an object as a periodic task handler. 

3579 

3580 Args: 

3581 obj: A node with a ``periodic_task`` method. 

3582 frequency: Interval between runs in seconds, the monitor default if 0. 

3583 

3584 Raises: 

3585 ``gws.Error``: If the object has no ``periodic_task`` method. 

3586 """ 

3587 

3588 def schedule_reload(self, with_reconfigure: bool = False): 

3589 """Schedule a reload of the web and spool backends. 

3590 

3591 The reload is performed by the monitor on its next tick. 

3592 

3593 Args: 

3594 with_reconfigure: Reconfigure the server before reloading. 

3595 """ 

3596 

3597 def start(self): 

3598 """Start watching files and register the timer that drives the monitor. 

3599 

3600 Must be called in a uWSGI process. 

3601 """ 

3602################################################################################ 

3603 

3604 

3605 

3606################################################################################ 

3607# /base/metadata/types.pyinc 

3608 

3609 

3610class MetadataLink(Data): 

3611 """Link to a metadata document or another resource related to an object.""" 

3612 

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

3633 

3634 

3635class Metadata(Data): 

3636 """Metadata of an object, used in the client, in OWS services and in catalog records.""" 

3637 

3638 name: str 

3639 """Object name.""" 

3640 title: str 

3641 """Object title.""" 

3642 

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

3667 

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

3700 

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

3707 

3708 metaLinks: list[MetadataLink] 

3709 """Links to metadata documents.""" 

3710 serviceMetadataURL: str 

3711 """URL of the service metadata document.""" 

3712 

3713 catalogCitationUid: str 

3714 """Identifier of the resource in catalog records.""" 

3715 catalogUid: str 

3716 """Identifier of the metadata record.""" 

3717 

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

3726 

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

3737 

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

3752 

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

3757 

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################################################################################ 

3789 

3790 

3791################################################################################ 

3792# /base/feature/types.pyinc 

3793 

3794 

3795FeatureUid: TypeAlias = str 

3796"""Unique Feature id.""" 

3797 

3798class FeatureRecord(Data): 

3799 """Raw data from a feature source.""" 

3800 

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

3811 

3812 

3813class FeatureProps(Props): 

3814 """Feature Proprieties.""" 

3815 

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 

3825 

3826 

3827class Feature: 

3828 """Feature object. 

3829 

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 """ 

3833 

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

3856 

3857 def get(self, name: str, default=None) -> Any: 

3858 """Get an attribute value. 

3859 

3860 Args: 

3861 name: Attribute name. 

3862 default: Value to return if the attribute does not exist. 

3863 

3864 Returns: 

3865 The attribute value, or ``default``. 

3866 """ 

3867 

3868 def has(self, name: str) -> bool: 

3869 """Check if an attribute exists. 

3870 

3871 Args: 

3872 name: Attribute name. 

3873 

3874 Returns: 

3875 ``True`` if the attribute exists. 

3876 """ 

3877 

3878 def set(self, name: str, value: Any) -> 'Feature': 

3879 """Set an attribute value. 

3880 

3881 Args: 

3882 name: Attribute name. 

3883 value: Attribute value. 

3884 

3885 Returns: 

3886 The feature itself. 

3887 """ 

3888 

3889 def raw(self, name: str) -> Any: 

3890 """Get a raw attribute value from the record. 

3891 

3892 Args: 

3893 name: Attribute name. 

3894 

3895 Returns: 

3896 The value, or ``None`` if the record has no such attribute. 

3897 """ 

3898 

3899 def render_views(self, templates: list['Template'], **kwargs) -> 'Feature': 

3900 """Render feature views and store them in ``views``. 

3901 

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. 

3905 

3906 Args: 

3907 templates: Feature templates. 

3908 **kwargs: Extra template arguments. 

3909 

3910 Returns: 

3911 The feature itself. 

3912 """ 

3913 

3914 def shape(self) -> Optional['Shape']: 

3915 """Get the feature geometry. 

3916 

3917 Returns: 

3918 The geometry, or ``None`` if the model has no geometry or the feature has no value. 

3919 """ 

3920 

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. 

3923 

3924 Args: 

3925 view: Map view. The geometry is transformed to its CRS. 

3926 label: Label text. 

3927 style: Style. 

3928 

3929 Returns: 

3930 A list of SVG elements, empty if the feature has no geometry. 

3931 """ 

3932 

3933 def to_geojson(self, keep_crs=False) -> dict: 

3934 """Convert the feature to a GeoJSON feature. 

3935 

3936 The geometry is converted to WGS84 unless ``keep_crs`` is set. The uid 

3937 is added as the ``id`` property. 

3938 

3939 Args: 

3940 keep_crs: Keep the geometry coordinates in the feature CRS. 

3941 

3942 Returns: 

3943 A GeoJSON feature dict. 

3944 """ 

3945 

3946 def transform_to(self, crs: 'Crs') -> 'Feature': 

3947 """Transform the feature geometry to another CRS, in place. 

3948 

3949 Args: 

3950 crs: Target CRS. 

3951 

3952 Returns: 

3953 The feature itself. 

3954 """ 

3955 

3956 def uid(self) -> FeatureUid: 

3957 """Get the unique id of the feature. 

3958 

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################################################################################ 

3964 

3965 

3966 

3967################################################################################ 

3968# /base/action/types.pyinc 

3969 

3970 

3971class ActionManager(Node): 

3972 """Action manager. 

3973 

3974 Locates actions in projects and the application and prepares command calls. 

3975 """ 

3976 

3977 def actions_for_project(self, project: 'Project', user: 'User') -> list['Action']: 

3978 """Get the actions a user can use in a project. 

3979 

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. 

3982 

3983 Args: 

3984 project: The project. 

3985 user: The user. 

3986 

3987 Returns: 

3988 A list of actions. 

3989 """ 

3990 

3991 def find_action(self, project: Optional['Project'], ext_type: str, user: 'User') -> Optional['Action']: 

3992 """Find an action by its type. 

3993 

3994 Searches the project actions first, if a project is given, then the application actions. 

3995 

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. 

4000 

4001 Returns: 

4002 The action object, or ``None`` if not found. 

4003 

4004 Raises: 

4005 ForbiddenError: If the action is found but the user may not use it. 

4006 """ 

4007 

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. 

4018 

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. 

4022 

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. 

4030 

4031 Returns: 

4032 A tuple of the bound command method and the parsed request object. 

4033 

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 """ 

4039 

4040 

4041class Action(Node): 

4042 """Server action. 

4043 

4044 An action is a configurable object that provides server commands. 

4045 """ 

4046################################################################################ 

4047 

4048 

4049################################################################################ 

4050# /base/auth/types.pyinc 

4051 

4052 

4053class User(Object): 

4054 """User. 

4055 

4056 A user has a set of roles, which are checked against the permissions of 

4057 objects to decide access. 

4058 """ 

4059 

4060 isGuest: bool 

4061 """The user is the guest user.""" 

4062 

4063 authProvider: 'AuthProvider' 

4064 """The provider that created the user.""" 

4065 

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

4074 

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

4089 

4090 def acl_bit(self, access: Access, obj: Object) -> Optional[int]: 

4091 """Get the access decision for an object itself, without parents. 

4092 

4093 Args: 

4094 access: Access mode. 

4095 obj: The object. 

4096 

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 """ 

4101 

4102 def can(self, access: Access, obj: Object, *context) -> bool: 

4103 """Check if the user can access an object. 

4104 

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. 

4107 

4108 Args: 

4109 access: Access mode. 

4110 obj: The object. 

4111 *context: Further objects to check, before the parents. 

4112 

4113 Returns: 

4114 ``True`` if access is granted. 

4115 """ 

4116 

4117 def can_create(self, obj: Object, *context) -> bool: 

4118 """Check if the user has the ``create`` permission on an object. 

4119 

4120 Args: 

4121 obj: The object. 

4122 *context: Further objects to check, before the parents. 

4123 

4124 Returns: 

4125 ``True`` if access is granted. 

4126 """ 

4127 

4128 def can_delete(self, obj: Object, *context) -> bool: 

4129 """Check if the user has the ``delete`` permission on an object. 

4130 

4131 Args: 

4132 obj: The object. 

4133 *context: Further objects to check, before the parents. 

4134 

4135 Returns: 

4136 ``True`` if access is granted. 

4137 """ 

4138 

4139 def can_read(self, obj: Object, *context) -> bool: 

4140 """Check if the user has the ``read`` permission on an object. 

4141 

4142 Args: 

4143 obj: The object. 

4144 *context: Further objects to check, before the parents. 

4145 

4146 Returns: 

4147 ``True`` if access is granted. 

4148 """ 

4149 

4150 def can_use(self, obj: Object, *context) -> bool: 

4151 """Check if the user can use an object, which requires the ``read`` permission. 

4152 

4153 Args: 

4154 obj: The object. 

4155 *context: Further objects to check, before the parents. 

4156 

4157 Returns: 

4158 ``True`` if access is granted. 

4159 """ 

4160 

4161 def can_write(self, obj: Object, *context) -> bool: 

4162 """Check if the user has the ``write`` permission on an object. 

4163 

4164 Args: 

4165 obj: The object. 

4166 *context: Further objects to check, before the parents. 

4167 

4168 Returns: 

4169 ``True`` if access is granted. 

4170 """ 

4171 

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. 

4174 

4175 Args: 

4176 obj: The object. 

4177 *context: Further objects to check, before the parents. 

4178 

4179 Returns: 

4180 ``True`` if access is granted. 

4181 """ 

4182 

4183 def has_role(self, role: str) -> bool: 

4184 """Check if the user has a role. 

4185 

4186 Args: 

4187 role: Role name. 

4188 

4189 Returns: 

4190 ``True`` if the user has the role. 

4191 """ 

4192 

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. 

4195 

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. 

4200 

4201 Returns: 

4202 The object, or ``None`` if it does not exist or the user may not access it. 

4203 """ 

4204 

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. 

4207 

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. 

4212 

4213 Returns: 

4214 The object. 

4215 

4216 Raises: 

4217 NotFoundError: If the object does not exist. 

4218 ForbiddenError: If the user may not access the object. 

4219 """ 

4220 

4221 def require_project(self, uid: str = None) -> 'Project': 

4222 """Get a project the user can read. 

4223 

4224 Args: 

4225 uid: Project uid. 

4226 

4227 Returns: 

4228 The project. 

4229 

4230 Raises: 

4231 NotFoundError: If the project does not exist. 

4232 ForbiddenError: If the user may not read the project. 

4233 """ 

4234 

4235 def require_layer(self, uid=None) -> 'Layer': 

4236 """Get a layer the user can read. 

4237 

4238 Args: 

4239 uid: Layer uid. 

4240 

4241 Returns: 

4242 The layer. 

4243 

4244 Raises: 

4245 NotFoundError: If the layer does not exist. 

4246 ForbiddenError: If the user may not read the layer. 

4247 """ 

4248 

4249 

4250class AuthManager(Node): 

4251 """Authorization manager. 

4252 

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 """ 

4256 

4257 guestSession: 'AuthSession' 

4258 """Session of the guest user, used for requests without a session.""" 

4259 

4260 guestUser: 'User' 

4261 """The guest user.""" 

4262 systemUser: 'User' 

4263 """The system user, allowed everything.""" 

4264 

4265 providers: list['AuthProvider'] 

4266 """Authentication providers.""" 

4267 methods: list['AuthMethod'] 

4268 """Authentication methods.""" 

4269 mfAdapters: list['AuthMultiFactorAdapter'] 

4270 """Multi-factor adapters.""" 

4271 

4272 sessionMgr: 'AuthSessionManager' 

4273 """Session manager.""" 

4274 

4275 def authenticate(self, method: 'AuthMethod', credentials: Data, req: 'WebRequester') -> Optional['User']: 

4276 """Authenticate a user with the providers that allow the method. 

4277 

4278 Args: 

4279 method: The authentication method. 

4280 credentials: The credentials, for example ``username`` and ``password``. 

4281 req: The web request. 

4282 

4283 Returns: 

4284 The user, or ``None`` if no provider accepts the credentials. 

4285 

4286 Raises: 

4287 ForbiddenError: If a provider rejects the credentials. 

4288 TooManyRequestsError: If the attempt is blocked by the throttle. 

4289 """ 

4290 

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. 

4293 

4294 The session is not stored in the session manager. 

4295 

4296 Args: 

4297 method: The method that creates the session. 

4298 user: The session user. 

4299 data: Session data. 

4300 

4301 Returns: 

4302 A new session. 

4303 """ 

4304 

4305 def get_user(self, user_uid: str) -> Optional['User']: 

4306 """Get a user by its global uid. 

4307 

4308 Args: 

4309 user_uid: Global user uid. 

4310 

4311 Returns: 

4312 The user, or ``None`` if the provider is not found or does not return the user. 

4313 """ 

4314 

4315 def add_provider(self, provider: 'AuthProvider'): 

4316 """Add an authentication provider. 

4317 

4318 Args: 

4319 provider: The provider. 

4320 """ 

4321 

4322 def add_method(self, method: 'AuthMethod'): 

4323 """Add an authentication method. 

4324 

4325 Args: 

4326 method: The method. 

4327 """ 

4328 

4329 def add_multi_factor_adapter(self, adapter: 'AuthMultiFactorAdapter'): 

4330 """Add a multi-factor adapter. 

4331 

4332 Args: 

4333 adapter: The adapter. 

4334 """ 

4335 

4336 def can_use_method(self, req: 'WebRequester', method: 'AuthMethod') -> bool: 

4337 """Check if a method may be used for a request. 

4338 

4339 A secure method can only be used on secure requests, or from the addresses 

4340 listed in its ``allowInsecureFrom``. 

4341 

4342 Args: 

4343 req: The web request. 

4344 method: The method. 

4345 

4346 Returns: 

4347 ``True`` if the method may be used. 

4348 """ 

4349 

4350 def get_provider(self, uid: str) -> Optional['AuthProvider']: 

4351 """Get an authentication provider by its uid. 

4352 

4353 Args: 

4354 uid: Provider uid. 

4355 

4356 Returns: 

4357 The provider, or ``None`` if not found. 

4358 """ 

4359 

4360 def get_method(self, uid: str) -> Optional['AuthMethod']: 

4361 """Get an authentication method by its uid. 

4362 

4363 Args: 

4364 uid: Method uid. 

4365 

4366 Returns: 

4367 The method, or ``None`` if not found. 

4368 """ 

4369 

4370 def get_multi_factor_adapter(self, uid: str) -> Optional['AuthMultiFactorAdapter']: 

4371 """Get a multi-factor adapter by its uid. 

4372 

4373 Args: 

4374 uid: Adapter uid. 

4375 

4376 Returns: 

4377 The adapter, or ``None`` if not found. 

4378 """ 

4379 

4380 def serialize_user(self, user: 'User') -> str: 

4381 """Serialize a user to a string, together with its provider uid. 

4382 

4383 Args: 

4384 user: The user. 

4385 

4386 Returns: 

4387 A JSON string. 

4388 """ 

4389 

4390 def unserialize_user(self, ser: str) -> Optional['User']: 

4391 """Restore a user serialized by ``serialize_user``. 

4392 

4393 Args: 

4394 ser: The serialized user. 

4395 

4396 Returns: 

4397 The user, or ``None`` if the provider is not found. 

4398 """ 

4399 

4400 def is_public_object(self, obj: Object, *context) -> bool: 

4401 """Check if the guest user can read an object. 

4402 

4403 Args: 

4404 obj: The object. 

4405 *context: Further objects to check, before the parents. 

4406 

4407 Returns: 

4408 ``True`` if the object is public. 

4409 """ 

4410 

4411 

4412class AuthMethod(Node): 

4413 """Authentication method. 

4414 

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 """ 

4418 

4419 secure: bool 

4420 """The method may only be used on secure (HTTPS) requests.""" 

4421 

4422 allowInsecureFrom: list[str] 

4423 """IP addresses from which the method may be used without HTTPS.""" 

4424 

4425 def open_session(self, req: 'WebRequester') -> Optional['AuthSession']: 

4426 """Try to open a session for a request. 

4427 

4428 Called at the start of every web request. 

4429 

4430 Args: 

4431 req: The web request. 

4432 

4433 Returns: 

4434 A session, or ``None`` if the request has no session for this method. 

4435 """ 

4436 

4437 def close_session(self, req: 'WebRequester', res: 'WebResponder') -> bool: 

4438 """Close the session of a request. 

4439 

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. 

4442 

4443 Args: 

4444 req: The web request. 

4445 res: The web response. 

4446 

4447 Returns: 

4448 ``True`` if the session was closed. 

4449 """ 

4450 

4451 

4452class AuthMultiFactorState(Enum): 

4453 """State of a multi-factor authentication transaction.""" 

4454 

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

4463 

4464 

4465class AuthMultiFactorTransaction(Data): 

4466 """Multi-factor authentication transaction. 

4467 

4468 Kept in the user's session from the login until the verification succeeds, 

4469 fails or expires. 

4470 """ 

4471 

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

4490 

4491 

4492class AuthMultiFactorAdapter(Node): 

4493 """Multi-factor authentication adapter. 

4494 

4495 Provides the second verification step of a login, for example a code sent by 

4496 email or generated by an authenticator app. 

4497 """ 

4498 

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

4507 

4508 def start(self, user: 'User') -> Optional[AuthMultiFactorTransaction]: 

4509 """Start a transaction for a user. 

4510 

4511 Args: 

4512 user: The user who logs in. 

4513 

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 """ 

4518 

4519 def verify(self, mfa: AuthMultiFactorTransaction, payload: dict) -> AuthMultiFactorTransaction: 

4520 """Verify a payload submitted by the user. 

4521 

4522 Args: 

4523 mfa: The transaction. 

4524 payload: The payload, for example ``{'code': '123456'}``. 

4525 

4526 Returns: 

4527 The transaction with an updated state. 

4528 """ 

4529 

4530 def cancel(self, mfa: AuthMultiFactorTransaction): 

4531 """Cancel a transaction. 

4532 

4533 Args: 

4534 mfa: The transaction. 

4535 """ 

4536 

4537 def check_state(self, mfa: AuthMultiFactorTransaction) -> bool: 

4538 """Check if a transaction is still valid, and mark it failed if not. 

4539 

4540 Args: 

4541 mfa: The transaction. 

4542 

4543 Returns: 

4544 ``True`` if the transaction is valid. 

4545 """ 

4546 

4547 def check_restart(self, mfa: AuthMultiFactorTransaction) -> bool: 

4548 """Check if a transaction can be restarted. 

4549 

4550 Args: 

4551 mfa: The transaction. 

4552 

4553 Returns: 

4554 ``True`` if a restart is allowed. 

4555 """ 

4556 

4557 def restart(self, mfa: AuthMultiFactorTransaction) -> Optional[AuthMultiFactorTransaction]: 

4558 """Restart a transaction, for example by sending a new code. 

4559 

4560 Args: 

4561 mfa: The transaction. 

4562 

4563 Returns: 

4564 A new transaction, or ``None`` if a restart is not possible. 

4565 """ 

4566 

4567 def key_uri(self, secret: str | bytes, issuer_name: str, account_name: str) -> Optional[str]: 

4568 """Generate a key URI for authenticator apps. 

4569 

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. 

4574 

4575 Returns: 

4576 An ``otpauth://`` URI, or ``None`` if the adapter does not support it. 

4577 """ 

4578 

4579 

4580class AuthProvider(Node): 

4581 """Authentication provider. 

4582 

4583 A source of users, for example a file, an LDAP directory or a database table, 

4584 which verifies credentials. 

4585 """ 

4586 

4587 allowedMethods: list[str] 

4588 """Method types this provider accepts, all methods if empty.""" 

4589 

4590 def get_user(self, local_uid: str) -> Optional['User']: 

4591 """Get a user by its local uid. 

4592 

4593 Args: 

4594 local_uid: User uid within the provider. 

4595 

4596 Returns: 

4597 The user, or ``None`` if not found. 

4598 """ 

4599 

4600 def authenticate(self, method: 'AuthMethod', credentials: Data) -> Optional['User']: 

4601 """Authenticate a user. 

4602 

4603 Args: 

4604 method: The authentication method. 

4605 credentials: The credentials, for example ``username`` and ``password``. 

4606 

4607 Returns: 

4608 The user, or ``None`` if the provider does not know the user. 

4609 

4610 Raises: 

4611 AuthenticationError: If the credentials are wrong or match more than one user. 

4612 """ 

4613 

4614 def serialize_user(self, user: 'User') -> str: 

4615 """Serialize a user to a string. 

4616 

4617 Args: 

4618 user: The user. 

4619 

4620 Returns: 

4621 The serialized user. 

4622 """ 

4623 

4624 def unserialize_user(self, ser: str) -> Optional['User']: 

4625 """Restore a user serialized by ``serialize_user``. 

4626 

4627 Args: 

4628 ser: The serialized user. 

4629 

4630 Returns: 

4631 The user, or ``None`` if it cannot be restored. 

4632 """ 

4633 

4634 

4635class AuthSession: 

4636 """Authentication session. 

4637 

4638 Holds the user and arbitrary data between requests. 

4639 """ 

4640 

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

4657 

4658 def get(self, key: str, default=None): 

4659 """Get a session data value. 

4660 

4661 Args: 

4662 key: Value name. 

4663 default: Default value. 

4664 

4665 Returns: 

4666 The value, or the default if it is not set. 

4667 """ 

4668 

4669 def set(self, key: str, value): 

4670 """Set a session data value and mark the session as changed. 

4671 

4672 Args: 

4673 key: Value name. 

4674 value: The value. 

4675 """ 

4676 

4677 

4678class AuthSessionManager(Node): 

4679 """Authentication session manager. 

4680 

4681 Stores sessions persistently. A session is valid until ``lifeTime`` has passed 

4682 since its last update, or ``maxLifeTime`` since its creation. 

4683 """ 

4684 

4685 lifeTime: int 

4686 """Session life time in seconds, counted from the last update.""" 

4687 

4688 maxLifeTime: int 

4689 """Absolute session life time in seconds, counted from the creation, or 0 if not limited.""" 

4690 

4691 def create(self, method: 'AuthMethod', user: 'User', data: Optional[dict] = None) -> 'AuthSession': 

4692 """Create and store a new session. 

4693 

4694 Args: 

4695 method: The method that creates the session. 

4696 user: The session user. 

4697 data: Session data. 

4698 

4699 Returns: 

4700 The new session. 

4701 """ 

4702 

4703 def delete(self, sess: 'AuthSession'): 

4704 """Delete a session. 

4705 

4706 Args: 

4707 sess: The session. 

4708 """ 

4709 

4710 def delete_all(self): 

4711 """Delete all sessions.""" 

4712 

4713 def get(self, uid: str) -> Optional['AuthSession']: 

4714 """Get a valid session by its uid. 

4715 

4716 Args: 

4717 uid: Session uid. 

4718 

4719 Returns: 

4720 The session, or ``None`` if it does not exist or has expired. 

4721 """ 

4722 

4723 def list_all(self) -> list['AuthSession']: 

4724 """Get all stored sessions. 

4725 

4726 Returns: 

4727 A list of sessions. 

4728 """ 

4729 

4730 def save(self, sess: 'AuthSession'): 

4731 """Save the session data. 

4732 

4733 Args: 

4734 sess: The session. 

4735 """ 

4736 

4737 def touch(self, sess: 'AuthSession'): 

4738 """Update the last activity time of a session. 

4739 

4740 Args: 

4741 sess: The session. 

4742 """ 

4743 

4744 def cleanup(self): 

4745 """Remove expired sessions from the storage.""" 

4746################################################################################ 

4747 

4748 

4749 

4750################################################################################ 

4751# /base/layer/types.pyinc 

4752 

4753 

4754class LayerDisplayMode(Enum): 

4755 """How a layer is rendered.""" 

4756 

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

4763 

4764 

4765class FeatureLoadingStrategy(Enum): 

4766 """When the client loads a layer's features.""" 

4767 

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

4774 

4775 

4776class LayerOwsBinding(Node): 

4777 """Binding of a layer to OWS services: access, names and models.""" 

4778 

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

4793 

4794 

4795class Layer(Node): 

4796 """Layer object.""" 

4797 

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

4854 

4855 def find_features(self, search: 'SearchQuery', user: 'User') -> list['Feature']: 

4856 """Find features in the layer. 

4857 

4858 Vector layers search in the first model the user can read; other 

4859 layers return an empty list. 

4860 

4861 Args: 

4862 search: Search query. 

4863 user: The user who searches. 

4864 

4865 Returns: 

4866 Found features. 

4867 """ 

4868 

4869 def render(self, lri: LayerRenderInput) -> Optional['LayerRenderOutput']: 

4870 """Render a box, a tile or an SVG fragment, depending on the input type. 

4871 

4872 Args: 

4873 lri: Render input. 

4874 

4875 Returns: 

4876 Render output with image content or SVG tags, or ``None`` if the 

4877 layer has nothing to render. 

4878 """ 

4879 

4880 def render_legend(self, args: Optional[dict | Data] = None) -> Optional['LegendRenderOutput']: 

4881 """Render the layer legend. 

4882 

4883 Without ``args`` the output is cached for the server lifetime. 

4884 

4885 Args: 

4886 args: Arguments passed to the legend renderer. 

4887 

4888 Returns: 

4889 Legend output, or ``None`` if the layer has no legend. 

4890 """ 

4891 

4892 def url_path_for(self, kind: str) -> str: 

4893 """Return the URL path for requests to this layer. 

4894 

4895 Args: 

4896 kind: ``box``, ``tile``, ``legend`` or ``features``. The ``tile`` 

4897 path contains ``{z}``, ``{x}`` and ``{y}`` placeholders. 

4898 

4899 Returns: 

4900 URL path. 

4901 

4902 Raises: 

4903 ``gws.Error``: If ``kind`` is not recognized. 

4904 """ 

4905################################################################################ 

4906 

4907 

4908################################################################################ 

4909# /base/grabber/types.pyinc 

4910 

4911 

4912class Grabber: 

4913 """Raster grabber. 

4914 

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 """ 

4918 

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

4933 

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. 

4936 

4937 A tile outside the layer's range is a transparent image. 

4938 

4939 Args: 

4940 mt: Tile. 

4941 params: Dynamic request parameters. With ``params``, the persistent store is bypassed. 

4942 

4943 Returns: 

4944 The encoded tile. 

4945 

4946 Raises: 

4947 ``Exception``: Errors of the source request are passed through. 

4948 """ 

4949 

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. 

4952 

4953 Same contract as ``get_tile_as_bytes``, decoded pixels instead of bytes. 

4954 

4955 Args: 

4956 mt: Tile. 

4957 params: Dynamic request parameters. With ``params``, the persistent store is bypassed. 

4958 

4959 Returns: 

4960 The tile image. 

4961 

4962 Raises: 

4963 ``Exception``: Errors of the source request are passed through. 

4964 """ 

4965 

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. 

4968 

4969 Args: 

4970 mtr: Tile range. 

4971 params: Dynamic request parameters. With ``params``, the persistent store is bypassed. 

4972 

4973 Returns: 

4974 Encoded tiles, keyed by tile. Sparse: contains entries only for tiles present in the grid. 

4975 

4976 Raises: 

4977 ``Exception``: Errors of the source request are passed through. 

4978 """ 

4979 

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. 

4982 

4983 Same contract as ``get_tiles_as_bytes_dict``, decoded pixels instead of bytes. 

4984 

4985 Args: 

4986 mtr: Tile range. 

4987 params: Dynamic request parameters. With ``params``, the persistent store is bypassed. 

4988 

4989 Returns: 

4990 Tile images, keyed by tile. 

4991 

4992 Raises: 

4993 ``Exception``: Errors of the source request are passed through. 

4994 """ 

4995 

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. 

4998 

4999 A box overlapping no data is a transparent image. 

5000 

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. 

5006 

5007 Returns: 

5008 The encoded image. 

5009 

5010 Raises: 

5011 ``Exception``: Errors of the source request are passed through. 

5012 """ 

5013 

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. 

5016 

5017 Same contract as ``get_box_as_bytes``, decoded pixels instead of bytes. 

5018 

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. 

5024 

5025 Returns: 

5026 The image. 

5027 

5028 Raises: 

5029 ``Exception``: Errors of the source request are passed through. 

5030 """ 

5031 

5032 def levels(self) -> list[int]: 

5033 """Return the levels this grabber supports. 

5034 

5035 Returns: 

5036 A list of levels. 

5037 """ 

5038 

5039 def tile_range_for_level(self, z: int) -> MapTileRange: 

5040 """Return the tile range covered by the grabber's extent at a level. 

5041 

5042 Args: 

5043 z: Level. 

5044 

5045 Returns: 

5046 The tile range in the grabber's grid. 

5047 """ 

5048################################################################################ 

5049 

5050 

5051################################################################################ 

5052# /base/legend/types.pyinc 

5053 

5054 

5055class LegendRenderOutput(Data): 

5056 """Legend render output.""" 

5057 

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

5064 

5065 

5066class Legend(Node): 

5067 """Legend object.""" 

5068 

5069 def render(self, args: Optional[dict | Data] = None) -> Optional[LegendRenderOutput]: 

5070 """Render the legend. 

5071 

5072 Args: 

5073 args: Arguments for the renderer, for example template arguments. 

5074 

5075 Returns: 

5076 Legend output, or ``None`` if there is nothing to show. 

5077 """ 

5078################################################################################ 

5079 

5080 

5081################################################################################ 

5082# /base/map/types.pyinc 

5083 

5084 

5085class Map(Node): 

5086 """Map object.""" 

5087 

5088 rootLayer: 'Layer' 

5089 """Root group layer that holds the map layers.""" 

5090 

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################################################################################ 

5106 

5107 

5108 

5109################################################################################ 

5110# /base/model/types.pyinc 

5111 

5112 

5113class ModelClientOptions(Data): 

5114 """Client options for a model.""" 

5115 

5116 keepFormOpen: Optional[bool] 

5117 """Keep the edit form open after saving.""" 

5118 

5119 

5120class ModelValidationError(Data): 

5121 """Validation error of a feature field.""" 

5122 

5123 fieldName: str 

5124 """Name of the field that failed validation.""" 

5125 message: str 

5126 """Error message, or a message key for the client.""" 

5127 

5128 

5129class ModelOperation(Enum): 

5130 """Model operation.""" 

5131 

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

5142 

5143 

5144class ModelReadTarget(Enum): 

5145 """Target for the read operation.""" 

5146 

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

5157 

5158 

5159class ModelSelectBuild(Data): 

5160 """Parts of a database select statement, collected from the model fields.""" 

5161 

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

5172 

5173 

5174class ModelContext(Data): 

5175 """Context of a model operation.""" 

5176 

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

5193 

5194 

5195EmptyValue = object() 

5196"""Special value for empty fields.""" 

5197 

5198ErrorValue = object() 

5199"""Special value for invalid fields.""" 

5200 

5201 

5202class ModelWidget(Node): 

5203 """Model widget. 

5204 

5205 Describes how the client displays and edits a field value. 

5206 """ 

5207 

5208 supportsTableView: bool = True 

5209 """The widget can be used in the table view.""" 

5210 

5211 

5212class ModelValidator(Node): 

5213 """Model validator. 

5214 

5215 Checks the value of a field. 

5216 """ 

5217 

5218 message: str 

5219 """Error message, or a message key for the client.""" 

5220 ops: set[ModelOperation] 

5221 """Operations the validator applies to.""" 

5222 

5223 def validate(self, field: 'ModelField', feature: 'Feature', mc: ModelContext) -> bool: 

5224 """Check the value of a field in a feature. 

5225 

5226 Args: 

5227 field: The field. 

5228 feature: The feature. 

5229 mc: The model context. 

5230 

5231 Returns: 

5232 True if the value is valid. 

5233 """ 

5234 

5235 

5236class ModelValue(Node): 

5237 """Model value. 

5238 

5239 Computes a value for a field. 

5240 """ 

5241 

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

5246 

5247 def compute(self, field: 'ModelField', feature: 'Feature', mc: 'ModelContext'): 

5248 """Compute the value of a field. 

5249 

5250 Args: 

5251 field: The field. 

5252 feature: The feature. 

5253 mc: The model context. 

5254 

5255 Returns: 

5256 The computed value. 

5257 """ 

5258 

5259 

5260class ModelField(Node): 

5261 """Model field. 

5262 

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 """ 

5267 

5268 name: str 

5269 """Field name.""" 

5270 title: str 

5271 """Field title.""" 

5272 

5273 attributeType: AttributeType 

5274 """Type of the field value.""" 

5275 

5276 widget: Optional['ModelWidget'] = None 

5277 """Widget for the client.""" 

5278 

5279 values: list['ModelValue'] 

5280 """Value objects.""" 

5281 validators: list['ModelValidator'] 

5282 """Validators.""" 

5283 

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

5294 

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

5301 

5302 model: 'Model' 

5303 """The model of the field.""" 

5304 

5305 def before_select(self, mc: ModelContext): 

5306 """Called before features are selected, adds columns and conditions to ``mc.dbSelect``. 

5307 

5308 Args: 

5309 mc: The model context. 

5310 """ 

5311 

5312 def after_select(self, features: list['Feature'], mc: ModelContext): 

5313 """Called after features are selected, sets the field value in the features. 

5314 

5315 Args: 

5316 features: The selected features. 

5317 mc: The model context. 

5318 """ 

5319 

5320 def before_create(self, feature: 'Feature', mc: ModelContext): 

5321 """Called before a feature is inserted, writes the field value to ``feature.record``. 

5322 

5323 Args: 

5324 feature: The feature. 

5325 mc: The model context. 

5326 """ 

5327 

5328 def after_create(self, feature: 'Feature', mc: ModelContext): 

5329 """Called after a feature is inserted. 

5330 

5331 Args: 

5332 feature: The feature. 

5333 mc: The model context. 

5334 """ 

5335 

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. 

5338 

5339 Args: 

5340 dst_feature: The feature being created. 

5341 mc: The model context. 

5342 """ 

5343 

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. 

5346 

5347 Args: 

5348 dst_feature: The created feature. 

5349 mc: The model context. 

5350 """ 

5351 

5352 def before_update(self, feature: 'Feature', mc: ModelContext): 

5353 """Called before a feature is updated, writes the field value to ``feature.record``. 

5354 

5355 Args: 

5356 feature: The feature. 

5357 mc: The model context. 

5358 """ 

5359 

5360 def after_update(self, feature: 'Feature', mc: ModelContext): 

5361 """Called after a feature is updated. 

5362 

5363 Args: 

5364 feature: The feature. 

5365 mc: The model context. 

5366 """ 

5367 

5368 def before_delete(self, feature: 'Feature', mc: ModelContext): 

5369 """Called before a feature is deleted. 

5370 

5371 Args: 

5372 feature: The feature. 

5373 mc: The model context. 

5374 """ 

5375 

5376 def after_delete(self, feature: 'Feature', mc: ModelContext): 

5377 """Called after a feature is deleted. 

5378 

5379 Args: 

5380 feature: The feature. 

5381 mc: The model context. 

5382 """ 

5383 

5384 def do_init(self, feature: 'Feature', mc: ModelContext): 

5385 """Set the initial field value of a new feature. 

5386 

5387 Args: 

5388 feature: The feature. 

5389 mc: The model context. 

5390 """ 

5391 

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. 

5394 

5395 Args: 

5396 dst_feature: The new feature. 

5397 mc: The model context. 

5398 """ 

5399 

5400 def do_validate(self, feature: 'Feature', mc: ModelContext): 

5401 """Validate the field value and append errors to ``feature.errors``. 

5402 

5403 Args: 

5404 feature: The feature. 

5405 mc: The model context. 

5406 """ 

5407 

5408 def from_props(self, feature: 'Feature', mc: ModelContext): 

5409 """Set the field value from ``feature.props``. 

5410 

5411 Args: 

5412 feature: The feature. 

5413 mc: The model context. 

5414 """ 

5415 

5416 def to_props(self, feature: 'Feature', mc: ModelContext): 

5417 """Write the field value to ``feature.props``. 

5418 

5419 Args: 

5420 feature: The feature. 

5421 mc: The model context. 

5422 """ 

5423 

5424 def from_record(self, feature: 'Feature', mc: ModelContext): 

5425 """Set the field value from ``feature.record``. 

5426 

5427 Args: 

5428 feature: The feature. 

5429 mc: The model context. 

5430 """ 

5431 

5432 def to_record(self, feature: 'Feature', mc: ModelContext): 

5433 """Write the field value to ``feature.record``. 

5434 

5435 Args: 

5436 feature: The feature. 

5437 mc: The model context. 

5438 """ 

5439 

5440 def related_models(self) -> list['Model']: 

5441 """Return the models related to this field. 

5442 

5443 Returns: 

5444 A list of models, empty for fields that are not related fields. 

5445 """ 

5446 

5447 def find_relatable_features(self, search: 'SearchQuery', mc: ModelContext) -> list['Feature']: 

5448 """Find features that can be linked by this field. 

5449 

5450 Args: 

5451 search: The search query. 

5452 mc: The model context. 

5453 

5454 Returns: 

5455 The features found in the related models. 

5456 """ 

5457 

5458 def raw_to_python(self, feature: 'Feature', value, mc: ModelContext): 

5459 """Convert a raw source value to a python value. 

5460 

5461 Args: 

5462 feature: The feature. 

5463 value: The value to convert. 

5464 mc: The model context. 

5465 

5466 Returns: 

5467 The converted value. 

5468 """ 

5469 

5470 def prop_to_python(self, feature: 'Feature', value, mc: ModelContext): 

5471 """Convert a client props value to a python value. 

5472 

5473 Args: 

5474 feature: The feature. 

5475 value: The value to convert. 

5476 mc: The model context. 

5477 

5478 Returns: 

5479 The converted value. 

5480 """ 

5481 

5482 def python_to_raw(self, feature: 'Feature', value, mc: ModelContext): 

5483 """Convert a python value to a raw source value. 

5484 

5485 Args: 

5486 feature: The feature. 

5487 value: The value to convert. 

5488 mc: The model context. 

5489 

5490 Returns: 

5491 The converted value. 

5492 """ 

5493 

5494 def python_to_prop(self, feature: 'Feature', value, mc: ModelContext): 

5495 """Convert a python value to a client props value. 

5496 

5497 Args: 

5498 feature: The feature. 

5499 value: The value to convert. 

5500 mc: The model context. 

5501 

5502 Returns: 

5503 The converted value. 

5504 """ 

5505 

5506 def describe(self) -> Optional['ColumnDescription']: 

5507 """Return the description of the source column of this field. 

5508 

5509 Returns: 

5510 The column description, or None if the source has no such column. 

5511 """ 

5512 

5513 

5514class Model(Node): 

5515 """Data model. 

5516 

5517 Reads features from a source, converts them to and from client props and, 

5518 if editable, writes them back. 

5519 """ 

5520 

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

5545 

5546 def find_features(self, search: 'SearchQuery', mc: ModelContext) -> list['Feature']: 

5547 """Find features matching a search query. 

5548 

5549 Args: 

5550 search: The search query. 

5551 mc: The model context. 

5552 

5553 Returns: 

5554 The features found. 

5555 """ 

5556 

5557 def get_features(self, uids: Iterable[str | int], mc: ModelContext) -> list['Feature']: 

5558 """Return features by uid. 

5559 

5560 Args: 

5561 uids: Feature uids. 

5562 mc: The model context. 

5563 

5564 Returns: 

5565 The features found, empty if no uids are given. 

5566 """ 

5567 

5568 def get_feature(self, uid: str | int, mc: ModelContext) -> Optional['Feature']: 

5569 """Return a feature by uid. 

5570 

5571 Args: 

5572 uid: The feature uid. 

5573 mc: The model context. 

5574 

5575 Returns: 

5576 The feature, or None if it is not found. 

5577 """ 

5578 

5579 def init_feature(self, feature: 'Feature', mc: ModelContext): 

5580 """Initialize a new feature with initial field values. 

5581 

5582 Args: 

5583 feature: The new feature. 

5584 mc: The model context. 

5585 

5586 Raises: 

5587 gws.ForbiddenError: If the user cannot create features of this model. 

5588 """ 

5589 

5590 def create_feature(self, feature: 'Feature', mc: ModelContext) -> FeatureUid: 

5591 """Insert a new feature into the source. 

5592 

5593 Args: 

5594 feature: The feature. 

5595 mc: The model context. 

5596 

5597 Returns: 

5598 The primary key of the inserted feature. 

5599 

5600 Raises: 

5601 gws.ForbiddenError: If the user cannot create features of this model. 

5602 """ 

5603 

5604 def update_feature(self, feature: 'Feature', mc: ModelContext) -> FeatureUid: 

5605 """Update an existing feature in the source. 

5606 

5607 Args: 

5608 feature: The feature. 

5609 mc: The model context. 

5610 

5611 Returns: 

5612 The uid of the feature. 

5613 

5614 Raises: 

5615 gws.ForbiddenError: If the user cannot write to this model. 

5616 """ 

5617 

5618 def delete_feature(self, feature: 'Feature', mc: ModelContext) -> FeatureUid: 

5619 """Delete a feature from the source. 

5620 

5621 Args: 

5622 feature: The feature. 

5623 mc: The model context. 

5624 

5625 Returns: 

5626 The uid of the feature. 

5627 

5628 Raises: 

5629 gws.ForbiddenError: If the user cannot delete features of this model. 

5630 """ 

5631 

5632 def validate_feature(self, feature: 'Feature', mc: ModelContext) -> bool: 

5633 """Validate a feature and store validation errors in ``feature.errors``. 

5634 

5635 Args: 

5636 feature: The feature. 

5637 mc: The model context. 

5638 

5639 Returns: 

5640 True if the feature has no errors. 

5641 """ 

5642 

5643 def feature_from_props(self, props: 'FeatureProps', mc: ModelContext) -> 'Feature': 

5644 """Create a feature from client props. 

5645 

5646 Args: 

5647 props: The feature props. 

5648 mc: The model context. 

5649 

5650 Returns: 

5651 A new feature. 

5652 """ 

5653 

5654 def feature_to_props(self, feature: 'Feature', mc: ModelContext) -> 'FeatureProps': 

5655 """Convert a feature to client props and store them in ``feature.props``. 

5656 

5657 Args: 

5658 feature: The feature. 

5659 mc: The model context. 

5660 

5661 Returns: 

5662 The feature props. 

5663 """ 

5664 

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. 

5667 

5668 Args: 

5669 feature: The feature. 

5670 mc: The model context. 

5671 

5672 Returns: 

5673 The feature props. 

5674 """ 

5675 

5676 def describe(self) -> Optional['DataSetDescription']: 

5677 """Return the description of the model source. 

5678 

5679 Returns: 

5680 The dataset description, or None if the source cannot be described. 

5681 """ 

5682 

5683 def field(self, name: str) -> Optional['ModelField']: 

5684 """Return a field by name. 

5685 

5686 Args: 

5687 name: The field name. 

5688 

5689 Returns: 

5690 The field, or None if it is not found. 

5691 """ 

5692 

5693 def related_models(self) -> list['Model']: 

5694 """Return the models related to the fields of this model. 

5695 

5696 Returns: 

5697 A list of models without duplicates. 

5698 """ 

5699 

5700 

5701class ModelManager(Node): 

5702 """Model manager. 

5703 

5704 Looks up models and provides the default model. 

5705 """ 

5706 

5707 def get_model(self, uid: str, user: 'User' = None, access: Access = None) -> Optional['Model']: 

5708 """Return a model by uid. 

5709 

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. 

5714 

5715 Returns: 

5716 The model, or None if it is not found or not accessible. 

5717 """ 

5718 

5719 def find_model(self, *objects, user: 'User' = None, access: Access = None) -> Optional['Model']: 

5720 """Return the first model of the given objects. 

5721 

5722 Looks in the ``models`` attribute of each object in turn. 

5723 

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. 

5728 

5729 Returns: 

5730 The model, or None if none is found. 

5731 """ 

5732 

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. 

5735 

5736 Args: 

5737 project: The project. 

5738 user: The user. 

5739 

5740 Returns: 

5741 The models, sorted by title. 

5742 """ 

5743 

5744 def default_model(self) -> 'Model': 

5745 """Return the shared default model. 

5746 

5747 Returns: 

5748 The default model. 

5749 """ 

5750################################################################################ 

5751 

5752 

5753################################################################################ 

5754# /base/database/types.pyinc 

5755 

5756 

5757class DatabaseModel(Model): 

5758 """Data model for a database table.""" 

5759 

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

5766 

5767 def table(self) -> 'sqlalchemy.Table': 

5768 """Return the SQLAlchemy ``Table`` object of the model table. 

5769 

5770 Returns: 

5771 The table object. 

5772 

5773 Raises: 

5774 ``sqlalchemy.exc.SQLAlchemyError``: If the table does not exist. 

5775 """ 

5776 

5777 def column(self, column_name: str) -> 'sqlalchemy.Column': 

5778 """Return the SQLAlchemy ``Column`` object of a column in the model table. 

5779 

5780 Args: 

5781 column_name: Column name. 

5782 

5783 Returns: 

5784 The column object. 

5785 

5786 Raises: 

5787 ``sqlalchemy.exc.SQLAlchemyError``: If the table or the column does not exist. 

5788 """ 

5789 

5790 def uid_column(self) -> 'sqlalchemy.Column': 

5791 """Return the SQLAlchemy ``Column`` object of the primary key column. 

5792 

5793 Returns: 

5794 The column object for ``uidName``. 

5795 

5796 Raises: 

5797 ``gws.Error``: If the model has no primary key or the key column does not exist. 

5798 """ 

5799 

5800 def uid_equals(self, uid: FeatureUid | Iterable[FeatureUid]) -> 'sqlalchemy.ColumnElement[bool]': 

5801 """Return a condition that matches features by uid. 

5802 

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. 

5805 

5806 Args: 

5807 uid: A feature uid, or an iterable of uids. 

5808 

5809 Returns: 

5810 An ``=`` condition for a single uid, an ``IN`` condition for an iterable. 

5811 

5812 Raises: 

5813 ``gws.Error``: If the model has no primary key or the key column does not exist. 

5814 """ 

5815 

5816 def fetch_features(self, select: 'sqlalchemy.Select') -> list['Feature']: 

5817 """Run a SELECT statement and create a feature for each row. 

5818 

5819 The row values become the attributes of the feature record. 

5820 

5821 Args: 

5822 select: SELECT statement. 

5823 

5824 Returns: 

5825 A list of features. 

5826 """ 

5827 

5828 def build_select(self, mc: 'ModelContext') -> Optional['sqlalchemy.Select']: 

5829 """Build a SELECT statement for a search. 

5830 

5831 Combines the search query in ``mc.search``, the columns and conditions 

5832 collected by the fields in ``mc.dbSelect`` and ``sqlFilter``. 

5833 

5834 Args: 

5835 mc: Model context with ``search`` and ``dbSelect`` set. 

5836 

5837 Returns: 

5838 The SELECT statement, or ``None`` if the search cannot match anything. 

5839 """ 

5840 

5841 

5842class ColumnDescription(Data): 

5843 """Description of a dataset column.""" 

5844 

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

5875 

5876 

5877class DataSetDescription(Data): 

5878 """Description of a dataset, like a DB table or a GDAL data set.""" 

5879 

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

5896 

5897 

5898class DatabaseManager(Node): 

5899 """Database manager.""" 

5900 

5901 providers: list['DatabaseProvider'] 

5902 """A list of database providers managed by this DatabaseManager.""" 

5903 

5904 def create_provider(self, cfg: Config, **kwargs) -> 'DatabaseProvider': 

5905 """Create a database provider and add it to ``providers``. 

5906 

5907 The provider is created as a shared object. A provider with the same uid 

5908 that is already in ``providers`` is replaced. 

5909 

5910 Args: 

5911 cfg: Provider configuration. 

5912 **kwargs: Extra configuration values. 

5913 

5914 Returns: 

5915 The provider. 

5916 """ 

5917 

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. 

5920 

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. 

5924 

5925 Args: 

5926 uid: Provider uid. 

5927 ext_type: Provider type, e.g. ``postgres``. 

5928 

5929 Returns: 

5930 The provider, or ``None`` if none matches. 

5931 """ 

5932 

5933 

5934DatabaseTableAlike: TypeAlias = Union['sqlalchemy.Table', str] 

5935"""An SQLAlchemy ``Table`` object or a string table name.""" 

5936 

5937 

5938DatabaseStmt: TypeAlias = Union['sqlalchemy.Executable', str] 

5939"""An Executable SQLAlchemy object or a string SQL statement.""" 

5940 

5941 

5942class DatabaseConnection: 

5943 """Database connection. 

5944 

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. 

5948 

5949 Statements can be SQLAlchemy objects or SQL strings with ``:name`` bind 

5950 parameters. The ``fetch_*`` methods roll back the transaction after reading. 

5951 """ 

5952 

5953 saConn: 'sqlalchemy.Connection' 

5954 """The underlying SQLAlchemy connection.""" 

5955 

5956 def __enter__(self) -> 'DatabaseConnection': ... 

5957 

5958 def __exit__(self, exc_type, exc_value, traceback): ... 

5959 

5960 def execute(self, stmt: 'sqlalchemy.Executable', params=None, execution_options: dict=None) -> 'sqlalchemy.CursorResult': 

5961 """Execute an SQLAlchemy statement. 

5962 

5963 Args: 

5964 stmt: Statement. 

5965 params: Bind parameters, a dict or a list of dicts. 

5966 execution_options: SQLAlchemy execution options. 

5967 

5968 Returns: 

5969 The result. 

5970 """ 

5971 

5972 def commit(self): 

5973 """Commit the current transaction.""" 

5974 

5975 def rollback(self): 

5976 """Roll back the current transaction.""" 

5977 

5978 def close(self): 

5979 """Close the connection. 

5980 

5981 The connection is shared by nested ``connect`` calls, and only the 

5982 outermost ``close`` closes the SQLAlchemy connection. 

5983 """ 

5984 

5985 def exec(self, stmt: 'DatabaseStmt', **params) -> 'sqlalchemy.CursorResult': 

5986 """Execute a statement. 

5987 

5988 Args: 

5989 stmt: Statement or SQL string. 

5990 **params: Bind parameters. 

5991 

5992 Returns: 

5993 The result. 

5994 """ 

5995 

5996 def exec_commit(self, stmt: 'DatabaseStmt', **params) -> 'sqlalchemy.CursorResult': 

5997 """Execute a statement and commit, or roll back on error. 

5998 

5999 Args: 

6000 stmt: Statement or SQL string. 

6001 **params: Bind parameters. 

6002 

6003 Returns: 

6004 The result. 

6005 

6006 Raises: 

6007 ``Exception``: Any error from the execution is re-raised after the rollback. 

6008 """ 

6009 

6010 def exec_rollback(self, stmt: 'DatabaseStmt', **params) -> 'sqlalchemy.CursorResult': 

6011 """Execute a statement and roll back afterwards. 

6012 

6013 Args: 

6014 stmt: Statement or SQL string. 

6015 **params: Bind parameters. 

6016 

6017 Returns: 

6018 The result. 

6019 """ 

6020 

6021 def fetch_all(self, stmt: 'DatabaseStmt', **params) -> list[dict]: 

6022 """Execute a statement and return all rows. 

6023 

6024 Args: 

6025 stmt: Statement or SQL string. 

6026 **params: Bind parameters. 

6027 

6028 Returns: 

6029 A list of rows as dicts. 

6030 """ 

6031 

6032 def fetch_first(self, stmt: 'DatabaseStmt', **params) -> dict | None: 

6033 """Execute a statement and return the first row. 

6034 

6035 Args: 

6036 stmt: Statement or SQL string. 

6037 **params: Bind parameters. 

6038 

6039 Returns: 

6040 The first row as a dict, or ``None`` if there are no rows. 

6041 """ 

6042 

6043 def fetch_scalars(self, stmt: 'DatabaseStmt', **params) -> list: 

6044 """Execute a statement and return the first column of all rows. 

6045 

6046 Args: 

6047 stmt: Statement or SQL string. 

6048 **params: Bind parameters. 

6049 

6050 Returns: 

6051 A list of values. 

6052 """ 

6053 

6054 def fetch_strings(self, stmt: 'DatabaseStmt', **params) -> list[str]: 

6055 """Execute a statement and return the first column of all rows as strings. 

6056 

6057 Args: 

6058 stmt: Statement or SQL string. 

6059 **params: Bind parameters. 

6060 

6061 Returns: 

6062 A list of strings, with ``NULL`` values as empty strings. 

6063 """ 

6064 

6065 def fetch_ints(self, stmt: 'DatabaseStmt', **params) -> list[int]: 

6066 """Execute a statement and return the first column of all rows as integers. 

6067 

6068 Args: 

6069 stmt: Statement or SQL string. 

6070 **params: Bind parameters. 

6071 

6072 Returns: 

6073 A list of integers. 

6074 

6075 Raises: 

6076 ``ValueError``: If a value is not an integer. 

6077 """ 

6078 

6079 def fetch_scalar(self, stmt: 'DatabaseStmt', **params) -> Any: 

6080 """Execute a statement and return the first column of the first row. 

6081 

6082 Args: 

6083 stmt: Statement or SQL string. 

6084 **params: Bind parameters. 

6085 

6086 Returns: 

6087 The value, or ``None`` if there are no rows. 

6088 """ 

6089 

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. 

6092 

6093 Args: 

6094 stmt: Statement or SQL string. 

6095 **params: Bind parameters. 

6096 

6097 Returns: 

6098 The string, or ``None`` if there are no rows or the value is ``NULL``. 

6099 """ 

6100 

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. 

6103 

6104 Args: 

6105 stmt: Statement or SQL string. 

6106 **params: Bind parameters. 

6107 

6108 Returns: 

6109 The integer, or ``None`` if there are no rows or the value is ``NULL``. 

6110 

6111 Raises: 

6112 ``ValueError``: If the value is not an integer. 

6113 """ 

6114 

6115class DatabaseInspectOptions(Data): 

6116 """Options for database inspection.""" 

6117 

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

6122 

6123 

6124class DatabaseProvider(Node): 

6125 """Database provider. 

6126 

6127 Wraps an SQLAlchemy ``Engine`` and hands out connections. Also reflects 

6128 table structures and describes tables and columns. 

6129 """ 

6130 

6131 def connect(self) -> 'DatabaseConnection': 

6132 """Open a connection, to be used as a context manager. 

6133 

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:: 

6137 

6138 with db.connect(): 

6139 ... 

6140 with db.connect(): # no-op 

6141 ... 

6142 # connection remains open 

6143 ... 

6144 # connection closed 

6145 

6146 Returns: 

6147 The connection. 

6148 """ 

6149 

6150 def engine_options(self, **kwargs): 

6151 """Add defaults to the SQLAlchemy engine options. 

6152 

6153 Args: 

6154 **kwargs: Engine options. Options passed here take precedence over the defaults. 

6155 

6156 Returns: 

6157 The options dict. 

6158 """ 

6159 

6160 def url(self) -> str: 

6161 """Return the connection URL. 

6162 

6163 Returns: 

6164 An SQLAlchemy connection URL. 

6165 """ 

6166 

6167 def engine(self) -> 'sqlalchemy.Engine': 

6168 """Return the SQLAlchemy ``Engine`` object for this provider, creating it if needed. 

6169 

6170 Returns: 

6171 The engine. 

6172 """ 

6173 

6174 def create_engine(self, **kwargs) -> 'sqlalchemy.Engine': 

6175 """Create a new SQLAlchemy ``Engine`` object for this provider. 

6176 

6177 Args: 

6178 **kwargs: Engine options, see ``engine_options``. 

6179 

6180 Returns: 

6181 The engine. 

6182 """ 

6183 

6184 def describe(self, table: DatabaseTableAlike) -> 'DataSetDescription': 

6185 """Describe a table. 

6186 

6187 Args: 

6188 table: Table object or table name. 

6189 

6190 Returns: 

6191 The table description. The first geometry column becomes the primary geometry. 

6192 

6193 Raises: 

6194 ``sqlalchemy.exc.SQLAlchemyError``: If the table does not exist. 

6195 """ 

6196 

6197 def describe_column(self, table: DatabaseTableAlike, column_name: str) -> ColumnDescription: 

6198 """Describe a column in a table. 

6199 

6200 Args: 

6201 table: Table object or table name. 

6202 column_name: Column name. 

6203 

6204 Returns: 

6205 The column description. 

6206 

6207 Raises: 

6208 ``sqlalchemy.exc.SQLAlchemyError``: If the table or the column does not exist. 

6209 """ 

6210 

6211 def table(self, table: 'DatabaseTableAlike', **kwargs) -> 'sqlalchemy.Table': 

6212 """Return the SQLAlchemy ``Table`` object for a table. 

6213 

6214 Args: 

6215 table: Table object or table name. 

6216 **kwargs: Not used by the base provider. 

6217 

6218 Returns: 

6219 The table object. 

6220 

6221 Raises: 

6222 ``sqlalchemy.exc.SQLAlchemyError``: If the table does not exist. 

6223 """ 

6224 

6225 def column(self, table: DatabaseTableAlike, column_name: str) -> 'sqlalchemy.Column': 

6226 """Return the SQLAlchemy ``Column`` object for a column. 

6227 

6228 Args: 

6229 table: Table object or table name. 

6230 column_name: Column name. 

6231 

6232 Returns: 

6233 The column object. 

6234 

6235 Raises: 

6236 ``sqlalchemy.exc.SQLAlchemyError``: If the table or the column does not exist. 

6237 """ 

6238 

6239 def count(self, table: DatabaseTableAlike) -> int: 

6240 """Return the number of rows in a table. 

6241 

6242 Args: 

6243 table: Table object or table name. 

6244 

6245 Returns: 

6246 The row count, or 0 if the table does not exist. 

6247 """ 

6248 

6249 def has_schema(self, schema_name: str) -> bool: 

6250 """Check if a schema exists. 

6251 

6252 Args: 

6253 schema_name: Schema name. 

6254 

6255 Returns: 

6256 ``True`` if the schema exists. 

6257 """ 

6258 

6259 def has_table(self, table_name: str) -> bool: 

6260 """Check if a table exists. 

6261 

6262 Args: 

6263 table_name: Table name, optionally schema-qualified. 

6264 

6265 Returns: 

6266 ``True`` if the table exists. 

6267 """ 

6268 

6269 def has_column(self, table: DatabaseTableAlike, column_name: str) -> bool: 

6270 """Check if a column exists. 

6271 

6272 Args: 

6273 table: Table object or table name. 

6274 column_name: Column name. 

6275 

6276 Returns: 

6277 ``True`` if the table and the column exist. 

6278 """ 

6279 

6280 def join_table_name(self, schema: str, name: str) -> str: 

6281 """Create a full table name from the schema and table names. 

6282 

6283 Args: 

6284 schema: Schema name. If empty, the default schema is used. 

6285 name: Table name. 

6286 

6287 Returns: 

6288 The schema-qualified table name. 

6289 """ 

6290 

6291 def split_table_name(self, table_name: str) -> tuple[str, str]: 

6292 """Split a full table name into the schema and table names. 

6293 

6294 Args: 

6295 table_name: Table name, optionally schema-qualified. 

6296 

6297 Returns: 

6298 A tuple of the schema name (the default schema if none is given) and the table name. 

6299 """ 

6300 

6301 def table_bounds(self, table: DatabaseTableAlike) -> Optional[Bounds]: 

6302 """Compute the bounding box of the primary geometry of a table. 

6303 

6304 Args: 

6305 table: Table object or table name. 

6306 

6307 Returns: 

6308 The bounds, or ``None`` if the table has no geometry or no data. 

6309 """ 

6310 

6311 def select_text(self, sql: str, **kwargs) -> list[dict]: 

6312 """Execute a textual SELECT statement. 

6313 

6314 Args: 

6315 sql: SQL statement with ``:name`` bind parameters. 

6316 **kwargs: Bind parameters. 

6317 

6318 Returns: 

6319 A list of rows as dicts. 

6320 

6321 Raises: 

6322 ``sqlalchemy.exc.SQLAlchemyError``: On database errors, after a rollback. 

6323 """ 

6324 

6325 def execute_text(self, sql: str, **kwargs) -> 'sqlalchemy.CursorResult': 

6326 """Execute a textual statement and commit. 

6327 

6328 Args: 

6329 sql: SQL statement with ``:name`` bind parameters. 

6330 **kwargs: Bind parameters. 

6331 

6332 Returns: 

6333 The result. 

6334 

6335 Raises: 

6336 ``sqlalchemy.exc.SQLAlchemyError``: On database errors, after a rollback. 

6337 """ 

6338 

6339 def schema_names(self) -> list[str]: 

6340 """Return the names of the schemas in the database. 

6341 

6342 Returns: 

6343 A list of schema names. 

6344 """ 

6345 

6346 def inspect_schema(self, schema: str, options: Optional[DatabaseInspectOptions] = None): 

6347 """Reflect the tables of a schema and keep the result. 

6348 

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. 

6353 

6354 Args: 

6355 schema: Schema name. 

6356 options: Inspection options. 

6357 """ 

6358################################################################################ 

6359 

6360 

6361 

6362################################################################################ 

6363# /base/job/types.pyinc 

6364 

6365 

6366class JobTerminated(Exception): 

6367 """Raised in a worker when its job is no longer running, e.g. because it was cancelled.""" 

6368 

6369 pass 

6370 

6371 

6372class JobState(Enum): 

6373 """Background job state.""" 

6374 

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

6387 

6388 

6389class Job(Data): 

6390 """Background job data.""" 

6391 

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

6416 

6417 

6418class JobRequest(Request): 

6419 """Request that refers to a job.""" 

6420 

6421 jobUid: str 

6422 """Job uid.""" 

6423 

6424 

6425class JobStatusResponse(Response): 

6426 """Job status.""" 

6427 

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

6438 

6439 

6440class JobManager(Node): 

6441 """Job manager.""" 

6442 

6443 def create_job(self, worker: type, user: User, payload: dict | Data = None) -> Job: 

6444 """Create a job in the ``open`` state. 

6445 

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. 

6450 

6451 Returns: 

6452 The new job. 

6453 """ 

6454 

6455 def get_job(self, job_uid: str, user: User = None, state: JobState = None) -> Optional[Job]: 

6456 """Read a job. 

6457 

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. 

6462 

6463 Returns: 

6464 The job, or ``None`` if it does not exist or does not match. The reason is logged. 

6465 """ 

6466 

6467 def update_job(self, job: Job, **kwargs) -> Optional[Job]: 

6468 """Update fields of a job. 

6469 

6470 Args: 

6471 job: The job. 

6472 **kwargs: Job fields to update. 

6473 

6474 Returns: 

6475 The updated job, or ``None`` if the job does not exist. 

6476 """ 

6477 

6478 def run_job(self, job: Job) -> Optional[Job]: 

6479 """Run an open job in the current process. 

6480 

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. 

6484 

6485 Args: 

6486 job: The job. 

6487 

6488 Returns: 

6489 The job after the run. 

6490 

6491 Raises: 

6492 ``gws.Error``: If the job is not open or is already taken by another process. 

6493 """ 

6494 

6495 def cancel_job(self, job: Job) -> Optional[Job]: 

6496 """Set a job to the ``cancel`` state. 

6497 

6498 The worker notices the change on its next job update and stops. 

6499 

6500 Args: 

6501 job: The job. 

6502 

6503 Returns: 

6504 The updated job, or ``None`` if the job does not exist. 

6505 """ 

6506 

6507 def remove_job(self, job: Job): 

6508 """Delete a job record. 

6509 

6510 Args: 

6511 job: The job. 

6512 """ 

6513 

6514 def schedule_job(self, job: Job) -> Job: 

6515 """Start an open job. 

6516 

6517 The job is passed to the uWSGI spooler if it is available, otherwise it 

6518 runs at once in the current process. 

6519 

6520 Args: 

6521 job: The job. 

6522 

6523 Returns: 

6524 The job. 

6525 

6526 Raises: 

6527 ``gws.Error``: If the job is not open. 

6528 """ 

6529 

6530 def require_job(self, req: 'WebRequester', p: JobRequest) -> Job: 

6531 """Return the job of a request, if it belongs to the requesting user. 

6532 

6533 Args: 

6534 req: Web request. 

6535 p: Job request. 

6536 

6537 Returns: 

6538 The job. 

6539 

6540 Raises: 

6541 ``gws.NotFoundError``: If the job does not exist or belongs to another user. 

6542 """ 

6543 

6544 def require_result(self, req: 'WebRequester', p: JobRequest) -> dict: 

6545 """Return the result of a completed job of the requesting user. 

6546 

6547 Args: 

6548 req: Web request. 

6549 p: Job request. 

6550 

6551 Returns: 

6552 The job result. 

6553 

6554 Raises: 

6555 ``gws.NotFoundError``: If the job does not exist, belongs to another user, 

6556 is not complete or has no result. 

6557 """ 

6558 

6559 def handle_status_request(self, req: 'WebRequester', p: JobRequest) -> JobStatusResponse: 

6560 """Return the status of a job of the requesting user. 

6561 

6562 Args: 

6563 req: Web request. 

6564 p: Job request. 

6565 

6566 Returns: 

6567 The job status. 

6568 

6569 Raises: 

6570 ``gws.NotFoundError``: If the job does not exist or belongs to another user. 

6571 """ 

6572 

6573 def handle_cancel_request(self, req: 'WebRequester', p: JobRequest) -> JobStatusResponse: 

6574 """Cancel a job of the requesting user. 

6575 

6576 Args: 

6577 req: Web request. 

6578 p: Job request. 

6579 

6580 Returns: 

6581 The job status after cancelling. 

6582 

6583 Raises: 

6584 ``gws.NotFoundError``: If the job does not exist or belongs to another user. 

6585 """ 

6586 

6587 def job_status_response(self, job: Job, **kwargs) -> 'JobStatusResponse': 

6588 """Create a status response for a job. 

6589 

6590 Args: 

6591 job: The job. 

6592 **kwargs: Extra or overriding response fields. 

6593 

6594 Returns: 

6595 The status response. 

6596 """ 

6597################################################################################ 

6598 

6599 

6600################################################################################ 

6601# /base/ows/types.pyinc 

6602 

6603 

6604import gws 

6605 

6606 

6607class OwsProtocol(Enum): 

6608 """Supported OWS protocols.""" 

6609 

6610 WMS = 'WMS' 

6611 WMTS = 'WMTS' 

6612 WCS = 'WCS' 

6613 WFS = 'WFS' 

6614 CSW = 'CSW' 

6615 

6616 

6617class OwsAuthorization(Data): 

6618 """Credentials for accessing an OWS service.""" 

6619 

6620 type: str 

6621 """Authorization type, only ``basic`` is supported.""" 

6622 username: str 

6623 """User name.""" 

6624 password: str 

6625 """Password.""" 

6626 

6627 

6628class OwsVerb(Enum): 

6629 """OWS request type.""" 

6630 

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' 

6652 

6653 

6654class OwsOperation(Data): 

6655 """OWS operation, as offered by a remote service or by our own service.""" 

6656 

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

6675 

6676 

6677class OwsCapabilities(Data): 

6678 """Parsed capabilities of a remote OWS service.""" 

6679 

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

6690 

6691 

6692class OwsService(Node): 

6693 """OWS service provided by GBD WebSuite.""" 

6694 

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

6701 

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

6736 

6737 def handle_request(self, req: 'WebRequester') -> ContentResponse: 

6738 """Handle a service request. 

6739 

6740 Errors are returned as OWS exception documents, not raised. 

6741 

6742 Args: 

6743 req: Web request. 

6744 

6745 Returns: 

6746 The service response. 

6747 """ 

6748 

6749 def layer_is_compatible(self, layer: 'Layer') -> bool: 

6750 """Check if a layer can be used in this service. 

6751 

6752 Args: 

6753 layer: Layer object. 

6754 

6755 Returns: 

6756 ``True`` if the layer can be published by this service. 

6757 """ 

6758 

6759 

6760class OwsServiceProvider(Node): 

6761 """Remote OWS service used as a data provider.""" 

6762 

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

6787 

6788 def get_operation(self, verb: 'OwsVerb', method: Optional['RequestMethod'] = None) -> Optional['OwsOperation']: 

6789 """Find an operation by its verb. 

6790 

6791 Args: 

6792 verb: Request type. 

6793 method: Request method. For ``POST``, the operation must have a POST URL, 

6794 otherwise a GET URL. 

6795 

6796 Returns: 

6797 The operation, or ``None`` if the service does not support it. 

6798 """ 

6799 

6800 def get_features(self, args: 'SearchQuery', source_layers: list['SourceLayer']) -> list['FeatureRecord']: 

6801 """Search for features in the given source layers. 

6802 

6803 Args: 

6804 args: Search query. 

6805 source_layers: Source layers to search. 

6806 

6807 Returns: 

6808 Found feature records. 

6809 """ 

6810################################################################################ 

6811 

6812 

6813################################################################################ 

6814# /base/printer/types.pyinc 

6815 

6816 

6817class PrintPlaneType(Enum): 

6818 """Print plane type.""" 

6819 

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

6832 

6833 

6834class PrintPlane(Data): 

6835 """Print plane, a single map layer in a print request.""" 

6836 

6837 type: PrintPlaneType 

6838 """Plane type.""" 

6839 

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

6844 

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

6853 

6854 url: Optional[str] 

6855 """Data URL of the image, for url planes.""" 

6856 

6857 features: Optional[list['FeatureProps']] 

6858 """Features, for features planes.""" 

6859 

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

6864 

6865 soupPoints: Optional[list[Point]] 

6866 """Points, for soup planes.""" 

6867 soupTags: Optional[list[Any]] 

6868 """SVG tags, for soup planes.""" 

6869 

6870 

6871class PrintMap(Data): 

6872 """Map properties for printing.""" 

6873 

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

6890 

6891 

6892class PrintRequestType(Enum): 

6893 """Type of the print request.""" 

6894 

6895 template = 'template' 

6896 map = 'map' 

6897 

6898 

6899class PrintRequest(Request): 

6900 """Print request.""" 

6901 

6902 type: PrintRequestType 

6903 """Request type.""" 

6904 

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

6913 

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

6920 

6921 

6922class PrintResult(Data): 

6923 """Print result.""" 

6924 

6925 path: str 

6926 """Path of the output file.""" 

6927 mimeType: str 

6928 """Mime type of the output file.""" 

6929 

6930 

6931class Printer(Node): 

6932 """Printer, a print template offered to users.""" 

6933 

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

6942 

6943 

6944class PrinterManager(Node): 

6945 """Print manager.""" 

6946 

6947 def start_print_job(self, request: PrintRequest, user: 'User') -> 'JobStatusResponse': 

6948 """Start a background print job. 

6949 

6950 Args: 

6951 request: Print request. 

6952 user: User who requested the print. 

6953 

6954 Returns: 

6955 The status of the new job. 

6956 """ 

6957 

6958 def exec_print(self, request: PrintRequest, out_path: str): 

6959 """Execute a print request synchronously, as the system user. 

6960 

6961 Args: 

6962 request: Print request. 

6963 out_path: Path to copy the output file to. 

6964 """ 

6965################################################################################ 

6966 

6967 

6968################################################################################ 

6969# /base/project/types.pyinc 

6970 

6971 

6972class Client(Node): 

6973 """Settings for the browser client: UI elements and client options.""" 

6974 

6975 options: dict 

6976 """Client options.""" 

6977 elements: list 

6978 """Client UI elements.""" 

6979 

6980 

6981class Project(Node): 

6982 """Project: a map application with its own map, actions, templates and services.""" 

6983 

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

6988 

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

6997 

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

7012 

7013 vars: dict 

7014 """Custom variables.""" 

7015################################################################################ 

7016 

7017 

7018################################################################################ 

7019# /base/search/types.pyinc 

7020 

7021 

7022class SearchSort(Data): 

7023 """Search sort specification.""" 

7024 

7025 fieldName: str 

7026 """Field name to sort by.""" 

7027 reverse: bool 

7028 """Sort in descending order.""" 

7029 

7030 

7031class SearchFilterOperator(Enum): 

7032 """Search filter operator, as defined in OGC Filter Encoding 2.0.""" 

7033 

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

7040 

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

7061 

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

7084 

7085 

7086class SearchFilterMatchAction(Enum): 

7087 """How a filter is applied to a multi-valued property.""" 

7088 

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

7095 

7096 

7097class SearchFilter(Data): 

7098 """Search filter, a tree of filter operators.""" 

7099 

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

7120 

7121 

7122class SearchQuery(Data): 

7123 """Search query.""" 

7124 

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

7155 

7156 

7157class SearchResult(Data): 

7158 """Search result.""" 

7159 

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

7166 

7167 

7168class TextSearchType(Enum): 

7169 """Text search type.""" 

7170 

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

7181 

7182 

7183class TextSearchOptions(Data): 

7184 """How keywords are matched against a text field.""" 

7185 

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

7192 

7193 

7194class SortOptions(Data): 

7195 """Sort order for features.""" 

7196 

7197 fieldName: str 

7198 """Field name to sort by.""" 

7199 reverse: bool = False 

7200 """Sort in descending order.""" 

7201 

7202 

7203class SearchManager(Node): 

7204 """Search manager, runs search queries through the finders.""" 

7205 

7206 def run_search(self, search: 'SearchQuery', user: 'User') -> list['SearchResult']: 

7207 """Run a search query. 

7208 

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. 

7211 

7212 Args: 

7213 search: Search query. 

7214 user: User running the search. 

7215 

7216 Returns: 

7217 Search results, at most ``search.limit`` if a limit is given. 

7218 """ 

7219 

7220 

7221class Finder(Node): 

7222 """Search provider, finds features for search queries.""" 

7223 

7224 title: str 

7225 """Finder title.""" 

7226 category: str 

7227 """Category assigned to the results.""" 

7228 

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

7235 

7236 withFilter: bool 

7237 """Filter searches are enabled.""" 

7238 withGeometry: bool 

7239 """Geometry searches are enabled.""" 

7240 withKeyword: bool 

7241 """Keyword searches are enabled.""" 

7242 

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

7249 

7250 tolerance: 'UomValue' 

7251 """Tolerance for geometry searches.""" 

7252 

7253 def run(self, search: SearchQuery, user: 'User', layer: Optional['Layer'] = None) -> list['Feature']: 

7254 """Run a search query. 

7255 

7256 Args: 

7257 search: Search query. 

7258 user: User running the search. 

7259 layer: Layer the finder belongs to, if any. 

7260 

7261 Returns: 

7262 Found features. 

7263 """ 

7264 

7265 def can_run(self, search: SearchQuery, user: 'User') -> bool: 

7266 """Check if the finder can run a search query. 

7267 

7268 Args: 

7269 search: Search query. 

7270 user: User running the search. 

7271 

7272 Returns: 

7273 ``True`` if the finder can run the query. 

7274 """ 

7275################################################################################ 

7276 

7277 

7278################################################################################ 

7279# /base/storage/types.pyinc 

7280 

7281 

7282class StorageManager(Node): 

7283 """Storage manager, holds the storage providers.""" 

7284 

7285 providers: list['StorageProvider'] 

7286 """Configured storage providers.""" 

7287 

7288 def create_provider(self, cfg: Config, **kwargs) -> 'StorageProvider': 

7289 """Create a storage provider and add it to the manager. 

7290 

7291 A provider with the same uid replaces the existing one. 

7292 

7293 Args: 

7294 cfg: Provider configuration. 

7295 **kwargs: Extra configuration values. 

7296 

7297 Returns: 

7298 The new provider. 

7299 """ 

7300 

7301 def find_provider(self, uid: Optional[str] = None) -> Optional['StorageProvider']: 

7302 """Find a storage provider. 

7303 

7304 Args: 

7305 uid: Provider uid. If not given, the first provider is returned. 

7306 

7307 Returns: 

7308 The provider, or ``None`` if not found. 

7309 """ 

7310 

7311 

7312 

7313class StorageRecord(Data): 

7314 """Storage record.""" 

7315 

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

7326 

7327 

7328class StorageProvider(Node): 

7329 """Storage provider, stores named records grouped by category.""" 

7330 

7331 def list_names(self, category: str) -> list[str]: 

7332 """List the record names in a category. 

7333 

7334 Args: 

7335 category: Category name. 

7336 

7337 Returns: 

7338 Record names. 

7339 """ 

7340 

7341 def read(self, category: str, name: str) -> Optional['StorageRecord']: 

7342 """Read a record. 

7343 

7344 Args: 

7345 category: Category name. 

7346 name: Record name. 

7347 

7348 Returns: 

7349 The record, or ``None`` if not found. 

7350 """ 

7351 

7352 def write(self, category: str, name: str, data: str, user_uid: str): 

7353 """Create a record or update an existing one. 

7354 

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 """ 

7361 

7362 def delete(self, category: str, name: str): 

7363 """Delete a record. 

7364 

7365 Args: 

7366 category: Category name. 

7367 name: Record name. 

7368 """ 

7369################################################################################ 

7370 

7371 

7372################################################################################ 

7373# /base/template/types.pyinc 

7374 

7375 

7376class TemplateArgs(Data): 

7377 """Template arguments.""" 

7378 

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

7389 

7390 

7391class TemplateRenderInput(Data): 

7392 """Template render input.""" 

7393 

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

7412 

7413 

7414class TemplateQualityLevel(Config): 

7415 """Print quality level users can choose.""" 

7416 

7417 name: str 

7418 """Quality level name shown to users.""" 

7419 dpi: int 

7420 """Print resolution in dots per inch.""" 

7421 

7422 

7423class Template(Node): 

7424 """Template, generates content from data.""" 

7425 

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

7438 

7439 def render(self, tri: TemplateRenderInput) -> ContentResponse: 

7440 """Render the template. 

7441 

7442 Args: 

7443 tri: Render input. 

7444 

7445 Returns: 

7446 A response with the generated content. 

7447 """ 

7448 

7449 

7450class TemplateManager(Node): 

7451 """Template manager, finds templates by subject and creates them from files.""" 

7452 

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. 

7455 

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. 

7461 

7462 Returns: 

7463 Found templates, one per subject at most. 

7464 """ 

7465 

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. 

7468 

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. 

7472 

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. 

7478 

7479 Returns: 

7480 The first matching template, or ``None``. 

7481 """ 

7482 

7483 def template_from_path(self, path: str) -> Optional['Template']: 

7484 """Create a template from a file. 

7485 

7486 The template type is derived from the file extension. 

7487 

7488 Args: 

7489 path: File path. 

7490 

7491 Returns: 

7492 A template, or ``None`` if the file is not a template. 

7493 """ 

7494################################################################################ 

7495 

7496 

7497################################################################################ 

7498# /base/web/types.pyinc 

7499 

7500 

7501class RequestMethod(Enum): 

7502 """Web request method.""" 

7503 

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' 

7513 

7514 

7515class WebRequester: 

7516 """Web requester, gives access to an incoming web request.""" 

7517 

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

7528 

7529 session: 'AuthSession' 

7530 """Current session.""" 

7531 user: 'User' 

7532 """Current user.""" 

7533 

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

7544 

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

7553 

7554 def parse(self): 

7555 """Parse the request path, the parameters and the structured payload. 

7556 

7557 Also determines the scheme, host, port and client address, taking proxy 

7558 headers into account if the site has proxies. 

7559 

7560 Raises: 

7561 ``gws.base.web.error.HTTPException``: If the request path, the host or the payload is invalid. 

7562 """ 

7563 

7564 def params(self) -> dict: 

7565 """Return the GET parameters. 

7566 

7567 Returns: 

7568 Parameters from the query string and from the request path. 

7569 """ 

7570 

7571 def query_params(self) -> dict: 

7572 """Return the GET parameters from the query string. 

7573 

7574 Returns: 

7575 Query string parameters. 

7576 """ 

7577 

7578 def path(self) -> str: 

7579 """Return the request path after the command. 

7580 

7581 Returns: 

7582 The rest of the path after ``/_/<command>/``. 

7583 """ 

7584 

7585 def struct(self) -> dict: 

7586 """Return the structured payload of an API request. 

7587 

7588 Returns: 

7589 The decoded JSON or MessagePack payload. 

7590 """ 

7591 

7592 def command(self) -> str: 

7593 """Return the command name. 

7594 

7595 Returns: 

7596 The command from the path, or from the ``cmd`` parameter. 

7597 """ 

7598 

7599 def data(self) -> bytes: 

7600 """Return the raw POST data, unzipped if gzip-encoded. 

7601 

7602 Returns: 

7603 POST data, empty for non-POST requests. 

7604 

7605 Raises: 

7606 ``gws.base.web.error.HTTPException``: If the content length is invalid or too large, or the data cannot be unzipped. 

7607 """ 

7608 

7609 def form(self) -> list[tuple[str, Any]]: 

7610 """Return the POST form data. 

7611 

7612 Returns: 

7613 A list of ``(key, value)`` tuples, including uploaded files; empty if the request is not a form. 

7614 

7615 Raises: 

7616 ``gws.base.web.error.HTTPException``: If the form data cannot be decoded. 

7617 """ 

7618 

7619 def text(self) -> str: 

7620 """Return the POST data decoded to text, with the charset of the request. 

7621 

7622 Returns: 

7623 POST data as text. 

7624 

7625 Raises: 

7626 ``gws.base.web.error.HTTPException``: If the data cannot be decoded. 

7627 """ 

7628 

7629 def cookie(self, key: str, default: str = '') -> str: 

7630 """Get a cookie. 

7631 

7632 Args: 

7633 key: Cookie name. 

7634 default: Default value. 

7635 

7636 Returns: 

7637 A cookie value. 

7638 """ 

7639 

7640 def header(self, key: str, default: str = '') -> str: 

7641 """Get a header. 

7642 

7643 Args: 

7644 key: Header name. 

7645 default: Default value. 

7646 

7647 Returns: 

7648 A header value. 

7649 """ 

7650 

7651 def has_param(self, key: str) -> bool: 

7652 """Check if a GET parameter exists, ignoring case. 

7653 

7654 Args: 

7655 key: Parameter name. 

7656 

7657 Returns: 

7658 ``True`` if the parameter exists. 

7659 """ 

7660 

7661 def param(self, key: str, default: str = '') -> str: 

7662 """Get a GET parameter, ignoring case. 

7663 

7664 Args: 

7665 key: Parameter name. 

7666 default: Default value. 

7667 

7668 Returns: 

7669 A parameter value. 

7670 """ 

7671 

7672 def env(self, key: str, default: str = '') -> str: 

7673 """Get a WSGI environment variable. 

7674 

7675 Args: 

7676 key: Variable name. 

7677 default: Default value. 

7678 

7679 Returns: 

7680 A variable value. 

7681 """ 

7682 

7683 def content_responder(self, response: ContentResponse) -> 'WebResponder': 

7684 """Create a responder for a content response. 

7685 

7686 Args: 

7687 response: Response with literal content or a content path. 

7688 

7689 Returns: 

7690 A responder. 

7691 """ 

7692 

7693 def redirect_responder(self, response: RedirectResponse) -> 'WebResponder': 

7694 """Create a responder for a redirect response. 

7695 

7696 Args: 

7697 response: Redirect response. 

7698 

7699 Returns: 

7700 A responder. 

7701 """ 

7702 

7703 def api_responder(self, response: Response) -> 'WebResponder': 

7704 """Create a responder for an API (structured) response. 

7705 

7706 The response is encoded as JSON or MessagePack, depending on the request. 

7707 

7708 Args: 

7709 response: Response object. 

7710 

7711 Returns: 

7712 A responder. 

7713 """ 

7714 

7715 def error_responder(self, exc: Exception) -> 'WebResponder': 

7716 """Create a responder for an exception. 

7717 

7718 Args: 

7719 exc: An exception; anything but an HTTP exception results in a 500 response. 

7720 

7721 Returns: 

7722 A responder. 

7723 """ 

7724 

7725 def absolute_url_for(self, request_path: str, **params) -> str: 

7726 """Create an absolute URL pointing to the requested host. 

7727 

7728 Args: 

7729 request_path: Request path. 

7730 **params: Additional GET parameters. 

7731 

7732 Returns: 

7733 A URL. 

7734 """ 

7735 

7736 def relative_url_for(self, request_path: str, **params) -> str: 

7737 """Create a host-relative URL. 

7738 

7739 Args: 

7740 request_path: Request path. 

7741 **params: Additional GET parameters. 

7742 

7743 Returns: 

7744 A URL. 

7745 """ 

7746 

7747 def canonical_url_for(self, request_path: str, **params) -> str: 

7748 """Create an absolute URL pointing to the canonical host. 

7749 

7750 Args: 

7751 request_path: Request path. 

7752 **params: Additional GET parameters. 

7753 

7754 Returns: 

7755 A URL. 

7756 """ 

7757 

7758 def set_session(self, session: 'AuthSession'): 

7759 """Attach a session to the requester and set the user from it. 

7760 

7761 Args: 

7762 session: A session object. 

7763 """ 

7764 

7765 

7766class WebResponder: 

7767 """Web responder, builds and sends the response to a web request.""" 

7768 

7769 status: int 

7770 """Response status.""" 

7771 

7772 def send_response(self, environ: dict, start_response: Callable): 

7773 """Send the response to the client. 

7774 

7775 Args: 

7776 environ: WSGI environment. 

7777 start_response: WSGI ``start_response`` function. 

7778 

7779 Returns: 

7780 The WSGI response iterable. 

7781 """ 

7782 

7783 def set_cookie(self, key: str, value: str, **kwargs): 

7784 """Set a cookie. 

7785 

7786 Args: 

7787 key: Cookie name. 

7788 value: Cookie value. 

7789 **kwargs: Cookie options. 

7790 """ 

7791 

7792 def delete_cookie(self, key: str, **kwargs): 

7793 """Delete a cookie. 

7794 

7795 Args: 

7796 key: Cookie name. 

7797 **kwargs: Cookie options. 

7798 """ 

7799 

7800 def set_status(self, status: int): 

7801 """Set the response status. 

7802 

7803 Args: 

7804 status: HTTP status code. 

7805 """ 

7806 

7807 def add_header(self, key: str, value: str): 

7808 """Add a header. 

7809 

7810 Args: 

7811 key: Header name. 

7812 value: Header value. 

7813 """ 

7814 

7815 def set_body(self, body: str | bytes): 

7816 """Set the response body. 

7817 

7818 Args: 

7819 body: New response body; strings are encoded as UTF-8. 

7820 """ 

7821 

7822 

7823class WebDocumentRoot(Data): 

7824 """Directory served over the web.""" 

7825 

7826 dir: DirPath 

7827 """Local directory.""" 

7828 allowMime: list[str] 

7829 """Allowed mime types.""" 

7830 denyMime: list[str] 

7831 """Restricted mime types.""" 

7832 

7833 

7834class WebRewriteRule(Data): 

7835 """URL rewrite rule.""" 

7836 

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

7845 

7846 

7847class WebCors(Data): 

7848 """CORS options.""" 

7849 

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

7858 

7859 

7860class WebManager(Node): 

7861 """Web manager, holds the web site.""" 

7862 

7863 site: 'WebSite' 

7864 """Configured web site.""" 

7865 

7866 

7867class WebSite(Node): 

7868 """Web site the server responds to.""" 

7869 

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

7886 

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. 

7889 

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. 

7894 

7895 Args: 

7896 req: Web requester. 

7897 path: Request path. 

7898 mode: ``absolute``, ``relative`` or ``canonical``. 

7899 **params: Extra GET parameters. 

7900 

7901 Returns: 

7902 A URL. 

7903 

7904 Raises: 

7905 ``gws.BadRequestError``: If an absolute URL is requested and there is no host. 

7906 """ 

7907################################################################################ 

7908 

7909 

7910################################################################################ 

7911# /base/exporter/types.pyinc 

7912 

7913 

7914class ExportArgs(Data): 

7915 """Arguments passed to ``Exporter.run``.""" 

7916 

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

7931 

7932 

7933class ExportTarget(Enum): 

7934 """Export target.""" 

7935 

7936 file = 'file' 

7937 """Save the export result to a file on the server.""" 

7938 download = 'download' 

7939 """Return the export result for download.""" 

7940 

7941 

7942class ExportResult(Data): 

7943 """Export result.""" 

7944 

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

7957 

7958 

7959class FeatureExportStrategy(Enum): 

7960 """How exported features are obtained.""" 

7961 

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

7966 

7967 

7968class ExportRequestType(Enum): 

7969 """Kind of data to export.""" 

7970 

7971 vector = 'vector' 

7972 """Vector features.""" 

7973 raster = 'raster' 

7974 """Raster data.""" 

7975 

7976 

7977class ExportRequest(Request): 

7978 """Export request from the client.""" 

7979 

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

7988 

7989 

7990class ExportResponse(Response): 

7991 """Export response with the content of the result file.""" 

7992 

7993 content: str | bytes 

7994 """File content.""" 

7995 contentFilename: str 

7996 """File name.""" 

7997 mimeType: str 

7998 """Mime type.""" 

7999 

8000 

8001class ExporterManager(Node): 

8002 """Exporter manager.""" 

8003 

8004 def start_export_job(self, request: ExportRequest, user: 'User') -> 'JobStatusResponse': 

8005 """Create and schedule a background export job. 

8006 

8007 Args: 

8008 request: Export request. 

8009 user: User the export runs for. 

8010 

8011 Returns: 

8012 The status of the new job. 

8013 """ 

8014 

8015 def exec_export(self, request: ExportRequest, out_path: str): 

8016 """Run an export directly, as the system user, and copy the result file. 

8017 

8018 Args: 

8019 request: Export request. 

8020 out_path: Path to copy the result file to. 

8021 

8022 Returns: 

8023 The export result. 

8024 

8025 Raises: 

8026 ``gws.Error``: If no features were exported. 

8027 """ 

8028 

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. 

8031 

8032 Of several exporters with the same title, only the first one is listed. 

8033 

8034 Args: 

8035 where: Objects with an ``exporters`` list, e.g. a project and the application. 

8036 ``None`` entries are ignored. 

8037 user: User. 

8038 

8039 Returns: 

8040 A list of exporters. 

8041 """ 

8042 

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. 

8045 

8046 Args: 

8047 where: Objects with an ``exporters`` list, e.g. a project and the application. 

8048 uid: Exporter uid. 

8049 user: User. 

8050 

8051 Returns: 

8052 The exporter, or ``None`` if it is not found. 

8053 """ 

8054 

8055 

8056class Exporter(Node): 

8057 """Exporter. 

8058 

8059 Writes features to files in a specific format. 

8060 """ 

8061 

8062 title: str 

8063 """Exporter title, shown in the client.""" 

8064 options: dict 

8065 """Format-specific options, passed to the GDAL driver.""" 

8066 

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

8073 

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

8082 

8083 supportedAttributeTypes: Optional[list[gws.AttributeType]] 

8084 """Attribute types the exporter can write. If empty, the types supported by GDAL are used.""" 

8085 

8086 def run(self, ea: ExportArgs, er: ExportResult): 

8087 """Export the features. 

8088 

8089 Writes the result file and sets its path, the mime type, the counts 

8090 and errors in the export result. 

8091 

8092 Args: 

8093 ea: Export arguments. 

8094 er: Export result, filled by the exporter. 

8095 """ 

8096################################################################################ 

8097 

8098 

8099 

8100################################################################################ 

8101# /base/application/types.pyinc 

8102 

8103 

8104class MiddlewareManager(Node): 

8105 """Middleware manager. 

8106 

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 """ 

8111 

8112 def register(self, obj: Node, name: str, depends_on: Optional[list[str]] = None): 

8113 """Register an object as a middleware. 

8114 

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 """ 

8120 

8121 def objects(self) -> list[Node]: 

8122 """Return the registered middleware objects in dependency order. 

8123 

8124 Returns: 

8125 A list of middleware objects, dependencies first. 

8126 

8127 Raises: 

8128 Error: If the dependencies are cyclic or refer to an unknown name. 

8129 """ 

8130 

8131 

8132class TemplateOptions(Data): 

8133 """Options for the built-in application and project home pages.""" 

8134 

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

8145 

8146 

8147class Application(Node): 

8148 """Application object. 

8149 

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 """ 

8153 

8154 client: 'Client' 

8155 """Default client, used by projects without their own client configuration.""" 

8156 

8157 localeUids: list[str] 

8158 """Default locale uids for all projects.""" 

8159 

8160 metadata: 'Metadata' 

8161 """Application metadata.""" 

8162 

8163 monitor: 'ServerMonitor' 

8164 """Server monitor, watches configuration files and runs periodic tasks.""" 

8165 

8166 templateOptions: TemplateOptions 

8167 """Options for the built-in home page templates.""" 

8168 

8169 title: str 

8170 """Application title.""" 

8171 

8172 vars: dict 

8173 """Custom variables from the configuration.""" 

8174 

8175 version: str 

8176 """Application version, for example ``8.5.3``.""" 

8177 

8178 versionString: str 

8179 """Version string for display, with the revision if known.""" 

8180 

8181 def supported_crs(self) -> list['Crs']: 

8182 """Return all CRS supported by the application. 

8183 

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. 

8186 

8187 Returns: 

8188 A list of CRS objects, sorted by srid. 

8189 """ 

8190 

8191 def register_supported_crs(self, crs: 'Crs'): 

8192 """Register an additional supported CRS. 

8193 

8194 Must be called during configuration. 

8195 

8196 Args: 

8197 crs: The CRS object. 

8198 """ 

8199 

8200 defaultPrinter: 'Printer' 

8201 """Default printer, used when no printer is configured.""" 

8202 

8203 actionMgr: 'ActionManager' 

8204 """Action manager.""" 

8205 

8206 authMgr: 'AuthManager' 

8207 """Authorization manager.""" 

8208 

8209 databaseMgr: 'DatabaseManager' 

8210 """Database manager.""" 

8211 

8212 exporterMgr: 'ExporterManager' 

8213 """Exporter manager.""" 

8214 

8215 jobMgr: 'JobManager' 

8216 """Job manager.""" 

8217 

8218 middlewareMgr: 'MiddlewareManager' 

8219 """Middleware manager.""" 

8220 

8221 modelMgr: 'ModelManager' 

8222 """Model manager.""" 

8223 

8224 printerMgr: 'PrinterManager' 

8225 """Printer manager.""" 

8226 

8227 searchMgr: 'SearchManager' 

8228 """Search manager.""" 

8229 

8230 serverMgr: 'ServerManager' 

8231 """Server manager.""" 

8232 

8233 storageMgr: 'StorageManager' 

8234 """Storage manager.""" 

8235 

8236 templateMgr: 'TemplateManager' 

8237 """Template manager.""" 

8238 

8239 webMgr: 'WebManager' 

8240 """Web manager.""" 

8241 

8242 actions: list['Action'] 

8243 """Actions available in all projects.""" 

8244 

8245 projects: list['Project'] 

8246 """Configured projects.""" 

8247 

8248 exporters: list['Exporter'] 

8249 """Global exporters.""" 

8250 

8251 finders: list['Finder'] 

8252 """Finders available in all projects.""" 

8253 

8254 templates: list['Template'] 

8255 """Global templates, including the built-in ones.""" 

8256 

8257 printers: list['Printer'] 

8258 """Global printers.""" 

8259 

8260 models: list['Model'] 

8261 """Global models.""" 

8262 

8263 owsServices: list['OwsService'] 

8264 """OWS services provided by the server.""" 

8265 

8266 def project(self, uid: str) -> Optional['Project']: 

8267 """Find a project by its uid. 

8268 

8269 Args: 

8270 uid: Project uid. 

8271 

8272 Returns: 

8273 The project, or ``None`` if not found. 

8274 """ 

8275 

8276 def helper(self, ext_type: str) -> Optional['Node']: 

8277 """Return a helper object by its type. 

8278 

8279 A helper that is not configured is created with default options on the first call. 

8280 

8281 Args: 

8282 ext_type: Helper type, for example ``upload``. 

8283 

8284 Returns: 

8285 The helper object. 

8286 

8287 Raises: 

8288 Error: If the helper type does not exist. 

8289 """ 

8290 

8291 def developer_option(self, key: str): 

8292 """Return the value of a developer option. 

8293 

8294 Developer options are configured in the ``developer`` property of the 

8295 application config and are meant for development and debugging only. 

8296 

8297 Args: 

8298 key: Option name, for example ``template.always_reload``. 

8299 

8300 Returns: 

8301 The option value, or ``None`` if it is not set. 

8302 """ 

8303################################################################################