def __init__(self, name=None, flags=None, short_flag=None, long_flag=None, *args, **kwargs): short_flag = True if short_flag is None else short_flag long_flag = True if long_flag is None else long_flag if flags is None: flags = [] if not isinstance(flags, list): flags = [flags] if not flags or short_flag or long_flag: if short_flag: short_name = name if short_flag is not True: short_name = short_flag if short_name: flags.append(f'-{short_name[0]}') if long_flag: long_name = name if long_flag is not True: long_name = long_flag if long_name: flags.append('--{}'.format(StringUtils.dash(long_name))) flags.append('--{}'.format(StringUtils.snake(long_name))) super().__init__(name=name, flags=tuple(flags), *args, **kwargs)
def __init__(self, name=None, store=None, usage=None, **kwargs): """ # Intialize the Flag Arg # Args - `name`, the name of the arg - `store`, the boolean value that this flag will take on when the arg has been specified. when True default is False, when False default is True """ flags = ( '-{}'.format(StringUtils.dash(name)), '-{}'.format(StringUtils.snake(name)), ) if store is None: store = True if store is True: action = 'store_true' else: action = 'store_false' dest = StringUtils.snake(name) super().__init__(name=name, dest=dest, action=action, flags=flags, usage=usage)
def perform(self, context: Dict = None, **kwargs): if context is None: context = {} ctx = self.get_context() ctx.update({ 'app': 'cli', 'entrypoint': StringUtils.dash(self.usage._package.__name__), 'action': StringUtils.dash(self.usage._action.__name__), }) ctx.update(context) # build a shell command # the first item is the command # the remaining items are arguments and kwarguments command = ctx['entrypoint'] args = self.build_args([ctx['app'], ctx['action']] + ctx['args']) kwargs = self.build_kwargs(ctx['kwargs']) command_line = [command] command_line.extend(args) command_line.extend(kwargs) # optionally indent every line but the first if self._indent_after_command: command_line[1:] = [f'{self.INDENT}{k}' for k in command_line[1:]] # set the value of cli display for when rendering the template ctx['cli_display'] = self.SPLIT.join(command_line) # finally render the template return super().perform(context=ctx)
def resolve_embryo_path(search_path: List[str], name: str) -> str: """ Return the filepath for the embryo with the given name. """ name = name.rstrip('/') if inspect.ismodule(name): # path to the provided python module return name.__path__._path[0] elif name[0] == '/': # absolute path to embryo dir return name else: for root_path in search_path: path = PathUtils.join(root_path, name) if PathUtils.exists(path): return path # try to coerce the name into the expected format name_parts = PathUtils.split(name) name_parts = [StringUtils.snake(n) for n in name_parts] path = PathUtils.join(root_path, *name_parts) if PathUtils.exists(path): return path def is_embryo(path): return os.path.isdir(path) and 'embryo.py' in os.listdir(path) for root_path in search_path: embryo_dirpath = PathUtils.join(root_path, name) if is_embryo(embryo_dirpath): return embryo_dirpath if is_embryo(embryo_dirpath.replace('-', '_')): return embryo_dirpath raise EmbryoNotFound(name)
def on_create(): singular_name = StringUtils.singular(self.name) self.nested.name = singular_name self.nested.source = singular_name self.np_dtype = self.nested.np_dtype on_create_custom = kwargs.pop('on_create', None) if on_create_custom: on_create_custom()
def get_samples_path(cls, sample_type: Text = None): """ # Get Samples Path Get the path containing all samples for a particular file type """ return PathUtils.join( PathUtils.get_dir_path(__file__), 'sample', StringUtils.dash(cls.get_klass().__name__), sample_type if sample_type is not None else 'valid')
def _build_subparser_kwargs(self, func): parser_kwargs = self.decorator.kwargs.get('parser') or {} custom_args = self.decorator.kwargs.get('args') or [] cli_args = self._build_cli_args(func, custom_args) name = StringUtils.dash(parser_kwargs.get('name') or self.program_name) return dict(parser_kwargs, **{ 'name': name, 'args': cli_args, 'perform': self, })
def _on_bootstrap_aggregate_response_message_types(self): """ Build a lookup table of protobuf response Message types for use when routing requests to their downstream actions. """ grpc = self.grpc grpc.response_types = {} for action in self.actions.values(): schema_type_name = get_class_name(action.schemas.response) message_type_name = get_stripped_schema_name( StringUtils.camel(schema_type_name)) response_message_type = getattr(self.grpc.pb2, message_type_name) grpc.response_types[action.name] = response_message_type
def _bootstrap_app_actions(self): for action in self.app.actions.values(): action.bootstrap() on_parts = [] pre_parts = [] post_parts = deque() def is_virtual(func): return getattr(func, 'is_virtual', None) # middleware bootstrapping... for idx, mware in enumerate(self.app.middleware): mware.bootstrap(app=self.app) # everything below is for generating the log message # containing the "action execution diagram" name = StringUtils.snake(get_class_name(mware)) if not is_virtual(mware.pre_request): pre_parts.append(f"↪ {name}.pre_request(raw_args, raw_kwargs)") if not is_virtual(mware.on_request): on_parts.append(f"↪ {name}.on_request(args, kwargs)") if not is_virtual(mware.post_request): if is_virtual(mware.post_bad_request): post_parts.appendleft(f"↪ {name}.post_request(result)") else: post_parts.appendleft( f"↪ {name}.post_[bad_]request(result|error)") elif not is_virtual(mware.post_bad_request): post_parts.appendleft(f"↪ {name}.post_bad_request(error)") parts = [] parts.append('➥ app.on_request(action, *raw_args, **raw_kwargs)') parts.extend(pre_parts) parts.append('➥ args, kwargs = action.marshal(raw_args, raw_kwargs)') parts.extend(on_parts) parts.append('➥ raw_result = action(*args, **kwargs)') parts.extend(post_parts) parts.append('➥ return app.on_response(action, raw_result)') diagram = '\n'.join(f'{" " * (i+1)}{s}' for i, s in enumerate(parts)) console.debug(message=(f"action execution diagram...\n\n {diagram}\n"))
def get_renderer(self, name: Text = None): """ # Get Renderer Get a renderer by the provided name. Name is a mapping available in `_renderers` """ renderer = None if name is None and self._renderer: renderer = self._renderer if not self._renderers: raise RenderersNotDefinedError() if isinstance(name, str): # renderer is a string. let's find a suitable renderer renderer = self._renderers.get(StringUtils.dash(name)) if not renderer: raise InvalidUsageRendererError(data={'renderer': name}) if not renderer: raise UnknownUsageRendererError() return renderer
def _build_func(self, action): key = StringUtils.camel(action.name) request_type = getattr(self._app.grpc.pb2, f'{key}Request') send_request = getattr(self._grpc_stub, action.name) def func(**kwargs): # prepare and send the request request = request_type(**kwargs) response = send_request(request) # translate the native proto response message to a plain dict if action.streams_response: data = [ self._extract_fields(x, action.schemas.response) for x in response ] else: data = self._extract_fields(response, action.schemas.response) return data return func
def process_message(self, level: Text, message: Text, data: Dict) -> Text: when = TimeUtils.utc_now().strftime('%m/%d/%Y %H:%M:%S') level = level.upper()[0] if data: data = self._json.decode(self._json.encode(data)) if self._style == 'json': dumped_data = self._to_json(data) elif self._style == 'yaml': dumped_data = self._to_yaml(data) else: raise ValueError(f'unrcognized log style: {self.style}') else: dumped_data = None thread = StringUtils.dash(current_thread().name) display_string = (f'{when} ({level}) {self._name}' f' - {message}') if dumped_data: display_string += f'\n\n{dumped_data}\n' return display_string
def on_bind( self, resource_type, root: Text = None, ftype: BaseFile = None, store_primitives=None, prefetch: bool = None, yaml_loader_class: Text = None, ): """ Ensure the data dir exists for this Resource type. """ if isinstance(ftype, str): self.ftype = import_object(ftype) if store_primitives is not None: self.store_primitives = store_primitives if prefetch is not None: self.do_prefetch = prefetch if yaml_loader_class is not None: if self.ftype.lower() == 'yaml': self.yaml_loader_class = getattr( yaml, yaml_loader_class, None ) else: self.yaml_loader_class = None self.paths.root = root or self.root self.paths.records = os.path.join( self.paths.root, StringUtils.snake(resource_type.__name__) ) os.makedirs(self.paths.records, exist_ok=True) # bootstrap, bind, and backfill the in-memory cache if self.do_prefetch: self.bust_cache(self.do_prefetch)
def on_bootstrap(self): self._msg_name_prefix = StringUtils.camel(self.name) self.schemas.request = self._build_request_schema() self.schemas.response = self._build_response_schema()
def infer( cls, target: Dict, name: Text = None, predicate: Callable = None, depth: int = 0, ) -> Type['Schema']: """ Return a new Schema class that mirrors the structure of the input target object, as best as possible. """ acc = {} depth -= 1 if not name: faker = Faker() name = f'{faker.color_name()}Schema' if predicate is None: predicate = lambda k, v: not k.startswith('_') py_type_2_field_type = { str: fields.String, int: fields.Int, float: fields.Float, bool: fields.Bool, bytes: fields.Bytes, UUID: fields.Uuid, datetime: fields.DateTime, date: fields.DateTime, } def build_nested_field(seq): contained_py_types = {type(x) for x in seq} if len(contained_py_types) == 1: sub_target = list(seq)[0] py_type = list(contained_py_types)[0] if py_type in py_type_2_field_type: field_type = py_type_2_field_type[py_type] return field_type(example=sub_target) elif py_type in (list, tuple, set): nested = build_nested_field(sub_target) return fields.List(nested) elif py_type is dict: return cls.infer(target=sub_target, predicate=predicate, depth=(depth - 1))() return fields.Field() for k, v in target.items(): if not predicate(k, v): continue if isinstance(v, dict): if depth != 0: sub_schema_type = cls.infer( target=v, name=StringUtils.camel(f'{k}Schema'), predicate=predicate, depth=(depth - 1)) acc[k] = fields.Nested(sub_schema_type, name=k, source=k, example=v) else: acc[k] = fields.Dict(name=k, source=k, example=v) else: scalar_field_type = py_type_2_field_type.get(type(v)) if scalar_field_type: if scalar_field_type is fields.String: # TODO resolve String to more specific field type if possible acc[k] = scalar_field_type(name=k, source=k, example=v) else: acc[k] = scalar_field_type(name=k, source=k, example=v) elif isinstance(v, (list, set, tuple)): nested = build_nested_field(v) nested.name = k nested.source = k if isinstance(nested, Schema): type(nested).__name__ = StringUtils.camel( f'{StringUtils.singular(k)}Schema', lower=False) acc[k] = fields.List(nested=nested, name=k, source=k, example=v) else: acc[k] = fields.Field(name=k, source=k, example=v) return type(name, (cls, ), acc)
def derive_table_name(resource_type: Type['Resource']) -> Text: return StringUtils.snake(get_class_name(resource_type))
class String(Field): np_dtype = '<U1' generator = Field.Generator(callbacks={ '_id': lambda f, **kwargs: UuidString.next_id(), 'id': lambda f, **kwargs: str(f.faker.random_number(digits=16)), 'public_id': lambda f, **kwargs: UuidString.next_id(), 'first_name': lambda f, **kwargs: f.faker.first_name(), 'last_name': lambda f, **kwargs: f.faker.last_name(), 'full_name': lambda f, **kwargs: f.faker.name(), 'name': lambda f, **kwargs: f.faker.catch_phrase().title(), 'description': lambda f, **kwargs: f.faker.paragraph(nb_sentences=10), 'descr': lambda f, **kwargs: f.faker.paragraph(nb_sentences=10), 'summary': lambda f, **kwargs: f.faker.paragraph(nb_sentences=6), 'comment': lambda f, **kwargs: f.faker.paragraph(nb_sentences=4), 'city': lambda f, **kwargs: f.faker.city(), 'address': lambda f, **kwargs: f.faker.address(), 'phone': lambda f, **kwargs: f.faker.phone_number(), 'phone_number': lambda f, **kwargs: f.faker.phone_number(), 'mobile': lambda f, **kwargs: f.faker.phone_number(), 'zip': lambda f, **kwargs: f.faker.zipcode(), 'zip_code': lambda f, **kwargs: f.faker.zipcode(), 'zipcode': lambda f, **kwargs: f.faker.zipcode(), 'postal_code': lambda f, **kwargs: f.faker.zipcode(), 'postalcode': lambda f, **kwargs: f.faker.zipcode(), 'year': lambda f, **kwargs: f.faker.year(), 'user_name': lambda f, **kwargs: f.faker.user_name(), 'username': lambda f, **kwargs: f.faker.user_name(), 'nick': lambda f, **kwargs: f.faker.user_name(), 'handle': lambda f, **kwargs: f.faker.user_name(), 'screen_name': lambda f, **kwargs: f.faker.user_name(), 'screenname': lambda f, **kwargs: f.faker.user_name(), 'state_code': lambda f, **kwargs: f.faker.state_abbr(), 'state': lambda f, **kwargs: f.faker.state(), 'country_code': lambda f, **kwargs: f.faker.country_code(), 'country': lambda f, **kwargs: f.faker.country(), 'card_number': lambda f, **kwargs: f.faker.credit_card_number(), 'credit_card_number': lambda f, **kwargs: f.faker.credit_card_number(), 'security_code': lambda f, **kwargs: f.faker.credit_card_security_code(), 'credit_card_security_code': lambda f, **kwargs: f.faker.credit_card_security_code(), 'label': lambda f, **kwargs: StringUtils.snake(f.faker.color_name()).lower(), 'color': lambda f, **kwargs: StringUtils.snake(f.faker.color_name()).lower(), 'currency_code': lambda f, **kwargs: f.faker.currency_code(), 'currency_name': lambda f, **kwargs: f.faker.currency_name(), 'ein': lambda f, **kwargs: f.faker.ein(), 'filename': lambda f, **kwargs: f.faker.ein(), 'file_name': lambda f, **kwargs: f.faker.ein(), 'fname': lambda f, **kwargs: f.faker.ein(), 'filepath': lambda f, **kwargs: f.faker.file_path(), 'file_path': lambda f, **kwargs: f.faker.file_path(), 'fpath': lambda f, **kwargs: f.faker.file_path(), 'file_extension': lambda f, **kwargs: f.faker.file_extension(), 'extension': lambda f, **kwargs: f.faker.file_extension(), 'ext': lambda f, **kwargs: f.faker.file_extension(), 'image_url': lambda f, **kwargs: f.faker.image_url(), 'url': lambda f, **kwargs: f.faker.url(), 'host': lambda f, **kwargs: f.faker.hostname(), 'hostname': lambda f, **kwargs: f.faker.hostname(), 'host_name': lambda f, **kwargs: f.faker.hostname(), 'port': lambda f, **kwargs: str(random.randrange(1001, 10000)), 'ssn': lambda f, **kwargs: f.faker.ssn(), 'ip_addr': lambda f, **kwargs: f.faker.ipv4(), 'ip_address': lambda f, **kwargs: f.faker.ipv4(), 'ip': lambda f, **kwargs: f.faker.ipv4(), 'ipv4': lambda f, **kwargs: f.faker.ipv4(), 'ipv6': lambda f, **kwargs: f.faker.ipv6(), 'langauge_code': lambda f, **kwargs: f.faker.langauge_code(), 'license_plate': lambda f, **kwargs: f.faker.license_plate(), 'locale': lambda f, **kwargs: f.faker.locale(), 'mac_addr': lambda f, **kwargs: f.faker.mac_address(), 'mac_address': lambda f, **kwargs: f.faker.mac_address(), 'md5': lambda f, **kwargs: str(f.faker.md5()), 'mime': lambda f, **kwargs: f.faker.mime_type(), 'mime_type': lambda f, **kwargs: f.faker.mime_type(), 'mimetype': lambda f, **kwargs: f.faker.mime_type(), 'month': lambda f, **kwargs: f.faker.month(), 'isbn': lambda f, **kwargs: f.faker.isbn(), 'slug': lambda f, **kwargs: f.faker.slug(), 'street': lambda f, **kwargs: f.faker.street_name(), 'street_name': lambda f, **kwargs: f.faker.street_name(), 'suffix': lambda f, **kwargs: f.faker.suffix(), 'timezone': lambda f, **kwargs: f.faker.timezone(), 'time_zone': lambda f, **kwargs: f.faker.timezone(), 'tz': lambda f, **kwargs: f.faker.timezone(), 'user_agent': lambda f, **kwargs: f.faker.user_agent(), 'useragent': lambda f, **kwargs: f.faker.user_agent(), 'ua': lambda f, **kwargs: f.faker.user_agent(), 'text': lambda f, **kwargs: f.faker.text(), 'event': lambda f, **kwargs: f.faker.word(), 'event_name': lambda f, **kwargs: f.faker.word(), 'email': lambda f, **kwargs: f.faker.email(), 'email_addr': lambda f, **kwargs: f.faker.email(), 'email_address': lambda f, **kwargs: f.faker.email(), 'message': lambda f, **kwargs: f.faker.text(max_nb_chars=140), 'keyword': lambda f, **kwargs: f.faker.word().lower(), 'tag': lambda f, **kwargs: f.faker.word().lower(), 'headline': lambda f, **kwargs: f.faker.catch_phrase().title(), 'amount': lambda f, **kwargs: str(random.randrange(0, 51)), 'count': lambda f, **kwargs: str(random.randrange(0, 51)), 'angle': lambda f, **kwargs: str(random.randrange(-360, 361)), 'password': lambda f, **kwargs: f.faker.password(), }, ) def process(self, value): if isinstance(value, str): return (value, None) elif value is not None: return (str(value), None) else: return (value, UNRECOGNIZED_VALUE) def on_generate(self, **kwargs): return self.faker.text(max_nb_chars=64) def on_generate_range(self, bounds: 'Bounds', **kwargs): def vec(text, n): padding = n - len(text) vec = [ord(c) for c in text] if padding: vec += [ord('a')] * padding return vec def midpoint(s1, s2): n = max(len(s1), len(s2)) v1 = vec(s1, n) v2 = vec(s2, n) return ''.join( chr(c) for c in (abs(i1 + i2) // 2 for i1, i2 in zip(v1, v2))) def increment(text, incr): return text[:-1] + chr(ord(text[-1]) + incr) lower = None upper = None if bounds.lower: lower = bounds.lower[:] if not bounds.lower_inclusive: lower = increment(lower, 1) if bounds.upper: upper = bounds.upper[:] if not bounds.upper_inclusive: upper = increment(upper, -1) if lower is not None and upper is not None: return midpoint(lower, upper) elif lower is not None: return lower assert upper is not None return upper
def on_bind(self, resource_type: Type['Resource'], **kwargs): self.type_name = StringUtils.snake(resource_type.__name__).lower() self.records = HashSet(self.redis, self.type_name) self.revs = HashSet(self.redis, f'{self.type_name}_revisions') self.indexes = self._bind_indexes()