summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormike bayer <mike_mp@zzzcomputing.com>2019-07-11 16:20:17 +0000
committerGerrit Code Review <gerrit@bbpush.zzzcomputing.com>2019-07-11 16:20:17 +0000
commit3e77f419a141a09ed89b0b49ecde15db3e86c552 (patch)
treefd112b215167e7d72632e5edd6dca8e0c11be3af
parentfa5db637dc93b3e2ec09506735833f2e764f3a0f (diff)
parent2cc7308c96f5598ba0aea9a240b9a52629042d07 (diff)
downloadsqlalchemy-3e77f419a141a09ed89b0b49ecde15db3e86c552.tar.gz
Merge "Add performance improvement for Enum w/ Python 2 enum library"
-rw-r--r--doc/build/changelog/unreleased_13/4758.rst9
-rw-r--r--lib/sqlalchemy/sql/sqltypes.py8
-rw-r--r--test/aaa_profiling/test_misc.py37
-rw-r--r--test/profiles.txt5
4 files changed, 54 insertions, 5 deletions
diff --git a/doc/build/changelog/unreleased_13/4758.rst b/doc/build/changelog/unreleased_13/4758.rst
new file mode 100644
index 000000000..238c74146
--- /dev/null
+++ b/doc/build/changelog/unreleased_13/4758.rst
@@ -0,0 +1,9 @@
+.. change::
+ :tags: bug, sql
+ :tickets: 4758
+
+ Adjusted the initialization for :class:`.Enum` to minimize how often it
+ invokes the ``.__members__`` attribute of a given PEP-435 enumeration
+ object, to suit the case where this attribute is expensive to invoke, as is
+ the case for some popular third party enumeration libraries.
+
diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py
index 6a520a2d5..af19cb05d 100644
--- a/lib/sqlalchemy/sql/sqltypes.py
+++ b/lib/sqlalchemy/sql/sqltypes.py
@@ -1424,14 +1424,12 @@ class Enum(Emulated, String, SchemaType):
if len(enums) == 1 and hasattr(enums[0], "__members__"):
self.enum_class = enums[0]
+ members = self.enum_class.__members__
if self.values_callable:
values = self.values_callable(self.enum_class)
else:
- values = list(self.enum_class.__members__)
- objects = [
- self.enum_class.__members__[k]
- for k in self.enum_class.__members__
- ]
+ values = list(members)
+ objects = [members[k] for k in members]
return values, objects
else:
self.enum_class = None
diff --git a/test/aaa_profiling/test_misc.py b/test/aaa_profiling/test_misc.py
new file mode 100644
index 000000000..c2b6f3d08
--- /dev/null
+++ b/test/aaa_profiling/test_misc.py
@@ -0,0 +1,37 @@
+from sqlalchemy import Enum
+from sqlalchemy.testing import fixtures
+from sqlalchemy.testing import profiling
+from sqlalchemy.util import classproperty
+
+
+class EnumTest(fixtures.TestBase):
+ __requires__ = ("cpython",)
+
+ def setup(self):
+ class SomeEnum(object):
+ # Implements PEP 435 in the minimal fashion needed by SQLAlchemy
+
+ _members = {}
+
+ @classproperty
+ def __members__(cls):
+ """simulate a very expensive ``__members__`` getter"""
+ for i in range(10):
+ x = {}
+ x.update({k: v for k, v in cls._members.items()}.copy())
+ return x.copy()
+
+ def __init__(self, name, value):
+ self.name = name
+ self.value = value
+ self._members[name] = self
+ setattr(self.__class__, name, self)
+
+ for i in range(400):
+ SomeEnum("some%d" % i, i)
+
+ self.SomeEnum = SomeEnum
+
+ @profiling.function_call_count()
+ def test_create_enum_from_pep_435_w_expensive_members(self):
+ Enum(self.SomeEnum)
diff --git a/test/profiles.txt b/test/profiles.txt
index d12b3c4ae..fe6c4368e 100644
--- a/test/profiles.txt
+++ b/test/profiles.txt
@@ -136,6 +136,11 @@ test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_postgre
test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_sqlite_pysqlite_dbapiunicode_cextensions 158
test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 158
+# TEST: test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_members
+
+test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_members 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 4638
+test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_members 3.7_sqlite_pysqlite_dbapiunicode_cextensions 942
+
# TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation
test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 2.7_mysql_mysqldb_dbapiunicode_cextensions 51975