Skip to content

Conversation

jhkennedy
Copy link

@jhkennedy jhkennedy commented Nov 29, 2017

This PR adds python 2 and 3 support using the module six as little as possible.

I've tried to commit like-changes in small chunks so you can easily see what was needed to change the code. Note: that means that all commits from 57dbcb9 to cb5e801 are broken. This could all be squashed for merging into master.

Status:

All tests pass in both python 2.7 and 3.5, but there are likely issues lurking in the python 2 code now with unicode vs byte strings.

Left to do:


fixes #43

Joseph H Kennedy added 6 commits November 28, 2017 14:12
In python 2, calling just `.items()`, `.values()`, or `.keys()` returns
a copy of dictionaries list of key-value pairs, values, or keys,
respectively. This results in extra memory overhead when used to iterate
over a dictionary and instead it was common to use the `.iteritems()` methods
to generate an iterator.

In python 3, `.items()` now returns an iterator-view, and the `iteritems()`
method has been removed.

Because python 3 is the current target, using `.items()` and taking the
memory hit in python 2 is preferable over using ifs or packages like six to
provide efficient iteration across both python 2 and 3.
@xylar
Copy link
Collaborator

xylar commented Nov 29, 2017

@jhkennedy, this is great!!!

I'm going through the commits one at a time. I'll note a few things here as I do because inline comments are mostly just confusing.

@xylar
Copy link
Collaborator

xylar commented Nov 29, 2017

# this is an array of date strings like 'xtime'
# convert to string
timeStrings = [''.join(xtime).strip() for xtime in timeVar.values]
timeStrings = [''.join(xtime.astype('U')) for xtime in timeVar.values]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jhkennedy, I don't think the .strip() should have been lost here. The xtime variable typically has trailing white space.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, blast. That's why I was having problems in timekeeping. 😧

I agree, this should be there still.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only thing I haven't fixed because I didn't want to edit your commit history. Once it's fixed, I'll run a few more tests but everything looks good to me so far.


# change underscores to spaces so both can be supported
dateString = dateString.replace('_', ' ')
dateString = dateString.replace('_', ' ').strip()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine, but I think the .strip() was previously in the calling code and you deleted it by mistake. Definitely doesn't hurt if this function handles dates with extra whitespace.

Copy link
Collaborator

@xylar xylar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to test this with some actual data but so far it looks really promising. Just a few very small changes I've seen so far.

@xylar
Copy link
Collaborator

xylar commented Nov 29, 2017

...and yet you get a giant red x from me suggesting you screwed something up. Thanks, GitHub, for making me look like a jerk.

@xylar
Copy link
Collaborator

xylar commented Nov 29, 2017

One other thing, our workflow is typically to work on our own forks of MPAS-Analysis rather than in branches within MPAS-Dev/MPAS-Analysis. I don't think this matters much. I personally just prefer it because it keeps the main repo free of clutter and it allows anyone who wants to to contribute without needing write access to the main repo.

Xylar Asay-Davis
'''

from __future__ import absolute_import, division, print_function, unicode_literals
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These lines are all too long (more than 80 characters) to be PEP8 compliant. Could they be broken into multiple lines, please?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can do! Are you trying to follow PEP8 exactly? I've got lots of warnings for variable naming capitalization so I turned off the PEP8 checks.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've taken care of these already, so no need to change them again.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're trying to follow PEP8 pretty closely but we use mixed case for variable names. This doesn't give me any trouble in spyder but I guess other checkers might be stricter about that particular issue.

We definitely allow longer lines when it doesn't make sense to break them but this would be a case where I would break up lines.

@xylar
Copy link
Collaborator

xylar commented Nov 29, 2017

Okay, I went ahead and pushed some commits that were needed in order for my python 2.7 test to run successfully. These address all of my comments above except the missing strip(), which I think should be done as a "fixup" on that commit.

@xylar
Copy link
Collaborator

xylar commented Nov 29, 2017

@jhkennedy, I don't think we're too worried about having every single commit work, so I don't think there's a need to squash commits later on. It could be useful to see the process here because we'll need to recreate it for other outstanding branches that have yet to be merged.


nt = len(inputData)
sp = (len(wgts) - 1)/2
sp = int((len(wgts) - 1)/2)
Copy link
Author

@jhkennedy jhkennedy Nov 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably better to use integer division here instead of a type cast:

sp = (len(wgts) - 1) // 2

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, agreed. I'll edit that commit, then. In which case, I'm not done after all...

@xylar
Copy link
Collaborator

xylar commented Nov 29, 2017

I'm about to mess with commit history so probably best not to do any committing just now. I've got tests working in both python2 and python3, so we're making rapid progress!

@xylar xylar force-pushed the jhkennedy/python3-43 branch from 00c1e14 to 180289c Compare November 29, 2017 14:20
@xylar
Copy link
Collaborator

xylar commented Nov 29, 2017

Okay, done with messing with the commit history. @jhkennedy, feel free to modify/add commits as you see fit.

@xylar xylar force-pushed the jhkennedy/python3-43 branch from 180289c to 836b39a Compare November 29, 2017 14:25
@xylar
Copy link
Collaborator

xylar commented Nov 29, 2017

@pwolfram, is this something you're going to have time to review?

In python 3, stdout/stderr are bytes objects, which get logged
incorrectly unless they get decoded into strings.
Must be decoded back to a unicode string before being written out.
@jhkennedy jhkennedy force-pushed the jhkennedy/python3-43 branch from 836b39a to 89666c4 Compare November 29, 2017 15:19
@jhkennedy
Copy link
Author

Regarding commit 7a474d1, I think there are at least 3 more init.py files with this problem that maybe the tests don't catch. What I've seen so far are:
https://github.com/MPAS-Dev/MPAS-Analysis/blob/develop/mpas_analysis/ocean/__init__.py
https://github.com/MPAS-Dev/MPAS-Analysis/blob/develop/mpas_analysis/sea_ice/__init__.py
https://github.com/MPAS-Dev/MPAS-Analysis/blob/develop/mpas_analysis/shared/time_series/__init__.py

It actually might be better to just stylistically pick absolute imports instead of relative imports (following the pythonism "explicit is better than implicit").

One other thing, our workflow is typically to work on our own forks of MPAS-Analysis rather than in branches within MPAS-Dev/MPAS-Analysis. I don't think this matters much. I personally just prefer it because it keeps the main repo free of clutter and it allows anyone who wants to to contribute without needing write access to the main repo.

Oh right, my bad! I actually prefer the forking workflow as well.

@xylar
Copy link
Collaborator

xylar commented Nov 29, 2017

It actually might be better to just stylistically pick absolute imports instead of relative imports (following the pythonism "explicit is better than implicit").

I can't honestly say why we use relative imports. I guess I just learned that way by following examples I found. @pwolfram, was this an explicit choice you made for some reason early on? Or were you following my lead?

@xylar
Copy link
Collaborator

xylar commented Nov 29, 2017

In any case, I would say a switch to absolute imports would be fine, but we should do it as a separate clean-up PR.

@jhkennedy jhkennedy force-pushed the jhkennedy/python3-43 branch from ff7d315 to fb9d482 Compare November 29, 2017 17:07
Travis will now test python 2.7, 3.5, and 3.6.
@jhkennedy jhkennedy force-pushed the jhkennedy/python3-43 branch from fb9d482 to 58bd2da Compare November 29, 2017 17:23
@xylar
Copy link
Collaborator

xylar commented Nov 29, 2017

Awesome! It looks like CI is working, too. We're still waiting on 3.6 but it would be a surprise to me if 3.5 worked and 3.6 didn't.

@jhkennedy
Copy link
Author

jhkennedy commented Nov 29, 2017

Awesome! It looks like CI is working, too. We're still waiting on 3.6 but it would be a surprise to me if 3.5 worked and 3.6 didn't.

I actually had to do a fixup just a little bit ago because 3.5 didn't work, but 3.6 did (forgot to use the conda-forge channel when creating the env).

Looks like they are all working now!

@xylar
Copy link
Collaborator

xylar commented Nov 29, 2017

Testing

I've successfully run:

  • QU240 test on my laptop:
    • python 2.7
    • python 3.6
  • 20171102.beta3rc02_1850.ne30_oECv3_ICG.edison on edison:
    • python 2.7 (from acme-unified 1.1.1)
    • python 3.6 (from my own conda environment with the listed MPAS-Analysis dependencies)

Links to the output are above.

@xylar
Copy link
Collaborator

xylar commented Nov 30, 2017

@pwolfram, unless you think you'll have time to review this today or tomorrow, I think I'm going to take you off as a reviewer and go ahead and merge this PR. Please let me know one way or another.

@xylar
Copy link
Collaborator

xylar commented Nov 30, 2017

@jhkennedy, if you are happy with the PR now, I'd suggest taking off the "don't merge" tag. You can merge it yourself if you like (once we've heard from @pwolfram) or I'll do it, whichever you prefer.

@jhkennedy
Copy link
Author

I just went through the output you linked, and it looks like we're ready to merge.

@jhkennedy
Copy link
Author

I'm happy to merge it; do you want me to leave the branch for easy python 2 -> 2+3 reference for a while?

@xylar
Copy link
Collaborator

xylar commented Nov 30, 2017

No, go ahead and delete the branch when you merge. It's easy enough to go back through the commit history as needed, especially because the commit names can give you at least a pretty good idea of what's in there.

@jhkennedy jhkennedy removed the request for review from pwolfram December 1, 2017 00:11
@jhkennedy jhkennedy merged commit 58bd2da into develop Dec 1, 2017
jhkennedy pushed a commit that referenced this pull request Dec 1, 2017
This adds python 2 and 3 support using the module `six` (as little as
possible).

The code base now follows python 3 styling with the use of __future__
imports for compatibility. This means:

* print is a function call instead of a statement
* Strings will typically be unicode instead of byte strings now.
* imports need to explicitly declare relative imports
* .keys()/.items()/.values() are used instead of iter versions from
  python 2 (there will be more memory overhead when running in python 2)
* Some imports like ConfigParser will need to be handled by six while
  python 2 is being supported.

Travis-CI will now run the pytests for python 2.7, 3.5, and 3.6.
@jhkennedy jhkennedy deleted the jhkennedy/python3-43 branch December 1, 2017 00:32
@jhkennedy jhkennedy restored the jhkennedy/python3-43 branch December 1, 2017 00:34
@jhkennedy jhkennedy deleted the jhkennedy/python3-43 branch December 1, 2017 00:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

python 3 not supported

2 participants