コード例 #1
0
    def test_rename_associated_file(self, setup: Any,
                                    preserve_files: bool) -> None:
        """Test removing associated files.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            preserve_files: argument to `DeleteCommand`.
        """
        try:
            config.commands.edit.editor = "sed -i 's/einstein:/dummy:/'"

            with tempfile.TemporaryDirectory() as tmpdirname:
                path = RelPath(tmpdirname + "/einstein.pdf")
                open(  # pylint: disable=consider-using-with
                    path.path,
                    "w",
                    encoding="utf-8").close()

                Database()["einstein"].file = str(path)

                args = ["einstein"]
                if preserve_files:
                    args.insert(2, "--preserve-files")
                EditCommand().execute(args)
                assert "dummy" in Database().keys()

                target = RelPath(tmpdirname + "/dummy.pdf")
                if preserve_files:
                    assert path.path.exists()
                else:
                    assert target.path.exists()
        finally:
            config.defaults()
コード例 #2
0
    def test_handle_argument_error(self,
                                   caplog: pytest.LogCaptureFixture) -> None:
        """Test handling of ArgumentError.

        Args:
            caplog: the built-in pytest fixture.
        """
        # use temporary config
        config.database.file = self.COBIB_TEST_DIR / "database.yaml"
        config.database.git = True

        # load temporary database
        os.makedirs(self.COBIB_TEST_DIR, exist_ok=True)
        copyfile(get_resource("example_literature.yaml"), config.database.file)
        Database().read()

        try:
            super().test_handle_argument_error(caplog)
        finally:
            # clean up file system
            os.remove(config.database.file)
            # clean up database
            Database().clear()
            # clean up config
            config.defaults()
コード例 #3
0
    def test_scroll_live(self, keys: str,
                         assertion_kwargs: Dict[str, Union[int, str]]) -> None:
        """Test scrolling while the TUI is actually running.

        Args:
            keys: the string of keys to send to the running TUI.
            assertion_kwargs: additional keyword arguments to pass to the assertion method.
        """
        def assertion(screen, logs, **kwargs):  # type: ignore
            direction = kwargs["direction"]
            update = kwargs["update"]
            term_width = len(screen.buffer[0])

            if direction == "y" or update == 0:
                assert [c.fg for c in screen.buffer[1 + update].values()
                        ] == ["white"] * term_width
                assert [c.bg for c in screen.buffer[1 + update].values()
                        ] == ["cyan"] * term_width
            elif direction == "x":
                # TODO: figure out how (or if) to actually use the update information
                assert [c.fg for c in screen.buffer[1].values()
                        ] == ["white"] * term_width
                assert [c.bg for c in screen.buffer[1].values()
                        ] == ["cyan"] * term_width

        # overwrite database
        config.database.file = get_resource("scrolling_database.yaml", "tui")
        try:
            Database().read()
            self.run_tui(keys, assertion, assertion_kwargs)
        finally:
            Database().clear()
コード例 #4
0
ファイル: test_database.py プロジェクト: mrossinek/cobib
def test_database_read() -> None:
    """Test the `cobib.database.Database.read` method."""
    bib = Database()
    bib.read()
    # pylint: disable=protected-access
    assert Database._unsaved_entries == {}  # pylint: disable=C1803
    assert list(bib.keys()) == ["einstein", "latexcompanion", "knuthwebsite"]
コード例 #5
0
ファイル: test_database.py プロジェクト: mrossinek/cobib
def test_database_update() -> None:
    """Test the `cobib.database.Database.update` method."""
    entries = {"dummy1": "test1", "dummy2": "test2", "dummy3": "test3"}
    bib = Database()
    bib.update(entries)  # type: ignore
    # pylint: disable=protected-access
    assert Database._unsaved_entries == {e: e for e in list(entries.keys())}
    for key, val in entries.items():
        assert bib[key] == val
コード例 #6
0
ファイル: test_database.py プロジェクト: mrossinek/cobib
def test_database_rename() -> None:
    """Test the `cobib.database.Database.rename` method."""
    bib = Database()
    # pylint: disable=protected-access
    Database._unsaved_entries = {}
    assert Database._unsaved_entries == {}  # pylint: disable=C1803
    bib.rename("einstein", "dummy")
    # pylint: disable=protected-access
    assert Database._unsaved_entries == {"einstein": "dummy"}
コード例 #7
0
    def test_command(self, setup: Any, args: List[str]) -> None:
        """Test the command itself.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            args: the arguments to pass to the command.
        """
        if "-z" in args:
            # add a dummy file to the `einstein` entry
            entry = Database()["einstein"]
            entry.file = get_resource("debug.py")
        ExportCommand().execute(args)
        self._assert(args)
コード例 #8
0
    def test_event_pre_delete_command(self, setup: Any) -> None:
        """Tests the PreDeleteCommand event."""

        @Event.PreDeleteCommand.subscribe
        def hook(largs: Namespace) -> None:
            largs.labels = ["einstein"]

        assert Event.PreDeleteCommand.validate()

        DeleteCommand().execute(["knuthwebsite"])

        assert "einstein" not in Database().keys()
        assert "knuthwebsite" in Database().keys()
コード例 #9
0
ファイル: test_database.py プロジェクト: mrossinek/cobib
def test_database_save_add() -> None:
    """Test the `cobib.database.Database.save` method after entry addition."""
    # prepare temporary database
    config.database.file = TMPDIR / "cobib_test_database_file.yaml"
    copyfile(EXAMPLE_LITERATURE, config.database.file)

    # initialize database
    bib = Database()
    bib.read()
    bib.update({"dummy": DUMMY_ENTRY})
    bib.save()

    expected = []
    with open(EXAMPLE_LITERATURE, "r", encoding="utf-8") as file:
        expected.extend(file.readlines())
    expected.extend(DUMMY_ENTRY_YAML.split("\n"))

    try:
        # pylint: disable=protected-access
        assert Database._unsaved_entries == {}  # pylint: disable=C1803

        with open(config.database.file, "r", encoding="utf-8") as file:
            # NOTE: do NOT use zip_longest to omit last entries (for testing simplicity)
            for line, truth in zip(file, expected):
                assert line.strip() == truth.strip()
            with pytest.raises(StopIteration):
                file.__next__()
    finally:
        os.remove(config.database.file)
        config.database.file = EXAMPLE_LITERATURE
コード例 #10
0
ファイル: test_database.py プロジェクト: mrossinek/cobib
def test_database_save_modify() -> None:
    """Test the `cobib.database.Database.save` method after entry modification."""
    # prepare temporary database
    config.database.file = TMPDIR / "cobib_test_database_file.yaml"
    copyfile(EXAMPLE_LITERATURE, config.database.file)

    # initialize database
    bib = Database()
    bib.read()
    entry = copy.deepcopy(bib["einstein"])
    entry.data["tags"] = "test"
    bib.update({"einstein": entry})
    bib.save()

    try:
        # pylint: disable=protected-access
        assert Database._unsaved_entries == {}  # pylint: disable=C1803

        with open(config.database.file, "r", encoding="utf-8") as file:
            with open(EXAMPLE_LITERATURE, "r", encoding="utf-8") as expected:
                # NOTE: do NOT use zip_longest to omit last entries (for testing simplicity)
                for line, truth in zip(file, expected):
                    if "tags" in line:
                        assert line == "  tags: test\n"
                        # advance only the `file` iterator one step in order to catch up with the
                        # `expected` iterator
                        line = next(file)
                    assert line == truth
                with pytest.raises(StopIteration):
                    file.__next__()
    finally:
        os.remove(config.database.file)
        config.database.file = EXAMPLE_LITERATURE
コード例 #11
0
ファイル: test_database.py プロジェクト: mrossinek/cobib
def test_database_save_delete() -> None:
    """Test the `cobib.database.Database.save` method after entry deletion."""
    # prepare temporary database
    config.database.file = TMPDIR / "cobib_test_database_file.yaml"
    copyfile(EXAMPLE_LITERATURE, config.database.file)

    # initialize database
    bib = Database()
    bib.read()
    bib.pop("knuthwebsite")
    bib.save()

    try:
        # pylint: disable=protected-access
        assert Database._unsaved_entries == {}  # pylint: disable=C1803

        with open(config.database.file, "r", encoding="utf-8") as file:
            with open(EXAMPLE_LITERATURE, "r", encoding="utf-8") as expected:
                # NOTE: do NOT use zip_longest to omit last entries (for testing simplicity)
                for line, truth in zip(file, expected):
                    assert line == truth
                with pytest.raises(StopIteration):
                    file.__next__()
    finally:
        os.remove(config.database.file)
        config.database.file = EXAMPLE_LITERATURE
コード例 #12
0
ファイル: test_database.py プロジェクト: mrossinek/cobib
def test_database_disambiguate_label(label_suffix: Tuple[str, Callable[[str],
                                                                       str]],
                                     expected: str) -> None:
    # pylint: disable=invalid-name
    """Test the `cobib.database.Database.disambiguate_label` method."""
    config.database.format.default_label_format = "test"
    config.database.format.label_suffix = label_suffix

    entries = {"dummy": "test", "test": "no"}
    bib = Database()
    bib.update(entries)  # type: ignore

    new_label = Database().disambiguate_label("test",
                                              entries["dummy"])  # type: ignore
    assert new_label == expected
コード例 #13
0
ファイル: test_add.py プロジェクト: mrossinek/cobib
    def test_command(self, setup: Any, more_args: List[str], entry_kwargs: Dict[str, Any]) -> None:
        """Test the command itself.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            more_args: additional arguments to be passed to the command.
            entry_kwargs: the expected contents of the resulting `Entry`.
        """
        git = setup.get("git", False)

        try:
            label = more_args[more_args.index("-l") + 1]
        except ValueError:
            label = "example_multi_file_entry"
        args = ["-b", EXAMPLE_MULTI_FILE_ENTRY_BIB] + more_args

        AddCommand().execute(args)

        assert Database()[label]

        if entry_kwargs or label != "example_multi_file_entry":
            self._assert_entry(label, **entry_kwargs)
        else:
            # only when we don't use extra arguments the files will match
            self._assert(EXAMPLE_MULTI_FILE_ENTRY_YAML)

        if git:
            # assert the git commit message
            # Note: we do not assert the arguments, because they depend on the available parsers
            self.assert_git_commit_message("add", None)
コード例 #14
0
    def post_setup(
        self, monkeypatch: pytest.MonkeyPatch,
        request: _pytest.fixtures.SubRequest
    ) -> Generator[Dict[str, Any], None, None]:
        """Additional setup instructions.

        Args:
            monkeypatch: the built-in pytest fixture.
            request: a pytest sub-request providing access to nested parameters.

        Yields:
            The internally used parameters for potential later re-use during the actual test.
        """
        if not hasattr(request, "param"):
            # use default settings
            request.param = {"stdin_list": None, "multi_file": True}

        if request.param.get("multi_file", True):
            with open(get_resource("example_multi_file_entry.yaml",
                                   "commands"),
                      "r",
                      encoding="utf-8") as multi_file_entry:
                with open(config.database.file, "a",
                          encoding="utf-8") as database:
                    database.write(multi_file_entry.read())
            Database().read()

        monkeypatch.setattr("sys.stdin",
                            MockStdin(request.param.get("stdin_list", None)))

        yield request.param
コード例 #15
0
ファイル: test_add.py プロジェクト: mrossinek/cobib
    def test_add_skip_download(self, setup: Any, caplog: pytest.LogCaptureFixture) -> None:
        """Test adding a new entry and skipping the automatic download.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            caplog: the built-in pytest fixture.
        """
        path = RelPath("/tmp/Cao2018.pdf")
        try:
            args = ["-a", "1812.09976", "--skip-download"]

            AddCommand().execute(args)

            if (
                "cobib.parsers.arxiv",
                logging.ERROR,
                "An Exception occurred while trying to query the arXiv ID: 1812.09976.",
            ) in caplog.record_tuples:
                pytest.skip("The requests API encountered an error. Skipping test.")

            entry = Database()["Cao2018"]
            assert entry.label == "Cao2018"
            assert entry.data["archivePrefix"] == "arXiv"
            assert entry.data["arxivid"].startswith("1812.09976")
            assert "_download" not in entry.data.keys()
            assert not os.path.exists(path.path)
        finally:
            try:
                os.remove(path.path)
            except FileNotFoundError:
                pass
コード例 #16
0
ファイル: test_add.py プロジェクト: mrossinek/cobib
    def test_disambiguate_label(self, setup: Any, caplog: pytest.LogCaptureFixture) -> None:
        """Test label disambiguation if the provided one already exists.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            caplog: the built-in pytest fixture.
        """
        git = setup.get("git", False)

        AddCommand().execute(["-b", EXAMPLE_DUPLICATE_ENTRY_BIB])

        assert (
            "cobib.commands.add",
            30,
            "You tried to add a new entry 'einstein' which already exists!",
        ) in caplog.record_tuples
        assert (
            "cobib.commands.add",
            30,
            "The label will be disambiguated based on the configuration option: "
            "config.database.format.label_suffix",
        ) in caplog.record_tuples

        assert Database()["einstein_a"]

        if git:
            # assert the git commit message
            self.assert_git_commit_message("add", None)
コード例 #17
0
    def _assert(self, labels: List[str]) -> None:
        """Common assertion utility method.

        Args:
            labels: the list of labels to be deleted.
        """
        bib = Database()

        for label in labels:
            assert bib.get(label, None) is None

        with open(config.database.file, "r", encoding="utf-8") as file:
            with open(get_resource("example_literature.yaml"), "r", encoding="utf-8") as expected:
                # NOTE: do NOT use zip_longest to omit last entries (for testing simplicity)
                for line, truth in zip(file, expected):
                    assert line == truth
                with pytest.raises(StopIteration):
                    file.__next__()
コード例 #18
0
ファイル: test_modify.py プロジェクト: mrossinek/cobib
    def test_cmdline(self, setup: Any, monkeypatch: pytest.MonkeyPatch, args: List[str]) -> None:
        """Test the command-line access of the command.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            monkeypatch: the built-in pytest fixture.
            args: additional arguments to pass to the command.
        """
        self.run_module(monkeypatch, "main", ["cobib", "modify"] + args)
        assert Database()["einstein"].data["tags"] == ["test"]
コード例 #19
0
ファイル: test_add.py プロジェクト: mrossinek/cobib
    def _assert_entry(self, label: str, **kwargs) -> None:  # type: ignore
        """An additional assertion utility to check specific entry fields.

        Args:
            label: the label of the entry.
            kwargs: additional keyword arguments whose contents are checked against the Entry's
                `data contents.
        """
        entry = Database()[label]
        for key, value in kwargs.items():
            assert entry.data.get(key, None) == value
コード例 #20
0
    def test_event_post_edit_command(self, setup: Any) -> None:
        """Tests the PostEditCommand event."""
        @Event.PostEditCommand.subscribe
        def hook(new_entry: Entry) -> None:
            new_entry.data["tags"] = "test"

        assert Event.PostEditCommand.validate()

        EditCommand().execute(["-a", "dummy"])

        assert Database()["dummy"].data["tags"] == "test"
コード例 #21
0
ファイル: test_add.py プロジェクト: mrossinek/cobib
    def test_event_pre_add_command(self, setup: Any) -> None:
        """Tests the PreAddCommand event."""

        @Event.PreAddCommand.subscribe
        def hook(largs: Namespace) -> None:
            largs.label = "dummy"

        assert Event.PreAddCommand.validate()

        AddCommand().execute(["-b", EXAMPLE_DUPLICATE_ENTRY_BIB])

        assert "dummy" in Database().keys()
コード例 #22
0
ファイル: test_modify.py プロジェクト: mrossinek/cobib
    def test_f_string_interpretation(self, setup: Any, modification: str, expected: Any) -> None:
        """Test f-string interpretation.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            modification: the modification string to apply.
            expected: the expected final `Entry` field.
        """
        # modify some data
        args = [modification, "++label", "einstein"]

        field, *_ = modification.split(":")

        ModifyCommand().execute(args)

        if field != "label":
            assert Database()["einstein"].data[field] == expected
        else:
            assert "eistein" not in Database().keys()
            assert expected in Database().keys()
            assert Database()[expected].label == expected
コード例 #23
0
ファイル: test_add.py プロジェクト: mrossinek/cobib
    def test_event_post_add_command(self, setup: Any) -> None:
        """Tests the PostAddCommand event."""

        @Event.PostAddCommand.subscribe
        def hook(new_entries: Dict[str, Entry]) -> None:
            new_entries["dummy"] = new_entries.pop("einstein_a")

        assert Event.PostAddCommand.validate()

        AddCommand().execute(["-b", EXAMPLE_DUPLICATE_ENTRY_BIB])

        assert "dummy" in Database().keys()
コード例 #24
0
ファイル: test_modify.py プロジェクト: mrossinek/cobib
    def test_event_pre_modify_command(self, setup: Any) -> None:
        """Tests the PreModifyCommand event."""

        @Event.PreModifyCommand.subscribe
        def hook(largs: Namespace) -> None:
            largs.modification = ("number", "2")

        assert Event.PreModifyCommand.validate()

        ModifyCommand().execute(["-a", "number:3", "++label", "einstein"])

        assert Database()["einstein"].data["number"] == 12
コード例 #25
0
ファイル: test_database.py プロジェクト: mrossinek/cobib
def setup() -> Generator[Any, None, None]:
    """Setup debugging configuration.

    This method also clears the `Database` after each test run.
    It is automatically enabled for all tests in this file.

    Yields:
        Access to the local fixture variables.
    """
    config.load(get_resource("debug.py"))
    yield
    Database().clear()
    config.defaults()
コード例 #26
0
ファイル: test_redo.py プロジェクト: mrossinek/cobib
    def _assert(self) -> None:
        """Common assertion utility method."""
        assert Database().get("example_multi_file_entry", None) is not None

        # get last commit message
        with subprocess.Popen(
            ["git", "-C", self.COBIB_TEST_DIR, "show", "--format=format:%B", "--no-patch", "HEAD"],
            stdout=subprocess.PIPE,
        ) as proc:
            message, _ = proc.communicate()
            # decode it
            split_message = message.decode("utf-8").split("\n")
            # assert subject line
            assert "Redo" in split_message[0]
コード例 #27
0
ファイル: shell_helper.py プロジェクト: mrossinek/cobib
def list_labels(args: List[str]) -> List[str]:
    """List all available labels in the database.

    Args:
        args: a sequence of additional arguments used for the execution. None are supported yet.

    Returns:
        The list of all labels.
    """
    # pylint: disable=import-outside-toplevel
    from cobib.database import Database

    labels = list(Database().keys())
    return labels
コード例 #28
0
ファイル: test_modify.py プロジェクト: mrossinek/cobib
    def test_rename_associated_file(self, setup: Any, preserve_files: bool) -> None:
        """Test removing associated files.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            preserve_files: argument to `DeleteCommand`.
        """
        with tempfile.TemporaryDirectory() as tmpdirname:
            path = RelPath(tmpdirname + "/knuthwebsite.pdf")
            open(path.path, "w", encoding="utf-8").close()  # pylint: disable=consider-using-with

            Database()["knuthwebsite"].file = str(path)

            args = ["label:dummy", "-s", "--", "knuthwebsite"]
            if preserve_files:
                args.insert(2, "--preserve-files")
            ModifyCommand().execute(args)
            assert "dummy" in Database().keys()

            target = RelPath(tmpdirname + "/dummy.pdf")
            if preserve_files:
                assert path.path.exists()
            else:
                assert target.path.exists()
コード例 #29
0
ファイル: test_modify.py プロジェクト: mrossinek/cobib
    def test_add_mode(self, setup: Any, modification: str, expected: Any) -> None:
        """Test more cases of the add mode.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            modification: the modification string to apply.
            expected: the expected final `Entry` field.
        """
        # modify some data
        args = ["-a", modification, "++label", "einstein"]

        field, _ = modification.split(":")

        ModifyCommand().execute(args)

        assert Database()["einstein"].data[field] == expected
コード例 #30
0
ファイル: shell_helper.py プロジェクト: mrossinek/cobib
def list_filters(args: List[str]) -> Set[str]:
    """Lists all field names available for filtering.

    Args:
        args: a sequence of additional arguments used for the execution. None are supported yet.

    Returns:
        The list of all available filters.
    """
    # pylint: disable=import-outside-toplevel
    from cobib.database import Database

    filters: Set[str] = {"label"}
    for entry in Database().values():
        filters.update(entry.data.keys())
    return filters