|
9 | 9 | from .semantics import MarcSearchSemantics
|
10 | 10 |
|
11 | 11 |
|
12 |
| -# memoize compiling of strings into AST using some searcher |
13 | 12 | class MarcSearchParser(MarcSpecParser):
|
14 | 13 | def __init__(self, *args, **kwargs):
|
15 | 14 | kwargs.update({
|
16 | 15 | 'whitespace': '',
|
17 | 16 | 'semantics': MarcSearchSemantics()
|
18 | 17 | })
|
19 | 18 | super().__init__(*args, **kwargs)
|
| 19 | + self.memoized = dict() |
| 20 | + |
| 21 | + |
| 22 | +# memoize compiling of strings into specs |
| 23 | +class MarcSearch: |
| 24 | + """ |
| 25 | + Memoizes compiled specifications to offset |
| 26 | + cost of compiling each again and again. |
| 27 | +
|
| 28 | + Can be used over multiple records and |
| 29 | + multiple specs. |
| 30 | + """ |
| 31 | + def __init__(self): |
| 32 | + self.parser = MarcSearchParser() |
| 33 | + self.specs = dict() |
| 34 | + |
| 35 | + def parse(self, spec): |
| 36 | + compiled_spec = self.specs.get(spec) |
| 37 | + if compiled_spec is None: |
| 38 | + self.specs[spec] = compiled_spec = self.parser.parse(spec) |
| 39 | + return compiled_spec |
| 40 | + |
| 41 | + def search(self, spec, record, **kwargs): |
| 42 | + compiled_spec = self.parse(spec) |
| 43 | + return compiled_spec.search(record, **kwargs) |
20 | 44 |
|
21 | 45 |
|
22 | 46 | def marc_search(marcspec, stream, field_delimiter=':', subfield_delimiter=''):
|
23 |
| - parser = MarcSearchParser() |
24 |
| - spec = parser.parse(marcspec) |
| 47 | + searcher = MarcSearch() |
| 48 | + searcher.parse(marcspec) |
25 | 49 |
|
26 | 50 | if stream.name.endswith('.xml'):
|
27 | 51 | generator = parse_xml_to_array(stream)
|
28 | 52 | else:
|
29 | 53 | generator = MARCReader(stream)
|
30 | 54 | for record in generator:
|
31 |
| - result = spec.search( |
32 |
| - record, |
| 55 | + result = searcher.search( |
| 56 | + marcspec, record, |
33 | 57 | field_delimiter=field_delimiter,
|
34 | 58 | subfield_delimiter=subfield_delimiter
|
35 | 59 | )
|
|
0 commit comments