diff --git a/api-openbis-python3-pybis/src/python/CHANGELOG.md b/api-openbis-python3-pybis/src/python/CHANGELOG.md index 192d809f9d59101d66966dd467a0d368fe5e6d41..d35eade24a93da1e76e6b3ab1624daa28dcb7842 100644 --- a/api-openbis-python3-pybis/src/python/CHANGELOG.md +++ b/api-openbis-python3-pybis/src/python/CHANGELOG.md @@ -1,3 +1,10 @@ +## Changes with pybis-1.36.3 + +- Refactored metaData and multiValue properties to be backwards-compatible. +- Refactored get_children/get_parents methods +- Refactored property formatting functionality + + ## Changes with pybis-1.36.2 - Refactoring of the set_token method. diff --git a/api-openbis-python3-pybis/src/python/pybis/attribute.py b/api-openbis-python3-pybis/src/python/pybis/attribute.py index 7ca192e5c12328e1996204cb74c57a4790463ef1..a5e9a8fa0b268a012ab75e5fc1ab5c95e0b6c924 100644 --- a/api-openbis-python3-pybis/src/python/pybis/attribute.py +++ b/api-openbis-python3-pybis/src/python/pybis/attribute.py @@ -745,6 +745,8 @@ class AttrHolder: """get the current parents and return them as a list (Things/DataFrame) or return empty list """ + if self.parents is None or self.parents == []: + return self.parents return getattr(self._openbis, "get_" + self._entity.lower())( self.parents, **kwargs ) @@ -791,6 +793,8 @@ class AttrHolder: """get the current children and return them as a list (Things/DataFrame) or return empty list """ + if self.children is None or self.children == []: + return self.children return getattr(self._openbis, "get_" + self._entity.lower())( self.children, **kwargs ) diff --git a/api-openbis-python3-pybis/src/python/pybis/experiment.py b/api-openbis-python3-pybis/src/python/pybis/experiment.py index 7e9f0bfd9f345c39e53c89f518eca1d6d9be65de..dd23a54ae0d3b40db2431a8f134a3c6af2aa2573 100644 --- a/api-openbis-python3-pybis/src/python/pybis/experiment.py +++ b/api-openbis-python3-pybis/src/python/pybis/experiment.py @@ -30,15 +30,26 @@ class Experiment( for key, value in data["properties"].items(): property_type = self.p._property_names[key.lower()] data_type = property_type['dataType'] - if data_type in ("ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"): - value = self.formatter.to_array(data_type, value) - elif "multiValue" in property_type: + if "multiValue" in property_type: if property_type['multiValue'] is True: if type(value) is not list: value = [value] + if data_type in ( + "ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"): + value = [self.formatter.to_array(data_type, x) for x in value] + else: + value = self.formatter.to_array(data_type, value) else: - if type(value) is list: - raise ValueError(f'Property type {property_type["code"]} is not a multi-value property!') + if type(value) is list and data_type not in ( + "ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"): + raise ValueError( + f'Property type {property_type} is not a multi-value property!') + if data_type in ( + "ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"): + value = self.formatter.to_array(data_type, value) + else: + if data_type in ("ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"): + value = self.formatter.to_array(data_type, value) self.p.__dict__[key.lower()] = value def __str__(self): diff --git a/api-openbis-python3-pybis/src/python/pybis/openbis_object.py b/api-openbis-python3-pybis/src/python/pybis/openbis_object.py index d19d90b8663914cd324e08e4130962df82702553..b6203079c3e952fdfc9389191adf0347554000dd 100644 --- a/api-openbis-python3-pybis/src/python/pybis/openbis_object.py +++ b/api-openbis-python3-pybis/src/python/pybis/openbis_object.py @@ -71,8 +71,26 @@ class OpenBisObject: # put the properties in the self.p namespace (without checking them) if "properties" in data: for key, value in data["properties"].items(): - if self.p.type: - data_type = self.p._property_names[key.lower()]['dataType'] + property_type = self.p._property_names[key.lower()] + data_type = property_type['dataType'] + if "multiValue" in property_type: + if property_type['multiValue'] is True: + if type(value) is not list: + value = [value] + if data_type in ( + "ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"): + value = [self.formatter.to_array(data_type, x) for x in value] + else: + value = self.formatter.to_array(data_type, value) + else: + if type(value) is list and data_type not in ( + "ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"): + raise ValueError( + f'Property type {property_type} is not a multi-value property!') + if data_type in ( + "ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"): + value = self.formatter.to_array(data_type, value) + else: if data_type in ("ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"): value = self.formatter.to_array(data_type, value) self.p.__dict__[key.lower()] = value @@ -208,6 +226,16 @@ class OpenBisObject: # NEW if self.is_new: request = self._new_attrs() + + version = self.openbis.get_server_information().openbis_version + if version is not None: + if 'SNAPSHOT' not in version and not version.startswith('7') and 'UNKNOWN' not in version: + if request['method'] == 'createPropertyTypes' and 'multiValue' in request['params'][1][0]: + del request['params'][1][0]['multiValue'] + if (request['method'] in ('createSampleTypes', 'createExperimentTypes', 'createDataSetTypes') + and 'metaData' in request['params'][1][0]): + del request['params'][1][0]['metaData'] + if props: request["params"][1][0]["properties"] = props @@ -223,6 +251,13 @@ class OpenBisObject: else: request = self._up_attrs(method_name=None, permId=self._permId) + version = self.openbis.get_server_information().openbis_version + if version is not None: + if 'SNAPSHOT' not in version and not version.startswith('7') and 'UNKNOWN' not in version: + if (request['method'] in ('updateSampleTypes', 'updateExperimentTypes', 'updateDataSetTypes') + and 'metaData' in request['params'][1][0]): + del request['params'][1][0]['metaData'] + if props: request["params"][1][0]["properties"] = props diff --git a/api-openbis-python3-pybis/src/python/pybis/property.py b/api-openbis-python3-pybis/src/python/pybis/property.py index e6fe02d6bfc02c98b012bc26ed253abd2247d181..d070345abca27ed5b650d06ed0b688460a06b24f 100644 --- a/api-openbis-python3-pybis/src/python/pybis/property.py +++ b/api-openbis-python3-pybis/src/python/pybis/property.py @@ -14,10 +14,6 @@ # from tabulate import tabulate -from pybis.utils import ( - check_datatype, -) - class PropertyHolder: def __init__(self, openbis_obj, type=None): @@ -163,8 +159,9 @@ class PropertyHolder: elif data_type in ( "INTEGER", "BOOLEAN", "VARCHAR", "ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"): - if not check_datatype(data_type, value): - raise ValueError(f"Value must be of type {data_type}") + pass + # if not check_datatype(data_type, value): + # raise ValueError(f"Value must be of type {data_type}") self.__dict__[name] = value def __setitem__(self, key, value): diff --git a/api-openbis-python3-pybis/src/python/pybis/property_reformatter.py b/api-openbis-python3-pybis/src/python/pybis/property_reformatter.py index 5257595ca8ddcdc129821f284f645104795a044a..2a038909b13c19765eeeae70dd1db5860236acad 100644 --- a/api-openbis-python3-pybis/src/python/pybis/property_reformatter.py +++ b/api-openbis-python3-pybis/src/python/pybis/property_reformatter.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # -import re from datetime import datetime import pandas as pd @@ -51,10 +50,14 @@ class PropertyReformatter: if property_type.dataType == 'TIMESTAMP': properties[key] = self._format_timestamp(value) elif property_type.dataType == 'ARRAY_TIMESTAMP': - properties[key] = ",".join([self._format_timestamp(x) for x in value]) + if property_type.multiValue: + properties[key] = ["[" + ",".join(map(str, [self._format_timestamp(x) for x in arr])) + "]" for arr in value] + else: + properties[key] = [self._format_timestamp(x) for x in value] elif property_type.dataType.startswith('ARRAY'): - properties[key] = ",".join(map(str, value)) - + if property_type.multiValue: + properties[key] = ["[" + ",".join(map(str, x)) + "]" for x in value] + return properties def _format_timestamp(self, value): @@ -72,12 +75,14 @@ class PropertyReformatter: if prop_value is None or prop_value == "": return [] result = [] - if data_type == "ARRAY_INTEGER": - result = [int(x.strip()) for x in prop_value.split(',')] - elif data_type == "ARRAY_REAL": - result = [float(x.strip()) for x in prop_value.split(',')] - elif data_type == "ARRAY_STRING": - result = [x.strip() for x in re.split(r"(?<!\\),", prop_value)] - elif data_type == "ARRAY_TIMESTAMP": - result = [x.strip() for x in prop_value.split(',')] + if data_type in ("ARRAY_INTEGER", "INTEGER"): + result = [int(x.strip()) for x in prop_value] + elif data_type in ("ARRAY_REAL", "REAL"): + result = [float(x.strip()) for x in prop_value] + elif data_type == "BOOLEAN": + result = [x.strip().lower() == "true" for x in prop_value] + elif data_type in ("ARRAY_TIMESTAMP", "TIMESTAMP", "DATE"): + result = [x.strip() for x in prop_value] + else: + result = prop_value return result diff --git a/api-openbis-python3-pybis/src/python/pybis/pybis.py b/api-openbis-python3-pybis/src/python/pybis/pybis.py index 1bf4019b30f090a429ebb574fdecd9dacad8b5f6..bd29d9171a85b47dfae7c69ec9aa7accefd74ed5 100644 --- a/api-openbis-python3-pybis/src/python/pybis/pybis.py +++ b/api-openbis-python3-pybis/src/python/pybis/pybis.py @@ -4112,7 +4112,7 @@ class Openbis: get_collection_types = get_experiment_types # Alias - def get_experiment_type(self, type, only_data=False): + def get_experiment_type(self, type, only_data=False, **kwargs): return self.get_entity_type( entity="experimentType", cls=ExperimentType, @@ -4133,7 +4133,7 @@ class Openbis: count=count, ) - def get_dataset_type(self, type, only_data=False): + def get_dataset_type(self, type, only_data=False, **kwargs): return self.get_entity_type( entity="dataSetType", identifier=type, diff --git a/api-openbis-python3-pybis/src/python/pybis/sample.py b/api-openbis-python3-pybis/src/python/pybis/sample.py index 717355be8b71991f3b34e304936490374afefa58..edddcdcedb848339d9abc097fd77a18c6083d599 100644 --- a/api-openbis-python3-pybis/src/python/pybis/sample.py +++ b/api-openbis-python3-pybis/src/python/pybis/sample.py @@ -94,15 +94,22 @@ class Sample(OpenBisObject, entity="sample", single_item_method_name="get_sample for key, value in data["properties"].items(): property_type = self.p._property_names[key.lower()] data_type = property_type['dataType'] - if data_type in ("ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"): - value = self.formatter.to_array(data_type, value) - elif "multiValue" in property_type: + if "multiValue" in property_type: if property_type['multiValue'] is True: if type(value) is not list: value = [value] + if data_type in ("ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"): + value = [self.formatter.to_array(data_type, x) for x in value] + else: + value = self.formatter.to_array(data_type, value) else: - if type(value) is list: + if type(value) is list and data_type not in ("ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"): raise ValueError(f'Property type {property_type} is not a multi-value property!') + if data_type in ("ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"): + value = self.formatter.to_array(data_type, value) + else: + if data_type in ("ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"): + value = self.formatter.to_array(data_type, value) self.p.__dict__[key.lower()] = value def __dir__(self):