diff options
Diffstat (limited to 'astroid')
| -rw-r--r-- | astroid/as_string.py | 133 | ||||
| -rw-r--r-- | astroid/bases.py | 27 | ||||
| -rw-r--r-- | astroid/brain/brain_gi.py | 4 | ||||
| -rw-r--r-- | astroid/brain/brain_namedtuple_enum.py | 6 | ||||
| -rw-r--r-- | astroid/brain/brain_six.py | 4 | ||||
| -rw-r--r-- | astroid/context.py | 2 | ||||
| -rw-r--r-- | astroid/helpers.py | 6 | ||||
| -rw-r--r-- | astroid/modutils.py | 4 | ||||
| -rw-r--r-- | astroid/node_classes.py | 10 | ||||
| -rw-r--r-- | astroid/scoped_nodes.py | 9 | ||||
| -rw-r--r-- | astroid/test_utils.py | 4 |
11 files changed, 95 insertions, 114 deletions
diff --git a/astroid/as_string.py b/astroid/as_string.py index fd708188..3fc40965 100644 --- a/astroid/as_string.py +++ b/astroid/as_string.py @@ -42,7 +42,7 @@ class AsStringVisitor: def _docs_dedent(self, doc): """Stop newlines in docs being indented by self._stmt_list""" - return '\n%s"""%s"""' % (self.indent, doc.replace("\n", DOC_NEWLINE)) + return '\n{}"""{}"""'.format(self.indent, doc.replace("\n", DOC_NEWLINE)) def _stmt_list(self, stmts, indent=True): """return a list of nodes to string""" @@ -103,7 +103,9 @@ class AsStringVisitor: def visit_assert(self, node): """return an astroid.Assert node as string""" if node.fail: - return "assert %s, %s" % (node.test.accept(self), node.fail.accept(self)) + return "assert {}, {}".format( + node.test.accept(self), node.fail.accept(self) + ) return "assert %s" % node.test.accept(self) def visit_assignname(self, node): @@ -113,11 +115,13 @@ class AsStringVisitor: def visit_assign(self, node): """return an astroid.Assign node as string""" lhs = " = ".join(n.accept(self) for n in node.targets) - return "%s = %s" % (lhs, node.value.accept(self)) + return "{} = {}".format(lhs, node.value.accept(self)) def visit_augassign(self, node): """return an astroid.AugAssign node as string""" - return "%s %s %s" % (node.target.accept(self), node.op, node.value.accept(self)) + return "{} {} {}".format( + node.target.accept(self), node.op, node.value.accept(self) + ) def visit_annassign(self, node): """Return an astroid.AugAssign node as string""" @@ -125,8 +129,8 @@ class AsStringVisitor: target = node.target.accept(self) annotation = node.annotation.accept(self) if node.value is None: - return "%s: %s" % (target, annotation) - return "%s: %s = %s" % (target, annotation, node.value.accept(self)) + return f"{target}: {annotation}" + return "{}: {} = {}".format(target, annotation, node.value.accept(self)) def visit_repr(self, node): """return an astroid.Repr node as string""" @@ -137,9 +141,9 @@ class AsStringVisitor: left = self._precedence_parens(node, node.left) right = self._precedence_parens(node, node.right, is_left=False) if node.op == "**": - return "%s%s%s" % (left, node.op, right) + return f"{left}{node.op}{right}" - return "%s %s %s" % (left, node.op, right) + return f"{left} {node.op} {right}" def visit_boolop(self, node): """return an astroid.BoolOp node as string""" @@ -160,7 +164,7 @@ class AsStringVisitor: keywords = [] args.extend(keywords) - return "%s(%s)" % (expr_str, ", ".join(args)) + return "{}({})".format(expr_str, ", ".join(args)) def visit_classdef(self, node): """return an astroid.ClassDef node as string""" @@ -171,33 +175,27 @@ class AsStringVisitor: args += [n.accept(self) for n in node.keywords] args = "(%s)" % ", ".join(args) if args else "" docs = self._docs_dedent(node.doc) if node.doc else "" - return "\n\n%sclass %s%s:%s\n%s\n" % ( - decorate, - node.name, - args, - docs, - self._stmt_list(node.body), + return "\n\n{}class {}{}:{}\n{}\n".format( + decorate, node.name, args, docs, self._stmt_list(node.body) ) def visit_compare(self, node): """return an astroid.Compare node as string""" rhs_str = " ".join( [ - "%s %s" % (op, self._precedence_parens(node, expr, is_left=False)) + "{} {}".format(op, self._precedence_parens(node, expr, is_left=False)) for op, expr in node.ops ] ) - return "%s %s" % (self._precedence_parens(node, node.left), rhs_str) + return "{} {}".format(self._precedence_parens(node, node.left), rhs_str) def visit_comprehension(self, node): """return an astroid.Comprehension node as string""" ifs = "".join(" if %s" % n.accept(self) for n in node.ifs) - generated = "for %s in %s%s" % ( - node.target.accept(self), - node.iter.accept(self), - ifs, + generated = "for {} in {}{}".format( + node.target.accept(self), node.iter.accept(self), ifs ) - return "%s%s" % ("async " if node.is_async else "", generated) + return "{}{}".format("async " if node.is_async else "", generated) def visit_const(self, node): """return an astroid.Const node as string""" @@ -237,14 +235,14 @@ class AsStringVisitor: # It can only be a DictUnpack node. yield key + value else: - yield "%s: %s" % (key, value) + yield f"{key}: {value}" def visit_dictunpack(self, node): return "**" def visit_dictcomp(self, node): """return an astroid.DictComp node as string""" - return "{%s: %s %s}" % ( + return "{{{}: {} {}}}".format( node.key.accept(self), node.value.accept(self), " ".join(n.accept(self) for n in node.generators), @@ -261,15 +259,14 @@ class AsStringVisitor: def visit_excepthandler(self, node): if node.type: if node.name: - excs = "except %s as %s" % ( - node.type.accept(self), - node.name.accept(self), + excs = "except {} as {}".format( + node.type.accept(self), node.name.accept(self) ) else: excs = "except %s" % node.type.accept(self) else: excs = "except" - return "%s:\n%s" % (excs, self._stmt_list(node.body)) + return "{}:\n{}".format(excs, self._stmt_list(node.body)) def visit_ellipsis(self, node): """return an astroid.Ellipsis node as string""" @@ -282,13 +279,15 @@ class AsStringVisitor: def visit_exec(self, node): """return an astroid.Exec node as string""" if node.locals: - return "exec %s in %s, %s" % ( + return "exec {} in {}, {}".format( node.expr.accept(self), node.locals.accept(self), node.globals.accept(self), ) if node.globals: - return "exec %s in %s" % (node.expr.accept(self), node.globals.accept(self)) + return "exec {} in {}".format( + node.expr.accept(self), node.globals.accept(self) + ) return "exec %s" % node.expr.accept(self) def visit_extslice(self, node): @@ -297,20 +296,17 @@ class AsStringVisitor: def visit_for(self, node): """return an astroid.For node as string""" - fors = "for %s in %s:\n%s" % ( - node.target.accept(self), - node.iter.accept(self), - self._stmt_list(node.body), + fors = "for {} in {}:\n{}".format( + node.target.accept(self), node.iter.accept(self), self._stmt_list(node.body) ) if node.orelse: - fors = "%s\nelse:\n%s" % (fors, self._stmt_list(node.orelse)) + fors = "{}\nelse:\n{}".format(fors, self._stmt_list(node.orelse)) return fors def visit_importfrom(self, node): """return an astroid.ImportFrom node as string""" - return "from %s import %s" % ( - "." * (node.level or 0) + node.modname, - _import_string(node.names), + return "from {} import {}".format( + "." * (node.level or 0) + node.modname, _import_string(node.names) ) def visit_joinedstr(self, node): @@ -377,9 +373,8 @@ class AsStringVisitor: def visit_generatorexp(self, node): """return an astroid.GeneratorExp node as string""" - return "(%s %s)" % ( - node.elt.accept(self), - " ".join(n.accept(self) for n in node.generators), + return "({} {})".format( + node.elt.accept(self), " ".join(n.accept(self) for n in node.generators) ) def visit_attribute(self, node): @@ -387,7 +382,7 @@ class AsStringVisitor: left = self._precedence_parens(node, node.expr) if left.isdigit(): left = "(%s)" % left - return "%s.%s" % (left, node.attrname) + return f"{left}.{node.attrname}" def visit_global(self, node): """return an astroid.Global node as string""" @@ -395,7 +390,7 @@ class AsStringVisitor: def visit_if(self, node): """return an astroid.If node as string""" - ifs = ["if %s:\n%s" % (node.test.accept(self), self._stmt_list(node.body))] + ifs = ["if {}:\n{}".format(node.test.accept(self), self._stmt_list(node.body))] if node.has_elif_block(): ifs.append("el%s" % self._stmt_list(node.orelse, indent=False)) elif node.orelse: @@ -404,7 +399,7 @@ class AsStringVisitor: def visit_ifexp(self, node): """return an astroid.IfExp node as string""" - return "%s if %s else %s" % ( + return "{} if {} else {}".format( self._precedence_parens(node, node.body, is_left=True), self._precedence_parens(node, node.test, is_left=True), self._precedence_parens(node, node.orelse, is_left=False), @@ -418,14 +413,14 @@ class AsStringVisitor: """return an astroid.Keyword node as string""" if node.arg is None: return "**%s" % node.value.accept(self) - return "%s=%s" % (node.arg, node.value.accept(self)) + return "{}={}".format(node.arg, node.value.accept(self)) def visit_lambda(self, node): """return an astroid.Lambda node as string""" args = node.args.accept(self) body = node.body.accept(self) if args: - return "lambda %s: %s" % (args, body) + return f"lambda {args}: {body}" return "lambda: %s" % body @@ -435,9 +430,8 @@ class AsStringVisitor: def visit_listcomp(self, node): """return an astroid.ListComp node as string""" - return "[%s %s]" % ( - node.elt.accept(self), - " ".join(n.accept(self) for n in node.generators), + return "[{} {}]".format( + node.elt.accept(self), " ".join(n.accept(self) for n in node.generators) ) def visit_module(self, node): @@ -453,7 +447,7 @@ class AsStringVisitor: """Return an assignment expression node as string""" target = node.target.accept(self) value = node.value.accept(self) - return "%s := %s" % (target, value) + return f"{target} := {value}" def visit_nonlocal(self, node): """return an astroid.Nonlocal node as string""" @@ -469,16 +463,15 @@ class AsStringVisitor: if not node.nl: nodes = "%s," % nodes if node.dest: - return "print >> %s, %s" % (node.dest.accept(self), nodes) + return "print >> {}, {}".format(node.dest.accept(self), nodes) return "print %s" % nodes def visit_raise(self, node): """return an astroid.Raise node as string""" if node.exc: if node.cause: - return "raise %s from %s" % ( - node.exc.accept(self), - node.cause.accept(self), + return "raise {} from {}".format( + node.exc.accept(self), node.cause.accept(self) ) return "raise %s" % node.exc.accept(self) return "raise" @@ -504,9 +497,8 @@ class AsStringVisitor: def visit_setcomp(self, node): """return an astroid.SetComp node as string""" - return "{%s %s}" % ( - node.elt.accept(self), - " ".join(n.accept(self) for n in node.generators), + return "{{{} {}}}".format( + node.elt.accept(self), " ".join(n.accept(self) for n in node.generators) ) def visit_slice(self, node): @@ -515,8 +507,8 @@ class AsStringVisitor: upper = node.upper.accept(self) if node.upper else "" step = node.step.accept(self) if node.step else "" if step: - return "%s:%s:%s" % (lower, upper, step) - return "%s:%s" % (lower, upper) + return f"{lower}:{upper}:{step}" + return f"{lower}:{upper}" def visit_subscript(self, node): """return an astroid.Subscript node as string""" @@ -528,7 +520,7 @@ class AsStringVisitor: # Remove parenthesis in tuple and extended slice. # a[(::1, 1:)] is not valid syntax. idxstr = idxstr[1:-1] - return "%s[%s]" % (self._precedence_parens(node, node.value), idxstr) + return "{}[{}]".format(self._precedence_parens(node, node.value), idxstr) def visit_tryexcept(self, node): """return an astroid.TryExcept node as string""" @@ -541,9 +533,8 @@ class AsStringVisitor: def visit_tryfinally(self, node): """return an astroid.TryFinally node as string""" - return "try:\n%s\nfinally:\n%s" % ( - self._stmt_list(node.body), - self._stmt_list(node.finalbody), + return "try:\n{}\nfinally:\n{}".format( + self._stmt_list(node.body), self._stmt_list(node.finalbody) ) def visit_tuple(self, node): @@ -558,13 +549,15 @@ class AsStringVisitor: operator = "not " else: operator = node.op - return "%s%s" % (operator, self._precedence_parens(node, node.operand)) + return "{}{}".format(operator, self._precedence_parens(node, node.operand)) def visit_while(self, node): """return an astroid.While node as string""" - whiles = "while %s:\n%s" % (node.test.accept(self), self._stmt_list(node.body)) + whiles = "while {}:\n{}".format( + node.test.accept(self), self._stmt_list(node.body) + ) if node.orelse: - whiles = "%s\nelse:\n%s" % (whiles, self._stmt_list(node.orelse)) + whiles = "{}\nelse:\n{}".format(whiles, self._stmt_list(node.orelse)) return whiles def visit_with(self, node): # 'with' without 'as' is possible @@ -573,7 +566,7 @@ class AsStringVisitor: ("%s" % expr.accept(self)) + (vars and " as %s" % (vars.accept(self)) or "") for expr, vars in node.items ) - return "with %s:\n%s" % (items, self._stmt_list(node.body)) + return "with {}:\n{}".format(items, self._stmt_list(node.body)) def visit_yield(self, node): """yield an ast.Yield node as string""" @@ -582,7 +575,7 @@ class AsStringVisitor: if node.parent.is_statement: return expr - return "(%s)" % (expr,) + return f"({expr})" def visit_yieldfrom(self, node): """ Return an astroid.YieldFrom node as string. """ @@ -591,7 +584,7 @@ class AsStringVisitor: if node.parent.is_statement: return expr - return "(%s)" % (expr,) + return f"({expr})" def visit_starred(self, node): """return Starred node as string""" @@ -620,7 +613,7 @@ def _import_string(names): _names = [] for name, asname in names: if asname is not None: - _names.append("%s as %s" % (name, asname)) + _names.append(f"{name} as {asname}") else: _names.append(name) return ", ".join(_names) diff --git a/astroid/bases.py b/astroid/bases.py index 49251223..282c8bf5 100644 --- a/astroid/bases.py +++ b/astroid/bases.py @@ -269,14 +269,12 @@ class Instance(BaseInstance): special_attributes = util.lazy_descriptor(lambda: objectmodel.InstanceModel()) def __repr__(self): - return "<Instance of %s.%s at 0x%s>" % ( - self._proxied.root().name, - self._proxied.name, - id(self), + return "<Instance of {}.{} at 0x{}>".format( + self._proxied.root().name, self._proxied.name, id(self) ) def __str__(self): - return "Instance of %s.%s" % (self._proxied.root().name, self._proxied.name) + return f"Instance of {self._proxied.root().name}.{self._proxied.name}" def callable(self): try: @@ -331,11 +329,8 @@ class UnboundMethod(Proxy): def __repr__(self): frame = self._proxied.parent.frame() - return "<%s %s of %s at 0x%s" % ( - self.__class__.__name__, - self._proxied.name, - frame.qname(), - id(self), + return "<{} {} of {} at 0x{}".format( + self.__class__.__name__, self._proxied.name, frame.qname(), id(self) ) def implicit_parameters(self): @@ -517,10 +512,8 @@ class Generator(BaseInstance): return True def __repr__(self): - return "<Generator(%s) l.%s at 0x%s>" % ( - self._proxied.name, - self.lineno, - id(self), + return "<Generator({}) l.{} at 0x{}>".format( + self._proxied.name, self.lineno, id(self) ) def __str__(self): @@ -537,10 +530,8 @@ class AsyncGenerator(Generator): return "AsyncGenerator" def __repr__(self): - return "<AsyncGenerator(%s) l.%s at 0x%s>" % ( - self._proxied.name, - self.lineno, - id(self), + return "<AsyncGenerator({}) l.{} at 0x{}>".format( + self._proxied.name, self.lineno, id(self) ) def __str__(self): diff --git a/astroid/brain/brain_gi.py b/astroid/brain/brain_gi.py index f776190d..68f0bbea 100644 --- a/astroid/brain/brain_gi.py +++ b/astroid/brain/brain_gi.py @@ -122,7 +122,7 @@ def _gi_build_stub(parent): strval = str(val) if isinstance(val, str): strval = '"%s"' % str(val).replace("\\", "\\\\") - ret += "%s = %s\n" % (name, strval) + ret += f"{name} = {strval}\n" if ret: ret += "\n\n" @@ -148,7 +148,7 @@ def _gi_build_stub(parent): base = "object" if issubclass(obj, Exception): base = "Exception" - ret += "class %s(%s):\n" % (name, base) + ret += f"class {name}({base}):\n" classret = _gi_build_stub(obj) if not classret: diff --git a/astroid/brain/brain_namedtuple_enum.py b/astroid/brain/brain_namedtuple_enum.py index 042f3d16..9fda8c05 100644 --- a/astroid/brain/brain_namedtuple_enum.py +++ b/astroid/brain/brain_namedtuple_enum.py @@ -182,7 +182,7 @@ def infer_named_tuple(node, context=None): if rename: attributes = _get_renamed_namedtuple_attributes(attributes) - replace_args = ", ".join("{arg}=None".format(arg=arg) for arg in attributes) + replace_args = ", ".join(f"{arg}=None" for arg in attributes) field_def = ( " {name} = property(lambda self: self[{index:d}], " "doc='Alias for field number {index:d}')" @@ -447,9 +447,7 @@ def infer_typing_namedtuple(node, context=None): field_names = "({},)".format(",".join(names)) else: field_names = "''" - node = extract_node( - "namedtuple({typename}, {fields})".format(typename=typename, fields=field_names) - ) + node = extract_node(f"namedtuple({typename}, {field_names})") return infer_named_tuple(node, context) diff --git a/astroid/brain/brain_six.py b/astroid/brain/brain_six.py index c6903282..82d782e1 100644 --- a/astroid/brain/brain_six.py +++ b/astroid/brain/brain_six.py @@ -204,13 +204,13 @@ def _looks_like_nested_from_six_with_metaclass(node): # format when explicit 'six.with_metaclass' is used mod = base.func.expr.name func = base.func.attrname - func = "{}.{}".format(mod, func) + func = f"{mod}.{func}" else: # format when 'with_metaclass' is used directly (local import from six) # check reference module to avoid 'with_metaclass' name clashes mod = base.parent.parent import_from = mod.locals["with_metaclass"][0] - func = "{}.{}".format(import_from.modname, base.func.name) + func = f"{import_from.modname}.{base.func.name}" except (AttributeError, KeyError, IndexError): return False return func == SIX_WITH_METACLASS diff --git a/astroid/context.py b/astroid/context.py index 27d1897f..1caedfd7 100644 --- a/astroid/context.py +++ b/astroid/context.py @@ -121,7 +121,7 @@ class InferenceContext: % (field, pprint.pformat(getattr(self, field), width=80 - len(field))) for field in self.__slots__ ) - return "%s(%s)" % (type(self).__name__, ",\n ".join(state)) + return "{}({})".format(type(self).__name__, ",\n ".join(state)) class CallContext: diff --git a/astroid/helpers.py b/astroid/helpers.py index a35635e8..b4ead8eb 100644 --- a/astroid/helpers.py +++ b/astroid/helpers.py @@ -142,7 +142,7 @@ def object_issubclass(node, class_or_seq, context=None): or its type's mro doesn't work """ if not isinstance(node, nodes.ClassDef): - raise TypeError("{node} needs to be a ClassDef node".format(node=node)) + raise TypeError(f"{node} needs to be a ClassDef node") return _object_type_is_subclass(node, class_or_seq, context=context) @@ -286,7 +286,7 @@ def object_len(node, context=None): len_call = next(node_type.igetattr("__len__", context=context)) except exceptions.AttributeInferenceError as e: raise exceptions.AstroidTypeError( - "object of type '{}' has no len()".format(node_type.pytype()) + f"object of type '{node_type.pytype()}' has no len()" ) from e result_of_len = next(len_call.infer_call_result(node, context)) @@ -301,5 +301,5 @@ def object_len(node, context=None): # Fake a result as we don't know the arguments of the instance call. return 0 raise exceptions.AstroidTypeError( - "'{}' object cannot be interpreted as an integer".format(result_of_len) + f"'{result_of_len}' object cannot be interpreted as an integer" ) diff --git a/astroid/modutils.py b/astroid/modutils.py index 2541e127..05968c02 100644 --- a/astroid/modutils.py +++ b/astroid/modutils.py @@ -301,7 +301,7 @@ def modpath_from_file_with_callback(filename, path=None, is_package_cb=None): return modpath raise ImportError( - "Unable to find module for %s in %s" % (filename, ", \n".join(sys.path)) + "Unable to find module for {} in {}".format(filename, ", \n".join(sys.path)) ) @@ -495,7 +495,7 @@ def get_source_file(filename, include_no_ext=False): filename = os.path.abspath(_path_from_filename(filename)) base, orig_ext = os.path.splitext(filename) for ext in PY_SOURCE_EXTS: - source_path = "%s.%s" % (base, ext) + source_path = f"{base}.{ext}" if os.path.exists(source_path): return source_path if include_no_ext and not orig_ext and os.path.exists(base): diff --git a/astroid/node_classes.py b/astroid/node_classes.py index e2db47a8..a6397c0f 100644 --- a/astroid/node_classes.py +++ b/astroid/node_classes.py @@ -418,7 +418,7 @@ class NodeNG: inner = [lines[0]] for line in lines[1:]: inner.append(" " * alignment + line) - result.append("%s=%s" % (field, "".join(inner))) + result.append("{}={}".format(field, "".join(inner))) return string % { "cname": cname, @@ -874,7 +874,9 @@ class NodeNG: if node in done: result.append( indent - + "<Recursion on %s with id=%s" % (type(node).__name__, id(node)) + + "<Recursion on {} with id={}".format( + type(node).__name__, id(node) + ) ) return False done.add(node) @@ -885,7 +887,7 @@ class NodeNG: depth += 1 cur_indent += indent if ids: - result.append("%s<0x%x>(\n" % (type(node).__name__, id(node))) + result.append("{}<0x{:x}>(\n".format(type(node).__name__, id(node))) else: result.append("%s(" % type(node).__name__) fields = [] @@ -2631,7 +2633,7 @@ class Const(mixins.NoChildrenMixin, NodeNG, bases.Instance): message="Type error {error!r}", node=self, index=index, context=context ) from exc - raise exceptions.AstroidTypeError("%r (value=%s)" % (self, self.value)) + raise exceptions.AstroidTypeError(f"{self!r} (value={self.value})") def has_dynamic_getattr(self): """Check if the node has a custom __getattr__ or __getattribute__. diff --git a/astroid/scoped_nodes.py b/astroid/scoped_nodes.py index 0567ac3e..269b1637 100644 --- a/astroid/scoped_nodes.py +++ b/astroid/scoped_nodes.py @@ -174,7 +174,7 @@ class LocalsDictNodeNG(node_classes.LookupMixIn, node_classes.NodeNG): # pylint: disable=no-member; github.com/pycqa/astroid/issues/278 if self.parent is None: return self.name - return "%s.%s" % (self.parent.frame().qname(), self.name) + return f"{self.parent.frame().qname()}.{self.name}" def frame(self): """The first parent frame node. @@ -687,7 +687,7 @@ class Module(LocalsDictNodeNG): if package_name: if not modname: return package_name - return "%s.%s" % (package_name, modname) + return f"{package_name}.{modname}" return modname def wildcard_import_names(self): @@ -2167,10 +2167,7 @@ class ClassDef(mixins.FilterStmtsMixin, LocalsDictNodeNG, node_classes.Statement def infer_call_result(self, caller, context=None): """infer what a class is returning when called""" - if ( - self.is_subtype_of("%s.type" % (BUILTINS,), context) - and len(caller.args) == 3 - ): + if self.is_subtype_of(f"{BUILTINS}.type", context) and len(caller.args) == 3: result = self._infer_type_call(caller, context) yield result return diff --git a/astroid/test_utils.py b/astroid/test_utils.py index 0897ae38..e7504454 100644 --- a/astroid/test_utils.py +++ b/astroid/test_utils.py @@ -47,11 +47,11 @@ def require_version(minver=None, maxver=None): def new_f(*args, **kwargs): if minver is not None: pytest.skip( - "Needs Python > %s. Current version is %s." % (minver, str_version) + f"Needs Python > {minver}. Current version is {str_version}." ) elif maxver is not None: pytest.skip( - "Needs Python <= %s. Current version is %s." % (maxver, str_version) + f"Needs Python <= {maxver}. Current version is {str_version}." ) return new_f |
