def test_encoder(self): # test date and datetime encoding payload = { 'my_date': date(1985, 9, 11), 'my_date_time': datetime(2018, 9, 18, 5, 25) } utils.json_dumps(payload)
def test_encoder_override(self): payload = {'testdate': datetime(2018, 9, 11, 6, 45)} try: # disable the "cls" override by passing None utils.json_dumps(payload, cls=None) except TypeError as e: if "is not JSON serializable" not in str(e): print("Did not see expected exception") raise e
def load_batch(server_context, assay_id, batch_id): # type: (ServerContext, int, int) -> Union[Batch, None] """ Loads a batch from the server. :param server_context: A LabKey server context. See utils.create_server_context. :param assay_id: The protocol id of the assay from which to load a batch. :param batch_id: :return: """ load_batch_url = server_context.build_url('assay', 'getAssayBatch.api') loaded_batch = None payload = { 'assayId': assay_id, 'batchId': batch_id } headers = { 'Content-type': 'application/json', 'Accept': 'text/plain' } json_body = server_context.make_request(load_batch_url, json_dumps(payload, sort_keys=True), headers=headers) if json_body is not None: loaded_batch = Batch.from_data(json_body['batch']) return loaded_batch
def save(server_context, schema_name, query_name, domain, container_path=None): # type: (ServerContext, str, str, Domain, str) -> None """ Saves the provided domain design :param server_context: A LabKey server context. See utils.create_server_context. :param schema_name: schema of domain :param query_name: query name of domain :param domain: Domain to save :param container_path: labkey container path if not already set in context :return: """ url = server_context.build_url('property', 'saveDomain.api', container_path=container_path) headers = {'Content-Type': 'application/json'} payload = { 'domainDesign': domain.to_json(), 'queryName': query_name, 'schemaName': schema_name } return server_context.make_request(url, json_dumps(payload), headers=headers)
def create(server_context, domain_definition, container_path=None): # type: (ServerContext, dict, str) -> Domain """ Create a domain :param server_context: A LabKey server context. See utils.create_server_context. :param domain_definition: A domain definition. :param container_path: labkey container path if not already set in context :return: Domain """ url = server_context.build_url('property', 'createDomain.api', container_path=container_path) headers = {'Content-Type': 'application/json'} domain = None raw_domain = server_context.make_request(url, json_dumps(domain_definition), headers=headers) if raw_domain is not None: domain = Domain.from_data(raw_domain) return domain
def delete_rows(server_context, schema_name, query_name, rows, container_path=None, timeout=_default_timeout): """ Delete a set of rows from the schema.query :param server_context: A LabKey server context. See utils.create_server_context. :param schema_name: schema of table :param query_name: table name to delete from :param rows: Set of rows to delete :param container_path: labkey container path if not already set in context :param timeout: timeout of request in seconds (defaults to 30s) :return: """ url = server_context.build_url('query', 'deleteRows.api', container_path=container_path) payload = { 'schemaName': schema_name, 'queryName': query_name, 'rows': rows } return server_context.make_request(url, json_dumps(payload, sort_keys=True), headers=_query_headers, timeout=timeout)
def save_batches(server_context, assay_id, batches): # type: (ServerContext, int, List[Batch]) -> Union[List[Batch], None] """ Saves a modified batches. :param server_context: A LabKey server context. See utils.create_server_context. :param assay_id: The assay protocol id. :param batches: The Batch(es) to save. :return: """ save_batch_url = server_context.build_url('assay', 'saveAssayBatch.api') json_batches = [] if batches is None: return None # Nothing to save for batch in batches: if isinstance(batch, Batch): json_batches.append(batch.to_json()) else: raise Exception( 'save_batch() "batches" expected to be a set Batch instances') payload = {'assayId': assay_id, 'batches': json_batches} headers = {'Content-type': 'application/json', 'Accept': 'text/plain'} json_body = server_context.make_request(save_batch_url, json_dumps(payload, sort_keys=True), headers=headers) if json_body is not None: resp_batches = json_body['batches'] return [Batch.from_data(resp_batch) for resp_batch in resp_batches] return None
def make_request( self, url: str, payload: any = None, headers: dict = None, timeout: int = 300, method: str = "POST", non_json_response: bool = False, file_payload: any = None, json: dict = None, ) -> any: if self._api_key is not None: if self._session.headers.get(API_KEY_TOKEN) is not self._api_key: self._session.headers.update({API_KEY_TOKEN: self._api_key}) if not self._disable_csrf and CSRF_TOKEN not in self._session.headers.keys(): try: csrf_url = self.build_url("login", "whoami.api") response = handle_response(self._session.get(csrf_url)) self._session.headers.update({CSRF_TOKEN: response["CSRF"]}) except RequestException as e: self.handle_request_exception(e) try: if method == "GET": response = self._session.get(url, params=payload, headers=headers, timeout=timeout) else: if file_payload is not None: response = self._session.post( url, data=payload, files=file_payload, headers=headers, timeout=timeout, ) elif json is not None: if headers is None: headers = {} headers_ = {**headers, "Content-Type": "application/json"} # sort_keys is a hack to make unit tests work data = json_dumps(json, sort_keys=True) response = self._session.post(url, data=data, headers=headers_, timeout=timeout) else: response = self._session.post( url, data=payload, headers=headers, timeout=timeout ) return handle_response(response, non_json_response) except RequestException as e: self.handle_request_exception(e)
def drop(server_context, schema_name, query_name, container_path=None): # type: (ServerContext, str, str, str) -> dict """ Delete a domain :param server_context: A LabKey server context. See utils.create_server_context. :param schema_name: schema of table :param query_name: table name of domain to drop :param container_path: labkey container path if not already set in context :return: """ url = server_context.build_url('property', 'deleteDomain.api', container_path=container_path) headers = {'Content-Type': 'application/json'} payload = {'schemaName': schema_name, 'queryName': query_name} return server_context.make_request(url, json_dumps(payload), headers=headers)
def update_wiki(server_context, wiki_name, wiki_body, container_path=None): """ Used to update an existing wiki page :param server_context: A LabKey server context. See labkey.utils.create_server_context. :param wiki_name: The name of the wiki. :param wiki_body: The body of the wiki. :param container_path: Optional container path that can be used to override the server_context container path :return: returns a dictionary containing the response from the server. The 'success' key in the dictionary will be true when the wiki was successfully updated. It will be false in the case of a failure. In the case of a failure, the 'error' key contains the error message returned by the server. """ # Build the URL for reading the wiki page read_wiki_url = server_context.build_url('wiki', 'editWiki.api', container_path=container_path) payload = {'name': wiki_name} headers = {'Content-type': 'application/json'} try: read_response = server_context.make_request(read_wiki_url, payload, headers=headers, method='GET', non_json_response=True) except SSLError as e: print( "There was a problem while attempting to submit the read for the wiki page " + str(wiki_name) + " via the URL " + str(e.geturl()) + ". The HTTP response code was " + str(e.getcode())) print("The HTTP client error was: " + format(e)) return 1 # TODO: this is incorrect, should return 'success'/'error' properly like the docs say data = read_response.text # Search HTML response for required information on wiki. This is stored in the javascript # variable named # - _wikiProps: for 14.3 and earlier # - LABKEY._wiki.setProps for 15.1 and later data_list = data.split('\n') # If LabKey Server is v14.3 or earlier find line containing '_wikiProp' v = next((i for i in range(len(data_list)) if '_wikiProp' in data_list[i]), None) # If v = None, then server is running 15.1 or later and find the line # containing 'LABKEY._wiki.setProps' if v is None: v = next((i for i in range(len(data_list)) if 'LABKEY._wiki.setProps' in data_list[i]), None) # Verify that we found the variable in the HTML response. If not # do not proceed if v is None: print( "There was a problem while attempting to read the data for the wiki page '" + str(wiki_name) + "'.") print( "The script is unable to find the wiki properties in the HTML response" ) return 1 # TODO: this is incorrect, should return 'success'/'error' properly like the docs say wiki_vars = {} for j in range(100): # Read each line, until find a javascript closing bracket. if '};' in data_list[v + j + 1]: break if '});' in data_list[v + j + 1]: break wvar = data_list[v + j + 1].rstrip().lstrip().replace('\'', '').replace( ',', '') wiki_vars[wvar.split(':')[0]] = wvar.split(':')[1] # Build the URL for updating the wiki page update_wiki_url = server_context.build_url('wiki', 'saveWiki.api', container_path=container_path) headers = {'Content-type': 'application/json'} # Update wiki_vars to use the new wiki content. wiki_vars['name'] = wiki_name wiki_vars['body'] = wiki_body try: data = server_context.make_request(update_wiki_url, payload=json_dumps(wiki_vars, sort_keys=True), headers=headers, non_json_response=True) except SSLError as e: print( "There was a problem while attempting to submit the read for the wiki page '" + str(wiki_name) + "' via the URL " + str(e.geturl()) + ". The HTTP response code was " + str(e.getcode())) print("The HTTP client error was: " + format(e)) return 1 # TODO: this is incorrect, should return 'success'/'error' properly like the docs say return data