diff --git a/ioc/get.py b/ioc/get.py index 5e8b1579..6d810087 100644 --- a/ioc/get.py +++ b/ioc/get.py @@ -121,7 +121,7 @@ def _lookup_config_value( def _lookup_jail_value( - resource: 'iocage.LaunchableResource.LaunchableResource', + resource: 'iocage.Resource.Launchable.LaunchableResource', key: str ) -> str: diff --git a/ioc/list.py b/ioc/list.py index 938cb6ad..370db0c0 100644 --- a/ioc/list.py +++ b/ioc/list.py @@ -32,7 +32,7 @@ import iocage.Host import iocage.Datasets import iocage.Resource -import iocage.ListableResource +import iocage.Resource.Listable import iocage.Jails import iocage.Releases @@ -162,7 +162,7 @@ def cli( def _print_table( resources: typing.Generator[ typing.Union[ - iocage.ListableResource.ListableResource, + iocage.Resource.Listable.ListableResource, typing.List[typing.Dict[str, str]] ], None, @@ -183,7 +183,7 @@ def _print_table( def _print_list( resources: typing.Generator[ typing.Union[ - iocage.ListableResource.ListableResource, + iocage.Resource.Listable.ListableResource, typing.List[typing.Dict[str, str]] ], None, @@ -204,7 +204,7 @@ def _print_list( def _print_json( resources: typing.Generator[ typing.Union[ - iocage.ListableResource.ListableResource, + iocage.Resource.Listable.ListableResource, typing.List[typing.Dict[str, str]] ], None, diff --git a/ioc/shared/jail.py b/ioc/shared/jail.py index 38bd257d..60cab5d6 100644 --- a/ioc/shared/jail.py +++ b/ioc/shared/jail.py @@ -49,7 +49,7 @@ def get_jail( def set_properties( properties: typing.Iterable[str], - target: 'iocage.LaunchableResource.LaunchableResource' + target: 'iocage.Resource.Launchable.LaunchableResource' ) -> set: """Set a bunch of jail properties from a Click option tuple.""" updated_properties = set() diff --git a/iocage/Config/Jail/File/__init__.py b/iocage/Config/Jail/File/__init__.py index 2e831d8e..73ea37d6 100644 --- a/iocage/Config/Jail/File/__init__.py +++ b/iocage/Config/Jail/File/__init__.py @@ -28,7 +28,7 @@ import iocage.helpers import iocage.helpers_object -import iocage.LaunchableResource +import iocage.Resource.Launchable class ResourceConfig: @@ -37,7 +37,7 @@ class ResourceConfig: def _require_path_relative_to_resource( self, filepath: str, - resource: 'iocage.LaunchableResource.LaunchableResource' + resource: 'iocage.Resource.Launchable.LaunchableResource' ) -> None: if self._is_path_relative_to_resource(filepath, resource) is False: @@ -48,7 +48,7 @@ def _require_path_relative_to_resource( def _is_path_relative_to_resource( self, filepath: str, - resource: 'iocage.LaunchableResource.LaunchableResource' + resource: 'iocage.Resource.Launchable.LaunchableResource' ) -> bool: real_resource_path = self._resolve_path(resource.dataset.mountpoint) @@ -226,7 +226,7 @@ class ResourceConfigFile(ConfigFile, ResourceConfig): def __init__( self, - resource: 'iocage.LaunchableResource.LaunchableResource', + resource: 'iocage.Resource.Launchable.LaunchableResource', file: typing.Optional[str]=None, logger: typing.Optional['iocage.Logger.Logger']=None ) -> None: diff --git a/iocage/Filter.py b/iocage/Filter.py index fa4c5d79..21e138b7 100644 --- a/iocage/Filter.py +++ b/iocage/Filter.py @@ -29,13 +29,12 @@ import iocage.errors import iocage.helpers import iocage.Resource -import iocage.ResourceSelector +import iocage.Resource.Selector -_ResourceSelector = iocage.ResourceSelector.ResourceSelector _TermValuesType = typing.Union[ str, typing.List[str], - iocage.ResourceSelector.ResourceSelector + 'iocage.Resource.Selector' ] _REGEX_PATTERN_SPLIT_COMMA = re.compile(r"(? bool: return any(map(self.matches, value)) input_value = iocage.helpers.to_string(value) + _ResourceSelector = iocage.Resource.Selector + print(_ResourceSelector, type(_ResourceSelector)) for filter_value in self: if isinstance(filter_value, str): if self._match_filter(input_value, filter_value, short): return True - elif isinstance(filter_value, _ResourceSelector): + elif isinstance(filter_value, iocage.Resource.Selector): if self._match_filter(input_value, filter_value.name, short): return True elif isinstance(filter_value, list): @@ -312,7 +313,7 @@ def _parse_term(self, user_input: str) -> Term: value = user_input if prop == "name": - value = [iocage.ResourceSelector.ResourceSelector( + value = [iocage.Resource.Selector( partial_value, logger=self.logger ) for partial_value in re.split( diff --git a/iocage/Jail.py b/iocage/Jail.py index ca1ec982..9712a546 100644 --- a/iocage/Jail.py +++ b/iocage/Jail.py @@ -47,16 +47,16 @@ import iocage.Storage import iocage.ZFSBasejailStorage import iocage.ZFSShareStorage -import iocage.LaunchableResource -import iocage.VersionedResource +import iocage.Resource.Launchable +import iocage.Resource.Versioned import iocage.Config.Jail.Properties.ResourceLimit -import iocage.ResourceSelector +import iocage.Resource.Selector import iocage.Config.Jail.File.Fstab class JailResource( - iocage.LaunchableResource.LaunchableResource, - iocage.VersionedResource.VersionedResource + iocage.Resource.Launchable.LaunchableResource, + iocage.Resource.Versioned.VersionedResource ): """Resource that represents a jail.""" @@ -88,7 +88,7 @@ def __init__( if jail is not None: self._jail = jail - iocage.LaunchableResource.LaunchableResource.__init__( + iocage.Resource.Launchable.LaunchableResource.__init__( self, dataset=dataset, dataset_name=dataset_name, @@ -2019,7 +2019,7 @@ def _resolve_name(self, text: str) -> str: if (text is None) or (len(text) == 0): raise iocage.errors.JailNotSupplied(logger=self.logger) - resource_selector = iocage.ResourceSelector.ResourceSelector( + resource_selector = iocage.Resource.Selector( name=text, logger=self.logger ) diff --git a/iocage/Jails.py b/iocage/Jails.py index de8d06d9..6cd10c45 100644 --- a/iocage/Jails.py +++ b/iocage/Jails.py @@ -28,11 +28,11 @@ import iocage.Jail import iocage.Filter -import iocage.ListableResource +import iocage.Resource.Listable import iocage.helpers_object -class JailsGenerator(iocage.ListableResource.ListableResource): +class JailsGenerator(iocage.Resource.Listable.ListableResource): """Asynchronous representation of a collection of jails.""" states = iocage.JailState.JailStates() @@ -58,7 +58,7 @@ def __init__( self.zfs = iocage.helpers_object.init_zfs(self, zfs) self.host = iocage.helpers_object.init_host(self, host) - iocage.ListableResource.ListableResource.__init__( + iocage.Resource.Listable.ListableResource.__init__( self, sources=self.host.datasets, namespace="jails", @@ -101,7 +101,7 @@ def __iter__( if self.states.queried is False: self.states.query(logger=self.logger) - iterator = iocage.ListableResource.ListableResource.__iter__(self) + iterator = iocage.Resource.Listable.ListableResource.__iter__(self) for jail in iterator: if jail.identifier in self.states: diff --git a/iocage/Pkg.py b/iocage/Pkg.py index 30a065de..2b4b3d7c 100644 --- a/iocage/Pkg.py +++ b/iocage/Pkg.py @@ -33,7 +33,7 @@ import iocage.events import iocage.helpers import iocage.helpers_object -import iocage.LaunchableResource +import iocage.Resource.Launchable _PkgConfDataType = typing.Union[ str, int, bool, diff --git a/iocage/Release.py b/iocage/Release.py index 06e2b3b9..c2a2283b 100644 --- a/iocage/Release.py +++ b/iocage/Release.py @@ -38,8 +38,8 @@ import iocage.helpers import iocage.helpers_object import iocage.events -import iocage.LaunchableResource -import iocage.ResourceSelector +import iocage.Resource.Launchable +import iocage.Resource.Selector import iocage.Jail import iocage.SecureTarfile @@ -51,7 +51,7 @@ import iocage.Config.Jail.File.SysctlConf -class ReleaseResource(iocage.LaunchableResource.LaunchableResource): +class ReleaseResource(iocage.Resource.Launchable.LaunchableResource): """Resource that represents an iocage release.""" _release: typing.Optional['ReleaseGenerator'] @@ -75,7 +75,7 @@ def __init__( self.host = iocage.helpers_object.init_host(self, host) self.root_datasets_name = root_datasets_name - iocage.LaunchableResource.LaunchableResource.__init__( + iocage.Resource.Launchable.LaunchableResource.__init__( self, dataset=dataset, dataset_name=dataset_name, @@ -256,7 +256,7 @@ def __init__( self.zfs = iocage.helpers_object.init_zfs(self, zfs) self.host = iocage.helpers_object.init_host(self, host) - resource_selector = iocage.ResourceSelector.ResourceSelector( + resource_selector = iocage.Resource.Selector( name, logger=self.logger ) diff --git a/iocage/Releases.py b/iocage/Releases.py index d0ec0047..3c15da95 100644 --- a/iocage/Releases.py +++ b/iocage/Releases.py @@ -24,7 +24,7 @@ # POSSIBILITY OF SUCH DAMAGE. """Model of multiple iocage Releases.""" import iocage.Release -import iocage.ListableResource +import iocage.Resource.Listable import iocage.Filter import iocage.helpers_object @@ -35,7 +35,7 @@ ReleaseListType = typing.List['iocage.Release.ReleaseGenerator'] -class ReleasesGenerator(iocage.ListableResource.ListableResource): +class ReleasesGenerator(iocage.Resource.Listable.ListableResource): """Generator Model of multiple iocage Releases.""" host: 'iocage.Host.HostGenerator' @@ -54,7 +54,7 @@ def __init__( self.zfs = iocage.helpers_object.init_zfs(self, zfs) self.host = iocage.helpers_object.init_host(self, host) - iocage.ListableResource.ListableResource.__init__( + iocage.Resource.Listable.ListableResource.__init__( self, sources=self.host.datasets, namespace="releases", @@ -70,7 +70,7 @@ def _class_release(self) -> 'iocage.Release.ReleaseGenerator': @property def local(self) -> ReleaseListType: """Return the locally available releases.""" - datasets = iocage.ListableResource.ListableResource.__iter__(self) + datasets = iocage.Resource.Listable.ListableResource.__iter__(self) return list(map( lambda x: self._class_release( # noqa: T484 name=x.name.split("/").pop(), diff --git a/iocage/ResourceBackup.py b/iocage/Resource/Backup.py similarity index 99% rename from iocage/ResourceBackup.py rename to iocage/Resource/Backup.py index f7b7b7e4..198ac44f 100644 --- a/iocage/ResourceBackup.py +++ b/iocage/Resource/Backup.py @@ -42,13 +42,13 @@ class LaunchableResourceBackup: state. """ - resource: 'iocage.LaunchableResource.LaunchableResource' + resource: 'iocage.Resource.Launchable.LaunchableResource' _temp_dir: typing.Optional[tempfile.TemporaryDirectory] _snapshot_name: typing.Optional[str] def __init__( self, - resource: 'iocage.LaunchableResource.LaunchableResource' + resource: 'iocage.Resource.Launchable.LaunchableResource' ) -> None: self.resource = resource self._temp_dir = None diff --git a/iocage/LaunchableResource.py b/iocage/Resource/Launchable.py similarity index 97% rename from iocage/LaunchableResource.py rename to iocage/Resource/Launchable.py index acd921e1..2cc979b3 100644 --- a/iocage/LaunchableResource.py +++ b/iocage/Resource/Launchable.py @@ -28,7 +28,7 @@ import iocage.helpers_object import iocage.Resource -import iocage.ResourceBackup +import iocage.Resource.Backup class LaunchableResource(iocage.Resource.Resource): @@ -45,7 +45,7 @@ class LaunchableResource(iocage.Resource.Resource): 'iocage.ResourceUpdater.LaunchableResourceUpdate' ] _backup: typing.Optional[ - 'iocage.ResourceBackup.LaunchableResourceBackup' + 'iocage.Resource.Backup.LaunchableResourceBackup' ] config: 'iocage.Config.Jail.JailConfig.JailConfig' @@ -101,7 +101,7 @@ def backup( if self._backup is not None: return self._backup - backup = iocage.ResourceBackup.LaunchableResourceBackup( + backup = iocage.Resource.Backup.LaunchableResourceBackup( resource=self ) self._backup = backup diff --git a/iocage/ListableResource.py b/iocage/Resource/Listable.py similarity index 100% rename from iocage/ListableResource.py rename to iocage/Resource/Listable.py diff --git a/iocage/ResourceSelector.py b/iocage/Resource/Selector.py similarity index 99% rename from iocage/ResourceSelector.py rename to iocage/Resource/Selector.py index 3550fc86..2239df63 100644 --- a/iocage/ResourceSelector.py +++ b/iocage/Resource/Selector.py @@ -29,7 +29,7 @@ import iocage.Datasets -class ResourceSelector: +class Selector: """Parse and wrap resource selectors.""" source_name: typing.Optional[str] diff --git a/iocage/ResourceUpdater.py b/iocage/Resource/Updater.py similarity index 99% rename from iocage/ResourceUpdater.py rename to iocage/Resource/Updater.py index 81c1ef55..b46a7036 100644 --- a/iocage/ResourceUpdater.py +++ b/iocage/Resource/Updater.py @@ -48,7 +48,7 @@ class Updater: def __init__( self, - resource: 'iocage.LaunchableResource.LaunchableResource', + resource: 'iocage.Resource.Launchable.LaunchableResource', host: 'iocage.Host.HostGenerator' ) -> None: self.resource = resource diff --git a/iocage/VersionedResource.py b/iocage/Resource/Versioned.py similarity index 100% rename from iocage/VersionedResource.py rename to iocage/Resource/Versioned.py diff --git a/iocage/Resource.py b/iocage/Resource/__init__.py similarity index 98% rename from iocage/Resource.py rename to iocage/Resource/__init__.py index 91588455..b6897486 100644 --- a/iocage/Resource.py +++ b/iocage/Resource/__init__.py @@ -413,3 +413,16 @@ def destroy( def save(self) -> None: """Save changes to the default configuration.""" self._write_config(self.config.user_data) + + +iocage.hook_module( + module_name="iocage.Resource", + hooked_submodule_names=[ + "Backup", + "Launchable", + "Listable", + "Selector", + "Updater", + "Versioned" + ] +) diff --git a/iocage/__init__.py b/iocage/__init__.py index de1e4ce8..220517ab 100644 --- a/iocage/__init__.py +++ b/iocage/__init__.py @@ -6,53 +6,70 @@ class _HookedModule: def __call__(self, *args, **kwargs) -> None: - return self.main_module(*args, **kwargs) - - @property - def main_module(self) -> typing.Any: name = self.__name__ - return sys.modules[name].__getattribute__(name.split(".").pop()) + main_module = sys.modules[name].__getattribute__(name.split(".").pop()) + return main_module(*args, **kwargs) + def __instancecheck__(self, target_class) -> bool: + import pdb; pdb.set_trace() -class _IocageModule(sys.modules["iocage"].__class__): +def hook_module(module_name: str, hooked_submodule_names: typing.List[str]): - hooked_modules = [ - "Host", - "Distribution", - "Jails", - "Jail", - "Releases", - "Release" - ] + class _IocageModule(sys.modules["iocage"].__class__, _HookedModule): - def __getattribute__(self, key: str) -> typing.Any: - if key.startswith("_") is True: - return super().__getattribute__(key) + hooked_modules = hooked_submodule_names + + def __getattribute__(self, key: str) -> typing.Any: + if key.startswith("_") is True: + return super().__getattribute__(key) + + try: + method = super().__getattribute__(key) + if callable(method) is True: + return method + except AttributeError: + pass - if key not in sys.modules.keys(): if key in object.__getattribute__(self, "hooked_modules"): - self.__load_hooked_module(key) + if key not in sys.modules.keys(): + self.__load_hooked_module(key) + elif not isinstance(sys.modules[name], _HookedModule): + import pdb; pdb.set_trace() + sys.modules[name] = self._hook_module(sys.modules) else: self.__load_module(key) - return super().__getattribute__(key) - def __load_module(self, name: str) -> None: - module = importlib.import_module(f"iocage.{name}") - sys.modules[name] = module + return super().__getattribute__(key) + + def __load_module(self, name: str) -> None: + module = importlib.import_module(f"{module_name}.{name}") + sys.modules[name] = module + + def __load_hooked_module(self, name: str) -> None: + module = importlib.import_module(f"{module_name}.{name}") + sys.modules[name] = self.__hook_module(module) - def __load_hooked_module(self, name: str) -> None: - module = importlib.import_module(f"iocage.{name}") - sys.modules[name] = self.__hook_module(module) + def __hook_module(self, module: typing.Any) -> None: - def __hook_module(self, module: typing.Any) -> None: + class _Module(module.__class__, _HookedModule): - class _Module(module.__class__, _HookedModule): + pass - pass + module.__class__ = _Module + return module - module.__class__ = _Module - return module + sys.modules[module_name].__class__ = _IocageModule -sys.modules["iocage"].__class__ = _IocageModule +hook_module( + module_name="iocage", + hooked_submodule_names=[ + "Host", + "Distribution", + "Jails", + "Jail", + "Releases", + "Release" + ] +) \ No newline at end of file