dcicutils 8.8.3.1b13__tar.gz → 8.8.3.1b15__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/PKG-INFO +1 -1
  2. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/datetime_utils.py +116 -25
  3. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/pyproject.toml +1 -1
  4. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/LICENSE.txt +0 -0
  5. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/README.rst +0 -0
  6. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/__init__.py +0 -0
  7. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/base.py +0 -0
  8. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/beanstalk_utils.py +0 -0
  9. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/bundle_utils.py +0 -0
  10. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/captured_output.py +0 -0
  11. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/cloudformation_utils.py +0 -0
  12. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/codebuild_utils.py +0 -0
  13. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/command_utils.py +0 -0
  14. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/common.py +0 -0
  15. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/contribution_scripts.py +0 -0
  16. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/contribution_utils.py +0 -0
  17. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/creds_utils.py +0 -0
  18. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/data_readers.py +0 -0
  19. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/data_utils.py +0 -0
  20. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/deployment_utils.py +0 -0
  21. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/diff_utils.py +0 -0
  22. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/docker_utils.py +0 -0
  23. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/ecr_scripts.py +0 -0
  24. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/ecr_utils.py +0 -0
  25. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/ecs_utils.py +0 -0
  26. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/env_base.py +0 -0
  27. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/env_manager.py +0 -0
  28. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/env_scripts.py +0 -0
  29. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/env_utils.py +0 -0
  30. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/env_utils_legacy.py +0 -0
  31. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/es_utils.py +0 -0
  32. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/exceptions.py +0 -0
  33. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/ff_mocks.py +0 -0
  34. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/ff_utils.py +0 -0
  35. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/file_utils.py +0 -0
  36. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/function_cache_decorator.py +0 -0
  37. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/glacier_utils.py +0 -0
  38. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/jh_utils.py +0 -0
  39. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/kibana/dashboards.json +0 -0
  40. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/kibana/readme.md +0 -0
  41. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/lang_utils.py +0 -0
  42. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/license_policies/c4-infrastructure.jsonc +0 -0
  43. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/license_policies/c4-python-infrastructure.jsonc +0 -0
  44. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/license_policies/park-lab-common-server.jsonc +0 -0
  45. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/license_policies/park-lab-common.jsonc +0 -0
  46. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/license_policies/park-lab-gpl-pipeline.jsonc +0 -0
  47. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/license_policies/park-lab-pipeline.jsonc +0 -0
  48. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/license_utils.py +0 -0
  49. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/log_utils.py +0 -0
  50. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/misc_utils.py +0 -0
  51. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/obfuscation_utils.py +0 -0
  52. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/opensearch_utils.py +0 -0
  53. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/portal_object_utils.py +0 -0
  54. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/portal_utils.py +0 -0
  55. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/progress_bar.py +0 -0
  56. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/project_utils.py +0 -0
  57. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/qa_checkers.py +0 -0
  58. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/qa_utils.py +0 -0
  59. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/redis_tools.py +0 -0
  60. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/redis_utils.py +0 -0
  61. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/s3_utils.py +0 -0
  62. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/schema_utils.py +0 -0
  63. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/scripts/publish_to_pypi.py +0 -0
  64. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/scripts/run_license_checker.py +0 -0
  65. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/scripts/view_portal_object.py +0 -0
  66. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/secrets_utils.py +0 -0
  67. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/sheet_utils.py +0 -0
  68. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/snapshot_utils.py +0 -0
  69. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/ssl_certificate_utils.py +0 -0
  70. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/structured_data.py +0 -0
  71. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/submitr/progress_constants.py +0 -0
  72. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/submitr/ref_lookup_strategy.py +0 -0
  73. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/task_utils.py +0 -0
  74. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/tmpfile_utils.py +0 -0
  75. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/trace_utils.py +0 -0
  76. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/validation_utils.py +0 -0
  77. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/variant_utils.py +0 -0
  78. {dcicutils-8.8.3.1b13 → dcicutils-8.8.3.1b15}/dcicutils/zip_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dcicutils
3
- Version: 8.8.3.1b13
3
+ Version: 8.8.3.1b15
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
@@ -3,6 +3,22 @@ from datetime import datetime, timedelta, timezone
3
3
  from dateutil import parser as datetime_parser
4
4
  from typing import Optional, Tuple, Union
5
5
 
6
+ TIMEZONE_LOCAL = datetime.now().astimezone().tzinfo # type: datetime.timezone
7
+ TIMEZONE_LOCAL_NAME = TIMEZONE_LOCAL.tzname(None) # type: str
8
+ TIMEZONE_LOCAL_OFFSET = TIMEZONE_LOCAL.utcoffset(None) # type: datetime.timedelta
9
+ TIMEZONE_LOCAL_OFFSET_TOTAL_MINUTES = int(TIMEZONE_LOCAL_OFFSET.total_seconds()) // 60 # type: int
10
+ TIMEZONE_LOCAL_OFFSET_HOURS = TIMEZONE_LOCAL_OFFSET_TOTAL_MINUTES // 60 # type: int
11
+ TIMEZONE_LOCAL_OFFSET_MINUTES = TIMEZONE_LOCAL_OFFSET_TOTAL_MINUTES % 60 # type: int
12
+ TIMEZONE_LOCAL_SUFFIX = f"{TIMEZONE_LOCAL_OFFSET_HOURS:+03d}:{TIMEZONE_LOCAL_OFFSET_MINUTES:02d}" # type: str
13
+
14
+ TIMEZONE_UTC = timezone.utc # type: datetime.timezone
15
+ TIMEZONE_UTC_NAME = TIMEZONE_UTC.tzname(None) # type: str
16
+ TIMEZONE_UTC_OFFSET = timedelta(0) # type: datetime.timedelta
17
+ TIMEZONE_UTC_OFFSET_TOTAL_MINUTES = 0 # type: int
18
+ TIMEZONE_UTC_OFFSET_HOURS = 0 # type: int
19
+ TIMEZONE_UTC_OFFSET_MINUTES = 0 # type: int
20
+ TIMEZONE_UTC_SUFFIX = "Z" # type: str
21
+
6
22
 
7
23
  def parse_datetime_string(value: str) -> Optional[datetime]:
8
24
  """
@@ -83,46 +99,60 @@ def normalize_date_string(value: str) -> Optional[str]:
83
99
  return d.strftime("%Y-%m-%d") if d else None
84
100
 
85
101
 
86
- def get_timezone(hours: int, minutes: Optional[int] = None) -> timezone:
102
+ def get_timezone(hours_or_timedelta: Union[int, timedelta], minutes: Optional[int] = None) -> timezone:
103
+ try:
104
+ if isinstance(hours_or_timedelta, timedelta):
105
+ return timezone(hours_or_timedelta)
106
+ return timezone(timedelta(hours=hours_or_timedelta, minutes=minutes or 0))
107
+ except Exception:
108
+ return TIMEZONE_LOCAL
109
+
110
+
111
+ def get_timezone_offset(tz: timezone) -> timedelta:
87
112
  try:
88
- return timezone(timedelta(hours=hours, minutes=minutes or 0))
113
+ return tz.utcoffset(None)
89
114
  except Exception:
90
- return timezone.utc
115
+ return TIMEZONE_LOCAL_OFFSET
91
116
 
92
117
 
93
118
  def get_timezone_hours_minutes(tz: timezone) -> Tuple[int, int]:
94
119
  """
95
120
  Returns a tuple with the integer hours and minutes offset for the given timezone.
121
+ If negative then only the hours is negative; the mintutes is always positive;
122
+ this is okay because there are no timezones less than one hour from UTC.
96
123
  """
97
- tz_minutes = datetime.now(tz).utcoffset().total_seconds() / 60
98
- return int(tz_minutes // 60), int(abs(tz_minutes % 60))
124
+ tz_offset = get_timezone_offset(tz)
125
+ tz_offset_total_minutes = int(tz_offset.total_seconds()) // 60
126
+ tz_offset_hours = tz_offset_total_minutes // 60
127
+ tz_offset_minutes = abs(tz_offset_total_minutes % 60)
128
+ return tz_offset_hours, tz_offset_minutes
99
129
 
100
130
 
101
131
  def get_utc_timezone() -> timezone:
102
- return timezone.utc
132
+ return TIMEZONE_UTC
103
133
 
104
134
 
105
135
  def get_local_timezone() -> timezone:
106
136
  """
107
137
  Returns current/local timezone as a datetime.timezone object.
108
138
  """
109
- return datetime.now().astimezone().tzinfo
139
+ return TIMEZONE_LOCAL
110
140
 
111
141
 
112
142
  def get_local_timezone_string() -> str:
113
143
  """
114
144
  Returns current/local timezone in format like: "-05:00".
115
145
  """
116
- tz_hours, tz_minutes = get_local_timezone_hours_minutes()
117
- return f"{tz_hours:+03d}:{tz_minutes:02d}"
146
+ return TIMEZONE_LOCAL_SUFFIX
118
147
 
119
148
 
120
149
  def get_local_timezone_hours_minutes() -> Tuple[int, int]:
121
150
  """
122
151
  Returns a tuple with the integer hours and minutes offset for the current/local timezone.
152
+ If negative then only the hours is negative; the mintutes is always positive;
153
+ this is okay because there are no timezones less than one hour from UTC.
123
154
  """
124
- tz_minutes = datetime.now(timezone.utc).astimezone().utcoffset().total_seconds() / 60
125
- return int(tz_minutes // 60), int(abs(tz_minutes % 60))
155
+ return TIMEZONE_LOCAL_OFFSET_HOURS, TIMEZONE_LOCAL_OFFSET_MINUTES
126
156
 
127
157
 
128
158
  def parse_datetime(value: str, utc: bool = False, tz: Optional[timezone] = None) -> Optional[datetime]:
@@ -154,14 +184,16 @@ def parse_datetime(value: str, utc: bool = False, tz: Optional[timezone] = None)
154
184
 
155
185
  def format_datetime(value: datetime,
156
186
  utc: bool = False,
157
- iso: bool = False,
158
- ms: bool = False,
159
187
  tz: Optional[Union[timezone, bool]] = None,
188
+ iso: bool = False,
160
189
  notz: bool = False,
161
190
  noseconds: bool = False,
191
+ ms: bool = False,
162
192
  verbose: bool = False,
163
193
  noseparator: bool = False,
164
- noday: bool = False) -> Optional[str]:
194
+ noday: bool = False,
195
+ nodate: bool = False,
196
+ notime: bool = False) -> str:
165
197
  """
166
198
  Returns the given datetime as a string in "YYYY:MM:DD hh:mm:ss tz" format, for
167
199
  example "2024-04-17 15:42:26 EDT". If the given notz argument is True then omits
@@ -173,9 +205,11 @@ def format_datetime(value: datetime,
173
205
  one; if the given utc argument is True then it will be UTC; or if the given tz
174
206
  argument is a datetime.timezone it will be in that timezone.
175
207
  """
208
+ if nodate is True and notime is True:
209
+ return ""
176
210
  if not isinstance(value, datetime):
177
211
  if not isinstance(value, str) or not (value := parse_datetime(value)):
178
- return None
212
+ return ""
179
213
  try:
180
214
  if utc is True:
181
215
  tz = timezone.utc
@@ -185,23 +219,80 @@ def format_datetime(value: datetime,
185
219
  notz = False
186
220
  elif tz is False:
187
221
  notz = True
222
+ if noseconds is True:
223
+ ms = False
188
224
  value = value.astimezone(tz)
189
225
  if iso:
190
226
  if notz is True:
191
227
  value = value.replace(tzinfo=None)
192
228
  if not (ms is True):
193
229
  value = value.replace(microsecond=0)
194
- return value.isoformat()
195
- if noseconds is True:
196
- ms = False
230
+ if noseconds is True:
231
+ if notz is True:
232
+ if nodate is True:
233
+ return value.strftime(f"%H:%M")
234
+ elif notime is True:
235
+ return value.strftime(f"%Y-%m-%d")
236
+ else:
237
+ return value.strftime(f"%Y-%m-%dT%H:%M")
238
+ tz = value.strftime("%z")
239
+ tz = tz[:3] + ":" + tz[3:]
240
+ if nodate is True:
241
+ return value.strftime(f"%H:%M") + tz
242
+ elif notime is True:
243
+ return value.strftime(f"%Y-%m-%d") + tz
244
+ else:
245
+ return value.strftime(f"%Y-%m-%dT%H:%M") + tz
246
+ if nodate is True:
247
+ return value.strftime(f"%H:%M:%S{f'.%f' if ms is True else ''}")
248
+ elif notime is True:
249
+ return value.strftime(f"%Y-%m-%d")
250
+ else:
251
+ return value.isoformat()
197
252
  if verbose:
198
- return value.strftime(
199
- f"{'' if noday is True else '%A, '}%B %-d, %Y{'' if noseparator is True else ' |'}"
200
- f" %-I:%M{'' if noseconds is True else ':%S'}"
201
- f"{f'.%f' if ms is True else ''} %p{'' if notz is True else ' %Z'}")
253
+ if nodate is True:
254
+ return value.strftime(
255
+ f"%-I:%M{'' if noseconds is True else ':%S'}"
256
+ f"{f'.%f' if ms is True else ''} %p{'' if notz is True else ' %Z'}")
257
+ elif notime is True:
258
+ return value.strftime(f"{'' if noday is True else '%A, '}%B %-d, %Y")
259
+ else:
260
+ return value.strftime(
261
+ f"{'' if noday is True else '%A, '}%B %-d, %Y{'' if noseparator is True else ' |'}"
262
+ f" %-I:%M{'' if noseconds is True else ':%S'}"
263
+ f"{f'.%f' if ms is True else ''} %p{'' if notz is True else ' %Z'}")
202
264
  else:
203
- return value.strftime(
204
- f"%Y-%m-%d %H:%M{'' if noseconds is True else ':%S'}"
205
- f"{f'.%f' if ms is True else ''}{'' if notz is True else ' %Z'}")
265
+ if nodate is True:
266
+ return value.strftime(
267
+ f"%H:%M{'' if noseconds is True else ':%S'}"
268
+ f"{f'.%f' if ms is True else ''}{'' if notz is True else ' %Z'}")
269
+ elif notime is True:
270
+ return value.strftime(f"%Y-%m-%d")
271
+ else:
272
+ return value.strftime(
273
+ f"%Y-%m-%d %H:%M{'' if noseconds is True else ':%S'}"
274
+ f"{f'.%f' if ms is True else ''}{'' if notz is True else ' %Z'}")
206
275
  except Exception:
207
276
  return None
277
+
278
+
279
+ def format_date(value: datetime,
280
+ utc: bool = False,
281
+ iso: bool = False,
282
+ tz: Optional[Union[timezone, bool]] = None,
283
+ verbose: bool = False,
284
+ noday: bool = False) -> str:
285
+ return format_datetime(value, utc=utc, iso=iso, tz=tz, verbose=verbose, noday=noday, notime=True)
286
+
287
+
288
+ def format_time(value: datetime,
289
+ utc: bool = False,
290
+ iso: bool = False,
291
+ ms: bool = False,
292
+ tz: Optional[Union[timezone, bool]] = None,
293
+ notz: bool = False,
294
+ noseconds: bool = False,
295
+ verbose: bool = False,
296
+ noday: bool = False) -> str:
297
+ return format_datetime(value, utc=utc, iso=iso, ms=ms, tz=tz, notz=notz,
298
+ noseconds=noseconds, verbose=verbose, nodate=True)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "dcicutils"
3
- version = "8.8.3.1b13" # TODO: To become 8.8.4
3
+ version = "8.8.3.1b15" # TODO: To become 8.8.4
4
4
  description = "Utility package for interacting with the 4DN Data Portal and other 4DN resources"
5
5
  authors = ["4DN-DCIC Team <support@4dnucleome.org>"]
6
6
  license = "MIT"