Commits

Mike Bayer committed e4a02f4

- add the new profiling system to 0.7

Comments (0)

Files changed (10)

test/aaa_profiling/test_compiler.py

 
         cls.dialect = default.DefaultDialect()
 
-    @profiling.function_call_count(versions={'2.7':62, '2.6':62,
-                                            '3':68})
+    @profiling.function_call_count(62)
     def test_insert(self):
         t1.insert().compile(dialect=self.dialect)
 
-    @profiling.function_call_count(versions={'2.6':56, '2.7':56})
+    @profiling.function_call_count(56)
     def test_update(self):
         t1.update().compile(dialect=self.dialect)
 
-    @profiling.function_call_count(versions={'2.6':117, '2.7':117, '3':124})
+    @profiling.function_call_count(110)
     def test_update_whereclause(self):
         t1.update().where(t1.c.c2==12).compile(dialect=self.dialect)
 
-    @profiling.function_call_count(versions={'2.7':148, '2.6':148,
-                                                '3':161})
+    @profiling.function_call_count(139)
     def test_select(self):
         s = select([t1], t1.c.c2==t2.c.c1)
         s.compile(dialect=self.dialect)

test/aaa_profiling/test_orm.py

 
 class MergeTest(fixtures.MappedTest):
 
-    __requires__ = 'cpython',
-
     @classmethod
     def define_tables(cls, metadata):
-        parent = Table('parent', metadata, Column('id', Integer,
+        Table('parent', metadata, Column('id', Integer,
                        primary_key=True,
                        test_needs_autoincrement=True), Column('data',
                        String(20)))
-        child = Table('child', metadata, Column('id', Integer,
+        Table('child', metadata, Column('id', Integer,
                       primary_key=True, test_needs_autoincrement=True),
                       Column('data', String(20)), Column('parent_id',
                       Integer, ForeignKey('parent.id'), nullable=False))
                                 cls.tables.parent,
                                 cls.tables.child)
 
-        mapper(Parent, parent, properties={'children'
-               : relationship(Child, backref='parent')})
+        mapper(Parent, parent, properties={'children':
+                        relationship(Child, backref='parent')})
         mapper(Child, child)
 
     @classmethod
         parent, child = cls.tables.parent, cls.tables.child
 
         parent.insert().execute({'id': 1, 'data': 'p1'})
-        child.insert().execute({'id': 1, 'data': 'p1c1', 'parent_id'
-                               : 1})
+        child.insert().execute({'id': 1, 'data': 'p1c1', 'parent_id': 1})
 
     def test_merge_no_load(self):
         Parent = self.classes.Parent
         # down from 185 on this this is a small slice of a usually
         # bigger operation so using a small variance
 
-        @profiling.function_call_count(variance=0.05,
-                versions={'2.7':80, '2.6':80, '2.5':94, '3': 83})
+        @profiling.function_call_count()
         def go():
             return sess2.merge(p1, load=False)
         p2 = go()
 
         # third call, merge object already present. almost no calls.
 
-        @profiling.function_call_count(variance=0.05,
-                versions={'2.7':11, '2.6':11, '2.5':15, '3': 12})
+        @profiling.function_call_count()
         def go():
             return sess2.merge(p2, load=False)
         p3 = go()
 
-    @testing.only_on('sqlite', 'Call counts tailored to pysqlite')
     def test_merge_load(self):
         Parent = self.classes.Parent
 
         # using sqlite3 the C extension took it back up to approx. 1257
         # (py2.6)
 
-        @profiling.function_call_count(variance=0.10,
-                                versions={'2.5':1050, '2.6':1050,
-                                        '2.6+cextension':1005,
-                                        '2.7':1005,
-                                        '3':1050}
-                            )
+        @profiling.function_call_count()
         def go():
             p2 = sess2.merge(p1)
         go()
 
     """
 
-    # only need to test for unexpected variance in a large call
-    # count here,
-    # so remove some platforms that have wildly divergent
-    # callcounts.
-    __requires__ = 'python25', 'cpython'
-    __unsupported_on__ = 'postgresql+pg8000', 'mysql+pymysql'
 
     @classmethod
     def define_tables(cls, metadata):
-        parent = Table('parent', metadata,
+        Table('parent', metadata,
                         Column('id', Integer, primary_key=True),
                        Column('data', String(20)),
                        Column('child_id', Integer, ForeignKey('child.id'))
                        )
 
-        child = Table('child', metadata,
-                    Column('id', Integer,primary_key=True),
+        Table('child', metadata,
+                    Column('id', Integer, primary_key=True),
                   Column('data', String(20))
                  )
 
         parents = sess.query(Parent).all()
 
 
-        @profiling.function_call_count(108019, variance=.2)
+        @profiling.function_call_count()
         def go():
             for p in parents:
                 p.child
         parents = sess.query(Parent).all()
         children = sess.query(Child).all()
 
-        @profiling.function_call_count(17987, {'3':18987})
+        @profiling.function_call_count()
         def go():
             for p in parents:
                 p.child
         go()
 
 class MergeBackrefsTest(fixtures.MappedTest):
-    __only_on__ = 'sqlite'  # keep things simple
 
     @classmethod
     def define_tables(cls, metadata):
     def setup_mappers(cls):
         A, B, C, D = cls.classes.A, cls.classes.B, \
                     cls.classes.C, cls.classes.D
-        a, b, c, d= cls.tables.a, cls.tables.b, \
+        a, b, c, d = cls.tables.a, cls.tables.b, \
                     cls.tables.c, cls.tables.d
         mapper(A, a, properties={
-            'bs':relationship(B, backref='a'),
-            'c':relationship(C, backref='as'),
-            'ds':relationship(D, backref='a'),
+            'bs': relationship(B, backref='a'),
+            'c': relationship(C, backref='as'),
+            'ds': relationship(D, backref='a'),
         })
         mapper(B, b)
         mapper(C, c)
         s = Session()
         s.add_all([
             A(id=i,
-                bs=[B(id=(i * 50) + j) for j in xrange(1, 50)],
+                bs=[B(id=(i * 5) + j) for j in xrange(1, 5)],
                 c=C(id=i),
-                ds=[D(id=(i * 50) + j) for j in xrange(1, 50)]
+                ds=[D(id=(i * 5) + j) for j in xrange(1, 5)]
             )
-            for i in xrange(1, 50)
+            for i in xrange(1, 5)
         ])
         s.commit()
 
-    @profiling.function_call_count(1092497, variance=.10)
+    @profiling.function_call_count()
     def test_merge_pending_with_all_pks(self):
         A, B, C, D = self.classes.A, self.classes.B, \
                     self.classes.C, self.classes.D
         s = Session()
         for a in [
             A(id=i,
-                bs=[B(id=(i * 50) + j) for j in xrange(1, 50)],
+                bs=[B(id=(i * 5) + j) for j in xrange(1, 5)],
                 c=C(id=i),
-                ds=[D(id=(i * 50) + j) for j in xrange(1, 50)]
+                ds=[D(id=(i * 5) + j) for j in xrange(1, 5)]
             )
-            for i in xrange(1, 50)
+            for i in xrange(1, 5)
         ]:
             s.merge(a)
 

test/aaa_profiling/test_pool.py

     # probably
     # due to the event mechanics being established
     # or not already...
-    @profiling.function_call_count(72, {'2.4': 68, '2.7': 75,
-                                            '2.7+cextension': 75,
-                                            '3': 62},
-                                            variance=.15)
+    @profiling.function_call_count()
     def test_first_connect(self):
         conn = pool.connect()
 
         conn = pool.connect()
         conn.close()
 
-        @profiling.function_call_count(32, {'2.4': 21, '2.7':29,
-                                            '3.2':25,
-                                            '2.7+cextension':29},
-                                            variance=.10)
+        @profiling.function_call_count()
         def go():
             conn2 = pool.connect()
             return conn2
     def test_second_samethread_connect(self):
         conn = pool.connect()
 
-        @profiling.function_call_count(6, {'2.4': 4, '3':7})
+        @profiling.function_call_count()
         def go():
             return pool.connect()
         c2 = go()

test/aaa_profiling/test_resultset.py

 
 
 class ResultSetTest(fixtures.TestBase, AssertsExecutionResults):
-    __requires__ = 'cpython',
-    __only_on__ = 'sqlite'
 
     @classmethod
     def setup_class(cls):
         global t, t2, metadata
         metadata = MetaData(testing.db)
-        t = Table('table', metadata, *[Column('field%d' % fnum, String)
+        t = Table('table', metadata, *[Column('field%d' % fnum, String(50))
                   for fnum in range(NUM_FIELDS)])
         t2 = Table('table2', metadata, *[Column('field%d' % fnum,
-                   Unicode) for fnum in range(NUM_FIELDS)])
+                   Unicode(50)) for fnum in range(NUM_FIELDS)])
 
     def setup(self):
         metadata.create_all()
     def teardown(self):
         metadata.drop_all()
 
-    @profiling.function_call_count(versions={
-                                    '2.4': 13214,
-                                    '2.6':14416,
-                                    '2.7':14416,
-                                   '2.6+cextension': 365,
-                                   '2.7+cextension':365})
+    @profiling.function_call_count()
     def test_string(self):
         [tuple(row) for row in t.select().execute().fetchall()]
 
     # sqlite3 returns native unicode.  so shouldn't be an increase here.
 
-    @profiling.function_call_count(versions={
-                                    '2.7':14396,
-                                    '2.6':14396,
-                                   '2.6+cextension': 365,
-                                   '2.7+cextension':365})
+    @profiling.function_call_count()
     def test_unicode(self):
         [tuple(row) for row in t2.select().execute().fetchall()]
 
     def test_contains_doesnt_compile(self):
         row = t.select().execute().first()
         c1 = Column('some column', Integer) + Column("some other column", Integer)
-        @profiling.function_call_count(9, variance=.15)
+        @profiling.function_call_count()
         def go():
             c1 in row
         go()
 
 class ExecutionTest(fixtures.TestBase):
-    __requires__ = 'cpython',
-    __only_on__ = 'sqlite'
 
     def test_minimal_connection_execute(self):
         # create an engine without any instrumentation.
         # ensure initial connect activities complete
         c.execute("select 1")
 
-        @profiling.function_call_count(versions={'2.7':40, '2.6':40, '2.5':35,
-                                                    '2.4':21, '3':40},
-                                            variance=.10)
+        @profiling.function_call_count()
         def go():
             c.execute("select 1")
         go()
         # ensure initial connect activities complete
         e.execute("select 1")
 
-        @profiling.function_call_count(versions={'2.4':41, '2.5':65,
-                                                    '2.6':65, '3':61,
-                                                    '2.7':65,
-                                                    '2.6+cextension':65},
-                                            variance=.05)
+        @profiling.function_call_count()
         def go():
             e.execute("select 1")
         go()
 
 
 class RowProxyTest(fixtures.TestBase):
+    __requires__ = 'cpython',
+
     def _rowproxy_fixture(self, keys, processors, row):
         from sqlalchemy.engine.base import RowProxy
         class MockMeta(object):
             return value
         value1, value2 = "x", "y"
         row = self._rowproxy_fixture(
-            [(col1, "a"),(col2, "b")],
+            [(col1, "a"), (col2, "b")],
             [proc1, None],
             seq_factory([value1, value2])
         )

test/aaa_profiling/test_zoomark.py

         metadata = MetaData(engine)
         engine.connect()
 
-    @profiling.function_call_count(3896, {'2.4': 1711})
     def test_profile_1_create_tables(self):
         self.test_baseline_1_create_tables()
 
-    @profiling.function_call_count(5045, {'2.6':5099, '2.4': 3650, '3.2':4699})
+    @profiling.function_call_count()
     def test_profile_1a_populate(self):
         self.test_baseline_1a_populate()
 
-    @profiling.function_call_count(245, {'2.4': 172})
+    @profiling.function_call_count()
     def test_profile_2_insert(self):
         self.test_baseline_2_insert()
 
-    @profiling.function_call_count(3333, {'2.4': 2358})
+    @profiling.function_call_count()
     def test_profile_3_properties(self):
         self.test_baseline_3_properties()
 
-    @profiling.function_call_count(11624, {'2.4': 7963, '2.6+cextension'
-                                   : 10736, '2.7+cextension': 10736},
-                                   variance=0.10)
+    @profiling.function_call_count()
     def test_profile_4_expressions(self):
         self.test_baseline_4_expressions()
 
-    @profiling.function_call_count(1059, {'2.4': 904, '2.6+cextension'
-                                   : 1027, '2.6.4':1167, '2.7+cextension': 1027},
-                                   variance=0.10)
+    @profiling.function_call_count()
     def test_profile_5_aggregates(self):
         self.test_baseline_5_aggregates()
 
-    @profiling.function_call_count(1788, {'2.4': 1118, '3.2':1647,
-                                        '2.7+cextension':1698})
+    @profiling.function_call_count()
     def test_profile_6_editing(self):
         self.test_baseline_6_editing()
 
-    @profiling.function_call_count(2252, {'2.4': 1673,
-                                            '2.6':2412,
-                                            '2.7':2412,
-                                            '3.2':2396,
-                                            '2.7+cextension':2110,
-                                            '2.6+cextension': 2252})
+    @profiling.function_call_count()
     def test_profile_7_multiview(self):
         self.test_baseline_7_multiview()
 

test/aaa_profiling/test_zoomark_orm.py

         session = sessionmaker(engine)()
         engine.connect()
 
-    @profiling.function_call_count(5600, {"3.2":5928})
+    @profiling.function_call_count()
     def test_profile_1_create_tables(self):
         self.test_baseline_1_create_tables()
 
-    @profiling.function_call_count(5786, {'2.7+cextension':5683,
-                                            '2.6+cextension':5992})
+    @profiling.function_call_count()
     def test_profile_1a_populate(self):
         self.test_baseline_1a_populate()
 
-    @profiling.function_call_count(413, {'3.2':398})
+    @profiling.function_call_count()
     def test_profile_2_insert(self):
         self.test_baseline_2_insert()
 
     # this number...
 
-    @profiling.function_call_count(6783, {
-        '2.6': 6058,
-        '2.7': 5922,
-        '2.7+cextension': 5714,
-        '2.6+cextension': 5714,
-        '3.2':5787,
-        })
+    @profiling.function_call_count()
     def test_profile_3_properties(self):
         self.test_baseline_3_properties()
 
     # and this number go down slightly when using the C extensions
 
-    @profiling.function_call_count(17698, {'2.7+cextension':17698, '2.6': 18943, '2.7':19110, '3.2':19264})
+    @profiling.function_call_count()
     def test_profile_4_expressions(self):
         self.test_baseline_4_expressions()
 
-    @profiling.function_call_count(1172, {'2.6+cextension': 1090,
-                                   '2.7+cextension': 1086},
-                                   variance=0.1)
+    @profiling.function_call_count()
     def test_profile_5_aggregates(self):
         self.test_baseline_5_aggregates()
 
-    @profiling.function_call_count(2545)
+    @profiling.function_call_count()
     def test_profile_6_editing(self):
         self.test_baseline_6_editing()
 

test/bootstrap/noseplugin.py

     _set_table_options, base_config, db, db_label, db_url, file_config, post_configure,
     pre_configure)
 
+testing = None
+engines = None
+util = None
+
 log = logging.getLogger('nose.plugins.sqlalchemy')
 
 class NoseSQLAlchemy(Plugin):
                  "a db-default/InnoDB combo.")
         opt("--table-option", action="append", dest="tableopts", default=[],
             help="Add a dialect-specific table option, key=value")
-
+        opt("--write-profiles", action="store_true", dest="write_profiles", default=False,
+                help="Write/update profiling data.")
         global file_config
         file_config = ConfigParser.ConfigParser()
         file_config.readfp(StringIO.StringIO(base_config))
 
     def beforeTest(self, test):
         testing.resetwarnings()
+        testing.current_test = test.id()
 
     def afterTest(self, test):
         engines.testing_reaper._after_test_ctx()

test/lib/profiles.txt

+# /Users/classic/dev/sa07/./test/lib/profiles.txt
+# This file is written out on a per-environment basis.
+# For each test in aaa_profiling, the corresponding function and 
+# environment is located within this file.  If it doesn't exist,
+# the test is skipped.
+# If a callcount does exist, it is compared to what we received. 
+# assertions are raised if the counts do not match.
+# 
+# To add a new callcount test, apply the function_call_count 
+# decorator and re-run the tests using the --write-profiles option - 
+# this file will be rewritten including the new count.
+# 
+
+# TEST: test.aaa_profiling.test_compiler.CompileTest.test_insert
+
+test.aaa_profiling.test_compiler.CompileTest.test_insert 2.6_sqlite_pysqlite_nocextensions 62
+test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mysql_mysqldb_cextensions 62
+test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mysql_mysqldb_nocextensions 62
+test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_postgresql_psycopg2_cextensions 62
+test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_postgresql_psycopg2_nocextensions 62
+test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_sqlite_pysqlite_cextensions 62
+test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_sqlite_pysqlite_nocextensions 62
+
+# TEST: test.aaa_profiling.test_compiler.CompileTest.test_select
+
+test.aaa_profiling.test_compiler.CompileTest.test_select 2.6_sqlite_pysqlite_nocextensions 152
+test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_mysqldb_cextensions 152
+test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_mysqldb_nocextensions 152
+test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_postgresql_psycopg2_cextensions 152
+test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_postgresql_psycopg2_nocextensions 152
+test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_sqlite_pysqlite_cextensions 152
+test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_sqlite_pysqlite_nocextensions 152
+
+# TEST: test.aaa_profiling.test_compiler.CompileTest.test_update
+
+test.aaa_profiling.test_compiler.CompileTest.test_update 2.6_sqlite_pysqlite_nocextensions 56
+test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mysql_mysqldb_cextensions 56
+test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mysql_mysqldb_nocextensions 56
+test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_postgresql_psycopg2_cextensions 56
+test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_postgresql_psycopg2_nocextensions 56
+test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_sqlite_pysqlite_cextensions 56
+test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_sqlite_pysqlite_nocextensions 56
+
+# TEST: test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause
+
+test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.6_sqlite_pysqlite_nocextensions 117
+test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mysql_mysqldb_cextensions 117
+test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mysql_mysqldb_nocextensions 117
+test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_postgresql_psycopg2_cextensions 117
+test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_postgresql_psycopg2_nocextensions 117
+test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_sqlite_pysqlite_cextensions 117
+test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_sqlite_pysqlite_nocextensions 117
+
+# TEST: test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity
+
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.6_sqlite_pysqlite_nocextensions 17987
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_mysql_mysqldb_cextensions 17987
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_mysql_mysqldb_nocextensions 17987
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_postgresql_psycopg2_cextensions 17987
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_postgresql_psycopg2_nocextensions 17987
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_sqlite_pysqlite_cextensions 17987
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_sqlite_pysqlite_nocextensions 17987
+
+# TEST: test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity
+
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.6_sqlite_pysqlite_nocextensions 112545
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_mysql_mysqldb_cextensions 119045
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_mysql_mysqldb_nocextensions 121045
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_postgresql_psycopg2_cextensions 111517
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_postgresql_psycopg2_nocextensions 113545
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_sqlite_pysqlite_cextensions 110545
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_sqlite_pysqlite_nocextensions 112517
+
+# TEST: test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks
+
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.6_sqlite_pysqlite_nocextensions 18493
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_mysql_mysqldb_cextensions 18845
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_mysql_mysqldb_nocextensions 19057
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_postgresql_psycopg2_cextensions 18313
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_postgresql_psycopg2_nocextensions 18525
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_sqlite_pysqlite_cextensions 18281
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_sqlite_pysqlite_nocextensions 18493
+
+# TEST: test.aaa_profiling.test_orm.MergeTest.test_merge_load
+
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.6_sqlite_pysqlite_nocextensions 1071,1024
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_mysql_mysqldb_cextensions 1244,1098
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_mysql_mysqldb_nocextensions 1263,1117
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_postgresql_psycopg2_cextensions 1103,1040
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_postgresql_psycopg2_nocextensions 1122,1059
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_sqlite_pysqlite_cextensions 1052,1005
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_sqlite_pysqlite_nocextensions 1071,1024
+
+# TEST: test.aaa_profiling.test_orm.MergeTest.test_merge_no_load
+
+test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.6_sqlite_pysqlite_nocextensions 82,11
+test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_mysql_mysqldb_cextensions 82,11
+test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_mysql_mysqldb_nocextensions 82,11
+test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_postgresql_psycopg2_cextensions 82,11
+test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_postgresql_psycopg2_nocextensions 82,11
+test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_sqlite_pysqlite_cextensions 82,11
+test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_sqlite_pysqlite_nocextensions 82,11
+
+# TEST: test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect
+
+test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.6_sqlite_pysqlite_nocextensions 75
+test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_mysql_mysqldb_cextensions 67
+test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_mysql_mysqldb_nocextensions 67
+test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_postgresql_psycopg2_cextensions 67
+test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_postgresql_psycopg2_nocextensions 67
+test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_sqlite_pysqlite_cextensions 75
+test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_sqlite_pysqlite_nocextensions 75
+
+# TEST: test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect
+
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.6_sqlite_pysqlite_nocextensions 29
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_mysql_mysqldb_cextensions 29
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_mysql_mysqldb_nocextensions 29
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_postgresql_psycopg2_cextensions 29
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_postgresql_psycopg2_nocextensions 29
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_sqlite_pysqlite_cextensions 29
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_sqlite_pysqlite_nocextensions 29
+
+# TEST: test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect
+
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.6_sqlite_pysqlite_nocextensions 6
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_mysql_mysqldb_cextensions 6
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_mysql_mysqldb_nocextensions 6
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_postgresql_psycopg2_cextensions 6
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_postgresql_psycopg2_nocextensions 6
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_sqlite_pysqlite_cextensions 6
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_sqlite_pysqlite_nocextensions 6
+
+# TEST: test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute
+
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.6_sqlite_pysqlite_nocextensions 43
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_mysql_mysqldb_cextensions 41
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_mysql_mysqldb_nocextensions 43
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_postgresql_psycopg2_cextensions 41
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_postgresql_psycopg2_nocextensions 43
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_sqlite_pysqlite_cextensions 41
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_sqlite_pysqlite_nocextensions 43
+
+# TEST: test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute
+
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.6_sqlite_pysqlite_nocextensions 66
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_mysql_mysqldb_cextensions 64
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_mysql_mysqldb_nocextensions 66
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_postgresql_psycopg2_cextensions 64
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_postgresql_psycopg2_nocextensions 66
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_sqlite_pysqlite_cextensions 64
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_sqlite_pysqlite_nocextensions 66
+
+# TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile
+
+test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.6_sqlite_pysqlite_nocextensions 9
+test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_mysql_mysqldb_cextensions 9
+test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_mysql_mysqldb_nocextensions 9
+test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_postgresql_psycopg2_cextensions 9
+test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_postgresql_psycopg2_nocextensions 9
+test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_sqlite_pysqlite_cextensions 9
+test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_sqlite_pysqlite_nocextensions 9
+
+# TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_string
+
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.6_sqlite_pysqlite_nocextensions 14388
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_mysqldb_cextensions 426
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_mysqldb_nocextensions 14446
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_cextensions 20412
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_nocextensions 34432
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_cextensions 368
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_nocextensions 14388
+
+# TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_unicode
+
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.6_sqlite_pysqlite_nocextensions 14388
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_mysqldb_cextensions 426
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_mysqldb_nocextensions 44446
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_cextensions 20412
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_nocextensions 34432
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_cextensions 368
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_nocextensions 14388
+
+# TEST: test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_1a_populate
+
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_1a_populate 2.7_postgresql_psycopg2_cextensions 4948
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_1a_populate 2.7_postgresql_psycopg2_nocextensions 4992
+
+# TEST: test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_2_insert
+
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_2_insert 2.7_postgresql_psycopg2_cextensions 247
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_2_insert 2.7_postgresql_psycopg2_nocextensions 247
+
+# TEST: test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_3_properties
+
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_3_properties 2.7_postgresql_psycopg2_cextensions 3293
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_3_properties 2.7_postgresql_psycopg2_nocextensions 3517
+
+# TEST: test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_4_expressions
+
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_4_expressions 2.7_postgresql_psycopg2_cextensions 10719
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_4_expressions 2.7_postgresql_psycopg2_nocextensions 12335
+
+# TEST: test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_5_aggregates
+
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_5_aggregates 2.7_postgresql_psycopg2_cextensions 1008
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_5_aggregates 2.7_postgresql_psycopg2_nocextensions 1112
+
+# TEST: test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_6_editing
+
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_6_editing 2.7_postgresql_psycopg2_cextensions 1711
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_6_editing 2.7_postgresql_psycopg2_nocextensions 1754
+
+# TEST: test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_7_multiview
+
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_7_multiview 2.7_postgresql_psycopg2_cextensions 2172
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_7_multiview 2.7_postgresql_psycopg2_nocextensions 2402
+
+# TEST: test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_1_create_tables
+
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_1_create_tables 2.7_postgresql_psycopg2_cextensions 5752
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_1_create_tables 2.7_postgresql_psycopg2_nocextensions 5760
+
+# TEST: test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_1a_populate
+
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_1a_populate 2.7_postgresql_psycopg2_cextensions 5745
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_1a_populate 2.7_postgresql_psycopg2_nocextensions 5813
+
+# TEST: test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_2_insert
+
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_2_insert 2.7_postgresql_psycopg2_cextensions 395
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_2_insert 2.7_postgresql_psycopg2_nocextensions 399
+
+# TEST: test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_3_properties
+
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_3_properties 2.7_postgresql_psycopg2_cextensions 5876
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_3_properties 2.7_postgresql_psycopg2_nocextensions 6084
+
+# TEST: test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_4_expressions
+
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_4_expressions 2.7_postgresql_psycopg2_cextensions 18057
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_4_expressions 2.7_postgresql_psycopg2_nocextensions 19425
+
+# TEST: test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_5_aggregates
+
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_5_aggregates 2.7_postgresql_psycopg2_cextensions 1021
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_5_aggregates 2.7_postgresql_psycopg2_nocextensions 1117
+
+# TEST: test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_6_editing
+
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_6_editing 2.7_postgresql_psycopg2_cextensions 2542
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_6_editing 2.7_postgresql_psycopg2_nocextensions 2590

test/lib/profiling.py

 
 """
 
-import os, sys
+import os
+import sys
 from test.lib.util import gc_collect, decorator
+from test.lib import testing
 from nose import SkipTest
+import pstats
+import time
+import collections
+from sqlalchemy import util
+try:
+    import cProfile
+except ImportError:
+    cProfile = None
+from sqlalchemy.util.compat import jython, pypy, win32
 
-__all__ = 'profiled', 'function_call_count', 'conditional_call_count'
-
-all_targets = set()
-profile_config = { 'targets': set(),
-                   'report': True,
-                   'print_callers':False,
-                   'print_callees':False,
-                   'graphic':False,
-                   'sort': ('time', 'calls'),
-                   'limit': None }
-profiler = None
+from test.lib.requires import _has_cextensions
+_has_cext = _has_cextensions()
 
 def profiled(target=None, **target_opts):
-    """Optional function profiling.
+    """Function profiling.
 
     @profiled('label')
     or
     configuration and command-line options.
     """
 
-    # manual or automatic namespacing by module would remove conflict issues
+    profile_config = {'targets': set(),
+                       'report': True,
+                       'print_callers': False,
+                       'print_callees': False,
+                       'graphic': False,
+                       'sort': ('time', 'calls'),
+                       'limit': None}
     if target is None:
         target = 'anonymous_target'
-    elif target in all_targets:
-        print "Warning: redefining profile target '%s'" % target
-    all_targets.add(target)
 
     filename = "%s.prof" % target
 
     @decorator
     def decorate(fn, *args, **kw):
-        if (target not in profile_config['targets'] and
-            not target_opts.get('always', None)):
-            return fn(*args, **kw)
-
         elapsed, load_stats, result = _profile(
             filename, fn, *args, **kw)
 
             if report:
                 sort_ = target_opts.get('sort', profile_config['sort'])
                 limit = target_opts.get('limit', profile_config['limit'])
-                print "Profile report for target '%s' (%s)" % (
+                print ("Profile report for target '%s' (%s)" % (
                     target, filename)
+                    )
 
                 stats = load_stats()
                 stats.sort_stats(*sort_)
         return result
     return decorate
 
-def function_call_count(count=None, versions={}, variance=0.05):
+
+class ProfileStatsFile(object):
+    """"Store per-platform/fn profiling results in a file.
+
+    We're still targeting Py2.5, 2.4 on 0.7 with no dependencies,
+    so no json lib :(  need to roll something silly
+
+    """
+    def __init__(self):
+        from test.bootstrap.config import options
+        self.write = options.write_profiles
+        dirname, fname = os.path.split(__file__)
+        self.short_fname = "profiles.txt"
+        self.fname = os.path.join(dirname, self.short_fname)
+        self.data = collections.defaultdict(lambda: collections.defaultdict(dict))
+        self._read()
+        if self.write:
+            # rewrite for the case where features changed,
+            # etc.
+            self._write()
+
+    @util.memoized_property
+    def platform_key(self):
+
+        dbapi_key = testing.db.name + "_" + testing.db.driver
+
+        # keep it at 2.7, 3.1, 3.2, etc. for now.
+        py_version = '.'.join([str(v) for v in sys.version_info[0:2]])
+
+        platform_tokens = [py_version]
+        platform_tokens.append(dbapi_key)
+        if jython:
+            platform_tokens.append("jython")
+        if pypy:
+            platform_tokens.append("pypy")
+        if win32:
+            platform_tokens.append("win")
+        platform_tokens.append(_has_cext and "cextensions" or "nocextensions")
+        return "_".join(platform_tokens)
+
+    def has_stats(self):
+        test_key = testing.current_test
+        return test_key in self.data and self.platform_key in self.data[test_key]
+
+    def result(self, callcount):
+        test_key = testing.current_test
+        per_fn = self.data[test_key]
+        per_platform = per_fn[self.platform_key]
+
+        if 'counts' not in per_platform:
+            per_platform['counts'] = counts = []
+        else:
+            counts = per_platform['counts']
+
+        if 'current_count' not in per_platform:
+            per_platform['current_count'] = current_count = 0
+        else:
+            current_count = per_platform['current_count']
+
+        has_count = len(counts) > current_count
+
+        if not has_count:
+            counts.append(callcount)
+            if self.write:
+                self._write()
+            result = None
+        else:
+            result = per_platform['lineno'], counts[current_count]
+        per_platform['current_count'] += 1
+        return result
+
+
+    def _header(self):
+        return \
+        "# %s\n"\
+        "# This file is written out on a per-environment basis.\n"\
+        "# For each test in aaa_profiling, the corresponding function and \n"\
+        "# environment is located within this file.  If it doesn't exist,\n"\
+        "# the test is skipped.\n"\
+        "# If a callcount does exist, it is compared to what we received. \n"\
+        "# assertions are raised if the counts do not match.\n"\
+        "# \n"\
+        "# To add a new callcount test, apply the function_call_count \n"\
+        "# decorator and re-run the tests using the --write-profiles option - \n"\
+        "# this file will be rewritten including the new count.\n"\
+        "# \n"\
+        "" % (self.fname)
+
+    def _read(self):
+        profile_f = open(self.fname)
+        for lineno, line in enumerate(profile_f):
+            line = line.strip()
+            if not line or line.startswith("#"):
+                continue
+
+            test_key, platform_key, counts = line.split()
+            per_fn = self.data[test_key]
+            per_platform = per_fn[platform_key]
+            per_platform['counts'] = [int(count) for count in counts.split(",")]
+            per_platform['lineno'] = lineno + 1
+            per_platform['current_count'] = 0
+        profile_f.close()
+
+    def _write(self):
+        print("Writing profile file %s" % self.fname)
+        profile_f = open(self.fname, "w")
+        profile_f.write(self._header())
+        for test_key in sorted(self.data):
+
+            per_fn = self.data[test_key]
+            profile_f.write("\n# TEST: %s\n\n" % test_key)
+            for platform_key in sorted(per_fn):
+                per_platform = per_fn[platform_key]
+                profile_f.write(
+                    "%s %s %s\n" % (
+                        test_key,
+                        platform_key, ",".join(str(count) for count in per_platform['counts'])
+                    )
+                )
+        profile_f.close()
+
+_profile_stats = ProfileStatsFile()
+
+from sqlalchemy.util.compat import update_wrapper
+
+def function_call_count(variance=0.05):
     """Assert a target for a test case's function call count.
 
-    count
-      Optional, general target function call count.
+    The main purpose of this assertion is to detect changes in
+    callcounts for various functions - the actual number is not as important.
+    Callcounts are stored in a file keyed to Python version and OS platform
+    information.  This file is generated automatically for new tests,
+    and versioned so that unexpected changes in callcounts will be detected.
 
-    versions
-      Optional, a dictionary of Python version strings to counts,
-      for example::
-
-        { '2.5.1': 110,
-          '2.5': 100,
-          '2.4': 150 }
-
-      The best match for the current running python will be used.
-      If none match, 'count' will be used as the fallback.
-
-    variance
-      An +/- deviation percentage, defaults to 5%.
     """
 
-    # this could easily dump the profile report if --verbose is in effect
+    def decorate(fn):
+        def wrap(*args, **kw):
 
-    version_info = list(sys.version_info)
-    py_version = '.'.join([str(v) for v in sys.version_info])
-    try:
-        from sqlalchemy.cprocessors import to_float
-        cextension = True
-    except ImportError:
-        cextension = False
 
-    while version_info:
-        version = '.'.join([str(v) for v in version_info])
-        if cextension and (version + "+cextension") in versions:
-            version += "+cextension"
-            count = versions[version]
-            break
-        elif version in versions:
-            count = versions[version]
-            break
+            if cProfile is None:
+                raise SkipTest("cProfile is not installed")
 
-        version_info.pop()
+            if not _profile_stats.has_stats() and not _profile_stats.write:
+                raise SkipTest("No profiling stats available on this "
+                            "platform for this function.  Run tests with "
+                            "--write-profiles to add statistics to %s for "
+                            "this platform." % _profile_stats.short_fname)
 
-    if count is None:
-        print "Warning: no function call count specified for version: '%s'" % py_version
-        return lambda fn: fn
+            gc_collect()
 
-    @decorator
-    def decorate(fn, *args, **kw):
-        try:
-            filename = "%s.prof" % fn.__name__
 
-            elapsed, stat_loader, result = _profile(
-                filename, fn, *args, **kw)
+            timespent, load_stats, fn_result = _profile(
+                fn, *args, **kw
+            )
+            stats = load_stats()
+            callcount = stats.total_calls
 
-            stats = stat_loader()
-            calls = stats.total_calls
+            expected = _profile_stats.result(callcount)
+            if expected is None:
+                expected_count = None
+            else:
+                line_no, expected_count = expected
 
-            stats.sort_stats('calls', 'cumulative')
+            print("Pstats calls: %d Expected %s" % (
+                    callcount,
+                    expected_count
+                )
+            )
             stats.print_stats()
             #stats.print_callers()
-            deviance = int(count * variance)
-            if (calls < (count - deviance) or
-                calls > (count + deviance)):
-                raise AssertionError(
-                    "Function call count %s not within %s%% "
-                    "of expected %s. (Python version %s)" % (
-                    calls, (variance * 100), count, py_version))
 
-            return result
-        finally:
-            if os.path.exists(filename):
-                os.unlink(filename)
+            if expected_count:
+                deviance = int(callcount * variance)
+                if abs(callcount - expected_count) > deviance:
+                    raise AssertionError(
+                        "Adjusted function call count %s not within %s%% "
+                        "of expected %s. (Delete line %d of file %s to regenerate "
+                            "this callcount, when tests are run with --write-profiles.)"
+                        % (
+                        callcount, (variance * 100),
+                        expected_count, line_no,
+                        _profile_stats.fname))
+            return fn_result
+        return update_wrapper(wrap, fn)
     return decorate
 
-def conditional_call_count(discriminator, categories):
-    """Apply a function call count conditionally at runtime.
 
-    Takes two arguments, a callable that returns a key value, and a dict
-    mapping key values to a tuple of arguments to function_call_count.
+def _profile(fn, *args, **kw):
+    filename = "%s.prof" % fn.__name__
 
-    The callable is not evaluated until the decorated function is actually
-    invoked.  If the `discriminator` returns a key not present in the
-    `categories` dictionary, no call count assertion is applied.
-
-    Useful for integration tests, where running a named test in isolation may
-    have a function count penalty not seen in the full suite, due to lazy
-    initialization in the DB-API, SA, etc.
-    """
-    @decorator
-    def decorate(fn, *args, **kw):
-        criteria = categories.get(discriminator(), None)
-        if criteria is None:
-            return fn(*args, **kw)
-
-        rewrapped = function_call_count(*criteria)(fn)
-        return rewrapped(*args, **kw)
-    return decorate
-
-
-def _profile(filename, fn, *args, **kw):
-    global profiler
-    if not profiler:
-        if sys.version_info > (2, 5):
-            try:
-                import cProfile
-                profiler = 'cProfile'
-            except ImportError:
-                pass
-        if not profiler:
-            try:
-                import hotshot
-                profiler = 'hotshot'
-            except ImportError:
-                profiler = 'skip'
-
-    if profiler == 'skip':
-        raise SkipTest('Profiling not supported on this platform')
-    elif profiler == 'cProfile':
-        return _profile_cProfile(filename, fn, *args, **kw)
-    else:
-        return _profile_hotshot(filename, fn, *args, **kw)
-
-def _profile_cProfile(filename, fn, *args, **kw):
-    import cProfile, pstats, time
-
-    load_stats = lambda: pstats.Stats(filename)
-    gc_collect()
+    def load_stats():
+        st = pstats.Stats(filename)
+        os.unlink(filename)
+        return st
 
     began = time.time()
     cProfile.runctx('result = fn(*args, **kw)', globals(), locals(),
 
     return ended - began, load_stats, locals()['result']
 
-def _profile_hotshot(filename, fn, *args, **kw):
-    import hotshot, hotshot.stats, time
-    load_stats = lambda: hotshot.stats.load(filename)
-
-    gc_collect()
-    prof = hotshot.Profile(filename)
-    began = time.time()
-    prof.start()
-    try:
-        result = fn(*args, **kw)
-    finally:
-        prof.stop()
-        ended = time.time()
-        prof.close()
-
-    return ended - began, load_stats, result
-

test/lib/requires.py

         skip_if(lambda: not _has_cextensions(), "C extensions not installed")
     )
 
+
 def dbapi_lastrowid(fn):
     if util.pypy:
         return _chain_decorators_on(
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.