Skip to content

POC: Implement the general BaseParams class for any class-like parameters #2895

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions doc/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,15 @@ Miscellaneous
print_clib_info
show_versions

Common Parameters
-----------------

.. autosummary::
:toctree: generated

params.Box


.. currentmodule:: pygmt

Datasets
Expand Down
5 changes: 5 additions & 0 deletions pygmt/params/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""
Classes for common parameters.
"""

from pygmt.params.box import Box
75 changes: 75 additions & 0 deletions pygmt/params/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"""
General class for PyGMT parameters.
"""

from __future__ import annotations

from typing import NamedTuple

from pygmt.helpers import is_nonstr_iter


class Alias(NamedTuple):
"""
Alias PyGMT long-form parameter to GMT single-letter option flag.
"""

name: str
modifier: str
separator: str | None = None


class BaseParams:
"""
Base class for PyGMT parameters.

Examples
--------
>>> import dataclasses
>>> from pygmt.params.base import BaseParams
>>>
>>> @dataclasses.dataclass(repr=False)
... class Test(BaseParams):
... attr1: Any = None
... attr2: Any = None
... attr3: Any = None
...
... __aliases__ = [
... Alias("attr1", ""),
... Alias("attr2", "+a"),
... Alias("attr3", "+b", "/"),
... ]
>>> var = Test(attr1="val1")
>>> str(var)
'val1'
>>> repr(var)
"Test(attr1='val1')"
"""

def __str__(self):
"""
String representation of the object that can be passed to GMT directly.
"""
values = []
for alias in self.__aliases__:
value = getattr(self, alias.name)
if value in (None, False):
continue
if value is True:
value = ""

Check warning on line 59 in pygmt/params/base.py

View check run for this annotation

Codecov / codecov/patch

pygmt/params/base.py#L59

Added line #L59 was not covered by tests
elif is_nonstr_iter(value):
value = alias.separator.join(map(str, value))

Check warning on line 61 in pygmt/params/base.py

View check run for this annotation

Codecov / codecov/patch

pygmt/params/base.py#L61

Added line #L61 was not covered by tests
values.append(f"{alias.modifier}{value}")
return "".join(values)

def __repr__(self):
"""
String representation of the object.
"""
string = []
for alias in self.__aliases__:
value = getattr(self, alias.name)
if value is None or value is False:
continue
string.append(f"{alias.name}={value!r}")
return f"{self.__class__.__name__}({', '.join(string)})"
45 changes: 45 additions & 0 deletions pygmt/params/box.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""
Class for the box around GMT embellishments.
"""

from collections.abc import Sequence
from dataclasses import dataclass
from typing import ClassVar

from pygmt.params.base import Alias, BaseParams


@dataclass(repr=False)
class Box(BaseParams):
"""
Class for the box around GMT embellishments.

Attributes
----------
clearance
Set clearances between the embellishment and the box border. Can be either a
scalar value or a list of two/four values.

- a scalar value means a uniform clearance in all four directions.
- a list of two values means separate clearances in x- and y- directions.
- a list of four values means separate clearances for left/right/bottom/top.
fill
Fill for the box. None means no fill.

"""

clearance: float | str | Sequence[float | str] | None = None
fill: str | None = None
innerborder: str | Sequence | None = None
pen: str | None = None
radius: float | bool | None = False
shading: str | Sequence | None = None

__aliases__: ClassVar = [
Alias("clearance", "+c", "/"),
Alias("fill", "+g"),
Alias("innerborder", "+i", "/"),
Alias("pen", "+p"),
Alias("radius", "+r"),
Alias("shading", "+s", "/"),
]
5 changes: 3 additions & 2 deletions pygmt/src/logo.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from pygmt.clib import Session
from pygmt.helpers import build_arg_list, fmt_docstring, kwargs_to_strings, use_alias
from pygmt.params import Box


@fmt_docstring
Expand All @@ -18,7 +19,7 @@
t="transparency",
)
@kwargs_to_strings(R="sequence", c="sequence_comma", p="sequence")
def logo(self, **kwargs):
def logo(self, box: bool | Box = False, **kwargs): # noqa: ARG001
r"""
Plot the GMT logo.

Expand All @@ -39,7 +40,7 @@ def logo(self, **kwargs):
[**g**\|\ **j**\|\ **J**\|\ **n**\|\ **x**]\ *refpoint*\
**+w**\ *width*\ [**+j**\ *justify*]\ [**+o**\ *dx*\ [/*dy*]].
Set reference point on the map for the image.
box : bool or str
box
If set to ``True``, draw a rectangular border around the
GMT logo.
style : str
Expand Down
Loading