Verified Commit 0f02fe86 authored by David Runge's avatar David Runge
Browse files

Add argparse for json2db

repo_management/argparse.py:
Add `ArgParseFactory.json2db()` as an ArgumentParser for the `json2db`
script.
Add `ArgParseFactory.string_to_writable_file_path()` for returning a
Path object, that is guaranteed to be a writable file.

tests/test_argparse.py:
Add tests for
`ArgParseFactory.{json2db,string_to_writable_file_path}()`.
parent d1fa043d
import argparse import argparse
import os
from pathlib import Path from pathlib import Path
...@@ -46,6 +47,78 @@ class ArgParseFactory: ...@@ -46,6 +47,78 @@ class ArgParseFactory:
return instance.parser return instance.parser
@classmethod
def json2db(self) -> argparse.ArgumentParser:
"""A class method to create an ArgumentParser for the json2db script
Returns
-------
argparse.ArgumentParser
An ArgumentParser instance specific for the json2db script
"""
instance = self(
description="Read a set of JSON files from a directory and create a repository database from them."
)
instance.parser.add_argument(
"-f",
"--files",
action="store_true",
help="create a .files database instead of a .db database",
)
instance.parser.add_argument(
"input_dir",
type=self.string_to_dir_path,
default=".",
help="the directory from which to read the JSON files (defaults to current directory)",
)
instance.parser.add_argument(
"db_file",
type=self.string_to_writable_file_path,
default=None,
help="the repository database to write to (the parent directory needs to exist)",
)
return instance.parser
@classmethod
def string_to_writable_file_path(self, input_: str) -> Path:
"""Convert an input string into a Path to a file
This method checks whether an (existing) file is writable. If the file does not exist the parent directory is
checked for existence and whether it is writable.
Parameters
----------
input_: str
A string that is used to create a Path
Raises
------
argparse.ArgumentTypeError:
If a Path created from input_ does not exist or is not a file
Returns
-------
Path
A Path instance created from input_
"""
path = Path(input_)
if path.exists():
if not path.is_file():
raise argparse.ArgumentTypeError(f"not a file: '{input_}'")
if not os.access(path, os.W_OK):
raise argparse.ArgumentTypeError(f"the file '{input_}' is not writable")
else:
if not path.parent.exists():
raise argparse.ArgumentTypeError(f"the parent directory of '{input_}' does not exist")
if not path.parent.is_dir():
raise argparse.ArgumentTypeError(f"parent is not a directory: '{input_}'")
if not os.access(path.parent, os.W_OK):
raise argparse.ArgumentTypeError(f"the parent directory of '{input_}' is not writable")
return path
@classmethod @classmethod
def string_to_file_path(self, input_: str) -> Path: def string_to_file_path(self, input_: str) -> Path:
"""Convert an input string into a Path to a file """Convert an input string into a Path to a file
......
...@@ -14,6 +14,10 @@ def test_argparsefactory__db2json() -> None: ...@@ -14,6 +14,10 @@ def test_argparsefactory__db2json() -> None:
assert isinstance(repo_argparse.ArgParseFactory.db2json(), argparse.ArgumentParser) assert isinstance(repo_argparse.ArgParseFactory.db2json(), argparse.ArgumentParser)
def test_argparsefactory__json2db() -> None:
assert isinstance(repo_argparse.ArgParseFactory.json2db(), argparse.ArgumentParser)
@patch( @patch(
"repo_management.argparse.Path", "repo_management.argparse.Path",
Mock(return_value=Mock(exists=Mock(side_effect=[False, True, True]), is_file=Mock(side_effect=[False, True]))), Mock(return_value=Mock(exists=Mock(side_effect=[False, True, True]), is_file=Mock(side_effect=[False, True]))),
...@@ -26,6 +30,30 @@ def test_argparsefactory_string_to_file_path() -> None: ...@@ -26,6 +30,30 @@ def test_argparsefactory_string_to_file_path() -> None:
assert repo_argparse.ArgParseFactory.string_to_file_path("foo") assert repo_argparse.ArgParseFactory.string_to_file_path("foo")
@patch(
"os.access",
Mock(side_effect=[False, False, True, True]),
)
@patch("repo_management.argparse.Path.exists", Mock(side_effect=[True, True, False, False, False, True, False]))
@patch("repo_management.argparse.Path.is_file", Mock(side_effect=[False, True, True]))
@patch("repo_management.argparse.Path.parent", return_value=Mock())
def test_argparsefactory_string_to_writable_file_path(parent_mock: Mock) -> None:
parent_mock.exists.side_effect = [False, True, True, True]
parent_mock.is_dir.side_effect = [False, True, True]
with raises(argparse.ArgumentTypeError):
repo_argparse.ArgParseFactory.string_to_writable_file_path("foo")
with raises(argparse.ArgumentTypeError):
repo_argparse.ArgParseFactory.string_to_writable_file_path("foo")
with raises(argparse.ArgumentTypeError):
repo_argparse.ArgParseFactory.string_to_writable_file_path("foo")
with raises(argparse.ArgumentTypeError):
repo_argparse.ArgParseFactory.string_to_writable_file_path("foo")
with raises(argparse.ArgumentTypeError):
repo_argparse.ArgParseFactory.string_to_writable_file_path("foo")
assert repo_argparse.ArgParseFactory.string_to_writable_file_path("foo")
assert repo_argparse.ArgParseFactory.string_to_writable_file_path("foo")
@patch( @patch(
"repo_management.argparse.Path", "repo_management.argparse.Path",
Mock(return_value=Mock(exists=Mock(side_effect=[False, True, True]), is_dir=Mock(side_effect=[False, True]))), Mock(return_value=Mock(exists=Mock(side_effect=[False, True, True]), is_dir=Mock(side_effect=[False, True]))),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment