diff --git a/schemainspect/misc.py b/schemainspect/misc.py index c4549cf..544b464 100644 --- a/schemainspect/misc.py +++ b/schemainspect/misc.py @@ -1,4 +1,5 @@ import inspect +import threading import six from pkg_resources import resource_stream as pkg_resource_stream @@ -13,15 +14,31 @@ def connection_from_s_or_c(s_or_c): # pragma: no cover return s_or_c.connection() +_already_repring = threading.local() + + @six.python_2_unicode_compatible class AutoRepr(object): # pragma: no cover def __repr__(self): + try: + working_set = _already_repring.working_set + except AttributeError: + working_set = set() + _already_repring.working_set = working_set + + if id(self) in working_set: + return "..." + cname = self.__class__.__name__ - vals = [ - "{}={}".format(k, repr(v)) - for k, v in sorted(self.__dict__.items()) - if not k.startswith("_") - ] + try: + working_set.add(id(self)) + vals = [ + "{}={}".format(k, repr(v)) + for k, v in sorted(self.__dict__.items()) + if not k.startswith("_") + ] + finally: + working_set.remove(id(self)) return "{}({})".format(cname, ", ".join(vals)) def __str__(self): diff --git a/tests/test_repr.py b/tests/test_repr.py new file mode 100644 index 0000000..bf42001 --- /dev/null +++ b/tests/test_repr.py @@ -0,0 +1,21 @@ +from sqlbag import S + +from schemainspect import get_inspector + + +CREATE = """ +create table t (id integer not null primary key); +""" + + +def test_repr(db): + with S(db) as s: + s.execute(CREATE) + i = get_inspector(s) + + table = i.tables['"public"."t"'] + assert repr(table).startswith("InspectedSelectable(") + + c = table.constraints['"public"."t"."t_pkey"'] + assert repr(c).startswith("InspectedConstraint(") + assert "constraint=..." in repr(c)