-
Notifications
You must be signed in to change notification settings - Fork 1
refactor: use modern python development pardigm #18
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
base: main
Are you sure you want to change the base?
Conversation
I guess by modern python development paradigm you mean using |
When I was about to finish reviewing |
If you look at the PR I also changed numerous things that were not available prior to Python 3.7 one-liner extention of dict, no init files, dataclasses so that's a bit more than just replacing files. |
Yeah, don't worry, improvements in behavior are also welcome 😃 I even have a todo list, like |
I think all these ideas are good ideas but they are out of scope for this PR. Could you open individual issues for each one of them so we can discuss implementation on case by case ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hey @12rambau, I reviewed almost all modification. I might need to give a final lookup before approving. Also we can discuss on my comment. Thanks
def _addImage(self, image, visParams=None, name=None, shown=True, opacity=1): | ||
"""Add Image Layer to map.""" | ||
vis = layers.VisParams.from_image(image, visParams) | ||
image = layers.Image(image, vis) | ||
layer = image.layer(opacity, shown) | ||
data = layer.info() | ||
data["name"] = name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry @12rambau, but I don't agree much on this, which also relates to changes in lines 25 and 26.. addLayer
is a proxy method to add different kind of layers, as in the code editor, the idea is to be able to add other types as FeatureCollection
, Geometry
, etc.. and I think having all procedures in the same method inside if..else
blocks is less convenient than having one hidden method for each case (_addImage
, _addFeatureCollection
, etc)
print("opacity cannot be less than 0, setting to 0") | ||
opacity = 0 | ||
self.opacity = opacity | ||
self.opacity = max(min(opacity, 1), 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this way we loose the benefit of telling the user what went wrong (lines 123 & 126)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TBH I think it isn't worth the extra lines, this clamp mechanism is super simple to read and it will reduce the number of if statements to check in the coverage. Is it a problem if when a user sets opacity to 14, we silently agree it's dum and set it to 1?
In your implementation the map is displayed anyway so apart from advanced users nobody will see the actual log.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 I don't think only advanced users will see it, since it's not going to the flask log but to the interpreter stdout (considering users read it, which is not always the case)... maybe we could use the logging
module. We could also reduce the number of if
statements by checking both greater and lower at the same time, like
if opacity > 1 or opacity < 0:
print("opacity cannot be greater than 1 or lower than 0, setting to 1")
opacity = 1
I know is an extra statement just to send some message to the user.. I guess it's a matter of deciding where we consider the trade off
if isinstance(bands, list): | ||
bands_list = bands | ||
bands_str = visparamsListToStr(bands) | ||
return ",".join([f"{b}" for b in viz_params]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this kind of makes sense from a python perspective, but it's not the needed solution. The issue arises when passing a two elements list, then it should only use the first one. When passing more than 3 elements, then I should think more in depth 🤔 the code says use only the first but maybe we could use the first 3 elements. This would require some testing.
for the current approach I'd suggest
if 0 < n < 3 :
newbands = f"{params[0]}"
else:
newbands = f"{params[0]},{params[1]},{params[2]}"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about something like this ? (I think the numbers re wrong I always need to double-check these things)
slice = 3 if n >= 3 else 1
return ",".join([f"{b}" for b in viz_params[:slice])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the output is the same, and is a bit less readable to me.. but I'm ok
Returns: | ||
a string formatted as needed by ee.data.getMapId | ||
""" | ||
if not params: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was for handling empty lists
for band in bands: | ||
proxy_bands.append(band.strip()) | ||
return proxy_bands | ||
return [b.strip() for b in viz_params.split(",")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here, as this is not used by the user, I agree with the list comprehension
@staticmethod | ||
def __format_bands(bands): | ||
"""TODO Missing docstring.""" | ||
def __format_bands(self, bands: Union[str, list]) -> list: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this doesn't need to be attached to self
, in fact, as it is here breaks the factory method VisParams.from_image
. I could've used the functions in helpers.py
but since some funcions there where exclusively to used in viz params, like visparamsListToStr
, I decided to put them as static methods of layers.VisParams
else: | ||
bands = visParams["bands"] | ||
bands = visParams.get("bands", image.bandNames().getInfo()) | ||
bands = cls.__format_bands(bands) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is failing 'cos __format_bands
is no longer an static method
if "bands" not in visParams: | ||
bands = image.bandNames().getInfo() | ||
else: | ||
bands = visParams["bands"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the same issue as in helpres.py
. The purpose of this was to avoid fetching the band names if the user provides them. I'd agree on doing
try:
bands = visParams["bands"]
except KeyError:
bands = image.bandNames().getInfo()
but using dict.get
will fetch every time
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is it a problem to fetch every time ? you worry about computation cost/time ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exactly, cost/time
bands = visParams["bands"] | ||
bands = visParams.get("bands", image.bandNames().getInfo()) | ||
bands = cls.__format_bands(bands) | ||
visParams["bands"] = bands |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
erasing this line makes previous lines useless
TODO
I already reviewed the
helper.py
file and I started to look at thelayers.py
one. There is a lot of duplicated code. As refactoring is a painful process I would like to make sure that this is needed. If not let me know and we'll try to get rid of the one that are done twice.@rodrigo-ldc could you help me on this?