-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from GSA-TTS/cli-scaffolding
Cli scaffolding
- Loading branch information
Showing
13 changed files
with
187 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import os | ||
from .gateways.storage_mock import StorageGatewayMock | ||
|
||
|
||
class ApplicationContext: | ||
def __init__(self): | ||
self._storage = StorageGatewayMock() | ||
|
||
@property | ||
def storage(self): | ||
return self._storage | ||
|
||
|
||
class TestApplicationContext(ApplicationContext): | ||
def __init__(self): | ||
self._storage = StorageGatewayMock() | ||
|
||
|
||
def create_app_context(): | ||
if os.environ.get('APP_ENV') == 'test': | ||
return TestApplicationContext() | ||
return ApplicationContext() |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import click | ||
from ..entities import File | ||
from ..use_cases import upload_file, list_files, get_file_metadata | ||
|
||
|
||
@click.group() | ||
@click.pass_context | ||
def cli(ctx): | ||
pass | ||
|
||
|
||
@cli.command() | ||
@click.pass_context | ||
@click.argument('filename') | ||
@click.argument('content') | ||
def upload(ctx, filename, content): | ||
context = ctx.obj | ||
file = File(name=filename, content=content) | ||
upload_file(context, file) | ||
click.echo(f"Uploaded {filename}") | ||
|
||
|
||
@cli.command() | ||
@click.pass_context | ||
def listall(ctx): | ||
context = ctx.obj | ||
files = list_files(context) | ||
for file in files: | ||
click.echo(file.name) | ||
|
||
|
||
@cli.command() | ||
@click.pass_context | ||
@click.argument('filename') | ||
def metadata(ctx, filename): | ||
context = ctx.obj | ||
metadata = get_file_metadata(context, filename) | ||
click.echo(f"File: {metadata.name}, Size: {metadata.size} bytes") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from dataclasses import dataclass | ||
|
||
|
||
@dataclass | ||
class File: | ||
name: str | ||
content: str | ||
|
||
|
||
@dataclass | ||
class FileMetadata: | ||
name: str | ||
size: int |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
from ..entities import File, FileMetadata | ||
from ..interfaces.storage import StorageGateway | ||
|
||
|
||
class StorageGatewayMock(StorageGateway): | ||
def __init__(self): | ||
self.files = [] | ||
|
||
def save(self, file: File) -> None: | ||
self.files.append(file) | ||
|
||
def list_all(self) -> list[File]: | ||
return self.files | ||
|
||
def get_file(self, file_name: str) -> File: | ||
file = next((f for f in self.files if f.name == file_name), None) | ||
if not file: | ||
raise ValueError(f"No file named {file_name} found!") | ||
return file | ||
|
||
def get_metadata(self, file_name: str) -> FileMetadata: | ||
file = next((f for f in self.files if f.name == file_name), None) | ||
if not file: | ||
raise ValueError(f"No file named {file_name} found!") | ||
return FileMetadata(name=file.name, size=len(file.content)) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from typing import Protocol | ||
from ..entities import File, FileMetadata | ||
|
||
|
||
class StorageGateway(Protocol): | ||
def save(self, file: File) -> None: | ||
... | ||
|
||
def list_all(self) -> list[File]: | ||
... | ||
|
||
def get_metadata(self, file_name: str) -> FileMetadata: | ||
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,18 @@ | ||
def get_greeting() -> str: | ||
return "Hello!" | ||
from .application_context import ApplicationContext | ||
from .entities import File, FileMetadata | ||
from .interfaces.storage import StorageGateway | ||
|
||
|
||
def upload_file(ctx: ApplicationContext, file: File) -> None: | ||
storage: StorageGateway = ctx.storage | ||
storage.save(file) | ||
|
||
|
||
def list_files(ctx: ApplicationContext) -> list[File]: | ||
storage: StorageGateway = ctx.storage | ||
return storage.list_all() | ||
|
||
|
||
def get_file_metadata(ctx: ApplicationContext, file_name: str) -> FileMetadata: | ||
storage: StorageGateway = ctx.storage | ||
return storage.get_metadata(file_name) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,42 @@ | ||
from nad_ch.use_cases import get_greeting | ||
import pytest | ||
from nad_ch.application_context import create_app_context | ||
from nad_ch.entities import File, FileMetadata | ||
from nad_ch.use_cases import upload_file, list_files, get_file_metadata | ||
|
||
|
||
def test_get_greeting(): | ||
expected_result = "Hello!" | ||
@pytest.fixture(scope="function") | ||
def app_context(): | ||
context = create_app_context() | ||
yield context | ||
|
||
actual_result = get_greeting() | ||
|
||
assert actual_result == expected_result | ||
def test_upload_file(app_context): | ||
file = File(name="test.txt", content="Sample content") | ||
|
||
upload_file(app_context, file) | ||
|
||
stored_file = app_context.storage.get_file("test.txt") | ||
assert stored_file.name == "test.txt" | ||
assert stored_file.content == "Sample content" | ||
|
||
|
||
def test_list_files(app_context): | ||
file1 = File(name="test1.txt", content="Content 1") | ||
file2 = File(name="test2.txt", content="Content 2") | ||
upload_file(app_context, file1) | ||
upload_file(app_context, file2) | ||
|
||
files = list_files(app_context) | ||
|
||
assert len(files) == 2 | ||
assert any(f.name == "test1.txt" for f in files) | ||
assert any(f.name == "test2.txt" for f in files) | ||
|
||
|
||
def test_get_file_metadata(app_context): | ||
file = File(name="test.txt", content="Sample content for metadata") | ||
upload_file(app_context, file) | ||
|
||
metadata = get_file_metadata(app_context, "test.txt") | ||
|
||
assert isinstance(metadata, FileMetadata) |