def create(cls, table_name: str, key_name: str, data: dict, master_loader): try: type = data['type'] return cls._type_table[type](table_name, key_name, data, master_loader) except Exception as e: ToolOutput.out_error(f'columnの生成に失敗 table={table_name}, key={key_name}') raise e
def render_enum_python(self, out_python_path: Path, enum_loader: EnumLoader): ToolOutput.anchor('generate python enum code...') out_enum_path = out_python_path / 'def_enum.py' pr = PythonEnumRenderer() for p, d in enum_loader.iter(): pr.add_unit(PythonEnumRenderUnit(d)) write_file(out_enum_path, pr.render()) ToolOutput.pop('OK')
def render_units(self): ToolOutput.anchor('Wiki出力を開始') u = IndentString() for k, table in self.master_loader.iter(): un = MasterDataWikiRenderUnit(table).render() u.add(un) ToolOutput.pop('OK') return u
def setup(self, dir_name=''): super().setup(dir_name) ToolOutput.anchor('MasterExcelを準備します') d = defaultdict(dict) for k, v in self.iter(): self.ref_table_name[v.table_name] = v d[v.excel_name][v.excel_sheet_name] = v self.ref_excel_name = dict(d) ToolOutput.pop()
async def handle(self, *args, **options): ToolOutput.anchor('Generate Excel...') in_path = Path(options['dsl_path']) out_path = Path(options['out']) in_master_path = in_path / 'master' in_enum_path = in_path / 'enum' in_dynamo_path = in_path / 'dynamo' out_excel_path = out_path / 'excel' out_python_path = out_path / 'python' if options['clean']: self.clean(out_excel_path, out_python_path) enum_loader = self.load_enum_yaml(in_enum_path) master_loader = self.load_master_yaml(in_master_path, enum_loader) self.render_master_excel(out_excel_path, master_loader) # CSモデルの書き出し # out_cs_path = options.get('out_cs_path', None) # if out_cs_path: # cs_model_path = Path(out_cs_path) # ToolOutput.anchor('generate cs model...') # for name, table in master_loader.iter(): # if not table.is_out_pack: # continue # p = cs_model_path / (table.class_name + '.cs') # r = MasterCSModelRenderer() # r.add_unit(MasterCSModelRenderUnit(table)) # write_file(p, r.render()) # ToolOutput.pop('OK') self.render_enum_excel(out_excel_path, enum_loader, master_loader) # pythonモデル&データストアの書き出し self.render_master_python(out_python_path, master_loader) # generate python master models. self.render_enum_python(out_python_path, enum_loader) self.render_dynamo(in_dynamo_path, out_python_path) # generate cs master models. # if out_cs_path: # ToolOutput.anchor('generate cs master models...') # out_cs_enum_path = Path(out_cs_path) / 'enums' # for p, d in enum_loader.iter(): # cs = CSEnumRenderer() # cs.add_unit(CSEnumRenderUnit(d)) # write_file(out_cs_enum_path / ('Enum' + d.full_classname + '.cs'), cs.render()) # ToolOutput.pop('OK') ToolOutput.pop('all done!')
def __init__(self, book: 'MasterExcel', sheet: Worksheet, formula_sheet: Worksheet, table: MasterTable, loader): from hatsudenki.packages.command.master.exporter.loader import MasterExcelLoader self.sheet = sheet self.formula_sheet = formula_sheet self.table = table self.loader: MasterExcelLoader = loader ToolOutput.out( f'[MasterExcel]Sheet準備 {self.sheet.title} = {table.table_name}') self.book = book self.resolved_headers = self._resolve_headers() self.datas: Dict[str, Dict[str, Tuple[MasterColumn, any]]] = self._resolve()
def __init__(self, base_path: Path, full_path: Path, table_data: Dict[str, MasterTable], loader, *args, **kwargs): from hatsudenki.packages.command.master.exporter.loader import MasterExcelLoader super().__init__(base_path, full_path, *args, **kwargs) self.data = MasterExcelData(Path(full_path)) self.table = table_data self.loader: MasterExcelLoader = loader self.table_sheets: Dict[str, MasterExcelSheet] = {} ToolOutput.anchor(f'{self.data.name} をよみこみます') for sheet in self.data.iter_table_sheet(): if sheet.title not in self.table: continue self.table_sheets[sheet.title] = self._create_sheet(sheet) ToolOutput.pop('OK')
def render_master_excel(self, out_excel_path: Path, master_loader: MasterTableLoader): ToolOutput.anchor('generate excel books...') for excel_name, sheet_list in master_loader.ref_excel_name.items(): ToolOutput.anchor(f'{excel_name}') book = MasterExcelBook(out_excel_path / (excel_name + '.xlsx'), sheet_list) ToolOutput.pop() book.save_file() ToolOutput.pop('OK')
def add_table(self, table_data: List[dict]): ToolOutput.anchor(f'{self.book.path.name} {self.sheet.title}にレストア') r = self.sheet.rows headers = next(r) idxes = [h.value for h in headers] self.sheet.delete_rows(2, self.sheet.max_row - 1) for d in table_data: dd = [] for idx in idxes: if idx == 'TAG': # TAGは出力されないので強制的に0入れる dd.append(0) continue dd.append(d.get(idx, None)) self.sheet.append(dd) ToolOutput.pop('OK')
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 cli(): # 引数の処理 parser = get_args() args = parser.parse_args() if hasattr(args, 'handler'): s = vars(args) # quietがセットされていない場合はToolのロガーをセットアップする if not s.get('quiet'): ToolOutput.setup() acv = asyncio.get_event_loop() try: # commandの実行 acv.run_until_complete(args.handler(*sys.argv, **s)) except: print_exc() else: # helpの表示(一応) parser.print_help()
def _load(self, path: Path): tbl_name = path.name.replace('.yml', '') ToolOutput.anchor(f'"{path}:1" をロード') table = self.master_loader.get_by_table_name(tbl_name) if table is None: ToolOutput.pop(f'みつからない {tbl_name}') return None a = MasterDataYaml(self.base_path, path, table, self) ToolOutput.pop('OK') return a
def clean(self, excel_path: Path, python_path: Path): ToolOutput.anchor('出力フォルダをクリア') ToolOutput.anchor('cleaning excel directory...') for book_file in excel_path.glob('*.xlsx'): ToolOutput.out(str(book_file)) book_file.unlink() ToolOutput.pop('OK') ToolOutput.anchor('cleaning output python directory...') p = python_path / 'def_enum.py' if p.exists(): p.unlink() p = python_path / 'masters.py' if p.exists(): p.unlink() ToolOutput.pop('OK') ToolOutput.print_with_pop('OK')
def setup(self, dir_name=''): ToolOutput.out(f'[{self.__class__.__name__}] setup...') self.datas = { Path(unicodedata.normalize('NFC', str(path))): None for path in (self.base_path / dir_name).glob('**/*' + self.ext) }
def _generate_table_sheets(self): """ マスターテーブルに対応するシートを生成 """ origin = 0 self.sort_dict = {} # 所属するテーブルでループ for idx, (sheet_name, table) in enumerate(self.table_infos.items()): ToolOutput.anchor(f'[{sheet_name}]シート作成開始...') if sheet_name in self.book.sheetnames: # すでに対応するシートが存在する sheet = self.book[sheet_name] old_header = self.get_header_values(sheet_name) self.sort_dict[sheet_name] = table.data[ 'priority'] if 'priority' in table.data else 0 else: sheet = self.book.create_sheet(sheet_name, origin + idx) ToolOutput.out(f'[{sheet_name}]シート を追加します') old_header = {} self.sort_dict[sheet_name] = table.data[ 'priority'] if 'priority' in table.data else 0 tail_coord = old_header.get('TAG', 'A1') # カラム列の生成 for idx_2, (k, c) in enumerate(table.columns.items()): # すでに列が存在するか? coord = old_header.get(c.excel_raw_header_name, None) if coord is None: # 新規に追加された列である ToolOutput.out( f'{c.excel_raw_header_name} 列が[{tail_coord}]に追加されました') row_idx, col_idx = coordinate_to_tuple(tail_coord) sheet.insert_cols(col_idx, 1) cell = sheet[tail_coord] tail_coord = cell.offset(row=0, column=1).coordinate else: cell = sheet[coord] cell.style = CellStyle.RED.name # 特殊なカラムの処理 if c.is_no_pack: # packに出力しない列 cell.style = CellStyle.GREEN.name if c.is_relation: # 参照が設定されている列 cell.value = c.excel_header_name cell.font = Font(name="Meiryo UI", size=10, underline="single", color=Color(rgb=None, indexed=None, auto=None, theme=10, tint=0.0, type="theme")) else: # 普通の列 cell.value = c.excel_header_name ToolOutput.pop('OK') cell = sheet[tail_coord] cell.style = CellStyle.BLUE.name cell.value = 'TAG'
def render_master_python(self, out_python_path: Path, master_loader: MasterTableLoader): ToolOutput.anchor('generate master python code...') model_renderer = MasterModelRenderer(master_loader) write_file(out_python_path / 'masters.py', model_renderer.render()) ToolOutput.pop()
def render_enum_excel(self, out_excel_path: Path, enum_loader: EnumLoader, master_loader: MasterTableLoader): ToolOutput.anchor('generate enum excel...') enum_book = EnumExcelBook(out_excel_path / 'pg_excel' / '定義タイプ.xlsx', enum_loader, master_loader) enum_book.save_file() ToolOutput.pop('OK')
async def handle(self, *args, **options): # 引数解析 in_path = Path(options.get('in')) out_path = Path(options.get('out')) dsl_path = Path(options.get('dsl_path')) target_tag: str = options.get('tag') enable_debug = options.get('debug', False) ToolOutput.print( f'dump master yaml... tag={target_tag} debug={enable_debug}', False) ToolOutput.out(f'parameter {in_path}, {out_path}, tag={target_tag}') # 出力TAG tag_loader = MasterTagLoader(dsl_path / 'define' / 'master_tag.yml') tag_loader.load() # TAG情報を取得 out_tag = tag_loader.get_tag(target_tag) if out_tag is None: raise Exception(f'出力タグ {target_tag} は定義されていません!') if out_tag.is_only: ToolOutput.out(f'onlyモードで出力します include={out_tag.include}') enum_path = dsl_path / 'enum' master_schema_path = dsl_path / 'master' master_excel_path = in_path out_raw_yaml_path = out_path / 'raw_yaml' # Enum準備 ToolOutput.print_with_anchor('enum準備') enum_loader = EnumLoader(enum_path) enum_loader.setup() ToolOutput.print_with_pop('OK') # スキーマパース ToolOutput.print_with_anchor('masterスキーマ準備') master_loader = MasterTableLoader(master_schema_path, enum_loader) master_loader.setup() ToolOutput.print_with_pop('OK') # Excel読み込み ToolOutput.print_with_anchor('excel準備') excel_loader = MasterExcelLoader(master_excel_path, master_loader, tag_loader) excel_loader.set_out_level(out_tag) excel_loader.set_debug_flg(enable_debug) excel_loader.setup() ToolOutput.print_with_pop('OK') # cleanフラグが設定されている場合は掃除する if options.get('clean', False): recreate_dir(out_raw_yaml_path) # YAML書き出し self.generate_yaml(excel_loader, out_raw_yaml_path, out_tag)
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 render_index(self, index: MarkdownTableRenderer): ToolOutput.anchor('目次') u = IndentString() u.add('# MasterData目次') u.add(index.render()) return u
def load_enum_yaml(self, in_enum_path: Path): ToolOutput.anchor('loading enum yaml files...') enum_loader = EnumLoader(in_enum_path) enum_loader.setup() ToolOutput.pop('OK') return enum_loader
def load_master_yaml(self, in_master_path: Path, enum_loader: EnumLoader): ToolOutput.anchor('loading master yaml files...') master_loader = MasterTableLoader(in_master_path, enum_loader) master_loader.setup() ToolOutput.pop('OK') return master_loader
def write_file(out_path: Path, data: str, mode: str = 'w'): ToolOutput.print(f'write to {out_path}', False) out_path.parent.mkdir(parents=True, exist_ok=True) with out_path.open(mode=mode, encoding='utf-8') as file: file.write(data)