def _get_list(self): hk = self.data.hash_key rk = self.data.range_key if rk is None: return None u = IndentString() n = f'{hk.cs_type_name} {hk.column_name}' u.add(f'public List<{self.record_type}> GetList({n})') u.indent('{') u.add(f'return _records[{hk.column_name}];') u.outdent('}') return u
def serial_resolver_name(self): if not self.is_serial_key: return None serial = f"'{self.table_name}_'" + f' + str(self.{self.column_name}).zfill(10)' i = IndentString() i.add('@property') i.indent('def log_id(self):') i.add(f'return {serial}') return i
def render_resolver(self): """ リゾルバの出力 :return: IndexString """ # 今の所aliasキーのリゾルバしか無い body = IndentString() for k, attr in self.data.attributes.items(): b = attr.resolver_string if b: body.add(b) return body
async def render_to_wiki(self, base_url, token_str): ToolOutput.anchor('Wiki出力を開始') wiki = GitWikiUploader(base_url, token_str) page_list = await wiki.get_page_list() page_slug_list = [v['slug'] for v in page_list] d: DefaultDict[str, List[MasterDataWikiRenderUnit]] = defaultdict(list) ToolOutput.anchor('YAML読み込み') for k, table in self.master_loader.iter(): ru = MasterDataWikiRenderUnit(table) ToolOutput.out(f'{ru.page_name} # {ru.data.excel_sheet_name}') d[ru.page_name].append(ru) ToolOutput.pop('OK') ToolOutput.anchor('書き出し') num = 1 index = MarkdownTableRenderer( ['ID', 'Book', 'Client', 'Server', 'Planner', 'Table']) for p, rus in d.items(): ToolOutput.anchor(p) u = IndentString() for r in rus: u.add(r.render()) idx = r.render_index() idx['ID'] = str(num) num += 1 index.append(idx) if p in page_slug_list: ToolOutput.print(f'{p}更新します') await wiki.update_page(content=u.render(), page_name=p) else: ToolOutput.print(f'{p}作成します') await wiki.create_page(content=u.render(), page_name=p) ToolOutput.pop('OK') ix = self.render_index(index) index_title = 'MasterData/☆INDEX☆' if index_title in page_slug_list: ToolOutput.print(f'{index_title}更新します') await wiki.update_page(content=ix.render(), page_name=index_title) else: ToolOutput.print(f'{index_title}作成します') await wiki.create_page(content=ix.render(), page_name=index_title) ToolOutput.pop('OK')
def _singleton(self): u = IndentString() # シングルトン実装 u.add(f'private static {self.data.class_name} _instance;') u.add(f'public static {self.data.class_name} Instance') u.indent('{') u.add('get') u.indent('{') u.add('if (_instance == null)') u.indent('{') u.add(f'_instance = new {self.data.class_name}();') u.outdent('}') u.add('return _instance;') u.outdent('}') u.outdent('}') return u
def render(self): u = IndentString() if self.data.is_out_desc: u.add(f'using System.ComponentModel;') u.blank_line() u.add(f'public enum Enum{self.data.full_classname}') u.indent('{') for v in self.data.values: if self.data.is_out_desc: u.add(f'{v.cs_desc}') u.add(f'{v.cs_str}') u.add(f'MAX = {len(self.data.values)},') u.outdent('}') return u
def _get(self): u = IndentString() hk = self.data.hash_key rk = self.data.range_key if rk: n = f'{hk.cs_type_name} {hk.column_name}, {rk.cs_type_name} {rk.column_name}' c = f'return _records[{hk.column_name}].Find(x => x.GetRangeKey() == {rk.column_name});' else: n = f'{hk.cs_type_name} {hk.column_name}' c = f'return _records[{hk.column_name}];' u.add(f'public {self.record_type} Get({n})') u.indent('{') u.add(f'{c}') u.outdent('}') return u
def render(self): """ 出力 :return: IndentString """ table = self.data # 継承元の決定 if table.is_alone: # solo or multi if table.range_key is not None: parent_cls_name = 'MultiHatsudenkiTable' else: parent_cls_name = 'SoloHatsudenkiTable' else: # solo or multi if table.range_key: parent_cls_name = f'{table.parent_table.class_name}, ChildMultiHatsudenkiTable' else: parent_cls_name = f'{table.parent_table.class_name}, ChildSoloHatsudenkiTable' # クラス定義 cls = IndentString(f'class {table.class_name}({parent_cls_name}):') # Metaクラス cls.add(self.render_meta()) cls.blank_line() cls.add(self.render_fields()) cls.blank_line() # Index cls.add(self.render_index()) cls.blank_line() # init cls.add(self.render_init()) cls.blank_line() # resolver cls.add(self.render_resolver()) cls.blank_line() return cls
def resolver_string(self): if not self.is_alias_key: return None if self.is_range: # 子テーブル且つレンジキーの場合はエイリアスキーとなる l = len(self.parent.tag_name) + len(TAG_SEPARATOR) parent = self.parent.parent_table parent_rk_name = parent.range_key.name body = IndentString() # getter body.add('@property') body.indent( f'def {self.name}(self) -> {self.python_value_type_str}:') body.indent(f'if self.{parent_rk_name}:') body.add( f'd = self.Meta.key_alias_type.get_data(self.{parent_rk_name}[{l}:])' ) body.outdent() body.indent('else:') body.add('d = self.Meta.key_alias_type.get_data(None)') body.outdent() body.add('d.parent = self') body.add('return d') body.outdent() body.blank_line() # setter body.add(f'@{self.name}.setter') body.indent(f'def {self.name}(self, val):') body.indent('if val is None:') body.add('return') body.outdent() body.indent('if val.is_empty():') body.add('return') body.outdent() body.add( f'self.{parent_rk_name} = f"{self.parent.tag_name}{TAG_SEPARATOR}{{val}}"' ) body.outdent() return body return None
def _find(self, is_all: bool): if self.data.range_key is None: return None u = IndentString() hk = self.data.hash_key if is_all: t = f'List<{self.record_type}>' n = 'FindAll' else: t = self.record_type n = 'Find' u.add( f'public {t} {n}({hk.cs_type_name} {hk.column_name}, Predicate<{self.record_type}> func)' ) u.indent('{') u.add(f'return _records[{hk.column_name}].{n}(func);') u.outdent('}') return u
def render(self): ToolOutput.anchor(f'{self.data.label} をMarkdownに変換') u = IndentString() u.add(f'# {self.data.excel_sheet_name}') u.add(f'## 情報') u.add(self.data.description if self.data. description else '*!! descriptionが設定されていません !!*') u.blank_line() u.add(self._gen_info().render()) u.add(f'## 担当者') u.add(self._gen_assigner().render()) u.add(f'## スキーマ情報') u.add(self._column().render()) ToolOutput.pop('OK') return u
def _model(self): u = IndentString() u.add('[MessagePackObject]') u.add(f'public class {self.record_type}') u.indent('{') keys = [c for c in self.data.columns.values() if not c.is_no_pack] keys.extend( [c for c in self.data.shadow_columns.values() if not c.is_no_pack]) args = ', '.join((c.cs_argument_name for c in keys)) u.add(f'public {self.record_type}({args})') u.indent('{') [u.add(c.cs_assign_name) for c in keys] u.outdent('}') for idx, c in enumerate(keys): if c.is_no_pack: continue u.add(f'[Key({idx})]', c.cs_define_name) hk = self.data.hash_key u.add(f'public {hk.cs_type_name} GetHashKey()') u.indent('{') u.add(f'return {hk.cs_name};') u.outdent('}') rk = self.data.range_key if rk: u.add(f'public {rk.cs_type_name} GetRangeKey()') u.indent('{') u.add(f'return {rk.cs_name};') u.outdent('}') for c in keys: if not c.is_no_pack: u.add(c.cs_access_name()) u.outdent('}') return u
def _records(self): u = IndentString() hk = self.data.hash_key rk = self.data.range_key # レコード本体 if rk: t = f'Dictionary<{hk.cs_type_name}, List<{self.record_type}>>' else: t = f'Dictionary<{hk.cs_type_name}, {self.record_type}>' u.add(f'private {t} _records = new {t}();') u.add(f'public {t} Records') u.indent('{') u.add('get') u.indent('{') u.add('return _records;') u.outdent('}') u.outdent('}') return u
def resolver_name(self): u = IndentString() u.add('@property') u.indent(f'def resolved_{self.python_name}(self):') t = self.get_target_table() if t.range_key is None: u.add(f'a = {self.get_target_table().class_name}.get(self.{self.python_name})') u.indent('if a is None:') u.add('return None') u.outdent() u.indent('if a.is_nothing:') u.add('return None') u.outdent() u.add('return a') else: u.add(f'a = {self.get_target_table().class_name}.find(self.{self.python_name})') u.indent('if len(a) > 0 and a[0].is_nothing:') u.add('return None') u.outdent() u.add('return a') return u
def _load(self): hk = self.data.hash_key u = IndentString() u.add(f'public void FinishedLoad({self.record_type}s records)') u.indent('{') u.add('_records.Clear();') u.add(f'foreach({self.record_type} rec in records.Array)') u.indent('{') u.add(f'{hk.cs_type_name} hk = rec.GetHashKey();') if self.data.range_key is None: u.add('_records.Add(hk, rec);') else: u.add('if(!_records.ContainsKey(hk))') u.indent('{') u.add(f'_records.Add(hk, new List<{self.record_type}>());') u.outdent('}') u.add('_records[hk].Add(rec);') u.outdent('}') u.outdent('}') return u
def render(self, name): hash_key = next((v for k, v in self.attributes.items() if v.is_hash)) u = IndentString() u.indent(f'class {name}(MarkedObjectWithIndex):') u.indent('class Meta:') u.add(f"hash_key = '{hash_key.name}'") u.outdent() u.blank_line() u.indent('class Field:') for k, v in self.attributes.items(): u.add(v.class_string) u.add(v.gen_def_str()) u.outdent() u.blank_line() u.indent('def __init__(self, name, parent: Markable, **kwargs):') u.add('super().__init__(name, parent)') u.add('ft = self.__class__.Field') for k, v in self.attributes.items(): u.add(v.gen_init_str(direct_assign=False)) u.add('') return u
def render(self, name): """ クラス出力 :param name: フィールド名 :return: IndentString """ u = IndentString() u.indent(f'class {name}(MarkedObject):') u.indent('class Field:') for k, v in self.attributes.items(): u.add(v.class_string) u.add(v.gen_def_str()) u.outdent() u.blank_line() u.indent('def __init__(self, name, parent: Markable, **kwargs):') u.add('super().__init__(name, parent)') u.add('ft = self.__class__.Field') for k, v in self.attributes.items(): u.add(v.gen_init_str(direct_assign=False)) u.add('') return u
def _repository(self): u = IndentString() u.add(f'public class {self.data.class_name}') u.indent('{') u.add(f'public const string TableName = "{self.data.table_name}";') # シングルトン実装 u.add(self._singleton()) # コンストラクタ u.add(f'private {self.data.class_name}() {{ }}') # レコード本体 u.add(self._records()) # 一件取得 u.add(self._get()) u.add(self._get_list()) # find u.add(self._find(is_all=False)) u.add(self._find(is_all=True)) # filter u.add(self._filter(is_all=False)) u.add(self._filter(is_all=True)) # loader u.add(self._load()) u.add(f'public void Release()') u.indent('{') u.add('_records.Clear();') u.add('_records = null;') u.add('_instance = null;') u.outdent('}') u.outdent('}') return u
def render_units(self): u = IndentString() [u.add(un.render()) for un in self.units] return u
def render(self) -> IndentString: return IndentString()
def render_index(self, index: MarkdownTableRenderer): ToolOutput.anchor('目次') u = IndentString() u.add('# MasterData目次') u.add(index.render()) return u
def render_index(self): """ インデックス情報の出力 :return: IndexString """ table = self.data # 単一か子かによって継承元が変わる is_alone = table.is_alone if is_alone: # 個別 lsi_class_str = IndentString('class LSIndex:') gsi_class_str = IndentString('class GSIndex:') else: # 子 pn = table.parent_table.class_name lsi_class_str = IndentString(f'class LSIndex({pn}.LSIndex):') gsi_class_str = IndentString(f'class GSIndex({pn}.LSIndex):') # インデックスは複数件あるのでループ for idx in table.indexes: opt = {} opt['projection_keys'] = idx.get('projection', []) # LSI or GSI if idx['type'] == 'global': # GSIはhashキーとrangeキーとキャパシティユニット opt['hash_key'] = idx['hash'] # インデックス名はgsi__{hash}__{range} opt['name'] = f'gsi_{idx["hash"]}' if 'range' in idx: opt['range_key'] = idx['range'] opt['name'] += '__' + idx['range'] # キャパシティユニット caps = idx.get('capacity_units', {}) if 'capacity_units' in caps: c = caps['capacity_units'] opt['read_cap'] = c['read'] opt['write_cap'] = c['write'] else: opt['read_cap'] = 1 opt['write_cap'] = 1 s = ', '.join((f'{k}={json.dumps(v)}' for k, v in opt.items())) gsi_class_str.add(f'{opt["name"]} = GSI({s})') else: # LSIはrangeキーのみ opt['name'] = f'lsi_{idx["range"]}' opt['range_key'] = idx['range'] # 処理の都合上PrimaryのHashキーを便宜上のhashキーとして登録する if is_alone: opt['hash_key'] = table.hash_key.name else: # 子テーブルの場合はPrimaryキーを親テーブルから引く opt['hash_key'] = table.parent_table.hash_key.name s = ', '.join((f'{k}={json.dumps(v)}' for k, v in opt.items())) lsi_class_str.add(f'{opt["name"]} = LSI({s})') # LSIが一つもない場合はpass if lsi_class_str.line_num is 1: lsi_class_str.add('pass') # GSIが一つもない場合はpass if gsi_class_str.line_num is 1: gsi_class_str.add('pass') body = IndentString() body.add(lsi_class_str, gsi_class_str) return body
def _filter(self, is_all: bool): u = IndentString() hk = self.data.hash_key if is_all: t = f'List<{self.record_type}>' n = 'FilterAll' fn = 'FindAll' else: t = self.record_type n = 'Filter' fn = 'Find' u.add(f'public {t} {n}(Predicate<{self.record_type}> func)') u.indent('{') if is_all: u.add( f'List<{self.record_type}> ret = new List<{self.record_type}>();' ) if self.data.range_key is None: u.add( f'foreach(KeyValuePair<{hk.cs_type_name}, {self.record_type}> l in _records)' ) else: u.add( f'foreach(KeyValuePair<{hk.cs_type_name}, List<{self.record_type}>> l in _records)' ) u.indent('{') if is_all: if self.data.range_key is None: u.add(f'{self.record_type} v = l.Value;') u.add('if(func(v))') u.indent('{') u.add('ret.Add(v);') u.outdent('}') u.outdent('}') u.add('return ret;') else: u.add(f'List<{self.record_type}> v = l.Value;') u.add(f'List<{self.record_type}> t = v.FindAll(func);') u.add('if(t.Count > 0)') u.indent('{') u.add('ret.AddRange(t);') u.outdent('}') u.outdent('}') u.add('return ret;') else: if self.data.range_key is None: u.add(f'{self.record_type} v = l.Value;') u.add('if(func(v))') u.indent('{') u.add('return v;') u.outdent('}') u.outdent('}') u.add('return null;') else: u.add(f'List<{self.record_type}> v = l.Value;') u.add(f'{self.record_type} t = v.Find(func);') u.add('if( t != null )') u.indent('{') u.add('return t;') u.outdent('}') u.outdent('}') u.add('return null;') u.outdent('}') return u
def render_header(self): u = IndentString() u.add('using System;') u.add('using System.Collections.Generic;') u.add('using MessagePack;') return u
def render(self): body = IndentString() body.add(self.render_header()) body.add(self.render_units()) return body.render()