-
Notifications
You must be signed in to change notification settings - Fork 2
/
display.py
195 lines (170 loc) · 5.93 KB
/
display.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
SQL results display functions
"""
import re
from datetime import datetime, timedelta
import pytz
from . import localzone
#
# specific functions for display datas
#
def display_keywords(value):
''' remove None from keywords '''
if value is None:
value = ''
return value
def display_aperture(value):
''' format aperture in F value '''
return 'F%.1f' % 2**((float(value)/2))
def display_iso(value):
''' format iso value '''
return '%.0f' % value
def display_speed(value):
''' format shutter speed value '''
value = 2**(float(value))
if value > 1:
return '1/%.0f' % value
return '%.0f' % (1/value)
def display_date(value):
''' format date : remove sub-seconds '''
return value[:19]
def display_lrtimestamp(value):
''' format LR timestamp (2001 based) '''
utc = pytz.utc.localize(datetime(2001, 1, 1, 0, 0, 0) + timedelta(seconds=float(value)))
return utc.astimezone(localzone).strftime("%Y-%m-%d %H:%M:%S")
#
# default columns width and display functions
#
DEFAULT_SPEC = ('%6s', None)
DEFAULT_SPECS = {
'name' : ('%-20s', None),
'name=full' : ('%-60s', None),
'name=base' : ('%-20s', None),
'name=basext' : ('%-25s', None),
'id' : ('%8s', None),
'uuid' : ('%38s', None),
'rating' : ('%1s', None),
'colorlabel': ('%8s', None),
'datemod' : ('%19s', display_lrtimestamp),
'datehist' : ('%19s', display_lrtimestamp),
'datecapt' : ('%19s', display_date),
'modcount' : ('%2s', None),
'master' : ('%10s', None),
'vname' : ('%10s', None),
'stackpos' : ('%3s', None),
'keywords' : ('%-30s', display_keywords),
'collections' : ('%-30s', None),
'camera' : ('%-15s', None),
'lens' : ('%-25s', None),
'iso' : ('%5s', display_iso),
'focal' : ('%6s', None),
'aperture' : ('%5s', display_aperture),
'speed' : ('%6s', display_speed),
'creator' : ('%-18s', None),
'caption' : ('%-30s', None),
'dims' : ('%-10s', None),
'pubcollection' : ('%30s', None),
'pubname' : ('%30s', None),
'pubtime' : ('%19s', display_lrtimestamp),
'latitude' : ('%-18s', None),
'longitude' : ('%-18s', None),
}
DEFAULT_SEPARATOR = ' | '
def prepare_display_columns(columns, widths):
'''
Prepare columns to display : set width and specific display functions
- columns : ([str]) columns names as defined by LRSelectPhotos
- widths : ([str]) width of each column, comma separated (ex: "15,-50")
'''
column_spec = {}
for num_col, name in enumerate(columns):
name = name.strip()
if not name:
continue
if name in DEFAULT_SPECS:
width, func = DEFAULT_SPECS[name]
else:
width, func = DEFAULT_SPEC
# chance to change widths from outside
if num_col < len(widths):
width = '%%%ss' % widths[num_col].strip()
column_spec[num_col] = (name, width, func)
return column_spec
def display_results(rows, columns, **kwargs):
'''
Display SQL results
- rows : SQL colummns to print
- columns : column names string selected
- kwargs :
* max_lines : max lines to display
* header : display header (columns names)
* indent : number of indentation space on each line
* widths : widths of columns
* separator : characters separator between columns
* raw_print : print raw value (for columns aperture, shutter speed, ido, dates)
'''
if not rows:
if kwargs.get('header', True):
print(' * None data result')
return
if isinstance(columns, str):
columns = [a.strip() for a in columns.split(',')]
widths = kwargs.get('widths', [])
if widths is None:
widths = []
if isinstance(widths, str):
widths = [a.strip() for a in widths.split(',')]
indent = kwargs.get('indent', 4)
separator = kwargs.get('separator', DEFAULT_SEPARATOR)
wanted_lines = kwargs.get('max_lines', 0)
if wanted_lines == 0 or wanted_lines >= len(rows):
max_lines = len(rows)
if kwargs.get('header', True):
print(' * Photo results (%s photos) :' % (len(rows)))
else:
max_lines = wanted_lines
if kwargs.get('header', True):
print(' * Photo results (first %s photos on %s) :' % (wanted_lines, len(rows)))
column_spec = prepare_display_columns(columns, widths)
# basic check : detect if suffisant column
for i in range(len(rows[0])):
if i < len(column_spec):
continue
column_spec[i] = (f'column{i}', DEFAULT_SPEC[0], DEFAULT_SPEC[1])
# display header
if kwargs.get('header', True):
total_width = 0
line = []
for num_col in range(0, len(column_spec)):
name, width, _ = column_spec[num_col]
match = re.search(r'(\d+)s', width)
if match:
val_width = int(match.group(1))
else:
val_width = 8
total_width += val_width
name = name[:val_width]
line.append(width % name)
print(indent * ' ', separator.join(line), sep='')
print(indent * ' ', (total_width + (len(column_spec) - 1) * len(separator)) * '=', sep='')
# display datas
for num in range(0, max_lines):
if num == len(rows):
break
line = []
for num_col, value in enumerate(rows[num]):
try:
_, width, func_format = column_spec[num_col]
except KeyError:
# invisible column (ex: criteria width/heightCropped)
continue
if not kwargs.get('raw_print', False):
if value is None:
value = ''
elif func_format:
value = func_format(value)
line.append(width % value)
print(indent * ' ', separator.join(line), sep='')
print()