From f6c9510c0b7e28d81e9be67a17bb465ee9af608c Mon Sep 17 00:00:00 2001 From: Dan Homola Date: Fri, 13 Sep 2024 10:35:24 +0200 Subject: [PATCH] feat: add the new gooddata-flexfun package At this point, it is basically a move of the flexfun folder in gooddata-flight-server. In the following commit, we will implement a method discovery mechanism for the flight server. JIRA: CQ-754 risk: low --- .envrc | 1 + .github/workflows/rw-collect-changes.yaml | 1 + .github/workflows/rw-python-tests.yaml | 2 +- .sonar.settings | 2 +- .sonarcloud.properties | 2 +- gooddata-flexfun/.gitignore | 69 ++++++++++++ gooddata-flexfun/.readthedocs.yaml | 19 ++++ gooddata-flexfun/Makefile | 19 ++++ gooddata-flexfun/README.md | 3 + gooddata-flexfun/gooddata_flexfun/__init__.py | 17 +++ .../gooddata_flexfun}/flexfun/__init__.py | 0 .../gooddata_flexfun}/flexfun/flex_fun.py | 4 +- .../flexfun/flex_fun_execution_context.py | 0 .../flexfun/flex_fun_registry.py | 5 +- .../flexfun/flex_fun_task.py | 10 +- .../flexfun/flight_methods.py | 22 ++-- gooddata-flexfun/mypy.ini | 26 +++++ gooddata-flexfun/requirements.txt | 6 + gooddata-flexfun/setup.py | 68 ++++++++++++ gooddata-flexfun/test-requirements.txt | 2 + gooddata-flexfun/tests/__init__.py | 1 + gooddata-flexfun/tests/assert_error_info.py | 11 ++ .../tests/flexfun/__init__.py | 0 .../tests/flexfun/conftest.py | 0 .../test_flex_fun_execution_context.py | 2 +- .../tests/flexfun/test_registry.py | 5 +- .../tests/flexfun/testing_funs.py | 5 +- gooddata-flexfun/tests/server/__init__.py | 1 + gooddata-flexfun/tests/server/conftest.py | 103 ++++++++++++++++++ .../tests/server/funs/__init__.py | 0 .../tests/server/funs/fun1.py | 4 +- .../tests/server/funs/fun2.py | 5 +- .../tests/server/test_flexfun_server.py | 0 gooddata-flexfun/tests/server/tls/ca-cert.pem | 35 ++++++ .../tests/server/tls/client-cert.pem | 34 ++++++ .../tests/server/tls/client-key.pem | 52 +++++++++ .../tests/server/tls/server-cert.pem | 34 ++++++ .../tests/server/tls/server-key.pem | 52 +++++++++ gooddata-flexfun/tox.ini | 36 ++++++ gooddata-flexfun/type-requirements.txt | 2 + .../gooddata_flight_server/__init__.py | 15 --- .../gooddata_flight_server/cli.py | 6 +- .../server/server_main.py | 9 +- gooddata-flight-server/setup.py | 3 +- .../tests/server/conftest.py | 19 ---- pyproject.toml | 19 +++- 46 files changed, 643 insertions(+), 88 deletions(-) create mode 100644 gooddata-flexfun/.gitignore create mode 100644 gooddata-flexfun/.readthedocs.yaml create mode 100644 gooddata-flexfun/Makefile create mode 100644 gooddata-flexfun/README.md create mode 100644 gooddata-flexfun/gooddata_flexfun/__init__.py rename {gooddata-flight-server/gooddata_flight_server => gooddata-flexfun/gooddata_flexfun}/flexfun/__init__.py (100%) rename {gooddata-flight-server/gooddata_flight_server => gooddata-flexfun/gooddata_flexfun}/flexfun/flex_fun.py (97%) rename {gooddata-flight-server/gooddata_flight_server => gooddata-flexfun/gooddata_flexfun}/flexfun/flex_fun_execution_context.py (100%) rename {gooddata-flight-server/gooddata_flight_server => gooddata-flexfun/gooddata_flexfun}/flexfun/flex_fun_registry.py (96%) rename {gooddata-flight-server/gooddata_flight_server => gooddata-flexfun/gooddata_flexfun}/flexfun/flex_fun_task.py (87%) rename {gooddata-flight-server/gooddata_flight_server => gooddata-flexfun/gooddata_flexfun}/flexfun/flight_methods.py (94%) create mode 100644 gooddata-flexfun/mypy.ini create mode 100644 gooddata-flexfun/requirements.txt create mode 100644 gooddata-flexfun/setup.py create mode 100644 gooddata-flexfun/test-requirements.txt create mode 100644 gooddata-flexfun/tests/__init__.py create mode 100644 gooddata-flexfun/tests/assert_error_info.py rename {gooddata-flight-server => gooddata-flexfun}/tests/flexfun/__init__.py (100%) rename {gooddata-flight-server => gooddata-flexfun}/tests/flexfun/conftest.py (100%) rename {gooddata-flight-server => gooddata-flexfun}/tests/flexfun/test_flex_fun_execution_context.py (97%) rename {gooddata-flight-server => gooddata-flexfun}/tests/flexfun/test_registry.py (88%) rename {gooddata-flight-server => gooddata-flexfun}/tests/flexfun/testing_funs.py (80%) create mode 100644 gooddata-flexfun/tests/server/__init__.py create mode 100644 gooddata-flexfun/tests/server/conftest.py rename {gooddata-flight-server => gooddata-flexfun}/tests/server/funs/__init__.py (100%) rename {gooddata-flight-server => gooddata-flexfun}/tests/server/funs/fun1.py (85%) rename {gooddata-flight-server => gooddata-flexfun}/tests/server/funs/fun2.py (84%) rename {gooddata-flight-server => gooddata-flexfun}/tests/server/test_flexfun_server.py (100%) create mode 100644 gooddata-flexfun/tests/server/tls/ca-cert.pem create mode 100644 gooddata-flexfun/tests/server/tls/client-cert.pem create mode 100644 gooddata-flexfun/tests/server/tls/client-key.pem create mode 100644 gooddata-flexfun/tests/server/tls/server-cert.pem create mode 100644 gooddata-flexfun/tests/server/tls/server-key.pem create mode 100644 gooddata-flexfun/tox.ini create mode 100644 gooddata-flexfun/type-requirements.txt diff --git a/.envrc b/.envrc index 9cba01a01..2d2cb3033 100644 --- a/.envrc +++ b/.envrc @@ -9,6 +9,7 @@ export PYTHONPATH="${PYTHONPATH}:${SCRIPT_DIR}/gooddata-api-client/" export PYTHONPATH="${PYTHONPATH}:${SCRIPT_DIR}/gooddata-sdk/" export PYTHONPATH="${PYTHONPATH}:${SCRIPT_DIR}/gooddata-pandas/" export PYTHONPATH="${PYTHONPATH}:${SCRIPT_DIR}/gooddata-flight-server/" +export PYTHONPATH="${PYTHONPATH}:${SCRIPT_DIR}/gooddata-flexfun/" export PYTHONPATH="${PYTHONPATH}:${SCRIPT_DIR}/gooddata-dbt/" export PATH="${PATH}:${SCRIPT_DIR}/gooddata-sdk/bin" diff --git a/.github/workflows/rw-collect-changes.yaml b/.github/workflows/rw-collect-changes.yaml index ab5863009..efb599ec9 100644 --- a/.github/workflows/rw-collect-changes.yaml +++ b/.github/workflows/rw-collect-changes.yaml @@ -47,3 +47,4 @@ jobs: - 'gooddata-api-client/**' - 'gooddata-dbt/**' - 'gooddata-flight-server/**' + - 'gooddata-flexfun/**' diff --git a/.github/workflows/rw-python-tests.yaml b/.github/workflows/rw-python-tests.yaml index f30e60879..0f7e1a1f3 100644 --- a/.github/workflows/rw-python-tests.yaml +++ b/.github/workflows/rw-python-tests.yaml @@ -24,7 +24,7 @@ jobs: if: ${{ matrix.python_version == 'py312' }} uses: codecov/codecov-action@v3 with: - files: ./gooddata-sdk/coverage.xml,./gooddata-pandas/coverage.xml,./gooddata-fdw/coverage.xml,./gooddata-flight-server/coverage.xml + files: ./gooddata-sdk/coverage.xml,./gooddata-pandas/coverage.xml,./gooddata-fdw/coverage.xml,./gooddata-flight-server/coverage.xml,./gooddata-flexfun/coverage.xml lint-and-format-check: runs-on: ubuntu-latest if: ${{inputs.changed-python-modules == 'true'}} diff --git a/.sonar.settings b/.sonar.settings index 6c11ab266..bc177f40e 100644 --- a/.sonar.settings +++ b/.sonar.settings @@ -1,4 +1,4 @@ # (C) 2021 GoodData Corporation -sonar.sources=gooddata-sdk,gooddata-fdw,gooddata-pandas +sonar.sources=gooddata-sdk,gooddata-fdw,gooddata-pandas,gooddata-flight-server,gooddata-flexfun sonar.exclusions=gooddata-api-client/**/* sonar.python.version=3.9, 3.10, 3.11, 3.12 diff --git a/.sonarcloud.properties b/.sonarcloud.properties index c8f8036bb..d484c9e19 100644 --- a/.sonarcloud.properties +++ b/.sonarcloud.properties @@ -1,4 +1,4 @@ # (C) 2022 GoodData Corporation -sonar.sources=gooddata-sdk,gooddata-fdw,gooddata-pandas +sonar.sources=gooddata-sdk,gooddata-fdw,gooddata-pandas,gooddata-flight-server,gooddata-flexfun sonar.exclusions=gooddata-api-client/**/* sonar.python.version=3.9, 3.10, 3.11, 3.12 diff --git a/gooddata-flexfun/.gitignore b/gooddata-flexfun/.gitignore new file mode 100644 index 000000000..2700a4f35 --- /dev/null +++ b/gooddata-flexfun/.gitignore @@ -0,0 +1,69 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ +venv/ +.venv/ +.python-version +.pytest_cache + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ +docs/_autosummary/ + +# PyBuilder +target/ + +#Ipython Notebook +.ipynb_checkpoints + +test_data diff --git a/gooddata-flexfun/.readthedocs.yaml b/gooddata-flexfun/.readthedocs.yaml new file mode 100644 index 000000000..2d13a3e2a --- /dev/null +++ b/gooddata-flexfun/.readthedocs.yaml @@ -0,0 +1,19 @@ +# (C) 2024 GoodData Corporation +# Read the Docs configuration file for Sphinx projects +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +sphinx: + configuration: gooddata-flexfun/docs/conf.py + +python: + install: + - requirements: gooddata-flexfun/docs/requirements.txt diff --git a/gooddata-flexfun/Makefile b/gooddata-flexfun/Makefile new file mode 100644 index 000000000..4d49fba58 --- /dev/null +++ b/gooddata-flexfun/Makefile @@ -0,0 +1,19 @@ +# (C) 2024 GoodData Corporation +include ../project_common.mk + +.PHONY: docs +docs: + tox $(TOX_FLAGS) -e docs + + +.PHONY: dev-certs +dev-certs: + mkdir -p test_data + # create CA with self-signed certificate > generate keys + cert requests for server and client > sign + cd test_data && \ + rm -f *.pem && \ + openssl req -x509 -newkey rsa:4096 -days 3650 -nodes -keyout ca-key.pem -out ca-cert.pem -subj "/C=NA/ST=Unknown/L=Unknown/O=Unknown/OU=Unknown/CN=localhost/emailAddress=example@example.com" && \ + openssl req -newkey rsa:4096 -nodes -keyout server-key.pem -out server-req.pem -subj "/C=NA/ST=Unknown/L=Unknown/O=Unknown/OU=Computer/CN=localhost/emailAddress=example@example.com" && \ + openssl req -newkey rsa:4096 -nodes -keyout client-key.pem -out client-req.pem -subj "/C=NA/ST=Unknown/L=Unknown/O=Unknown/OU=Computer/CN=testClient1/emailAddress=example@example.com" && \ + openssl x509 -req -in server-req.pem -days 3650 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem && \ + openssl x509 -req -in client-req.pem -days 3650 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem diff --git a/gooddata-flexfun/README.md b/gooddata-flexfun/README.md new file mode 100644 index 000000000..a706bf8e4 --- /dev/null +++ b/gooddata-flexfun/README.md @@ -0,0 +1,3 @@ +# GoodData Flex function + +... diff --git a/gooddata-flexfun/gooddata_flexfun/__init__.py b/gooddata-flexfun/gooddata_flexfun/__init__.py new file mode 100644 index 000000000..f6eec5ed7 --- /dev/null +++ b/gooddata-flexfun/gooddata_flexfun/__init__.py @@ -0,0 +1,17 @@ +# (C) 2024 GoodData Corporation + +from gooddata_flexfun.flexfun.flex_fun import FlexFun +from gooddata_flexfun.flexfun.flex_fun_execution_context import ( + ExecutionContext, + ExecutionContextAbsoluteDateFilter, + ExecutionContextAttribute, + ExecutionContextAttributeSorting, + ExecutionContextNegativeAttributeFilter, + ExecutionContextPositiveAttributeFilter, + ExecutionContextRelativeDateFilter, + ExecutionRequest, + ExecutionType, + LabelElementsExecutionRequest, + ReportExecutionRequest, +) +from gooddata_flexfun.flexfun.flight_methods import create_flexfun_flight_methods diff --git a/gooddata-flight-server/gooddata_flight_server/flexfun/__init__.py b/gooddata-flexfun/gooddata_flexfun/flexfun/__init__.py similarity index 100% rename from gooddata-flight-server/gooddata_flight_server/flexfun/__init__.py rename to gooddata-flexfun/gooddata_flexfun/flexfun/__init__.py diff --git a/gooddata-flight-server/gooddata_flight_server/flexfun/flex_fun.py b/gooddata-flexfun/gooddata_flexfun/flexfun/flex_fun.py similarity index 97% rename from gooddata-flight-server/gooddata_flight_server/flexfun/flex_fun.py rename to gooddata-flexfun/gooddata_flexfun/flexfun/flex_fun.py index f58c44fa4..198fb4bc3 100644 --- a/gooddata-flight-server/gooddata_flight_server/flexfun/flex_fun.py +++ b/gooddata-flexfun/gooddata_flexfun/flexfun/flex_fun.py @@ -3,9 +3,7 @@ from typing import Optional import pyarrow - -from gooddata_flight_server.server.base import ServerContext -from gooddata_flight_server.tasks.base import ArrowData +from gooddata_flight_server import ArrowData, ServerContext class FlexFun(abc.ABC): diff --git a/gooddata-flight-server/gooddata_flight_server/flexfun/flex_fun_execution_context.py b/gooddata-flexfun/gooddata_flexfun/flexfun/flex_fun_execution_context.py similarity index 100% rename from gooddata-flight-server/gooddata_flight_server/flexfun/flex_fun_execution_context.py rename to gooddata-flexfun/gooddata_flexfun/flexfun/flex_fun_execution_context.py diff --git a/gooddata-flight-server/gooddata_flight_server/flexfun/flex_fun_registry.py b/gooddata-flexfun/gooddata_flexfun/flexfun/flex_fun_registry.py similarity index 96% rename from gooddata-flight-server/gooddata_flight_server/flexfun/flex_fun_registry.py rename to gooddata-flexfun/gooddata_flexfun/flexfun/flex_fun_registry.py index b7c973d56..a5a87bb3a 100644 --- a/gooddata-flight-server/gooddata_flight_server/flexfun/flex_fun_registry.py +++ b/gooddata-flexfun/gooddata_flexfun/flexfun/flex_fun_registry.py @@ -3,10 +3,9 @@ from collections.abc import Iterable import structlog +from gooddata_flight_server import ErrorInfo, ServerContext -from gooddata_flight_server.errors.error_info import ErrorInfo -from gooddata_flight_server.flexfun.flex_fun import FlexFun -from gooddata_flight_server.server.base import ServerContext +from gooddata_flexfun.flexfun.flex_fun import FlexFun class FlexFunRegistry: diff --git a/gooddata-flight-server/gooddata_flight_server/flexfun/flex_fun_task.py b/gooddata-flexfun/gooddata_flexfun/flexfun/flex_fun_task.py similarity index 87% rename from gooddata-flight-server/gooddata_flight_server/flexfun/flex_fun_task.py rename to gooddata-flexfun/gooddata_flexfun/flexfun/flex_fun_task.py index d450e36bf..5afdcde45 100644 --- a/gooddata-flight-server/gooddata_flight_server/flexfun/flex_fun_task.py +++ b/gooddata-flexfun/gooddata_flexfun/flexfun/flex_fun_task.py @@ -4,15 +4,9 @@ import pyarrow import structlog +from gooddata_flight_server import ArrowData, FlightDataTaskResult, Task, TaskError, TaskResult -from gooddata_flight_server.flexfun.flex_fun import FlexFun -from gooddata_flight_server.tasks.base import ArrowData -from gooddata_flight_server.tasks.task import Task -from gooddata_flight_server.tasks.task_error import TaskError -from gooddata_flight_server.tasks.task_result import ( - FlightDataTaskResult, - TaskResult, -) +from gooddata_flexfun.flexfun.flex_fun import FlexFun _LOGGER = structlog.get_logger("gooddata_flexfun.task") diff --git a/gooddata-flight-server/gooddata_flight_server/flexfun/flight_methods.py b/gooddata-flexfun/gooddata_flexfun/flexfun/flight_methods.py similarity index 94% rename from gooddata-flight-server/gooddata_flight_server/flexfun/flight_methods.py rename to gooddata-flexfun/gooddata_flexfun/flexfun/flight_methods.py index d524a93f4..c3102932c 100644 --- a/gooddata-flight-server/gooddata_flight_server/flexfun/flight_methods.py +++ b/gooddata-flexfun/gooddata_flexfun/flexfun/flight_methods.py @@ -5,22 +5,20 @@ import orjson import pyarrow.flight import structlog - -from gooddata_flight_server.errors.error_code import ErrorCode -from gooddata_flight_server.errors.error_info import ErrorInfo -from gooddata_flight_server.flexfun.flex_fun import FlexFun -from gooddata_flight_server.flexfun.flex_fun_registry import FlexFunRegistry -from gooddata_flight_server.flexfun.flex_fun_task import FlexFunTask -from gooddata_flight_server.server.base import ServerContext -from gooddata_flight_server.server.flight_rpc.server_methods import ( - FlightServerMethods, -) -from gooddata_flight_server.tasks.base import TaskWaitTimeoutError -from gooddata_flight_server.tasks.task_result import ( +from gooddata_flight_server import ( + ErrorCode, + ErrorInfo, FlightDataTaskResult, + FlightServerMethods, + ServerContext, TaskExecutionResult, + TaskWaitTimeoutError, ) +from gooddata_flexfun.flexfun.flex_fun import FlexFun +from gooddata_flexfun.flexfun.flex_fun_registry import FlexFunRegistry +from gooddata_flexfun.flexfun.flex_fun_task import FlexFunTask + _LOGGER = structlog.get_logger("gooddata_flexfun.rpc") _DEFAULT_TASK_WAIT = 60.0 diff --git a/gooddata-flexfun/mypy.ini b/gooddata-flexfun/mypy.ini new file mode 100644 index 000000000..7e7408647 --- /dev/null +++ b/gooddata-flexfun/mypy.ini @@ -0,0 +1,26 @@ +# (C) 2024 GoodData Corporation + [mypy] + plugins = pydantic.mypy + disallow_untyped_defs = True + warn_redundant_casts = True + strict_equality = True + no_implicit_optional = True + python_version = 3.9 + + [mypy-gooddata_api_client.*] + ignore_missing_imports = True + + [mypy-gooddata_sdk.*] + ignore_missing_imports = True + + [mypy-gooddata_flight_server.*] + ignore_missing_imports = True + + [mypy-pyarrow.*] + ignore_missing_imports = True + + [mypy-orjson.*] + ignore_missing_imports = True + + [mypy-structlog.*] + ignore_missing_imports = True diff --git a/gooddata-flexfun/requirements.txt b/gooddata-flexfun/requirements.txt new file mode 100644 index 000000000..b2cf846aa --- /dev/null +++ b/gooddata-flexfun/requirements.txt @@ -0,0 +1,6 @@ + orjson>=3.9.15,<4.0.0 + pyarrow>=16.1.0 + structlog>=24.0.0,<25.0.0 + + setuptools~=74.1.2 + typing_extensions~=4.12.2 diff --git a/gooddata-flexfun/setup.py b/gooddata-flexfun/setup.py new file mode 100644 index 000000000..743a0ff35 --- /dev/null +++ b/gooddata-flexfun/setup.py @@ -0,0 +1,68 @@ +# (C) 2024 GoodData Corporation +from pathlib import Path + +from setuptools import find_packages, setup + +this_directory = Path(__file__).parent +long_description = (this_directory / "README.md").read_text(encoding="utf-8") + +REQUIRES = [ + "dynaconf>=3.1.11,<4.0.0", + "gooddata-flight-server~=1.26.0", + "gooddata-sdk~=1.26.0", + "orjson>=3.9.15,<4.0.0", + "pyarrow>=16.1.0", + "structlog>=24.0.0,<25.0.0", +] + +setup( + name="gooddata-flexfun", + description="Set of gooddata-flight-server methods to host custom functions for GoodData Cloud", + long_description=long_description, + long_description_content_type="text/markdown", + version="1.26.0", + author="GoodData", + author_email="support@gooddata.com", + license="MIT", + license_file="LICENSE.txt", + license_files=("LICENSE.txt",), + install_requires=REQUIRES, + packages=find_packages(exclude=["tests*"]), + include_package_data=True, + python_requires=">=3.9.0", + project_urls={ + "Documentation": "https://gooddata-flexfun.readthedocs.io/en/v1.26.0", + "Source": "https://github.com/gooddata/gooddata-python-sdk", + }, + classifiers=[ + "Development Status :: 4 - Beta", + "Environment :: Console", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Database", + "Topic :: Scientific/Engineering", + "Topic :: Software Development", + "Typing :: Typed", + ], + keywords=[ + "gooddata", + "flight", + "rpc", + "flight rpc", + "custom functions", + "analytics", + "headless", + "business", + "intelligence", + "headless-bi", + "cloud", + "native", + "semantic", + "layer", + "sql", + "metrics", + ], +) diff --git a/gooddata-flexfun/test-requirements.txt b/gooddata-flexfun/test-requirements.txt new file mode 100644 index 000000000..80c3cdcf1 --- /dev/null +++ b/gooddata-flexfun/test-requirements.txt @@ -0,0 +1,2 @@ +pytest~=8.2.2 +pytest-cov~=5.0.0 diff --git a/gooddata-flexfun/tests/__init__.py b/gooddata-flexfun/tests/__init__.py new file mode 100644 index 000000000..06549c73b --- /dev/null +++ b/gooddata-flexfun/tests/__init__.py @@ -0,0 +1 @@ +# (C) 2024 GoodData Corporation diff --git a/gooddata-flexfun/tests/assert_error_info.py b/gooddata-flexfun/tests/assert_error_info.py new file mode 100644 index 000000000..333235576 --- /dev/null +++ b/gooddata-flexfun/tests/assert_error_info.py @@ -0,0 +1,11 @@ +# (C) 2024 GoodData Corporation +import pyarrow.flight +from gooddata_flight_server import ErrorCode, ErrorInfo + + +def assert_error_code(code: int, err: pyarrow.flight.FlightError): + info = ErrorInfo.maybe_from_pyarrow_error(err) + assert info is not None, "The error does not contain the ErrorInfo." + + if code != info.code: + raise AssertionError(f"Expected error code '{ErrorCode.name(code)}'. Got: '{ErrorCode.name(info.code)}'") diff --git a/gooddata-flight-server/tests/flexfun/__init__.py b/gooddata-flexfun/tests/flexfun/__init__.py similarity index 100% rename from gooddata-flight-server/tests/flexfun/__init__.py rename to gooddata-flexfun/tests/flexfun/__init__.py diff --git a/gooddata-flight-server/tests/flexfun/conftest.py b/gooddata-flexfun/tests/flexfun/conftest.py similarity index 100% rename from gooddata-flight-server/tests/flexfun/conftest.py rename to gooddata-flexfun/tests/flexfun/conftest.py diff --git a/gooddata-flight-server/tests/flexfun/test_flex_fun_execution_context.py b/gooddata-flexfun/tests/flexfun/test_flex_fun_execution_context.py similarity index 97% rename from gooddata-flight-server/tests/flexfun/test_flex_fun_execution_context.py rename to gooddata-flexfun/tests/flexfun/test_flex_fun_execution_context.py index 81a1f38b3..aaca69892 100644 --- a/gooddata-flight-server/tests/flexfun/test_flex_fun_execution_context.py +++ b/gooddata-flexfun/tests/flexfun/test_flex_fun_execution_context.py @@ -1,5 +1,5 @@ # (C) 2024 GoodData Corporation -from gooddata_flight_server.flexfun.flex_fun_execution_context import ( +from gooddata_flexfun.flexfun.flex_fun_execution_context import ( ExecutionContext, ExecutionContextAttribute, ExecutionContextNegativeAttributeFilter, diff --git a/gooddata-flight-server/tests/flexfun/test_registry.py b/gooddata-flexfun/tests/flexfun/test_registry.py similarity index 88% rename from gooddata-flight-server/tests/flexfun/test_registry.py rename to gooddata-flexfun/tests/flexfun/test_registry.py index c4e5aa4d2..6013eb70e 100644 --- a/gooddata-flight-server/tests/flexfun/test_registry.py +++ b/gooddata-flexfun/tests/flexfun/test_registry.py @@ -1,9 +1,8 @@ # (C) 2024 GoodData Corporation import pyarrow.flight import pytest -from gooddata_flight_server.errors.error_code import ErrorCode -from gooddata_flight_server.flexfun.flex_fun_registry import FlexFunRegistry -from gooddata_flight_server.server.base import ServerContext +from gooddata_flexfun.flexfun.flex_fun_registry import FlexFunRegistry +from gooddata_flight_server import ErrorCode, ServerContext from tests.assert_error_info import assert_error_code from tests.flexfun.testing_funs import Fun1, Fun2 diff --git a/gooddata-flight-server/tests/flexfun/testing_funs.py b/gooddata-flexfun/tests/flexfun/testing_funs.py similarity index 80% rename from gooddata-flight-server/tests/flexfun/testing_funs.py rename to gooddata-flexfun/tests/flexfun/testing_funs.py index 92c6a295d..85740c283 100644 --- a/gooddata-flight-server/tests/flexfun/testing_funs.py +++ b/gooddata-flexfun/tests/flexfun/testing_funs.py @@ -1,9 +1,8 @@ # (C) 2024 GoodData Corporation import pyarrow -from gooddata_flight_server.flexfun.flex_fun import FlexFun -from gooddata_flight_server.server.base import ServerContext -from gooddata_flight_server.tasks.base import ArrowData +from gooddata_flexfun.flexfun.flex_fun import FlexFun +from gooddata_flight_server import ArrowData, ServerContext class Fun1(FlexFun): diff --git a/gooddata-flexfun/tests/server/__init__.py b/gooddata-flexfun/tests/server/__init__.py new file mode 100644 index 000000000..06549c73b --- /dev/null +++ b/gooddata-flexfun/tests/server/__init__.py @@ -0,0 +1 @@ +# (C) 2024 GoodData Corporation diff --git a/gooddata-flexfun/tests/server/conftest.py b/gooddata-flexfun/tests/server/conftest.py new file mode 100644 index 000000000..9433775ff --- /dev/null +++ b/gooddata-flexfun/tests/server/conftest.py @@ -0,0 +1,103 @@ +# (C) 2024 GoodData Corporation +import contextlib +import os +import socket +from collections.abc import Iterable +from contextlib import closing +from pathlib import Path +from typing import Union + +import pytest +from gooddata_flexfun.flexfun.flight_methods import ( + create_flexfun_flight_methods, +) +from gooddata_flight_server import FlightServerMethods, FlightServerMethodsFactory, GoodDataFlightServer, create_server + +_CURRENT_DIR = Path(__file__).parent +_TLS_DIR = _CURRENT_DIR / "tls" + + +def _find_free_port(): + """ + see: https://stackoverflow.com/a/45690594 + """ + with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s: + s.bind(("127.0.0.1", 0)) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + return s.getsockname()[1] + + +def _clean_env_vars(): + to_drop = [key for key in os.environ if key.startswith("GOODDATA_FLIGHT")] + + for key in to_drop: + os.environ.pop(key, None) + + +@contextlib.contextmanager +def server( + methods: Union[FlightServerMethods, FlightServerMethodsFactory], + tls: bool = False, + mtls: bool = False, +) -> GoodDataFlightServer: + port = _find_free_port() + os.environ["GOODDATA_FLIGHT_SERVER__LISTEN_PORT"] = str(port) + os.environ["GOODDATA_FLIGHT_SERVER__ADVERTISE_HOST"] = "localhost" + + if tls: + cert = os.path.join(_TLS_DIR, "server-cert.pem") + key = os.path.join(_TLS_DIR, "server-key.pem") + os.environ["GOODDATA_FLIGHT_SERVER__USE_TLS"] = "TRUE" + os.environ["GOODDATA_FLIGHT_SERVER__TLS_CERTIFICATE"] = f"@{cert}" + os.environ["GOODDATA_FLIGHT_SERVER__TLS_PRIVATE_KEY"] = f"@{key}" + + if mtls: + ca_cert = os.path.join(_TLS_DIR, "ca-cert.pem") + os.environ["GOODDATA_FLIGHT_SERVER__TLS_ROOT_CERTIFICATE"] = f"@{ca_cert}" + + _server = create_server(methods) + _server.start() + + # started = _server.wait_for_start(timeout=5.0) + started = _server.wait_for_start() + if not started: + raise AssertionError(f"Test fixture unable to start server in time on port {port}.") + + yield _server + + _clean_env_vars() + _server.stop() + _server.wait_for_stop() + + +@contextlib.contextmanager +def flexfun_server( + modules: Iterable[str], + tls: bool = False, + mtls: bool = False, +) -> GoodDataFlightServer: + envvar = ", ".join([f'"{module}"' for module in modules]) + envvar = f"[{envvar}]" + + os.environ["GOODDATA_FLIGHT_FLEXFUN__FUNCTIONS"] = envvar + + with server(create_flexfun_flight_methods, tls, mtls) as s: + yield s + + +@pytest.fixture(scope="session") +def tls_ca_cert(): + with open(os.path.join(_TLS_DIR, "ca-cert.pem"), "rb") as f: + return f.read() + + +@pytest.fixture(scope="session") +def tls_client_cert(): + with open(os.path.join(_TLS_DIR, "client-cert.pem"), "rb") as f: + return f.read() + + +@pytest.fixture(scope="session") +def tls_client_key(): + with open(os.path.join(_TLS_DIR, "client-key.pem"), "rb") as f: + return f.read() diff --git a/gooddata-flight-server/tests/server/funs/__init__.py b/gooddata-flexfun/tests/server/funs/__init__.py similarity index 100% rename from gooddata-flight-server/tests/server/funs/__init__.py rename to gooddata-flexfun/tests/server/funs/__init__.py diff --git a/gooddata-flight-server/tests/server/funs/fun1.py b/gooddata-flexfun/tests/server/funs/fun1.py similarity index 85% rename from gooddata-flight-server/tests/server/funs/fun1.py rename to gooddata-flexfun/tests/server/funs/fun1.py index 7dda15181..8529e3e79 100644 --- a/gooddata-flight-server/tests/server/funs/fun1.py +++ b/gooddata-flexfun/tests/server/funs/fun1.py @@ -1,8 +1,8 @@ # (C) 2024 GoodData Corporation import pyarrow -from gooddata_flight_server.flexfun.flex_fun import FlexFun -from gooddata_flight_server.tasks.base import ArrowData +from gooddata_flexfun.flexfun.flex_fun import FlexFun +from gooddata_flight_server import ArrowData class _SimpleFun(FlexFun): diff --git a/gooddata-flight-server/tests/server/funs/fun2.py b/gooddata-flexfun/tests/server/funs/fun2.py similarity index 84% rename from gooddata-flight-server/tests/server/funs/fun2.py rename to gooddata-flexfun/tests/server/funs/fun2.py index 16661d0cf..09a335b9f 100644 --- a/gooddata-flight-server/tests/server/funs/fun2.py +++ b/gooddata-flexfun/tests/server/funs/fun2.py @@ -2,9 +2,8 @@ from typing import Optional import pyarrow -from gooddata_flight_server.flexfun.flex_fun import FlexFun -from gooddata_flight_server.server.base import ServerContext -from gooddata_flight_server.tasks.base import ArrowData +from gooddata_flexfun.flexfun.flex_fun import FlexFun +from gooddata_flight_server import ArrowData, ServerContext _DATA: Optional[pyarrow.Table] = None diff --git a/gooddata-flight-server/tests/server/test_flexfun_server.py b/gooddata-flexfun/tests/server/test_flexfun_server.py similarity index 100% rename from gooddata-flight-server/tests/server/test_flexfun_server.py rename to gooddata-flexfun/tests/server/test_flexfun_server.py diff --git a/gooddata-flexfun/tests/server/tls/ca-cert.pem b/gooddata-flexfun/tests/server/tls/ca-cert.pem new file mode 100644 index 000000000..7242311a1 --- /dev/null +++ b/gooddata-flexfun/tests/server/tls/ca-cert.pem @@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +MIIF/TCCA+WgAwIBAgIULlfleSLLlRCHANgVpiT/FhvcxIkwDQYJKoZIhvcNAQEL +BQAwgY0xCzAJBgNVBAYTAk5BMRAwDgYDVQQIDAdVbmtub3duMRAwDgYDVQQHDAdV +bmtub3duMRAwDgYDVQQKDAdVbmtub3duMRAwDgYDVQQLDAdVbmtub3duMRIwEAYD +VQQDDAlsb2NhbGhvc3QxIjAgBgkqhkiG9w0BCQEWE2V4YW1wbGVAZXhhbXBsZS5j +b20wHhcNMjQwOTEzMTEwMDE0WhcNMzQwOTExMTEwMDE0WjCBjTELMAkGA1UEBhMC +TkExEDAOBgNVBAgMB1Vua25vd24xEDAOBgNVBAcMB1Vua25vd24xEDAOBgNVBAoM +B1Vua25vd24xEDAOBgNVBAsMB1Vua25vd24xEjAQBgNVBAMMCWxvY2FsaG9zdDEi +MCAGCSqGSIb3DQEJARYTZXhhbXBsZUBleGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAJd/3kt8OfuPpp2R8HCnV4DLP6pbFhEziHoZGzee +mxwfH7Y4A3tNh1Lrdc3+c6jN9tVY2vQSUvo9v9auCk4Wc96LoOyyY0xYWe2nrIO1 +WgtC5/j3j3rZOKkHYdjtaGiud+1P0X9mK9zFF0w7UfoO/Z9OcryPG2S3rAjGIQSc +u/hAx7Y08VF2amIkBc7HTFJqXQcFRxPccQ+1SUaQN5nhVJCiX0eM94RjnYYC5GBr +3cL8ahexFhYE195ASoNR1c9PNnj1pgikrj8jJAe7X1OidYW/06tJs59dOv9OzPwz +ckcYhyOq1Caii5BYrp+QSjCojP7MtT1TOWGPII1eL0iXTMyasHZ9+4s1YLYNf0BS +VB0cLcmurXfCcz9fJXb1lwi0Hs6BJVPh2y8nG/pZK5EzpY3t5yE3Vq6m+eyEEWSG +uRetl8CSg+LtE+Q5KKEkuzvCl3JrpcIoV9+JYO64FlJ/BT8hhDiwEF7PDEaSmM2J +KIySWJ78CNY8AY1bp5DwXDjkTqgch8D/D34X/jLBhx1eVSZ3MVez8GJLl1GVK0UL +uEZXtOtyWU/7STRqOqCqltsvjdwijgdIOb/mDp8j9Rjav++OKCays1TaxPVSwXSl +1KQcx7r6FL6OvOzMYOW0Pkm8d9rEc3aLfpscIi37Y8mdN62LyMTuCTXKD1su6nDi +tXzzAgMBAAGjUzBRMB0GA1UdDgQWBBS3fBuz7gwb4bD3nLSgKB6AvpoEtzAfBgNV +HSMEGDAWgBS3fBuz7gwb4bD3nLSgKB6AvpoEtzAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4ICAQBiZR26yvizQuGCi3GQD2zQuRwycy31mKeH9FYNBdhZ +RLX45/v7tHMAMQxAPSeJ8RSpsK4Di8nQkz5u80KT/0j6P9yQWLwKbp5N0Sl7Eypf +YbjtWLTtj5RP0DuWFvdqPFlwHO0PP7jT8LVlW2KhCWmrc3SUACINnGJ1nmEgqv8c +inUt/SQKSXM7v/sNCiziW+r07ofI1XgAEtMiaWGsMcxSLFcCEko5hukqmVZtk4Ze +mRW5CaayTE46P6SBXOmlJA4C+srz8sQp9ss40R0YMzHP/H5pK/1CUa9oyrCPPjtu +69Gjj9k1NUi0sxbBIJg7TqS5m3Crf4xU0tE+GHqQJlai/Vbmh+TtgxnNSFhL8DbC +25MLvHHd5ROZT5wmH6c1bU3Y6CwIMOVi4v+flxhoGv9wfhTiyQKcATVKWCpKlYIr +RtP20HbhhyJLSVVFI0Ri0TQu+wsPlC7VrfB11ix5KQZtaTlCeDYSqS7iZnaDvIOb +T6mIzjccqTZD4gMT2nfEh2nUtCFa/PNgzL9C2KIviUyOBDAB+z9FQIv1NGuSyQIS +SbvEtLGcuuN6m/+2GZYuIm0hCGubBVY0upP/SiXFpUTlDpk0DpfcUwhjbWhSWDfj +TovIicWGEqJ4wwG9F7+9UrQMXJ4O/k0COMZlev1fnbYxnHFrB0RSI44/tm7FkQlq +cA== +-----END CERTIFICATE----- diff --git a/gooddata-flexfun/tests/server/tls/client-cert.pem b/gooddata-flexfun/tests/server/tls/client-cert.pem new file mode 100644 index 000000000..4ac9ca345 --- /dev/null +++ b/gooddata-flexfun/tests/server/tls/client-cert.pem @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/gooddata-flexfun/tests/server/tls/client-key.pem b/gooddata-flexfun/tests/server/tls/client-key.pem new file mode 100644 index 000000000..d065b029b --- /dev/null +++ b/gooddata-flexfun/tests/server/tls/client-key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDOUbYrUEgpV3oL +GPwcdQ0d87KGfwzrtjZ7qI5nTRj7bx8Ud0Jq9sn+jb9fPHUDMUEk2JGL1uyNP0XB +L8dXM4wDuAs8RfaFTut4qW5vy8Qm5WxJFpBrzEOQMVuHK4HvsGjpmtk9D82oMMsG +ZFQVKhaDnG1kjsyFfvHh6nWkdn4O4Ua8awidtInNlTjT7sxm9KZhFER+9AT4uakU +hXGcPrLlB1erYVwMECM3M9GSTWQ/x8/Q/TnP2VPZ4BfUCG9zBvP7qDDtTFak5a3f +aEbW1LTAg9kNcwMQYF5n9Wb92iQxME4jLsADMZzxozdqW2Rg0vuX0EHxKI5sZVt6 +qe0A2F+691fuO3sSc0ZBqJjb1ceTK8oA9SXIYHxRzghF+AU4HMyISJBogDQi3A1Y +4UIq6S6WSqVq+jhFPQOGQ0a1pFeDpXkU6NP4TFdsmYWr3F52HBRdLb6MZwt3/yBv +lC6NgPH5KUJ+y2Sp14ygjPhwfEf3a/QLqgEv6cwYdPsfKttar77R4YcLlDL/ueAw +hxgnF6scO8RIynniMREDeFllmMz3D2YB2t3Om1v+8e7ANfAQRBuQ/G31Fr1WGzSl +eFVAdJH1He/BdzFMIW/TGXUdorZr3miSU2A/fLREN4kgzihzcAidTjnbbFNw950j ++zhUaHlDcUp/o3QTsCGUSr6K00XLhQIDAQABAoICACs/WpG6ut2bnhP8cUBf0teP +8UCbGjDAmawTGYKS2SU/VkL6erwkLhRDTzWd3SNFrFOWZ+/ppd03wZ3sr3rabcOL +zSMdwT6RW++HiIQ7sMq8dZXeenh2MUVk6zwqxQpirqMlF9tiWCgkzjHxTuS+1UhS +PmYBPuLOyNIjzPQj+GmTFDpDr2MraGVlHavjFwqPxt57mp4H9ZDTjhskm7t2Mxaq +Etj0SBCpQ1B7drcVrOlnr2qt4fPtKNP3UtdZy07Pys3aJCNhyJm5IVi+qXa30Im4 +OYPFs4M3yCI/gQ6+Lq724rIiRxKEUFMgdOnA7YoUP7PDbkcoSq5zEplkTC9Mq8gL +Vg62x+HKqKSkJumOOFWc3F+Cz7pgP9U68c6PD36LVF+KPwxuGmwo710ICHM1d+Td +/8A5yhYSNwkAIpoH9AJND8pMU1bLATBXG7HIDJvL1vSci7GpHjB5X7bw5f0EkH24 +PGL/DsOo/9InqITMGWHK9Ag3kmv+fPQoPxEu2RR99Ge7YlasMbvdTX40ghbjBVq2 +pANy94Y/37nYjmLmp2YN/hxId4zgunGyps6XOYCw/dM2ZpCz197cq6+0Tfb+Uf6S +YvFCbf9PQnysBuyqrwD+47ENLNOVmGhAUrBs2SNX+tqUYSBW47pQxiUJjbZqPSNq +ifNpxA4DOx8Z8snr7f9zAoIBAQDr79kQdjVmi1JnDfbfAlBMKse9yV+jORHxYcXI +XdxFmQE+UcfVc3jH+DbgyBld1Ytx6JxJaMJq6ziPMcxGiWWgjyQ3e3kO6qUUgOQA +YEJIvfFByMg7xjmcRCqzOw2sgIQeFe98335zLvE8F/LBZLybJ0w1HRUEv2CKhFaR +Iix5aG1WOPf8yeGw1to3Q3WUGvkmNvr3eFB7vabfpJ9zDvBlo/5fNMjEJm4SraKo +lYNHouQq9v1R4CI10HkwKxknnFaLqDQhKwW1N3ik57muDmwIj8uuzmyxoRI5ACnc +5r53mjQKv7Caql/nr5+nnbY4qhAQ0d98nVeiv93F8y3r2E1/AoIBAQDf3Rw+OuKm +GTah4pjDMMn73R9Y5lVgueGLXQD1EsBCX5e5vT/+ld+LltMX5spoAR/7GTb7O8Pa +Ba7av2a27Uee7A7S1vsQXZN09F1+rf2NPKQKlylHAvwb80Sr74DwCqkbH624ZAqg +aJ7q2w9QkiZ83tbjadH1YmQEToYTHfGQSCSJVA6uM/8vJeBvcvtrM9LXaK8vDggz +ncbnlZRhr5bYV7RUNBcemo0PNjWZprIGDK5EfoD7KluNA2mVEZPargZ5R7xYc5y5 +/QByh1I0JvnKTIBMOQgSkZwIfL6ivISjVvLOGZ1XQR25iT6skp1eIqL17WdKuwwC +oHEhKeuBVjD7AoIBAA0VJaImC9v9ybnxKkk/ZZhzntPFQMpaNcZ+t2re2YH6c/ky +q7QITSA5gUGBlvZ/CtZsIY5ogq9PD7nQ9xTKNZprlYSGEjZjiHfUlc/3hnVmIuSU +75Vw7mzd0shRc/amwayxZrAz7F0Ss0mzwkA7B8JKsY0YabvzqLTFlc9CZ9jrk3R+ +gDHCOAOIRl1eHjzyKfKWheAHCd9yqrgn9rd4kpfwOgCpeqB1yRC8FBLpB3iHbcN8 +IpvRo9P8FVw4Z5KstpfT4eAc9JoR01zBhKhEIHVxE8hDpf9LgSkr+yZGnTUgldYq +vu40mFDOijnPIvWNaIqmOJA+YUei//cj/t3fBp0CggEAYE19VeP9FpkoIHIbZ3S4 +n4nbb2H+/pJYTZyfyc3cOXFoEvYv7nRI64LhopmdHyrEuD97oI5wTX0+YEoQhMcE +lYBVTCxBayPmSFzLT7DHr5eTth6bGjpVfCylsRViMWFUqB9zmywmSiVXoA7GwtFs +jzFJ3iDqupYuEpA5K0YpYfk3BoDLo/MoZv7zUt5y/AYaQKJ/Ik32B0Zrh7qYT4G6 +8ayhHcwe2gKAhje6zTOhx+pymXKWR/ZL1hjOtdsO8PcGP+w1QRPTK0uEgsBmA5t0 +v6szUhcCuwI6zofjdpyErsO7xh/MyPlxMRyygoi7/AAIfKU5VzOqEgM1R6AB+Oy8 +OwKCAQEAyOTQ/ytLtWPySeOLI23XBv7xfL/AX7Ny+fK7OjzyvIH9/qHiD3SuLoiq +BlVW2Vg8LXioeKKZJLs4XRQdysFCBku1TjYKWh0MF+MukJbNQ96TTVN+uaewbGq4 +um4RSf/PJzQXi02Us1UEKIU0rF8NAgBFXmMjcFjxDqiR5aamjXxfuWnSvPq9s6Su +vBH7jtrAy5pztc+W7jTSYge8ul42TDxS0p3qouSZvPUwC1uN2j/02Wype55apgB4 +YpK9VJxQ8QBndS1QIn0SoS5m9Kr/Kb3dxd58aryuO5F1Eb3xuRXic7V7m5oDeYBO +ZeU8QBy0L2+wZRtfqQlNZpkimP3S1w== +-----END PRIVATE KEY----- diff --git a/gooddata-flexfun/tests/server/tls/server-cert.pem b/gooddata-flexfun/tests/server/tls/server-cert.pem new file mode 100644 index 000000000..5251d9a08 --- /dev/null +++ b/gooddata-flexfun/tests/server/tls/server-cert.pem @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/gooddata-flexfun/tests/server/tls/server-key.pem b/gooddata-flexfun/tests/server/tls/server-key.pem new file mode 100644 index 000000000..1534476eb --- /dev/null +++ b/gooddata-flexfun/tests/server/tls/server-key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +Jh1drqEi0FT7mSL1hxOs8CmfjUtBsmM= +-----END PRIVATE KEY----- diff --git a/gooddata-flexfun/tox.ini b/gooddata-flexfun/tox.ini new file mode 100644 index 000000000..46a5bc532 --- /dev/null +++ b/gooddata-flexfun/tox.ini @@ -0,0 +1,36 @@ +# (C) 2024 GoodData Corporation +[tox] +envlist = py3{9,10,11} + +[testenv] +package = wheel +wheel_build_env = .pkg +deps = + -r{toxinidir}/test-requirements.txt + -e../gooddata-api-client + -e../gooddata-sdk + -e../gooddata-flight-server + -e../tests-support +setenv= + PYTHONDONTWRITEBYTECODE=1 +commands = + pytest -v --cov=gooddata_flexfun --cov-report=xml tests {posargs} + +[testenv:mypy] +basepython = python3.12 +skip_install = true +deps = + -r{toxinidir}/type-requirements.txt + -e../gooddata-api-client + -e../gooddata-sdk + -e../gooddata-flight-server +commands = + mypy gooddata_flexfun + +[testenv:docs] +basepython = python3.12 +skip_install = true +deps = + -r{toxinidir}/docs/requirements.txt +commands = + sphinx-build -b html docs docs/_build/html diff --git a/gooddata-flexfun/type-requirements.txt b/gooddata-flexfun/type-requirements.txt new file mode 100644 index 000000000..9622bb14d --- /dev/null +++ b/gooddata-flexfun/type-requirements.txt @@ -0,0 +1,2 @@ +mypy~=1.8.0 +pydantic~=2.6.0 diff --git a/gooddata-flight-server/gooddata_flight_server/__init__.py b/gooddata-flight-server/gooddata_flight_server/__init__.py index c9b96fb2b..ede51ad24 100644 --- a/gooddata-flight-server/gooddata_flight_server/__init__.py +++ b/gooddata-flight-server/gooddata_flight_server/__init__.py @@ -8,21 +8,6 @@ ) from gooddata_flight_server.errors.error_code import ErrorCode from gooddata_flight_server.errors.error_info import ErrorInfo, RetryInfo -from gooddata_flight_server.flexfun.flex_fun import FlexFun -from gooddata_flight_server.flexfun.flex_fun_execution_context import ( - ExecutionContext, - ExecutionContextAbsoluteDateFilter, - ExecutionContextAttribute, - ExecutionContextAttributeSorting, - ExecutionContextNegativeAttributeFilter, - ExecutionContextPositiveAttributeFilter, - ExecutionContextRelativeDateFilter, - ExecutionRequest, - ExecutionType, - LabelElementsExecutionRequest, - ReportExecutionRequest, -) -from gooddata_flight_server.flexfun.flight_methods import create_flexfun_flight_methods from gooddata_flight_server.health.server_health_monitor import ModuleHealthStatus, ServerHealthMonitor from gooddata_flight_server.server.auth.auth_middleware import TokenAuthMiddleware from gooddata_flight_server.server.auth.token_verifier import TokenVerificationStrategy diff --git a/gooddata-flight-server/gooddata_flight_server/cli.py b/gooddata-flight-server/gooddata_flight_server/cli.py index 8ceaf104c..7dc2b89a6 100644 --- a/gooddata-flight-server/gooddata_flight_server/cli.py +++ b/gooddata-flight-server/gooddata_flight_server/cli.py @@ -6,9 +6,6 @@ from dynaconf import ValidationError -from gooddata_flight_server.flexfun.flight_methods import ( - create_flexfun_flight_methods, -) from gooddata_flight_server.server.server_base import ( DEFAULT_LOGGING_INI, ServerStartupInterrupted, @@ -73,8 +70,9 @@ def _create_server(args: argparse.Namespace) -> GoodDataFlightServer: _config_files: tuple[str, ...] = args.config or () config_files = tuple(f for f in _config_files if f is not None) + # TODO add methods discovery return create_server( - methods=create_flexfun_flight_methods, + methods=None, config_files=config_files, logging_config=args.logging_config or DEFAULT_LOGGING_INI, dev_log=args.dev_log or False, diff --git a/gooddata-flight-server/gooddata_flight_server/server/server_main.py b/gooddata-flight-server/gooddata_flight_server/server/server_main.py index 8e7c369c0..4047dbeeb 100644 --- a/gooddata-flight-server/gooddata_flight_server/server/server_main.py +++ b/gooddata-flight-server/gooddata_flight_server/server/server_main.py @@ -5,9 +5,6 @@ from dynaconf import Dynaconf from gooddata_flight_server.config.config import ServerConfig, read_config -from gooddata_flight_server.flexfun.flight_methods import ( - create_flexfun_flight_methods, -) from gooddata_flight_server.server.base import ( FlightServerMethodsFactory, ServerContext, @@ -119,6 +116,8 @@ def create_server( ) initialize_otel_tracing(config=config.otel_config) - _methods = methods or create_flexfun_flight_methods - return GoodDataFlightServer(settings=settings, config=config, methods=_methods) + # TODO add methods discovery + assert methods + + return GoodDataFlightServer(settings=settings, config=config, methods=methods) diff --git a/gooddata-flight-server/setup.py b/gooddata-flight-server/setup.py index 93f82c6da..f2a46386d 100644 --- a/gooddata-flight-server/setup.py +++ b/gooddata-flight-server/setup.py @@ -8,7 +8,6 @@ REQUIRES = [ "dynaconf>=3.1.11,<4.0.0", - "gooddata-sdk~=1.26.0", "opentelemetry-api>=1.24.0,<=2.0.0", "opentelemetry-sdk>=1.24.0,<=2.0.0", "orjson>=3.8.5,<4.0.0", @@ -20,7 +19,7 @@ setup( name="gooddata-flight-server", - description="Flight RPC server to host custom functions for GoodData Cloud", + description="Flight RPC server to host custom functions", long_description=long_description, long_description_content_type="text/markdown", version="1.26.0", diff --git a/gooddata-flight-server/tests/server/conftest.py b/gooddata-flight-server/tests/server/conftest.py index d5e9fec5a..0e890b3df 100644 --- a/gooddata-flight-server/tests/server/conftest.py +++ b/gooddata-flight-server/tests/server/conftest.py @@ -2,15 +2,11 @@ import contextlib import os import socket -from collections.abc import Iterable from contextlib import closing from pathlib import Path from typing import Union import pytest -from gooddata_flight_server.flexfun.flight_methods import ( - create_flexfun_flight_methods, -) from gooddata_flight_server.server.base import FlightServerMethodsFactory from gooddata_flight_server.server.flight_rpc.server_methods import ( FlightServerMethods, @@ -77,21 +73,6 @@ def server( _server.wait_for_stop() -@contextlib.contextmanager -def flexfun_server( - modules: Iterable[str], - tls: bool = False, - mtls: bool = False, -) -> GoodDataFlightServer: - envvar = ", ".join([f'"{module}"' for module in modules]) - envvar = f"[{envvar}]" - - os.environ["GOODDATA_FLIGHT_FLEXFUN__FUNCTIONS"] = envvar - - with server(create_flexfun_flight_methods, tls, mtls) as s: - yield s - - @pytest.fixture(scope="session") def tls_ca_cert(): with open(os.path.join(_TLS_DIR, "ca-cert.pem"), "rb") as f: diff --git a/pyproject.toml b/pyproject.toml index 8c82ebfc6..299c8ed1b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,7 @@ target-version = "py39" "gooddata-dbt/gooddata_dbt/__init__.py" = ["F401"] "gooddata-fdw/gooddata_fdw/__init__.py" = ["F401"] "gooddata-flight-server/gooddata_flight_server/__init__.py" = ["F401"] +"gooddata-flexfun/gooddata_flexfun/__init__.py" = ["F401"] [tool.ruff.format] exclude = ['(gooddata-api-client|.*\.snapshot\..*)'] @@ -120,10 +121,20 @@ src = "gooddata-flight-server/setup.py" search = "version=\"{current_version}\"" [[tool.tbump.file]] -# gooddata-flight-server setup.py dependency -src = "gooddata-flight-server/setup.py" +# gooddata-flexfun setup.py +src = "gooddata-flexfun/setup.py" +search = "version=\"{current_version}\"" + +[[tool.tbump.file]] +# gooddata-flexfun setup.py dependency +src = "gooddata-flexfun/setup.py" search = "gooddata-sdk~={current_version}" +[[tool.tbump.file]] +# gooddata-flexfun setup.py dependency +src = "gooddata-flexfun/setup.py" +search = "gooddata-flight-server~={current_version}" + [[tool.tbump.file]] # clients README src = "gooddata-*-client/README.md" @@ -164,6 +175,10 @@ search = '"Documentation": "https://gooddata-fdw.readthedocs.io/en/v{current_ver src = "gooddata-flight-server/setup.py" search = '"Documentation": "https://gooddata-flight-server.readthedocs.io/en/v{current_version}"' +[[tool.tbump.file]] +src = "gooddata-flexfun/setup.py" +search = '"Documentation": "https://gooddata-flexfun.readthedocs.io/en/v{current_version}"' + # You can specify a list of commands to # run after the files have been patched # and before the git commit is made