labkey 3.2.0__py3-none-any.whl → 3.4.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 CHANGED
@@ -14,6 +14,6 @@
14
14
  # limitations under the License.
15
15
  #
16
16
  __title__ = "labkey"
17
- __version__ = "3.2.0"
17
+ __version__ = "3.4.0"
18
18
  __author__ = "LabKey"
19
19
  __license__ = "Apache License 2.0"
labkey/domain.py CHANGED
@@ -14,7 +14,7 @@
14
14
  # limitations under the License.
15
15
  #
16
16
  import functools
17
- from typing import Dict, List, Union, Tuple
17
+ from typing import Dict, List, Union, Tuple, TextIO
18
18
 
19
19
  from .server_context import ServerContext
20
20
  from labkey.query import QueryFilter
@@ -109,6 +109,7 @@ class PropertyDescriptor:
109
109
  )
110
110
  self.type_editable = kwargs.pop("type_editable", kwargs.pop("typeEditable", None))
111
111
  self.url = kwargs.pop("url", None)
112
+ self.value_expression = kwargs.pop("value_expression", kwargs.pop("valueExpression", None))
112
113
 
113
114
  def to_json(self, strip_none=True):
114
115
  # TODO: Likely only want to include those that are not None
@@ -155,6 +156,7 @@ class PropertyDescriptor:
155
156
  "shownInUpdateView": self.shown_in_update_view,
156
157
  "typeEditable": self.type_editable,
157
158
  "url": self.url,
159
+ "valueExpression": self.value_expression,
158
160
  }
159
161
 
160
162
  json_formats = []
@@ -232,9 +234,11 @@ class Domain:
232
234
  "template_description", kwargs.pop("templateDescription", None)
233
235
  )
234
236
 
235
- fields = kwargs.pop("fields", [])
236
237
  fields_instances = []
237
-
238
+ fields = kwargs.pop("fields", [])
239
+ for field in fields:
240
+ fields_instances.append(PropertyDescriptor(**field))
241
+ fields = kwargs.pop("calculated_fields", kwargs.pop("calculatedFields", []))
238
242
  for field in fields:
239
243
  fields_instances.append(PropertyDescriptor(**field))
240
244
 
@@ -483,7 +487,7 @@ def get_domain_details(
483
487
 
484
488
 
485
489
  def infer_fields(
486
- server_context: ServerContext, data_file: any, container_path: str = None
490
+ server_context: ServerContext, data_file: TextIO, container_path: str = None
487
491
  ) -> List[PropertyDescriptor]:
488
492
  """
489
493
  Infer fields for a domain from a file
labkey/query.py CHANGED
@@ -41,7 +41,7 @@ https://www.labkey.org/home/developer/forum/project-start.view
41
41
  ############################################################################
42
42
  """
43
43
  import functools
44
- from typing import List
44
+ from typing import List, TextIO
45
45
 
46
46
  from .server_context import ServerContext
47
47
  from .utils import waf_encode
@@ -357,6 +357,56 @@ def insert_rows(
357
357
  )
358
358
 
359
359
 
360
+ def import_rows(
361
+ server_context: ServerContext,
362
+ schema_name: str,
363
+ query_name: str,
364
+ data_file: TextIO,
365
+ container_path: str = None,
366
+ insert_option: str = None,
367
+ audit_behavior: str = None,
368
+ import_lookup_by_alternate_key: bool = False,
369
+ ):
370
+ """
371
+ Import row(s) into a table
372
+ :param server_context: A LabKey server context. See utils.create_server_context.
373
+ :param schema_name: schema of table
374
+ :param query_name: table name to import into
375
+ :param data_file: the file containing the rows to import. The column names in the file must match the column names
376
+ from the LabKey server.
377
+ :param container_path: labkey container path if not already set in context
378
+ :param insert_option: Whether the import action should be done as an insert, creating new rows for each provided row
379
+ of the data frame, or a merge. When merging during import, any data you provide for the rows representing records
380
+ that already exist will replace the previous values. Note that when updating an existing record, you only need to
381
+ provide the columns you wish to update, existing data for other columns will be left as is. Available options are
382
+ "INSERT" and "MERGE". Defaults to "INSERT".
383
+ :param audit_behavior: Set the level of auditing details for this import action. Available options are "SUMMARY" and
384
+ "DETAILED". SUMMARY - Audit log reflects that a change was made, but does not mention the nature of the change.
385
+ DETAILED - Provides full details on what change was made, including values before and after the change. Defaults to
386
+ the setting as specified by the LabKey query.
387
+ :param import_lookup_by_alternate_key: Allows lookup target rows to be resolved by values rather than the target's
388
+ primary key. This option will only be available for lookups that are configured with unique column information
389
+ :return:
390
+ """
391
+ url = server_context.build_url("query", "import.api", container_path=container_path)
392
+ file_payload = {"file": data_file}
393
+ payload = {
394
+ "schemaName": schema_name,
395
+ "queryName": query_name,
396
+ }
397
+
398
+ if insert_option is not None:
399
+ payload["insertOption"] = insert_option
400
+
401
+ if audit_behavior is not None:
402
+ payload["auditBehavior"] = audit_behavior
403
+
404
+ if import_lookup_by_alternate_key is not None:
405
+ payload["importLookupByAlternateKey"] = import_lookup_by_alternate_key
406
+
407
+ return server_context.make_request(url, payload, method="POST", file_payload=file_payload)
408
+
409
+
360
410
  def select_rows(
361
411
  server_context: ServerContext,
362
412
  schema_name: str,
@@ -654,6 +704,28 @@ class QueryWrapper:
654
704
  timeout,
655
705
  )
656
706
 
707
+ @functools.wraps(import_rows)
708
+ def import_rows(
709
+ self,
710
+ schema_name: str,
711
+ query_name: str,
712
+ data_file,
713
+ container_path: str = None,
714
+ insert_option: str = None,
715
+ audit_behavior: str = None,
716
+ import_lookup_by_alternate_key: bool = False,
717
+ ):
718
+ return import_rows(
719
+ self.server_context,
720
+ schema_name,
721
+ query_name,
722
+ data_file,
723
+ container_path,
724
+ insert_option,
725
+ audit_behavior,
726
+ import_lookup_by_alternate_key,
727
+ )
728
+
657
729
  @functools.wraps(select_rows)
658
730
  def select_rows(
659
731
  self,
labkey/security.py CHANGED
@@ -121,6 +121,7 @@ def deactivate_users(
121
121
  target_ids=target_ids,
122
122
  api="deactivateUsers.view",
123
123
  container_path=container_path,
124
+ allow_redirects=True,
124
125
  )
125
126
  if response is not None and response["status_code"] == 200:
126
127
  return dict(success=True)
@@ -360,7 +361,11 @@ def __make_security_role_api_request(
360
361
 
361
362
 
362
363
  def __make_user_api_request(
363
- server_context: ServerContext, target_ids: List[int], api: str, container_path: str = None
364
+ server_context: ServerContext,
365
+ target_ids: List[int],
366
+ api: str,
367
+ container_path: str = None,
368
+ allow_redirects: bool = False,
364
369
  ):
365
370
  """
366
371
  Make a request to the LabKey User Controller
@@ -372,7 +377,7 @@ def __make_user_api_request(
372
377
  """
373
378
  url = server_context.build_url(USER_CONTROLLER, api, container_path)
374
379
 
375
- return server_context.make_request(url, {"userId": target_ids})
380
+ return server_context.make_request(url, {"userId": target_ids}, allow_redirects=allow_redirects)
376
381
 
377
382
 
378
383
  class SecurityWrapper:
labkey/server_context.py CHANGED
@@ -1,3 +1,4 @@
1
+ from typing import Dict, TextIO
1
2
  from labkey.utils import json_dumps
2
3
  from . import __version__
3
4
  import requests
@@ -163,7 +164,12 @@ class ServerContext:
163
164
  return client
164
165
 
165
166
  def handle_request_exception(self, exception):
166
- if type(exception) in [RequestAuthorizationError, QueryNotFoundError, ServerNotFoundError]:
167
+ if type(exception) in [
168
+ RequestAuthorizationError,
169
+ QueryNotFoundError,
170
+ ServerNotFoundError,
171
+ UnexpectedRedirectError,
172
+ ]:
167
173
  raise exception
168
174
 
169
175
  raise ServerContextError(self, exception)
@@ -176,7 +182,7 @@ class ServerContext:
176
182
  timeout: int = 300,
177
183
  method: str = "POST",
178
184
  non_json_response: bool = False,
179
- file_payload: any = None,
185
+ file_payload: Dict[str, TextIO] = None,
180
186
  json: dict = None,
181
187
  allow_redirects=False,
182
188
  ) -> any:
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: labkey
3
- Version: 3.2.0
3
+ Version: 3.4.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
@@ -21,21 +21,34 @@ Classifier: Programming Language :: Python :: 3
21
21
  Classifier: Topic :: Scientific/Engineering
22
22
  License-File: LICENSE.txt
23
23
  Requires-Dist: requests
24
- Provides-Extra: build
25
- Requires-Dist: setuptools ; extra == 'build'
26
- Requires-Dist: build ; extra == 'build'
27
- Requires-Dist: twine ; extra == 'build'
28
- Requires-Dist: wheel ; extra == 'build'
29
- Provides-Extra: dev
30
- Requires-Dist: pytest ; extra == 'dev'
31
- Requires-Dist: requests ; extra == 'dev'
32
- Requires-Dist: mock ; extra == 'dev'
33
- Requires-Dist: pytest-cov ; extra == 'dev'
34
- Requires-Dist: black ; extra == 'dev'
35
24
  Provides-Extra: test
36
- Requires-Dist: pytest ; extra == 'test'
37
- Requires-Dist: requests ; extra == 'test'
38
- Requires-Dist: mock ; extra == 'test'
39
- Requires-Dist: pytest-cov ; extra == 'test'
25
+ Requires-Dist: pytest; extra == "test"
26
+ Requires-Dist: requests; extra == "test"
27
+ Requires-Dist: mock; extra == "test"
28
+ Requires-Dist: pytest-cov; extra == "test"
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest; extra == "dev"
31
+ Requires-Dist: requests; extra == "dev"
32
+ Requires-Dist: mock; extra == "dev"
33
+ Requires-Dist: pytest-cov; extra == "dev"
34
+ Requires-Dist: black; extra == "dev"
35
+ Provides-Extra: build
36
+ Requires-Dist: setuptools; extra == "build"
37
+ Requires-Dist: build; extra == "build"
38
+ Requires-Dist: twine; extra == "build"
39
+ Requires-Dist: wheel; extra == "build"
40
+ Dynamic: author
41
+ Dynamic: author-email
42
+ Dynamic: classifier
43
+ Dynamic: description
44
+ Dynamic: home-page
45
+ Dynamic: keywords
46
+ Dynamic: license
47
+ Dynamic: license-file
48
+ Dynamic: maintainer
49
+ Dynamic: maintainer-email
50
+ Dynamic: provides-extra
51
+ Dynamic: requires-dist
52
+ Dynamic: summary
40
53
 
41
54
  Python client API for LabKey Server. Supports query and experiment APIs.
@@ -0,0 +1,16 @@
1
+ labkey/__init__.py,sha256=dM58BofELTYOYGq-HlslSKn1Vqqi2wIc_hH-L6Miu6s,695
2
+ labkey/api_wrapper.py,sha256=OxnV6_5jONWiwsi24TOXTKP5inXtAfABGqXAPua3eCM,1427
3
+ labkey/container.py,sha256=DXmLhGsNnN_QLXa_tMCM0Xf_Kkz7B8KjRFhJT5I4FtY,5497
4
+ labkey/domain.py,sha256=HpZ2zz1lqJcet4np_cCq06LfrCJsBClsPvSsCTKAj9M,22829
5
+ labkey/exceptions.py,sha256=00x-4oP_2d0SfZKxsGIs8QGvXiNq2y7C5hAzuzT3Gkk,3619
6
+ labkey/experiment.py,sha256=6U4BXnYHNXCUF_mee0maK_CZDVm_lbMjC82ywx9YCTE,12062
7
+ labkey/query.py,sha256=zQH7qO2UH8aSHLa8GhEklNvEb6fj2cjdB3AI4Q4m2n8,27133
8
+ labkey/security.py,sha256=wX_4qQkllh-y7U4cqYIxs89XHGUtbC5cCebBKbgl0Y8,15417
9
+ labkey/server_context.py,sha256=pM8GtVu403mD8DQ3yz5mpC-DMUq-ZWPA-JzEHTRIJhA,7871
10
+ labkey/storage.py,sha256=WpgpTWQzgig_qJXMGszFcFjtf8oMd2-6TBehSkpJPUg,6144
11
+ labkey/utils.py,sha256=oL6qmHkpzLTm_9c7gSEzumv_MVh5s8fj6bOrbuslrV0,3233
12
+ labkey-3.4.0.dist-info/licenses/LICENSE.txt,sha256=xllut76FgcGL5zbIRvuRc7aezPbvlMUTWJPsVr2Sugg,11358
13
+ labkey-3.4.0.dist-info/METADATA,sha256=ylw_5Z7GEKb-di9tDYJHO2aQEQ8mhajp2tpzEFN4hLQ,1733
14
+ labkey-3.4.0.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
15
+ labkey-3.4.0.dist-info/top_level.txt,sha256=DQIk1fQNg7NxxBsEt_K7k-aopiH87jmnU98zwDp0n04,7
16
+ labkey-3.4.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (74.1.2)
2
+ Generator: setuptools (79.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,16 +0,0 @@
1
- labkey/__init__.py,sha256=BxplFb91voofYbNkCpovsh5LfOdvBLWqCmHPjhy2Lj0,695
2
- labkey/api_wrapper.py,sha256=OxnV6_5jONWiwsi24TOXTKP5inXtAfABGqXAPua3eCM,1427
3
- labkey/container.py,sha256=DXmLhGsNnN_QLXa_tMCM0Xf_Kkz7B8KjRFhJT5I4FtY,5497
4
- labkey/domain.py,sha256=SABG7BfSqQGJr8DPjUsvhi8C7xP2MTpkq24sdtAu4J8,22486
5
- labkey/exceptions.py,sha256=00x-4oP_2d0SfZKxsGIs8QGvXiNq2y7C5hAzuzT3Gkk,3619
6
- labkey/experiment.py,sha256=6U4BXnYHNXCUF_mee0maK_CZDVm_lbMjC82ywx9YCTE,12062
7
- labkey/query.py,sha256=w6vYDwiwnLalrDQ8pGY-c9DvoPQuMXaFXnZLRUiezuk,24041
8
- labkey/security.py,sha256=eMa2b_22FWB2rVvVpxTeWrK0VgGTszhRchsApbDR6sA,15306
9
- labkey/server_context.py,sha256=0YcA7BRijLMs172qTrTB12MlnIcqz4X9dkkCwSxxzaA,7741
10
- labkey/storage.py,sha256=WpgpTWQzgig_qJXMGszFcFjtf8oMd2-6TBehSkpJPUg,6144
11
- labkey/utils.py,sha256=oL6qmHkpzLTm_9c7gSEzumv_MVh5s8fj6bOrbuslrV0,3233
12
- labkey-3.2.0.dist-info/LICENSE.txt,sha256=xllut76FgcGL5zbIRvuRc7aezPbvlMUTWJPsVr2Sugg,11358
13
- labkey-3.2.0.dist-info/METADATA,sha256=0xOPpsSbHkT9ow_bUQeILdYVPAcFIwmr_KG1tlHHbxQ,1481
14
- labkey-3.2.0.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
15
- labkey-3.2.0.dist-info/top_level.txt,sha256=DQIk1fQNg7NxxBsEt_K7k-aopiH87jmnU98zwDp0n04,7
16
- labkey-3.2.0.dist-info/RECORD,,