[Python-modules-commits] [python-axiom] 01/06: Import python-axiom_0.7.5.orig.tar.gz
Tristan Seligmann
mithrandi at moszumanska.debian.org
Thu Feb 4 07:13:38 UTC 2016
This is an automated email from the git hooks/post-receive script.
mithrandi pushed a commit to branch master
in repository python-axiom.
commit 9fba2622ce4ed3c88d401dbd4aa56ab9444f5c63
Author: Tristan Seligmann <mithrandi at debian.org>
Date: Thu Feb 4 09:07:26 2016 +0200
Import python-axiom_0.7.5.orig.tar.gz
---
Axiom.egg-info/PKG-INFO | 2 +-
PKG-INFO | 2 +-
axiom/_version.py | 2 +-
axiom/attributes.py | 32 +++++++++++-
axiom/scripts/axiomatic.py | 32 +++++++++---
axiom/store.py | 7 +++
axiom/test/morenewapp.py | 13 ++++-
axiom/test/test_axiomatic.py | 113 +++++++++++++++++++++++++++++++++++++------
axiom/test/test_query.py | 85 ++++++++++++++++++--------------
axiom/test/test_reference.py | 42 ++++++++++++----
axiom/test/test_upgrading.py | 10 +++-
11 files changed, 264 insertions(+), 76 deletions(-)
diff --git a/Axiom.egg-info/PKG-INFO b/Axiom.egg-info/PKG-INFO
index a9f70b7..4a02ba3 100644
--- a/Axiom.egg-info/PKG-INFO
+++ b/Axiom.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: Axiom
-Version: 0.7.4
+Version: 0.7.5
Summary: An in-process object-relational database
Home-page: https://github.com/twisted/axiom
Author: Divmod, Inc.
diff --git a/PKG-INFO b/PKG-INFO
index a9f70b7..4a02ba3 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: Axiom
-Version: 0.7.4
+Version: 0.7.5
Summary: An in-process object-relational database
Home-page: https://github.com/twisted/axiom
Author: Divmod, Inc.
diff --git a/axiom/_version.py b/axiom/_version.py
index ed9d4d8..ab55bb1 100644
--- a/axiom/_version.py
+++ b/axiom/_version.py
@@ -1 +1 @@
-__version__ = "0.7.4"
+__version__ = "0.7.5"
diff --git a/axiom/attributes.py b/axiom/attributes.py
index b2b6b34..3ebf7d6 100644
--- a/axiom/attributes.py
+++ b/axiom/attributes.py
@@ -10,7 +10,9 @@ hotfix.require('twisted', 'filepath_copyTo')
from zope.interface import implements
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
@@ -915,11 +917,34 @@ class bytes(SQLAttribute):
raise ConstraintError(self, "str or other byte buffer", pyval)
return buffer(pyval)
+
def outfilter(self, dbval, oself):
if dbval is None:
return None
return str(dbval)
+
+ @deprecated(Version("Axiom", 0, 7, 5))
+ def like(self, *others):
+ return super(SQLAttribute, self).like(*others)
+
+
+ @deprecated(Version("Axiom", 0, 7, 5))
+ def notLike(self, *others):
+ return super(SQLAttribute, self).notLike(*others)
+
+
+ @deprecated(Version("Axiom", 0, 7, 5))
+ def startswith(self, other):
+ return super(SQLAttribute, self).startswith(other)
+
+
+ @deprecated(Version("Axiom", 0, 7, 5))
+ def endswith(self, other):
+ return super(SQLAttribute, self).endswith(other)
+
+
+
class InvalidPathError(ValueError):
"""
A path that could not be used with the database was attempted to be used
@@ -1123,7 +1148,12 @@ class reference(integer):
assert self.whenDeleted is reference.NULLIFY, (
"not sure what to do if not...")
return None
- if rv.__legacy__:
+ # If the current cached value is a legacy item, we discard it in order
+ # to force another fetch from the database. However, if *this item* is
+ # also a legacy item, then the item referred to may have been created
+ # in an upgrader and not have been stored yet, so we shouldn't discard
+ # it.
+ if rv.__legacy__ and not oself.__legacy__:
delattr(oself, self.underlying)
return super(reference, self).__get__(oself, cls)
return rv
diff --git a/axiom/scripts/axiomatic.py b/axiom/scripts/axiomatic.py
index 2eb9f1c..826ebe3 100644
--- a/axiom/scripts/axiomatic.py
+++ b/axiom/scripts/axiomatic.py
@@ -104,11 +104,23 @@ class Start(twistd.ServerOptions):
def getArguments(self, store, args):
run = store.dbdir.child("run")
logs = run.child("logs")
- if "--logfile" not in args and "-l" not in args and "--nodaemon" not in args and "-n" not in args:
+ handleLogfile = True
+ handlePidfile = True
+
+ for arg in args:
+ if arg.startswith("--logfile=") or arg in (
+ "-l", "--logfile", "-n", "--nodaemon"
+ ):
+ handleLogfile = False
+ elif arg.startswith("--pidfile=") or arg == "--pidfile":
+ handlePidfile = False
+
+ if handleLogfile:
if not logs.exists():
logs.makedirs()
args.extend(["--logfile", logs.child("axiomatic.log").path])
- if not platform.isWindows() and "--pidfile" not in args:
+
+ if not platform.isWindows() and handlePidfile:
args.extend(["--pidfile", run.child("axiomatic.pid").path])
args.extend(["axiomatic-start", "--dbdir", store.dbdir.path])
return args
@@ -121,11 +133,17 @@ class Start(twistd.ServerOptions):
# If a reactor is being selected, it must be done before the store
# is opened, since that may execute arbitrary application code
# which may in turn install the default reactor.
- if "--reactor" in args:
- reactorIndex = args.index("--reactor")
- shortName = args[reactorIndex + 1]
- del args[reactorIndex:reactorIndex + 2]
- self.opt_reactor(shortName)
+ for index, arg in enumerate(args):
+ if arg in ("--reactor", "-r"):
+ shortName = args[index + 1]
+ del args[index:index + 2]
+ self.opt_reactor(shortName)
+ break
+ elif arg.startswith("--reactor="):
+ shortName = arg.split("=")[1]
+ del args[index]
+ self.opt_reactor(shortName)
+ break
sys.argv[1:] = self.getArguments(self.parent.getStore(), args)
self.run()
diff --git a/axiom/store.py b/axiom/store.py
index f795e9d..76bcc9a 100644
--- a/axiom/store.py
+++ b/axiom/store.py
@@ -2099,6 +2099,13 @@ class Store(Empowered):
if self.tablesCreatedThisTransaction is not None:
self.tablesCreatedThisTransaction.append(tableClass)
+ # If the new type is a legacy type (not the current version), we need
+ # to queue it for upgrade to ensure that if we are in the middle of an
+ # upgrade, legacy items of this version get upgraded.
+ cls = _typeNameToMostRecentClass.get(tableClass.typeName)
+ if cls is not None and tableClass.schemaVersion != cls.schemaVersion:
+ self._upgradeManager.queueTypeUpgrade(tableClass)
+
# We can pass () for extantIndexes here because since the table didn't
# exist for tableClass, none of its indexes could have either.
# Whatever checks _createIndexesFor will make would give the same
diff --git a/axiom/test/morenewapp.py b/axiom/test/morenewapp.py
index 6c4b17d..45cd846 100644
--- a/axiom/test/morenewapp.py
+++ b/axiom/test/morenewapp.py
@@ -4,7 +4,7 @@
from axiom.item import Item
from axiom.attributes import text, integer, reference, inmemory
-from axiom.upgrade import registerUpgrader
+from axiom.upgrade import registerUpgrader, registerAttributeCopyingUpgrader
class ActivateHelper:
activated = 0
@@ -13,7 +13,7 @@ class ActivateHelper:
class Adventurer(ActivateHelper, Item):
typeName = 'test_app_player'
- schemaVersion = 2
+ schemaVersion = 3
name = text()
activated = inmemory()
@@ -65,6 +65,15 @@ registerUpgrader(sword2to3, 'test_app_sword', 2, 3)
from axiom.item import declareLegacyItem
+
+declareLegacyItem(
+ typeName='test_app_player',
+ schemaVersion=2,
+ attributes=dict(
+ name=text(allowNone=True)))
+
+registerAttributeCopyingUpgrader(Adventurer, 2, 3)
+
declareLegacyItem(typeName = 'test_app_sword',
schemaVersion = 2,
diff --git a/axiom/test/test_axiomatic.py b/axiom/test/test_axiomatic.py
index db528bc..075120f 100644
--- a/axiom/test/test_axiomatic.py
+++ b/axiom/test/test_axiomatic.py
@@ -117,6 +117,9 @@ class StartTests(TestCase):
start.getArguments(store, []),
logfileArg + pidfileArg + restArg)
self.assertEqual(
+ start.getArguments(store, ["--logfile=foo"]),
+ ["--logfile=foo"] + pidfileArg + restArg)
+ self.assertEqual(
start.getArguments(store, ["--logfile", "foo"]),
["--logfile", "foo"] + pidfileArg + restArg)
self.assertEqual(
@@ -129,6 +132,9 @@ class StartTests(TestCase):
start.getArguments(store, ["-n"]),
["-n"] + pidfileArg + restArg)
self.assertEqual(
+ start.getArguments(store, ["--pidfile=foo"]),
+ ["--pidfile=foo"] + logfileArg + restArg)
+ self.assertEqual(
start.getArguments(store, ["--pidfile", "foo"]),
["--pidfile", "foo"] + logfileArg + restArg)
@@ -256,21 +262,7 @@ class StartTests(TestCase):
self.assertTrue(store.getItemByID(recorder.storeID).started)
- def test_reactorSelection(self):
- """
- L{AxiomaticStart} optionally takes the name of a reactor and
- installs it instead of the default reactor.
- """
- # Since this process is already hopelessly distant from the state in
- # which I{axiomatic start} operates, it would make no sense to try a
- # functional test of this behavior in this process. Since the
- # behavior being tested involves lots of subtle interactions between
- # lots of different pieces of code (the reactor might get installed
- # at the end of a ten-deep chain of imports going through as many
- # different projects), it also makes no sense to try to make this a
- # unit test. So, start a child process and try to use the alternate
- # reactor functionality there.
-
+ def _getAxiomaticScript(self):
here = FilePath(__file__)
# Try to find it relative to the source of this test.
bin = here.parent().parent().parent().child("bin")
@@ -289,6 +281,25 @@ class StartTests(TestCase):
raise SkipTest(
"Could not find axiomatic script on path or at %s" % (
axiomatic.path,))
+ return axiomatic
+
+
+ def test_reactorSelection(self):
+ """
+ L{AxiomaticStart} optionally takes the name of a reactor in the form
+ --reactor [shortName] and installs it instead of the default reactor.
+ """
+ # Since this process is already hopelessly distant from the state in
+ # which I{axiomatic start} operates, it would make no sense to try a
+ # functional test of this behavior in this process. Since the
+ # behavior being tested involves lots of subtle interactions between
+ # lots of different pieces of code (the reactor might get installed
+ # at the end of a ten-deep chain of imports going through as many
+ # different projects), it also makes no sense to try to make this a
+ # unit test. So, start a child process and try to use the alternate
+ # reactor functionality there.
+
+ axiomatic = self._getAxiomaticScript()
# Create a store for the child process to use and put an item in it.
# This will force an import of the module that defines that item's
@@ -300,7 +311,7 @@ class StartTests(TestCase):
SomeItem(store=store)
store.close()
- # Install select reactor because it available on all platforms, and
+ # Install select reactor because it is available on all platforms, and
# it is still an error to try to install the select reactor even if
# the already installed reactor was the select reactor.
argv = [
@@ -317,6 +328,76 @@ class StartTests(TestCase):
return complete
+ def test_reactorSelectionLongOptionStyle(self):
+ """
+ L{AxiomaticStart} optionally takes the name of a reactor in the form
+ --reactor=[shortName] and installs it instead of the default reactor.
+ """
+
+ axiomatic = self._getAxiomaticScript()
+
+ # Create a store for the child process to use and put an item in it.
+ # This will force an import of the module that defines that item's
+ # class when the child process starts. The module imports the default
+ # reactor at the top-level, making this the worst-case for the reactor
+ # selection code.
+ storePath = self.mktemp()
+ store = Store(storePath)
+ SomeItem(store=store)
+ store.close()
+
+ # Install select reactor because it is available on all platforms, and
+ # it is still an error to try to install the select reactor even if
+ # the already installed reactor was the select reactor.
+ argv = [
+ sys.executable,
+ axiomatic, "-d", storePath,
+ "start", "--reactor=select", "-n"]
+ expected = [
+ "reactor class: twisted.internet.selectreactor.SelectReactor.",
+ "reactor class: <class 'twisted.internet.selectreactor.SelectReactor'>"]
+ proto, complete = AxiomaticStartProcessProtocol.protocolAndDeferred(expected)
+
+ environ = os.environ.copy()
+ reactor.spawnProcess(proto, sys.executable, argv, env=environ)
+ return complete
+
+
+ def test_reactorSelectionShortOptionStyle(self):
+ """
+ L{AxiomaticStart} optionally takes the name of a reactor in the form
+ -r [shortName] and installs it instead of the default reactor.
+ """
+
+ axiomatic = self._getAxiomaticScript()
+
+ # Create a store for the child process to use and put an item in it.
+ # This will force an import of the module that defines that item's
+ # class when the child process starts. The module imports the default
+ # reactor at the top-level, making this the worst-case for the reactor
+ # selection code.
+ storePath = self.mktemp()
+ store = Store(storePath)
+ SomeItem(store=store)
+ store.close()
+
+ # Install select reactor because it is available on all platforms, and
+ # it is still an error to try to install the select reactor even if
+ # the already installed reactor was the select reactor.
+ argv = [
+ sys.executable,
+ axiomatic, "-d", storePath,
+ "start", "-r", "select", "-n"]
+ expected = [
+ "reactor class: twisted.internet.selectreactor.SelectReactor.",
+ "reactor class: <class 'twisted.internet.selectreactor.SelectReactor'>"]
+ proto, complete = AxiomaticStartProcessProtocol.protocolAndDeferred(expected)
+
+ environ = os.environ.copy()
+ reactor.spawnProcess(proto, sys.executable, argv, env=environ)
+ return complete
+
+
class AxiomaticStartProcessProtocol(ProcessProtocol):
"""
diff --git a/axiom/test/test_query.py b/axiom/test/test_query.py
index 139a6ce..8048661 100644
--- a/axiom/test/test_query.py
+++ b/axiom/test/test_query.py
@@ -1218,8 +1218,8 @@ class WildcardQueries(QueryingTestCase):
D.one.notLike('foobar%'),
'(%s NOT LIKE (?))' % (D.one.getColumnName(self.store),),
['foobar%'])
- self.assertEquals(self.query(D, D.one.like('d1.one')), [self.d1])
- self.assertEquals(self.query(D, D.one.notLike('d%.one')), [])
+ self.assertEquals(self.query(D, D.four.like(u'd1.four')), [self.d1])
+ self.assertEquals(self.query(D, D.four.notLike(u'd%.four')), [])
def testOneColumn(self):
self.assertQuery(
@@ -1230,11 +1230,11 @@ class WildcardQueries(QueryingTestCase):
def testOneColumnAndStrings(self):
self.assertQuery(
- D.one.like('%', D.id, '%one'),
- '(%s LIKE (? || %s || ?))' % (D.one.getColumnName(self.store),
+ D.four.like(u'%', D.id, u'%four'),
+ '(%s LIKE (? || %s || ?))' % (D.four.getColumnName(self.store),
D.id.getColumnName(self.store)),
- ['%', '%one'])
- q = self.query(D, D.one.like('%', D.id, '%one'))
+ [u'%', u'%four'])
+ q = self.query(D, D.four.like(u'%', D.id, u'%four'))
e = [self.d1, self.d2, self.d3]
self.assertEquals(sorted(q), sorted(e))
@@ -1251,27 +1251,17 @@ class WildcardQueries(QueryingTestCase):
def testStartsEndsWith(self):
self.assertQuery(
- D.one.startswith('foo'),
- '(%s LIKE (?))' % (D.one.getColumnName(self.store),),
+ D.four.startswith(u'foo'),
+ '(%s LIKE (?))' % (D.four.getColumnName(self.store),),
['foo%'])
self.assertQuery(
- D.one.endswith('foo'),
- '(%s LIKE (?))' % (D.one.getColumnName(self.store),),
+ D.four.endswith(u'foo'),
+ '(%s LIKE (?))' % (D.four.getColumnName(self.store),),
['%foo'])
self.assertEquals(
- self.query(D, D.one.startswith('d1')), [self.d1])
+ self.query(D, D.four.startswith(u'd1')), [self.d1])
self.assertEquals(
- self.query(D, D.one.endswith('3.one')), [self.d3])
-
-
- def testStartsEndsWithColumn(self):
- self.assertQuery(
- D.one.startswith(D.two),
- '(%s LIKE (%s || ?))' % (D.one.getColumnName(self.store),
- D.two.getColumnName(self.store)),
- ['%'])
- self.assertEquals(
- self.query(D, D.one.startswith(D.two)), [])
+ self.query(D, D.four.endswith(u'3.four')), [self.d3])
def testStartsEndsWithText(self):
@@ -1283,20 +1273,6 @@ class WildcardQueries(QueryingTestCase):
[self.d2])
- def testOtherTable(self):
- self.assertQuery(
- D.one.startswith(A.type),
- '(%s LIKE (%s || ?))' % (D.one.getColumnName(self.store),
- A.type.getColumnName(self.store)),
- ['%'])
-
- C(store=self.store, name=u'd1.')
- C(store=self.store, name=u'2.one')
- self.assertEquals(
- self.query(D, D.one.startswith(C.name)), [self.d1])
- self.assertEquals(
- self.query(D, D.one.endswith(C.name)), [self.d2])
-
class UniqueTest(TestCase):
@@ -1796,3 +1772,40 @@ class PlaceholderTestCase(TestCase):
expectedSQL = "placeholder_0.oid, placeholder_0.[attr], placeholder_0.[characters], placeholder_0.[other]"
self.assertEquals(query._queryTarget, expectedSQL)
+
+
+
+class BytesDeprecatedLikeTests(TestCase):
+ """
+ Deprecated tests for LIKE queries on L{axiom.attributes.bytes}.
+ """
+ def test_startsWith(self):
+ self.assertWarns(
+ DeprecationWarning,
+ 'axiom.attributes.startswith was deprecated in Axiom 0.7.5',
+ __file__,
+ lambda: D.one.startswith('string'))
+
+
+ def test_endsWith(self):
+ self.assertWarns(
+ DeprecationWarning,
+ 'axiom.attributes.endswith was deprecated in Axiom 0.7.5',
+ __file__,
+ lambda: D.one.endswith('string'))
+
+
+ def test_like(self):
+ self.assertWarns(
+ DeprecationWarning,
+ 'axiom.attributes.like was deprecated in Axiom 0.7.5',
+ __file__,
+ lambda: D.one.like('string'))
+
+
+ def test_notLike(self):
+ self.assertWarns(
+ DeprecationWarning,
+ 'axiom.attributes.notLike was deprecated in Axiom 0.7.5',
+ __file__,
+ lambda: D.one.notLike('string'))
diff --git a/axiom/test/test_reference.py b/axiom/test/test_reference.py
index 301ba14..89bd6ee 100644
--- a/axiom/test/test_reference.py
+++ b/axiom/test/test_reference.py
@@ -3,7 +3,7 @@ import gc
from twisted.trial.unittest import TestCase
from axiom.store import Store
-from axiom.upgrade import registerUpgrader
+from axiom.upgrade import registerUpgrader, registerAttributeCopyingUpgrader
from axiom.item import Item, declareLegacyItem
from axiom.attributes import integer, reference
from axiom.errors import BrokenReference, DeletionDisallowed
@@ -187,18 +187,35 @@ class BadReferenceTestCase(TestCase):
"""
store = Store()
referent = SimpleReferent(store=store)
- oldReferee = nonUpgradedItem(store=store)
+ oldReferee = nonUpgradedItem2(store=store)
referent.ref = oldReferee
# Manually run the upgrader on this specific legacy item. This is the
# same as if the SimpleReferent item had been created in an upgrader
# for UpgradedItem, except that we can keep a strong reference to
# oldReferee to ensure it is not garbage collected (this would
# otherwise happen nondeterministically on platforms like PyPy).
- newReferee = item1to2(oldReferee)
+ newReferee = item2to3(oldReferee)
self.assertIsInstance(newReferee, UpgradedItem)
self.assertIdentical(referent.ref, newReferee)
+ def test_dummyItemReferenceInUpgrade(self):
+ """
+ Setting the value of a reference attribute to a legacy item during an
+ upgrade results in the same value being set on the upgraded item.
+ """
+ store = Store()
+ def tx():
+ oldReferent = nonUpgradedItem(store=store)
+ oldReferee = nonUpgradedItem(store=store)
+ newReferent = oldReferent.upgradeVersion(
+ UpgradedItem.typeName, 1, 2)
+ newReferee = oldReferee.upgradeVersion(
+ UpgradedItem.typeName, 1, 2, ref=newReferent)
+ self.assertIdentical(newReferee.ref, newReferent)
+ store.transact(tx)
+
+
def test_dummyItemGetItemByID(self):
"""
Instantiating a dummy item and then getting it by its storeID should
@@ -218,21 +235,28 @@ class UpgradedItem(Item):
"""
A simple item which is the current version of L{nonUpgradedItem}.
"""
- schemaVersion = 2
- dummy = integer()
+ schemaVersion = 3
+ ref = reference()
nonUpgradedItem = declareLegacyItem(
UpgradedItem.typeName, 1,
- dict(dummy=integer()))
+ dict(ref=reference()))
+
+
+
+nonUpgradedItem2 = declareLegacyItem(
+ UpgradedItem.typeName, 2,
+ dict(ref=reference()))
+registerAttributeCopyingUpgrader(UpgradedItem, 1, 2)
-def item1to2(old):
+def item2to3(old):
"""
Upgrade an nonUpgradedItem to UpgradedItem
"""
- return old.upgradeVersion(UpgradedItem.typeName, 1, 2, dummy=old.dummy)
+ return old.upgradeVersion(UpgradedItem.typeName, 2, 3, ref=old.ref)
-registerUpgrader(item1to2, UpgradedItem.typeName, 1, 2)
+registerUpgrader(item2to3, UpgradedItem.typeName, 2, 3)
diff --git a/axiom/test/test_upgrading.py b/axiom/test/test_upgrading.py
index 177afa8..2cb19aa 100644
--- a/axiom/test/test_upgrading.py
+++ b/axiom/test/test_upgrading.py
@@ -239,7 +239,14 @@ class SwordUpgradeTest(SchemaUpgradeTest):
Verify that if an exception is raised in an upgrader, the exception
will be logged.
"""
- playerID, swordID = self._testTwoObjectUpgrade()
+ choose(oldapp)
+ s = self.openStore()
+ swordID = oldapp.Sword(
+ store=s,
+ name=u'flaming vorpal doom',
+ hurtfulness=7).storeID
+ self.closeStore()
+
choose(brokenapp)
s = self.openStore()
self.startStoreService()
@@ -253,7 +260,6 @@ class SwordUpgradeTest(SchemaUpgradeTest):
loggedErrors = self.flushLoggedErrors(brokenapp.UpgradersAreBrokenHere)
self.assertEqual(len(loggedErrors), 1)
- originalError = loggedErrors[0]
oldType = item.declareLegacyItem(
oldapp.Sword.typeName,
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-axiom.git
More information about the Python-modules-commits
mailing list