polyapi-python 0.3.1.dev17__tar.gz → 0.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. {polyapi_python-0.3.1.dev17/polyapi_python.egg-info → polyapi_python-0.3.2}/PKG-INFO +2 -2
  2. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/cli.py +3 -3
  3. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/deployables.py +5 -5
  4. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/function_cli.py +7 -5
  5. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/parser.py +13 -12
  6. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2/polyapi_python.egg-info}/PKG-INFO +2 -2
  7. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi_python.egg-info/requires.txt +1 -1
  8. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/pyproject.toml +2 -2
  9. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/tests/test_deployables.py +13 -4
  10. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/tests/test_parser.py +23 -4
  11. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/LICENSE +0 -0
  12. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/README.md +0 -0
  13. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/__init__.py +0 -0
  14. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/__main__.py +0 -0
  15. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/api.py +0 -0
  16. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/auth.py +0 -0
  17. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/client.py +0 -0
  18. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/config.py +0 -0
  19. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/constants.py +0 -0
  20. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/error_handler.py +0 -0
  21. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/exceptions.py +0 -0
  22. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/execute.py +0 -0
  23. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/generate.py +0 -0
  24. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/prepare.py +0 -0
  25. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/py.typed +0 -0
  26. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/rendered_spec.py +0 -0
  27. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/schema.py +0 -0
  28. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/server.py +0 -0
  29. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/sync.py +0 -0
  30. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/typedefs.py +0 -0
  31. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/utils.py +0 -0
  32. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/variables.py +0 -0
  33. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi/webhook.py +0 -0
  34. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi_python.egg-info/SOURCES.txt +0 -0
  35. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi_python.egg-info/dependency_links.txt +0 -0
  36. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/polyapi_python.egg-info/top_level.txt +0 -0
  37. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/setup.cfg +0 -0
  38. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/tests/test_api.py +0 -0
  39. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/tests/test_auth.py +0 -0
  40. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/tests/test_rendered_spec.py +0 -0
  41. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/tests/test_schema.py +0 -0
  42. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/tests/test_server.py +0 -0
  43. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/tests/test_utils.py +0 -0
  44. {polyapi_python-0.3.1.dev17 → polyapi_python-0.3.2}/tests/test_variables.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: polyapi-python
3
- Version: 0.3.1.dev17
3
+ Version: 0.3.2
4
4
  Summary: The Python Client for PolyAPI, the IPaaS by Developers for Developers
5
5
  Author-email: Dan Fellin <dan@polyapi.io>
6
6
  License: MIT License
@@ -29,7 +29,7 @@ Requires-Python: >=3.10
29
29
  Description-Content-Type: text/markdown
30
30
  License-File: LICENSE
31
31
  Requires-Dist: requests==2.31.0
32
- Requires-Dist: typing_extensions==4.10.0
32
+ Requires-Dist: typing_extensions>=4.10.0
33
33
  Requires-Dist: jsonschema-gentypes==2.6.0
34
34
  Requires-Dist: pydantic==2.6.4
35
35
  Requires-Dist: stdlib_list==0.10.0
@@ -21,7 +21,7 @@ def execute_from_cli():
21
21
  description="Manage your Poly API configurations and functions",
22
22
  formatter_class=argparse.RawTextHelpFormatter
23
23
  )
24
-
24
+
25
25
  subparsers = parser.add_subparsers(help="Available commands")
26
26
 
27
27
  ###########################################################################
@@ -66,13 +66,13 @@ def execute_from_cli():
66
66
  fn_add_parser.add_argument("--description", required=False, default="", help="Description of the function")
67
67
  fn_add_parser.add_argument("--server", action="store_true", help="Marks the function as a server function")
68
68
  fn_add_parser.add_argument("--client", action="store_true", help="Marks the function as a client function")
69
- fn_add_parser.add_argument("--logs", choices=["enabled", "disabled"], default="disabled", help="Enable or disable logs for the function.")
69
+ fn_add_parser.add_argument("--logs", choices=["enabled", "disabled"], default=None, help="Enable or disable logs for the function.")
70
70
  fn_add_parser.add_argument("--execution-api-key", required=False, default="", help="API key for execution (for server functions only).")
71
71
  fn_add_parser.add_argument("--disable-ai", "--skip-generate", action="store_true", help="Pass --disable-ai skip AI generation of missing descriptions")
72
72
 
73
73
  def add_function(args):
74
74
  initialize_config()
75
- logs_enabled = args.logs == "enabled"
75
+ logs_enabled = args.logs == "enabled" if args.logs else None
76
76
  err = ""
77
77
  if args.server and args.client:
78
78
  err = "Specify either `--server` or `--client`. Found both."
@@ -245,7 +245,7 @@ def update_deployment_comments(file_content: str, deployable: dict) -> str:
245
245
  if deployable['deployments']:
246
246
  deployment_comments = write_deploy_comments(deployable['deployments'])
247
247
  deployable['deploymentCommentRanges'] = [(0, len(deployment_comments) + 1)]
248
- file_content = f"{deployment_comments}{file_content}"
248
+ file_content = f"{deployment_comments}\n{file_content}"
249
249
  return file_content
250
250
 
251
251
  def update_deployable_function_comments(file_content: str, deployable: dict, disable_docs: bool = False) -> str:
@@ -261,7 +261,7 @@ def update_deployable_function_comments(file_content: str, deployable: dict, dis
261
261
  if deployable["docStartIndex"] == deployable["docEndIndex"]:
262
262
  # Function doesn't yet have any docstrings so we need to add additional whitespace
263
263
  docstring = " " + docstring + "\n"
264
-
264
+
265
265
  return f"{file_content[:deployable['docStartIndex']]}{docstring}{file_content[deployable['docEndIndex']:]}"
266
266
  return file_content
267
267
 
@@ -271,17 +271,17 @@ def write_updated_deployable(deployable: dict, disable_docs: bool = False) -> di
271
271
  """
272
272
  with open(deployable['file'], 'r', encoding='utf-8') as file:
273
273
  file_contents = file.read()
274
-
274
+
275
275
  if deployable['type'] in ['client-function', 'server-function']:
276
276
  file_contents = update_deployable_function_comments(file_contents, deployable, disable_docs)
277
277
  else:
278
278
  raise ValueError(f"Unsupported deployable type: '{deployable['type']}'")
279
279
 
280
280
  file_contents = update_deployment_comments(file_contents, deployable)
281
-
281
+
282
282
  with open(deployable['file'], 'w', encoding='utf-8') as file:
283
283
  file.write(file_contents)
284
-
284
+
285
285
  deployable['fileRevision'] = get_deployable_file_revision(file_contents)
286
286
  return deployable
287
287
 
@@ -1,5 +1,5 @@
1
1
  import sys
2
- from typing import Any, List
2
+ from typing import Any, List, Optional
3
3
  import requests
4
4
  from polyapi.generate import get_functions_and_parse, generate_functions
5
5
  from polyapi.config import get_api_key_and_url
@@ -23,7 +23,7 @@ def function_add_or_update(
23
23
  description: str,
24
24
  client: bool,
25
25
  server: bool,
26
- logs_enabled: bool,
26
+ logs_enabled: Optional[bool],
27
27
  generate: bool = True,
28
28
  execution_api_key: str = ""
29
29
  ):
@@ -45,6 +45,9 @@ def function_add_or_update(
45
45
  )
46
46
  sys.exit(1)
47
47
 
48
+ if logs_enabled is None:
49
+ logs_enabled = parsed["config"].get("logs_enabled", None)
50
+
48
51
  data = {
49
52
  "context": context or parsed["context"],
50
53
  "name": name,
@@ -52,9 +55,8 @@ def function_add_or_update(
52
55
  "code": code,
53
56
  "language": "python",
54
57
  "returnType": get_jsonschema_type(return_type),
55
- "returnTypeSchema": parsed["types"]["returns"]["typeSchema"],
56
- "arguments": [{**p, "key": p["name"], "type": get_jsonschema_type(p["type"]) } for p in parsed["types"]["params"]],
57
- "logsEnabled": logs_enabled or parsed["config"].get("logs_enabled", False),
58
+ "arguments": [{**p, "key": p["name"], "type": get_jsonschema_type(p["type"])} for p in parsed["types"]["params"]],
59
+ "logsEnabled": logs_enabled,
58
60
  }
59
61
 
60
62
  if server and parsed["dependencies"]:
@@ -47,7 +47,7 @@ def _parse_sphinx_docstring(docstring: str) -> Dict[str, Any]:
47
47
  "type": "Any"
48
48
  }
49
49
  current_section = None
50
-
50
+
51
51
  for line in lines:
52
52
  stripped_line = line.strip()
53
53
  if stripped_line.startswith(":param "):
@@ -56,7 +56,7 @@ def _parse_sphinx_docstring(docstring: str) -> Dict[str, Any]:
56
56
  param_name = param_name.strip()
57
57
  if param_name in params:
58
58
  params[param_name]["description"] = param_desc.strip()
59
- else:
59
+ else:
60
60
  params[param_name] = { "name": param_name, "type": "", "description": param_desc.strip() }
61
61
  current_section = param_name
62
62
 
@@ -118,7 +118,7 @@ def _parse_google_docstring(docstring: str) -> Dict[str, Any]:
118
118
  for line in lines:
119
119
  line = line.rstrip()
120
120
  section_match = section_pattern.match(line)
121
-
121
+
122
122
  if section_match:
123
123
  mode = section_match.group(1).lower()
124
124
  continue
@@ -181,7 +181,7 @@ def _get_schemas(code: str) -> List[Dict]:
181
181
 
182
182
  def get_jsonschema_type(python_type: str):
183
183
  if python_type == "Any":
184
- return "Any"
184
+ return "any"
185
185
 
186
186
  if python_type == "List":
187
187
  return "array"
@@ -338,6 +338,7 @@ def parse_function_code(code: str, name: Optional[str] = "", context: Optional[s
338
338
  "params": [],
339
339
  "returns": {
340
340
  "type": "",
341
+ "typeSchema": None,
341
342
  "description": "",
342
343
  }
343
344
  },
@@ -364,7 +365,7 @@ def parse_function_code(code: str, name: Optional[str] = "", context: Optional[s
364
365
  self._line_offsets.append(
365
366
  self._line_offsets[i-1] + len(self._lines[i-1])
366
367
  )
367
-
368
+
368
369
  self._extract_deploy_comments()
369
370
 
370
371
  def visit_AnnAssign(self, node):
@@ -435,13 +436,14 @@ def parse_function_code(code: str, name: Optional[str] = "", context: Optional[s
435
436
 
436
437
  def _extract_deploy_comments(self):
437
438
  for i in range(len(self._lines)):
438
- line = self._lines[i].strip()
439
+ line = self._lines[i]
439
440
  if line and not line.startswith("#"):
440
441
  return
441
- deployment = _parse_deploy_comment(line)
442
+ deployment = _parse_deploy_comment(line.strip())
442
443
  if deployment:
444
+ start = self._line_offsets[i]
443
445
  deployable["deployments"].append(deployment)
444
- deployable["deploymentCommentRanges"].append([self._line_offsets[i], len(line)])
446
+ deployable["deploymentCommentRanges"].append([start, start + len(line)])
445
447
 
446
448
  def visit_Import(self, node: ast.Import):
447
449
  # TODO maybe handle `import foo.bar` case?
@@ -471,8 +473,7 @@ def parse_function_code(code: str, name: Optional[str] = "", context: Optional[s
471
473
  "type": python_type,
472
474
  "description": "",
473
475
  }
474
- if type_schema:
475
- json_arg["typeSchema"] = json.dumps(type_schema)
476
+ json_arg["typeSchema"] = json.dumps(type_schema) if type_schema else None
476
477
 
477
478
  if docstring_params:
478
479
  try:
@@ -482,7 +483,7 @@ def parse_function_code(code: str, name: Optional[str] = "", context: Optional[s
482
483
  if docstring_params[type_index]["type"] != python_type:
483
484
  deployable["dirty"] = True
484
485
  except:
485
- pass
486
+ pass
486
487
  else:
487
488
  deployable["dirty"] = True
488
489
 
@@ -496,7 +497,7 @@ def parse_function_code(code: str, name: Optional[str] = "", context: Optional[s
496
497
  deployable["types"]["returns"]["typeSchema"] = return_type_schema
497
498
  else:
498
499
  deployable["types"]["returns"]["type"] = "Any"
499
-
500
+
500
501
  def generic_visit(self, node):
501
502
  if hasattr(node, 'lineno') and hasattr(node, 'col_offset'):
502
503
  self._current_offset = self._line_offsets[node.lineno - 1] + node.col_offset
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: polyapi-python
3
- Version: 0.3.1.dev17
3
+ Version: 0.3.2
4
4
  Summary: The Python Client for PolyAPI, the IPaaS by Developers for Developers
5
5
  Author-email: Dan Fellin <dan@polyapi.io>
6
6
  License: MIT License
@@ -29,7 +29,7 @@ Requires-Python: >=3.10
29
29
  Description-Content-Type: text/markdown
30
30
  License-File: LICENSE
31
31
  Requires-Dist: requests==2.31.0
32
- Requires-Dist: typing_extensions==4.10.0
32
+ Requires-Dist: typing_extensions>=4.10.0
33
33
  Requires-Dist: jsonschema-gentypes==2.6.0
34
34
  Requires-Dist: pydantic==2.6.4
35
35
  Requires-Dist: stdlib_list==0.10.0
@@ -1,5 +1,5 @@
1
1
  requests==2.31.0
2
- typing_extensions==4.10.0
2
+ typing_extensions>=4.10.0
3
3
  jsonschema-gentypes==2.6.0
4
4
  pydantic==2.6.4
5
5
  stdlib_list==0.10.0
@@ -3,12 +3,12 @@ requires = ["setuptools>=61.2", "wheel"]
3
3
 
4
4
  [project]
5
5
  name = "polyapi-python"
6
- version = "0.3.1.dev17"
6
+ version = "0.3.2"
7
7
  description = "The Python Client for PolyAPI, the IPaaS by Developers for Developers"
8
8
  authors = [{ name = "Dan Fellin", email = "dan@polyapi.io" }]
9
9
  dependencies = [
10
10
  "requests==2.31.0",
11
- "typing_extensions==4.10.0",
11
+ "typing_extensions>=4.10.0",
12
12
  "jsonschema-gentypes==2.6.0",
13
13
  "pydantic==2.6.4",
14
14
  "stdlib_list==0.10.0",
@@ -65,17 +65,26 @@ def foobar(foo: str, bar: Dict[str, str]) -> int:
65
65
  """A function that does something really import.
66
66
 
67
67
  Args:
68
- foo (str):
69
- bar (Dict[str, str]):
68
+ foo (str):
69
+ bar (Dict[str, str]):
70
70
 
71
71
  Returns:
72
- int:
72
+ int:
73
73
  """
74
74
  print("Okay then!")
75
75
  return 7
76
76
  '''
77
77
 
78
78
  class T(unittest.TestCase):
79
+ def test_parse_and_write_deployment_comment(self):
80
+ test_deployable = parse_function_code(EXPECTED_SERVER_FN_DEPLOYMENTS, "foobar")
81
+ deployable_comment_ranges = test_deployable["deploymentCommentRanges"]
82
+ updated_file_contents = update_deployment_comments(EXPECTED_SERVER_FN_DEPLOYMENTS, test_deployable)
83
+ self.assertEqual(updated_file_contents, EXPECTED_SERVER_FN_DEPLOYMENTS)
84
+ # Deployment comment ranges collapsed into one of equal size
85
+ self.assertEqual(test_deployable["deploymentCommentRanges"][0][0], deployable_comment_ranges[0][0])
86
+ self.assertEqual(test_deployable["deploymentCommentRanges"][0][1], deployable_comment_ranges[1][1])
87
+
79
88
  def test_write_deployment_comment(self):
80
89
  test_deployable = {
81
90
  "deployments": [
@@ -98,7 +107,7 @@ class T(unittest.TestCase):
98
107
  'type': 'server-function'
99
108
  }
100
109
  ],
101
- "deploymentCommentRanges": [[0, 178]]
110
+ "deploymentCommentRanges": [[0, 177]]
102
111
  }
103
112
  updated_file_contents = update_deployment_comments(INITIAL_SERVER_FN_DEPLOYMENTS, test_deployable)
104
113
  self.assertEqual(updated_file_contents, EXPECTED_SERVER_FN_DEPLOYMENTS)
@@ -3,6 +3,11 @@ import unittest
3
3
  from polyapi.parser import parse_function_code
4
4
 
5
5
 
6
+ CODE_NO_TYPES = """
7
+ def foobar(a, b):
8
+ return a + b
9
+ """
10
+
6
11
  SIMPLE_CODE = """
7
12
  def foobar(n: int) -> int:
8
13
  return 9
@@ -124,11 +129,21 @@ def foobar(foo: str, bar: Dict[str, str]) -> int:
124
129
  '''
125
130
 
126
131
  class T(unittest.TestCase):
132
+ def test_no_types(self):
133
+ deployable = parse_function_code(CODE_NO_TYPES, "foobar")
134
+ types = deployable["types"]
135
+ self.assertEqual(len(types["params"]), 2)
136
+ self.assertEqual(types["params"][0], {"name": "a", "type": "Any", "typeSchema": None, "description": ""})
137
+ self.assertEqual(types["params"][1], {"name": "b", "type": "Any", "typeSchema": None, "description": ""})
138
+ self.assertEqual(types["returns"]["type"], "Any")
139
+ self.assertIsNone(types["returns"]["typeSchema"])
140
+ self.assertEqual(deployable["dependencies"], [])
141
+
127
142
  def test_simple_types(self):
128
143
  deployable = parse_function_code(SIMPLE_CODE, "foobar")
129
144
  types = deployable["types"]
130
145
  self.assertEqual(len(types["params"]), 1)
131
- self.assertEqual(types["params"][0], {"name": "n", "type": "int", "description": ""})
146
+ self.assertEqual(types["params"][0], {"name": "n", "type": "int", "typeSchema": None, "description": ""})
132
147
  self.assertEqual(types["returns"]["type"], "int")
133
148
  self.assertIsNone(types["returns"]["typeSchema"])
134
149
  self.assertEqual(deployable["dependencies"], [])
@@ -137,7 +152,7 @@ class T(unittest.TestCase):
137
152
  deployable = parse_function_code(COMPLEX_RETURN_TYPE, "foobar")
138
153
  types = deployable["types"]
139
154
  self.assertEqual(len(types["params"]), 1)
140
- self.assertEqual(types["params"][0], {"name": "n", "type": "int", "description": ""})
155
+ self.assertEqual(types["params"][0], {"name": "n", "type": "int", "typeSchema": None, "description": ""})
141
156
  self.assertEqual(types["returns"]["type"], "Barbar")
142
157
  self.assertEqual(types["returns"]["typeSchema"]['title'], "Barbar")
143
158
 
@@ -153,7 +168,7 @@ class T(unittest.TestCase):
153
168
  deployable = parse_function_code(LIST_COMPLEX_RETURN_TYPE, "foobar")
154
169
  types = deployable["types"]
155
170
  self.assertEqual(len(types["params"]), 1)
156
- self.assertEqual(types["params"][0], {"name": "n", "type": "int", "description": ""})
171
+ self.assertEqual(types["params"][0], {"name": "n", "type": "int", "typeSchema": None, "description": ""})
157
172
  self.assertEqual(types["returns"]["type"], "List[Barbar]")
158
173
  self.assertEqual(types["returns"]["typeSchema"]["items"]['title'], "Barbar")
159
174
 
@@ -171,7 +186,7 @@ class T(unittest.TestCase):
171
186
  code = "import requests\n\n\ndef foobar(n: int) -> int:\n return 9\n"
172
187
  deployable = parse_function_code(code, "foobar")
173
188
  self.assertEqual(deployable["dependencies"], [])
174
-
189
+
175
190
  def test_parse_glide_server_function_no_docstring(self):
176
191
  code = GLIDE_SIMPLE_SERVER_FN
177
192
  deployable = parse_function_code(code, "foobar")
@@ -186,11 +201,13 @@ class T(unittest.TestCase):
186
201
  self.assertEqual(deployable["types"]["params"][0], {
187
202
  "name": "foo",
188
203
  "type": "Any",
204
+ "typeSchema": None,
189
205
  "description": "The foo in question"
190
206
  })
191
207
  self.assertEqual(deployable["types"]["params"][1], {
192
208
  "name": "bar",
193
209
  "type": "Any",
210
+ "typeSchema": None,
194
211
  "description": "Configuration of bars"
195
212
  })
196
213
  self.assertEqual(deployable["types"]["returns"], {
@@ -205,11 +222,13 @@ class T(unittest.TestCase):
205
222
  self.assertEqual(deployable["types"]["params"][0], {
206
223
  "name": "foo",
207
224
  "type": "str",
225
+ "typeSchema": None,
208
226
  "description": "The foo in question"
209
227
  })
210
228
  self.assertEqual(deployable["types"]["params"][1], {
211
229
  "name": "bar",
212
230
  "type": "Dict[str, str]",
231
+ "typeSchema": None,
213
232
  "description": "Configuration of bars"
214
233
  })
215
234
  self.assertEqual(deployable["types"]["returns"], {