Skip to content

Commit

Permalink
feat(stubs): make StubSource proper abstract, add prepare abstractm…
Browse files Browse the repository at this point in the history
…ethod + impls.
  • Loading branch information
BradenM committed Dec 11, 2022
1 parent 3ec08dd commit d690e71
Showing 1 changed file with 31 additions and 15 deletions.
46 changes: 31 additions & 15 deletions micropy/stubs/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,23 @@
and their location.
"""

from __future__ import annotations

import abc
import json
import shutil
import tempfile
from contextlib import contextmanager
from functools import partial
from pathlib import Path, PurePosixPath
from typing import Any, Callable, Optional, final
from urllib import parse

import micropy.exceptions as exc
import requests
from micropy import utils
from micropy.logger import Log
from micropy.utils.types import PathStr


class StubRepo:
Expand Down Expand Up @@ -123,7 +127,10 @@ def from_json(cls, content):
for source in data:
source_url = source["source"]
source_data = requests.get(source_url).json()
cls(**source_data)
try:
cls(**source_data)
except Exception as e:
pass
return cls.repos

def __eq__(self, other):
Expand All @@ -133,19 +140,25 @@ def __hash__(self):
return hash(self.location)


class StubSource:
class StubSource(abc.ABC):
"""Abstract Base Class for Stub Sources."""

def __init__(self, location, log=None):
location: PathStr

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

@abc.abstractmethod
def prepare(self) -> tuple[PathStr, Optional[Callable[..., Any]]]:
"""Prepares the source."""

@contextmanager
def ready(self, path=None, teardown=None):
def ready(self):
"""Yields prepared Stub Source.
Allows StubSource subclasses to have a preperation
Allows StubSource subclasses to have a preparation
method before providing a local path to itself.
Args:
Expand All @@ -158,9 +171,11 @@ def ready(self, path=None, teardown=None):
Resolved PathLike object to stub source
"""
_path = path or self.location
info_path = next(_path.rglob("info.json"), None)
path = Path(info_path.parent) if info_path else _path
prep = iter(self.prepare())
path = next(prep, self.location)
teardown = next(prep, lambda: None)
info_path = next(Path(path).rglob("info.json"), None)
path = Path(info_path.parent) if info_path else path
yield path
if teardown:
teardown()
Expand All @@ -170,6 +185,7 @@ def __str__(self):
return f"<{_name}@{self.location}>"


@final
class LocalStubSource(StubSource):
"""Stub Source Subclass for local locations.
Expand All @@ -181,11 +197,15 @@ class LocalStubSource(StubSource):
"""

def prepare(self) -> tuple[PathStr, Optional[Callable[..., Any]]]:
return self.location, None

def __init__(self, path, **kwargs):
location = utils.ensure_existing_dir(path)
return super().__init__(location, **kwargs)
super().__init__(location, **kwargs)


@final
class RemoteStubSource(StubSource):
"""Stub Source for remote locations.
Expand All @@ -197,10 +217,6 @@ class RemoteStubSource(StubSource):
"""

def __init__(self, name, **kwargs):
location = StubRepo.resolve_package(name)
return super().__init__(location, **kwargs)

def _unpack_archive(self, file_bytes, path):
"""Unpack archive from bytes buffer.
Expand All @@ -217,7 +233,7 @@ def _unpack_archive(self, file_bytes, path):
output = next(path.iterdir())
return output

def ready(self):
def prepare(self) -> tuple[PathStr, Optional[Callable[..., Any]]]:
"""Retrieves and unpacks source.
Prepares remote stub resource by downloading and
Expand All @@ -238,7 +254,7 @@ def ready(self):
)
source_path = self._unpack_archive(content, tmp_path)
teardown = partial(shutil.rmtree, tmp_path)
return super().ready(path=source_path, teardown=teardown)
return source_path, teardown


def get_source(location, **kwargs):
Expand Down

0 comments on commit d690e71

Please sign in to comment.