Skip to content

R18 release #30

New issue

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

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

Already on GitHub? # to your account

Merged
merged 38 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
2a4b538
# Feature (2970): Update python client to support setup command (#22)
sudiptatj Oct 31, 2024
8723978
improve polyapi-python setup (#24)
eupharis Nov 4, 2024
7ece4d0
# Feature (3007): Update python -m polyapi function add --logs option…
sudiptatj Nov 4, 2024
e292e4e
Project Glide + Refactor main command line args parsing (#26)
aarongoin Nov 14, 2024
cd89d8a
fix for poly cache directory path construction
aarongoin Nov 18, 2024
a8c2f52
one more adjustment to the deployables cache directory so there can't…
aarongoin Nov 18, 2024
4a0277a
this better?
aarongoin Nov 18, 2024
571e85a
verbose logging on upload code to see what's failing in CI/CD
aarongoin Nov 18, 2024
dbbbe61
bumpity
aarongoin Nov 18, 2024
c03268e
whoops
aarongoin Nov 18, 2024
64c2e37
so close
aarongoin Nov 18, 2024
2f71748
better?
aarongoin Nov 18, 2024
57a2d40
okay this should be the fix
aarongoin Nov 18, 2024
0e78bd3
is it this?
aarongoin Nov 18, 2024
30b2a28
maybe
aarongoin Nov 18, 2024
156d3df
oh for the love of pete
aarongoin Nov 18, 2024
20d8982
whatever. might be a pypi issue
aarongoin Nov 19, 2024
37b421b
removing verbose logging
aarongoin Nov 19, 2024
4cc8a16
fixing bugs in sync command to use correct api urls
aarongoin Nov 19, 2024
aa0be64
update logging
aarongoin Nov 19, 2024
db8aec6
lint
aarongoin Nov 19, 2024
32a65d1
improved auth
aarongoin Nov 19, 2024
14cf1ce
last fix for function sync
aarongoin Nov 19, 2024
9d4824a
fix bug when comment arguments don't align with the function
aarongoin Nov 19, 2024
ffe19f0
try forcing the poly directory to exist
aarongoin Nov 20, 2024
0d32c4a
test logging
aarongoin Nov 20, 2024
8bbb2c7
remove debug logging
aarongoin Nov 20, 2024
2808c97
fixing project glide deployable types and bumping the version
aarongoin Nov 22, 2024
123f0b7
fixing missing arguments in python client function upload
aarongoin Nov 22, 2024
7dc7afe
fixing return type for trained functions
aarongoin Nov 22, 2024
e117f1e
fix bug preventing use of poly sync command locally
aarongoin Nov 22, 2024
d4a656f
next version of client!
eupharis Nov 26, 2024
7441019
EN #3183 allow null logs flag for python client (#28)
eneumann Dec 5, 2024
57e7369
let the typing_extensions versions increase to support latest openai …
eupharis Dec 6, 2024
03fd34c
update dependency in one more place
eupharis Dec 6, 2024
28a1c39
Some bug fixes for python client (#29)
aarongoin Dec 14, 2024
027ceb5
Merge branch 'main' into develop
eupharis Dec 23, 2024
4ff9ba9
0.3.2
eupharis Dec 23, 2024
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
6 changes: 3 additions & 3 deletions polyapi/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def execute_from_cli():
description="Manage your Poly API configurations and functions",
formatter_class=argparse.RawTextHelpFormatter
)

subparsers = parser.add_subparsers(help="Available commands")

###########################################################################
Expand Down Expand Up @@ -66,13 +66,13 @@ def generate_command(args):
fn_add_parser.add_argument("--description", required=False, default="", help="Description of the function")
fn_add_parser.add_argument("--server", action="store_true", help="Marks the function as a server function")
fn_add_parser.add_argument("--client", action="store_true", help="Marks the function as a client function")
fn_add_parser.add_argument("--logs", choices=["enabled", "disabled"], default="disabled", help="Enable or disable logs for the function.")
fn_add_parser.add_argument("--logs", choices=["enabled", "disabled"], default=None, help="Enable or disable logs for the function.")
fn_add_parser.add_argument("--execution-api-key", required=False, default="", help="API key for execution (for server functions only).")
fn_add_parser.add_argument("--disable-ai", "--skip-generate", action="store_true", help="Pass --disable-ai skip AI generation of missing descriptions")

def add_function(args):
initialize_config()
logs_enabled = args.logs == "enabled"
logs_enabled = args.logs == "enabled" if args.logs else None
err = ""
if args.server and args.client:
err = "Specify either `--server` or `--client`. Found both."
Expand Down
10 changes: 5 additions & 5 deletions polyapi/deployables.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ def update_deployment_comments(file_content: str, deployable: dict) -> str:
if deployable['deployments']:
deployment_comments = write_deploy_comments(deployable['deployments'])
deployable['deploymentCommentRanges'] = [(0, len(deployment_comments) + 1)]
file_content = f"{deployment_comments}{file_content}"
file_content = f"{deployment_comments}\n{file_content}"
return file_content

def update_deployable_function_comments(file_content: str, deployable: dict, disable_docs: bool = False) -> str:
Expand All @@ -261,7 +261,7 @@ def update_deployable_function_comments(file_content: str, deployable: dict, dis
if deployable["docStartIndex"] == deployable["docEndIndex"]:
# Function doesn't yet have any docstrings so we need to add additional whitespace
docstring = " " + docstring + "\n"

return f"{file_content[:deployable['docStartIndex']]}{docstring}{file_content[deployable['docEndIndex']:]}"
return file_content

Expand All @@ -271,17 +271,17 @@ def write_updated_deployable(deployable: dict, disable_docs: bool = False) -> di
"""
with open(deployable['file'], 'r', encoding='utf-8') as file:
file_contents = file.read()

if deployable['type'] in ['client-function', 'server-function']:
file_contents = update_deployable_function_comments(file_contents, deployable, disable_docs)
else:
raise ValueError(f"Unsupported deployable type: '{deployable['type']}'")

file_contents = update_deployment_comments(file_contents, deployable)

with open(deployable['file'], 'w', encoding='utf-8') as file:
file.write(file_contents)

deployable['fileRevision'] = get_deployable_file_revision(file_contents)
return deployable

Expand Down
12 changes: 7 additions & 5 deletions polyapi/function_cli.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import sys
from typing import Any, List
from typing import Any, List, Optional
import requests
from polyapi.generate import get_functions_and_parse, generate_functions
from polyapi.config import get_api_key_and_url
Expand All @@ -23,7 +23,7 @@ def function_add_or_update(
description: str,
client: bool,
server: bool,
logs_enabled: bool,
logs_enabled: Optional[bool],
generate: bool = True,
execution_api_key: str = ""
):
Expand All @@ -45,16 +45,18 @@ def function_add_or_update(
)
sys.exit(1)

if logs_enabled is None:
logs_enabled = parsed["config"].get("logs_enabled", None)

data = {
"context": context or parsed["context"],
"name": name,
"description": description or parsed["types"]["description"],
"code": code,
"language": "python",
"returnType": get_jsonschema_type(return_type),
"returnTypeSchema": parsed["types"]["returns"]["typeSchema"],
"arguments": [{**p, "key": p["name"], "type": get_jsonschema_type(p["type"]) } for p in parsed["types"]["params"]],
"logsEnabled": logs_enabled or parsed["config"].get("logs_enabled", False),
"arguments": [{**p, "key": p["name"], "type": get_jsonschema_type(p["type"])} for p in parsed["types"]["params"]],
"logsEnabled": logs_enabled,
}

if server and parsed["dependencies"]:
Expand Down
25 changes: 13 additions & 12 deletions polyapi/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def _parse_sphinx_docstring(docstring: str) -> Dict[str, Any]:
"type": "Any"
}
current_section = None

for line in lines:
stripped_line = line.strip()
if stripped_line.startswith(":param "):
Expand All @@ -56,7 +56,7 @@ def _parse_sphinx_docstring(docstring: str) -> Dict[str, Any]:
param_name = param_name.strip()
if param_name in params:
params[param_name]["description"] = param_desc.strip()
else:
else:
params[param_name] = { "name": param_name, "type": "", "description": param_desc.strip() }
current_section = param_name

Expand Down Expand Up @@ -118,7 +118,7 @@ def _parse_google_docstring(docstring: str) -> Dict[str, Any]:
for line in lines:
line = line.rstrip()
section_match = section_pattern.match(line)

if section_match:
mode = section_match.group(1).lower()
continue
Expand Down Expand Up @@ -181,7 +181,7 @@ def _get_schemas(code: str) -> List[Dict]:

def get_jsonschema_type(python_type: str):
if python_type == "Any":
return "Any"
return "any"

if python_type == "List":
return "array"
Expand Down Expand Up @@ -338,6 +338,7 @@ def parse_function_code(code: str, name: Optional[str] = "", context: Optional[s
"params": [],
"returns": {
"type": "",
"typeSchema": None,
"description": "",
}
},
Expand All @@ -364,7 +365,7 @@ def __init__(self):
self._line_offsets.append(
self._line_offsets[i-1] + len(self._lines[i-1])
)

self._extract_deploy_comments()

def visit_AnnAssign(self, node):
Expand Down Expand Up @@ -435,13 +436,14 @@ def _extract_docstring_from_function(self, node: ast.FunctionDef):

def _extract_deploy_comments(self):
for i in range(len(self._lines)):
line = self._lines[i].strip()
line = self._lines[i]
if line and not line.startswith("#"):
return
deployment = _parse_deploy_comment(line)
deployment = _parse_deploy_comment(line.strip())
if deployment:
start = self._line_offsets[i]
deployable["deployments"].append(deployment)
deployable["deploymentCommentRanges"].append([self._line_offsets[i], len(line)])
deployable["deploymentCommentRanges"].append([start, start + len(line)])

def visit_Import(self, node: ast.Import):
# TODO maybe handle `import foo.bar` case?
Expand Down Expand Up @@ -471,8 +473,7 @@ def visit_FunctionDef(self, node: ast.FunctionDef):
"type": python_type,
"description": "",
}
if type_schema:
json_arg["typeSchema"] = json.dumps(type_schema)
json_arg["typeSchema"] = json.dumps(type_schema) if type_schema else None

if docstring_params:
try:
Expand All @@ -482,7 +483,7 @@ def visit_FunctionDef(self, node: ast.FunctionDef):
if docstring_params[type_index]["type"] != python_type:
deployable["dirty"] = True
except:
pass
pass
else:
deployable["dirty"] = True

Expand All @@ -496,7 +497,7 @@ def visit_FunctionDef(self, node: ast.FunctionDef):
deployable["types"]["returns"]["typeSchema"] = return_type_schema
else:
deployable["types"]["returns"]["type"] = "Any"

def generic_visit(self, node):
if hasattr(node, 'lineno') and hasattr(node, 'col_offset'):
self._current_offset = self._line_offsets[node.lineno - 1] + node.col_offset
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ requires = ["setuptools>=61.2", "wheel"]

[project]
name = "polyapi-python"
version = "0.3.1"
version = "0.3.2"
description = "The Python Client for PolyAPI, the IPaaS by Developers for Developers"
authors = [{ name = "Dan Fellin", email = "dan@polyapi.io" }]
dependencies = [
"requests==2.31.0",
"typing_extensions==4.10.0",
"typing_extensions>=4.10.0",
"jsonschema-gentypes==2.6.0",
"pydantic==2.6.4",
"stdlib_list==0.10.0",
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
requests==2.31.0
typing_extensions==4.10.0
typing_extensions>=4.10.0
jsonschema-gentypes==2.6.0
pydantic==2.6.4
stdlib_list==0.10.0
Expand Down
17 changes: 13 additions & 4 deletions tests/test_deployables.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,26 @@ def foobar(foo: str, bar: Dict[str, str]) -> int:
"""A function that does something really import.

Args:
foo (str):
bar (Dict[str, str]):
foo (str):
bar (Dict[str, str]):

Returns:
int:
int:
"""
print("Okay then!")
return 7
'''

class T(unittest.TestCase):
def test_parse_and_write_deployment_comment(self):
test_deployable = parse_function_code(EXPECTED_SERVER_FN_DEPLOYMENTS, "foobar")
deployable_comment_ranges = test_deployable["deploymentCommentRanges"]
updated_file_contents = update_deployment_comments(EXPECTED_SERVER_FN_DEPLOYMENTS, test_deployable)
self.assertEqual(updated_file_contents, EXPECTED_SERVER_FN_DEPLOYMENTS)
# Deployment comment ranges collapsed into one of equal size
self.assertEqual(test_deployable["deploymentCommentRanges"][0][0], deployable_comment_ranges[0][0])
self.assertEqual(test_deployable["deploymentCommentRanges"][0][1], deployable_comment_ranges[1][1])

def test_write_deployment_comment(self):
test_deployable = {
"deployments": [
Expand All @@ -98,7 +107,7 @@ def test_write_deployment_comment(self):
'type': 'server-function'
}
],
"deploymentCommentRanges": [[0, 178]]
"deploymentCommentRanges": [[0, 177]]
}
updated_file_contents = update_deployment_comments(INITIAL_SERVER_FN_DEPLOYMENTS, test_deployable)
self.assertEqual(updated_file_contents, EXPECTED_SERVER_FN_DEPLOYMENTS)
Expand Down
27 changes: 23 additions & 4 deletions tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
from polyapi.parser import parse_function_code


CODE_NO_TYPES = """
def foobar(a, b):
return a + b
"""

SIMPLE_CODE = """
def foobar(n: int) -> int:
return 9
Expand Down Expand Up @@ -124,11 +129,21 @@ def foobar(foo: str, bar: Dict[str, str]) -> int:
'''

class T(unittest.TestCase):
def test_no_types(self):
deployable = parse_function_code(CODE_NO_TYPES, "foobar")
types = deployable["types"]
self.assertEqual(len(types["params"]), 2)
self.assertEqual(types["params"][0], {"name": "a", "type": "Any", "typeSchema": None, "description": ""})
self.assertEqual(types["params"][1], {"name": "b", "type": "Any", "typeSchema": None, "description": ""})
self.assertEqual(types["returns"]["type"], "Any")
self.assertIsNone(types["returns"]["typeSchema"])
self.assertEqual(deployable["dependencies"], [])

def test_simple_types(self):
deployable = parse_function_code(SIMPLE_CODE, "foobar")
types = deployable["types"]
self.assertEqual(len(types["params"]), 1)
self.assertEqual(types["params"][0], {"name": "n", "type": "int", "description": ""})
self.assertEqual(types["params"][0], {"name": "n", "type": "int", "typeSchema": None, "description": ""})
self.assertEqual(types["returns"]["type"], "int")
self.assertIsNone(types["returns"]["typeSchema"])
self.assertEqual(deployable["dependencies"], [])
Expand All @@ -137,7 +152,7 @@ def test_complex_return_type(self):
deployable = parse_function_code(COMPLEX_RETURN_TYPE, "foobar")
types = deployable["types"]
self.assertEqual(len(types["params"]), 1)
self.assertEqual(types["params"][0], {"name": "n", "type": "int", "description": ""})
self.assertEqual(types["params"][0], {"name": "n", "type": "int", "typeSchema": None, "description": ""})
self.assertEqual(types["returns"]["type"], "Barbar")
self.assertEqual(types["returns"]["typeSchema"]['title'], "Barbar")

Expand All @@ -153,7 +168,7 @@ def test_list_complex_return_type(self):
deployable = parse_function_code(LIST_COMPLEX_RETURN_TYPE, "foobar")
types = deployable["types"]
self.assertEqual(len(types["params"]), 1)
self.assertEqual(types["params"][0], {"name": "n", "type": "int", "description": ""})
self.assertEqual(types["params"][0], {"name": "n", "type": "int", "typeSchema": None, "description": ""})
self.assertEqual(types["returns"]["type"], "List[Barbar]")
self.assertEqual(types["returns"]["typeSchema"]["items"]['title'], "Barbar")

Expand All @@ -171,7 +186,7 @@ def test_parse_import_base(self):
code = "import requests\n\n\ndef foobar(n: int) -> int:\n return 9\n"
deployable = parse_function_code(code, "foobar")
self.assertEqual(deployable["dependencies"], [])

def test_parse_glide_server_function_no_docstring(self):
code = GLIDE_SIMPLE_SERVER_FN
deployable = parse_function_code(code, "foobar")
Expand All @@ -186,11 +201,13 @@ def test_parse_glide_server_function_bad_docstring(self):
self.assertEqual(deployable["types"]["params"][0], {
"name": "foo",
"type": "Any",
"typeSchema": None,
"description": "The foo in question"
})
self.assertEqual(deployable["types"]["params"][1], {
"name": "bar",
"type": "Any",
"typeSchema": None,
"description": "Configuration of bars"
})
self.assertEqual(deployable["types"]["returns"], {
Expand All @@ -205,11 +222,13 @@ def test_parse_glide_server_function_ok_docstring(self):
self.assertEqual(deployable["types"]["params"][0], {
"name": "foo",
"type": "str",
"typeSchema": None,
"description": "The foo in question"
})
self.assertEqual(deployable["types"]["params"][1], {
"name": "bar",
"type": "Dict[str, str]",
"typeSchema": None,
"description": "Configuration of bars"
})
self.assertEqual(deployable["types"]["returns"], {
Expand Down
Loading