Kirill Simonov avatar Kirill Simonov committed 7923959

tweak.override: report unused labeling patterns.

Comments (0)

Files changed (6)

src/htsql/cache.py

     @functools.wraps(service)
     def wrapper(*args, **kwds):
         cache = context.app.htsql.cache
-        key = (service.func_name,)+args
+        key = (service.__module__, service.__name__) + args
         try:
             return cache.values[key]
         except KeyError:

src/htsql/classify.py

             arcs.append(arc)
         labels_by_arc[arc].append(label)
     for arc in arcs:
-        key = ('relabel', arc)
+        key = (relabel.__module__, relabel.__name__, arc)
         value = labels_by_arc[arc]
         if key not in cache.values:
             cache.set(key, value)

src/htsql_tweak/override/__init__.py

 from . import classify, introspect, pattern
 from htsql.addon import Addon, Parameter
 from htsql.validator import SeqVal, MapVal
-from htsql.introspect import introspect
-from htsql.classify import classify
 from .pattern import (TablePatternVal, ColumnPatternVal,
                       UniqueKeyPatternVal, ForeignKeyPatternVal,
                       ClassPatternVal, FieldPatternVal, LabelVal, QLabelVal)
 from .introspect import UnusedPatternCache
+from .classify import validate
 
 
 class TweakOverrideAddon(Addon):
         self.unused_pattern_cache = UnusedPatternCache()
 
     def validate(self):
-        catalog = introspect()
+        validate()
         unused_patterns = self.unused_pattern_cache.patterns
         if unused_patterns:
             raise ValueError("unused override patterns: %s"
-                             % ", ".join(str(pattern)
-                                         for pattern in unused_patterns))
+                             % ", ".join(unused_patterns))
 
 

src/htsql_tweak/override/classify.py

             pattern = addon.class_labels[name]
             arc = pattern.extract(node)
             if arc is None:
-                addon.unused_pattern_cache.add(pattern)
+                addon.unused_pattern_cache.add(str(pattern))
                 continue
             self.names_by_arc.setdefault(arc, []).append(name)
             self.arc_by_name[name] = arc
             self.node_by_name[label.name] = label.target
             self.name_by_node[label.target] = label.name
         for class_name, field_name in sorted(addon.field_labels):
+            name = u"%s.%s" % (class_name, field_name)
             pattern = addon.field_labels[class_name, field_name]
             if class_name not in self.node_by_name:
-                addon.unused_pattern_cache.add(pattern)
+                addon.unused_pattern_cache.add(name.encode('utf-8'))
                 continue
             node = self.node_by_name[class_name]
             arc = pattern.extract(node)
             if arc is None:
-                addon.unused_pattern_cache.add(pattern)
+                addon.unused_pattern_cache.add(str(pattern))
                 continue
             self.names_by_arc_by_node.setdefault(node, {})
             self.names_by_arc_by_node[node].setdefault(arc, [])
         class_name = cache.name_by_node.get(self.node)
         if class_name not in addon.field_orders:
             return super(OverrideOrderTable, self).__call__()
+        names = set(label.name for label in self.labels)
         orders = {}
         for idx, name in enumerate(addon.field_orders[class_name]):
             orders[name] = idx
+            if name not in names:
+                name = u"%s.%s" % (class_name, name)
+                addon.unused_pattern_cache.add(name.encode('utf-8'))
         labels = [label.clone(is_public=(label.name in orders))
                   for label in self.labels]
         labels.sort(key=(lambda label: (label.name not in orders,
         return labels
 
 
+@once
+def validate():
+    addon = context.app.tweak.override
+    cache = field_cache()
+    for name in sorted(addon.field_orders):
+        if name not in cache.node_by_name:
+            addon.unused_pattern_cache.add(name.encode('utf-8'))
+            continue
+        node = cache.node_by_name[name]
+        classify(node)
+
+

src/htsql_tweak/override/introspect.py

                                               pattern.is_partial)
                         unused.discard(pattern)
 
+        if addon.unlabeled_tables:
+            unused.update(addon.unlabeled_tables)
+            for schema in catalog.schemas:
+                schema_matches = [pattern
+                                  for pattern in addon.unlabeled_tables
+                                  if pattern.matches(schema)]
+                if not schema_matches:
+                    continue
+                for table in schema.tables:
+                    matches = [pattern
+                               for pattern in schema_matches
+                               if pattern.matches(table)]
+                    unused.difference_update(matches)
+
+        if addon.unlabeled_columns:
+            unused.update(addon.unlabeled_columns)
+            for schema in catalog.schemas:
+                schema_matches = [pattern
+                                  for pattern in addon.unlabeled_columns
+                                  if pattern.matches(schema)]
+                if not schema_matches:
+                    continue
+                for table in schema.tables:
+                    table_matches = [pattern
+                                     for pattern in schema_matches
+                                     if pattern.matches(table)]
+                    if not table_matches:
+                        continue
+                    for column in table.columns:
+                        matches = [pattern
+                                   for pattern in table_matches
+                                   if pattern.matches(column)]
+                        unused.difference_update(matches)
+
         for pattern in (addon.include_tables + addon.exclude_tables +
                         addon.include_columns + addon.exclude_columns +
                         addon.not_nulls + addon.unique_keys +
-                        addon.foreign_keys):
+                        addon.foreign_keys +
+                        addon.unlabeled_tables + addon.unlabeled_columns):
             if pattern in unused:
-                addon.unused_pattern_cache.add(pattern)
+                addon.unused_pattern_cache.add(str(pattern))
 
         return catalog
 

src/htsql_tweak/override/pattern.py

         return u"".join(chunks)
 
 
-class ArcPattern(Printable):
+class ArcPattern(Pattern):
 
     is_column = False
     is_table = False
         chunks.append(self.table_pattern)
         if self.column_patterns is not None:
             chunks.append(u"(%s)" % u",".join(self.column_patterns))
-        if self.is_partial:
-            chunks.append("?")
         chunks.append(" -> ")
         if self.target_schema_pattern is not None:
             chunks.append(self.target_schema_pattern)
         return ChainArc(table, joins)
 
     def __unicode__(self):
-        return u", ".join(self.join_patterns)
+        return u", ".join(unicode(pattern) for pattern in self.join_patterns)
 
 
 class SyntaxArcPattern(ArcPattern):
         assert isinstance(node, Node)
         return SyntaxArc(node, self.syntax)
 
-    def __str__(self):
+    def __unicode__(self):
         return unicode(self.syntax)
 
 
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.