Coverage for gws-app/gws/spec/generator/main.py: 77%
100 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-16 22:59 +0200
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-16 22:59 +0200
1import os
3from .. import core
4from . import base, configref, manifest, normalizer, parser, extractor, strings, typescript, util
6Error = base.Error
9def generate_and_write(root_dir='', out_dir='', manifest_path='', debug=False):
10 base.log.set_level('DEBUG' if debug else 'INFO')
12 gen = _run_generator(root_dir, out_dir, manifest_path, debug)
14 to_path(gen.specData, out_dir + '/specs.json')
16 util.write_file(gen.outDir + '/gws.generated.ts', gen.typescript)
18 util.write_file(gen.outDir + '/configref.en.md', gen.configRef['en'])
19 util.write_file(gen.outDir + '/configref.de.md', gen.configRef['de'])
22def generate(manifest_path='') -> core.SpecData:
23 gen = _run_generator(manifest_path=manifest_path)
24 return gen.specData
27def to_path(specs: core.SpecData, path: str):
28 util.write_json(
29 path,
30 {
31 'meta': specs.meta,
32 'chunks': specs.chunks,
33 'serverTypes': specs.serverTypes,
34 'strings': specs.strings,
35 },
36 )
37 return path
40def from_path(path: str) -> core.SpecData:
41 d = util.read_json(path)
42 s = core.SpecData()
43 s.meta = d['meta']
44 s.chunks = [core.Chunk(**c) for c in d['chunks']]
45 s.serverTypes = [core.make_type(t) for t in d['serverTypes']]
46 s.strings = d['strings']
47 return s
50def _run_generator(root_dir='', out_dir='', manifest_path='', debug=False):
51 gen = base.Generator()
52 gen.rootDir = root_dir or base.v.APP_DIR
53 gen.outDir = out_dir
54 gen.selfDir = base.v.SELF_DIR
55 gen.debug = debug
56 gen.manifestPath = manifest_path
58 _init_generator(gen)
59 gen.dump('000_init')
61 parser.parse(gen)
62 gen.dump('001_parsed')
64 normalizer.normalize(gen)
65 gen.dump('002_normalized')
67 extractor.extract(gen)
68 gen.dump('003_extracted')
70 gen.typescript = typescript.create(gen)
71 gen.strings = strings.collect(gen)
73 gen.configRef['en'] = configref.create(gen, 'en')
74 gen.configRef['de'] = configref.create(gen, 'de')
76 gen.specData = core.SpecData()
77 gen.specData.meta = gen.meta
78 gen.specData.chunks = gen.chunks
79 gen.specData.serverTypes = gen.serverTypes
80 gen.specData.strings = gen.strings
82 return gen
85def _init_generator(gen: base.Generator):
86 gen.meta = {
87 'version': util.read_file(gen.rootDir + '/VERSION').strip(),
88 'manifestPath': None,
89 'manifest': None,
90 }
92 def _chunk(name, source_dir, bundle_dir):
93 cc = core.Chunk()
94 cc.name = name
95 cc.sourceDir = source_dir
96 cc.bundleDir = bundle_dir
97 cc.paths = {kind: [] for _, kind in base.v.FILE_KINDS}
98 cc.exclude = []
99 return cc
101 gen.chunks = []
103 for name, path in base.v.SYSTEM_CHUNKS:
104 cc = _chunk(
105 name,
106 gen.rootDir + path,
107 base.v.APP_DIR,
108 )
109 gen.chunks.append(cc)
111 manifest_plugins = None
113 if gen.manifestPath:
114 try:
115 base.log.debug(f'loading manifest {gen.manifestPath!r}')
116 gen.meta['manifestPath'] = gen.manifestPath
117 gen.meta['manifest'] = manifest.from_path(gen.manifestPath)
118 except Exception as exc:
119 raise base.GeneratorError(f'error loading manifest {gen.manifestPath!r}') from exc
120 manifest_plugins = gen.meta['manifest'].get('plugins')
122 plugin_dict = {}
124 # our plugins
125 for path in util.find_dirs(gen.rootDir + base.v.PLUGIN_DIR):
126 name = os.path.basename(path)
127 cc = _chunk(
128 base.v.PLUGIN_PREFIX + '.' + name,
129 path,
130 path,
131 )
132 plugin_dict[cc.name] = cc
134 # manifest plugins
135 for p in manifest_plugins or []:
136 path = p.get('path')
137 name = p.get('name') or os.path.basename(path)
138 if not os.path.isdir(path):
139 raise base.GeneratorError(f'error loading plugin {name!r}: directory {path!r} not found')
140 cc = _chunk(
141 base.v.PLUGIN_PREFIX + '.' + name,
142 path,
143 path,
144 )
145 plugin_dict[cc.name] = cc
147 gen.chunks.extend(plugin_dict.values())
149 for chunk in gen.chunks:
150 if not os.path.isdir(chunk.sourceDir):
151 continue
153 excl = base.v.EXCLUDE_PATHS + (chunk.exclude or [])
155 for path in util.find_files(chunk.sourceDir):
156 if any(x in path for x in excl):
157 continue
158 for pattern, kind in base.v.FILE_KINDS:
159 if path.endswith(pattern):
160 chunk.paths[kind].append(path)
161 break
163 root_cc = _chunk(
164 'gws',
165 gen.rootDir + '/gws',
166 gen.rootDir + '/gws',
167 )
168 root_cc.paths['python'] = [gen.rootDir + '/gws/__init__.py']
169 gen.chunks.insert(0, root_cc)