# UDF Mock for Python
This projects provides a mock runner for Python3 UDFs which allows you
to test your UDFs locally without a database.
**Note:** This project is in a very early development phase.
Please, be aware that the behavior of the mock runner doesn't perfectly
reflect the behaviors of the UDFs inside the database and that the interface still can change.
In any case, you need to verify your UDFs with integrations test inside the database.
## Getting started
**Attention:** We changed the default branch to main and the master branch is deprecated.
### Installing via pip
```
pip install exasol-udf-mock-python
```
### Installing via poetry
Add it to your `tool.poetry.dependencies` or `tool.poetry.dev-dependencies`
```
[tool.poetry.dev-dependencies]
exasol-udf-mock-python = "^0.1.0"
...
```
### How to use the Mock
The mock runner runs your python UDF in a python environment in which
no external variables, functions or classes are visble.
This means in practice, you can only use things you defined inside your
UDF and what gets provided by the UDF frameworks,
such as exa.meta and the context for the run function.
This includes imports, variables, functions, classes and so on.
You define a UDF in this framework within in a wrapper function.
This wrapper function then contains all necessary imports, functions,
variables and classes.
You then handover the wrapper function to the `UDFMockExecutor`
which runs the UDF inside if the isolated python environment.
The following example shows, how you use this framework:
The following example shows the general setup for a test with the Mock:
```
def udf_wrapper():
def run(ctx):
return ctx.t1+1, ctx.t2+1.1, ctx.t3+"1"
executor = UDFMockExecutor()
meta = MockMetaData(
script_code_wrapper_function=udf_wrapper,
input_type="SCALAR",
input_columns=[Column("t1", int, "INTEGER"),
Column("t2", float, "FLOAT"),
Column("t3", str, "VARCHAR(20000)")],
output_type="RETURNS",
output_columns=[Column("t1", int, "INTEGER"),
Column("t2", float, "FLOAT"),
Column("t3", str, "VARCHAR(20000)")]
)
exa = MockExaEnvironment(meta)
result = executor.run([Group([(1,1.0,"1"), (5,5.0,"5"), (6,6.0,"6")])], exa)
```
**Checkout the [tests](tests) for more information about, how to use the Mock.**
## Limitations or missing features
Some of the following limitations are fundamental, other are missing
feature and might get removed by later releases:
- Data type checks for outputs are more strict as in real UDFs
- No support for Import or Export Specification or Virtual Schema adapter
- No support for dynamic input and output parameters
- No support for exa.import_script
- No BucketFS
- Execution is not isolated in a container
- Can access and manipulate the file system of the system running the Mock
- UDF inside of the database only can write /tmp to tmp and
only see the file system of the script-language container and the mounted bucketfs
- Can use all python package available in the system running the Mock
- If you use package which are currently not available in the script-language containers,
you need create your own container for testing inside of the database
- Does not emulate the ressource limitations which get a applied in the database
- Only one instance of the UDF gets executed
- No support for Python2, because Python2 is officially End of Life
Raw data
{
"_id": null,
"home_page": "https://github.com/exasol/udf-mock-python",
"name": "exasol-udf-mock-python",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.10",
"maintainer_email": null,
"keywords": "exasol, udf, mock, testing",
"author": "Torsten Kilias",
"author_email": "torsten.kilias@exasol.com",
"download_url": "https://files.pythonhosted.org/packages/13/78/9a7ac7fca2bcc24f132c6dfdc4f5e9e45dc409aa221ee4278558f5b80762/exasol_udf_mock_python-0.3.0.tar.gz",
"platform": null,
"description": "# UDF Mock for Python\n\nThis projects provides a mock runner for Python3 UDFs which allows you\nto test your UDFs locally without a database.\n\n**Note:** This project is in a very early development phase.\nPlease, be aware that the behavior of the mock runner doesn't perfectly\nreflect the behaviors of the UDFs inside the database and that the interface still can change.\nIn any case, you need to verify your UDFs with integrations test inside the database.\n\n## Getting started\n\n**Attention:** We changed the default branch to main and the master branch is deprecated.\n\n### Installing via pip\n```\npip install exasol-udf-mock-python\n```\n\n### Installing via poetry\nAdd it to your `tool.poetry.dependencies` or `tool.poetry.dev-dependencies`\n\n```\n[tool.poetry.dev-dependencies]\nexasol-udf-mock-python = \"^0.1.0\"\n...\n```\n\n### How to use the Mock\n\nThe mock runner runs your python UDF in a python environment in which\nno external variables, functions or classes are visble.\nThis means in practice, you can only use things you defined inside your\nUDF and what gets provided by the UDF frameworks,\nsuch as exa.meta and the context for the run function.\nThis includes imports, variables, functions, classes and so on.\n\nYou define a UDF in this framework within in a wrapper function.\nThis wrapper function then contains all necessary imports, functions,\nvariables and classes.\nYou then handover the wrapper function to the `UDFMockExecutor`\nwhich runs the UDF inside if the isolated python environment.\nThe following example shows, how you use this framework:\nThe following example shows the general setup for a test with the Mock:\n\n```\ndef udf_wrapper():\n\n def run(ctx):\n return ctx.t1+1, ctx.t2+1.1, ctx.t3+\"1\"\n\nexecutor = UDFMockExecutor()\nmeta = MockMetaData(\n script_code_wrapper_function=udf_wrapper,\n input_type=\"SCALAR\",\n input_columns=[Column(\"t1\", int, \"INTEGER\"),\n Column(\"t2\", float, \"FLOAT\"),\n Column(\"t3\", str, \"VARCHAR(20000)\")],\n output_type=\"RETURNS\",\n output_columns=[Column(\"t1\", int, \"INTEGER\"),\n Column(\"t2\", float, \"FLOAT\"),\n Column(\"t3\", str, \"VARCHAR(20000)\")]\n)\nexa = MockExaEnvironment(meta)\nresult = executor.run([Group([(1,1.0,\"1\"), (5,5.0,\"5\"), (6,6.0,\"6\")])], exa)\n```\n\n**Checkout the [tests](tests) for more information about, how to use the Mock.**\n\n## Limitations or missing features\n\nSome of the following limitations are fundamental, other are missing\nfeature and might get removed by later releases:\n\n- Data type checks for outputs are more strict as in real UDFs\n- No support for Import or Export Specification or Virtual Schema adapter\n- No support for dynamic input and output parameters\n- No support for exa.import_script\n- No BucketFS\n- Execution is not isolated in a container\n - Can access and manipulate the file system of the system running the Mock\n - UDF inside of the database only can write /tmp to tmp and\n only see the file system of the script-language container and the mounted bucketfs\n - Can use all python package available in the system running the Mock\n - If you use package which are currently not available in the script-language containers,\n you need create your own container for testing inside of the database\n - Does not emulate the ressource limitations which get a applied in the database\n- Only one instance of the UDF gets executed\n- No support for Python2, because Python2 is officially End of Life\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Mocking framework for Exasol Python UDFs",
"version": "0.3.0",
"project_urls": {
"Homepage": "https://github.com/exasol/udf-mock-python",
"Repository": "https://github.com/exasol/udf-mock-python"
},
"split_keywords": [
"exasol",
" udf",
" mock",
" testing"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "d05339fccc4c5353866822a1f11042e6449bb377bee8ec395dc7bc0451554949",
"md5": "ba11402bc2dee7a58c8ef6c708b35126",
"sha256": "a5c59b5ecbb4efc700d5b35ebda2415b69da42a33bbf9feba377e95a3535bb94"
},
"downloads": -1,
"filename": "exasol_udf_mock_python-0.3.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "ba11402bc2dee7a58c8ef6c708b35126",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.10",
"size": 13486,
"upload_time": "2024-11-15T15:08:24",
"upload_time_iso_8601": "2024-11-15T15:08:24.889978Z",
"url": "https://files.pythonhosted.org/packages/d0/53/39fccc4c5353866822a1f11042e6449bb377bee8ec395dc7bc0451554949/exasol_udf_mock_python-0.3.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "13789a7ac7fca2bcc24f132c6dfdc4f5e9e45dc409aa221ee4278558f5b80762",
"md5": "5e135d1600409d6d1e0ad95d37495920",
"sha256": "d8a39504aabd3d9e3e5e7c6f2771cf14181f1fc09d8095115be68df0ced562cf"
},
"downloads": -1,
"filename": "exasol_udf_mock_python-0.3.0.tar.gz",
"has_sig": false,
"md5_digest": "5e135d1600409d6d1e0ad95d37495920",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.10",
"size": 11781,
"upload_time": "2024-11-15T15:08:25",
"upload_time_iso_8601": "2024-11-15T15:08:25.819168Z",
"url": "https://files.pythonhosted.org/packages/13/78/9a7ac7fca2bcc24f132c6dfdc4f5e9e45dc409aa221ee4278558f5b80762/exasol_udf_mock_python-0.3.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-15 15:08:25",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "exasol",
"github_project": "udf-mock-python",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "exasol-udf-mock-python"
}