]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- add support for pulling in an external requirements file
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 6 Feb 2013 22:50:11 +0000 (17:50 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 6 Feb 2013 22:50:11 +0000 (17:50 -0500)
- start filling in default versions of remaining requirements that are still only in test/

lib/sqlalchemy/testing/plugin/noseplugin.py
lib/sqlalchemy/testing/requirements.py
test/requirements.py
test/sql/test_query.py

index 81e724bbe8bb470ddc1cef5b9ed815e3b2f64853..4ce76363e3d0779de8360ecace454ae4faacdbe5 100644 (file)
@@ -222,13 +222,23 @@ def _reverse_topological(options, file_config):
                 dependency.set = RandomSet
 
 
+def _requirements_opt(options, opt_str, value, parser):
+    _setup_requirements(value)
+
 @post
 def _requirements(options, file_config):
+
+    requirement_cls = file_config.get('sqla_testing', "requirement_cls")
+    _setup_requirements(requirement_cls)
+
+def _setup_requirements(argument):
     from sqlalchemy.testing import config
     from sqlalchemy import testing
-    requirement_cls = file_config.get('sqla_testing', "requirement_cls")
 
-    modname, clsname = requirement_cls.split(":")
+    if config.requirements is not None:
+        return
+
+    modname, clsname = argument.split(":")
 
     # importlib.import_module() only introduced in 2.7, a little
     # late
@@ -236,7 +246,7 @@ def _requirements(options, file_config):
     for component in modname.split(".")[1:]:
         mod = getattr(mod, component)
     req_cls = getattr(mod, clsname)
-    config.requirements = testing.requires = req_cls(db, config)
+    config.requirements = testing.requires = req_cls(config)
 
 
 @post
@@ -290,6 +300,9 @@ class NoseSQLAlchemy(Plugin):
         opt("--reversetop", action="store_true", dest="reversetop", default=False,
             help="Use a random-ordering set implementation in the ORM (helps "
                   "reveal dependency issues)")
+        opt("--requirements", action="callback", type="string",
+            callback=_requirements_opt,
+            help="requirements class for testing, overrides setup.cfg")
         opt("--with-cdecimal", action="store_true", dest="cdecimal", default=False,
             help="Monkeypatch the cdecimal library into Python 'decimal' for all tests")
         opt("--unhashable", action="store_true", dest="unhashable", default=False,
index e44a333beb48e6fabca2c8fda4d50bd70daa1b20..7228f38f9e132b271eb8a764da5b83378bcc2f5a 100644 (file)
@@ -8,14 +8,16 @@ to provide specific inclusion/exlusions.
 
 """
 
-from . import exclusions
+from . import exclusions, config
 
 
 class Requirements(object):
-    def __init__(self, db, config):
-        self.db = db
+    def __init__(self, config):
         self.config = config
 
+    @property
+    def db(self):
+        return config.db
 
 class SuiteRequirements(Requirements):
 
@@ -61,6 +63,47 @@ class SuiteRequirements(Requirements):
 
         return exclusions.open()
 
+    @property
+    def offset(self):
+        """target database can render OFFSET, or an equivalent, in a SELECT."""
+
+        return exclusions.open()
+
+    @property
+    def boolean_col_expressions(self):
+        """Target database must support boolean expressions as columns"""
+
+        return exclusions.closed()
+
+    @property
+    def nullsordering(self):
+        """Target backends that support nulls ordering."""
+
+        return exclusions.closed()
+
+    @property
+    def standalone_binds(self):
+        """target database/driver supports bound parameters as column expressions
+        without being in the context of a typed column.
+
+        """
+        return exclusions.closed()
+
+    @property
+    def intersect(self):
+        """Target database must support INTERSECT or equivalent."""
+        return exclusions.closed()
+
+    @property
+    def except_(self):
+        """Target database must support EXCEPT or equivalent (i.e. MINUS)."""
+        return exclusions.closed()
+
+    @property
+    def window_functions(self):
+        """Target database must support window functions."""
+        return exclusions.closed()
+
     @property
     def autoincrement_insert(self):
         """target platform generates new surrogate integer primary key values
@@ -300,3 +343,9 @@ class SuiteRequirements(Requirements):
             )
         """
         return exclusions.open()
+
+    @property
+    def mod_operator_as_percent_sign(self):
+        """target database must use a plain percent '%' as the 'modulus'
+        operator."""
+        return exclusions.closed()
index e23a5422502d5ea2c96bea2e705a117fc1a2a503..525786f72a668c791c5fb27d0065bc163fec12be 100644 (file)
@@ -237,6 +237,15 @@ class DefaultRequirements(SuiteRequirements):
 
         return skip_if(exclude('mysql', '<', (4, 1, 1)), 'no subquery support')
 
+    @property
+    def mod_operator_as_percent_sign(self):
+        """target database must use a plain percent '%' as the 'modulus'
+        operator."""
+
+        return only_if(
+                    ['mysql', 'sqlite', 'postgresql+psycopg2', 'mssql']
+                )
+
     @property
     def intersect(self):
         """Target database must support INTERSECT or equivalent."""
index 16b0f79fd975084fb8a1ce720e36845b8501fd11..b5f50aeea71590c30f1673691ae446ed9cab259d 100644 (file)
@@ -443,10 +443,7 @@ class QueryTest(fixtures.TestBase):
         ):
             eq_(expr.execute().fetchall(), result)
 
-    @testing.fails_on("firebird", "see dialect.test_firebird:MiscTest.test_percents_in_text")
-    @testing.fails_on("oracle", "neither % nor %% are accepted")
-    @testing.fails_on("informix", "neither % nor %% are accepted")
-    @testing.fails_on("+pg8000", "can't interpret result column from '%%'")
+    @testing.requires.mod_operator_as_percent_sign
     @testing.emits_warning('.*now automatically escapes.*')
     def test_percents_in_text(self):
         for expr, result in (
@@ -534,6 +531,7 @@ class QueryTest(fixtures.TestBase):
         a_eq(prep(r"(\:that$other)"), "(:that$other)")
         a_eq(prep(r".\:that$ :other."), ".:that$ ?.")
 
+    @testing.requires.standalone_binds
     def test_select_from_bindparam(self):
         """Test result row processing when selecting from a plain bind param."""
 
@@ -911,15 +909,23 @@ class QueryTest(fixtures.TestBase):
         eq_(users.select().execute().fetchall(), [(1, 'john')])
 
     def test_result_as_args(self):
-        users.insert().execute([dict(user_id=1, user_name='john'), dict(user_id=2, user_name='ed')])
+        users.insert().execute([
+                dict(user_id=1, user_name='john'),
+                dict(user_id=2, user_name='ed')])
         r = users.select().execute()
         users2.insert().execute(list(r))
-        assert users2.select().execute().fetchall() == [(1, 'john'), (2, 'ed')]
+        eq_(
+            users2.select().order_by(users2.c.user_id).execute().fetchall(),
+            [(1, 'john'), (2, 'ed')]
+        )
 
         users2.delete().execute()
         r = users.select().execute()
         users2.insert().execute(*list(r))
-        assert users2.select().execute().fetchall() == [(1, 'john'), (2, 'ed')]
+        eq_(
+            users2.select().order_by(users2.c.user_id).execute().fetchall(),
+            [(1, 'john'), (2, 'ed')]
+        )
 
     def test_ambiguous_column(self):
         users.insert().execute(user_id=1, user_name='john')
@@ -1744,7 +1750,6 @@ class LimitTest(fixtures.TestBase):
         self.assert_(r == [(1, 'john'), (2, 'jack'), (3, 'ed')], repr(r))
 
     @testing.requires.offset
-    @testing.fails_on('maxdb', 'FIXME: unknown')
     def test_select_limit_offset(self):
         """Test the interaction between limit and offset"""
 
@@ -2369,7 +2374,7 @@ class OperatorTest(fixtures.TestBase):
         eq_(
             select([flds.c.intcol % 3],
                    order_by=flds.c.idcol).execute().fetchall(),
-            [(2,),(1,)]
+            [(2,), (1,)]
         )
 
     @testing.requires.window_functions