def execute(self, name, current, and_exit, loader): cwd = os.path.split(api.log.data_source)[0] if name is None and not current: file = 'output.txt' if file in os.listdir(cwd): i = 1 file = 'output_{}.txt'.format(i) while file in os.listdir(cwd): i += 1 file = 'output_{}.txt'.format(i) file = os.path.join(cwd, file) else: if current: name = os.path.basename(api.log.data_source) if name in os.listdir(cwd): print('File already exists - do you want to overwrite?') r = input('Type \'yes\' to overwrite\n').strip().lower() if r != 'yes': return file = os.path.join(cwd, name) try: loader = api.loaders[loader]() except KeyError: raise api.CommandError(f'no loader \'{loader}\'') if not hasattr(loader, 'save'): raise api.CommandError('loader has no save method') loader.save(file) print('Saved to {}'.format(file)) api.log.unsaved_changes = False if and_exit: api.manual_execute(ExitCommand(), {})
def parse_using_signature(self, command): """Parse a command's arguments using its signature. command: command instance [Command] return: command with inputs assigned to it [Command] """ if hasattr(command, 'sig_cache'): self.signature_parts = command.sig_cache else: signature = api.resolve_signature(command) if api.is_disabled(command): raise api.CommandError(f'command \'{command.ID}\' is disabled') self.sig = SignatureParser(lexers.SignatureLexer(signature), command.ID) self.signature_parts = self.sig.make_signature() type(command).sig_cache = self.signature_parts # set on class self.parts = Buffer(iter(self.signature_parts)) found_inputs = self.scan_for_inputs_or_flags(self.signature_parts) self.inputs = found_inputs self.next_part() # to initialise self.current_part while not isinstance(self.current_part, structure.End): try: if self.current_token.type == STAR: self.eat(STAR) self.parse_signature_token() except api.CommandError as e: self.raise_error( f'{str(e)} for command \'{command.ID}\'\n' f'(signature: {api.resolve_signature(command)})', error=api.CommandError) command.inputs = self.inputs return command
def parse(self, parser): for part in self.parts: current = parser.current_token if current.type == KEYWORD and current.value == part.value: parser.eat(KEYWORD) else: raise api.CommandError( f'expected token KEYWORD ({part.value})')
def execute(self, file, loader): try: loader = api.loaders[loader]() except KeyError: raise api.CommandError(f'no loader \'{loader}\'') if not hasattr(loader, 'load'): raise api.CommandError('loader has no load method') prev = api.log.disable_all, api.log.is_startup api.log.disable_all = False api.log.is_startup = True api.log.data_source = os.path.abspath(file) api.log.new_commands = 0 api._import_base_plugin(reload=True) api.log.new_hooks = 0 api.log.new_loaders = 0 r = loader.load(file) api.log.disable_all, api.log.is_startup = prev # run the loading command api.tree = api.Tree(r)
def set_input(self, parser, key, value): try: current = parser.inputs[key] except KeyError: raise api.CommandError('signature object tried to assign to ' f'unscanned input \'{key}\'') if isinstance(current, list): current.append(value) else: parser.inputs[key] = value
def parse_child(self, parser): ref = [] if parser.current_token.type == DOT: ref.append(parser.eat(parser.current_token.type)) parser.eat(SLASH) else: ref.append('.') if parser.current_token.type in (NUMBER, KEYWORD): ref.append(parser.eat(parser.current_token.type)) else: raise api.CommandError( 'expected token NUMBER or KEYWORD (child reference)') self.set_input(parser, self.value, ref)
def phrase(self, optional=False): self.eat(LBRACKET if optional else LPAREN) parts = [self.get_part()] end = RBRACKET if optional else RPAREN while self.current_token.type != end: if self.current_token.type == EOF: raise api.CommandError( f'missing {end}, got {self.current_token.type}') parts.append(self.get_part()) self.eat(RBRACKET if optional else RPAREN) if optional: r = structure.OptionalPhrase(parts) else: r = structure.Phrase(parts) return r
def parse_signature_token(self): """Parse one element of a command's signature.""" current_part = self.current_part if current_part.match(self): current_part.parse(self) self.next_part() elif current_part.is_optional: self.next_part() else: message = (f'expected token {current_part.type} ' f'(got {self.current_token.type})') if isinstance(current_part, structure.Keyword): message += f' ({current_part.value})' message += f' in {current_part.__class__.__name__}' raise api.CommandError(message)
def load(self, file): with open(file, 'r') as f: try: object = json.load(f) except json.decoder.JSONDecodeError as e: raise api.CommandError(f'cannot load file:\n{str(e)}') if 'data' not in object: api.warning('no tree title given, defaulting to Tree') object['data'] = 'Tree' root = structure.Root(object['data']) tags = object.get('tags', {}) if 'config' in tags: self.found_plugin_file(tags['config']) self.add_tags(root, tags) for child in object.get('children', []): root.children.append( self.recursive_construct(child, depth=1, parent=root)) return root
def parse_forward(self, parser): ref = [] if parser.current_token.type == DOT: ref.append(parser.eat(parser.current_token.type)) elif parser.current_token.type == KEYWORD: ref.extend(['.', parser.eat(KEYWORD)]) elif parser.current_token.type == NUMBER: ref.extend(['.', parser.eat(NUMBER)]) else: ref.append('.') # assume starting slash means from current (dot) while parser.current_token.type == SLASH: parser.eat(SLASH) if parser.current_token.type in (NUMBER, KEYWORD): ref.append(parser.eat(parser.current_token.type)) else: raise api.CommandError( 'expected token NUMBER or KEYWORD (forward reference)') self.set_input(parser, self.value, ref)
def parse(self, parser): if self.option == 'forward': self.parse_forward(parser) return elif self.option == 'child': self.parse_child(parser) return ref = [] if parser.current_token.type in (DOT, DOTDOT, TILDE): ref.append(parser.eat(parser.current_token.type)) elif parser.current_token.type == KEYWORD: ref.extend(['.', parser.eat(KEYWORD)]) elif parser.current_token.type == NUMBER: ref.extend(['.', parser.eat(NUMBER)]) else: ref.append('.') # assume starting slash means from current (dot) while parser.current_token.type == SLASH: parser.eat(SLASH) if parser.current_token.type in (DOTDOT, NUMBER, KEYWORD): ref.append(parser.eat(parser.current_token.type)) else: raise api.CommandError( 'expected token NUMBER, KEYWORD or DOTDOT') self.set_input(parser, self.value, ref)
def parse(self, parser): if self.part_found is None: raise api.CommandError('cannot parse OR expression') self.parts[self.part_found].parse(parser)
def parse(self, parser): raise api.CommandError(f'parsing for {self.__class__.__name__} not yet' 'implemented')