def walk_dir(self, base, ignore_index=False, prefix=''): from inflector import Inflector from django.utils.module_loading import import_string from drf_auto_endpoint.app_settings import settings as auto_settings inflector_language = import_string(auto_settings.INFLECTOR_LANGUAGE) inflector = Inflector(inflector_language) imports = [] for item in os.listdir(base): filename = os.path.join(base, item) if os.path.isdir(filename): imports += self.walk_dir(filename, prefix=os.path.join( prefix, item.replace('_', '-'))) elif item == 'index.js' and ignore_index: continue else: try: base_name, extension = item.rsplit('.', 1) except ValueError: # a file without extension continue if extension != 'js': continue imports.append( (os.path.join(prefix, inflector.pluralize(base_name)), os.path.join(prefix, base_name).replace('/', '_').replace('-', '_'), os.path.join('.', prefix.replace('-', '_'), base_name))) return imports
def get_search_results(query, exact_match=False): query = join_bigrams.bigramar(query.lower(), bigrams) query = [query] if exact_match else query.split() results = [[], [], []] for row in data: query_match_level = 0 for query_word in query: search_list = [query_word] if exact_match else [ query_word, Inflector.pluralize(query_word), Inflector.singularize(query_word) ] word_match_level = consts.NOT_FOUND for word in search_list: word_match_level = min(word_match_level, get_match_level(word, row)) query_match_level = max(query_match_level, word_match_level) if query_match_level != consts.NOT_FOUND: results[query_match_level].append(copy.copy(row)) merged_results = results[0] + results[1] + results[2] for result in merged_results: for level in range(3): for column in consts.SEARCH_COLUMNS[level]: result.pop(column + '_processed') return json.dumps(merged_results)
def wizard(target_model, serializer, icon_class=None, btn_class=None, text=None, **kwargs): inflector_language = import_string(settings.INFLECTOR_LANGUAGE) inflector = Inflector(inflector_language) _kwargs = { 'type': 'wizard', 'params': {}, } _kwargs.update(kwargs) kwargs = _kwargs fieldsets = kwargs.pop('fieldsets', None) if fieldsets is None: fieldsets = [ {'name': field} for field in serializer.Meta.fields ] kwargs['params']['fieldsets'] = fieldsets serializer_instance = serializer() needs = [] fields = [] Adapter = import_string(settings.METADATA_ADAPTER) for field in serializer.Meta.fields: field_instance = serializer_instance.fields[field] if isinstance(field_instance, PrimaryKeyRelatedField): model = field_instance.queryset.model needs.append({ 'app': model._meta.app_label, 'singular': model._meta.model_name.lower(), 'plural': inflector.pluralize(model._meta.model_name.lower()), }) fields.append(Adapter.adapt_field(get_field_dict(field, serializer))) kwargs['params']['needs'] = needs kwargs['params']['fields'] = fields kwargs['languages'] = get_languages() def decorator(func): # cls = getattr(inspect.getmodule(func), # func.__qualname__.split('.<locals>', 1)[0].rsplit('.', 1)[0]) func.bind_to_methods = [kwargs.pop('method', 'POST'), ] func.detail = True func.action_type = 'custom' func.action_kwargs = action_kwargs(icon_class, btn_class, text, func, kwargs) func.kwargs = {} func.action_kwargs['params']['model'] = '{}/{}/{}'.format( target_model._meta.app_label.lower(), inflector.pluralize(target_model._meta.model_name.lower()), func.__name__ ) func.serializer = serializer return Adapter.adapt_wizard(func) return decorator
class EnglishInflectorTestCase(unittest.TestCase): singular_to_plural = { "search" : "searches", "switch" : "switches", "fix" : "fixes", "box" : "boxes", "process" : "processes", "address" : "addresses", "case" : "cases", "stack" : "stacks", "wish" : "wishes", "fish" : "fish", "category" : "categories", "query" : "queries", "ability" : "abilities", "agency" : "agencies", "movie" : "movies", "archive" : "archives", "index" : "indices", "wife" : "wives", "safe" : "saves", "half" : "halves", "move" : "moves", "salesperson" : "salespeople", "person" : "people", "spokesman" : "spokesmen", "man" : "men", "woman" : "women", "basis" : "bases", "diagnosis" : "diagnoses", "datum" : "data", "medium" : "media", "analysis" : "analyses", "node_child" : "node_children", "child" : "children", "experience" : "experiences", "day" : "days", "comment" : "comments", "foobar" : "foobars", "newsletter" : "newsletters", "old_news" : "old_news", "news" : "news", "series" : "series", "species" : "species", "quiz" : "quizzes", "perspective" : "perspectives", "ox" : "oxen", "photo" : "photos", "buffalo" : "buffaloes", "tomato" : "tomatoes", "dwarf" : "dwarves", "elf" : "elves", "information" : "information", "equipment" : "equipment", "bus" : "buses", "status" : "statuses", "mouse" : "mice", "louse" : "lice", "house" : "houses", "octopus" : "octopi", "virus" : "viri", "alias" : "aliases", "portfolio" : "portfolios", "vertex" : "vertices", "matrix" : "matrices", "axis" : "axes", "testis" : "testes", "crisis" : "crises", "rice" : "rice", "shoe" : "shoes", "horse" : "horses", "prize" : "prizes", "edge" : "edges" } def setUp(self): self.inflector = Inflector(English) def tearDown(self): self.inflector = None def test_pluralize(self) : for singular in self.singular_to_plural.keys() : assert self.inflector.pluralize(singular) == self.singular_to_plural[singular], \ 'English Inlector pluralize(%s) should produce "%s" and NOT "%s"' % (singular, self.singular_to_plural[singular], self.inflector.pluralize(singular)) def test_singularize(self) : for singular in self.singular_to_plural.keys() : assert self.inflector.singularize(self.singular_to_plural[singular]) == singular, \ 'English Inlector singularize(%s) should produce "%s" and NOT "%s"' % (self.singular_to_plural[singular], singular, self.inflector.singularize(self.singular_to_plural[singular]))
class Endpoint(object): base_serializer = import_string(settings.BASE_SERIALIZER) base_viewset = import_string(settings.BASE_VIEWSET) base_readonly_viewset = import_string(settings.BASE_READONLY_VIEWSET) model = None fields = None serializer = None fieldsets = None list_display = None list_editable = None extra_fields = None permission_classes = None filter_fields = None search_fields = None ordering_fields = None page_size = None viewset = None read_only = False include_str = True list_me = True save_twice = False sortable_by = None custom_actions = None bulk_actions = None inflector_language = import_string(settings.INFLECTOR_LANGUAGE) _translated_fields = None _translated_field_names = None _default_language_field_names = None def __init__(self, model=None, **kwargs): self.inflector = Inflector(self.inflector_language) if model is not None: self.model = model arg_names = ('fields', 'serializer', 'permission_classes', 'filter_fields', 'search_fields', 'viewset', 'read_only', 'include_str', 'ordering_fields', 'page_size', 'base_viewset', 'fields_annotation', 'fieldsets', 'base_serializer', 'list_me') for arg_name in arg_names: setattr(self, arg_name, kwargs.pop(arg_name, getattr(self, arg_name, None))) if len(kwargs.keys()) > 0: raise Exception( '{} got an unexpected keyword argument: "{}"'.format( self.__class__.__name__, list(kwargs.keys())[0])) if self.serializer is not None: assert self.fields is None, 'You cannot specify both fields and serializer' else: assert self.viewset is not None or self.model is not None, \ 'You need to specify at least a model or a viewset' self.get_serializer() if self.viewset is not None: for attr in ('permission_classes', 'filter_fields', 'search_fields', 'ordering_fields', 'page_size'): assert getattr(self, attr, None) is None, \ 'You cannot specify both {} and viewset'.format(attr) else: self.get_viewset() if self.model is None: self.model = self.get_serializer().Meta.model def get_languages(self): return get_languages() @property def singular_model_name(self): return self.model._meta.model_name.lower() @property def model_name(self): return self.inflector.pluralize(self.singular_model_name) @property def application_name(self): return self.model._meta.app_label.lower() def get_fields_for_serializer(self): if self.fields is None: self.fields = tuple([ f for f in get_all_field_names(self.model) if f not in self.default_language_field_names ]) if self.extra_fields is not None: self.fields += tuple(self.extra_fields) if self.include_str: self.fields += ('__str__', ) return self.fields def get_serializer(self, data=None): if self.serializer is None: if self.viewset is None: self.serializer = serializer_factory(self) else: self.serializer = self.viewset.serializer_class if data is None: return self.serializer return self.serializer(data) def get_base_viewset(self): return self.base_viewset if not self.read_only or self.base_viewset != viewsets.ModelViewSet \ else self.base_readonly_viewset def get_viewset(self): if self.viewset is None: self.viewset = viewset_factory(self) return self.viewset def get_url(self): return '{}/{}'.format(self.application_name.replace('_', '-'), self.model_name.replace('_', '-')) def _get_field_dict(self, field): return get_field_dict(field, self.get_serializer(), self.get_translated_fields(), self.fields_annotation, self.model) def get_fields(self): return [ self._get_field_dict(field) for field in self.get_fields_for_serializer() ] def get_fieldsets(self): if self.fieldsets is not None: return [{ 'key': field } if not isinstance(field, dict) else field for field in self.fieldsets] return [{ 'key': field } for field in self.get_fields_for_serializer() if field != 'id' and field != '__str__' and field not in self.translated_field_names and self._get_field_dict(field)['type'][:6] != 'tomany'] def get_list_display(self): if self.list_display is None: if '__str__' in self.get_fields_for_serializer(): return [ '__str__', ] return [self.get_fields()[0]['key']] return self.list_display def _get_endpoint_list(self, name): value = getattr(self, name, None) if value is None: return [] return value def get_filter_fields(self): fields = self._get_endpoint_list('filter_fields') return fields @property def search_enabled(self): fields = self._get_endpoint_list('search_fields') return len(fields) > 0 def get_ordering_fields(self): fields = self._get_endpoint_list('ordering_fields') return fields def get_needs(self): related_models = [ f.related_model if f.related_model else f.model if f.model and f.model != self.model else None for f in self.model._meta.get_fields() if f.is_relation and f.name in self.get_fields_for_serializer() ] return [{ 'app': model._meta.app_label, 'singular': model._meta.model_name.lower(), 'plural': self.inflector.pluralize(model._meta.model_name.lower()), } for model in related_models] def get_list_editable(self): if self.list_editable is None: return [] return self.list_editable def get_sortable_by(self): return self.sortable_by def get_translated_fields(self): if self._translated_fields is None: models = translator.get_registered_models() if self.model in models: options = translator.get_options_for_model(self.model) rv = [field for field in options.fields] self._translated_fields = rv else: self._translated_fields = [] return self._translated_fields @property def translated_field_names(self): if self._translated_field_names is None: rv = [] for field in self.get_translated_fields(): for language in self.get_languages(): l = language.replace('-', '_') rv.append('{}_{}'.format(field, l)) self._translated_field_names = rv return self._translated_field_names @property def default_language_field_names(self): from django.conf import settings as django_settings if self._default_language_field_names is None: l = django_settings.LANGUAGE_CODE.replace('-', '_') rv = [] for field in self.get_translated_fields(): rv.append('{}_{}'.format(field, l)) self._default_language_field_names = rv return self._default_language_field_names def get_custom_actions(self): rv = [] viewset = self.get_viewset() for action_name in dir(viewset): action = getattr(viewset, action_name) if getattr(action, 'action_type', None) == 'custom': custom_action = { 'url': reverse('{}-{}'.format(self.get_url(), action.__name__.lower()), kwargs={'pk': ':id'}), 'verb': action.bind_to_methods[0], } custom_action.update(action.action_kwargs) rv.append(custom_action) if self.custom_actions is not None: rv += self.custom_actions return rv def get_bulk_actions(self): rv = [] viewset = self.get_viewset() for action_name in dir(viewset): action = getattr(viewset, action_name) if getattr(action, 'action_type', None) == 'bulk': bulk_action = { 'url': reverse('{}-{}'.format(self.get_url(), action.__name__.lower())), 'verb': action.bind_to_methods[0], } bulk_action.update(action.action_kwargs) rv.append(bulk_action) if self.bulk_actions is not None: rv += [] return rv
def wizard(target_model, serializer=None, icon_class=None, btn_class=None, text=None, meta_type='custom', **kwargs): if serializer is None and target_model is not None: serializer = target_model target_model = None assert serializer is not None, "You need to pass a serializer to the wizard decorator" assert meta_type in ['custom', 'list'] inflector_language = import_string(settings.INFLECTOR_LANGUAGE) inflector = Inflector(inflector_language) _kwargs = { 'type': 'wizard', 'params': {}, } _kwargs.update(kwargs) kwargs = _kwargs kwargs['params']['fieldsets'] = kwargs.pop('fieldsets', None) serializer_instance = serializer() needs = [] fields = [] Adapter = import_string(settings.METADATA_ADAPTER) for field_name, field in serializer_instance.fields.items(): if isinstance(field, PrimaryKeyRelatedField): model = field.queryset.model needs.append({ 'app': model._meta.app_label, 'singular': model._meta.model_name.lower(), 'plural': inflector.pluralize(model._meta.model_name.lower()), }) fields.append( Adapter.adapt_field(get_field_dict(field_name, serializer))) kwargs['params']['needs'] = needs kwargs['params']['fields'] = fields kwargs['languages'] = get_languages() def decorator(func): def wizard_func(self, request, *args, **kwargs): Serializer = serializer serializer_instance = Serializer(data=request.data) if not serializer_instance.is_valid(): return Response(serializer_instance.errors, status=400) request.validated_data = serializer_instance.validated_data return func(self, request, *args, **kwargs) wizard_func.__name__ = func.__name__ if meta_type == 'custom': detail = True else: detail = False if action is not None: wizard_func = action(methods=[kwargs.pop('method', 'post')], detail=detail, **kwargs) # NoQA wizard_func.__name__ = func.__name__ else: wizard_func.bind_to_methods = [ kwargs.pop('method', 'POST'), ] wizard_func.detail = detail wizard_func.action_type = meta_type wizard_func.wizard = True wizard_func.action_kwargs = action_kwargs(icon_class, btn_class, text, wizard_func, kwargs) wizard_func.kwargs = {} if target_model is not None: wizard_func.action_kwargs['params']['model'] = '{}/{}/{}'.format( target_model._meta.app_label.lower().replace('_', '-'), inflector.pluralize(target_model._meta.model_name.lower()), wizard_func.__name__) print(wizard_func.action_kwargs['params']['model']) wizard_func.serializer = serializer return Adapter.adapt_wizard(wizard_func) return decorator
class EnglishInflectorTestCase(unittest.TestCase): singular_to_plural = { "search": "searches", "switch": "switches", "fix": "fixes", "box": "boxes", "process": "processes", "address": "addresses", "case": "cases", "stack": "stacks", "wish": "wishes", "fish": "fish", "category": "categories", "query": "queries", "ability": "abilities", "agency": "agencies", "movie": "movies", "archive": "archives", "index": "indices", "wife": "wives", "safe": "saves", "half": "halves", "move": "moves", "salesperson": "salespeople", "person": "people", "spokesman": "spokesmen", "man": "men", "woman": "women", "basis": "bases", "diagnosis": "diagnoses", "datum": "data", "medium": "media", "analysis": "analyses", "node_child": "node_children", "child": "children", "experience": "experiences", "day": "days", "comment": "comments", "foobar": "foobars", "newsletter": "newsletters", "old_news": "old_news", "news": "news", "series": "series", "species": "species", "quiz": "quizzes", "perspective": "perspectives", "ox": "oxen", "photo": "photos", "buffalo": "buffaloes", "tomato": "tomatoes", "dwarf": "dwarves", "elf": "elves", "information": "information", "equipment": "equipment", "bus": "buses", "status": "statuses", "mouse": "mice", "louse": "lice", "house": "houses", "octopus": "octopi", "virus": "viri", "alias": "aliases", "portfolio": "portfolios", "vertex": "vertices", "matrix": "matrices", "axis": "axes", "testis": "testes", "crisis": "crises", "rice": "rice", "shoe": "shoes", "horse": "horses", "prize": "prizes", "edge": "edges" } def setUp(self): self.inflector = Inflector(English) def tearDown(self): self.inflector = None def test_pluralize(self): for singular in self.singular_to_plural.keys(): assert self.inflector.pluralize(singular) == self.singular_to_plural[singular], \ 'English Inlector pluralize(%s) should produce "%s" and NOT "%s"' % (singular, self.singular_to_plural[singular], self.inflector.pluralize(singular)) def test_singularize(self): for singular in self.singular_to_plural.keys(): assert self.inflector.singularize(self.singular_to_plural[singular]) == singular, \ 'English Inlector singularize(%s) should produce "%s" and NOT "%s"' % (self.singular_to_plural[singular], singular, self.inflector.singularize(self.singular_to_plural[singular]))
def __new__(cls, name, bases, attrs): new_class = super(EndpointMetaClass, cls).__new__(cls, name, bases, attrs) inflector = None processed = [] black_list = dir(BaseEndpoint) model = getattr(new_class, 'model', None) for base in reversed(new_class.__mro__): for key, value in list(base.__dict__.items()): if key not in black_list and key not in processed and hasattr( value, 'wizard') and value.wizard: if getattr(value, 'action_kwargs', {}).get( 'params', {}).get('model', None) is None: if model is not None: if inflector is None: inflector_language = import_string( settings.INFLECTOR_LANGUAGE) inflector = Inflector(inflector_language) getattr(new_class, key).action_kwargs['params'][ 'model'] = '{}/{}/{}'.format( model._meta.app_label.lower(), inflector.pluralize( model._meta.model_name.lower()), value.__name__) processed.append(key) if getattr(value, 'action_kwargs', {}).get('params', {}).get('fieldsets', None) is None \ and getattr(new_class, 'model', None) is not None and hasattr(value, 'serializer'): fieldsets_path = os.path.join( django_settings.BASE_DIR, new_class.__module__.rsplit('.', 1)[0], 'fieldsets.json') try: with open(fieldsets_path, 'r') as f: fieldsets = json.load(f) value.action_kwargs['params']['fieldsets'] = \ fieldsets['{}_{}'.format(new_class.model.__name__, key)] except FileNotFoundError: pass except KeyError: pass if getattr(value, 'action_kwargs', {}).get( 'params', {}).get('fieldsets', None) is None: value.action_kwargs = getattr( value, 'action_kwargs', {}) value.action_kwargs[ 'params'] = value.action_kwargs.get( 'params', {}) value.action_kwargs['params']['fieldsets'] = [{ 'name': field } for field in value.serializer.Meta.fields] if new_class.fieldsets is None and new_class.model is not None: fieldsets_path = os.path.join( django_settings.BASE_DIR, new_class.__module__.rsplit('.', 1)[0], 'fieldsets.json') try: with open(fieldsets_path, 'r') as f: fieldsets = json.load(f) new_class.fieldsets = fieldsets[new_class.model.__name__] except FileNotFoundError: pass except KeyError: pass return new_class
class SpanishInflectorTestCase(unittest.TestCase): singular_to_plural = { "álbum": "álbumes", "almacén": "almacenes", "androide": "androides", "antifaz": "antifaces", "árbol": "árboles", "atlas": "atlas", "autobús": "autobuses", "base": "bases", "bebé": "bebés", "camión": "camiones", "casa": "casas", "ceutí": "ceutíes", "chimpancé": "chimpancés", "clan": "clanes", "compás": "compases", "convoy": "convoyes", "coxis": "coxis", "crisis": "crisis", "déficit": "déficits", "eje": "ejes", "espíritu": "espíritus", "flash": "flashes", "frac": "fracs", "gafas": "gafas", "hipótesis": "hipótesis", "inglés": "ingleses", "lápiz": "lápices", "luz": "luces", "montaje": "montajes", "no": "noes", "otitis": "otitis", "padre": "padres", "país": "países", "papá": "papás", "parking": "parkings", "portaequipaje": "portaequipajes", "radiocasete": "radiocasetes", "show": "shows", "si": "sis", "sí": "síes", "tabú": "tabúes", "tamiz": "tamices", "tanque": "tanques", "taxi": "taxis", "tijeras": "tijeras", "tren": "trenes", "virus": "virus", } def setUp(self): self.inflector = Inflector(Spanish) def tearDown(self): self.inflector = None def test_pluralize(self): for singular, plural in self.singular_to_plural.iteritems(): inflector_pluralize = self.inflector.pluralize(singular) assert inflector_pluralize == plural, \ 'Spanish Inflector pluralize(%s) should produce "%s" and NOT "%s"' % ( singular, plural, inflector_pluralize) def test_singularize(self): for singular, plural in self.singular_to_plural.iteritems(): inflector_singularize = self.inflector.singularize(plural) assert inflector_singularize == singular, \ 'Spanish Inflector singularize(%s) should produce "%s" and NOT "%s"' % ( plural, singular, inflector_singularize)