Skip to content

Commit a3f3b56

Browse files
committed
Implement a general BaseParams class for complex options
1 parent 118a873 commit a3f3b56

File tree

5 files changed

+137
-2
lines changed

5 files changed

+137
-2
lines changed

doc/api/index.rst

+9
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,15 @@ Miscellaneous
206206
print_clib_info
207207
show_versions
208208

209+
Common Parameters
210+
-----------------
211+
212+
.. autosummary::
213+
:toctree: generated
214+
215+
params.Box
216+
217+
209218
.. currentmodule:: pygmt
210219

211220
Datasets

pygmt/params/__init__.py

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""
2+
Classes for common parameters.
3+
"""
4+
5+
from pygmt.params.box import Box

pygmt/params/base.py

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""
2+
General class for PyGMT parameters.
3+
"""
4+
5+
from __future__ import annotations
6+
7+
from typing import NamedTuple
8+
9+
from pygmt.helpers import is_nonstr_iter
10+
11+
12+
class Alias(NamedTuple):
13+
"""
14+
Alias PyGMT long-form parameter to GMT single-letter option flag.
15+
"""
16+
17+
name: str
18+
modifier: str
19+
separator: str | None = None
20+
21+
22+
class BaseParams:
23+
"""
24+
Base class for PyGMT parameters.
25+
26+
Examples
27+
--------
28+
>>> import dataclasses
29+
>>> from pygmt.params.base import BaseParams
30+
>>>
31+
>>> @dataclasses.dataclass(repr=False)
32+
... class Test(BaseParams):
33+
... attr1: Any = None
34+
... attr2: Any = None
35+
... attr3: Any = None
36+
...
37+
... __aliases__ = [
38+
... Alias("attr1", ""),
39+
... Alias("attr2", "+a"),
40+
... Alias("attr3", "+b", "/"),
41+
... ]
42+
>>> var = Test(attr1="val1")
43+
>>> str(var)
44+
'val1'
45+
>>> repr(var)
46+
"Test(attr1='val1')"
47+
"""
48+
49+
def __str__(self):
50+
"""
51+
String representation of the object that can be passed to GMT directly.
52+
"""
53+
values = []
54+
for alias in self.__aliases__:
55+
value = getattr(self, alias.name)
56+
if value in (None, False):
57+
continue
58+
if value is True:
59+
value = ""
60+
elif is_nonstr_iter(value):
61+
value = alias.separator.join(map(str, value))
62+
values.append(f"{alias.modifier}{value}")
63+
return "".join(values)
64+
65+
def __repr__(self):
66+
"""
67+
String representation of the object.
68+
"""
69+
string = []
70+
for alias in self.__aliases__:
71+
value = getattr(self, alias.name)
72+
if value is None or value is False:
73+
continue
74+
string.append(f"{alias.name}={value!r}")
75+
return f"{self.__class__.__name__}({', '.join(string)})"

pygmt/params/box.py

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""
2+
Class for the box around GMT embellishments.
3+
"""
4+
5+
from collections.abc import Sequence
6+
from dataclasses import dataclass
7+
from typing import ClassVar
8+
9+
from pygmt.params.base import Alias, BaseParams
10+
11+
12+
@dataclass(repr=False)
13+
class Box(BaseParams):
14+
"""
15+
Class for the box around GMT embellishments.
16+
17+
Attributes
18+
----------
19+
clearance
20+
Set clearances between the embellishment and the box border. Can be either a
21+
scalar value or a list of two/four values.
22+
23+
- a scalar value means a uniform clearance in all four directions.
24+
- a list of two values means separate clearances in x- and y- directions.
25+
- a list of four values means separate clearances for left/right/bottom/top.
26+
fill
27+
Fill for the box. None means no fill.
28+
29+
"""
30+
31+
clearance: float | str | Sequence[float | str] | None = None
32+
fill: str | None = None
33+
innerborder: str | Sequence | None = None
34+
pen: str | None = None
35+
radius: float | bool | None = False
36+
shading: str | Sequence | None = None
37+
38+
__aliases__: ClassVar = [
39+
Alias("clearance", "+c", "/"),
40+
Alias("fill", "+g"),
41+
Alias("innerborder", "+i", "/"),
42+
Alias("pen", "+p"),
43+
Alias("radius", "+r"),
44+
Alias("shading", "+s", "/"),
45+
]

pygmt/src/logo.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from pygmt.clib import Session
66
from pygmt.helpers import build_arg_list, fmt_docstring, kwargs_to_strings, use_alias
7+
from pygmt.params import Box
78

89

910
@fmt_docstring
@@ -18,7 +19,7 @@
1819
t="transparency",
1920
)
2021
@kwargs_to_strings(R="sequence", c="sequence_comma", p="sequence")
21-
def logo(self, **kwargs):
22+
def logo(self, box: bool | Box = False, **kwargs): # noqa: ARG001
2223
r"""
2324
Plot the GMT logo.
2425
@@ -39,7 +40,7 @@ def logo(self, **kwargs):
3940
[**g**\|\ **j**\|\ **J**\|\ **n**\|\ **x**]\ *refpoint*\
4041
**+w**\ *width*\ [**+j**\ *justify*]\ [**+o**\ *dx*\ [/*dy*]].
4142
Set reference point on the map for the image.
42-
box : bool or str
43+
box
4344
If set to ``True``, draw a rectangular border around the
4445
GMT logo.
4546
style : str

0 commit comments

Comments
 (0)