From 5423e6817b737a5f3026c720ede2afabc6aa6454 Mon Sep 17 00:00:00 2001 From: PIETRO MARCHIORATO <120272502+pietromarchiorato@users.noreply.github.com> Date: Wed, 1 May 2024 21:52:09 +0200 Subject: [PATCH 1/4] Add Persistenza Embeddings e Relative Exceptions Aggiunta Persistenza Semplice degli Embeddings --- .../persistance/EmbeddingRepositoryAdapter.py | 29 ++++++++++++++----- backend/chatsql/utils/Exceptions.py | 15 ++++++++++ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/backend/chatsql/adapter/outcoming/persistance/EmbeddingRepositoryAdapter.py b/backend/chatsql/adapter/outcoming/persistance/EmbeddingRepositoryAdapter.py index 262fea6..b7f61b0 100644 --- a/backend/chatsql/adapter/outcoming/persistance/EmbeddingRepositoryAdapter.py +++ b/backend/chatsql/adapter/outcoming/persistance/EmbeddingRepositoryAdapter.py @@ -1,8 +1,9 @@ from typing import List - -from chatsql.application.port.outcoming.persistance.BaseEmbeddingRepository import BaseEmbeddingRepository - +import os +import numpy as np from chatsql.domain.Embedding import Embedding +from chatsql.application.port.outcoming.persistance.BaseEmbeddingRepository import BaseEmbeddingRepository +from chatsql.utils import Exceptions class EmbeddingRepositoryAdapter(BaseEmbeddingRepository): @@ -10,11 +11,25 @@ def __init__(self, folder: str) -> None: self._folder = folder def save(self, filename: str, embeddings: List[Embedding]) -> bool: - raise NotImplementedError() + try: + filepath = os.path.join(self._folder, filename) + np.save(filepath, embeddings) + return True + except Exception as e: + raise Exceptions.FileNotSaved(f"Error while saving embeddings to {filename}: {e}") def load(self, filename: str) -> List[Embedding]: - raise NotImplementedError() + try: + filepath = os.path.join(self._folder, filename) + embeddings = np.load(filepath, allow_pickle=True) + return embeddings.tolist() # Convert to list of Embedding objects + except Exception as e: + raise Exceptions.EmbeddingsNotLoaded(f"Error while loading embeddings from {filename}: {e}") def remove(self, filename: str) -> bool: - raise NotImplementedError() - \ No newline at end of file + try: + filepath = os.path.join(self._folder, filename) + os.remove(filepath) + return True + except Exception as e: + raise Exceptions.FileNotRemoved(f"Error while removing embeddings file {filename}: {e}. Check if permissions are correct.") diff --git a/backend/chatsql/utils/Exceptions.py b/backend/chatsql/utils/Exceptions.py index 662a213..1d45871 100644 --- a/backend/chatsql/utils/Exceptions.py +++ b/backend/chatsql/utils/Exceptions.py @@ -18,4 +18,19 @@ def __init__(self, message="Invalid file structure"): class FileAlreadyUploaded(CustomException): def __init__(self, message="File Already uploaded"): + super().__init__(message) + +class FileNotSaved(CustomException): + + def __init__(self, message="Error saving file"): + super().__init__(message) + +class EmbeddingsNotLoaded(CustomException): + + def __init__(self, message="Error during embeddings loading from file"): + super().__init__(message) + +class FileNotRemoved(CustomException): + + def __init__(self, message="Error removing file. Check if permissions are correct"): super().__init__(message) \ No newline at end of file From 46c6470607337cf76c1ab9e107f4cca651d6ad0f Mon Sep 17 00:00:00 2001 From: Vullnet Date: Wed, 1 May 2024 22:16:56 +0200 Subject: [PATCH 2/4] fix --- .github/workflows/backend.yaml | 47 +++++++++++++ .github/workflows/frontend.yaml | 61 +++++++++++++++++ .github/workflows/validate.yml | 83 ----------------------- __init__.py | 0 tests/__init__.py | 0 tests/backend/test_backend.py | 8 --- tests/{backend => }/test_jsonvalidator.py | 20 +++--- 7 files changed, 119 insertions(+), 100 deletions(-) create mode 100644 .github/workflows/backend.yaml create mode 100644 .github/workflows/frontend.yaml delete mode 100644 .github/workflows/validate.yml delete mode 100644 __init__.py delete mode 100644 tests/__init__.py delete mode 100644 tests/backend/test_backend.py rename tests/{backend => }/test_jsonvalidator.py (69%) diff --git a/.github/workflows/backend.yaml b/.github/workflows/backend.yaml new file mode 100644 index 0000000..d55e89c --- /dev/null +++ b/.github/workflows/backend.yaml @@ -0,0 +1,47 @@ +name: Backend build + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +permissions: + contents: read + +jobs: + build-backend: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Python 3.10 + uses: actions/setup-python@v3 + with: + python-version: "3.10" + + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 coverage + if [ -f requirements.txt ]; then + pip install -r requirements.txt; + fi + working-directory: "backend" + + - name: Linting Codice Python (Flake8) + run: | + flake8 backend/ --count --exit-zero --select=E9,F63,F7,F82 --show-source --max-line-length=127 --statistics + flake8 backend/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + + - name: Run Python tests and generate coverage report + run: | + coverage run -m unittest discover -s tests/ -p "test_*.py" + coverage xml -o tests/coverage.xml + + - name: Upload backend coverage report to Codecov + uses: codecov/codecov-action@v4.0.1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + file: tests/coverage.xml + flags: python + name: backend-coverage \ No newline at end of file diff --git a/.github/workflows/frontend.yaml b/.github/workflows/frontend.yaml new file mode 100644 index 0000000..9580a64 --- /dev/null +++ b/.github/workflows/frontend.yaml @@ -0,0 +1,61 @@ +name: Frontend + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +permissions: + contents: read + +jobs: + + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Installazione Node.js and NPM + uses: actions/setup-node@v2 + with: + node-version: '14' + + - name: Installazione Vue CLI + run: | + npm install -g @vue/cli + + - name: Installazione Dipendenze Bootstrap + run: | + npm install jquery popper.js + - name: Installazione Vue.js dependencies + run: | + cd frontend + npm install + + - name: Build FrontEnd + run: | + cd frontend + npm run build + + - name: Linting Codice Vue.js + run: | + cd frontend + npm run lint + + - name: Build Unit Test + run: | + cd frontend + npm run test:unit + + - name: Run Vue.js tests and generate coverage report + run: | + cd frontend + npx jest --coverage + + - name: Upload frontend coverage report to Codecov + uses: codecov/codecov-action@v4.0.1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + file: frontend/coverage/lcov.info + flags: frontend + name: frontend-coverage \ No newline at end of file diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml deleted file mode 100644 index 16b643a..0000000 --- a/.github/workflows/validate.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: Build - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -permissions: - contents: read - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - name: Set up Python 3.10 - uses: actions/setup-python@v3 - with: - python-version: "3.10" - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install flake8 coverage - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - - name: Run Python tests and generate coverage report - run: | - coverage run -m unittest - coverage xml -o tests/results/coverage.xml - - name: Installazione Node.js and NPM - uses: actions/setup-node@v2 - with: - node-version: '14' - - name: Installazione Vue CLI - run: | - npm install -g @vue/cli - - name: Installazione Dipendenze Bootstrap - run: | - npm install jquery popper.js - - name: Installazione Vue.js dependencies - run: | - cd frontend - npm install - cd .. - - name: Linting Codice Python (Flake8) - run: | - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - - name: Test Python - run: | - cd tests/backend - python -m unittest discover - cd .. - - name: Build Unit Test - run: | - cd frontend - npm run test:unit - - name: Run Vue.js tests and generate coverage report - run: | - cd frontend - npx jest --coverage - cd ../.. - - name: Build FrontEnd - run: | - cd frontend - npm run build - cd .. - - name: Linting Codice Vue.js - run: | - cd frontend - npm run lint - cd .. - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v4.0.1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - file: | - backend/coverage.xml - frontend/coverage/lcov.info # Aggiungi il percorso del report di copertura del frontend - flags: python,frontend # Flags opzionali, utili per separare i report di copertura - name: backend-coverage,frontend-coverage # Nomi opzionali, utili per separare i report di copertura diff --git a/__init__.py b/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/backend/test_backend.py b/tests/backend/test_backend.py deleted file mode 100644 index b60742e..0000000 --- a/tests/backend/test_backend.py +++ /dev/null @@ -1,8 +0,0 @@ -import unittest - -class TestEverythingWorking(unittest.TestCase): - def test_everything_working(self): - self.assertEqual(True, True) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/backend/test_jsonvalidator.py b/tests/test_jsonvalidator.py similarity index 69% rename from tests/backend/test_jsonvalidator.py rename to tests/test_jsonvalidator.py index 6aefe29..8b465c8 100644 --- a/tests/backend/test_jsonvalidator.py +++ b/tests/test_jsonvalidator.py @@ -1,7 +1,8 @@ -from backend.chatsql.utils.JSONValidator import JSONValidator # Assumi che JSONValidator sia nella stessa directory o importabile +import unittest +from unittest import TestCase +from backend.chatsql.utils.JSONValidator import JSONValidator -# Test di unità per JSONValidator -class TestJSONValidator: +class TestJSONValidator(TestCase): def test_is_valid_structure_valid(self): json_data = { "tables_info": { @@ -15,7 +16,7 @@ def test_is_valid_structure_valid(self): def test_is_valid_structure_invalid(self): # Test caso in cui mancano chiavi json_data_missing_keys = {"tables_info": {}, "primary_key": {}, "foreign_keys": {}} - assert JSONValidator.is_valid_structure(json_data_missing_keys) == False + TestCase.assertTrue(self, JSONValidator.is_valid_structure(json_data_missing_keys)) # Test caso in cui le tabelle non hanno tutte le informazioni necessarie json_data_invalid_tables_info = { @@ -23,7 +24,7 @@ def test_is_valid_structure_invalid(self): "primary_key": {"table1": ["column1"]}, "foreign_keys": [] } - assert JSONValidator.is_valid_structure(json_data_invalid_tables_info) == False + TestCase.assertFalse(self, JSONValidator.is_valid_structure(json_data_invalid_tables_info)) # Test caso in cui le chiavi primarie non sono correttamente strutturate json_data_invalid_primary_key = { @@ -31,14 +32,15 @@ def test_is_valid_structure_invalid(self): "primary_key": {"table1": "column1"}, "foreign_keys": [] } - assert JSONValidator.is_valid_structure(json_data_invalid_primary_key) == False - + TestCase.assertFalse(self, JSONValidator.is_valid_structure(json_data_invalid_primary_key)) + # Test caso in cui le chiavi esterne non sono correttamente strutturate json_data_invalid_foreign_keys = { "tables_info": {"table1": {"table_description": "Description", "columns": [], "attribute_types": []}}, "primary_key": {"table1": ["column1"]}, "foreign_keys": [{"table": "table1"}] } - assert JSONValidator.is_valid_structure(json_data_invalid_foreign_keys) == False + TestCase.assertFalse(self, JSONValidator.is_valid_structure(json_data_invalid_foreign_keys)) - # Aggiungi altri test per i metodi di validazione delle tabelle, delle chiavi primarie e delle chiavi esterne se necessario +if __name__ == '__main__': + unittest.main() From bf5e535e1b7b6489b72f8ae4f562d17b92219fa0 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 May 2024 16:11:19 +0200 Subject: [PATCH 3/4] Corretto e aggiunto test --- frontend/jest.config.js | 6 +- frontend/src/components/InputFile.vue | 16 +-- frontend/src/components/LoadButton.vue | 4 +- frontend/src/components/ToastPopup.vue | 76 ++++++------ .../sendrequestbutton.spec.js.snap | 10 -- .../viewgeneratedprompts.spec.js.snap | 65 ---------- frontend/tests/unit/inputfile.spec.js | 114 ++++++++++++------ frontend/tests/unit/loadbutton.spec.js | 6 +- frontend/tests/unit/redirectbutton.spec.js | 90 ++++---------- frontend/tests/unit/requestviewmodel.spec.js | 55 --------- frontend/tests/unit/toastpopup.spec.js | 20 +++ frontend/tests/unit/uploadbutton.spec.js | 40 ++++++ frontend/tests/unit/viewdictionary.spec.js | 114 ++++++++++++++---- 13 files changed, 293 insertions(+), 323 deletions(-) delete mode 100644 frontend/tests/unit/__snapshots__/sendrequestbutton.spec.js.snap delete mode 100644 frontend/tests/unit/__snapshots__/viewgeneratedprompts.spec.js.snap delete mode 100644 frontend/tests/unit/requestviewmodel.spec.js create mode 100644 frontend/tests/unit/toastpopup.spec.js create mode 100644 frontend/tests/unit/uploadbutton.spec.js diff --git a/frontend/jest.config.js b/frontend/jest.config.js index 98fe091..4853be3 100644 --- a/frontend/jest.config.js +++ b/frontend/jest.config.js @@ -12,5 +12,9 @@ module.exports = { // Directory dove Jest deve mettere i risultati della copertura coverageDirectory: '/coverage', - transformIgnorePatterns: ['node_modules/(?!(axios)/)'], + transformIgnorePatterns: [ + 'node_modules/(?!(axios)/)', + '/node_modules/(?!(bootstrap)/)', + '\\.css$' + ], } diff --git a/frontend/src/components/InputFile.vue b/frontend/src/components/InputFile.vue index f682073..7146969 100644 --- a/frontend/src/components/InputFile.vue +++ b/frontend/src/components/InputFile.vue @@ -4,7 +4,6 @@ -

{{ message }}

@@ -33,7 +32,6 @@ export default { * @property {ref} isUploading - A reference to a boolean indicating if the file is currently being uploaded. */ const file = ref(null); - const message = ref(' '); const isUploading = ref(false); /** @@ -43,7 +41,6 @@ export default { * @param {Event} event - The file upload event. */ function handleFileUpload(event) { - this.changeMessage(''); file.value = event.target.files[0]; } @@ -54,21 +51,12 @@ export default { * @emits file-selected - Event emitted when a file is selected */ function emitFile() { - if (file.value) { + if (file) { isUploading.value = true; emit('file-selected', file.value); } } - /** - * Updates the value of the message. - * - * @param {string} newMessage - The new message value. - */ - function changeMessage(newMessage) { - message.value = newMessage; - } - /** * Sets the value of the isUploading reactive variable. * @@ -81,10 +69,8 @@ export default { return { file, - message, handleFileUpload, emitFile, - changeMessage, isUploading, setIsUploading }; diff --git a/frontend/src/components/LoadButton.vue b/frontend/src/components/LoadButton.vue index e505090..a8ebf9f 100644 --- a/frontend/src/components/LoadButton.vue +++ b/frontend/src/components/LoadButton.vue @@ -33,8 +33,8 @@ export default { * * @param {number} id - The ID of the dictionary to load. */ - function loadDictionary(id) { - emit('load-click', id); + function loadDictionary() { + emit('load-click', props.id); } return { diff --git a/frontend/src/components/ToastPopup.vue b/frontend/src/components/ToastPopup.vue index 2fe9f82..e42f766 100644 --- a/frontend/src/components/ToastPopup.vue +++ b/frontend/src/components/ToastPopup.vue @@ -1,50 +1,52 @@ -