labkey 2.6.1__py3-none-any.whl → 3.0.0__py3-none-any.whl
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.
- labkey/__init__.py +1 -1
- labkey/query.py +177 -4
- labkey/utils.py +20 -0
- {labkey-2.6.1.dist-info → labkey-3.0.0.dist-info}/METADATA +2 -4
- {labkey-2.6.1.dist-info → labkey-3.0.0.dist-info}/RECORD +8 -8
- {labkey-2.6.1.dist-info → labkey-3.0.0.dist-info}/WHEEL +1 -1
- {labkey-2.6.1.dist-info → labkey-3.0.0.dist-info}/LICENSE.txt +0 -0
- {labkey-2.6.1.dist-info → labkey-3.0.0.dist-info}/top_level.txt +0 -0
labkey/__init__.py
CHANGED
labkey/query.py
CHANGED
@@ -44,6 +44,7 @@ import functools
|
|
44
44
|
from typing import List
|
45
45
|
|
46
46
|
from .server_context import ServerContext
|
47
|
+
from .utils import waf_encode
|
47
48
|
|
48
49
|
_default_timeout = 60 * 5 # 5 minutes
|
49
50
|
|
@@ -164,12 +165,25 @@ class QueryFilter:
|
|
164
165
|
return "<QueryFilter [{} {} {}]>".format(self.column_name, self.filter_type, self.value)
|
165
166
|
|
166
167
|
|
168
|
+
class AuditBehavior:
|
169
|
+
"""
|
170
|
+
Enum of different auditing levels
|
171
|
+
"""
|
172
|
+
|
173
|
+
DETAILED = "DETAILED"
|
174
|
+
NONE = "NONE"
|
175
|
+
SUMMARY = "SUMMARY"
|
176
|
+
|
177
|
+
|
167
178
|
def delete_rows(
|
168
179
|
server_context: ServerContext,
|
169
180
|
schema_name: str,
|
170
181
|
query_name: str,
|
171
182
|
rows: any,
|
172
183
|
container_path: str = None,
|
184
|
+
transacted: bool = True,
|
185
|
+
audit_behavior: AuditBehavior = None,
|
186
|
+
audit_user_comment: str = None,
|
173
187
|
timeout: int = _default_timeout,
|
174
188
|
):
|
175
189
|
"""
|
@@ -179,12 +193,25 @@ def delete_rows(
|
|
179
193
|
:param query_name: table name to delete from
|
180
194
|
:param rows: Set of rows to delete
|
181
195
|
:param container_path: labkey container path if not already set in context
|
196
|
+
:param transacted: whether all of the updates should be done in a single transaction
|
197
|
+
:param audit_behavior: used to override the audit behavior for the update. See class query.AuditBehavior
|
198
|
+
:param audit_user_comment: used to provide a comment that will be attached to certain detailed audit log records
|
182
199
|
:param timeout: timeout of request in seconds (defaults to 30s)
|
183
200
|
:return:
|
184
201
|
"""
|
185
202
|
url = server_context.build_url("query", "deleteRows.api", container_path=container_path)
|
203
|
+
|
186
204
|
payload = {"schemaName": schema_name, "queryName": query_name, "rows": rows}
|
187
205
|
|
206
|
+
if transacted is False:
|
207
|
+
payload["transacted"] = transacted
|
208
|
+
|
209
|
+
if audit_behavior is not None:
|
210
|
+
payload["auditBehavior"] = audit_behavior
|
211
|
+
|
212
|
+
if audit_user_comment is not None:
|
213
|
+
payload["auditUserComment"] = audit_user_comment
|
214
|
+
|
188
215
|
return server_context.make_request(
|
189
216
|
url,
|
190
217
|
json=payload,
|
@@ -231,6 +258,7 @@ def execute_sql(
|
|
231
258
|
parameters: dict = None,
|
232
259
|
required_version: float = None,
|
233
260
|
timeout: int = _default_timeout,
|
261
|
+
waf_encode_sql: bool = True
|
234
262
|
):
|
235
263
|
"""
|
236
264
|
Execute sql query against a LabKey server.
|
@@ -248,11 +276,12 @@ def execute_sql(
|
|
248
276
|
:param parameters: parameter values to pass through to a parameterized query
|
249
277
|
:param required_version: Api version of response
|
250
278
|
:param timeout: timeout of request in seconds (defaults to 30s)
|
279
|
+
:param waf_encode_sql: WAF encode sql in request (defaults to True)
|
251
280
|
:return:
|
252
281
|
"""
|
253
282
|
url = server_context.build_url("query", "executeSql.api", container_path=container_path)
|
254
283
|
|
255
|
-
payload = {"schemaName": schema_name, "sql": sql}
|
284
|
+
payload = {"schemaName": schema_name, "sql": waf_encode(sql) if waf_encode_sql else sql}
|
256
285
|
|
257
286
|
if container_filter is not None:
|
258
287
|
payload["containerFilter"] = container_filter
|
@@ -285,6 +314,10 @@ def insert_rows(
|
|
285
314
|
query_name: str,
|
286
315
|
rows: List[any],
|
287
316
|
container_path: str = None,
|
317
|
+
skip_reselect_rows: bool = False,
|
318
|
+
transacted: bool = True,
|
319
|
+
audit_behavior: AuditBehavior = None,
|
320
|
+
audit_user_comment: str = None,
|
288
321
|
timeout: int = _default_timeout,
|
289
322
|
):
|
290
323
|
"""
|
@@ -294,6 +327,10 @@ def insert_rows(
|
|
294
327
|
:param query_name: table name to insert into
|
295
328
|
:param rows: set of rows to insert
|
296
329
|
:param container_path: labkey container path if not already set in context
|
330
|
+
:param skip_reselect_rows: whether the full detailed response for the insert can be skipped
|
331
|
+
:param transacted: whether all of the updates should be done in a single transaction
|
332
|
+
:param audit_behavior: used to override the audit behavior for the update. See class query.AuditBehavior
|
333
|
+
:param audit_user_comment: used to provide a comment that will be attached to certain detailed audit log records
|
297
334
|
:param timeout: timeout of request in seconds (defaults to 30s)
|
298
335
|
:return:
|
299
336
|
"""
|
@@ -301,6 +338,18 @@ def insert_rows(
|
|
301
338
|
|
302
339
|
payload = {"schemaName": schema_name, "queryName": query_name, "rows": rows}
|
303
340
|
|
341
|
+
if skip_reselect_rows is True:
|
342
|
+
payload["skipReselectRows"] = skip_reselect_rows
|
343
|
+
|
344
|
+
if transacted is False:
|
345
|
+
payload["transacted"] = transacted
|
346
|
+
|
347
|
+
if audit_behavior is not None:
|
348
|
+
payload["auditBehavior"] = audit_behavior
|
349
|
+
|
350
|
+
if audit_user_comment is not None:
|
351
|
+
payload["auditUserComment"] = audit_user_comment
|
352
|
+
|
304
353
|
return server_context.make_request(
|
305
354
|
url,
|
306
355
|
json=payload,
|
@@ -419,6 +468,9 @@ def update_rows(
|
|
419
468
|
query_name: str,
|
420
469
|
rows: List[any],
|
421
470
|
container_path: str = None,
|
471
|
+
transacted: bool = True,
|
472
|
+
audit_behavior: AuditBehavior = None,
|
473
|
+
audit_user_comment: str = None,
|
422
474
|
timeout: int = _default_timeout,
|
423
475
|
):
|
424
476
|
"""
|
@@ -429,6 +481,9 @@ def update_rows(
|
|
429
481
|
:param query_name: table name to update
|
430
482
|
:param rows: Set of rows to update
|
431
483
|
:param container_path: labkey container path if not already set in context
|
484
|
+
:param transacted: whether all of the updates should be done in a single transaction
|
485
|
+
:param audit_behavior: used to override the audit behavior for the update. See class query.AuditBehavior
|
486
|
+
:param audit_user_comment: used to provide a comment that will be attached to certain detailed audit log records
|
432
487
|
:param timeout: timeout of request in seconds (defaults to 30s)
|
433
488
|
:return:
|
434
489
|
"""
|
@@ -436,6 +491,61 @@ def update_rows(
|
|
436
491
|
|
437
492
|
payload = {"schemaName": schema_name, "queryName": query_name, "rows": rows}
|
438
493
|
|
494
|
+
if transacted is False:
|
495
|
+
payload["transacted"] = transacted
|
496
|
+
|
497
|
+
if audit_behavior is not None:
|
498
|
+
payload["auditBehavior"] = audit_behavior
|
499
|
+
|
500
|
+
if audit_user_comment is not None:
|
501
|
+
payload["auditUserComment"] = audit_user_comment
|
502
|
+
|
503
|
+
return server_context.make_request(
|
504
|
+
url,
|
505
|
+
json=payload,
|
506
|
+
timeout=timeout,
|
507
|
+
)
|
508
|
+
|
509
|
+
|
510
|
+
def move_rows(
|
511
|
+
server_context: ServerContext,
|
512
|
+
target_container_path: str,
|
513
|
+
schema_name: str,
|
514
|
+
query_name: str,
|
515
|
+
rows: any,
|
516
|
+
container_path: str = None,
|
517
|
+
transacted: bool = True,
|
518
|
+
audit_behavior: AuditBehavior = None,
|
519
|
+
audit_user_comment: str = None,
|
520
|
+
timeout: int = _default_timeout,
|
521
|
+
):
|
522
|
+
"""
|
523
|
+
Move a set of rows from the schema.query
|
524
|
+
:param server_context: A LabKey server context. See utils.create_server_context.
|
525
|
+
:param target_container_path: target labkey container path for the move
|
526
|
+
:param schema_name: schema of table
|
527
|
+
:param query_name: table name to move from
|
528
|
+
:param rows: Set of rows to move
|
529
|
+
:param container_path: source labkey container path if not already set in context
|
530
|
+
:param transacted: whether all of the updates should be done in a single transaction
|
531
|
+
:param audit_behavior: used to override the audit behavior for the update. See class query.AuditBehavior
|
532
|
+
:param audit_user_comment: used to provide a comment that will be attached to certain detailed audit log records
|
533
|
+
:param timeout: timeout of request in seconds (defaults to 30s)
|
534
|
+
:return:
|
535
|
+
"""
|
536
|
+
url = server_context.build_url("query", "moveRows.api", container_path=container_path)
|
537
|
+
|
538
|
+
payload = {"targetContainerPath": target_container_path, "schemaName": schema_name, "queryName": query_name, "rows": rows}
|
539
|
+
|
540
|
+
if transacted is False:
|
541
|
+
payload["transacted"] = transacted
|
542
|
+
|
543
|
+
if audit_behavior is not None:
|
544
|
+
payload["auditBehavior"] = audit_behavior
|
545
|
+
|
546
|
+
if audit_user_comment is not None:
|
547
|
+
payload["auditUserComment"] = audit_user_comment
|
548
|
+
|
439
549
|
return server_context.make_request(
|
440
550
|
url,
|
441
551
|
json=payload,
|
@@ -458,10 +568,21 @@ class QueryWrapper:
|
|
458
568
|
query_name: str,
|
459
569
|
rows: any,
|
460
570
|
container_path: str = None,
|
571
|
+
transacted: bool = True,
|
572
|
+
audit_behavior: AuditBehavior = None,
|
573
|
+
audit_user_comment: str = None,
|
461
574
|
timeout: int = _default_timeout,
|
462
575
|
):
|
463
576
|
return delete_rows(
|
464
|
-
self.server_context,
|
577
|
+
self.server_context,
|
578
|
+
schema_name,
|
579
|
+
query_name,
|
580
|
+
rows,
|
581
|
+
container_path,
|
582
|
+
transacted,
|
583
|
+
audit_behavior,
|
584
|
+
audit_user_comment,
|
585
|
+
timeout
|
465
586
|
)
|
466
587
|
|
467
588
|
@functools.wraps(truncate_table)
|
@@ -484,6 +605,7 @@ class QueryWrapper:
|
|
484
605
|
parameters: dict = None,
|
485
606
|
required_version: float = None,
|
486
607
|
timeout: int = _default_timeout,
|
608
|
+
waf_encode_sql: bool = True
|
487
609
|
):
|
488
610
|
return execute_sql(
|
489
611
|
self.server_context,
|
@@ -498,6 +620,7 @@ class QueryWrapper:
|
|
498
620
|
parameters,
|
499
621
|
required_version,
|
500
622
|
timeout,
|
623
|
+
waf_encode_sql
|
501
624
|
)
|
502
625
|
|
503
626
|
@functools.wraps(insert_rows)
|
@@ -507,10 +630,23 @@ class QueryWrapper:
|
|
507
630
|
query_name: str,
|
508
631
|
rows: List[any],
|
509
632
|
container_path: str = None,
|
633
|
+
skip_reselect_rows: bool = False,
|
634
|
+
transacted: bool = True,
|
635
|
+
audit_behavior: AuditBehavior = None,
|
636
|
+
audit_user_comment: str = None,
|
510
637
|
timeout: int = _default_timeout,
|
511
638
|
):
|
512
639
|
return insert_rows(
|
513
|
-
self.server_context,
|
640
|
+
self.server_context,
|
641
|
+
schema_name,
|
642
|
+
query_name,
|
643
|
+
rows,
|
644
|
+
container_path,
|
645
|
+
skip_reselect_rows,
|
646
|
+
transacted,
|
647
|
+
audit_behavior,
|
648
|
+
audit_user_comment,
|
649
|
+
timeout
|
514
650
|
)
|
515
651
|
|
516
652
|
@functools.wraps(select_rows)
|
@@ -566,8 +702,45 @@ class QueryWrapper:
|
|
566
702
|
query_name: str,
|
567
703
|
rows: List[any],
|
568
704
|
container_path: str = None,
|
705
|
+
transacted: bool = True,
|
706
|
+
audit_behavior: AuditBehavior = None,
|
707
|
+
audit_user_comment: str = None,
|
569
708
|
timeout: int = _default_timeout,
|
570
709
|
):
|
571
710
|
return update_rows(
|
572
|
-
self.server_context,
|
711
|
+
self.server_context,
|
712
|
+
schema_name,
|
713
|
+
query_name,
|
714
|
+
rows,
|
715
|
+
container_path,
|
716
|
+
transacted,
|
717
|
+
audit_behavior,
|
718
|
+
audit_user_comment,
|
719
|
+
timeout
|
720
|
+
)
|
721
|
+
|
722
|
+
@functools.wraps(move_rows)
|
723
|
+
def move_rows(
|
724
|
+
self,
|
725
|
+
target_container_path: str,
|
726
|
+
schema_name: str,
|
727
|
+
query_name: str,
|
728
|
+
rows: any,
|
729
|
+
container_path: str = None,
|
730
|
+
transacted: bool = True,
|
731
|
+
audit_behavior: AuditBehavior = None,
|
732
|
+
audit_user_comment: str = None,
|
733
|
+
timeout: int = _default_timeout,
|
734
|
+
):
|
735
|
+
return move_rows(
|
736
|
+
self.server_context,
|
737
|
+
target_container_path,
|
738
|
+
schema_name,
|
739
|
+
query_name,
|
740
|
+
rows,
|
741
|
+
container_path,
|
742
|
+
transacted,
|
743
|
+
audit_behavior,
|
744
|
+
audit_user_comment,
|
745
|
+
timeout
|
573
746
|
)
|
labkey/utils.py
CHANGED
@@ -16,6 +16,8 @@
|
|
16
16
|
import json
|
17
17
|
from functools import wraps
|
18
18
|
from datetime import date, datetime
|
19
|
+
from base64 import b64encode
|
20
|
+
from urllib import parse
|
19
21
|
|
20
22
|
|
21
23
|
# Issue #14: json.dumps on datetime throws TypeError
|
@@ -71,3 +73,21 @@ def transform_helper(user_transform_func, file_path_run_properties):
|
|
71
73
|
row = [str(el).strip() for el in row]
|
72
74
|
row = "\t".join(row)
|
73
75
|
file_out.write(row + "\n")
|
76
|
+
|
77
|
+
|
78
|
+
def btoa(value: str) -> str:
|
79
|
+
if not value:
|
80
|
+
return value
|
81
|
+
binary = value.encode("utf-8")
|
82
|
+
return b64encode(binary).decode()
|
83
|
+
|
84
|
+
|
85
|
+
def encode_uri_component(value: str) -> str:
|
86
|
+
# https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
|
87
|
+
return parse.quote(value, encoding="utf-8", safe="-_.!~*'()")
|
88
|
+
|
89
|
+
|
90
|
+
def waf_encode(value: str) -> str:
|
91
|
+
if value:
|
92
|
+
return "/*{{base64/x-www-form-urlencoded/wafText}}*/" + btoa(encode_uri_component(value))
|
93
|
+
return value
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: labkey
|
3
|
-
Version:
|
3
|
+
Version: 3.0.0
|
4
4
|
Summary: Python client API for LabKey Server
|
5
5
|
Home-page: https://github.com/LabKey/labkey-api-python
|
6
6
|
Author: LabKey
|
@@ -9,7 +9,6 @@ Maintainer: Alan Vezina
|
|
9
9
|
Maintainer-email: alanv@labkey.com
|
10
10
|
License: Apache License 2.0
|
11
11
|
Keywords: labkey api client
|
12
|
-
Platform: UNKNOWN
|
13
12
|
Classifier: Development Status :: 4 - Beta
|
14
13
|
Classifier: Environment :: Console
|
15
14
|
Classifier: Intended Audience :: Science/Research
|
@@ -20,6 +19,7 @@ Classifier: Operating System :: Microsoft
|
|
20
19
|
Classifier: Operating System :: POSIX
|
21
20
|
Classifier: Programming Language :: Python :: 3
|
22
21
|
Classifier: Topic :: Scientific/Engineering
|
22
|
+
License-File: LICENSE.txt
|
23
23
|
Requires-Dist: requests
|
24
24
|
Provides-Extra: test
|
25
25
|
Requires-Dist: pytest ; extra == 'test'
|
@@ -28,5 +28,3 @@ Requires-Dist: mock ; extra == 'test'
|
|
28
28
|
Requires-Dist: pytest-cov ; extra == 'test'
|
29
29
|
|
30
30
|
Python client API for LabKey Server. Supports query and experiment APIs.
|
31
|
-
|
32
|
-
|
@@ -1,16 +1,16 @@
|
|
1
|
-
labkey/__init__.py,sha256=
|
1
|
+
labkey/__init__.py,sha256=q1xx8gL3h06R1DGXoOOInvVNbmuIOmuCexBPMyEApxM,695
|
2
2
|
labkey/api_wrapper.py,sha256=ks6q5qwcGkutg2m5sMdTvryhfK42yltfPCV5iLPi22k,1351
|
3
3
|
labkey/container.py,sha256=DXmLhGsNnN_QLXa_tMCM0Xf_Kkz7B8KjRFhJT5I4FtY,5497
|
4
4
|
labkey/domain.py,sha256=SABG7BfSqQGJr8DPjUsvhi8C7xP2MTpkq24sdtAu4J8,22486
|
5
5
|
labkey/exceptions.py,sha256=VtuKphEczSsfHAXgWRv-2HRzxSiObBnOEC_sgEPPR3c,2929
|
6
6
|
labkey/experiment.py,sha256=Wtuz52bhuvDWk_o2AbTw7SJnwEji2iD6Q04ct0PWSxE,8804
|
7
|
-
labkey/query.py,sha256=
|
7
|
+
labkey/query.py,sha256=0Hp8P-mFuqurGlVbF71BN3Woz6tZfdweRKW0s4GFsh4,23995
|
8
8
|
labkey/security.py,sha256=cVrlYbb7Yogjo9L1exGKgpscRFEljBpzFITQZWHW2X8,15284
|
9
9
|
labkey/server_context.py,sha256=UGf4fJ9Cw_YIM_DwdPVP8WgKORt5aO_4bFCz14rjsrg,6950
|
10
10
|
labkey/storage.py,sha256=WpgpTWQzgig_qJXMGszFcFjtf8oMd2-6TBehSkpJPUg,6144
|
11
|
-
labkey/utils.py,sha256=
|
12
|
-
labkey-
|
13
|
-
labkey-
|
14
|
-
labkey-
|
15
|
-
labkey-
|
16
|
-
labkey-
|
11
|
+
labkey/utils.py,sha256=oL6qmHkpzLTm_9c7gSEzumv_MVh5s8fj6bOrbuslrV0,3233
|
12
|
+
labkey-3.0.0.dist-info/LICENSE.txt,sha256=xllut76FgcGL5zbIRvuRc7aezPbvlMUTWJPsVr2Sugg,11358
|
13
|
+
labkey-3.0.0.dist-info/METADATA,sha256=BtwRKk5F9ja7CD37QvyCljOi0_R9Dq-10uUS0OH3BHQ,1076
|
14
|
+
labkey-3.0.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
15
|
+
labkey-3.0.0.dist-info/top_level.txt,sha256=DQIk1fQNg7NxxBsEt_K7k-aopiH87jmnU98zwDp0n04,7
|
16
|
+
labkey-3.0.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|