Uh oh!
There was an error while loading. Please reload this page.
New Alias System: Add the AliasSystem class - #4000
Conversation
4c2cd8c to
f74919eComparef74919e to
410b433Compare70f883c to
95af3d5Compare95af3d5 to
ddcc7b8Compare| basemap - Plot base maps and frames. | ||
| """ | ||
| from pygmt.alias import Alias, AliasSystem |
There was a problem hiding this comment.
Changes in basemap.py is only meant for proof of concept. I plan to revert the changes in basemap.py and open separate PRs for it.
There was a problem hiding this comment.
Pull Request Overview
This PR implements the AliasSystem class to provide a new alias system that can coexist with the existing system, enabling more Pythonic parameter handling by building GMT options from multiple PyGMT parameters without abusing kwargs.
Key changes:
- Implements the
AliasSystemclass with validation for short/long-form parameter conflicts - Adds comprehensive test coverage for the new alias system functionality
- Updates the
basemapfunction to demonstrate usage of the new alias system
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
pygmt/alias.py | Implements the core AliasSystem class with parameter conflict detection and warnings |
pygmt/tests/test_alias_system.py | Adds comprehensive tests for long-form, short-form, and conflict scenarios |
pygmt/src/basemap.py | Updates basemap function to use the new alias system for region, projection, and frame parameters |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| alias = AliasSystem( | ||
| R=Alias(region, name="region", separator="/", size=[4, 6]), | ||
| J=Alias(projection, name="projection"), | ||
| B=Alias(frame, name="frame"), | ||
| ).update(kwargs) |
There was a problem hiding this comment.
Actually, I'm still debating if we should change these lines to:
| alias=AliasSystem( | |
| R=Alias(region, name="region", separator="/", size=[4, 6]), | |
| J=Alias(projection, name="projection"), | |
| B=Alias(frame, name="frame"), | |
| ).update(kwargs) | |
| kwdict=AliasSystem( | |
| R=Alias(region, name="region", separator="/", size=[4, 6]), | |
| J=Alias(projection, name="projection"), | |
| B=Alias(frame, name="frame"), | |
| ).update(kwargs).kwdict |
since only alias.kwdict is used below.
There was a problem hiding this comment.
I did wonder if we could turn the AliasSystem class into a subclass of collections.UserDict or collections.OrderedDict (or maybe collections.ChainMap?), since it is essentially just holding a dictonary with a custom update method. But then you'll need to reconcile self.aliasdict with self.kwdict.
There was a problem hiding this comment.
I did wonder if we could turn the
AliasSystemclass into a subclass ofcollections.UserDictorcollections.OrderedDict(or maybecollections.ChainMap?), since it is essentially just holding a dictonary with a customupdatemethod.
Then we will have codes like
alias = AliasSystem(A=Alias(...), B=Alias(...), ...)
build_arg_list(alias)
or rename alias to kwdict, but both may be confusing.
There was a problem hiding this comment.
or rename
aliastokwdict, but both may be confusing.
how about aliasdict = AliasSystem(...)?
There was a problem hiding this comment.
aliasdict looks good.
I just tried UserDict and it looks good. Here is a minimal example:
fromcollectionsimportUserDictfromcollections.abcimportSequencefrompygmt.aliasimportAliasclassAliasSystem(UserDict):
def__init__(self, **kwargs):
self.aliasdict=kwargskwdict= {}
foroption, aliasesinkwargs.items():
ifisinstance(aliases, Sequence):
values= [alias._valueforaliasinaliasesifalias._valueisnotNone]
ifvalues:
kwdict[option] ="".join(values)
elifaliases._valueisnotNone:
kwdict[option] =aliases._valuesuper().__init__(kwdict)
defupdate(self, kwargs):
print("Updating dict")
# Add more checks later.forshort_param, valueinkwargs.items():
self[short_param] =valuereturnselfaliasdict=AliasSystem(
A=Alias("label"),
B=Alias((0, 10), separator="/"),
C=[Alias("text"), Alias("TL", prefix="+j")]
).update({"C": "abc"})
print(aliasdict)The script output is:
Updating dict
Updating dict
{'A': 'label', 'B': '0/10', 'C': 'abc'}
As you can see, it prints Updating dict twice. One is by the super().__init__ call, another by the AliasSystem().update call. Since update is a built-in method of dict/UserDict, overriding it is not a good idea. I guess we need to change the method name from update() to something like merge()/check()?
There was a problem hiding this comment.
I've updated the AliasSystem class using UserDict in 99845c2.
| Initialize the alias system as a dictionary with current parameter values. | ||
| """ | ||
| # Store the aliases in a dictionary, to be used in the merge() method. | ||
| self.aliasdict = kwargs |
There was a problem hiding this comment.
Should't this be overriding the UserDict's data attribute? https://docs.python.org/3/library/collections.html#collections.UserDict.data
| self.aliasdict=kwargs | |
| self.data=kwargs |
Then I suppose you can use update as method name? Unless it's still not advised to override that.
There was a problem hiding this comment.
data is the real dictionary that stores the contents of the UserDict class, so changing the UserDict object also affects data.
fromcollectionsimportUserDictalias=UserDict(A="label", B="text")
print(alias.data)
print(alias)
alias.data= {"C": True}
print(alias.data)
print(alias)
alias.update({"D": "good"})
print(alias.data)
print(alias)The output is:
{'A': 'label', 'B': 'text'}
{'A': 'label', 'B': 'text'}
{'C': True}
{'C': True}
{'C': True, 'D': 'good'}
{'C': True, 'D': 'good'}
…iasSystem/aliassystem
This PR implements the
AliasSystemclass for the new alias system proposed in #3239.As mentioned in #3239, the new alias system has the following pros and cons:
pros:
kwargsanymoreCons:
{aliases}in docstrings is not supported in the new alias system, since we can't access the local variables in a decorator. So we need to manually edit the{aliases}in docstrings.