예제 #1
0
    def test_repository_raises_error_if_get_finds_more_than_one_entity(
            self, repo: Repository) -> None:
        """
        Given: Two entities of different type with the same ID
        When: We get the ID without specifying the model
        Then: a TooManyEntitiesError error is raised
        """
        entities = AuthorFactory.batch(2, name="same name")
        repo.add(entities)
        repo.commit()

        with pytest.raises(TooManyEntitiesError, match=""):
            repo.get("same name", Author, "name")  # act
예제 #2
0
 def test_repository_raises_error_if_no_entity_found_by_get(
     self,
     repo: Repository,
     entity: Entity,
 ) -> None:
     """As the entity is not inserted into the repository, it shouldn't be found."""
     with pytest.raises(
             EntityNotFoundError,
             match=(
                 f"There are no entities of type {entity.model_name} in the "
                 f"repository with id_ {entity.id_}."),
     ):
         repo.get(entity.id_, type(entity))
예제 #3
0
파일: test_cli.py 프로젝트: lyz-code/pydo
    def test_thaw_task_by_id(
        self,
        runner: CliRunner,
        insert_frozen_parent_task_e2e: RecurrentTask,
        repo_e2e: Repository,
        caplog: LogCaptureFixture,
    ) -> None:
        """
        Given: A frozen recurrent task
        When: Thawed
        Then: The task is back active and it's next children is breed.
        """
        parent_task = insert_frozen_parent_task_e2e
        now = datetime.now()

        result = runner.invoke(cli, ["thaw", str(parent_task.id_)])

        parent_task = repo_e2e.get(parent_task.id_, [RecurrentTask])
        child_task = repo_e2e.search({"parent_id": parent_task.id_}, [Task])[0]
        assert result.exit_code == 0
        assert (
            "pydo.services",
            logging.INFO,
            f"Thawed task {parent_task.id_}: {parent_task.description}, and created "
            f"it's next child task with id {child_task.id_}",
        ) in caplog.record_tuples
        assert parent_task.state == TaskState.BACKLOG
        assert parent_task.active is True
        assert child_task.state == TaskState.BACKLOG
        assert child_task.active is True
        assert child_task.due is not None
        assert child_task.due > now
예제 #4
0
파일: test_cli.py 프로젝트: lyz-code/pydo
    def test_modify_task_can_remove_tag_that_starts_with_p(
        self,
        runner: CliRunner,
        insert_tasks_e2e: List[Task],
        faker: Faker,
        repo_e2e: Repository,
        caplog: LogCaptureFixture,
    ) -> None:
        """
        Given: A task with a tag that starts with a p
        When: removing the tag
        Then: the tag is removed

        It's necessary in case we start using the `--parent` flag as `-p`, in that case
        when using `pydo mod 0 -python`, it interprets that the parent flag is set
        and that the tag is ython.
        """
        task = insert_tasks_e2e[0]
        task.tags = ["python"]
        repo_e2e.add(task)
        repo_e2e.commit()

        result = runner.invoke(cli, ["mod", str(task.id_), "-python"])

        modified_task = repo_e2e.get(task.id_, [Task])
        assert result.exit_code == 0
        assert re.match(f"Modified task {task.id_}", caplog.records[0].msg)
        assert modified_task.tags == []
        assert modified_task.description == task.description
예제 #5
0
파일: services.py 프로젝트: lyz-code/pydo
def freeze_tasks(
    repo: Repository,
    selector: TaskSelector,
) -> None:
    """Freeze a list of tasks based on a task filter."""
    tasks = _tasks_from_selector(repo, selector)
    for task in tasks:
        if type(task) == Task:
            child_task = task
            if child_task.parent_id is None:
                raise ValueError(
                    f"Task {child_task.id_}: {child_task.description} is not the child"
                    " of any recurrent task, so it can't be frozen")
            parent_task = repo.get(child_task.parent_id, [RecurrentTask])
        elif type(task) == RecurrentTask:
            parent_task = task
            try:
                child_task = repo.search(
                    {
                        "active": True,
                        "parent_id": task.id_
                    }, [Task])[0]
            except EntityNotFoundError as error:
                raise EntityNotFoundError(
                    f"The recurrent task {task.id_}: {task.description} has no active "
                    "children") from error
        parent_task.freeze()
        repo.add(parent_task)
        repo.delete(child_task)
        log.info(
            f"Frozen recurrent task {parent_task.id_}: {parent_task.description} and "
            f"deleted it's last child {child_task.id_}")
    repo.commit()
예제 #6
0
    def test_repository_raises_error_if_get_finds_more_than_one_entity(
        self, repo: Repository, inserted_entity: Entity
    ) -> None:
        """
        Given: Two entities of different type with the same ID
        When: We get the ID without specifying the model
        Then: a TooManyEntitiesError error is raised
        """
        other_entity = OtherEntity(id_=inserted_entity.id_, name="Other entity")
        repo.models = [type(inserted_entity), OtherEntity]  # type: ignore
        repo.add(other_entity)
        repo.commit()
        with pytest.warns(
            UserWarning, match="In 2022-06-10.*deprecated"
        ), pytest.raises(TooManyEntitiesError, match=""):

            repo.get(inserted_entity.id_)  # act
예제 #7
0
    def test_repository_can_retrieve_an_entity_if_no_model_defined(
        self,
        repo: Repository,
        inserted_entity: Entity,
    ) -> None:
        """Given an entity_id the repository returns the entity object."""
        repo.models = [type(inserted_entity)]  # type: ignore
        with pytest.warns(UserWarning, match="In 2022-06-10.*deprecated"):

            result: Entity = repo.get(inserted_entity.id_)

        assert result == inserted_entity
        assert result.id_ == inserted_entity.id_
예제 #8
0
    def test_repository_can_retrieve_an_entity_if_list_of_models_defined(
        self,
        repo: Repository,
        inserted_entity: Entity,
    ) -> None:
        """Given an entity_id the repository returns the entity object."""
        entity_models: List[Type[Entity]] = [type(inserted_entity), OtherEntity]
        repo.models = entity_models  # type: ignore
        with pytest.warns(UserWarning, match="In 2022-06-10.*deprecated"):

            result = repo.get(inserted_entity.id_, entity_models)

        assert result == inserted_entity
        assert result.id_ == inserted_entity.id_
예제 #9
0
파일: test_cli.py 프로젝트: lyz-code/pydo
    def test_add_a_task_with_an_inexistent_tag(
        self,
        runner: CliRunner,
        faker: Faker,
        caplog: LogCaptureFixture,
        repo_e2e: Repository,
    ) -> None:
        """Test the insertion of a task with a tag."""
        description = faker.sentence()
        tag = faker.word()

        result = runner.invoke(cli, ["add", description, f"+{tag}"])

        task = repo_e2e.get(0, [Task])
        assert result.exit_code == 0
        assert re.match(f"Added task .*: {description}", caplog.records[0].msg)
        assert tag in task.tags
예제 #10
0
    def test_repository_can_retrieve_an_entity_by_a_different_attribute(
        self,
        repo: Repository,
        inserted_str_entity: Entity,
    ) -> None:
        """
        Given an attribute and it's value, the repository returns the entity object.

        The entity is also added to the cache.
        """
        entity = inserted_str_entity

        result = repo.get(entity.name, type(entity), "name")

        assert result == entity
        assert result.id_ == entity.id_
        assert repo.cache.get(entity) == entity
        assert result.defined_values == {}
예제 #11
0
파일: test_cli.py 프로젝트: lyz-code/pydo
    def test_thaw_task_by_id_accepts_state(
        self,
        runner: CliRunner,
        insert_frozen_parent_task_e2e: RecurrentTask,
        repo_e2e: Repository,
        caplog: LogCaptureFixture,
    ) -> None:
        """Test thawing accepts the thawing state of the tasks."""
        parent_task = insert_frozen_parent_task_e2e

        result = runner.invoke(
            cli, ["thaw", str(parent_task.id_), "-s", "todo"])

        parent_task = repo_e2e.get(parent_task.id_, [RecurrentTask])
        child_task = repo_e2e.search({"parent_id": parent_task.id_}, [Task])[0]
        assert result.exit_code == 0
        # T101: fixme found (T O D O). Lol, it's not a comment to fix something
        assert parent_task.state == TaskState.TODO  # noqa: T101
        assert child_task.state == TaskState.TODO  # noqa: T101
예제 #12
0
    def test_repository_can_retrieve_an_entity(
        self,
        repo: Repository,
        inserted_entity: Entity,
    ) -> None:
        """Given an entity_id the repository returns the entity object.

        The entity is also added to the cache.

        The entity _desired_values are empty. This is needed because otherwise all
        attributes are set when you do repo.get() and therefore the merge behaves
        weirdly.
        """
        result = repo.get(inserted_entity.id_, type(inserted_entity))

        assert result == inserted_entity
        assert result.id_ == inserted_entity.id_
        assert repo.cache.get(inserted_entity) == inserted_entity
        assert result.defined_values == {}
예제 #13
0
파일: services.py 프로젝트: lyz-code/pydo
def _close_task(
    repo: Repository,
    task: Task,
    state: TaskState,
    close_date_str: str = "now",
    delete_parent: bool = False,
) -> None:
    """Close a task.

    It gathers the common actions required to complete or delete tasks.
    """
    close_date = convert_date(close_date_str)

    task.close(state, close_date)

    repo.add(task)

    # If it's a child task of another task
    if task.parent_id is not None:
        log.info(
            f"Closing child task {task.id_}: {task.description} with state {state}"
        )
        parent_task = repo.get(task.parent_id, [Task, RecurrentTask])
        # If we want to close the parent of the task.
        if delete_parent:
            parent_task.close(state, close_date)
            repo.add(parent_task)
            log.info(
                f"Closing parent task {parent_task.id_}: {parent_task.description} with"
                f" state {state}")
        # If it's a child task of a recurrent one, we need to spawn the next child.
        elif isinstance(parent_task, RecurrentTask):
            new_child_task = parent_task.breed_children(task)
            repo.add(new_child_task)
            log.info(
                f"Added child task {new_child_task.id_}: {new_child_task.description}",
            )
    # If it's a simple task
    else:
        log.info(
            f"Closing task {task.id_}: {task.description} with state {state}")
        if delete_parent:
            log.info(f"Task {task.id_} doesn't have a parent")
예제 #14
0
파일: services.py 프로젝트: lyz-code/pydo
def _tasks_from_selector(repo: Repository,
                         selector: TaskSelector) -> List[TaskType]:
    """Return the tasks that match the criteria of the task selector."""
    tasks: List[TaskType] = [
        repo.get(task_id, [selector.model]) for task_id in selector.task_ids
    ]

    if selector.task_filter != {}:
        # Remove the tasks that don't meet the task_filter
        for task in tasks:
            # Check if the task_filter is not a subset of the properties of the task.
            # SIM205: Use 'selector.task_filter.items() > task.dict().items()' instead
            # No can't do, if we do, the subset checking doesn't work
            if not selector.task_filter.items() <= task.dict().items(
            ):  # noqa: SIM205
                tasks.remove(task)

        with suppress(EntityNotFoundError):
            tasks.extend(repo.search(selector.task_filter, [selector.model]))

    # Remove duplicates
    return list(set(tasks))
예제 #15
0
파일: test_cli.py 프로젝트: lyz-code/pydo
    def test_modify_task_can_unset_attribute(
        self,
        runner: CliRunner,
        insert_tasks_e2e: List[Task],
        faker: Faker,
        repo_e2e: Repository,
        caplog: LogCaptureFixture,
    ) -> None:
        """
        Given: A task with the priority attribute set
        When: setting the attribute to none
        Then: the priority is set to None
        """
        task = insert_tasks_e2e[0]
        task.priority = 3
        repo_e2e.add(task)
        repo_e2e.commit()

        result = runner.invoke(cli, ["mod", str(task.id_), "pri:"])

        modified_task = repo_e2e.get(task.id_, [Task])
        assert result.exit_code == 0
        assert modified_task.priority is None
예제 #16
0
def create_greeting(repo: Repository, author_id: int) -> str:
    author = repo.get(author_id, Author)
    return f"Hi {author.first_name}!"