Repository: manicmaniac/sqlalchemy-repr

Issue:
Allow for whitelist/blacklist list of fields
Some of my models have data columns that are much too verbose to print, it would be great if I could easily specify a whitelist/blacklist of fields that should be shown or hidden.

Perhaps something like this:

```
class SomeModel(Base):
    ...
    repr_blacklist = {'field_a', 'field_b'}
```

Discussion:

Patch:
diff --git a/sqlalchemy_repr.py b/sqlalchemy_repr.py
index 7d011b0..eb9ee8f 100644
--- a/sqlalchemy_repr.py
+++ b/sqlalchemy_repr.py
@@ -11,7 +11,6 @@ try:
 except ImportError:
     from repr import Repr as _Repr
 
-
 __all__ = ['Repr', 'PrettyRepr', 'RepresentableBase',
            'PrettyRepresentableBase']
 
@@ -46,8 +45,17 @@ class Repr(_Repr):
         return '%s=%r' % (attr_name, attr_value)
 
     def _iter_attrs(self, obj):
+        blacklist = set(getattr(obj, '__repr_blacklist__', set()))
+        whitelist = set(getattr(obj, '__repr_whitelist__', set()))
+
         attr_names = inspect(obj.__class__).columns.keys()
         for attr_name in attr_names:
+            if attr_name in blacklist:
+                continue
+
+            if whitelist and attr_name not in whitelist:
+                continue
+
             yield (attr_name, getattr(obj, attr_name))
 
 


Test patch:
diff --git a/tests/test_sqlalchemy_repr.py b/tests/test_sqlalchemy_repr.py
index 069e3dd..8fbe8ed 100644
--- a/tests/test_sqlalchemy_repr.py
+++ b/tests/test_sqlalchemy_repr.py
@@ -28,6 +28,16 @@ class Entry(Base):
     user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
 
 
+class EntryWithBlacklistAndWhitelist(Base):
+    __tablename__ = 'entries_with_blacklist'
+    id = Column(Integer, primary_key=True)
+    title = Column(Unicode(255), nullable=False)
+    text = Column(UnicodeText, nullable=False, default='')
+    user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
+    __repr_blacklist__ = ('text',)
+    __repr_whitelist__ = ('text', 'title')
+
+
 class TestRepr(unittest.TestCase):
     def setUp(self):
         engine = create_engine('sqlite://')
@@ -39,9 +49,11 @@ class TestRepr(unittest.TestCase):
 
         self.session = Session()
         self.entry = Entry(title='ham', text=self.dummy_text, user_id=1)
+        self.blacklist_entry = EntryWithBlacklistAndWhitelist(title='ham', text=self.dummy_text, user_id=1)
         self.user = User(name='spam', created=self._date)
         self.session.add(self.user)
         self.session.add(self.entry)
+        self.session.add(self.blacklist_entry)
         self.session.commit()
 
     def test_repr_with_user(self):
@@ -72,6 +84,11 @@ class TestRepr(unittest.TestCase):
         pattern = r"<Entry\n    id=1,\n    title=u?'ham',\n    text=u?'Lorem.*',\n    user_id=1>"
         self.assertMatch(result, pattern)
 
+    def test_pretty_repr_with_blacklist_and_whitelist(self):
+        result = PrettyRepr().repr(self.blacklist_entry)
+        pattern = r"<EntryWithBlacklistAndWhitelist\n    title='ham'>"
+        self.assertMatch(result, pattern)
+
     def assertMatch(self, string, pattern):
         if not re.match(pattern, string):
             message = "%r doesn't match %r" % (string, pattern)