# Path: axiom/slotmachine.py
# class Attribute(object):
#     def __init__(self, doc=''):
#         self.doc = doc
# 
#     def requiredSlots(self, modname, classname, attrname):
#         self.name = attrname
#         yield attrname
# 
#     def __get__(self, oself, type=None):
#         assert oself is None, "{}: should be masked".format(self.name)
#         return self
# 
# Path: axiom/errors.py
# class NoCrossStoreReferences(AttributeError):
#     """
#     References are not allowed between items within different Stores.
#     """
# 
# class BrokenReference(DataIntegrityError):
#     """
#     A reference to a nonexistent item was detected when this should be
#     impossible.
#     """
# 
# Path: axiom/iaxiom.py
# class IComparison(Interface):
#     """
#     An object that represents an in-database comparison.  A predicate that may
#     apply to certain items in a store.  Passed as an argument to
#     attributes.AND, .OR, and Store.query(...)
#     """
#     def getInvolvedTables():
#         """
#         Return a sequence of L{Item} subclasses which are referenced by this
#         comparison.  A class may appear at most once.
#         """
# 
# 
#     def getQuery(store):
#         """
#         Return an SQL string with ?-style bind parameter syntax thingies.
#         """
# 
# 
#     def getArgs(store):
#         """
#         Return a sequence of arguments suitable for use to satisfy the bind
#         parameters in the result of L{getQuery}.
#         """
# 
# class IOrdering(Interface):
#     """
#     An object suitable for passing to the 'sort' argument of a query method.
#     """
#     def orderColumns():
#         """
#         Return a list of two-tuples of IColumn providers and either C{'ASC'} or
#         C{'DESC'} defining this ordering.
#         """
# 
# class IColumn(Interface):
#     """
#     An object that represents a column in the database.
#     """
#     def getShortColumnName(store):
#         """
#         @rtype: C{str}
#         @return: Just the name of this column.
#         """
# 
# 
#     def getColumnName(store):
#         """
#         @rtype: C{str}
# 
#         @return: The fully qualified name of this object as a column within the
#         database, eg, C{"main_database.some_table.[this_column]"}.
#         """
# 
#     def fullyQualifiedName():
#         """
#         @rtype: C{str}
# 
#         @return: The fully qualfied name of this object as an attribute in
#         Python code, eg, C{myproject.mymodule.MyClass.myAttribute}.  If this
#         attribute is represented by an actual Python code object, it will be a
#         dot-separated sequence of Python identifiers; otherwise, it will
#         contain invalid identifier characters other than '.'.
#         """
# 
#     def __get__(row):
#         """
#         @param row: an item that has this column.
#         @type row: L{axiom.item.Item}
# 
#         @return: The value of the column described by this object, for the given
#         row.
# 
#         @rtype: depends on the underlying type of the column.
#         """
# 
# class IQuery(Interface):
#     """
#     An object that represents a query that can be performed against a database.
#     """
# 
#     limit = Attribute(
#         """
#         An integer representing the maximum number of rows to be returned from
#         this query, or None, if the query is unlimited.
#         """)
# 
#     store = Attribute(
#         """
#         The Axiom store that this query will return results from.
#         """)
# 
#     def __iter__():
#         """
#         Retrieve an iterator for the results of this query.
# 
#         The query is performed whenever this is called.
#         """
# 
# 
#     def count():
#         """
#         Return the number of results in this query.
# 
#         NOTE: In most cases, this will have to load all of the rows in this
#         query.  It is therefore very slow and should generally be considered
#         discouraged.  Call with caution!
#         """
# 
# 
#     def cloneQuery(limit):
#         """
#         Create a similar-but-not-identical copy of this query with certain
#         attributes changed.
# 
#         (Currently this only supports the manipulation of the "limit"
#         parameter, but it is the intent that with a richer query-introspection
#         interface, this signature could be expanded to support many different
#         attributes.)
# 
#         @param limit: an integer, representing the maximum number of rows that
#         this query should return.
# 
#         @return: an L{IQuery} provider with the new limit.
#         """


import os
import six
from six.moves import map
from decimal import Decimal
from epsilon import hotfix
from zope.interface import implementer
from twisted.python import filepath
from twisted.python.deprecate import deprecated
from twisted.python.components import registerAdapter
from twisted.python.versions import Version
from epsilon.extime import Time
from axiom.slotmachine import Attribute as inmemory
from axiom.errors import NoCrossStoreReferences, BrokenReference
from axiom.iaxiom import IComparison, IOrdering, IColumn, IQuery
                from twisted.python.reflect import namedAny
        if oself is None:
            return pyval.storeID
        if oself.store is None:
            return pyval.storeID
        if oself.store != pyval.store:
            raise NoCrossStoreReferences(
                "You can't establish references to items in other stores.")

        return integer.infilter(self, pyval.storeID, oself, store)

    def outfilter(self, dbval, oself):
        if dbval is None:
            return None

        referee = oself.store.getItemByID(dbval, default=None, autoUpgrade=not oself.__legacy__)
        if referee is None and self.whenDeleted is not reference.NULLIFY:

            # If referee merely changed to another valid referent,
            # SQLAttribute.__get__ will notice that what we returned is
            # inconsistent and try again.  However, it doesn't know about the
            # BrokenReference that is raised if the old referee is no longer a
            # valid referent.  Check to see if the dbunderlying is still the
            # same as the dbval passed in.  If it's different, we should try to
            # load the value again.  Only if it is unchanged will we raise the
            # BrokenReference.  It would be better if all of this
            # change-detection logic were in one place, but I can't figure out
            # how to do that. -exarkun
            if dbval != getattr(oself, self.dbunderlying):
                return self.__get__(oself, None)


# Path: axiom/slotmachine.py
# class Attribute(object):
#     def __init__(self, doc=''):
#         self.doc = doc
# 
#     def requiredSlots(self, modname, classname, attrname):
#         self.name = attrname
#         yield attrname
# 
#     def __get__(self, oself, type=None):
#         assert oself is None, "{}: should be masked".format(self.name)
#         return self
# 
# Path: axiom/errors.py
# class NoCrossStoreReferences(AttributeError):
#     """
#     References are not allowed between items within different Stores.
#     """
# 
# class BrokenReference(DataIntegrityError):
#     """
#     A reference to a nonexistent item was detected when this should be
#     impossible.
#     """
# 
# Path: axiom/iaxiom.py
# class IComparison(Interface):
#     """
#     An object that represents an in-database comparison.  A predicate that may
#     apply to certain items in a store.  Passed as an argument to
#     attributes.AND, .OR, and Store.query(...)
#     """
#     def getInvolvedTables():
#         """
#         Return a sequence of L{Item} subclasses which are referenced by this
#         comparison.  A class may appear at most once.
#         """
# 
# 
#     def getQuery(store):
#         """
#         Return an SQL string with ?-style bind parameter syntax thingies.
#         """
# 
# 
#     def getArgs(store):
#         """
#         Return a sequence of arguments suitable for use to satisfy the bind
#         parameters in the result of L{getQuery}.
#         """
# 
# class IOrdering(Interface):
#     """
#     An object suitable for passing to the 'sort' argument of a query method.
#     """
#     def orderColumns():
#         """
#         Return a list of two-tuples of IColumn providers and either C{'ASC'} or
#         C{'DESC'} defining this ordering.
#         """
# 
# class IColumn(Interface):
#     """
#     An object that represents a column in the database.
#     """
#     def getShortColumnName(store):
#         """
#         @rtype: C{str}
#         @return: Just the name of this column.
#         """
# 
# 
#     def getColumnName(store):
#         """
#         @rtype: C{str}
# 
#         @return: The fully qualified name of this object as a column within the
#         database, eg, C{"main_database.some_table.[this_column]"}.
#         """
# 
#     def fullyQualifiedName():
#         """
#         @rtype: C{str}
# 
#         @return: The fully qualfied name of this object as an attribute in
#         Python code, eg, C{myproject.mymodule.MyClass.myAttribute}.  If this
#         attribute is represented by an actual Python code object, it will be a
#         dot-separated sequence of Python identifiers; otherwise, it will
#         contain invalid identifier characters other than '.'.
#         """
# 
#     def __get__(row):
#         """
#         @param row: an item that has this column.
#         @type row: L{axiom.item.Item}
# 
#         @return: The value of the column described by this object, for the given
#         row.
# 
#         @rtype: depends on the underlying type of the column.
#         """
# 
# class IQuery(Interface):
#     """
#     An object that represents a query that can be performed against a database.
#     """
# 
#     limit = Attribute(
#         """
#         An integer representing the maximum number of rows to be returned from
#         this query, or None, if the query is unlimited.
#         """)
# 
#     store = Attribute(
#         """
#         The Axiom store that this query will return results from.
#         """)
# 
#     def __iter__():
#         """
#         Retrieve an iterator for the results of this query.
# 
#         The query is performed whenever this is called.
#         """
# 
# 
#     def count():
#         """
#         Return the number of results in this query.
# 
#         NOTE: In most cases, this will have to load all of the rows in this
#         query.  It is therefore very slow and should generally be considered
#         discouraged.  Call with caution!
#         """
# 
# 
#     def cloneQuery(limit):
#         """
#         Create a similar-but-not-identical copy of this query with certain
#         attributes changed.
# 
#         (Currently this only supports the manipulation of the "limit"
#         parameter, but it is the intent that with a richer query-introspection
#         interface, this signature could be expanded to support many different
#         attributes.)
# 
#         @param limit: an integer, representing the maximum number of rows that
#         this query should return.
# 
#         @return: an L{IQuery} provider with the new limit.
#         """


# Path: axiom/attributes.py
import os
import six
from six.moves import map
from decimal import Decimal
from epsilon import hotfix
from zope.interface import implementer
from twisted.python import filepath
from twisted.python.deprecate import deprecated
from twisted.python.components import registerAdapter
from twisted.python.versions import Version
from epsilon.extime import Time
from axiom.slotmachine import Attribute as inmemory
from axiom.errors import NoCrossStoreReferences, BrokenReference
from axiom.iaxiom import IComparison, IOrdering, IColumn, IQuery
                from twisted.python.reflect import namedAny

        if oself is None:
            return pyval.storeID
        if oself.store is None:
            return pyval.storeID
        if oself.store != pyval.store:
            raise NoCrossStoreReferences(
                "You can't establish references to items in other stores.")

        return integer.infilter(self, pyval.storeID, oself, store)

    def outfilter(self, dbval, oself):
        if dbval is None:
            return None

        referee = oself.store.getItemByID(dbval, default=None, autoUpgrade=not oself.__legacy__)
        if referee is None and self.whenDeleted is not reference.NULLIFY:

            # If referee merely changed to another valid referent,
            # SQLAttribute.__get__ will notice that what we returned is
            # inconsistent and try again.  However, it doesn't know about the
            # BrokenReference that is raised if the old referee is no longer a
            # valid referent.  Check to see if the dbunderlying is still the
            # same as the dbval passed in.  If it's different, we should try to
            # load the value again.  Only if it is unchanged will we raise the
            # BrokenReference.  It would be better if all of this
            # change-detection logic were in one place, but I can't figure out
            # how to do that. -exarkun
            if dbval != getattr(oself, self.dbunderlying):
                return self.__get__(oself, None)


            raise BrokenReference('Reference to storeID %r is broken' % (dbval,))