Skip to content

Commit 26d00e0

Browse files
seismanweiji14
andauthored
Convert booleans arguments in build_arg_string, not in kwargs_to_strings (#1125)
* Do not convert booleans in the kwargs_to_strings decorator * Deal with boolean values in build_arg_string * load_earth_relief no longer need the convert_bools=False hack * Fix the weird codes in subplot autolabel * Fix the weird codes in text Co-authored-by: Wei Ji <[email protected]>
1 parent d105c72 commit 26d00e0

File tree

6 files changed

+52
-75
lines changed

6 files changed

+52
-75
lines changed

pygmt/datasets/earth_relief.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from pygmt.src import grdcut, which
1111

1212

13-
@kwargs_to_strings(convert_bools=False, region="sequence")
13+
@kwargs_to_strings(region="sequence")
1414
def load_earth_relief(resolution="01d", region=None, registration=None, use_srtm=False):
1515
r"""
1616
Load Earth relief grids (topography and bathymetry) in various resolutions.

pygmt/helpers/decorators.py

+8-38
Original file line numberDiff line numberDiff line change
@@ -302,14 +302,14 @@ def new_module(*args, **kwargs):
302302
return alias_decorator
303303

304304

305-
def kwargs_to_strings(convert_bools=True, **conversions):
305+
def kwargs_to_strings(**conversions):
306306
"""
307307
Decorator to convert given keyword arguments to strings.
308308
309309
The strings are what GMT expects from command line arguments.
310310
311-
Converts all boolean arguments by default. Transforms ``True`` into ``''``
312-
(empty string) and removes the argument from ``kwargs`` if ``False``.
311+
Boolean arguments and None are not converted and will be processed in the
312+
``build_arg_string`` function.
313313
314314
You can also specify other conversions to specific arguments.
315315
@@ -323,9 +323,6 @@ def kwargs_to_strings(convert_bools=True, **conversions):
323323
324324
Parameters
325325
----------
326-
convert_bools : bool
327-
If ``True``, convert all boolean arguments to strings using the rules
328-
specified above. If ``False``, leave them as they are.
329326
conversions : keyword arguments
330327
Keyword arguments specifying other kinds of conversions that should be
331328
performed. The keyword is the name of the argument and the value is the
@@ -356,16 +353,18 @@ def kwargs_to_strings(convert_bools=True, **conversions):
356353
>>> module(R="5/6/7/8")
357354
{'R': '5/6/7/8'}
358355
>>> module(P=True)
359-
{'P': ''}
356+
{'P': True}
360357
>>> module(P=False)
361-
{}
358+
{'P': False}
359+
>>> module(P=None)
360+
{'P': None}
362361
>>> module(i=[1, 2])
363362
{'i': '1,2'}
364363
>>> module(files=["data1.txt", "data2.txt"])
365364
{'files': 'data1.txt data2.txt'}
366365
>>> # Other non-boolean arguments are passed along as they are
367366
>>> module(123, bla=(1, 2, 3), foo=True, A=False, i=(5, 6))
368-
{'bla': (1, 2, 3), 'foo': '', 'i': '5,6'}
367+
{'A': False, 'bla': (1, 2, 3), 'foo': True, 'i': '5,6'}
369368
args: 123
370369
>>> import datetime
371370
>>> module(
@@ -416,8 +415,6 @@ def new_module(*args, **kwargs):
416415
"""
417416
New module instance that converts the arguments first.
418417
"""
419-
if convert_bools:
420-
kwargs = remove_bools(kwargs)
421418
for arg, fmt in conversions.items():
422419
if arg in kwargs:
423420
value = kwargs[arg]
@@ -442,30 +439,3 @@ def new_module(*args, **kwargs):
442439
return new_module
443440

444441
return converter
445-
446-
447-
def remove_bools(kwargs):
448-
"""
449-
Remove booleans from arguments.
450-
451-
If ``True``, replace it with an empty string. If ``False``, completely
452-
remove the entry from the argument list.
453-
454-
Parameters
455-
----------
456-
kwargs : dict
457-
Dictionary with the keyword arguments.
458-
459-
Returns
460-
-------
461-
new_kwargs : dict
462-
A copy of `kwargs` with the booleans parsed.
463-
"""
464-
new_kwargs = {}
465-
for arg, value in kwargs.items():
466-
if isinstance(value, bool):
467-
if value:
468-
new_kwargs[arg] = ""
469-
else:
470-
new_kwargs[arg] = value
471-
return new_kwargs

pygmt/helpers/utils.py

+26-13
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ def build_arg_string(kwargs):
106106
Transform keyword arguments into a GMT argument string.
107107
108108
Make sure all arguments have been previously converted to a string
109-
representation using the ``kwargs_to_strings`` decorator.
109+
representation using the ``kwargs_to_strings`` decorator. The only
110+
exceptions are True, False and None.
110111
111112
Any lists or tuples left will be interpreted as multiple entries for the
112113
same command line argument. For example, the kwargs entry ``'B': ['xa',
@@ -128,10 +129,20 @@ def build_arg_string(kwargs):
128129
129130
>>> print(
130131
... build_arg_string(
131-
... dict(R="1/2/3/4", J="X4i", P="", E=200, X=None, Y=None)
132+
... dict(
133+
... A=True,
134+
... B=False,
135+
... E=200,
136+
... J="X4c",
137+
... P="",
138+
... R="1/2/3/4",
139+
... X=None,
140+
... Y=None,
141+
... Z=0,
142+
... )
132143
... )
133144
... )
134-
-E200 -JX4i -P -R1/2/3/4
145+
-A -E200 -JX4c -P -R1/2/3/4 -Z0
135146
>>> print(
136147
... build_arg_string(
137148
... dict(
@@ -142,20 +153,22 @@ def build_arg_string(kwargs):
142153
... )
143154
... )
144155
... )
145-
-Bxaf -Byaf -BWSen -I1/1p,blue -I2/0.25p,blue -JX4i -R1/2/3/4
156+
-BWSen -Bxaf -Byaf -I1/1p,blue -I2/0.25p,blue -JX4i -R1/2/3/4
146157
"""
147-
sorted_args = []
148-
for key in sorted(kwargs):
158+
gmt_args = []
159+
# Exclude arguments that are None and False
160+
filtered_kwargs = {
161+
k: v for k, v in kwargs.items() if (v is not None and v is not False)
162+
}
163+
for key in filtered_kwargs:
149164
if is_nonstr_iter(kwargs[key]):
150165
for value in kwargs[key]:
151-
sorted_args.append("-{}{}".format(key, value))
152-
elif kwargs[key] is None: # arguments like -XNone are invalid
153-
continue
166+
gmt_args.append(f"-{key}{value}")
167+
elif kwargs[key] is True:
168+
gmt_args.append(f"-{key}")
154169
else:
155-
sorted_args.append("-{}{}".format(key, kwargs[key]))
156-
157-
arg_str = " ".join(sorted_args)
158-
return arg_str
170+
gmt_args.append(f"-{key}{kwargs[key]}")
171+
return " ".join(sorted(gmt_args))
159172

160173

161174
def is_nonstr_iter(value):

pygmt/src/subplot.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,9 @@ def subplot(self, nrows=1, ncols=1, **kwargs):
148148
{XY}
149149
"""
150150
kwargs = self._preprocess(**kwargs) # pylint: disable=protected-access
151-
# allow for spaces in string with needing double quotes
152-
kwargs["A"] = f'"{kwargs.get("A")}"' if kwargs.get("A") is not None else None
151+
# allow for spaces in string without needing double quotes
152+
if isinstance(kwargs.get("A"), str):
153+
kwargs["A"] = f'"{kwargs.get("A")}"'
153154
kwargs["T"] = f'"{kwargs.get("T")}"' if kwargs.get("T") else None
154155

155156
if nrows < 1 or ncols < 1:

pygmt/src/text.py

+14-4
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,23 @@ def text_(
177177
)
178178
):
179179
kwargs.update({"F": ""})
180-
if angle is not None and isinstance(angle, (int, float, str)):
180+
181+
if angle is True:
182+
kwargs["F"] += "+a"
183+
elif isinstance(angle, (int, float, str)):
181184
kwargs["F"] += f"+a{str(angle)}"
182-
if font is not None and isinstance(font, str):
185+
186+
if font is True:
187+
kwargs["F"] += "+f"
188+
elif isinstance(font, str):
183189
kwargs["F"] += f"+f{font}"
184-
if justify is not None and isinstance(justify, str):
190+
191+
if justify is True:
192+
kwargs["F"] += "+j"
193+
elif isinstance(justify, str):
185194
kwargs["F"] += f"+j{justify}"
186-
if position is not None and isinstance(position, str):
195+
196+
if isinstance(position, str):
187197
kwargs["F"] += f'+c{position}+t"{text}"'
188198

189199
extra_arrays = []

pygmt/tests/test_helpers.py

-17
Original file line numberDiff line numberDiff line change
@@ -50,23 +50,6 @@ def test_kwargs_to_strings_fails():
5050
kwargs_to_strings(bla="blablabla")
5151

5252

53-
def test_kwargs_to_strings_no_bools():
54-
"""
55-
Test that not converting bools works.
56-
"""
57-
58-
@kwargs_to_strings(convert_bools=False)
59-
def my_module(**kwargs):
60-
"""
61-
Function that does nothing.
62-
"""
63-
return kwargs
64-
65-
# The module should return the exact same arguments it was given
66-
args = dict(P=True, A=False, R="1/2/3/4")
67-
assert my_module(**args) == args
68-
69-
7053
def test_gmttempfile():
7154
"""
7255
Check that file is really created and deleted.

0 commit comments

Comments
 (0)