Coverage for gws-app / gws / __init__.py: 99%

2022 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-03 10:12 +0100

1"""Basic types. 

2 

3This module contains essential type definitions and utilities from the core GWS library. 

4It should be imported in every gws module. 

5""" 

6 

7from typing import ( 

8 TYPE_CHECKING, 

9 TypeAlias, 

10 cast, 

11 Any, 

12 Callable, 

13 ContextManager, 

14 Generator, 

15 Iterable, 

16 Iterator, 

17 Literal, 

18 Optional, 

19 Protocol, 

20 Union, 

21) 

22 

23from collections.abc import ( 

24 Mapping, 

25 Sequence, 

26) 

27 

28import enum 

29import datetime 

30 

31if TYPE_CHECKING: 

32 import sqlalchemy 

33 import numpy.typing 

34 

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

36 

37 

38from . import ext 

39 

40from .core import ( 

41 log, 

42 debug, 

43 env, 

44 const as c, 

45 util as u, 

46) 

47 

48 

49################################################################################ 

50# /core/_data.pyinc 

51 

52 

53# basic data type 

54 

55class Data: 

56 """Basic data object. 

57 

58 This object can be instantiated by passing one or or ``dict`` arguments 

59 and/or keyword args. All dicts keys and keywords become attributes of the object. 

60 

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

62 unless the attribute name starts with an underscore. 

63 """ 

64 

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

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

67 

68 def __repr__(self): 

69 return repr(vars(self)) 

70 

71 def __getitem__(self, key): 

72 return vars(self).get(key) 

73 

74 def __setitem__(self, key, value): 

75 vars(self)[key] = value 

76 

77 # def __getattr__(self, attr): 

78 # if attr.startswith('_'): 

79 # # do not use None fallback for special props 

80 # raise AttributeError(attr) 

81 # return None 

82 

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

84 """Get an attribute value. 

85 

86 Args: 

87 key: Attribute name. 

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

89 """ 

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

91 

92 def setdefault(self, key, val): 

93 """Set an attribute value if not already set. 

94 

95 Args: 

96 key: Attribute name. 

97 val: Attribute value. 

98 """ 

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

100 

101 def set(self, key, val): 

102 """Set an attribute value. 

103 

104 Args: 

105 key: Attribute name. 

106 val: Attribute value. 

107 """ 

108 vars(self)[key] = val 

109 

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

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

112 

113 Args: 

114 *args: Dicts or Mappings. 

115 kwargs: Keyword args. 

116 """ 

117 

118 d = {} 

119 for a in args: 

120 if isinstance(a, Mapping): 

121 d.update(a) 

122 elif isinstance(a, Data): 

123 d.update(vars(a)) 

124 d.update(kwargs) 

125 vars(self).update(d) 

126 

127 

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

129 

130def _data_getattr(self, attr): 

131 if attr.startswith('_'): 

132 # do not use None fallback for special props 

133 raise AttributeError(attr) 

134 return None 

135 

136 

137setattr(Data, '__getattr__', _data_getattr) 

138 

139 

140def is_data_object(x): 

141 """True if the argument is a ``Data`` object.""" 

142 return isinstance(x, Data) 

143 

144 

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

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

147 

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

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

150 

151 Args: 

152 x: A Mapping or ``None``. 

153 """ 

154 

155 if is_data_object(x): 

156 return x 

157 if isinstance(x, Mapping): 

158 return Data(x) 

159 if x is None: 

160 return Data() 

161 raise ValueError(f'cannot convert {x!r} to Data') 

162################################################################################ 

163 

164 

165 

166u.is_data_object = is_data_object 

167u.to_data_object = to_data_object 

168 

169 

170 

171################################################################################ 

172# /core/_basic.pyinc 

173 

174 

175class Enum(enum.Enum): 

176 """Enumeration type. 

177 

178 Despite being declared as extending ``Enum`` (for IDE support), this class is actually just a simple object 

179 and intended to be used as a collection of attributes. It doesn't provide any ``Enum``-specific utilities. 

180 

181 The rationale behind this is that we need ``Enum`` members (e.g. ``Color.RED``) to be scalars, 

182 and not complex objects as in the standard ``Enum``. 

183 """ 

184 pass 

185 

186 

187# hack to make Enum a simple object 

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

189 

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

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

192 

193Point: TypeAlias = tuple[float, float] 

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

195 

196Size: TypeAlias = tuple[float, float] 

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

198 

199 

200class Origin(Enum): 

201 """Grid origin.""" 

202 

203 nw = 'nw' 

204 """North-west.""" 

205 sw = 'sw' 

206 """South-west.""" 

207 ne = 'ne' 

208 """North-east.""" 

209 se = 'se' 

210 """South-east.""" 

211 lt = 'nw' 

212 """Left top.""" 

213 lb = 'sw' 

214 """Left bottom.""" 

215 rt = 'ne' 

216 """Right top.""" 

217 rb = 'se' 

218 """Right bottom.""" 

219 

220 

221FilePath: TypeAlias = str 

222"""File path on the server.""" 

223 

224DirPath: TypeAlias = str 

225"""Directory path on the server.""" 

226 

227Duration: TypeAlias = str 

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

229 

230Color: TypeAlias = str 

231"""CSS color name.""" 

232 

233Regex: TypeAlias = str 

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

235 

236FormatStr: TypeAlias = str 

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

238 

239DateStr: TypeAlias = str 

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

241 

242DateTimeStr: TypeAlias = str 

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

244 

245Url: TypeAlias = str 

246"""URL.""" 

247 

248ClassRef: TypeAlias = type | str 

249"""Class reference, a type, and 'ext' object or a class name.""" 

250 

251 

252class Config(Data): 

253 """Object configuration.""" 

254 

255 uid: str = '' 

256 """Unique ID.""" 

257 

258 

259class Props(Data): 

260 """Object properties.""" 

261 

262 uid: str = '' 

263 """Unique ID.""" 

264 

265 

266class Request(Data): 

267 """Command request.""" 

268 

269 projectUid: Optional[str] 

270 """Unique ID of the project.""" 

271 localeUid: Optional[str] 

272 """Locale ID for this request.""" 

273 

274 

275class EmptyRequest(Data): 

276 """Empty command request.""" 

277 

278 pass 

279 

280 

281class ResponseError(Data): 

282 """Response error.""" 

283 

284 code: Optional[int] 

285 """Error code.""" 

286 info: Optional[str] 

287 """Information about the error.""" 

288 

289 

290class Response(Data): 

291 """Command response.""" 

292 

293 error: Optional[ResponseError] 

294 """Response error.""" 

295 status: int 

296 """Response status or exit code.""" 

297 

298 

299class ContentResponse(Response): 

300 """Web response with literal content.""" 

301 

302 content: bytes | str 

303 """Response content.""" 

304 contentFilename: str 

305 """Name for the attachment, if provided, content will be served as an attachment.""" 

306 contentPath: str 

307 """Local path with the content.""" 

308 mime: str 

309 """Response mime type.""" 

310 headers: dict 

311 """Additional headers.""" 

312 

313 

314class RedirectResponse(Response): 

315 """Web redirect response.""" 

316 

317 location: str 

318 """Redirect URL.""" 

319 headers: dict 

320 """Additional headers.""" 

321 

322 

323class AttributeType(Enum): 

324 """Feature attribute type.""" 

325 

326 bool = 'bool' 

327 """Boolean value.""" 

328 bytes = 'bytes' 

329 """Binary data.""" 

330 date = 'date' 

331 """Date value.""" 

332 datetime = 'datetime' 

333 """Date and time value.""" 

334 feature = 'feature' 

335 """Feature reference.""" 

336 featurelist = 'featurelist' 

337 """List of features.""" 

338 file = 'file' 

339 """File reference.""" 

340 float = 'float' 

341 """Floating-point number.""" 

342 floatlist = 'floatlist' 

343 """List of floating-point numbers.""" 

344 geometry = 'geometry' 

345 """Geometry reference.""" 

346 int = 'int' 

347 """Integer number.""" 

348 intlist = 'intlist' 

349 """List of integer numbers.""" 

350 str = 'str' 

351 """String value.""" 

352 strlist = 'strlist' 

353 """List of strings.""" 

354 time = 'time' 

355 """Time value.""" 

356 

357 

358class GeometryType(Enum): 

359 """Feature geometry type. 

360 

361 OGC and SQL/MM geometry types. 

362 

363 References: 

364 

365 - OGC 06-103r4 (https://www.ogc.org/standards/sfa),  

366 - https://postgis.net/docs/manual-3.3/using_postgis_dbmanagement.html 

367 """ 

368 

369 geometry = 'geometry' 

370 

371 point = 'point' 

372 curve = 'curve' 

373 surface = 'surface' 

374 

375 geometrycollection = 'geometrycollection' 

376 

377 linestring = 'linestring' 

378 line = 'line' 

379 linearring = 'linearring' 

380 

381 polygon = 'polygon' 

382 triangle = 'triangle' 

383 

384 polyhedralsurface = 'polyhedralsurface' 

385 tin = 'tin' 

386 

387 multipoint = 'multipoint' 

388 multicurve = 'multicurve' 

389 multilinestring = 'multilinestring' 

390 multipolygon = 'multipolygon' 

391 multisurface = 'multisurface' 

392 

393 circularstring = 'circularstring' 

394 compoundcurve = 'compoundcurve' 

395 curvepolygon = 'curvepolygon' 

396 

397 

398class CliParams(Data): 

399 """CLI params""" 

400 pass 

401################################################################################ 

402 

403 

404################################################################################ 

405# /core/_access.pyinc 

406 

407 

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

409"""Access Control list. 

410 

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

412""" 

413 

414AclStr: TypeAlias = str 

415"""A string of comma-separated pairs ``allow <role>`` or ``deny <role>``.""" 

416 

417 

418class Access(Enum): 

419 """Access mode.""" 

420 

421 read = 'read' 

422 """Permission to read the object.""" 

423 write = 'write' 

424 """Permission to change the object.""" 

425 create = 'create' 

426 """Permission to create new objects.""" 

427 delete = 'delete' 

428 """Permission to delete objects.""" 

429 

430 

431class PermissionsConfig: 

432 """Permissions configuration.""" 

433 

434 all: Optional[AclStr] 

435 """All permissions.""" 

436 read: Optional[AclStr] 

437 """Permission to read the object.""" 

438 write: Optional[AclStr] 

439 """Permission to change the object.""" 

440 create: Optional[AclStr] 

441 """Permission to create new objects.""" 

442 delete: Optional[AclStr] 

443 """Permission to delete objects.""" 

444 edit: Optional[AclStr] 

445 """A combination of write, create and delete.""" 

446 

447 

448class ConfigWithAccess(Config): 

449 """Basic config with permissions.""" 

450 

451 access: Optional[AclStr] 

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

453 permissions: Optional[PermissionsConfig] 

454 """Access permissions.""" 

455################################################################################ 

456 

457 

458################################################################################ 

459# /core/_error.pyinc 

460 

461 

462"""App Error object""" 

463 

464class Error(Exception): 

465 """Generic GWS error.""" 

466 def __repr__(self): 

467 return log.exception_backtrace(self)[0] 

468 

469 

470class ConfigurationError(Error): 

471 """GWS Configuration error.""" 

472 pass 

473 

474 

475class NotFoundError(Error): 

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

477 pass 

478 

479 

480class ForbiddenError(Error): 

481 """Generic 'forbidden' error.""" 

482 pass 

483 

484 

485class BadRequestError(Error): 

486 """Generic 'bad request' error.""" 

487 pass 

488 

489 

490class ResponseTooLargeError(Error): 

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

492 pass 

493################################################################################ 

494 

495 

496 

497################################################################################ 

498# /spec/types.pyinc 

499 

500 

501class ApplicationManifestPlugin(Data): 

502 """Plugin description.""" 

503 

504 path: DirPath 

505 """Path to the plugin python module.""" 

506 

507 name: str = '' 

508 """Optional name, when omitted, the directory name will be used.""" 

509 

510 

511class ApplicationManifest(Data): 

512 """Application manifest.""" 

513 

514 excludePlugins: Optional[list[str]] 

515 """Names of the core plugins that should be deactivated.""" 

516 plugins: Optional[list[ApplicationManifestPlugin]] 

517 """Custom plugins.""" 

518 locales: list[str] 

519 """Locale names supported by this application.""" 

520 tsConfig: list[str] 

521 """Path to tsconfig.json.""" 

522 withFallbackConfig: bool = False 

523 """Use a minimal fallback configuration.""" 

524 withStrictConfig: bool = False 

525 """Stop the application upon a configuration error.""" 

526 

527 

528class ExtObjectDescriptor(Data): 

529 """Extension object descriptor.""" 

530 

531 extName: str 

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

533 extType: str 

534 """Extension type like ``wms``.""" 

535 classPtr: type 

536 """Class object.""" 

537 ident: str 

538 """Identifier.""" 

539 modName: str 

540 """Name of the module that contains the class.""" 

541 modPath: str 

542 """Path to the module that contains the class.""" 

543 

544 

545class ExtCommandDescriptor(Data): 

546 """ 

547 Represents a command descriptor for an extension. 

548 

549 Contains attributes to describe and handle a specific extension command. 

550 """ 

551 extName: str 

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

553 extType: str 

554 """Extension type like ``wms``.""" 

555 extCommandCategory: 'CommandCategory' 

556 """Command category.""" 

557 methodName: str 

558 """Command method name.""" 

559 methodPtr: Callable 

560 """Command method.""" 

561 request: 'Request' 

562 """Request sent to the command.""" 

563 tArg: str 

564 """Type of the command argument.""" 

565 tOwner: str 

566 """Type of the command owner.""" 

567 owner: ExtObjectDescriptor 

568 """Descriptor of the command owner.""" 

569 

570 

571class SpecReadOption(Enum): 

572 """Options for structured reading based on Specs.""" 

573 

574 acceptExtraProps = 'acceptExtraProps' 

575 """Accept extra object properties.""" 

576 allowMissing = 'allowMissing' 

577 """Allow otherwise required properties to be missing.""" 

578 caseInsensitive = 'caseInsensitive' 

579 """Case insensitive search for properties. """ 

580 convertValues = 'convertValues' 

581 """Try to convert values to specified types.""" 

582 ignoreExtraProps = 'ignoreExtraProps' 

583 """Silently ignore extra object properties.""" 

584 verboseErrors = 'verboseErrors' 

585 """Provide verbose error messages.""" 

586 

587 

588class CommandCategory(Enum): 

589 """Command category.""" 

590 

591 api = 'api' 

592 """API command.""" 

593 cli = 'cli' 

594 """CLI command.""" 

595 get = 'get' 

596 """Web GET command.""" 

597 post = 'post' 

598 """Web POST command.""" 

599 raw = 'raw' 

600 """Raw Web command without preprocessing.""" 

601 

602 

603class SpecRuntime: 

604 """Specification runtime.""" 

605 

606 version: str 

607 """Application version.""" 

608 manifest: ApplicationManifest 

609 """Application manifest.""" 

610 appBundlePaths: list[str] 

611 """List of client bundle paths.""" 

612 

613 def read(self, value, type_name: str, path: str = '', options: set[SpecReadOption] = None): 

614 """Read a raw value according to a spec. 

615 

616 Args: 

617 value: Raw value from config or request. 

618 type_name: Object type name. 

619 path: Config file path. 

620 options: Read options. 

621 

622 Returns: 

623 A parsed object. 

624 """ 

625 

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

627 """Get an object descriptor. 

628 

629 Args: 

630 type_name: Object type name. 

631 

632 Returns: 

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

634 """ 

635 

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

637 """Get a command descriptor. 

638 

639 Args: 

640 command_category: Command category. 

641 command_name: Command name. 

642 

643 Returns: 

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

645 """ 

646 

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

648 """Dynamically register an extension object.""" 

649 

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

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

652 

653 Args: 

654 classref: Class reference. 

655 ext_type: Extension type. 

656 

657 Returns: 

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

659 """ 

660 

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

662 """Parse a class reference. 

663 

664 Args: 

665 classref: Class reference. 

666 

667 Returns: 

668 A tuple ``(class object, class name, extension name)``. 

669 """ 

670################################################################################ 

671 

672 

673 

674################################################################################ 

675# /core/_tree.pyinc 

676 

677 

678class Object: 

679 """Basic GWS object.""" 

680 

681 permissions: dict[Access, Acl] 

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

683 

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

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

686 

687 Args: 

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

689 """ 

690 

691 def __init__(self): 

692 self.permissions = {} 

693 

694 

695from .core import tree_impl 

696 

697setattr(tree_impl, 'Access', Access) 

698setattr(tree_impl, 'Error', Error) 

699setattr(tree_impl, 'ConfigurationError', ConfigurationError) 

700setattr(tree_impl, 'Data', Data) 

701setattr(tree_impl, 'Props', Props) 

702setattr(tree_impl, 'Object', Object) 

703 

704Object.__repr__ = tree_impl.object_repr 

705 

706 

707class Node(Object): 

708 """GWS object tree node.""" 

709 

710 extName: str 

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

712 extType: str 

713 """Extension type like ``wms``.""" 

714 

715 config: Config 

716 """Configuration for this object.""" 

717 root: 'Root' 

718 """Root object.""" 

719 parent: 'Node' 

720 """Parent object.""" 

721 children: list['Node'] 

722 """Child objects.""" 

723 uid: str 

724 """Unique ID.""" 

725 

726 def initialize(self, config): 

727 return tree_impl.node_initialize(self, config) 

728 

729 def pre_configure(self): 

730 """Pre-configuration hook.""" 

731 

732 def configure(self): 

733 """Configuration hook.""" 

734 

735 def post_configure(self): 

736 """Post-configuration hook.""" 

737 

738 def activate(self): 

739 """Activation hook.""" 

740 

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

742 """Create a child object. 

743 

744 Args: 

745 classref: Class reference. 

746 config: Configuration. 

747 **kwargs: Additional configuration properties. 

748 

749 Returns: 

750 A newly created object or ``None`` if the object cannot be initialized. 

751 """ 

752 return tree_impl.node_create_child(self, classref, config, **kwargs) 

753 

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

755 """Create a child object if the configuration is not None. 

756 

757 Args: 

758 classref: Class reference. 

759 config: Configuration. 

760 **kwargs: Additional configuration properties. 

761 

762 Returns: 

763 A newly created object or ``None`` if the configuration is ``None`` or the object cannot be initialized. 

764 """ 

765 return tree_impl.node_create_child_if_configured(self, classref, config, **kwargs) 

766 

767 def create_children(self, classref: ClassRef, configs: list[Config], **kwargs) -> list['Node']: 

768 """Create a list of child objects from a list of configurations. 

769 

770 Args: 

771 classref: Class reference. 

772 configs: List of configurations. 

773 **kwargs: Additional configuration properties. 

774 

775 Returns: 

776 A list of newly created objects. 

777 """ 

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

779 

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

781 """Fetch a configuration property. 

782 

783 Args: 

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

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

786 

787 Returns: 

788 A property value. 

789 """ 

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

791 

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

793 """Check if a the node matches the class reference. 

794 

795 Args: 

796 classref: Class reference. 

797 

798 Returns: 

799 A boolean. 

800 """ 

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

802 

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

804 """Find all children that match a specific class. 

805 

806 Args: 

807 classref: Class reference. 

808 

809 Returns: 

810 A list of objects. 

811 """ 

812 return tree_impl.node_find_all(self, classref) 

813 

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

815 """Find the first child that matches a specific class. 

816 

817 Args: 

818 classref: Class reference. 

819 

820 Returns: 

821 An object or ``None``. 

822 """ 

823 return tree_impl.node_find_first(self, classref) 

824 

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

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

827 

828 Args: 

829 classref: Class reference. 

830 

831 Returns: 

832 An object or ``None``. 

833 """ 

834 

835 return tree_impl.node_find_closest(self, classref) 

836 

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

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

839 

840 Args: 

841 classref: Class reference. 

842 

843 Returns: 

844 A list of objects. 

845 """ 

846 return tree_impl.node_find_ancestors(self, classref) 

847 

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

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

850 

851 Args: 

852 classref: Class reference. 

853 

854 Returns: 

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

856 """ 

857 

858 return tree_impl.node_find_descendants(self, classref) 

859 

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

861 """Begin middleware processing. 

862 

863 Args: 

864 req: Requester object. 

865 

866 Returns: 

867 A Responder object or ``None``. 

868 """ 

869 

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

871 """Finish middleware processing. 

872 

873 Args: 

874 req: Requester object. 

875 res: Current responder object. 

876 """ 

877 

878 def periodic_task(self): 

879 """Periodic task hook.""" 

880 

881 

882class Root: 

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

884 

885 app: 'Application' 

886 """Application object.""" 

887 specs: 'SpecRuntime' 

888 """Specs runtime.""" 

889 configErrors: list 

890 """List of configuration errors.""" 

891 

892 nodes: list['Node'] 

893 uidMap: dict[str, 'Node'] 

894 uidCount: int 

895 configStack: list['Node'] 

896 configPaths: list[str] 

897 

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

899 tree_impl.root_init(self, specs) 

900 

901 def initialize(self, obj, config): 

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

903 

904 def post_initialize(self): 

905 """Post-initialization hook.""" 

906 return tree_impl.root_post_initialize(self) 

907 

908 def activate(self): 

909 return tree_impl.root_activate(self) 

910 

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

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

913 

914 Args: 

915 classref: Class reference. 

916 

917 Returns: 

918 A list of objects. 

919 """ 

920 return tree_impl.root_find_all(self, classref) 

921 

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

923 """Find the first object that match a specific class. 

924 

925 Args: 

926 classref: Class reference. 

927 

928 Returns: 

929 An object or ``None``. 

930 """ 

931 return tree_impl.root_find_first(self, classref) 

932 

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

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

935 

936 Args: 

937 uid: Object uid. 

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

939 

940 Returns: 

941 An object or ``None``. 

942 """ 

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

944 

945 def object_count(self) -> int: 

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

947 return tree_impl.root_object_count(self) 

948 

949 def create( 

950 self, 

951 classref: ClassRef, 

952 parent: Optional['Node'] = None, 

953 config: Config = None, 

954 **kwargs, 

955 ) -> Optional['Node']: 

956 """Create an object. 

957 

958 Args: 

959 classref: Class reference. 

960 parent: Parent object. 

961 config: Configuration. 

962 **kwargs: Additional configuration properties. 

963 

964 Returns: 

965 A newly created object or ``None`` if the object cannot be initialized. 

966 """ 

967 return tree_impl.root_create(self, classref, parent, config, **kwargs) 

968 

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

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

971 

972 Args: 

973 classref: Class reference. 

974 config: Configuration. 

975 **kwargs: Additional configuration properties. 

976 

977 Returns: 

978 A newly created object or ``None`` if the object cannot be initialized. 

979 """ 

980 return tree_impl.root_create_shared(self, classref, config, **kwargs) 

981 

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

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

984 

985 Args: 

986 classref: Class reference. 

987 config: Configuration. 

988 **kwargs: Additional configuration properties. 

989 

990 Returns: 

991 A newly created object or ``None`` if the object cannot be initialized. 

992 """ 

993 return tree_impl.root_create_temporary(self, classref, config, **kwargs) 

994 

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

996 """Create the Application object. 

997 

998 Args: 

999 config: Configuration. 

1000 **kwargs: Additional configuration properties. 

1001 

1002 Returns: 

1003 The Application object. 

1004 """ 

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

1006 

1007 

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

1009 return Root(specs) 

1010 

1011 

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

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

1014################################################################################ 

1015 

1016 

1017 

1018################################################################################ 

1019# /lib/mime/types.pyinc 

1020 

1021 

1022MimeType: TypeAlias = str 

1023"""A mime type or an alias.""" 

1024################################################################################ 

1025 

1026 

1027################################################################################ 

1028# /lib/uom/types.pyinc 

1029 

1030 

1031class Uom(Enum): 

1032 """Unit of measure.""" 

1033 

1034 mi = 'mi' 

1035 """statute mile (EPSG 9093)""" 

1036 us_ch = 'us-ch' 

1037 """us survey chain (EPSG 9033)""" 

1038 us_ft = 'us-ft' 

1039 """us survey foot (EPSG 9003)""" 

1040 us_in = 'us-in' 

1041 """us survey inch us_in""" 

1042 us_mi = 'us-mi' 

1043 """us survey mile (EPSG 9035)""" 

1044 us_yd = 'us-yd' 

1045 """us survey yard us_yd""" 

1046 cm = 'cm' 

1047 """centimetre (EPSG 1033)""" 

1048 ch = 'ch' 

1049 """chain (EPSG 9097)""" 

1050 dm = 'dm' 

1051 """decimeter dm""" 

1052 deg = 'deg' 

1053 """degree (EPSG 9102)""" 

1054 fath = 'fath' 

1055 """fathom (EPSG 9014)""" 

1056 ft = 'ft' 

1057 """foot (EPSG 9002)""" 

1058 grad = 'grad' 

1059 """grad (EPSG 9105)""" 

1060 inch = 'in' 

1061 """inch in""" 

1062 km = 'km' 

1063 """kilometre (EPSG 9036)""" 

1064 link = 'link' 

1065 """link (EPSG 9098)""" 

1066 m = 'm' 

1067 """metre (EPSG 9001)""" 

1068 mm = 'mm' 

1069 """millimetre (EPSG 1025)""" 

1070 kmi = 'kmi' 

1071 """nautical mile (EPSG 9030)""" 

1072 rad = 'rad' 

1073 """radian (EPSG 9101)""" 

1074 yd = 'yd' 

1075 """yard (EPSG 9096)""" 

1076 px = 'px' 

1077 """pixel""" 

1078 pt = 'pt' 

1079 """point""" 

1080 

1081 

1082UomValue: TypeAlias = tuple[float, Uom] 

1083"""A value with a unit.""" 

1084 

1085UomValueStr: TypeAlias = str 

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

1087 

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

1089"""A Point with a unit.""" 

1090 

1091UomPointStr: TypeAlias = list[str] 

1092"""A Point with a unit like ``["1mm", "2mm"]``.""" 

1093 

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

1095"""A Size with a unit.""" 

1096 

1097UomSizeStr: TypeAlias = list[str] 

1098"""A Size with a unit like ``["1mm", "2mm"]``.""" 

1099 

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

1101"""Extent with a unit.""" 

1102 

1103UomExtentStr: TypeAlias = list[str] 

1104"""Extent with a unit like ``["1mm", "2mm", "3mm", "4mm"]``.""" 

1105################################################################################ 

1106 

1107 

1108################################################################################ 

1109# /lib/image/types.pyinc 

1110 

1111 

1112class ImageFormat(Data): 

1113 """Image format""" 

1114 

1115 mimeTypes: list[str] 

1116 """Mime types for this format.""" 

1117 options: dict 

1118 """Image options.""" 

1119 

1120 

1121class Image: 

1122 """Image object.""" 

1123 

1124 def size(self) -> Size: 

1125 """Get the image size. 

1126 

1127 Returns: 

1128 A tuple ``(width, height)``. 

1129 """ 

1130 

1131 def mode(self) -> str: 

1132 """Get the image mode. 

1133 

1134 Returns: 

1135 PIL image mode. 

1136 """ 

1137 

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

1139 """Creates a 1 pixel wide box on the image's edge. 

1140 

1141 Args: 

1142 color: Color of the box's lines. 

1143 

1144 Returns: 

1145 The image with a box around the edges. 

1146 """ 

1147 

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

1149 """Adds text to an image object. 

1150 

1151 Args: 

1152 text: Text to be displayed. 

1153 

1154 x: x-coordinate. 

1155 

1156 y: y-coordinate. 

1157 

1158 color: Color of the text. 

1159 

1160 Returns: 

1161 The image object with the text displayed. 

1162 """ 

1163 

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

1165 """Places other image on top of the current image. 

1166 

1167 Args: 

1168 other: Image to place on top. 

1169 opacity: other image's opacity. 

1170 

1171 Returns: 

1172 The image object with the other image on top as an alpha composition. 

1173 """ 

1174 

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

1176 """Crops the image with respect to the given box. 

1177 

1178 Args: 

1179 box: `(width, height)` 

1180 

1181 Returns: 

1182 The cropped image object. 

1183 """ 

1184 

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

1186 """Pastes an image to a specific location. 

1187 

1188 Args: 

1189 other: Image that will be placed. 

1190 

1191 where: `(x-coord, y-coord)` indicating where the upper left corer should be pasted. 

1192 

1193 Returns: 

1194 The image object with the other image placed inside. 

1195 """ 

1196 

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

1198 """Resizes the image and scales it to fit the new size. 

1199 

1200 Args: 

1201 size: `(width, height)` 

1202 

1203 Returns: 

1204 The resized image object. 

1205 """ 

1206 

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

1208 """Rotates the image. 

1209 

1210 Args: 

1211 angle: Angle to rotate the image. 

1212 

1213 Returns: 

1214 The rotated image object. 

1215 """ 

1216 

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

1218 """Converts the image object to bytes. 

1219 

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

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

1222 

1223 An additional option ``mode`` is the image mode 

1224 (see https://pillow.readthedocs.io/en/stable/handbook/concepts.html#concept-modes). 

1225 If provided, the image is converted to that mode before saving. 

1226 

1227 An additional option ``background`` sets the color to replace the alpha channel with 

1228 when converting from RGBA to RGB (default is white). 

1229 

1230 Args: 

1231 mime: The mime type. 

1232 options: A dict of options. 

1233 

1234 Returns: 

1235 The image as bytes. 

1236 """ 

1237 

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

1239 """Return the image content as a base64 encoded string.""" 

1240 

1241 def to_data_url(self, mime: Optional[str] = None, options: Optional[dict] = None) -> str: 

1242 """Return the image content as a base64-based data url.""" 

1243 

1244 def to_path(self, path: str, mime: Optional[str] = None, options: Optional[dict] = None) -> str: 

1245 """Saves the image object at a given path. 

1246 

1247 Args: 

1248 path: Image's path location. 

1249 mime: The mime type. 

1250 options: A dict of options. 

1251 

1252 Returns: 

1253 The path to the image. 

1254 """ 

1255 

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

1257 """Converts the image to an array. 

1258 

1259 Returns: 

1260 The image as an array. For each row each entry contains the pixel information. 

1261 """ 

1262 

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

1264 """Compare this image to another one. 

1265 

1266 @TODO describe the alogrithm 

1267 

1268 Returns: 

1269 The similarity factor as a float (the more, the different). 

1270 '0' means images are equal. 

1271 """ 

1272################################################################################ 

1273 

1274 

1275################################################################################ 

1276# /lib/intl/types.pyinc 

1277 

1278 

1279LocaleUid: TypeAlias = str 

1280"""Locale uid like `de_DE`.""" 

1281 

1282 

1283class Locale(Data): 

1284 """Locale data.""" 

1285 

1286 uid: str 

1287 dateFormatLong: str 

1288 dateFormatMedium: str 

1289 dateFormatShort: str 

1290 dateUnits: str 

1291 """date unit names, e.g. 'YMD' for 'en', 'JMT' for 'de'""" 

1292 dayNamesLong: list[str] 

1293 dayNamesShort: list[str] 

1294 dayNamesNarrow: list[str] 

1295 firstWeekDay: int 

1296 

1297 language: str 

1298 """Language code: ``de``""" 

1299 language3: str 

1300 """ISO 3166-1 alpha-3 language code: ``deu``.""" 

1301 languageBib: str 

1302 """Bibliographic language code..""" 

1303 languageName: str 

1304 """Native language name: ``Deutsch``.""" 

1305 languageNameEn: str 

1306 """English language name: ``German``.""" 

1307 

1308 territory: str 

1309 territoryName: str 

1310 monthNamesLong: list[str] 

1311 monthNamesShort: list[str] 

1312 monthNamesNarrow: list[str] 

1313 numberDecimal: str 

1314 numberGroup: str 

1315 

1316 

1317class DateTimeFormat(Enum): 

1318 """Enumeration indicating the length of the date/time format.""" 

1319 short = 'short' 

1320 """Local short format.""" 

1321 medium = 'medium' 

1322 """Local medium format.""" 

1323 long = 'long' 

1324 """Local long format.""" 

1325 iso = 'iso' 

1326 """ISO 8601 format.""" 

1327 

1328 

1329class NumberFormat(Enum): 

1330 """Enumeration indicating the number format.""" 

1331 decimal = 'decimal' 

1332 """Locale decimal format.""" 

1333 grouped = 'grouped' 

1334 """Locale grouped format.""" 

1335 currency = 'currency' 

1336 """Locale currency format""" 

1337 percent = 'percent' 

1338 """Locale percent format.""" 

1339 

1340 

1341class DateFormatter: 

1342 """Locale-aware date formatter.""" 

1343 

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

1345 """Formats the date. 

1346 

1347 Args: 

1348 fmt: Format type or a `strftime` format string 

1349 date: Date, if none is given the current date will be used as default. 

1350 

1351 Returns: 

1352 A formatted date string. 

1353 """ 

1354 

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

1356 """Returns the date in the short format ``11.12.13``.""" 

1357 

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

1359 """Returns the date in the medium format ``11.12.2013``.""" 

1360 

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

1362 """Returns the date in the medium format ``11. Dezember 2013``.""" 

1363 

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

1365 """Returns the date in the ISO 8601 format ``2013-12-11``.""" 

1366 

1367 

1368class TimeFormatter: 

1369 """Locale-aware time formatter.""" 

1370 

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

1372 """Formats the time. 

1373 

1374 Args: 

1375 fmt: Format type or a `strftime` format string 

1376 time: Time, if none is given the current time will be used as default. 

1377 

1378 Returns: 

1379 A formatted time string. 

1380 """ 

1381 

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

1383 """Returns the time in the short format ``11:22``.""" 

1384 

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

1386 """Returns the time in the medium format ``11:22:33``.""" 

1387 

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

1389 """Returns the time in the medium format ``11:22:33``.""" 

1390 

1391 def iso(self, time=None) -> str: 

1392 """Returns the time and date in the ISO 8601 format.""" 

1393 

1394 

1395class NumberFormatter: 

1396 """Locale-aware number formatter.""" 

1397 

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

1399 """Formats the number with respect to the locale. 

1400 

1401 Args: 

1402 fmt: Format type or a python `format` string 

1403 n: Number. 

1404 kwargs: Passes the currency parameter forward. 

1405 

1406 Returns: 

1407 A formatted number. 

1408 """ 

1409 

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

1411 """Returns formatted decimal value.""" 

1412 

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

1414 """Returns formatted decimal value with group separators.""" 

1415 

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

1417 """Returns formatted currency value.""" 

1418 

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

1420 """Returns formatted percent value.""" 

1421################################################################################ 

1422 

1423 

1424################################################################################ 

1425# /lib/style/types.pyinc 

1426 

1427 

1428class StyleValues(Data): 

1429 """CSS Style values.""" 

1430 

1431 fill: Color 

1432 

1433 stroke: Color 

1434 stroke_dasharray: list[int] 

1435 stroke_dashoffset: int 

1436 stroke_linecap: Literal['butt', 'round', 'square'] 

1437 stroke_linejoin: Literal['bevel', 'round', 'miter'] 

1438 stroke_miterlimit: int 

1439 stroke_width: int 

1440 

1441 marker: Literal['circle', 'square', 'arrow', 'cross'] 

1442 marker_fill: Color 

1443 marker_size: int 

1444 marker_stroke: Color 

1445 marker_stroke_dasharray: list[int] 

1446 marker_stroke_dashoffset: int 

1447 marker_stroke_linecap: Literal['butt', 'round', 'square'] 

1448 marker_stroke_linejoin: Literal['bevel', 'round', 'miter'] 

1449 marker_stroke_miterlimit: int 

1450 marker_stroke_width: int 

1451 

1452 with_geometry: Literal['all', 'none'] 

1453 with_label: Literal['all', 'none'] 

1454 

1455 label_align: Literal['left', 'right', 'center'] 

1456 label_background: Color 

1457 label_fill: Color 

1458 label_font_family: str 

1459 label_font_size: int 

1460 label_font_style: Literal['normal', 'italic'] 

1461 label_font_weight: Literal['normal', 'bold'] 

1462 label_line_height: int 

1463 label_max_scale: int 

1464 label_min_scale: int 

1465 label_offset_x: int 

1466 label_offset_y: int 

1467 label_padding: list[int] 

1468 label_placement: Literal['start', 'end', 'middle'] 

1469 label_stroke: Color 

1470 label_stroke_dasharray: list[int] 

1471 label_stroke_dashoffset: int 

1472 label_stroke_linecap: Literal['butt', 'round', 'square'] 

1473 label_stroke_linejoin: Literal['bevel', 'round', 'miter'] 

1474 label_stroke_miterlimit: int 

1475 label_stroke_width: int 

1476 

1477 point_size: int 

1478 icon: str 

1479 

1480 offset_x: int 

1481 offset_y: int 

1482 

1483 

1484class StyleProps(Props): 

1485 """CSS Style properties.""" 

1486 

1487 cssSelector: Optional[str] 

1488 text: Optional[str] 

1489 values: Optional[dict] 

1490 

1491 

1492class Style: 

1493 """CSS Style object.""" 

1494 

1495 cssSelector: str 

1496 text: str 

1497 values: StyleValues 

1498################################################################################ 

1499 

1500 

1501################################################################################ 

1502# /lib/xmlx/types.pyinc 

1503 

1504 

1505class XmlNamespace(Data): 

1506 """XML namespace.""" 

1507 

1508 uid: str 

1509 """Unique ID.""" 

1510 xmlns: str 

1511 """Default prefix for this Namespace.""" 

1512 uri: Url 

1513 """Namespace uri.""" 

1514 schemaLocation: Url 

1515 """Namespace schema location.""" 

1516 version: str 

1517 """Namespace version.""" 

1518 isDefault: bool 

1519 """Is this the default namespace for the given xmlns prefix.""" 

1520 extendsGml: bool 

1521 """Namespace schema extends the GML3 schema.""" 

1522 

1523 

1524class XmlOptions(Data): 

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

1526 

1527 namespaces: Optional[dict[str, XmlNamespace]] = None 

1528 """Mapping of prefixes to namespaces.""" 

1529 

1530 customXmlns: Optional[dict[str, str]] = None 

1531 """A mapping of namespace ids to custom prefixes.""" 

1532 

1533 defaultNamespace: Optional['XmlNamespace'] = None 

1534 """Default namespace to use for serialization.""" 

1535 

1536 doctype: Optional[str] = None 

1537 """Document type definition (DTD) to use for serialization.""" 

1538 

1539 compactWhitespace: bool = False 

1540 """Remove all whitespace outside of tags and elements.""" 

1541 

1542 removeNamespaces: bool = False 

1543 """Remove all namespace references.""" 

1544 

1545 foldTags: bool = False 

1546 """If true, folds nested tag names into ``parent/child`` names.""" 

1547 

1548 withNamespaceDeclarations: bool = False 

1549 """Include the namespace declarations.""" 

1550 

1551 withSchemaLocations: bool = False 

1552 """Include schema locations.""" 

1553 

1554 withXmlDeclaration: bool = False 

1555 """Include the xml declaration.""" 

1556 

1557 

1558class XmlElement(Iterable): 

1559 """XML Element. 

1560 

1561 Extends ``ElementTree.Element`` (https://docs.python.org/3/library/xml.etree.elementtree.html#element-objects). 

1562 """ 

1563 

1564 tag: str 

1565 """Tag name, with an optional namespace in the Clark notation.""" 

1566 

1567 text: str 

1568 """Text before first subelement.""" 

1569 

1570 tail: str 

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

1572 

1573 attrib: dict 

1574 """Dictionary of element attributes.""" 

1575 

1576 name: str 

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

1578 

1579 lcName: str 

1580 """Element name (tag without a namespace) in lower case.""" 

1581 

1582 caseInsensitive: bool 

1583 """Element is case-insensitive.""" 

1584 

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

1586 

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

1588 

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

1590 

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

1592 """Adds the element subelement to the end of this element’s internal list of subelements.""" 

1593 

1594 def clear(self): 

1595 """Resets an element.""" 

1596 

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

1598 """Appends subelements from a sequence object with zero or more elements.""" 

1599 

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

1601 """Finds first matching element by tag name or path.""" 

1602 

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

1604 """Finds first matching element and raises an error if not found.""" 

1605 

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

1607 """Finds all matching subelements by name or path.""" 

1608 

1609 def findtext(self, path: str, default: Optional[str] = None) -> str: 

1610 """Finds text for first matching element by name or path.""" 

1611 

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

1613 """Gets the element attribute named key.""" 

1614 

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

1616 """Inserts subelement at the given position in this element.""" 

1617 

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

1619 """Returns the element attributes as a sequence of (name, value) pairs.""" 

1620 

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

1622 """Creates a tree iterator.""" 

1623 

1624 def iterfind(self, path: Optional[str] = None) -> Iterable['XmlElement']: 

1625 """Returns an iterable of all matching subelements by name or path.""" 

1626 

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

1628 """Creates a text iterator and returns all inner text.""" 

1629 

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

1631 """Returns the elements attribute names as a list.""" 

1632 

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

1634 """Removes the other element from the element.""" 

1635 

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

1637 """Set the attribute key on the element to value.""" 

1638 

1639 # extensions 

1640 

1641 def attr(self, key: str, default='') -> str: 

1642 """Alias for 'get'.""" 

1643 

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

1645 """Check if an attribute exists.""" 

1646 

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

1648 """Creates a new element and adds it as a child. 

1649 

1650 Args: 

1651 tag: XML tag. 

1652 attrib: XML attributes ``{key, value}``. 

1653 """ 

1654 

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

1656 """Returns the children of the current element.""" 

1657 

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

1659 """Given a list of paths, returns the first matching element.""" 

1660 

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

1662 """Given a list of paths, returns the text of the first matching element that has text.""" 

1663 

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

1665 """Collects texts from child elements. 

1666 

1667 Args: 

1668 paths: List of paths to search for. 

1669 deep: If ``False`` it only looks into direct children, otherwise search the entire subtree. 

1670 

1671 Returns: 

1672 A list containing all the text from the child-elements. 

1673 """ 

1674 

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

1676 """Collects texts from child elements. 

1677 

1678 Args: 

1679 paths: List of paths to search for. 

1680 deep: If ``False`` it only looks into direct children, otherwise search the entire subtree. 

1681 

1682 Returns: 

1683 A dict tag name -> text. 

1684 """ 

1685 

1686 def remove_namespaces(self) -> 'XmlElement': 

1687 """Removes all namespace references from the element and its children.""" 

1688 

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

1690 """Converts the Element object to a string. 

1691 

1692 Args: 

1693 opts: XML options for serialization. 

1694 

1695 Returns: 

1696 An XML string. 

1697 """ 

1698 

1699 def to_dict(self) -> dict: 

1700 """Creates a dictionary from an XmlElement object.""" 

1701 

1702 def to_list(self, opts: Optional[XmlOptions] = None) -> list: 

1703 """Parse an XML element into a list of arguments (reverse of `gws.lib.xmlx.tag`). 

1704 

1705 Args: 

1706 opts: XML options for serialization. 

1707 """ 

1708################################################################################ 

1709 

1710 

1711 

1712################################################################################ 

1713# /lib/crs/types.pyinc 

1714 

1715 

1716CrsName: TypeAlias = int | str 

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

1718 

1719 

1720class CrsFormat(Enum): 

1721 """CRS name format.""" 

1722 

1723 none = '' 

1724 """No format.""" 

1725 crs = 'crs' 

1726 """Like ``crs84``.""" 

1727 srid = 'srid' 

1728 """Like ``3857``.""" 

1729 epsg = 'epsg' 

1730 """Like ``EPSG:3857``.""" 

1731 url = 'url' 

1732 """Like ``http://www.opengis.net/gml/srs/epsg.xml#3857``.""" 

1733 uri = 'uri' 

1734 """Like ``http://www.opengis.net/def/crs/epsg/0/3857``.""" 

1735 urnx = 'urnx' 

1736 """Like ``urn:x-ogc:def:crs:EPSG:3857``.""" 

1737 urn = 'urn' 

1738 """Like ``urn:ogc:def:crs:EPSG::3857``.""" 

1739 

1740 

1741class Axis(Enum): 

1742 """Axis orientation.""" 

1743 

1744 xy = 'xy' 

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

1746 yx = 'yx' 

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

1748 

1749 

1750class Bounds(Data): 

1751 """Geo-referenced extent.""" 

1752 

1753 crs: 'Crs' 

1754 extent: Extent 

1755 

1756 

1757class Crs: 

1758 """Coordinate reference system.""" 

1759 

1760 srid: int 

1761 """CRS SRID.""" 

1762 axis: Axis 

1763 """Axis orientation.""" 

1764 uom: Uom 

1765 """CRS unit.""" 

1766 isGeographic: bool 

1767 """This CRS is geographic.""" 

1768 isProjected: bool 

1769 """This CRS is projected.""" 

1770 isYX: bool 

1771 """This CRS has a lat/lon axis.""" 

1772 proj4text: str 

1773 """Proj4 definition.""" 

1774 wkt: str 

1775 """WKT definition.""" 

1776 

1777 epsg: str 

1778 """Name in the "epsg" format.""" 

1779 urn: str 

1780 """Name in the "urn" format.""" 

1781 urnx: str 

1782 """Name in the "urnx" format.""" 

1783 url: str 

1784 """Name in the "url" format.""" 

1785 uri: str 

1786 """Name in the "uri" format.""" 

1787 

1788 name: str 

1789 """CRS name.""" 

1790 base: int 

1791 """Base CRS code.""" 

1792 datum: str 

1793 """Datum.""" 

1794 

1795 wgsExtent: Extent 

1796 """CRS Extent in the WGS projection.""" 

1797 extent: Extent 

1798 """CRS own Extent.""" 

1799 bounds: Bounds 

1800 """CRS own Bounds.""" 

1801 

1802 coordinatePrecision: int 

1803 """Preferred precision for coordinates in this CRS.""" 

1804 

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

1806 """Get the axis depending on the string format. 

1807 

1808 We adhere to the GeoServer convention here: 

1809 https://docs.geoserver.org/latest/en/user/services/wfs/axis_order.html 

1810 """ 

1811 

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

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

1814 

1815 Args: 

1816 extent: Extent. 

1817 crs_to: Target CRS. 

1818 

1819 Returns: 

1820 A transformed Extent. 

1821 """ 

1822 

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

1824 """Calculate the width and height of an extent in meters; 

1825 

1826 Args: 

1827 extent: Extent. 

1828 """ 

1829 

1830 def point_offset_in_meters(self, xy: Point, dist: float, az: int) -> Point: 

1831 """Calculate a point with an offset in meters. 

1832 Args: 

1833 xy: Point. 

1834 dist: Distance in meters. 

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

1836 """ 

1837 

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

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

1840 

1841 Args: 

1842 crs_to: Target CRS. 

1843 

1844 Returns: 

1845 A function. 

1846 """ 

1847 

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

1849 """Return a string representation of the CRS. 

1850 

1851 Args: 

1852 fmt: Format to use. 

1853 

1854 Returns: 

1855 A string. 

1856 """ 

1857 

1858 def to_geojson(self) -> dict: 

1859 """Return a geojson representation of the CRS (as per GJ2008). 

1860 

1861 Returns: 

1862 A GeoJson dict. 

1863 

1864 References: 

1865 https://geojson.org/geojson-spec#named-crs 

1866 """ 

1867################################################################################ 

1868 

1869 

1870################################################################################ 

1871# /gis/render/types.pyinc 

1872 

1873 

1874class MapView(Data): 

1875 """Map view.""" 

1876 

1877 bounds: Bounds 

1878 center: Point 

1879 rotation: int 

1880 scale: int 

1881 mmSize: Size 

1882 pxSize: Size 

1883 dpi: int 

1884 

1885 

1886class MapRenderInputPlaneType(Enum): 

1887 """Map render input plane type.""" 

1888 

1889 features = 'features' 

1890 image = 'image' 

1891 imageLayer = 'imageLayer' 

1892 svgLayer = 'svgLayer' 

1893 svgSoup = 'svgSoup' 

1894 

1895 

1896class MapRenderInputPlane(Data): 

1897 """Map render input plane.""" 

1898 

1899 type: MapRenderInputPlaneType 

1900 features: list['Feature'] 

1901 image: 'Image' 

1902 layer: 'Layer' 

1903 opacity: float 

1904 soupPoints: list[Point] 

1905 soupTags: list[Any] 

1906 styles: list['Style'] 

1907 compositeLayerUids: list[str] 

1908 

1909 

1910class MapRenderInput(Data): 

1911 """Map render input.""" 

1912 

1913 backgroundColor: int 

1914 bbox: Extent 

1915 center: Point 

1916 crs: 'Crs' 

1917 dpi: int 

1918 mapSize: UomSize 

1919 notify: Callable 

1920 planes: list['MapRenderInputPlane'] 

1921 project: 'Project' 

1922 rotation: int 

1923 scale: int 

1924 user: 'User' 

1925 visibleLayers: Optional[list['Layer']] 

1926 

1927 

1928class MapRenderOutputPlaneType(Enum): 

1929 """Map render output plane type.""" 

1930 

1931 image = 'image' 

1932 path = 'path' 

1933 svg = 'svg' 

1934 

1935 

1936class MapRenderOutputPlane(Data): 

1937 """Map render output plane.""" 

1938 

1939 type: MapRenderOutputPlaneType 

1940 path: str 

1941 elements: list[XmlElement] 

1942 image: 'Image' 

1943 

1944 

1945class MapRenderOutput(Data): 

1946 """Map render output.""" 

1947 

1948 planes: list['MapRenderOutputPlane'] 

1949 view: MapView 

1950 

1951 

1952class LayerRenderInputType(Enum): 

1953 """Layer render input type.""" 

1954 

1955 box = 'box' 

1956 xyz = 'xyz' 

1957 svg = 'svg' 

1958 

1959 

1960class LayerRenderInput(Data): 

1961 """Layer render input.""" 

1962 

1963 extraParams: dict 

1964 project: 'Project' 

1965 style: 'Style' 

1966 type: LayerRenderInputType 

1967 user: 'User' 

1968 view: MapView 

1969 x: int 

1970 y: int 

1971 z: int 

1972 

1973 

1974class LayerRenderOutput(Data): 

1975 """Layer render output.""" 

1976 

1977 content: bytes 

1978 tags: list[XmlElement] 

1979################################################################################ 

1980 

1981 

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

1983# /gis/source/types.pyinc 

1984 

1985 

1986class TileMatrix(Data): 

1987 """WMTS TileMatrix object.""" 

1988 

1989 uid: str 

1990 scale: float 

1991 x: float 

1992 y: float 

1993 width: float 

1994 height: float 

1995 tileWidth: float 

1996 tileHeight: float 

1997 extent: Extent 

1998 

1999 

2000class TileMatrixSet(Data): 

2001 """WMTS TileMatrixSet object.""" 

2002 

2003 uid: str 

2004 crs: 'Crs' 

2005 matrices: list[TileMatrix] 

2006 

2007 

2008class SourceStyle(Data): 

2009 """Generic OGC Style.""" 

2010 

2011 isDefault: bool 

2012 legendUrl: Url 

2013 metadata: 'Metadata' 

2014 name: str 

2015 

2016 

2017class SourceLayer(Data): 

2018 """Generic OGC Layer.""" 

2019 

2020 aLevel: int 

2021 aPath: str 

2022 aUid: str 

2023 

2024 dataSource: dict 

2025 metadata: 'Metadata' 

2026 

2027 supportedCrs: list['Crs'] 

2028 wgsExtent: Extent 

2029 

2030 isExpanded: bool 

2031 isGroup: bool 

2032 isImage: bool 

2033 isQueryable: bool 

2034 isVisible: bool 

2035 

2036 layers: list['SourceLayer'] 

2037 

2038 name: str 

2039 title: str 

2040 

2041 legendUrl: Url 

2042 opacity: float 

2043 scaleRange: list[float] 

2044 

2045 styles: list[SourceStyle] 

2046 defaultStyle: Optional[SourceStyle] 

2047 

2048 tileMatrixIds: list[str] 

2049 tileMatrixSets: list[TileMatrixSet] 

2050 imageFormat: str 

2051 resourceUrls: dict 

2052 

2053 sourceId: str 

2054 properties: dict 

2055################################################################################ 

2056 

2057 

2058 

2059################################################################################ 

2060# /config/types.pyinc 

2061 

2062 

2063class ConfigContext(Data): 

2064 """Configuration context for parsing and validation.""" 

2065 

2066 specs: SpecRuntime 

2067 readOptions: set[SpecReadOption] 

2068 errors: list 

2069 paths: set[str] 

2070################################################################################ 

2071 

2072 

2073################################################################################ 

2074# /server/types.pyinc 

2075 

2076 

2077class ServerManager(Node): 

2078 """Server configuration manager.""" 

2079 

2080 templates: list['Template'] 

2081 

2082 def create_server_configs(self, target_dir: str, script_path: str, pid_paths: dict): 

2083 """Create server configuration files.""" 

2084 

2085 

2086class ServerMonitor(Node): 

2087 """File Monitor facility.""" 

2088 

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

2090 """Add a directory to watch. 

2091 

2092 Args: 

2093 path: Directory path. 

2094 pattern: Regex pattern for files to watch. 

2095 recursive: Watch subdirectories. 

2096 """ 

2097 

2098 def watch_file(self, path: str): 

2099 """Add a file to watch. 

2100 

2101 Args: 

2102 path: File path. 

2103 """ 

2104 

2105 def register_periodic_task(self, obj: Node): 

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

2107 

2108 Args: 

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

2110 """ 

2111 

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

2113 """Schedule a system reload. 

2114 

2115 Args: 

2116 with_reconfigure: Reconfigure the server before reloading. 

2117 """ 

2118 

2119 def start(self): 

2120 """Start the monitor.""" 

2121################################################################################ 

2122 

2123 

2124 

2125################################################################################ 

2126# /base/metadata/types.pyinc 

2127 

2128 

2129class MetadataLink(Data): 

2130 about: str 

2131 description: str 

2132 format: str 

2133 formatVersion: str 

2134 function: str 

2135 mimeType: str 

2136 scheme: str 

2137 title: str 

2138 type: str 

2139 url: str 

2140 

2141 

2142class Metadata(Data): 

2143 name: str 

2144 title: str 

2145 

2146 abstract: str 

2147 accessConstraints: str 

2148 accessConstraintsType: str 

2149 attribution: str 

2150 attributionUrl: str 

2151 dateCreated: Optional['datetime.datetime'] 

2152 dateUpdated: Optional['datetime.datetime'] 

2153 fees: str 

2154 image: str 

2155 keywords: list[str] 

2156 license: str 

2157 licenseUrl: str 

2158 

2159 contactAddress: str 

2160 contactAddressType: str 

2161 contactArea: str 

2162 contactCity: str 

2163 contactCountry: str 

2164 contactEmail: str 

2165 contactFax: str 

2166 contactOrganization: str 

2167 contactPerson: str 

2168 contactPhone: str 

2169 contactPosition: str 

2170 contactProviderName: str 

2171 contactProviderSite: str 

2172 contactRole: str 

2173 contactUrl: str 

2174 contactZip: str 

2175 

2176 authorityIdentifier: str 

2177 authorityName: str 

2178 authorityUrl: str 

2179 

2180 metaLinks: list[MetadataLink] 

2181 serviceMetadataURL: str 

2182 

2183 catalogCitationUid: str 

2184 catalogUid: str 

2185 

2186 language: str 

2187 language3: str 

2188 languageBib: str 

2189 languageName: str 

2190 

2191 parentIdentifier: str 

2192 wgsExtent: Optional[Extent] 

2193 crs: Optional['Crs'] 

2194 temporalBegin: Optional['datetime.datetime'] 

2195 temporalEnd: Optional['datetime.datetime'] 

2196 

2197 inspireMandatoryKeyword: str 

2198 inspireDegreeOfConformity: str 

2199 inspireResourceType: str 

2200 inspireSpatialDataServiceType: str 

2201 inspireSpatialScope: str 

2202 inspireSpatialScopeName: str 

2203 inspireTheme: str 

2204 

2205 inspireThemeNameLocal: str 

2206 inspireThemeNameEn: str 

2207 

2208 isoMaintenanceFrequencyCode: str 

2209 isoQualityConformanceExplanation: str 

2210 isoQualityConformanceQualityPass: bool 

2211 isoQualityConformanceSpecificationDate: str 

2212 isoQualityConformanceSpecificationTitle: str 

2213 isoQualityLineageSource: str 

2214 isoQualityLineageSourceScale: int 

2215 isoQualityLineageStatement: str 

2216 isoRestrictionCode: str 

2217 isoServiceFunction: str 

2218 isoScope: str 

2219 isoScopeName: str 

2220 isoSpatialRepresentationType: str 

2221 isoTopicCategories: list[str] 

2222 isoSpatialResolution: int 

2223################################################################################ 

2224 

2225 

2226################################################################################ 

2227# /base/feature/types.pyinc 

2228 

2229 

2230FeatureUid: TypeAlias = str 

2231"""Unique Feature id.""" 

2232 

2233class FeatureRecord(Data): 

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

2235 

2236 attributes: dict 

2237 meta: dict 

2238 uid: Optional[str] 

2239 shape: Optional['Shape'] 

2240 ewkt: str 

2241 

2242 

2243class FeatureProps(Props): 

2244 """Feature Proprieties.""" 

2245 

2246 attributes: dict 

2247 category: Optional[str] 

2248 cssSelector: str 

2249 errors: Optional[list['ModelValidationError']] 

2250 createWithFeatures: Optional[list['FeatureProps']] 

2251 isNew: bool 

2252 modelUid: str 

2253 uid: str 

2254 views: dict 

2255 

2256 

2257class Feature: 

2258 """Feature object.""" 

2259 

2260 attributes: dict 

2261 category: str 

2262 cssSelector: str 

2263 errors: list['ModelValidationError'] 

2264 isNew: bool 

2265 model: 'Model' 

2266 props: 'FeatureProps' 

2267 record: 'FeatureRecord' 

2268 views: dict 

2269 createWithFeatures: list['Feature'] 

2270 insertedPrimaryKey: Optional[int | str] 

2271 

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

2273 """Get attribute value.""" 

2274 

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

2276 """Check if attribute exists.""" 

2277 

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

2279 """Set attribute value.""" 

2280 

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

2282 """Get raw attribute value from the record.""" 

2283 

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

2285 """Render feature views using provided templates, populate views`.""" 

2286 

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

2288 """Get feature shape.""" 

2289 

2290 def to_svg(self, view: 'MapView', label: Optional[str] = None, style: Optional['Style'] = None) -> list[XmlElement]: 

2291 """Render feature shape to SVG fragments for the given map view.""" 

2292 

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

2294 """Convert feature to GeoJSON dict.""" 

2295 

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

2297 """Transform feature shape to the given CRS.""" 

2298 

2299 def uid(self) -> FeatureUid: 

2300 """Get feature unique id.""" 

2301################################################################################ 

2302 

2303 

2304################################################################################ 

2305# /base/shape/types.pyinc 

2306 

2307 

2308class ShapeProps(Props): 

2309 """Shape properties.""" 

2310 

2311 crs: str 

2312 geometry: dict 

2313 

2314 

2315class Shape(Object): 

2316 """Geo-referenced geometry.""" 

2317 

2318 type: GeometryType 

2319 """Geometry type.""" 

2320 

2321 crs: 'Crs' 

2322 """CRS of this shape.""" 

2323 

2324 x: Optional[float] 

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

2326 

2327 y: Optional[float] 

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

2329 

2330 # common props 

2331 

2332 def area(self) -> float: 

2333 """Computes the area of the geometry.""" 

2334 

2335 def bounds(self) -> Bounds: 

2336 """Returns a Bounds object that bounds this shape.""" 

2337 

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

2339 """Returns a centroid as a Point shape.""" 

2340 

2341 # formats 

2342 

2343 def to_wkb(self) -> bytes: 

2344 """Returns a WKB representation of this shape as a binary string.""" 

2345 

2346 def to_wkb_hex(self) -> str: 

2347 """Returns a WKB representation of this shape as a hex string.""" 

2348 

2349 def to_ewkb(self) -> bytes: 

2350 """Returns an EWKB representation of this shape as a binary string.""" 

2351 

2352 def to_ewkb_hex(self) -> str: 

2353 """Returns an EWKB representation of this shape as a hex string.""" 

2354 

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

2356 """Returns a WKT representation of this shape.""" 

2357 

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

2359 """Returns an EWKT representation of this shape.""" 

2360 

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

2362 """Returns a GeoJSON representation of this shape. 

2363 

2364 Args: 

2365 keep_crs: Do not transform to WGS. 

2366 """ 

2367 

2368 def to_props(self) -> ShapeProps: 

2369 """Returns a GeoJSON representation of this shape.""" 

2370 

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

2372 

2373 def is_empty(self) -> bool: 

2374 """Returns True if this shape is empty.""" 

2375 

2376 def is_ring(self) -> bool: 

2377 """Returns True if this shape is a ring.""" 

2378 

2379 def is_simple(self) -> bool: 

2380 """Returns True if this shape is 'simple'.""" 

2381 

2382 def is_valid(self) -> bool: 

2383 """Returns True if this shape is valid.""" 

2384 

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

2386 """Returns True if this shape is equal to the other.""" 

2387 

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

2389 """Returns True if this shape contains the other.""" 

2390 

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

2392 """Returns True if this shape covers the other.""" 

2393 

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

2395 """Returns True if this shape is covered by the other.""" 

2396 

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

2398 """Returns True if this shape crosses the other.""" 

2399 

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

2401 """Returns True if this shape does not intersect with the other.""" 

2402 

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

2404 """Returns True if this shape intersects with the other.""" 

2405 

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

2407 """Returns True if this shape overlaps the other.""" 

2408 

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

2410 """Returns True if this shape touches the other.""" 

2411 

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

2413 """Returns True if this shape is within the other.""" 

2414 

2415 # set operations 

2416 

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

2418 """Computes a union of this shape and other shapes.""" 

2419 

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

2421 """Computes an intersection of this shape and other shapes.""" 

2422 

2423 # convertors 

2424 

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

2426 """Converts a singly-geometry shape to a multi-geometry one.""" 

2427 

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

2429 """Converts a geometry to another type.""" 

2430 

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

2432 """Converts a geometry to 2-dimensional.""" 

2433 

2434 # misc 

2435 

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

2437 """Builds a buffer polygon around the shape.""" 

2438 

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

2440 """Returns this shape transformed to another CRS.""" 

2441################################################################################ 

2442 

2443 

2444 

2445################################################################################ 

2446# /base/action/types.pyinc 

2447 

2448 

2449class ActionManager(Node): 

2450 """Action manager.""" 

2451 

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

2453 """ 

2454 Get a list of actions for a project, to which a user has access to. 

2455 

2456 Args: 

2457 project: The project requiring actions. 

2458 user: The user for whom the actions are retrieved. 

2459 

2460 Returns: 

2461 A list of accessible actions. 

2462 """ 

2463 

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

2465 """ 

2466 Locate an Action object. 

2467 

2468 Args: 

2469 project: If provided, find the action for that project; otherwise, search globally. 

2470 ext_type: The extension type to search for. 

2471 user: Locate actions only for this user. 

2472 

2473 Returns: 

2474 The located action object, or None if no match is found. 

2475 """ 

2476 

2477 def prepare_action( 

2478 self, 

2479 command_category: CommandCategory, 

2480 command_name: str, 

2481 params: dict, 

2482 user: 'User', 

2483 read_options: Optional[set[SpecReadOption]]=None, 

2484 ) -> tuple[Callable, Request]: 

2485 """ 

2486 Prepare an action to be executed based on the provided parameters. 

2487 

2488 Args: 

2489 command_category: The category of the command to execute. 

2490 command_name: The name of the command to execute. 

2491 params: Additional parameters required for the action. 

2492 user: The user initiating the action. 

2493 read_options: Read options for parsing parameters. 

2494 

2495 Returns: 

2496 A tuple containing the callable to execute and the associated request object. 

2497 """ 

2498 

2499 

2500class Action(Node): 

2501 """Base Action class.""" 

2502################################################################################ 

2503 

2504 

2505################################################################################ 

2506# /base/auth/types.pyinc 

2507 

2508 

2509class User(Object): 

2510 """User object.""" 

2511 

2512 isGuest: bool 

2513 """User is a Guest.""" 

2514 

2515 authProvider: 'AuthProvider' 

2516 """User authorization provider.""" 

2517 

2518 attributes: dict 

2519 """Public user attributes.""" 

2520 data: dict 

2521 """Private user data.""" 

2522 roles: set[str] 

2523 """User roles.""" 

2524 uid: str 

2525 """Global user uid.""" 

2526 

2527 authToken: str 

2528 """Token used for authorization.""" 

2529 displayName: str 

2530 """User display name.""" 

2531 email: str 

2532 """User email.""" 

2533 localUid: str 

2534 """User uid within its authorization provider.""" 

2535 loginName: str 

2536 """User login name.""" 

2537 mfaUid: str 

2538 """MFA adapter uid.""" 

2539 mfaSecret: str 

2540 """MFA secret.""" 

2541 

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

2543 """Get the ACL bit for a specific object. 

2544 

2545 Args: 

2546 access: Access mode. 

2547 obj: Requested object. 

2548 

2549 Returns: 

2550 ``1`` or ``0`` if the user's permissions have the bit and ``None`` otherwise. 

2551 """ 

2552 

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

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

2555 

2556 Args: 

2557 access: Access mode. 

2558 obj: Requested object. 

2559 *context: Further objects to check. 

2560 

2561 Returns: 

2562 ``True`` is access is granted. 

2563 """ 

2564 

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

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

2567 

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

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

2570 

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

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

2573 

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

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

2576 

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

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

2579 

2580 def can_edit(self, obj: Object, *context) -> bool: 

2581 """Check if the user has "edit" permissions on an object.""" 

2582 

2583 def acquire(self, uid: str = None, classref: Optional[ClassRef] = None, access: Optional[Access] = None) -> Optional[Object]: 

2584 """Get a readable object by uid. 

2585 

2586 Args: 

2587 uid: Object uid. 

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

2589 access: Access mode, assumed ``Access.read`` if omitted. 

2590 

2591 Returns: 

2592 A readable object or ``None`` if the object does not exists or user doesn't have a permission. 

2593 """ 

2594 

2595 def require(self, uid: str = None, classref: Optional[ClassRef] = None, access: Optional[Access] = None) -> Object: 

2596 """Get a readable object by uid and fail if not found. 

2597 

2598 Args: 

2599 uid: Object uid. 

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

2601 access: Access mode, assumed ``Access.read`` if omitted. 

2602 

2603 Returns: 

2604 A readable object. 

2605 

2606 Raises: 

2607 ``NotFoundError`` if the object doesn't exist. 

2608 ``ForbiddenError`` if the user cannot read the object. 

2609 """ 

2610 

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

2612 """Get a readable Project object. 

2613 

2614 Args: 

2615 uid: Project uid. 

2616 

2617 Returns: 

2618 A Project object. 

2619 """ 

2620 

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

2622 """Get a readable Layer object. 

2623 

2624 Args: 

2625 uid: Layer uid. 

2626 

2627 Returns: 

2628 A Layer object. 

2629 """ 

2630 

2631 

2632class AuthManager(Node): 

2633 """Authentication manager.""" 

2634 

2635 guestSession: 'AuthSession' 

2636 """Preconfigured Guest session.""" 

2637 

2638 guestUser: 'User' 

2639 """Preconfigured Guest user.""" 

2640 systemUser: 'User' 

2641 """Preconfigured System user.""" 

2642 

2643 providers: list['AuthProvider'] 

2644 """Authentication providers.""" 

2645 methods: list['AuthMethod'] 

2646 """Authentication methods.""" 

2647 mfAdapters: list['AuthMultiFactorAdapter'] 

2648 """Authentication MFA handlers.""" 

2649 

2650 sessionMgr: 'AuthSessionManager' 

2651 """Session manager.""" 

2652 

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

2654 """Authenticate a user. 

2655 

2656 Args: 

2657 method: Authentication method. 

2658 credentials: Credentials object. 

2659 

2660 Returns: 

2661 An authenticated User or ``None`` if authentication failed. 

2662 """ 

2663 

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

2665 """Get a User by its global uid. 

2666 

2667 Args: 

2668 user_uid: Global user uid. 

2669 Returns: 

2670 A User or ``None``. 

2671 """ 

2672 

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

2674 """Get an authentication Provider by its uid. 

2675 

2676 Args: 

2677 uid: Uid. 

2678 Returns: 

2679 A Provider or ``None``. 

2680 """ 

2681 

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

2683 """Get an authentication Method by its uid. 

2684 

2685 Args: 

2686 uid: Uid. 

2687 Returns: 

2688 A Method or ``None``. 

2689 """ 

2690 

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

2692 """Get a Multi-Factor Adapter by its uid. 

2693 

2694 Args: 

2695 uid: Adapter uid. 

2696 Returns: 

2697 A Multi-Factor Adapter or ``None`` if not found. 

2698 """ 

2699 return None 

2700 

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

2702 """Return a string representation of a User. 

2703 

2704 Args: 

2705 user: A User object. 

2706 

2707 Returns: 

2708 A json string. 

2709 """ 

2710 

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

2712 """Restore a User object from a serialized representation. 

2713 

2714 Args: 

2715 ser: A json string. 

2716 

2717 Returns: 

2718 A User object. 

2719 """ 

2720 

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

2722 """Check if an object is public.""" 

2723 

2724 

2725class AuthMethod(Node): 

2726 """Authentication Method.""" 

2727 

2728 secure: bool 

2729 """Method is only allowed in a secure context.""" 

2730 

2731 allowInsecureFrom: list[str] 

2732 """List of IPs from which insecure access is allowed.""" 

2733 

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

2735 """Attempt to open a Session for a Requester. 

2736 

2737 Args: 

2738 req: Requester object. 

2739 

2740 Returns: 

2741 A Session or ``None``. 

2742 """ 

2743 

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

2745 """Close a previously opened Session. 

2746 

2747 Args: 

2748 req: Requester object. 

2749 res: Responder object. 

2750 

2751 Returns: 

2752 True if the Session was successfully closed. 

2753 """ 

2754 

2755 

2756class AuthMultiFactorState(Enum): 

2757 """State of a multifactor authorization transaction.""" 

2758 open = 'open' 

2759 """Transaction opened.""" 

2760 ok = 'ok' 

2761 """Transaction completed successfully.""" 

2762 retry = 'retry' 

2763 """Authorization has to be retried.""" 

2764 failed = 'failed' 

2765 """Authorization failed.""" 

2766 

2767 

2768class AuthMultiFactorTransaction(Data): 

2769 """Multifactor authorization transaction.""" 

2770 

2771 state: AuthMultiFactorState 

2772 """The current state of the authorization transaction.""" 

2773 restartCount: int 

2774 """The number of times the transaction has been restarted.""" 

2775 verifyCount: int 

2776 """The number of verification attempts made.""" 

2777 secret: str 

2778 """The secret associated with this transaction.""" 

2779 startTime: int 

2780 """The timestamp when the transaction started.""" 

2781 generateTime: int 

2782 """The timestamp when the code was last generated.""" 

2783 message: str 

2784 """A message associated with the transaction.""" 

2785 adapter: 'AuthMultiFactorAdapter' 

2786 """The MFA adapter handling this transaction.""" 

2787 user: 'User' 

2788 """The user associated with this transaction.""" 

2789 

2790 

2791class AuthMultiFactorAdapter(Node): 

2792 """Multi-factor authentication adapter.""" 

2793 

2794 message: str 

2795 lifeTime: int 

2796 maxRestarts: int 

2797 maxVerifyAttempts: int 

2798 

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

2800 """Initialize an MFA transaction for the user.""" 

2801 

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

2803 """Verify a payload.""" 

2804 

2805 def cancel(self, mfa: AuthMultiFactorTransaction): 

2806 """Cancel the transaction.""" 

2807 

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

2809 """Check if the MFA transaction is valid.""" 

2810 

2811 def check_restart(self, mfa: AuthMultiFactorTransaction) -> bool: 

2812 """Check if the transaction can be restarted.""" 

2813 

2814 def restart(self, mfa: AuthMultiFactorTransaction) -> Optional[AuthMultiFactorTransaction]: 

2815 """Restart the transaction.""" 

2816 

2817 def key_uri(self, secret: str | bytes, issuer_name: str, account_name: str) -> Optional[str]: 

2818 """Generate a key uri for this adapter.""" 

2819 

2820 

2821class AuthProvider(Node): 

2822 """Authentication Provider.""" 

2823 

2824 allowedMethods: list[str] 

2825 """List of Method types allowed to be used with this Provider.""" 

2826 

2827 def get_user(self, local_uid: str) -> Optional['User']: 

2828 """Get a User from its local uid. 

2829 

2830 Args: 

2831 local_uid: User local uid. 

2832 

2833 Returns: 

2834 A User or ``None``. 

2835 """ 

2836 

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

2838 """Authenticate a user. 

2839 

2840 Args: 

2841 method: Authentication method. 

2842 credentials: Credentials object. 

2843 

2844 Returns: 

2845 An authenticated User or ``None`` if authentication failed. 

2846 """ 

2847 

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

2849 """Return a string representation of a User. 

2850 

2851 Args: 

2852 user: A User object. 

2853 

2854 Returns: 

2855 A json string. 

2856 """ 

2857 

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

2859 """Restore a User object from a serialized representation. 

2860 

2861 Args: 

2862 ser: A json string. 

2863 

2864 Returns: 

2865 A User object. 

2866 """ 

2867 

2868 

2869class AuthSession: 

2870 """Authentication session.""" 

2871 

2872 uid: str 

2873 """Session uid.""" 

2874 method: Optional['AuthMethod'] 

2875 """Authentication method that created the session.""" 

2876 user: 'User' 

2877 """Authorized User.""" 

2878 data: dict 

2879 """Session data.""" 

2880 created: 'datetime.datetime' 

2881 """Session create time.""" 

2882 updated: 'datetime.datetime' 

2883 """Session update time.""" 

2884 isChanged: bool 

2885 """Session has changed since the last update..""" 

2886 

2887 def get(self, key: str, default=None): 

2888 """Get a session data value. 

2889 

2890 Args: 

2891 key: Value name. 

2892 default: Default value. 

2893 

2894 Returns: 

2895 A value or the default. 

2896 """ 

2897 

2898 def set(self, key: str, value): 

2899 """Set a session data value. 

2900 

2901 Args: 

2902 key: Value name. 

2903 value: A value. 

2904 """ 

2905 

2906 

2907class AuthSessionManager(Node): 

2908 """Authentication session Manager.""" 

2909 

2910 lifeTime: int 

2911 """Session lifetime in seconds.""" 

2912 

2913 def create(self, method: 'AuthMethod', user: 'User', data: Optional[dict] = None) -> 'AuthSession': 

2914 """Create a new Session, 

2915 

2916 Args: 

2917 method: Auth Method that creates the Session. 

2918 user: 'User' for which the Session is created. 

2919 data: Session data. 

2920 

2921 Returns: 

2922 A new Session. 

2923 """ 

2924 

2925 def delete(self, sess: 'AuthSession'): 

2926 """Delete a Session. 

2927 

2928 Args: 

2929 sess: Session object. 

2930 """ 

2931 

2932 def delete_all(self): 

2933 """Delete all Sessions. 

2934 """ 

2935 

2936 def get(self, uid: str) -> Optional['AuthSession']: 

2937 """Get Session by its uid. 

2938 

2939 Args: 

2940 uid: Session uid. 

2941 

2942 Returns: 

2943 A Session or ``None``. 

2944 """ 

2945 

2946 def get_valid(self, uid: str) -> Optional['AuthSession']: 

2947 """Get a valid Session by its uid. 

2948 

2949 Args: 

2950 uid: Session uid. 

2951 

2952 Returns: 

2953 A Session or ``None`` if uid does not exists or the Session is not valid. 

2954 """ 

2955 

2956 def get_all(self) -> list['AuthSession']: 

2957 """Get all sessions.""" 

2958 

2959 def save(self, sess: 'AuthSession'): 

2960 """Save the Session state into a persistent storage. 

2961 

2962 Args: 

2963 sess: Session object. 

2964 """ 

2965 

2966 def touch(self, sess: 'AuthSession'): 

2967 """Update the Session last activity timestamp. 

2968 

2969 Args: 

2970 sess: Session object. 

2971 """ 

2972 

2973 def cleanup(self): 

2974 """Remove invalid Sessions from the storage. 

2975 """ 

2976################################################################################ 

2977 

2978 

2979 

2980################################################################################ 

2981# /base/layer/types.pyinc 

2982 

2983 

2984class LayerDisplayMode(Enum): 

2985 """Layer display mode.""" 

2986 

2987 box = 'box' 

2988 """Display a layer as one big image (WMS-alike).""" 

2989 tile = 'tile' 

2990 """Display a layer in a tile grid.""" 

2991 client = 'client' 

2992 """Draw a layer in the client.""" 

2993 

2994 

2995class LayerClientOptions(Data): 

2996 """Client options for a layer.""" 

2997 

2998 expanded: bool 

2999 """A layer is expanded in the list view.""" 

3000 unlisted: bool 

3001 """A layer is hidden in the list view.""" 

3002 selected: bool 

3003 """A layer is initially selected.""" 

3004 hidden: bool 

3005 """A layer is initially hidden.""" 

3006 unfolded: bool 

3007 """A layer is not listed, but its children are.""" 

3008 exclusive: bool 

3009 """Only one of this layer children is visible at a time.""" 

3010 treeClassName: str 

3011 """CSS class name for the layer tree item.""" 

3012 

3013 

3014class TileGrid(Data): 

3015 """Tile grid.""" 

3016 

3017 uid: str 

3018 bounds: Bounds 

3019 origin: Origin 

3020 resolutions: list[float] 

3021 tileSize: int 

3022 

3023 

3024class LayerCache(Data): 

3025 """Layer cache.""" 

3026 

3027 maxAge: int 

3028 maxLevel: int 

3029 requestBuffer: int 

3030 requestTiles: int 

3031 

3032 

3033class FeatureLoadingStrategy(Enum): 

3034 """Loading strategy for features.""" 

3035 

3036 all = 'all' 

3037 """Load all features.""" 

3038 bbox = 'bbox' 

3039 """Load only features in the current map extent.""" 

3040 lazy = 'lazy' 

3041 """Load features on demand.""" 

3042 

3043 

3044class LayerOws(Node): 

3045 """Layer OWS controller.""" 

3046 

3047 allowedServiceUids: list[str] 

3048 deniedServiceUids: list[str] 

3049 featureName: str 

3050 geometryName: str 

3051 layerName: str 

3052 models: list['Model'] 

3053 xmlNamespace: Optional['XmlNamespace'] 

3054 

3055 

3056class Layer(Node): 

3057 """Layer object.""" 

3058 

3059 canRenderBox: bool 

3060 canRenderSvg: bool 

3061 canRenderXyz: bool 

3062 

3063 isEnabledForOws: bool 

3064 isGroup: bool 

3065 isSearchable: bool 

3066 

3067 hasLegend: bool 

3068 

3069 bounds: Bounds 

3070 zoomBounds: Bounds 

3071 wgsExtent: Extent 

3072 mapCrs: 'Crs' 

3073 clientOptions: LayerClientOptions 

3074 displayMode: LayerDisplayMode 

3075 loadingStrategy: FeatureLoadingStrategy 

3076 imageFormat: ImageFormat 

3077 opacity: float 

3078 resolutions: list[float] 

3079 title: str 

3080 

3081 grid: Optional[TileGrid] 

3082 cache: Optional[LayerCache] 

3083 

3084 metadata: 'Metadata' 

3085 legend: Optional['Legend'] 

3086 legendUrl: str 

3087 

3088 finders: list['Finder'] 

3089 templates: list['Template'] 

3090 models: list['Model'] 

3091 ows: 'LayerOws' 

3092 

3093 layers: list['Layer'] 

3094 

3095 sourceLayers: list['SourceLayer'] 

3096 

3097 def render(self, lri: LayerRenderInput) -> Optional['LayerRenderOutput']: ... 

3098 

3099 def find_features(self, search: 'SearchQuery', user: 'User') -> list['Feature']: ... 

3100 

3101 def render_legend(self, args: Optional[dict] = None) -> Optional['LegendRenderOutput']: ... 

3102 

3103 def url_path(self, kind: str) -> str: ... 

3104 

3105 def ancestors(self) -> list['Layer']: ... 

3106 

3107 def descendants(self) -> list['Layer']: ... 

3108################################################################################ 

3109 

3110 

3111################################################################################ 

3112# /base/legend/types.pyinc 

3113 

3114 

3115class LegendRenderOutput(Data): 

3116 """Legend render output.""" 

3117 

3118 html: str 

3119 image: 'Image' 

3120 image_path: str 

3121 size: Size 

3122 mime: str 

3123 

3124 

3125class Legend(Node): 

3126 """Legend object.""" 

3127 

3128 def render(self, args: Optional[dict] = None) -> Optional[LegendRenderOutput]: ... 

3129################################################################################ 

3130 

3131 

3132################################################################################ 

3133# /base/map/types.pyinc 

3134 

3135 

3136class Map(Node): 

3137 """Map object.""" 

3138 

3139 rootLayer: 'Layer' 

3140 

3141 bounds: Bounds 

3142 center: Point 

3143 coordinatePrecision: int 

3144 initResolution: float 

3145 resolutions: list[float] 

3146 title: str 

3147 wgsExtent: Extent 

3148################################################################################ 

3149 

3150 

3151 

3152################################################################################ 

3153# /base/model/types.pyinc 

3154 

3155 

3156class ModelClientOptions(Data): 

3157 """Client options for a model""" 

3158 

3159 keepFormOpen: Optional[bool] 

3160 

3161class ModelValidationError(Data): 

3162 """Validation error.""" 

3163 

3164 fieldName: str 

3165 message: str 

3166 

3167 

3168class ModelOperation(Enum): 

3169 """Model operation.""" 

3170 

3171 read = 'read' 

3172 create = 'create' 

3173 update = 'update' 

3174 delete = 'delete' 

3175 

3176 

3177class ModelReadTarget(Enum): 

3178 """Target for the read operation.""" 

3179 

3180 map = 'map' 

3181 """The feature is to be drawn on a map.""" 

3182 searchResults = 'searchResults' 

3183 """The feature is to be displayed in the search results list.""" 

3184 list = 'list' 

3185 """The feature is to be displayed in a list view.""" 

3186 editList = 'editList' 

3187 """The feature is to be displayed in an editable list view.""" 

3188 editForm = 'editForm' 

3189 """The feature is to be displayed in an edit form .""" 

3190 

3191 

3192class ModelSelectBuild(Data): 

3193 """Database select statement.""" 

3194 

3195 columns: list['sqlalchemy.Column'] 

3196 geometryWhere: list 

3197 keywordWhere: list 

3198 where: list 

3199 order: list 

3200 

3201 

3202class ModelContext(Data): 

3203 """Model context.""" 

3204 

3205 op: ModelOperation 

3206 target: ModelReadTarget 

3207 user: 'User' 

3208 project: 'Project' 

3209 relDepth: int = 0 

3210 maxDepth: int = 0 

3211 search: 'SearchQuery' 

3212 dbSelect: ModelSelectBuild 

3213 

3214 

3215EmptyValue = object() 

3216"""Special value for empty fields.""" 

3217 

3218ErrorValue = object() 

3219"""Special value for invalid fields.""" 

3220 

3221 

3222class ModelWidget(Node): 

3223 """Model widget.""" 

3224 

3225 supportsTableView: bool = True 

3226 

3227 

3228class ModelValidator(Node): 

3229 """Model Validator.""" 

3230 

3231 message: str 

3232 ops: set[ModelOperation] 

3233 

3234 def validate(self, field: 'ModelField', feature: 'Feature', mc: ModelContext) -> bool: ... 

3235 

3236 

3237class ModelValue(Node): 

3238 """Model value.""" 

3239 

3240 isDefault: bool 

3241 ops: set[ModelOperation] 

3242 

3243 def compute(self, field: 'ModelField', feature: 'Feature', mc: 'ModelContext'): ... 

3244 

3245 

3246class ModelField(Node): 

3247 """Model field.""" 

3248 

3249 name: str 

3250 title: str 

3251 

3252 attributeType: AttributeType 

3253 

3254 widget: Optional['ModelWidget'] = None 

3255 

3256 values: list['ModelValue'] 

3257 validators: list['ModelValidator'] 

3258 

3259 isPrimaryKey: bool 

3260 isRequired: bool 

3261 isUnique: bool 

3262 isAuto: bool 

3263 isHidden: bool 

3264 

3265 supportsFilterSearch: bool = False 

3266 supportsGeometrySearch: bool = False 

3267 supportsKeywordSearch: bool = False 

3268 

3269 model: 'Model' 

3270 

3271 def before_select(self, mc: ModelContext): ... 

3272 

3273 def after_select(self, features: list['Feature'], mc: ModelContext): ... 

3274 

3275 def before_create(self, feature: 'Feature', mc: ModelContext): ... 

3276 

3277 def after_create(self, feature: 'Feature', mc: ModelContext): ... 

3278 

3279 def before_create_related(self, to_feature: 'Feature', mc: ModelContext): ... 

3280 

3281 def after_create_related(self, to_feature: 'Feature', mc: ModelContext): ... 

3282 

3283 def before_update(self, feature: 'Feature', mc: ModelContext): ... 

3284 

3285 def after_update(self, feature: 'Feature', mc: ModelContext): ... 

3286 

3287 def before_delete(self, feature: 'Feature', mc: ModelContext): ... 

3288 

3289 def after_delete(self, feature: 'Feature', mc: ModelContext): ... 

3290 

3291 def do_init(self, feature: 'Feature', mc: ModelContext): ... 

3292 

3293 def do_init_related(self, to_feature: 'Feature', mc: ModelContext): ... 

3294 

3295 def do_validate(self, feature: 'Feature', mc: ModelContext): ... 

3296 

3297 def from_props(self, feature: 'Feature', mc: ModelContext): ... 

3298 

3299 def to_props(self, feature: 'Feature', mc: ModelContext): ... 

3300 

3301 def from_record(self, feature: 'Feature', mc: ModelContext): ... 

3302 

3303 def to_record(self, feature: 'Feature', mc: ModelContext): ... 

3304 

3305 def related_models(self) -> list['Model']: ... 

3306 

3307 def find_relatable_features(self, search: 'SearchQuery', mc: ModelContext) -> list['Feature']: ... 

3308 

3309 def raw_to_python(self, feature: 'Feature', value, mc: ModelContext): ... 

3310 

3311 def prop_to_python(self, feature: 'Feature', value, mc: ModelContext): ... 

3312 

3313 def python_to_raw(self, feature: 'Feature', value, mc: ModelContext): ... 

3314 

3315 def python_to_prop(self, feature: 'Feature', value, mc: ModelContext): ... 

3316 

3317 def describe(self) -> Optional['ColumnDescription']: ... 

3318 

3319 

3320class Model(Node): 

3321 """Data Model.""" 

3322 

3323 clientOptions: ModelClientOptions 

3324 defaultSort: list['SearchSort'] 

3325 fields: list['ModelField'] 

3326 geometryCrs: Optional['Crs'] 

3327 geometryName: str 

3328 geometryType: Optional[GeometryType] 

3329 isEditable: bool 

3330 loadingStrategy: 'FeatureLoadingStrategy' 

3331 title: str 

3332 uidName: str 

3333 withTableView: bool 

3334 

3335 def find_features(self, search: 'SearchQuery', mc: ModelContext) -> list['Feature']: ... 

3336 

3337 def get_features(self, uids: Iterable[str | int], mc: ModelContext) -> list['Feature']: ... 

3338 

3339 def get_feature(self, uid: str | int, mc: ModelContext) -> Optional['Feature']: ... 

3340 

3341 def init_feature(self, feature: 'Feature', mc: ModelContext): ... 

3342 

3343 def create_feature(self, feature: 'Feature', mc: ModelContext) -> FeatureUid: ... 

3344 

3345 def update_feature(self, feature: 'Feature', mc: ModelContext) -> FeatureUid: ... 

3346 

3347 def delete_feature(self, feature: 'Feature', mc: ModelContext) -> FeatureUid: ... 

3348 

3349 def validate_feature(self, feature: 'Feature', mc: ModelContext) -> bool: ... 

3350 

3351 def feature_from_props(self, props: 'FeatureProps', mc: ModelContext) -> 'Feature': ... 

3352 

3353 def feature_to_props(self, feature: 'Feature', mc: ModelContext) -> 'FeatureProps': ... 

3354 

3355 def feature_to_view_props(self, feature: 'Feature', mc: ModelContext) -> 'FeatureProps': ... 

3356 

3357 def describe(self) -> Optional['DataSetDescription']: ... 

3358 

3359 def field(self, name: str) -> Optional['ModelField']: ... 

3360 

3361 def related_models(self) -> list['Model']: ... 

3362 

3363 

3364class ModelManager(Node): 

3365 """Model manager.""" 

3366 

3367 def get_model(self, uid: str, user: 'User' = None, access: Access = None) -> Optional['Model']: ... 

3368 

3369 def find_model(self, *objects, user: 'User' = None, access: Access = None) -> Optional['Model']: ... 

3370 

3371 def editable_models(self, project: 'Project', user: 'User') -> list['Model']: ... 

3372 

3373 def default_model(self) -> 'Model': ... 

3374################################################################################ 

3375 

3376 

3377################################################################################ 

3378# /base/database/types.pyinc 

3379 

3380 

3381class DatabaseModel(Model): 

3382 """Database-based data model.""" 

3383 

3384 db: 'DatabaseProvider' 

3385 """Database provider.""" 

3386 sqlFilter: str 

3387 """Literal SQL condition applied when selecting rows.""" 

3388 tableName: str 

3389 """Table name associated with this model.""" 

3390 

3391 def table(self) -> 'sqlalchemy.Table': 

3392 """Return the SQLAlchemy Table object for this database model.""" 

3393 

3394 def column(self, column_name: str) -> 'sqlalchemy.Column': 

3395 """Retrieve the SQLAlchemy Column object for the given column name.""" 

3396 

3397 def uid_column(self) -> 'sqlalchemy.Column': 

3398 """Return the SQLAlchemy Column object representing the unique identifier column.""" 

3399 

3400 def fetch_features(self, select: 'sqlalchemy.Select') -> list['Feature']: 

3401 """Fetch features from the database based on the provided SQLAlchemy Select statement.""" 

3402 

3403 def build_select(self, mc: 'ModelContext') -> Optional['sqlalchemy.Select']: 

3404 """Build a SQLAlchemy Select statement based on the provided ModelContext.""" 

3405 

3406 

3407class ColumnDescription(Data): 

3408 """Description of a dataset column.""" 

3409 

3410 columnIndex: int 

3411 """The index of the column within the table.""" 

3412 comment: str 

3413 """Column comment or description provided in the database metadata.""" 

3414 default: str 

3415 """The default value assigned to the column, if any.""" 

3416 geometrySrid: int 

3417 """The Spatial Reference Identifier (SRID) for geometry columns.""" 

3418 geometryType: GeometryType 

3419 """The type of geometry stored in the column (e.g., Point, Polygon).""" 

3420 isAutoincrement: bool 

3421 """Indicates if the column is auto-incremented.""" 

3422 isNullable: bool 

3423 """Specifies if the column permits NULL values.""" 

3424 isPrimaryKey: bool 

3425 """Specifies if the column is part of the primary key.""" 

3426 isUnique: bool 

3427 """Indicates if the column has a unique constraint.""" 

3428 hasDefault: bool 

3429 """Indicates if the column has a database-defined default value.""" 

3430 isIndexed: bool 

3431 """Indicates if the column has an index.""" 

3432 name: str 

3433 """The name of the column.""" 

3434 nativeType: str 

3435 """The database-specific data type of the column.""" 

3436 options: dict 

3437 """Additional options or configurations for the column, if any.""" 

3438 type: AttributeType 

3439 """The abstract type of the column used in higher-level processing.""" 

3440 

3441 

3442class DataSetDescription(Data): 

3443 """Description of a dataset, like a DB table or a GDAL data set.""" 

3444 

3445 columns: list[ColumnDescription] 

3446 """A list of column descriptions.""" 

3447 columnMap: dict[str, ColumnDescription] 

3448 """A dictionary mapping column names to their descriptions.""" 

3449 fullName: str 

3450 """The full name of the dataset, including schema if applicable.""" 

3451 geometryName: str 

3452 """The name of the geometry column, if any.""" 

3453 geometrySrid: int 

3454 """The Spatial Reference Identifier (SRID) for the geometry.""" 

3455 geometryType: GeometryType 

3456 """The type of geometry stored in the dataset.""" 

3457 name: str 

3458 """The name of the dataset or table.""" 

3459 schema: str 

3460 """The schema to which the dataset belongs.""" 

3461 

3462 

3463class DatabaseManager(Node): 

3464 """Database manager.""" 

3465 

3466 providers: list['DatabaseProvider'] 

3467 """A list of database providers managed by this DatabaseManager.""" 

3468 

3469 def create_provider(self, cfg: Config, **kwargs) -> 'DatabaseProvider': 

3470 """Create and return a DatabaseProvider instance based on the given configuration. 

3471 

3472 Args: 

3473 cfg: The configuration object for the database provider. 

3474 **kwargs: Additional keyword arguments to customize the provider creation. 

3475 

3476 Returns: 

3477 DatabaseProvider: A new database provider instance. 

3478 """ 

3479 

3480 def find_provider(self, uid: Optional[str] = None, ext_type: Optional[str] = None) -> Optional['DatabaseProvider']: 

3481 """Find and return a DatabaseProvider that matches the given UID and/or extension type. 

3482 

3483 Args: 

3484 uid: The unique identifier of the database provider to find. 

3485 ext_type: The type of the database provider to find. 

3486 

3487 Returns: 

3488 The matching database provider if found, otherwise None. 

3489 """ 

3490 

3491 

3492DatabaseTableAlike: TypeAlias = Union['sqlalchemy.Table', str] 

3493"""An SQLAlchemy ``Table`` object or a string table name.""" 

3494 

3495 

3496DatabaseStmt: TypeAlias = Union['sqlalchemy.Executable', str] 

3497"""An Executable SQLAlchemy object or a string SQL statement.""" 

3498 

3499 

3500class DatabaseConnection: 

3501 """Database connection. 

3502 

3503 Extends ``sqlalchemy.Connection`` and provides some convenience methods. 

3504 """ 

3505 

3506 saConn: 'sqlalchemy.Connection' 

3507 

3508 def __enter__(self) -> 'DatabaseConnection': ... 

3509 

3510 def __exit__(self, exc_type, exc_value, traceback): ... 

3511 

3512 def execute(self, stmt: 'sqlalchemy.Executable', params=None, execution_options: dict=None) -> 'sqlalchemy.CursorResult': ... 

3513 

3514 def commit(self): ... 

3515 

3516 def rollback(self): ... 

3517 

3518 def close(self): ... 

3519 

3520 def exec(self, stmt: 'DatabaseStmt', **params) -> 'sqlalchemy.CursorResult': ... 

3521 

3522 def exec_commit(self, stmt: 'DatabaseStmt', **params) -> 'sqlalchemy.CursorResult': ... 

3523 

3524 def exec_rollback(self, stmt: 'DatabaseStmt', **params) -> 'sqlalchemy.CursorResult': ... 

3525 

3526 def fetch_all(self, stmt: 'DatabaseStmt', **params) -> list[dict]: ... 

3527 

3528 def fetch_first(self, stmt: 'DatabaseStmt', **params) -> dict | None: ... 

3529 

3530 def fetch_scalars(self, stmt: 'DatabaseStmt', **params) -> list: ... 

3531 

3532 def fetch_strings(self, stmt: 'DatabaseStmt', **params) -> list[str]: ... 

3533 

3534 def fetch_ints(self, stmt: 'DatabaseStmt', **params) -> list[int]: ... 

3535 

3536 def fetch_scalar(self, stmt: 'DatabaseStmt', **params) -> Any: ... 

3537 

3538 def fetch_string(self, stmt: 'DatabaseStmt', **params) -> str | None: ... 

3539 

3540 def fetch_int(self, stmt: 'DatabaseStmt', **params) -> int | None: ... 

3541 

3542class DatabaseInspectOptions(Data): 

3543 """Options for database inspection.""" 

3544 

3545 refresh: bool = False 

3546 """Whether to force inspection even if cached information is available.""" 

3547 cacheLifeTime: int = 0 

3548 """Schema cache lifetime in seconds.""" 

3549 

3550 

3551class DatabaseProvider(Node): 

3552 """Database Provider. 

3553 

3554 A database Provider wraps SQLAlchemy ``Engine`` and ``Connection`` objects 

3555 and provides common db functionality. 

3556 """ 

3557 

3558 def connect(self) -> 'DatabaseConnection': 

3559 """Context manager for SQLAlchemy ``Connection``. 

3560 

3561 Context calls to this method can be nested. An inner call is a no-op, as no new connection is created. 

3562 Only the outermost connection is closed upon exit:: 

3563 

3564 with db.connect(): 

3565 ... 

3566 with db.connect(): # no-op 

3567 ... 

3568 # connection remains open 

3569 ... 

3570 # connection closed 

3571 """ 

3572 

3573 def engine_options(self, **kwargs): 

3574 """Add defaults to the SA engine options.""" 

3575 

3576 def url(self) -> str: 

3577 """Return the connection URL.""" 

3578 

3579 def engine(self) -> 'sqlalchemy.Engine': 

3580 """Get SQLAlchemy ``Engine`` object for this provider.""" 

3581 

3582 def create_engine(self, **kwargs) -> 'sqlalchemy.Engine': 

3583 """CreateSQLAlchemy ``Engine`` object for this provider.""" 

3584 

3585 def describe(self, table: DatabaseTableAlike) -> 'DataSetDescription': 

3586 """Describe a table.""" 

3587 

3588 def table(self, table: 'DatabaseTableAlike', **kwargs) -> 'sqlalchemy.Table': 

3589 """SQLAlchemy ``Table`` object for a specific table.""" 

3590 

3591 def column(self, table: DatabaseTableAlike, column_name: str) -> 'sqlalchemy.Column': 

3592 """SQLAlchemy ``Column`` object for a specific column.""" 

3593 

3594 def count(self, table: DatabaseTableAlike) -> int: 

3595 """Return table record count or 0 if the table does not exist.""" 

3596 

3597 def has_schema(self, schema_name: str) -> bool: 

3598 """Check if a specific schema exists.""" 

3599 

3600 def has_table(self, table_name: str) -> bool: 

3601 """Check if a specific table exists.""" 

3602 

3603 def has_column(self, table: DatabaseTableAlike, column_name: str) -> bool: 

3604 """Check if a specific column exists.""" 

3605 

3606 def join_table_name(self, schema: str, name: str) -> str: 

3607 """Create a full table name from the schema and table names.""" 

3608 

3609 def split_table_name(self, table_name: str) -> tuple[str, str]: 

3610 """Split a full table name into the schema and table names.""" 

3611 

3612 def table_bounds(self, table: DatabaseTableAlike) -> Optional[Bounds]: 

3613 """Compute a bounding box for the table primary geometry.""" 

3614 

3615 def select_text(self, sql: str, **kwargs) -> list[dict]: 

3616 """Execute a textual SELECT stmt and return a list of record dicts.""" 

3617 

3618 def execute_text(self, sql: str, **kwargs) -> 'sqlalchemy.CursorResult': 

3619 """Execute a textual DML stmt and return a result.""" 

3620 

3621 def schema_names(self) -> list[str]: 

3622 """Return a list of schema names in the database.""" 

3623 

3624 def inspect_schema(self, schema: str, options: Optional[DatabaseInspectOptions] = None): 

3625 """Inspect the database schema and cache the results based on the provided options.""" 

3626################################################################################ 

3627 

3628 

3629 

3630################################################################################ 

3631# /base/job/types.pyinc 

3632 

3633 

3634class JobTerminated(Exception): 

3635 pass 

3636 

3637 

3638class JobState(Enum): 

3639 """Background job state.""" 

3640 

3641 init = 'init' 

3642 """The job is being created.""" 

3643 open = 'open' 

3644 """The job is just created and waiting for start.""" 

3645 running = 'running' 

3646 """The job is running.""" 

3647 complete = 'complete' 

3648 """The job has been completed successfully.""" 

3649 error = 'error' 

3650 """There was an error.""" 

3651 cancel = 'cancel' 

3652 """The job was cancelled.""" 

3653 

3654 

3655class Job(Data): 

3656 """Background job data.""" 

3657 

3658 uid: str 

3659 user: 'User' 

3660 worker: str 

3661 state: JobState 

3662 error: str 

3663 numSteps: int 

3664 step: int 

3665 stepName: str 

3666 payload: dict 

3667 timeCreated: datetime.datetime 

3668 timeUpdated: datetime.datetime 

3669 

3670 

3671class JobRequest(Request): 

3672 jobUid: str 

3673 

3674 

3675class JobStatusResponse(Response): 

3676 jobUid: str 

3677 state: JobState 

3678 progress: int 

3679 stepName: str 

3680 output: dict 

3681 

3682 

3683class JobManager(Node): 

3684 """Job Manager.""" 

3685 

3686 def create_job(self, worker: type, user: User, payload: dict = None) -> Job: ... 

3687 

3688 def get_job(self, job_uid: str, user: User = None, state: JobState = None) -> Optional[Job]: ... 

3689 

3690 def update_job(self, job: Job, **kwargs) -> Optional[Job]: ... 

3691 

3692 def run_job(self, job: Job) -> Optional[Job]: ... 

3693 

3694 def cancel_job(self, job: Job) -> Optional[Job]: ... 

3695 

3696 def remove_job(self, job: Job): ... 

3697 

3698 def schedule_job(self, job: Job) -> Job: ... 

3699 

3700 def require_job(self, req: 'WebRequester', p: JobRequest) -> Job: ... 

3701 

3702 def handle_status_request(self, req: 'WebRequester', p: JobRequest) -> JobStatusResponse: ... 

3703 

3704 def handle_cancel_request(self, req: 'WebRequester', p: JobRequest) -> JobStatusResponse: ... 

3705 

3706 def job_status_response(self, job: Job, **kwargs) -> 'JobStatusResponse': ... 

3707################################################################################ 

3708 

3709 

3710################################################################################ 

3711# /base/ows/types.pyinc 

3712 

3713 

3714import gws 

3715 

3716 

3717class OwsProtocol(Enum): 

3718 """Supported OWS protocol.""" 

3719 

3720 WMS = 'WMS' 

3721 WMTS = 'WMTS' 

3722 WCS = 'WCS' 

3723 WFS = 'WFS' 

3724 CSW = 'CSW' 

3725 

3726 

3727class OwsAuthorization(Data): 

3728 type: str 

3729 username: str 

3730 password: str 

3731 

3732 

3733class OwsVerb(Enum): 

3734 """OWS verb.""" 

3735 

3736 CreateStoredQuery = 'CreateStoredQuery' 

3737 DescribeCoverage = 'DescribeCoverage' 

3738 DescribeFeatureType = 'DescribeFeatureType' 

3739 DescribeLayer = 'DescribeLayer' 

3740 DescribeRecord = 'DescribeRecord' 

3741 DescribeStoredQueries = 'DescribeStoredQueries' 

3742 DropStoredQuery = 'DropStoredQuery' 

3743 GetCapabilities = 'GetCapabilities' 

3744 GetFeature = 'GetFeature' 

3745 GetFeatureInfo = 'GetFeatureInfo' 

3746 GetFeatureWithLock = 'GetFeatureWithLock' 

3747 GetLegendGraphic = 'GetLegendGraphic' 

3748 GetMap = 'GetMap' 

3749 GetPrint = 'GetPrint' 

3750 GetPropertyValue = 'GetPropertyValue' 

3751 GetRecordById = 'GetRecordById' 

3752 GetRecords = 'GetRecords' 

3753 GetTile = 'GetTile' 

3754 ListStoredQueries = 'ListStoredQueries' 

3755 LockFeature = 'LockFeature' 

3756 Transaction = 'Transaction' 

3757 

3758 

3759class OwsOperation(Data): 

3760 """OWS operation.""" 

3761 

3762 allowedParameters: dict[str, list[str]] 

3763 constraints: dict[str, list[str]] 

3764 formats: list[str] 

3765 handlerName: str 

3766 params: dict[str, str] 

3767 postUrl: Url 

3768 preferredFormat: str 

3769 url: Url 

3770 verb: OwsVerb 

3771 

3772 

3773class OwsCapabilities(Data): 

3774 """OWS capabilities structure.""" 

3775 

3776 metadata: 'Metadata' 

3777 operations: list['OwsOperation'] 

3778 sourceLayers: list['SourceLayer'] 

3779 tileMatrixSets: list['TileMatrixSet'] 

3780 version: str 

3781 

3782 

3783class OwsService(Node): 

3784 """OWS Service.""" 

3785 

3786 isRasterService: bool = False 

3787 """Service provides raster services.""" 

3788 isVectorService: bool = False 

3789 """Service provides vector services.""" 

3790 isOwsCommon: bool = False 

3791 """Conforms to OGC Web Services Common Standard.""" 

3792 

3793 alwaysXY: bool 

3794 """Force lon/lat order for geographic projections.""" 

3795 metadata: 'Metadata' 

3796 """Service metadata.""" 

3797 name: str 

3798 """Service name.""" 

3799 project: Optional['Project'] 

3800 """Project this service is configured for.""" 

3801 rootLayer: Optional['Layer'] 

3802 """Root layer of the service.""" 

3803 protocol: OwsProtocol 

3804 """Supported protocol.""" 

3805 defaultFeatureCount: int 

3806 """Default limit of features per page.""" 

3807 maxFeatureCount: int 

3808 """Max limit of features per page.""" 

3809 searchTolerance: UomValue 

3810 """Default tolerance for spatial search.""" 

3811 supportedBounds: list[Bounds] 

3812 """Supported bounds.""" 

3813 supportedVersions: list[str] 

3814 """Supported versions.""" 

3815 supportedOperations: list['OwsOperation'] 

3816 """Supported operations.""" 

3817 templates: list['Template'] 

3818 """Service templates.""" 

3819 imageFormats: list[ImageFormat] 

3820 """Supported image formats.""" 

3821 updateSequence: str 

3822 """Service update sequence.""" 

3823 withInspireMeta: bool 

3824 """Include INSPIRE metadata.""" 

3825 withStrictParams: bool 

3826 """Strict parameter checking.""" 

3827 

3828 def handle_request(self, req: 'WebRequester') -> ContentResponse: 

3829 """Handle a service request.""" 

3830 

3831 def layer_is_compatible(self, layer: 'Layer') -> bool: 

3832 """True if layer can be used in this service.""" 

3833 

3834 

3835class OwsProvider(Node): 

3836 """OWS services Provider.""" 

3837 

3838 alwaysXY: bool 

3839 authorization: Optional['OwsAuthorization'] 

3840 bounds: Optional[Bounds] 

3841 forceCrs: 'Crs' 

3842 maxRequests: int 

3843 metadata: 'Metadata' 

3844 operations: list['OwsOperation'] 

3845 protocol: 'OwsProtocol' 

3846 sourceLayers: list['SourceLayer'] 

3847 url: Url 

3848 version: str 

3849 wgsExtent: Optional[Extent] 

3850 

3851 def get_operation(self, verb: 'OwsVerb', method: Optional['RequestMethod'] = None) -> Optional['OwsOperation']: ... 

3852 

3853 def get_features(self, args: 'SearchQuery', source_layers: list['SourceLayer']) -> list['FeatureRecord']: ... 

3854################################################################################ 

3855 

3856 

3857################################################################################ 

3858# /base/printer/types.pyinc 

3859 

3860 

3861class PrintPlaneType(Enum): 

3862 """Print plane type.""" 

3863 

3864 bitmap = 'bitmap' 

3865 url = 'url' 

3866 features = 'features' 

3867 raster = 'raster' 

3868 vector = 'vector' 

3869 soup = 'soup' 

3870 

3871 

3872class PrintPlane(Data): 

3873 """Print plane.""" 

3874 

3875 type: PrintPlaneType 

3876 

3877 opacity: Optional[float] 

3878 cssSelector: Optional[str] 

3879 

3880 bitmapData: Optional[bytes] 

3881 bitmapMode: Optional[str] 

3882 bitmapWidth: Optional[int] 

3883 bitmapHeight: Optional[int] 

3884 

3885 url: Optional[str] 

3886 

3887 features: Optional[list['FeatureProps']] 

3888 

3889 layerUid: Optional[str] 

3890 compositeLayerUids: Optional[list[str]] 

3891 

3892 soupPoints: Optional[list[Point]] 

3893 soupTags: Optional[list[Any]] 

3894 

3895 

3896class PrintMap(Data): 

3897 """Map properties for printing.""" 

3898 

3899 backgroundColor: Optional[int] 

3900 bbox: Optional[Extent] 

3901 center: Optional[Point] 

3902 planes: list[PrintPlane] 

3903 rotation: Optional[int] 

3904 scale: int 

3905 styles: Optional[list['StyleProps']] 

3906 visibleLayers: Optional[list[str]] 

3907 

3908 

3909class PrintRequestType(Enum): 

3910 """Type of the print request.""" 

3911 

3912 template = 'template' 

3913 map = 'map' 

3914 

3915 

3916class PrintRequest(Request): 

3917 """Print request.""" 

3918 

3919 type: PrintRequestType 

3920 

3921 args: Optional[dict] 

3922 crs: Optional[CrsName] 

3923 outputFormat: Optional[str] 

3924 maps: Optional[list[PrintMap]] 

3925 

3926 printerUid: Optional[str] 

3927 dpi: Optional[int] 

3928 outputSize: Optional[Size] 

3929 

3930 

3931class Printer(Node): 

3932 """Printer object.""" 

3933 

3934 title: str 

3935 template: 'Template' 

3936 models: list['Model'] 

3937 qualityLevels: list['TemplateQualityLevel'] 

3938 

3939 

3940class PrinterManager(Node): 

3941 """Print Manager.""" 

3942 

3943 def start_print_job(self, request: PrintRequest, user: 'User') -> 'JobStatusResponse': ... 

3944 

3945 def exec_print(self, request: PrintRequest, out_path: str): ... 

3946################################################################################ 

3947 

3948 

3949################################################################################ 

3950# /base/project/types.pyinc 

3951 

3952 

3953class Client(Node): 

3954 """GWS Client control object.""" 

3955 

3956 options: dict 

3957 elements: list 

3958 

3959 

3960class Project(Node): 

3961 """Project object.""" 

3962 

3963 assetsRoot: Optional['WebDocumentRoot'] 

3964 client: 'Client' 

3965 

3966 localeUids: list[str] 

3967 map: 'Map' 

3968 metadata: 'Metadata' 

3969 

3970 actions: list['Action'] 

3971 finders: list['Finder'] 

3972 models: list['Model'] 

3973 printers: list['Printer'] 

3974 templates: list['Template'] 

3975 owsServices: list['OwsService'] 

3976 

3977 vars: dict 

3978################################################################################ 

3979 

3980 

3981################################################################################ 

3982# /base/search/types.pyinc 

3983 

3984 

3985class SearchSort(Data): 

3986 """Search sort specification.""" 

3987 

3988 fieldName: str 

3989 reverse: bool 

3990 

3991 

3992class SearchFilterOperator(Enum): 

3993 """Search filter operator.""" 

3994 

3995 And = 'And' 

3996 Or = 'Or' 

3997 Not = 'Not' 

3998 

3999 PropertyIsEqualTo = 'PropertyIsEqualTo' 

4000 PropertyIsNotEqualTo = 'PropertyIsNotEqualTo' 

4001 PropertyIsLessThan = 'PropertyIsLessThan' 

4002 PropertyIsGreaterThan = 'PropertyIsGreaterThan' 

4003 PropertyIsLessThanOrEqualTo = 'PropertyIsLessThanOrEqualTo' 

4004 PropertyIsGreaterThanOrEqualTo = 'PropertyIsGreaterThanOrEqualTo' 

4005 PropertyIsLike = 'PropertyIsLike' 

4006 PropertyIsNull = 'PropertyIsNull' 

4007 PropertyIsNil = 'PropertyIsNil' 

4008 PropertyIsBetween = 'PropertyIsBetween' 

4009 

4010 Equals = 'Equals' 

4011 Disjoint = 'Disjoint' 

4012 Touches = 'Touches' 

4013 Within = 'Within' 

4014 Overlaps = 'Overlaps' 

4015 Crosses = 'Crosses' 

4016 Intersects = 'Intersects' 

4017 Contains = 'Contains' 

4018 DWithin = 'DWithin' 

4019 Beyond = 'Beyond' 

4020 BBOX = 'BBOX' 

4021 

4022 

4023class SearchFilterMatchAction(Enum): 

4024 """Search filter match action.""" 

4025 

4026 All = 'All' 

4027 Any = 'Any' 

4028 One = 'One' 

4029 

4030 

4031class SearchFilter(Data): 

4032 """Search filter.""" 

4033 

4034 operator: SearchFilterOperator 

4035 property: str 

4036 value: str 

4037 shape: 'Shape' 

4038 subFilters: list['SearchFilter'] 

4039 matchCase: bool 

4040 matchAction: SearchFilterMatchAction 

4041 wildCard: str 

4042 singleChar: str 

4043 escapeChar: str 

4044 

4045 

4046class SearchQuery(Data): 

4047 """Search query.""" 

4048 

4049 bounds: Bounds 

4050 """Search bounds.""" 

4051 extraArgs: dict 

4052 """Extra arguments for custom searches.""" 

4053 extraColumns: list 

4054 """Extra columns to select.""" 

4055 extraParams: dict 

4056 """Extra parameters to pass to a provider""" 

4057 extraWhere: list 

4058 """Extra where clauses.""" 

4059 keyword: str 

4060 """Keyword to search for.""" 

4061 layers: list['Layer'] 

4062 """Layers to search in.""" 

4063 limit: int 

4064 """Limit the number of results.""" 

4065 filter: SearchFilter 

4066 """Search filter.""" 

4067 project: 'Project' 

4068 """Project to search in.""" 

4069 resolution: float 

4070 """Pixel resolution for geometry search.""" 

4071 shape: 'Shape' 

4072 """Shape to search in.""" 

4073 sort: list[SearchSort] 

4074 """Sort options.""" 

4075 tolerance: 'UomValue' 

4076 """Tolerance for geometry search.""" 

4077 uids: list[str] 

4078 """UIDs to search for.""" 

4079 

4080 

4081class SearchResult(Data): 

4082 """Search result.""" 

4083 

4084 feature: 'Feature' 

4085 layer: 'Layer' 

4086 finder: 'Finder' 

4087 

4088 

4089class TextSearchType(Enum): 

4090 """Text search type.""" 

4091 

4092 exact = 'exact' 

4093 """Match the whole string.""" 

4094 begin = 'begin' 

4095 """Match the beginning of the string.""" 

4096 end = 'end' 

4097 """Match the end of the string.""" 

4098 any = 'any' 

4099 """Match any substring.""" 

4100 like = 'like' 

4101 """Use the percent sign as a placeholder.""" 

4102 

4103 

4104class TextSearchOptions(Data): 

4105 """Text search options.""" 

4106 

4107 type: TextSearchType 

4108 """Type of the search.""" 

4109 minLength: int = 0 

4110 """Minimal pattern length.""" 

4111 caseSensitive: bool = False 

4112 """Use the case sensitive search.""" 

4113 

4114 

4115class SortOptions(Data): 

4116 """Sort options.""" 

4117 

4118 fieldName: str 

4119 """Field name to sort by.""" 

4120 reverse: bool = False 

4121 """Sort in reverse order.""" 

4122 

4123 

4124class SearchManager(Node): 

4125 """Search Manager.""" 

4126 

4127 def run_search(self, search: 'SearchQuery', user: 'User') -> list['SearchResult']: ... 

4128 

4129 

4130class Finder(Node): 

4131 """Finder object.""" 

4132 

4133 title: str 

4134 category: str 

4135 

4136 supportsFilterSearch: bool = False 

4137 supportsGeometrySearch: bool = False 

4138 supportsKeywordSearch: bool = False 

4139 

4140 withFilter: bool 

4141 withGeometry: bool 

4142 withKeyword: bool 

4143 

4144 templates: list['Template'] 

4145 models: list['Model'] 

4146 sourceLayers: list['SourceLayer'] 

4147 

4148 tolerance: 'UomValue' 

4149 

4150 def run(self, search: SearchQuery, user: 'User', layer: Optional['Layer'] = None) -> list['Feature']: ... 

4151 

4152 def can_run(self, search: SearchQuery, user: 'User') -> bool: ... 

4153################################################################################ 

4154 

4155 

4156################################################################################ 

4157# /base/storage/types.pyinc 

4158 

4159 

4160class StorageManager(Node): 

4161 """Storage manager.""" 

4162 

4163 providers: list['StorageProvider'] 

4164 

4165 def create_provider(self, cfg: Config, **kwargs) -> 'StorageProvider': ... 

4166 

4167 def find_provider(self, uid: Optional[str] = None) -> Optional['StorageProvider']: ... 

4168 

4169 

4170 

4171class StorageRecord(Data): 

4172 """Storage record.""" 

4173 

4174 name: str 

4175 userUid: str 

4176 data: str 

4177 created: int 

4178 updated: int 

4179 

4180 

4181class StorageProvider(Node): 

4182 """Storage provider.""" 

4183 

4184 def list_names(self, category: str) -> list[str]: ... 

4185 

4186 def read(self, category: str, name: str) -> Optional['StorageRecord']: ... 

4187 

4188 def write(self, category: str, name: str, data: str, user_uid: str): ... 

4189 

4190 def delete(self, category: str, name: str): ... 

4191################################################################################ 

4192 

4193 

4194################################################################################ 

4195# /base/template/types.pyinc 

4196 

4197 

4198class TemplateArgs(Data): 

4199 """Template arguments.""" 

4200 

4201 app: 'Application' 

4202 """Application object.""" 

4203 locale: 'Locale' 

4204 """Current locale.""" 

4205 date: 'DateFormatter' 

4206 """Locale-aware date formatter.""" 

4207 time: 'TimeFormatter' 

4208 """Locale-aware time formatter.""" 

4209 number: 'NumberFormatter' 

4210 """Locale-aware number formatter.""" 

4211 

4212 

4213class TemplateRenderInput(Data): 

4214 """Template render input.""" 

4215 

4216 args: dict | Data 

4217 crs: 'Crs' 

4218 dpi: int 

4219 locale: 'Locale' 

4220 maps: list[MapRenderInput] 

4221 mimeOut: str 

4222 notify: Callable 

4223 project: 'Project' 

4224 user: 'User' 

4225 

4226 

4227class TemplateQualityLevel(Data): 

4228 """Template quality level.""" 

4229 

4230 name: str 

4231 """Quality level name.""" 

4232 dpi: int 

4233 """DPI for the quality level.""" 

4234 

4235 

4236class Template(Node): 

4237 """Template object.""" 

4238 

4239 mapSize: UomSize 

4240 """Default map size for the template.""" 

4241 mimeTypes: list[str] 

4242 """MIME types the template can generate.""" 

4243 pageSize: UomSize 

4244 """Default page size for printing.""" 

4245 pageMargin: UomExtent 

4246 """Default page margin for printing.""" 

4247 subject: str 

4248 """Template subject (category).""" 

4249 title: str 

4250 """Template title.""" 

4251 

4252 def render(self, tri: TemplateRenderInput) -> ContentResponse: 

4253 """Render the template and return the generated response.""" 

4254 

4255 

4256class TemplateManager(Node): 

4257 """Template manager.""" 

4258 

4259 def find_templates(self, subjects: list[str], where: list[Node], user: 'User' = None, mime: str = None) -> list['Template']: ... 

4260 

4261 def find_template(self, subject: str, where: list[Node], user: 'User' = None, mime: str = None) -> Optional['Template']: ... 

4262 

4263 def template_from_path(self, path: str) -> Optional['Template']: ... 

4264################################################################################ 

4265 

4266 

4267################################################################################ 

4268# /base/web/types.pyinc 

4269 

4270 

4271class RequestMethod(Enum): 

4272 """Web request method.""" 

4273 

4274 GET = 'GET' 

4275 HEAD = 'HEAD' 

4276 POST = 'POST' 

4277 PUT = 'PUT' 

4278 DELETE = 'DELETE' 

4279 CONNECT = 'CONNECT' 

4280 OPTIONS = 'OPTIONS' 

4281 TRACE = 'TRACE' 

4282 PATCH = 'PATCH' 

4283 

4284 

4285class WebRequester: 

4286 """Web Requester object.""" 

4287 

4288 environ: dict 

4289 """Request environment.""" 

4290 method: RequestMethod 

4291 """Request method.""" 

4292 contentType: str 

4293 """Request content type.""" 

4294 root: 'Root' 

4295 """Object tree root.""" 

4296 site: 'WebSite' 

4297 """Website the request is processed for.""" 

4298 

4299 session: 'AuthSession' 

4300 """Current session.""" 

4301 user: 'User' 

4302 """Current use.""" 

4303 

4304 isGet: bool 

4305 """The request is a GET request.""" 

4306 isPost: bool 

4307 """The request is a POST request.""" 

4308 isApi: bool 

4309 """The request provides json data in the POST body.""" 

4310 isForm: bool 

4311 """The request provides form data in the POST body.""" 

4312 isSecure: bool 

4313 """The request is secure.""" 

4314 

4315 def parse(self): 

4316 """Parse the request data, raise an error if the request is invalid.""" 

4317 

4318 def params(self) -> dict: 

4319 """GET parameters, including parsed path params.""" 

4320 

4321 def query_params(self) -> dict: 

4322 """GET parameters from the query string.""" 

4323 

4324 def path(self) -> str: 

4325 """Request path, after the command is removed.""" 

4326 

4327 def struct(self) -> dict: 

4328 """Structured JSON payload.""" 

4329 

4330 def command(self) -> str: 

4331 """Command name from the request.""" 

4332 

4333 def data(self) -> bytes: 

4334 """Raw POST data.""" 

4335 

4336 def form(self) -> list[tuple[str, Any]]: 

4337 """POST form data as a list of (key, value) tuples.""" 

4338 

4339 def text(self) -> str: 

4340 """POST data decoded to text.""" 

4341 

4342 def cookie(self, key: str, default: str = '') -> str: 

4343 """Get a cookie. 

4344 

4345 Args: 

4346 key: Cookie name. 

4347 default: Default value. 

4348 

4349 Returns: 

4350 A cookie value. 

4351 """ 

4352 

4353 def header(self, key: str, default: str = '') -> str: 

4354 """Get a header. 

4355 

4356 Args: 

4357 key: Header name. 

4358 default: Default value. 

4359 

4360 Returns: 

4361 A header value. 

4362 """ 

4363 

4364 def has_param(self, key: str) -> bool: 

4365 """Check if a GET parameter exists. 

4366 

4367 Args: 

4368 key: Parameter name. 

4369 """ 

4370 

4371 def param(self, key: str, default: str = '') -> str: 

4372 """Get a GET parameter. 

4373 

4374 Args: 

4375 key: Parameter name. 

4376 default: Default value. 

4377 

4378 Returns: 

4379 A parameter value. 

4380 """ 

4381 

4382 def env(self, key: str, default: str = '') -> str: 

4383 """Get an environment variable. 

4384 

4385 Args: 

4386 key: Variable name. 

4387 default: Default value. 

4388 

4389 Returns: 

4390 A variable value. 

4391 """ 

4392 

4393 def content_responder(self, response: ContentResponse) -> 'WebResponder': 

4394 """Return a Responder object for a content response. 

4395 

4396 Args: 

4397 response: Response object. 

4398 

4399 Returns: 

4400 A Responder. 

4401 """ 

4402 

4403 def redirect_responder(self, response: RedirectResponse) -> 'WebResponder': 

4404 """Return a Responder object for a redirect response. 

4405 

4406 Args: 

4407 response: Response object. 

4408 

4409 Returns: 

4410 A Responder. 

4411 """ 

4412 

4413 def api_responder(self, response: Response) -> 'WebResponder': 

4414 """Return a Responder object for an Api (structured) response. 

4415 

4416 Args: 

4417 response: Response object. 

4418 

4419 Returns: 

4420 A Responder. 

4421 """ 

4422 

4423 def error_responder(self, exc: Exception) -> 'WebResponder': 

4424 """Return a Responder object for an Exception. 

4425 

4426 Args: 

4427 exc: An Exception. 

4428 

4429 Returns: 

4430 A Responder. 

4431 """ 

4432 

4433 def url_for(self, request_path: str, **kwargs) -> str: 

4434 """Return a canonical Url for the given request path. 

4435 

4436 Args: 

4437 request_path: Request path. 

4438 **kwargs: Additional GET parameters. 

4439 

4440 Returns: 

4441 An URL. 

4442 """ 

4443 

4444 def set_session(self, session: 'AuthSession'): 

4445 """Attach a session to the requester. 

4446 

4447 Args: 

4448 session: A Session object. 

4449 """ 

4450 

4451 

4452class WebResponder: 

4453 """Web Responder object.""" 

4454 

4455 status: int 

4456 """Response status.""" 

4457 

4458 def send_response(self, environ: dict, start_response: Callable): 

4459 """Send the response to the client. 

4460 

4461 Args: 

4462 environ: WSGI environment. 

4463 start_response: WSGI ``start_response`` function. 

4464 """ 

4465 

4466 def set_cookie(self, key: str, value: str, **kwargs): 

4467 """Set a cookie. 

4468 

4469 Args: 

4470 key: Cookie name. 

4471 value: Cookie value. 

4472 **kwargs: Cookie options. 

4473 """ 

4474 

4475 def delete_cookie(self, key: str, **kwargs): 

4476 """Delete a cookie. 

4477 

4478 Args: 

4479 key: Cookie name. 

4480 **kwargs: Cookie options. 

4481 """ 

4482 

4483 def set_status(self, status: int): 

4484 """Set the response status. 

4485 

4486 Args: 

4487 status: HTTP status code. 

4488 """ 

4489 

4490 def add_header(self, key: str, value: str): 

4491 """Add a header. 

4492 

4493 Args: 

4494 key: Header name. 

4495 value: Header value. 

4496 """ 

4497 

4498 def set_body(self, body: str | bytes): 

4499 """Set the response body. 

4500 

4501 Args: 

4502 body: New response body. 

4503 """ 

4504 

4505 

4506class WebDocumentRoot(Data): 

4507 """Web document root.""" 

4508 

4509 dir: DirPath 

4510 """Local directory.""" 

4511 allowMime: list[str] 

4512 """Allowed mime types.""" 

4513 denyMime: list[str] 

4514 """Restricted mime types.""" 

4515 

4516 

4517class WebRewriteRule(Data): 

4518 """Rewrite rule.""" 

4519 

4520 pattern: Regex 

4521 """URL matching pattern.""" 

4522 target: str 

4523 """Rule target, with dollar placeholders.""" 

4524 options: dict 

4525 """Extra options.""" 

4526 reversed: bool 

4527 """Reversed rewrite rule.""" 

4528 

4529 

4530class WebCors(Data): 

4531 """CORS options.""" 

4532 

4533 allowCredentials: bool 

4534 allowHeaders: str 

4535 allowMethods: str 

4536 allowOrigin: str 

4537 

4538 

4539class WebManager(Node): 

4540 """Web manager.""" 

4541 

4542 sites: list['WebSite'] 

4543 """Configured web sites.""" 

4544 

4545 def site_from_environ(self, environ: dict) -> 'WebSite': 

4546 """Returns a site object for the given request environment. 

4547 

4548 Args: 

4549 environ: WSGI environment. 

4550 

4551 Returns: 

4552 A Site object. 

4553 """ 

4554 

4555 

4556class WebSite(Node): 

4557 """Web site.""" 

4558 

4559 assetsRoot: Optional[WebDocumentRoot] 

4560 """Root directory for assets.""" 

4561 corsOptions: WebCors 

4562 """CORS options.""" 

4563 errorPage: Optional['Template'] 

4564 """Error page template.""" 

4565 host: str 

4566 """Host name for this site.""" 

4567 rewriteRules: list[WebRewriteRule] 

4568 """Rewrite rule.""" 

4569 staticRoot: WebDocumentRoot 

4570 """Root directory for static files.""" 

4571 

4572 def url_for(self, req: 'WebRequester', path: str, **kwargs) -> str: 

4573 """Rewrite a request path to an Url. 

4574 

4575 Args: 

4576 req: Web Requester. 

4577 path: Raw request path. 

4578 **kwargs: Extra GET params. 

4579 

4580 Returns: 

4581 A rewritten URL. 

4582 """ 

4583 

4584 def match_host(self, environ: dict) -> bool: 

4585 """Check if the site matches the request host. 

4586 

4587 Args: 

4588 environ: WSGI environment. 

4589 Returns: 

4590 True if the site matches the request host. 

4591 """ 

4592################################################################################ 

4593 

4594 

4595 

4596################################################################################ 

4597# /base/application/types.pyinc 

4598 

4599 

4600class MiddlewareManager(Node): 

4601 """Manage middleware and their dependencies.""" 

4602 

4603 def register(self, obj: Node, name: str, depends_on: Optional[list[str]] = None): 

4604 """Register an object as a middleware.""" 

4605 

4606 def objects(self) -> list[Node]: 

4607 """Return a list of registered middleware objects.""" 

4608 

4609 

4610class Application(Node): 

4611 """Main Application object.""" 

4612 

4613 client: 'Client' 

4614 """Represents the client object associated with the application.""" 

4615 

4616 localeUids: list[str] 

4617 """List of locale identifiers.""" 

4618 

4619 metadata: 'Metadata' 

4620 """Metadata for the application.""" 

4621 

4622 monitor: 'ServerMonitor' 

4623 """Server monitor object.""" 

4624 

4625 vars: dict 

4626 """Application variables.""" 

4627 

4628 version: str 

4629 """Application version as a string.""" 

4630 

4631 versionString: str 

4632 """Full version string for display purposes.""" 

4633 

4634 defaultPrinter: 'Printer' 

4635 """Default printer object.""" 

4636 

4637 actionMgr: 'ActionManager' 

4638 """Manager for application actions.""" 

4639 

4640 authMgr: 'AuthManager' 

4641 """Manager for authentication operations.""" 

4642 

4643 databaseMgr: 'DatabaseManager' 

4644 """Manager for database operations.""" 

4645 

4646 jobMgr: 'JobManager' 

4647 """Manager for handling jobs.""" 

4648 

4649 middlewareMgr: 'MiddlewareManager' 

4650 """Manager for middleware and dependencies.""" 

4651 

4652 modelMgr: 'ModelManager' 

4653 """Manager for model operations.""" 

4654 

4655 printerMgr: 'PrinterManager' 

4656 """Manager for printers.""" 

4657 

4658 searchMgr: 'SearchManager' 

4659 """Manager for search functionality.""" 

4660 

4661 serverMgr: 'ServerManager' 

4662 """Manager for server operations.""" 

4663 

4664 storageMgr: 'StorageManager' 

4665 """Manager for storage operations.""" 

4666 

4667 templateMgr: 'TemplateManager' 

4668 """Manager for templates.""" 

4669 

4670 webMgr: 'WebManager' 

4671 """Manager for web operations.""" 

4672 

4673 actions: list['Action'] 

4674 """List of defined application actions.""" 

4675 

4676 projects: list['Project'] 

4677 """List of configured projects.""" 

4678 

4679 finders: list['Finder'] 

4680 """List of finder objects.""" 

4681 

4682 templates: list['Template'] 

4683 """List of global templates.""" 

4684 

4685 printers: list['Printer'] 

4686 """List of global printer objects.""" 

4687 

4688 models: list['Model'] 

4689 """List of global models.""" 

4690 

4691 owsServices: list['OwsService'] 

4692 """List of OWS services.""" 

4693 

4694 def project(self, uid: str) -> Optional['Project']: 

4695 """Get a Project object by its uid.""" 

4696 

4697 def helper(self, ext_type: str) -> Optional['Node']: 

4698 """Get a Helper object by its extension type.""" 

4699 

4700 def developer_option(self, key: str): 

4701 """Get a value of a developer option.""" 

4702################################################################################