Skip to content

Commit 0acb9a0

Browse files
committed
chore(ruff): cleanup indexer_* code after ruff analysis.
indexer_common.py: use 'for x, y in adict.items() rather than 'for x in adict' and later reference 'adict[x]'. indexer_dbm.py: use 'with open() ... as fd: <stuff>' rather than 'fd = open()<stuff>close()'. 4 instances. whitespace fixes around operators use 'for x, y in adict.items() rather than 'for x in adict' and later reference 'adict[x]'. replace 'return 0' with 'return' as ruff was reporting function didn't have explicit return at end when internal return returned a not None value. AFICT load_index's return value is never checked. replace 'for _key, value in x.items()' with 'for value in x.values()'. _key is never used. indexer_postgresql_fts.py: import sorting. symbolic string for server version needed for FTS support. rename variable id. remove unneeded flow control (else after raise) indexer_rdbms.py: import sorting. rename variable id 2 places. add variable 'a = self.db.arg' to make scanning SQL code that uses % to insert placeholders easier. Also reduces dereferencing. replaced 'tuple([list comprehension])' with tuple(same comprehension but is a generator) indexer_sqlite_fts.py: import sorting. rename variable id. remove unneeded flow control (else after raise). indexer_whoosh.py: import sorting. remove qparser from whoosh import. Unused andnot needed until we implement using whoosh query language in roundup searches. indexer_xapian.py: import sorting. rewrite loop that appended to a list as a list comprehension
1 parent 02e10d0 commit 0acb9a0

8 files changed

Lines changed: 71 additions & 74 deletions

File tree

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ Fixed:
8080
- fix back_anydm::Class::get() method to properly return default value
8181
if requested property is set to None. This should fix missing text
8282
indexing for the anydbm backend. (John Rouillard)
83+
- ruff driven cleanups/refactor of indexer* files. (John Rouillard)
8384

8485
Features:
8586

roundup/backends/indexer_common.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,15 +100,15 @@ def search(self, search_terms, klass, ignore=None):
100100
nodeids[resid] = {}
101101
node_dict = nodeids[resid]
102102
# now figure out where it came from
103-
for linkprop in propspec:
103+
for linkprop, linkprop_value in propspec.items():
104104
v = klass.get(resid, linkprop)
105105
# the link might be a Link so deal with a single result or None
106106
if isinstance(propdefs[linkprop], hyperdb.Link):
107107
if v is None:
108108
continue
109109
v = [v]
110110
for nodeid in v:
111-
if nodeid in propspec[linkprop]:
111+
if nodeid in linkprop_value:
112112
# OK, this node[propname] has a winner
113113
if linkprop not in node_dict:
114114
node_dict[linkprop] = [nodeid]

roundup/backends/indexer_dbm.py

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,8 @@ def __init__(self, db):
5757
# for now the file itself is a flag
5858
self.force_reindex()
5959
elif os.path.exists(version):
60-
fd = open(version)
61-
version = fd.read()
62-
fd.close()
60+
with open(version) as fd:
61+
version = fd.read()
6362
# check the value and reindex if it's not the latest
6463
if version.strip() != '1':
6564
self.force_reindex()
@@ -70,10 +69,9 @@ def force_reindex(self):
7069
if os.path.exists(self.indexdb_path):
7170
shutil.rmtree(self.indexdb_path)
7271
os.makedirs(self.indexdb_path)
73-
os.chmod(self.indexdb_path, 0o775) # nosec - allow group write
74-
fd = open(os.path.join(self.indexdb_path, 'version'), 'w')
75-
fd.write('1\n')
76-
fd.close()
72+
os.chmod(self.indexdb_path, 0o775) # noqa: S103 allow group write
73+
with open(os.path.join(self.indexdb_path, 'version'), 'w') as fd:
74+
fd.write('1\n')
7775
self.reindex = 1
7876
self.changed = 1
7977

@@ -98,7 +96,7 @@ def add_text(self, identifier, text, mime_type='text/plain'):
9896

9997
# Find new file index, and assign it to identifier
10098
# (_TOP uses trick of negative to avoid conflict with file index)
101-
self.files['_TOP'] = (self.files['_TOP'][0]-1, None)
99+
self.files['_TOP'] = (self.files['_TOP'][0] - 1, None)
102100
file_index = abs(self.files['_TOP'][0])
103101
self.files[identifier] = (file_index, len(words))
104102
self.fileids[file_index] = identifier
@@ -109,12 +107,12 @@ def add_text(self, identifier, text, mime_type='text/plain'):
109107
if self.is_stopword(word):
110108
continue
111109
if word in filedict:
112-
filedict[word] = filedict[word]+1
110+
filedict[word] = filedict[word] + 1
113111
else:
114112
filedict[word] = 1
115113

116114
# now add to the totals
117-
for word in filedict:
115+
for word, word_dict in filedict.items():
118116
# each word has a dict of {identifier: count}
119117
if word in self.words:
120118
entry = self.words[word]
@@ -124,7 +122,7 @@ def add_text(self, identifier, text, mime_type='text/plain'):
124122
self.words[word] = entry
125123

126124
# make a reference to the file for this word
127-
entry[file_index] = filedict[word]
125+
entry[file_index] = word_dict
128126

129127
# save needed
130128
self.changed = 1
@@ -165,7 +163,7 @@ def find(self, wordlist):
165163
if not self.minlength <= len(word) <= self.maxlength:
166164
# word outside the bounds of what we index - ignore
167165
continue
168-
word = word.upper()
166+
word = word.upper() # noqa: PLW2901 # set loop var is ok
169167
if self.is_stopword(word):
170168
continue
171169
entry = self.words.get(word) # For each word, get index
@@ -192,7 +190,7 @@ def find(self, wordlist):
192190
def load_index(self, reload=0, wordlist=None):
193191
# Unless reload is indicated, do not load twice
194192
if self.index_loaded() and not reload:
195-
return 0
193+
return
196194

197195
# Ok, now let's actually load it
198196
db = {'WORDS': {}, 'FILES': {'_TOP': (0, None)}, 'FILEIDS': {}}
@@ -211,13 +209,13 @@ def load_index(self, reload=0, wordlist=None):
211209
# Load the segments
212210
for segment in segments:
213211
try:
214-
f = open(self.indexdb + segment, 'rb')
215-
except IOError as error:
212+
with open(self.indexdb + segment, 'rb') as f:
213+
pickle_str = zlib.decompress(f.read())
214+
except IOError as error: # noqa: PERF203 allow except inside loop
216215
# probably just nonexistent segment index file
217216
if error.errno != errno.ENOENT: raise # noqa: E701
218217
else:
219-
pickle_str = zlib.decompress(f.read())
220-
f.close()
218+
# FIXME 3.13 add allow_code=False to call
221219
dbslice = marshal.loads(pickle_str)
222220
if dbslice.get('WORDS'):
223221
# if it has some words, add them
@@ -244,15 +242,14 @@ def save_index(self):
244242
for segment in self.segments:
245243
try:
246244
os.remove(self.indexdb + segment)
247-
except OSError as error:
245+
except OSError as error: # noqa: PERF203 allow except inside loop
248246
# probably just nonexistent segment index file
249247
if error.errno != errno.ENOENT: raise # noqa: E701
250248

251249
# First write the much simpler filename/fileid dictionaries
252250
dbfil = {'WORDS': None, 'FILES': self.files, 'FILEIDS': self.fileids}
253-
marshal_fh = open(self.indexdb+'-', 'wb')
254-
marshal_fh.write(zlib.compress(marshal.dumps(dbfil)))
255-
marshal_fh.close()
251+
with open(self.indexdb + '-', 'wb') as marshal_fh:
252+
marshal_fh.write(zlib.compress(marshal.dumps(dbfil)))
256253

257254
# The hard part is splitting the word dictionary up, of course
258255
letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ#_"
@@ -271,10 +268,9 @@ def save_index(self):
271268
db = {'WORDS': segdicts[initchar], 'FILES': None, 'FILEIDS': None}
272269
pickle_str = marshal.dumps(db)
273270
filename = self.indexdb + initchar
274-
pickle_fh = open(filename, 'wb')
275-
pickle_fh.write(zlib.compress(pickle_str))
276-
pickle_fh.close()
277-
os.chmod(filename, 0o664)
271+
with open(filename, 'wb') as pickle_fh:
272+
pickle_fh.write(zlib.compress(pickle_str))
273+
os.chmod(filename, 0o664) # noqa: S103 allow group write
278274

279275
# save done
280276
self.changed = 0
@@ -292,7 +288,7 @@ def purge_entry(self, identifier):
292288
del self.fileids[file_index]
293289

294290
# The much harder part, cleanup the word index
295-
for _key, occurs in self.words.items():
291+
for occurs in self.words.values():
296292
if file_index in occurs:
297293
del occurs[file_index]
298294

roundup/backends/indexer_postgresql_fts.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@
66

77
import re
88

9+
from psycopg2.errors import InFailedSqlTransaction, SyntaxError, UndefinedObject # noqa: A004
10+
911
from roundup.backends.indexer_common import Indexer as IndexerBase
10-
from roundup.i18n import _
1112
from roundup.cgi.exceptions import IndexerQueryError
12-
13-
from psycopg2.errors import InFailedSqlTransaction, SyntaxError, \
14-
UndefinedObject
13+
from roundup.i18n import _
1514

1615

1716
class Indexer(IndexerBase):
1817
def __init__(self, db):
1918
IndexerBase.__init__(self, db)
2019
self.db = db
21-
if db.conn.server_version < 110000:
20+
min_fts_server_version = 110000
21+
if db.conn.server_version < min_fts_server_version:
2222
db.sql("select version()")
2323
server_descr = db.cursor.fetchone()
2424
raise ValueError("Postgres native_fts indexing requires postgres "
@@ -79,11 +79,11 @@ def add_text(self, identifier, text, mime_type='text/plain'):
7979
# we get a ValueError. For right now ignore it.
8080
pass
8181
else:
82-
id = r[0]
82+
row_id = r[0]
8383
sql = 'update __fts set _tsv=to_tsvector(%s, %s) where ctid=%s' % \
8484
(a, a, a)
8585
self.db.cursor.execute(sql, (self.db.config['INDEXER_LANGUAGE'],
86-
text, id))
86+
text, row_id))
8787

8888
def find(self, wordlist):
8989
"""look up all the words in the wordlist.
@@ -106,21 +106,21 @@ def find(self, wordlist):
106106
sql = ('select _class, _itemid, _prop from __fts '
107107
'where _tsv @@ to_tsquery(%s, %s)' % (a, a))
108108

109-
else:
110-
if re.search(r'[<>!&|()*]', " ".join(wordlist)):
111-
# assume this is a ts query processed by websearch_to_tsquery.
112-
# since it has operator characters in it.
113-
raise IndexerQueryError(_('You have non-word/operator '
109+
elif re.search(r'[<>!&|()*]', " ".join(wordlist)):
110+
# assume this is a ts query processed by websearch_to_tsquery.
111+
# since it has operator characters in it.
112+
raise IndexerQueryError(_(
113+
'You have non-word/operator '
114114
'characters "<>!&|()*" in your query. Did you want to '
115115
'do a tsquery search and forgot to start it with "ts:"?'))
116-
else:
117-
sql = 'select _class, _itemid, _prop from __fts '\
118-
'where _tsv @@ websearch_to_tsquery(%s, %s)' % (a, a)
116+
else:
117+
sql = 'select _class, _itemid, _prop from __fts '\
118+
'where _tsv @@ websearch_to_tsquery(%s, %s)' % (a, a)
119119

120120
try:
121121
# tests supply a multi element word list. Join them.
122122
self.db.cursor.execute(sql, (self.db.config['INDEXER_LANGUAGE'],
123-
" ".join(wordlist),))
123+
" ".join(wordlist)))
124124
except SyntaxError as e:
125125
# reset the cursor as it's invalid currently
126126
# reuse causes an InFailedSqlTransaction
@@ -145,7 +145,6 @@ def find(self, wordlist):
145145
raise ValueError(_("Check tracker config.ini for a bad "
146146
"indexer_language setting. Error is: %s") %
147147
e)
148-
else:
149-
raise
148+
raise
150149

151150
return self.db.cursor.fetchall()

roundup/backends/indexer_rdbms.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
"""
55
import re
66

7+
from roundup.anypy.strings import u2s, us2u
78
from roundup.backends.indexer_common import Indexer as IndexerBase
8-
from roundup.anypy.strings import us2u, u2s
99

1010

1111
class Indexer(IndexerBase):
@@ -52,15 +52,15 @@ def add_text(self, identifier, text, mime_type='text/plain'):
5252
r = self.db.cursor.fetchone()
5353
if not r:
5454
# not previously indexed
55-
id = self.db.newid('__textids')
55+
text_id = self.db.newid('__textids')
5656
sql = 'insert into __textids (_textid, _class, _itemid, _prop)'\
5757
' values (%s, %s, %s, %s)' % (a, a, a, a)
58-
self.db.cursor.execute(sql, (id, ) + identifier)
58+
self.db.cursor.execute(sql, (text_id, ) + identifier)
5959
else:
60-
id = int(r[0])
60+
text_id = int(r[0])
6161
# clear out any existing indexed values
6262
sql = 'delete from __words where _textid=%s' % a
63-
self.db.cursor.execute(sql, (id, ))
63+
self.db.cursor.execute(sql, (text_id, ))
6464

6565
# ok, find all the unique words in the text
6666
text = us2u(text, "replace")
@@ -77,7 +77,7 @@ def add_text(self, identifier, text, mime_type='text/plain'):
7777

7878
# for each word, add an entry in the db
7979
sql = 'insert into __words (_word, _textid) values (%s, %s)' % (a, a)
80-
words = [(word, id) for word in words]
80+
words = [(word, text_id) for word in words]
8181
self.db.cursor.executemany(sql, words)
8282

8383
def find(self, wordlist):
@@ -88,6 +88,7 @@ def find(self, wordlist):
8888
if not wordlist:
8989
return []
9090

91+
a = self.db.arg # placeholder for prepared statement
9192
cap_wl = [word.upper() for word in wordlist
9293
if self.minlength <= len(word) <= self.maxlength]
9394
clean_wl = [word for word in cap_wl if not self.is_stopword(word)]
@@ -97,17 +98,16 @@ def find(self, wordlist):
9798

9899
if self.db.implements_intersect:
99100
# simple AND search
100-
sql = 'select distinct(_textid) from __words where _word=%s' % (
101-
self.db.arg)
102-
sql = '\nINTERSECT\n'.join([sql]*len(clean_wl))
101+
sql = 'select distinct(_textid) from __words where _word=%s' % a
102+
sql = '\nINTERSECT\n'.join([sql] * len(clean_wl))
103103
self.db.cursor.execute(sql, tuple(clean_wl))
104104
r = self.db.cursor.fetchall()
105105
if not r:
106106
return []
107-
a = ','.join([self.db.arg] * len(r))
107+
a = ','.join([a] * len(r))
108108
sql = 'select _class, _itemid, _prop from __textids '\
109109
'where _textid in (%s)' % a
110-
self.db.cursor.execute(sql, tuple([int(row[0]) for row in r]))
110+
self.db.cursor.execute(sql, tuple(int(row[0]) for row in r))
111111

112112
else:
113113
# A more complex version for MySQL since it doesn't
@@ -126,17 +126,17 @@ def find(self, wordlist):
126126
match_list = []
127127
for n in range(len(clean_wl) - 1):
128128
join_list.append(join_tmpl % (n + 2))
129-
match_list.append(match_tmpl % (n + 2, self.db.arg))
129+
match_list.append(match_tmpl % (n + 2, a))
130130

131-
sql = sql % (' '.join(join_list), self.db.arg,
131+
sql = sql % (' '.join(join_list), a,
132132
' '.join(match_list))
133133
self.db.cursor.execute(sql, clean_wl)
134134

135135
r = [x[0] for x in self.db.cursor.fetchall()]
136136
if not r:
137137
return []
138138

139-
a = ','.join([self.db.arg] * len(r))
139+
a = ','.join([a] * len(r))
140140
sql = 'select _class, _itemid, _prop from __textids '\
141141
'where _textid in (%s)' % a
142142

roundup/backends/indexer_sqlite_fts.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
"""
2020

2121
from roundup.backends.indexer_common import Indexer as IndexerBase
22-
from roundup.i18n import _
2322
from roundup.cgi.exceptions import IndexerQueryError
23+
from roundup.i18n import _
2424

2525
try:
2626
import sqlite3 as sqlite
@@ -84,10 +84,10 @@ def add_text(self, identifier, text, mime_type='text/plain'):
8484
' values (%s, %s, %s, %s)' % (a, a, a, a)
8585
self.db.cursor.execute(sql, identifier + (text,))
8686
else:
87-
id = int(r[0])
87+
text_id = int(r[0])
8888
sql = 'update __fts set _textblob=%s where rowid=%s' % \
8989
(a, a)
90-
self.db.cursor.execute(sql, (text, id))
90+
self.db.cursor.execute(sql, (text, text_id))
9191

9292
def find(self, wordlist):
9393
"""look up all the words in the wordlist.
@@ -132,8 +132,8 @@ def find(self, wordlist):
132132
raise IndexerQueryError(
133133
_("Search failed. Try quoting any terms that "
134134
"include a '-' and retry the search."))
135-
else:
136-
raise IndexerQueryError(e.args[0].replace("fts5:",
137-
"Query error:"))
135+
136+
raise IndexerQueryError(e.args[0].replace("fts5:",
137+
"Query error:"))
138138

139139
return self.db.cursor.fetchall()

roundup/backends/indexer_whoosh.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
'''
33
import os
44

5-
from whoosh import fields, qparser, index, query, analysis
5+
from whoosh import analysis, fields, index, query
66

7-
from roundup.backends.indexer_common import Indexer as IndexerBase
87
from roundup.anypy.strings import us2u
8+
from roundup.backends.indexer_common import Indexer as IndexerBase
99

1010

1111
class Indexer(IndexerBase):

0 commit comments

Comments
 (0)