diff options
| -rw-r--r-- | lib/sqlalchemy/orm/mapper.py | 10 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/query.py | 4 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/compiler.py | 40 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/expression.py | 19 | ||||
| -rw-r--r-- | lib/sqlalchemy/util.py | 5 | ||||
| -rw-r--r-- | test/profiling/compiler.py | 7 |
6 files changed, 45 insertions, 40 deletions
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index bd96b9e69..279fcd60c 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -314,7 +314,7 @@ class Mapper(object): def _iterate_polymorphic_properties(self, mappers=None): if mappers is None: mappers = self._with_polymorphic_mappers - return iter(util.OrderedSet( + return iter(util.unique_list( chain(*[list(mapper.iterate_properties) for mapper in [self] + mappers]) )) @@ -842,7 +842,7 @@ class Mapper(object): if manager is not None: if manager.class_ is not self.class_: # An inherited manager. Install one for this subclass. - raise "eh?" + # TODO: no coverage here manager = None elif manager.mapper: raise sa_exc.ArgumentError( @@ -970,8 +970,8 @@ class Mapper(object): A ``sqlalchemy.engine.base.RowProxy`` instance or a dictionary corresponding result-set ``ColumnElement`` instances to their values within a row. - """ + """ pk_cols = self.primary_key if adapter: pk_cols = [adapter.columns[c] for c in pk_cols] @@ -984,6 +984,7 @@ class Mapper(object): primary_key A list of values indicating the identifier. + """ return (self._identity_class, tuple(util.to_list(primary_key))) @@ -1003,6 +1004,7 @@ class Mapper(object): def primary_key_from_instance(self, instance): """Return the list of primary key values for the given instance. + """ state = attributes.instance_state(instance) return self._primary_key_from_state(state) @@ -1020,7 +1022,7 @@ class Mapper(object): else: raise exc.UnmappedColumnError("No column %s is configured on mapper %s..." % (column, self)) - # TODO: improve names + # TODO: improve names? def _get_state_attr_by_column(self, state, column): return self._get_col_to_prop(column).getattr(state, column) diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index 12a69855d..b53256a24 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -1103,9 +1103,9 @@ class Query(object): if filtered: if single_entity: - filter = util.OrderedIdentitySet + filter = lambda x: util.unique_list(x, util.IdentitySet) else: - filter = util.OrderedSet + filter = util.unique_list else: filter = None diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 6d3769906..0117b96ff 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -470,18 +470,20 @@ class DefaultCompiler(engine.Compiled): self.stack.append({'from':correlate_froms, 'iswrapper':iswrapper}) # the actual list of columns to print in the SELECT column list. - inner_columns = util.OrderedSet( - [c for c in [ + inner_columns = util.unique_list( + c for c in [ self.process( self.label_select_column(select, co, asfrom=asfrom), within_columns_clause=True, **column_clause_args) for co in select.inner_columns ] - if c is not None] + if c is not None ) - - text = " ".join(["SELECT"] + [self.process(x) for x in select._prefixes]) + " " + + text = "SELECT " # we're off to a good start ! + if select._prefixes: + text += " ".join(self.process(x) for x in select._prefixes) + " " text += self.get_select_precolumns(select) text += ', '.join(inner_columns) @@ -985,8 +987,8 @@ class IdentifierPreparer(object): self.initial_quote = initial_quote self.final_quote = final_quote or self.initial_quote self.omit_schema = omit_schema - self.__strings = {} - + self._strings = {} + def _escape_identifier(self, value): """Escape an identifier. @@ -1021,21 +1023,21 @@ class IdentifierPreparer(object): or self.illegal_initial_characters.match(value[0]) or not self.legal_characters.match(unicode(value)) or (lc_value != value)) - + def quote(self, ident, force): - if force: + if force is None: + if ident in self._strings: + return self._strings[ident] + else: + if self._requires_quotes(ident): + self._strings[ident] = self.quote_identifier(ident) + else: + self._strings[ident] = ident + return self._strings[ident] + elif force: return self.quote_identifier(ident) - elif force is False: - return ident - - if ident in self.__strings: - return self.__strings[ident] else: - if self._requires_quotes(ident): - self.__strings[ident] = self.quote_identifier(ident) - else: - self.__strings[ident] = ident - return self.__strings[ident] + return ident def format_sequence(self, sequence, use_schema=True): name = self.quote(sequence.name, sequence.quote) diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py index 2663c61a1..b721e5884 100644 --- a/lib/sqlalchemy/sql/expression.py +++ b/lib/sqlalchemy/sql/expression.py @@ -870,20 +870,17 @@ def _cloned_intersection(a, b): """ all_overlap = set(_expand_cloned(a)).intersection(_expand_cloned(b)) - return a.intersection( - [ - elem for elem in a if all_overlap.intersection(elem._cloned_set) - ] - ) + return a.intersection(elem for elem in a if all_overlap.intersection(elem._cloned_set)) def _compound_select(keyword, *selects, **kwargs): return CompoundSelect(keyword, *selects, **kwargs) def _is_literal(element): - global schema - if not schema: - from sqlalchemy import schema - return not isinstance(element, (ClauseElement, Operators, schema.SchemaItem)) + global _is_literal + from sqlalchemy import schema + def _is_literal(element): + return not isinstance(element, (ClauseElement, Operators, schema.SchemaItem)) + return _is_literal(element) def _from_objects(*elements, **kwargs): return itertools.chain(*[element._get_from_objects(**kwargs) for element in elements]) @@ -2960,8 +2957,8 @@ class Select(_SelectBaseMixin, FromClause): Select statements support appendable clauses, as well as the ability to execute themselves and return a result set. - """ + """ def __init__(self, columns, whereclause=None, from_obj=None, distinct=False, having=None, correlate=True, prefixes=None, **kwargs): """Construct a Select object. @@ -2971,8 +2968,8 @@ class Select(_SelectBaseMixin, FromClause): Additional generative and mutator methods are available on the [sqlalchemy.sql.expression#_SelectBaseMixin] superclass. - """ + """ self._should_correlate = correlate self._distinct = distinct diff --git a/lib/sqlalchemy/util.py b/lib/sqlalchemy/util.py index 925c59349..237772a40 100644 --- a/lib/sqlalchemy/util.py +++ b/lib/sqlalchemy/util.py @@ -40,6 +40,7 @@ if sys.version_info >= (2, 5): def __init__(self, creator): self.creator = creator + def __missing__(self, key): self[key] = val = self.creator(key) return val @@ -49,6 +50,7 @@ else: def __init__(self, creator): self.creator = creator + def __getitem__(self, key): try: return dict.__getitem__(self, key) @@ -1009,6 +1011,9 @@ class OrderedIdentitySet(IdentitySet): for o in iterable: self.add(o) +def unique_list(seq, compare_with=set): + seen = compare_with() + return [x for x in seq if x not in seen and not seen.add(x)] class UniqueAppender(object): """Appends items to a collection ensuring uniqueness. diff --git a/test/profiling/compiler.py b/test/profiling/compiler.py index 90d8c6b24..86f1c058f 100644 --- a/test/profiling/compiler.py +++ b/test/profiling/compiler.py @@ -15,19 +15,18 @@ class CompileTest(TestBase, AssertsExecutionResults): Column('c1', Integer, primary_key=True), Column('c2', String(30))) - @profiling.function_call_count(72, {'2.3': 44, '2.4': 46}) + @profiling.function_call_count(72, {'2.4': 46}) def test_insert(self): t1.insert().compile() - @profiling.function_call_count(68, {'2.3': 47, '2.4': 42}) + @profiling.function_call_count(70, {'2.4': 42}) def test_update(self): t1.update().compile() - @profiling.function_call_count(228, versions={'2.3': 153, '2.4':131}) + @profiling.function_call_count(228, versions={'2.4':131}) def test_select(self): s = select([t1], t1.c.c2==t2.c.c1) s.compile() - if __name__ == '__main__': testenv.main() |
