def func(value): if value is None: return None t = type(value) if t is not unicode: if t is buffer: value = hexlify(value).decode('ascii') else: value = unicode(value) result = base_func(value) return result
def tostring(x): if isinstance(x, basestring): return x if hasattr(x, '__unicode__'): try: return unicode(x) except: pass if hasattr(x, 'makeelement'): return cElementTree.tostring(x) try: return str(x) except: pass try: return repr(x) except: pass if type(x) == types.InstanceType: return '<%s instance at 0x%X>' % (x.__class__.__name__) return '<%s object at 0x%X>' % (x.__class__.__name__)
def tostring(x): if isinstance(x, basestring): return x if hasattr(x, '__unicode__'): try: return unicode(x) except: pass if hasattr(x, 'makeelement'): return cElementTree.tostring(x) try: return str(x) except: pass try: return repr(x) except: pass if type(x) == types.InstanceType: return '<%s instance at 0x%X>' % (x.__class__.__name__) return '<%s object at 0x%X>' % (x.__class__.__name__)
def force_text(s, encoding='utf-8', strings_only=False, errors='strict'): """ Similar to smart_text, except that lazy instances are resolved to strings, rather than kept as lazy objects. If strings_only is True, don't convert (some) non-string-like objects. """ # Handle the common case first for performance reasons. if issubclass(type(s), unicode): return s if strings_only and is_protected_type(s): return s try: if not issubclass(type(s), basestring): if not PY2: if isinstance(s, bytes): s = unicode(s, encoding, errors) else: s = unicode(s) elif hasattr(s, '__unicode__'): s = unicode(s) else: s = unicode(bytes(s), encoding, errors) else: # Note: We use .decode() here, instead of unicode(s, encoding, # errors), so that if s is a SafeBytes, it ends up being a # SafeText at the end. s = s.decode(encoding, errors) except UnicodeDecodeError as e: if isinstance(s, Exception): # If we get to here, the caller has passed in an Exception # subclass populated with non-ASCII bytestring data without a # working unicode method. Try to handle this without raising a # further exception by individually forcing the exception args # to unicode. s = ' '.join( force_text(arg, encoding, strings_only, errors) for arg in s) else: raise return s
def _get_ops(self): result = [] entities = get_entities(self.db) entities_prev = get_entities(self.db_prev) eadded = {} emodified = {} for ename, entity in self.db.entities.items(): if ename not in self.db_prev.entities: eadded[ename] = sorted((a.name, a) for a in entity._new_attrs_) eremoved = {} for ename, prev_entity in self.db_prev.entities.items(): if ename not in self.db.entities: eremoved[ename] = sorted( (a.name, a) for a in prev_entity._new_attrs_) entity_renames = {} @contextmanager def apply_renames(renames): for from_, to_ in renames.items(): entity = entities[to_] entity.__name__ = from_ yield for from_, to_ in renames.items(): entity = entities[to_] entity.__name__ = to_ for rem_ename, rem_attrs in sorted(eremoved.items()): for add_ename, add_attrs in sorted(eadded.items()): with apply_renames({rem_ename: add_ename}): for (add_aname, add_attr), (rem_aname, rem_attr) in zip(add_attrs, rem_attrs): if add_aname != rem_aname: break if add_attr.get_declaration_id( ) != rem_attr.get_declaration_id(): break else: if self.questioner.ask_rename_model( rem_ename, add_ename): result.append( ops.RenameEntity(rem_ename, add_ename)) entity_renames[rem_ename] = add_ename del eadded[add_ename] del eremoved[rem_ename] with apply_renames(entity_renames): for entity in sorted(self.db.entities.values(), key=attrgetter('_id_')): ename = entity.__name__ if ename == 'Migration' or ename not in entities_prev: continue prev_entity = entities_prev[ename] aadded, aremoved, amodified = self._get_entity_changes( ename, entity, prev_entity) for add_name, add_attr in sorted(aadded.items()): for rem_name, rem_attr in sorted(aremoved.items()): try: add_attr.name = rem_attr.name if add_attr.get_declaration_id() == rem_attr.get_declaration_id() \ and self.questioner.ask_rename(ename, rem_name, add_name): result.append( ops.RenameAttr(ename, rem_name, add_name)) del aremoved[rem_name] del aadded[add_name] finally: add_attr.name = add_name emodified[ename] = aadded, aremoved, amodified def get_id(pair): return tuple( tuple(a and a.get_declaration_id() for a in attrs or (None, None)) for attrs in pair) def sort_pair(pair): result = [] for attrs in pair: if attrs: attr, rattr = attrs if getattr(attr, 'name', '') < getattr(rattr, 'name', ''): attrs = rattr, attr result.append(attrs) return result pairs = {} for ename, (aadded, aremoved, amodified) in sorted(emodified.items()): # Get entity operations for aname, attr in sorted(aadded.items()): if not attr.reverse: if issubclass(attr.py_type, str) and isinstance( attr, orm.Optional): kwargs = attr._constructor_args[1] value_class = self.db.provider.sqlbuilder_cls.value_class value = value_class(self.db.provider.paramstyle, '') kwargs.update(sql_default=unicode(value)) elif not attr.nullable and attr.initial is None and attr.default is None and not attr.is_pk: initial = self.questioner.ask_not_null_addition( aname, ename) attr.initial = attr._constructor_args[1][ 'initial'] = initial result.append(ops.AddAttr(ename, aname, attr)) for aname, attr in sorted(aremoved.items()): if not attr.reverse: result.append(ops.RemoveAttr(ename, aname)) for aname, attr in sorted(amodified.items()): if not attr.reverse: attr_prev = self.db_prev.entities[ename]._adict_[aname] result.append( ops.AddAttr(ename, aname, attr) if attr_prev. reverse else ops.ModifyAttr(ename, aname, attr)) new_entity = entities.get(ename) or entities.get( entity_renames.get(ename)) assert new_entity is not None adict = {a.name: a for a in new_entity._new_attrs_} prev_entity = entities_prev[ename] prev_adict = {a.name: a for a in prev_entity._new_attrs_} for aname in chain(aadded, amodified): attr = adict[aname] prev_attr = prev_adict.get(aname) if prev_attr and not prev_attr.reverse: prev_attr = None if attr and not attr.reverse: attr = None if not attr and not prev_attr: continue if prev_attr: pair = (attr and attr.reverse, attr), (prev_attr, prev_attr.reverse) elif attr.reverse.name in prev_adict: attr = attr.reverse prev_attr = getattr(prev_entity, attr.name) pair = (attr, attr.reverse), (prev_attr, prev_attr.reverse) else: pair = (attr, attr.reverse), None pair = sort_pair(pair) pairs[get_id(pair)] = pair for aname in aremoved: prev_attr = prev_adict[aname] if not prev_attr.reverse: prev_attr = None attr = adict.get(aname) if attr and not attr.reverse: attr = None if not attr and not prev_attr: continue if attr: pair = (attr, attr.reverse), (prev_attr, prev_attr and prev_attr.reverse) else: pair = None, (prev_attr, prev_attr.reverse) pair = sort_pair(pair) pairs[get_id(pair)] = pair def name(attr): return attr and attr.name def ename(attr): return attr.entity.__name__ for pair, pair_prev in pairs.values(): attr = attr_prev = None if pair_prev: attr_prev, rattr_prev = pair_prev if pair: attr, rattr = pair if getattr(attr, 'reverse', None) and getattr( attr_prev, 'reverse', None): result.append( ops.ModifyRelation(ename(attr), name(attr), attr, name(rattr), rattr)) elif getattr(attr, 'reverse', None): result.append( ops.AddRelation(ename(attr), name(attr), attr, name(rattr), rattr)) elif getattr(attr_prev, 'reverse', None): result.append( ops.RemoveRelation(ename(attr_prev), attr_prev.name)) for ename, attrs in sorted(eadded.items(), key=lambda x: entities[x[0]]._id_): bases = [c.__name__ for c in entities[ename].__bases__] regular = [(k, v) for k, v in attrs if not v.reverse] # Patch by andgein. Add _table_, _discriminator_ and _table_options_ fields to entity attributes. special_fields = ["_table_", "_discriminator_", "_table_options_"] # Some special fields can't been redefined in child entity. special_fields_blocked_in_child = ["_table_", "_table_options_"] entity = self.db.entities[ename] for field in special_fields: is_child = len(entity._all_bases_) > 0 if is_child and field in special_fields_blocked_in_child: continue field_value = getattr(entity, field, None) if field_value is not None: regular.append((field, field_value)) own_indexes = [ index for index in entity._indexes_ if index.entity == entity ] composite_indexes = [ index for index in own_indexes if len(index.attrs) > 1 and not index.is_pk ] # Auto_created indices will be created by Pono automatically be entity attribute definition # (orm.PrimaryKey() or orm.Required(..., unique=True) will be used). auto_created_indexes = [ index for index in own_indexes if (index.is_unique or index.is_pk) and len(index.attrs) == 1 ] regular.append(("_indexes_", list( set(own_indexes) - set(composite_indexes) - set(auto_created_indexes)))) # End of patch by andgein result.append(ops.AddEntity(ename, bases, regular)) for aname, attr in attrs: if not attr.reverse: continue prev_entity = entities_prev.get(attr.reverse.entity.__name__) prev_attr = None if prev_entity: prev_attr = prev_entity._adict_.get(attr.reverse.name) if prev_attr is None: # attribute was added from other entity continue if prev_attr.entity is not prev_entity: assert False, 'Not implemented' if prev_attr and not prev_attr.reverse: prev_attr = None if prev_attr: pair = (attr, attr.reverse), (prev_attr, prev_attr.reverse) else: pair = (attr, attr.reverse), None pair = sort_pair(pair) iden = get_id(pair) if iden not in pairs: pairs[iden] = pair result.append( ops.AddRelation(ename, name(attr), attr, name(attr.reverse), attr.reverse)) # Patch by andgein. Composite indices should be added after relations for index in composite_indexes: result.append( ops.AddIndex(ename, [attr.name for attr in index.attrs], index.name, index.is_unique)) # End of patch for ename, attrs in sorted(eremoved.items()): result.append(ops.RemoveEntity(ename)) for aname, prev_attr in attrs: if not prev_attr.reverse: continue entity = entities.get(prev_attr.reverse.entity.__name__) attr = None if entity: attr = entity._adict_.get(prev_attr.reverse.name) if attr.entity is not entity: assert False, 'Not implemented' if attr and not attr.reverse: attr = None if attr: pair = (attr, attr.reverse), (prev_attr, prev_attr.reverse) else: pair = None, (prev_attr, prev_attr.reverse) pair = sort_pair(pair) iden = get_id(pair) if iden not in pairs: pairs[iden] = pair result.append(ops.RemoveRelation(ename, aname)) # sorting def keyfunc(op): if isinstance(op, ops.RenameAttr): return 0 if isinstance(op, ops.RenameEntity): return 1 if isinstance(op, ops.RemoveRelation): return 2 if 'Remove' in op.__class__.__name__: return 3 if isinstance(op, ops.AddEntity): return 4 return 5 return sorted(result, key=keyfunc)