diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..1c89bcb --- /dev/null +++ b/.coveragerc @@ -0,0 +1,44 @@ +# .coveragerc to control coverage.py +[run] +branch = True +omit = + */site-packages/* + */distutils/* + */test/* + */__init__.py + */setup.py +source = + ner +relative_files = True +data_file = .coverage + +[report] +# Regexes for lines to exclude from consideration +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + + # Don't complain about missing debug-only code: + def __repr__ + if self\.debug + + # Don't complain if tests don't hit defensive assertion code: + raise AssertionError + raise NotImplementedError + + # Don't complain if non-runnable code isn't run: + if 0: + if __name__ == .__main__.: +omit = + */test/* + *test.py + */__init__.py + */setup.py + +ignore_errors = True + +[html] +directory = reports + +[xml] +output = reports/coverage.xml \ No newline at end of file diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..05168ba --- /dev/null +++ b/.dockerignore @@ -0,0 +1,100 @@ +/build_venv/ +/bamboo-specs/ +README.md +*idea +*egg-info +*pycache* + +# Git +.git +.gitignore + +# CI +.codeclimate.yml +.travis.yml +.taskcluster.yml + +# Docker +docker-compose.yml +.docker + +# Byte-compiled / optimized / DLL files +__pycache__/ +*/__pycache__/ +*/*/__pycache__/ +*/*/*/__pycache__/ +*.py[cod] +*/*.py[cod] +*/*/*.py[cod] +*/*/*/*.py[cod] + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.cache +nosetests.xml +coverage.xml + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Virtual environment +.env/ +.venv/ +#venv/ + +# PyCharm +.idea + +# Python mode for VIM +.ropeproject +*/.ropeproject +*/*/.ropeproject +*/*/*/.ropeproject + +# Vim swap files +*.swp +*/*.swp +*/*/*.swp +*/*/*/*.swp \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bc7d2a3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +ARG BASE_ROOT="nexus.iqser.com:5001/red/" +ARG VERSION_TAG=latest + +FROM ${BASE_ROOT}ner-prediction-base:${VERSION_TAG} + +WORKDIR /app/service + +COPY ./src ./src +COPY ner ./ner + +RUN python3 -m pip install -e . + +WORKDIR /app/service + +EXPOSE 5000 +EXPOSE 8080 + +CMD ["python3", "src/run_service.py"] \ No newline at end of file diff --git a/Dockerfile_base b/Dockerfile_base new file mode 100644 index 0000000..04ab480 --- /dev/null +++ b/Dockerfile_base @@ -0,0 +1,25 @@ +FROM python:3.10 as builder1 + +# Use a virtual environment. +RUN python -m venv /app/venv +ENV PATH="/app/venv/bin:$PATH" + +# Upgrade pip. +RUN python -m pip install --upgrade pip + +# Make a directory for the service files and copy the service repo into the container. +WORKDIR /app/service +COPY . ./ + +# Install dependencies. +RUN python3 -m pip install -r requirements.txt + +# Make a new container and copy all relevant files over to filter out temporary files +# produced during setup to reduce the final container's size. +FROM python:3.10 + +WORKDIR /app/ +COPY --from=builder1 /app . +ENV PATH="/app/venv/bin:$PATH" + +WORKDIR /app/service \ No newline at end of file diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..fec30ad --- /dev/null +++ b/config.yaml @@ -0,0 +1,9 @@ +device: cpu +service: + logging_level: $LOGGING_LEVEL_ROOT|INFO # Logging level for log file messages + logfile_path: $LOGFILE_PATH|null # Overwrites the default path for the service logfile (image_service/log.log) + +webserver: + host: $SERVER_HOST|"127.0.0.1" # webserver address + port: $SERVER_PORT|5000 # webserver port + mode: $SERVER_MODE|production # webserver mode: {development, production} \ No newline at end of file diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..7939746 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,4 @@ +sonar.exclusions=bamboo-specs/**, venv/**, **/*.js, **/*.html, **/*.css, data/** +sonar.c.file.suffixes=- +sonar.cpp.file.suffixes=- +sonar.objc.file.suffixes=- \ No newline at end of file diff --git a/src/run_service.py b/src/run_service.py new file mode 100644 index 0000000..b5fcf6d --- /dev/null +++ b/src/run_service.py @@ -0,0 +1,85 @@ +import argparse +import json +import logging +""" +from tkinter import W + +from flask import Flask, request, jsonify + +from ner.logging import logger +from ner.predictor import Predictor +from ner.utils.utils import extract_section_numbers2texts +from ner.config import CONFIG +from waitress import serve + + +def suppress_user_warnings(): + import warnings + + warnings.filterwarnings("ignore") + + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument("--warnings", action="store_true", default=False) + args = parser.parse_args() + + return args + + +def main(args): + + if not args.warnings: + suppress_user_warnings() + + run_server() + + +def run_server(): + def initialize_predictor(): + predictor = Predictor() + return predictor + + app = Flask(__name__) + + @app.route("/", methods=["POST"]) + def predict_request(): + def inner(): + data = request.data + logger.info(f"<3 Received data.") + section_text = json.loads(data) + section_numbers2texts = extract_section_numbers2texts(section_text) + logger.info(f"Processing data. <3") + predictions = predictor.predict(section_numbers2texts) + + return jsonify({"result": predictions}) + + try: + return inner() + except Exception as err: + logger.warning("Analysis failed") + logger.exception(err) + resp = jsonify("Analysis failed") + resp.status_code = 500 + return resp + + @app.route("/status", methods=["GET"]) + def status(): + response = "OK" + return jsonify(response) + + predictor = initialize_predictor() + + logger.info("<3 Predictor ready.") + + mode = CONFIG.webserver.mode + if mode == "development": + app.run(host=CONFIG.webserver.host, port=CONFIG.webserver.port, debug=True) + elif mode == "production": + serve(app, host=CONFIG.webserver.host, port=CONFIG.webserver.port) + + +if __name__ == "__main__": + args = parse_args() + main(args) +"""