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

1989 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-16 22:59 +0200

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 

29 

30if TYPE_CHECKING: 

31 import datetime 

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 asAttachment: bool 

303 """Serve the content as an attachment.""" 

304 attachmentName: str 

305 """Name for the attachment.""" 

306 content: bytes | str 

307 """Response content.""" 

308 contentPath: str 

309 """Local path with the content.""" 

310 mime: str 

311 """Response mime type.""" 

312 headers: dict 

313 """Additional headers.""" 

314 

315 

316class RedirectResponse(Response): 

317 """Web redirect response.""" 

318 

319 location: str 

320 """Redirect URL.""" 

321 headers: dict 

322 """Additional headers.""" 

323 

324 

325class AttributeType(Enum): 

326 """Feature attribute type.""" 

327 

328 bool = 'bool' 

329 """Boolean value.""" 

330 bytes = 'bytes' 

331 """Binary data.""" 

332 date = 'date' 

333 """Date value.""" 

334 datetime = 'datetime' 

335 """Date and time value.""" 

336 feature = 'feature' 

337 """Feature reference.""" 

338 featurelist = 'featurelist' 

339 """List of features.""" 

340 file = 'file' 

341 """File reference.""" 

342 float = 'float' 

343 """Floating-point number.""" 

344 floatlist = 'floatlist' 

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

346 geometry = 'geometry' 

347 """Geometry reference.""" 

348 int = 'int' 

349 """Integer number.""" 

350 intlist = 'intlist' 

351 """List of integer numbers.""" 

352 str = 'str' 

353 """String value.""" 

354 strlist = 'strlist' 

355 """List of strings.""" 

356 time = 'time' 

357 """Time value.""" 

358 

359 

360class GeometryType(Enum): 

361 """Feature geometry type. 

362 

363 OGC and SQL/MM geometry types. 

364 

365 References: 

366 

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

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

369 """ 

370 

371 geometry = 'geometry' 

372 

373 point = 'point' 

374 curve = 'curve' 

375 surface = 'surface' 

376 

377 geometrycollection = 'geometrycollection' 

378 

379 linestring = 'linestring' 

380 line = 'line' 

381 linearring = 'linearring' 

382 

383 polygon = 'polygon' 

384 triangle = 'triangle' 

385 

386 polyhedralsurface = 'polyhedralsurface' 

387 tin = 'tin' 

388 

389 multipoint = 'multipoint' 

390 multicurve = 'multicurve' 

391 multilinestring = 'multilinestring' 

392 multipolygon = 'multipolygon' 

393 multisurface = 'multisurface' 

394 

395 circularstring = 'circularstring' 

396 compoundcurve = 'compoundcurve' 

397 curvepolygon = 'curvepolygon' 

398 

399 

400class CliParams(Data): 

401 """CLI params""" 

402 pass 

403################################################################################ 

404 

405 

406################################################################################ 

407# /core/_access.pyinc 

408 

409 

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

411"""Access Control list. 

412 

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

414""" 

415 

416AclStr: TypeAlias = str 

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

418 

419 

420class Access(Enum): 

421 """Access mode.""" 

422 

423 read = 'read' 

424 """Permission to read the object.""" 

425 write = 'write' 

426 """Permission to change the object.""" 

427 create = 'create' 

428 """Permission to create new objects.""" 

429 delete = 'delete' 

430 """Permission to delete objects.""" 

431 

432 

433class PermissionsConfig: 

434 """Permissions configuration.""" 

435 

436 all: Optional[AclStr] 

437 """All permissions.""" 

438 read: Optional[AclStr] 

439 """Permission to read the object.""" 

440 write: Optional[AclStr] 

441 """Permission to change the object.""" 

442 create: Optional[AclStr] 

443 """Permission to create new objects.""" 

444 delete: Optional[AclStr] 

445 """Permission to delete objects.""" 

446 edit: Optional[AclStr] 

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

448 

449 

450class ConfigWithAccess(Config): 

451 """Basic config with permissions.""" 

452 

453 access: Optional[AclStr] 

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

455 permissions: Optional[PermissionsConfig] 

456 """Access permissions.""" 

457################################################################################ 

458 

459 

460################################################################################ 

461# /core/_error.pyinc 

462 

463 

464"""App Error object""" 

465 

466class Error(Exception): 

467 """Generic GWS error.""" 

468 def __repr__(self): 

469 return log.exception_backtrace(self)[0] 

470 

471 

472class ConfigurationError(Error): 

473 """GWS Configuration error.""" 

474 pass 

475 

476 

477class NotFoundError(Error): 

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

479 pass 

480 

481 

482class ForbiddenError(Error): 

483 """Generic 'forbidden' error.""" 

484 pass 

485 

486 

487class BadRequestError(Error): 

488 """Generic 'bad request' error.""" 

489 pass 

490 

491 

492class ResponseTooLargeError(Error): 

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

494 pass 

495################################################################################ 

496 

497 

498 

499################################################################################ 

500# /spec/types.pyinc 

501 

502 

503class ApplicationManifestPlugin(Data): 

504 """Plugin description.""" 

505 

506 path: DirPath 

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

508 

509 name: str = '' 

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

511 

512 

513class ApplicationManifest(Data): 

514 """Application manifest.""" 

515 

516 excludePlugins: Optional[list[str]] 

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

518 plugins: Optional[list[ApplicationManifestPlugin]] 

519 """Custom plugins.""" 

520 locales: list[str] 

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

522 tsConfig: list[str] 

523 """Path to tsconfig.json.""" 

524 withFallbackConfig: bool = False 

525 """Use a minimal fallback configuration.""" 

526 withStrictConfig: bool = False 

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

528 

529 

530class ExtObjectDescriptor(Data): 

531 """Extension object descriptor.""" 

532 

533 extName: str 

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

535 extType: str 

536 """Extension type like ``wms``.""" 

537 classPtr: type 

538 """Class object.""" 

539 ident: str 

540 """Identifier.""" 

541 modName: str 

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

543 modPath: str 

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

545 

546 

547class ExtCommandDescriptor(Data): 

548 """ 

549 Represents a command descriptor for an extension. 

550 

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

552 """ 

553 extName: str 

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

555 extType: str 

556 """Extension type like ``wms``.""" 

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 

600 

601class SpecRuntime: 

602 """Specification runtime.""" 

603 

604 version: str 

605 """Application version.""" 

606 manifest: ApplicationManifest 

607 """Application manifest.""" 

608 appBundlePaths: list[str] 

609 """List of client bundle paths.""" 

610 

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

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

613 

614 Args: 

615 value: Raw value from config or request. 

616 type_name: Object type name. 

617 path: Config file path. 

618 options: Read options. 

619 

620 Returns: 

621 A parsed object. 

622 """ 

623 

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

625 """Get an object descriptor. 

626 

627 Args: 

628 type_name: Object type name. 

629 

630 Returns: 

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

632 """ 

633 

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

635 """Get a command descriptor. 

636 

637 Args: 

638 command_category: Command category. 

639 command_name: Command name. 

640 

641 Returns: 

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

643 """ 

644 

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

646 """Dynamically register an extension object.""" 

647 

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

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

650 

651 Args: 

652 classref: Class reference. 

653 ext_type: Extension type. 

654 

655 Returns: 

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

657 """ 

658 

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

660 """Parse a class reference. 

661 

662 Args: 

663 classref: Class reference. 

664 

665 Returns: 

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

667 """ 

668################################################################################ 

669 

670 

671 

672################################################################################ 

673# /core/_tree.pyinc 

674 

675 

676class Object: 

677 """Basic GWS object.""" 

678 

679 permissions: dict[Access, Acl] 

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

681 

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

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

684 

685 Args: 

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

687 """ 

688 

689 def __init__(self): 

690 self.permissions = {} 

691 

692 

693from .core import tree_impl 

694 

695setattr(tree_impl, 'Access', Access) 

696setattr(tree_impl, 'Error', Error) 

697setattr(tree_impl, 'ConfigurationError', ConfigurationError) 

698setattr(tree_impl, 'Data', Data) 

699setattr(tree_impl, 'Props', Props) 

700setattr(tree_impl, 'Object', Object) 

701 

702Object.__repr__ = tree_impl.object_repr 

703 

704 

705class Node(Object): 

706 """GWS object tree node.""" 

707 

708 extName: str 

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

710 extType: str 

711 """Extension type like ``wms``.""" 

712 

713 config: Config 

714 """Configuration for this object.""" 

715 root: 'Root' 

716 """Root object.""" 

717 parent: 'Node' 

718 """Parent object.""" 

719 children: list['Node'] 

720 """Child objects.""" 

721 uid: str 

722 """Unique ID.""" 

723 

724 def initialize(self, config): 

725 return tree_impl.node_initialize(self, config) 

726 

727 def pre_configure(self): 

728 """Pre-configuration hook.""" 

729 

730 def configure(self): 

731 """Configuration hook.""" 

732 

733 def post_configure(self): 

734 """Post-configuration hook.""" 

735 

736 def activate(self): 

737 """Activation hook.""" 

738 

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

740 """Create a child object. 

741 

742 Args: 

743 classref: Class reference. 

744 config: Configuration. 

745 **kwargs: Additional configuration properties. 

746 

747 Returns: 

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

749 """ 

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

751 

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

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

754 

755 Args: 

756 classref: Class reference. 

757 config: Configuration. 

758 **kwargs: Additional configuration properties. 

759 

760 Returns: 

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

762 """ 

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

764 

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

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

767 

768 Args: 

769 classref: Class reference. 

770 configs: List of configurations. 

771 **kwargs: Additional configuration properties. 

772 

773 Returns: 

774 A list of newly created objects. 

775 """ 

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

777 

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

779 """Fetch a configuration property. 

780 

781 Args: 

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

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

784 

785 Returns: 

786 A property value. 

787 """ 

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

789 

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

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

792 

793 Args: 

794 classref: Class reference. 

795 

796 Returns: 

797 A boolean. 

798 """ 

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

800 

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

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

803 

804 Args: 

805 classref: Class reference. 

806 

807 Returns: 

808 A list of objects. 

809 """ 

810 return tree_impl.node_find_all(self, classref) 

811 

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

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

814 

815 Args: 

816 classref: Class reference. 

817 

818 Returns: 

819 An object or ``None``. 

820 """ 

821 return tree_impl.node_find_first(self, classref) 

822 

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

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

825 

826 Args: 

827 classref: Class reference. 

828 

829 Returns: 

830 An object or ``None``. 

831 """ 

832 

833 return tree_impl.node_find_closest(self, classref) 

834 

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

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

837 

838 Args: 

839 classref: Class reference. 

840 

841 Returns: 

842 A list of objects. 

843 """ 

844 return tree_impl.node_find_ancestors(self, classref) 

845 

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

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

848 

849 Args: 

850 classref: Class reference. 

851 

852 Returns: 

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

854 """ 

855 

856 return tree_impl.node_find_descendants(self, classref) 

857 

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

859 """Begin middleware processing. 

860 

861 Args: 

862 req: Requester object. 

863 

864 Returns: 

865 A Responder object or ``None``. 

866 """ 

867 

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

869 """Finish middleware processing. 

870 

871 Args: 

872 req: Requester object. 

873 res: Current responder object. 

874 """ 

875 

876 def periodic_task(self): 

877 """Periodic task hook.""" 

878 

879 

880class Root: 

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

882 

883 app: 'Application' 

884 """Application object.""" 

885 specs: 'SpecRuntime' 

886 """Specs runtime.""" 

887 configErrors: list 

888 """List of configuration errors.""" 

889 

890 nodes: list['Node'] 

891 uidMap: dict[str, 'Node'] 

892 uidCount: int 

893 configStack: list['Node'] 

894 configPaths: list[str] 

895 

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

897 tree_impl.root_init(self, specs) 

898 

899 def initialize(self, obj, config): 

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

901 

902 def post_initialize(self): 

903 """Post-initialization hook.""" 

904 return tree_impl.root_post_initialize(self) 

905 

906 def activate(self): 

907 return tree_impl.root_activate(self) 

908 

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

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

911 

912 Args: 

913 classref: Class reference. 

914 

915 Returns: 

916 A list of objects. 

917 """ 

918 return tree_impl.root_find_all(self, classref) 

919 

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

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

922 

923 Args: 

924 classref: Class reference. 

925 

926 Returns: 

927 An object or ``None``. 

928 """ 

929 return tree_impl.root_find_first(self, classref) 

930 

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

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

933 

934 Args: 

935 uid: Object uid. 

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

937 

938 Returns: 

939 An object or ``None``. 

940 """ 

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

942 

943 def object_count(self) -> int: 

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

945 return tree_impl.root_object_count(self) 

946 

947 def create( 

948 self, 

949 classref: ClassRef, 

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

951 config: Config = None, 

952 **kwargs, 

953 ) -> Optional['Node']: 

954 """Create an object. 

955 

956 Args: 

957 classref: Class reference. 

958 parent: Parent object. 

959 config: Configuration. 

960 **kwargs: Additional configuration properties. 

961 

962 Returns: 

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

964 """ 

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

966 

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

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

969 

970 Args: 

971 classref: Class reference. 

972 config: Configuration. 

973 **kwargs: Additional configuration properties. 

974 

975 Returns: 

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

977 """ 

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

979 

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

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

982 

983 Args: 

984 classref: Class reference. 

985 config: Configuration. 

986 **kwargs: Additional configuration properties. 

987 

988 Returns: 

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

990 """ 

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

992 

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

994 """Create the Application object. 

995 

996 Args: 

997 config: Configuration. 

998 **kwargs: Additional configuration properties. 

999 

1000 Returns: 

1001 The Application object. 

1002 """ 

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

1004 

1005 

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

1007 return Root(specs) 

1008 

1009 

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

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

1012################################################################################ 

1013 

1014 

1015 

1016################################################################################ 

1017# /lib/mime/types.pyinc 

1018 

1019 

1020MimeType: TypeAlias = str 

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

1022################################################################################ 

1023 

1024 

1025################################################################################ 

1026# /lib/uom/types.pyinc 

1027 

1028 

1029class Uom(Enum): 

1030 """Unit of measure.""" 

1031 

1032 mi = 'mi' 

1033 """statute mile (EPSG 9093)""" 

1034 us_ch = 'us-ch' 

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

1036 us_ft = 'us-ft' 

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

1038 us_in = 'us-in' 

1039 """us survey inch us_in""" 

1040 us_mi = 'us-mi' 

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

1042 us_yd = 'us-yd' 

1043 """us survey yard us_yd""" 

1044 cm = 'cm' 

1045 """centimetre (EPSG 1033)""" 

1046 ch = 'ch' 

1047 """chain (EPSG 9097)""" 

1048 dm = 'dm' 

1049 """decimeter dm""" 

1050 deg = 'deg' 

1051 """degree (EPSG 9102)""" 

1052 fath = 'fath' 

1053 """fathom (EPSG 9014)""" 

1054 ft = 'ft' 

1055 """foot (EPSG 9002)""" 

1056 grad = 'grad' 

1057 """grad (EPSG 9105)""" 

1058 inch = 'in' 

1059 """inch in""" 

1060 km = 'km' 

1061 """kilometre (EPSG 9036)""" 

1062 link = 'link' 

1063 """link (EPSG 9098)""" 

1064 m = 'm' 

1065 """metre (EPSG 9001)""" 

1066 mm = 'mm' 

1067 """millimetre (EPSG 1025)""" 

1068 kmi = 'kmi' 

1069 """nautical mile (EPSG 9030)""" 

1070 rad = 'rad' 

1071 """radian (EPSG 9101)""" 

1072 yd = 'yd' 

1073 """yard (EPSG 9096)""" 

1074 px = 'px' 

1075 """pixel""" 

1076 pt = 'pt' 

1077 """point""" 

1078 

1079 

1080UomValue: TypeAlias = tuple[float, Uom] 

1081"""A value with a unit.""" 

1082 

1083UomValueStr: TypeAlias = str 

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

1085 

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

1087"""A Point with a unit.""" 

1088 

1089UomPointStr: TypeAlias = list[str] 

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

1091 

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

1093"""A Size with a unit.""" 

1094 

1095UomSizeStr: TypeAlias = list[str] 

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

1097 

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

1099"""Extent with a unit.""" 

1100 

1101UomExtentStr: TypeAlias = list[str] 

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

1103################################################################################ 

1104 

1105 

1106################################################################################ 

1107# /lib/image/types.pyinc 

1108 

1109 

1110class ImageFormat(Data): 

1111 """Image format""" 

1112 

1113 mimeTypes: list[str] 

1114 """Mime types for this format.""" 

1115 options: dict 

1116 """Image options.""" 

1117 

1118 

1119class Image: 

1120 """Image object.""" 

1121 

1122 def size(self) -> Size: 

1123 """Get the image size. 

1124 

1125 Returns: 

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

1127 """ 

1128 

1129 def mode(self) -> str: 

1130 """Get the image mode. 

1131 

1132 Returns: 

1133 PIL image mode. 

1134 """ 

1135 

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

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

1138 

1139 Args: 

1140 color: Color of the box's lines. 

1141 

1142 Returns: 

1143 The image with a box around the edges. 

1144 """ 

1145 

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

1147 """Adds text to an image object. 

1148 

1149 Args: 

1150 text: Text to be displayed. 

1151 

1152 x: x-coordinate. 

1153 

1154 y: y-coordinate. 

1155 

1156 color: Color of the text. 

1157 

1158 Returns: 

1159 The image object with the text displayed. 

1160 """ 

1161 

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

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

1164 

1165 Args: 

1166 other: Image to place on top. 

1167 opacity: other image's opacity. 

1168 

1169 Returns: 

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

1171 """ 

1172 

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

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

1175 

1176 Args: 

1177 box: `(width, height)` 

1178 

1179 Returns: 

1180 The cropped image object. 

1181 """ 

1182 

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

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

1185 

1186 Args: 

1187 other: Image that will be placed. 

1188 

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

1190 

1191 Returns: 

1192 The image object with the other image placed inside. 

1193 """ 

1194 

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

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

1197 

1198 Args: 

1199 size: `(width, height)` 

1200 

1201 Returns: 

1202 The resized image object. 

1203 """ 

1204 

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

1206 """Rotates the image. 

1207 

1208 Args: 

1209 angle: Angle to rotate the image. 

1210 

1211 Returns: 

1212 The rotated image object. 

1213 """ 

1214 

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

1216 """Converts the image object to bytes. 

1217 

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

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

1220 

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

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

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

1224 

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

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

1227 

1228 Args: 

1229 mime: The mime type. 

1230 options: A dict of options. 

1231 

1232 Returns: 

1233 The image as bytes. 

1234 """ 

1235 

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

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

1238 

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

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

1241 

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

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

1244 

1245 Args: 

1246 path: Image's path location. 

1247 mime: The mime type. 

1248 options: A dict of options. 

1249 

1250 Returns: 

1251 The path to the image. 

1252 """ 

1253 

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

1255 """Converts the image to an array. 

1256 

1257 Returns: 

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

1259 """ 

1260 

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

1262 """Compare this image to another one. 

1263 

1264 @TODO describe the alogrithm 

1265 

1266 Returns: 

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

1268 '0' means images are equal. 

1269 """ 

1270################################################################################ 

1271 

1272 

1273################################################################################ 

1274# /lib/intl/types.pyinc 

1275 

1276 

1277LocaleUid: TypeAlias = str 

1278"""Locale uid like `de_DE`.""" 

1279 

1280 

1281class Locale(Data): 

1282 """Locale data.""" 

1283 

1284 uid: str 

1285 dateFormatLong: str 

1286 dateFormatMedium: str 

1287 dateFormatShort: str 

1288 dateUnits: str 

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

1290 dayNamesLong: list[str] 

1291 dayNamesShort: list[str] 

1292 dayNamesNarrow: list[str] 

1293 firstWeekDay: int 

1294 

1295 language: str 

1296 """Language code: ``de``""" 

1297 language3: str 

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

1299 languageBib: str 

1300 """Bibliographic language code..""" 

1301 languageName: str 

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

1303 languageNameEn: str 

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

1305 

1306 territory: str 

1307 territoryName: str 

1308 monthNamesLong: list[str] 

1309 monthNamesShort: list[str] 

1310 monthNamesNarrow: list[str] 

1311 numberDecimal: str 

1312 numberGroup: str 

1313 

1314 

1315class DateTimeFormat(Enum): 

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

1317 short = 'short' 

1318 """Local short format.""" 

1319 medium = 'medium' 

1320 """Local medium format.""" 

1321 long = 'long' 

1322 """Local long format.""" 

1323 iso = 'iso' 

1324 """ISO 8601 format.""" 

1325 

1326 

1327class NumberFormat(Enum): 

1328 """Enumeration indicating the number format.""" 

1329 decimal = 'decimal' 

1330 """Locale decimal format.""" 

1331 grouped = 'grouped' 

1332 """Locale grouped format.""" 

1333 currency = 'currency' 

1334 """Locale currency format""" 

1335 percent = 'percent' 

1336 """Locale percent format.""" 

1337 

1338 

1339class DateFormatter: 

1340 """Locale-aware date formatter.""" 

1341 

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

1343 """Formats the date. 

1344 

1345 Args: 

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

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

1348 

1349 Returns: 

1350 A formatted date string. 

1351 """ 

1352 

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

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

1355 

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

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

1358 

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

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

1361 

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

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

1364 

1365 

1366class TimeFormatter: 

1367 """Locale-aware time formatter.""" 

1368 

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

1370 """Formats the time. 

1371 

1372 Args: 

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

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

1375 

1376 Returns: 

1377 A formatted time string. 

1378 """ 

1379 

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

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

1382 

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

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

1385 

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

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

1388 

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

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

1391 

1392 

1393class NumberFormatter: 

1394 """Locale-aware number formatter.""" 

1395 

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

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

1398 

1399 Args: 

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

1401 n: Number. 

1402 kwargs: Passes the currency parameter forward. 

1403 

1404 Returns: 

1405 A formatted number. 

1406 """ 

1407 

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

1409 """Returns formatted decimal value.""" 

1410 

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

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

1413 

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

1415 """Returns formatted currency value.""" 

1416 

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

1418 """Returns formatted percent value.""" 

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

1420 

1421 

1422################################################################################ 

1423# /lib/style/types.pyinc 

1424 

1425 

1426class StyleValues(Data): 

1427 """CSS Style values.""" 

1428 

1429 fill: Color 

1430 

1431 stroke: Color 

1432 stroke_dasharray: list[int] 

1433 stroke_dashoffset: int 

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

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

1436 stroke_miterlimit: int 

1437 stroke_width: int 

1438 

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

1440 marker_fill: Color 

1441 marker_size: int 

1442 marker_stroke: Color 

1443 marker_stroke_dasharray: list[int] 

1444 marker_stroke_dashoffset: int 

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

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

1447 marker_stroke_miterlimit: int 

1448 marker_stroke_width: int 

1449 

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

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

1452 

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

1454 label_background: Color 

1455 label_fill: Color 

1456 label_font_family: str 

1457 label_font_size: int 

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

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

1460 label_line_height: int 

1461 label_max_scale: int 

1462 label_min_scale: int 

1463 label_offset_x: int 

1464 label_offset_y: int 

1465 label_padding: list[int] 

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

1467 label_stroke: Color 

1468 label_stroke_dasharray: list[int] 

1469 label_stroke_dashoffset: int 

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

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

1472 label_stroke_miterlimit: int 

1473 label_stroke_width: int 

1474 

1475 point_size: int 

1476 icon: str 

1477 

1478 offset_x: int 

1479 offset_y: int 

1480 

1481 

1482class StyleProps(Props): 

1483 """CSS Style properties.""" 

1484 

1485 cssSelector: Optional[str] 

1486 text: Optional[str] 

1487 values: Optional[dict] 

1488 

1489 

1490class Style: 

1491 """CSS Style object.""" 

1492 

1493 cssSelector: str 

1494 text: str 

1495 values: StyleValues 

1496################################################################################ 

1497 

1498 

1499################################################################################ 

1500# /lib/xmlx/types.pyinc 

1501 

1502 

1503class XmlNamespace(Data): 

1504 """XML namespace.""" 

1505 

1506 uid: str 

1507 """Unique ID.""" 

1508 xmlns: str 

1509 """Default prefix for this Namespace.""" 

1510 uri: Url 

1511 """Namespace uri.""" 

1512 schemaLocation: Url 

1513 """Namespace schema location.""" 

1514 version: str 

1515 """Namespace version.""" 

1516 isDefault: bool 

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

1518 extendsGml: bool 

1519 """Namespace schema extends the GML3 schema.""" 

1520 

1521 

1522class XmlOptions(Data): 

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

1524 

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

1526 """Mapping of prefixes to namespaces.""" 

1527 

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

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

1530 

1531 defaultNamespace: Optional['XmlNamespace'] = None 

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

1533 

1534 doctype: Optional[str] = None 

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

1536 

1537 compactWhitespace: bool = False 

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

1539 

1540 removeNamespaces: bool = False 

1541 """Remove all namespace references.""" 

1542 

1543 foldTags: bool = False 

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

1545 

1546 withNamespaceDeclarations: bool = False 

1547 """Include the namespace declarations.""" 

1548 

1549 withSchemaLocations: bool = False 

1550 """Include schema locations.""" 

1551 

1552 withXmlDeclaration: bool = False 

1553 """Include the xml declaration.""" 

1554 

1555 

1556class XmlElement(Iterable): 

1557 """XML Element. 

1558 

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

1560 """ 

1561 

1562 tag: str 

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

1564 

1565 text: str 

1566 """Text before first subelement.""" 

1567 

1568 tail: str 

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

1570 

1571 attrib: dict 

1572 """Dictionary of element attributes.""" 

1573 

1574 name: str 

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

1576 

1577 lcName: str 

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

1579 

1580 caseInsensitive: bool 

1581 """Element is case-insensitive.""" 

1582 

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

1584 

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

1586 

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

1588 

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

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

1591 

1592 def clear(self): 

1593 """Resets an element.""" 

1594 

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

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

1597 

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

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

1600 

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

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

1603 

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

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

1606 

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

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

1609 

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

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

1612 

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

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

1615 

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

1617 """Creates a tree iterator.""" 

1618 

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

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

1621 

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

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

1624 

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

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

1627 

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

1629 """Removes the other element from the element.""" 

1630 

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

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

1633 

1634 # extensions 

1635 

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

1637 """Alias for 'get'.""" 

1638 

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

1640 """Check if an attribute exists.""" 

1641 

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

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

1644 

1645 Args: 

1646 tag: XML tag. 

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

1648 """ 

1649 

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

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

1652 

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

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

1655 

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

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

1658 

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

1660 """Collects texts from child elements. 

1661 

1662 Args: 

1663 paths: List of paths to search for. 

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

1665 

1666 Returns: 

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

1668 """ 

1669 

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

1671 """Collects texts from child elements. 

1672 

1673 Args: 

1674 paths: List of paths to search for. 

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

1676 

1677 Returns: 

1678 A dict tag name -> text. 

1679 """ 

1680 

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

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

1683 

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

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

1686 

1687 Args: 

1688 opts: XML options for serialization. 

1689 

1690 Returns: 

1691 An XML string. 

1692 """ 

1693 

1694 def to_dict(self) -> dict: 

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

1696 

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

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

1699 

1700 Args: 

1701 opts: XML options for serialization. 

1702 """ 

1703################################################################################ 

1704 

1705 

1706 

1707################################################################################ 

1708# /lib/crs/types.pyinc 

1709 

1710 

1711CrsName: TypeAlias = int | str 

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

1713 

1714 

1715class CrsFormat(Enum): 

1716 """CRS name format.""" 

1717 

1718 none = '' 

1719 """No format.""" 

1720 crs = 'crs' 

1721 """Like ``crs84``.""" 

1722 srid = 'srid' 

1723 """Like ``3857``.""" 

1724 epsg = 'epsg' 

1725 """Like ``EPSG:3857``.""" 

1726 url = 'url' 

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

1728 uri = 'uri' 

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

1730 urnx = 'urnx' 

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

1732 urn = 'urn' 

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

1734 

1735 

1736class Axis(Enum): 

1737 """Axis orientation.""" 

1738 

1739 xy = 'xy' 

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

1741 yx = 'yx' 

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

1743 

1744 

1745class Bounds(Data): 

1746 """Geo-referenced extent.""" 

1747 

1748 crs: 'Crs' 

1749 extent: Extent 

1750 

1751 

1752class Crs: 

1753 """Coordinate reference system.""" 

1754 

1755 srid: int 

1756 """CRS SRID.""" 

1757 axis: Axis 

1758 """Axis orientation.""" 

1759 uom: Uom 

1760 """CRS unit.""" 

1761 isGeographic: bool 

1762 """This CRS is geographic.""" 

1763 isProjected: bool 

1764 """This CRS is projected.""" 

1765 isYX: bool 

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

1767 proj4text: str 

1768 """Proj4 definition.""" 

1769 wkt: str 

1770 """WKT definition.""" 

1771 

1772 epsg: str 

1773 """Name in the "epsg" format.""" 

1774 urn: str 

1775 """Name in the "urn" format.""" 

1776 urnx: str 

1777 """Name in the "urnx" format.""" 

1778 url: str 

1779 """Name in the "url" format.""" 

1780 uri: str 

1781 """Name in the "uri" format.""" 

1782 

1783 name: str 

1784 """CRS name.""" 

1785 base: int 

1786 """Base CRS code.""" 

1787 datum: str 

1788 """Datum.""" 

1789 

1790 wgsExtent: Extent 

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

1792 extent: Extent 

1793 """CRS own Extent.""" 

1794 bounds: Bounds 

1795 """CRS own Bounds.""" 

1796 

1797 coordinatePrecision: int 

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

1799 

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

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

1802 

1803 We adhere to the GeoServer convention here: 

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

1805 """ 

1806 

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

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

1809 

1810 Args: 

1811 extent: Extent. 

1812 crs_to: Target CRS. 

1813 

1814 Returns: 

1815 A transformed Extent. 

1816 """ 

1817 

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

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

1820 

1821 Args: 

1822 extent: Extent. 

1823 """ 

1824 

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

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

1827 Args: 

1828 xy: Point. 

1829 dist: Distance in meters. 

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

1831 """ 

1832 

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

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

1835 

1836 Args: 

1837 crs_to: Target CRS. 

1838 

1839 Returns: 

1840 A function. 

1841 """ 

1842 

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

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

1845 

1846 Args: 

1847 fmt: Format to use. 

1848 

1849 Returns: 

1850 A string. 

1851 """ 

1852 

1853 def to_geojson(self) -> dict: 

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

1855 

1856 Returns: 

1857 A GeoJson dict. 

1858 

1859 References: 

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

1861 """ 

1862################################################################################ 

1863 

1864 

1865################################################################################ 

1866# /gis/render/types.pyinc 

1867 

1868 

1869class MapView(Data): 

1870 """Map view.""" 

1871 

1872 bounds: Bounds 

1873 center: Point 

1874 rotation: int 

1875 scale: int 

1876 mmSize: Size 

1877 pxSize: Size 

1878 dpi: int 

1879 

1880 

1881class MapRenderInputPlaneType(Enum): 

1882 """Map render input plane type.""" 

1883 

1884 features = 'features' 

1885 image = 'image' 

1886 imageLayer = 'imageLayer' 

1887 svgLayer = 'svgLayer' 

1888 svgSoup = 'svgSoup' 

1889 

1890 

1891class MapRenderInputPlane(Data): 

1892 """Map render input plane.""" 

1893 

1894 type: MapRenderInputPlaneType 

1895 features: list['Feature'] 

1896 image: 'Image' 

1897 layer: 'Layer' 

1898 opacity: float 

1899 soupPoints: list[Point] 

1900 soupTags: list[Any] 

1901 styles: list['Style'] 

1902 compositeLayerUids: list[str] 

1903 

1904 

1905class MapRenderInput(Data): 

1906 """Map render input.""" 

1907 

1908 backgroundColor: int 

1909 bbox: Extent 

1910 center: Point 

1911 crs: 'Crs' 

1912 dpi: int 

1913 mapSize: UomSize 

1914 notify: Callable 

1915 planes: list['MapRenderInputPlane'] 

1916 project: 'Project' 

1917 rotation: int 

1918 scale: int 

1919 user: 'User' 

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

1921 

1922 

1923class MapRenderOutputPlaneType(Enum): 

1924 """Map render output plane type.""" 

1925 

1926 image = 'image' 

1927 path = 'path' 

1928 svg = 'svg' 

1929 

1930 

1931class MapRenderOutputPlane(Data): 

1932 """Map render output plane.""" 

1933 

1934 type: MapRenderOutputPlaneType 

1935 path: str 

1936 elements: list[XmlElement] 

1937 image: 'Image' 

1938 

1939 

1940class MapRenderOutput(Data): 

1941 """Map render output.""" 

1942 

1943 planes: list['MapRenderOutputPlane'] 

1944 view: MapView 

1945 

1946 

1947class LayerRenderInputType(Enum): 

1948 """Layer render input type.""" 

1949 

1950 box = 'box' 

1951 xyz = 'xyz' 

1952 svg = 'svg' 

1953 

1954 

1955class LayerRenderInput(Data): 

1956 """Layer render input.""" 

1957 

1958 extraParams: dict 

1959 project: 'Project' 

1960 style: 'Style' 

1961 type: LayerRenderInputType 

1962 user: 'User' 

1963 view: MapView 

1964 x: int 

1965 y: int 

1966 z: int 

1967 

1968 

1969class LayerRenderOutput(Data): 

1970 """Layer render output.""" 

1971 

1972 content: bytes 

1973 tags: list[XmlElement] 

1974################################################################################ 

1975 

1976 

1977################################################################################ 

1978# /gis/source/types.pyinc 

1979 

1980 

1981class TileMatrix(Data): 

1982 """WMTS TileMatrix object.""" 

1983 

1984 uid: str 

1985 scale: float 

1986 x: float 

1987 y: float 

1988 width: float 

1989 height: float 

1990 tileWidth: float 

1991 tileHeight: float 

1992 extent: Extent 

1993 

1994 

1995class TileMatrixSet(Data): 

1996 """WMTS TileMatrixSet object.""" 

1997 

1998 uid: str 

1999 crs: 'Crs' 

2000 matrices: list[TileMatrix] 

2001 

2002 

2003class SourceStyle(Data): 

2004 """Generic OGC Style.""" 

2005 

2006 isDefault: bool 

2007 legendUrl: Url 

2008 metadata: 'Metadata' 

2009 name: str 

2010 

2011 

2012class SourceLayer(Data): 

2013 """Generic OGC Layer.""" 

2014 

2015 aLevel: int 

2016 aPath: str 

2017 aUid: str 

2018 

2019 dataSource: dict 

2020 metadata: 'Metadata' 

2021 

2022 supportedCrs: list['Crs'] 

2023 wgsExtent: Extent 

2024 

2025 isExpanded: bool 

2026 isGroup: bool 

2027 isImage: bool 

2028 isQueryable: bool 

2029 isVisible: bool 

2030 

2031 layers: list['SourceLayer'] 

2032 

2033 name: str 

2034 title: str 

2035 

2036 legendUrl: Url 

2037 opacity: float 

2038 scaleRange: list[float] 

2039 

2040 styles: list[SourceStyle] 

2041 defaultStyle: Optional[SourceStyle] 

2042 

2043 tileMatrixIds: list[str] 

2044 tileMatrixSets: list[TileMatrixSet] 

2045 imageFormat: str 

2046 resourceUrls: dict 

2047 

2048 sourceId: str 

2049 properties: dict 

2050################################################################################ 

2051 

2052 

2053 

2054################################################################################ 

2055# /config/types.pyinc 

2056 

2057 

2058class ConfigContext(Data): 

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

2060 

2061 specs: SpecRuntime 

2062 readOptions: set[SpecReadOption] 

2063 errors: list 

2064 paths: set[str] 

2065################################################################################ 

2066 

2067 

2068################################################################################ 

2069# /server/types.pyinc 

2070 

2071 

2072class ServerManager(Node): 

2073 """Server configuration manager.""" 

2074 

2075 templates: list['Template'] 

2076 

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

2078 """Create server configuration files.""" 

2079 

2080 

2081class ServerMonitor(Node): 

2082 """File Monitor facility.""" 

2083 

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

2085 """Add a directory to watch. 

2086 

2087 Args: 

2088 path: Directory path. 

2089 pattern: Regex pattern for files to watch. 

2090 recursive: Watch subdirectories. 

2091 """ 

2092 

2093 def watch_file(self, path: str): 

2094 """Add a file to watch. 

2095 

2096 Args: 

2097 path: File path. 

2098 """ 

2099 

2100 def register_periodic_task(self, obj: Node): 

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

2102 

2103 Args: 

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

2105 """ 

2106 

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

2108 """Schedule a system reload. 

2109 

2110 Args: 

2111 with_reconfigure: Reconfigure the server before reloading. 

2112 """ 

2113 

2114 def start(self): 

2115 """Start the monitor.""" 

2116################################################################################ 

2117 

2118 

2119 

2120################################################################################ 

2121# /base/metadata/types.pyinc 

2122 

2123 

2124class MetadataLink(Data): 

2125 about: str 

2126 description: str 

2127 format: str 

2128 formatVersion: str 

2129 function: str 

2130 mimeType: str 

2131 scheme: str 

2132 title: str 

2133 type: str 

2134 url: str 

2135 

2136 

2137class Metadata(Data): 

2138 name: str 

2139 title: str 

2140 

2141 abstract: str 

2142 accessConstraints: str 

2143 accessConstraintsType: str 

2144 attribution: str 

2145 attributionUrl: str 

2146 dateCreated: Optional['datetime.datetime'] 

2147 dateUpdated: Optional['datetime.datetime'] 

2148 fees: str 

2149 image: str 

2150 keywords: list[str] 

2151 license: str 

2152 licenseUrl: str 

2153 

2154 contactAddress: str 

2155 contactAddressType: str 

2156 contactArea: str 

2157 contactCity: str 

2158 contactCountry: str 

2159 contactEmail: str 

2160 contactFax: str 

2161 contactOrganization: str 

2162 contactPerson: str 

2163 contactPhone: str 

2164 contactPosition: str 

2165 contactProviderName: str 

2166 contactProviderSite: str 

2167 contactRole: str 

2168 contactUrl: str 

2169 contactZip: str 

2170 

2171 authorityIdentifier: str 

2172 authorityName: str 

2173 authorityUrl: str 

2174 

2175 metaLinks: list[MetadataLink] 

2176 serviceMetadataURL: str 

2177 

2178 catalogCitationUid: str 

2179 catalogUid: str 

2180 

2181 language: str 

2182 language3: str 

2183 languageBib: str 

2184 languageName: str 

2185 

2186 parentIdentifier: str 

2187 wgsExtent: Optional[Extent] 

2188 crs: Optional['Crs'] 

2189 temporalBegin: Optional['datetime.datetime'] 

2190 temporalEnd: Optional['datetime.datetime'] 

2191 

2192 inspireMandatoryKeyword: str 

2193 inspireDegreeOfConformity: str 

2194 inspireResourceType: str 

2195 inspireSpatialDataServiceType: str 

2196 inspireSpatialScope: str 

2197 inspireSpatialScopeName: str 

2198 inspireTheme: str 

2199 

2200 inspireThemeNameLocal: str 

2201 inspireThemeNameEn: str 

2202 

2203 isoMaintenanceFrequencyCode: str 

2204 isoQualityConformanceExplanation: str 

2205 isoQualityConformanceQualityPass: bool 

2206 isoQualityConformanceSpecificationDate: str 

2207 isoQualityConformanceSpecificationTitle: str 

2208 isoQualityLineageSource: str 

2209 isoQualityLineageSourceScale: int 

2210 isoQualityLineageStatement: str 

2211 isoRestrictionCode: str 

2212 isoServiceFunction: str 

2213 isoScope: str 

2214 isoScopeName: str 

2215 isoSpatialRepresentationType: str 

2216 isoTopicCategories: list[str] 

2217 isoSpatialResolution: int 

2218################################################################################ 

2219 

2220 

2221################################################################################ 

2222# /base/feature/types.pyinc 

2223 

2224 

2225FeatureUid: TypeAlias = str 

2226"""Unique Feature id.""" 

2227 

2228class FeatureRecord(Data): 

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

2230 

2231 attributes: dict 

2232 meta: dict 

2233 uid: Optional[str] 

2234 shape: Optional['Shape'] 

2235 ewkt: str 

2236 

2237 

2238class FeatureProps(Props): 

2239 """Feature Proprieties.""" 

2240 

2241 attributes: dict 

2242 category: Optional[str] 

2243 cssSelector: str 

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

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

2246 isNew: bool 

2247 modelUid: str 

2248 uid: str 

2249 views: dict 

2250 

2251 

2252class Feature: 

2253 """Feature object.""" 

2254 

2255 attributes: dict 

2256 category: str 

2257 cssSelector: str 

2258 errors: list['ModelValidationError'] 

2259 isNew: bool 

2260 model: 'Model' 

2261 props: 'FeatureProps' 

2262 record: 'FeatureRecord' 

2263 views: dict 

2264 createWithFeatures: list['Feature'] 

2265 insertedPrimaryKey: Optional[int | str] 

2266 

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

2268 

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

2270 

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

2272 

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

2274 

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

2276 

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

2278 

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

2280 

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

2282 

2283 def uid(self) -> FeatureUid: ... 

2284################################################################################ 

2285 

2286 

2287################################################################################ 

2288# /base/shape/types.pyinc 

2289 

2290 

2291class ShapeProps(Props): 

2292 """Shape properties.""" 

2293 

2294 crs: str 

2295 geometry: dict 

2296 

2297 

2298class Shape(Object): 

2299 """Geo-referenced geometry.""" 

2300 

2301 type: GeometryType 

2302 """Geometry type.""" 

2303 

2304 crs: 'Crs' 

2305 """CRS of this shape.""" 

2306 

2307 x: Optional[float] 

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

2309 

2310 y: Optional[float] 

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

2312 

2313 # common props 

2314 

2315 def area(self) -> float: 

2316 """Computes the area of the geometry.""" 

2317 

2318 def bounds(self) -> Bounds: 

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

2320 

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

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

2323 

2324 # formats 

2325 

2326 def to_wkb(self) -> bytes: 

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

2328 

2329 def to_wkb_hex(self) -> str: 

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

2331 

2332 def to_ewkb(self) -> bytes: 

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

2334 

2335 def to_ewkb_hex(self) -> str: 

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

2337 

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

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

2340 

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

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

2343 

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

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

2346 

2347 Args: 

2348 keep_crs: Do not transform to WGS. 

2349 """ 

2350 

2351 def to_props(self) -> ShapeProps: 

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

2353 

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

2355 

2356 def is_empty(self) -> bool: 

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

2358 

2359 def is_ring(self) -> bool: 

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

2361 

2362 def is_simple(self) -> bool: 

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

2364 

2365 def is_valid(self) -> bool: 

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

2367 

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

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

2370 

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

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

2373 

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

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

2376 

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

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

2379 

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

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

2382 

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

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

2385 

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

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

2388 

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

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

2391 

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

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

2394 

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

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

2397 

2398 # set operations 

2399 

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

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

2402 

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

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

2405 

2406 # convertors 

2407 

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

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

2410 

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

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

2413 

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

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

2416 

2417 # misc 

2418 

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

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

2421 

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

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

2424################################################################################ 

2425 

2426 

2427 

2428################################################################################ 

2429# /base/action/types.pyinc 

2430 

2431 

2432class ActionManager(Node): 

2433 """Action manager.""" 

2434 

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

2436 """ 

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

2438 

2439 Args: 

2440 project: The project requiring actions. 

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

2442 

2443 Returns: 

2444 A list of accessible actions. 

2445 """ 

2446 

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

2448 """ 

2449 Locate an Action object. 

2450 

2451 Args: 

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

2453 ext_type: The extension type to search for. 

2454 user: Locate actions only for this user. 

2455 

2456 Returns: 

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

2458 """ 

2459 

2460 def prepare_action( 

2461 self, 

2462 command_category: CommandCategory, 

2463 command_name: str, 

2464 params: dict, 

2465 user: 'User', 

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

2467 ) -> tuple[Callable, Request]: 

2468 """ 

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

2470 

2471 Args: 

2472 command_category: The category of the command to execute. 

2473 command_name: The name of the command to execute. 

2474 params: Additional parameters required for the action. 

2475 user: The user initiating the action. 

2476 read_options: Read options for parsing parameters. 

2477 

2478 Returns: 

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

2480 """ 

2481 

2482 

2483class Action(Node): 

2484 """Base Action class.""" 

2485################################################################################ 

2486 

2487 

2488################################################################################ 

2489# /base/auth/types.pyinc 

2490 

2491 

2492class User(Object): 

2493 """User object.""" 

2494 

2495 isGuest: bool 

2496 """User is a Guest.""" 

2497 

2498 authProvider: 'AuthProvider' 

2499 """User authorization provider.""" 

2500 

2501 attributes: dict 

2502 """Public user attributes.""" 

2503 data: dict 

2504 """Private user data.""" 

2505 roles: set[str] 

2506 """User roles.""" 

2507 uid: str 

2508 """Global user uid.""" 

2509 

2510 authToken: str 

2511 """Token used for authorization.""" 

2512 displayName: str 

2513 """User display name.""" 

2514 email: str 

2515 """User email.""" 

2516 localUid: str 

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

2518 loginName: str 

2519 """User login name.""" 

2520 mfaUid: str 

2521 """MFA adapter uid.""" 

2522 mfaSecret: str 

2523 """MFA secret.""" 

2524 

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

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

2527 

2528 Args: 

2529 access: Access mode. 

2530 obj: Requested object. 

2531 

2532 Returns: 

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

2534 """ 

2535 

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

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

2538 

2539 Args: 

2540 access: Access mode. 

2541 obj: Requested object. 

2542 *context: Further objects to check. 

2543 

2544 Returns: 

2545 ``True`` is access is granted. 

2546 """ 

2547 

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

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

2550 

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

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

2553 

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

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

2556 

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

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

2559 

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

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

2562 

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

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

2565 

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

2567 """Get a readable object by uid. 

2568 

2569 Args: 

2570 uid: Object uid. 

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

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

2573 

2574 Returns: 

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

2576 """ 

2577 

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

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

2580 

2581 Args: 

2582 uid: Object uid. 

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

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

2585 

2586 Returns: 

2587 A readable object. 

2588 

2589 Raises: 

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

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

2592 """ 

2593 

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

2595 """Get a readable Project object. 

2596 

2597 Args: 

2598 uid: Project uid. 

2599 

2600 Returns: 

2601 A Project object. 

2602 """ 

2603 

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

2605 """Get a readable Layer object. 

2606 

2607 Args: 

2608 uid: Layer uid. 

2609 

2610 Returns: 

2611 A Layer object. 

2612 """ 

2613 

2614 

2615class AuthManager(Node): 

2616 """Authentication manager.""" 

2617 

2618 guestSession: 'AuthSession' 

2619 """Preconfigured Guest session.""" 

2620 

2621 guestUser: 'User' 

2622 """Preconfigured Guest user.""" 

2623 systemUser: 'User' 

2624 """Preconfigured System user.""" 

2625 

2626 providers: list['AuthProvider'] 

2627 """Authentication providers.""" 

2628 methods: list['AuthMethod'] 

2629 """Authentication methods.""" 

2630 mfAdapters: list['AuthMultiFactorAdapter'] 

2631 """Authentication MFA handlers.""" 

2632 

2633 sessionMgr: 'AuthSessionManager' 

2634 """Session manager.""" 

2635 

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

2637 """Authenticate a user. 

2638 

2639 Args: 

2640 method: Authentication method. 

2641 credentials: Credentials object. 

2642 

2643 Returns: 

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

2645 """ 

2646 

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

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

2649 

2650 Args: 

2651 user_uid: Global user uid. 

2652 Returns: 

2653 A User or ``None``. 

2654 """ 

2655 

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

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

2658 

2659 Args: 

2660 uid: Uid. 

2661 Returns: 

2662 A Provider or ``None``. 

2663 """ 

2664 

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

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

2667 

2668 Args: 

2669 uid: Uid. 

2670 Returns: 

2671 A Method or ``None``. 

2672 """ 

2673 

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

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

2676 

2677 Args: 

2678 uid: Adapter uid. 

2679 Returns: 

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

2681 """ 

2682 return None 

2683 

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

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

2686 

2687 Args: 

2688 user: A User object. 

2689 

2690 Returns: 

2691 A json string. 

2692 """ 

2693 

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

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

2696 

2697 Args: 

2698 ser: A json string. 

2699 

2700 Returns: 

2701 A User object. 

2702 """ 

2703 

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

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

2706 

2707 

2708class AuthMethod(Node): 

2709 """Authentication Method.""" 

2710 

2711 secure: bool 

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

2713 

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

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

2716 

2717 Args: 

2718 req: Requester object. 

2719 

2720 Returns: 

2721 A Session or ``None``. 

2722 """ 

2723 

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

2725 """Close a previously opened Session. 

2726 

2727 Args: 

2728 req: Requester object. 

2729 res: Responder object. 

2730 

2731 Returns: 

2732 True if the Session was successfully closed. 

2733 """ 

2734 

2735 

2736class AuthMultiFactorState(Enum): 

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

2738 open = 'open' 

2739 """Transaction opened.""" 

2740 ok = 'ok' 

2741 """Transaction completed successfully.""" 

2742 retry = 'retry' 

2743 """Authorization has to be retried.""" 

2744 failed = 'failed' 

2745 """Authorization failed.""" 

2746 

2747 

2748class AuthMultiFactorTransaction(Data): 

2749 """Multifactor authorization transaction.""" 

2750 

2751 state: AuthMultiFactorState 

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

2753 restartCount: int 

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

2755 verifyCount: int 

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

2757 secret: str 

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

2759 startTime: int 

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

2761 generateTime: int 

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

2763 message: str 

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

2765 adapter: 'AuthMultiFactorAdapter' 

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

2767 user: 'User' 

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

2769 

2770 

2771class AuthMultiFactorAdapter(Node): 

2772 """Multi-factor authentication adapter.""" 

2773 

2774 message: str 

2775 lifeTime: int 

2776 maxRestarts: int 

2777 maxVerifyAttempts: int 

2778 

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

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

2781 

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

2783 """Verify a payload.""" 

2784 

2785 def cancel(self, mfa: AuthMultiFactorTransaction): 

2786 """Cancel the transaction.""" 

2787 

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

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

2790 

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

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

2793 

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

2795 """Restart the transaction.""" 

2796 

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

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

2799 

2800 

2801class AuthProvider(Node): 

2802 """Authentication Provider.""" 

2803 

2804 allowedMethods: list[str] 

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

2806 

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

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

2809 

2810 Args: 

2811 local_uid: User local uid. 

2812 

2813 Returns: 

2814 A User or ``None``. 

2815 """ 

2816 

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

2818 """Authenticate a user. 

2819 

2820 Args: 

2821 method: Authentication method. 

2822 credentials: Credentials object. 

2823 

2824 Returns: 

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

2826 """ 

2827 

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

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

2830 

2831 Args: 

2832 user: A User object. 

2833 

2834 Returns: 

2835 A json string. 

2836 """ 

2837 

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

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

2840 

2841 Args: 

2842 ser: A json string. 

2843 

2844 Returns: 

2845 A User object. 

2846 """ 

2847 

2848 

2849class AuthSession: 

2850 """Authentication session.""" 

2851 

2852 uid: str 

2853 """Session uid.""" 

2854 method: Optional['AuthMethod'] 

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

2856 user: 'User' 

2857 """Authorized User.""" 

2858 data: dict 

2859 """Session data.""" 

2860 created: 'datetime.datetime' 

2861 """Session create time.""" 

2862 updated: 'datetime.datetime' 

2863 """Session update time.""" 

2864 isChanged: bool 

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

2866 

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

2868 """Get a session data value. 

2869 

2870 Args: 

2871 key: Value name. 

2872 default: Default value. 

2873 

2874 Returns: 

2875 A value or the default. 

2876 """ 

2877 

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

2879 """Set a session data value. 

2880 

2881 Args: 

2882 key: Value name. 

2883 value: A value. 

2884 """ 

2885 

2886 

2887class AuthSessionManager(Node): 

2888 """Authentication session Manager.""" 

2889 

2890 lifeTime: int 

2891 """Session lifetime in seconds.""" 

2892 

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

2894 """Create a new Session, 

2895 

2896 Args: 

2897 method: Auth Method that creates the Session. 

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

2899 data: Session data. 

2900 

2901 Returns: 

2902 A new Session. 

2903 """ 

2904 

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

2906 """Delete a Session. 

2907 

2908 Args: 

2909 sess: Session object. 

2910 """ 

2911 

2912 def delete_all(self): 

2913 """Delete all Sessions. 

2914 """ 

2915 

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

2917 """Get Session by its uid. 

2918 

2919 Args: 

2920 uid: Session uid. 

2921 

2922 Returns: 

2923 A Session or ``None``. 

2924 """ 

2925 

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

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

2928 

2929 Args: 

2930 uid: Session uid. 

2931 

2932 Returns: 

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

2934 """ 

2935 

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

2937 """Get all sessions.""" 

2938 

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

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

2941 

2942 Args: 

2943 sess: Session object. 

2944 """ 

2945 

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

2947 """Update the Session last activity timestamp. 

2948 

2949 Args: 

2950 sess: Session object. 

2951 """ 

2952 

2953 def cleanup(self): 

2954 """Remove invalid Sessions from the storage. 

2955 """ 

2956################################################################################ 

2957 

2958 

2959 

2960################################################################################ 

2961# /base/layer/types.pyinc 

2962 

2963 

2964class LayerDisplayMode(Enum): 

2965 """Layer display mode.""" 

2966 

2967 box = 'box' 

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

2969 tile = 'tile' 

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

2971 client = 'client' 

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

2973 

2974 

2975class LayerClientOptions(Data): 

2976 """Client options for a layer.""" 

2977 

2978 expanded: bool 

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

2980 unlisted: bool 

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

2982 selected: bool 

2983 """A layer is initially selected.""" 

2984 hidden: bool 

2985 """A layer is initially hidden.""" 

2986 unfolded: bool 

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

2988 exclusive: bool 

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

2990 treeClassName: str 

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

2992 

2993 

2994class TileGrid(Data): 

2995 """Tile grid.""" 

2996 

2997 uid: str 

2998 bounds: Bounds 

2999 origin: Origin 

3000 resolutions: list[float] 

3001 tileSize: int 

3002 

3003 

3004class LayerCache(Data): 

3005 """Layer cache.""" 

3006 

3007 maxAge: int 

3008 maxLevel: int 

3009 requestBuffer: int 

3010 requestTiles: int 

3011 

3012 

3013class FeatureLoadingStrategy(Enum): 

3014 """Loading strategy for features.""" 

3015 

3016 all = 'all' 

3017 """Load all features.""" 

3018 bbox = 'bbox' 

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

3020 lazy = 'lazy' 

3021 """Load features on demand.""" 

3022 

3023 

3024class LayerOws(Node): 

3025 """Layer OWS controller.""" 

3026 

3027 allowedServiceUids: list[str] 

3028 deniedServiceUids: list[str] 

3029 featureName: str 

3030 geometryName: str 

3031 layerName: str 

3032 models: list['Model'] 

3033 xmlNamespace: Optional['XmlNamespace'] 

3034 

3035 

3036class Layer(Node): 

3037 """Layer object.""" 

3038 

3039 canRenderBox: bool 

3040 canRenderSvg: bool 

3041 canRenderXyz: bool 

3042 

3043 isEnabledForOws: bool 

3044 isGroup: bool 

3045 isSearchable: bool 

3046 

3047 hasLegend: bool 

3048 

3049 bounds: Bounds 

3050 zoomBounds: Bounds 

3051 wgsExtent: Extent 

3052 mapCrs: 'Crs' 

3053 clientOptions: LayerClientOptions 

3054 displayMode: LayerDisplayMode 

3055 loadingStrategy: FeatureLoadingStrategy 

3056 imageFormat: ImageFormat 

3057 opacity: float 

3058 resolutions: list[float] 

3059 title: str 

3060 

3061 grid: Optional[TileGrid] 

3062 cache: Optional[LayerCache] 

3063 

3064 metadata: 'Metadata' 

3065 legend: Optional['Legend'] 

3066 legendUrl: str 

3067 

3068 finders: list['Finder'] 

3069 templates: list['Template'] 

3070 models: list['Model'] 

3071 ows: 'LayerOws' 

3072 

3073 layers: list['Layer'] 

3074 

3075 sourceLayers: list['SourceLayer'] 

3076 

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

3078 

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

3080 

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

3082 

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

3084 

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

3086 

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

3088################################################################################ 

3089 

3090 

3091################################################################################ 

3092# /base/legend/types.pyinc 

3093 

3094 

3095class LegendRenderOutput(Data): 

3096 """Legend render output.""" 

3097 

3098 html: str 

3099 image: 'Image' 

3100 image_path: str 

3101 size: Size 

3102 mime: str 

3103 

3104 

3105class Legend(Node): 

3106 """Legend object.""" 

3107 

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

3109################################################################################ 

3110 

3111 

3112################################################################################ 

3113# /base/map/types.pyinc 

3114 

3115 

3116class Map(Node): 

3117 """Map object.""" 

3118 

3119 rootLayer: 'Layer' 

3120 

3121 bounds: Bounds 

3122 center: Point 

3123 coordinatePrecision: int 

3124 initResolution: float 

3125 resolutions: list[float] 

3126 title: str 

3127 wgsExtent: Extent 

3128################################################################################ 

3129 

3130 

3131 

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

3133# /base/model/types.pyinc 

3134 

3135 

3136class ModelClientOptions(Data): 

3137 """Client options for a model""" 

3138 

3139 keepFormOpen: Optional[bool] 

3140 

3141class ModelValidationError(Data): 

3142 """Validation error.""" 

3143 

3144 fieldName: str 

3145 message: str 

3146 

3147 

3148class ModelOperation(Enum): 

3149 """Model operation.""" 

3150 

3151 read = 'read' 

3152 create = 'create' 

3153 update = 'update' 

3154 delete = 'delete' 

3155 

3156 

3157class ModelReadTarget(Enum): 

3158 """Target for the read operation.""" 

3159 

3160 map = 'map' 

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

3162 searchResults = 'searchResults' 

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

3164 list = 'list' 

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

3166 editList = 'editList' 

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

3168 editForm = 'editForm' 

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

3170 

3171 

3172class ModelSelectBuild(Data): 

3173 """Database select statement.""" 

3174 

3175 columns: list['sqlalchemy.Column'] 

3176 geometryWhere: list 

3177 keywordWhere: list 

3178 where: list 

3179 order: list 

3180 

3181 

3182class ModelContext(Data): 

3183 """Model context.""" 

3184 

3185 op: ModelOperation 

3186 target: ModelReadTarget 

3187 user: 'User' 

3188 project: 'Project' 

3189 relDepth: int = 0 

3190 maxDepth: int = 0 

3191 search: 'SearchQuery' 

3192 dbSelect: ModelSelectBuild 

3193 

3194 

3195EmptyValue = object() 

3196"""Special value for empty fields.""" 

3197 

3198ErrorValue = object() 

3199"""Special value for invalid fields.""" 

3200 

3201 

3202class ModelWidget(Node): 

3203 """Model widget.""" 

3204 

3205 supportsTableView: bool = True 

3206 

3207 

3208class ModelValidator(Node): 

3209 """Model Validator.""" 

3210 

3211 message: str 

3212 ops: set[ModelOperation] 

3213 

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

3215 

3216 

3217class ModelValue(Node): 

3218 """Model value.""" 

3219 

3220 isDefault: bool 

3221 ops: set[ModelOperation] 

3222 

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

3224 

3225 

3226class ModelField(Node): 

3227 """Model field.""" 

3228 

3229 name: str 

3230 title: str 

3231 

3232 attributeType: AttributeType 

3233 

3234 widget: Optional['ModelWidget'] = None 

3235 

3236 values: list['ModelValue'] 

3237 validators: list['ModelValidator'] 

3238 

3239 isPrimaryKey: bool 

3240 isRequired: bool 

3241 isUnique: bool 

3242 isAuto: bool 

3243 isHidden: bool 

3244 

3245 supportsFilterSearch: bool = False 

3246 supportsGeometrySearch: bool = False 

3247 supportsKeywordSearch: bool = False 

3248 

3249 model: 'Model' 

3250 

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

3252 

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

3254 

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

3256 

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

3258 

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

3260 

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

3262 

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

3264 

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

3266 

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

3268 

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

3270 

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

3272 

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

3274 

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

3276 

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

3278 

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

3280 

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

3282 

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

3284 

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

3286 

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

3288 

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

3290 

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

3292 

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

3294 

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

3296 

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

3298 

3299 

3300class Model(Node): 

3301 """Data Model.""" 

3302 

3303 clientOptions: ModelClientOptions 

3304 defaultSort: list['SearchSort'] 

3305 fields: list['ModelField'] 

3306 geometryCrs: Optional['Crs'] 

3307 geometryName: str 

3308 geometryType: Optional[GeometryType] 

3309 isEditable: bool 

3310 loadingStrategy: 'FeatureLoadingStrategy' 

3311 title: str 

3312 uidName: str 

3313 withTableView: bool 

3314 

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

3316 

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

3318 

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

3320 

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

3322 

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

3324 

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

3326 

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

3328 

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

3330 

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

3332 

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

3334 

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

3336 

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

3338 

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

3340 

3341 

3342class ModelManager(Node): 

3343 """Model manager.""" 

3344 

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

3346 

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

3348 

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

3350 

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

3352################################################################################ 

3353 

3354 

3355################################################################################ 

3356# /base/database/types.pyinc 

3357 

3358 

3359class DatabaseModel(Model): 

3360 """Database-based data model.""" 

3361 

3362 db: 'DatabaseProvider' 

3363 """Database provider.""" 

3364 sqlFilter: str 

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

3366 tableName: str 

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

3368 

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

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

3371 

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

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

3374 

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

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

3377 

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

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

3380 

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

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

3383 

3384 

3385class ColumnDescription(Data): 

3386 """Description of a dataset column.""" 

3387 

3388 columnIndex: int 

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

3390 comment: str 

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

3392 default: str 

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

3394 geometrySrid: int 

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

3396 geometryType: GeometryType 

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

3398 isAutoincrement: bool 

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

3400 isNullable: bool 

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

3402 isPrimaryKey: bool 

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

3404 isUnique: bool 

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

3406 hasDefault: bool 

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

3408 isIndexed: bool 

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

3410 name: str 

3411 """The name of the column.""" 

3412 nativeType: str 

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

3414 options: dict 

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

3416 type: AttributeType 

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

3418 

3419 

3420class DataSetDescription(Data): 

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

3422 

3423 columns: list[ColumnDescription] 

3424 """A list of column descriptions.""" 

3425 columnMap: dict[str, ColumnDescription] 

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

3427 fullName: str 

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

3429 geometryName: str 

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

3431 geometrySrid: int 

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

3433 geometryType: GeometryType 

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

3435 name: str 

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

3437 schema: str 

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

3439 

3440 

3441class DatabaseManager(Node): 

3442 """Database manager.""" 

3443 

3444 providers: list['DatabaseProvider'] 

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

3446 

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

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

3449 

3450 Args: 

3451 cfg: The configuration object for the database provider. 

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

3453 

3454 Returns: 

3455 DatabaseProvider: A new database provider instance. 

3456 """ 

3457 

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

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

3460 

3461 Args: 

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

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

3464 

3465 Returns: 

3466 The matching database provider if found, otherwise None. 

3467 """ 

3468 

3469 

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

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

3472 

3473 

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

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

3476 

3477 

3478class DatabaseConnection: 

3479 """Database connection. 

3480 

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

3482 """ 

3483 

3484 saConn: 'sqlalchemy.Connection' 

3485 

3486 def __enter__(self) -> 'DatabaseConnection': ... 

3487 

3488 def __exit__(self, exc_type, exc_value, traceback): ... 

3489 

3490 def execute(self, stmt: 'sqlalchemy.Executable', params=None, execution_options: dict=None) -> 'sqlalchemy.CursorResult': ... 

3491 

3492 def commit(self): ... 

3493 

3494 def rollback(self): ... 

3495 

3496 def close(self): ... 

3497 

3498 def exec(self, stmt: 'DatabaseStmt', **params) -> 'sqlalchemy.CursorResult': ... 

3499 

3500 def exec_commit(self, stmt: 'DatabaseStmt', **params) -> 'sqlalchemy.CursorResult': ... 

3501 

3502 def exec_rollback(self, stmt: 'DatabaseStmt', **params) -> 'sqlalchemy.CursorResult': ... 

3503 

3504 def fetch_all(self, stmt: 'DatabaseStmt', **params) -> list[dict]: ... 

3505 

3506 def fetch_first(self, stmt: 'DatabaseStmt', **params) -> dict | None: ... 

3507 

3508 def fetch_scalars(self, stmt: 'DatabaseStmt', **params) -> list: ... 

3509 

3510 def fetch_strings(self, stmt: 'DatabaseStmt', **params) -> list[str]: ... 

3511 

3512 def fetch_ints(self, stmt: 'DatabaseStmt', **params) -> list[int]: ... 

3513 

3514 def fetch_scalar(self, stmt: 'DatabaseStmt', **params) -> Any: ... 

3515 

3516 def fetch_string(self, stmt: 'DatabaseStmt', **params) -> str | None: ... 

3517 

3518 def fetch_int(self, stmt: 'DatabaseStmt', **params) -> int | None: ... 

3519 

3520 

3521class DatabaseProvider(Node): 

3522 """Database Provider. 

3523 

3524 A database Provider wraps SQLAlchemy ``Engine`` and ``Connection`` objects 

3525 and provides common db functionality. 

3526 """ 

3527 

3528 def connect(self) -> 'DatabaseConnection': 

3529 """Context manager for SQLAlchemy ``Connection``. 

3530 

3531 Context calls to this method can be nested. An inner call is a no-op, as no new connection is created. 

3532 Only the outermost connection is closed upon exit:: 

3533 

3534 with db.connect(): 

3535 ... 

3536 with db.connect(): # no-op 

3537 ... 

3538 # connection remains open 

3539 ... 

3540 # connection closed 

3541 """ 

3542 

3543 def engine_options(self, **kwargs): 

3544 """Add defaults to the SA engine options.""" 

3545 

3546 def url(self) -> str: 

3547 """Return the connection URL.""" 

3548 

3549 def engine(self) -> 'sqlalchemy.Engine': 

3550 """Get SQLAlchemy ``Engine`` object for this provider.""" 

3551 

3552 def create_engine(self, **kwargs) -> 'sqlalchemy.Engine': 

3553 """CreateSQLAlchemy ``Engine`` object for this provider.""" 

3554 

3555 def describe(self, table: DatabaseTableAlike) -> 'DataSetDescription': 

3556 """Describe a table.""" 

3557 

3558 def table(self, table: 'DatabaseTableAlike', **kwargs) -> 'sqlalchemy.Table': 

3559 """SQLAlchemy ``Table`` object for a specific table.""" 

3560 

3561 def column(self, table: DatabaseTableAlike, column_name: str) -> 'sqlalchemy.Column': 

3562 """SQLAlchemy ``Column`` object for a specific column.""" 

3563 

3564 def count(self, table: DatabaseTableAlike) -> int: 

3565 """Return table record count or 0 if the table does not exist.""" 

3566 

3567 def has_table(self, table_name: str) -> bool: 

3568 """Check if a specific table exists.""" 

3569 

3570 def has_column(self, table: DatabaseTableAlike, column_name: str) -> bool: 

3571 """Check if a specific column exists.""" 

3572 

3573 def join_table_name(self, schema: str, name: str) -> str: 

3574 """Create a full table name from the schema and table names.""" 

3575 

3576 def split_table_name(self, table_name: str) -> tuple[str, str]: 

3577 """Split a full table name into the schema and table names.""" 

3578 

3579 def table_bounds(self, table: DatabaseTableAlike) -> Optional[Bounds]: 

3580 """Compute a bounding box for the table primary geometry.""" 

3581 

3582 def select_text(self, sql: str, **kwargs) -> list[dict]: 

3583 """Execute a textual SELECT stmt and return a list of record dicts.""" 

3584 

3585 def execute_text(self, sql: str, **kwargs) -> 'sqlalchemy.CursorResult': 

3586 """Execute a textual DML stmt and return a result.""" 

3587################################################################################ 

3588 

3589 

3590 

3591################################################################################ 

3592# /base/job/types.pyinc 

3593 

3594 

3595class JobTerminated(Exception): 

3596 pass 

3597 

3598 

3599class JobState(Enum): 

3600 """Background job state.""" 

3601 

3602 init = 'init' 

3603 """The job is being created.""" 

3604 open = 'open' 

3605 """The job is just created and waiting for start.""" 

3606 running = 'running' 

3607 """The job is running.""" 

3608 complete = 'complete' 

3609 """The job has been completed successfully.""" 

3610 error = 'error' 

3611 """There was an error.""" 

3612 cancel = 'cancel' 

3613 """The job was cancelled.""" 

3614 

3615 

3616class Job(Data): 

3617 """Background job data.""" 

3618 

3619 uid: str 

3620 user: 'User' 

3621 worker: str 

3622 state: JobState 

3623 error: str 

3624 numSteps: int 

3625 step: int 

3626 stepName: str 

3627 payload: dict 

3628 

3629 

3630class JobRequest(Request): 

3631 jobUid: str 

3632 

3633 

3634class JobStatusResponse(Response): 

3635 jobUid: str 

3636 state: JobState 

3637 progress: int 

3638 stepName: str 

3639 output: dict 

3640 

3641 

3642class JobManager(Node): 

3643 """Job Manager.""" 

3644 

3645 def create_job(self, user: User, worker: type, payload: dict = None) -> Job: ... 

3646 

3647 def get_job(self, job_uid: str, user: User = None, state: JobState = None) -> Optional[Job]: ... 

3648 

3649 def update_job(self, job: Job, **kwargs) -> Optional[Job]: ... 

3650 

3651 def run_job(self, job: Job) -> Optional[Job]: ... 

3652 

3653 def cancel_job(self, job: Job) -> Optional[Job]: ... 

3654 

3655 def remove_job(self, job: Job): ... 

3656 

3657 def schedule_job(self, job: Job) -> Job: ... 

3658 

3659 def require_job(self, req: 'WebRequester', p: JobRequest) -> Job: ... 

3660 

3661 def handle_status_request(self, req: 'WebRequester', p: JobRequest) -> JobStatusResponse: ... 

3662 

3663 def handle_cancel_request(self, req: 'WebRequester', p: JobRequest) -> JobStatusResponse: ... 

3664 

3665 def job_status_response(self, job: Job, **kwargs) -> 'JobStatusResponse': ... 

3666################################################################################ 

3667 

3668 

3669################################################################################ 

3670# /base/ows/types.pyinc 

3671 

3672 

3673import gws 

3674 

3675 

3676class OwsProtocol(Enum): 

3677 """Supported OWS protocol.""" 

3678 

3679 WMS = 'WMS' 

3680 WMTS = 'WMTS' 

3681 WCS = 'WCS' 

3682 WFS = 'WFS' 

3683 CSW = 'CSW' 

3684 

3685 

3686class OwsAuthorization(Data): 

3687 type: str 

3688 username: str 

3689 password: str 

3690 

3691 

3692class OwsVerb(Enum): 

3693 """OWS verb.""" 

3694 

3695 CreateStoredQuery = 'CreateStoredQuery' 

3696 DescribeCoverage = 'DescribeCoverage' 

3697 DescribeFeatureType = 'DescribeFeatureType' 

3698 DescribeLayer = 'DescribeLayer' 

3699 DescribeRecord = 'DescribeRecord' 

3700 DescribeStoredQueries = 'DescribeStoredQueries' 

3701 DropStoredQuery = 'DropStoredQuery' 

3702 GetCapabilities = 'GetCapabilities' 

3703 GetFeature = 'GetFeature' 

3704 GetFeatureInfo = 'GetFeatureInfo' 

3705 GetFeatureWithLock = 'GetFeatureWithLock' 

3706 GetLegendGraphic = 'GetLegendGraphic' 

3707 GetMap = 'GetMap' 

3708 GetPrint = 'GetPrint' 

3709 GetPropertyValue = 'GetPropertyValue' 

3710 GetRecordById = 'GetRecordById' 

3711 GetRecords = 'GetRecords' 

3712 GetTile = 'GetTile' 

3713 ListStoredQueries = 'ListStoredQueries' 

3714 LockFeature = 'LockFeature' 

3715 Transaction = 'Transaction' 

3716 

3717 

3718class OwsOperation(Data): 

3719 """OWS operation.""" 

3720 

3721 allowedParameters: dict[str, list[str]] 

3722 constraints: dict[str, list[str]] 

3723 formats: list[str] 

3724 handlerName: str 

3725 params: dict[str, str] 

3726 postUrl: Url 

3727 preferredFormat: str 

3728 url: Url 

3729 verb: OwsVerb 

3730 

3731 

3732class OwsCapabilities(Data): 

3733 """OWS capabilities structure.""" 

3734 

3735 metadata: 'Metadata' 

3736 operations: list['OwsOperation'] 

3737 sourceLayers: list['SourceLayer'] 

3738 tileMatrixSets: list['TileMatrixSet'] 

3739 version: str 

3740 

3741 

3742class OwsService(Node): 

3743 """OWS Service.""" 

3744 

3745 isRasterService: bool = False 

3746 """Service provides raster services.""" 

3747 isVectorService: bool = False 

3748 """Service provides vector services.""" 

3749 isOwsCommon: bool = False 

3750 """Conforms to OGC Web Services Common Standard.""" 

3751 

3752 alwaysXY: bool 

3753 """Force lon/lat order for geographic projections.""" 

3754 metadata: 'Metadata' 

3755 """Service metadata.""" 

3756 name: str 

3757 """Service name.""" 

3758 project: Optional['Project'] 

3759 """Project this service is configured for.""" 

3760 rootLayer: Optional['Layer'] 

3761 """Root layer of the service.""" 

3762 protocol: OwsProtocol 

3763 """Supported protocol.""" 

3764 defaultFeatureCount: int 

3765 """Default limit of features per page.""" 

3766 maxFeatureCount: int 

3767 """Max limit of features per page.""" 

3768 searchTolerance: UomValue 

3769 """Default tolerance for spatial search.""" 

3770 supportedBounds: list[Bounds] 

3771 """Supported bounds.""" 

3772 supportedVersions: list[str] 

3773 """Supported versions.""" 

3774 supportedOperations: list['OwsOperation'] 

3775 """Supported operations.""" 

3776 templates: list['Template'] 

3777 """Service templates.""" 

3778 imageFormats: list[ImageFormat] 

3779 """Supported image formats.""" 

3780 updateSequence: str 

3781 """Service update sequence.""" 

3782 withInspireMeta: bool 

3783 """Include INSPIRE metadata.""" 

3784 withStrictParams: bool 

3785 """Strict parameter checking.""" 

3786 

3787 def handle_request(self, req: 'WebRequester') -> ContentResponse: 

3788 """Handle a service request.""" 

3789 

3790 def layer_is_compatible(self, layer: 'Layer') -> bool: 

3791 """True if layer can be used in this service.""" 

3792 

3793 

3794class OwsProvider(Node): 

3795 """OWS services Provider.""" 

3796 

3797 alwaysXY: bool 

3798 authorization: Optional['OwsAuthorization'] 

3799 bounds: Optional[Bounds] 

3800 forceCrs: 'Crs' 

3801 maxRequests: int 

3802 metadata: 'Metadata' 

3803 operations: list['OwsOperation'] 

3804 protocol: 'OwsProtocol' 

3805 sourceLayers: list['SourceLayer'] 

3806 url: Url 

3807 version: str 

3808 wgsExtent: Optional[Extent] 

3809 

3810 def get_operation(self, verb: 'OwsVerb', method: Optional['RequestMethod'] = None) -> Optional['OwsOperation']: ... 

3811 

3812 def get_features(self, args: 'SearchQuery', source_layers: list['SourceLayer']) -> list['FeatureRecord']: ... 

3813################################################################################ 

3814 

3815 

3816################################################################################ 

3817# /base/printer/types.pyinc 

3818 

3819 

3820class PrintPlaneType(Enum): 

3821 """Print plane type.""" 

3822 

3823 bitmap = 'bitmap' 

3824 url = 'url' 

3825 features = 'features' 

3826 raster = 'raster' 

3827 vector = 'vector' 

3828 soup = 'soup' 

3829 

3830 

3831class PrintPlane(Data): 

3832 """Print plane.""" 

3833 

3834 type: PrintPlaneType 

3835 

3836 opacity: Optional[float] 

3837 cssSelector: Optional[str] 

3838 

3839 bitmapData: Optional[bytes] 

3840 bitmapMode: Optional[str] 

3841 bitmapWidth: Optional[int] 

3842 bitmapHeight: Optional[int] 

3843 

3844 url: Optional[str] 

3845 

3846 features: Optional[list['FeatureProps']] 

3847 

3848 layerUid: Optional[str] 

3849 compositeLayerUids: Optional[list[str]] 

3850 

3851 soupPoints: Optional[list[Point]] 

3852 soupTags: Optional[list[Any]] 

3853 

3854 

3855class PrintMap(Data): 

3856 """Map properties for printing.""" 

3857 

3858 backgroundColor: Optional[int] 

3859 bbox: Optional[Extent] 

3860 center: Optional[Point] 

3861 planes: list[PrintPlane] 

3862 rotation: Optional[int] 

3863 scale: int 

3864 styles: Optional[list['StyleProps']] 

3865 visibleLayers: Optional[list[str]] 

3866 

3867 

3868class PrintRequestType(Enum): 

3869 """Type of the print request.""" 

3870 

3871 template = 'template' 

3872 map = 'map' 

3873 

3874 

3875class PrintRequest(Request): 

3876 """Print request.""" 

3877 

3878 type: PrintRequestType 

3879 

3880 args: Optional[dict] 

3881 crs: Optional[CrsName] 

3882 outputFormat: Optional[str] 

3883 maps: Optional[list[PrintMap]] 

3884 

3885 printerUid: Optional[str] 

3886 dpi: Optional[int] 

3887 outputSize: Optional[Size] 

3888 

3889 

3890class Printer(Node): 

3891 """Printer object.""" 

3892 

3893 title: str 

3894 template: 'Template' 

3895 models: list['Model'] 

3896 qualityLevels: list['TemplateQualityLevel'] 

3897 

3898 

3899class PrinterManager(Node): 

3900 """Print Manager.""" 

3901 

3902 def start_print_job(self, request: PrintRequest, user: 'User') -> 'JobStatusResponse': ... 

3903 

3904 def exec_print(self, request: PrintRequest, out_path: str): ... 

3905################################################################################ 

3906 

3907 

3908################################################################################ 

3909# /base/project/types.pyinc 

3910 

3911 

3912class Client(Node): 

3913 """GWS Client control object.""" 

3914 

3915 options: dict 

3916 elements: list 

3917 

3918 

3919class Project(Node): 

3920 """Project object.""" 

3921 

3922 assetsRoot: Optional['WebDocumentRoot'] 

3923 client: 'Client' 

3924 

3925 localeUids: list[str] 

3926 map: 'Map' 

3927 metadata: 'Metadata' 

3928 

3929 actions: list['Action'] 

3930 finders: list['Finder'] 

3931 models: list['Model'] 

3932 printers: list['Printer'] 

3933 templates: list['Template'] 

3934 owsServices: list['OwsService'] 

3935 

3936 vars: dict 

3937################################################################################ 

3938 

3939 

3940################################################################################ 

3941# /base/search/types.pyinc 

3942 

3943 

3944class SearchSort(Data): 

3945 """Search sort specification.""" 

3946 

3947 fieldName: str 

3948 reverse: bool 

3949 

3950 

3951class SearchFilterOperator(Enum): 

3952 """Search filter operator.""" 

3953 

3954 And = 'And' 

3955 Or = 'Or' 

3956 Not = 'Not' 

3957 

3958 PropertyIsEqualTo = 'PropertyIsEqualTo' 

3959 PropertyIsNotEqualTo = 'PropertyIsNotEqualTo' 

3960 PropertyIsLessThan = 'PropertyIsLessThan' 

3961 PropertyIsGreaterThan = 'PropertyIsGreaterThan' 

3962 PropertyIsLessThanOrEqualTo = 'PropertyIsLessThanOrEqualTo' 

3963 PropertyIsGreaterThanOrEqualTo = 'PropertyIsGreaterThanOrEqualTo' 

3964 PropertyIsLike = 'PropertyIsLike' 

3965 PropertyIsNull = 'PropertyIsNull' 

3966 PropertyIsNil = 'PropertyIsNil' 

3967 PropertyIsBetween = 'PropertyIsBetween' 

3968 

3969 Equals = 'Equals' 

3970 Disjoint = 'Disjoint' 

3971 Touches = 'Touches' 

3972 Within = 'Within' 

3973 Overlaps = 'Overlaps' 

3974 Crosses = 'Crosses' 

3975 Intersects = 'Intersects' 

3976 Contains = 'Contains' 

3977 DWithin = 'DWithin' 

3978 Beyond = 'Beyond' 

3979 BBOX = 'BBOX' 

3980 

3981 

3982class SearchFilterMatchAction(Enum): 

3983 """Search filter match action.""" 

3984 

3985 All = 'All' 

3986 Any = 'Any' 

3987 One = 'One' 

3988 

3989 

3990class SearchFilter(Data): 

3991 """Search filter.""" 

3992 

3993 operator: SearchFilterOperator 

3994 property: str 

3995 value: str 

3996 shape: 'Shape' 

3997 subFilters: list['SearchFilter'] 

3998 matchCase: bool 

3999 matchAction: SearchFilterMatchAction 

4000 wildCard: str 

4001 singleChar: str 

4002 escapeChar: str 

4003 

4004 

4005class SearchQuery(Data): 

4006 """Search query.""" 

4007 

4008 bounds: Bounds 

4009 """Search bounds.""" 

4010 extraArgs: dict 

4011 """Extra arguments for custom searches.""" 

4012 extraColumns: list 

4013 """Extra columns to select.""" 

4014 extraParams: dict 

4015 """Extra parameters to pass to a provider""" 

4016 extraWhere: list 

4017 """Extra where clauses.""" 

4018 keyword: str 

4019 """Keyword to search for.""" 

4020 layers: list['Layer'] 

4021 """Layers to search in.""" 

4022 limit: int 

4023 """Limit the number of results.""" 

4024 filter: SearchFilter 

4025 """Search filter.""" 

4026 project: 'Project' 

4027 """Project to search in.""" 

4028 resolution: float 

4029 """Pixel resolution for geometry search.""" 

4030 shape: 'Shape' 

4031 """Shape to search in.""" 

4032 sort: list[SearchSort] 

4033 """Sort options.""" 

4034 tolerance: 'UomValue' 

4035 """Tolerance for geometry search.""" 

4036 uids: list[str] 

4037 """UIDs to search for.""" 

4038 

4039 

4040class SearchResult(Data): 

4041 """Search result.""" 

4042 

4043 feature: 'Feature' 

4044 layer: 'Layer' 

4045 finder: 'Finder' 

4046 

4047 

4048class TextSearchType(Enum): 

4049 """Text search type.""" 

4050 

4051 exact = 'exact' 

4052 """Match the whole string.""" 

4053 begin = 'begin' 

4054 """Match the beginning of the string.""" 

4055 end = 'end' 

4056 """Match the end of the string.""" 

4057 any = 'any' 

4058 """Match any substring.""" 

4059 like = 'like' 

4060 """Use the percent sign as a placeholder.""" 

4061 

4062 

4063class TextSearchOptions(Data): 

4064 """Text search options.""" 

4065 

4066 type: TextSearchType 

4067 """Type of the search.""" 

4068 minLength: int = 0 

4069 """Minimal pattern length.""" 

4070 caseSensitive: bool = False 

4071 """Use the case sensitive search.""" 

4072 

4073 

4074class SortOptions(Data): 

4075 """Sort options.""" 

4076 

4077 fieldName: str 

4078 """Field name to sort by.""" 

4079 reverse: bool = False 

4080 """Sort in reverse order.""" 

4081 

4082 

4083class SearchManager(Node): 

4084 """Search Manager.""" 

4085 

4086 def run_search(self, search: 'SearchQuery', user: 'User') -> list['SearchResult']: ... 

4087 

4088 

4089class Finder(Node): 

4090 """Finder object.""" 

4091 

4092 title: str 

4093 category: str 

4094 

4095 supportsFilterSearch: bool = False 

4096 supportsGeometrySearch: bool = False 

4097 supportsKeywordSearch: bool = False 

4098 

4099 withFilter: bool 

4100 withGeometry: bool 

4101 withKeyword: bool 

4102 

4103 templates: list['Template'] 

4104 models: list['Model'] 

4105 sourceLayers: list['SourceLayer'] 

4106 

4107 tolerance: 'UomValue' 

4108 

4109 def run(self, search: SearchQuery, user: 'User', layer: Optional['Layer'] = None) -> list['Feature']: ... 

4110 

4111 def can_run(self, search: SearchQuery, user: 'User') -> bool: ... 

4112################################################################################ 

4113 

4114 

4115################################################################################ 

4116# /base/storage/types.pyinc 

4117 

4118 

4119class StorageManager(Node): 

4120 """Storage manager.""" 

4121 

4122 providers: list['StorageProvider'] 

4123 

4124 def create_provider(self, cfg: Config, **kwargs) -> 'StorageProvider': ... 

4125 

4126 def find_provider(self, uid: Optional[str] = None) -> Optional['StorageProvider']: ... 

4127 

4128 

4129 

4130class StorageRecord(Data): 

4131 """Storage record.""" 

4132 

4133 name: str 

4134 userUid: str 

4135 data: str 

4136 created: int 

4137 updated: int 

4138 

4139 

4140class StorageProvider(Node): 

4141 """Storage provider.""" 

4142 

4143 def list_names(self, category: str) -> list[str]: ... 

4144 

4145 def read(self, category: str, name: str) -> Optional['StorageRecord']: ... 

4146 

4147 def write(self, category: str, name: str, data: str, user_uid: str): ... 

4148 

4149 def delete(self, category: str, name: str): ... 

4150################################################################################ 

4151 

4152 

4153################################################################################ 

4154# /base/template/types.pyinc 

4155 

4156 

4157class TemplateArgs(Data): 

4158 """Template arguments.""" 

4159 

4160 app: 'Application' 

4161 """Application object.""" 

4162 locale: 'Locale' 

4163 """Current locale.""" 

4164 date: 'DateFormatter' 

4165 """Locale-aware date formatter.""" 

4166 time: 'TimeFormatter' 

4167 """Locale-aware time formatter.""" 

4168 number: 'NumberFormatter' 

4169 """Locale-aware number formatter.""" 

4170 

4171 

4172class TemplateRenderInput(Data): 

4173 """Template render input.""" 

4174 

4175 args: dict | Data 

4176 crs: 'Crs' 

4177 dpi: int 

4178 locale: 'Locale' 

4179 maps: list[MapRenderInput] 

4180 mimeOut: str 

4181 notify: Callable 

4182 project: 'Project' 

4183 user: 'User' 

4184 

4185 

4186class TemplateQualityLevel(Data): 

4187 """Template quality level.""" 

4188 

4189 name: str 

4190 """Quality level name.""" 

4191 dpi: int 

4192 """DPI for the quality level.""" 

4193 

4194 

4195class Template(Node): 

4196 """Template object.""" 

4197 

4198 mapSize: UomSize 

4199 """Default map size for the template.""" 

4200 mimeTypes: list[str] 

4201 """MIME types the template can generate.""" 

4202 pageSize: UomSize 

4203 """Default page size for printing.""" 

4204 pageMargin: UomExtent 

4205 """Default page margin for printing.""" 

4206 subject: str 

4207 """Template subject (category).""" 

4208 title: str 

4209 """Template title.""" 

4210 

4211 def render(self, tri: TemplateRenderInput) -> ContentResponse: 

4212 """Render the template and return the generated response.""" 

4213 

4214 

4215class TemplateManager(Node): 

4216 """Template manager.""" 

4217 

4218 def find_templates(self, subjects: list[str], where: list[Node], user: 'User' = None, mime: str = None) -> list['Template']: ... 

4219 

4220 def find_template(self, subject: str, where: list[Node], user: 'User' = None, mime: str = None) -> Optional['Template']: ... 

4221 

4222 def template_from_path(self, path: str) -> Optional['Template']: ... 

4223################################################################################ 

4224 

4225 

4226################################################################################ 

4227# /base/web/types.pyinc 

4228 

4229 

4230class RequestMethod(Enum): 

4231 """Web request method.""" 

4232 

4233 GET = 'GET' 

4234 HEAD = 'HEAD' 

4235 POST = 'POST' 

4236 PUT = 'PUT' 

4237 DELETE = 'DELETE' 

4238 CONNECT = 'CONNECT' 

4239 OPTIONS = 'OPTIONS' 

4240 TRACE = 'TRACE' 

4241 PATCH = 'PATCH' 

4242 

4243 

4244class WebRequester: 

4245 """Web Requester object.""" 

4246 

4247 environ: dict 

4248 """Request environment.""" 

4249 method: RequestMethod 

4250 """Request method.""" 

4251 contentType: str 

4252 """Request content type.""" 

4253 root: 'Root' 

4254 """Object tree root.""" 

4255 site: 'WebSite' 

4256 """Website the request is processed for.""" 

4257 

4258 session: 'AuthSession' 

4259 """Current session.""" 

4260 user: 'User' 

4261 """Current use.""" 

4262 

4263 isApi: bool 

4264 """The request is an 'api' request.""" 

4265 isGet: bool 

4266 """The request is a 'get' request.""" 

4267 isPost: bool 

4268 """The request is a 'post' request.""" 

4269 isSecure: bool 

4270 """The request is secure.""" 

4271 

4272 def params(self) -> dict: 

4273 """GET parameters.""" 

4274 

4275 def struct(self) -> dict: 

4276 """Structured JSON payload.""" 

4277 

4278 def command(self) -> str: 

4279 """Command name to execute.""" 

4280 

4281 def cookie(self, key: str, default: str = '') -> str: 

4282 """Get a cookie. 

4283 

4284 Args: 

4285 key: Cookie name. 

4286 default: Default value. 

4287 

4288 Returns: 

4289 A cookie value. 

4290 """ 

4291 

4292 def header(self, key: str, default: str = '') -> str: 

4293 """Get a header. 

4294 

4295 Args: 

4296 key: Header name. 

4297 default: Default value. 

4298 

4299 Returns: 

4300 A header value. 

4301 """ 

4302 

4303 def has_param(self, key: str) -> bool: 

4304 """Check if a GET parameter exists. 

4305 

4306 Args: 

4307 key: Parameter name. 

4308 """ 

4309 

4310 def param(self, key: str, default: str = '') -> str: 

4311 """Get a GET parameter. 

4312 

4313 Args: 

4314 key: Parameter name. 

4315 default: Default value. 

4316 

4317 Returns: 

4318 A parameter value. 

4319 """ 

4320 

4321 def env(self, key: str, default: str = '') -> str: 

4322 """Get an environment variable. 

4323 

4324 Args: 

4325 key: Variable name. 

4326 default: Default value. 

4327 

4328 Returns: 

4329 A variable value. 

4330 """ 

4331 

4332 def data(self) -> Optional[bytes]: 

4333 """Get POST data. 

4334 

4335 Returns: 

4336 Data bytes or ``None`` if request is not a POST. 

4337 """ 

4338 

4339 def text(self) -> Optional[str]: 

4340 """Get POST data as a text. 

4341 

4342 Returns: 

4343 Data string or ``None`` if request is not a POST. 

4344 """ 

4345 

4346 def content_responder(self, response: ContentResponse) -> 'WebResponder': 

4347 """Return a Responder object for a content response. 

4348 

4349 Args: 

4350 response: Response object. 

4351 

4352 Returns: 

4353 A Responder. 

4354 """ 

4355 

4356 def redirect_responder(self, response: RedirectResponse) -> 'WebResponder': 

4357 """Return a Responder object for a redirect response. 

4358 

4359 Args: 

4360 response: Response object. 

4361 

4362 Returns: 

4363 A Responder. 

4364 """ 

4365 

4366 def api_responder(self, response: Response) -> 'WebResponder': 

4367 """Return a Responder object for an Api (structured) response. 

4368 

4369 Args: 

4370 response: Response object. 

4371 

4372 Returns: 

4373 A Responder. 

4374 """ 

4375 

4376 def error_responder(self, exc: Exception) -> 'WebResponder': 

4377 """Return a Responder object for an Exception. 

4378 

4379 Args: 

4380 exc: An Exception. 

4381 

4382 Returns: 

4383 A Responder. 

4384 """ 

4385 

4386 def url_for(self, request_path: str, **kwargs) -> str: 

4387 """Return a canonical Url for the given request path. 

4388 

4389 Args: 

4390 request_path: Request path. 

4391 **kwargs: Additional GET parameters. 

4392 

4393 Returns: 

4394 An URL. 

4395 """ 

4396 

4397 def set_session(self, session: 'AuthSession'): 

4398 """Attach a session to the requester. 

4399 

4400 Args: 

4401 session: A Session object. 

4402 """ 

4403 

4404 

4405class WebResponder: 

4406 """Web Responder object.""" 

4407 

4408 status: int 

4409 """Response status.""" 

4410 

4411 def send_response(self, environ: dict, start_response: Callable): 

4412 """Send the response to the client. 

4413 

4414 Args: 

4415 environ: WSGI environment. 

4416 start_response: WSGI ``start_response`` function. 

4417 """ 

4418 

4419 def set_cookie(self, key: str, value: str, **kwargs): 

4420 """Set a cookie. 

4421 

4422 Args: 

4423 key: Cookie name. 

4424 value: Cookie value. 

4425 **kwargs: Cookie options. 

4426 """ 

4427 

4428 def delete_cookie(self, key: str, **kwargs): 

4429 """Delete a cookie. 

4430 

4431 Args: 

4432 key: Cookie name. 

4433 **kwargs: Cookie options. 

4434 """ 

4435 

4436 def set_status(self, status: int): 

4437 """Set the response status. 

4438 

4439 Args: 

4440 status: HTTP status code. 

4441 """ 

4442 

4443 def add_header(self, key: str, value: str): 

4444 """Add a header. 

4445 

4446 Args: 

4447 key: Header name. 

4448 value: Header value. 

4449 """ 

4450 

4451 

4452class WebDocumentRoot(Data): 

4453 """Web document root.""" 

4454 

4455 dir: DirPath 

4456 """Local directory.""" 

4457 allowMime: list[str] 

4458 """Allowed mime types.""" 

4459 denyMime: list[str] 

4460 """Restricted mime types.""" 

4461 

4462 

4463class WebRewriteRule(Data): 

4464 """Rewrite rule.""" 

4465 

4466 pattern: Regex 

4467 """URL matching pattern.""" 

4468 target: str 

4469 """Rule target, with dollar placeholders.""" 

4470 options: dict 

4471 """Extra options.""" 

4472 reversed: bool 

4473 """Reversed rewrite rule.""" 

4474 

4475 

4476class WebCors(Data): 

4477 """CORS options.""" 

4478 

4479 allowCredentials: bool 

4480 allowHeaders: str 

4481 allowMethods: str 

4482 allowOrigin: str 

4483 

4484 

4485class WebManager(Node): 

4486 """Web manager.""" 

4487 

4488 sites: list['WebSite'] 

4489 """Configured web sites.""" 

4490 

4491 def site_from_environ(self, environ: dict) -> 'WebSite': 

4492 """Returns a site object for the given request environment. 

4493 

4494 Args: 

4495 environ: WSGI environment. 

4496 

4497 Returns: 

4498 A Site object. 

4499 """ 

4500 

4501 

4502class WebSite(Node): 

4503 """Web site.""" 

4504 

4505 assetsRoot: Optional[WebDocumentRoot] 

4506 """Root directory for assets.""" 

4507 corsOptions: WebCors 

4508 """CORS options.""" 

4509 errorPage: Optional['Template'] 

4510 """Error page template.""" 

4511 host: str 

4512 """Host name for this site.""" 

4513 rewriteRules: list[WebRewriteRule] 

4514 """Rewrite rule.""" 

4515 staticRoot: WebDocumentRoot 

4516 """Root directory for static files.""" 

4517 

4518 def url_for(self, req: 'WebRequester', path: str, **kwargs) -> str: 

4519 """Rewrite a request path to an Url. 

4520 

4521 Args: 

4522 req: Web Requester. 

4523 path: Raw request path. 

4524 **kwargs: Extra GET params. 

4525 

4526 Returns: 

4527 A rewritten URL. 

4528 """ 

4529 

4530 def match_host(self, environ: dict) -> bool: 

4531 """Check if the site matches the request host. 

4532 

4533 Args: 

4534 environ: WSGI environment. 

4535 Returns: 

4536 True if the site matches the request host. 

4537 """ 

4538################################################################################ 

4539 

4540 

4541 

4542################################################################################ 

4543# /base/application/types.pyinc 

4544 

4545 

4546class MiddlewareManager(Node): 

4547 """Manage middleware and their dependencies.""" 

4548 

4549 def register(self, obj: Node, name: str, depends_on: Optional[list[str]] = None): 

4550 """Register an object as a middleware.""" 

4551 

4552 def objects(self) -> list[Node]: 

4553 """Return a list of registered middleware objects.""" 

4554 

4555 

4556class Application(Node): 

4557 """Main Application object.""" 

4558 

4559 client: 'Client' 

4560 """Represents the client object associated with the application.""" 

4561 

4562 localeUids: list[str] 

4563 """List of locale identifiers.""" 

4564 

4565 metadata: 'Metadata' 

4566 """Metadata for the application.""" 

4567 

4568 monitor: 'ServerMonitor' 

4569 """Server monitor object.""" 

4570 

4571 vars: dict 

4572 """Application variables.""" 

4573 

4574 version: str 

4575 """Application version as a string.""" 

4576 

4577 versionString: str 

4578 """Full version string for display purposes.""" 

4579 

4580 defaultPrinter: 'Printer' 

4581 """Default printer object.""" 

4582 

4583 actionMgr: 'ActionManager' 

4584 """Manager for application actions.""" 

4585 

4586 authMgr: 'AuthManager' 

4587 """Manager for authentication operations.""" 

4588 

4589 databaseMgr: 'DatabaseManager' 

4590 """Manager for database operations.""" 

4591 

4592 jobMgr: 'JobManager' 

4593 """Manager for handling jobs.""" 

4594 

4595 middlewareMgr: 'MiddlewareManager' 

4596 """Manager for middleware and dependencies.""" 

4597 

4598 modelMgr: 'ModelManager' 

4599 """Manager for model operations.""" 

4600 

4601 printerMgr: 'PrinterManager' 

4602 """Manager for printers.""" 

4603 

4604 searchMgr: 'SearchManager' 

4605 """Manager for search functionality.""" 

4606 

4607 serverMgr: 'ServerManager' 

4608 """Manager for server operations.""" 

4609 

4610 storageMgr: 'StorageManager' 

4611 """Manager for storage operations.""" 

4612 

4613 templateMgr: 'TemplateManager' 

4614 """Manager for templates.""" 

4615 

4616 webMgr: 'WebManager' 

4617 """Manager for web operations.""" 

4618 

4619 actions: list['Action'] 

4620 """List of defined application actions.""" 

4621 

4622 projects: list['Project'] 

4623 """List of configured projects.""" 

4624 

4625 finders: list['Finder'] 

4626 """List of finder objects.""" 

4627 

4628 templates: list['Template'] 

4629 """List of global templates.""" 

4630 

4631 printers: list['Printer'] 

4632 """List of global printer objects.""" 

4633 

4634 models: list['Model'] 

4635 """List of global models.""" 

4636 

4637 owsServices: list['OwsService'] 

4638 """List of OWS services.""" 

4639 

4640 def project(self, uid: str) -> Optional['Project']: 

4641 """Get a Project object by its uid.""" 

4642 

4643 def helper(self, ext_type: str) -> Optional['Node']: 

4644 """Get a Helper object by its extension type.""" 

4645 

4646 def developer_option(self, key: str): 

4647 """Get a value of a developer option.""" 

4648################################################################################