Skip to content

Commit

Permalink
SFA: Load single-file applications from remote resources
Browse files Browse the repository at this point in the history
  • Loading branch information
amotl committed Nov 7, 2024
1 parent d23124f commit b956646
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 5 deletions.
1 change: 1 addition & 0 deletions pueblo/sfa/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ not be used together.
# Invoke Python entrypoint with given specification.
PYTHONPATH=$(pwd) sfa run tests.testdata.entrypoint:main
sfa run tests/testdata/entrypoint.py:main
sfa run https://github.com/pyveci/pueblo/raw/refs/heads/sfa/tests/testdata/entrypoint.py#main
```


Expand Down
30 changes: 25 additions & 5 deletions pueblo/sfa/core.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import importlib.util
import logging
import sys
import typing as t
from pathlib import Path
from tempfile import NamedTemporaryFile
from types import ModuleType
from urllib.parse import urlparse

Check warning on line 8 in pueblo/sfa/core.py

View check run for this annotation

Codecov / codecov/patch

pueblo/sfa/core.py#L1-L8

Added lines #L1 - L8 were not covered by tests

from attrs import define

Check warning on line 10 in pueblo/sfa/core.py

View check run for this annotation

Codecov / codecov/patch

pueblo/sfa/core.py#L10

Added line #L10 was not covered by tests

logger = logging.getLogger(__name__)

Check warning on line 12 in pueblo/sfa/core.py

View check run for this annotation

Codecov / codecov/patch

pueblo/sfa/core.py#L12

Added line #L12 was not covered by tests


class InvalidTarget(Exception):
pass

Check warning on line 16 in pueblo/sfa/core.py

View check run for this annotation

Codecov / codecov/patch

pueblo/sfa/core.py#L15-L16

Added lines #L15 - L16 were not covered by tests
Expand Down Expand Up @@ -139,13 +143,29 @@ def load(self):

def load_any(self):
if self.address.is_url:
mod = None
from upath import UPath

Check warning on line 146 in pueblo/sfa/core.py

View check run for this annotation

Codecov / codecov/patch

pueblo/sfa/core.py#L144-L146

Added lines #L144 - L146 were not covered by tests

upath = UPath(self.address.target)
logger.info(f"Loading remote single-file application, source: {upath}")
name = "_".join([upath.parent.stem, upath.stem])
fragment = upath._url.fragment
suffix = upath.suffix
app_file = NamedTemporaryFile(prefix=f"{name}_", suffix=suffix, delete=False)
target = app_file.name
if fragment:
target = f"{app_file.name}:{fragment}"
logger.info(f"Writing remote single-file application, target: {target}")
app_file.write(upath.read_bytes())
app_file.flush()
path = Path(app_file.name)

Check warning on line 160 in pueblo/sfa/core.py

View check run for this annotation

Codecov / codecov/patch

pueblo/sfa/core.py#L148-L160

Added lines #L148 - L160 were not covered by tests
else:
path = Path(self.address.target)

Check warning on line 162 in pueblo/sfa/core.py

View check run for this annotation

Codecov / codecov/patch

pueblo/sfa/core.py#L162

Added line #L162 was not covered by tests
if path.is_file():
mod = self.load_file(path)
else:
mod = importlib.import_module(self.address.target)

if path.is_file():
mod = self.load_file(path)

Check warning on line 165 in pueblo/sfa/core.py

View check run for this annotation

Codecov / codecov/patch

pueblo/sfa/core.py#L164-L165

Added lines #L164 - L165 were not covered by tests
else:
mod = importlib.import_module(self.address.target)

Check warning on line 167 in pueblo/sfa/core.py

View check run for this annotation

Codecov / codecov/patch

pueblo/sfa/core.py#L167

Added line #L167 was not covered by tests

self._module = mod

Check warning on line 169 in pueblo/sfa/core.py

View check run for this annotation

Codecov / codecov/patch

pueblo/sfa/core.py#L169

Added line #L169 was not covered by tests

@staticmethod
Expand Down
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ optional-dependencies.release = [
]
optional-dependencies.sfa = [
"attrs",
# FIXME: Incomplete reads?
# https://github.com/fsspec/filesystem_spec/issues/614
"fsspec[github,http,libarchive,s3]<2021",
"tomli<3",
"universal-pathlib",
]
optional-dependencies.test = [
"pueblo[testing]",
Expand Down
5 changes: 5 additions & 0 deletions tests/test_sfa.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def test_address_url():
[
"tests.testdata.entrypoint:main",
"tests/testdata/entrypoint.py:main",
"https://github.com/pyveci/pueblo/raw/refs/heads/sfa/tests/testdata/entrypoint.py#main",
],
)
def test_application_api_success(capsys, spec):
Expand All @@ -53,6 +54,9 @@ def test_application_api_success(capsys, spec):
[
"pueblo.context:pueblo_cache_path",
"pueblo/context.py:pueblo_cache_path",
# FIXME: Incomplete reads?
# https://github.com/fsspec/filesystem_spec/issues/614
# "https://github.com/pyveci/pueblo/raw/refs/heads/main/pueblo/context.py#pueblo_cache_path",
],
)
def test_application_api_not_callable(capsys, spec):
Expand All @@ -67,6 +71,7 @@ def test_application_api_not_callable(capsys, spec):
[
"tests.testdata.entrypoint:main",
"tests/testdata/entrypoint.py:main",
"https://github.com/pyveci/pueblo/raw/refs/heads/sfa/tests/testdata/entrypoint.py#main",
],
)
def test_application_cli(mocker, capfd, spec):
Expand Down

0 comments on commit b956646

Please sign in to comment.