Return an Attribute from the assignment or None if you can't make one.
(
ctx: mypy.plugin.ClassDefContext,
auto_attribs: bool,
class_kw_only: bool,
lhs: NameExpr,
rvalue: CallExpr,
stmt: AssignmentStmt,
)
| 621 | |
| 622 | |
| 623 | def _attribute_from_attrib_maker( |
| 624 | ctx: mypy.plugin.ClassDefContext, |
| 625 | auto_attribs: bool, |
| 626 | class_kw_only: bool, |
| 627 | lhs: NameExpr, |
| 628 | rvalue: CallExpr, |
| 629 | stmt: AssignmentStmt, |
| 630 | ) -> Attribute | None: |
| 631 | """Return an Attribute from the assignment or None if you can't make one.""" |
| 632 | if auto_attribs and not stmt.new_syntax: |
| 633 | # auto_attribs requires an annotation on *every* attr.ib. |
| 634 | assert lhs.node is not None |
| 635 | ctx.api.msg.need_annotation_for_var(lhs.node, stmt) |
| 636 | return None |
| 637 | |
| 638 | if len(stmt.lvalues) > 1: |
| 639 | ctx.api.fail("Too many names for one attribute", stmt) |
| 640 | return None |
| 641 | |
| 642 | # This is the type that belongs in the __init__ method for this attrib. |
| 643 | init_type = stmt.type |
| 644 | |
| 645 | # Read all the arguments from the call. |
| 646 | init = _get_bool_argument(ctx, rvalue, "init", True) |
| 647 | # The class decorator kw_only value can be overridden by the attribute value |
| 648 | # See https://github.com/python-attrs/attrs/pull/1457 |
| 649 | kw_only = _get_bool_argument(ctx, rvalue, "kw_only", class_kw_only) |
| 650 | |
| 651 | # TODO: Check for attr.NOTHING |
| 652 | attr_has_default = bool(_get_argument(rvalue, "default")) |
| 653 | attr_has_factory = bool(_get_argument(rvalue, "factory")) |
| 654 | |
| 655 | if attr_has_default and attr_has_factory: |
| 656 | ctx.api.fail('Can\'t pass both "default" and "factory".', rvalue) |
| 657 | elif attr_has_factory: |
| 658 | attr_has_default = True |
| 659 | |
| 660 | # If the type isn't set through annotation but is passed through `type=` use that. |
| 661 | type_arg = _get_argument(rvalue, "type") |
| 662 | if type_arg and not init_type: |
| 663 | try: |
| 664 | un_type = expr_to_unanalyzed_type(type_arg, ctx.api.options, ctx.api.is_stub_file) |
| 665 | except TypeTranslationError: |
| 666 | ctx.api.fail("Invalid argument to type", type_arg) |
| 667 | else: |
| 668 | init_type = ctx.api.anal_type(un_type) |
| 669 | if init_type and isinstance(lhs.node, Var) and not lhs.node.type: |
| 670 | # If there is no annotation, add one. |
| 671 | lhs.node.type = init_type |
| 672 | lhs.is_inferred_def = False |
| 673 | |
| 674 | # Note: convert is deprecated but works the same as converter. |
| 675 | converter = _get_argument(rvalue, "converter") |
| 676 | convert = _get_argument(rvalue, "convert") |
| 677 | if convert and converter: |
| 678 | ctx.api.fail('Can\'t pass both "convert" and "converter".', rvalue) |
| 679 | elif convert: |
| 680 | ctx.api.fail("convert is deprecated, use converter", rvalue) |
no test coverage detected
searching dependent graphs…