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

Add support for NamedTuple methods #3081

Merged
merged 14 commits into from May 16, 2017

Conversation

Projects
None yet
4 participants
@JelleZijlstra
Collaborator

JelleZijlstra commented Mar 29, 2017

This is the mypy implementation of python/typing#352. cc @ilevkivskyi who wrote the runtime implementation.

Also fixes #3075.

This was pretty simple to implement.

@JelleZijlstra JelleZijlstra changed the title from Implement NamedTuple methods to Add support for NamedTuple methods Mar 29, 2017

@gvanrossum

Pretty close to the target!

Show outdated Hide outdated mypy/semanal.py
self.fail('Cannot overwrite NamedTuple attribute "{}"'.format(prohibited),
named_tuple_info.names[prohibited].node)
named_tuple_info.names.update(nt_names)

This comment has been minimized.

@gvanrossum

gvanrossum Mar 29, 2017

Member

Could you assert here that the sets of keys merged here are distinct? ISTM if there's a key being overwritten by this update() call it's problematic.

@gvanrossum

gvanrossum Mar 29, 2017

Member

Could you assert here that the sets of keys merged here are distinct? ISTM if there's a key being overwritten by this update() call it's problematic.

This comment has been minimized.

@JelleZijlstra

JelleZijlstra Mar 29, 2017

Collaborator

The sets will actually always overlap, because build_namedtuple_typeinfo inserts names for the namedtuple fields, and visiting the class body will insert those names again. I think that's safe because build_namedtuple_typeinfo is very restrictive in the kind of statements it accepts within a class body, but I'll add some more tests to verify that it's correct (you already suggested some below).

@JelleZijlstra

JelleZijlstra Mar 29, 2017

Collaborator

The sets will actually always overlap, because build_namedtuple_typeinfo inserts names for the namedtuple fields, and visiting the class body will insert those names again. I think that's safe because build_namedtuple_typeinfo is very restrictive in the kind of statements it accepts within a class body, but I'll add some more tests to verify that it's correct (you already suggested some below).

Show outdated Hide outdated mypy/semanal.py
@@ -912,9 +936,11 @@ def check_namedtuple_classdef(
for stmt in defn.defs.body:
if not isinstance(stmt, AssignmentStmt):
# Still allow pass or ... (for empty namedtuples).
# Also allow methods.
if (not isinstance(stmt, PassStmt) and

This comment has been minimized.

@gvanrossum

gvanrossum Mar 29, 2017

Member

I'd rewrite this using positive logic -- if not X and not (Y and Z) and not Q is a little hard to understand.

@gvanrossum

gvanrossum Mar 29, 2017

Member

I'd rewrite this using positive logic -- if not X and not (Y and Z) and not Q is a little hard to understand.

Show outdated Hide outdated mypy/semanal.py
@@ -3488,8 +3515,10 @@ def visit_func_def(self, fdef: FuncDef) -> None:
self.errors.pop_function()
def visit_class_def(self, tdef: ClassDef) -> None:
for type in tdef.info.bases:
self.analyze(type)
# NamedTuple base classes are special; we don't have to check them again here

This comment has been minimized.

@gvanrossum

gvanrossum Mar 29, 2017

Member

Call out in which function they are analyzed?

@gvanrossum

gvanrossum Mar 29, 2017

Member

Call out in which function they are analyzed?

Show outdated Hide outdated test-data/unit/check-class-namedtuple.test
@@ -482,3 +483,76 @@ Y(y=1, x='1').method()
class CallsBaseInit(X):
def __init__(self, x: str) -> None:
super().__init__(x)
[case testNewNamedTupleWithMethods]
# flags: --python-version 3.6

This comment has been minimized.

@gvanrossum

gvanrossum Mar 29, 2017

Member

Do you still need this flag? IIRC mypy now defaults to 3.6 everywhere?

@gvanrossum

gvanrossum Mar 29, 2017

Member

Do you still need this flag? IIRC mypy now defaults to 3.6 everywhere?

This comment has been minimized.

@JelleZijlstra

JelleZijlstra Mar 29, 2017

Collaborator

I don't feel strongly about it, but it seems mildly useful to call out that this code will only work in 3.6 and not earlier versions.

@JelleZijlstra

JelleZijlstra Mar 29, 2017

Collaborator

I don't feel strongly about it, but it seems mildly useful to call out that this code will only work in 3.6 and not earlier versions.

This comment has been minimized.

@gvanrossum

gvanrossum Mar 29, 2017

Member

But we're not doing consistently, so I don't think it adds value.

@gvanrossum

gvanrossum Mar 29, 2017

Member

But we're not doing consistently, so I don't think it adds value.

Show outdated Hide outdated test-data/unit/check-class-namedtuple.test
class MagicalFields(NamedTuple):
x: int
def __slots__(self) -> None: ... # E: Cannot overwrite NamedTuple attribute "__slots__"
def __new__(cls) -> None: ... # E: Cannot overwrite NamedTuple attribute "__new__"

This comment has been minimized.

@gvanrossum

gvanrossum Mar 29, 2017

Member

I'd like to see a test that shows you can't have both a method and a field with the same name (the update() call I pointed out made me nervous about that).

@gvanrossum

gvanrossum Mar 29, 2017

Member

I'd like to see a test that shows you can't have both a method and a field with the same name (the update() call I pointed out made me nervous about that).

Show outdated Hide outdated mypy/semanal.py
@@ -151,6 +151,11 @@
FUNCTION_FIRST_PHASE_POSTPONE_SECOND = 1 # Add to symbol table but postpone body
FUNCTION_SECOND_PHASE = 2 # Only analyze body
# Matches "_prohibited" in typing.py
NAMEDTUPLE_PROHIBITED_NAMES = ('__new__', '__init__', '__slots__', '__getnewargs__',

This comment has been minimized.

@gvanrossum

gvanrossum Mar 29, 2017

Member

Maybe you don't need this? There's already an error when you define a field starting with underscore.

@gvanrossum

gvanrossum Mar 29, 2017

Member

Maybe you don't need this? There's already an error when you define a field starting with underscore.

This comment has been minimized.

@JelleZijlstra

JelleZijlstra Mar 29, 2017

Collaborator

That's only for fields, but we also need to disallow methods with these names.

@JelleZijlstra

JelleZijlstra Mar 29, 2017

Collaborator

That's only for fields, but we also need to disallow methods with these names.

Show outdated Hide outdated mypy/semanal.py
self.enter_class(defn)
named_tuple_info = self.analyze_namedtuple_classdef(defn)
if named_tuple_info is not None:
# temporarily clear the names dict so we don't get errors about duplicate names that

This comment has been minimized.

@gvanrossum

gvanrossum Mar 29, 2017

Member

While you're at it I prefer comments to start with a capital letter and ended with proper punctuation (except for non-whole-sentence inline comments).

@gvanrossum

gvanrossum Mar 29, 2017

Member

While you're at it I prefer comments to start with a capital letter and ended with proper punctuation (except for non-whole-sentence inline comments).

@gvanrossum

This comment has been minimized.

Show comment
Hide comment
@gvanrossum

gvanrossum Mar 29, 2017

Member

PS. Would also like to see @ilevkivskyi's review.

Member

gvanrossum commented Mar 29, 2017

PS. Would also like to see @ilevkivskyi's review.

@JelleZijlstra

This comment has been minimized.

Show comment
Hide comment
@JelleZijlstra

JelleZijlstra Mar 29, 2017

Collaborator

Thanks for the review! I'll push an update soon.

I realized we still disallow docstrings in namedtuples. Do you mind if I fix that in this PR too? Otherwise I can send another PR.

Collaborator

JelleZijlstra commented Mar 29, 2017

Thanks for the review! I'll push an update soon.

I realized we still disallow docstrings in namedtuples. Do you mind if I fix that in this PR too? Otherwise I can send another PR.

@gvanrossum

This comment has been minimized.

Show comment
Hide comment
@gvanrossum

gvanrossum Mar 29, 2017

Member

I realized we still disallow docstrings in namedtuples. Do you mind if I fix that in this PR too?

Yes please.

Member

gvanrossum commented Mar 29, 2017

I realized we still disallow docstrings in namedtuples. Do you mind if I fix that in this PR too?

Yes please.

@ilevkivskyi

Just few more comments from me.

@@ -2128,6 +2154,7 @@ def add_field(var: Var, is_initialized_in_class: bool = False,
add_field(Var('_field_types', dictype), is_initialized_in_class=True)
add_field(Var('_field_defaults', dictype), is_initialized_in_class=True)
add_field(Var('_source', strtype), is_initialized_in_class=True)
add_field(Var('__annotations__', ordereddictype), is_initialized_in_class=True)

This comment has been minimized.

@ilevkivskyi

ilevkivskyi Mar 29, 2017

Collaborator

This could be unrelated to this PR, but despite the fact that you define it here as ordereddicttype it is revealed as dict in tests. Also, __annotations__ is still just a dict (although it is ordered in 3.6+) and does not have OrderedDict methods like move_to_end().

Also I am not sure why you need it here. Latest typeshed stubs define object.__annotations__

@ilevkivskyi

ilevkivskyi Mar 29, 2017

Collaborator

This could be unrelated to this PR, but despite the fact that you define it here as ordereddicttype it is revealed as dict in tests. Also, __annotations__ is still just a dict (although it is ordered in 3.6+) and does not have OrderedDict methods like move_to_end().

Also I am not sure why you need it here. Latest typeshed stubs define object.__annotations__

This comment has been minimized.

@JelleZijlstra

JelleZijlstra Mar 29, 2017

Collaborator

ordereddictype and dictype are actually the same thing here (they're initialized the same way). Maybe I should just have cleaned up ordereddictype.

@JelleZijlstra

JelleZijlstra Mar 29, 2017

Collaborator

ordereddictype and dictype are actually the same thing here (they're initialized the same way). Maybe I should just have cleaned up ordereddictype.

This comment has been minimized.

@JelleZijlstra

JelleZijlstra Mar 30, 2017

Collaborator

Also, mypy really does think that NamedTuples don't have __annotations__ if I remove this line.

@JelleZijlstra

JelleZijlstra Mar 30, 2017

Collaborator

Also, mypy really does think that NamedTuples don't have __annotations__ if I remove this line.

This comment has been minimized.

@JelleZijlstra

JelleZijlstra Mar 30, 2017

Collaborator

__annotations__ is in fact an OrderedDict at runtime; see _make_nmtuple in typing. I tried to actually specify OrderedDict in the code here, but couldn't get it work, maybe because this code runs early enough in semantic analysis that we don't have other modules imported yet.

@JelleZijlstra

JelleZijlstra Mar 30, 2017

Collaborator

__annotations__ is in fact an OrderedDict at runtime; see _make_nmtuple in typing. I tried to actually specify OrderedDict in the code here, but couldn't get it work, maybe because this code runs early enough in semantic analysis that we don't have other modules imported yet.

This comment has been minimized.

@ilevkivskyi

ilevkivskyi Mar 30, 2017

Collaborator

Also, mypy really does think that NamedTuples don't have __annotations__ if I remove this line.

This looks like a bug (although unrelated to this PR).

@ilevkivskyi

ilevkivskyi Mar 30, 2017

Collaborator

Also, mypy really does think that NamedTuples don't have __annotations__ if I remove this line.

This looks like a bug (although unrelated to this PR).

class Base(NamedTuple):
x: int
def copy(self: T) -> T:

This comment has been minimized.

@ilevkivskyi

ilevkivskyi Mar 29, 2017

Collaborator

I would test another recently added feature: overloaded methods.

@ilevkivskyi

ilevkivskyi Mar 29, 2017

Collaborator

I would test another recently added feature: overloaded methods.

Show outdated Hide outdated test-data/unit/check-class-namedtuple.test
class Child(Base):
def new_method(self) -> int:
return self.x

This comment has been minimized.

@ilevkivskyi

ilevkivskyi Mar 29, 2017

Collaborator

I would add tests checking for self[0] inside a method, its type, access, and error on assignment.

@ilevkivskyi

ilevkivskyi Mar 29, 2017

Collaborator

I would add tests checking for self[0] inside a method, its type, access, and error on assignment.

Show outdated Hide outdated mypy/semanal.py
nt_names = named_tuple_info.names
named_tuple_info.names = SymbolTable()
self.bind_class_type_vars(named_tuple_info)

This comment has been minimized.

@ilevkivskyi

ilevkivskyi Mar 29, 2017

Collaborator

There are few old issues to enable generic named tuples, see e.g. #685
The fact that you are binding an empty symbol table here and then repopulating it later, may complicate the implementation of generic named tuples in future.

@ilevkivskyi

ilevkivskyi Mar 29, 2017

Collaborator

There are few old issues to enable generic named tuples, see e.g. #685
The fact that you are binding an empty symbol table here and then repopulating it later, may complicate the implementation of generic named tuples in future.

This comment has been minimized.

@JelleZijlstra

JelleZijlstra Mar 29, 2017

Collaborator

Generic namedtuples would be nice, but I'm not sure there's anything actionable here. Or should we approach support for methods in a different way?

@JelleZijlstra

JelleZijlstra Mar 29, 2017

Collaborator

Generic namedtuples would be nice, but I'm not sure there's anything actionable here. Or should we approach support for methods in a different way?

This comment has been minimized.

@ilevkivskyi

ilevkivskyi Mar 29, 2017

Collaborator

Or should we approach support for methods in a different way?

I don't have a strong opinion here, but if there is another possible way in view, I would prefer not to trick SymbolTable.

@ilevkivskyi

ilevkivskyi Mar 29, 2017

Collaborator

Or should we approach support for methods in a different way?

I don't have a strong opinion here, but if there is another possible way in view, I would prefer not to trick SymbolTable.

This comment has been minimized.

@gvanrossum

gvanrossum Mar 29, 2017

Member

Agreed the save/restore trick feels unprincipled.

@gvanrossum

gvanrossum Mar 29, 2017

Member

Agreed the save/restore trick feels unprincipled.

This comment has been minimized.

@JelleZijlstra

JelleZijlstra Mar 29, 2017

Collaborator

I agree that it's not ideal but an alternative implementation would probably be more complicated.

@JelleZijlstra

JelleZijlstra Mar 29, 2017

Collaborator

I agree that it's not ideal but an alternative implementation would probably be more complicated.

JelleZijlstra added some commits Mar 29, 2017

allow overriding _source and __doc__
I was testing with an outdated version of typing. Replacing _source does work.

I'm also OK with deciding that all of this is too obscure to support and we shouldn't
care about special-casing __doc__ and _source.
Show outdated Hide outdated test-data/unit/check-class-namedtuple.test
@@ -583,7 +583,7 @@ class MagicalFields(NamedTuple):
x: int
def __slots__(self) -> None: pass # E: Cannot overwrite NamedTuple attribute "__slots__"
def __new__(cls) -> None: pass # E: Cannot overwrite NamedTuple attribute "__new__"
def _source(self) -> int: pass # E: Cannot overwrite NamedTuple attribute "_source"
def _source(self) -> int: pass # _source is ok

This comment has been minimized.

@ilevkivskyi

ilevkivskyi Mar 30, 2017

Collaborator

I think this is an oversight in typing. _source should probably be prohibited. I will make a PR to typing now.

@ilevkivskyi

ilevkivskyi Mar 30, 2017

Collaborator

I think this is an oversight in typing. _source should probably be prohibited. I will make a PR to typing now.

@gvanrossum

This comment has been minimized.

Show comment
Hide comment
@gvanrossum

gvanrossum Mar 31, 2017

Member

I'll have another look when @ilevkivskyi is happy.

Member

gvanrossum commented Mar 31, 2017

I'll have another look when @ilevkivskyi is happy.

Show outdated Hide outdated test-data/unit/check-class-namedtuple.test
def __new__(cls) -> None: pass # E: Cannot overwrite NamedTuple attribute "__new__"
def _source(self) -> int: pass # E: Cannot overwrite NamedTuple attribute "_source"
__annotations__ = {'x': float} # E: NamedTuple field name cannot start with an underscore: __annotations__ \
# E: Invalid statement in NamedTuple definition; expected "field_name: field_type" \

This comment has been minimized.

@ilevkivskyi

ilevkivskyi Mar 31, 2017

Collaborator

While you at it, maybe you could update the error message to use "field_name: field_type [= default]"?

@ilevkivskyi

ilevkivskyi Mar 31, 2017

Collaborator

While you at it, maybe you could update the error message to use "field_name: field_type [= default]"?

@ilevkivskyi

This comment has been minimized.

Show comment
Hide comment
@ilevkivskyi

ilevkivskyi Mar 31, 2017

Collaborator

I'll have another look when @ilevkivskyi is happy.

I am almost happy now, I am only a bit worried about the trick with SymbolTable().

Collaborator

ilevkivskyi commented Mar 31, 2017

I'll have another look when @ilevkivskyi is happy.

I am almost happy now, I am only a bit worried about the trick with SymbolTable().

@JelleZijlstra

This comment has been minimized.

Show comment
Hide comment
@JelleZijlstra

JelleZijlstra Apr 28, 2017

Collaborator

There's a pretty big merge conflict now, I'll try to resolve it tonight.

Collaborator

JelleZijlstra commented Apr 28, 2017

There's a pretty big merge conflict now, I'll try to resolve it tonight.

@gvanrossum

This comment has been minimized.

Show comment
Hide comment
@gvanrossum

gvanrossum Apr 28, 2017

Member

Before merging I want to be sure this passes with our internal code bases and also the quick and incremental tests that Jukka is developing.

Member

gvanrossum commented Apr 28, 2017

Before merging I want to be sure this passes with our internal code bases and also the quick and incremental tests that Jukka is developing.

@Daenyth

This comment has been minimized.

Show comment
Hide comment
@Daenyth

Daenyth May 3, 2017

Until this is merged, is there a way I can suppress this specific error so that I can use mypy on files with NamedTuples like this?

Daenyth commented May 3, 2017

Until this is merged, is there a way I can suppress this specific error so that I can use mypy on files with NamedTuples like this?

@gvanrossum

This comment has been minimized.

Show comment
Hide comment
@gvanrossum

gvanrossum May 3, 2017

Member

Until this is merged, is there a way I can suppress this specific error so that I can use mypy on files with NamedTuples like this?

You can put a # type: ignore comment on the line where the unwanted error appears.

Member

gvanrossum commented May 3, 2017

Until this is merged, is there a way I can suppress this specific error so that I can use mypy on files with NamedTuples like this?

You can put a # type: ignore comment on the line where the unwanted error appears.

@JelleZijlstra

This comment has been minimized.

Show comment
Hide comment
@JelleZijlstra

JelleZijlstra May 3, 2017

Collaborator

It probably still won't recognize that the methods exist though.

Collaborator

JelleZijlstra commented May 3, 2017

It probably still won't recognize that the methods exist though.

@Daenyth

Can you add a test case covering @classmethod?

It crashes in master but works in this branch

from typing import *

class Bar(NamedTuple):
    x: str

    @classmethod
    def new(cls, f: str) -> 'Bar':
        return Bar(x=f)

Also I still get a type error: foo.py:6: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]"

It's probably worth also checking @property and @staticmethod

@JelleZijlstra

This comment has been minimized.

Show comment
Hide comment
@JelleZijlstra

JelleZijlstra May 4, 2017

Collaborator

Added tests for all those and fixed some issues it uncovered. I needed another hack to make the cls argument to classmethods work.

Collaborator

JelleZijlstra commented May 4, 2017

Added tests for all those and fixed some issues it uncovered. I needed another hack to make the cls argument to classmethods work.

@Daenyth

Class level fields fail:

from typing import *
class Foo(NamedTuple):
    x: int
    y = 1  # Not one of the tuple fields but a class attribute
foo.py:4: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]"
@JelleZijlstra

This comment has been minimized.

Show comment
Hide comment
@JelleZijlstra

JelleZijlstra May 5, 2017

Collaborator

Wow, I hadn't thought of doing that. It does seem to work at runtime. I'd prefer to leave it out of this PR though, since the PR has been going on for long enough as is and I see some issues with that pattern. I think the fact that it works at runtime is probably an accident; it's not tested in typing and wasn't mentioned as far as I remember in the discussions about adding the feature there.

If you have a class variable, it becomes very awkward to annotate it. If I make

class Foo(NamedTuple):
    x = []
    y: int = 1

mypy will tell me that I need to specify a more precise type for the list. But if I do

class Foo(NamedTuple):
    x: List['Foo'] = []
    y: int = 1

x has become an instance field. I suppose

class Foo(NamedTuple):
    x = []  # type: List[Foo]
    y = 1

would work, but that just seems really confusing, since now you get radically different behavior depending on whether you used a type comment or a PEP 526-style annotation. Maybe we can figure out an acceptable way to handle this problem, but it seems complex enough that it's better to separate it out. Let's keep this PR focused on methods (and docstrings, which were trivial to implement).

Collaborator

JelleZijlstra commented May 5, 2017

Wow, I hadn't thought of doing that. It does seem to work at runtime. I'd prefer to leave it out of this PR though, since the PR has been going on for long enough as is and I see some issues with that pattern. I think the fact that it works at runtime is probably an accident; it's not tested in typing and wasn't mentioned as far as I remember in the discussions about adding the feature there.

If you have a class variable, it becomes very awkward to annotate it. If I make

class Foo(NamedTuple):
    x = []
    y: int = 1

mypy will tell me that I need to specify a more precise type for the list. But if I do

class Foo(NamedTuple):
    x: List['Foo'] = []
    y: int = 1

x has become an instance field. I suppose

class Foo(NamedTuple):
    x = []  # type: List[Foo]
    y = 1

would work, but that just seems really confusing, since now you get radically different behavior depending on whether you used a type comment or a PEP 526-style annotation. Maybe we can figure out an acceptable way to handle this problem, but it seems complex enough that it's better to separate it out. Let's keep this PR focused on methods (and docstrings, which were trivial to implement).

@Daenyth

This comment has been minimized.

Show comment
Hide comment
@Daenyth

Daenyth May 5, 2017

Daenyth commented May 5, 2017

@ilevkivskyi

This comment has been minimized.

Show comment
Hide comment
@ilevkivskyi

ilevkivskyi May 5, 2017

Collaborator

Wow, I hadn't thought of doing that. It does seem to work at runtime. I'd prefer to leave it out of this PR though, since the PR has been going on for long enough as is and I see some issues with that pattern

It works at runtime since it is not easy to prohibit everything at runtime :-)
But seriously, I don't think we need this. Named tuples are intended to be "minimalistic" classes, and possible syntactic solutions for class variables in named tuples seem confusing.

Collaborator

ilevkivskyi commented May 5, 2017

Wow, I hadn't thought of doing that. It does seem to work at runtime. I'd prefer to leave it out of this PR though, since the PR has been going on for long enough as is and I see some issues with that pattern

It works at runtime since it is not easy to prohibit everything at runtime :-)
But seriously, I don't think we need this. Named tuples are intended to be "minimalistic" classes, and possible syntactic solutions for class variables in named tuples seem confusing.

@gvanrossum

This comment has been minimized.

Show comment
Hide comment
@gvanrossum

gvanrossum May 10, 2017

Member

Gah! I thought we had this feature already. What will it take to finish this?

Member

gvanrossum commented May 10, 2017

Gah! I thought we had this feature already. What will it take to finish this?

@ilevkivskyi

This comment has been minimized.

Show comment
Hide comment
@ilevkivskyi

ilevkivskyi May 10, 2017

Collaborator

Gah! I thought we had this feature already. What will it take to finish this?

I think it is waiting for your review.

I'll have another look when @ilevkivskyi is happy.

I am practically happy with this, the SymbolTable() trick looks not too aesthetic to me, but this is probably just a matter of taste.

Collaborator

ilevkivskyi commented May 10, 2017

Gah! I thought we had this feature already. What will it take to finish this?

I think it is waiting for your review.

I'll have another look when @ilevkivskyi is happy.

I am practically happy with this, the SymbolTable() trick looks not too aesthetic to me, but this is probably just a matter of taste.

@JelleZijlstra

This comment has been minimized.

Show comment
Hide comment
@JelleZijlstra

JelleZijlstra May 10, 2017

Collaborator

You need to merge it. :)

As far as I'm aware, this code works and the only concern (brought up by you and Ivan above) is that the approach taken is hacky, since it has some strange manual manipulation of the symbol table. I don't know of an easy way to avoid the symtable manipulation, so my preference is to merge this as is and maybe later do a refactoring to make NamedTuples more like normal classes.

Collaborator

JelleZijlstra commented May 10, 2017

You need to merge it. :)

As far as I'm aware, this code works and the only concern (brought up by you and Ivan above) is that the approach taken is hacky, since it has some strange manual manipulation of the symbol table. I don't know of an easy way to avoid the symtable manipulation, so my preference is to merge this as is and maybe later do a refactoring to make NamedTuples more like normal classes.

@gvanrossum

This comment has been minimized.

Show comment
Hide comment
@gvanrossum

gvanrossum May 11, 2017

Member

Sorry about that! I'm trying to restore personal state that I've apparently lost. I will review this.

Member

gvanrossum commented May 11, 2017

Sorry about that! I'm trying to restore personal state that I've apparently lost. I will review this.

@gvanrossum gvanrossum merged commit 3589c08 into python:master May 16, 2017

2 checks passed

continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@gvanrossum

This comment has been minimized.

Show comment
Hide comment
@gvanrossum

gvanrossum May 16, 2017

Member

Finally! Sorry again.

Member

gvanrossum commented May 16, 2017

Finally! Sorry again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment