Spaces:
Configuration error
Configuration error
LucaVivona
commited on
Commit
Β·
f06506b
1
Parent(s):
bbd6e0a
π§° refactor/clean module, demos, docker-compose, and README.md
Browse files- README.md +18 -10
- backend/src/__init__.py +2 -2
- backend/src/__pycache__/__init__.cpython-39.pyc +0 -0
- backend/src/__pycache__/demo.cpython-39.pyc +0 -0
- backend/src/{index.py β demoC.py} +8 -2
- backend/src/{demo.py β demoF.py} +6 -1
- backend/src/example/__pycache__/examples.cpython-37.pyc +0 -0
- backend/src/example/__pycache__/examples.cpython-38.pyc +0 -0
- backend/src/example/__pycache__/examples.cpython-39.pyc +0 -0
- backend/src/resources/__pycache__/__init__.cpython-38.pyc +0 -0
- backend/src/resources/__pycache__/compiler.cpython-39.pyc +0 -0
- backend/src/resources/__pycache__/dock.cpython-39.pyc +0 -0
- backend/src/resources/__pycache__/module.cpython-38.pyc +0 -0
- backend/src/resources/__pycache__/module.cpython-39.pyc +0 -0
- backend/src/resources/module.py +80 -77
- backend/test/test.py +35 -6
- docker-compose.yml +1 -0
README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
# Gradio Flow π€
|
2 |
|
3 |
-
**A web application with a backend in Flask and frontend in Rect, and
|
4 |
-
stream both gradio and streamlit interfaces, within a single application.**
|
5 |
|
6 |
|
7 |
## Tabel Of Contents π
|
@@ -78,7 +78,7 @@ Now that you're within the docker backend container environment you can start ad
|
|
78 |
|
79 |
```console
|
80 |
> cd ./src
|
81 |
-
> python
|
82 |
//run example gradio application
|
83 |
```
|
84 |
|
@@ -110,7 +110,7 @@ It is quite simple, and similar within the docker build, the first way you can a
|
|
110 |
**NOTE** If you use the gradio decorator compiler for gradio flow you need to set a listen port to 2000 or else the api will never get the key and will throw you an error, I'll also provided an example below if this isn't clear.
|
111 |
|
112 |
```python
|
113 |
-
#backend/src/
|
114 |
##########
|
115 |
from resources import register, tabularGradio
|
116 |
|
@@ -118,33 +118,41 @@ from resources import register, tabularGradio
|
|
118 |
def Hello_World(name):
|
119 |
return f"Hello {name}, and welcome to Gradio Flow π€"
|
120 |
|
121 |
-
@register(["number", "number"], ["number"], examples=[[1,1]])
|
122 |
def add(x, y):
|
123 |
return x + y
|
124 |
|
125 |
if __name__ == "__main__":
|
|
|
126 |
tabularGradio([Hello_World(), add()], ["Hello World", "Add"])
|
|
|
|
|
|
|
|
|
127 |
```
|
128 |
|
129 |
```python
|
130 |
-
#backend/src/
|
131 |
###########
|
132 |
from resources import GradioModule, register
|
133 |
|
134 |
@GradioModule
|
135 |
class Greeting:
|
136 |
|
137 |
-
@register(["text"], ["text"])
|
138 |
def Hello_World(self, name):
|
139 |
return f"Hello {name}, and welcome to Gradio Flow π€"
|
140 |
|
141 |
-
@register(["number", "number"], ["number"], examples=[[1,1]])
|
142 |
def add(self, x, y):
|
143 |
return x + y
|
144 |
|
145 |
|
146 |
if __name__ == "__main__":
|
147 |
-
|
|
|
|
|
|
|
148 |
````
|
149 |
## Application ποΈ
|
150 |
-
![Application](https://github.com/commune-ai/Gradio-Flow/blob/gradio-flow/gradio-only/app.png)
|
|
|
1 |
# Gradio Flow π€
|
2 |
|
3 |
+
**A web application with a backend in Flask and frontend in Rect, and [React flow](https://reactflow.dev/) node base environment to
|
4 |
+
stream both [gradio](https://gradio.app) ( and later [streamlit](https://streamlit.io) ) interfaces, within a single application.**
|
5 |
|
6 |
|
7 |
## Tabel Of Contents π
|
|
|
78 |
|
79 |
```console
|
80 |
> cd ./src
|
81 |
+
> python demoC.py
|
82 |
//run example gradio application
|
83 |
```
|
84 |
|
|
|
110 |
**NOTE** If you use the gradio decorator compiler for gradio flow you need to set a listen port to 2000 or else the api will never get the key and will throw you an error, I'll also provided an example below if this isn't clear.
|
111 |
|
112 |
```python
|
113 |
+
#backend/src/demoF.py (functional base)
|
114 |
##########
|
115 |
from resources import register, tabularGradio
|
116 |
|
|
|
118 |
def Hello_World(name):
|
119 |
return f"Hello {name}, and welcome to Gradio Flow π€"
|
120 |
|
121 |
+
@register(inputs=["number", "number"], outputs=["number"], examples=[[1,1]])
|
122 |
def add(x, y):
|
123 |
return x + y
|
124 |
|
125 |
if __name__ == "__main__":
|
126 |
+
# run single gradio
|
127 |
tabularGradio([Hello_World(), add()], ["Hello World", "Add"])
|
128 |
+
|
129 |
+
# run it within Gradio-Flow
|
130 |
+
# tabularGradio([Hello_World(), add()], ["Hello World", "Add"], listen=2000)
|
131 |
+
|
132 |
```
|
133 |
|
134 |
```python
|
135 |
+
#backend/src/demoC.py (Class Base)
|
136 |
###########
|
137 |
from resources import GradioModule, register
|
138 |
|
139 |
@GradioModule
|
140 |
class Greeting:
|
141 |
|
142 |
+
@register(["text"], ["text"], examples=[["Luca Vivona"]])
|
143 |
def Hello_World(self, name):
|
144 |
return f"Hello {name}, and welcome to Gradio Flow π€"
|
145 |
|
146 |
+
@register(inputs=["number", "number"], outputs=["number"], examples=[[1,1]])
|
147 |
def add(self, x, y):
|
148 |
return x + y
|
149 |
|
150 |
|
151 |
if __name__ == "__main__":
|
152 |
+
# run just gradio
|
153 |
+
Greeting().launch()
|
154 |
+
# run it within Gradio-flow
|
155 |
+
# Greeting().launch(listen=2000)
|
156 |
````
|
157 |
## Application ποΈ
|
158 |
+
![Application](https://github.com/commune-ai/Gradio-Flow/blob/gradio-flow/gradio-only/app.png)
|
backend/src/__init__.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
import examples
|
2 |
import resource
|
3 |
-
import src.
|
4 |
-
import src.
|
|
|
1 |
import examples
|
2 |
import resource
|
3 |
+
import src.demoF
|
4 |
+
import src.demoC
|
backend/src/__pycache__/__init__.cpython-39.pyc
DELETED
Binary file (254 Bytes)
|
|
backend/src/__pycache__/demo.cpython-39.pyc
DELETED
Binary file (701 Bytes)
|
|
backend/src/{index.py β demoC.py}
RENAMED
@@ -3,7 +3,7 @@ from resources import GradioModule, register
|
|
3 |
@GradioModule
|
4 |
class Greeting:
|
5 |
|
6 |
-
@register(["text"], ["text"])
|
7 |
def Hello_World(self, name):
|
8 |
return f"Hello {name}, and welcome to Gradio Flow π€"
|
9 |
|
@@ -11,5 +11,11 @@ class Greeting:
|
|
11 |
def add(self, x, y):
|
12 |
return x + y
|
13 |
|
|
|
14 |
if __name__ == "__main__":
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
3 |
@GradioModule
|
4 |
class Greeting:
|
5 |
|
6 |
+
@register(["text"], ["text"], examples=[["Luca Vivona"]])
|
7 |
def Hello_World(self, name):
|
8 |
return f"Hello {name}, and welcome to Gradio Flow π€"
|
9 |
|
|
|
11 |
def add(self, x, y):
|
12 |
return x + y
|
13 |
|
14 |
+
|
15 |
if __name__ == "__main__":
|
16 |
+
# run just gradio
|
17 |
+
Greeting().launch()
|
18 |
+
# run it within Gradio-flow
|
19 |
+
# Greeting().launch(listen=2000)
|
20 |
+
|
21 |
+
|
backend/src/{demo.py β demoF.py}
RENAMED
@@ -10,4 +10,9 @@ def add(x, y):
|
|
10 |
return x + y
|
11 |
|
12 |
if __name__ == "__main__":
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
10 |
return x + y
|
11 |
|
12 |
if __name__ == "__main__":
|
13 |
+
# run single gradio
|
14 |
+
tabularGradio([Hello_World(), add()], ["Hello World", "Add"])
|
15 |
+
|
16 |
+
# run it within Gradio-Flow
|
17 |
+
# tabularGradio([Hello_World(), add()], ["Hello World", "Add"], listen=2000)
|
18 |
+
|
backend/src/example/__pycache__/examples.cpython-37.pyc
DELETED
Binary file (6.13 kB)
|
|
backend/src/example/__pycache__/examples.cpython-38.pyc
DELETED
Binary file (4.52 kB)
|
|
backend/src/example/__pycache__/examples.cpython-39.pyc
DELETED
Binary file (4.58 kB)
|
|
backend/src/resources/__pycache__/__init__.cpython-38.pyc
DELETED
Binary file (144 Bytes)
|
|
backend/src/resources/__pycache__/compiler.cpython-39.pyc
DELETED
Binary file (7.74 kB)
|
|
backend/src/resources/__pycache__/dock.cpython-39.pyc
DELETED
Binary file (1.15 kB)
|
|
backend/src/resources/__pycache__/module.cpython-38.pyc
DELETED
Binary file (7.84 kB)
|
|
backend/src/resources/__pycache__/module.cpython-39.pyc
CHANGED
Binary files a/backend/src/resources/__pycache__/module.cpython-39.pyc and b/backend/src/resources/__pycache__/module.cpython-39.pyc differ
|
|
backend/src/resources/module.py
CHANGED
@@ -32,10 +32,15 @@ DOCKER_LOCAL_HOST = '0.0.0.0'
|
|
32 |
DOCKER_PORT = Dock()
|
33 |
|
34 |
def tabularGradio(funcs, names, name="Tabular Temp Name", **kwargs):
|
35 |
-
|
36 |
-
|
37 |
-
|
|
|
|
|
|
|
38 |
port= kwargs["port"] if "port" in kwargs else DOCKER_PORT.determinePort()
|
|
|
|
|
39 |
if 'listen' in kwargs:
|
40 |
try:
|
41 |
requests.post(f"http://{DOCKER_LOCAL_HOST}:{ kwargs[ 'listen' ] }/api/append/port", json={"port" : port, "host" : f'http://localhost:{port}', "file" : 'Not Applicable', "name" : name, "kwargs" : kwargs})
|
@@ -43,6 +48,7 @@ def tabularGradio(funcs, names, name="Tabular Temp Name", **kwargs):
|
|
43 |
print(f"**{bcolor.BOLD}{bcolor.FAIL}CONNECTION ERROR{bcolor.ENDC}** πThe listening api is either not up or you choose the wrong port.π \n {e}")
|
44 |
return
|
45 |
|
|
|
46 |
gr.TabbedInterface(funcs, names).launch(server_port=port,
|
47 |
server_name=f"{DOCKER_LOCAL_HOST}",
|
48 |
inline= kwargs['inline'] if "inline" in kwargs else True,
|
@@ -63,53 +69,74 @@ def tabularGradio(funcs, names, name="Tabular Temp Name", **kwargs):
|
|
63 |
ssl_certfile=kwargs['ssl_certfile'] if "ssl_certfile" in kwargs else None,
|
64 |
ssl_keyfile_password=kwargs['ssl_keyfile_password'] if "ssl_keyfile_password" in kwargs else None,
|
65 |
quiet=kwargs['quiet'] if "quiet" in kwargs else False)
|
|
|
|
|
66 |
if 'listen' in kwargs:
|
67 |
try:
|
68 |
requests.post(f"http://{DOCKER_LOCAL_HOST}:{ kwargs[ 'listen' ] }/api/remove/port", json={"port" : port, "host" : f'http://localhost:{port}', "file" : 'Not Applicable', "name" : name, "kwargs" : kwargs})
|
69 |
-
except Exception as e:
|
70 |
-
|
71 |
print(f"**{bcolor.BOLD}{bcolor.FAIL}CONNECTION ERROR{bcolor.ENDC}** πThe api either lost connection or was turned off...π \n {e}")
|
72 |
|
73 |
return
|
74 |
|
75 |
-
|
|
|
76 |
def register(inputs, outputs, examples=None, **kwargs):
|
77 |
def register_gradio(func):
|
78 |
-
|
79 |
-
fn_name = func.__name__
|
80 |
|
81 |
-
|
82 |
-
|
|
|
|
|
|
|
|
|
83 |
"""
|
84 |
given the decorator is on a class then
|
85 |
initialize a registered_gradio_functons
|
86 |
if not already initialize.
|
87 |
"""
|
88 |
-
|
|
|
|
|
89 |
|
90 |
try:
|
91 |
self = args[0]
|
92 |
self.registered_gradio_functons
|
93 |
except AttributeError:
|
94 |
-
print("β¨Initializing Class Functions...β¨\n")
|
95 |
self.registered_gradio_functons = dict()
|
96 |
|
97 |
-
|
98 |
-
|
99 |
if not fn_name in self.registered_gradio_functons:
|
100 |
-
self.registered_gradio_functons[fn_name] = dict(inputs=inputs,
|
101 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
if len(args[1:]) == (func.__code__.co_argcount - 1):
|
103 |
return func(*args, **wargs)
|
|
|
104 |
else :
|
105 |
"""
|
106 |
the function is not a class function
|
107 |
"""
|
108 |
-
|
|
|
109 |
|
|
|
110 |
if len(args) == (func.__code__.co_argcount):
|
111 |
return func(*args, **wargs)
|
112 |
|
|
|
113 |
return gr.Interface(fn=func,
|
114 |
inputs=inputs,
|
115 |
outputs=outputs,
|
@@ -126,82 +153,60 @@ def register(inputs, outputs, examples=None, **kwargs):
|
|
126 |
allow_flagging=kwargs['allow_flagging'] if "allow_flagging" in kwargs else None,
|
127 |
theme='default',
|
128 |
)
|
129 |
-
|
130 |
-
return None
|
131 |
-
return wrap
|
132 |
return register_gradio
|
133 |
|
134 |
def GradioModule(cls):
|
135 |
class Decorator:
|
136 |
|
137 |
def __init__(self) -> None:
|
138 |
-
self.
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
for func in self.get_funcs():
|
146 |
-
this = getattr(self.cls, func, None)
|
147 |
-
if this.__name__ == "wrap":
|
148 |
-
this()
|
149 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
demos, names = [], []
|
151 |
-
for func, param in self.
|
152 |
names.append(func)
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
num_shap=kwargs['num_shap'] if "num_shap" in kwargs else 2.0,
|
161 |
-
title=kwargs['title'] if "title" in kwargs else None,
|
162 |
-
article=kwargs['article'] if "article" in kwargs else None,
|
163 |
-
thumbnail=kwargs['thumbnail'] if "thumbnail" in kwargs else None,
|
164 |
-
css=kwargs['css'] if "css" in kwargs else None,
|
165 |
-
live=kwargs['live'] if "live" in kwargs else False,
|
166 |
-
allow_flagging=kwargs['allow_flagging'] if "allow_flagging" in kwargs else None,
|
167 |
-
theme='default',
|
168 |
-
))
|
169 |
-
print(f"{func}....{bcolor.BOLD}{bcolor.OKGREEN} done {bcolor.ENDC}")
|
170 |
-
|
171 |
-
print("\nHappy Visualizing... π")
|
172 |
return gr.TabbedInterface(demos, names)
|
173 |
|
174 |
-
def
|
175 |
-
try:
|
176 |
-
self.cls.registered_gradio_functons
|
177 |
-
except AttributeError:
|
178 |
-
return None
|
179 |
-
return self.cls.registered_gradio_functons
|
180 |
-
|
181 |
-
|
182 |
-
def run(self, **kwargs):
|
183 |
port= kwargs["port"] if "port" in kwargs else DOCKER_PORT.determinePort()
|
184 |
if 'listen' in kwargs:
|
185 |
try:
|
186 |
-
requests.post(f"http://{DOCKER_LOCAL_HOST}:{ kwargs[ 'listen' ] }/api/append/port", json={"port" : port, "host" : f'http://localhost:{port}', "file" : getfile(self.
|
187 |
except Exception:
|
188 |
print(f"**{bcolor.BOLD}{bcolor.FAIL}CONNECTION ERROR{bcolor.ENDC}** πThe listening api is either not up or you choose the wrong port.π")
|
189 |
return
|
190 |
|
191 |
-
self.
|
192 |
-
allow_flagging=kwargs[ 'allow_flagging' ] if "allow_flagging" in kwargs else None,
|
193 |
-
cache_examples=kwargs['cache_examples'] if "cache_examples" in kwargs else None,
|
194 |
-
examples_per_page=kwargs['cache_examples'] if "cache_examples" in kwargs else 10,
|
195 |
-
interpretation=kwargs['interpretation'] if "interpretation" in kwargs else None,
|
196 |
-
num_shap=kwargs['num_shap'] if "num_shap" in kwargs else 2.0,
|
197 |
-
title=kwargs['title'] if "title" in kwargs else None,
|
198 |
-
article=kwargs['article'] if "article" in kwargs else None,
|
199 |
-
thumbnail=kwargs['thumbnail'] if "thumbnail" in kwargs else None,
|
200 |
-
css=kwargs['css'] if "css" in kwargs else None,
|
201 |
-
theme=kwargs['theme'] if "theme" in kwargs else None,
|
202 |
-
).launch(server_port=port,
|
203 |
server_name=f"{DOCKER_LOCAL_HOST}",
|
204 |
-
inline= kwargs['inline'] if "inline" in kwargs else
|
205 |
share=kwargs['share'] if "share" in kwargs else None,
|
206 |
debug=kwargs['debug'] if "debug" in kwargs else False,
|
207 |
enable_queue=kwargs['enable_queue'] if "enable_queue" in kwargs else None,
|
@@ -221,15 +226,13 @@ def GradioModule(cls):
|
|
221 |
quiet=kwargs['quiet'] if "quiet" in kwargs else False)
|
222 |
if 'listen' in kwargs:
|
223 |
try:
|
224 |
-
requests.post(f"http://{DOCKER_LOCAL_HOST}:{ kwargs[ 'listen' ] }/api/remove/port", json={"port" : port, "host" : f'http://localhost:{port}', "file" : getfile(self.
|
225 |
except Exception:
|
226 |
print(f"**{bcolor.BOLD}{bcolor.FAIL}CONNECTION ERROR{bcolor.ENDC}** πThe api either lost connection or was turned off...π")
|
227 |
return
|
228 |
|
229 |
return Decorator
|
230 |
|
231 |
-
|
232 |
-
|
233 |
class bcolor:
|
234 |
HEADER = '\033[95m'
|
235 |
OKBLUE = '\033[94m'
|
|
|
32 |
DOCKER_PORT = Dock()
|
33 |
|
34 |
def tabularGradio(funcs, names, name="Tabular Temp Name", **kwargs):
|
35 |
+
"""
|
36 |
+
takes all gradio Interfaces, and names
|
37 |
+
from input and launch the gradio.
|
38 |
+
"""
|
39 |
+
|
40 |
+
assert len(funcs) == len(names), f"{bcolor.BOLD}{bcolor.FAIL}π something went wrong!!! The function you appended dose not match the length of the names{bcolor.ENDC}"
|
41 |
port= kwargs["port"] if "port" in kwargs else DOCKER_PORT.determinePort()
|
42 |
+
|
43 |
+
# send this to the backend api for it to be read by the react frontend
|
44 |
if 'listen' in kwargs:
|
45 |
try:
|
46 |
requests.post(f"http://{DOCKER_LOCAL_HOST}:{ kwargs[ 'listen' ] }/api/append/port", json={"port" : port, "host" : f'http://localhost:{port}', "file" : 'Not Applicable', "name" : name, "kwargs" : kwargs})
|
|
|
48 |
print(f"**{bcolor.BOLD}{bcolor.FAIL}CONNECTION ERROR{bcolor.ENDC}** πThe listening api is either not up or you choose the wrong port.π \n {e}")
|
49 |
return
|
50 |
|
51 |
+
# provided by gradio a tabularInterface function that take function and names
|
52 |
gr.TabbedInterface(funcs, names).launch(server_port=port,
|
53 |
server_name=f"{DOCKER_LOCAL_HOST}",
|
54 |
inline= kwargs['inline'] if "inline" in kwargs else True,
|
|
|
69 |
ssl_certfile=kwargs['ssl_certfile'] if "ssl_certfile" in kwargs else None,
|
70 |
ssl_keyfile_password=kwargs['ssl_keyfile_password'] if "ssl_keyfile_password" in kwargs else None,
|
71 |
quiet=kwargs['quiet'] if "quiet" in kwargs else False)
|
72 |
+
|
73 |
+
# Ctrl+C that ends the process and then continue the code which will remove from the api
|
74 |
if 'listen' in kwargs:
|
75 |
try:
|
76 |
requests.post(f"http://{DOCKER_LOCAL_HOST}:{ kwargs[ 'listen' ] }/api/remove/port", json={"port" : port, "host" : f'http://localhost:{port}', "file" : 'Not Applicable', "name" : name, "kwargs" : kwargs})
|
77 |
+
except Exception as e:
|
|
|
78 |
print(f"**{bcolor.BOLD}{bcolor.FAIL}CONNECTION ERROR{bcolor.ENDC}** πThe api either lost connection or was turned off...π \n {e}")
|
79 |
|
80 |
return
|
81 |
|
82 |
+
|
83 |
+
|
84 |
def register(inputs, outputs, examples=None, **kwargs):
|
85 |
def register_gradio(func):
|
86 |
+
|
|
|
87 |
|
88 |
+
def decorator(*args, **wargs):
|
89 |
+
if type(outputs) is list:
|
90 |
+
assert len(outputs) >= 1, f"β {bcolor.BOLD}{bcolor.FAIL}you have no outputs π€¨... {str(type(outputs))} {bcolor.ENDC}"
|
91 |
+
|
92 |
+
fn_name = func.__name__
|
93 |
+
if 'self' in func.__code__.co_varnames and func.__code__.co_varnames[0] == 'self' and fn_name in dir(args[0]):
|
94 |
"""
|
95 |
given the decorator is on a class then
|
96 |
initialize a registered_gradio_functons
|
97 |
if not already initialize.
|
98 |
"""
|
99 |
+
|
100 |
+
if type(inputs) is list:
|
101 |
+
assert len(inputs) == func.__code__.co_argcount - 1, f"β {bcolor.BOLD}{bcolor.FAIL}inputs should have the same length as arguments{bcolor.ENDC}"
|
102 |
|
103 |
try:
|
104 |
self = args[0]
|
105 |
self.registered_gradio_functons
|
106 |
except AttributeError:
|
|
|
107 |
self.registered_gradio_functons = dict()
|
108 |
|
|
|
|
|
109 |
if not fn_name in self.registered_gradio_functons:
|
110 |
+
self.registered_gradio_functons[fn_name] = dict(inputs=inputs,
|
111 |
+
outputs=outputs,
|
112 |
+
examples=examples,
|
113 |
+
cache_examples=kwargs['cache_examples'] if "cache_examples" in kwargs else None,
|
114 |
+
examples_per_page=kwargs['examples_per_page'] if "examples_per_page" in kwargs else 10,
|
115 |
+
interpretation=kwargs['interpretation'] if "interpretation" in kwargs else None,
|
116 |
+
num_shap=kwargs['num_shap'] if "num_shap" in kwargs else 2.0,
|
117 |
+
title=kwargs['title'] if "title" in kwargs else None,
|
118 |
+
article=kwargs['article'] if "article" in kwargs else None,
|
119 |
+
thumbnail=kwargs['thumbnail'] if "thumbnail" in kwargs else None,
|
120 |
+
css=kwargs['css'] if "css" in kwargs else None,
|
121 |
+
live=kwargs['live'] if "live" in kwargs else False,
|
122 |
+
allow_flagging=kwargs['allow_flagging'] if "allow_flagging" in kwargs else None,
|
123 |
+
theme=kwargs['theme'] if "theme" in kwargs else 'default', )
|
124 |
+
|
125 |
if len(args[1:]) == (func.__code__.co_argcount - 1):
|
126 |
return func(*args, **wargs)
|
127 |
+
return None
|
128 |
else :
|
129 |
"""
|
130 |
the function is not a class function
|
131 |
"""
|
132 |
+
if type(inputs) is list:
|
133 |
+
assert len(inputs) == func.__code__.co_argcount, f"β {bcolor.BOLD}{bcolor.FAIL}inputs should have the same length as arguments{bcolor.ENDC}"
|
134 |
|
135 |
+
# if the arguments within the functions are inputed then just return the output
|
136 |
if len(args) == (func.__code__.co_argcount):
|
137 |
return func(*args, **wargs)
|
138 |
|
139 |
+
# if there is nothing in the arugumrnt then return the gradio interface
|
140 |
return gr.Interface(fn=func,
|
141 |
inputs=inputs,
|
142 |
outputs=outputs,
|
|
|
153 |
allow_flagging=kwargs['allow_flagging'] if "allow_flagging" in kwargs else None,
|
154 |
theme='default',
|
155 |
)
|
156 |
+
return decorator
|
|
|
|
|
157 |
return register_gradio
|
158 |
|
159 |
def GradioModule(cls):
|
160 |
class Decorator:
|
161 |
|
162 |
def __init__(self) -> None:
|
163 |
+
self.__cls__ = cls()
|
164 |
+
self.__get_funcs_attr()
|
165 |
+
self.interface = self.__compile()
|
166 |
+
|
167 |
+
def get_funcs_names(self):
|
168 |
+
assert self.get_registered_map() != None, "this is not possible..."
|
169 |
+
return [ name for name in self.get_registered_map().keys()]
|
|
|
|
|
|
|
|
|
170 |
|
171 |
+
def get_registered_map(self):
|
172 |
+
assert self.__cls__.registered_gradio_functons != None, "what happen!!!!"
|
173 |
+
return self.__cls__.registered_gradio_functons
|
174 |
+
|
175 |
+
def __get_funcs_attr(self):
|
176 |
+
for func in dir(self.__cls__):
|
177 |
+
fn = getattr(self.__cls__, func, None)
|
178 |
+
if not func.startswith("__") and fn.__name__ == "decorator":
|
179 |
+
fn()
|
180 |
+
|
181 |
+
def __compile(self):
|
182 |
+
"""
|
183 |
+
Initialize all the function
|
184 |
+
within the class that are registeed
|
185 |
+
"""
|
186 |
demos, names = [], []
|
187 |
+
for func, param in self.get_registered_map().items():
|
188 |
names.append(func)
|
189 |
+
try:
|
190 |
+
demos.append(gr.Interface(fn=getattr(self.__cls__, func, None), **param))
|
191 |
+
except Exception as e :
|
192 |
+
raise e
|
193 |
+
|
194 |
+
print(f"{bcolor.OKBLUE}COMPLETED: {bcolor.ENDC}All functions are mapped, and ready to launch π",
|
195 |
+
"\n===========================================================\n")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
return gr.TabbedInterface(demos, names)
|
197 |
|
198 |
+
def launch(self, **kwargs):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
199 |
port= kwargs["port"] if "port" in kwargs else DOCKER_PORT.determinePort()
|
200 |
if 'listen' in kwargs:
|
201 |
try:
|
202 |
+
requests.post(f"http://{DOCKER_LOCAL_HOST}:{ kwargs[ 'listen' ] }/api/append/port", json={"port" : port, "host" : f'http://localhost:{port}', "file" : getfile(self.__cls__.__class__), "name" : self.__cls__.__class__.__name__, "kwargs" : kwargs})
|
203 |
except Exception:
|
204 |
print(f"**{bcolor.BOLD}{bcolor.FAIL}CONNECTION ERROR{bcolor.ENDC}** πThe listening api is either not up or you choose the wrong port.π")
|
205 |
return
|
206 |
|
207 |
+
self.interface.launch(server_port=port,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
208 |
server_name=f"{DOCKER_LOCAL_HOST}",
|
209 |
+
inline= kwargs['inline'] if "inline" in kwargs else None,
|
210 |
share=kwargs['share'] if "share" in kwargs else None,
|
211 |
debug=kwargs['debug'] if "debug" in kwargs else False,
|
212 |
enable_queue=kwargs['enable_queue'] if "enable_queue" in kwargs else None,
|
|
|
226 |
quiet=kwargs['quiet'] if "quiet" in kwargs else False)
|
227 |
if 'listen' in kwargs:
|
228 |
try:
|
229 |
+
requests.post(f"http://{DOCKER_LOCAL_HOST}:{ kwargs[ 'listen' ] }/api/remove/port", json={"port" : port, "host" : f'http://localhost:{port}', "file" : getfile(self.__cls__.__class__), "name" : self.__cls__.__class__.__name__, "kwargs" : kwargs})
|
230 |
except Exception:
|
231 |
print(f"**{bcolor.BOLD}{bcolor.FAIL}CONNECTION ERROR{bcolor.ENDC}** πThe api either lost connection or was turned off...π")
|
232 |
return
|
233 |
|
234 |
return Decorator
|
235 |
|
|
|
|
|
236 |
class bcolor:
|
237 |
HEADER = '\033[95m'
|
238 |
OKBLUE = '\033[94m'
|
backend/test/test.py
CHANGED
@@ -21,19 +21,48 @@ def Hello(name):
|
|
21 |
def Goodbye(name):
|
22 |
return f"Goodbye, {name}."
|
23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
class GradioFlowTestCase(unittest.TestCase):
|
25 |
-
|
26 |
def test_class_func_return(self):
|
27 |
-
self.assertEqual(self.
|
28 |
-
self.assertEqual(self.
|
29 |
|
|
|
|
|
30 |
|
31 |
def test_func_return(self):
|
32 |
self.assertEqual(Hello("Luca"), "Hello, Luca.")
|
33 |
self.assertEqual(Goodbye("Luca"), "Goodbye, Luca.")
|
34 |
-
|
35 |
-
|
36 |
|
37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
|
39 |
unittest.main()
|
|
|
21 |
def Goodbye(name):
|
22 |
return f"Goodbye, {name}."
|
23 |
|
24 |
+
@register(['number', 'number'], ['number'], examples=[[9, 10]])
|
25 |
+
def add(x=0, y=0):
|
26 |
+
return x + y
|
27 |
+
|
28 |
+
@register(['number'], ['number'], examples=[[9, 10]])
|
29 |
+
def error_param(x=0, y=0):
|
30 |
+
return x + y
|
31 |
+
|
32 |
+
@register(['number', "number"], [], examples=[[9, 10]])
|
33 |
+
def error_no_output(x=0, y=0):
|
34 |
+
return x + y
|
35 |
+
|
36 |
+
@register(['number', "number"], "number", examples=[[9, 10]])
|
37 |
+
def foo(x=0, y=0):
|
38 |
+
return x + y
|
39 |
+
|
40 |
+
|
41 |
+
|
42 |
+
|
43 |
class GradioFlowTestCase(unittest.TestCase):
|
44 |
+
hodl = test()
|
45 |
def test_class_func_return(self):
|
46 |
+
self.assertEqual(self.hodl.__cls__.Hello("Luca"), "Hello, Luca.")
|
47 |
+
self.assertEqual(self.hodl.__cls__.Goodbye("Luca"), "Goodbye, Luca.")
|
48 |
|
49 |
+
def test_func_default_return(self):
|
50 |
+
self.assertEqual(add(1,1), 2)
|
51 |
|
52 |
def test_func_return(self):
|
53 |
self.assertEqual(Hello("Luca"), "Hello, Luca.")
|
54 |
self.assertEqual(Goodbye("Luca"), "Goodbye, Luca.")
|
|
|
|
|
55 |
|
56 |
+
def test_foo(self):
|
57 |
+
self.assertEqual(foo(1,1),2)
|
58 |
+
|
59 |
+
def test_functions_error_catch(self):
|
60 |
+
with self.assertRaises(AssertionError):
|
61 |
+
error_param()
|
62 |
+
|
63 |
+
def test_function_error_no_output(self):
|
64 |
+
with self.assertRaises(AssertionError):
|
65 |
+
error_no_output()
|
66 |
+
|
67 |
|
68 |
unittest.main()
|
docker-compose.yml
CHANGED
@@ -11,6 +11,7 @@ services:
|
|
11 |
ports:
|
12 |
- "2000:2000"
|
13 |
- "7860-7880:7860-7880"
|
|
|
14 |
command: "python app.py -p 2000"
|
15 |
frontend :
|
16 |
container_name: frontend
|
|
|
11 |
ports:
|
12 |
- "2000:2000"
|
13 |
- "7860-7880:7860-7880"
|
14 |
+
# - "8501:8501" # streamlit application test
|
15 |
command: "python app.py -p 2000"
|
16 |
frontend :
|
17 |
container_name: frontend
|