Skip to content

Commit aad12e0

Browse files
committed
Decorator to setup aliases for commands
1 parent 32ce456 commit aad12e0

File tree

6 files changed

+81
-16
lines changed

6 files changed

+81
-16
lines changed

gmt/ps_modules.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
Function wrapper for the ps* modules.
33
"""
44
from .clib import call_module
5-
from .utils import fmt_docstring, parse_bools, parse_region, kwargs2string
5+
from .utils import fmt_docstring, parse_bools, parse_region, kwargs2string, \
6+
use_alias
67

78

9+
@use_alias(R='region', J='projection', B='frame', P='portrait', S='style',
10+
G='color')
811
@fmt_docstring
912
@parse_bools
1013
@parse_region
@@ -54,12 +57,14 @@ def psxy(data, **kwargs):
5457
W : str
5558
Set pen attributes for lines or the outline of symbols.
5659
60+
5761
"""
5862
assert isinstance(data, str), 'Only accepts file names for now.'
5963
arg_str = ' '.join([data, kwargs2string(kwargs)])
6064
call_module('psxy', arg_str)
6165

6266

67+
@use_alias(R='region', J='projection', B='frame', P='portrait')
6368
@fmt_docstring
6469
@parse_bools
6570
@parse_region
17.2 KB
Loading
39.8 KB
Loading

gmt/tests/test_psbasemap.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def test_basemap_required_args():
1818
def test_basemap_d():
1919
"Make sure the D option works"
2020
figure()
21-
psbasemap(region='10/70/-300/800', J='X3i/5i', B='af',
21+
psbasemap(R='10/70/-300/800', J='X3i/5i', B='af',
2222
D='30/35/-200/500', F=True)
2323

2424

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

4545

4646
@figure_comparison_test
@@ -71,3 +71,11 @@ def test_psbasemap_winkel_tripel():
7171
"Create a Winkel Tripel basemap plot"
7272
figure()
7373
psbasemap(R='90/450/-90/90', J='R270/25c', B='afg')
74+
75+
76+
@figure_comparison_test
77+
def test_psbasemap_aliases():
78+
"Make sure the argument aliases work"
79+
figure()
80+
psbasemap(region=[0, 360, -90, 90], projection='W7i', frame=True,
81+
portrait=True)

gmt/tests/test_psxy.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,11 @@ def test_psxy_projection():
2323
"Plot the data in green squares with a projection"
2424
figure()
2525
psxy(POINTS_DATA, R='g', J='R270/4i', S='s0.2c', G='green', B='ag')
26+
27+
28+
@figure_comparison_test
29+
def test_psxy_aliases():
30+
"Use aliases for the arguments and make sure they work"
31+
figure()
32+
psxy(POINTS_DATA, region=[10, 70, -3, 8], projection='X10i',
33+
style='d0.5c', color='yellow', frame=True, portrait=True)

gmt/utils.py

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99

1010
COMMON_OPTIONS = {
1111
'R': '''\
12-
R or region : str or list
12+
R : str or list
1313
*Required if this is the first plot command*.
1414
``'xmin/xmax/ymin/ymax[+r][+uunit]'``.
1515
Specify the region of interest.''',
1616
'J': '''\
17-
J or projection : str
17+
J : str
1818
*Required if this is the first plot command*.
1919
Select map projection.''',
2020
'B': '''\
@@ -31,9 +31,9 @@
3131
File name of a CPT file or ``C='color1,color2[,color3,...]'`` to
3232
build a linear continuous CPT from those colors automatically.''',
3333
'G': '''\
34-
G : str
35-
Select color or pattern for filling of symbols or polygons. Default is
36-
no fill.''',
34+
G : str
35+
Select color or pattern for filling of symbols or polygons. Default
36+
is no fill.''',
3737
}
3838

3939

@@ -82,11 +82,11 @@ def fmt_docstring(module_func):
8282
<BLANKLINE>
8383
Parameters
8484
----------
85-
R or region : str or list
85+
R : str or list
8686
*Required if this is the first plot command*.
8787
``'xmin/xmax/ymin/ymax[+r][+uunit]'``.
8888
Specify the region of interest.
89-
J or projection : str
89+
J : str
9090
*Required if this is the first plot command*.
9191
Select map projection.
9292
<BLANKLINE>
@@ -142,6 +142,56 @@ def kwargs2string(kwargs):
142142
return arg_str
143143

144144

145+
def use_alias(**aliases):
146+
"""
147+
Decorator to add aliases to keyword arguments of a function.
148+
149+
Replaces the aliases with their desired names before passing them along to
150+
the module function.
151+
152+
Keywords passed to this decorator are the desired argument name and their
153+
value is the alias.
154+
155+
Use this as the last decorator applied to a function (the furthest from the
156+
``def`` statement).
157+
158+
Examples
159+
--------
160+
161+
>>> @use_alias(R='region', J='projection')
162+
... def my_module(**kwargs):
163+
... print('R =', kwargs['R'], 'J =', kwargs['J'])
164+
>>> my_module(R='bla', J='meh')
165+
R = bla J = meh
166+
>>> my_module(region='bla', J='meh')
167+
R = bla J = meh
168+
>>> my_module(R='bla', projection='meh')
169+
R = bla J = meh
170+
>>> my_module(region='bla', projection='meh')
171+
R = bla J = meh
172+
173+
"""
174+
175+
def alias_decorator(module_func):
176+
"""
177+
Decorator that replaces the aliases for arguments.
178+
"""
179+
180+
@functools.wraps(module_func)
181+
def new_module(*args, **kwargs):
182+
"""
183+
New module that parses and replaces the registered aliases.
184+
"""
185+
for arg, alias in aliases.items():
186+
if alias in kwargs:
187+
kwargs[arg] = kwargs.pop(alias)
188+
return module_func(*args, **kwargs)
189+
190+
return new_module
191+
192+
return alias_decorator
193+
194+
145195
def parse_bools(module_func):
146196
"""
147197
Parse boolean arguments and transform them into option strings.
@@ -228,10 +278,6 @@ def parse_region(module_func):
228278
{'R': '1/2/3/4'}
229279
>>> my_module(R=[1, 2, 3, 4])
230280
{'R': '1/2/3/4'}
231-
>>> my_module(region=[1, 2, 3, 4])
232-
{'R': '1/2/3/4'}
233-
>>> my_module(region='1/2/3/4')
234-
{'R': '1/2/3/4'}
235281
236282
"""
237283

@@ -240,8 +286,6 @@ def new_module(*args, **kwargs):
240286
"""
241287
New function that parses R before executing the module.
242288
"""
243-
if 'region' in kwargs:
244-
kwargs['R'] = kwargs.pop('region')
245289
if 'R' in kwargs:
246290
value = kwargs['R']
247291
if is_nonstr_iter(value):

0 commit comments

Comments
 (0)