Skip to content

Conversation

@JelleZijlstra
Copy link
Member

Similar to deque, which was added recently.

return _generic_new(collections.deque, cls, *args, **kwds)


class Counter(collections.Counter, MutableSequence[T]):
Copy link
Member

Choose a reason for hiding this comment

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

I believe this should be Dict[T, int] instead

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, sorry for missing that.

src/typing.py Outdated
return _generic_new(collections.deque, cls, *args, **kwds)


class Counter(collections.Counter, MutableSequence[T], extra=collections.Counter):
Copy link
Member

Choose a reason for hiding this comment

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

Dict[T, int], see above comment.

@ilevkivskyi
Copy link
Member

I am not against this. If others are also not against this, then I think we could add these two new generic collections.

# ChainMap only exists in 3.3+
__all__.append('ChainMap')

class ChainMap(collections.ChainMap, MutableMapping[KT, VT],
Copy link
Member

Choose a reason for hiding this comment

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

typeshed defines this as Dict[KT, VT], I am not sure this is right, but typing and typeshed should be in sync for sure.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think MutableMapping is right; ChainMap is not a subclass of dict. I'll submit that change to typeshed.

def __new__(cls, *args, **kwds):
if _geqv(cls, Counter):
raise TypeError("Type Counter cannot be instantiated; "
"use Counter() instead")
Copy link
Member

Choose a reason for hiding this comment

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

I would use full name collections.Counter() in the second line, otherwise this error message reads unclear.
(The same applies to Python 3 version).


def test_counter(self):
self.assertIsSubclass(collections.Counter, typing.Counter)

Copy link
Member

Choose a reason for hiding this comment

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

Please add a test checking that a subclass of counter could be instantiated, as you do for ChainMap in test_chainmap_subclass. (And also for Python 3)

@ilevkivskyi
Copy link
Member

Thank you!
I have added two more minor comments. I would wait for typeshed PR, then this one could be merged.

@ilevkivskyi
Copy link
Member

@gvanrossum Could you please take a look at this PR and python/typeshed#878?

I think the PRs are ready, but I would like to have your approval.

@ilevkivskyi
Copy link
Member

@JelleZijlstra could you please update the PR allowing instantiation of Counter and ChainMap following #381? (Don't worry about merge conflict, I will take care if necessary)

@JelleZijlstra
Copy link
Member Author

Nice, thanks! Now we'll no longer need both from typing import Counter and from collections import Counter to make a typed Counter. I'll push the change.

Pretty much copied from deque.
Only to the Python 3 version because ChainMap was added in 3.3.
Apparently typing still supports 3.2
@JelleZijlstra
Copy link
Member Author

Rebased the branch and changed it to allow instantiation.

def test_chainmap_type_erasure_special(self):
class MyChain(typing.ChainMap[str, T]): ...
self.assertIs(MyChain[int]().__class__, MyChain)
self.assertIs(MyChain[int]().__orig_class__, MyChain[int])
Copy link
Member

Choose a reason for hiding this comment

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

One last thing, you use assertIs here that relies on generic type cache. This is a bit dangerous if the test is run in refleak hunting mode (-R). I see two options here:

  • change this to use assertEqual
  • add self.clear_caches() at beginning and edit the comment in the previous test_type_erasure_special to say something like # this test and the next one are only two that rely on type caching

Sorry for not noticing this before.

Copy link
Member

Choose a reason for hiding this comment

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

Note that assertIs in other places in your PR is OK since it does not depend on generic type caching.

Copy link
Member Author

Choose a reason for hiding this comment

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

I copied this from similar tests for defaultdict above; should I change those too?

Copy link
Member

Choose a reason for hiding this comment

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

No, that one is intentional. (note that it is already "protected" by self.clear_caches())

@gvanrossum
Copy link
Member

I am happy to see this go in. (I haven't done a detailed code review, but I trust the two of you.)

Once this goes in we need additional changes in typeshed, right?

@ilevkivskyi
Copy link
Member

Once this goes in we need additional changes in typeshed, right?

Yes, @JelleZijlstra would you prefer to make a PR for typeshed?

@ilevkivskyi ilevkivskyi merged commit d6390f3 into python:master Feb 10, 2017
@JelleZijlstra
Copy link
Member Author

Yes, I can do that later today or tomorrow. Thanks for merging it in!

@JelleZijlstra JelleZijlstra deleted the counter branch February 10, 2017 19:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants