dcicutils 7.11.0__tar.gz → 7.11.0.1b9__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/PKG-INFO +3 -1
  2. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/misc_utils.py +95 -1
  3. dcicutils-7.11.0.1b9/dcicutils/sheet_utils.py +1131 -0
  4. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/pyproject.toml +9 -6
  5. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/LICENSE.txt +0 -0
  6. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/README.rst +0 -0
  7. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/__init__.py +0 -0
  8. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/base.py +0 -0
  9. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/beanstalk_utils.py +0 -0
  10. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/cloudformation_utils.py +0 -0
  11. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/codebuild_utils.py +0 -0
  12. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/command_utils.py +0 -0
  13. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/common.py +0 -0
  14. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/contribution_scripts.py +0 -0
  15. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/contribution_utils.py +0 -0
  16. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/creds_utils.py +0 -0
  17. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/data_utils.py +0 -0
  18. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/deployment_utils.py +0 -0
  19. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/diff_utils.py +0 -0
  20. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/docker_utils.py +0 -0
  21. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/ecr_scripts.py +0 -0
  22. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/ecr_utils.py +0 -0
  23. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/ecs_utils.py +0 -0
  24. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/env_base.py +0 -0
  25. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/env_manager.py +0 -0
  26. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/env_scripts.py +0 -0
  27. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/env_utils.py +0 -0
  28. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/env_utils_legacy.py +0 -0
  29. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/es_utils.py +0 -0
  30. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/exceptions.py +0 -0
  31. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/ff_mocks.py +0 -0
  32. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/ff_utils.py +0 -0
  33. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/function_cache_decorator.py +0 -0
  34. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/glacier_utils.py +0 -0
  35. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/jh_utils.py +0 -0
  36. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/kibana/dashboards.json +0 -0
  37. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/kibana/readme.md +0 -0
  38. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/lang_utils.py +0 -0
  39. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/license_utils.py +0 -0
  40. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/log_utils.py +0 -0
  41. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/obfuscation_utils.py +0 -0
  42. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/opensearch_utils.py +0 -0
  43. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/project_utils.py +0 -0
  44. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/qa_checkers.py +0 -0
  45. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/qa_utils.py +0 -0
  46. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/redis_tools.py +0 -0
  47. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/redis_utils.py +0 -0
  48. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/s3_utils.py +0 -0
  49. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/scripts/publish_to_pypi.py +0 -0
  50. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/secrets_utils.py +0 -0
  51. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/snapshot_utils.py +0 -0
  52. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/ssl_certificate_utils.py +0 -0
  53. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/task_utils.py +0 -0
  54. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/trace_utils.py +0 -0
  55. {dcicutils-7.11.0 → dcicutils-7.11.0.1b9}/dcicutils/variant_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dcicutils
3
- Version: 7.11.0
3
+ Version: 7.11.0.1b9
4
4
  Summary: Utility package for interacting with the 4DN Data Portal and other 4DN resources
5
5
  Home-page: https://github.com/4dn-dcic/utils
6
6
  License: MIT
@@ -25,9 +25,11 @@ Requires-Dist: PyYAML (>=5.1,<5.5)
25
25
  Requires-Dist: aws-requests-auth (>=0.4.2,<1)
26
26
  Requires-Dist: boto3 (>=1.17.39,<2.0.0)
27
27
  Requires-Dist: botocore (>=1.20.39,<2.0.0)
28
+ Requires-Dist: chardet (>=5.2.0,<6.0.0)
28
29
  Requires-Dist: docker (>=4.4.4,<5.0.0)
29
30
  Requires-Dist: elasticsearch (==7.13.4)
30
31
  Requires-Dist: gitpython (>=3.1.2,<4.0.0)
32
+ Requires-Dist: openpyxl (>=3.1.2,<4.0.0)
31
33
  Requires-Dist: opensearch-py (>=2.0.1,<3.0.0)
32
34
  Requires-Dist: pyOpenSSL (>=23.1.1,<24.0.0)
33
35
  Requires-Dist: pytz (>=2020.4)
@@ -9,6 +9,7 @@ import hashlib
9
9
  import inspect
10
10
  import math
11
11
  import io
12
+ import json
12
13
  import os
13
14
  import logging
14
15
  import pytz
@@ -191,7 +192,11 @@ class _VirtualAppHelper(webtest.TestApp):
191
192
  pass
192
193
 
193
194
 
194
- class VirtualApp:
195
+ class AbstractVirtualApp:
196
+ pass
197
+
198
+
199
+ class VirtualApp(AbstractVirtualApp):
195
200
  """
196
201
  Wrapper class for TestApp, to allow custom control over submitting Encoded requests,
197
202
  simulating a number of conditions, including permissions.
@@ -1352,6 +1357,25 @@ def capitalize1(s):
1352
1357
  return s[:1].upper() + s[1:]
1353
1358
 
1354
1359
 
1360
+ """
1361
+ Python's UUID ignores all dashes, whereas Postgres is more strict
1362
+ http://www.postgresql.org/docs/9.2/static/datatype-uuid.html
1363
+ See also http://www.postgresql.org/docs/9.2/static/datatype-uuid.html
1364
+ And, anyway, this pattern is what our portals have been doing
1365
+ for quite a while, so it's the most stable choice for us now.
1366
+ """
1367
+
1368
+ uuid_re = re.compile(r'(?i)[{]?(?:[0-9a-f]{4}-?){8}[}]?')
1369
+
1370
+
1371
+ def is_uuid(instance):
1372
+ """
1373
+ Predicate returns true for any group of 32 hex characters with optional hyphens every four characters.
1374
+ We insist on lowercase to make matching faster. See other notes on this design choice above.
1375
+ """
1376
+ return bool(uuid_re.match(instance))
1377
+
1378
+
1355
1379
  def string_list(s):
1356
1380
  """
1357
1381
  Turns a comma-separated list into an actual list, trimming whitespace and ignoring nulls.
@@ -2313,3 +2337,73 @@ def parse_in_radix(text: str, *, radix: int):
2313
2337
  except Exception:
2314
2338
  pass
2315
2339
  raise ValueError(f"Unable to parse: {text!r}")
2340
+
2341
+
2342
+ def pad_to(target_size: int, data: list, *, padding=None):
2343
+ """
2344
+ This will pad to a given target size, a list of a potentially different actual size, using given padding.
2345
+ e.g., pad_to(3, [1, 2]) will return [1, 2, None]
2346
+ """
2347
+ actual_size = len(data)
2348
+ if actual_size < target_size:
2349
+ data = data + [padding] * (target_size - actual_size)
2350
+ return data
2351
+
2352
+
2353
+ class JsonLinesReader:
2354
+
2355
+ def __init__(self, fp, padded=False, padding=None):
2356
+ """
2357
+ Given an fp (the conventional name for a "file pointer", the thing a call to io.open returns,
2358
+ this creates an object that can be used to iterate across the lines in the JSON lines file
2359
+ that the fp is reading from.
2360
+
2361
+ There are two possible formats that this will return.
2362
+
2363
+ For files that contain a series of dictionaries, such as:
2364
+ {"something": 1, "else": "a"}
2365
+ {"something": 2, "else": "b"}
2366
+ ...etc
2367
+ this will just return thos those dictionaries one-by-one when iterated over.
2368
+
2369
+ The same set of dictionaries will also be yielded by a file containing:
2370
+ ["something", "else"]
2371
+ [1, "a"]
2372
+ [2, "b"]
2373
+ ...etc
2374
+ this will just return thos those dictionaries one-by-one when iterated over.
2375
+
2376
+ NOTES:
2377
+
2378
+ * In the second case, shorter lists on subsequent lines return only partial dictionaries.
2379
+ * In the second case, longer lists on subsequent lines will quietly drop any extra elements.
2380
+ """
2381
+
2382
+ self.fp = fp
2383
+ self.padded: bool = padded
2384
+ self.padding = padding
2385
+ self.headers = None # Might change after we see first line
2386
+
2387
+ def __iter__(self):
2388
+ first_line = True
2389
+ n_headers = 0
2390
+ for raw_line in self.fp:
2391
+ line = json.loads(raw_line)
2392
+ if first_line:
2393
+ first_line = False
2394
+ if isinstance(line, list):
2395
+ self.headers = line
2396
+ n_headers = len(line)
2397
+ continue
2398
+ # If length of line is more than we expect, ignore it. Let user put comments beyond our table
2399
+ # But if length of line is less than we expect, extend the line with None
2400
+ if self.headers:
2401
+ if not isinstance(line, list):
2402
+ raise Exception("If the first line is a list, all lines must be.")
2403
+ if self.padded and len(line) < n_headers:
2404
+ line = pad_to(n_headers, line, padding=self.padding)
2405
+ yield dict(zip(self.headers, line))
2406
+ elif isinstance(line, dict):
2407
+ yield line
2408
+ else:
2409
+ raise Exception(f"If the first line is not a list, all lines must be dictionaries: {line!r}")