Skip to content
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

fix RuntimeError with Python 3.5 #27

Closed
wants to merge 11 commits into from
Closed

fix RuntimeError with Python 3.5 #27

wants to merge 11 commits into from

Conversation

kophy
Copy link
Contributor

@kophy kophy commented May 20, 2017

  1. fix Python 3.5 RuntimeError mentioned in issue RuntimeError with Python3.5 #25
  2. add callback support for expired items (personally think it's useful)

@horkhe
Copy link
Member

horkhe commented Jun 12, 2017

It is better not to mix a bug fix and a feature proposal in one PR.

@kophy
Copy link
Contributor Author

kophy commented Jun 13, 2017

Sure. Shall I remove callback part and make a new PR later? @horkhe

@horkhe
Copy link
Member

horkhe commented Jun 13, 2017

yes, please

@kophy kophy changed the title fix RuntimeError with Python 3.5 and add callback support fix RuntimeError with Python 3.5 Jun 14, 2017
@@ -69,7 +69,10 @@ def __setitem__(self, key, value):
""" Set d[key] to value. """
with self.lock:
if len(self) == self.max_len:
self.popitem(last=False)
try:
self.popitem(last=False)
Copy link
Member

Choose a reason for hiding this comment

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

I assume that python 3.x raises exception if it is empty? If so then it should be a specific exception type so please catch only that specific exception in the except clause below.

@@ -110,7 +113,7 @@ def get(self, key, default=None, with_age=False):
def items(self):
""" Return a copy of the dictionary's list of (key, value) pairs. """
r = []
for key in self:
for key in list(self.keys()):
Copy link
Member

Choose a reason for hiding this comment

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

I am not familiar with python 3.x, why do we need list here? Anyway even if it is needed for 3.x it is definitely not needed in 2.x and it would be better not to have this overhead when it is not needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That makes sense. I will check version first.
In python 3.5, there are some implementation changes of OrderedDict, so directly iterating will give RuntimeError: OrderedDict mutated during iteration.

r.append((key, self[key]))
except KeyError:
pass
if sys.version_info >= (3, 5):
Copy link
Member

Choose a reason for hiding this comment

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

I am not very fond of this solution for two reasons. Code duplication and the version check is performed every time when we call the method. How about we create _safe_keys alias at the class level:

if sys.version_info >= (3, 5):
    _safe_keys = lambda self: list(self.keys())
else:
    _safe_keys = keys

And will use it as follows:

def items(self):
        """ Return a copy of the dictionary's list of (key, value) pairs. """
        r = []
        for key in self._safe_keys():
            try:
                r.append((key, self[key]))
            except KeyError:
                pass
        return r

In this case version check is performed only once when the class is imported and code duplication is avoided.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that's certainly a better solution, but the lambda function will give TypeError under python 3. I will try to solve this.

@horkhe
Copy link
Member

horkhe commented Jun 15, 2017

@kophy please squash the changes and I will merge the PR.

@kophy kophy closed this Jun 15, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants