Additional loading functions.

This commit is contained in:
luxick
2018-03-05 22:57:14 +01:00
parent 25d237e81e
commit 8b0422b1b0
9 changed files with 140 additions and 66 deletions

View File

@@ -8,31 +8,31 @@ except ImportError:
class Access:
def __init__(self, connection):
self.host = connection.get('host')
self.port = connection.get('port')
self.buffer = connection.get('buffer_size')
self.auth_key = connection.get('auth_key')
self.socket = socket.socket()
def __init__(self, conn_dict):
self.host = conn_dict.get('host')
self.port = conn_dict.get('port')
self.buffer = conn_dict.get('buffer_size')
self.auth_token = conn_dict.get('auth_token')
def send_request(self, action: str, *args):
request = {'auth_key': self.auth_key,
request = {'auth_token': self.auth_token,
'action': action,
'args': args}
request = pickle.dumps(request)
soc = socket.socket()
try:
self.socket.connect((self.host, self.port))
util.send_msg(self.socket, request)
response = util.recv_msg(self.socket)
response = pickle.loads(response)
if not response.get('success'):
raise Exception(response.get('message'))
soc.connect((self.host, self.port))
util.send_msg(soc, request)
message = util.recv_msg(soc)
message = pickle.loads(message)
if not message.get('success'):
raise Exception(message.get('message'))
finally:
self.socket.close()
return response.get('data')
soc.close()
return message.get('data')
if __name__ == '__main__':
access = Access({'host': 'europa', 'port': 12345, 'buffer_size': 1024, 'auth_key': 'a'})
access = Access({'host': 'europa', 'port': 12345, 'buffer_size': 1024, 'auth_token': 'a'})
action = 'load_seasons'
response = access.send_request(action)
pp = pprint.PrettyPrinter(indent=1)

View File

@@ -5,7 +5,7 @@ import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from dsst_gtk3.handlers import handlers
from dsst_gtk3 import util, reload
from dsst_gtk3 import util, reload, client
import sql_func
import sql
@@ -26,27 +26,41 @@ class GtkUi:
self.ui.connect_signals(self.handlers)
# Show all widgets
self.ui.get_object('main_window').show_all()
db_config = config['sql_connections'][0]
# Initialize the database
sql.db.init(db_config['db_name'], host=db_config['host'], port=db_config['port'],
user=db_config['user'], password=db_config['password'])
# Show database info in status bar
self.set_db_status_label(db_config)
# Create database if not exists
sql_func.create_tables()
self.reload()
# Connect to data server
config = config['servers'][0]
self.data_client = client.Access(config)
self.data = {}
# Load base data and seasons
self.initial_load()
def initial_load(self):
with util.handle_exception(Exception):
self.data['players'] = self.data_client.send_request('load_players')
self.data['drinks'] = self.data_client.send_request('load_drinks')
self.data['seasons'] = self.data_client.send_request('load_seasons')
reload.reload_base_data(self.ui, self)
def reload(self):
reload.reload_base_data(self.ui, self)
season_id = self.get_selected_season_id()
if season_id:
reload.reload_episodes(self.ui, self, season_id)
reload.reload_season_stats(self.ui, self, season_id)
else:
return
episode_id = self.get_selected_episode_id()
if episode_id:
reload.reload_episode_stats(self.ui, self, episode_id)
with util.handle_exception(Exception):
self.data['episodes'] = self.data_client.send_request('load_episodes', self.get_selected_season_id())
reload.reload_episodes(self.ui, self)
pass
# reload.reload_base_data(self.ui, self)
# season_id = self.get_selected_season_id()
# if season_id:
# reload.reload_episodes(self.ui, self, season_id)
# reload.reload_season_stats(self.ui, self, season_id)
# else:
# return
# episode_id = self.get_selected_episode_id()
# if episode_id:
# reload.reload_episode_stats(self.ui, self, episode_id)
def load(self, data_dict: dict, value_field: str, request_name: str):
try:
data_dict[value_field] = self.data_client.send_request('request_name')
except Exception as e:
print()
def set_db_status_label(self, db_conf: dict):
self.ui.get_object('connection_label').set_text(f'{db_conf["user"]}@{db_conf["host"]}')

View File

@@ -29,7 +29,6 @@ class Handlers(SeasonHandlers, BaseDataHandlers, DialogHandlers, DeathHandlers,
""" Signal will be sent when app should close
:param _: Arguments to the delete event
"""
sql.db.close()
Gtk.main_quit()
# DEBUG Functions ##################################################################################################

View File

@@ -3,21 +3,21 @@ from collections import Counter
from gi.repository import Gtk
from data_access import sql, sql_func
from dsst_gtk3 import util
from dsst_gtk3 import util, gtk_ui
def reload_base_data(builder: Gtk.Builder, app: 'gtk_ui.GtkUi'):
def reload_base_data(builder: Gtk.Builder, app: 'gtk_ui.GtkUi',):
"""Reload function for all base data witch is not dependant on a selected season or episode
:param app: GtkUi instance
:param builder: Gtk.Builder with loaded UI
"""
# Rebuild all players store
builder.get_object('all_players_store').clear()
for player in sql.Player.select():
for player in app.data['players']:
builder.get_object('all_players_store').append([player.id, player.name, player.hex_id])
# Rebuild drink store
builder.get_object('drink_store').clear()
for drink in sql.Drink.select():
for drink in app.data['drinks']:
builder.get_object('drink_store').append([drink.id, drink.name, '{:.2f}%'.format(drink.vol)])
# Rebuild seasons store
combo = builder.get_object('season_combo_box') # type: Gtk.ComboBox
@@ -25,23 +25,22 @@ def reload_base_data(builder: Gtk.Builder, app: 'gtk_ui.GtkUi'):
with util.block_handler(combo, app.handlers.do_season_selected):
store = builder.get_object('seasons_store')
store.clear()
for season in sql.Season.select().order_by(sql.Season.number):
for season in app.data['seasons']:
store.append([season.id, season.game_name])
combo.set_active(active)
def reload_episodes(builder: Gtk.Builder, app: 'gtk_ui.GtkUi', season_id: int):
def reload_episodes(builder: Gtk.Builder, app: 'gtk_ui.GtkUi'):
"""Reload all data that is dependant on a selected season
:param app: GtkUi instance
:param builder: Gtk.Builder with loaded UI
:param season_id: ID of the season for witch to load data
"""
# Rebuild episodes store
selection = builder.get_object('episodes_tree_view').get_selection()
with util.block_handler(selection, app.handlers.on_selected_episode_changed):
model, selected_paths = selection.get_selected_rows()
model.clear()
for episode in sql_func.get_episodes_for_season(season_id):
for episode in app.data['episodes']:
model.append([episode.id, episode.name, str(episode.date), episode.number])
if selected_paths:
selection.select_path(selected_paths[0])

View File

@@ -5,18 +5,17 @@ import json
import os
from contextlib import contextmanager
from gi.repository import Gtk
from typing import Callable
from typing import Callable, Type
from zipfile import ZipFile
CONFIG_PATH = os.path.join(os.path.expanduser('~'), '.config', 'dsst', 'config.json')
DEFAULT_CONFIG = {
'auto_connect': False,
'sql_connections': [{
'servers': [{
'host': 'localhost',
'port': 3306,
'db_name': 'dsst',
'user': 'dsst',
'password': 'dsst'}
'port': 12345,
'buffer_size': 1024,
'auth_token': 'a'}
]
}
@@ -32,6 +31,17 @@ def block_handler(widget: 'Gtk.Widget', handler_func: Callable):
widget.handler_unblock_by_func(handler_func)
@contextmanager
def handle_exception(exception: 'Type[Exception]'):
"""Run operation in try/except block and display exception in a dialog
:param exception:
"""
try:
yield
except exception as e:
print(e)
def get_combo_value(combo, index: int):
""" Retrieve the selected value of a combo box at the selected index in the model
:param combo: Any Gtk Widget that supports 'get_active_iter()'

View File

@@ -10,20 +10,46 @@ def map_base_fields(cls, db_model):
return model
def db_to_drink(drink: 'sql.Drink'):
return map_base_fields(models.Drink, drink)
def db_to_enemy(enemy: 'sql.Enemy'):
return map_base_fields(models.Enemy, enemy)
def db_to_player(player: 'sql.Player'):
model = map_base_fields(models.Player, player)
return map_base_fields(models.Player, player)
def db_to_penalty(penalty: 'sql.Penalty'):
model = map_base_fields(models.Penalty, penalty)
model.drink = db_to_drink(penalty.drink)
model.player = db_to_player(penalty.player)
return model
def db_to_death(death: 'sql.Death'):
model = map_base_fields(models.Death, death)
model.player = db_to_player(death.player)
model.enemy = db_to_enemy(death.enemy)
model.penalties = [db_to_penalty(penalty) for penalty in death.penalties]
return model
def db_to_victory(victory: 'sql.Victory'):
model = map_base_fields(models.Victory, victory)
model.player = db_to_player(victory.player)
model.enemy = db_to_enemy(victory.enemy)
return model
def db_to_episode(episode: 'sql.Episode'):
model = map_base_fields(models.Episode, episode)
model.players = [db_to_player(player) for player in episode.players]
model.deaths = []
model.victories = []
model.deaths = [db_to_death(death) for death in episode.deaths]
model.victories = [db_to_victory(victory) for victory in episode.victories]
return model
def db_to_season(season: 'sql.Season'):

View File

@@ -13,7 +13,16 @@ class ReadFunctions:
def load_seasons_all(*_):
return [shortcuts.model_to_dict(season, backrefs=True, max_depth=2) for season in sql.Season.select()]
@staticmethod
def load_episodes(season_id, *_):
if not season_id:
raise Exception('Exception: Missing argument (season_id)')
return [mapping.db_to_episode(ep) for ep in sql.Season.get(sql.Season.id == season_id).episodes]
@staticmethod
def load_players(*_):
return [mapping.db_to_player(player) for player in sql.Player.select()]
@staticmethod
def load_drinks(*_):
return [mapping.db_to_drink(drink) for drink in sql.Drink.select()]

View File

@@ -6,7 +6,7 @@ import sys
import os
from common import util, models
from dsst_server import read_functions, write_functions
from dsst_server import read_functions, write_functions, tokens
from dsst_server.func_proxy import FunctionProxy
from dsst_server.data_access import sql
@@ -23,12 +23,19 @@ class DsstServer:
self.socket_server.bind((HOST, PORT))
print(f'Bound socket to {PORT} on host {HOST}')
self.read_actions = util.list_class_methods(read_functions.ReadFunctions)
self.write_actions = util.list_class_methods(write_functions.WriteFunctions)
# Initialize database
sql.db.init('dsst', user='dsst', password='dsst')
print(f'Database initialized ({sql.db.database})')
self.key_access = {'a': self.read_actions,
'b': self.read_actions + self.write_actions}
# Load access tokens and map them to their allowed methods
read_actions = util.list_class_methods(read_functions.ReadFunctions)
write_actions = util.list_class_methods(write_functions.WriteFunctions)
parm_access = {
'r': read_actions,
'rw': read_actions + write_actions
}
self.tokens = {token: parm_access[perms] for token, perms in tokens.TOKENS}
print(f'Loaded auth tokens: {self.tokens.keys()}')
def run(self):
self.socket_server.listen(5)
@@ -41,17 +48,22 @@ class DsstServer:
data = util.recv_msg(client)
request = pickle.loads(data)
print(f'Request: {request}')
# Validate auth key in request
key = request.get('auth_key')
if key not in self.key_access:
util.send_msg(client, pickle.dumps({'success': False, 'message': 'Auth Key invalid'}))
print(f'Rejected request from {address}. Auth key invalid ({key})')
# Validate auth token in request
token = request.get('auth_token')
if token not in self.tokens:
util.send_msg(client, pickle.dumps({'success': False, 'message': 'Auth token invalid'}))
print(f'Rejected request from {address}. Auth token invalid ({token})')
continue
# Check read functions
action_name = request.get('action')
if action_name in self.key_access[key]:
if action_name in self.tokens[token]:
action = getattr(FunctionProxy, action_name)
try:
value = action(request.get('args'))
except Exception as e:
response = {'success': False, 'message': f'Exception was thrown on server.\n{e}'}
util.send_msg(client, pickle.dumps(response))
raise
response = {'success': True, 'data': value}
util.send_msg(client, pickle.dumps(response))
continue

View File

@@ -0,0 +1,5 @@
# Define access tokens here
# i.E: { 'read': ['a', 'b''],
# 'write': ['a']
# }
TOKENS = [('a', 'rw'), ('b', 'r')]