Completed
Push — master ( f43547...71985b )
by Chris
12:00 queued 10s
created

abydos.stemmer._lovins.Lovins._cond_n()   A

Complexity

Conditions 4

Size

Total Lines 23
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 7
nop 3
dl 0
loc 23
ccs 7
cts 7
cp 1
crap 4
rs 10
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
0 ignored issues
show
coding-style introduced by
Too many lines in module (1108/1000)
Loading history...
2
3
# Copyright 2014-2018 by Christopher C. Little.
4
# This file is part of Abydos.
5
#
6
# Abydos is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation, either version 3 of the License, or
9
# (at your option) any later version.
10
#
11
# Abydos is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with Abydos. If not, see <http://www.gnu.org/licenses/>.
18
19 1
"""abydos.stemmer._lovins.
20
21
Lovins stemmer.
22
"""
23
24 1
from __future__ import (
25
    absolute_import,
26
    division,
27
    print_function,
28
    unicode_literals,
29
)
30
31 1
from unicodedata import normalize
32
33 1
from six import text_type
34 1
from six.moves import range
35
36 1
from ._stemmer import _Stemmer
37
38 1
__all__ = ['Lovins', 'lovins']
39
40
41 1
class Lovins(_Stemmer):
0 ignored issues
show
Unused Code introduced by
The variable __class__ seems to be unused.
Loading history...
42
    """Lovins stemmer.
43
44
    The Lovins stemmer is described in Julie Beth Lovins's article
45
    :cite:`Lovins:1968`.
46
    """
47
48 1
    def _cond_b(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
49
        """Return Lovins' condition B.
50
51
        Parameters
52
        ----------
53
        word : str
54
            Word to check
55
        suffix_len : int
56
            Suffix length
57
58
        Returns
59
        -------
60
        bool
61
            True if condition is met
62
63
        """
64 1
        return len(word) - suffix_len >= 3
65
66 1
    def _cond_c(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
67
        """Return Lovins' condition C.
68
69
        Parameters
70
        ----------
71
        word : str
72
            Word to check
73
        suffix_len : int
74
            Suffix length
75
76
        Returns
77
        -------
78
        bool
79
            True if condition is met
80
81
        """
82 1
        return len(word) - suffix_len >= 4
83
84 1
    def _cond_d(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
85
        """Return Lovins' condition D.
86
87
        Parameters
88
        ----------
89
        word : str
90
            Word to check
91
        suffix_len : int
92
            Suffix length
93
94
        Returns
95
        -------
96
        bool
97
            True if condition is met
98
99
        """
100 1
        return len(word) - suffix_len >= 5
101
102 1
    def _cond_e(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
103
        """Return Lovins' condition E.
104
105
        Parameters
106
        ----------
107
        word : str
108
            Word to check
109
        suffix_len : int
110
            Suffix length
111
112
        Returns
113
        -------
114
        bool
115
            True if condition is met
116
117
        """
118 1
        return word[-suffix_len - 1] != 'e'
119
120 1
    def _cond_f(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
121
        """Return Lovins' condition F.
122
123
        Parameters
124
        ----------
125
        word : str
126
            Word to check
127
        suffix_len : int
128
            Suffix length
129
130
        Returns
131
        -------
132
        bool
133
            True if condition is met
134
135
        """
136 1
        return len(word) - suffix_len >= 3 and word[-suffix_len - 1] != 'e'
137
138 1
    def _cond_g(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
139
        """Return Lovins' condition G.
140
141
        Parameters
142
        ----------
143
        word : str
144
            Word to check
145
        suffix_len : int
146
            Suffix length
147
148
        Returns
149
        -------
150
        bool
151
            True if condition is met
152
153
        """
154 1
        return len(word) - suffix_len >= 3 and word[-suffix_len - 1] == 'f'
155
156 1
    def _cond_h(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
157
        """Return Lovins' condition H.
158
159
        Parameters
160
        ----------
161
        word : str
162
            Word to check
163
        suffix_len : int
164
            Suffix length
165
166
        Returns
167
        -------
168
        bool
169
            True if condition is met
170
171
        """
172 1
        return (
173
            word[-suffix_len - 1] == 't'
174
            or word[-suffix_len - 2 : -suffix_len] == 'll'
175
        )
176
177 1
    def _cond_i(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
178
        """Return Lovins' condition I.
179
180
        Parameters
181
        ----------
182
        word : str
183
            Word to check
184
        suffix_len : int
185
            Suffix length
186
187
        Returns
188
        -------
189
        bool
190
            True if condition is met
191
192
        """
193 1
        return word[-suffix_len - 1] not in {'e', 'o'}
194
195 1
    def _cond_j(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
196
        """Return Lovins' condition J.
197
198
        Parameters
199
        ----------
200
        word : str
201
            Word to check
202
        suffix_len : int
203
            Suffix length
204
205
        Returns
206
        -------
207
        bool
208
            True if condition is met
209
210
        """
211 1
        return word[-suffix_len - 1] not in {'a', 'e'}
212
213 1
    def _cond_k(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
214
        """Return Lovins' condition K.
215
216
        Parameters
217
        ----------
218
        word : str
219
            Word to check
220
        suffix_len : int
221
            Suffix length
222
223
        Returns
224
        -------
225
        bool
226
            True if condition is met
227
228
        """
229 1
        return (len(word) - suffix_len >= 3) and (
230
            word[-suffix_len - 1] in {'i', 'l'}
231
            or (word[-suffix_len - 3] == 'u' and word[-suffix_len - 1] == 'e')
232
        )
233
234 1
    def _cond_l(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
235
        """Return Lovins' condition L.
236
237
        Parameters
238
        ----------
239
        word : str
240
            Word to check
241
        suffix_len : int
242
            Suffix length
243
244
        Returns
245
        -------
246
        bool
247
            True if condition is met
248
249
        """
250 1
        return (
251
            word[-suffix_len - 1] not in {'s', 'u', 'x'}
252
            or word[-suffix_len - 1] == 'os'
253
        )
254
255 1
    def _cond_m(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
256
        """Return Lovins' condition M.
257
258
        Parameters
259
        ----------
260
        word : str
261
            Word to check
262
        suffix_len : int
263
            Suffix length
264
265
        Returns
266
        -------
267
        bool
268
            True if condition is met
269
270
        """
271 1
        return word[-suffix_len - 1] not in {'a', 'c', 'e', 'm'}
272
273 1
    def _cond_n(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
274
        """Return Lovins' condition N.
275
276
        Parameters
277
        ----------
278
        word : str
279
            Word to check
280
        suffix_len : int
281
            Suffix length
282
283
        Returns
284
        -------
285
        bool
286
            True if condition is met
287
288
        """
289 1
        if len(word) - suffix_len >= 3:
290 1
            if word[-suffix_len - 3] == 's':
291 1
                if len(word) - suffix_len >= 4:
292 1
                    return True
293
            else:
294 1
                return True
295 1
        return False
296
297 1
    def _cond_o(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
298
        """Return Lovins' condition O.
299
300
        Parameters
301
        ----------
302
        word : str
303
            Word to check
304
        suffix_len : int
305
            Suffix length
306
307
        Returns
308
        -------
309
        bool
310
            True if condition is met
311
312
        """
313 1
        return word[-suffix_len - 1] in {'i', 'l'}
314
315 1
    def _cond_p(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
316
        """Return Lovins' condition P.
317
318
        Parameters
319
        ----------
320
        word : str
321
            Word to check
322
        suffix_len : int
323
            Suffix length
324
325
        Returns
326
        -------
327
        bool
328
            True if condition is met
329
330
        """
331 1
        return word[-suffix_len - 1] != 'c'
332
333 1
    def _cond_q(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
334
        """Return Lovins' condition Q.
335
336
        Parameters
337
        ----------
338
        word : str
339
            Word to check
340
        suffix_len : int
341
            Suffix length
342
343
        Returns
344
        -------
345
        bool
346
            True if condition is met
347
348
        """
349 1
        return len(word) - suffix_len >= 3 and word[-suffix_len - 1] not in {
350
            'l',
351
            'n',
352
        }
353
354 1
    def _cond_r(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
355
        """Return Lovins' condition R.
356
357
        Parameters
358
        ----------
359
        word : str
360
            Word to check
361
        suffix_len : int
362
            Suffix length
363
364
        Returns
365
        -------
366
        bool
367
            True if condition is met
368
369
        """
370 1
        return word[-suffix_len - 1] in {'n', 'r'}
371
372 1
    def _cond_s(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
373
        """Return Lovins' condition S.
374
375
        Parameters
376
        ----------
377
        word : str
378
            Word to check
379
        suffix_len : int
380
            Suffix length
381
382
        Returns
383
        -------
384
        bool
385
            True if condition is met
386
387
        """
388 1
        return word[-suffix_len - 2 : -suffix_len] == 'dr' or (
389
            word[-suffix_len - 1] == 't'
390
            and word[-suffix_len - 2 : -suffix_len] != 'tt'
391
        )
392
393 1
    def _cond_t(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
394
        """Return Lovins' condition T.
395
396
        Parameters
397
        ----------
398
        word : str
399
            Word to check
400
        suffix_len : int
401
            Suffix length
402
403
        Returns
404
        -------
405
        bool
406
            True if condition is met
407
408
        """
409 1
        return (
410
            word[-suffix_len - 1] in {'s', 't'}
411
            and word[-suffix_len - 2 : -suffix_len] != 'ot'
412
        )
413
414 1
    def _cond_u(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
415
        """Return Lovins' condition U.
416
417
        Parameters
418
        ----------
419
        word : str
420
            Word to check
421
        suffix_len : int
422
            Suffix length
423
424
        Returns
425
        -------
426
        bool
427
            True if condition is met
428
429
        """
430 1
        return word[-suffix_len - 1] in {'l', 'm', 'n', 'r'}
431
432 1
    def _cond_v(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
433
        """Return Lovins' condition V.
434
435
        Parameters
436
        ----------
437
        word : str
438
            Word to check
439
        suffix_len : int
440
            Suffix length
441
442
        Returns
443
        -------
444
        bool
445
            True if condition is met
446
447
        """
448 1
        return word[-suffix_len - 1] == 'c'
449
450 1
    def _cond_w(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
451
        """Return Lovins' condition W.
452
453
        Parameters
454
        ----------
455
        word : str
456
            Word to check
457
        suffix_len : int
458
            Suffix length
459
460
        Returns
461
        -------
462
        bool
463
            True if condition is met
464
465
        """
466 1
        return word[-suffix_len - 1] not in {'s', 'u'}
467
468 1
    def _cond_x(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
469
        """Return Lovins' condition X.
470
471
        Parameters
472
        ----------
473
        word : str
474
            Word to check
475
        suffix_len : int
476
            Suffix length
477
478
        Returns
479
        -------
480
        bool
481
            True if condition is met
482
483
        """
484 1
        return word[-suffix_len - 1] in {'i', 'l'} or (
485
            word[-suffix_len - 3 : -suffix_len] == 'u'
486
            and word[-suffix_len - 1] == 'e'
487
        )
488
489 1
    def _cond_y(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
490
        """Return Lovins' condition Y.
491
492
        Parameters
493
        ----------
494
        word : str
495
            Word to check
496
        suffix_len : int
497
            Suffix length
498
499
        Returns
500
        -------
501
        bool
502
            True if condition is met
503
504
        """
505 1
        return word[-suffix_len - 2 : -suffix_len] == 'in'
506
507 1
    def _cond_z(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
508
        """Return Lovins' condition Z.
509
510
        Parameters
511
        ----------
512
        word : str
513
            Word to check
514
        suffix_len : int
515
            Suffix length
516
517
        Returns
518
        -------
519
        bool
520
            True if condition is met
521
522
        """
523 1
        return word[-suffix_len - 1] != 'f'
524
525 1
    def _cond_aa(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
526
        """Return Lovins' condition AA.
527
528
        Parameters
529
        ----------
530
        word : str
531
            Word to check
532
        suffix_len : int
533
            Suffix length
534
535
        Returns
536
        -------
537
        bool
538
            True if condition is met
539
540
        """
541 1
        return word[-suffix_len - 1] in {'d', 'f', 'l', 't'} or word[
542
            -suffix_len - 2 : -suffix_len
543
        ] in {'ph', 'th', 'er', 'or', 'es'}
544
545 1
    def _cond_bb(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
546
        """Return Lovins' condition BB.
547
548
        Parameters
549
        ----------
550
        word : str
551
            Word to check
552
        suffix_len : int
553
            Suffix length
554
555
        Returns
556
        -------
557
        bool
558
            True if condition is met
559
560
        """
561 1
        return (
562
            len(word) - suffix_len >= 3
563
            and word[-suffix_len - 3 : -suffix_len] != 'met'
564
            and word[-suffix_len - 4 : -suffix_len] != 'ryst'
565
        )
566
567 1
    def _cond_cc(self, word, suffix_len):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
568
        """Return Lovins' condition CC.
569
570
        Parameters
571
        ----------
572
        word : str
573
            Word to check
574
        suffix_len : int
575
            Suffix length
576
577
        Returns
578
        -------
579
        bool
580
            True if condition is met
581
582
        """
583 1
        return word[-suffix_len - 1] == 'l'
584
585 1
    def _recode9(self, stem):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
586
        """Return Lovins' conditional recode rule 9.
587
588
        Parameters
589
        ----------
590
        stem : str
591
            Word to stem
592
593
        Returns
594
        -------
595
        str
596
            Word stripped of suffix
597
598
        """
599 1
        if stem[-3:-2] in {'a', 'i', 'o'}:
600 1
            return stem
601 1
        return stem[:-2] + 'l'
602
603 1
    def _recode24(self, stem):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
604
        """Return Lovins' conditional recode rule 24.
605
606
        Parameters
607
        ----------
608
        stem : str
609
            Word to stem
610
611
        Returns
612
        -------
613
        str
614
            Word stripped of suffix
615
616
        """
617 1
        if stem[-4:-3] == 's':
618 1
            return stem
619 1
        return stem[:-1] + 's'
620
621 1
    def _recode28(self, stem):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
622
        """Return Lovins' conditional recode rule 28.
623
624
        Parameters
625
        ----------
626
        stem : str
627
            Word to stem
628
629
        Returns
630
        -------
631
        str
632
            Word stripped of suffix
633
634
        """
635 1
        if stem[-4:-3] in {'p', 't'}:
636 1
            return stem
637 1
        return stem[:-1] + 's'
638
639 1
    def _recode30(self, stem):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
640
        """Return Lovins' conditional recode rule 30.
641
642
        Parameters
643
        ----------
644
        stem : str
645
            Word to stem
646
647
        Returns
648
        -------
649
        str
650
            Word stripped of suffix
651
652
        """
653 1
        if stem[-4:-3] == 'm':
654 1
            return stem
655 1
        return stem[:-1] + 's'
656
657 1
    def _recode32(self, stem):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
658
        """Return Lovins' conditional recode rule 32.
659
660
        Parameters
661
        ----------
662
        stem : str
663
            Word to stem
664
665
        Returns
666
        -------
667
        str
668
            Word stripped of suffix
669
670
        """
671 1
        if stem[-3:-2] == 'n':
672 1
            return stem
673 1
        return stem[:-1] + 's'
674
675 1
    _suffix = {}
676 1
    _recode = ()
677
678 1
    def __init__(self):
679
        """Initialize the stemmer."""
680 1
        self._suffix = {
681
            'alistically': self._cond_b,
682
            'arizability': None,
683
            'izationally': self._cond_b,
684
            'antialness': None,
685
            'arisations': None,
686
            'arizations': None,
687
            'entialness': None,
688
            'allically': self._cond_c,
689
            'antaneous': None,
690
            'antiality': None,
691
            'arisation': None,
692
            'arization': None,
693
            'ationally': self._cond_b,
694
            'ativeness': None,
695
            'eableness': self._cond_e,
696
            'entations': None,
697
            'entiality': None,
698
            'entialize': None,
699
            'entiation': None,
700
            'ionalness': None,
701
            'istically': None,
702
            'itousness': None,
703
            'izability': None,
704
            'izational': None,
705
            'ableness': None,
706
            'arizable': None,
707
            'entation': None,
708
            'entially': None,
709
            'eousness': None,
710
            'ibleness': None,
711
            'icalness': None,
712
            'ionalism': None,
713
            'ionality': None,
714
            'ionalize': None,
715
            'iousness': None,
716
            'izations': None,
717
            'lessness': None,
718
            'ability': None,
719
            'aically': None,
720
            'alistic': self._cond_b,
721
            'alities': None,
722
            'ariness': self._cond_e,
723
            'aristic': None,
724
            'arizing': None,
725
            'ateness': None,
726
            'atingly': None,
727
            'ational': self._cond_b,
728
            'atively': None,
729
            'ativism': None,
730
            'elihood': self._cond_e,
731
            'encible': None,
732
            'entally': None,
733
            'entials': None,
734
            'entiate': None,
735
            'entness': None,
736
            'fulness': None,
737
            'ibility': None,
738
            'icalism': None,
739
            'icalist': None,
740
            'icality': None,
741
            'icalize': None,
742
            'ication': self._cond_g,
743
            'icianry': None,
744
            'ination': None,
745
            'ingness': None,
746
            'ionally': None,
747
            'isation': None,
748
            'ishness': None,
749
            'istical': None,
750
            'iteness': None,
751
            'iveness': None,
752
            'ivistic': None,
753
            'ivities': None,
754
            'ization': self._cond_f,
755
            'izement': None,
756
            'oidally': None,
757
            'ousness': None,
758
            'aceous': None,
759
            'acious': self._cond_b,
760
            'action': self._cond_g,
761
            'alness': None,
762
            'ancial': None,
763
            'ancies': None,
764
            'ancing': self._cond_b,
765
            'ariser': None,
766
            'arized': None,
767
            'arizer': None,
768
            'atable': None,
769
            'ations': self._cond_b,
770
            'atives': None,
771
            'eature': self._cond_z,
772
            'efully': None,
773
            'encies': None,
774
            'encing': None,
775
            'ential': None,
776
            'enting': self._cond_c,
777
            'entist': None,
778
            'eously': None,
779
            'ialist': None,
780
            'iality': None,
781
            'ialize': None,
782
            'ically': None,
783
            'icance': None,
784
            'icians': None,
785
            'icists': None,
786
            'ifully': None,
787
            'ionals': None,
788
            'ionate': self._cond_d,
789
            'ioning': None,
790
            'ionist': None,
791
            'iously': None,
792
            'istics': None,
793
            'izable': self._cond_e,
794
            'lessly': None,
795
            'nesses': None,
796
            'oidism': None,
797
            'acies': None,
798
            'acity': None,
799
            'aging': self._cond_b,
800
            'aical': None,
801
            'alist': None,
802
            'alism': self._cond_b,
803
            'ality': None,
804
            'alize': None,
805
            'allic': self._cond_bb,
806
            'anced': self._cond_b,
807
            'ances': self._cond_b,
808
            'antic': self._cond_c,
809
            'arial': None,
810
            'aries': None,
811
            'arily': None,
812
            'arity': self._cond_b,
813
            'arize': None,
814
            'aroid': None,
815
            'ately': None,
816
            'ating': self._cond_i,
817
            'ation': self._cond_b,
818
            'ative': None,
819
            'ators': None,
820
            'atory': None,
821
            'ature': self._cond_e,
822
            'early': self._cond_y,
823
            'ehood': None,
824
            'eless': None,
825
            'elity': None,
826
            'ement': None,
827
            'enced': None,
828
            'ences': None,
829
            'eness': self._cond_e,
830
            'ening': self._cond_e,
831
            'ental': None,
832
            'ented': self._cond_c,
833
            'ently': None,
834
            'fully': None,
835
            'ially': None,
836
            'icant': None,
837
            'ician': None,
838
            'icide': None,
839
            'icism': None,
840
            'icist': None,
841
            'icity': None,
842
            'idine': self._cond_i,
843
            'iedly': None,
844
            'ihood': None,
845
            'inate': None,
846
            'iness': None,
847
            'ingly': self._cond_b,
848
            'inism': self._cond_j,
849
            'inity': self._cond_cc,
850
            'ional': None,
851
            'ioned': None,
852
            'ished': None,
853
            'istic': None,
854
            'ities': None,
855
            'itous': None,
856
            'ively': None,
857
            'ivity': None,
858
            'izers': self._cond_f,
859
            'izing': self._cond_f,
860
            'oidal': None,
861
            'oides': None,
862
            'otide': None,
863
            'ously': None,
864
            'able': None,
865
            'ably': None,
866
            'ages': self._cond_b,
867
            'ally': self._cond_b,
868
            'ance': self._cond_b,
869
            'ancy': self._cond_b,
870
            'ants': self._cond_b,
871
            'aric': None,
872
            'arly': self._cond_k,
873
            'ated': self._cond_i,
874
            'ates': None,
875
            'atic': self._cond_b,
876
            'ator': None,
877
            'ealy': self._cond_y,
878
            'edly': self._cond_e,
879
            'eful': None,
880
            'eity': None,
881
            'ence': None,
882
            'ency': None,
883
            'ened': self._cond_e,
884
            'enly': self._cond_e,
885
            'eous': None,
886
            'hood': None,
887
            'ials': None,
888
            'ians': None,
889
            'ible': None,
890
            'ibly': None,
891
            'ical': None,
892
            'ides': self._cond_l,
893
            'iers': None,
894
            'iful': None,
895
            'ines': self._cond_m,
896
            'ings': self._cond_n,
897
            'ions': self._cond_b,
898
            'ious': None,
899
            'isms': self._cond_b,
900
            'ists': None,
901
            'itic': self._cond_h,
902
            'ized': self._cond_f,
903
            'izer': self._cond_f,
904
            'less': None,
905
            'lily': None,
906
            'ness': None,
907
            'ogen': None,
908
            'ward': None,
909
            'wise': None,
910
            'ying': self._cond_b,
911
            'yish': None,
912
            'acy': None,
913
            'age': self._cond_b,
914
            'aic': None,
915
            'als': self._cond_bb,
916
            'ant': self._cond_b,
917
            'ars': self._cond_o,
918
            'ary': self._cond_f,
919
            'ata': None,
920
            'ate': None,
921
            'eal': self._cond_y,
922
            'ear': self._cond_y,
923
            'ely': self._cond_e,
924
            'ene': self._cond_e,
925
            'ent': self._cond_c,
926
            'ery': self._cond_e,
927
            'ese': None,
928
            'ful': None,
929
            'ial': None,
930
            'ian': None,
931
            'ics': None,
932
            'ide': self._cond_l,
933
            'ied': None,
934
            'ier': None,
935
            'ies': self._cond_p,
936
            'ily': None,
937
            'ine': self._cond_m,
938
            'ing': self._cond_n,
939
            'ion': self._cond_q,
940
            'ish': self._cond_c,
941
            'ism': self._cond_b,
942
            'ist': None,
943
            'ite': self._cond_aa,
944
            'ity': None,
945
            'ium': None,
946
            'ive': None,
947
            'ize': self._cond_f,
948
            'oid': None,
949
            'one': self._cond_r,
950
            'ous': None,
951
            'ae': None,
952
            'al': self._cond_bb,
953
            'ar': self._cond_x,
954
            'as': self._cond_b,
955
            'ed': self._cond_e,
956
            'en': self._cond_f,
957
            'es': self._cond_e,
958
            'ia': None,
959
            'ic': None,
960
            'is': None,
961
            'ly': self._cond_b,
962
            'on': self._cond_s,
963
            'or': self._cond_t,
964
            'um': self._cond_u,
965
            'us': self._cond_v,
966
            'yl': self._cond_r,
967
            '\'s': None,
968
            's\'': None,
969
            'a': None,
970
            'e': None,
971
            'i': None,
972
            'o': None,
973
            's': self._cond_w,
974
            'y': self._cond_b,
975
        }
976
977 1
        self._recode = (
978
            ('iev', 'ief'),
979
            ('uct', 'uc'),
980
            ('umpt', 'um'),
981
            ('rpt', 'rb'),
982
            ('urs', 'ur'),
983
            ('istr', 'ister'),
984
            ('metr', 'meter'),
985
            ('olv', 'olut'),
986
            ('ul', self._recode9),
987
            ('bex', 'bic'),
988
            ('dex', 'dic'),
989
            ('pex', 'pic'),
990
            ('tex', 'tic'),
991
            ('ax', 'ac'),
992
            ('ex', 'ec'),
993
            ('ix', 'ic'),
994
            ('lux', 'luc'),
995
            ('uad', 'uas'),
996
            ('vad', 'vas'),
997
            ('cid', 'cis'),
998
            ('lid', 'lis'),
999
            ('erid', 'eris'),
1000
            ('pand', 'pans'),
1001
            ('end', self._recode24),
1002
            ('ond', 'ons'),
1003
            ('lud', 'lus'),
1004
            ('rud', 'rus'),
1005
            ('her', self._recode28),
1006
            ('mit', 'mis'),
1007
            ('ent', self._recode30),
1008
            ('ert', 'ers'),
1009
            ('et', self._recode32),
1010
            ('yt', 'ys'),
1011
            ('yz', 'ys'),
1012
        )
1013
1014 1
    def stem(self, word):
0 ignored issues
show
Bug introduced by
Parameters differ from overridden 'stem' method
Loading history...
1015
        """Return Lovins stem.
1016
1017
        Parameters
1018
        ----------
1019
        word : str
1020
            The word to stem
1021
1022
        Returns
1023
        -------
1024
        str
1025
            Word stem
1026
1027
        Examples
1028
        --------
1029
        >>> stmr = Lovins()
1030
        >>> stmr.stem('reading')
1031
        'read'
1032
        >>> stmr.stem('suspension')
1033
        'suspens'
1034
        >>> stmr.stem('elusiveness')
1035
        'elus'
1036
1037
        """
1038
        # lowercase, normalize, and compose
1039 1
        word = normalize('NFC', text_type(word.lower()))
1040
1041 1
        for suffix_len in range(11, 0, -1):
1042 1
            ending = word[-suffix_len:]
1043 1
            if (
1044
                ending in self._suffix
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
1045
                and len(word) - suffix_len >= 2
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
1046
                and (
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
1047
                    self._suffix[ending] is None
1048
                    or self._suffix[ending](word, suffix_len)
1049
                )
1050
            ):
1051 1
                word = word[:-suffix_len]
1052 1
                break
1053
1054 1
        if word[-2:] in {
1055
            'bb',
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
1056
            'dd',
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
1057
            'gg',
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
1058
            'll',
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
1059
            'mm',
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
1060
            'nn',
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
1061
            'pp',
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
1062
            'rr',
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
1063
            'ss',
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
1064
            'tt',
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
1065
        }:
1066 1
            word = word[:-1]
1067
1068 1
        for ending, replacement in self._recode:
1069 1
            if word.endswith(ending):
1070 1
                if callable(replacement):
1071 1
                    word = replacement(word)
1072
                else:
1073 1
                    word = word[: -len(ending)] + replacement
1074
1075 1
        return word
1076
1077
1078 1
def lovins(word):
1079
    """Return Lovins stem.
1080
1081
    This is a wrapper for :py:meth:`Lovins.stem`.
1082
1083
    Parameters
1084
    ----------
1085
    word : str
1086
        The word to stem
1087
1088
    Returns
1089
    -------
1090
    str: Word stem
1091
1092
    Examples
1093
    --------
1094
    >>> lovins('reading')
1095
    'read'
1096
    >>> lovins('suspension')
1097
    'suspens'
1098
    >>> lovins('elusiveness')
1099
    'elus'
1100
1101
    """
1102 1
    return Lovins().stem(word)
1103
1104
1105
if __name__ == '__main__':
1106
    import doctest
1107
1108
    doctest.testmod()
1109