From 258843536d8505baa95bb2071726fbbfc0cf3433 Mon Sep 17 00:00:00 2001 From: quentinformatique Date: Mon, 19 May 2025 13:41:23 +0200 Subject: [PATCH 1/4] feat: add exmeple images --- tests/images/back.png | Bin 0 -> 6594 bytes tests/images/down.png | Bin 0 -> 6586 bytes tests/images/front.png | Bin 0 -> 7018 bytes tests/images/left.png | Bin 0 -> 6705 bytes tests/images/right.png | Bin 0 -> 6908 bytes tests/images/up.png | Bin 0 -> 6525 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/images/back.png create mode 100644 tests/images/down.png create mode 100644 tests/images/front.png create mode 100644 tests/images/left.png create mode 100644 tests/images/right.png create mode 100644 tests/images/up.png diff --git a/tests/images/back.png b/tests/images/back.png new file mode 100644 index 0000000000000000000000000000000000000000..6160782b4082bf2f0c9c4df1bdd211a8a57e100e GIT binary patch literal 6594 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 M+gJ;)dF%c^0LnFQ-2eap literal 0 HcmV?d00001 diff --git a/tests/images/down.png b/tests/images/down.png new file mode 100644 index 0000000000000000000000000000000000000000..a65761dc5fe34faf38e4a0c0166d1e12ab1793cc GIT binary patch literal 6586 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 literal 0 HcmV?d00001 diff --git a/tests/images/front.png b/tests/images/front.png new file mode 100644 index 0000000000000000000000000000000000000000..47c14cc716b1328437fbcd4852442e100cce4d7b GIT binary patch literal 7018 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 literal 0 HcmV?d00001 diff --git a/tests/images/left.png b/tests/images/left.png new file mode 100644 index 0000000000000000000000000000000000000000..13f86009358fc825298582f6dcd09a268774bc41 GIT binary patch literal 6705 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 E2O?2}bpQYW literal 0 HcmV?d00001 diff --git a/tests/images/right.png b/tests/images/right.png new file mode 100644 index 0000000000000000000000000000000000000000..2de6b8f0d7778ec5440375b95620f2f13290b1fd GIT binary patch literal 6908 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 literal 0 HcmV?d00001 diff --git a/tests/images/up.png b/tests/images/up.png new file mode 100644 index 0000000000000000000000000000000000000000..e6e680c00fc3d9cd2b17569e0a06dc587b199805 GIT binary patch literal 6525 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 literal 0 HcmV?d00001 From e8c3469ac37430442b7b47ce3b43d8e3c2e66d2c Mon Sep 17 00:00:00 2001 From: quentinformatique Date: Mon, 19 May 2025 13:41:37 +0200 Subject: [PATCH 2/4] fix(tests): add manual script to test API --- tests/manual/test_api.py | 45 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 tests/manual/test_api.py diff --git a/tests/manual/test_api.py b/tests/manual/test_api.py new file mode 100644 index 0000000..abde09a --- /dev/null +++ b/tests/manual/test_api.py @@ -0,0 +1,45 @@ +import requests +import os + +def test_api(): + url = 'http://localhost:5000/cubeFacesToCubeString' + + image_files = [ + 'tests/images/up.png', + 'tests/images/right.png', + 'tests/images/front.png', + 'tests/images/down.png', + 'tests/images/left.png', + 'tests/images/back.png' + ] + + for img_file in image_files: + if not os.path.exists(img_file): + print(f"Erreur: Le fichier {img_file} n'existe pas") + return + + files = [] + for img_file in image_files: + files.append(('images', (os.path.basename(img_file), open(img_file, 'rb'), 'image/png'))) + + try: + response = requests.post(url, files=files) + + if response.status_code == 200: + result = response.json() + print("Succès! Réponse de l'API:") + print(f"Cube string: {result.get('cube_string')}") + else: + print(f"Erreur: {response.status_code}") + print(response.text) + + except requests.exceptions.RequestException as e: + print(f"Erreur de connexion: {e}") + assert False, f"API connection failed: {e}" + + finally: + for _, (_, file, _) in files: + file.close() + +if __name__ == '__main__': + test_api() \ No newline at end of file From 7c2e077f6048e93d06e68cacb1a96b9aacfeb8c6 Mon Sep 17 00:00:00 2001 From: quentinformatique Date: Mon, 19 May 2025 13:41:46 +0200 Subject: [PATCH 3/4] fix: running context --- .dockerignore | 46 +++++++++++++++++++++++++++++++++++++++++ Dockerfile | 15 +++++++++++--- app/cube_recognition.py | 4 ---- app/routes.py | 4 ++++ run.py | 2 +- 5 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0681275 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,46 @@ +# Git +.git +.gitignore + +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# Virtual Environment +venv/ +ENV/ + +# IDE +.idea/ +.vscode/ +*.swp +*.swo + +# Docker +Dockerfile +.dockerignore + +# Logs +*.log + +# Local development +.env +.env.local \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 586cdfe..df74a89 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,12 +4,21 @@ FROM python:3.11-slim # Set working directory WORKDIR /app -# Copy project files -COPY . . +# Install system dependencies required for OpenCV +RUN apt-get update && apt-get install -y \ + libgl1-mesa-glx \ + libglib2.0-0 \ + && rm -rf /var/lib/apt/lists/* + +# Copy only requirements first to leverage Docker cache +COPY requirements.txt . -# Install dependencies +# Install Python dependencies RUN pip install --no-cache-dir -r requirements.txt +# Copy the rest of the application +COPY . . + # Expose the port the app runs on EXPOSE 5000 diff --git a/app/cube_recognition.py b/app/cube_recognition.py index 855c059..608b06f 100644 --- a/app/cube_recognition.py +++ b/app/cube_recognition.py @@ -2,10 +2,6 @@ import numpy as np from .color_detection import detect_colors -# Rubik's cube face labels in standard order -FACE_ORDER = ['U', 'R', 'F', 'D', 'L', 'B'] - - def generate_cube_string(images): cube_string = '' diff --git a/app/routes.py b/app/routes.py index 5098a2b..768c82d 100644 --- a/app/routes.py +++ b/app/routes.py @@ -3,6 +3,10 @@ main = Blueprint('main', __name__) +@main.route('/', methods=['GET']) +def health_check(): + return jsonify({'status': 'API is running'}), 200 + @main.route('/cubeFacesToCubeString', methods=['POST']) def upload_faces(): if 'images' not in request.files: diff --git a/run.py b/run.py index a3fdaf3..8640e59 100644 --- a/run.py +++ b/run.py @@ -3,4 +3,4 @@ app = create_app() if __name__ == '__main__': - app.run(debug=True) + app.run(host='0.0.0.0', debug=True) From ce2676e9d65152227f0389ebccaf6df017322d53 Mon Sep 17 00:00:00 2001 From: quentinformatique Date: Mon, 19 May 2025 14:14:44 +0200 Subject: [PATCH 4/4] fix: ignore manual tests in CI and Makefile --- .github/workflows/ci.yml | 2 +- Makefile | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 68b389a..acdfed8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,4 +29,4 @@ jobs: - name: Run tests run: | - pytest tests/ \ No newline at end of file + pytest tests/ --ignore=tests/manual \ No newline at end of file diff --git a/Makefile b/Makefile index 7de0b27..27a0ee8 100644 --- a/Makefile +++ b/Makefile @@ -8,13 +8,13 @@ train: python app/model/train_color_model.py test: - pytest tests/ + pytest tests/ --ignore=tests/manual coverage: - coverage run -m pytest tests/ + coverage run -m pytest tests/ --ignore=tests/manual coverage report coverage html docker-test: docker build -t rubik-api . - docker run --rm rubik-api pytest tests/ + docker run --rm rubik-api pytest tests/ --ignore=tests/manual