From 220d76ed72cc0f801936152d74fcc94fbf7e459c Mon Sep 17 00:00:00 2001 From: Thomas Luechtefeld Date: Fri, 23 Feb 2024 11:54:30 -0500 Subject: [PATCH] first steps towards tests --- README.md | 5 ++++- biobricks/brick.py | 5 +++-- biobricks/cli.py | 20 +++++++++-------- biobricks/config.py | 11 +++++++-- changelog.md | 2 ++ docker/Dockerfile | 8 ++++++- requirements.txt | 4 ++-- tests/test_init.py | 54 ++++++++++++++++++++++++++++++--------------- 8 files changed, 74 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 336eb5e..914684c 100644 --- a/README.md +++ b/README.md @@ -30,4 +30,7 @@ import biobricks as bb bb.assets('tox21') # get the paths for the 'tox21' brick ``` -To list the bricks currently available visit [github.com/biobricks-ai](https://github.com/biobricks-ai) \ No newline at end of file +To list the bricks currently available visit [github.com/biobricks-ai](https://github.com/biobricks-ai) + +# TODO +1. eventually need to special case (or remove) the testing biobricks token \ No newline at end of file diff --git a/biobricks/brick.py b/biobricks/brick.py index f7e7bd1..925eb3d 100644 --- a/biobricks/brick.py +++ b/biobricks/brick.py @@ -1,10 +1,11 @@ import subprocess, functools, os, re, datetime, json from subprocess import run, DEVNULL -import types, pyarrow.parquet as pq, re +import types from pathlib import Path from .config import bblib, token from .logger import logger -import os, urllib.request as request, functools, dvc.api, shutil +import os, urllib.request as request, functools, shutil +# import dvc.api from urllib.parse import urlparse import sys from .checks import check_url_available, check_token, check_symlink_permission, check_safe_git_repo diff --git a/biobricks/cli.py b/biobricks/cli.py index de8d545..c3f6ca7 100755 --- a/biobricks/cli.py +++ b/biobricks/cli.py @@ -5,7 +5,7 @@ from importlib import metadata from .logger import logger -from .config import read_config, write_config, init_bblib +from .config import biobricks_config_path, read_config, write_config, init_bblib from .checks import check_token from .brick import Brick from .local_bb import LocalBB @@ -22,20 +22,22 @@ class Sect: @click.option("--bblib", default=None, type=click.Path(), help="path to store bricks") @click.option("--token", default=None, help="biobricks.ai/token auth token") @click.option("--overwrite", default=False, help="overwrite existing config?") -def configure(bblib, token, overwrite): +@click.option("--interactive", default=True, help="run configure interactively?") +def configure(bblib, token, overwrite, interactive): + + if not interactive: + config = { "BBLIB": f"{bblib}", "TOKEN": token } + write_config(config) + init_bblib() + return - path = Path.home().joinpath(".biobricks") + path = biobricks_config_path() config = read_config() # CHECK IF CONFIG WILL OVERWRITE EXISTING msg = click.style("WARNING: overwrite existing config?", fg="red") if path.exists() and not overwrite and not click.confirm(msg): sys.exit(0) - - # EMAIL PROMPT - email = click.prompt("Choose Email", type=click.Path()) - click.echo("\nRegister and log in to: https://biobricks.ai\nThen copy your token from https://biobricks.ai/token\n") - token = click.prompt("Copy token from https://biobricks.ai/token here") # VALIDATE TOKEN while not check_token(token, silent=True): @@ -50,7 +52,7 @@ def configure(bblib, token, overwrite): bblib = click.prompt("Choose path to store bricks", type=click.Path()) # write configuration - config = { "BBLIB": bblib, "TOKEN": token, "EMAIL": email } + config = { "BBLIB": bblib, "TOKEN": token } write_config(config) # initialize bblib diff --git a/biobricks/config.py b/biobricks/config.py index 61f3c25..36a781f 100644 --- a/biobricks/config.py +++ b/biobricks/config.py @@ -1,20 +1,27 @@ import os, warnings, json, urllib from subprocess import run, DEVNULL, STDOUT from pathlib import Path +import shutil + +def biobricks_config_path(): + return Path.home().joinpath(".biobricks") def read_config(): - path = Path.home().joinpath(".biobricks") + path = biobricks_config_path() if not path.exists(): return {} return json.loads(path.read_text()) def write_config(config): - path = Path.home().joinpath(".biobricks") + path = biobricks_config_path() path.write_text(json.dumps(config)) def init_bblib() -> None: + breakpoint() bbpath = Path(read_config()['BBLIB']) os.makedirs(bbpath, exist_ok=True) os.makedirs(bbpath / "cache", exist_ok=True) + if not shutil.which('git'): + raise Exception('Program "git" is not installed. Please install "git"') run("git init", cwd=bbpath, stdout=DEVNULL, stderr=STDOUT, shell=True) return bblib() diff --git a/changelog.md b/changelog.md index e69de29..f3e68ad 100644 --- a/changelog.md +++ b/changelog.md @@ -0,0 +1,2 @@ +- remove pyarrow dependency +- remove git from local_bb diff --git a/docker/Dockerfile b/docker/Dockerfile index e9e9e97..652f664 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,10 +1,16 @@ # Create an ubuntu docker image with pip, python, and git # build with `docker build -t ubuntu-pip-python-git .` # create a container from the image that gets destroyed after use -# `docker run --rm -it -v ./:/biobricks ubuntu-pip-python-git /bin/bash` +# `docker run --rm -it -v ./:/home/appuser/biobricks ubuntu-pip-python-git /bin/bash` FROM python:3.9-slim +# Install system dependencies including Git +RUN apt-get update && \ + apt-get install -y --no-install-recommends git && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + # Install pipx RUN python -m pip install --upgrade pip && \ pip install pipx && \ diff --git a/requirements.txt b/requirements.txt index 5643b1a..8e0dad4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -dvc==2.45.1 pytest-cov==4.0.0 click>=8.1.3 -GitPython==3.1.37 \ No newline at end of file +requests>=2.0.0,<3.0.0 +cloup>=3.0.0,<4.0.0 \ No newline at end of file diff --git a/tests/test_init.py b/tests/test_init.py index d4c4687..649bd62 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -1,21 +1,39 @@ -# test_cli.py -import pytest -from biobricks.cli import register_on_biobricks +import unittest +from unittest.mock import patch, MagicMock +from pathlib import Path +from biobricks import Brick, cli +from biobricks.config import write_config, init_bblib +import tempfile -# Using requests_mock to mock API responses -@pytest.fixture -def mock_request(requests_mock): - mock_url = 'https://biobricks.ai/api/register' - mock_response = { - 'auth_numbers': '12345', - 'auth_url': 'https://biobricks.ai/auth' - } - requests_mock.post(mock_url, json=mock_response, status_code=200) - return requests_mock # This return isn't necessary but can be useful if you want to add more specifics in the fixture. +def configure(bblib, token, overwrite, interactive): + + if not interactive: + config = { "BBLIB": f"{bblib}", "TOKEN": token } + write_config(config) + init_bblib() + return -def test_register_on_biobricks(mock_request): # This should be the fixture name. - result = register_on_biobricks('test@example.com') +class TestBrickResolve(unittest.TestCase): + + tempdir = tempfile.TemporaryDirectory() - assert result['message'] == "Authentication needed." - assert result['auth_numbers'] == '12345' - assert result['auth_url'] == 'https://biobricks.ai/auth' + def setUp(self): + bblib = Path(f"{TestBrickResolve.tempdir.name}/biobricks") + bblib.mkdir(exist_ok=True,parents=True) + configure(f"{bblib}", "VQF6Q2U-NKktZ31ioVYa9w", None, None) + + def tearDown(self) -> None: + return super().tearDown() + + # test basic install of the hello-brick + @patch('biobricks.bblib') + def test_install_hello_brick(): + from biobricks.brick import Brick + brick = Brick.Resolve("hello-brick") + brick.install() + assert brick.path().exists() + assert (brick.path() / "hello.txt").exists() + assert (brick.path() / "hello.txt").read_text() == "hello world\n" + +if __name__ == '__main__': + unittest.main() \ No newline at end of file