-
Notifications
You must be signed in to change notification settings - Fork 345
feat: drop cachetools dependency in favor of simple local implementation
#1590
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
Changes from all commits
727e193
f233c7c
bf9556b
b95e292
e08656c
6978b07
c213cfe
11b3325
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| # Copyright 2025 Google LLC | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # https://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| from collections import OrderedDict | ||
|
|
||
|
|
||
| class LRUCache(dict): | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a benefit to using a custom implementation over
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Daniel: Thanks for asking the question. The short answer is that Incompatible Introspection: The consuming code that uses Explicit Invalidation: If the token is expired, the code needs to explicitly replace it. Usage Pattern: |
||
| def __init__(self, maxsize): | ||
| super().__init__() | ||
| self._order = OrderedDict() | ||
| self.maxsize = maxsize | ||
|
|
||
| def clear(self): | ||
| super().clear() | ||
| self._order.clear() | ||
|
|
||
| def get(self, key, default=None): | ||
| try: | ||
| value = super().__getitem__(key) | ||
| self._update(key) | ||
| return value | ||
| except KeyError: | ||
| return default | ||
|
|
||
| def __getitem__(self, key): | ||
| value = super().__getitem__(key) | ||
| self._update(key) | ||
| return value | ||
|
|
||
| def __setitem__(self, key, value): | ||
| maxsize = self.maxsize | ||
| if maxsize <= 0: | ||
| return | ||
| if key not in self: | ||
| while len(self) >= maxsize: | ||
| self.popitem() | ||
| super().__setitem__(key, value) | ||
| self._update(key) | ||
|
|
||
| def __delitem__(self, key): | ||
| super().__delitem__(key) | ||
| del self._order[key] | ||
|
|
||
| def popitem(self): | ||
| """Remove and return the least recently used key-value pair.""" | ||
| key, _ = self._order.popitem(last=False) | ||
| return key, super().pop(key) | ||
|
|
||
| def _update(self, key): | ||
| try: | ||
| self._order.move_to_end(key) | ||
| except KeyError: | ||
| self._order[key] = None | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| from google.auth._cache import LRUCache | ||
|
|
||
|
|
||
| def test_lru_cache(): | ||
| """Test the LRUCache for generally expected functionality and ordering.""" | ||
| lru_cache = LRUCache(2) | ||
| lru_cache["a"] = 1 | ||
| lru_cache["b"] = 2 | ||
| assert lru_cache["a"] == 1 | ||
| lru_cache["c"] = 3 | ||
| assert "b" not in lru_cache | ||
| assert lru_cache["a"] == 1 | ||
| assert lru_cache["c"] == 3 | ||
| lru_cache["d"] = 4 | ||
| assert "a" not in lru_cache | ||
| assert lru_cache["c"] == 3 | ||
| assert lru_cache["d"] == 4 | ||
|
|
||
|
|
||
| def test_zero_size_lru_cache(): | ||
| """Confirm the LRUCache handles zero-size correctly.""" | ||
| lru_cache = LRUCache(0) | ||
| lru_cache["a"] = 1 | ||
| assert "a" not in lru_cache | ||
|
|
||
|
|
||
| def test_lru_cache_get_updates_lru(): | ||
| """Confirm the LRUCache handles get calls correctly.""" | ||
| lru_cache = LRUCache(2) | ||
| lru_cache["a"] = 1 | ||
| lru_cache["b"] = 2 | ||
|
|
||
| # Access "a" via get(), making it MRU. | ||
| assert lru_cache.get("a") == 1 | ||
|
|
||
| # Add "c", which should evict "b" (LRU), not "a". | ||
| lru_cache["c"] = 3 | ||
|
|
||
| assert "a" in lru_cache | ||
| assert "b" not in lru_cache | ||
| assert "c" in lru_cache | ||
|
|
||
|
|
||
| def test_lru_cache_get_missing(): | ||
| """Confirm the LRUCache handles missing keys correctly.""" | ||
| lru_cache = LRUCache(2) | ||
| assert lru_cache.get("missing") is None | ||
| assert lru_cache.get("missing", "default") == "default" | ||
chalmerlowe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| def test_lru_cache_clear(): | ||
| """Confirm the LRUCache clears the cache properly.""" | ||
| lru_cache = LRUCache(2) | ||
| lru_cache["a"] = 1 | ||
| lru_cache["b"] = 2 | ||
| assert len(lru_cache) == 2 | ||
|
|
||
| lru_cache.clear() | ||
| assert len(lru_cache) == 0 | ||
| assert "a" not in lru_cache | ||
| assert "b" not in lru_cache | ||
| # Ensure internal order is also cleared | ||
| assert len(lru_cache._order) == 0 | ||
|
|
||
|
|
||
| def test_lru_cache_delitem(): | ||
| """Confirm the LRUCache deletes individual items properly.""" | ||
| lru_cache = LRUCache(2) | ||
| lru_cache["a"] = 1 | ||
| lru_cache["b"] = 2 | ||
|
|
||
| del lru_cache["a"] | ||
| assert "a" not in lru_cache | ||
| assert len(lru_cache) == 1 | ||
| # Ensure it's removed from internal order | ||
| assert "a" not in lru_cache._order | ||
|
|
||
| # Test that we can continue using the cache | ||
| lru_cache["c"] = 3 | ||
| assert "c" in lru_cache | ||
| assert "b" in lru_cache | ||
| assert len(lru_cache) == 2 | ||
Uh oh!
There was an error while loading. Please reload this page.