diff options
author | Six <unknown> | 2011-05-19 22:46:48 -0400 |
---|---|---|
committer | Six <unknown> | 2011-05-19 22:46:48 -0400 |
commit | a825456d3a44c21975822e5b5e64e1d3093a3803 (patch) | |
tree | b4a027b48d715f15b9ea18de9ba1977960fca943 | |
parent | eed3f81529d7f0109b554031c9121cb5be1a2137 (diff) | |
download | d2-a825456d3a44c21975822e5b5e64e1d3093a3803.tar.bz2 d2-a825456d3a44c21975822e5b5e64e1d3093a3803.tar.xz d2-a825456d3a44c21975822e5b5e64e1d3093a3803.zip |
created new search to handle multiple plots. Mainly for the Empty occupant
-rw-r--r-- | lib/d2/app/adapters/detail.py | 164 | ||||
-rw-r--r-- | lib/d2/app/adapters/search.py | 190 | ||||
-rw-r--r-- | lib/d2/bin/d2_agi_db_setup.py | 45 |
3 files changed, 338 insertions, 61 deletions
diff --git a/lib/d2/app/adapters/detail.py b/lib/d2/app/adapters/detail.py index 7231faa..738230b 100644 --- a/lib/d2/app/adapters/detail.py +++ b/lib/d2/app/adapters/detail.py | |||
@@ -2,6 +2,9 @@ from d2.app.adapters import BaseAdapter | |||
2 | from datetime import datetime | 2 | from datetime import datetime |
3 | from d2.db import DetailType | 3 | from d2.db import DetailType |
4 | from d2.db import Detail | 4 | from d2.db import Detail |
5 | from d2.db import Forge | ||
6 | from d2.db import Plot | ||
7 | from d2.db import Occupant | ||
5 | from sqlalchemy import or_ | 8 | from sqlalchemy import or_ |
6 | from sqlalchemy import func | 9 | from sqlalchemy import func |
7 | from d2.config import Config | 10 | from d2.config import Config |
@@ -12,12 +15,16 @@ from whoosh.index import create_in | |||
12 | 15 | ||
13 | class DetailAdapter(BaseAdapter): | 16 | class DetailAdapter(BaseAdapter): |
14 | 17 | ||
15 | def __init__(self, db, log, static, detail, detail_type): | 18 | def __init__(self, db, log, static, detail, detail_type, forge, plot, |
19 | occupant): | ||
16 | self._db = db | 20 | self._db = db |
17 | self._log = log | 21 | self._log = log |
18 | self._static = static | 22 | self._static = static |
19 | self._detail = detail | 23 | self._detail = detail |
20 | self._detail_type = detail_type | 24 | self._detail_type = detail_type |
25 | self._forge = forge | ||
26 | self._plot = plot | ||
27 | self._occupant = occupant | ||
21 | self._search_schema_ = None | 28 | self._search_schema_ = None |
22 | self._search_index_ = None | 29 | self._search_index_ = None |
23 | self._label_detail_type_ids_ = None | 30 | self._label_detail_type_ids_ = None |
@@ -28,7 +35,8 @@ class DetailAdapter(BaseAdapter): | |||
28 | def load(cls, config=None, static=None): | 35 | def load(cls, config=None, static=None): |
29 | config = config or Config.load() | 36 | config = config or Config.load() |
30 | static = static or StaticData.load(config.db)() | 37 | static = static or StaticData.load(config.db)() |
31 | return cls(config.db, config.log, static, Detail, DetailType) | 38 | return cls(config.db, config.log, static, Detail, DetailType, Forge, |
39 | Plot, Occupant) | ||
32 | 40 | ||
33 | @property | 41 | @property |
34 | def _label_detail_type_ids(self): | 42 | def _label_detail_type_ids(self): |
@@ -45,7 +53,7 @@ class DetailAdapter(BaseAdapter): | |||
45 | def _multiple_value_labels(self): | 53 | def _multiple_value_labels(self): |
46 | if not self._multiple_value_labels_: | 54 | if not self._multiple_value_labels_: |
47 | self._multiple_value_labels_ = [ | 55 | self._multiple_value_labels_ = [ |
48 | self._static.detail_type.network_jack, | 56 | self._static.detail_type.network_jack, |
49 | ] | 57 | ] |
50 | return self._multiple_value_labels_ | 58 | return self._multiple_value_labels_ |
51 | 59 | ||
@@ -103,6 +111,8 @@ class DetailAdapter(BaseAdapter): | |||
103 | ).first() | 111 | ).first() |
104 | 112 | ||
105 | def _fetch_details(self, plot_id, occupant_id, date_start): | 113 | def _fetch_details(self, plot_id, occupant_id, date_start): |
114 | if not plot_id and not occupant_id: | ||
115 | return [] | ||
106 | date_start = self.build_date(date_start) | 116 | date_start = self.build_date(date_start) |
107 | obj = self._db.session.query(self._detail | 117 | obj = self._db.session.query(self._detail |
108 | ).filter(self._detail.plot_id==plot_id | 118 | ).filter(self._detail.plot_id==plot_id |
@@ -117,6 +127,7 @@ class DetailAdapter(BaseAdapter): | |||
117 | else: | 127 | else: |
118 | return obj | 128 | return obj |
119 | 129 | ||
130 | |||
120 | def insert_occupant_detail(self, occupant_id, detail_type_id, data, | 131 | def insert_occupant_detail(self, occupant_id, detail_type_id, data, |
121 | date_start=None, date_end=None): | 132 | date_start=None, date_end=None): |
122 | """Inserts detail data for an occupant | 133 | """Inserts detail data for an occupant |
@@ -221,6 +232,14 @@ class DetailAdapter(BaseAdapter): | |||
221 | results = self.fetch_all_plot_details(plot_id, date_start) | 232 | results = self.fetch_all_plot_details(plot_id, date_start) |
222 | return self._details_to_tuple(results) | 233 | return self._details_to_tuple(results) |
223 | 234 | ||
235 | def occupant_dict(self, occupant_id, date_start=None): | ||
236 | details = self.fetch_all_occupant_details(occupant_id, date_start) | ||
237 | return self.details_to_dict(details) | ||
238 | |||
239 | def plot_dict(self, plot_id, date_start=None): | ||
240 | details = self.fetch_all_plot_details(plot_id, date_start) | ||
241 | return self.details_to_dict(details) | ||
242 | |||
224 | def _label_from_details(self, details): | 243 | def _label_from_details(self, details): |
225 | if details: | 244 | if details: |
226 | out = [] | 245 | out = [] |
@@ -243,6 +262,56 @@ class DetailAdapter(BaseAdapter): | |||
243 | out.append(u'Unknown') | 262 | out.append(u'Unknown') |
244 | return u' '.join(out) | 263 | return u' '.join(out) |
245 | 264 | ||
265 | def details_to_dict(self, details): | ||
266 | out = {} | ||
267 | if details: | ||
268 | out[u'label'] = self._label_from_details(details) | ||
269 | out[u'plot_id'] = details[0].plot_id | ||
270 | out[u'occupant_id'] = details[0].occupant_id | ||
271 | for detail in details: | ||
272 | if (detail.detail_type_id not in self._label_detail_type_ids | ||
273 | and detail.data): | ||
274 | name = detail.detail_type.name | ||
275 | key = name.lower().strip().replace(u' ', u'_') | ||
276 | if detail.detail_type_id in self._multiple_value_labels: | ||
277 | if key in out: | ||
278 | name = out[key][u'name'].strip() | ||
279 | if not name.endswith(u's'): | ||
280 | name = u"{0}s".format(name) | ||
281 | out[key][u'name'] = name | ||
282 | data = out[key][u'data'] | ||
283 | data.append(detail.data) | ||
284 | out[key][u'data'] = data | ||
285 | else: | ||
286 | out[key] = {} | ||
287 | out[key][u'name'] = name | ||
288 | out[key][u'data'] = [detail.data] | ||
289 | else: | ||
290 | out[key] = {} | ||
291 | out[key][u'name'] = name | ||
292 | out[key][u'data'] = detail.data | ||
293 | return out | ||
294 | |||
295 | def _details_dict_to_tuple(self, details): | ||
296 | """Takes a details dictionary and turnes it into a named tuple | ||
297 | """ | ||
298 | if details: | ||
299 | keys = [u'label', u'plot_id', u'occupant_id'] | ||
300 | key_hold = [] | ||
301 | vals = [] | ||
302 | for key in details.keys(): | ||
303 | if key not in keys and key not in key_hold: | ||
304 | key_hold.append(key) | ||
305 | key_hold.sort() | ||
306 | keys = keys + key_hold | ||
307 | for key in keys: | ||
308 | val = details[key] | ||
309 | if isinstance(val, dict): | ||
310 | val = self._make(val[u'name'], val[u'data']) | ||
311 | vals.append(val) | ||
312 | make = namedtuple('details', keys) | ||
313 | return make(*vals) | ||
314 | |||
246 | def _details_to_tuple(self, details): | 315 | def _details_to_tuple(self, details): |
247 | if details: | 316 | if details: |
248 | hold = {} | 317 | hold = {} |
@@ -250,11 +319,11 @@ class DetailAdapter(BaseAdapter): | |||
250 | vals = [] | 319 | vals = [] |
251 | hold[u'label'] = self._label_from_details(details) | 320 | hold[u'label'] = self._label_from_details(details) |
252 | if details[0].plot_id: | 321 | if details[0].plot_id: |
253 | hold[u'id'] = details[0].plot_id | 322 | hold[u'plot_id'] = details[0].plot_id |
254 | hold[u'id_type'] = u'plot' | 323 | hold[u'occupant_id'] = None |
255 | else: | 324 | else: |
256 | hold[u'id'] = details[0].occupant_id | 325 | hold[u'plot_id'] = None |
257 | hold[u'id_type'] = u'occupant' | 326 | hold[u'occupant_id'] = details[0].occupant_id |
258 | for detail in details: | 327 | for detail in details: |
259 | if (detail.detail_type_id not in self._label_detail_type_ids | 328 | if (detail.detail_type_id not in self._label_detail_type_ids |
260 | and detail.data): | 329 | and detail.data): |
@@ -278,3 +347,84 @@ class DetailAdapter(BaseAdapter): | |||
278 | vals.append(hold[key]) | 347 | vals.append(hold[key]) |
279 | make = namedtuple('details', keys) | 348 | make = namedtuple('details', keys) |
280 | return make(*vals) | 349 | return make(*vals) |
350 | |||
351 | def details(self, plot_id=None, occupant_id=None): | ||
352 | """ Returns a named tuple with complete details. | ||
353 | """ | ||
354 | plot_id, occupant_id = self._validate(plot_id, occupant_id) | ||
355 | plot = self.details_to_dict(self.fetch_all_plot_details(plot_id)) | ||
356 | occupant = self.details_to_dict(self.fetch_all_occupant_details( | ||
357 | occupant_id)) | ||
358 | |||
359 | if plot and occupant: | ||
360 | occupant[u'plot_id'] = plot[u'plot_id'] | ||
361 | occupant[u'plot'] = { | ||
362 | u'name': u'Plot', | ||
363 | u'data': plot['label'] | ||
364 | } | ||
365 | del plot[u'plot_id'] | ||
366 | del plot[u'occupant_id'] | ||
367 | del plot[u'label'] | ||
368 | |||
369 | for key, val in plot.items(): | ||
370 | occupant[key] = val | ||
371 | return self._details_dict_to_tuple(occupant) | ||
372 | |||
373 | if plot: | ||
374 | return self._details_dict_to_tuple(plot) | ||
375 | |||
376 | if occupant: | ||
377 | return self._details_dict_to_tuple(occupant) | ||
378 | |||
379 | def _validate(self, plot_id, occupant_id, start_date=None): | ||
380 | """Validates that the given plot_id and occupant_id | ||
381 | are valid. Also checks forge | ||
382 | """ | ||
383 | if not self._is_valid_plot(plot_id): | ||
384 | plot_id = None | ||
385 | if not self._is_valid_occupant(occupant_id): | ||
386 | occupant_id = None | ||
387 | if plot_id and occupant_id: | ||
388 | if not self._is_valid_forge(plot_id, occupant_id, start_date): | ||
389 | plot_id = None | ||
390 | return plot_id, occupant_id | ||
391 | |||
392 | def _is_valid_plot(self, plot_id): | ||
393 | """Validates that the given plot_id actually exists | ||
394 | """ | ||
395 | if plot_id: | ||
396 | obj = self._db.session.query(self._plot | ||
397 | ).filter(self._plot.id==plot_id | ||
398 | ).first() | ||
399 | if obj: | ||
400 | return True | ||
401 | return False | ||
402 | |||
403 | def _is_valid_occupant(self, occupant_id): | ||
404 | """Validates that the given occupant_id actually exists | ||
405 | """ | ||
406 | if occupant_id: | ||
407 | obj = self._db.session.query(self._occupant | ||
408 | ).filter(self._occupant.id==occupant_id | ||
409 | ).first() | ||
410 | if obj: | ||
411 | return True | ||
412 | return False | ||
413 | |||
414 | def _is_valid_forge(self, plot_id, occupant_id, date_start=None): | ||
415 | """Validates that the given plot_id and occupant_id are related | ||
416 | in the forge table. | ||
417 | """ | ||
418 | date_start = self.build_date(date_start) | ||
419 | obj = self._db.session.query(self._forge | ||
420 | ).filter(self._forge.plot_id==plot_id | ||
421 | ).filter(self._forge.occupant_id==occupant_id | ||
422 | ).filter(self._forge.date_override==None | ||
423 | ).filter(self._forge.date_start<=date_start | ||
424 | ).filter(or_(self._forge.date_end>date_start, | ||
425 | self._forge.date_end==None) | ||
426 | ).first() | ||
427 | if obj: | ||
428 | return True | ||
429 | else: | ||
430 | return False | ||
diff --git a/lib/d2/app/adapters/search.py b/lib/d2/app/adapters/search.py index 92d0ee5..693cdda 100644 --- a/lib/d2/app/adapters/search.py +++ b/lib/d2/app/adapters/search.py | |||
@@ -13,16 +13,20 @@ from whoosh.index import create_in | |||
13 | from whoosh.index import open_dir | 13 | from whoosh.index import open_dir |
14 | from whoosh.qparser import QueryParser | 14 | from whoosh.qparser import QueryParser |
15 | from whoosh.spelling import SpellChecker | 15 | from whoosh.spelling import SpellChecker |
16 | from d2.app.adapters.forge import ForgeAdapter | ||
16 | import os | 17 | import os |
17 | import stat | 18 | import stat |
18 | import re | 19 | import re |
20 | from copy import deepcopy | ||
21 | from collections import namedtuple | ||
19 | 22 | ||
20 | class SearchAdapter(BaseAdapter): | 23 | class SearchAdapter(BaseAdapter): |
21 | 24 | ||
22 | PERM_DIR = stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR | 25 | PERM_DIR = stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR |
26 | SEARCH_ARGS = ['label', 'description', 'plot_id', 'occupant_id'] | ||
23 | 27 | ||
24 | def __init__(self, db, log, index_directory, static, detail, detail_type, | 28 | def __init__(self, db, log, index_directory, static, detail, detail_type, |
25 | detail_adapter): | 29 | detail_adapter, forge_adapter): |
26 | self._db = db | 30 | self._db = db |
27 | self._log = log | 31 | self._log = log |
28 | self._index_directory = index_directory | 32 | self._index_directory = index_directory |
@@ -30,18 +34,22 @@ class SearchAdapter(BaseAdapter): | |||
30 | self._detail = detail | 34 | self._detail = detail |
31 | self._detail_type = detail_type | 35 | self._detail_type = detail_type |
32 | self._detail_adapter = detail_adapter | 36 | self._detail_adapter = detail_adapter |
37 | self._forge_adapter = forge_adapter | ||
33 | self._label_detail_type_ids_ = None | 38 | self._label_detail_type_ids_ = None |
34 | self._search_schema_ = None | 39 | self._search_schema_ = None |
35 | self._index_ = None | 40 | self._index_ = None |
36 | self._index_directory_ = None | 41 | self._index_directory_ = None |
42 | self._make_search_result = namedtuple('Result', self.SEARCH_ARGS) | ||
37 | 43 | ||
38 | @classmethod | 44 | @classmethod |
39 | def load(cls, config=None, static=None, detail_adapter=None): | 45 | def load(cls, config=None, static=None, detail_adapter=None, |
46 | forge_adapter=None): | ||
40 | config = config or Config.load() | 47 | config = config or Config.load() |
41 | static = static or StaticData.load(config.db)() | 48 | static = static or StaticData.load(config.db)() |
42 | detail_adapter = detail_adapter or DetailAdapter.load(config, static) | 49 | detail_adapter = detail_adapter or DetailAdapter.load(config, static) |
50 | forge_adapter = forge_adapter or ForgeAdapter.load(config, static) | ||
43 | return cls(config.db, config.log, config.index_directory, static, | 51 | return cls(config.db, config.log, config.index_directory, static, |
44 | Detail, DetailType, detail_adapter) | 52 | Detail, DetailType, detail_adapter, forge_adapter) |
45 | 53 | ||
46 | @property | 54 | @property |
47 | def _label_detail_type_ids(self): | 55 | def _label_detail_type_ids(self): |
@@ -58,8 +66,9 @@ class SearchAdapter(BaseAdapter): | |||
58 | if not self._search_schema_: | 66 | if not self._search_schema_: |
59 | self._search_schema_ = Schema( | 67 | self._search_schema_ = Schema( |
60 | label=TEXT(stored=True), | 68 | label=TEXT(stored=True), |
61 | id=NUMERIC(stored=True), | 69 | description=TEXT(stored=True), |
62 | id_type=ID(stored=True), | 70 | plot_id=NUMERIC(stored=True), |
71 | occupant_id=NUMERIC(stored=True), | ||
63 | context=TEXT) | 72 | context=TEXT) |
64 | return self._search_schema_ | 73 | return self._search_schema_ |
65 | 74 | ||
@@ -81,7 +90,9 @@ class SearchAdapter(BaseAdapter): | |||
81 | def build_index(self): | 90 | def build_index(self): |
82 | index = create_in(self.index_directory, self.search_schema) | 91 | index = create_in(self.index_directory, self.search_schema) |
83 | writer = index.writer() | 92 | writer = index.writer() |
84 | results = self.search_index_data() | 93 | results = self._search_index_data() |
94 | results = self._add_descriptions(results) | ||
95 | results = self._build_search_dictionaries(results) | ||
85 | for row in results: | 96 | for row in results: |
86 | writer.add_document(**row) | 97 | writer.add_document(**row) |
87 | writer.commit() | 98 | writer.commit() |
@@ -92,8 +103,8 @@ class SearchAdapter(BaseAdapter): | |||
92 | speller = SpellChecker(ix.storage) | 103 | speller = SpellChecker(ix.storage) |
93 | speller.add_field(ix, "context") | 104 | speller.add_field(ix, "context") |
94 | 105 | ||
95 | def search_index_data(self, date_start=None): | 106 | def _search_index_data(self, date_start=None): |
96 | hold = {u'plot':{}, u'occupant':{}} | 107 | hold = {} |
97 | data = [] | 108 | data = [] |
98 | date_start = self.build_date(date_start) | 109 | date_start = self.build_date(date_start) |
99 | results = self._db.session.query(self._detail | 110 | results = self._db.session.query(self._detail |
@@ -103,45 +114,137 @@ class SearchAdapter(BaseAdapter): | |||
103 | self._detail.date_end==None) | 114 | self._detail.date_end==None) |
104 | ).all() | 115 | ).all() |
105 | for row in results: | 116 | for row in results: |
106 | if row.plot_id: | 117 | key = (row.plot_id, row.occupant_id) |
107 | if row.plot_id not in hold[u'plot']: | 118 | if key not in hold: |
108 | hold[u'plot'][row.plot_id] = [] | 119 | hold[key] = [] |
109 | hold[u'plot'][row.plot_id].append(row) | 120 | hold[key].append(row) |
110 | else: | 121 | |
111 | if row.occupant_id not in hold[u'occupant']: | 122 | for key, details in hold.items(): |
112 | hold[u'occupant'][row.occupant_id] = [] | 123 | data.append(self._detail_adapter.details_to_dict(details)) |
113 | hold[u'occupant'][row.occupant_id].append(row) | 124 | |
114 | for key, details in hold[u'plot'].items(): | ||
115 | data.append(self._details_to_search_dictionary(details)) | ||
116 | for key, details in hold[u'occupant'].items(): | ||
117 | data.append(self._details_to_search_dictionary(details)) | ||
118 | return data | 125 | return data |
119 | 126 | ||
127 | def _add_descriptions(self, results): | ||
128 | out = [] | ||
129 | for details in results: | ||
130 | if details[u'occupant_id']: | ||
131 | plots = self._get_plots(details[u'occupant_id']) | ||
132 | if plots: | ||
133 | for plot_id in plots: | ||
134 | details_ = deepcopy(details) | ||
135 | details_[u'plot_id'] = plot_id | ||
136 | details_[u'description'] = \ | ||
137 | self._build_occupant_decription_with_plot( | ||
138 | details_) | ||
139 | out.append(details_) | ||
140 | else: | ||
141 | details[u'description'] = \ | ||
142 | self._build_occupant_decription(details) | ||
143 | out.append(details) | ||
144 | |||
145 | else: | ||
146 | occupants = self._get_occupants(details[u'plot_id']) | ||
147 | details[u'description'] = \ | ||
148 | self._build_plot_description(details, occupants) | ||
149 | out.append(details) | ||
150 | return out | ||
151 | |||
152 | def _get_plots(self, occupant_id, date_start=None): | ||
153 | """Returns a set of plot_ids from forge with the given occupant_id | ||
154 | """ | ||
155 | out = set() | ||
156 | forges = self._forge_adapter.get_forge_by_occupant_id(occupant_id, | ||
157 | date_start) | ||
158 | for forge in forges: | ||
159 | if forge.plot_id: | ||
160 | out.add(forge.plot_id) | ||
161 | return out | ||
162 | |||
163 | def _get_occupants(self, plot_id, date_start=None): | ||
164 | """Returns a set of occupant_ids from forge with the given plot_id | ||
165 | """ | ||
166 | out = set() | ||
167 | forges = self._forge_adapter.get_forge_by_plot_id(plot_id, date_start) | ||
168 | for forge in forges: | ||
169 | if forge.occupant_id: | ||
170 | out.add(forge.occupant_id) | ||
171 | return out | ||
172 | |||
173 | def _build_occupant_decription_with_plot(self, details): | ||
174 | out = [] | ||
175 | plot_dict = self._detail_adapter.plot_dict(details[u'plot_id']) | ||
176 | out.append(u'Plot: {0}'.format(plot_dict[u'label'])) | ||
177 | if u'title' in details: | ||
178 | out.append(details[u'title'][u'data']) | ||
179 | if u'department' in details: | ||
180 | out.append(details[u'department'][u'data']) | ||
181 | return u' '.join(out) | ||
182 | |||
183 | def _build_occupant_decription(self, details): | ||
184 | out = [] | ||
185 | if u'title' in details: | ||
186 | out.append(details[u'title'][u'data']) | ||
187 | if u'department' in details: | ||
188 | out.append(details[u'department'][u'data']) | ||
189 | return u' '.join(out) | ||
190 | |||
191 | def _build_plot_description(self, details, occupants): | ||
192 | out = [] | ||
193 | for occupant_id in occupants: | ||
194 | occupant = self._detail_adapter.occupant_dict(occupant_id) | ||
195 | out.append(occupant[u'label']) | ||
196 | return u', '.join(out) | ||
197 | |||
198 | |||
120 | def _split_label(self, data): | 199 | def _split_label(self, data): |
121 | name_pattern = re.compile("([A-Z]\w*)([A-Z].*)") | 200 | name_pattern = re.compile("([A-Z]\w*)([A-Z].*)") |
122 | return re.sub(name_pattern, r"\1" + " " + r"\2", data) | 201 | return re.sub(name_pattern, r"\1" + " " + r"\2", data) |
123 | 202 | ||
203 | def _label_to_initials(self, data): | ||
204 | out = [] | ||
205 | data = data.split(u' ') | ||
206 | for word in data: | ||
207 | out.append(word[0]) | ||
208 | if len(out) >= 2: | ||
209 | break | ||
210 | if len(out) == 2: | ||
211 | out = u''.join(out) | ||
212 | return out.upper() | ||
213 | |||
214 | |||
215 | def _build_search_dictionaries(self, results): | ||
216 | out = [] | ||
217 | for details in results: | ||
218 | out.append(self._details_to_search_dictionary(details)) | ||
219 | return out | ||
220 | |||
124 | def _details_to_search_dictionary(self, details): | 221 | def _details_to_search_dictionary(self, details): |
222 | out = {} | ||
125 | if details: | 223 | if details: |
126 | out = {} | 224 | context = [details[u'label']] |
127 | label = self._detail_adapter._label_from_details(details) | 225 | out[u'label'] = details[u'label'] |
128 | out['label'] = label | 226 | out[u'plot_id'] = details[u'plot_id'] |
129 | alt_label = self._split_label(label) | 227 | out[u'occupant_id'] = details[u'occupant_id'] |
130 | hold = [label] | 228 | out[u'description'] = details[u'description'] |
131 | if alt_label != label: | 229 | if details[u'plot_id']: |
132 | hold.append(alt_label) | 230 | if u'empty' in out['description'].lower(): |
133 | 231 | context.append(u'Empty') | |
134 | if details[0].plot_id: | ||
135 | out['id'] = details[0].plot_id | ||
136 | out['id_type'] = u'plot' | ||
137 | else: | 232 | else: |
138 | out['id'] = details[0].occupant_id | 233 | alt_label = self._split_label(out[u'label']) |
139 | out['id_type'] = u'occupant' | 234 | if alt_label != out[u'label']: |
140 | for detail in details: | 235 | context.append(alt_label) |
141 | if (detail.detail_type_id not in self._label_detail_type_ids | 236 | initials = self._label_to_initials(out[u'label']) |
142 | and detail.data): | 237 | if initials: |
143 | hold.append(detail.data) | 238 | context.append(initials) |
144 | out['context'] = u' '.join(hold) | 239 | |
240 | for key, detail in details.items(): | ||
241 | if isinstance(detail, dict): | ||
242 | if isinstance(detail[u'data'], list): | ||
243 | for data in detail[u'data']: | ||
244 | context.append(data) | ||
245 | else: | ||
246 | context.append(detail[u'data']) | ||
247 | out['context'] = u' '.join(context) | ||
145 | return out | 248 | return out |
146 | 249 | ||
147 | def _all_terms(self, user_query): | 250 | def _all_terms(self, user_query): |
@@ -191,9 +294,10 @@ class SearchAdapter(BaseAdapter): | |||
191 | myquery = query.parse(user_query_string) | 294 | myquery = query.parse(user_query_string) |
192 | results = searcher.search(myquery) | 295 | results = searcher.search(myquery) |
193 | for row in results[0:len(results)]: | 296 | for row in results[0:len(results)]: |
194 | if row[u'id_type'] == 'plot': | 297 | out.append(self._make_search_result( |
195 | out.append(self._detail_adapter.plot_details(row[u'id'])) | 298 | row[u'label'], |
196 | else: | 299 | row[u'description'], |
197 | out.append(self._detail_adapter.occupant_details( | 300 | row[u'plot_id'], |
198 | row[u'id'])) | 301 | row[u'occupant_id'] |
302 | )) | ||
199 | return out | 303 | return out |
diff --git a/lib/d2/bin/d2_agi_db_setup.py b/lib/d2/bin/d2_agi_db_setup.py index f9bdf96..4cf3602 100644 --- a/lib/d2/bin/d2_agi_db_setup.py +++ b/lib/d2/bin/d2_agi_db_setup.py | |||
@@ -1,22 +1,45 @@ | |||
1 | import argparse | 1 | import argparse |
2 | from d2.config import Config as D2Config | 2 | from d2.config import Config |
3 | from d2.app.model.static import StaticData | ||
3 | from d2.db import Base | 4 | from d2.db import Base |
4 | from d2.db import Location | 5 | from d2.db import Location |
5 | from d2.db import Map | 6 | from d2.db import Map |
6 | 7 | from d2.db import Room | |
7 | class Config(object): | 8 | from d2.db import Floor |
8 | 9 | ||
9 | DESCRIPTION = """ | 10 | class Args(object): |
10 | Populate static tables that are AGI specific. | 11 | |
11 | The database connection information is read from the d2 configuration | 12 | DATA = { |
12 | file: ~/.d2/config | 13 | u'Cleveland': { |
13 | """ | 14 | u'floors': [u'1', u'2', u'3'], |
14 | def __init__(self): | 15 | u'rooms': [u'a', u'b', u'c'] |
16 | }, | ||
17 | u'Bucharest': { | ||
18 | u'floors': [u'1', u'2', u'3', u'4', u'5', u'6', u'7'] | ||
19 | } | ||
20 | } | ||
21 | |||
22 | DESCRIPTION = "Populate static tables that are AGI specific. The "\ | ||
23 | "database connection information is read from the d2 "\ | ||
24 | "configuration file: ~/.d2/config" | ||
25 | |||
26 | def __init__(self, config, static): | ||
27 | self._config = config | ||
28 | self._static = static | ||
15 | self._parser = argparse.ArgumentParser(description=self.DESCRIPTION) | 29 | self._parser = argparse.ArgumentParser(description=self.DESCRIPTION) |
16 | 30 | ||
31 | @classmethod | ||
32 | def load(cls, config=None): | ||
33 | config = config or Config.load() | ||
34 | static = StaticData.load(config.db)() | ||
35 | obj = cls(config, static) | ||
36 | return obj() | ||
37 | |||
17 | def __call__(self): | 38 | def __call__(self): |
18 | args = self._parser.parse_args() | 39 | args = self._parser.parse_args() |
19 | return D2Config.load() | 40 | args.config = self._config |
41 | args.static = self._static | ||
42 | return args | ||
20 | 43 | ||
21 | 44 | ||
22 | class PopulateLocation(object): | 45 | class PopulateLocation(object): |