def _init_users(): """ Initialize user data. """ for status in User.STATUS: db.add(UserStatus(status.value, titleize(status.name))) db.flush() for permission in PERMISSION: db.add(Permission(permission.value, pluralize(titleize(permission.name)))) db.flush() # user records users_stream = pkg_resources.resource_stream('dx.orm', os.path.join('data', 'users.tsv')) for row in csv.DictReader(users_stream, delimiter='\t'): user = User(row['email'], app.config['DEFAULT_PASSWORD'], row['name']) user.status_id = int(User.STATUS.ACTIVE) user.confirmed = True user.force_password_reset = True user.bio = UserBio() if row['permissions']: for permission_id in row['permissions'].split(','): user.permissions[permission_id] = Permission.query.get(permission_id) db.add(user) db.flush() db.add(Project('test', 'Test', User.query.first())) db.flush() log.info('user data initialized')
def singular_plural(n, word): if word == 0: return ('no', inflection.pluralize(word)) elif word == 1: return (1, word) else: return (str(n), inflection.pluralize(word))
def pluralize_label(label): if ' ' in label: if ' - ' in label: parts = label.split(' - ') parts[0] = pluralize_label(parts[0]) label = ' - '.join(parts) elif ' of ' in label: part = label[:label.find(' of ')] label = f'{pluralize_label(part)}{label[label.find(" of "):]}' elif ' for ' in label: part = label[:label.find(' for ')] label = f'{pluralize_label(part)}{label[label.find(" for "):]}' elif ' and ' in label: part1 = label[:label.find(' and ')] part2 = label[label.find(' and ') + 5:] label = f'{pluralize_label(part1)} and {pluralize_label(part2)}' elif ' or ' in label: part1 = label[:label.find(' or ')] part2 = label[label.find(' or ') + 4:] label = f'{pluralize_label(part1)} or {pluralize_label(part2)}' else: parts = label.split(' ') parts[-1] = pluralize(parts[-1]) label = ' '.join(parts) else: label = pluralize(label) return label
def __generate_plural_part(self, model_class_name: str): self._variables['plural_snake_case_model_name'] = inflection.pluralize( inflection.underscore(model_class_name)) self._variables['plural_camel_case_model_name'] = inflection.pluralize( inflection.camelize(model_class_name, False)) self._variables[ 'plural_pascal_case_model_name'] = inflection.pluralize( model_class_name)
def __init__(newcls, classname, supers, classdict): #: Used primarily for setting the lower-cased and underscored model name in the payload #: for post and patch operations. newcls.MODEL_NAME = inflection.underscore(newcls.__name__) #: Elasticsearch index name for the Pulsar model. newcls.ES_INDEX_NAME = inflection.pluralize(newcls.MODEL_NAME) newcls.URL = os.path.join(p.URL, inflection.pluralize(newcls.MODEL_NAME)) if getattr(newcls, "MODEL_ABBR"): Meta._MODEL_ABBREVS.append(newcls.MODEL_ABBR)
def url_deviations(s): """ Produce common REST url deviations, always lowercased because URLs. """ d = set() d.add(s.lower()) d.add(pluralize(s).lower()) d.add(underscore(s).lower()) d.add(pluralize(underscore(s)).lower()) return sorted(list(d))
def __handle_field(self, model, field_name, field_type): """ Determines what options are present with each model field. :param model: the current model :param field_name: name of model field. i.e. first_name :param field_type: type of model field. i.e. CharField :return: """ # Parse field type and name for fixtures self.__handle_fixture(field_name, field_type) # Parse field type and name for model if DEFAULT_MODEL_OPTIONS[field_type] is not None: template = 'model-field.tpl' name = None related_name = None if field_type in RELATIONSHIP_TYPES: name = 'get_user_model()' if field_name == 'user' else field_name.capitalize( ) related_name = inflection.pluralize(model.lower()) if field_type == 'ForeignKey' \ else inflection.singularize(model) # Add import if field is to be imported if name not in SPECIAL_RELATIONSHIP: self.find_resource_in_scope(field_name) self.append_import(field_name) options = Template(DEFAULT_MODEL_OPTIONS[field_type]).render( name=name, related_name=related_name, path=inflection.pluralize(field_name), ) if field_type not in UNSUPPORTED_ADMIN_FIELD_TYPES: self.__append_admin_field(field_name) return rendered_file_template(path=TEMPLATE_DIR, template=template, context={ 'name': field_name, 'type': field_type, 'options': options, 'lazy_name': field_name.replace("_", " "), })
def _camelize(cls, property=None): """Camelize the model name. :param property: :return: """ name = inflection.underscore(cls.model_name) if property is not None: name += "_" + inflection.pluralize(property) else: name = inflection.pluralize(name) name = inflection.camelize(name) name = name[0].lower() + name[1:] return name
def test_uncountable_word_is_not_greedy(): uncountable_word = "ors" countable_word = "sponsor" inflection.UNCOUNTABLES.add(uncountable_word) try: assert uncountable_word == inflection.singularize(uncountable_word) assert uncountable_word == inflection.pluralize(uncountable_word) assert inflection.pluralize(uncountable_word) == inflection.singularize(uncountable_word) assert "sponsor" == inflection.singularize(countable_word) assert "sponsors" == inflection.pluralize(countable_word) assert "sponsor" == inflection.singularize(inflection.pluralize(countable_word)) finally: inflection.UNCOUNTABLES.remove(uncountable_word)
def get_plural_inflection(self, word): """Gets proper plural inflection for a word. e.g. model: cat, collection: cats model: cactus, collection: cacti """ return inflection.pluralize(word)
def _configure_sideloads(self, meta): """ Assemble configuration for each sideload. """ self.sideloads = [] configs = [] for conf in getattr(meta, 'sideloads', []): assert isinstance(conf, tuple) and len(conf) >= 2 \ and len(conf) <= 3, ( '`Meta.sideloads` must be a list of tuples in the following ' 'format: (<model class>, <serializer class>, ' '<queryset instance (optional)>)' ) model, serializer = conf[:2] queryset = conf[0].objects.all() if (len(conf) == 2) else conf[2] configs.append((model, serializer, queryset)) relations = get_field_info(self.model).relations fields = self.base_serializer.fields.values() for field_name, relation_info in relations.items(): try: related_model = compat.get_related_model(relation_info) conf = configs[[t[0] for t in configs].index(related_model)] except ValueError: continue field = fields[[f.source for f in fields].index(field_name)] key_name = getattr(conf[1].Meta, 'base_key', underscore(conf[0].__name__)) self.sideloads.append( Sideload(field=field, model=conf[0], serializer=conf[1], queryset=conf[2], key_name=pluralize(key_name)))
def render(self, data, accepted_media_type=None, renderer_context=None): view = renderer_context.get('view') resource_name = get_resource_name(view) if isinstance(data, dict): for key, value in data.items(): data[inflection.camelize(key, False)] = data.pop(key) elif isinstance(data, (list, tuple)): for obj in data: if hasattr(obj, 'items'): for key, value in obj.items(): obj[inflection.camelize(key, False)] = obj.pop(key) resource_name = inflection.pluralize(resource_name) if resource_name == False: return super(JSONRenderer, self).render( data, accepted_media_type, renderer_context) try: data_copy = copy.copy(data) content = data_copy.pop('results') data = {resource_name : content, "meta" : data_copy} except (TypeError, KeyError, AttributeError) as e: data = {resource_name : data} return super(JSONRenderer, self).render( data, accepted_media_type, renderer_context)
def scaffold_content_components(): cfg = get_cfg() title = cfg['current_scaffold']['model']['title'] need_owner = cfg['current_scaffold']['need_owner'] == 'True' content_plural = pluralize(title.lower()) # Get the directory mkdir('$out/components/' + content_plural) comps = f('$out/components/' + content_plural, '$') # Make the files create_asset = parse_content( f('$assets/components/content_plural/Create.js', 'r')) f(comps + '/Create.js', 'w', create_asset) details_asset = parse_content( f('$assets/components/content_plural/Details.js', 'r')) f(comps + '/Details.js', 'w', details_asset) list_asset = parse_content( f('$assets/components/content_plural/List.js', 'r')) f(comps + '/List.js', 'w', list_asset) update_asset = parse_content( f('$assets/components/content_plural/Update.js', 'r')) f(comps + '/Update.js', 'w', update_asset) delete_asset = parse_content( f('$assets/components/content_plural/Delete.js', 'r')) f(comps + '/Delete.js', 'w', delete_asset)
def parse(self): """ Parse the configuration file Parsing is a three step process: 1) Read the cloud specific configurations 2) Read the topology specification 3) Add the cloud specific configuration to the topology configuration. """ self._tree = ET.parse(self._file) # 1) Read the cloud specific configurations self.read_cloud_configuration() for entity in Entity.entities(): classify = inflection.camelize(inflection.singularize(entity)) dasherize = inflection.dasherize(inflection.underscore(classify)) pluralize = inflection.pluralize(dasherize) add_name = 'add_' + inflection.underscore(dasherize) ext_name = 'extend_' + inflection.underscore(dasherize) path = './' + pluralize + '/' + dasherize # 2) Parse topology specific configuration self._parse_group('./' + pluralize + '/' + dasherize, getattr(self, add_name)) # 3) Parse cloud specific configuration for topology self._parse_group( './' + self.cloud + '/' + pluralize + '/add-values', getattr(self, ext_name))
def configure_count(self, ns, definition): """ Register a count endpoint. The definition's func should be a count function, which must: - accept kwargs for the query string - return a count is the total number of items available The definition's request_schema will be used to process query string arguments. :param ns: the namespace :param definition: the endpoint definition """ @self.add_route(ns.collection_path, Operation.Count, ns) @qs(definition.request_schema) @wraps(definition.func) def count(**path_data): request_data = load_query_string_data(definition.request_schema) response_data = dict() count = definition.func(**merge_data(path_data, request_data)) headers = encode_count_header(count) definition.header_func(headers, response_data) response_format = self.negotiate_response_content(definition.response_formats) return dump_response_data( None, None, headers=headers, response_format=response_format, ) count.__doc__ = "Count the size of the collection of all {}".format(pluralize(ns.subject_name))
def get_subject_properties(parsed_tokens, verb_token, object_token, ner_tagger, sentence): list_of_subjects = [subj_token for subj_token in parsed_tokens if subj_token.dep_ == "nsubj" and subj_token.head is verb_token] if len(list_of_subjects) == 1: subj_token = list_of_subjects[0] subject_word = subj_token.orth_.lower() #if the verb conjugation is singular 3rd person for sure if (verb_token.tag_ == u'VBZ') or ((verb_token.tag_ == u'VBG' or verb_token.tag_ == u'VBN') and [aux_verb_token for aux_verb_token in parsed_tokens if aux_verb_token.dep_ == u'aux' and aux_verb_token.head is verb_token and aux_verb_token.tag_ == u'VBZ']): return person_or_not (sentence, subject_word, ner_tagger, parsed_tokens, verb_token, subj_token) #check if it's in the tiny pronoun dictionary if subject_word in possessive_dictionary: return [person_dictionary[subject_word], number_dictionary[subject_word], possessive_dictionary[subject_word]] #if the subject is not 'i' or 'you' or 'we' and the verb form is not 3rd person singular if (verb_token.tag_ == u'VBP') or ((verb_token.tag_ == u'VBG' or verb_token.tag_ == u'VBN') and [aux_verb_token for aux_verb_token in parsed_tokens if aux_verb_token.dep_ == u'aux' and aux_verb_token.head is verb_token and aux_verb_token.tag_ == u'VBP']): return [3, 2, u'their'] """#if the subject has a conjunction compounded_subjects = [tok.orth_.lower() for tok in parsed_tokens if tok.dep_ == "conj" and tok.head is subj_token] if compounded_subjects: if [tok for tok in parsed_tokens if tok.orth_.lower() == "and" and tok.dep_ == "cc" and tok.head is subj_token]: if u'i' in compounded_subjects: return [1, 2, u'our'] elif 'you' in compounded_subjects: return [2, 2, u'your'] else: return [3, 2, u'their']""" #if the subject is plural according to the inflector, and the verb form is not singular - doing this test only for dictionary words and not for NEs which were not detected if wn.synsets(subj_token.lemma_.lower(), pos=wn.NOUN) and inflection.pluralize(subject_word) == subject_word and inflection.singularize(subject_word) != subject_word: return [3, 2, u'their'] else: return None
def configure_deletefor(self, ns, definition): """ Register a delete-for relation endpoint. The definition's func should be a delete function, which must: - accept kwargs for path data - return truthy/falsey :param ns: the namespace :param definition: the endpoint definition """ @self.add_route(ns.relation_path, Operation.DeleteFor, ns) @wraps(definition.func) def delete(**path_data): headers = dict() response_data = dict() require_response_data(definition.func(**path_data)) definition.header_func(headers, response_data) response_format = self.negotiate_response_content( definition.response_formats) return dump_response_data( "", None, status_code=Operation.DeleteFor.value.default_code, headers=headers, response_format=response_format, ) delete.__doc__ = "Delete a {} relative to a {}".format( pluralize(ns.object_name), ns.subject_name)
def test_that_registry_exposes_properties(): # Assert that lowercased, underscored, pluralized methods # are attached to registry for each element type assert all( inflection.pluralize(inflection.underscore(element_type.value.lower())) for element_type in DomainObjects )
class Meta(AbstractDocumentManagementModel.Meta): """Meta class definition""" abstract = False db_table = db_table(app_label, _annotation) verbose_name = _(_annotation_verbose) verbose_name_plural = _(pluralize(_annotation_verbose)) unique_together = ('client', 'name')
def __resources(self, resource): """ Print the vanilla listing for a resource. """ resource = inflection.pluralize(resource) items = getattr(self.dao, resource)() self.fmt.print_list(items, self.headers[resource])
def pluralize(word: str, collection: Union[Sized, int]) -> str: """ Pluralize the given word, based off of either a sized collection or off an item count. """ count = collection if isinstance(collection, int) else len(collection) return word if count == 1 else inflection.pluralize(word)
def main(): if len(sys.argv) == 1: raise Exception('expected one argument: concept name is missing!') candidate_app_packages = [p for p in Path.cwd().glob('src/ekklesia_*') if not '.' in p.name] if not candidate_app_packages: raise Exception('app package in src cannot be found. Did you run the script from the root directory of a ekklesia project?') if len(candidate_app_packages) > 1: raise Exception('Multiple candidates for the app package in src!') app_package = candidate_app_packages[0] concepts_package = app_package / 'concepts' concept_name = sys.argv[1] concept_name_plural = inflection.pluralize(concept_name) concept_name_camelcase_upper = case_conversion.pascalcase(concept_name) concept_name_camelcase_upper_plural = case_conversion.pascalcase(concept_name_plural) extra_context = { 'app_package': app_package.name, 'concept_name': concept_name, 'concept_names': concept_name_plural, 'ConceptName': concept_name_camelcase_upper, 'ConceptNames': concept_name_camelcase_upper_plural } run_cookiecutter(COOKIECUTTER_TEMPLATE, output_dir=concepts_package, no_input=True, extra_context=extra_context) print(f"generated concept {concepts_package / concept_name}, tests are located at tests/concepts/{concept_name}")
def calculate_offsets(self, text, applicable_terms, exclusions=[]): """Search for defined terms in this text, with a preference for all larger (i.e. containing) terms.""" # don't modify the original exclusions = list(exclusions) # add plurals to applicable terms pluralized = [(pluralize(t[0]), t[1]) for t in applicable_terms] applicable_terms += pluralized # longer terms first applicable_terms.sort(key=lambda x: len(x[0]), reverse=True) matches = [] for term, ref in applicable_terms: re_term = ur'\b' + re.escape(term) + ur'\b' offsets = [ (m.start(), m.end()) for m in re.finditer(re_term, text.lower())] safe_offsets = [] for start, end in offsets: # Start is contained in an existing def if any(start >= e[0] and start <= e[1] for e in exclusions): continue # End is contained in an existing def if any(end >= e[0] and end <= e[1] for e in exclusions): continue safe_offsets.append((start, end)) if not safe_offsets: continue exclusions.extend(safe_offsets) matches.append((term, ref, safe_offsets)) return matches
def invert_singular_plural_noun(doc, pos_tags, sent): nouns_count = pos_tags.count("NN") + pos_tags.count("NNS") rand_noun_index = random.randint(0, nouns_count - 1) current_noun_count = 0 word_to_change = None is_plural = False for index, word in enumerate(doc): # text = word.text if word.tag_ == 'NN' or word.tag_ == 'NNS': if current_noun_count == rand_noun_index: word_to_change = word.text if word.tag_ == 'NNS': is_plural = True break else: current_noun_count += 1 inverted_word = None m = re.search(r'(^|\b)%s\b' % word_to_change, sent) if m: if is_plural: inverted_word = inflection.singularize(word_to_change) else: inverted_word = inflection.pluralize(word_to_change) alt_s = re.sub(r'(?<=(^|\b))%s(?=\b)' % word_to_change, inverted_word, sent, count=1) return alt_s # print(word_to_change) # print(sent) return None
def create_remote_arr_fk_ish_relationships(self, tables_schema, remote, remote_tables_schema): fk_constrnts = self.pg.get_all_fk_constraints(tables_schema) for (_, _, t, c, fs, ft, _) in fk_constrnts: rel_name = 'remote_' + inflection.pluralize(t) + '_by_' + c query ={ 'type': 'create_remote_relationship', 'args' : { 'name' : rel_name, 'table' : { 'schema': fs, 'name': ft }, 'remote_schema': remote, 'hasura_fields': ['id'], 'remote_field': { remote_tables_schema + '_' + t : { 'arguments' : { 'where': { c : { '_eq': '$id' } } } } } } } print(query) self.v1q(query)
def _configure_sideloads(self, meta): """ Assemble configuration for each sideload. """ self.sideloads = [] configs = [] for conf in getattr(meta, 'sideloads', []): assert isinstance(conf, tuple) and len(conf) >= 2 \ and len(conf) <= 3, ( '`Meta.sideloads` must be a list of tuples in the following ' 'format: (<model class>, <serializer class>, ' '<queryset instance (optional)>)' ) model, serializer = conf[:2] queryset = conf[0].objects.all() if (len(conf) == 2) else conf[2] configs.append((model, serializer, queryset)) relations = get_field_info(self.model).relations fields = self.base_serializer.fields.values() for field_name, info in relations.items(): try: conf = configs[[t[0] for t in configs].index(info.related)] except ValueError: continue field = fields[[f.source for f in fields].index(field_name)] key_name = getattr(conf[1].Meta, 'base_key', underscore(conf[0].__name__)) self.sideloads.append(Sideload( field=field, model=conf[0], serializer=conf[1], queryset=conf[2], key_name=pluralize(key_name) ))
def _process(self): # TODO, include try catch for database errors? if self._parser.link: target_class = self._cfg.api_manager.get_model( self._cfg.resource_name_case(self._parser.link)) join_class = self._cfg.model_class else: target_class = self._cfg.model_class join_class = None if len(self._parser.idents) > 0: resources = self._get_all_or_404(self._parser.idents, target_class, join_class) else: resources = self._get_all(target_class) # Should we render response as a list? - tricky logic here # if no route parm ids or, # if route parm ids provided is more than 1 & it's not a link resource # or, if it's a link resource and the link name is plural, # then true, otherwise false self._render_as_list = ( (len(self._parser.idents) == 0) or (len(self._parser.idents) > 1 and self._parser.link is None) or (self._parser.link and self._parser.link == pluralize( self._parser.link))) self._process_includes_for(resources) self._resources.extend(resources)
async def act(self, ctx, *, target: Union[discord.Member, str] = None): """ Acts on the specified user. """ if not target or isinstance(target, str): return # no help text action = inflection.humanize(ctx.invoked_with).split() iverb = -1 for cycle in range(2): if iverb > -1: break for i, act in enumerate(action): act = act.lower() if (act in NOLY_ADV or act in CONJ or (act.endswith("ly") and act not in LY_VERBS) or (not cycle and act in SOFT_VERBS)): continue action[i] = inflection.pluralize(action[i]) iverb = max(iverb, i) if iverb < 0: return action.insert(iverb + 1, target.mention) await ctx.send(italics(" ".join(action)))
def configure_replacefor(self, ns, definition): """ Register a replace-for relation endpoint. For typical usage, this relation is not strictly required; once an object exists and has its own ID, it is better to operate on it directly via dedicated CRUD routes. However, in some cases, the composite key of (subject_id, object_id) is required to look up the object. This happens, for example, when using DynamoDB where an object which maintains both a hash key and a range key requires specifying them both for access. The definition's func should be a replace function, which must: - accept kwargs for the new instance replacement parameters - return the instance :param ns: the namespace :param definition: the endpoint definition """ @self.graph.route(ns.relation_path, Operation.ReplaceFor, ns) @request(definition.request_schema) @response(definition.response_schema) def replace(**path_data): request_data = load_request_data(definition.request_schema) response_data = require_response_data( definition.func(**merge_data(path_data, request_data))) return dump_response_data( definition.response_schema, response_data, Operation.ReplaceFor.value.default_code, ) replace.__doc__ = "Replace a {} relative to a {}".format( pluralize(ns.object_name), ns.subject_name)
def expose(self, model, route='/api', access_control=None, resource_class=Resource, **kwargs): """ this adds methods for updating/adding the objects defined by model eg: if you expose User(MongoModel) class this will add POST /api/users => create PUT /api/users/:id: => update PATCH /api/user/:id: => update DELETE /api/user/:id: => delete GET /api/user/:id: => returns user GET /api/users => returns all users (you can use ?limit=... ) """ endpoint_path = route + '/' + inflection.pluralize(inflection.underscore(model.__name__)) endpoint = endpoint_path resource = Resource(model=model, access_control=access_control) self._add_api_method(endpoint_path, resource.list_, methods=['GET'], endpoint=endpoint + '/list') self._add_api_method('%s/<id>' % endpoint_path, resource.get_, methods=['GET'], endpoint=endpoint + '/get') self._add_api_method(endpoint_path, resource.put_, methods=['PUT'], endpoint=endpoint + '/put') self._add_api_method('%s/<id>' % endpoint_path, resource.delete_, methods=['DELETE'], endpoint=endpoint + '/delete') self._add_api_method(endpoint_path, resource.post_, methods=['POST'], endpoint=endpoint + 'post') self._add_api_method('%s/<id>' % endpoint_path, resource.patch_, methods=['PATCH'], endpoint=endpoint + 'patch')
def get_dataset_description(self): final_scores = self.get_dataset_class_scores() top_word = self.tree.classes[np.argmax(final_scores)] description = 'This dataset is about {0}.'.format(pluralize(top_word)) self.vprint('\n\n dataset description:', description, '\n\n') return (description)
def _get_entity_ids(field_name, attrs): """Find the IDs for a one to many relationship. The server may return JSON data in the following forms for a :class:`nailgun.entity_fields.OneToManyField`:: 'user': [{'id': 1, …}, {'id': 42, …}] 'users': [{'id': 1, …}, {'id': 42, …}] 'user_ids': [1, 42] Search ``attrs`` for a one to many ``field_name`` and return its ID. :param field_name: A string. The name of a field. :param attrs: A dict. A JSON payload as returned from a server. :returns: An iterable of entity IDs. """ field_name_ids = field_name + '_ids' plural_field_name = pluralize(field_name) if field_name_ids in attrs: return attrs[field_name_ids] elif field_name in attrs: return [entity['id'] for entity in attrs[field_name]] elif plural_field_name in attrs: return [entity['id'] for entity in attrs[plural_field_name]] else: raise MissingValueError( 'Cannot find a value for the "{0}" field. Searched for keys named ' '{1}, but available keys are {2}.' .format( field_name, (field_name_ids, field_name, plural_field_name), attrs.keys() ) )
def _process(self): # TODO, include try catch for database errors? if self._parser.link: target_class = self._cfg.api_manager.get_model( self._cfg.resource_name_case(self._parser.link)) join_class = self._cfg.model_class else: target_class = self._cfg.model_class join_class = None if len(self._parser.idents) > 0: resources = self._get_all_or_404(self._parser.idents, target_class, join_class) else: resources = self._get_all(target_class) # Should we render response as a list? - tricky logic here # if no route parm ids or, # if route parm ids provided is more than 1 & it's not a link resource # or, if it's a link resource and the link name is plural, # then true, otherwise false self._render_as_list = ( (len(self._parser.idents) == 0) or (len(self._parser.idents) > 1 and self._parser.link is None) or (self._parser.link and self._parser.link == pluralize(self._parser.link))) self._process_includes_for(resources) self._resources.extend(resources)
def __init__(self, name, dbname='', display='', inherits='', database='', namespace='', idColumn='id', flags=0, columns=None, indexes=None, collectors=None): default_db_name = inflection.pluralize(inflection.underscore(name)) self.__name = name self.__dbname = dbname or default_db_name self.__database = database self.__namespace = namespace self.__flags = flags self.__inherits = inherits self.__display = display self.__cache = {} self.__idColumn = idColumn self.__model = None self.__columns = columns or {} self.__indexes = indexes or {} self.__collectors = collectors or {}
def get_resource_name(view): """ Return the name of a resource """ try: # is the resource name set directly on the view? resource_name = getattr(view, 'resource_name') except AttributeError: try: # was it set in the serializer Meta class? resource_name = getattr(view, 'serializer_class')\ .Meta.resource_name except AttributeError: # camelCase the name of the model if it hasn't been set # in either of the other places try: name = resource_name = getattr(view, 'serializer_class')\ .Meta.model.__name__ except AttributeError: try: name = view.model.__name__ except AttributeError: name = view.__class__.__name__ resource_name = name[:1].lower() + name[1:] if hasattr(view, 'action') and view.action == 'list': resource_name = inflection.pluralize(resource_name) return inflection.underscore(resource_name)
def configure_createfor(self, ns, definition): """ Register a create-for relation endpoint. The definition's func should be a create function, which must: - accept kwargs for the new instance creation parameters - return the created instance :param ns: the namespace :param definition: the endpoint definition """ @self.graph.route(ns.relation_path, Operation.CreateFor, ns) @request(definition.request_schema) @response(definition.response_schema) def create(**path_data): request_data = load_request_data(definition.request_schema) response_data = require_response_data( definition.func(**merge_data(path_data, request_data))) return dump_response_data(definition.response_schema, response_data, Operation.CreateFor.value.default_code) create.__doc__ = "Create a new {} relative to a {}".format( pluralize(ns.object_name), ns.subject_name)
def _get_entity_ids(field_name, attrs): """Find the IDs for a one to many relationship. The server may return JSON data in the following forms for a :class:`nailgun.entity_fields.OneToManyField`:: 'user': [{'id': 1, …}, {'id': 42, …}] 'users': [{'id': 1, …}, {'id': 42, …}] 'user_ids': [1, 42] Search ``attrs`` for a one to many ``field_name`` and return its ID. :param field_name: A string. The name of a field. :param attrs: A dict. A JSON payload as returned from a server. :returns: An iterable of entity IDs. """ field_name_ids = field_name + '_ids' plural_field_name = pluralize(field_name) if field_name_ids in attrs: return attrs[field_name_ids] elif field_name in attrs: return [entity['id'] for entity in attrs[field_name]] elif plural_field_name in attrs: return [entity['id'] for entity in attrs[plural_field_name]] else: raise MissingValueError( 'Cannot find a value for the "{0}" field. Searched for keys named ' '{1}, but available keys are {2}.'.format( field_name, (field_name_ids, field_name, plural_field_name), attrs.keys()))
def configure_retrievefor(self, ns, definition): """ Register a relation endpoint. The definition's func should be a retrieve function, which must: - accept kwargs for path data and optional request data - return an item The definition's request_schema will be used to process query string arguments, if any. :param ns: the namespace :param definition: the endpoint definition """ request_schema = definition.request_schema or Schema() @self.graph.route(ns.relation_path, Operation.RetrieveFor, ns) @qs(request_schema) @response(definition.response_schema) def retrieve(**path_data): request_data = load_query_string_data(request_schema) response_data = require_response_data( definition.func(**merge_data(path_data, request_data))) return dump_response_data(definition.response_schema, response_data) retrieve.__doc__ = "Retrieve {} relative to a {}".format( pluralize(ns.object_name), ns.subject_name)
def create_arr_fk_relationships(self, schema='public'): print("Creating array foreign key relationships for tables in schema ", schema) fk_constrnts = self.pg.get_all_fk_constraints(schema) queries = [] for (s, _, t, c, fs, ft, _) in fk_constrnts: rel_name = inflection.pluralize(t) + '_by_' + c queries.append({ 'type' : 'create_array_relationship', 'args': { 'table': { 'schema': fs, 'name': ft }, 'name': rel_name, 'using': { 'foreign_key_constraint_on': { 'table': { 'schema': s, 'name': t }, 'column': c } } } }) self.arr_fk_rels.add(((fs,ft),rel_name)) return self.run_bulk(queries)
def test_init(self): # If: I construct a new server object host = 'host' port = '1234' dbname = 'dbname' mock_conn = utils.MockConnection(None, name=dbname, host=host, port=port) server = Server(mock_conn) # Then: # ... The assigned properties should be assigned self.assertIsInstance(server._conn, ServerConnection) self.assertIsInstance(server.connection, ServerConnection) self.assertIs(server.connection.connection, mock_conn) self.assertEqual(server._host, host) self.assertEqual(server.host, host) self.assertEqual(server._port, int(port)) self.assertEqual(server.port, int(port)) self.assertEqual(server._maintenance_db_name, dbname) self.assertEqual(server.maintenance_db_name, dbname) self.assertTupleEqual(server.version, server._conn.version) # ... Recovery options should be a lazily loaded thing self.assertIsInstance(server._recovery_props, NodeLazyPropertyCollection) for key, collection in server._child_objects.items(): # ... The child object collection a NodeCollection self.assertIsInstance(collection, NodeCollection) # ... There should be a property mapped to the node collection prop = getattr(server, inflection.pluralize(key.lower())) self.assertIs(prop, collection)
def get_ember_json_key_for_model(model, singular=False): """ Get the key that a model's records should be nested under. """ name = model.__name__ if not singular: name = pluralize(name) return underscore(name)
def format_resource_name(obj, name): """ Pluralize the resource name if more than one object in results. """ if getattr(settings, 'REST_EMBER_PLURALIZE_KEYS', False) and isinstance(obj, list): return inflection.pluralize(name) if len(obj) > 1 else name else: return name
def get_sideload_key_name(self, model, singular=False): """ Gets the dictionary key to nest a model's instances under. """ name = model.__name__ if not singular: name = pluralize(name) return underscore(name)
def __init__(self, base): """ Initialize the serializer. :param base: Declarative base instance """ self.base = base self.models = {} for name, model in base._decl_class_registry.items(): if name.startswith('_'): continue prepped_name = underscore(pluralize(name)) api_type = getattr(model, '__jsonapi_type__', prepped_name) model.__jsonapi_attribute_descriptors__ = {} model.__jsonapi_rel_desc__ = {} model.__jsonapi_permissions__ = {} model.__jsonapi_type__ = api_type for prop_name, prop_value in iterate_attributes(model): if hasattr(prop_value, '__jsonapi_desc_for_attrs__'): defaults = {'get': None, 'set': None} descriptors = model.__jsonapi_attribute_descriptors__ for attribute in prop_value.__jsonapi_desc_for_attrs__: descriptors.setdefault(attribute, defaults) attr_desc = descriptors[attribute] attr_desc[prop_value.__jsonapi_action__] = prop_value if hasattr(prop_value, '__jsonapi_desc_for_rels__'): defaults = { 'get': None, 'set': None, 'append': None, 'remove': None } rels_desc = model.__jsonapi_rel_desc__ for relationship in prop_value.__jsonapi_desc_for_rels__: rels_desc.setdefault(attribute, defaults) rel_desc = rels_desc[relationship] rel_desc[prop_value.__jsonapi_action__] = prop_value if hasattr(prop_value, '__jsonapi_check_permission__'): defaults = { 'view': [], 'create': [], 'edit': [], 'delete': [], 'remove': [], 'append': [] } perm_obj = model.__jsonapi_permissions__ for check_for in prop_value.__jsonapi_chk_perm_for__: perm_obj.setdefault(check_for, defaults) perm_idv = perm_obj[check_for] check_perm = prop_value.__jsonapi_check_permission__ perm_idv[check_perm] = prop_value self.models[model.__jsonapi_type__] = model
def to_dasherized_plural(name): """ Pluralizes a name, as well as transforming camelCase name into dasherized formatting """ plural = inflection.pluralize(name) underscore = inflection.underscore(plural) dasherized = inflection.dasherize(underscore) return dasherized
def resolve_name(self): cls = type(self) name = getattr(cls, 'name', None) if name is None: name = cls.__name__[:-len('Resource')] name = inflection.underscore(name) name = inflection.pluralize(name) return name
def render(self, data, media_type=None, renderer_context=None): name = renderer_context['view'].get_queryset().first().__class__.__name__ name = inflection.underscore(name) if type(data) is ReturnList: name = inflection.pluralize(name) data = {name: data} return json.dumps(data)
def _view_name(cls, operation): '''Returns the name of a view to perform the given operation on this model''' # TODO: validate this against actual views name = inflection.underscore(cls._model_name()) if operation in ['list']: # add any other plural operation here name = inflection.pluralize(name) return "%s_%s" % (operation, name)
def model_directories(cls): """ Return the directories in which to look for models. Defaults to pluralized module name in the modules directory. """ plural = inflection.pluralize( inflection.dasherize(inflection.underscore(cls.__name__))).lower() return [plural]
def plural_en(noun): ''' Return the plural form of the argument string, assuming that it is an English noun. Some results come from lookup tables, but most come from rules, and thus may be wrong, especially for loaner words, OOVs, etc. BUGS: inflection's rules sometimes go awry, e.g. (safe <-> saves) ''' if noun.lower()[-3:] == 'afe': return noun + 's' return inflection.pluralize(noun)
def __init__(self, left, right, through, left_id_column, right_id_column, **kwargs): self.left = left self.right = right self.through = through self.left_id_column = left_id_column self.right_id_column = right_id_column # add getter property to left # user.projects prop_name = inflection.pluralize(self.left.__name__).lower() setattr(right, prop_name, self)
def success_response_structure_test(self, response, status, relationship_keys=None): """ This can be extended in the future to cover stricter validation of the response as follows: * Top level response MUST contain AT LEAST ONE of ['data', 'meta'] * Top level response MUST contain ['links'] # Our requirement - Top level links MUST contain ['self']; MAY contain ['related'] * Resource object MUST contain ['id', 'type'] * Resource object MUST contain AT LEAST ONE of ['attributes', 'relationships'] * Resource object MAY contain ['links', 'meta'] * Relationship object MUST contain AT LEAST ONE of ['links', 'data', 'meta'] - Relationship links object MUST contain AT LEAST ONE of ['self', 'related'] """ self.assertEqual(response.status_code, status) response_content = self.load_json(response) self.assertTrue( all(key in response_content for key in self.SUCCESS_HIGH_LEVEL_KEYS)) for data in self.convert_to_list(response_content['data']): self.assertTrue(all(key in data for key in self.SUCCESS_DATA_KEYS)) if relationship_keys: self.assertTrue('relationships' in data) relationships = data['relationships'] self.assertTrue( all(camelize(key, False) in relationships for key in relationship_keys)) for relationship_name, relationship in relationships.iteritems(): self.assertTrue( all(key in relationship for key in ['data', 'links'])) for relationship_data in self.convert_to_list(relationship['data']): self.assertTrue( all(key in relationship_data for key in ['type', 'id'])) links = relationship['links'] resource_pk = self.resource.pk if hasattr(self, 'resource') else '[0-9A-Za-z]*' self.assertRegexpMatches(links['self'], r'^https?://.*/{}/{}/relationships/{}'.format( self.resource_name, resource_pk, underscore(relationship_name))) if hasattr(self, 'remote_relationship_keys') \ and relationship_name in self.remote_relationship_keys: self.assertRegexpMatches(links['related'], r'^https?://.*/{}/\w'.format( pluralize(underscore(self.get_remote_relationship_name(relationship_name))))) else: self.assertRegexpMatches(links['related'], r'^https?://.*/{}/{}/{}'.format( self.resource_name, resource_pk, underscore(relationship_name)))
def _set_include(self, resc, inc): # include nodes are always plural inc_key = pluralize(inc) if inc_key not in self._links: self._links[inc_key] = [] # TODO should we check for duplicates here and # remove from builder process? # TODO if inc is a list will it get loaded by calling # getattr, do we need to limit here what loads or handle # this in the builder process? self._links[inc_key].append(getattr(resc, inc))
def format_relation_name(value, format_type=None): if format_type is None: format_type = getattr(settings, 'JSON_API_FORMAT_RELATION_KEYS', False) pluralize = getattr(settings, 'JSON_API_PLURALIZE_RELATION_TYPE', False) if format_type: # format_type will never be None here so we can use format_value value = format_value(value, format_type) return inflection.pluralize(value) if pluralize else value