parent
09f1683c8c
commit
90f1d3de62
@ -0,0 +1,81 @@ |
||||
import os |
||||
from typing import Union |
||||
|
||||
|
||||
class InvalidCNABDirectoryError(Exception): |
||||
pass |
||||
|
||||
|
||||
class CNABDirectory(object): |
||||
path: str |
||||
|
||||
def __init__(self, path: str): |
||||
self.path = path |
||||
|
||||
def has_cnab_directory(self) -> bool: |
||||
cnab = os.path.join(self.path, "cnab") |
||||
return os.path.isdir(cnab) |
||||
|
||||
def has_app_directory(self) -> bool: |
||||
app = os.path.join(self.path, "cnab", "app") |
||||
return os.path.isdir(app) |
||||
|
||||
def has_no_misc_files_in_cnab_dir(self) -> bool: |
||||
cnab = os.path.join(self.path, "cnab") |
||||
for root, dirs, files in os.walk(cnab): |
||||
disallowed_dirs = [x for x in dirs if x not in ["app", "build"]] |
||||
disallowed_files = [ |
||||
x for x in files if x not in ["LICENSE", "README.md", "README.txt"] |
||||
] |
||||
break |
||||
if disallowed_dirs or disallowed_files: |
||||
return False |
||||
else: |
||||
return True |
||||
|
||||
def has_run(self) -> bool: |
||||
run = os.path.join(self.path, "cnab", "app", "run") |
||||
return os.path.isfile(run) |
||||
|
||||
def has_executable_run(self) -> bool: |
||||
run = os.path.join(self.path, "cnab", "app", "run") |
||||
return os.access(run, os.X_OK) |
||||
|
||||
def readme(self) -> Union[bool, str]: |
||||
readme = os.path.join(self.path, "cnab", "README") |
||||
txt = readme + ".txt" |
||||
md = readme + ".md" |
||||
if os.path.isfile(txt): |
||||
with open(txt, "r") as content: |
||||
return content.read() |
||||
elif os.path.isfile(md): |
||||
with open(md, "r") as content: |
||||
return content.read() |
||||
else: |
||||
return False |
||||
|
||||
def license(self) -> Union[bool, str]: |
||||
license = os.path.join(self.path, "cnab", "LICENSE") |
||||
if os.path.isfile(license): |
||||
with open(license, "r") as content: |
||||
return content.read() |
||||
else: |
||||
return False |
||||
|
||||
def valid(self) -> bool: |
||||
errors = [] |
||||
if not self.has_executable_run(): |
||||
errors.append("Run entrypoint is not executable") |
||||
if not self.has_run(): |
||||
errors.append("Missing a run entrypoint") |
||||
if not self.has_app_directory(): |
||||
errors.append("Missing the app directory") |
||||
if not self.has_cnab_directory(): |
||||
errors.append("Missing the cnab directory") |
||||
if not self.has_no_misc_files_in_cnab_dir(): |
||||
errors.append("Has additional files in the cnab directory") |
||||
|
||||
if len(errors) == 0: |
||||
return True |
||||
else: |
||||
raise InvalidCNABDirectoryError(errors) |
@ -0,0 +1,69 @@ |
||||
import pytest # type: ignore |
||||
|
||||
from cnab import CNABDirectory |
||||
from cnab.invocation_image import InvalidCNABDirectoryError |
||||
|
||||
|
||||
class SampleCNAB(object): |
||||
@pytest.fixture |
||||
def directory(self): |
||||
return CNABDirectory("fixtures/invocationimage") |
||||
|
||||
|
||||
class TestCNABDirectory(SampleCNAB): |
||||
def test_has_app_dir(self, directory): |
||||
assert directory.has_app_directory() |
||||
|
||||
def test_has_cnab_dir(self, directory): |
||||
assert directory.has_cnab_directory() |
||||
|
||||
def test_has_readme(self, directory): |
||||
assert isinstance(directory.readme(), str) |
||||
|
||||
def test_has_license(self, directory): |
||||
assert isinstance(directory.license(), str) |
||||
|
||||
def test_has_no_misc_files(self, directory): |
||||
assert directory.has_no_misc_files_in_cnab_dir() |
||||
|
||||
def test_has_run(self, directory): |
||||
assert directory.has_run() |
||||
|
||||
def test_has_executable(self, directory): |
||||
assert directory.has_executable_run() |
||||
|
||||
def test_is_valid(self, directory): |
||||
assert directory.valid() |
||||
|
||||
|
||||
class InvalidCNAB(object): |
||||
@pytest.fixture |
||||
def directory(self): |
||||
return CNABDirectory("fixtures/invalidinvocationimage") |
||||
|
||||
|
||||
class TestInvalidCNABDirectory(InvalidCNAB): |
||||
def test_has_no_app_dir(self, directory): |
||||
assert not directory.has_app_directory() |
||||
|
||||
def test_has_cnab_dir(self, directory): |
||||
assert directory.has_cnab_directory() |
||||
|
||||
def test_has_readme(self, directory): |
||||
assert isinstance(directory.readme(), str) |
||||
|
||||
def test_has_no_license(self, directory): |
||||
assert not directory.license() |
||||
|
||||
def test_has_invalid_misc_files(self, directory): |
||||
assert not directory.has_no_misc_files_in_cnab_dir() |
||||
|
||||
def test_has_no_run(self, directory): |
||||
assert not directory.has_run() |
||||
|
||||
def test_has_no_executable(self, directory): |
||||
assert not directory.has_executable_run() |
||||
|
||||
def test_is_invalid(self, directory): |
||||
with pytest.raises(InvalidCNABDirectoryError): |
||||
directory.valid() |
@ -1,5 +1,7 @@ |
||||
[pytest] |
||||
addopts = --black --mypy --verbose --ignore scratch --cov=cnab --cov-report term-missing |
||||
filterwarnings = |
||||
ignore::DeprecationWarning |
||||
|
||||
markers = |
||||
docker: tests which rely on Docker |
||||
|
Loading…
Reference in new issue