Completed
Push — master ( 9b088f...73be1b )
by Asif
01:05
created

crudbuilder.plural()   D

Complexity

Conditions 9

Size

Total Lines 62

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 9
dl 0
loc 62
rs 4.7926

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
import re
2
import string
3
import imp
4
5
try:
6
    # Django versions >= 1.9
7
    from django.utils.module_loading import import_module
8
except ImportError:
9
    # Django versions < 1.9
10
    from django.utils.importlib import import_module
11
12
13
__all__ = ['plural', 'mixedToUnder', 'capword', 'lowerword', 'underToMixed']
14
15
# http://code.activestate.com/recipes/82102-smart-pluralisation-english/
16
17
18
def plural(text):
19
    """
20
        >>> plural('activity')
21
        'activities'
22
    """
23
    aberrant = {
24
        'knife': 'knives',
25
        'self': 'selves',
26
        'elf': 'elves',
27
        'life': 'lives',
28
        'hoof': 'hooves',
29
        'leaf': 'leaves',
30
        'echo': 'echoes',
31
        'embargo': 'embargoes',
32
        'hero': 'heroes',
33
        'potato': 'potatoes',
34
        'tomato': 'tomatoes',
35
        'torpedo': 'torpedoes',
36
        'veto': 'vetoes',
37
        'child': 'children',
38
        'woman': 'women',
39
        'man': 'men',
40
        'person': 'people',
41
        'goose': 'geese',
42
        'mouse': 'mice',
43
        'barracks': 'barracks',
44
        'deer': 'deer',
45
        'nucleus': 'nuclei',
46
        'syllabus': 'syllabi',
47
        'focus': 'foci',
48
        'fungus': 'fungi',
49
        'cactus': 'cacti',
50
        'phenomenon': 'phenomena',
51
        'index': 'indices',
52
        'appendix': 'appendices',
53
        'criterion': 'criteria',
54
55
56
    }
57
58
    if text in aberrant:
59
        result = '%s' % aberrant[text]
60
    else:
61
        postfix = 's'
62
        if len(text) > 2:
63
            vowels = 'aeiou'
64
            if text[-2:] in ('ch', 'sh'):
65
                postfix = 'es'
66
            elif text[-1:] == 'y':
67
                if (text[-2:-1] in vowels) or (text[0] in string.ascii_uppercase):
68
                    postfix = 's'
69
                else:
70
                    postfix = 'ies'
71
                    text = text[:-1]
72
            elif text[-2:] == 'is':
73
                postfix = 'es'
74
                text = text[:-2]
75
            elif text[-1:] in ('s', 'z', 'x'):
76
                postfix = 'es'
77
78
        result = '%s%s' % (text, postfix)
79
    return result
80
81
82
# Text utilities
83
#
84
_mixedToUnderRE = re.compile(r'[A-Z]+')
85
86
87
def mixedToUnder(s):  # pragma: no cover
88
    """
89
    Sample:
90
        >>> mixedToUnder("FooBarBaz")
91
        'foo_bar_baz'
92
93
    Special case for ID:
94
        >>> mixedToUnder("FooBarID")
95
        'foo_bar_id'
96
    """
97
    if s.endswith('ID'):
98
        return mixedToUnder(s[:-2] + "_id")
99
    trans = _mixedToUnderRE.sub(mixedToUnderSub, s)
100
    if trans.startswith('_'):
101
        trans = trans[1:]
102
    return trans
103
104
105
def mixedToUnderSub(match):
106
    m = match.group(0).lower()
107
    if len(m) > 1:
108
        return '_%s_%s' % (m[:-1], m[-1])
109
    else:
110
        return '_%s' % m
111
112
113
def capword(s):
114
    """
115
    >>> capword('foo')
116
    'Foo'
117
    """
118
    return s[0].upper() + s[1:]
119
120
121
def lowerword(s):  # pragma: no cover
122
    """
123
    >>> lowerword('Hello')
124
    'hello'
125
    """
126
    return s[0].lower() + s[1:]
127
128
_underToMixedRE = re.compile('_.')
129
130
131
def underToMixed(name):
132
    """
133
    >>> underToMixed('some_large_model_name_perhaps')
134
    'someLargeModelNamePerhaps'
135
136
    >>> underToMixed('exception_for_id')
137
    'exceptionForID'
138
    """
139
    if name.endswith('_id'):
140
        return underToMixed(name[:-3] + "ID")
141
    return _underToMixedRE.sub(lambda m: m.group(0)[1].upper(),
142
                               name)
143
144
145
def model_class_form(name):
146
    """
147
    >>> model_class_form('foo_bar_baz')
148
    'FooBarBaz'
149
    """
150
    return capword(underToMixed(name))
151
152
153
def underToAllCaps(value):  # pragma: no cover
154
    """
155
    >>> underToAllCaps('foo_bar_baz')
156
    'Foo Bar Baz'
157
    """
158
    return ' '.join(map(lambda x: x.title(), value.split('_')))
159
160
161
def import_crud(app):
162
    '''
163
    Import moderator module and register all models it contains with moderation
164
    '''
165
166
    try:
167
        app_path = import_module(app).__path__
168
    except AttributeError:
169
        return None
170
171
    try:
172
        imp.find_module('crud', app_path)
173
    except ImportError:
174
        return None
175
176
    module = import_module("%s.crud" % app)
177
178
    return module
179
180
181
def auto_discover():
182
    '''
183
    Auto register all apps that have module moderator with moderation
184
    '''
185
    from django.conf import settings
186
187
    for app in settings.INSTALLED_APPS:
188
        import_crud(app)
189
190