Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/psqlgml/dictionaries/readers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
import os
from pathlib import Path
from typing import Optional, cast
from typing import Optional, Union, cast

from psqlgml.dictionaries import repository, schemas

Expand All @@ -25,7 +25,10 @@ def __init__(self, name: str, version: str) -> None:

self.reader: Optional[repository.Repository] = None

def local(self, base_directory: Optional[Path] = None) -> "DictionaryReader":
def local(self, base_directory: Optional[Union[str, Path]] = None) -> "DictionaryReader":
base_directory = (
Path(base_directory) if isinstance(base_directory, str) else base_directory
)
logger.debug(f"Reading local Dictionary {self.name}: {self.version} @ {base_directory}")
self._base_dir = base_directory or self._base_dir
return self
Expand Down
3 changes: 1 addition & 2 deletions src/psqlgml/dictionaries/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ def get_dictionary_directory(self, version: str) -> Path:
@abc.abstractmethod
def read(self, version: str) -> schemas.Dictionary:
"""Reads the specified dictionary version from the repository"""
...


@attr.s(auto_attribs=True)
Expand Down Expand Up @@ -129,7 +128,7 @@ def get_commit_id(self, commit_ref: str) -> bytes:
return obj.id
if isinstance(obj, objects.Tag):
return obj.object[1]
raise ValueError(f"Unrecognized commit {commit_ref}")
raise IOError(f"unknown commit type for ref {commit_ref}")

def clone(self) -> None:

Expand Down
43 changes: 43 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import glob
import shutil
import sys
import threading
from pathlib import Path

import pkg_resources
import pytest
from _pytest.fixtures import SubRequest
from _pytest.legacypath import TempdirFactory
from dulwich import porcelain
from dulwich.server import DictBackend, TCPGitServer

import psqlgml
from tests.helpers import SchemaInfo
Expand Down Expand Up @@ -32,3 +40,38 @@ def test_schema(local_schema: SchemaInfo) -> psqlgml.GmlSchema:
version=local_schema.version,
schema_location=local_schema.source_dir,
)


@pytest.fixture(scope="session")
def git_server(request: SubRequest, tmpdir_factory: TempdirFactory, data_dir: str):

base_dir = f"{tmpdir_factory.mktemp('gitdata')}/rsvr"

# copy dictionary files to tmp dir
shutil.copytree(f"{data_dir}/dictionary/0.1.0", f"{base_dir}/gdcdictionary/schemas")

# make a git repo for tests
repo = porcelain.Repo.init(base_dir)

# stage & commit dictionary files
paths = [p.replace(f"{base_dir}/", "") for p in glob.glob(f"{base_dir}/**", recursive=True)]
repo.stage(paths)
print(",".join([f.decode(sys.getfilesystemencoding()) for f in repo.open_index()]))
commit = repo.do_commit(b"Add items", committer=b"pytest <pytest@psqlgml.com>")

# add tag and master branch
assert repo.head() == commit
repo.refs[b"refs/heads/master"] = commit
repo.refs[b"refs/tags/0.1.0"] = commit

print("================ refs ====================")
print(repo.refs)

# create remote repo
backend = DictBackend({b"/rsvr": repo})
dul_server = TCPGitServer(backend, b"localhost", 0)
threading.Thread(target=dul_server.serve).start()

server_addr, server_port = dul_server.socket.getsockname()
request.addfinalizer(dul_server.shutdown)
return f"git://{server_addr}:{server_port}/rsvr"
1 change: 1 addition & 0 deletions tests/data/dictionary/0.1.0/samples/project.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
id: projects
78 changes: 70 additions & 8 deletions tests/unit/test_git_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

from psqlgml.dictionaries import repository

REMOTE_GIT_URL = "https://github.com/NCI-GDC/gdcdictionary.git"


@pytest.mark.parametrize(
"default_base, expectation",
Expand All @@ -23,7 +21,7 @@ def test_get_dictionary_dir(data_dir: str, default_base: str, expectation) -> No
gml_dir = f"{Path.home()}/.gml/dictionaries" if default_base else data_dir
with mock.patch.dict(os.environ, {"GML_DICTIONARY_HOME": gml_dir}):

repo = repository.GitRepository(name="dictionary", url=REMOTE_GIT_URL, lazy_load=True)
repo = repository.GitRepository(name="dictionary", url="", lazy_load=True)
assert repo.name == "dictionary"
assert Path(expectation) == repo.get_dictionary_directory("0.1.0")

Expand All @@ -40,22 +38,86 @@ def test_get_local_git_dir(local_git_home: str) -> None:

with mock.patch.dict(os.environ, {"GML_GIT_HOME": local_git_home}):

repo = repository.GitRepository(name="dictionary", url=REMOTE_GIT_URL, lazy_load=True)
repo = repository.GitRepository(name="dictionary", url="", lazy_load=True)
assert repo.name == "dictionary"
assert Path(f"{local_git_home}/dictionary") == repo.local_directory


def test_lazy_load_no_clone(tmpdir: Path) -> None:
with mock.patch.dict(os.environ, {"GML_GIT_HOME": str(tmpdir)}):
rm = repository.GitRepository(url=REMOTE_GIT_URL, name="smiths", lazy_load=True)
rm = repository.GitRepository(url="", name="smiths", lazy_load=True)
assert rm.is_cloned is False


@pytest.mark.parametrize(
"is_tag, expected_ref", [(True, "refs/tags/0.1.0"), (False, "refs/remotes/origin/0.1.0")]
)
def test_get_commit_ref(is_tag: bool, expected_ref: str) -> None:
rm = repository.GitRepository(
url=REMOTE_GIT_URL, name="smiths", lazy_load=True, is_tag=is_tag
)
rm = repository.GitRepository(url="", name="smiths", lazy_load=True, is_tag=is_tag)
assert expected_ref == rm.get_commit_ref("0.1.0")


@pytest.mark.parametrize(
"commit, is_tag",
[
("0.1.0", True),
("master", False),
],
)
def test_get_git_commit_id(tmpdir: Path, git_server: str, commit: str, is_tag: bool) -> None:
with mock.patch.dict(os.environ, {"GML_GIT_HOME": str(tmpdir)}):
rm = repository.GitRepository(url=git_server, name="smiths", is_tag=is_tag)
rm.clone()
assert rm.get_commit_id(rm.get_commit_ref(commit))


def test_get_invalid_commit_id(tmpdir: Path, git_server: str) -> None:
with mock.patch.dict(os.environ, {"GML_GIT_HOME": str(tmpdir)}):
rm = repository.GitRepository(url=git_server, name="smiths", is_tag=False)
rm.clone()
assert rm.get_commit_id(rm.get_commit_ref("master"))


@pytest.mark.parametrize("lazy", [True, False])
def test_read_remote_dictionary(tmpdir: Path, git_server: str, lazy: bool) -> None:
with mock.patch.dict(os.environ, {"GML_GIT_HOME": str(tmpdir)}):

project = repository.GitRepository(
url=git_server,
name="smiths",
force=True,
schema_path="gdcdictionary/schemas",
lazy_load=lazy,
)
chk_dir = project.get_dictionary_directory("0.1.0")
dictionary = project.read("0.1.0")
assert chk_dir.exists()

entries = [f.name for f in chk_dir.iterdir()]
assert "program.yaml" in entries

assert dictionary.name == "smiths"
assert dictionary.version == "0.1.0"


def test_read_existing_remote_dictionary(tmpdir: Path, git_server: str) -> None:
with mock.patch.dict(os.environ, {"GML_GIT_HOME": str(tmpdir)}):

project = repository.GitRepository(
url=git_server,
name="smiths",
force=True,
schema_path="gdcdictionary/schemas",
)
project.read("0.1.0")

p2 = repository.GitRepository(
url=git_server,
name="smiths",
force=False,
schema_path="gdcdictionary/schemas",
)
dictionary = p2.read("0.1.0")

assert dictionary.name == "smiths"
assert dictionary.version == "0.1.0"
37 changes: 37 additions & 0 deletions tests/unit/test_readers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import os
from pathlib import Path
from unittest import mock

from psqlgml.dictionaries import readers


def test_local_reader(data_dir: str):
dictionary = readers.DictionaryReader("dictionary", "0.1.0").local(f"{data_dir}").read()
assert dictionary.name == "dictionary"
assert dictionary.version == "0.1.0"


def test_load_local(data_dir: str):
dictionary = readers.load_local("dictionary", "0.1.0", data_dir)
assert dictionary.name == "dictionary"
assert dictionary.version == "0.1.0"


def test_remote_reader(data_dir: str, git_server: str, tmpdir: Path) -> None:
with mock.patch.dict(
os.environ,
{"GML_GIT_HOME": f"{tmpdir}/git", "GML_DICTIONARY_HOME": f"{tmpdir}/dictionaries"},
):
dictionary = readers.DictionaryReader("dictionary", "0.1.0").git(git_server, True).read()
assert dictionary.name == "dictionary"
assert dictionary.version == "0.1.0"


def test_load_remote(data_dir: str, git_server: str, tmpdir: Path) -> None:
with mock.patch.dict(
os.environ,
{"GML_GIT_HOME": f"{tmpdir}/git", "GML_DICTIONARY_HOME": f"{tmpdir}/dictionaries"},
):
dictionary = readers.load(name="dictionary", version="0.1.0", git_url=git_server)
assert dictionary.name == "dictionary"
assert dictionary.version == "0.1.0"