Skip to content

Commit

Permalink
feat(main): implement adding new materials via MaterialDatabase
Browse files Browse the repository at this point in the history
  • Loading branch information
Iamhexi committed Oct 4, 2024
1 parent 7503f65 commit c558f05
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 5 deletions.
63 changes: 59 additions & 4 deletions knowledge_verificator/materials.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
"""Module with tools for managing learning material."""

from dataclasses import dataclass
import os
from pathlib import Path

from knowledge_verificator.utils.filesystem import in_directory


@dataclass
class Material:
Expand Down Expand Up @@ -33,14 +36,14 @@ def __init__(self, materials_dir: Path | str) -> None:
if isinstance(materials_dir, str):
materials_dir = Path(materials_dir)

materials_dir = materials_dir.resolve()
if not materials_dir.exists():
self.materials_dir = materials_dir.resolve()
if not self.materials_dir.exists():
raise FileNotFoundError(
f'There is no directory under `{materials_dir}`.'
f'There is no directory under `{self.materials_dir}`.'
)

self.materials: list[Material] = []
for directory_path, _, filenames in materials_dir.walk():
for directory_path, _, filenames in self.materials_dir.walk():
for filename in filenames:
path = Path(directory_path).joinpath(filename)
material = self.load_material(path)
Expand Down Expand Up @@ -72,3 +75,55 @@ def load_material(self, path: Path) -> Material:
paragraphs=paragraphs,
tags=tags,
)

def add_material(self, material: Material) -> None:
"""
Add a learning material to a database, also material's its
representation in a file.
Args:
material (Material): Initialised learning material without
existing file representation.
Raises:
ValueError: Raised if title of a learning material is empty.
FileExistsError: Raised if learning material in a supplied
path already exists.
ValueError: Raised if a supplied path path is outside the
directory for learning materials.
"""
if not material.title:
raise ValueError('Title of a learning material cannot be empty.')
if material.path.exists():
raise FileExistsError(
'A file in the provided path already exists. '
'Choose a different filename.'
)
if not in_directory(file=material.path, directory=self.materials_dir):
raise ValueError(
f'A file {os.path.basename(material.path)}'
f' has to be in {self.materials_dir}'
)
self._create_file_with_material(material=material)
self.materials.append(material)

def _format_file_content(self, material: Material) -> str:
output = ''
# Format a title.
output += material.title
output += '\n---\n'

# Format tags.
tags_line = ', '.join('tags')
output += tags_line + '\n'

# Format content.
content_lines = '\n\n'.join(material.paragraphs)
output += content_lines + '\n\n'

return output

def _create_file_with_material(self, material: Material) -> None:
with open(material.path, 'wt', encoding='utf-8') as fd:
file_content = self._format_file_content(material=material)
fd.write(file_content)
20 changes: 20 additions & 0 deletions knowledge_verificator/utils/filesystem.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""Module with filesystem utility functions."""

from pathlib import Path


def in_directory(file: Path, directory: Path) -> bool:
"""
Determine if a file is located in the supplied directory
or one of its subdirectories.
Args:
file (Path): Path to a file.
directory (Path): Path to a directory.
Returns:
bool: Present in a directory or subdirectories (True) or not (False).
"""
return str(directory.resolve()) in str(
file.resolve()
) and not file.samefile(directory)
29 changes: 29 additions & 0 deletions tests/test_filesystem_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""Module with tests for filesystem utils."""

from pathlib import Path
import pytest

from knowledge_verificator.utils.filesystem import in_directory


@pytest.mark.parametrize(
'directory, file, exists_there',
(
('knowledge_verificator', 'knowledge_verificator/main.py', True),
('knowledge_verificator', 'tests/test_filesystem_utils.py', False),
(
'knowledge_verificator',
'knowledge_verificator/utils/filesystem.py',
True,
),
('knowledge_verificator', 'knowledge_verificator', False),
),
)
def test_in_directory(file: str, directory: str, exists_there: bool):
"""
Test if a function determining if a file is located inside a directory
or one of its subdirectories works properly.
"""
assert (
in_directory(file=Path(file), directory=Path(directory)) == exists_there
)
5 changes: 4 additions & 1 deletion tests/test_qg.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@

@pytest.fixture
def qg():
"""Provide non-deterministically initialized instance of the `QuestionGeneration` class."""
"""
Provide non-deterministically initialized instance of
the `QuestionGeneration` class.
"""
set_seed(0)
question_generation = QuestionGeneration()
return question_generation
Expand Down

0 comments on commit c558f05

Please sign in to comment.