Skip to content

Commit

Permalink
Create a mix-in for InitializedState
Browse files Browse the repository at this point in the history
  • Loading branch information
jaraco committed Oct 8, 2022
1 parent 9dffcf3 commit 6f700a4
Showing 1 changed file with 10 additions and 64 deletions.
74 changes: 10 additions & 64 deletions zipp.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,47 +62,24 @@ def _difference(minuend, subtrahend):
return itertools.filterfalse(set(subtrahend).__contains__, minuend)


class PickleableClass:
class InitializedState:
"""
Mix-in to save the initialization state for pickling.
"""
Utility object that wraps another un-pickleable object that,
for example, might hold a file object, and saves the
initialization parameters. When pickeled, the un-pickleable
object is discarded, and when loaded, it is rebuilt from the
initialization params."""

_class: type = object

def __init__(self, *args, **kwargs):
self._args = args
self._kwargs = kwargs
self._obj = None

def __getattr__(self, name):
if self._obj is None:
self._obj = self._class(*self._args, **self._kwargs)
return getattr(self._obj, name)
self.__args = args
self.__kwargs = kwargs
super().__init__(*args, **kwargs)

def __getstate__(self):
state = self.__dict__.copy()
state['_obj'] = None
return state
return dict(args=self.__args, kwargs=self.__kwargs)

def __setstate__(self, state):
self.__dict__.update(state)
super().__init__(*state['args'], **state['kwargs'])

def __repr__(self):
args = f"class={self._class}, args={self._args}, kwargs={self._kwargs}"
return f"{self.__class__.__name__}({args})"

def __eq__(self, other):
return (
self._class == other._class
and self._args == other._args
and self._kwargs == other._kwargs
)


class CompleteDirs(zipfile.ZipFile):
class CompleteDirs(InitializedState, zipfile.ZipFile):
"""
A ZipFile subclass that ensures that implied directories
are always included in the namelist.
Expand Down Expand Up @@ -170,14 +147,6 @@ def _name_set(self):
return self.__lookup


class PickleableFastLookup(PickleableClass):
_class = FastLookup

@property
def filename(self):
return self._args[0]


class Path:
"""
A pathlib-compatible interface for zip files.
Expand Down Expand Up @@ -268,32 +237,9 @@ def __init__(self, root, at=""):
original type, the caller should either create a
separate ZipFile object or pass a filename.
"""
self.root = self._make_root(root)
self.root = FastLookup.make(root)
self.at = at

def _make_root(self, source):
"""
Given a source (filename or zipfile), return an
appropriate root object.
"""
if isinstance(source, CompleteDirs):
return source

if isinstance(source, (str, pathlib.Path)):
return PickleableFastLookup(source)

if not isinstance(source, zipfile.ZipFile):
return FastLookup(source)

# Only allow for FastLookup when supplied zipfile is read-only
if 'r' not in source.mode:
subcls = CompleteDirs
else:
subcls = FastLookup

source.__class__ = subcls
return source

def open(self, mode='r', *args, pwd=None, **kwargs):
"""
Open this entry as text or binary following the semantics
Expand Down

0 comments on commit 6f700a4

Please sign in to comment.