Skip to content

Commit 9a82e5f

Browse files
Merge pull request #140 from eywalker/master
Rearrange `__repr__`
2 parents 38c3a15 + 6758adc commit 9a82e5f

File tree

4 files changed

+55
-17
lines changed

4 files changed

+55
-17
lines changed

datajoint/fetch.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from datajoint import DataJointError
99
from . import key as PRIMARY_KEY
1010
from collections import abc
11+
from . import config
1112

1213

1314
def prepare_attributes(relation, item):
@@ -35,7 +36,9 @@ def ret(*args, **kwargs):
3536

3637
return ret
3738

39+
3840
class Fetch:
41+
3942
def __init__(self, relation):
4043
if isinstance(relation, Fetch): # copy constructor
4144
self.behavior = dict(relation.behavior)
@@ -46,7 +49,6 @@ def __init__(self, relation):
4649
)
4750
self._relation = relation
4851

49-
5052
@copy_first
5153
def order_by(self, *args):
5254
if len(args) > 0:
@@ -162,6 +164,23 @@ def __getitem__(self, item):
162164
]
163165
return return_values[0] if single_output else return_values
164166

167+
def __repr__(self):
168+
limit = config['display.limit']
169+
width = config['display.width']
170+
rel = self._relation.project(*self._relation.heading.non_blobs) # project out blobs
171+
template = '%%-%d.%ds' % (width, width)
172+
columns = rel.heading.names
173+
repr_string = ' '.join([template % column for column in columns]) + '\n'
174+
repr_string += ' '.join(['+' + '-' * (width - 2) + '+' for _ in columns]) + '\n'
175+
for tup in rel.fetch(limit=limit):
176+
repr_string += ' '.join([template % column for column in tup]) + '\n'
177+
if len(rel) > limit:
178+
repr_string += '...\n'
179+
repr_string += ' (%d tuples)\n' % len(rel)
180+
return repr_string
181+
182+
def __len__(self):
183+
return len(self._relation)
165184

166185
class Fetch1:
167186
def __init__(self, relation):

datajoint/relation.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ def descendants(self):
106106
for table in self.connection.erm.get_descendants(self.full_table_name))
107107
return [relation for relation in relations if relation.is_declared]
108108

109+
def _repr_helper(self):
110+
return "%s.%s()" % (self.__module__, self.__class__.__name__)
111+
109112
# --------- SQL functionality --------- #
110113
@property
111114
def is_declared(self):
@@ -282,6 +285,9 @@ def __init__(self, connection, full_table_name, definition=None, context=None):
282285
self._definition = definition
283286
self._context = context
284287

288+
def __repr__(self):
289+
return "FreeRelation(`%s`.`%s`)" % (self.database, self._table_name)
290+
285291
@property
286292
def definition(self):
287293
return self._definition

datajoint/relational_operand.py

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,17 @@ def __sub__(self, restriction):
143143
"""
144144
inverted restriction aka antijoin
145145
"""
146-
return self & Not(restriction)
146+
return \
147+
self & Not(restriction)
148+
149+
def _repr_helper(self):
150+
return "None"
151+
152+
def __repr__(self):
153+
ret = self._repr_helper()
154+
if self._restrictions:
155+
ret += ' & %r' % self._restrictions
156+
return ret
147157

148158
# ------ data retrieval methods -----------
149159

@@ -190,21 +200,6 @@ def cursor(self, offset=0, limit=None, order_by=None, as_dict=False):
190200
logger.debug(sql)
191201
return self.connection.query(sql, as_dict=as_dict)
192202

193-
def __repr__(self):
194-
limit = config['display.limit']
195-
width = config['display.width']
196-
rel = self.project(*self.heading.non_blobs) # project out blobs
197-
template = '%%-%d.%ds' % (width, width)
198-
columns = rel.heading.names
199-
repr_string = ' '.join([template % column for column in columns]) + '\n'
200-
repr_string += ' '.join(['+' + '-' * (width - 2) + '+' for _ in columns]) + '\n'
201-
for tup in rel.fetch(limit=limit):
202-
repr_string += ' '.join([template % column for column in tup]) + '\n'
203-
if len(self) > limit:
204-
repr_string += '...\n'
205-
repr_string += ' (%d tuples)\n' % len(self)
206-
return repr_string
207-
208203
@property
209204
def fetch1(self):
210205
return Fetch1(self)
@@ -274,6 +269,9 @@ def __init__(self, arg1, arg2):
274269
self._arg2 = Subquery(arg1) if arg2.heading.computed else arg2
275270
self._restrictions = self._arg1.restrictions + self._arg2.restrictions
276271

272+
def _repr_helper(self):
273+
return "(%r) * (%r)" % (self._arg1, self._arg2)
274+
277275
@property
278276
def connection(self):
279277
return self._arg1.connection
@@ -352,6 +350,10 @@ def _restrict(self, restriction):
352350
else:
353351
return super()._restrict(restriction)
354352

353+
def _repr_helper(self):
354+
# TODO: create better repr
355+
return "project(%r, %r)" % (self._arg, self._attributes)
356+
355357

356358
class Subquery(RelationalOperand):
357359
"""
@@ -379,3 +381,6 @@ def from_clause(self):
379381
@property
380382
def heading(self):
381383
return self._arg.heading.resolve()
384+
385+
def _repr_helper(self):
386+
return "%r" % self._arg

tests/test_fetch.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,11 @@ def test_copy(self):
125125
f2 = f.order_by('name')
126126
assert_true(f.behavior['order_by'] is None and len(f2.behavior['order_by']) == 1, 'Object was not copied')
127127

128+
def test_repr(self):
129+
"""Test string representation of fetch, returning table preview"""
130+
repr = self.subject.fetch.__repr__()
131+
n = len(repr.strip().split('\n'))
132+
limit = dj.config['display.limit']
133+
# 3 lines are used for headers (2) and summary statement (1)
134+
assert_true(n - 3 <= limit)
135+

0 commit comments

Comments
 (0)