[DEV] a basic version

This commit is contained in:
Edouard DUPIN 2019-11-26 00:02:39 +01:00
parent 317b7cc26a
commit 54db5f4a7f
10 changed files with 578 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
config.*
config.env
.env
config
data
cache

20
Dockerfile Executable file
View File

@ -0,0 +1,20 @@
FROM python:alpine
RUN pip install --upgrade pip
RUN pip install flask
RUN pip install flask_restful
RUN pip install python-dateutil
RUN pip install realog
EXPOSE 80
ADD src /application/
WORKDIR /application/
CMD ["python", "-u", "./app_video.py"]

10
docker-compose.yaml Executable file
View File

@ -0,0 +1,10 @@
version: '3'
services:
REST_video_service:
build: .
restart: always
image: yui.heero/video_rest_api
container_name: video_rest_api
ports:
- 15080:80

Binary file not shown.

Binary file not shown.

Binary file not shown.

280
src/app_video.py Executable file
View File

@ -0,0 +1,280 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2019, Edouard DUPIN, all right reserved
##
## @license MPL v2.0 (see license file)
##
#pip install flask --user
#pip install flask_restful --user
#pip install python-dateutil --user
from flask import Flask
from flask_restful import Api, Resource, reqparse
import dateutil.parser
import time
import os
import sys
import datetime
import time, threading
import realog.debug as debug
import config
import tools
import data_interface
import data_global_elements
debug.info("connect BDD interface");
app = Flask(__name__)
api = Api(app)
def add_interface(_name):
data_global_elements.add_interface(_name, data_interface.DataInterface(_name, os.path.join(tools.get_run_path(), "data", "bdd_" + _name + ".json")))
API_THEME = "theme"
add_interface(API_THEME)
API_GROUP = "group"
add_interface(API_GROUP)
API_SAISON = "saison"
add_interface(API_SAISON)
API_VIDEO = "video"
add_interface(API_VIDEO)
"""
LIST_themes = [
{
'id': 0,
'name': 'Documentary',
'description': 'Documentary (annimals, space, earth...)',
},{
'id': 1,
'name': 'Movie',
'description': 'Movie with real humans (film)',
},{
'id': 2,
'name': 'Annimation',
'description': 'Annimation movies (film)',
},{
'id': 3,
'name': 'Short Films',
'description': 'Small movies (less 2 minutes)',
},{
'id': 4,
'name': 'tv show',
'description': 'Tv show form old peoples',
}, {
'id': 5,
'name': 'Anniation tv show',
'description': 'Tv show form young peoples',
},
]
class ThemeList(Resource):
# example use: curl http://127.0.0.1:15080/api/v1/theme
def get(self):
debug.info("Request temes: " + str(time))
return LIST_themes, 200
class Theme(Resource):
# example use: curl http://127.0.0.1:15080/api/v1/theme/xxx
def get(self, id):
debug.info("Request theme: " + str(id))
for elem in LIST_themes:
if 'id' in elem.keys() \
and elem["id"] == id:
return elem, 200
return "No data found in list of element: " + str(len(LIST_themes)), 404
"""
class ThemeList(Resource):
def __init__(self):
self.name = API_THEME
# example use: curl http://127.0.0.1:15080/api/v1/theme
def get(self):
return data_global_elements.get_interface(self.name).gets(), 200
"""
def post(self):
args = parser.parse_args()
todo_id = int(max(TODOS.keys()).lstrip('todo')) + 1
todo_id = 'todo%i' % todo_id
TODOS[todo_id] = {'task': args['task']}
return TODOS[todo_id], 201
"""
class Theme(Resource):
def __init__(self):
self.name = API_THEME
# example use: curl http://127.0.0.1:15080/api/v1/theme/xxx
def get(self, id):
value = data_global_elements.get_interface(self.name).get(id)
if value != None:
return value, 200
return "No data found", 404
def delete(self, id):
ret = data_global_elements.get_interface(self.name).delete(id)
if ret == True:
return '', 204
return "No data found", 404
"""
def put(self, id):
ret = data_global_elements.get_interface(self.name).put(id)
return task, 201
"""
api.add_resource(ThemeList, "/api/v1/" + API_THEME)
api.add_resource(Theme, "/api/v1/" + API_THEME + "/<int:id>")
#---------------------------------------------------------------------------------------
class GroupList(Resource):
def __init__(self):
self.name = API_GROUP
# example use: curl http://127.0.0.1:15080/api/v1/Group
def get(self):
return data_global_elements.get_interface(self.name).gets(), 200
"""
def post(self):
args = parser.parse_args()
todo_id = int(max(TODOS.keys()).lstrip('todo')) + 1
todo_id = 'todo%i' % todo_id
TODOS[todo_id] = {'task': args['task']}
return TODOS[todo_id], 201
"""
class Group(Resource):
def __init__(self):
self.name = API_GROUP
# example use: curl http://127.0.0.1:15080/api/v1/Group/xxx
def get(self, id):
value = data_global_elements.get_interface(self.name).get(id)
if value != None:
return value, 200
return "No data found", 404
def delete(self, id):
ret = data_global_elements.get_interface(self.name).delete(id)
if ret == True:
return '', 204
return "No data found", 404
"""
def put(self, id):
ret = data_global_elements.get_interface(self.name).put(id)
return task, 201
"""
api.add_resource(GroupList, "/api/v1/" + API_GROUP)
api.add_resource(Group, "/api/v1/" + API_GROUP + "/<int:id>")
#---------------------------------------------------------------------------------------
class SaisonList(Resource):
def __init__(self):
self.name = API_SAISON
# example use: curl http://127.0.0.1:15080/api/v1/Saison
def get(self):
return data_global_elements.get_interface(self.name).gets(), 200
"""
def post(self):
args = parser.parse_args()
todo_id = int(max(TODOS.keys()).lstrip('todo')) + 1
todo_id = 'todo%i' % todo_id
TODOS[todo_id] = {'task': args['task']}
return TODOS[todo_id], 201
"""
class Saison(Resource):
def __init__(self):
self.name = API_SAISON
# example use: curl http://127.0.0.1:15080/api/v1/Saison/xxx
def get(self, id):
value = data_global_elements.get_interface(self.name).get(id)
if value != None:
return value, 200
return "No data found", 404
def delete(self, id):
ret = data_global_elements.get_interface(self.name).delete(id)
if ret == True:
return '', 204
return "No data found", 404
"""
def put(self, id):
ret = data_global_elements.get_interface(self.name).put(id)
return task, 201
"""
api.add_resource(SaisonList, "/api/v1/" + API_SAISON)
api.add_resource(Saison, "/api/v1/" + API_SAISON + "/<int:id>")
#---------------------------------------------------------------------------------------
class VideoList(Resource):
def __init__(self):
self.name = API_VIDEO
# example use: curl http://127.0.0.1:15080/api/v1/Video
def get(self):
return data_global_elements.get_interface(self.name).gets(), 200
"""
def post(self):
args = parser.parse_args()
todo_id = int(max(TODOS.keys()).lstrip('todo')) + 1
todo_id = 'todo%i' % todo_id
TODOS[todo_id] = {'task': args['task']}
return TODOS[todo_id], 201
"""
class Video(Resource):
def __init__(self):
self.name = API_VIDEO
# example use: curl http://127.0.0.1:15080/api/v1/Video/xxx
def get(self, id):
value = data_global_elements.get_interface(self.name).get(id)
if value != None:
return value, 200
return "No data found", 404
def delete(self, id):
ret = data_global_elements.get_interface(self.name).delete(id)
if ret == True:
return '', 204
return "No data found", 404
"""
def put(self, id):
ret = data_global_elements.get_interface(self.name).put(id)
return task, 201
"""
api.add_resource(VideoList, "/api/v1/" + API_VIDEO)
api.add_resource(Video, "/api/v1/" + API_VIDEO + "/<int:id>")
rest_config = config.get_rest_config()
debug.info("Start REST application: " + str(rest_config["host"]) + ":" + str(rest_config["port"]))
app.run(debug=False, host=rest_config["host"], port=str(rest_config["port"]))
debug.info("END program");
sys.exit(0)

View File

@ -0,0 +1,34 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2019, Edouard DUPIN, all right reserved
##
## @license MPL v2.0 (see license file)
##
interfaces = {}
def get_list_interface():
global interfaces
return interfaces
def get_interface(_name):
global interfaces
return interfaces[_name]
def add_interface(_name, _interface):
global interfaces
interfaces[_name] = _interface
import time, threading
def check_save():
print(time.ctime())
for elem in interfaces.keys():
interfaces[elem].check_save()
threading.Timer(10, check_save).start()
check_save()

94
src/data_interface.py Normal file
View File

@ -0,0 +1,94 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2019, Edouard DUPIN, all right reserved
##
## @license MPL v2.0 (see license file)
##
global_id = 0;
import tools
import json
from realog import debug
class DataInterface():
def __init__(self, _name, _file):
self.name = _name
self.file = _file
self.bdd = []
self.need_save = False
if tools.exist(self.file) == False:
self.need_save = True
else:
data = tools.file_read_data(self.file)
self.bdd = json.loads(data)
def upgrade_global_bd_id(self):
global global_id
for elem in self.bdd:
if 'id' not in elem.keys():
continue
if elem["id"] >= global_id:
global_id = elem["id"] + 1
def get_table_index(id):
id_in_bdd = 0
for elem in self.bdd:
if 'id' in elem.keys() \
and elem["id"] == id:
return id_in_bdd
id_in_bdd += 1
return None
def check_save(self):
if self.need_save == False:
return
debug.warning("Save bdd: " + self.file)
data = json.dumps(self.bdd, sort_keys=True, indent=4)
self.need_save = False
tools.file_write_data_safe(self.file, data)
def gets(self):
debug.info("gets " + self.name)
return self.bdd
def get(self, id):
debug.info("get " + self.name + ": " + str(id))
for elem in self.bdd:
if 'id' in elem.keys() \
and elem["id"] == id:
return elem
return None
def delete(self, id):
debug.info("delete " + self.name + ": " + str(id))
id_in_bdd = self.get_table_index(id)
if id_in_bdd == None:
return False
del self.bdd[id_in_bdd]
self.need_save = True
return True
def put(self, id, value):
debug.info("put " + self.name + ": " + str(id))
id_in_bdd = self.get_table_index(id)
if id_in_bdd == None:
return False
value["id"] = id
self.bdd[id_in_bdd] = value
self.need_save = True
return True
def post(self, value):
debug.info("post " + self.name)
global global_id
value["id"] = global_id
global_id += 1
self.bdd.append(value)
self.need_save = True
return value

133
src/tools.py Normal file
View File

@ -0,0 +1,133 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2012, Edouard DUPIN, all right reserved
##
## @license MPL v2.0 (see license file)
##
import os
import shutil
import errno
import fnmatch
import stat
# Local import
from realog import debug
"""
"""
def get_run_path():
return os.getcwd()
"""
"""
def get_current_path(file):
return os.path.dirname(os.path.realpath(file))
def create_directory_of_file(file):
debug.info("Create directory of path: '" + file + "'")
path = os.path.dirname(file)
debug.info("Create directory: '" + path + "'")
try:
os.stat(path)
except:
os.makedirs(path)
def get_list_sub_path(path):
# TODO : os.listdir(path)
for dirname, dirnames, filenames in os.walk(path):
return dirnames
return []
def remove_path_and_sub_path(path):
if os.path.isdir(path):
debug.verbose("remove path : '" + path + "'")
shutil.rmtree(path)
def remove_file(path):
if os.path.isfile(path):
os.remove(path)
elif os.path.islink(path):
os.remove(path)
def exist(path):
if os.path.isdir(path):
return True
if os.path.isfile(path):
return True
if os.path.islink(path):
return True
return False
def file_size(path):
if not os.path.isfile(path):
return 0
statinfo = os.stat(path)
return statinfo.st_size
def file_read_data(path, binary=False):
debug.verbose("path= " + path)
if not os.path.isfile(path):
return ""
if binary == True:
file = open(path, "rb")
else:
file = open(path, "r")
data_file = file.read()
file.close()
return data_file
def version_to_string(version):
version_ID = ""
for id in version:
if len(version_ID) != 0:
if type(id) == str:
version_ID += "-"
else:
version_ID += "."
version_ID += str(id)
return version_ID
##
## @brief Write data in a specific path.
## @param[in] path Path of the data might be written.
## @param[in] data Data To write in the file.
## @param[in] only_if_new (default: False) Write data only if data is different.
## @return True Something has been copied
## @return False Nothing has been copied
##
def file_write_data(path, data, only_if_new=False):
if only_if_new == True:
if os.path.exists(path) == True:
old_data = file_read_data(path)
if old_data == data:
return False
#real write of data:
create_directory_of_file(path)
file = open(path, "w")
file.write(data)
file.close()
return True
def file_write_data_safe(path, data):
#real write of data:
create_directory_of_file(path)
file = open(path + ".tmp", "w")
file.write(data)
file.close()
shutil.move(path + ".tmp", path)
return True
def list_to_str(list):
if type(list) == type(str()):
return list + " "
else:
result = ""
# mulyiple imput in the list ...
for elem in list:
result += list_to_str(elem)
return result