# SPDX-License-Identifier: Apache-2.0
# Copyright Contributors to the Rez Project
"""
In-memory package repository
"""
from rez.package_repository import PackageRepository
from rez.package_resources import PackageFamilyResource, VariantResourceHelper, \
PackageResourceHelper, package_pod_schema
from rez.utils.formatting import is_valid_package_name
from rez.utils.resources import ResourcePool, cached_property
from rez.vendor.version.requirement import VersionedObject
# This repository type is used when loading 'developer' packages (a package.yaml
# or package.py in a developer's working directory), and when programmatically
# creating packages via `PackageMaker`.
#------------------------------------------------------------------------------
# resource classes
#------------------------------------------------------------------------------
[docs]class MemoryPackageFamilyResource(PackageFamilyResource):
key = "memory.family"
repository_type = "memory"
def _uri(self):
return "%s:%s" % (self.location, self.name)
[docs] def iter_packages(self):
data = self._repository.data.get(self.name, {})
# check for unversioned package
if "_NO_VERSION" in data:
package = self._repository.get_resource(
MemoryPackageResource.key,
location=self.location,
name=self.name)
yield package
return
# versioned packages
for version_str in data.keys():
package = self._repository.get_resource(
MemoryPackageResource.key,
location=self.location,
name=self.name,
version=version_str)
yield package
[docs]class MemoryPackageResource(PackageResourceHelper):
key = "memory.package"
variant_key = "memory.variant"
repository_type = "memory"
schema = package_pod_schema
def _uri(self):
obj = VersionedObject.construct(self.name, self.version)
return "%s:%s" % (self.location, str(obj))
@property
def base(self):
return None # memory types do not have 'base'
@cached_property
def parent(self):
family = self._repository.get_resource(
MemoryPackageFamilyResource.key,
location=self.location,
name=self.name)
return family
def _load(self):
family_data = self._repository.data.get(self.name, {})
version_str = self.get("version")
if not version_str:
version_str = "_NO_VERSION"
package_data = family_data.get(version_str, {})
return package_data
[docs]class MemoryVariantResource(VariantResourceHelper):
key = "memory.variant"
repository_type = "memory"
def _root(self):
return None # memory types do not have 'root'
@cached_property
def parent(self):
package = self._repository.get_resource(
MemoryPackageResource.key,
location=self.location,
name=self.name,
version=self.get("version")
)
return package
#------------------------------------------------------------------------------
# repository
#------------------------------------------------------------------------------
[docs]class MemoryPackageRepository(PackageRepository):
"""An in-memory package repository.
Packages are stored in a dict, organised like so:
{
"foo": {
"1.0.0": {
"name": "foo",
"version": "1.0.0",
"description": "does foo-like things.",
}
},
"bah": {
"_NO_VERSION": {
"name": "bah",
"description": "does bah-like things.",
"requires": ["python-2.6", "foo-1+"]
}
}
}
This example repository contains one versioned package 'foo', and one
unversioned package 'bah'.
"""
[docs] @classmethod
def name(cls):
return "memory"
[docs] @classmethod
def create_repository(cls, repository_data):
"""Create a standalone, in-memory repository.
Using this function bypasses the `package_repository_manager` singleton.
This is usually desired however, since in-memory repositories are for
temporarily storing programmatically created packages, which we do not
want to cache and that do not persist.
Args:
repository_data (dict): Repository data, see class docstring.
Returns:
`MemoryPackageRepository` object.
"""
location = "memory{%s}" % hex(id(repository_data))
resource_pool = ResourcePool(cache_size=None)
repo = MemoryPackageRepository(location, resource_pool)
repo.data = repository_data
return repo
def __init__(self, location, resource_pool):
"""Create an in-memory package repository.
Args:
location (str): Path containing the package repository.
"""
super(MemoryPackageRepository, self).__init__(location, resource_pool)
self.data = {}
self.register_resource(MemoryPackageFamilyResource)
self.register_resource(MemoryPackageResource)
self.register_resource(MemoryVariantResource)
[docs] def get_package_family(self, name):
is_valid_package_name(name, raise_error=True)
if name in self.data:
family = self.get_resource(
MemoryPackageFamilyResource.key,
location=self.location,
name=name)
return family
return None
[docs] def iter_package_families(self):
for name in self.data.keys():
family = self.get_package_family(name)
yield family
[docs] def iter_packages(self, package_family_resource):
for package in package_family_resource.iter_packages():
yield package
[docs] def iter_variants(self, package_resource):
for variant in package_resource.iter_variants():
yield variant
[docs] def get_parent_package_family(self, package_resource):
return package_resource.parent
[docs] def get_parent_package(self, variant_resource):
return variant_resource.parent
[docs]def register_plugin():
return MemoryPackageRepository