def process_dict(self, dict_): """ deal with multiple fields """ out = {k:v for k, v in dict_.items() if k not in self.skip} for h_unit, h_value in zip(self.h_unit, self.h_value): if h_value not in dict_: # we drop null cells so if one of these was null then we have to skip it here too continue dhv = dict_[h_value] if isinstance(dhv, str): try: dhv = ast.literal_eval(dhv) except ValueError as e: raise exc.UnhandledTypeError(f'{h_value} {dhv!r} was not parsed!') from e compose = dhv * pyru.ur.parse_units(dict_[h_unit]) #_, v, rest = parameter_expression(compose) #out[h_value] = str(UnitsParser(compose).for_text) # FIXME sparc repr #breakpoint() out[h_value] = compose #UnitsParser(compose).asPython() if 'gender' in out and 'species' in out: if out['species'] != OntTerm('NCBITaxon:9606'): out['sex'] = out.pop('gender') return out
def __call__(self, field, value): if type(value) == str: return value try: return getattr(self, field)(value) except AttributeError as e: raise exc.UnhandledTypeError(field) from e
def encode(self, field, value): #if field in ('created', 'updated') and not isinstance(value, datetime): #field.replace(cls.path_field_sep, ',') # FIXME hack around iso8601 # turns it 8601 isnt actually standard >_< with . instead of , sigh empty_iterable = hasattr(value, '__iter__') and not value if value is None or empty_iterable: raise TypeError('cannot encode an empty value') try: return _bytes_encode(field, value) except exc.UnhandledTypeError: log.warning(f'conversion not implemented for field {field}') raise exc.UnhandledTypeError(f'dont know what to do with {value!r}') return if field == 'errors': value = ';'.join(value) if isinstance(value, datetime): # FIXME :/ vs iso8601 value = value.isoformat().replace('.', ',') #value = value.timestamp() # I hate dealing with time :/ if isinstance(value, int): # this is local and will pass through here before move? #out = value.to_bytes(value.bit_length() , sys.byteorder) out = str(value).encode() # better to have human readable elif isinstance(value, float): out = struct.pack('d', value) #= bytes(value.hex()) elif isinstance(value, str): out = value.encode() else: raise exc.UnhandledTypeError( f'dont know what to do with {value!r}') return out
def uri_human(self): # org /datasets/ N:dataset /files/ N:collection # org /datasets/ N:dataset /files/ wat? /N:package # opaque but consistent id?? # org /datasets/ N:dataset /viewer/ N:package id = self.id N, type, suffix = id.split(':') if id.startswith('N:package:'): prefix = '/viewer/' elif id.startswith('N:collection:'): prefix = '/files/' elif id.startswith('N:dataset:'): prefix = '/' # apparently organization needs /datasets after it return self.parent.uri_human + prefix + id elif id.startswith('N:organization:'): return f'https://app.blackfynn.io/{id}/datasets' else: raise exc.UnhandledTypeError(type) if self.dataset_id is None: raise exc.NotInProjectError(f'{self}') return self.dataset.uri_human + prefix + id
def _populate(blob, top=False): if isinstance(blob, list) or isinstance(blob, tuple): # TODO alternatively if the schema is uniform, could use bc here ... def _all(self, l=blob): # FIXME don't autocomplete? keys = set(k for b in l if isinstance(b, dict) for k in b) obj = {k: [] for k in keys} _list = [] _other = [] for b in l: if isinstance(b, dict): for k in keys: if k in b: obj[k].append(b[k]) else: obj[k].append(None) elif any(isinstance(b, t) for t in (list, tuple)): _list.append(JT(b)) else: _other.append(b) for k in keys: obj[k].append(None) # super inefficient if _list: obj['_list'] = JT(_list) if obj: j = JT(obj) else: j = JT(blob) if _other: #obj['_'] = _other # infinite, though lazy setattr(j, '_', _other) setattr(j, '_b', blob) #lb = len(blob) #setattr(j, '__len__', lambda: lb) # FIXME len() return j def it(self, l=blob): for b in l: if any(isinstance(b, t) for t in (dict, list, tuple)): yield JT(b) else: yield b if top: # FIXME iter is non homogenous return [('__iter__', it), ('_all', property(_all))] #elif not [e for e in b if isinstance(self, dict)]: #return property(id) else: # FIXME this can render as {} if there are no keys return property(_all) #obj = {'_all': property(_all), #'_l': property(it),} #j = JT(obj) #return j #nl = JT(obj) #nl._list = blob #return property(it) elif isinstance(blob, dict): if top: out = [('_keys', tuple(blob))] for k, v in blob.items(): # FIXME normalize keys ... nv = _populate(v) out.append((k, nv)) #setattr(cls, k, nv) return out else: return JT(blob) else: if top: raise exc.UnhandledTypeError('asdf') else: @property def prop(self, v=blob): return v return prop