def to_key_val_mode(self, token: Token): if not self.has_value(): raise InvalidParameterSyntax( f"L{token.start[0]}:Operator = used with no preceding key") try: exec(f"{self.value} = 0") except SyntaxError: raise InvalidParameterSyntax( f"L{token.start[0]}:Invalid key {self.value}") from None self.key = self.value self.value = ""
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if len(self.keyword_params) > 0: raise InvalidParameterSyntax(( f"{self.line_nb}{self.keyword_name} definition does not accept " f"key/value parameters"))
def format_param( self, parameter: Parameter, target_indent: int, inline_formatting: bool, param_list: bool = True, ) -> str: string_indent = TAB * target_indent if inline_formatting: target_indent = 0 val = str(parameter) try: # A snakemake parameter is syntactically like a function parameter ast_parse(f"param({val})") except SyntaxError: raise InvalidParameterSyntax(f"{parameter.line_nb}{val}") from None if inline_formatting or param_list: val = " ".join( val.rstrip().split("\n") ) # collapse strings on multiple lines extra_spacing = 0 if param_list: val = f"f({val})" extra_spacing = 3 val = self.run_black_format_str(val, target_indent, extra_spacing) if param_list: match_equal = re.match(r"f\((.*)\)", val, re.DOTALL) val = match_equal.group(1) val = textwrap.dedent(val) val = self.align_strings(val, target_indent) result = "" if not inline_formatting: for comment in parameter.pre_comments: result += f"{string_indent}{comment}\n" result += val.strip("\n") if param_list: result += "," post_comment_iter = iter(parameter.post_comments) if parameter._has_inline_comment: result += f"{COMMENT_SPACING}{next(post_comment_iter)}" result += "\n" for comment in post_comment_iter: result += f"{string_indent}{comment}\n" return result
def process_token(self, cur_param: Parameter) -> Parameter: token_type = self.token.type if token_type == tokenize.INDENT: self.cur_indent += 1 elif token_type == tokenize.DEDENT: if self.cur_indent > 0: self.cur_indent -= 1 elif token_type == tokenize.NEWLINE or token_type == tokenize.NL: self.found_newline = True if cur_param.has_value(): cur_param.add_elem(self.token) elif token_type == tokenize.COMMENT and not self.in_brackets: if str(cur_param) == "" and self.latest_pushed_param is not None: target = self.latest_pushed_param.comments else: target = cur_param.comments target.append(" " + self.token.string) elif is_equal_sign(self.token) and not self.in_brackets: cur_param.to_key_val_mode(self.token) elif is_comma_sign( self.token) and not self.in_brackets and not self.in_lambda: self.flush_param(cur_param) cur_param = Parameter(self.line_nb) elif token_type != tokenize.ENDMARKER: if brack_open(self.token): self._brackets.append(self.token.string) if brack_close(self.token): self._brackets.pop() if is_colon(self.token) and self.in_lambda: self.in_lambda = False if len(cur_param.value.split()) == 1: if cur_param.value == "lambda": self.in_lambda = True if self.incident_vocab.recognises(cur_param.value): raise InvalidParameterSyntax(( f"{self.line_nb}Over-indented recognised keyword found: " f"'{cur_param.value}'")) cur_param.add_elem(self.token) return cur_param
def format_param( self, parameter: Parameter, target_indent: int, inline_formatting: bool, single_param: bool = False, ) -> str: if inline_formatting: target_indent = 0 comments = f"\n{TAB * target_indent}".join(parameter.comments) val = str(parameter) try: # A snakemake parameter is syntactically like a function parameter ast_parse(f"param({val})") except SyntaxError: raise InvalidParameterSyntax(f"{parameter.line_nb}{val}") from None if inline_formatting: val = val.replace("\n", "") # collapse strings on multiple lines try: val = self.run_black_format_str(val, target_indent) except InvalidPython: if "**" in val: val = val.replace("** ", "**") val = self.align_strings(val, target_indent) if parameter.has_a_key(): # Remove space either side of '=' match_equal = re.match("(.*?) = (.*)", val, re.DOTALL) val = f"{match_equal.group(1)}={match_equal.group(2)}" val = val.strip("\n") if single_param: result = f"{val}{comments}\n" else: result = f"{val},{comments}\n" return result