Example #1
0
def get_obj_state(obj):
    if object_session(obj) is None and not has_identity(obj):
        return 'transient'
    elif object_session(obj) is not None and not has_identity(obj):
        return 'pending'
    elif object_session(obj) is None and has_identity(obj):
        return 'detached'
    elif object_session(obj) is not None and has_identity(obj):
        return 'persistent'
Example #2
0
 def delete_existing(self, obj, name):
     if has_identity(obj):
         sess = session(obj)
         items = getattr(obj, name, set([]))
         while items:
             item = items.pop()
             # only delete persistent objects
             if has_identity(item):
                 sess.delete(item)
 def get_object_state(self):
     if object_session(self) is None and not has_identity(self):
         return 'transient'
     elif object_session(self) is not None and not has_identity(self):
         return 'pending'
     elif object_session(self) is None and has_identity(self):
         return 'detached'
     elif object_session(self) is not None and has_identity(self):
         return 'persistent'
     raise Exception
Example #4
0
    def test_sql_session(self, rw_dir):
        """Test basic SQL handling"""
        session = PackageSession.new(url=self.temporary_sqlite_url(rw_dir))
        assert len(list(session.query(SQLPackage))) == 0
        now = datetime.now()

        # Setup a package
        pkg = SQLPackage(host='foo', root_path='path/foo', package_path='package_dir', managed_at=now, stable_since=now)

        assert len(pkg.transactions) == 0
        session.add(pkg)
        session.commit()
        assert has_identity(pkg)

        assert session.to_sql_package(pkg) is pkg

        # Create a new package, for the fun of it
        dpkg = DummyPackage('hello/world', 'package')
        self.failUnlessRaises(ValueError, session.to_sql_package, dpkg)
        other_pkg = session.to_sql_package(dpkg, stable_since=10.0)
        assert other_pkg != pkg
        assert object_session(other_pkg) is session and not has_identity(other_pkg)


        # unmanage the package and verify it's not returned
        pkg.unmanage()
        self.failUnlessRaises(ValueError, session.to_sql_package, pkg)
        assert session.to_sql_package(pkg, managed_only=False) is pkg

        # Setup a simple transaction
        trans = SQLPackageTransaction(host='foo', type_name='testing', in_package=pkg, 
                                            in_package_stable_since = pkg.stable_since, spooled_at=now)
        assert len(pkg.transactions) == 1
        assert trans.in_package is pkg
        assert trans.out_package is None
        assert len(trans.files) == 0
        session.add(trans)
        session.commit()

        # Add a transaction file
        file = SQLTransactionFile(transaction = trans, path='foo/bar', size=14, uid=2, gid=1, mode=0)
        assert len(trans.files) == 1 and trans.files[0] is file
        assert file.transaction is trans

        session.add(file)
        session.commit()

        # it will work indirectly as well
        trans.files.append(SQLTransactionFile(path='foo/bar2', size=14, uid=2, gid=1, mode=0))
        session.commit()
Example #5
0
def print_state(obj):
    from sqlalchemy.orm import object_session 
    from sqlalchemy.orm.util import has_identity 
    obj = obj
    if object_session(obj) is None and not has_identity(obj):
        print "transient:" 
    if object_session(obj) is not None and not has_identity(obj):
        print "pending: "
    if object_session(obj) is None and has_identity(obj):
        print "# detached: "
    if object_session(obj) is not None and has_identity(obj):
        print "# persistent: "


    print type(obj)
Example #6
0
def printstatus(obj):
    """
        print an object's status regarding the sqla's session
    """
    from sqlalchemy.orm import object_session
    from sqlalchemy.orm.util import has_identity
    if object_session(obj) is None and not has_identity(obj):
        print "Sqlalchemy status : transient"
    elif object_session(obj) is not None and not has_identity(obj):
        print "Sqlalchemy status : pending"
    elif object_session(obj) is None and has_identity(obj):
        print "Sqlalchemy status : detached"
    elif object_session(obj) is not None and has_identity(obj):
        print "Sqlalchemy status : persistent"
    else:
        print "Unknown Status"
Example #7
0
    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
                 initial=None, instance=None, nested=False, **kwargs):
        opts = self._meta
        exclude = list(opts.exclude)
        if opts.model is None:
            raise ValueError('ModelForm has no model class specified.')
        self.nested = nested
        if self.nested:
            exclude.extend(opts.exclude_on_nested)
        if instance is None:
            exclude.extend(opts.exclude_on_create)
            self.instance = opts.model()
            object_data = {}
        else:
            self.instance = instance
            object_data = model_to_dict(instance, opts.fields, exclude)
            if has_identity(instance):
                exclude.extend(opts.exclude_on_update)
            else:
                exclude.extend(opts.exclude_on_create)

        if initial is not None:
            object_data.update(initial)
        object_data.update(data)
        super(BaseSQLAModelForm, self).__init__(object_data, files, auto_id, prefix)

        for k in exclude:
            if k in self.fields:
                del self.fields[k]
Example #8
0
    def populate_obj(self, obj, name):
        if has_identity(obj):
            sess = session(obj)
            item = getattr(obj, name, None)
            if item:
                # only delete persistent objects
                if has_identity(item):
                    sess.delete(item)
                elif item in sess:
                    sess.expunge(item)
                setattr(obj, name, None)

        if self.data:
            setattr(obj, name, self.form.Meta.model())

        FormField.populate_obj(self, obj, name)
Example #9
0
 def validate_login(self, _, value):
     assert not has_identity(
         self
     ), "user already in the database - cannot change login anymore!"
     if not User.login_regex.match(value) or value in self.blocked_logins:
         raise Exception("invalid unix-login!")
     return value
Example #10
0
 def refresh(self):
     """Refresh object and reconnect it with session."""
     #: Detached
     if object_session(self) is None and has_identity(self):
         DatabaseManager.db().add(self)
     DatabaseManager.db().refresh(self)
     return self
Example #11
0
    def save(self, session=None, commit=True):
        """
        Save the changes to the model. If the model has not been persisted
        then it adds the model to the declared session. Then it flushes the
        object session and optionally commits it.

        @param[in] session
            A specific session to use instead of the thread-local, scoped
            session.
        """
        if has_identity(self):
            # Object has already been persisted to the database; grab its
            # session.
            session = object_session(self)

        else:
            # Ensure we have a database session.
            if session is None:
                session = __import__('alchemist.db').db.session

            # Object has not been persisted to the database.
            session.add(self)

        if commit:
            # Commit the session as requested.
            session.commit()

        else:
            # Just flush the session; do not commit.
            session.flush()
Example #12
0
    def update_from_SE(self, force=False, cache=timedelta(86400)):
        if (
            has_identity(self) and self.user_id and not force
            and (datetime.utcnow() - self.updated) < cache
        ):
            return self

        user = requests.get(
            'http://api.stackexchange.com/2.2/users/{}'.format(self.user_id),
            {'site': 'stackoverflow'}
        ).json()['items'][0]

        self.display_name = user['display_name']
        self.reputation = user['reputation']
        self.profile_image = user['profile_image']
        self.user_type = user['user_type']

        gold_badges = requests.get(
            'http://api.stackexchange.com/2.2/users/{}/badges'.format(self.user_id),
            {'site': 'stackoverflow', 'max': 'gold', 'sort': 'rank'}
        ).json()

        self.gold_tag_badges = ' '.join(
            badge['name'] for badge in gold_badges['items']
            if badge['badge_type'] == 'tag_based'
        )

        self.updated = datetime.utcnow()
Example #13
0
def printstatus(obj):
    """
        print an object's status regarding the sqla's session
    """
    from sqlalchemy.orm import object_session
    from sqlalchemy.orm.util import has_identity
    if object_session(obj) is None and not has_identity(obj):
        print "Sqlalchemy status : transient"
    elif object_session(obj) is not None and not has_identity(obj):
        print "Sqlalchemy status : pending"
    elif object_session(obj) is None and has_identity(obj):
        print "Sqlalchemy status : detached"
    elif object_session(obj) is not None and has_identity(obj):
        print "Sqlalchemy status : persistent"
    else:
        print "Unknown Status"
Example #14
0
    def save(self, session=None, commit=True):
        """
        Save the changes to the model. If the model has not been persisted
        then it adds the model to the declared session. Then it flushes the
        object session and optionally commits it.

        @param[in] session
            A specific session to use instead of the thread-local, scoped
            session.
        """
        if has_identity(self):
            # Object has already been persisted to the database; grab its
            # session.
            session = object_session(self)

        else:
            # Ensure we have a database session.
            if session is None:
                session = __import__('alchemist.db').db.session

            # Object has not been persisted to the database.
            session.add(self)

        if commit:
            # Commit the session as requested.
            session.commit()

        else:
            # Just flush the session; do not commit.
            session.flush()
Example #15
0
    def serialize(self, fields=None, include=None, exclude=None):
        obj = {}

        if fields is None:
            fields = set(self.__class__.serializable)

            if include is not None:
                fields |= set(include)

            if exclude is not None:
                fields ^= set(exclude)

        for prop in fields:
            serializer_name = "serialize_" + prop
            if hasattr(self, serializer_name):
                obj[prop] = getattr(self, serializer_name)()

            else:
                is_transient = object_session(self) is None and not has_identity(self)
                if is_transient:
                    # transiet instances are not tied to a session,
                    # so we can't call getattr() because that can cause an attribute refresh,
                    # which is a hard SQLAlchemy error
                    v = self.__dict__.get(prop)
                else:
                    v = getattr(self, prop)
                serializers = self.__serializable_args__["serializers"]
                opts = self.__serializable_args__["opts"]
                obj[prop] = serialize(v, serializers, opts)

        return obj
Example #16
0
 def __session(self):
     sess = object_session(self.instance)
     if sess is not None and self.autoflush and sess.autoflush and self.instance in sess:
         sess.flush()
     if not has_identity(self.instance):
         return None
     else:
         return sess
Example #17
0
 def cache_key(self):
     """
   Instance property which returns the cache key for a single object
   """
     self.validate_cache_mode('detail')
     if not has_identity(self):
         raise Exception('This instance has no identity')
     return self.build_cache_key('detail', **self.cache_data)
Example #18
0
 def clear(self, obj):
     """Delete this object from the session"""
     from sqlalchemy.orm.util import has_identity
     if obj not in self.session:
         # detached object; merge it with the one stored in session
         obj = self.session.merge(obj)
     if has_identity(obj):
         self.session.delete(obj)
Example #19
0
 def cache_key(self):
   """
   Instance property which returns the cache key for a single object
   """
   self.validate_cache_mode('detail')
   if not has_identity(self):
     raise Exception('This instance has no identity')
   return self.build_cache_key('detail', **self.cache_data)
Example #20
0
 def clear(self, obj):
     """Delete this object from the session"""
     from sqlalchemy.orm.util import has_identity
     if obj not in self.session:
         # detached object; merge it with the one stored in session
         obj = self.session.merge(obj)
     if has_identity(obj):
         self.session.delete(obj)
Example #21
0
 def __session(self):
     sess = object_session(self.instance)
     if sess is not None and self.autoflush and sess.autoflush and self.instance in sess:
         sess.flush()
     if not has_identity(self.instance):
         return None
     else:
         return sess
Example #22
0
 def cache_detail_key(self, data=None):
     if not hasattr(self._meta, 'cache_detail_keys'):
         raise Exception('Class meta has no cache_detail_keys')
     if not has_identity(self):
         raise Exception('Cannot generate detail cache key for instance ' \
             'with no identity')
     data = data or instance_dict(self)
     raw_key, attrs = self._meta.cache_detail_keys[0]
     return self.format_key(raw_key % data)
Example #23
0
 def cache_list_version_key(self, data=None):
     if not self._meta.cache_list_keys:
         raise Exception('Class._meta has no cache_list_keys')
     if not has_identity(self):
         raise Exception('Cannot generate list cache key for instance ' \
             'with no identity')
     data = data or instance_dict(self)
     raw_key, attrs = self._meta.cache_list_keys[0]
     return raw_key % data
Example #24
0
 def make_asset_key(self, key, asset_type=None):
     """
   Generates an asset key, which will be invalidated when the
   parent object is invalidated
   """
     self.validate_cache_mode('asset')
     if not has_identity(self):
         raise Exception('This instance has no identity')
     return self.build_cache_key('asset', key, asset_type,
                                 **self.cache_data)
Example #25
0
 def make_asset_key(self, key, asset_type=None):
   """
   Generates an asset key, which will be invalidated when the
   parent object is invalidated
   """
   self.validate_cache_mode('asset')
   if not has_identity(self):
     raise Exception('This instance has no identity')
   return self.build_cache_key('asset', key, asset_type,
                               **self.cache_data)      
Example #26
0
 def _get_file_info(self, file_obj):
     try:
         file_obj = self.parser.parse(file_obj, Session)
     except Exception:
         if util.has_identity(file_obj):
             Session.delete(file_obj)
         else:
             Session.expunge(file_obj)
         log_traceback(level="info")
         return None
     return file_obj
Example #27
0
    def fetch(self, locale):
        session = sa.orm.object_session(self.obj)
        # If the object has no identity and its not in session or if the object
        # has _translations relationship loaded get the locale object from the
        # relationship.
        if '_translations' not in sa.inspect(
                self.obj).unloaded or (not session
                                       or not has_identity(self.obj)):
            return self.obj._translations.get(locale)

        return session.query(self.obj.__translatable__['class']).get(
            sa.inspect(self.obj).identity + (locale, ))
Example #28
0
    def set_password(self, value):
        is_new = has_identity(self)

        # Set password as a hash
        self._password = utils.generate_hash(value, hash='sha1')
        # (Re)generate API token and key after password is updated
        if is_new or not self.token:
            salt = (self.email or '') + self.salt + value
            self.token = utils.generate_random_hash(salt=salt, hash='sha256')
        if is_new or not self.key:
            salt = value + self.salt
            self.key = utils.generate_random_hash(salt=salt, hash='sha256')
Example #29
0
    def fetch(self, locale):
        session = sa.orm.object_session(self.obj)
        # If the object has no identity and its not in session or if the object
        # has _translations relationship loaded get the locale object from the
        # relationship.
        if '_translations' not in sa.inspect(self.obj).unloaded or (
            not session or not has_identity(self.obj)
        ):
            return self.obj._translations.get(locale)

        return session.query(self.obj.__translatable__['class']).get(
            sa.inspect(self.obj).identity + (locale, )
        )
Example #30
0
    def is_transient(self):
        """True if the allocation does not exist in the database, and is not
        about to be written to the database. If an allocation is transient it
        means that the given instance only exists in memory.

        See:
        http://www.sqlalchemy.org/docs/orm/session.html
        #quickie-intro-to-object-states
        http://stackoverflow.com/questions/3885601/
        sqlalchemy-get-object-instance-state

        """

        return object_session(self) is None and not has_identity(self)
    def is_transient(self):
        """True if the allocation does not exist in the database, and is not
        about to be written to the database. If an allocation is transient it
        means that the given instance only exists in memory.

        See:
        http://www.sqlalchemy.org/docs/orm/session.html
        #quickie-intro-to-object-states
        http://stackoverflow.com/questions/3885601/
        sqlalchemy-get-object-instance-state

        """

        return object_session(self) is None and not has_identity(self)
Example #32
0
    def save(self, commit=False):
        """
        Saves this ``form``'s cleaned_data into model instance
        ``self.instance``.

        If commit=True, then the changes to ``instance`` will be saved to the
        database. Returns ``instance``.
        """
        if not has_identity(self.instance):
            fail_message = 'created'
        else:
            fail_message = 'changed'
        return save_instance(self, self.instance, self._meta.fields,
                             fail_message, commit, self._meta.exclude)
Example #33
0
 def __init__(self, *args, **kwargs):
     instance = kwargs.pop('instance', None)
     nested = kwargs.pop('nested', False)
     super(BaseSQLAModelForm, self).__init__(*args, **kwargs)
     self.instance = instance
     if instance and has_identity(instance):
         excludes = self._meta.exclude_on_update[:]
     else:
         excludes = self._meta.exclude_on_create[:]
     if nested:
         excludes.extend(self._meta.exclude_on_nested)
     for k in excludes:
         if k in self.fields:
             del self.fields[k]
Example #34
0
 def __init__(self, *args, **kwargs):
     instance = kwargs.pop("instance", None)
     nested = kwargs.pop("nested", False)
     super(BaseSQLAModelForm, self).__init__(*args, **kwargs)
     self.instance = instance
     if instance and has_identity(instance):
         excludes = self._meta.exclude_on_update[:]
     else:
         excludes = self._meta.exclude_on_create[:]
     if nested:
         excludes.extend(self._meta.exclude_on_nested)
     for k in excludes:
         if k in self.fields:
             del self.fields[k]
Example #35
0
def pyfa_abandon(obj):
    """
    Remove object from database session.
    """
    db_session = PyfaDataManager.session
    # If object isn't in session (transient or detached state),
    # do not do anything at all
    if db_session is None:
        return
    # Delete if persistent state
    if has_identity(obj):
        db_session.delete(obj)
    # Expunge if pending state
    else:
        db_session.expunge(obj)
Example #36
0
 def get_changes(self, ignore=[]):
   """
   Returns a dict of pending changes to the current instance
   key: attribute name
   value: tuple in the form (old_value, new_value)
   """
   insp = inspect(self)
   fields = self.get_checked_fields(ignore)
   changes = {}
   for field in fields:
     attr = getattr(insp.attrs, field)
     ins, eq, rm = attr.history
     if ins or rm:
       old_value = rm[0] if rm and has_identity(self) else None
       new_value = ins[0] if ins else None
       changes[field] = (old_value, new_value)
   return changes
Example #37
0
 def get_changes(self, ignore=[]):
     """
   Returns a dict of pending changes to the current instance
   key: attribute name
   value: tuple in the form (old_value, new_value)
   """
     insp = inspect(self)
     fields = self.get_checked_fields(ignore)
     changes = {}
     for field in fields:
         attr = getattr(insp.attrs, field)
         ins, eq, rm = attr.history
         if ins or rm:
             old_value = rm[0] if rm and has_identity(self) else None
             new_value = ins[0] if ins else None
             changes[field] = (old_value, new_value)
     return changes
Example #38
0
    def save(self, commit=False):
        """Save the changes to the model.

        If the model has not been persisted
        then it adds the model to the declared session. Then it flushes the
        object session and optionally commits it.
        """
        if not has_identity(self):
            # Object has not been persisted to the database.
            session.add(self)

        if commit:
            # Commit the session as requested.
            session.commit()

        else:
            # Just flush the session; do not commit.
            session.flush()
Example #39
0
    def save(self, commit=False):
        """Save the changes to the model.

        If the model has not been persisted
        then it adds the model to the declared session. Then it flushes the
        object session and optionally commits it.
        """
        if not has_identity(self):
            # Object has not been persisted to the database.
            session.add(self)

        if commit:
            # Commit the session as requested.
            session.commit()

        else:
            # Just flush the session; do not commit.
            session.flush()
Example #40
0
    def has_db_conflicts(self, instance, slug):
        """
    Checks in the database for items with conflicting slugs
    """
        session = object_session(instance)
        keys = self.comparison_keys['col_keys'][:]
        for rel_key, fk_keys in self.comparison_keys['rel_keys']:
            keys.extend(fk_keys)
        filters = {key: getattr(instance, key) for key in keys}
        filters[self.slug_key] = slug

        query = session.query(self.cls).filter_by(**filters)
        if has_identity(instance):
            # for existing objects, exclude the object from the search
            ident = instance.pk_as_query_filters(force=True)
            query = query.filter(not_(ident))
        with session.no_autoflush:
            conflicts = query.count()
        return conflicts > 0
Example #41
0
  def has_db_conflicts(self, instance, slug):
    """
    Checks in the database for items with conflicting slugs
    """
    session = object_session(instance)
    keys = self.comparison_keys['col_keys'][:]
    for rel_key, fk_keys in self.comparison_keys['rel_keys']:
      keys.extend(fk_keys)
    filters = {key: getattr(instance, key) for key in keys}
    filters[self.slug_key] = slug

    query = session.query(self.cls).filter_by(**filters)
    if has_identity(instance):
      # for existing objects, exclude the object from the search
      ident = instance.pk_as_query_filters(force=True)
      query = query.filter(not_(ident))
    with session.no_autoflush:
      conflicts = query.count()
    return conflicts > 0
    def is_active(self, value):
        """is_active property setter.

        If set to True - removes deactivated_at, deleted_at, activate_key and set activated_at to datetime now
        If set to False - set deactivated_at to now and activated_at to None
        """

        # Allow to modify this only if object is in the persistent state to prevent "default values" errors/bugs.
        # http://stackoverflow.com/questions/3885601/sqlalchemy-get-object-instance-state
        if object_session(self) is not None and has_identity(self):
            if value:
                self.deactivated_at = None
                self.deleted_at = None
                self.activate_key = None
                self.activated_at = datetime.now()
            else:
                self.deactivated_at = datetime.now()
                self.activated_at = None
        else:
            raise AttributeError("User has to be in the persistent state - stored in the DB")
Example #43
0
File: user.py Project: JuKu/pycroft
 def validate_login(self, _, value):
     assert not has_identity(
         self
     ), "user already in the database - cannot change login anymore!"
     if not self.login_regex.match(value):
         raise IllegalLoginError(
             "Illegal login '{}': Logins must begin with a lower case "
             "letter and may be followed by lower case letters, digits or "
             "punctuation (dash, underscore and dot). Punctuation "
             "characters must be separated by at least on letter or digit.".
             format(value))
     if value in self.blocked_logins:
         raise IllegalLoginError(
             "Illegal login '{}': This login is blocked and may not be used."
             .format(value))
     if len(value) > self.login_character_limit:
         raise IllegalLoginError(
             "Illegal login '{}': Logins are limited to at most {} "
             "characters.".format(value, self.login_character_limit))
     return value
Example #44
0
 def validate_login(self, _, value):
     assert not has_identity(self), "user already in the database - cannot change login anymore!"
     if not self.login_regex.match(value):
         raise IllegalLoginError(
             "Illegal login '{}': Logins must begin with a lower case "
             "letter and may be followed by lower case letters, digits or "
             "punctuation (dash, underscore and dot). Punctuation "
             "characters must be separated by at least on letter or digit."
             .format(value)
         )
     if value in self.blocked_logins:
         raise IllegalLoginError(
             "Illegal login '{}': This login is blocked and may not be used."
             .format(value)
         )
     if len(value) > self.login_character_limit:
         raise IllegalLoginError(
             "Illegal login '{}': Logins are limited to at most {} "
             "characters.".format(value, self.login_character_limit)
         )
     return value
Example #45
0
    def is_active(self, value):
        """
        Set user as active/inactive.

        :param bood value:
            True - removes deactivated_at, deleted_at, activate_key and set activated_at to datetime now
            False - set deactivated_at to now and activated_at to None

        """
        # Allow to modify this only if object is in the persistent state to prevent "default values" errors/bugs.
        # http://stackoverflow.com/questions/3885601/sqlalchemy-get-object-instance-state
        if object_session(self) is not None and has_identity(self):
            if value:
                self.deactivated_at = None
                self.deleted_at = None
                self.activate_key = None
                self.activated_at = datetime.now()
            else:
                self.deactivated_at = datetime.now()
                self.activated_at = None
        else:
            raise AttributeError('User has to be in the persistent state - stored in the DB')
Example #46
0
    def get_cache_keys(self, child_updated=False):
        #print 'getting keys from', self
        cache_keys = set()
        version_keys = set()

        if not any(getattr(self._meta, k) for k in [
            'cache_detail_keys',
            'cache_list_keys',
            'cache_pointers',
            'cache_cascades',
            'cache_relations',
            ]):
            return cache_keys, version_keys
            
        session = Session.object_session(self)
        deleted = self.is_deleted or self in session.deleted
        data = instance_dict(self)
        cache = get_cache('objects')

        # get a list of all fields which changed
        changed_keys = []
        for attr in self.__mapper__.iterate_properties:
            if not isinstance(attr, ColumnProperty) and \
               attr.key not in self._meta.cache_relations:
                continue
            if attr.key in IGNORABLE_KEYS:
                continue
            ins, eq, rm = get_history(self, attr.key)
            if ins or rm:
                changed_keys.append(attr.key)
        self_updated = bool(changed_keys) or deleted

        if not self_updated and not child_updated:
            return (cache_keys, version_keys)

        if has_identity(self):
            # we only kill primary cache keys if the object exists
            # this key won't exist during CREATE
            for raw_key, attrs in self._meta.cache_detail_keys:
                if attrs and not any(key in changed_keys for key in attrs):
                    # the fields which trigger this key were not changed
                    continue
                cache_key = self.format_key(raw_key % data)
                cache_keys.add(cache_key)

        # collections will be altered by any action, so we always
        # kill these keys
        for raw_key, attrs in self._meta.cache_list_keys:
            if attrs and not any(key in changed_keys for key in attrs):
                # the fields which trigger this key were not changed
                continue
            cache_key = raw_key % data
            version_keys.add(cache_key)

        # pointer records contain only the id of the parent resource
        # if changed, we set the old key to False, and set the new key
        for raw_key, attrs, name in self._meta.cache_pointers:
            if attrs and not any(key in changed_keys for key in attrs):
                # the fields which trigger this key were not changed
                continue
            cache_key = raw_key % data
            c, idkey = identity_key(instance=self)
            if len(idkey) > 1:
                idkey = ','.join(str(i) for i in idkey)
            else:
                idkey = idkey[0]
            if not self.is_deleted:
                cache.set(cache_key, idkey)

            # if this is an existing object, we need to handle the old key
            if not has_identity(self):
                continue

            old_data = {}
            for attr in attrs:
                ins,eq,rm = get_history(self, attr)
                old_data[attr] = rm[0] if rm else eq[0]
            old_key = raw_key % old_data
            if old_key == cache_key and not self.is_deleted:
                continue
            old_idkey = cache.get(old_key)
            if old_idkey == idkey:
                # this object is the current owner of the key
                #print 'setting %s to False' % old_key, old_idkey, idkey
                cache.set(old_key, False)

        # cascade the cache kill operation to related objects, so parents
        # know if children have changed, in order to rebuild the cache
        for cascade in self._meta.cache_cascades:
            objs = getattr(self, cascade)
            if not objs:
                continue
            if not isinstance(objs, list):
                objs = [objs]
            for obj in objs:
                k1,k2 = obj.get_cache_keys(child_updated=True)
                cache_keys.update(k1)
                version_keys.update(k2)

        return (cache_keys, version_keys)
Example #47
0
 def delete(self):
     if has_identity(self):
         session = object_session(self)
         session.delete(self)
         session.commit()
Example #48
0
    def get_cache_keys(self,
                       child_updated=False,
                       force_expire_pointers=False,
                       force=False):
        cache_alias = self._meta.cache_alias
        cache = self.get_cache()
        cache_keys = set()
        version_keys = set()

        if not self.is_cacheable:
            return (cache_keys, version_keys)

        orm = ORM.get()
        session = object_session(self) or orm.sessionmaker()

        deleted = self.is_deleted or self in session.deleted
        changes = self.get_changes(ignore=IGNORABLE_KEYS)
        self_updated = bool(changes) or deleted

        if not self_updated and not child_updated and not force:
            return (cache_keys, version_keys)

        changed_attrs = set(changes.keys())
        data = self.cache_data

        old_data = {}
        if has_identity(self):
            for attr in self.cache_fields():
                ins, eq, rm = get_history(self, attr)
                old_data[attr] = rm[0] if rm else eq[0]

        if 'detail' in self._meta.cache_modes:
            # we only kill primary cache keys if the object exists
            # this key won't exist during CREATE
            if has_identity(self):
                cache_key = self.cache_key
                cache_keys.add((cache_alias, cache_key))

        if 'list' in self._meta.cache_modes:
            # collections will be altered by any action, so we always
            # kill these keys
            version_key = self.cache_list_version_key
            version_keys.add((cache_alias, version_key))
            if self._meta.cache_partitions:
                # add the partition keys as well
                for pversion_key in self.cache_partition_version_keys:
                    version_keys.add((cache_alias, pversion_key))
                if changed_attrs.intersection(self._meta.cache_partitions):
                    # if partition field values were changed, we need to
                    # increment the version keys for the previous values
                    for pversion_key in self.get_cache_partition_version_keys(
                            **old_data):
                        version_keys.add((cache_alias, pversion_key))

        if 'asset' in self._meta.cache_modes:
            # models with sub-assets need to increment the version key
            # of the parent detail
            if has_identity(self):
                key = self.cache_detail_version_key
                if deleted:
                    # delete the detail version key
                    cache_keys.add((cache_alias, key))
                else:
                    # for updates, increment the version key
                    version_keys.add((cache_alias, key))

        # pointer records contain only the id of the parent resource
        # if changed, we set the old key to False, and set the new key
        for raw_key, attrs, name in self._meta.cache_pointers:
            if not changed_attrs.intersection(
                    attrs) and not force_expire_pointers:
                # the fields which trigger this pointer were not changed
                continue
            cache_key = raw_key % data
            _, ident = identity_key(instance=self)
            if len(ident) > 1:
                ident = ','.join(map(str, ident))
            else:
                ident = ident[0]
            if not self.is_deleted:
                cache.set(cache_key, ident)
            if force_expire_pointers:
                cache_keys.add((cache_alias, cache_key))

            # if this is a new object, we're done
            if not has_identity(self):
                continue

            # if this is an existing object, we need to handle the old key
            old_data = {}
            for attr in attrs:
                ins, eq, rm = get_history(self, attr)
                old_data[attr] = rm[0] if rm else eq[0]

            old_key = raw_key % old_data
            if old_key == cache_key and not self.is_deleted:
                # the pointer key is unchanged, nothing to do here
                continue

            old_ident = cache.get(old_key)
            if old_ident and str(old_ident) == str(ident):
                # this object is the current owner of the key. we need to remove
                # the reference to this instance
                cache.set(old_key, False)

        # cascade the cache kill operation to related objects, so parents
        # know if children have changed, in order to rebuild the cache
        for cascade in self._meta.cache_cascades:
            objs = getattr(self, cascade)
            if not objs:
                # no related objects
                continue
            if not isinstance(objs, list):
                # *-to-one relation, force into a list
                objs = [objs]
            for obj in objs:
                child_keys = obj.get_cache_keys(child_updated=True)
                cache_keys.update(child_keys[0])
                version_keys.update(child_keys[1])

        return (cache_keys, version_keys)
Example #49
0
 def is_new(self):
     """Return True if the instance wasn't fetched from the database."""
     return not has_identity(self)
Example #50
0
 def is_persisted(self):
     '''
     Check if this instance has ever been persisted. Means it is either
     `detached` or `persistent`.
     '''
     return has_identity(self)
Example #51
0
    def validate_login(self, _, value):
        assert not has_identity(
            self), "user already in the database - cannot change login anymore!"

        return super().validate_login(_, value)
Example #52
0
 def is_persisted(self):
     '''
     Check if this instance has ever been persisted. Means it is either
     `detached` or `persistent`.
     '''
     return has_identity(self)
Example #53
0
File: base.py Project: devhub/baph
 def delete(self):
     if has_identity(self):
         session = object_session(self)
         session.delete(self)
         session.commit()
Example #54
0
 def object_exists(self):
     return has_identity(self.object)