def proc(self, context: CommandContext): """ メイン処理を行います。 context.get_rows()を呼び出して、データ行を取得しながら、 データ加工を行ってください。 渡されてくるデータは、イテレータの場合もあるので、次に 引き継ぐために、context.set_rows()で、データを引き渡してください。 """ # 次へ引き渡す行 rows = [row for row in context.get_rows()] if len(rows) == 0: return rows if type(rows[0]) == Row: rows = [row.raw() for row in rows] output_path = self.__params.output.format(**rows[0]) # テンプレートを適用 result = self.__template.render(rows=rows, args=self.__params.args) with open(output_path, 'w') as f: f.write(result) # 次のコマンドへ引渡し context.set_rows(rows)
def proc(self, context: CommandContext): """ メイン処理を行います。 context.get_rows()を呼び出して、データ行を取得しながら、 データ加工を行ってください。 渡されてくるデータは、イテレータの場合もあるので、次に 引き継ぐために、context.set_rows()で、データを引き渡してください。 """ rows = [] for row in context.get_rows(): if type(row) == Row: rows.append(objdict(row.raw())) else: rows.append(objdict(row)) local = { 'input_rows': rows, 'output_rows': [], 'args': self.__params.args } # スクリプトの実行を行う try: exec(self.__script, self.__modules, local) except Exception as e: logger.error(e) raise e # 次のコマンドへ引渡し context.set_rows(local['output_rows'])
def proc(self, context: CommandContext): targets = self.__args.target_keys newRows = [Row(row) for row in context.get_rows()] if len(newRows) == 0: return rowColumns = [len(r.keys()) for r in newRows] index = rowColumns.index(max(rowColumns)) if len(newRows) == 0: return if len(targets) == 0: targets = newRows[index].keys() table = prettytable.PrettyTable(targets) # アラインの設定 for key in targets: val = newRows[0].get(key) table.align[key] = 'l' if type(val) == int: table.align[key] = 'r' if type(val) == bool: table.align[key] = 'c' for row in newRows: table.add_row([row.get(target) for target in targets]) print(table) context.set_rows(newRows)
def init(self, context: CommandContext): # パラメータを取得する self.__params = context.get_parameters() self.__rows = [] context.set_supplier(self) self.__has_data = True try: dataType = self.__params.data_type if dataType == 'csv': lines = self.__params.data.split('\n') head = [x.rstrip() for x in lines[0].split(',')] data = [line for line in lines[1:] if not line.strip() == ""] for row in data: row = [x.rstrip() for x in row.split(',')] newData = {} for i in range(len(head)): newData[head[i]] = row[i] self.__rows.append(newData) if dataType == 'json': self.__rows = json.loads(self.__params.data) if dataType == 'yaml': self.__rows = yaml.load(self.__params.data) if dataType == 'object': if type(self.__params.data) == list: self.__rows = self.__params.data else: logger.error('データ型がlist構造になっていません') except Exception as e: logger.error(e) raise e
def proc(self, context: CommandContext): """ メイン処理を行います。 context.get_rows()を呼び出して、データ行を取得しながら、 データ加工を行ってください。 渡されてくるデータは、イテレータの場合もあるので、次に 引き継ぐために、context.set_rows()で、データを引き渡してください。 """ # 次へ引き渡す行 rows = [] for row in iter(context.get_rows()): # Rowラッパーに変換 row = Row(row) if self.__write_header == False: self.__write_header = True headers = self.__params.headers if len(self.__params.headers) == 0: headers = row.keys() self.__headers = headers if self.__params.header: self.__writer.writerow(headers) rows.append(row) # 行を追加 self.__writer.writerow([row.get(x) for x in self.__headers]) # 次のコマンドへ引渡し context.set_rows(rows)
def proc(self, context: CommandContext): rows = [] sql = self.__params.main_sql # Rowラッパーに変換 rows = [] if self.__params.batch_count <= 0: # まとめてインサート rows = [Row(row) for row in context.get_rows()] if len(rows) > 0: self.__dbService.execute_updates(self.__cursor, sql, rows) self.__db.commit() logger.info(f"executed {len(rows)} parameters..") else: # 指定件数ずつまとめて実行 insRows = [] for row in context.get_rows(): insRows.append(Row(row)) if len(insRows) == self.__params.batch_count: rows = rows + insRows self.__dbService.execute_updates(self.__cursor, sql, insRows) logger.info(f"executed {len(insRows)} parameters.") insRows = [] self.__db.commit() if len(insRows) > 0: rows = rows + insRows self.__dbService.execute_updates(self.__cursor, sql, insRows) logger.info(f"executed {len(insRows)} parameters.") # 次のコマンドへ引渡し context.set_rows(rows)
def init(self, context: CommandContext): """ スクリプト読み込み後に、利用するコマンドの初期化時に呼び出れます。 context.get_parameters()で、スクリプトに記述されたコマンドパラメータ を取得することができます。 """ # このコマンドがデータを供給する宣言 context.set_supplier(self) # フェッチサイズの指定 self.set_fetch_size(0)
def init(self, context: CommandContext): """ スクリプト読み込み後に、利用するコマンドの初期化時に呼び出れます。 context.get_parameters()で、スクリプトに記述されたコマンドパラメータ を取得することができます。 """ # パラメータを取得する( self.__params.プロパティ名 でアクセス可能) self.__params = context.get_parameters() # 正規表現オプションを構築 option = 0 for opt in self.__params.match_options: if opt == 'verbose': option |= re.VERBOSE elif opt == 'multiline': option |= re.MULTILINE elif opt == 'dotall': option |= re.DOTALL elif opt == 'ignore': option |= re.IGNORECASE # 正規表現をコンパイルする reg = re.compile(parse_easy_regexp(self.__params.pattern), option) self.__reg = reg
def init(self, context: CommandContext): """ スクリプト読み込み後に、利用するコマンドの初期化時に呼び出れます。 context.get_parameters()で、スクリプトに記述されたコマンドパラメータ を取得することができます。 """ # パラメータを取得する( self.__params.プロパティ名 でアクセス可能) self.__params = context.get_parameters() # ファイルをオープンする logger.info(f"open file for csv write {self.__params.file_path}") self.__open_file = open(self.__params.file_path, 'w', encoding=self.__params.encoding) # 区切り文字を決定 delimiter = "," if self.__params.delimiter == "tab": delimiter = "\t" if self.__params.delimiter == "semi": delimiter = ";" # 書き込みオブジェクトを作成 self.__writer = csv.writer(self.__open_file, delimiter=delimiter, doublequote=self.__params.doublequote, escapechar=self.__params.escape_char, quotechar=self.__params.quotechar) self.__write_header = False
def init(self, context: CommandContext): """ スクリプト読み込み後に、利用するコマンドの初期化時に呼び出れます。 context.get_parameters()で、スクリプトに記述されたコマンドパラメータ を取得することができます。 """ # パラメータを取得する( self.__params.プロパティ名 でアクセス可能) self.__params = context.get_parameters()
def init(self, context: CommandContext): # パラメータを取得する self.__params = context.get_parameters() # データベースサービスを取得 self.__dbService = cast(DatabaseService, services.get_service('database')[0]) # アクセスしたいDB名を指定してDBインスタンスを取得 logger.info(f"open database {self.__params.db_name}") self.__db = self.__dbService.open(self.__params.db_name) self.__cursor = self.__dbService.cursor(self.__db) # 事前の処理を実施 for sql in self.__params.init_sql.split(";"): sql = sql.strip() self.__dbService.execute(self.__cursor, sql, context.get_script_parameters())
def init(self, context: CommandContext): """ スクリプト読み込み後に、利用するコマンドの初期化時に呼び出れます。 context.get_parameters()で、スクリプトに記述されたコマンドパラメータ を取得することができます。 """ # パラメータを取得する( self.__params.プロパティ名 でアクセス可能) self.__params = context.get_parameters() # このコマンドがデータを供給するならコメントアウト # context.set_supplier(self) self.__template = Template(self.__params.template)
def proc(self, context: CommandContext): """ メイン処理を行います。 context.get_rows()を呼び出して、データ行を取得しながら、 データ加工を行ってください。 渡されてくるデータは、イテレータの場合もあるので、次に 引き継ぐために、context.set_rows()で、データを引き渡してください。 """ # 次へ引き渡す行 rows = [] for row in iter(context.get_rows()): # Rowラッパーに変換 row = Row(row) print(row) rows.append(row) # 次のコマンドへ引渡し context.set_rows(rows)
def init(self, context: CommandContext): """ スクリプト読み込み後に、利用するコマンドの初期化時に呼び出れます。 context.get_parameters()で、スクリプトに記述されたコマンドパラメータ を取得することができます。 """ # 親クラス呼出 super().init(context) # パラメータを取得する( self.__params.プロパティ名 でアクセス可能) self.__params = context.get_parameters() # フェッチサイズを指定 super().set_fetch_size(0)
def term(self, context: CommandContext): # 事後のSQL処理を実行 for sql in self.__params.term_sql.split(";"): sql = sql.strip() self.__dbService.execute(self.__cursor, sql, context.get_script_parameters()) try: self.__cursor.close() except: pass logger.info(f"close database {self.__params.db_name}") self.__db.commit() self.__db.close() self.__db = None
def init(self, context: CommandContext): ''' スクリプト読み込み後に、利用するコマンドの初期化時に呼び出れます。 context.get_parameters()で、スクリプトに記述されたコマンドパラメータ を取得することができます。 ''' super().init(context) # パラメータを取得する( self.__params.プロパティ名 でアクセス可能) self.__params = context.get_parameters() # フェッチサイズを指定 super().set_fetch_size(self.__params.fetch_size) self.__white_filters = [re.compile(x) for x in self.__params.white_list] self.__black_filters = [re.compile(x) for x in self.__params.black_list] self.__detector = UniversalDetector()
def init(self, context: CommandContext): """ スクリプト読み込み後に、利用するコマンドの初期化時に呼び出れます。 context.get_parameters()で、スクリプトに記述されたコマンドパラメータ を取得することができます。 """ super().init(context) # パラメータを取得する( self.__params.プロパティ名 でアクセス可能) self.__params = context.get_parameters() # フェッチサイズを指定 super().set_fetch_size(self.__params.fetch_size) # データベースサービスを取得 self.__dbService = cast(DatabaseService, services.get_service('database')[0]) # アクセスしたいDB名を指定してDBインスタンスを取得 logger.info(f"open database {self.__params.db_name}") self.__db = self.__dbService.open(self.__params.db_name) self.__cursor = self.__dbService.cursor(self.__db)
def init(self, context: CommandContext): """ スクリプト読み込み後に、利用するコマンドの初期化時に呼び出れます。 context.get_parameters()で、スクリプトに記述されたコマンドパラメータ を取得することができます。 """ # パラメータを取得する( self.__params.プロパティ名 でアクセス可能) self.__params = context.get_parameters() # このコマンドがデータを供給するならコメントアウト # context.set_supplier(self) modules = {} for key in self.__params.modules.keys(): module_name = self.__params.modules[key] modules[key] = importlib.import_module(module_name) modules['objdict'] = objdict self.__modules = modules script = self.__params.script script = f'\n{script}\noutput_rows = proc(input_rows, args)' logger.debug(script) self.__script = script
def init(self, context: CommandContext): super().init(context) # パラメータ取得 self.__params = context.get_parameters() super().set_fetch_size(self.__params.fetch_size)
def proc(self, context: CommandContext): """ メイン処理を行います。 context.get_rows()を呼び出して、データ行を取得しながら、 データ加工を行ってください。 渡されてくるデータは、イテレータの場合もあるので、次に 引き継ぐために、context.set_rows()で、データを引き渡してください。 """ # 正規表現取得 reg = self.__reg # マッチングターゲットキーを取得 target_key = self.__params.target_key # 結果格納用のキーを取得 match_result_key = self.__params.match_result_key # 出力用のフィールド output = self.__params.output_keys # 次へ引き渡す行 rows = [] for row in iter(context.get_rows()): if type(row) == dict: row = dict(row) if type(row) == Row: row = dict(row.raw()) # Rowラッパーに変換 row = Row(row) row.set(match_result_key, False) # 検索対象文字列を取得 line = row.get(target_key) if line == None: continue newRow = dict(output) # 正規表現マッチング pos = None matchResult = reg.match(line) if matchResult: # マッチ結果を保存 row.set(match_result_key, True) # グループ1の発見場所を保存 groups = matchResult.groups() if len(groups) > 0: pos = matchResult.start(1) if len(groups) > 0: # 正規表現のマッチング結果を、置換します。 if self.__params.extract_type == 'index': for key in self.__params.group_key_map: index = int(self.__params.group_key_map[key]) newRow[key] = groups[index - 1] else: # ?Pで指定された正規表現のマッチ結果を抽出 d = matchResult.groupdict() for key in d.keys(): newRow[key] = d[key] elif self.__params.skip_unmatch: continue row.set('pos', pos) # 結果をマージ for key in newRow.keys(): row.set(key, newRow.get(key)) rows.append(row.raw()) # 次のコマンドへ引渡し context.set_rows(rows)
def main(script_path: str, config_parameters: dict): context = CommandContext() commandList = [] # スクリプトロード with open(script_path, 'r') as f: script = yaml.load(f, Loader=yaml.FullLoader) commands = script['commands'] # スクリプトパラメータを設定 script['parameters'].update(config_parameters) context.set_script_parameters(script['parameters']) logger.info(f"start script '{script_path}'") debug_mode = False if 'debug' in script['parameters']: if type(script['parameters']['debug']) == bool: debug_mode = script['parameters']['debug'] == True logger.info(f"debug mode = {debug_mode}") # スクリプトからコマンド群を順番に生成 for command in commands: command = objdict(command) if debug_mode == False and command.debug == True: continue # コマンド名からコマンドインスタンスを作成 logger.info(f"create command {command.type}") commandInstance = factory.new_instance(command.type, logger) # コマンド引数の仕様を取得する spec = factory.get_command_arg_spec(command.type) # コマンドの仕様を記述した情報からパラメータのバリデーション情報を取得 try: logger.info(f'{command.type}:{command.comment}: start validate') argSpec = validate_spec(command.type, spec, logger) except Exception as e: logger.error(f'{command.type}:{command.comment}: {e}') context.set_parameterspec(argSpec) # 引数仕様に則ったパラメータ定義をしているか確認 argSpec.validate(command.parameters) # コマンド引数を設定 context.set_parameters(command.parameters) # コマンドの初期化 logger.info(f"init command {command.type}") commandInstance.init(context) # コマンドリストへ追加 commandList.append(commandInstance) # スクリプトパラメータを1行目のデータとして渡す context.set_rows([script['parameters']]) # コマンド実行処理 logger.info(f"start command loop") loop = 1 while context.is_stop() == False: step = 1 if loop > 1: context.set_rows([]) for commandInstance in commandList: context.set_step(step) # コマンド実行 commandInstance.proc(context) step += 1 loop += 1 # コマンド終了処理 logger.info(f"finalize command") for commandInstance in commandList: commandInstance.term(context) return context
def proc(self, context: CommandContext): rows = self.__rows context.set_rows(rows) self.__has_data = False
def init(self, context: CommandContext): self.__args = context.get_parameters()
def proc(self, context: CommandContext): """ メイン処理を行います。 context.get_rows()を呼び出して、データ行を取得しながら、 データ加工を行ってください。 渡されてくるデータは、イテレータの場合もあるので、次に 引き継ぐために、context.set_rows()で、データを引き渡してください。s """ # 親データを保存 if self.__iter_parent == None: self.__iter_parent = iter([row for row in context.get_rows()]) self.__has_parent_data = True # 親から1行取得する if self.__iter_current == None: try: self.__parent_row = {} if self.__has_parent_data: self.__parent_row = Row(next(self.__iter_parent)) except StopIteration: self.__has_parent_data = False self.__iter_parent = None context.set_rows([]) return if self.__iter_current == None: # このコマンドが提供するデータの取得処理を行う。 # 例)ファイルをオープンして、データを読み込む if not self.__has_parent_data: self.__has_current_data = False context.set_rows([]) return # データ取得処理 newRows = [] newRows = self.get_new_data(self.__parent_row) # 取得したデータを、未加工のまま次の処理へ self.__iter_current = iter(newRows) retRows = [] while True: try: row = {} row = next(self.__iter_current) except StopIteration: self.__iter_current = None self.__has_current_data = False context.set_rows(retRows) return # 返却データを追加 newRow = self.create_new_row(row) if newRow == None: continue retRows.append(newRow) # フェッチサイズに達したらwhileループ終了 if self.__fetch_size > 0 and len(retRows) == self.__fetch_size: break # データを設定 context.set_rows(retRows)