8000 Support metaclasses by elazarg · Pull Request #2475 · python/mypy · GitHub
[go: up one dir, main page]

Skip to content

Support metaclasses #2475

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Feb 7, 2017
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
nodes
  • Loading branch information
elazarg committed Feb 6, 2017
commit 6ab73681e3a99457035461d9cf591c48d296dae3
8000
23 changes: 23 additions & 0 deletions mypy/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1946,6 +1946,29 @@ def __init__(self, names: 'SymbolTable', defn: ClassDef, module_name: str) -> No
for vd in defn.type_vars:
self.type_vars.append(vd.name)

_metaclass_type = None # type: Optional[mypy.types.Instance]

@property
def metaclass_type(self) -> 'Optional[mypy.types.Instance]':
if self._metaclass_type:
return self._metaclass_type
if self._fullname == 'builtins.type':
return mypy.types.Instance(self, [])
if self.mro is None:
# XXX why does this happen?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a sample that triggers this condition?

Presumably the clue is the comment in __init__ on line 1940 above. Maybe it has something to do with the MRO being calculated twice -- the first time (in semanal.py on line 850) it may fail if there's an import cycle causing a base class being a forward reference; the second time on line 3128 in ThirdPass, called from build.py line 1440. (There's also a call from fixup.py, but I think that's not what you're seeing.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turns out it happens during deserialization in incremental mode: the type of a direct base class may be None. (I should have looked into it long time ago. Sorry)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I will remove the call from deserialize, since it shouldn't be done yet - it should be done from fixup.py. Does it sound reasonable?

return None
if len(self.mro) > 1:
return self.mro[1].metaclass_type
# FIX: assert False
return None

@metaclass_type.setter
def metaclass_type(self, value: 'mypy.types.Instance'):
self._metaclass_type = value

def is_metaclass(self) -> bool:
return self.has_base('builtins.type')

def name(self) -> str:
"""Short name."""
return self.defn.name
3CAE Expand Down
0