Skip to content

#55 Fixed the empty input bug #57

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pytest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [ "3.8", "3.10" ]
python-version: [ "3.10", "3.11" ]
runs-on: ubuntu-latest

steps:
Expand Down
6 changes: 5 additions & 1 deletion doc/changes/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ Code name: tbd

### Bugs

n/a
* #55: Fixed bug when creating a `StandaloneMockContext` with empty input list

### Features

* #56: Made `script_code_wrapper_function` parameter of the `MockMetaData` optional.
47 changes: 26 additions & 21 deletions exasol_udf_mock_python/mock_context.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import List, Tuple, Iterator, Iterable, Any, Optional, Union
from collections.abc import Sized
from functools import wraps

import pandas as pd
Expand Down Expand Up @@ -133,24 +134,30 @@ def emit(self, *args) -> None:
self._current_context.emit(*args)


def get_scalar_input(inp: Any) -> Iterable[Tuple[Any, ...]]:
def get_scalar_input(inp: Any) -> Iterable[Iterable[Any]]:
"""
Figures out if the SCALAR parameters are provided as a scalar value or a tuple
and also if there is a wrapping container around.
Unless the parameters are already in a wrapping container returns parameters as a tuple wrapped
into a one-item list, e.g [(param1[, param2, ...)]. Otherwise, returns the original input.
Unless the parameters are already in a wrapping Sized container, returns parameters as an iterable
wrapped into a one-item list, e.g [(param1, [param2, ...])]. Otherwise, returns the original input.

:param inp: Input parameters.
"""

if isinstance(inp, Iterable) and not isinstance(inp, str):
row1 = next(iter(inp))
if isinstance(row1, Iterable) and not isinstance(row1, str):
return inp
else:
return [inp]
else:
return [(inp,)]
if inp is not None:
if (not isinstance(inp, Iterable)) or isinstance(inp, str):
return [(inp,)]
try:
row1 = next(iter(inp))
if (not isinstance(row1, Iterable)) or isinstance(row1, str):
return [inp]
elif not isinstance(inp, Sized):
return list(inp)
else:
return inp
except StopIteration:
pass
return [tuple()]


class StandaloneMockContext(UDFContext):
Expand Down Expand Up @@ -205,20 +212,18 @@ def get_dataframe(self, num_rows='all', start_col=0):
columns_ = [column.name for column in self._metadata.input_columns[start_col:]]

i = 0
df = None
dfs: list[pd.DataFrame] = []
while num_rows == 'all' or i < num_rows:
df_current = pd.DataFrame.from_records(
[self._data[start_col:]], columns=columns_)
if df is None:
df = df_current
else:
df = df.append(df_current)
dfs.append(pd.DataFrame.from_records(
[self._data[start_col:]], columns=columns_))
if not self.next():
break
i += 1
if df is not None:
df = df.reset_index(drop=True)
return df
if dfs:
df = pd.concat(dfs, ignore_index=True)
df.reset_index(inplace=True, drop=True)
return df
return None

def __getattr__(self, name):
return None if self._data is None else self._data[self._name_position_map[name]]
Expand Down
3 changes: 2 additions & 1 deletion exasol_udf_mock_python/mock_meta_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ def __init__(
self._current_user = current_user
self._current_schema = current_schema
self._scope_user = scope_user
self._script_code = self._extract_script_code(script_code_wrapper_function)
self._script_code = (None if script_code_wrapper_function is None
else self._extract_script_code(script_code_wrapper_function))
self._connection_id = connection_id
self._database_name = database_name
self._database_version = database_version
Expand Down
Loading