Coverage for gws-app/gws/spec/generator/base.py: 83%

99 statements  

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

1from typing import Optional 

2import sys 

3 

4from .. import core 

5from . import util 

6 

7c = core.c 

8v = core.v 

9Error = core.Error 

10GeneratorError = core.GeneratorError 

11LoadError = core.LoadError 

12ReadError = core.ReadError 

13Type = core.Type 

14 

15 

16class Data: 

17 def __init__(self, **kwargs): 

18 vars(self).update(kwargs) 

19 

20 def __repr__(self): 

21 return repr(vars(self)) 

22 

23 def get(self, k, default=None): 

24 return vars(self).get(k, default) 

25 

26 def __getattr__(self, item): 

27 return None 

28 

29 

30class _Logger: 

31 level = 'INFO' 

32 levels = 'ERROR', 'WARNING', 'INFO', 'DEBUG' 

33 

34 def set_level(self, level): 

35 self.level = level 

36 

37 def log(self, level, *args): 

38 if self.levels.index(level) <= self.levels.index(self.level): 

39 msg = f'[spec] {level}: ' + ' '.join(str(a) for a in args) 

40 sys.stdout.write(msg + '\n') 

41 sys.stdout.flush() 

42 

43 def error(self, *args): 

44 self.log('ERROR', *args) 

45 

46 def warning(self, *args): 

47 self.log('WARNING', *args) 

48 

49 def info(self, *args): 

50 self.log('INFO', *args) 

51 

52 def debug(self, *args): 

53 self.log('DEBUG', *args) 

54 

55 

56log = _Logger() 

57 

58 

59class Generator: 

60 def __init__(self): 

61 self.aliases: dict[str, str] = {} 

62 self.chunks: list[core.Chunk] = [] 

63 self.meta: dict = {} 

64 self.typeDict: dict[str, Type] = {} 

65 self.serverTypes: list[Type] = [] 

66 self.specData: core.SpecData 

67 self.configRef = {} 

68 self.strings = {} 

69 self.manifestPath = '' 

70 self.outDir = '' 

71 self.rootDir = '' 

72 self.selfDir = '' 

73 self.typescript = '' 

74 self.debug = False 

75 

76 def add_type(self, **kwargs): 

77 if kwargs.get('name'): 

78 kwargs['uid'] = kwargs['name'] 

79 if not kwargs.get('uid'): 

80 kwargs['uid'] = kwargs['c'] + ':' + _auto_uid(kwargs) 

81 typ = core.make_type(kwargs) 

82 self.typeDict[typ.uid] = typ 

83 return typ 

84 

85 def get_type(self, uid) -> Optional[Type]: 

86 return self.typeDict.get(uid) 

87 

88 def require_type(self, uid) -> Type: 

89 typ = self.typeDict.get(uid) 

90 if not typ: 

91 raise GeneratorError(f'unknown type {uid!r}') 

92 return typ 

93 

94 def dump(self, tag): 

95 if self.debug: 

96 util.write_json(self.outDir + '/' + tag + '.debug.json', vars(self)) 

97 

98 

99def _auto_uid(args): 

100 tc = args['c'] 

101 if tc == c.DICT: 

102 return args['tKey'] + ',' + args['tValue'] 

103 if tc == c.LIST: 

104 return args['tItem'] 

105 if tc == c.SET: 

106 return args['tItem'] 

107 if tc == c.LITERAL: 

108 return _comma(repr(v) for v in args['literalValues']) 

109 if tc == c.OPTIONAL: 

110 return args['tTarget'] 

111 if tc == c.TUPLE: 

112 return _comma(args['tItems']) 

113 if tc == c.UNION: 

114 return _comma(sorted(args['tItems'])) 

115 if tc == c.CALLABLE: 

116 return _comma(sorted(args['tItems'])) 

117 if tc == c.EXT: 

118 return args['extName'] 

119 if tc == c.VARIANT: 

120 if 'tMembers' in args: 

121 return _comma(sorted(args['tMembers'].values())) 

122 return _comma(sorted(args['tItems'])) 

123 raise GeneratorError(f'auto uid for {tc!r} not implemented: {args}') 

124 

125 

126_comma = ','.join