From 8b1a7edc11a72f679689fa9ba9e632907f9304f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Mon, 27 Dec 2021 21:25:38 +0100 Subject: [PATCH 1/4] refactor: Use annotation getter for base classes --- src/griffe/agents/visitor.py | 5 ++--- src/griffe/dataclasses.py | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/griffe/agents/visitor.py b/src/griffe/agents/visitor.py index ce5b30cc6..45d2ba698 100644 --- a/src/griffe/agents/visitor.py +++ b/src/griffe/agents/visitor.py @@ -20,7 +20,6 @@ from griffe.agents.nodes import ( ASTNode, get_annotation, - get_baseclass, get_docstring, get_instance_names, get_names, @@ -219,7 +218,7 @@ def visit_classdef(self, node: ast.ClassDef) -> None: bases = [] if node.bases: for base in node.bases: - bases.append(get_baseclass(base, self.current)) + bases.append(get_annotation(base, self.current)) class_ = Class( name=node.name, @@ -227,7 +226,7 @@ def visit_classdef(self, node: ast.ClassDef) -> None: endlineno=node.end_lineno, # type: ignore[attr-defined] docstring=self._get_docstring(node), decorators=decorators, - bases=bases, + bases=bases, # type: ignore[arg-type] ) self.current[node.name] = class_ self.current = class_ diff --git a/src/griffe/dataclasses.py b/src/griffe/dataclasses.py index 1b48495d6..bff5e85d7 100644 --- a/src/griffe/dataclasses.py +++ b/src/griffe/dataclasses.py @@ -960,7 +960,7 @@ class Class(Object): def __init__( self, *args: Any, - bases: list[Name | Expression] | None = None, + bases: list[Name | Expression | str] | None = None, decorators: list[Decorator] | None = None, **kwargs: Any, ) -> None: @@ -973,7 +973,7 @@ def __init__( **kwargs: See [`griffe.dataclasses.Object`][]. """ super().__init__(*args, **kwargs) - self.bases: list[Name | Expression] = bases or [] + self.bases: list[Name | Expression | str] = bases or [] self.decorators: list[Decorator] = decorators or [] def as_dict(self, **kwargs: Any) -> dict[str, Any]: # type: ignore[override] From cd1b305932832ad5347ce829a48a311e3c44d542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Mon, 27 Dec 2021 21:26:03 +0100 Subject: [PATCH 2/4] feat: Support more AST nodes --- src/griffe/agents/nodes.py | 173 ++++++++++++++++++++++++++++--------- src/griffe/expressions.py | 11 +++ 2 files changed, 141 insertions(+), 43 deletions(-) diff --git a/src/griffe/agents/nodes.py b/src/griffe/agents/nodes.py index f8a2bcdf0..2f539e774 100644 --- a/src/griffe/agents/nodes.py +++ b/src/griffe/agents/nodes.py @@ -6,6 +6,7 @@ import inspect import sys from ast import AST +from ast import Add as NodeAdd from ast import And as NodeAnd from ast import AnnAssign as NodeAnnAssign from ast import Assign as NodeAssign @@ -13,6 +14,7 @@ from ast import BinOp as NodeBinOp from ast import BitAnd as NodeBitAnd from ast import BitOr as NodeBitOr +from ast import BitXor as NodeBitXor from ast import BoolOp as NodeBoolOp from ast import Call as NodeCall from ast import Compare as NodeCompare @@ -21,28 +23,41 @@ from ast import DictComp as NodeDictComp from ast import Div as NodeDiv from ast import Ellipsis as NodeEllipsis +from ast import Eq as NodeEq from ast import Expr as NodeExpr +from ast import FloorDiv as NodeFloorDiv from ast import FormattedValue as NodeFormattedValue from ast import GeneratorExp as NodeGeneratorExp from ast import Gt as NodeGt from ast import GtE as NodeGtE from ast import IfExp as NodeIfExp +from ast import In as NodeIn +from ast import Invert as NodeInvert +from ast import Is as NodeIs +from ast import IsNot as NodeIsNot from ast import JoinedStr as NodeJoinedStr from ast import Lambda as NodeLambda from ast import List as NodeList from ast import ListComp as NodeListComp +from ast import LShift as NodeLShift from ast import Lt as NodeLt from ast import LtE as NodeLtE +from ast import Mod as NodeMod from ast import Mult as NodeMult from ast import Name as NodeName from ast import Not as NodeNot from ast import NotEq as NodeNotEq +from ast import NotIn as NodeNotIn from ast import Num as NodeNum from ast import Or as NodeOr +from ast import Pow as NodePow +from ast import RShift as NodeRShift from ast import Set as NodeSet +from ast import SetComp as NodeSetComp from ast import Slice as NodeSlice from ast import Starred as NodeStarred from ast import Str as NodeStr +from ast import Sub as NodeSub from ast import Subscript as NodeSubscript from ast import Tuple as NodeTuple from ast import UAdd as NodeUAdd @@ -468,48 +483,6 @@ def _join(sequence, item): return new_sequence -# ========================================================== -# base classes -def _get_baseclass_name(node: NodeName, parent: Module | Class) -> Name: - return Name(node.id, partial(parent.resolve, node.id)) - - -def _get_baseclass_attribute(node: NodeAttribute, parent: Module | Class) -> Expression: - left = get_baseclass(node.value, parent) - - def resolver(): # noqa: WPS430 - return f"{left.full}.{node.attr}" - - right = Name(node.attr, resolver) - return Expression(left, ".", right) - - -def _get_baseclass_subscript(node: NodeSubscript, parent: Module | Class) -> Expression: - left = get_baseclass(node.value, parent) - subscript = get_baseclass(node.slice, parent) - return Expression(left, "[", subscript, "]") - - -_node_baseclass_map: dict[Type, Callable[[Any, Module | Class], Name | Expression]] = { - NodeName: _get_baseclass_name, - NodeAttribute: _get_baseclass_attribute, - NodeSubscript: _get_baseclass_subscript, -} - - -def get_baseclass(node: AST, parent: Module | Class) -> Name | Expression: - """Extract a resolvable name for a given base class. - - Parameters: - node: The base class node. - parent: The parent used to resolve the name. - - Returns: - A resovable name or expression. - """ - return _node_baseclass_map[type(node)](node, parent) - - # ========================================================== # annotations def _get_name_annotation(node: NodeName, parent: Module | Class) -> Name: @@ -530,6 +503,21 @@ def resolver(): # noqa: WPS430 return Expression(left, ".", right) +def _get_call_annotation(node: NodeCall, parent: Module | Class) -> Expression: + posargs = Expression(*[_get_annotation(arg, parent) for arg in node.args]) + kwargs = Expression(*[_get_annotation(kwarg, parent) for kwarg in node.keywords]) + args: Expression | str + if posargs and kwargs: + args = Expression(posargs, ", ", kwargs) + elif posargs: + args = posargs + elif kwargs: + args = kwargs + else: + args = "" + return Expression(_get_annotation(node.func, parent), "(", args, ")") + + def _get_binop_annotation(node: NodeBinOp, parent: Module | Class) -> Expression: left = _get_annotation(node.left, parent) right = _get_annotation(node.right, parent) @@ -540,7 +528,7 @@ def _get_bitor_annotation(node: NodeBitOr, parent: Module | Class) -> str: return " | " -def _get_bitand_annotation(node: NodeBitOr, parent: Module | Class) -> str: +def _get_bitand_annotation(node: NodeBitAnd, parent: Module | Class) -> str: return " & " @@ -558,6 +546,20 @@ def _get_list_annotation(node: NodeList, parent: Module | Class) -> Expression: return Expression("[", *_join([_get_annotation(el, parent) for el in node.elts], ", "), "]") +def _get_ellipsis_annotation(node: NodeEllipsis, parent: Module | Class) -> str: + return "..." + + +def _get_ifexp_annotation(node: NodeIfExp, parent: Module | Class) -> Expression: + return Expression( + _get_annotation(node.body, parent), + " if ", + _get_annotation(node.test, parent), + " else", + _get_annotation(node.orelse, parent), + ) + + _node_annotation_map: dict[Type, Callable[[Any, Module | Class], str | Name | Expression]] = { NodeName: _get_name_annotation, NodeConstant: _get_constant_annotation, @@ -568,6 +570,9 @@ def _get_list_annotation(node: NodeList, parent: Module | Class) -> Expression: NodeSubscript: _get_subscript_annotation, NodeTuple: _get_tuple_annotation, NodeList: _get_list_annotation, + NodeCall: _get_call_annotation, + NodeEllipsis: _get_ellipsis_annotation, + NodeIfExp: _get_ifexp_annotation, } # TODO: remove once Python 3.8 support is dropped @@ -659,6 +664,38 @@ def _get_bitor_value(node: NodeBitOr) -> str: return "|" +def _get_bitand_value(node: NodeBitAnd) -> str: + return "&" + + +def _get_bitxor_value(node: NodeBitXor) -> str: + return "^" + + +def _get_invert_value(node: NodeInvert) -> str: + return "~" + + +def _get_in_value(node: NodeIn) -> str: + return "in" + + +def _get_notin_value(node: NodeNotIn) -> str: + return "not in" + + +def _get_eq_value(node: NodeEq) -> str: + return "==" + + +def _get_add_value(node: NodeAdd) -> str: + return "+" + + +def _get_sub_value(node: NodeSub) -> str: + return "-" + + def _get_mult_value(node: NodeMult) -> str: return "*" @@ -667,6 +704,26 @@ def _get_div_value(node: NodeDiv) -> str: return "/" +def _get_floordiv_value(node: NodeFloorDiv) -> str: + return "//" + + +def _get_pow_value(node: NodePow) -> str: + return "**" + + +def _get_mod_value(node: NodeMod) -> str: + return "%" + + +def _get_lshift_value(node: NodeLShift) -> str: + return "<<" + + +def _get_rshift_value(node: NodeRShift) -> str: + return ">>" + + def _get_unaryop_value(node: NodeUnaryOp) -> str: return f"{get_value(node.op)}{get_value(node.operand)}" @@ -791,6 +848,12 @@ def _get_listcomp_value(node: NodeListComp) -> str: return f"[{element} " + " ".join(generators) + "]" +def _get_setcomp_value(node: NodeSetComp) -> str: + element = get_value(node.elt) + generators = [get_value(gen) for gen in node.generators] + return f"{{{element} " + " ".join(generators) + "}" + + def _get_dictcomp_value(node: NodeDictComp) -> str: key = get_value(node.key) value = get_value(node.value) @@ -828,6 +891,14 @@ def _get_call_value(node: NodeCall) -> str: return f"{get_value(node.func)}({args})" +def _get_isnot_value(node: NodeIsNot) -> str: + return "is not" + + +def _get_is_value(node: NodeIs) -> str: + return "is" + + _node_value_map: dict[Type, Callable[[Any], str]] = { type(None): lambda _: repr(None), NodeName: _get_name_value, @@ -858,6 +929,7 @@ def _get_call_value(node: NodeCall) -> str: NodeBitOr: _get_bitor_value, NodeMult: _get_mult_value, NodeListComp: _get_listcomp_value, + NodeSetComp: _get_setcomp_value, NodeLambda: _get_lambda_value, NodeDictComp: _get_dictcomp_value, NodeStarred: _get_starred_value, @@ -869,6 +941,21 @@ def _get_call_value(node: NodeCall) -> str: NodeNot: _get_not_value, NodeArguments: _get_arguments_value, NodeDiv: _get_div_value, + NodeIsNot: _get_isnot_value, + NodeIs: _get_is_value, + NodeAdd: _get_add_value, + NodeSub: _get_sub_value, + NodeEq: _get_eq_value, + NodePow: _get_pow_value, + NodeMod: _get_mod_value, + NodeLShift: _get_lshift_value, + NodeRShift: _get_rshift_value, + NodeIn: _get_in_value, + NodeBitAnd: _get_bitand_value, + NodeFloorDiv: _get_floordiv_value, + NodeNotIn: _get_notin_value, + NodeInvert: _get_invert_value, + NodeBitXor: _get_bitxor_value, } # TODO: remove once Python 3.8 support is dropped diff --git a/src/griffe/expressions.py b/src/griffe/expressions.py index 74e9008eb..ae6afc226 100644 --- a/src/griffe/expressions.py +++ b/src/griffe/expressions.py @@ -104,6 +104,17 @@ def __init__(self, *values: str | Expression | Name) -> None: def __str__(self): return "".join(str(element) for element in self) + @property + def full(self) -> str: + """Return self as a string. + + This property is only useful to the AST utils. + + Returns: + Self as a string. + """ + return str(self) + @property def is_tuple(self) -> bool: """Tell whether this expression represents a tuple. From 2b26b61a61277ecfb025f61f636a32089a62a214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Mon, 27 Dec 2021 21:40:58 +0100 Subject: [PATCH 3/4] style: Sort functions in nodes module --- src/griffe/agents/nodes.py | 416 +++++++++++++++++++------------------ 1 file changed, 209 insertions(+), 207 deletions(-) diff --git a/src/griffe/agents/nodes.py b/src/griffe/agents/nodes.py index 2f539e774..fe04da055 100644 --- a/src/griffe/agents/nodes.py +++ b/src/griffe/agents/nodes.py @@ -485,14 +485,6 @@ def _join(sequence, item): # ========================================================== # annotations -def _get_name_annotation(node: NodeName, parent: Module | Class) -> Name: - return Name(node.id, partial(parent.resolve, node.id)) - - -def _get_constant_annotation(node: NodeConstant, parent: Module | Class) -> str: - return repr(node.value) - - def _get_attribute_annotation(node: NodeAttribute, parent: Module | Class) -> Expression: left = _get_annotation(node.value, parent) @@ -503,6 +495,20 @@ def resolver(): # noqa: WPS430 return Expression(left, ".", right) +def _get_binop_annotation(node: NodeBinOp, parent: Module | Class) -> Expression: + left = _get_annotation(node.left, parent) + right = _get_annotation(node.right, parent) + return Expression(left, _get_annotation(node.op, parent), right) + + +def _get_bitand_annotation(node: NodeBitAnd, parent: Module | Class) -> str: + return " & " + + +def _get_bitor_annotation(node: NodeBitOr, parent: Module | Class) -> str: + return " | " + + def _get_call_annotation(node: NodeCall, parent: Module | Class) -> Expression: posargs = Expression(*[_get_annotation(arg, parent) for arg in node.args]) kwargs = Expression(*[_get_annotation(kwarg, parent) for kwarg in node.keywords]) @@ -518,32 +524,8 @@ def _get_call_annotation(node: NodeCall, parent: Module | Class) -> Expression: return Expression(_get_annotation(node.func, parent), "(", args, ")") -def _get_binop_annotation(node: NodeBinOp, parent: Module | Class) -> Expression: - left = _get_annotation(node.left, parent) - right = _get_annotation(node.right, parent) - return Expression(left, _get_annotation(node.op, parent), right) - - -def _get_bitor_annotation(node: NodeBitOr, parent: Module | Class) -> str: - return " | " - - -def _get_bitand_annotation(node: NodeBitAnd, parent: Module | Class) -> str: - return " & " - - -def _get_subscript_annotation(node: NodeSubscript, parent: Module | Class) -> Expression: - left = _get_annotation(node.value, parent) - subscript = _get_annotation(node.slice, parent) - return Expression(left, "[", subscript, "]") - - -def _get_tuple_annotation(node: NodeTuple, parent: Module | Class) -> Expression: - return Expression(*_join([_get_annotation(el, parent) for el in node.elts], ", ")) - - -def _get_list_annotation(node: NodeList, parent: Module | Class) -> Expression: - return Expression("[", *_join([_get_annotation(el, parent) for el in node.elts], ", "), "]") +def _get_constant_annotation(node: NodeConstant, parent: Module | Class) -> str: + return repr(node.value) def _get_ellipsis_annotation(node: NodeEllipsis, parent: Module | Class) -> str: @@ -560,6 +542,24 @@ def _get_ifexp_annotation(node: NodeIfExp, parent: Module | Class) -> Expression ) +def _get_list_annotation(node: NodeList, parent: Module | Class) -> Expression: + return Expression("[", *_join([_get_annotation(el, parent) for el in node.elts], ", "), "]") + + +def _get_name_annotation(node: NodeName, parent: Module | Class) -> Name: + return Name(node.id, partial(parent.resolve, node.id)) + + +def _get_subscript_annotation(node: NodeSubscript, parent: Module | Class) -> Expression: + left = _get_annotation(node.value, parent) + subscript = _get_annotation(node.slice, parent) + return Expression(left, "[", subscript, "]") + + +def _get_tuple_annotation(node: NodeTuple, parent: Module | Class) -> Expression: + return Expression(*_join([_get_annotation(el, parent) for el in node.elts], ", ")) + + _node_annotation_map: dict[Type, Callable[[Any, Module | Class], str | Name | Expression]] = { NodeName: _get_name_annotation, NodeConstant: _get_constant_annotation, @@ -644,12 +644,18 @@ def get_docstring( # ========================================================== # values -def _get_name_value(node: NodeName) -> str: - return node.id -def _get_constant_value(node: NodeConstant) -> str: - return repr(node.value) +def _get_add_value(node: NodeAdd) -> str: + return "+" + + +def _get_and_value(node: NodeAnd) -> str: + return " and " + + +def _get_arguments_value(node: NodeArguments) -> str: + return ", ".join(arg.arg for arg in node.args) def _get_attribute_value(node: NodeAttribute) -> str: @@ -672,180 +678,186 @@ def _get_bitxor_value(node: NodeBitXor) -> str: return "^" -def _get_invert_value(node: NodeInvert) -> str: - return "~" +def _get_boolop_value(node: NodeBoolOp) -> str: + return get_value(node.op).join(get_value(value) for value in node.values) -def _get_in_value(node: NodeIn) -> str: - return "in" +def _get_call_value(node: NodeCall) -> str: + posargs = ", ".join(get_value(arg) for arg in node.args) + kwargs = ", ".join(get_value(kwarg) for kwarg in node.keywords) + if posargs and kwargs: + args = f"{posargs}, {kwargs}" + elif posargs: + args = posargs + elif kwargs: + args = kwargs + else: + args = "" + return f"{get_value(node.func)}({args})" -def _get_notin_value(node: NodeNotIn) -> str: - return "not in" +def _get_compare_value(node: NodeCompare) -> str: + left = get_value(node.left) + ops = [get_value(op) for op in node.ops] + comparators = [get_value(comparator) for comparator in node.comparators] + return f"{left} " + " ".join(f"{op} {comp}" for op, comp in zip(ops, comparators)) -def _get_eq_value(node: NodeEq) -> str: - return "==" +def _get_comprehension_value(node: NodeComprehension) -> str: + target = get_value(node.target) + iterable = get_value(node.iter) + conditions = [get_value(condition) for condition in node.ifs] + value = f"for {target} in {iterable}" + if conditions: + value = f"{value} if " + " if ".join(conditions) + if node.is_async: + value = f"async {value}" + return value -def _get_add_value(node: NodeAdd) -> str: - return "+" +def _get_constant_value(node: NodeConstant) -> str: + return repr(node.value) -def _get_sub_value(node: NodeSub) -> str: - return "-" +def _get_dict_value(node: NodeDict) -> str: + pairs = zip(node.keys, node.values) + gen = (f"{'None' if key is None else get_value(key)}: {get_value(value)}" for key, value in pairs) # noqa: WPS509 + return "{" + ", ".join(gen) + "}" -def _get_mult_value(node: NodeMult) -> str: - return "*" +def _get_dictcomp_value(node: NodeDictComp) -> str: + key = get_value(node.key) + value = get_value(node.value) + generators = [get_value(gen) for gen in node.generators] + return f"{{{key}: {value} " + " ".join(generators) + "}" def _get_div_value(node: NodeDiv) -> str: return "/" -def _get_floordiv_value(node: NodeFloorDiv) -> str: - return "//" - - -def _get_pow_value(node: NodePow) -> str: - return "**" - - -def _get_mod_value(node: NodeMod) -> str: - return "%" +def _get_ellipsis_value(node: NodeEllipsis) -> str: + return "..." -def _get_lshift_value(node: NodeLShift) -> str: - return "<<" +def _get_eq_value(node: NodeEq) -> str: + return "==" -def _get_rshift_value(node: NodeRShift) -> str: - return ">>" +def _get_floordiv_value(node: NodeFloorDiv) -> str: + return "//" -def _get_unaryop_value(node: NodeUnaryOp) -> str: - return f"{get_value(node.op)}{get_value(node.operand)}" +def _get_formatted_value(node: NodeFormattedValue) -> str: + return f"{{{get_value(node.value)}}}" -def _get_usub_value(node: NodeUSub) -> str: - return "-" +def _get_generatorexp_value(node: NodeGeneratorExp) -> str: + element = get_value(node.elt) + generators = [get_value(gen) for gen in node.generators] + return f"{element} " + " ".join(generators) -def _get_uadd_value(node: NodeUAdd) -> str: - return "+" +def _get_gte_value(node: NodeNotEq) -> str: + return ">=" -def _get_not_value(node: NodeNot) -> str: - return "not " +def _get_gt_value(node: NodeNotEq) -> str: + return ">" -def _get_slice_value(node: NodeSlice) -> str: - value = f"{get_value(node.lower) if node.lower else ''}:{get_value(node.upper) if node.upper else ''}" - if node.step: - value = f"{value}:{get_value(node.step)}" - return value +def _get_ifexp_value(node: NodeIfExp) -> str: + return f"{get_value(node.body)} if {get_value(node.test)} else {get_value(node.orelse)}" -def _get_subscript_value(node: NodeSubscript) -> str: - return f"{get_value(node.value)}[{get_value(node.slice).strip('()')}]" +def _get_invert_value(node: NodeInvert) -> str: + return "~" -def _get_lambda_value(node: NodeLambda) -> str: - return f"lambda {get_value(node.args)}: {get_value(node.body)}" +def _get_in_value(node: NodeIn) -> str: + return "in" -def _get_arguments_value(node: NodeArguments) -> str: - return ", ".join(arg.arg for arg in node.args) +def _get_is_value(node: NodeIs) -> str: + return "is" -def _get_list_value(node: NodeList) -> str: - return "[" + ", ".join(get_value(el) for el in node.elts) + "]" +def _get_isnot_value(node: NodeIsNot) -> str: + return "is not" -def _get_tuple_value(node: NodeTuple) -> str: - return "(" + ", ".join(get_value(el) for el in node.elts) + ")" +def _get_joinedstr_value(node: NodeJoinedStr) -> str: + return "".join(get_value(value) for value in node.values) def _get_keyword_value(node: NodeKeyword) -> str: return f"{node.arg}={get_value(node.value)}" -def _get_dict_value(node: NodeDict) -> str: - pairs = zip(node.keys, node.values) - gen = (f"{'None' if key is None else get_value(key)}: {get_value(value)}" for key, value in pairs) # noqa: WPS509 - return "{" + ", ".join(gen) + "}" +def _get_lambda_value(node: NodeLambda) -> str: + return f"lambda {get_value(node.args)}: {get_value(node.body)}" -def _get_set_value(node: NodeSet) -> str: - return "{" + ", ".join(get_value(el) for el in node.elts) + "}" +def _get_list_value(node: NodeList) -> str: + return "[" + ", ".join(get_value(el) for el in node.elts) + "]" -def _get_ellipsis_value(node: NodeEllipsis) -> str: - return "..." +def _get_listcomp_value(node: NodeListComp) -> str: + element = get_value(node.elt) + generators = [get_value(gen) for gen in node.generators] + return f"[{element} " + " ".join(generators) + "]" -def _get_starred_value(node: NodeStarred) -> str: - return get_value(node.value) +def _get_lshift_value(node: NodeLShift) -> str: + return "<<" -def _get_formatted_value(node: NodeFormattedValue) -> str: - return f"{{{get_value(node.value)}}}" +def _get_lte_value(node: NodeNotEq) -> str: + return "<=" -def _get_joinedstr_value(node: NodeJoinedStr) -> str: - return "".join(get_value(value) for value in node.values) +def _get_lt_value(node: NodeNotEq) -> str: + return "<" -def _get_boolop_value(node: NodeBoolOp) -> str: - return get_value(node.op).join(get_value(value) for value in node.values) +def _get_mod_value(node: NodeMod) -> str: + return "%" -def _get_or_value(node: NodeOr) -> str: - return " or " +def _get_mult_value(node: NodeMult) -> str: + return "*" -def _get_and_value(node: NodeAnd) -> str: - return " and " +def _get_name_value(node: NodeName) -> str: + return node.id -def _get_compare_value(node: NodeCompare) -> str: - left = get_value(node.left) - ops = [get_value(op) for op in node.ops] - comparators = [get_value(comparator) for comparator in node.comparators] - return f"{left} " + " ".join(f"{op} {comp}" for op, comp in zip(ops, comparators)) +def _get_not_value(node: NodeNot) -> str: + return "not " def _get_noteq_value(node: NodeNotEq) -> str: return "!=" -def _get_gte_value(node: NodeNotEq) -> str: - return ">=" - - -def _get_gt_value(node: NodeNotEq) -> str: - return ">" +def _get_notin_value(node: NodeNotIn) -> str: + return "not in" -def _get_lte_value(node: NodeNotEq) -> str: - return "<=" +def _get_or_value(node: NodeOr) -> str: + return " or " -def _get_lt_value(node: NodeNotEq) -> str: - return "<" +def _get_pow_value(node: NodePow) -> str: + return "**" -def _get_generatorexp_value(node: NodeGeneratorExp) -> str: - element = get_value(node.elt) - generators = [get_value(gen) for gen in node.generators] - return f"{element} " + " ".join(generators) +def _get_rshift_value(node: NodeRShift) -> str: + return ">>" -def _get_listcomp_value(node: NodeListComp) -> str: - element = get_value(node.elt) - generators = [get_value(gen) for gen in node.generators] - return f"[{element} " + " ".join(generators) + "]" +def _get_set_value(node: NodeSet) -> str: + return "{" + ", ".join(get_value(el) for el in node.elts) + "}" def _get_setcomp_value(node: NodeSetComp) -> str: @@ -854,108 +866,98 @@ def _get_setcomp_value(node: NodeSetComp) -> str: return f"{{{element} " + " ".join(generators) + "}" -def _get_dictcomp_value(node: NodeDictComp) -> str: - key = get_value(node.key) - value = get_value(node.value) - generators = [get_value(gen) for gen in node.generators] - return f"{{{key}: {value} " + " ".join(generators) + "}" +def _get_slice_value(node: NodeSlice) -> str: + value = f"{get_value(node.lower) if node.lower else ''}:{get_value(node.upper) if node.upper else ''}" + if node.step: + value = f"{value}:{get_value(node.step)}" + return value -def _get_comprehension_value(node: NodeComprehension) -> str: - target = get_value(node.target) - iterable = get_value(node.iter) - conditions = [get_value(condition) for condition in node.ifs] - value = f"for {target} in {iterable}" - if conditions: - value = f"{value} if " + " if ".join(conditions) - if node.is_async: - value = f"async {value}" - return value +def _get_starred_value(node: NodeStarred) -> str: + return get_value(node.value) -def _get_ifexp_value(node: NodeIfExp) -> str: - return f"{get_value(node.body)} if {get_value(node.test)} else {get_value(node.orelse)}" +def _get_sub_value(node: NodeSub) -> str: + return "-" -def _get_call_value(node: NodeCall) -> str: - posargs = ", ".join(get_value(arg) for arg in node.args) - kwargs = ", ".join(get_value(kwarg) for kwarg in node.keywords) - if posargs and kwargs: - args = f"{posargs}, {kwargs}" - elif posargs: - args = posargs - elif kwargs: - args = kwargs - else: - args = "" - return f"{get_value(node.func)}({args})" +def _get_subscript_value(node: NodeSubscript) -> str: + return f"{get_value(node.value)}[{get_value(node.slice).strip('()')}]" -def _get_isnot_value(node: NodeIsNot) -> str: - return "is not" +def _get_tuple_value(node: NodeTuple) -> str: + return "(" + ", ".join(get_value(el) for el in node.elts) + ")" -def _get_is_value(node: NodeIs) -> str: - return "is" +def _get_uadd_value(node: NodeUAdd) -> str: + return "+" + + +def _get_unaryop_value(node: NodeUnaryOp) -> str: + return f"{get_value(node.op)}{get_value(node.operand)}" + + +def _get_usub_value(node: NodeUSub) -> str: + return "-" _node_value_map: dict[Type, Callable[[Any], str]] = { type(None): lambda _: repr(None), - NodeName: _get_name_value, - NodeConstant: _get_constant_value, + NodeAdd: _get_add_value, + NodeAnd: _get_and_value, + NodeArguments: _get_arguments_value, NodeAttribute: _get_attribute_value, NodeBinOp: _get_binop_value, - NodeUnaryOp: _get_unaryop_value, - NodeEllipsis: _get_ellipsis_value, - NodeSubscript: _get_subscript_value, - NodeList: _get_list_value, - NodeTuple: _get_tuple_value, - NodeKeyword: _get_keyword_value, + NodeBitAnd: _get_bitand_value, + NodeBitOr: _get_bitor_value, + NodeBitXor: _get_bitxor_value, + NodeBoolOp: _get_boolop_value, + NodeCall: _get_call_value, + NodeCompare: _get_compare_value, + NodeComprehension: _get_comprehension_value, + NodeConstant: _get_constant_value, + NodeDictComp: _get_dictcomp_value, NodeDict: _get_dict_value, - NodeSet: _get_set_value, + NodeDiv: _get_div_value, + NodeEllipsis: _get_ellipsis_value, + NodeEq: _get_eq_value, + NodeFloorDiv: _get_floordiv_value, NodeFormattedValue: _get_formatted_value, - NodeJoinedStr: _get_joinedstr_value, - NodeCall: _get_call_value, - NodeSlice: _get_slice_value, - NodeBoolOp: _get_boolop_value, NodeGeneratorExp: _get_generatorexp_value, - NodeComprehension: _get_comprehension_value, - NodeCompare: _get_compare_value, - NodeNotEq: _get_noteq_value, NodeGtE: _get_gte_value, NodeGt: _get_gt_value, + NodeIfExp: _get_ifexp_value, + NodeIn: _get_in_value, + NodeInvert: _get_invert_value, + NodeIs: _get_is_value, + NodeIsNot: _get_isnot_value, + NodeJoinedStr: _get_joinedstr_value, + NodeKeyword: _get_keyword_value, + NodeLambda: _get_lambda_value, + NodeListComp: _get_listcomp_value, + NodeList: _get_list_value, + NodeLShift: _get_lshift_value, NodeLtE: _get_lte_value, NodeLt: _get_lt_value, - NodeBitOr: _get_bitor_value, + NodeMod: _get_mod_value, NodeMult: _get_mult_value, - NodeListComp: _get_listcomp_value, - NodeSetComp: _get_setcomp_value, - NodeLambda: _get_lambda_value, - NodeDictComp: _get_dictcomp_value, - NodeStarred: _get_starred_value, - NodeIfExp: _get_ifexp_value, - NodeOr: _get_or_value, - NodeAnd: _get_and_value, - NodeUSub: _get_usub_value, - NodeUAdd: _get_uadd_value, + NodeName: _get_name_value, + NodeNotEq: _get_noteq_value, NodeNot: _get_not_value, - NodeArguments: _get_arguments_value, - NodeDiv: _get_div_value, - NodeIsNot: _get_isnot_value, - NodeIs: _get_is_value, - NodeAdd: _get_add_value, - NodeSub: _get_sub_value, - NodeEq: _get_eq_value, + NodeNotIn: _get_notin_value, + NodeOr: _get_or_value, NodePow: _get_pow_value, - NodeMod: _get_mod_value, - NodeLShift: _get_lshift_value, NodeRShift: _get_rshift_value, - NodeIn: _get_in_value, - NodeBitAnd: _get_bitand_value, - NodeFloorDiv: _get_floordiv_value, - NodeNotIn: _get_notin_value, - NodeInvert: _get_invert_value, - NodeBitXor: _get_bitxor_value, + NodeSetComp: _get_setcomp_value, + NodeSet: _get_set_value, + NodeSlice: _get_slice_value, + NodeStarred: _get_starred_value, + NodeSub: _get_sub_value, + NodeSubscript: _get_subscript_value, + NodeTuple: _get_tuple_value, + NodeUAdd: _get_uadd_value, + NodeUnaryOp: _get_unaryop_value, + NodeUSub: _get_usub_value, } # TODO: remove once Python 3.8 support is dropped From ce44c328f90475c78a57cea09ca1551123b6797f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Mon, 27 Dec 2021 21:43:55 +0100 Subject: [PATCH 4/4] chore: Prepare release 0.6.0 --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd2447fd9..e913b3459 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.6.0](https://github.com/pawamoy/griffe/releases/tag/0.6.0) - 2021-12-27 + +[Compare with 0.5.0](https://github.com/pawamoy/griffe/compare/0.5.0...0.6.0) + +### Features +- Support more AST nodes ([cd1b305](https://github.com/pawamoy/griffe/commit/cd1b305932832ad5347ce829a48a311e3c44d542) by Timothée Mazzucotelli). + +### Code Refactoring +- Use annotation getter for base classes ([8b1a7ed](https://github.com/pawamoy/griffe/commit/8b1a7edc11a72f679689fa9ba9e632907f9304f8) by Timothée Mazzucotelli). + + ## [0.5.0](https://github.com/pawamoy/griffe/releases/tag/0.5.0) - 2021-12-20 [Compare with 0.4.0](https://github.com/pawamoy/griffe/compare/0.4.0...0.5.0)