Commit 4ad28a59 authored by Yori Fournier's avatar Yori Fournier
Browse files

Add MplUnpickler class.

This Unpickler translate any pickled object into the correct (local) namespace.

Add the first functional test
1. to setup: ./setup_test_folder.sh
2. to test: python test_com.py
3. to clean: ./clean_test_folder.py
parent 4ff18cab
......@@ -40,6 +40,9 @@ import os as os
import numpy as np
np.set_printoptions(threshold='nan')
from signal import Signal, Query, Status, Answer
from mpl_unpickler import MplUnpickler
# matplotlib import for client/local -----------------------------------
if D_HIERARCHY in ('CLIENT', 'client', 'LOCAL', 'local'):
......@@ -113,15 +116,18 @@ elif(D_HIERARCHY in ('SERVER', 'server')):
from .myFig_server import MyFig_server as MyFig
# from .test import FigTestServer
from .test import FigTest
# from .test import FigTest
# for testing purpose
from .test import readStupidData, readStupidData2
# from .test import readStupidData, readStupidData2
SERVER_IOFUNCTIONS = {'readStupidData': readStupidData,
'readStupidData2': readStupidData2
SERVER_IOFUNCTIONS = {
# 'readStupidData': readStupidData,
# 'readStupidData2': readStupidData2
}
SERVER_FIGURES = {
#'FigTest': FigTest
}
SERVER_FIGURES = {'FigTest': FigTest}
from .mplServer import MplServer
from .mplServer2 import MplServer2, MplHandler
......@@ -162,19 +168,19 @@ if D_HIERARCHY in ('CLIENT', 'client', 'LOCAL', 'local'):
#from .mytool import print2file # need to make tools for server ?? or just put them in client/local
#from .mytool import FigOneAxes
if D_HIERARCHY in ('CLIENT', 'client', 'LOCAL', 'local'):
#if D_HIERARCHY in ('CLIENT', 'client', 'LOCAL', 'local'):
from .mytool import print2file # need to make tools for server ?? or just put them in client/local
from .mytool import FigOneAxes
from .mytool import window_exists, getCurrentWindowIDs
from .mytool import print2file, print2screen, printListCurrentWindows
from .mytool import getWindow, getFigOnWindow, drawFigOnWindow, giveDataToWindow
from .mytool import closeWindow, closeAllWindows
# from .mytool import print2file # need to make tools for server ?? or just put them in client/local
# from .mytool import FigOneAxes
# from .mytool import window_exists, getCurrentWindowIDs
# from .mytool import print2file, print2screen, printListCurrentWindows
# from .mytool import getWindow, getFigOnWindow, drawFigOnWindow, giveDataToWindow
# from .mytool import closeWindow, closeAllWindows
# TESTS ----------------------------------------------------------------
# from .test import myTest
# from .test import testList
from .test import FigTest
# from .test import FigTest
from . import socket, AF_INET, SOCK_STREAM
import pickle
from .signal import Signal,Query,Status,Answer
#from .signal import Signal, Status, Answer
#from .signal import Query as Server_Query
from . import Query, Status, Answer, Signal
debug = True
from . import DBUG,WARN,SPCE,SEVR,INFO
from . import MplUnpickler
class MplClient2():
......@@ -20,7 +24,7 @@ class MplClient2():
self.sock = socket(AF_INET,SOCK_STREAM)
self.sock.connect(con)
self.connected = True
def disconnect(self):
''' shutdown socket. Warning: If server and client are local the client can not shut down the port because the server has still a handle on it'''
print('closing the connection...')
......@@ -60,7 +64,8 @@ class MplClient2():
rf = self.sock.makefile(mode='rb')
try :
response = pickle.load(rf)
unpickler = MplUnpickler(rf)
response = unpickler.load()
if debug and isinstance(response,Signal):
print('CLIENT Received: {} with content \"{}\"'.format(type(response),response.content))
except EOFError :
......
import SocketServer
import pickle
from .signal import Signal,Status,Query,Answer
from . import Signal,Status,Query,Answer
from . import SERVER_IOFUNCTIONS
from . import SERVER_FIGURES
......@@ -9,6 +9,7 @@ from . import SERVER_FIGURES
from . import MyFig
from . import DBUG,WARN,SPCE,SEVR,INFO
from . import MplUnpickler
G_RAWDATA = dict()
G_FIGURES = dict()
......@@ -35,7 +36,8 @@ class MplHandler(SocketServer.StreamRequestHandler):
5. send dataID.
'''
fct = SERVER_IOFUNCTIONS[content.get('func')]
# fct = SERVER_IOFUNCTIONS[content.get('func')]
fct = self.server.knownFunctions[content.get('func')]
args = content.get('args')
kwargs = content.get('kwargs')
dataName = content.get('dataname')
......@@ -59,7 +61,7 @@ class MplHandler(SocketServer.StreamRequestHandler):
def treatNewSyncFigure(self,content) :
# Try to create the requested figure
FigClass = SERVER_FIGURES[content.get('figClassName')]
FigClass = self.server.knownFigures[content.get('figClassName')]
args = content.get('args')
kwargs = content.get('kwargs')
datanames = content.get('dataName')
......@@ -153,7 +155,8 @@ class MplHandler(SocketServer.StreamRequestHandler):
rf = self.server.socket.makefile(mode='rb')
try :
response = pickle.load(rf)
unpickler = MplUnpickler(rf)
response = unpickler.load()
if DEBUG and isinstance(response,Signal):
print('CLIENT Received: {} with content \"{}\"'.format(type(response),response.content))
except EOFError :
......@@ -203,7 +206,8 @@ class MplHandler(SocketServer.StreamRequestHandler):
# we can now use e.g. readline() instead of raw recv() calls
## self.data = self.rfile.readline()#.strip()
while self.server.running :
request = pickle.load(self.rfile)
unpickler = MplUnpickler(self.rfile)
request = unpickler.load()
reply = self.treatSig(request)
# Likewise, self.wfile is a file-like object used to write back
# to the client
......@@ -218,25 +222,25 @@ class MplServer2(SocketServer.TCPServer):
allow_reuse_address=True
# DEFINE KNOWN I/O FUNCTIONS ---------------------------------------
def defineKnownFunctions(self):
def defineKnownFunctions(self, functions):
'''Function to overwrite in order to declare the known
I/O functions by the server context.'''
self.knownFunctions = SERVER_IOFUNCTIONS
self.knownFunctions = functions
# DEFINE KNOWN FIGURE CLASSES --------------------------------------
def defineKnownFigures(self):
def defineKnownFigures(self, figures):
'''Function to overwrite in order to declare the known
Figure classes by the server context.'''
self.knownFigures = SERVER_FIGURES
self.knownFigures = figures
def __init__(self,*args, **kwargs) :
def __init__(self, ip='', port=52386, handler=MplHandler, knownFunctions=SERVER_IOFUNCTIONS, knownFigures=SERVER_FIGURES) :
'''Intialisation of the server, defines known functions, known
figure classes. It needs to be called.'''
# Define functions and figure classes
self.defineKnownFunctions()
self.defineKnownFigures()
SocketServer.TCPServer.__init__(self,*args, **kwargs)
self.defineKnownFunctions(knownFunctions)
self.defineKnownFigures(knownFigures)
SocketServer.TCPServer.__init__(self, (ip, port), handler)
self.initialized = True
self.running = True
......
import sys
import pickle
class MplUnpickler(pickle.Unpickler):
def find_class(self, module, name):
# print('MODULE: '+module)
# print('CLASS: '+name)
# print('OWN MODULE: ' + self.__module__)
own_module = self.__module__
own_module = own_module.replace('.mpl_unpickler', '')
modulelist = module.split('.')
# print(modulelist)
if 'myplotlib' in modulelist:
index = modulelist.index('myplotlib')
class_path = '.' + '.'.join(modulelist[index+1:])
module = own_module + class_path
# print('NEW MODULE: ' + module)
return(getattr(sys.modules[module], name))
# Destroy the symbolic links
# On the server side
cd serverside/myplotlib
# save the config
mv config.py config.save
find . -maxdepth 1 -name "*.py" -exec unlink {} \;
# recover theconfig
mv config.save config.py
# On the client side
cd ../../clientside/myplotlib
# save the config
mv config.py config.save
find . -maxdepth 1 -name "*.py" -exec unlink {} \;
# recover theconfig
mv config.save config.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# ================= FILE HEADER ========================================
#
# myplotlib v3.0.1,
#
# @file myAxes.py
# @author Yori 'AGy' Fournier
# @licence CC-BY-SA
#
# MyAxes class: Overlay of matplotlib Axes class
# It is done such that the user can concentrate on
# the important aspect of the figure and not the
# technical part. It consists of a constructor,
# that requires a Figure, the ratio of the xaxis over
# the yaxis, and the frame in which the figure
# should be plotted.
#
# @Class MyAxes
#
# @Constructor(self, fig, ratio, frame, +user defined kw):
#
# @section Functions
#
# - plotting: this is the overwritten function
# from Axes. It is called by it's
# parent-figure's function .plot()
#
# - formatRawData: it computes out of the rawData
# given as argument some quantities that
# are returned as a dictionary and
# become accessable for plotting.
#
# @section History
#
# v 0.0.0 - MyAxes class for the myplotlib module, consists
# of a constructor, a pltting function and
# formatRawData.
#
# ======================================================================
#
#
# IMPORT ---------------------------------------------------------------
from myplotlib import MyAxes
D_XRANGE = None
D_YRANGE = None
D_LOGY = False
D_LOGX = False
# Class MyAxes Overwriting Matplotlib.figure.Axes
class AxTest(MyAxes):
# DECLARE KEYWORDS -------------------------------------------------
def declareKeywords(self):
self.keywords = {'xRange': D_XRANGE,
'yRange': D_YRANGE}
return(True)
# FORMATTING -------------------------------------------------------
def formatRawData(self, rawdata):
# give value to data a dict
# with xdata, ydata1, zdata, ydata2 ...
try:
self.data = {'xdata': [rawdata.data[0], rawdata.data[1]],
'ydata': [rawdata.data[2], rawdata.data[3]]}
except(TypeError, KeyError, IndexError):
print(SEVR + 'The Raw Data could not be formatted --> EXIT')
return(False)
if(self.fig.debug):
print(DBUG + 'I formatted the raw data!')
return(True)
# IMPORT ---------------------------------------------------------------
from .. import D_HIERARCHY
from .. import SEVR, DBUG, INFO
if D_HIERARCHY in ('SERVER', 'server'):
print(INFO+"Testing the server.")
else:
print(SEVR+"This is atest for the server, the imports are not correct.")
raise ImportError
from .. import MyFig
from . import AxTestServer
class FigTestServer(MyFig):
FIGSIZE = (8., 6.)
def addAxes(self):
ratio = 6. / 8. # height/width of the axes (in inch)
frame1 = [0.1, 0.1, 0.8, 0.8] # part of the fig that is available
self.add_axes(AxTestServer(self, ratio, frame1), "p1")
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# ================= FILE HEADER ========================================
#
# myplotlib v3.0.1,
#
# @file myIOs.py
# @author Yori 'AGy' Fournier
# @licence CC-BY-SA
#
# myIOs module: a few Input/Output functions for testing
#
# @function readStupidData
#
# create some stupid data format them as myData format
# and add then in G_RAWDATA such that they could be used
# by myAxes and myFig.
#
# @function readStupidData2
#
# same as readStupidData just with another identifier
#
# @section History
#
# v 0.0.0 - myIOs class for the myplotlib module.
#
# ======================================================================
#
#
# IMPORT ---------------------------------------------------------------
from .. import DBUG
from .. import D_IPATH
from .. import MyData
# READ STUPID DATA -----------------------------------------------------
def readStupidData(ipath=D_IPATH, *args, **kwargs):
debug = kwargs.get('debug', 0)
lrawdata = MyData()
lrawdata.name = str(ipath)
lrawdata.data = [-1., 1., 1, -1.]
if(debug):
print(DBUG + 'I read the raw data with readStupidData')
return(lrawdata)
# READ STUPID DATA 2 ---------------------------------------------------
def readStupidData2(ipath=D_IPATH, *args, **kwargs):
debug = kwargs.get('debug', 0)
lrawdata = MyData()
lrawdata.name = str(ipath)
lrawdata.data = [-1., 1., -2., 2.]
if(debug):
print(DBUG + 'I read the raw data with readStupidData2')
return(lrawdata)
from .myData import MyData
# TECHNICAL ------------------------------------------------------------
D_VERSION='v5'
D_HIERARCHY='CLIENT'
D_HOST='localhost'
D_PORT=50803
# FORM -----------------------------------------------------------------
INFO = " > info-: "
WARN = " > warn-: "
SEVR = " > sevr-: "
DBUG = " > dbug-: "
SPCE = " > -----: "
# CONFIGURATION --------------------------------------------------------
# myFig
D_FIGNUM = 0 # default figure number
D_FIGSIZE = (8., 6.) # default figure size
D_REFORMAT = True # default reformat value
D_FORMATTED = False # default formatted value
D_RAWDATA = MyData() # default raw data
D_INPUTARG = 'current' # default Input argument
# myIOs
D_IPATH = '../' # default path to project
# print2file
D_OPATH = 'myplotlib/img/' # default path to ouput
D_OFORMAT = 'png' # default format for ouput
# Debug
D_DEBUG = True # default debug value
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# ================= FILE HEADER ========================================
#
# myplotlib v3.0.1,
#
# @file myAxes.py
# @author Yori 'AGy' Fournier
# @licence CC-BY-SA
#
# MyAxes class: Overlay of matplotlib Axes class
# It is done such that the user can concentrate on
# the important aspect of the figure and not the
# technical part. It consists of a constructor,
# that requires a Figure, the ratio of the xaxis over
# the yaxis, and the frame in which the figure
# should be plotted.
#
# @Class MyAxes
#
# @Constructor(self, fig, ratio, frame, +user defined kw):
#
# @section Functions
#
# - plotting: this is the overwritten function
# from Axes. It is called by it's
# parent-figure's function .plot()
#
# - formatRawData: it computes out of the rawData
# given as argument some quantities that
# are returned as a dictionary and
# become accessable for plotting.
#
# @section History
#
# v 0.0.0 - MyAxes class for the myplotlib module, consists
# of a constructor, a pltting function and
# formatRawData.
#
# ======================================================================
#
#
# IMPORT ---------------------------------------------------------------
from myplotlib import MyAxes
D_XRANGE = None
D_YRANGE = None
D_LOGY = False
D_LOGX = False
# Class MyAxes Overwriting Matplotlib.figure.Axes
class AxTest(MyAxes):
# DECLARE KEYWORDS -------------------------------------------------
def declareKeywords(self):
self.keywords = {'xRange': D_XRANGE,
'yRange': D_YRANGE}
return(True)
# FORMATTING -------------------------------------------------------
def formatRawData(self, rawdata):
# give value to data a dict
# with xdata, ydata1, zdata, ydata2 ...
try:
self.data = {'xdata': [rawdata.data[0], rawdata.data[1]],
'ydata': [rawdata.data[2], rawdata.data[3]]}
except(TypeError, KeyError, IndexError):
print(SEVR + 'The Raw Data could not be formatted --> EXIT')
return(False)
if(self.fig.debug):
print(DBUG + 'I formatted the raw data!')
return(True)
# IMPORT ---------------------------------------------------------------
from myplotlib import MyFig
from axTest import AxTest
class FigTest(MyFig):
FIGSIZE = (8., 6.)
def addAxes(self):
ratio = 6. / 8. # height/width of the axes (in inch)
frame1 = [0.1, 0.1, 0.8, 0.8] # part of the fig that is available
self.add_axes(AxTest(self, ratio, frame1), "p1")
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# ================= FILE HEADER ========================================
#
# myplotlib v3.0.1,
#
# @file myIOs.py
# @author Yori 'AGy' Fournier
# @licence CC-BY-SA
#
# myIOs module: a few Input/Output functions for testing
#
# @function readStupidData
#
# create some stupid data format them as myData format
# and add then in G_RAWDATA such that they could be used
# by myAxes and myFig.
#
# @function readStupidData2
#
# same as readStupidData just with another identifier
#
# @section History
#
# v 0.0.0 - myIOs class for the myplotlib module.
#
# ======================================================================
#
#
# IMPORT ---------------------------------------------------------------
from myplotlib import DBUG
from myplotlib import D_IPATH
from myplotlib import MyData
# READ STUPID DATA -----------------------------------------------------
def readStupidData(ipath=D_IPATH, *args, **kwargs):
debug = kwargs.get('debug', 0)
lrawdata = MyData()
lrawdata.name = str(ipath)
lrawdata.data = [-1., 1., 1, -1.]
if(debug):
print(DBUG + 'I read the raw data with readStupidData')
return(lrawdata)
# READ STUPID DATA 2 ---------------------------------------------------
def readStupidData2(ipath=D_IPATH, *args, **kwargs):
debug = kwargs.get('debug', 0)
lrawdata = MyData()
lrawdata.name = str(ipath)
lrawdata.data = [-1., 1., -2., 2.]
if(debug):
print(DBUG + 'I read the raw data with readStupidData2')
return(lrawdata)
from .myData import MyData
# TECHNICAL ------------------------------------------------------------
D_VERSION='v5'
D_HIERARCHY='SERVER'
D_HOST='localhost'
D_PORT=50803
# FORM -----------------------------------------------------------------
INFO = " > info-: "
WARN = " > warn-: "
SEVR = " > sevr-: "