Commit 36ede192 authored by Yori's avatar Yori
Browse files

Merge branch 'dev' into toward-v6

new test suite.
parents f3239319 29a2eb6f
Pipeline #695 failed with stage
in 14 seconds
before_script:
- python3 --version
- python3 -m pip --version
- python3 -m venv --version
- apt-get update -q -y
- apt-get install python3 python3-dev python3-tk -q -y
- wget https://bootstrap.pypa.io/get-pip.py
- python3 get-pip.py
- python3 -m pip --version
- python3 -m pip install --upgrade pip
- python3 -m pip install -U matplotlib
- python3 -m pip install pep8
- python3 -m venv --python=python3.6 mplenv
- . mplenv/bin/activate
- pip install matplotlib
myplotlib_import_local_latex_tkagg:
script:
......@@ -18,30 +18,3 @@ myplotlib_import_local_latex_tkagg:
- python3 -m tests
- python3 -m tutorials
- ./clean_test_folder.sh
myplotlib_test_mytool:
script:
- git name-rev --name-only HEAD
- ls -l
- cd mpl_toolbox/
- cp ../.configs/tests/config-local.py ../config.py
- python3 -m tests
- python3 -m tutorials
myplotlib_import_network_latex_tkagg:
script:
- git name-rev --name-only HEAD
- ls -l
- cd test/network
- ./setup_test_folder.sh -r latex-tkagg
- python3 test_com_nogl.py
- python3 -m tests
- ./clean_test_folder.sh
myplotlib_test_pep8:
script:
- git name-rev --name-only HEAD
- ls -l
- cd test
- python3 -m comp_pep8
allow_failure: true
from .mpl_Data import MplData
from .mpl_data import MplData
from matplotlib import rcParams
# FORM -----------------------------------------------------------------
......@@ -9,6 +9,8 @@ DBUG = " > dbug-: "
SPCE = " > -----: "
# CONFIGURATION --------------------------------------------------------
CONTEXT= 'CLIENT'
# myFig
D_FIGNUM = 0 # default figure number
D_FIGSIZE = (8., 6.) # default figure size
......
......@@ -333,6 +333,7 @@ class MplClient():
print(str(formated_data.content))
datas = None
else:
# set the figure data to answerSig.value
datas = formated_data.content
......
......@@ -170,6 +170,7 @@ class MplFig(metaclass=FigureClassFactory, context=CONTEXT.lower()):
self.reformat = kwargs.pop('reformat', D_REFORMAT)
self.debug = kwargs.pop('debug', D_DEBUG)
self.formatted = kwargs.pop('formatted', D_FORMATTED)
self._tagged_keywords = {}
self.aliases = {}
self.FIGSIZE = kwargs.pop('figsize', self.FIGSIZE)
......@@ -196,7 +197,10 @@ class MplFig(metaclass=FigureClassFactory, context=CONTEXT.lower()):
self.addAxes()
# This will throw a pep8 error but its needed to prevent
# confusion with matplotlib -- need another name
# automatically create keys for the axes keywords to provide a 1 to 1 mapping
self._generate_tagged_keywords()
# declare the aliases
self.declare_aliases()
......@@ -206,6 +210,8 @@ class MplFig(metaclass=FigureClassFactory, context=CONTEXT.lower()):
# PRIVATE UPDATE ---------------------------------------------------
def _update(self, **kwargs):
forax = {}
# check attributes in keywords
for keyword in kwargs.keys():
......@@ -224,37 +230,62 @@ class MplFig(metaclass=FigureClassFactory, context=CONTEXT.lower()):
# update value
setattr(self, keyword, kwargs[keyword])
# For each axes update the keywords
# it is a keyword
else:
if keyword in self.aliases.keys():
alias_value = kwargs[keyword]
key_group = self.aliases[keyword]
for key in key_group:
# if the key doe not already exists (case of explicit keyword)
if not forax.get(key, False):
forax.update({key: alias_value})
else:
forax.update({keyword: kwargs[keyword]})
# For each axes collect the keywords
for ax in self.get_axes():
forax = {}
ax_specific_keys = {}
for keyword in kwargs.keys():
for keyword in forax.keys():
# ignore figure attributes
if keyword in ['rawdata'] + self._attributes_to_update_keys:
pass
if keyword in self._tagged_keywords.keys():
# Check if a key of kwargs has an alias for this axes
elif keyword in self.aliases.keys():
alax, alkey = self.aliases[keyword]
tag_ax, tag_key = self._tagged_keywords[keyword]
# If an alias is found then update axkwargs
if ax == alax:
forax.update(**{alkey: kwargs[keyword]})
if ax == tag_ax:
ax_specific_keys.update({tag_key: forax[keyword]})
# use keyword as it is for the axes
else:
forax.update(**{keyword: kwargs[keyword]})
# if the keyword was not yet updated by a specific keyword.
if (not ax_specific_keys.get(keyword, False)) and (keyword in ax.keywords):
ax_specific_keys.update({keyword: forax[keyword]})
# Then eventually all collected Keywords are updated in one go
if (forax):
if (ax_specific_keys):
if self.debug:
print (DBUG + ' fig.update ', ax, 'keywords: ', forax)
ax.update(**forax)
print (DBUG+' fig.update ', ax, 'keywords: ', ax_specific_keys)
ax.update(**ax_specific_keys)
return(True)
# GENERATE TAGGED KEYWORDS -----------------------------------------
def _generate_tagged_keywords(self):
""" make the axes keywords accessible in the figure context by inserting
a generated name to _tagged_keywords. An auto-naming scheme is
applied like so:
<axes_name>_<keyword_from_axes_context>"""
for ax in self.axes:
for key,val in ax.keywords.items():
self._tagged_keywords.update({ax.name+"_"+key : (ax , key) })
# GET AXES BY NAME -------------------------------------------------
def get_axes_by_name(self, name):
......@@ -275,11 +306,31 @@ class MplFig(metaclass=FigureClassFactory, context=CONTEXT.lower()):
if unknownax == ax :
return ax.name
# LIST KEYWORDS AVAILABLE IN THE FIGURE ----------------------------
def list_keywords(self):
""" list all keywords (_tagged_keywords) and aliases in readable form.
use get_state() for info on value."""
for ax in self.get_axes():
print(INFO+'Keywords for axes "{}":'.format(self.get_axes_name(ax)))
for key in ax.keywords:
#~ print(self._tagged_keywords.items())
for tk,axkey in self._tagged_keywords.items():
#~ print(tk,axkey)
if (axkey[1] == key) and (axkey[0] == ax):
print(INFO+' "{}": Access by "{}"'.format(key, tk))
for alias,repace_keys in self.aliases.items():
#~ print(alias,repace_keys)
for rk in repace_keys:
#~ print(rk)
if rk == tk:
print(INFO+' or via figure .alias: "{}"'.format(alias))
# GET AXES ---------------------------------------------------------
def get_axes(self):
return(self.axes)
# DEBUG --------------------------------------------------------------
# DEBUG ------------------------------------------------------------
def print_debug(self):
class_name = str(self.__class__.__name__)
print('\n' + DBUG + " {0} PARAMETERS: ".format(class_name))
......@@ -296,6 +347,26 @@ class MplFig(metaclass=FigureClassFactory, context=CONTEXT.lower()):
def layout(self):
self.grid.layout()
# GET STATE -----------------------------------------------------------
def get_state(self):
""" this function collects the current state of in the figure
by creating a dict that holds all keyword,value pairs
(taking the aliases into account)
Warning: myplotlib allows in a transparent manner to modify
the axes directly. Those changes can not be covert.
"""
state = dict()
# test for double keywords and print a waring
for tagged_key, key_value in self._tagged_keywords.items():
ax, ax_key = key_value
state.update({tagged_key : ax.keywords[ax_key]})
return state
# DEF METHOD (DECORATOR) -------------------------------------------
def def_method(self, f):
name = f.__name__
......@@ -305,6 +376,7 @@ class MplFig(metaclass=FigureClassFactory, context=CONTEXT.lower()):
raise KeyError('Fig has no method called {name}'.format(name=name))
return(f)
# === INTERFACE METHODS ============================================
#
# The interfaces methods are the one that the user supposely
......@@ -443,6 +515,16 @@ class MplFig(metaclass=FigureClassFactory, context=CONTEXT.lower()):
"""
pass
# PRINT IN NOTEBOOK ------------------------------------------------
def print_in_notebook(self, **kwargs):
"""Print the rendered figure into the current notebook.
In the server context the MplFig can not be rendered, and therefore,
can not print anything into the notebook.
"""
pass
# PRINT TO FILE ----------------------------------------------------
def print_to_file(self, filename, *args, **kwargs):
"""Print the rendered figure into a file.
......@@ -469,16 +551,6 @@ class MplFig(metaclass=FigureClassFactory, context=CONTEXT.lower()):
"""
pass
# GET STATE --------------------------------------------------------
def get_state(self):
"""Extract the state of the MplFig used to tests synchronisation.
This method make sens only in the client context, and is therefore
implemented in the ClassFactory.
"""
pass
# RE-SYNC FIGURE ---------------------------------------------------
def re_sync_fig(self):
"""Re-Synchronise a client figure with the server side.
......@@ -717,20 +789,15 @@ class MplFig(metaclass=FigureClassFactory, context=CONTEXT.lower()):
self._initialize(*args, **kwargs)
self.plot()
# DEBUG --------------------------------------------------------------
def print_debug(self):
class_name = str(self.__class__.__name__)
print('\n' + DBUG + " {0} PARAMETERS: ".format(class_name))
print(SPCE + " Raw data: " + str(self.rawdata))
print(SPCE + " ID the figure: " + str(self.fignum))
print(SPCE + "Size of the figure: " + str(self.FIGSIZE) + ' [inch] \n')
# PRINT IN NOTEBOOK --------------------------------------------------
def print_in_notebook(self, **kwargs):
pass
def _print_in_notebook_local(self, **kwargs):
"""Print the rendered figure into the current notebook.
keywords:
- as_seen : [without recalling the MplFig.plot method]
"""
as_seen = kwargs.get('as_seen', False)
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
......@@ -922,47 +989,6 @@ class MplFig(metaclass=FigureClassFactory, context=CONTEXT.lower()):
'The client is not connected to a server yet.'
'Please use the client to set up a sync conection.')
def _get_state_client(self):
""" this function collects the current state of in the figure
by creating a dict that holds all keyword,value pairs
(taking the aliases into account)
Warning: myplotlib allows in a transparent manner to modify
the axes directly. Those changes can not be covert.
"""
state = dict()
# test for double keywords and print a waring
for ax in self.axes:
# find aliases for this specific axes
masks = dict()
for alias in self.aliases.keys():
axes_for_alias, keyword = self.aliases[alias]
if axes_for_alias == ax:
masks.update({keyword: alias})
# collect all keywords of the axes and replace the keys with the
# aliases
ax_keywords = ax.keywords.copy()
for mask in masks:
if mask in ax_keywords:
ax_keywords[masks[mask]] = ax_keywords.pop(mask)
# Test if kewords are already set by an other axes
for key in ax_keywords.keys():
if key in state.keys():
print(
'Warning: The keyword \"',
key,
'\" appears in multiple axes. The Defaults will'
' be overwritten. Prevent this by using aliases')
# update the global keyword index
state.update(ax_keywords)
return state
def _re_sync_fig_client(self):
if self.client is not None:
......
from .. import D_HIERARCHY
#~ from .. import D_HIERARCHY
from .myIOs import readStupidData, readStupidData2
if D_HIERARCHY in ('CLIENT', 'client'):
#~ if D_HIERARCHY in ('CLIENT', 'client'):
from .axTestClient import AxTestClient
from .figTestClient import FigTestClient as FigTest
#~ from .axTestClient import AxTestClient
#~ from .figTestClient import FigTestClient as FigTest
# from .tests_client import myTest
# from .tests_client import test100
# from .tests import myTest
......@@ -12,50 +12,50 @@ if D_HIERARCHY in ('CLIENT', 'client'):
# testList = [test100,
# ]
elif D_HIERARCHY in ('SERVER', 'server'):
from .axTestServer import AxTestServer
from .figTestServer import FigTestServer as FigTest
#~ elif D_HIERARCHY in ('SERVER', 'server'):
#~ from .axTestServer import AxTestServer
#~ from .figTestServer import FigTestServer as FigTest
# from .tests_server import myTest
# from .tests_server import test100
# testList = [test100,
# ]
elif D_HIERARCHY in ('local', 'LOCAL'):
#~ elif D_HIERARCHY in ('local', 'LOCAL'):
from .axTest1 import AxTest1
from .axTest1 import AxTestPlot2D, AxTestPlots2D
from .figTest import FigTest1, FigTest2
from .axTest1 import AxTest1
#~ from .axTest1 import AxTestPlot2D, AxTestPlots2D
from .figTest import FigTest1, FigTest2
from .tests import myTest
#~ from .tests import myTest
# import the tests
from .tests import test100
from .tests import test200, test201, test202, test203, test204
from .tests import test300, test301, test302, test303, test304, test305
from .tests import test306, test307, test308, test309, test310, test311
from .tests import test312
from .tests import test400, test401, test402, test403
from .tests import test500, test501, test502, test503, test504
from .tests import test505, test506, test507, test508, test509
from .tests import test510, test511
from .tests import test600
# the tests to run
testList = [test100,
test201, test202, test203, test204,
test300, test301, test302, test303, test304, test305,
test306, test307, test308, test309, test310, test311,
test312,
test400, test401, test402,
test503, test506, test500, test507, test501, test502,
test504, test505, test508, test509, test510, test511,
test600,
]
# for the demos
from ..mytool import print2screen
else:
raise ImportError
#~ from .tests import test100
#~ from .tests import test200, test201, test202, test203, test204
#~ from .tests import test300, test301, test302, test303, test304, test305
#~ from .tests import test306, test307, test308, test309, test310, test311
#~ from .tests import test312
#~ from .tests import test400, test401, test402, test403
#~ from .tests import test500, test501, test502, test503, test504
#~ from .tests import test505, test506, test507, test508, test509
#~ from .tests import test510, test511
#~ from .tests import test600
#~
#~ # the tests to run
#~ testList = [test100,
#~ test201, test202, test203, test204,
#~ test300, test301, test302, test303, test304, test305,
#~ test306, test307, test308, test309, test310, test311,
#~ test312,
#~ test400, test401, test402,
#~ test503, test506, test500, test507, test501, test502,
#~ test504, test505, test508, test509, test510, test511,
#~ test600,
#~ ]
#~
#~ # for the demos
#~ from ..mytool import print2screen
#~
#~ else:
#~
#~ raise ImportError
......@@ -98,6 +98,7 @@ class AxTest(MplAxes):
return(True)
class AxBroken(MplAxes):
def FormatRawdata(self, rawdata):
......@@ -106,6 +107,7 @@ class AxBroken(MplAxes):
def Plottting(self):
return(True)
class AxMinimumImplementation(MplAxes):
def format_rawdata(self, rawdata):
......@@ -114,14 +116,20 @@ class AxMinimumImplementation(MplAxes):
def plotting(self):
return(True)
class AxWithKeywords(MplAxes):
def declare_keywords(self):
self.keywords = {'x_range': [-1., 1.],
'y_range': [-1., 1.]}
'y_range': [-1., 1.],
'title': None}
def format_rawdata(self, rawdata):
return(True)
def plotting(self):
title = self.keywords.get('title',None)
if title:
self.set_title(title)
return(True)
# IMPORT ---------------------------------------------------------------
from myplotlib import MplFig
from axes_tests import AxTest
from axes_tests import AxWithKeywords
class FigTest(MplFig):
......@@ -10,6 +12,7 @@ class FigTest(MplFig):
self.add_axes(AxTest(self), "p1")
class EmptyFig(MplFig):
FIGSIZE = (8., 6.)
......@@ -17,6 +20,7 @@ class EmptyFig(MplFig):
def addAxes(self):
pass
class BrokenFigure(MplFig):
FIGSIZE = (12., 6.)
......@@ -24,6 +28,7 @@ class BrokenFigure(MplFig):
def AddAxes(self):
pass
class FigTestWithAliases(MplFig):
FIGSIZE = (8., 6.)
......@@ -38,7 +43,23 @@ class FigTestWithAliases(MplFig):
def declare_aliases(self):
self.aliases.update({'x_range_p1': (self.axes[0], 'x_range'),
'y_range_p1': (self.axes[0], 'y_range'),
'x_range_p2': (self.axes[1], 'x_range'),
'y_range_p2': (self.axes[1], 'y_range')})
self.aliases.update({'x_range': ('p1_x_range', 'p2_x_range'),
'y_range': ('p1_y_range', 'p2_y_range')})
class FigTestAxesAliases(MplFig):
FIGSIZE = (8., 6.)
def addAxes(self):
frame1 = [0.1, 0.1, 0.4, 0.8]
frame2 = [0.6, 0.1, 0.4, 0.8]
self.add_axes(AxWithKeywords(self, frame=frame1), "p1")
self.add_axes(AxWithKeywords(self, frame=frame2), "p2")
def declare_aliases(self):
self.aliases.update({'x_range_alias': ('p1_x_range', 'p2_x_range'),
'y_range_alias': ('p1_y_range', 'p2_y_range')})
......@@ -39,9 +39,13 @@ class TestMyAxes(unittest.TestCase):
'''Verify the keywords assignments of the constructor.
'''
ax1 = AxWithKeywords(self.fig)
self.assertEqual(ax1.keywords, {'x_range': [-1., 1.], 'y_range': [-1., 1.]})
self.assertEqual(ax1.keywords, {'x_range': [-1., 1.],
'y_range': [-1., 1.],
'title': None})
ax2 = AxWithKeywords(self.fig, x_range=[1., 2.], y_range=[0., 1.])
self.assertEqual(ax2.keywords, {'x_range': [1., 2.], 'y_range': [0., 1.]})
self.assertEqual(ax2.keywords, {'x_range': [1., 2.],
'y_range': [0., 1.],
'title': None})
def test_compute_rect_default(self):
'''Test the compute_rect function without keywords.
......
......@@ -6,6 +6,7 @@ import unittest
sys.path.append('../')
from figures_tests import FigTest, BrokenFigure, EmptyFig, FigTestWithAliases
from figures_tests import FigTestAxesAliases
from axes_tests import AxWithKeywords
from ios_tests import read_stupid_data
from myplotlib import HorizontalGrid
......@@ -109,44 +110,87 @@ class TestMyFig(unittest.TestCase):
Test that the keyword xRange given to the constructor is passed to the
axes.
'''
fig = FigTest((self.data_1,), x_range=[-1., 1.])
fig = FigTest((self.data_1,), p1_x_range=[-1., 1.])
# test axes attributes
self.assertEqual(fig.axes[0].keywords['x_range'], [-1., 1.])
def test_constructore_with_aliased_keywords(self):
'''Verify that keywords meant for axes are well passed, even when aliased.
Test that a non-alised keyword goes to all axes (x_range) and that aliased
keywords are well passed (y_range_p1)
Test that a non-aliased keyword goes to all axes (x_range) and that tagged
keywords are well passed (p1_y_range)
'''
fig = FigTestWithAliases((self.data_1, self.data_2), x_range=[-1., 1.], y_range_p1=[-2., 2.])
fig = FigTestAxesAliases((self.data_1, self.data_2), x_range=[-2., 2.], p1_y_range=[-3., 3.])
# test axes attributes
self.assertEqual(fig.axes[0].keywords['x_range'], [-1., 1.])
self.assertEqual(fig.axes[1].keywords['x_range'], [-1., 1.])
self.assertEqual(fig.axes[0].keywords['y_range'], [-2., 2.])
self.assertEqual(fig.axes[1].keywords['y_range'], None)
self.assertEqual(fig.axes[0].keywords['x_range'], [-2., 2.])
self.assertEqual(fig.axes[1].keywords['x_range'], [-2., 2.])
self.assertEqual(fig.axes[0].keywords['y_range'], [-3., 3.])
self.assertEqual(fig.axes[1].keywords['y_range'], [-1., 1.])
def test_update_fig_attributes(self):
'''Verify that figure's keywords are well updated.
Test that updatable keywords from the figure can be updated by the
update function.
'''
fig = FigTest((self.data_1,))
fig.aliases = {'y_range_log': (fig.axes[0], 'y_range')}