Skip to content

Commit

Permalink
feat: Resolve Path to both Local and Remote Source
Browse files Browse the repository at this point in the history
Added ready method to resolve path to a local or remote stub. In the case of a remote, the source is
first downloaded/unpacked into a temporary directory.
  • Loading branch information
BradenM committed Jun 27, 2019
1 parent 73532d5 commit 7497290
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 2 deletions.
3 changes: 2 additions & 1 deletion micropy/stubs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
to stub files/frozen modules and their usage in MicropyCli
"""

from . import source
from .stubs import StubManager

__all__ = ['StubManager']
__all__ = ['StubManager', 'source']
70 changes: 69 additions & 1 deletion micropy/stubs/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,50 @@
"""


import io
import shutil
import tarfile
import tempfile
from contextlib import contextmanager
from functools import partial
from pathlib import Path

import requests

from micropy import utils
from micropy.logger import Log


class StubSource:
"""Stub Source Base Class"""
"""Abstract Base Class for Stub Sources"""

def __init__(self, location):
self.location = location
_name = self.__class__.__name__
self.log = Log.add_logger(_name)

@contextmanager
def ready(self, path=None, teardown=None):
"""Yields prepared Stub Source
Allows StubSource subclasses to have a preperation
method before providing a local path to itself.
Args:
path (str, optional): path to stub source.
Defaults to location.
teardown (func, optional): callback to execute on exit.
Defaults to None.
Yields:
Resolved PathLike object to stub source
"""
_path = path or self.location
path = Path(_path).resolve()
yield path
if teardown:
teardown()


class LocalStubSource(StubSource):
"""Stub Source Subclass for local locations
Expand Down Expand Up @@ -51,6 +83,42 @@ def __init__(self, url):
location = utils.ensure_valid_url(url)
return super().__init__(location)

def _unpack_archive(self, file_bytes, path):
"""Unpack archive from bytes buffer
Args:
file_bytes (bytes): Byte array to extract from
Must be from tarfile with gzip compression
path (str): path to extract file to
Returns:
path: path extracted to
"""
tar_bytes_obj = io.BytesIO(file_bytes)
with tarfile.open(fileobj=tar_bytes_obj, mode="r:gz") as tar:
tar.extractall(path)
return path

def ready(self):
"""Retrieves and unpacks source
Prepares remote stub resource by downloading and
unpacking it into a temporary directory.
This directory is removed on exit of the superclass
context manager
Returns:
callable: StubSource.ready parent method
"""
tmp_dir = tempfile.mkdtemp()
tmp_path = Path(tmp_dir)
filename = utils.get_url_filename(self.location).split(".tar.gz")[0]
outpath = tmp_path / filename
resp = requests.get(self.location)
source_path = self._unpack_archive(resp.content, outpath)
teardown = partial(shutil.rmtree, tmp_path)
return super().ready(path=source_path, teardown=teardown)


def get_source(location, **kwargs):
"""Factory for StubSource Instance
Expand Down

0 comments on commit 7497290

Please sign in to comment.