Skip to content

Commit

Permalink
dep: move Dep caching support into CachedDep class
Browse files Browse the repository at this point in the history
That provides LRU-based instance caching for Dep objects.
  • Loading branch information
radhermit committed Nov 29, 2023
1 parent 6fb051e commit 2bc7a5d
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 21 deletions.
3 changes: 2 additions & 1 deletion benches/test_dep.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from pkgcore.ebuild.atom import atom as pkgcore_dep
from portage.dep import Atom as portage_dep

from pkgcraft.dep import CachedDep as pkgcraft_cached_dep
from pkgcraft.dep import Dep as pkgcraft_dep

pytest_plugins = ("benchmark", "pkgcraft")
Expand All @@ -16,7 +17,7 @@ def random_dep(func, random_str):

dep_funcs = [
("pkgcraft", pkgcraft_dep),
("pkgcraft", pkgcraft_dep.cached),
("pkgcraft", pkgcraft_cached_dep),
("pkgcore", pkgcore_dep),
("portage", portage_dep),
]
Expand Down
6 changes: 3 additions & 3 deletions membench/dep.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
from pkgcore.ebuild.atom import atom as pkgcore_dep
from portage.dep import Atom as portage_dep

from pkgcraft.dep import Dep as pkgcraft_dep
from pkgcraft.dep import CachedDep, Dep

eprint = lambda x: print(x, file=sys.stderr)

dep_funcs = [
("pkgcraft", pkgcraft_dep),
("pkgcraft-cached", pkgcraft_dep.cached),
("pkgcraft", Dep),
("pkgcraft-cached", CachedDep),
("pkgcore", pkgcore_dep),
("portage", portage_dep),
]
Expand Down
18 changes: 5 additions & 13 deletions src/pkgcraft/dep/pkg.pyx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from enum import IntEnum
from functools import lru_cache
from types import MappingProxyType

cimport cython
Expand All @@ -12,18 +11,12 @@ from ..restrict cimport Restrict
from . cimport Cpv
from .version cimport Version

from .._misc import LruInstanceCache
from ..eapi import EAPI_LATEST
from ..error import InvalidDep
from ..types import OrderedFrozenSet


# TODO: merge with Dep.cached function when cython bug is fixed
# https://github.com/cython/cython/issues/1434
@lru_cache(maxsize=10000)
def _cached_dep(cls, dep, eapi=None):
return cls(dep, eapi)


class Blocker(IntEnum):
"""Package dependency blocker."""
Strong = C.BLOCKER_STRONG
Expand Down Expand Up @@ -125,11 +118,6 @@ cdef class Dep:
inst.ptr = <C.Dep *>ptr
return inst

@classmethod
def cached(cls, s: str, eapi=None):
"""Return a cached Dep if one exists, otherwise return a new instance."""
return _cached_dep(cls, s, eapi)

@staticmethod
def valid(s: str, eapi=None, raised=False):
"""Determine if a string is a valid package dependency.
Expand Down Expand Up @@ -618,6 +606,10 @@ cdef class Dep:
C.pkgcraft_dep_free(self.ptr)


class CachedDep(Dep, metaclass=LruInstanceCache):
"""Package dependency with LRU-based instance caching."""


@cython.final
cdef class Cpn(Dep):
"""Unversioned package dependency."""
Expand Down
10 changes: 6 additions & 4 deletions tests/dep/test_pkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,16 +355,18 @@ def test_hash(self):
length = 1 if d["equal"] else len(d["versions"])
assert len(s) == length

def test_cached(self):
l = [Dep.cached("cat/pkg") for _ in range(1000)]
assert len(l) == 1000

def test_pickle(self):
dep = Dep("=cat/pkg-1-r2:0/2=[a,b,c]")
new_dep = pickle.loads(pickle.dumps(dep))
assert dep == new_dep


class TestCachedDep:
def test_cached(self):
assert CachedDep("cat/pkg") is CachedDep("cat/pkg")
assert Dep("cat/pkg") is not Dep("cat/pkg")


class TestCpn:
def test_creation(self):
dep = Cpn("cat/pkg")
Expand Down

0 comments on commit 2bc7a5d

Please sign in to comment.