Skip to content

Commit d020554

Browse files
committed
tesseract executor
1 parent b3f4363 commit d020554

File tree

6 files changed

+166
-24
lines changed

6 files changed

+166
-24
lines changed

main.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,30 @@
1-
from piper.services import TestMessageAdder, StringValue
2-
from piper.envs import CurrentEnv
1+
from piper.services import TestMessageAdder, StringValue, TesseractRecognizer
2+
from piper.envs import CurrentEnv, DockerEnv
33
from piper.configurations import get_configuration
4-
4+
import time
55
import asyncio
66
from loguru import logger
77
logger.add("file.log", level="INFO", backtrace=True, diagnose=True, rotation='5 MB')
88

99
if __name__ == '__main__':
10+
# cfg = get_configuration()
11+
# loop = asyncio.get_event_loop()
12+
# with CurrentEnv() as env:
13+
# x = StringValue(value="hello, world")
14+
# adder = TestMessageAdder(appender="!", port=cfg.docker_app_port)
15+
# result = loop.run_until_complete(adder(x))
16+
# print(result)
17+
18+
# x = StringValue(value="hello, world")
19+
# adder = TestMessageAdder(appender="!", port=cfg.docker_app_port)
20+
# result = loop.run_until_complete(adder(x))
21+
# print(result)
22+
# adder.rm_container()
23+
24+
logger.info(f'main here {time.time()}')
1025
cfg = get_configuration()
1126
loop = asyncio.get_event_loop()
12-
with CurrentEnv() as env:
13-
x = StringValue(value="hello, world")
14-
adder = TestMessageAdder(appender="!", port=cfg.docker_app_port)
15-
result = loop.run_until_complete(adder(x))
27+
with DockerEnv() as env:
28+
recognizer = TesseractRecognizer(port=cfg.docker_app_port)
29+
result = loop.run_until_complete(recognizer())
1630
print(result)
17-
18-
x = StringValue(value="hello, world")
19-
adder = TestMessageAdder(appender="!", port=cfg.docker_app_port)
20-
result = loop.run_until_complete(adder(x))
21-
print(result)
22-
adder.rm_container()

piper/base/backend/utils.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,19 @@ def render_fast_api_backend(**kwargs):
1414
print(jinja_env.list_templates())
1515
template = jinja_env.get_template('fast-api.j2')
1616
return template.render(**kwargs)
17+
18+
def render_fast_api_tsrct_backend(**kwargs):
19+
"""
20+
Render backend template to app.py
21+
"""
22+
print(os.path.dirname(__file__))
23+
template_dir = os.path.join(os.path.dirname(__file__), 'templates/')
24+
jinja_env = jinja2.Environment(
25+
loader=jinja2.FileSystemLoader(template_dir),
26+
trim_blocks=True,
27+
lstrip_blocks=True
28+
)
29+
30+
print(jinja_env.list_templates())
31+
template = jinja_env.get_template('fast-api-tsrct.j2')
32+
return template.render(**kwargs)

piper/base/docker/__init__.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,22 @@ def render(self):
1919
lstrip_blocks=True)
2020
template = jinja_env.get_template('default-python.j2')
2121
return template.render(cmd=self.cmd, python_docker_version=self.python_docker_version)
22+
23+
24+
class PythonTsrImage:
25+
26+
def __init__(self, tag, python_docker_version, cmd):
27+
self.tag = tag
28+
self.python_docker_version = python_docker_version
29+
self.cmd = cmd
30+
31+
def render(self):
32+
"""
33+
Render docker template
34+
"""
35+
template_dir = os.path.join(os.path.dirname(__file__), 'images')
36+
jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(template_dir),
37+
trim_blocks=True,
38+
lstrip_blocks=True)
39+
template = jinja_env.get_template('python-tesrct.j2')
40+
return template.render(cmd=self.cmd, python_docker_version=self.python_docker_version)

piper/base/executors.py

Lines changed: 79 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from abc import abstractmethod, ABC
2+
from distutils.command.config import config
23
import os
34
import time
45
from typing import Dict
@@ -7,10 +8,11 @@
78
import aiohttp
89
from loguru import logger
910
import docker
10-
from pydantic import BaseModel
11+
from pydantic import BaseModel #, BytesObject, ListOfStringsObject
1112

12-
from piper.base.docker import PythonImage
13-
from piper.base.backend.utils import render_fast_api_backend
13+
# from piper.base.docker import PythonImage
14+
from piper.base.docker import PythonTsrImage
15+
from piper.base.backend.utils import render_fast_api_backend, render_fast_api_tsrct_backend
1416
from piper.envs import is_docker_env, is_current_env, get_env
1517
from piper.configurations import get_configuration
1618
from piper.utils import docker_utils as du
@@ -157,7 +159,7 @@ def __init__(self, port: int = 8080, **service_kwargs):
157159

158160
copy_piper(project_output_path)
159161
copy_scripts(project_output_path, self.scripts())
160-
162+
# build_image(project_output_path, docker_image)
161163
self.create_fast_api_files(project_output_path, **service_kwargs)
162164

163165
# create and run docker container
@@ -170,15 +172,11 @@ def __init__(self, port: int = 8080, **service_kwargs):
170172
port
171173
)
172174

173-
wait_for_fast_api_app_start('localhost', 8788, 0.5, 10)
175+
wait_for_fast_api_app_start('localhost', cfg.docker_app_port, cfg.wait_on_iter, cfg.n_iters)
174176
else:
175177
# TODO: Local ENVIRONMENT checks
176178
pass
177179

178-
# a = super().__init__('localhost', port, 'hl')
179-
# a.__call__()
180-
# print('hl', a)
181-
182180
super().__init__('localhost', port, self.base_handler)
183181

184182
def rm_container(self):
@@ -189,6 +187,8 @@ def scripts(self):
189187
return {"service": inspect.getfile(self.__class__)}
190188

191189
def create_fast_api_files(self, path: str, **service_kwargs):
190+
cfg = get_configuration()
191+
192192
backend = render_fast_api_backend(service_class=self.__class__.__name__,
193193
service_kwargs=dict(service_kwargs),
194194
scripts=self.scripts(),
@@ -202,6 +202,75 @@ def create_fast_api_files(self, path: str, **service_kwargs):
202202
write_requirements(path, self.requirements)
203203

204204
gunicorn = "#!/bin/bash \n" \
205-
"gunicorn -b 0.0.0.0:8080 --workers 4 main:app --worker-class uvicorn.workers.UvicornWorker --preload --timeout 120"
205+
f"gunicorn -b 0.0.0.0:8080 --workers {cfg.n_gunicorn_workers} main:app --worker-class uvicorn.workers.UvicornWorker --preload --timeout 120 --reload=True"
206+
with open(f"{path}/run.sh", "w") as output:
207+
output.write(gunicorn)
208+
209+
210+
class FastAPITesseractExecutor(HTTPExecutor):
211+
requirements = ["gunicorn", "fastapi", "uvicorn", "aiohttp", "docker", "Jinja2", "pydantic", "loguru", "numpy", "opencv-python", "Pillow", "pytesseract", "python-multipart"]
212+
base_handler = "recognize"
213+
214+
def __init__(self, port: int = 8080, **service_kwargs):
215+
self.container = None
216+
self.image_tag = 'piper:latest'
217+
self.container_name = "piper_FastAPITsrct"
218+
219+
if is_docker_env():
220+
docker_client = docker.DockerClient(base_url='unix://var/run/docker.sock')
221+
cfg = get_configuration()
222+
project_output_path = cfg.path
223+
224+
copy_piper(project_output_path)
225+
copy_scripts(project_output_path, self.scripts())
226+
227+
docker_image = PythonTsrImage(self.image_tag, "3.9", cmd=f"./run.sh")
228+
build_image(project_output_path, docker_image)
229+
230+
self.create_fast_api_files(project_output_path, **service_kwargs)
231+
232+
# create and run docker container
233+
# if container exits it will be recreated!
234+
du.create_image_and_container_by_dockerfile(
235+
docker_client,
236+
project_output_path,
237+
self.image_tag,
238+
self.container_name,
239+
port
240+
)
241+
242+
wait_for_fast_api_app_start('localhost', cfg.docker_app_port, cfg.wait_on_iter, cfg.n_iters)
243+
else:
244+
# TODO: Local ENVIRONMENT checks
245+
pass
246+
247+
super().__init__('localhost', port, self.base_handler)
248+
249+
def rm_container(self):
250+
if self.container:
251+
self.container.remove(force=True)
252+
253+
def scripts(self):
254+
return {"service": inspect.getfile(self.__class__)}
255+
256+
def create_fast_api_files(self, path: str, **service_kwargs):
257+
cfg = get_configuration()
258+
259+
backend = render_fast_api_tsrct_backend(
260+
service_class=self.__class__.__name__,
261+
service_kwargs=dict(service_kwargs),
262+
scripts=self.scripts(),
263+
function_name=self.base_handler,
264+
# request_model="BytesObject",
265+
# response_model="ListOfStringsObject"
266+
)
267+
268+
with open(f"{path}/main.py", "w") as output:
269+
output.write(backend)
270+
271+
write_requirements(path, self.requirements)
272+
273+
gunicorn = "#!/bin/bash \n" \
274+
f"gunicorn -b 0.0.0.0:8080 --workers {cfg.n_gunicorn_workers} main:app --worker-class uvicorn.workers.UvicornWorker --preload --timeout 120"
206275
with open(f"{path}/run.sh", "w") as output:
207276
output.write(gunicorn)

piper/configurations.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ class Configuration:
1111
wait_on_iter = 0.5
1212
n_iters = 10
1313

14+
n_gunicorn_workers = 1
15+
1416

1517
def get_configuration():
1618
return Configuration

piper/services/__init__.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
1-
from piper.base.executors import FastAPIExecutor
1+
from piper.base.executors import FastAPIExecutor, FastAPITesseractExecutor
2+
from fastapi.responses import JSONResponse
23

34
from pydantic import BaseModel
5+
from loguru import logger
6+
import json
7+
from piper.utils import tesrct_utils as tu
8+
9+
10+
logger.add("file.log", level="INFO", backtrace=True, diagnose=True, rotation='5 MB')
411

512

613
class StringValue(BaseModel):
714
value: str
815

16+
class BytesObject(BaseModel):
17+
value: bytes
18+
19+
class ListOfStringsObject(BaseModel):
20+
value: list
921

1022
class TestMessageAdder(FastAPIExecutor):
1123

@@ -15,3 +27,19 @@ def __init__(self, appender="TEST", **kwargs):
1527

1628
async def run(self, message: StringValue) -> StringValue:
1729
return StringValue(value=(message.value + self.appender))
30+
31+
32+
class TesseractRecognizer(FastAPITesseractExecutor):
33+
def __init__(self, **kwargs):
34+
super().__init__(**kwargs)
35+
36+
async def run(self, file_ : BytesObject) -> ListOfStringsObject:
37+
print('1')
38+
return {1:1}
39+
# return tess_utils.file_handler(file_)
40+
41+
async def recognize(self, file_content : BytesObject) -> ListOfStringsObject:
42+
logger.info(f'file_content {type(file_content)}')
43+
text_dict = tu.img_bytes_handler(file_content)
44+
return JSONResponse(content=text_dict)
45+

0 commit comments

Comments
 (0)