def inner(text=''): module = 'sys' while module_imported(module): name = f'temp_module_{random.randint(0, 10 ** 6)}' module_path = fs.current_module_path(name) + '.py' with open(module_path, 'w') as f: f.write(text) modules.append(module_path) module = f'tests.ext.{name}' return module
def test_metric__callable_works(tmpdir): from metric import my_custom_metric metric: CallableMetric = MetricAnalyzer.analyze(my_custom_metric) write(os.path.join(tmpdir, 'metric.json'), metric) shutil.copy(fs.current_module_path('use_metric.py'), tmpdir) cp = subprocess.run('python use_metric.py', shell=True, cwd=tmpdir) assert cp.returncode == 0, cp.stderr
def test_requirements_analyzer__model_works(tmpdir): from proxy_model import model reqs = get_object_requirements(model) for r in reqs.custom: for p, src in r.to_sources_dict().items(): join = os.path.join(tmpdir, p) os.makedirs(os.path.dirname(join), exist_ok=True) with open(join, 'w') as f: f.write(src) with open(os.path.join(tmpdir, 'model.pkl'), 'wb') as f: dill.dump(model, f) shutil.copy(fs.current_module_path('use_model.py'), tmpdir) cp = subprocess.run('python use_model.py', shell=True, cwd=tmpdir) assert cp.returncode == 0
def test_module_dir_path(): assert fs.current_module_path('test_fs.py') == __file__
class FlaskServer(Server): """ HTTP-based Ebonite runtime server. Interface definition is exposed for clients via HTTP GET call to `/interface.json`, method calls - via HTTP POST calls to `/<name>`, server health check - via HTTP GET call to `/health`. Host to which server binds is configured via `EBONITE_HOST` environment variable: default is `0.0.0.0` which means any local or remote, for rejecting remote connections use `localhost` instead. Port to which server binds to is configured via `EBONITE_PORT` environment variable: default is 9000. """ additional_sources = [ current_module_path('build_templates', 'flask-site-nginx.conf'), current_module_path('build_templates', 'nginx.conf'), current_module_path('build_templates', 'supervisord.conf'), current_module_path('build_templates', 'uwsgi.ini') ] def __init__(self): # we do not reference real Flask/Flasgger objects here and this breaks `get_object_requirements` self.__requires = Swagger super().__init__() def _create_app(self): app = flask.Flask(__name__) Swagger(app) @app.errorhandler(FlaskServerError) def handle_bad_request(e: FlaskServerError): return e.to_response() @app.route('/health') def health(): return 'OK' @app.before_request def log_request_info(): flask.g.ebonite_id = str(uuid.uuid4()) app.logger.debug('Headers: %s', request.headers) app.logger.debug('Body: %s', request.get_data()) return app def _prepare_app(self, app, interface): create_interface_routes(app, interface) create_schema_route(app, interface) def run(self, interface: Interface): """ Starts flask service :param interface: runtime interface to expose via HTTP """ global current_app app = self._create_app() self._prepare_app(app, interface) current_app = app if FlaskConfig.run_flask: rlogger.debug('Running flask on %s:%s', FlaskConfig.host, FlaskConfig.port) app.run(FlaskConfig.host, FlaskConfig.port) else: rlogger.debug('Skipping direct flask application run')
class FlaskServer(BaseHTTPServer): """ Flask- and Flasgger-based :class:`.BaseHTTPServer` implementation """ additional_sources = [ current_module_path('build_templates', 'flask-site-nginx.conf'), current_module_path('build_templates', 'nginx.conf'), current_module_path('build_templates', 'supervisord.conf'), current_module_path('build_templates', 'uwsgi.ini') ] # TODO somehow make this depend on builder implementation? additional_options = { 'templates_dir': os.path.join(os.path.dirname(__file__), TEMPLATES_DIR), 'run_cmd': '["/usr/bin/supervisord"]' } def __init__(self): # we do not reference real Flask/Flasgger objects here and this breaks `get_object_requirements` self.__requires = Swagger super().__init__() def _create_app(self): app = flask.Flask(__name__) app.config['SWAGGER'] = {'uiversion': 3, 'openapi': '3.0.2'} Swagger(app) @app.route('/health') def health(): return 'OK' @app.route('/') def root(): return redirect('/apidocs') @app.before_request def log_request_info(): flask.g.ebonite_id = str(uuid.uuid4()) app.logger.debug('Headers: %s', request.headers) app.logger.debug('Body: %s', request.get_data()) return app def _prepare_app(self, app, interface): create_interface_routes(app, interface) create_schema_route(app, interface) def run(self, interface: Interface): """ Starts flask service :param interface: runtime interface to expose via HTTP """ global current_app app = self._create_app() self._prepare_app(app, interface) current_app = app if FlaskConfig.run_flask: rlogger.debug('Running flask on %s:%s', HTTPServerConfig.host, HTTPServerConfig.port) app.run(HTTPServerConfig.host, HTTPServerConfig.port) else: rlogger.debug('Skipping direct flask application run')
class FlaskServer(BaseHTTPServer): """ Flask- and Flasgger-based :class:`.BaseHTTPServer` implementation """ additional_sources = [ current_module_path('build', 'app.py') # replace stub in base image ] additional_options = {'docker': { 'templates_dir': current_module_path('build'), 'base_image': lambda python_version: BASE_IMAGE_TEMPLATE.format(python_version), 'run_cmd': False, # base image has already specified command 'prebuild_hook': prebuild_hook }} def _create_app(self): from flasgger import Swagger from flask import Flask, g, redirect, request app = Flask(__name__) app.config['SWAGGER'] = { 'uiversion': 3, 'openapi': '3.0.2' } Swagger(app) @app.route('/health') def health(): return 'OK' @app.route('/') def root(): return redirect('/apidocs') @app.before_request def log_request_info(): g.ebonite_id = str(uuid.uuid4()) app.logger.debug('Headers: %s', request.headers) app.logger.debug('Body: %s', request.get_data()) return app def _prepare_app(self, app, interface): create_interface_routes(app, interface) create_schema_route(app, interface) def run(self, interface: Interface): """ Starts flask service :param interface: runtime interface to expose via HTTP """ global current_app app = self._create_app() self._prepare_app(app, interface) current_app = app if FlaskConfig.run_flask: rlogger.debug('Running flask on %s:%s', HTTPServerConfig.host, HTTPServerConfig.port) app.run(HTTPServerConfig.host, HTTPServerConfig.port) else: rlogger.debug('Skipping direct flask application run')
def create_schema_route(app, interface: Interface): from flask import jsonify schema = InterfaceDescriptor.from_interface(interface).to_dict() rlogger.debug('Creating /interface.json route with schema: %s', schema) app.add_url_rule('/interface.json', 'schema', lambda: jsonify(schema)) class FlaskConfig(Config): run_flask = Param('run_flask', default='true', parser=bool) if Core.DEBUG: FlaskConfig.log_params() PREBUILD_PATH = current_module_path('prebuild') BASE_IMAGE_TEMPLATE = 'zyfraai/flask:{}' def prebuild_hook(python_version): from ebonite.ext.docker.prebuild import prebuild_image prebuild_image(PREBUILD_PATH, BASE_IMAGE_TEMPLATE, python_version) class FlaskServer(BaseHTTPServer): """ Flask- and Flasgger-based :class:`.BaseHTTPServer` implementation """ additional_sources = [ current_module_path('build', 'app.py') # replace stub in base image