def project_initialization(self, instances): """ Custom initialization of your project Please define your class Initializer in vanilla/project/initialization.py """ try: meta = Meta() module_path = "%s.%s.%s" % \ (CUSTOM_PACKAGE, 'initialization', 'initialization') module = meta.get_module_from_string( module_path, debug_on_fail=False, ) Initializer = meta.get_class_from_string('Initializer', module, skip_error=True) if Initializer is None: log.debug("No custom init available") else: try: Initializer(instances) except BaseException as e: log.error("Errors during custom initialization: %s", e) else: log.info("Vanilla project has been initialized") except BaseException: log.debug("No custom init available")
def test(): meta = Meta() cls_name = "Meta" import utilities modules = meta.get_submodules_from_package(utilities) assert "meta" in modules sub_modules = meta.import_submodules_from_package("utilities") assert sub_modules is not None assert isinstance(sub_modules, list) assert len(sub_modules) > 0 module = meta.get_module_from_string("utilities.meta") assert module is not None assert hasattr(module, cls_name) classes = meta.get_classes_from_module(module) assert classes is not None assert isinstance(classes, dict) assert cls_name in classes assert classes[cls_name].__name__ == cls_name new_classes = meta.get_new_classes_from_module(module) assert new_classes is not None assert isinstance(new_classes, dict) assert cls_name in new_classes assert new_classes[cls_name].__name__ == cls_name meta_class = meta.get_class_from_string(cls_name, module) assert meta_class is not None assert meta_class.__name__ == cls_name methods = meta.get_methods_inside_instance(meta, private_methods=True) assert methods is not None assert isinstance(methods, dict) # it is a static method assert "get_methods_inside_instance" not in methods assert "get_authentication_module" in methods metacls = meta.metaclassing(Meta, "Test") assert metacls is not None assert metacls.__name__ == "Test" self_ref = meta.get_self_reference_from_args(meta, "test", 1) assert self_ref == meta
def custom_post_handle_user_input(self, user_node, input_data): meta = Meta() module_path = "%s.%s.%s" % \ (CUSTOM_PACKAGE, 'initialization', 'initialization') module = meta.get_module_from_string( module_path, debug_on_fail=False, ) Customizer = meta.get_class_from_string('Customizer', module, skip_error=True) if Customizer is None: log.debug("No user properties customizer available") else: try: Customizer().custom_post_handle_user_input( self, user_node, input_data) except BaseException as e: log.error("Unable to customize user properties: %s", e)
def custom_user_properties(self, userdata): meta = Meta() module_path = "%s.%s.%s" % \ (CUSTOM_PACKAGE, 'initialization', 'initialization') module = meta.get_module_from_string( module_path, debug_on_fail=False, ) Customizer = meta.get_class_from_string('Customizer', module, skip_error=True) if Customizer is None: log.debug("No user properties customizer available") else: try: userdata = Customizer().custom_user_properties(userdata) except BaseException as e: log.error("Unable to customize user properties: %s", e) if "email" in userdata: userdata["email"] = userdata["email"].lower() return userdata
class Customizer(object): """ Customize your BACKEND: Read all of available configurations and definitions. """ def __init__(self, testing=False, production=False, init=False): # Input self._testing = testing self._production = production self._initiliazing = init # Some initialization self._endpoints = [] self._definitions = {} self._configurations = {} self._query_params = {} self._schemas_map = {} self._meta = Meta() # Do things self.read_configuration() if not self._initiliazing: self.do_schema() self.find_endpoints() self.do_swagger() def read_configuration(self): ################## # Reading configuration default_file_path = helpers.current_dir(CONF_PATH) project_file_path = helpers.current_dir(CONF_PATH) self._configurations = configuration.read( default_file_path, project_path=project_file_path, ) def do_schema(self): """ Schemas exposing, if requested """ name = '%s.%s.%s' % (BACKEND_PACKAGE, 'rest', 'schema') module = self._meta.get_module_from_string( name, exit_if_not_found=True ) schema_class = getattr(module, 'RecoverSchema') self._schema_endpoint = EndpointElements( cls=schema_class, exists=True, custom={ 'methods': { 'get': ExtraAttributes(auth=None), # WHY DOES POST REQUEST AUTHENTICATION # 'post': ExtraAttributes(auth=None) } }, methods={} ) # TODO: find a way to map authentication # as in the original endpoint for the schema 'get' method # TODO: find a way to publish on swagger the schema # if endpoint is enabled to publish and the developer asks for it def find_endpoints(self): ################## # Walk swagger directories looking for endpoints # FIXME: how to do this? # from utilities import helpers # custom_dir = helpers.current_dir(CUSTOM_PACKAGE) # base_dir = helpers.script_abspath(__file__) base_swagger_confdir = helpers.script_abspath(__file__) custom_swagger_confdir = helpers.current_dir(CUSTOM_PACKAGE) # for base_dir in [BACKEND_PACKAGE, CUSTOM_PACKAGE]: for base_dir in [base_swagger_confdir, custom_swagger_confdir]: swagger_dir = os.path.join(base_dir, 'swagger') log.verbose("Swagger dir: %s" % swagger_dir) for ep in os.listdir(swagger_dir): swagger_endpoint_dir = os.path.join(swagger_dir, ep) if os.path.isfile(swagger_endpoint_dir): exception = '%s.yaml' % SWAGGER_MODELS_FILE if not swagger_endpoint_dir.endswith('/' + exception): log.debug( "Found a file instead of a folder: %s", swagger_endpoint_dir ) continue # isbase = base_dir == BACKEND_PACKAGE isbase = base_dir.startswith('/usr/local') base_module = helpers.last_dir(base_dir) from utilities import ENDPOINTS_CODE_DIR if isbase: apiclass_module = '%s.%s' % (base_module, 'resources') else: apiclass_module = '%s.%s' % ( base_module, ENDPOINTS_CODE_DIR) current = self.lookup( ep, apiclass_module, swagger_endpoint_dir, isbase) if current is not None and current.exists: # Add endpoint to REST mapping self._endpoints.append(current) def do_swagger(self): # SWAGGER read endpoints definition swag = BeSwagger(self._endpoints, self) swag_dict = swag.swaggerish() # TODO: update internal endpoints from swagger self._endpoints = swag._endpoints[:] # SWAGGER validation if not swag.validation(swag_dict): log.critical_exit("Current swagger definition is invalid") self._definitions = swag_dict def read_frameworks(self): file = os.path.join("config", "frameworks.yaml") self._frameworks = load_yaml_file(file) def lookup(self, endpoint, apiclass_module, swagger_endpoint_dir, isbase): log.verbose("Found endpoint dir: '%s'" % endpoint) if os.path.exists(os.path.join(swagger_endpoint_dir, 'SKIP')): log.info("Skipping: %s", endpoint) return None # Find yaml files conf = None yaml_files = {} yaml_listing = os.path.join(swagger_endpoint_dir, "*.%s" % YAML_EXT) for file in glob.glob(yaml_listing): if file.endswith('specs.%s' % YAML_EXT): # load configuration and find file and class conf = load_yaml_file(file) else: # add file to be loaded from swagger extension p = re.compile(r'\/([^\.\/]+)\.' + YAML_EXT + '$') match = p.search(file) method = match.groups()[0] yaml_files[method] = file if len(yaml_files) < 1: raise Exception("%s: no methods defined in any YAML" % endpoint) if conf is None or 'class' not in conf: raise ValueError("No 'class' defined for '%s'" % endpoint) current = self.load_endpoint(endpoint, apiclass_module, conf, isbase) current.methods = yaml_files return current # def read_complex_config(self, configfile): # """ A more complex configuration is available in JSON format """ # content = {} # with open(configfile) as fp: # content = json.load(fp) # return content def load_endpoint(self, default_uri, apiclass_module, conf, isbase): endpoint = EndpointElements(custom={}) # Load the endpoint class defined in the YAML file file_name = conf.pop('file', default_uri) class_name = conf.pop('class') name = '%s.%s' % (apiclass_module, file_name) module = self._meta.get_module_from_string(name, exit_on_fail=False) # Error if unable to find the module in python if module is None: log.critical_exit( "Could not find module %s (in %s)" % (name, file_name)) # Check for dependecies and skip if missing from restapi.services.detect import detector for var in conf.pop('depends_on', []): negate = '' pieces = var.strip().split(' ') pieces_num = len(pieces) if pieces_num == 1: dependency = pieces.pop() elif pieces_num == 2: negate, dependency = pieces else: log.exit('Wrong parameter: %s', var) check = detector.get_bool_from_os(dependency) # Enable the possibility to depend on not having a variable if negate.lower() == 'not': check = not check # Skip if not meeting the requirements of the dependency if not check: if not self._testing: log.warning("Skip '%s': unmet %s", default_uri, dependency) return endpoint # Get the class from the module endpoint.cls = self._meta.get_class_from_string(class_name, module) if endpoint.cls is None: log.critical("Could not extract python class '%s'", class_name) return endpoint else: endpoint.exists = True # Is this a base or a custom class? endpoint.isbase = isbase # DEPRECATED # endpoint.instance = endpoint.cls() # Global tags # to be applied to all methods endpoint.tags = conf.pop('labels', []) # base URI base = conf.pop('baseuri', API_URL) if base not in BASE_URLS: log.warning("Invalid base %s", base) base = API_URL base = base.strip('/') ##################### # MAPPING schema = conf.pop('schema', {}) mappings = conf.pop('mapping', []) if len(mappings) < 1: raise KeyError("Missing 'mapping' section") endpoint.uris = {} # attrs python lib bug? endpoint.custom['schema'] = { 'expose': schema.get('expose', False), 'publish': {} } for label, uri in mappings.items(): # BUILD URI total_uri = '/%s%s' % (base, uri) endpoint.uris[label] = total_uri # If SCHEMA requested create if endpoint.custom['schema']['expose']: schema_uri = '%s%s%s' % (API_URL, '/schemas', uri) p = hex(id(endpoint.cls)) self._schema_endpoint.uris[label + p] = schema_uri endpoint.custom['schema']['publish'][label] = \ schema.get('publish', False) self._schemas_map[schema_uri] = total_uri # Description for path parameters endpoint.ids = conf.pop('ids', {}) # Check if something strange is still in configuration if len(conf) > 0: raise KeyError("Unwanted keys: %s" % list(conf.keys())) return endpoint