From f8418a308e87be37e86e65a0703a8baa37ad23e9 Mon Sep 17 00:00:00 2001 From: Steven Kemp Date: Thu, 10 Sep 2020 11:00:09 -0400 Subject: [PATCH 1/4] Refactor flaskapp.py to use external modules flaskapp.py now relies less on making HTTP requests and is more DRY (Don't Repeat Yourself) by using the new mathpix.py and latex_solver.py modules. --- flask/flaskapp/flaskapp.py | 56 ++++++++++++++++------------------ flask/flaskapp/latex_solver.py | 11 +++++++ flask/flaskapp/mathpix.py | 21 +++++++++++++ 3 files changed, 59 insertions(+), 29 deletions(-) create mode 100644 flask/flaskapp/latex_solver.py create mode 100644 flask/flaskapp/mathpix.py diff --git a/flask/flaskapp/flaskapp.py b/flask/flaskapp/flaskapp.py index cf62a6f..ff5545f 100644 --- a/flask/flaskapp/flaskapp.py +++ b/flask/flaskapp/flaskapp.py @@ -1,8 +1,7 @@ -import sys -from flask import Flask, request, jsonify -import requests -from sympy.parsing.latex import parse_latex -from sympy import latex +import mathpix +import latex_solver +from flask import Flask, request + app = Flask(__name__) @app.route('/') @@ -11,40 +10,39 @@ def hello_world(): @app.route('/mathpix-ocr', methods=['POST']) def mathpix_ocr(): - body = request.get_json() - img = body['b64_img'] - data = {"src":"data:image/png;base64,"+img} - headers = {"Content-Type":"application/json","app_id":"spencerb_warpmail_net_6b5480","app_key":"59e12123f380e59b4514"} - url = "https://api.mathpix.com/v3/text" - response = requests.post(url, headers=headers, json=data) - return response.json(), response.status_code + img = request.get_json()['b64_img'] + + try: + return mathpix.submit_text(img) + except mathpix.MathpixApiException as e: + return e, 500 @app.route('/solve-image', methods=['POST']) def solve_image(): body = request.get_json() - response = requests.post('http://0.0.0.0:5000/mathpix-ocr', json=body) - print("Response", file=sys.stdout) - if response.status_code != 200: - return response.text, response.status_code - latex_styled = response.json()['latex_styled'] - new_latex = r'{}'.format(latex_styled) - print("new latex: {}".format(new_latex)) - expr = parse_latex(new_latex) + try: - data = {'solved':str(latex(expr.doit())), 'input_detected':new_latex, 'confidence':response.json()['confidence']} - print("Doit: {}".format(data), file=sys.stdout) + response = mathpix.submit_text(body['b64_img']) + latex_styled = response['latex_styled'] + + data = { + 'solved': latex_solver.solve(latex_styled), + 'input_detected': latex_solver.format_latex(latex_styled), + 'confidence': response['confidence'] + } + return data, 200 - except Exception as e: - return str(e), 400 + except mathpix.MathpixApiException as e: + return e, 500 + @app.route('/solve-latex', methods=['POST']) def solve_latex(): - body = request.get_json() - latex_styled = body['latex'] - new_latex = r'{}'.format(latex_styled) - expr = parse_latex(new_latex) + latex_styled = request.get_json()['latex'] try: - data = {'solved':str(latex(expr.doit()))} + data = { + 'solved': latex_solver.solve(latex_styled) + } return data, 200 except Exception as e: return str(e), 400 diff --git a/flask/flaskapp/latex_solver.py b/flask/flaskapp/latex_solver.py new file mode 100644 index 0000000..5eb4933 --- /dev/null +++ b/flask/flaskapp/latex_solver.py @@ -0,0 +1,11 @@ +from sympy.parsing.latex import parse_latex +from sympy import latex + +def solve(latex_styled): + latex_formatted = format_latex(latex_styled) + expr = parse_latex(latex_formatted) + + return str(latex(expr.doit())) + +def format_latex(latex_styled): + return r'{}'.format(latex_styled) \ No newline at end of file diff --git a/flask/flaskapp/mathpix.py b/flask/flaskapp/mathpix.py new file mode 100644 index 0000000..398174c --- /dev/null +++ b/flask/flaskapp/mathpix.py @@ -0,0 +1,21 @@ +import requests + + +BASE_URL = "https://api.mathpix.com/v3" +APP_ID = "spencerb_warpmail_net_6b5480" +APP_KEY = "59e12123f380e59b4514" +HEADERS = {"Content-Type": "application/json", "app_id": APP_ID, "app_key": APP_KEY} + + +class MathpixApiException(Exception): + pass + +def submit_text(b64_image): + data = { "src": "data:image/png;base64," + b64_image } + url = BASE_URL + "/text" + response = requests.post(url, headers=HEADERS, json=data) + + if response.status_code == 200: + return response.json() + else: + raise MathpixApiException(response.json()['message']) From 9a53ba7873fdd0d05bb9a27d7be96410ec7f2350 Mon Sep 17 00:00:00 2001 From: Steven Kemp Date: Thu, 10 Sep 2020 11:24:53 -0400 Subject: [PATCH 2/4] [Minor] Add Stevens IDE files to .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 0a92e9b..4ca09d7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ __pycache__ .pytest_cache -flaskenv/ \ No newline at end of file +flaskenv/ +.idea/ \ No newline at end of file From 5162bd0e42acecb86ade2ac50242748aefd2828e Mon Sep 17 00:00:00 2001 From: Steven Kemp Date: Thu, 10 Sep 2020 11:28:28 -0400 Subject: [PATCH 3/4] Move Mathpix keys to environment file (breaks things) See instructions in mathpix-variables.env.example for how to add environment variables --- .gitignore | 3 ++- docker-compose.yml | 2 ++ flask/flaskapp/mathpix.py | 5 +++-- mathpix-variables.env.example | 7 +++++++ 4 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 mathpix-variables.env.example diff --git a/.gitignore b/.gitignore index 4ca09d7..77cb773 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ __pycache__ .pytest_cache flaskenv/ -.idea/ \ No newline at end of file +.idea/ +mathpix-variables.env diff --git a/docker-compose.yml b/docker-compose.yml index 76ad5fd..18c90af 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,6 +4,8 @@ version: '2.0' services: flask: + env_file: + - "mathpix-variables.env" build: . image: mathlm:latest ports: diff --git a/flask/flaskapp/mathpix.py b/flask/flaskapp/mathpix.py index 398174c..5dd6a16 100644 --- a/flask/flaskapp/mathpix.py +++ b/flask/flaskapp/mathpix.py @@ -1,9 +1,10 @@ import requests +import os +APP_ID = os.environ['MATHPIX_APP_ID'] +APP_KEY = os.environ['MATHPIX_APP_KEY'] BASE_URL = "https://api.mathpix.com/v3" -APP_ID = "spencerb_warpmail_net_6b5480" -APP_KEY = "59e12123f380e59b4514" HEADERS = {"Content-Type": "application/json", "app_id": APP_ID, "app_key": APP_KEY} diff --git a/mathpix-variables.env.example b/mathpix-variables.env.example new file mode 100644 index 0000000..98c5c2f --- /dev/null +++ b/mathpix-variables.env.example @@ -0,0 +1,7 @@ +# How to use this file: +# 1. Copy this file as "mathpix-variables.env" +# 2. Insert the APP_ID and APP_KEY variables as shown below +# 3. Do NOT commit "mathpix-variables.env" to source control! +# It is in the `.gitignore` +MATHPIX_APP_ID= +MATHPIX_APP_KEY= \ No newline at end of file From 22f95d9496b8c948ecddbadd3d144100ceb34975 Mon Sep 17 00:00:00 2001 From: Steven Kemp Date: Thu, 10 Sep 2020 21:21:08 -0400 Subject: [PATCH 4/4] Update Docker documentation - Made a specific note to help users add the environment variables. - Moved some of the documentation to a separate folder. - Made a note of the docker documentation from the README --- docker.md => docs/docker.md | 8 ++++++-- readme.md | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) rename docker.md => docs/docker.md (55%) diff --git a/docker.md b/docs/docker.md similarity index 55% rename from docker.md rename to docs/docker.md index 77cae2e..41ed396 100644 --- a/docker.md +++ b/docs/docker.md @@ -1,7 +1,11 @@ -Docker will work on both Windows and Linux, you just need to install (Docker)[https://docs.docker.com/docker-for-windows/]. -For better performance on Windows, install (Windows Subsystem for Linux 2)[https://docs.docker.com/docker-for-windows/wsl/] +# Docker Usage + +Docker will work on both Windows and Linux, you just need to install [Docker](https://docs.docker.com/docker-for-windows/). +For better performance on Windows, install [Windows Subsystem for Linux 2](https://docs.docker.com/docker-for-windows/wsl/). The Dockerfile in this repo configures the image environment for our app. Docker-Compose is used as a simple way to do cross-platform building. It reduces the number of commands that have to be run manually, while avoiding platform-dependent bash or batch scripts. +**NOTE:** Before building or running the image, it is necessary to create the enviornment file, which contains private API keys. An [example file](/mathpix-variables.env.example) is provided with instructions. + Run `docker-compose build` to build the image, including code changes. Run `docker-compose run --entrypoint bash flask` to launch the container and drop into a shell for development. diff --git a/readme.md b/readme.md index 3e9fc83..e8b5063 100644 --- a/readme.md +++ b/readme.md @@ -32,6 +32,9 @@ Your git credentials will be shared from your local host to the container, so gi Open the integrated terminal to run commands in the container. ## Running Application + +> See [Docker Usage](./docs/docker.md) for Docker-specific instructions. + `$ flask run` will start the flask development server and send requests to the flask application. ## Running Unit Tests