Skip to content
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

v3.6.0 #36

Merged
merged 1 commit into from
Apr 17, 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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# Changelog

## v3.5.7 (2024-04-17)
## v3.6.0 (2024-04-18)

### Updates

* modified dict response for `executeStmt`
* modified error response for `execute`

## v3.5.4 (2024-04-11)

Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -194,4 +194,4 @@ To publish the package to PyPI, run the following command:

::

twine upload --config-file .pypirc dist/pystackql-3.5.7.tar.gz
twine upload --config-file .pypirc dist/pystackql-3.6.0.tar.gz
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
# The short X.Y version
version = ''
# The full version, including alpha/beta/rc tags
release = '3.5.7'
release = '3.6.0'


# -- General configuration ---------------------------------------------------
Expand Down
76 changes: 55 additions & 21 deletions pystackql/stackql.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,17 @@ def _run_query(self, query):
:type query: str

:return: The output result of the query, which can either be the actual query result or an error message.
:rtype: str
:rtype: dict

Example:
::

{
"data": "[{\"machine_type\": \"n1-standard-1\", \"status\": \"RUNNING\", \"num_instances\": 3}, ...]",
"error": "stderr message if present",
"exception": "ERROR: {\"exception\": \"<exception message>\", \"doc\": \"<exception doc>\", \"params\": \"<params>\", \"stdout\": \"<stdout>\", \"stderr\": \"<stderr>\"}
}

Possible error messages include:
- Indications that the StackQL binary wasn't found.
- Generic error messages for other exceptions encountered during the query execution.
Expand Down Expand Up @@ -219,11 +228,6 @@ def _run_query(self, query):
}
output["exception"] = f"ERROR: {json.dumps(error_details)}"

# output = {'data': <stdout str>, 'error': <stderr str>, 'exception': <exception as a json string> }
# for a statement you would expect 'error' to exist
# for a query you would expect 'data' to exist
# 'exception' in output indicates an error occurred during the execution (statement or query)

return output

def __init__(self,
Expand Down Expand Up @@ -487,12 +491,20 @@ def executeStmt(self, query):
else:
return result
else:

# returns either...
# {'error': '<error message>'} if something went wrong; or
# {'message': '<message>'} if the statement was executed successfully

result = self._run_query(query)
if "exception" in result:
return {"error": result["exception"]}
exception_msg = result["exception"]
if self.output == 'pandas':
return pd.DataFrame({'error': [exception_msg]}) if exception_msg else pd.DataFrame({'error': []})
elif self.output == 'csv':
return exception_msg
else:
return {"error": exception_msg}

# message on stderr
message = result["error"]
Expand Down Expand Up @@ -543,35 +555,57 @@ def execute(self, query, suppress_errors=True):
return result
else:
# returns either...
# {'error': <error json str>} if something went wrong; or
# [{<data>}] if the statement was executed successfully, messages to stderr are ignored
# [{'error': <error json str>}] if something went wrong; or
# [{<row1>},...] if the statement was executed successfully, messages to stderr are ignored

output = self._run_query(query)
if "exception" in output:
return {"error": output["exception"]}
exception_msg = output["exception"]
if self.output == 'pandas':
return pd.DataFrame({'error': [exception_msg]}) if exception_msg else pd.DataFrame({'error': []})
elif self.output == 'csv':
return exception_msg
else:
return [{"error": exception_msg}]

if "data" in output:
data = output["data"]
# theres data, return it
if self.output == 'csv':
return output["data"]
return data
elif self.output == 'pandas':
try:
return pd.read_json(StringIO(output["data"]))
return pd.read_json(StringIO(data))
except ValueError:
return pd.DataFrame([{"error": "Invalid JSON output"}])
else: # Assume 'dict' output
try:
return json.loads(output["data"])
return json.loads(data)
except ValueError:
return {"error": f"Invalid JSON output : {output['data']}"}
else:
if "error" in output:
if suppress_errors:
return []
else:
return {"error": output["error"]}
return [{"error": f"Invalid JSON output : {data}"}]

if "error" in output:
# theres no data but there is stderr from the request, could be an expected error like a 404
if suppress_errors:
# we dont care about errors, return an empty list
csv_ret = ""
pd_ret = pd.DataFrame()
dict_ret = []
else:
# we care about errors, return the error
err_msg = output["error"]
csv_ret = err_msg
pd_ret = pd.DataFrame([{"error": err_msg}])
dict_ret = [{"error": err_msg}]

if self.output == 'csv':
return csv_ret
elif self.output == 'pandas':
return pd_ret
else: # Assume 'dict' output
return dict_ret


#
# asnyc query support
#

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

setup(
name='pystackql',
version='3.5.7',
version='3.6.0',
description='A Python interface for StackQL',
long_description=readme,
author='Jeffrey Aven',
Expand Down