Coverage for gws-app/gws/spec/core.py: 100%

180 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-24 12:46 +0200

1from typing import TypeAlias, Any 

2import os 

3 

4 

5class Error(Exception): 

6 pass 

7 

8 

9class GeneratorError(Error): 

10 pass 

11 

12 

13class ReadError(Error): 

14 pass 

15 

16 

17class LoadError(Error): 

18 pass 

19 

20 

21class c: 

22 """Type kinds.""" 

23 

24 ATOM = 'ATOM' 

25 """Atomic, one of the built-in types.""" 

26 CLASS = 'CLASS' 

27 """Class, a user-defined type.""" 

28 CALLABLE = 'CALLABLE' 

29 """Callable, a callable argument.""" 

30 CONSTANT = 'CONSTANT' 

31 """Constant type.""" 

32 DICT = 'DICT' 

33 """Generic dictionary type.""" 

34 ENUM = 'ENUM' 

35 """Enum type.""" 

36 EXPR = 'EXPR' 

37 """Compile-time expression type.""" 

38 FUNCTION = 'FUNCTION' 

39 """Function, a callable type.""" 

40 LIST = 'LIST' 

41 """Generic list type.""" 

42 LITERAL = 'LITERAL' 

43 """Literal type.""" 

44 METHOD = 'METHOD' 

45 """Method, a callable type with a specific signature.""" 

46 MODULE = 'MODULE' 

47 """Module type.""" 

48 NONE = 'NONE' 

49 """None type.""" 

50 OPTIONAL = 'OPTIONAL' 

51 """Optional, a type that can be None.""" 

52 PROPERTY = 'PROPERTY' 

53 """Property, a type that is a property of a class.""" 

54 SET = 'SET' 

55 """Generic set type.""" 

56 TUPLE = 'TUPLE' 

57 """Generic tuple type.""" 

58 TYPE = 'TYPE' 

59 """Type alias.""" 

60 UNION = 'UNION' 

61 """Union, a type that can be one of several types.""" 

62 UNDEFINED = 'UNDEFINED' 

63 """Undefined, a type that is not defined.""" 

64 VARIANT = 'VARIANT' 

65 """Variant, a type that can be one of several types with a tag.""" 

66 

67 EXT = 'EXT' 

68 """Extension, a ``gws.ext`` alias.""" 

69 COMMAND = 'COMMAND' 

70 """Command, a method decorated as ``gws.ext.command``.""" 

71 

72 

73TypeKind: TypeAlias = str 

74"""Type kind, one of the constants in `c`.""" 

75TypeUid: TypeAlias = str 

76"""Type unique identifier, a string that identifies the type.""" 

77 

78 

79class Type: 

80 """Type data structure, repsents a GWS type.""" 

81 

82 c: TypeKind 

83 """Type class, one of the constants in `c`.""" 

84 uid: TypeUid 

85 """Type unique identifier, a string that identifies the type.""" 

86 

87 extName: str = '' 

88 """Name of the extension that defines this, if any.""" 

89 

90 title: str = '' 

91 """Documentation title string for the type.""" 

92 doc: str = '' 

93 """Documentation string for the type.""" 

94 ident: str = '' 

95 """Source code identifier for the type, used in the documentation.""" 

96 name: str = '' 

97 """Name of the type.""" 

98 pos: str = '' 

99 """Source code position of the type definition.""" 

100 

101 modName: str = '' 

102 """Name of the module that defines this type.""" 

103 modPath: str = '' 

104 """Path to the module that defines this type.""" 

105 

106 tArg: TypeUid = '' 

107 """For c.METHOD types, type uid of its last argument.""" 

108 tItem: TypeUid = '' 

109 """For c.LIST, c.SET and c.DICT types, type uid of its item.""" 

110 tKey: TypeUid = '' 

111 """For c.DICT types, type uid of its key.""" 

112 tModule: TypeUid = '' 

113 """Type uid of the type's module.""" 

114 tOwner: TypeUid = '' 

115 """For c.PROPERTY types, type uid of the type that owns this property.""" 

116 tReturn: TypeUid = '' 

117 """For c.METHOD types, type uid of its return value.""" 

118 tTarget: TypeUid = '' 

119 """For c.TYPE or c.EXT types, type uid of the target type.""" 

120 tValue: TypeUid = '' 

121 """For c.PROPERTY types, type uid of the constant value.""" 

122 

123 tArgs: list[TypeUid] = [] 

124 """For c.METHOD types, type uids of its arguments.""" 

125 tItems: list[TypeUid] = [] 

126 """For c.UNION or c.TUPLE types, type uids of its items.""" 

127 tSupers: list[TypeUid] = [] 

128 """For c.CLASS types, type uids of its super types.""" 

129 tMembers: dict[str, TypeUid] = {} 

130 """For c.VARIANT types, type uids of its members.""" 

131 tProperties: dict[str, TypeUid] = {} 

132 """For c.CLASS types, type uids of its properties.""" 

133 

134 defaultValue: Any = None 

135 """Default value for a property.""" 

136 defaultExpression: Any = None 

137 """Default expression for a property.""" 

138 hasDefault: bool = False 

139 """True if the type has a default value.""" 

140 constValue: Any = None 

141 """Constant value for a constant type.""" 

142 

143 enumDocs: dict = {} 

144 """Documentation strings for the enum values.""" 

145 enumValues: dict = {} 

146 """Enum values for the enum type.""" 

147 

148 literalValues: list = [] 

149 """Literal values for the c.LITERAL type.""" 

150 

151 isConfig: bool = False 

152 """True if this type is a configuration type.""" 

153 

154 

155def make_type(args: dict): 

156 typ = Type() 

157 vars(typ).update(args) 

158 return typ 

159 

160 

161class Chunk: 

162 """Source code chunk.""" 

163 

164 name: str 

165 """Name of the chunk.""" 

166 sourceDir: str 

167 """Source directory of the chunk.""" 

168 bundleDir: str 

169 """Directory to save the compiled chunk bundle.""" 

170 paths: dict[str, list[str]] 

171 """Source code paths.""" 

172 exclude: list[str] 

173 """List of patterns to exclude from the chunk.""" 

174 

175 

176class SpecData: 

177 """Specs data structure.""" 

178 

179 meta: dict 

180 """Meta data for the specs.""" 

181 chunks: list[Chunk] 

182 """List of chunks.""" 

183 serverTypes: list[Type] 

184 """List of types used by the server (configuration types, request types and commands).""" 

185 strings: dict[str, dict[str, str]] 

186 """Documentation strings, translated to multiple languages.""" 

187 

188 

189class v: 

190 """Constants for the Specs generator.""" 

191 

192 APP_NAME = 'gws' 

193 EXT_PREFIX = APP_NAME + '.ext' 

194 EXT_DECL_PREFIX = EXT_PREFIX + '.new.' 

195 EXT_CONFIG_PREFIX = EXT_PREFIX + '.config.' 

196 EXT_PROPS_PREFIX = EXT_PREFIX + '.props.' 

197 EXT_OBJECT_PREFIX = EXT_PREFIX + '.object.' 

198 EXT_COMMAND_PREFIX = EXT_PREFIX + '.command.' 

199 

200 EXT_COMMAND_API_PREFIX = EXT_COMMAND_PREFIX + 'api.' 

201 EXT_COMMAND_GET_PREFIX = EXT_COMMAND_PREFIX + 'get.' 

202 EXT_COMMAND_CLI_PREFIX = EXT_COMMAND_PREFIX + 'cli.' 

203 

204 EXT_OBJECT_CLASS = 'Object' 

205 EXT_CONFIG_CLASS = 'Config' 

206 EXT_PROPS_CLASS = 'Props' 

207 

208 CLIENT_NAME = 'gc' 

209 VARIANT_TAG = 'type' 

210 """Tag property name for Variant types.""" 

211 DEFAULT_VARIANT_TAG = 'default' 

212 """Default variant tag.""" 

213 

214 ATOMS = ['any', 'bool', 'bytes', 'float', 'int', 'str'] 

215 

216 BUILTINS = ATOMS + ['type', 'object', 'Exception', 'dict', 'list', 'set', 'tuple'] 

217 

218 BUILTIN_TYPES = [ 

219 'Any', 

220 'Callable', 

221 'ContextManager', 

222 'Dict', 

223 'Enum', 

224 'Iterable', 

225 'Iterator', 

226 'List', 

227 'Literal', 

228 'Optional', 

229 'Protocol', 

230 'Set', 

231 'Tuple', 

232 'TypeAlias', 

233 'Union', 

234 # imported in TYPE_CHECKING 

235 'datetime.datetime', 

236 'osgeo', 

237 'sqlalchemy', 

238 # vendor libs 

239 'gws.lib.vendor', 

240 'gws.lib.sa', 

241 ] 

242 

243 # those star-imported in gws/__init__.py 

244 GLOBAL_MODULES = [ 

245 APP_NAME + '.core.const', 

246 APP_NAME + '.core.util', 

247 ] 

248 

249 DEFAULT_EXT_SUPERS = { 

250 'config': APP_NAME + '.core.types.ConfigWithAccess', 

251 'props': APP_NAME + '.core.types.Props', 

252 } 

253 

254 # prefix for gws.plugin class names 

255 PLUGIN_PREFIX = APP_NAME + '.plugin' 

256 

257 # inline comment symbol 

258 INLINE_COMMENT_SYMBOL = '#:' 

259 

260 # where we are 

261 SELF_DIR = os.path.dirname(__file__) 

262 

263 # path to `/repository-root/app` 

264 APP_DIR = os.path.abspath(SELF_DIR + '/../..') 

265 

266 EXCLUDE_PATHS = ['___', '/vendor/', 'test', 'core/ext', '__pycache__'] 

267 

268 FILE_KINDS = [ 

269 ['.py', 'python'], 

270 ['/index.ts', 'ts'], 

271 ['/index.tsx', 'ts'], 

272 ['/index.css.js', 'css'], 

273 ['.theme.css.js', 'theme'], 

274 ['/strings.ini', 'strings'], 

275 ] 

276 

277 PLUGIN_DIR = '/gws/plugin' 

278 

279 SYSTEM_CHUNKS = [ 

280 [CLIENT_NAME, f'/js/src/{CLIENT_NAME}'], 

281 [f'{APP_NAME}.core', '/gws/core'], 

282 [f'{APP_NAME}.base', '/gws/base'], 

283 [f'{APP_NAME}.gis', '/gws/gis'], 

284 [f'{APP_NAME}.lib', '/gws/lib'], 

285 [f'{APP_NAME}.server', '/gws/server'], 

286 [f'{APP_NAME}.helper', '/gws/helper'], 

287 ]