Skip to content

Commit

Permalink
Decorator to setup aliases for commands
Browse files Browse the repository at this point in the history
  • Loading branch information
leouieda committed Jul 8, 2017
1 parent 32ce456 commit aad12e0
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 16 deletions.
7 changes: 6 additions & 1 deletion gmt/ps_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
Function wrapper for the ps* modules.
"""
from .clib import call_module
from .utils import fmt_docstring, parse_bools, parse_region, kwargs2string
from .utils import fmt_docstring, parse_bools, parse_region, kwargs2string, \
use_alias


@use_alias(R='region', J='projection', B='frame', P='portrait', S='style',
G='color')
@fmt_docstring
@parse_bools
@parse_region
Expand Down Expand Up @@ -54,12 +57,14 @@ def psxy(data, **kwargs):
W : str
Set pen attributes for lines or the outline of symbols.
"""
assert isinstance(data, str), 'Only accepts file names for now.'
arg_str = ' '.join([data, kwargs2string(kwargs)])
call_module('psxy', arg_str)


@use_alias(R='region', J='projection', B='frame', P='portrait')
@fmt_docstring
@parse_bools
@parse_region
Expand Down
Binary file added gmt/tests/baseline/test_psbasemap_aliases.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gmt/tests/baseline/test_psxy_aliases.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 10 additions & 2 deletions gmt/tests/test_psbasemap.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def test_basemap_required_args():
def test_basemap_d():
"Make sure the D option works"
figure()
psbasemap(region='10/70/-300/800', J='X3i/5i', B='af',
psbasemap(R='10/70/-300/800', J='X3i/5i', B='af',
D='30/35/-200/500', F=True)


Expand All @@ -40,7 +40,7 @@ def test_psbasemap():
def test_psbasemap_list_region():
"Create a simple basemap plot passing the region as a list"
figure()
psbasemap(region=[-20, 50, 200, 500], J='X3i/3i', B='a')
psbasemap(R=[-20, 50, 200, 500], J='X3i/3i', B='a')


@figure_comparison_test
Expand Down Expand Up @@ -71,3 +71,11 @@ def test_psbasemap_winkel_tripel():
"Create a Winkel Tripel basemap plot"
figure()
psbasemap(R='90/450/-90/90', J='R270/25c', B='afg')


@figure_comparison_test
def test_psbasemap_aliases():
"Make sure the argument aliases work"
figure()
psbasemap(region=[0, 360, -90, 90], projection='W7i', frame=True,
portrait=True)
8 changes: 8 additions & 0 deletions gmt/tests/test_psxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,11 @@ def test_psxy_projection():
"Plot the data in green squares with a projection"
figure()
psxy(POINTS_DATA, R='g', J='R270/4i', S='s0.2c', G='green', B='ag')


@figure_comparison_test
def test_psxy_aliases():
"Use aliases for the arguments and make sure they work"
figure()
psxy(POINTS_DATA, region=[10, 70, -3, 8], projection='X10i',
style='d0.5c', color='yellow', frame=True, portrait=True)
70 changes: 57 additions & 13 deletions gmt/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@

COMMON_OPTIONS = {
'R': '''\
R or region : str or list
R : str or list
*Required if this is the first plot command*.
``'xmin/xmax/ymin/ymax[+r][+uunit]'``.
Specify the region of interest.''',
'J': '''\
J or projection : str
J : str
*Required if this is the first plot command*.
Select map projection.''',
'B': '''\
Expand All @@ -31,9 +31,9 @@
File name of a CPT file or ``C='color1,color2[,color3,...]'`` to
build a linear continuous CPT from those colors automatically.''',
'G': '''\
G : str
Select color or pattern for filling of symbols or polygons. Default is
no fill.''',
G : str
Select color or pattern for filling of symbols or polygons. Default
is no fill.''',
}


Expand Down Expand Up @@ -82,11 +82,11 @@ def fmt_docstring(module_func):
<BLANKLINE>
Parameters
----------
R or region : str or list
R : str or list
*Required if this is the first plot command*.
``'xmin/xmax/ymin/ymax[+r][+uunit]'``.
Specify the region of interest.
J or projection : str
J : str
*Required if this is the first plot command*.
Select map projection.
<BLANKLINE>
Expand Down Expand Up @@ -142,6 +142,56 @@ def kwargs2string(kwargs):
return arg_str


def use_alias(**aliases):
"""
Decorator to add aliases to keyword arguments of a function.
Replaces the aliases with their desired names before passing them along to
the module function.
Keywords passed to this decorator are the desired argument name and their
value is the alias.
Use this as the last decorator applied to a function (the furthest from the
``def`` statement).
Examples
--------
>>> @use_alias(R='region', J='projection')
... def my_module(**kwargs):
... print('R =', kwargs['R'], 'J =', kwargs['J'])
>>> my_module(R='bla', J='meh')
R = bla J = meh
>>> my_module(region='bla', J='meh')
R = bla J = meh
>>> my_module(R='bla', projection='meh')
R = bla J = meh
>>> my_module(region='bla', projection='meh')
R = bla J = meh
"""

def alias_decorator(module_func):
"""
Decorator that replaces the aliases for arguments.
"""

@functools.wraps(module_func)
def new_module(*args, **kwargs):
"""
New module that parses and replaces the registered aliases.
"""
for arg, alias in aliases.items():
if alias in kwargs:
kwargs[arg] = kwargs.pop(alias)
return module_func(*args, **kwargs)

return new_module

return alias_decorator


def parse_bools(module_func):
"""
Parse boolean arguments and transform them into option strings.
Expand Down Expand Up @@ -228,10 +278,6 @@ def parse_region(module_func):
{'R': '1/2/3/4'}
>>> my_module(R=[1, 2, 3, 4])
{'R': '1/2/3/4'}
>>> my_module(region=[1, 2, 3, 4])
{'R': '1/2/3/4'}
>>> my_module(region='1/2/3/4')
{'R': '1/2/3/4'}
"""

Expand All @@ -240,8 +286,6 @@ def new_module(*args, **kwargs):
"""
New function that parses R before executing the module.
"""
if 'region' in kwargs:
kwargs['R'] = kwargs.pop('region')
if 'R' in kwargs:
value = kwargs['R']
if is_nonstr_iter(value):
Expand Down

0 comments on commit aad12e0

Please sign in to comment.