clams-python 1.2.1__tar.gz → 1.2.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 (41) hide show
  1. {clams_python-1.2.1/clams_python.egg-info → clams_python-1.2.2}/PKG-INFO +2 -2
  2. clams_python-1.2.2/VERSION +1 -0
  3. {clams_python-1.2.1 → clams_python-1.2.2}/clams/app/__init__.py +23 -5
  4. {clams_python-1.2.1 → clams_python-1.2.2}/clams/restify/__init__.py +3 -1
  5. clams_python-1.2.2/clams/ver/__init__.py +1 -0
  6. {clams_python-1.2.1 → clams_python-1.2.2/clams_python.egg-info}/PKG-INFO +2 -2
  7. {clams_python-1.2.1 → clams_python-1.2.2}/clams_python.egg-info/requires.txt +1 -1
  8. {clams_python-1.2.1 → clams_python-1.2.2}/requirements.txt +1 -1
  9. {clams_python-1.2.1 → clams_python-1.2.2}/tests/test_clamsapp.py +22 -4
  10. clams_python-1.2.1/VERSION +0 -1
  11. clams_python-1.2.1/clams/ver/__init__.py +0 -1
  12. {clams_python-1.2.1 → clams_python-1.2.2}/LICENSE +0 -0
  13. {clams_python-1.2.1 → clams_python-1.2.2}/MANIFEST.in +0 -0
  14. {clams_python-1.2.1 → clams_python-1.2.2}/README.md +0 -0
  15. {clams_python-1.2.1 → clams_python-1.2.2}/clams/__init__.py +0 -0
  16. {clams_python-1.2.1 → clams_python-1.2.2}/clams/appmetadata/__init__.py +0 -0
  17. {clams_python-1.2.1 → clams_python-1.2.2}/clams/develop/__init__.py +0 -0
  18. {clams_python-1.2.1 → clams_python-1.2.2}/clams/develop/templates/app/.dockerignore.template +0 -0
  19. {clams_python-1.2.1 → clams_python-1.2.2}/clams/develop/templates/app/.gitignore.template +0 -0
  20. {clams_python-1.2.1 → clams_python-1.2.2}/clams/develop/templates/app/Containerfile.template +0 -0
  21. {clams_python-1.2.1 → clams_python-1.2.2}/clams/develop/templates/app/LICENSE.template +0 -0
  22. {clams_python-1.2.1 → clams_python-1.2.2}/clams/develop/templates/app/README.md.template +0 -0
  23. {clams_python-1.2.1 → clams_python-1.2.2}/clams/develop/templates/app/app.py.template +0 -0
  24. {clams_python-1.2.1 → clams_python-1.2.2}/clams/develop/templates/app/metadata.py.template +0 -0
  25. {clams_python-1.2.1 → clams_python-1.2.2}/clams/develop/templates/app/requirements.txt.template +0 -0
  26. {clams_python-1.2.1 → clams_python-1.2.2}/clams/develop/templates/gha/for-clams-team.md.template +0 -0
  27. {clams_python-1.2.1 → clams_python-1.2.2}/clams/develop/templates/gha/workflows/issue-apps-project.yml.template +0 -0
  28. {clams_python-1.2.1 → clams_python-1.2.2}/clams/develop/templates/gha/workflows/issue-assign.yml.template +0 -0
  29. {clams_python-1.2.1 → clams_python-1.2.2}/clams/develop/templates/gha/workflows/issue-close.yml.template +0 -0
  30. {clams_python-1.2.1 → clams_python-1.2.2}/clams/develop/templates/gha/workflows/publish.yml.template +0 -0
  31. {clams_python-1.2.1 → clams_python-1.2.2}/clams/mmif_utils/__init__.py +0 -0
  32. {clams_python-1.2.1 → clams_python-1.2.2}/clams/mmif_utils/rewind.py +0 -0
  33. {clams_python-1.2.1 → clams_python-1.2.2}/clams/mmif_utils/source.py +0 -0
  34. {clams_python-1.2.1 → clams_python-1.2.2}/clams/serve/__init__.py +0 -0
  35. {clams_python-1.2.1 → clams_python-1.2.2}/clams_python.egg-info/SOURCES.txt +0 -0
  36. {clams_python-1.2.1 → clams_python-1.2.2}/clams_python.egg-info/dependency_links.txt +0 -0
  37. {clams_python-1.2.1 → clams_python-1.2.2}/clams_python.egg-info/entry_points.txt +0 -0
  38. {clams_python-1.2.1 → clams_python-1.2.2}/clams_python.egg-info/top_level.txt +0 -0
  39. {clams_python-1.2.1 → clams_python-1.2.2}/setup.cfg +0 -0
  40. {clams_python-1.2.1 → clams_python-1.2.2}/setup.py +0 -0
  41. {clams_python-1.2.1 → clams_python-1.2.2}/tests/test_clamscli.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: clams-python
3
- Version: 1.2.1
3
+ Version: 1.2.2
4
4
  Summary: A collection of APIs to develop CLAMS app for python
5
5
  Home-page: https://clams.ai
6
6
  Author: Brandeis Lab for Linguistics and Computation
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3 :: Only
14
14
  Requires-Python: >=3.8
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
- Requires-Dist: mmif-python==1.0.13
17
+ Requires-Dist: mmif-python==1.0.14
18
18
  Requires-Dist: Flask>=2
19
19
  Requires-Dist: Flask-RESTful>=0.3.9
20
20
  Requires-Dist: gunicorn>=20
@@ -0,0 +1 @@
1
+ 1.2.2
@@ -178,7 +178,14 @@ class ClamsApp(ABC):
178
178
  raise ValueError(f"Value for parameter \"{parameter.name}\" must be one of {parameter.choices}.")
179
179
  refined[parameter.name] = casted[parameter.name]
180
180
  elif parameter.default is not None:
181
- refined[parameter.name] = parameter.default
181
+ # have to cast the default values as well, since
182
+ # 1. `map` type default values are not actually expected as a map (dict)
183
+ # 2. developers can use data type not matching the spec
184
+ if isinstance(parameter.default, list):
185
+ casted_default = self.annotate_param_caster.cast({parameter.name: list(map(str, parameter.default))})
186
+ else:
187
+ casted_default = self.annotate_param_caster.cast({parameter.name: [str(parameter.default)]})
188
+ refined.update(casted_default)
182
189
  else:
183
190
  raise ValueError(f"Cannot find configuration for a required parameter \"{parameter.name}\".")
184
191
  # raw input params are hidden under a special key
@@ -338,8 +345,8 @@ class ParameterCaster(object):
338
345
  assert isinstance(vs, list), f"Expected a list of values for key {k}, but got {vs} of type {type(vs)}"
339
346
  assert all(isinstance(v, str) for v in vs), f"Expected a list of strings for key {k}, but got {vs} of types {[type(v) for v in vs]}"
340
347
  if k in self.param_spec:
348
+ valuetype, multivalued = self.param_spec[k]
341
349
  for v in vs:
342
- valuetype, multivalued = self.param_spec[k]
343
350
  if multivalued or k not in casted: # effectively only keeps the first value for non-multi params
344
351
  if valuetype == bool:
345
352
  v = self.bool_param(v)
@@ -358,11 +365,22 @@ class ParameterCaster(object):
358
365
  casted.setdefault(k, []).append(v)
359
366
  else:
360
367
  casted[k] = v
368
+ # when an empty value is passed (usually as a default value)
369
+ # just add an empty list or dict as a placeholder
370
+ # explicit check for `len == 0` is required to prevent
371
+ # empty values are set for params that don't have default values
372
+ if multivalued and len(vs) == 0:
373
+ if valuetype == dict:
374
+ casted.setdefault(k, {})
375
+ else:
376
+ casted.setdefault(k, [])
361
377
  else:
362
- if len(vs) > 1:
363
- casted[k] = vs
364
- else:
378
+ # if the parameter is not defined in the spec, there's no easy way to figure out
379
+ # the user's intention whether it should be a list (multivalued) or a single value.
380
+ if len(vs) == 1:
365
381
  casted[k] = vs[0]
382
+ else:
383
+ casted[k] = vs
366
384
  return casted # pytype: disable=bad-return-type
367
385
 
368
386
  @staticmethod
@@ -124,7 +124,9 @@ class ClamsHTTPApi(Resource):
124
124
 
125
125
  :return: Returns app metadata in a HTTP response.
126
126
  """
127
- return self.json_to_response(self.cla.appmetadata(**request.args))
127
+ # this will catch duplicate arguments with different values into a list under the key
128
+ raw_params = request.args.to_dict(flat=False)
129
+ return self.json_to_response(self.cla.appmetadata(**raw_params))
128
130
 
129
131
  def post(self) -> Response:
130
132
  """
@@ -0,0 +1 @@
1
+ __version__ = "1.2.2"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: clams-python
3
- Version: 1.2.1
3
+ Version: 1.2.2
4
4
  Summary: A collection of APIs to develop CLAMS app for python
5
5
  Home-page: https://clams.ai
6
6
  Author: Brandeis Lab for Linguistics and Computation
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3 :: Only
14
14
  Requires-Python: >=3.8
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
- Requires-Dist: mmif-python==1.0.13
17
+ Requires-Dist: mmif-python==1.0.14
18
18
  Requires-Dist: Flask>=2
19
19
  Requires-Dist: Flask-RESTful>=0.3.9
20
20
  Requires-Dist: gunicorn>=20
@@ -1,4 +1,4 @@
1
- mmif-python==1.0.13
1
+ mmif-python==1.0.14
2
2
  Flask>=2
3
3
  Flask-RESTful>=0.3.9
4
4
  gunicorn>=20
@@ -1,4 +1,4 @@
1
- mmif-python==1.0.13
1
+ mmif-python==1.0.14
2
2
 
3
3
  Flask>=2
4
4
  Flask-RESTful>=0.3.9
@@ -236,8 +236,8 @@ class TestClamsApp(unittest.TestCase):
236
236
  self.assertEqual(v1.metadata.app, self.app.metadata.identifier)
237
237
  self.assertEqual(len(v1.metadata.parameters), 0)
238
238
  v2 = m.new_view()
239
- raw_query_string_arguments = {'undefined_param1': ['value1']} # values are lists as our restifier uses `to_dict(flat=False)`
240
- self.app.sign_view(v2, self.app._refine_params(**raw_query_string_arguments))
239
+ args2 = {'undefined_param1': ['value1']} # values are lists as our restifier uses `to_dict(flat=False)`
240
+ self.app.sign_view(v2, self.app._refine_params(**args2))
241
241
  self.assertEqual(v2.metadata.app, self.app.metadata.identifier)
242
242
  self.assertEqual(len(v2.metadata.parameters), 1)
243
243
  self.assertFalse(clams.ClamsApp._RAW_PARAMS_KEY in v2.metadata.appConfiguration)
@@ -245,8 +245,22 @@ class TestClamsApp(unittest.TestCase):
245
245
  # any parameter with defaults should be recorded
246
246
  if param.default is not None:
247
247
  self.assertTrue(param.name in v2.metadata.appConfiguration)
248
- elif param.name not in raw_query_string_arguments:
248
+ elif param.name not in args2:
249
249
  self.assertFalse(param.name in v2.metadata.appConfiguration)
250
+ v3 = m.new_view()
251
+ self.app.metadata.add_parameter('multivalued_param', 'dummy parameter with multivalues', type='string', multivalued=True, default=[])
252
+ args3 = {'undefined_param1': ['value1']}
253
+ self.app.sign_view(v3, self.app._refine_params(**args3))
254
+ self.assertEqual(len(v3.metadata.parameters), 1)
255
+ self.assertEqual(len(v3.metadata.appConfiguration), 3) # universal (pretty) + `raise_error` in metadata.py + `multivalued_param`
256
+ self.assertEqual(v3.metadata.appConfiguration['multivalued_param'], [])
257
+ v4 = m.new_view()
258
+ multiple_values = ['value1', 'value2']
259
+ args4 = {'multivalued_param': multiple_values}
260
+ self.app.sign_view(v4, self.app._refine_params(**args4))
261
+ self.assertEqual(len(v4.metadata.parameters), 1)
262
+ self.assertEqual(len(v4.metadata.appConfiguration), 3)
263
+ self.assertEqual(len(v4.metadata.parameters['multivalued_param']), len(str(multiple_values)))
250
264
 
251
265
  def test_annotate(self):
252
266
  # The example app is hard-coded to **always** emit version mismatch warning
@@ -307,6 +321,10 @@ class TestClamsApp(unittest.TestCase):
307
321
  description='float +def +mv')
308
322
  self.app.metadata.add_parameter('param7', type='number', default=[], multivalued=True,
309
323
  description='float +def +empty +mv')
324
+ # need to manually rebuild caster object, because the metadata has updated after the app is initialized
325
+ for param_spec in self.app.metadata.parameters:
326
+ self.app.annotate_param_spec[param_spec.name] = (param_spec.type, param_spec.multivalued)
327
+ self.app.annotate_param_caster = ParameterCaster(self.app.annotate_param_spec)
310
328
  with self.assertRaises(ValueError):
311
329
  self.app._refine_params(**{}) # param1 is required, but not passed
312
330
  dummy_params = {'param1': ['okay'], 'non_parameter': ['should be ignored']}
@@ -375,7 +393,7 @@ class TestRestifier(unittest.TestCase):
375
393
  def test_can_put_as_json(self):
376
394
  put = self.app.put('/', data=ExampleInputMMIF.get_mmif(), headers={"Content-Type": "Application/json"})
377
395
  self.assertIsNotNone(put)
378
- self.assertEqual(put.status_code, 200)
396
+ self.assertEqual(200, put.status_code)
379
397
  self.assertIsNotNone(Mmif(put.get_data(as_text=True)))
380
398
 
381
399
  def test_can_pass_params(self):
@@ -1 +0,0 @@
1
- 1.2.1
@@ -1 +0,0 @@
1
- __version__ = "1.2.1"
File without changes
File without changes
File without changes
File without changes
File without changes