diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000..f63ba2e --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,11 @@ +documentation: +- changed-files: + - any-glob-to-any-file: ['doc/source/**/*', 'README.md'] + +maintenance: +- changed-files: + - any-glob-to-any-file: ['.github/**/*', 'pyproject.toml', '.pre-commit-config.yaml'] + +testing: +- changed-files: + - any-glob-to-any-file: ['tests/*'] diff --git a/.github/labels.yml b/.github/labels.yml new file mode 100644 index 0000000..b24d889 --- /dev/null +++ b/.github/labels.yml @@ -0,0 +1,44 @@ +- name: bug + description: Something isn't working + color: d42a34 + +- name: dependencies + description: Related with project dependencies + color: ffc0cb + +- name: documentation + description: Improvements or additions to documentation + color: 0677ba + +- name: enhancement + description: New features or code improvements + color: FFD827 + +- name: good first issue + description: Easy to solve for newcomers + color: 62ca50 + +- name: maintenance + description: Package and maintenance related + color: f78c37 + +- name: release + description: Anything related to an incoming release + color: ffffff + +- name: testing + description: Anything related to testing + color: 5802B8 + +- name: graphics + description: Anything related to graphics + color: 5903A8 + +- name: triage + description: Need some assessment + color: f78a50 + +- name: top priority + description: Must be fixed promptly + color: ab8a50 + diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index ab53757..36a385c 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -9,6 +9,8 @@ on: env: MAIN_PYTHON_VERSION: '3.12' + DOCUMENTATION_CNAME: expert-adventure-nvnoo1y.pages.github.io + PACKAGE_NAME: allie-flowkit-python concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -24,38 +26,75 @@ jobs: runs-on: ubuntu-latest steps: - name: "Run PyAnsys code style checks" - uses: ansys/actions/code-style@v6 + uses: ansys/actions/code-style@v7 + + smoke-tests: + name: Build and Smoke tests + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + python-version: ['3.10', '3.11', '3.12'] + should-release: + - ${{ github.event_name == 'push' && contains(github.ref, 'refs/tags') }} + exclude: + - should-release: false + os: macos-latest + steps: + - name: Build wheelhouse and perform smoke test + uses: ansys/actions/build-wheelhouse@v7 + with: + library-name: ${{ env.PACKAGE_NAME }} + operating-system: ${{ matrix.os }} + python-version: ${{ matrix.python-version }} + + docs-style: + name: Documentation Style Check + runs-on: ubuntu-latest + steps: + - name: PyAnsys documentation style checks + uses: ansys/actions/doc-style@v7 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + docs-build: + name: Documentation Build + runs-on: ubuntu-latest + needs: [docs-style] + steps: + + - name: "Run Ansys documentation building action" + uses: ansys/actions/doc-build@v7 + with: + add-pdf-html-docs-as-assets: true + + upload_dev_docs: + name: Upload dev documentation + if: github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + needs: [docs-build] + steps: + - name: Deploy the latest documentation + uses: ansys/actions/doc-deploy-dev@v7 + with: + cname: ${{ env.DOCUMENTATION_CNAME }} + token: ${{ secrets.GITHUB_TOKEN }} tests: name: "Tests" runs-on: ${{ matrix.os }} - needs: [code-style] + needs: [smoke-tests] strategy: matrix: os: [ubuntu-latest, windows-latest] python-version: ['3.9', '3.12'] fail-fast: false steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - name: Testing - uses: ansys/actions/tests-pytest@v6 + uses: ansys/actions/tests-pytest@v7 timeout-minutes: 12 - with: - checkout: false - skip-install: true - pytest-extra-args: "--cov=ansys.allie.flowkit.python --cov-report=term --cov-report=html:.cov/html --cov-report=xml:.cov/coverage.xml" - name: Upload coverage results (HTML) uses: actions/upload-artifact@v4 @@ -68,7 +107,7 @@ jobs: release: name: "Release project" if: github.event_name == 'push' && contains(github.ref, 'refs/tags') - needs: [code-style] + needs: [docs-build, tests] runs-on: ubuntu-latest steps: - name: Checkout code @@ -79,6 +118,19 @@ jobs: with: generate_release_notes: true + upload_docs_release: + name: Upload release documentation + if: github.event_name == 'push' && contains(github.ref, 'refs/tags') + runs-on: ubuntu-latest + needs: [release] + steps: + - name: Deploy the stable documentation + uses: ansys/actions/doc-deploy-stable@v7 + with: + cname: ${{ env.DOCUMENTATION_CNAME }} + token: ${{ secrets.GITHUB_TOKEN }} + + release-docker: name : Generate Docker release if: github.event_name == 'push' && contains(github.ref, 'refs/tags') diff --git a/.gitignore b/.gitignore index abaf5ac..2453a3e 100644 --- a/.gitignore +++ b/.gitignore @@ -40,4 +40,8 @@ dist/ config.yaml # Do not ignore config.yaml in the configs/ directory -!configs/config.yaml \ No newline at end of file +!configs/config.yaml + +# Docs +doc/_build/ +doc/source/api/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9e58958..074ca48 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,29 +1,12 @@ repos: -- repo: https://github.com/psf/black - rev: 23.12.1 +- repo: https://github.com/adamchainz/blacken-docs + rev: 1.18.0 hooks: - - id: black - -- repo: https://github.com/pycqa/isort - rev: 5.13.2 - hooks: - - id: isort - -- repo: https://github.com/PyCQA/flake8 - rev: 6.1.0 - hooks: - - id: flake8 - -- repo: https://github.com/pycqa/pydocstyle - rev: 6.3.0 - hooks: - - id: pydocstyle - args: ["--ignore=D205,D100,D213,D203"] - exclude: examples - additional_dependencies: [toml] + - id: blacken-docs + additional_dependencies: [black==23.12.1] - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: check-merge-conflict - id: debug-statements @@ -31,6 +14,22 @@ repos: - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.27.3 + rev: 0.29.1 + hooks: + - id: check-github-workflows + + +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.5.7 + hooks: + - id: ruff + args: [--fix] + - id: ruff-format + +- repo: https://github.com/ansys/pre-commit-hooks + rev: v0.4.3 hooks: - - id: check-github-workflows \ No newline at end of file + - id: add-license-headers + files: '(src|examples|tests|docker)/.*\.(py)|\.(proto)' + args: + - --start_year=2024 \ No newline at end of file diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..3d923f3 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,12 @@ +# This is the list of allie-flowkit-python's significant contributors. +# +# This file does not necessarily list everyone who has contributed code. +# +# For contributions made under a Corporate CLA, the organization is +# added to this file. +# +# If you have contributed to the repository and wish to be added to this file +# please submit a request. +# +# +ANSYS, Inc. \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..5a9533d --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,65 @@ +# Contributor covenant code of conduct + +## Pledge + +In the interest of fostering an open and welcoming environment, +all contributors and maintainers pledge to making participation +in the Ansys project and community a harassment-free experience +for everyone, regardless of age, body size, disability, ethnicity, +sex characteristics, gender identity and expression, level of +experience, education, socioeconomic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Standards + +Examples of behavior that contribute to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual + attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, or to ban temporarily or permanently any +contributor for other behaviors that they deem inappropriate, threatening, +offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project email +address, posting using an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Attribution + +This code of conduct is adapted from the [Contributor Covenant][homepage], +version 1.4, available at +https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..86cfed2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,10 @@ +# Contribute + +Overall guidance on contributing to a PyAnsys library appears in the +*Contributing* topic in the *[PyAnsys developer's guide]*. Ensure that you +are thoroughly familiar with this guide before attempting to contribute to +allie-flowkit-python. For contributing to this project, please refer to the +[Contributing] section of this project's documentation. + +[PyAnsys Developer's Guide]: https://dev.docs.pyansys.com/index.html +[Contributing]: expert-adventure-nvnoo1y.pages.github.io/dev/contributing.html \ No newline at end of file diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md new file mode 100644 index 0000000..209a3ad --- /dev/null +++ b/CONTRIBUTORS.md @@ -0,0 +1,5 @@ +# Contributors + +## Project Lead or Owner + +* [Laura Sanchez-Gallego Kadri](https://github.com/laurasgkadri98) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0add157 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 ANSYS, Inc. and/or its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index dd89532..34a6ab8 100644 --- a/README.md +++ b/README.md @@ -59,16 +59,16 @@ Allie FlowKit Python can be run locally or as a Docker container. Follow the ins cd allie-flowkit-python ``` -2. Install the required dependencies: +2. Install the project: ```sh - pip install -r requirements.txt + pip install . ``` #### Usage 1. Start the service: ```sh - uvicorn app.app:app --host 0.0.0.0 --port 50052 --workers 1 + allie-flowkit-python --host 0.0.0.0 --port 50052 --workers 1 ``` You can specify the host, port, and number of workers as needed. @@ -93,27 +93,27 @@ Allie FlowKit Python can be run locally or as a Docker container. Follow the ins ## Adding custom functions 1. **Create a New Function:** - - Add your function code as an endpoint to a new Python file in the `app/endpoints` directory. - - Use the `app/endpoints/splitter.py` file and its endpoints as an example. + - Add your function code as an endpoint to a new Python file in the `allie/flowkit/endpoints` directory. + - Use the `allie/flowkit/endpoints/splitter.py` file and its endpoints as an example. - Explicitly define the input and output of the function using Pydantic models, as these will be used by the Allie Agent to call the function. 2. **Add the models for the function:** - - Create the models for the input and output of the function in the `app/models` directory. - - Use the `app/models/splitter.py` file and its models as an example. + - Create the models for the input and output of the function in the `allie/flowkit/models` directory. + - Use the `allie/flowkit/models/splitter.py` file and its models as an example. 3. **Add the endpoints to the service:** - - Import your module in the `app/app.py` file and add the router to the service. + - Import your module in the `allie/flowkit/flowkit_service.py` file and add the router to the service. 4. **Add the function to the function map:** - - Add your function to the `function_map` dictionary in the `app/app.py` file. + - Add your function to the `function_map` dictionary in the `allie/flowkit/flowkit_service.py` file. ### Example´ 1. **Create a new file for all your custom functions:** -- In the `app/endpoints` directory, create a new Python file named `custom_endpoint.py`. +- In the `allie/flowkit/endpoints` directory, create a new Python file named `custom_endpoint.py`. 2. **Create the models for the custom function:** -- In the `app/models` directory, create a new Python file named `custom_model.py`. +- In the `allie/flowkit/models` directory, create a new Python file named `custom_model.py`. **custom_model.py**: ```python @@ -152,7 +152,7 @@ Allie FlowKit Python can be run locally or as a Docker container. Follow the ins **custom_endpoint.py**: ```python from fastapi import FastAPI, APIRouter - from app.models.custom_model import CustomRequest, CustomResponse + from allie.flowkit.models.custom_model import CustomRequest, CustomResponse @router.post("/custom_function", response_model=CustomResponse) @@ -176,22 +176,22 @@ Allie FlowKit Python can be run locally or as a Docker container. Follow the ins ``` 4. **Import the module and add the router to the service:** -- Import the module in the ``app/app.py`` file and add the router to the service. +- Import the module in the ``allie/flowkit/flowkit_service.py`` file and add the router to the service. - **app.py**: + **flowkit_service.py**: ```python - from app.endpoints import custom_endpoint + from allie.flowkit.endpoints import custom_endpoint - app.include_router(splitter.router, prefix="/splitter", tags=["splitter"]) - app.include_router( + flowkit_servie.include_router(splitter.router, prefix="/splitter", tags=["splitter"]) + flowkit_servie.include_router( custom_endpoint.router, prefix="/custom_endpoint", tags=["custom_endpoint"] ) ``` 5. **Add the function to the function map:** -- Add your function to the ``function_map`` dictionary in the ``app/app.py`` file. +- Add your function to the ``function_map`` dictionary in the ``allie/flowkit/flowkit_service.py`` file. - **app.py**: + **flowkit_service.py**: ```python function_map = { "split_ppt": splitter.split_ppt, diff --git a/app/__init__.py b/app/__init__.py deleted file mode 100644 index dac4bb9..0000000 --- a/app/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""App package responsible for creating the FastAPI app.""" diff --git a/app/app.py b/app/app.py deleted file mode 100644 index 7578e6a..0000000 --- a/app/app.py +++ /dev/null @@ -1,42 +0,0 @@ -from typing import List - -from app.config._config import CONFIG -from app.endpoints import splitter -from app.fastapi_utils import extract_endpoint_info -from app.models.functions import EndpointInfo -from fastapi import FastAPI, Header, HTTPException - -app = FastAPI() - -# Include routers from all endpoints -app.include_router(splitter.router, prefix="/splitter", tags=["splitter"]) - -# Map of function names to function objects -function_map = { - "split_ppt": splitter.split_ppt, - "split_pdf": splitter.split_pdf, - "split_py": splitter.split_py, -} - - -# Endpoint to list all enpoint information -@app.get("/", response_model=List[EndpointInfo]) -async def list_functions(api_key: str = Header(...)) -> List[EndpointInfo]: - """List all available functions and their endpoints. - - Parameters - ---------- - api_key : str - The API key for authentication. - - Returns - ------- - List[EndpointInfo] - A list of EndpointInfo objects representing the endpoints. - - """ - # Check if the API key is valid - if api_key != CONFIG.flowkit_python_api_key: - raise HTTPException(status_code=401, detail="Invalid API key") - - return extract_endpoint_info(function_map, app.routes) diff --git a/app/config/__init__.py b/app/config/__init__.py deleted file mode 100644 index b459b87..0000000 --- a/app/config/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -"""Configuration package for the application.""" - -from app.config._config import CONFIG diff --git a/app/endpoints/__init__.py b/app/endpoints/__init__.py deleted file mode 100644 index d9e6743..0000000 --- a/app/endpoints/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Endpoints package responsible for defining the endpoints.""" diff --git a/app/models/__init__.py b/app/models/__init__.py deleted file mode 100644 index a19d65b..0000000 --- a/app/models/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Models package used to define the data models.""" diff --git a/app/models/functions.py b/app/models/functions.py deleted file mode 100644 index ba8415a..0000000 --- a/app/models/functions.py +++ /dev/null @@ -1,34 +0,0 @@ -from typing import Any, Dict, List - -from pydantic import BaseModel - - -class ParameterInfo(BaseModel): - """Parameter information model. - - Parameters - ---------- - BaseModel : pydantic.BaseModel - The base model for the parameter information - - """ - - name: str - type: str - - -class EndpointInfo(BaseModel): - """Endpoint information model. - - Parameters - ---------- - BaseModel : pydantic.BaseModel - The base model for the endpoint information - - """ - - name: str - path: str - inputs: List[ParameterInfo] - outputs: List[ParameterInfo] - definitions: Dict[str, Any] diff --git a/app/models/splitter.py b/app/models/splitter.py deleted file mode 100644 index 1ee4bb5..0000000 --- a/app/models/splitter.py +++ /dev/null @@ -1,31 +0,0 @@ -from typing import List - -from pydantic import BaseModel - - -class SplitterRequest(BaseModel): - """Request model for the splitter endpoint. - - Parameters - ---------- - BaseModel : pydantic.BaseModel - The base model for the request. - - """ - - document_content: bytes - chunk_size: int - chunk_overlap: int - - -class SplitterResponse(BaseModel): - """Response model for the splitter endpoint. - - Parameters - ---------- - BaseModel : pydantic.BaseModel - The base model for the response. - - """ - - chunks: List[str] diff --git a/doc/.vale.ini b/doc/.vale.ini new file mode 100644 index 0000000..c148a37 --- /dev/null +++ b/doc/.vale.ini @@ -0,0 +1,31 @@ +# Core settings +# ============= + +# Location of our `styles` +StylesPath = "styles" + +# The options are `suggestion`, `warning`, or `error` (defaults to “warning”). +MinAlertLevel = warning + +# By default, `code` and `tt` are ignored. +IgnoredScopes = code, tt + +# By default, `script`, `style`, `pre`, and `figure` are ignored. +SkippedScopes = script, style, pre, figure + +# WordTemplate specifies what Vale will consider to be an individual word. +WordTemplate = \b(?:%s)\b + +# List of Packages to be used for our guidelines +Packages = Google + +# Define the Ansys vocabulary +Vocab = ANSYS + +[*.{md,rst}] + +# Apply the following styles +[*.{rst}] +BasedOnStyles = Vale, Google +Vale.Terms = NO +Google.Headings = NO \ No newline at end of file diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..cbc69ea --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,36 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = -j auto -W --color +SPHINXBUILD = sphinx-build +APIDIR = api +EXAMPLESDIR = examples +SOURCEDIR = source +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +# Customized clean due to examples gallery +clean: + rm -rf $(BUILDDIR)/* + find . -type d -name $(APIDIR) -exec rm -rf {} + + find . -type d -name $(EXAMPLESDIR) -exec rm -rf {} + + +# Create PDF +pdf: + @$(SPHINXBUILD) -M latex "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + cd $(BUILDDIR)/latex && latexmk -r latexmkrc -pdf *.tex -interaction=nonstopmode || true + +# Build HTML files and generate examples as .py files +html: + @$(SPHINXBUILD) -M html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/doc/make.bat b/doc/make.bat new file mode 100644 index 0000000..a5c1640 --- /dev/null +++ b/doc/make.bat @@ -0,0 +1,64 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +if "%SPHINXOPTS%" == "" ( + set SPHINXOPTS=-j auto -W --color +) +set SOURCEDIR=source +set APIDIR=api +set EXAMPLESDIR=examples +set BUILDDIR=_build + +if "%1" == "" goto help +if "%1" == "clean" goto clean +if "%1" == "pdf" goto pdf +if "%1" == "html" goto html + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:html +%SPHINXBUILD% -M html %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:pdf +%SPHINXBUILD% -M latex %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +cd "%BUILDDIR%\latex" +for %%f in (*.tex) do ( +pdflatex "%%f" --interaction=nonstopmode) +if NOT EXIST allie-flowkit-python.pdf ( + Echo "no pdf generated!" + exit /b 1) +Echo "pdf generated!" +goto end + +:clean +rmdir /s /q %BUILDDIR% > /NUL 2>&1 +for /d /r %SOURCEDIR% %%d in (%APIDIR%, %EXAMPLESDIR%) do @if exist "%%d" rmdir /s /q "%%d" +goto end + +:end +popd diff --git a/doc/source/conf.py b/doc/source/conf.py new file mode 100644 index 0000000..a0c9e04 --- /dev/null +++ b/doc/source/conf.py @@ -0,0 +1,217 @@ +"""Sphinx documentation configuration file.""" + +from datetime import datetime +import os + +from allie.flowkit import __version__ +from ansys_sphinx_theme import ( + ansys_favicon, + ansys_logo_white, + ansys_logo_white_cropped, + get_version_match, + latex, + watermark, +) +from sphinx.builders.latex import LaTeXBuilder + +LaTeXBuilder.supported_image_types = ["image/png", "image/pdf", "image/svg+xml"] + +# Project information +project = "allie-flowkit-python" +copyright = f"(c) {datetime.now().year} ANSYS, Inc. All rights reserved" +author = "ANSYS, Inc." +release = version = __version__ +cname = os.getenv("DOCUMENTATION_CNAME", default="expert-adventure-nvnoo1y.pages.github.io") +switcher_version = get_version_match(__version__) + +# Select desired logo, theme, and declare the html title +html_theme = "ansys_sphinx_theme" +html_short_title = html_title = "Allie Flowkit Python" +html_baseurl = f"https://{cname}/version/stable" + +# specify the location of your github repo +html_context = { + "github_user": "ansys", + "github_repo": "allie-flowkit-python", + "github_version": "main", + "doc_path": "doc/source", +} +html_theme_options = { + "logo": "pyansys", + "switcher": { + "json_url": f"https://{cname}/versions.json", + "version_match": switcher_version, + }, + "check_switcher": False, + "github_url": "https://github.com/ansys/allie-flowkit-python", + "show_prev_next": False, + "show_breadcrumbs": True, + "collapse_navigation": True, + "use_edit_page_button": True, + "additional_breadcrumbs": [ + ("PyAnsys", "https://docs.pyansys.com/"), + ], + "icon_links": [ + { + "name": "Support", + "url": "https://github.com/ansys/allie-flowkit-python/discussions", + "icon": "fa fa-comment fa-fw", + }, + { + "name": "Download documentation in PDF", + "url": f"https://{cname}/version/{switcher_version}/_static/assets/download/allie-flowkit-python.pdf", # noqa: E501 + "icon": "fa fa-file-pdf fa-fw", + }, + ], + "ansys_sphinx_theme_autoapi": { + "project": "Allie Flowkit Python", + "output": "api", + "use_implicit_namespaces": True, + "directory": "src", + "keep_files": True, + "own_page_level": "class", + "type": "python", + "options": [ + "members", + "undoc-members", + "show-inheritance", + "show-module-summary", + "special-members", + ], + "class_content": "class", + }, +} + +suppress_warnings = ["autoapi.python_import_resolution", "design.grid", "config.cache", "autoapi.not_readable"] + + +# Sphinx extensions +extensions = [ + "sphinx.ext.intersphinx", + "sphinx_copybutton", + "sphinx_design", + "sphinx_jinja", + "autoapi.extension", + "numpydoc", + "ansys_sphinx_theme.extension.autoapi", +] + +nbsphinx_execute = "always" +sphinx_gallery_conf = { + # path to your examples scripts + "examples_dirs": ["../../examples"], + # path where to save gallery generated examples + "gallery_dirs": ["examples"], + # Pattern to search for example files + "filename_pattern": r"\.py", + # Remove the "Download all examples" button from the top level gallery + "download_all_examples": False, + # Sort gallery example by file name instead of number of lines (default) + # directory where function granular galleries are stored + "backreferences_dir": None, + # Modules for which function level galleries are created. In + "doc_module": "allie-flowkit-python", + "ignore_pattern": "flycheck*", + "thumbnail_size": (350, 350), + "remove_config_comments": True, + "show_signature": False, +} + + +# Intersphinx mapping +intersphinx_mapping = { + "python": ("https://docs.python.org/3.11", None), + "numpy": ("https://numpy.org/doc/stable", None), + "scipy": ("https://docs.scipy.org/doc/scipy/", None), + "grpc": ("https://grpc.github.io/grpc/python/", None), + "pint": ("https://pint.readthedocs.io/en/stable", None), + "beartype": ("https://beartype.readthedocs.io/en/stable/", None), + "docker": ("https://docker-py.readthedocs.io/en/stable/", None), + "pypim": ("https://pypim.docs.pyansys.com/version/stable", None), +} + +# numpydoc configuration +numpydoc_show_class_members = False +numpydoc_xref_param_type = True + +# Consider enabling numpydoc validation. See: +# https://numpydoc.readthedocs.io/en/latest/validation.html# +numpydoc_validate = True +numpydoc_validation_checks = { + "GL06", # Found unknown section + "GL07", # Sections are in the wrong order. + # "GL08", # The object does not have a docstring + "GL09", # Deprecation warning should precede extended summary + "GL10", # reST directives {directives} must be followed by two colons + "SS01", # No summary found + "SS02", # Summary does not start with a capital letter + # "SS03", # Summary does not end with a period + "SS04", # Summary contains heading whitespaces + # "SS05", # Summary must start with infinitive verb, not third person + "RT02", # The first line of the Returns section should contain only the + # type, unless multiple values are being returned" +} + +html_favicon = ansys_favicon + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# The suffix(es) of source filenames. +source_suffix = { + ".rst": "restructuredtext", + ".md": "markdown", +} + +# The master toctree document. +master_doc = "index" + + +typehints_defaults = "comma" +simplify_optional_unions = False + +# additional logos for the latex coverpage +latex_additional_files = [watermark, ansys_logo_white, ansys_logo_white_cropped] + +# change the preamble of latex with customized title page +# variables are the title of pdf, watermark +latex_elements = {"preamble": latex.generate_preamble(html_title)} + +linkcheck_exclude_documents = ["index", "getting_started/local/index", "assets"] +linkcheck_ignore = ["https://github.com/ansys/allie-flowkit-python/"] +# -- Declare the Jinja context ----------------------------------------------- +exclude_patterns = [ + "examples/**/*.ipynb", + "examples/**/*.py", + "examples/**/*.md5", +] + +BUILD_API = True +if not BUILD_API: + exclude_patterns.append("autoapi") + +BUILD_EXAMPLES = True +if not BUILD_EXAMPLES: + exclude_patterns.append("examples/**") + exclude_patterns.append("examples.rst") + +jinja_contexts = { + "main_toctree": { + "build_api": BUILD_API, + "build_examples": BUILD_EXAMPLES, + } +} + + +def prepare_jinja_env(jinja_env) -> None: + """Customize the jinja env. + + Notes + ----- + See https://jinja.palletsprojects.com/en/3.0.x/api/#jinja2.Environment + + """ + jinja_env.globals["project_name"] = project + + +autoapi_prepare_jinja_env = prepare_jinja_env diff --git a/doc/source/contributing.rst b/doc/source/contributing.rst new file mode 100644 index 0000000..eb27025 --- /dev/null +++ b/doc/source/contributing.rst @@ -0,0 +1,81 @@ +.. _contribute: + +Contribute +########## + +Overall guidance on contributing to a PyAnsys library appears in the +`Contributing `_ topic +in the *PyAnsys developer's guide*. Ensure that you are thoroughly familiar +with this guide before attempting to contribute to the Allie Flowkit Python. + +The following contribution information is specific to the Allie Flowkit Python. + + +Clone the repository +-------------------- + +To clone and install the latest *Allie Flowkit Python* release in development mode, run +these commands: + +.. code:: + + git clone https://github.com/ansys/allie-flowkit-python/ + cd allie-flowkit-python + python -m pip install --upgrade pip + pip install -e . + +Adhere to code style +-------------------- + +*Allie Flowkit Python* follows the PEP8 standard as outlined in PEP 8 in the PyAnsys Developer’s Guide and implements style checking using pre-commit. + +To ensure your code meets minimum code styling standards, run these commands: + +.. code:: + + pip install pre-commit + pre-commit run --all-files + +You can also install this as a pre-commit hook by running this command: + +.. code:: + + pre-commit install + +Run the tests +------------- + +Prior to running the tests, you must run this command to install the test dependencies: + +.. code:: + + pip install -e .[tests] + +To run the tests, navigate to the root directory of the repository and run this command: + +.. code:: + + pytest + +Build the documentation +----------------------- + +Prior to building the documentation, you must run this command to install the documentation dependencies: + +.. code:: + + pip install -e .[doc] + +To build the documentation, run the following commands: + +.. code:: + + cd doc + + # On linux + make html + + # On windows + ./make.bat html + +The documentation is built in the `docs/_build/html` directory. diff --git a/doc/source/examples/index.rst b/doc/source/examples/index.rst new file mode 100644 index 0000000..9a19fef --- /dev/null +++ b/doc/source/examples/index.rst @@ -0,0 +1,7 @@ +.. _ref_examples: + +Examples +======== + +This section show how to use the Allie Flowkit Python to perform many different +types of operations. diff --git a/doc/source/getting_started/index.rst b/doc/source/getting_started/index.rst new file mode 100644 index 0000000..117efbb --- /dev/null +++ b/doc/source/getting_started/index.rst @@ -0,0 +1,39 @@ +.. _ref_getting_started: + +Getting started +############### + +This section describes how to install the Allie Flowkit Python in user mode and +quickly begin using it. If you are interested in contributing to the Allie Flowkit Python, +see :ref:`contribute` for information on installing in developer mode. + +Installation +============ + +To use `pip `_ to install the Allie Flowkit Python, +run this command: + +.. code:: bash + + pip install allie-flowkit-python + +Alternatively, to install the latest version from this library's +`GitHub repository `_, +run these commands: + +.. code:: bash + + git clone https://github.com/ansys/allie-flowkit-python + cd allie-flowkit-python + pip install . + +Quick start +^^^^^^^^^^^ + +The following examples show how to use the Allie Flowkit Python. + +.. code:: bash + + allie-flowkit-python --host 0.0.0.0 --port 50052 --workers 1 + + diff --git a/doc/source/index.rst b/doc/source/index.rst new file mode 100644 index 0000000..f0a65b3 --- /dev/null +++ b/doc/source/index.rst @@ -0,0 +1,73 @@ +Allie Flowkit Python documentation |version| +============================================= + +The Allie Flowkit Python is a Python service that exposes features from Allie Flowkit to Python users. This documentation provides information on how to install and use the Allie Flowkit Python. + +The Allie Flowkit Python offers these main features: + + + +.. grid:: 1 2 2 2 + + + .. grid-item-card:: Getting started :material-regular:`directions_run` + :padding: 2 2 2 2 + :link: getting_started/index + :link-type: doc + + Learn how to install the Allie Flowkit Python in user mode and quickly + begin using it. + + .. grid-item-card:: User guide :material-regular:`menu_book` + :padding: 2 2 2 2 + :link: user_guide/index + :link-type: doc + + Understand key concepts for implementing the Allie Flowkit Python in + your workflow. + + .. jinja:: main_toctree + + {% if build_api %} + .. grid-item-card:: API reference :material-regular:`bookmark` + :padding: 2 2 2 2 + :link: api/src/allie/flowkit/index + :link-type: doc + + Understand how to use Python to interact programmatically with + the Allie Flowkit Python. + {% endif %} + + {% if build_examples %} + .. grid-item-card:: Examples :material-regular:`play_arrow` + :padding: 2 2 2 2 + :link: examples/index + :link-type: doc + + Explore examples that show how to use the Allie Flowkit Python to + perform many different types of operations. + {% endif %} + + .. grid-item-card:: Contribute :material-regular:`group` + :padding: 2 2 2 2 + :link: contributing + :link-type: doc + + Learn how to contribute to the Allie Flowkit Python codebase or documentation. + + +.. jinja:: main_toctree + + .. toctree:: + :hidden: + :maxdepth: 3 + + getting_started/index + user_guide/index + {% if build_api %} + api/index + {% endif %} + {% if build_examples %} + examples/index + {% endif %} + contributing \ No newline at end of file diff --git a/doc/source/user_guide/index.rst b/doc/source/user_guide/index.rst new file mode 100644 index 0000000..dd33799 --- /dev/null +++ b/doc/source/user_guide/index.rst @@ -0,0 +1,9 @@ +.. _ref_user_guide: + +========== +User guide +========== + +This section explains key concepts for implementing the Allie Flowkit Python in your workflow. +You can use the Allie Flowkit Python in your examples as well as integrate this library into +your own code. diff --git a/doc/styles/config/vocabularies/ANSYS/accept.txt b/doc/styles/config/vocabularies/ANSYS/accept.txt new file mode 100644 index 0000000..b7774a9 --- /dev/null +++ b/doc/styles/config/vocabularies/ANSYS/accept.txt @@ -0,0 +1,3 @@ +(?i)Ansys +pytest +(?i)Flowkit \ No newline at end of file diff --git a/doc/styles/config/vocabularies/ANSYS/reject.txt b/doc/styles/config/vocabularies/ANSYS/reject.txt new file mode 100644 index 0000000..e69de29 diff --git a/docker/Dockerfile b/docker/Dockerfile index dd8dee9..86c48bc 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -3,12 +3,16 @@ FROM python:3.12-slim WORKDIR /app # Copy the app folder and the config.yaml file -COPY requirements.txt . -COPY app/ ./app/ -COPY configs/config.yaml . +COPY src /app + +# readme required by pip +COPY README.md /app +COPY pyproject.toml /app +COPY configs/config.yaml /app # Install dependencies -RUN pip install --no-cache-dir -r requirements.txt +RUN echo $(ls) +RUN pip install --no-cache-dir .[all] EXPOSE 8000 @@ -16,4 +20,4 @@ EXPOSE 8000 ENV WORKERS=4 # Use the environment variable in CMD -CMD ["sh", "-c", "uvicorn app.app:app --host 0.0.0.0 --port 8000 --workers ${WORKERS}"] \ No newline at end of file +CMD ["sh", "-c", "allie-flowkit-python --host 0.0.0.0 --port 8000 --workers $WORKERS"] \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index d9fca73..59011ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,72 @@ +[build-system] +requires = ["flit_core >=3.2,<4"] +build-backend = "flit_core.buildapi" + +[project] +name = "allie-flowkit-python" +version = "0.1.dev0" +description = "A Python service for Allie Flowkit." +readme = "README.md" +requires-python = ">=3.10,<4" +license = { file = "LICENSE" } +authors = [{ name = "ANSYS, Inc.", email = "pyansys.core@ansys.com" }] +maintainers = [{ name = "ANSYS, Inc.", email = "pyansys.core@ansys.com" }] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Science/Research", + "Topic :: Scientific/Engineering :: Information Analysis", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", +] +dependencies = [ + "fastapi >= 0.111.1,<1", + "langchain >= 0.2.11,<1", + "pydantic >= 2.8.2,<3", + "pymupdf >= 1.24.9,<2", + "python_pptx >= 0.6.23,<1", + "PyYAML >= 6.0.1,<7", + "httpx >= 0.27.0", +] + +[project.optional-dependencies] +all = [ + "uvicorn[standard] >= 0.30.5,<1", +] + +tests = [ + "pytest >= 8.3.2,<9", + "pytest-cov >= 5.0.0,<6", + "pytest-asyncio >= 0.23.8,<1", +] +doc = [ + "ansys-sphinx-theme==1.0.3", + "numpydoc==1.7.0", + "sphinx==8.0.2", + "sphinx-autoapi==3.2.1", + "sphinx-copybutton==0.5.2", + "sphinx_design==0.6.1", + "sphinx-gallery==0.17.0", + "sphinx-jinja==2.0.2", +] + +[project.urls] +Source = "https://github.com/ansys/allie-flowkit-python" +Issues = "https://github.com/ansys/allie-flowkit-python/issues" +Discussions = "https://github.com/ansys/allie-flowkit-python/discussions" +Releases = "https://github.com/ansys/allie-flowkit-python/releases/" + +[project.scripts] +allie-flowkit-python = "allie.flowkit.__main__:main" + +[tool.flit.module] +name = "allie.flowkit" + +[tool.pytest.ini_options] +addopts = "--cov=allie.flowkit --cov-report=term --cov-report=html:.cov/html --cov-report=xml:.cov/coverage.xml" + [tool.codespell] skip = "*.pyc,*.xml,*.txt,*.gif,*.png,*.jpg,*.js,*.html,*.doctree,*.ttf,*.woff,*.woff2,*.eot,*.mp4,*.inv,*.pickle,*.ipynb,flycheck*,./.git/*,./.hypothesis/*,*.yml,./docs/build/*,./docs/images/*,./dist/*,*~,.hypothesis*,./docs/source/examples/*,*cover,*.dat,*.mac" @@ -17,3 +86,35 @@ convention = "numpy" [tool.mypy] strict = true ignore_missing_imports = true + +[tool.ruff] +line-length = 120 +extend-exclude = ["examples/**/*.py"] + +[tool.ruff.lint] +select = [ + "E", # pycodestyle, see https://beta.ruff.rs/docs/rules/#pycodestyle-e-w + "D", # pydocstyle, see https://beta.ruff.rs/docs/rules/#pydocstyle-d + "F", # pyflakes, see https://beta.ruff.rs/docs/rules/#pyflakes-f + "I", # isort, see https://beta.ruff.rs/docs/rules/#isort-i + "N", # pep8-naming, see https://beta.ruff.rs/docs/rules/#pep8-naming-n + "PTH", # flake8-use-pathlib, https://beta.ruff.rs/docs/rules/#flake8-use-pathlib-pth +] +ignore = ["D416"] + +[tool.ruff.format] +quote-style = "double" +line-ending = "auto" + +[tool.ruff.lint.isort] +combine-as-imports = true +force-sort-within-sections = true +known-first-party = ["ansys"] + +[tool.ruff.lint.pydocstyle] +# Settings: https://docs.astral.sh/ruff/settings/#lintpydocstyle +convention = "google" + +[tool.setuptools.packages.find] +include = ["app", "docker", "configs"] + diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index c17fcc8..0000000 --- a/requirements.txt +++ /dev/null @@ -1,9 +0,0 @@ -fastapi==0.112.0 -httpx==0.27.0 -langchain==0.2.12 -pydantic==2.8.2 -pymupdf==1.24.9 -pytest==8.3.2 -pytest-cov==5.0.0 -python_pptx==1.0.1 -PyYAML==6.0.1 diff --git a/setup.py b/setup.py deleted file mode 100644 index 0033fb9..0000000 --- a/setup.py +++ /dev/null @@ -1,7 +0,0 @@ -from setuptools import find_packages, setup - -setup( - name="ansys-allie-flowkit-python", - version="0.1.0", - packages=find_packages(include=["app", "docker", "configs"]), -) diff --git a/src/allie/flowkit/__init__.py b/src/allie/flowkit/__init__.py new file mode 100644 index 0000000..5dc4eb3 --- /dev/null +++ b/src/allie/flowkit/__init__.py @@ -0,0 +1,29 @@ +# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""App package responsible for creating the FastAPI app.""" + +import importlib.metadata as importlib_metadata + +__version__ = importlib_metadata.version("allie-flowkit-python") + +from allie.flowkit.flowkit_service import flowkit_service # noqa F401 diff --git a/src/allie/flowkit/__main__.py b/src/allie/flowkit/__main__.py new file mode 100644 index 0000000..66f5f9c --- /dev/null +++ b/src/allie/flowkit/__main__.py @@ -0,0 +1,43 @@ +# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Main module for the FlowKit service.""" + +try: + import uvicorn +except ImportError: + raise ImportError("Please install uvicorn to run the service: pip install allie-flowkit-python[all]") +import argparse + + +def main(): + """Run entrypoint for the FlowKit service.""" + parse = argparse.ArgumentParser() + parse.add_argument("--host", type=str, default="0.0.0.0", help="The host to run the service on. By default 0.0.0.0") + parse.add_argument("--port", type=int, default=8000, help="The port to run the service on. By default 8000") + parse.add_argument("--workers", type=int, default=4, help="The number of workers to use. By default 4") + args = parse.parse_args() + uvicorn.run("allie.flowkit:flowkit_service", host=args.host, port=args.port, workers=args.workers) + + +if __name__ == "__main__": + main() diff --git a/src/allie/flowkit/config/__init__.py b/src/allie/flowkit/config/__init__.py new file mode 100644 index 0000000..c8f8f09 --- /dev/null +++ b/src/allie/flowkit/config/__init__.py @@ -0,0 +1,25 @@ +# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Configuration package for the application.""" + +from allie.flowkit.config._config import CONFIG # noqa F401 diff --git a/app/config/_config.py b/src/allie/flowkit/config/_config.py similarity index 53% rename from app/config/_config.py rename to src/allie/flowkit/config/_config.py index f7a1c35..de35ec7 100644 --- a/app/config/_config.py +++ b/src/allie/flowkit/config/_config.py @@ -1,4 +1,29 @@ +# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Module for reading the configuration settings from a YAML file.""" + import os +from pathlib import Path import yaml @@ -21,6 +46,7 @@ class Config: def __init__(self): """Initialize the Config object by reading the configuration file. + Also, check if the 'FLOWKIT_PYTHON_API_KEY' is present in the configuration file. @@ -58,15 +84,19 @@ def _load_config(self, config_path: str) -> dict: """ try: - with open(config_path, "r") as file: + with Path(config_path).open("r") as file: return yaml.safe_load(file) except FileNotFoundError: print(f"Configuration file not found at: {config_path}, using default location.") try: - with open("configs/config.yaml", "r") as file: + with Path("configs/config.yaml").open("r") as file: return yaml.safe_load(file) except FileNotFoundError: - raise FileNotFoundError("Configuration file not found at the default location.") + try: + with Path("../../configs/config.yaml").open("r") as file: + return yaml.safe_load(file) + except FileNotFoundError: + raise FileNotFoundError("Configuration file not found at the default location.") # Initialize the config object diff --git a/src/allie/flowkit/endpoints/__init__.py b/src/allie/flowkit/endpoints/__init__.py new file mode 100644 index 0000000..e5f13a3 --- /dev/null +++ b/src/allie/flowkit/endpoints/__init__.py @@ -0,0 +1,23 @@ +# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Endpoints package responsible for defining the endpoints.""" diff --git a/app/endpoints/splitter.py b/src/allie/flowkit/endpoints/splitter.py similarity index 78% rename from app/endpoints/splitter.py rename to src/allie/flowkit/endpoints/splitter.py index d5f8ef3..b94826e 100644 --- a/app/endpoints/splitter.py +++ b/src/allie/flowkit/endpoints/splitter.py @@ -1,8 +1,32 @@ +# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Module for splitting text into chunks.""" + import base64 import io -from app.config._config import CONFIG -from app.models.splitter import SplitterRequest, SplitterResponse +from allie.flowkit.config._config import CONFIG +from allie.flowkit.models.splitter import SplitterRequest, SplitterResponse from fastapi import APIRouter, Header, HTTPException from langchain.text_splitter import PythonCodeTextSplitter, RecursiveCharacterTextSplitter from pptx import Presentation @@ -108,9 +132,7 @@ def process_ppt(request: SplitterRequest) -> SplitterResponse: if not ppt_text: raise HTTPException(status_code=400, detail="No text found in PowerPoint document") - splitter = RecursiveCharacterTextSplitter( - chunk_size=request.chunk_size, chunk_overlap=request.chunk_overlap - ) + splitter = RecursiveCharacterTextSplitter(chunk_size=request.chunk_size, chunk_overlap=request.chunk_overlap) chunks = splitter.split_text(ppt_text) response = SplitterResponse(chunks=chunks) @@ -142,9 +164,7 @@ def process_python_code(request: SplitterRequest) -> SplitterResponse: except UnicodeDecodeError: raise HTTPException(status_code=400, detail="Error decoding Python code") - splitter = PythonCodeTextSplitter( - chunk_size=request.chunk_size, chunk_overlap=request.chunk_overlap - ) + splitter = PythonCodeTextSplitter(chunk_size=request.chunk_size, chunk_overlap=request.chunk_overlap) chunks = splitter.split_text(document_content_str) response = SplitterResponse(chunks=chunks) @@ -183,9 +203,7 @@ def process_pdf(request: SplitterRequest) -> SplitterResponse: if not pdf_text: raise HTTPException(status_code=400, detail="No text found in PDF document") - splitter = RecursiveCharacterTextSplitter( - chunk_size=request.chunk_size, chunk_overlap=request.chunk_overlap - ) + splitter = RecursiveCharacterTextSplitter(chunk_size=request.chunk_size, chunk_overlap=request.chunk_overlap) chunks = splitter.split_text(pdf_text) response = SplitterResponse(chunks=chunks) @@ -227,6 +245,4 @@ def validate_request(request: SplitterRequest, api_key: str): # Check if chunk overlap is greater than or equal to 0 if request.chunk_overlap < 0: - raise HTTPException( - status_code=400, detail="Chunk overlap must be greater than or equal to 0" - ) + raise HTTPException(status_code=400, detail="Chunk overlap must be greater than or equal to 0") diff --git a/app/fastapi_utils.py b/src/allie/flowkit/fastapi_utils.py similarity index 72% rename from app/fastapi_utils.py rename to src/allie/flowkit/fastapi_utils.py index 133644e..195604e 100644 --- a/app/fastapi_utils.py +++ b/src/allie/flowkit/fastapi_utils.py @@ -1,7 +1,31 @@ +# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Utils module for FastAPI related operations.""" + import inspect -from typing import Any, Dict, List, Type, get_type_hints +from typing import Any, get_type_hints -from app.models.functions import EndpointInfo, ParameterInfo +from allie.flowkit.models.functions import EndpointInfo, ParameterInfo from fastapi.routing import APIRoute from pydantic import BaseModel @@ -55,7 +79,7 @@ def extract_fields_from_schema(schema: dict): return fields -def get_parameters_info(params): +def get_parameters_info(params: dict): """Get parameter information from function parameters. Parameters @@ -74,7 +98,7 @@ def get_parameters_info(params): # If the param is a header skip it if "alias" in str(param.default) and "annotation" in str(param.default): continue - if param.annotation == bytes: + if isinstance(param.annotation, bytes): param_info = ParameterInfo(name=param.name, type="bytes") parameters_info.append(param_info) elif hasattr(param.annotation, "model_json_schema"): @@ -87,12 +111,12 @@ def get_parameters_info(params): return parameters_info -def get_return_type_info(return_type: Type[BaseModel]): +def get_return_type_info(return_type: type[BaseModel]): """Get return type information from the function's return type. Parameters ---------- - return_type : Type[BaseModel] + return_type : type[BaseModel] The return type of the function. Returns @@ -107,7 +131,7 @@ def get_return_type_info(return_type: Type[BaseModel]): return [ParameterInfo(name="return", type=str(return_type.__name__))] -def extract_definitions_from_schema(schema: dict) -> Dict[str, Any]: +def extract_definitions_from_schema(schema: dict) -> dict[str, Any]: """Extract definitions from a schema. Parameters @@ -125,7 +149,7 @@ def extract_definitions_from_schema(schema: dict) -> Dict[str, Any]: return definitions -def get_definitions_from_params(params: dict) -> Dict[str, Any]: +def get_definitions_from_params(params: dict) -> dict[str, Any]: """Get definitions from function parameters. Parameters @@ -147,12 +171,12 @@ def get_definitions_from_params(params: dict) -> Dict[str, Any]: return definitions -def get_definitions_from_return_type(return_type: Type[BaseModel]) -> Dict[str, Any]: +def get_definitions_from_return_type(return_type: type[BaseModel]) -> dict[str, Any]: """Get definitions from the function's return type. Parameters ---------- - return_type : Type[BaseModel] + return_type : type[BaseModel] The return type of the function. Returns @@ -167,16 +191,14 @@ def get_definitions_from_return_type(return_type: Type[BaseModel]) -> Dict[str, return {} -def extract_endpoint_info( - function_map: Dict[str, Any], routes: List[APIRoute] -) -> List[EndpointInfo]: +def extract_endpoint_info(function_map: dict[str, Any], routes: list[APIRoute]) -> list[EndpointInfo]: """Extract endpoint information from the given routes. Parameters ---------- - function_map : dict + function_map : dict[str, Any] A dictionary mapping function names to their implementations. - routes : list + routes : list[APIRoute] A list of APIRoute objects representing the API routes. Returns @@ -197,9 +219,7 @@ def extract_endpoint_info( # Get definitions from both inputs and outputs input_definitions = get_definitions_from_params(signature.parameters) - output_definitions = ( - get_definitions_from_return_type(return_type) if return_type else {} - ) + output_definitions = get_definitions_from_return_type(return_type) if return_type else {} definitions = {**input_definitions, **output_definitions} endpoint_info = EndpointInfo( diff --git a/src/allie/flowkit/flowkit_service.py b/src/allie/flowkit/flowkit_service.py new file mode 100644 index 0000000..afd970d --- /dev/null +++ b/src/allie/flowkit/flowkit_service.py @@ -0,0 +1,64 @@ +# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Module for the Allie Flowkit service.""" + +from allie.flowkit.config._config import CONFIG +from allie.flowkit.endpoints import splitter +from allie.flowkit.fastapi_utils import extract_endpoint_info +from allie.flowkit.models.functions import EndpointInfo +from fastapi import FastAPI, Header, HTTPException + +flowkit_service = FastAPI() + +# Include routers from all endpoints +flowkit_service.include_router(splitter.router, prefix="/splitter", tags=["splitter"]) + +# Map of function names to function objects +function_map = { + "split_ppt": splitter.split_ppt, + "split_pdf": splitter.split_pdf, + "split_py": splitter.split_py, +} + + +# Endpoint to list all enpoint information +@flowkit_service.get("/", response_model=list[EndpointInfo]) +async def list_functions(api_key: str = Header(...)) -> list[EndpointInfo]: + """List all available functions and their endpoints. + + Parameters + ---------- + api_key : str + The API key for authentication. + + Returns + ------- + list[EndpointInfo] + A list of EndpointInfo objects representing the endpoints. + + """ + # Check if the API key is valid + if api_key != CONFIG.flowkit_python_api_key: + raise HTTPException(status_code=401, detail="Invalid API key") + + return extract_endpoint_info(function_map, flowkit_service.routes) diff --git a/src/allie/flowkit/models/__init__.py b/src/allie/flowkit/models/__init__.py new file mode 100644 index 0000000..fd4aed7 --- /dev/null +++ b/src/allie/flowkit/models/__init__.py @@ -0,0 +1,23 @@ +# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Models package used to define the data models.""" diff --git a/src/allie/flowkit/models/functions.py b/src/allie/flowkit/models/functions.py new file mode 100644 index 0000000..d844934 --- /dev/null +++ b/src/allie/flowkit/models/functions.py @@ -0,0 +1,58 @@ +# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Module for defining the models used in the endpoints.""" + +from typing import Any + +from pydantic import BaseModel + + +class ParameterInfo(BaseModel): + """Parameter information model. + + Parameters + ---------- + BaseModel : pydantic.BaseModel + The base model for the parameter information + + """ + + name: str + type: str + + +class EndpointInfo(BaseModel): + """Endpoint information model. + + Parameters + ---------- + BaseModel : pydantic.BaseModel + The base model for the endpoint information + + """ + + name: str + path: str + inputs: list[ParameterInfo] + outputs: list[ParameterInfo] + definitions: dict[str, Any] diff --git a/src/allie/flowkit/models/splitter.py b/src/allie/flowkit/models/splitter.py new file mode 100644 index 0000000..c074f4e --- /dev/null +++ b/src/allie/flowkit/models/splitter.py @@ -0,0 +1,53 @@ +# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Model for the splitter endpoint.""" + +from pydantic import BaseModel + + +class SplitterRequest(BaseModel): + """Request model for the splitter endpoint. + + Parameters + ---------- + BaseModel : pydantic.BaseModel + The base model for the request. + + """ + + document_content: bytes + chunk_size: int + chunk_overlap: int + + +class SplitterResponse(BaseModel): + """Response model for the splitter endpoint. + + Parameters + ---------- + BaseModel : pydantic.BaseModel + The base model for the response. + + """ + + chunks: list[str] diff --git a/tests/__init__.py b/tests/__init__.py index f1b390f..b4a288b 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +1,23 @@ +# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """Tests module.""" diff --git a/tests/conftest.py b/tests/conftest.py index 4f9d61d..4d2e66c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,26 @@ +# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +"""Module for test helper functions.""" + from unittest.mock import patch import pytest @@ -9,5 +32,5 @@ @pytest.fixture(autouse=True) def mock_api_key(): """Mock the API key for testing.""" - with patch("app.config.CONFIG.flowkit_python_api_key", MOCK_API_KEY): + with patch("allie.flowkit.config.CONFIG.flowkit_python_api_key", MOCK_API_KEY): yield diff --git a/tests/test_endpoints_splitter.py b/tests/test_endpoints_splitter.py index c947fda..32f26b8 100644 --- a/tests/test_endpoints_splitter.py +++ b/tests/test_endpoints_splitter.py @@ -1,8 +1,32 @@ +# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +"""Test module for the splitter endpoints.""" + import base64 +from pathlib import Path -from app.app import app -from app.endpoints.splitter import validate_request -from app.models.splitter import SplitterRequest +from allie.flowkit import flowkit_service +from allie.flowkit.endpoints.splitter import validate_request +from allie.flowkit.models.splitter import SplitterRequest from fastapi import HTTPException from fastapi.testclient import TestClient import pytest @@ -10,12 +34,12 @@ from tests.conftest import MOCK_API_KEY # Create a test client -client = TestClient(app) +client = TestClient(flowkit_service) def encode_file_to_base64(file_path): """Encode a file to base64 string.""" - with open(file_path, "rb") as file: + with Path(file_path).open("rb") as file: return base64.b64encode(file.read()).decode("utf-8") @@ -69,7 +93,9 @@ async def test_split_pdf(): # Test case 1: valid request ( SplitterRequest( - document_content="dGVzdA==", chunk_size=100, chunk_overlap=10 # base64 for "test" + document_content="dGVzdA==", + chunk_size=100, + chunk_overlap=10, # base64 for "test" ), MOCK_API_KEY, None, diff --git a/tests/test_list_functions.py b/tests/test_list_functions.py index c2e50b4..94202f9 100644 --- a/tests/test_list_functions.py +++ b/tests/test_list_functions.py @@ -1,9 +1,32 @@ -from app.app import app +# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +"""Test module for list functions.""" + +from allie.flowkit import flowkit_service from fastapi.testclient import TestClient import pytest # Initialize the test client -client = TestClient(app) +client = TestClient(flowkit_service) @pytest.mark.asyncio