From 860d9b5da9ffb7dd53f315ace5f8dd99e5e25b09 Mon Sep 17 00:00:00 2001 From: Falko Habel Date: Sun, 9 Feb 2025 21:51:00 +0100 Subject: [PATCH 1/8] added vscode depending dependencies --- .vscode/c_cpp_properties.json | 19 +++++++++ .vscode/settings.json | 75 +++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/settings.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..774906b --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,19 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${workspaceFolder}/**", + "C:/Users/Falko/AppData/Local/Programs/Python/Python311/include", + "C:/Users/Falko/AppData/Local/Programs/Python/Python311/Lib/site-packages/pybind11/include" + ], + "defines": [], + "windowsSdkVersion": "10.0.19041.0", + "compilerPath": "cl.exe", + "cStandard": "c17", + "cppStandard": "c++17", + "intelliSenseMode": "windows-msvc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5dc5c07 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,75 @@ +{ + "files.associations": { + "*.py": "python", + "algorithm": "cpp", + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "cctype": "cpp", + "charconv": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "compare": "cpp", + "concepts": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "exception": "cpp", + "filesystem": "cpp", + "format": "cpp", + "forward_list": "cpp", + "functional": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "ios": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "iterator": "cpp", + "limits": "cpp", + "list": "cpp", + "locale": "cpp", + "memory": "cpp", + "mutex": "cpp", + "new": "cpp", + "optional": "cpp", + "ostream": "cpp", + "ratio": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "string": "cpp", + "system_error": "cpp", + "thread": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "utility": "cpp", + "vector": "cpp", + "xfacet": "cpp", + "xhash": "cpp", + "xiosbase": "cpp", + "xlocale": "cpp", + "xlocbuf": "cpp", + "xlocinfo": "cpp", + "xlocmes": "cpp", + "xlocmon": "cpp", + "xlocnum": "cpp", + "xloctime": "cpp", + "xmemory": "cpp", + "xstring": "cpp", + "xtr1common": "cpp", + "xutility": "cpp", + "fstream": "cpp", + "iostream": "cpp", + "codecvt": "cpp" + } +} \ No newline at end of file From b84115ce34859a86788b0d161158d7a78e19b41b Mon Sep 17 00:00:00 2001 From: Falko Habel Date: Sun, 9 Feb 2025 21:52:15 +0100 Subject: [PATCH 2/8] added testing files --- tests/__init__.py | 0 tests/functions/test_simple_functions.py | 0 tests/test__main__.py | 0 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/__init__.py create mode 100644 tests/functions/test_simple_functions.py create mode 100644 tests/test__main__.py diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/functions/test_simple_functions.py b/tests/functions/test_simple_functions.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test__main__.py b/tests/test__main__.py new file mode 100644 index 0000000..e69de29 From 8c74e60f548ba8217c7aab42884ed0db652556ce Mon Sep 17 00:00:00 2001 From: Falko Habel Date: Sun, 9 Feb 2025 21:53:03 +0100 Subject: [PATCH 3/8] basic functionallity for is odd/even --- example.py | 3 ++ pyproject.toml | 12 +++++++ setup.py | 30 ++++++++++++++++ src/fabelous_math/__init__.py | 3 ++ src/fabelous_math/__main__.py | 0 src/fabelous_math/cpp/functions/bindings.cpp | 36 +++++++++++++++++++ .../cpp/functions/simple_functions.cpp | 11 ++++++ .../include/simple_functions.hpp | 6 ++++ 8 files changed, 101 insertions(+) create mode 100644 example.py create mode 100644 pyproject.toml create mode 100644 setup.py create mode 100644 src/fabelous_math/__init__.py create mode 100644 src/fabelous_math/__main__.py create mode 100644 src/fabelous_math/cpp/functions/bindings.cpp create mode 100644 src/fabelous_math/cpp/functions/simple_functions.cpp create mode 100644 src/fabelous_math/include/simple_functions.hpp diff --git a/example.py b/example.py new file mode 100644 index 0000000..ee0f1ff --- /dev/null +++ b/example.py @@ -0,0 +1,3 @@ +from fabelous_math import is_even, is_odd + +print(is_even(5)) \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..91c3f0e --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,12 @@ +[build-system] +requires = ["setuptools>=42", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "fabelous_math" +version = "0.0.1" +description = "Math functions written in C++ for faster code" +authors = [ + {name = "Falko Habel", email = "falko.habel@fabelous.app"} +] +requires-python = ">=3.7" diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..c59254f --- /dev/null +++ b/setup.py @@ -0,0 +1,30 @@ +from setuptools import setup, Extension +import platform + +extra_compile_args = [] +extra_link_args = [] + +# Set C++17 flag based on the compiler +if platform.system() == "Windows": + extra_compile_args.append('/std:c++17') +else: + extra_compile_args.append('-std=c++17') + +module = Extension( + 'fabelous_math.simple_functions', + sources=[ + 'src/fabelous_math/cpp/functions/simple_functions.cpp', + 'src/fabelous_math/cpp/functions/bindings.cpp' + ], + include_dirs=['src/fabelous_math/include'], + extra_compile_args=extra_compile_args, + extra_link_args=extra_link_args, +) + +setup( + name='fabelous_math', + description='Math functions written in C++ for faster code', + ext_modules=[module], + author="Falko Habel", + author_email="falko.habel@fabelous.app" +) \ No newline at end of file diff --git a/src/fabelous_math/__init__.py b/src/fabelous_math/__init__.py new file mode 100644 index 0000000..40c1e47 --- /dev/null +++ b/src/fabelous_math/__init__.py @@ -0,0 +1,3 @@ +from fabelous_math.simple_functions import is_even, is_odd + +__all__ = ["is_even", "is_odd"] \ No newline at end of file diff --git a/src/fabelous_math/__main__.py b/src/fabelous_math/__main__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/fabelous_math/cpp/functions/bindings.cpp b/src/fabelous_math/cpp/functions/bindings.cpp new file mode 100644 index 0000000..aef16dc --- /dev/null +++ b/src/fabelous_math/cpp/functions/bindings.cpp @@ -0,0 +1,36 @@ +#include +#include "simple_functions.hpp" + +static PyObject* is_even_wrapper(PyObject* self, PyObject* args) { + long long number; + if (!PyArg_ParseTuple(args, "L", &number)) { + return NULL; + } + return PyBool_FromLong(simple_functions::is_even(number)); +} + +static PyObject* is_odd_wrapper(PyObject* self, PyObject* args) { + long long number; + if (!PyArg_ParseTuple(args, "L", &number)) { + return NULL; + } + return PyBool_FromLong(simple_functions::is_odd(number)); +} + +static PyMethodDef NumberUtilsMethods[] = { + {"is_even", is_even_wrapper, METH_VARARGS, "Check if a number is even"}, + {"is_odd", is_odd_wrapper, METH_VARARGS, "Check if a number is odd"}, + {NULL, NULL, 0, NULL} +}; + +static struct PyModuleDef number_utils_module = { + PyModuleDef_HEAD_INIT, + "simple_functions", + "Module for checking if numbers are even or odd", + -1, + NumberUtilsMethods +}; + +PyMODINIT_FUNC PyInit_simple_functions(void) { + return PyModule_Create(&number_utils_module); +} \ No newline at end of file diff --git a/src/fabelous_math/cpp/functions/simple_functions.cpp b/src/fabelous_math/cpp/functions/simple_functions.cpp new file mode 100644 index 0000000..6638dae --- /dev/null +++ b/src/fabelous_math/cpp/functions/simple_functions.cpp @@ -0,0 +1,11 @@ +#include "simple_functions.hpp" + +namespace simple_functions { + bool is_even(long long number) { + return (number & 1) == 0; + } + + bool is_odd(long long number) { + return (number & 1) == 1; + } +} \ No newline at end of file diff --git a/src/fabelous_math/include/simple_functions.hpp b/src/fabelous_math/include/simple_functions.hpp new file mode 100644 index 0000000..4678dd8 --- /dev/null +++ b/src/fabelous_math/include/simple_functions.hpp @@ -0,0 +1,6 @@ +#pragma once + +namespace simple_functions { + bool is_even(long long number); + bool is_odd(long long number); +} \ No newline at end of file From 4d6684d4b6a50acb0e82365a3a9b1d1d08e74b3a Mon Sep 17 00:00:00 2001 From: Falko Habel Date: Mon, 10 Feb 2025 17:05:59 +0100 Subject: [PATCH 4/8] improved performance --- example.py | 3 ++- src/fabelous_math/__main__.py | 0 src/fabelous_math/cpp/functions/simple_functions.cpp | 4 ++-- tests/functions/test_simple_functions.py | 0 tests/test__main__.py | 0 5 files changed, 4 insertions(+), 3 deletions(-) delete mode 100644 src/fabelous_math/__main__.py delete mode 100644 tests/functions/test_simple_functions.py delete mode 100644 tests/test__main__.py diff --git a/example.py b/example.py index ee0f1ff..c9b0ffc 100644 --- a/example.py +++ b/example.py @@ -1,3 +1,4 @@ from fabelous_math import is_even, is_odd -print(is_even(5)) \ No newline at end of file +print(is_even(5)) +print(is_odd(19)) \ No newline at end of file diff --git a/src/fabelous_math/__main__.py b/src/fabelous_math/__main__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/fabelous_math/cpp/functions/simple_functions.cpp b/src/fabelous_math/cpp/functions/simple_functions.cpp index 6638dae..4d5ecab 100644 --- a/src/fabelous_math/cpp/functions/simple_functions.cpp +++ b/src/fabelous_math/cpp/functions/simple_functions.cpp @@ -2,10 +2,10 @@ namespace simple_functions { bool is_even(long long number) { - return (number & 1) == 0; + return (number & 1) == 0; } bool is_odd(long long number) { - return (number & 1) == 1; + return (number & 1); } } \ No newline at end of file diff --git a/tests/functions/test_simple_functions.py b/tests/functions/test_simple_functions.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test__main__.py b/tests/test__main__.py deleted file mode 100644 index e69de29..0000000 From 39661bf788e7c22a6a3053c2fd10f7579e79784b Mon Sep 17 00:00:00 2001 From: Falko Habel Date: Mon, 10 Feb 2025 18:13:33 +0100 Subject: [PATCH 5/8] added documentation --- README.md | 73 ++++++++++++++++++++++++++++++- docs/high_numbers_comparison.png | Bin 0 -> 52354 bytes docs/low_numbers_comparison.png | Bin 0 -> 55813 bytes 3 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 docs/high_numbers_comparison.png create mode 100644 docs/low_numbers_comparison.png diff --git a/README.md b/README.md index 5ba9681..f7e1609 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,72 @@ -# fabelous-math +# Fabelous Math -Python addtional math libary \ No newline at end of file +Fabelous Math is a simple library designed to provide basic mathematical functions, saving you the trouble of writing these common utilities repeatedly. This library includes essential functions like checking if a number is even or odd. + +## Installation + +You can easily install `fabelous-math` using pip: + +```sh +pip install https://gitea.fabelous.app/Fabel/fabelous-math.git +``` + +## Usage + +### Python + +To use the functions provided by Fabelous Math in your Python code, you can import them as follows: + +```python +from fabelous_math import is_even, is_odd + +# Example usage: +number = 42 +print(f"Is {number} even? {is_even(number)}") +print(f"Is {number} odd? {is_odd(number)}") +``` + +## Functions + +### `is_even` + +Checks if a given number is even. + +- **Python:** + ```python + def is_even(number: int) -> bool: + pass + ``` + +- **C++:** + ```cpp + namespace simple_functions { + bool is_even(long long number); + } + ``` + +### `is_odd` + +Checks if a given number is odd. + +- **Python:** + ```python + def is_odd(number: int) -> bool: + pass + ``` + +- **C++:** + ```cpp + namespace simple_functions { + bool is_odd(long long number); + } + ``` +## Performance Comparison + +To understand the performance of `fabelous-math` functions, I conducted a series of tests comparing my methods with traditional modulo operations. Below are the results: + +### Low Numbers Performance: +![Low Numbers Performance](docs/low_numbers_comparison.png) + + +### High Numbers Performance: +![High Numbers Performance](docs/high_numbers_comparison.png) diff --git a/docs/high_numbers_comparison.png b/docs/high_numbers_comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..3fb7d96a460890a98d08f2a833d996a6c499e7bc GIT binary patch literal 52354 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 literal 0 HcmV?d00001 diff --git a/docs/low_numbers_comparison.png b/docs/low_numbers_comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..55729bd54bd2a0a7bfd4a1bd55e75cd679d15e66 GIT binary patch literal 55813 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%0A!h+ryezKJb8V_OJ)&|*phNgFhiQ3@X{)<0jS*R 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 O>ra?5K6LDYAO06NZ=ELq literal 0 HcmV?d00001 From 25e0d4d72d7645c98eeced6ea56eb52f2527f0e7 Mon Sep 17 00:00:00 2001 From: Falko Habel Date: Mon, 10 Feb 2025 18:13:54 +0100 Subject: [PATCH 6/8] added tests --- pytest.ini | 2 + requirements.txt | 2 + result.py | 138 +++++++++++++++++++++++ tests/functions/__init__.py | 0 tests/functions/test_simple_functions.py | 62 ++++++++++ 5 files changed, 204 insertions(+) create mode 100644 pytest.ini create mode 100644 requirements.txt create mode 100644 result.py create mode 100644 tests/functions/__init__.py create mode 100644 tests/functions/test_simple_functions.py diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..5ee6477 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +testpaths = tests diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..0002b62 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +pytest +pytest-cpp \ No newline at end of file diff --git a/result.py b/result.py new file mode 100644 index 0000000..3dedc1a --- /dev/null +++ b/result.py @@ -0,0 +1,138 @@ +import timeit +import random +import statistics +import matplotlib.pyplot as plt +import numpy as np +from fabelous_math import is_even, is_odd + +def generate_test_numbers(count: int, min_val: int, max_val: int): + return random.sample(range(min_val, max_val), count) + +def run_benchmark(numbers, func, iterations=100): + times = [] + for _ in range(iterations): + start_time = timeit.default_timer() + for num in numbers: + func(num) + end_time = timeit.default_timer() + times.append(end_time - start_time) + return times + +def create_visualization(results, title): + # Prepare data + methods = list(results.keys()) + means = [statistics.mean(times) * 1000 for times in results.values()] # Convert to milliseconds + stds = [statistics.stdev(times) * 1000 for times in results.values()] # Convert to milliseconds + + # Create figure with two subplots + fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10), height_ratios=[2, 1]) + fig.suptitle(title, fontsize=14) + plt.subplots_adjust(top=0.9) # Adjust spacing for title + + # Bar plot + x = np.arange(len(methods)) + width = 0.35 + bars = ax1.bar(x, means, width, yerr=stds, capsize=5) + + # Customize bar plot + ax1.set_ylabel('Time (milliseconds)') + ax1.set_xticks(x) + ax1.set_xticklabels(methods, rotation=0) + ax1.grid(True, axis='y', linestyle='--', alpha=0.7) + + # Add value labels on bars + for bar in bars: + height = bar.get_height() + ax1.text(bar.get_x() + bar.get_width()/2., height, + f'{height:.3f}ms', + ha='center', va='bottom') + + # Create table + cell_text = [] + for method, times in results.items(): + mean_time = statistics.mean(times) * 1000 + std_dev = statistics.stdev(times) * 1000 + min_time = min(times) * 1000 + max_time = max(times) * 1000 + + cell_text.append([ + method, + f"{mean_time:.3f}", + f"{std_dev:.3f}", + f"{min_time:.3f}", + f"{max_time:.3f}" + ]) + + # Add table + ax2.axis('tight') + ax2.axis('off') + columns = ['Method', 'Mean (ms)', 'Std Dev (ms)', 'Min (ms)', 'Max (ms)'] + table = ax2.table(cellText=cell_text, + colLabels=columns, + loc='center', + cellLoc='center') + + # Adjust table appearance + table.auto_set_font_size(False) + table.set_fontsize(9) + table.scale(1.2, 1.5) + + plt.tight_layout() + return plt + +def main(): + # Test parameters + SAMPLE_SIZE = 5000 + LOW_RANGE = (1, 10000000) + HIGH_RANGE = (1000000000000, 1000000010000000) + ITERATIONS = 100 + + print(f"Running benchmarks with {SAMPLE_SIZE} numbers, {ITERATIONS} iterations each...") + + # Generate test numbers + low_numbers = generate_test_numbers(SAMPLE_SIZE, *LOW_RANGE) + high_numbers = generate_test_numbers(SAMPLE_SIZE, *HIGH_RANGE) + + # Run benchmarks for low numbers + print("\nTesting low numbers...") + low_results = { + 'Fabelous Even': run_benchmark(low_numbers, is_even, ITERATIONS), + 'Fabelous Odd': run_benchmark(low_numbers, is_odd, ITERATIONS), + 'Modulo Even': run_benchmark(low_numbers, lambda x: x % 2 == 0, ITERATIONS), + 'Modulo Odd': run_benchmark(low_numbers, lambda x: x % 2 == 1, ITERATIONS) + } + + # Run benchmarks for high numbers + print("Testing high numbers...") + high_results = { + 'Fabelous Even': run_benchmark(high_numbers, is_even, ITERATIONS), + 'Fabelous Odd': run_benchmark(high_numbers, is_odd, ITERATIONS), + 'Modulo Even': run_benchmark(high_numbers, lambda x: x % 2 == 0, ITERATIONS), + 'Modulo Odd': run_benchmark(high_numbers, lambda x: x % 2 == 1, ITERATIONS) + } + + # Create and save visualizations + print("\nGenerating visualizations...") + plt_low = create_visualization(low_results, 'Performance Comparison - Low Numbers') + plt_low.savefig('low_numbers_comparison.png') + plt_low.show() + + plt_high = create_visualization(high_results, 'Performance Comparison - High Numbers') + plt_high.savefig('high_numbers_comparison.png') + plt_high.show() + + # Print summary + print("\nSummary of Findings:") + print("-------------------") + print("1. Low Numbers Performance:") + for method, times in low_results.items(): + mean_time = statistics.mean(times) * 1000 + print(f" - {method}: {mean_time:.3f}ms average") + + print("\n2. High Numbers Performance:") + for method, times in high_results.items(): + mean_time = statistics.mean(times) * 1000 + print(f" - {method}: {mean_time:.3f}ms average") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/tests/functions/__init__.py b/tests/functions/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/functions/test_simple_functions.py b/tests/functions/test_simple_functions.py new file mode 100644 index 0000000..1463747 --- /dev/null +++ b/tests/functions/test_simple_functions.py @@ -0,0 +1,62 @@ +import pytest +from fabelous_math import is_even, is_odd + +def test_is_even(): + # Test positive even numbers + assert is_even(0) == True + assert is_even(2) == True + assert is_even(4) == True + assert is_even(100) == True + + # Test positive odd numbers + assert is_even(1) == False + assert is_even(3) == False + assert is_even(99) == False + + # Test negative even numbers + assert is_even(-2) == True + assert is_even(-4) == True + assert is_even(-100) == True + + # Test negative odd numbers + assert is_even(-1) == False + assert is_even(-3) == False + assert is_even(-99) == False + + # Test large numbers + assert is_even(1000000) == True + assert is_even(-1000001) == False + +def test_is_odd(): + # Test positive odd numbers + assert is_odd(1) == True + assert is_odd(3) == True + assert is_odd(99) == True + + # Test positive even numbers + assert is_odd(0) == False + assert is_odd(2) == False + assert is_odd(4) == False + assert is_odd(100) == False + + # Test negative odd numbers + assert is_odd(-1) == True + assert is_odd(-3) == True + assert is_odd(-99) == True + + # Test negative even numbers + assert is_odd(-2) == False + assert is_odd(-4) == False + assert is_odd(-100) == False + + # Test large numbers + assert is_odd(1000001) == True + assert is_odd(-1000000) == False + +def test_is_even_is_odd_complementary(): + # Ensure is_even and is_odd are complementary for various numbers + test_numbers = [0, 1, -1, 2, -2, 99, -99, 1000000, -1000001] + + for num in test_numbers: + assert is_even(num) != is_odd(num), \ + f"Failed for number {num}: is_even and is_odd should be opposite" \ No newline at end of file From da4c8233dd1edb0c0be35e340741c9119edeb6f7 Mon Sep 17 00:00:00 2001 From: Falko Habel Date: Mon, 10 Feb 2025 18:15:07 +0100 Subject: [PATCH 7/8] added yaml configs --- .gitea/workflows/embed.yaml | 37 +++++++++++++++++++++++++++++++++++++ .gitea/workflows/test.yaml | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 .gitea/workflows/embed.yaml create mode 100644 .gitea/workflows/test.yaml diff --git a/.gitea/workflows/embed.yaml b/.gitea/workflows/embed.yaml new file mode 100644 index 0000000..2a0d240 --- /dev/null +++ b/.gitea/workflows/embed.yaml @@ -0,0 +1,37 @@ +name: Run VectorLoader Script + +on: + push: + branches: + - main + +jobs: + Explore-Gitea-Actions: + runs-on: ubuntu-latest + container: catthehacker/ubuntu:act-latest + steps: + - name: Check out repository code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: '3.11.7' + + - name: Clone additional repository + run: | + git config --global credential.helper cache + git clone https://fabel:${{ secrets.CICD }}@gitea.fabelous.app/fabel/VectorLoader.git + + - name: Install dependencies + run: | + cd VectorLoader + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run vectorizing + env: + VECTORDB_TOKEN: ${{ secrets.VECTORDB_TOKEN }} + run: | + cd VectorLoader + python -m src.run --full diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml new file mode 100644 index 0000000..4e8d7b4 --- /dev/null +++ b/.gitea/workflows/test.yaml @@ -0,0 +1,36 @@ +name: Gitea Actions For Fabelous-Math +run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀 +on: [push] + +jobs: + Explore-Gitea-Actions: + runs-on: ubuntu-latest + container: catthehacker/ubuntu:act-latest + steps: + - name: Check out repository code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11.7' + + - name: Cache pip and model + uses: actions/cache@v3 + with: + path: | + ~/.cache/pip + ./fabel + key: ${{ runner.os }}-pip-model-${{ hashFiles('requirements-dev.txt')}} + + restore-keys: | + ${{ runner.os }}-pip-model- + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements-dev.txt + - name: Run tests + run: | + pip install -e . + pytest tests \ No newline at end of file From 8e027a05c45e162fba731bc9997f156022fe417c Mon Sep 17 00:00:00 2001 From: Falko Habel Date: Mon, 10 Feb 2025 18:20:23 +0100 Subject: [PATCH 8/8] loaded correct requirements --- requirements.txt => requirements-dev.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename requirements.txt => requirements-dev.txt (100%) diff --git a/requirements.txt b/requirements-dev.txt similarity index 100% rename from requirements.txt rename to requirements-dev.txt