Skip to content

Python 3 Upgrade #160

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

Merged
merged 35 commits into from
Aug 19, 2020
Merged

Python 3 Upgrade #160

merged 35 commits into from
Aug 19, 2020

Conversation

fanpu
Copy link
Contributor

@fanpu fanpu commented Dec 27, 2019

Plan:

Unfortunately, we have almost no test coverage so regressions must be detected by hand. Our goal is to port Tango to Python 3 while still maintaining Python 2 compatibility.

  1. Follow Futurize porting guide (http://python-future.org/automatic_conversion.html) with manual inspection. For each stage, create PRs that merge into this PR so it is clearer which changes are being introduced at which stage for accountability.
  2. Test Tango CLI on Python 3 manually (maybe write some tests?)
  3. Test Tango on Python 3 with Autolab
  4. Test Tango CLI on Python 2 manually
  5. Test Tango on Python 2 with Autolab

Tested with all CLI commands given in https://autolab.github.io/docs/tango-cli/

This is now ready for review!

@fanpu
Copy link
Contributor Author

fanpu commented Feb 29, 2020

I have looked through the stage 1 fixes applied by futurize and they LGTM, mostly very safe

@fanpu fanpu requested a review from droh April 17, 2020 00:06
@victorhuangwq victorhuangwq requested a review from TheodorJ April 17, 2020 00:09
@fanpu fanpu removed the request for review from TheodorJ May 25, 2020 20:28
Copy link
Contributor

@victorhuangwq victorhuangwq left a comment

Choose a reason for hiding this comment

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

Tested Tango by grading various assignments through Autolab, and it works as expected.
Overall the changes looks good, and I think this is a good patch (and improvement).

Some minor issues should be addressed before merging, but other than that it should be okay!

preallocator.py Outdated
@@ -29,7 +31,7 @@ def __init__(self, vmms):
def poolSize(self, vmName):
""" poolSize - returns the size of the vmName pool, for external callers
"""
if vmName not in self.machines.keys():
if vmName not in list(self.machines.keys()):
Copy link
Contributor

Choose a reason for hiding this comment

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

same comment with regards to the key situation in jobqueue

Copy link
Contributor Author

Choose a reason for hiding this comment

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

self.machines here is also either a TangoNativeDictionary or TangoRemoteDictionary

Copy link
Contributor

Choose a reason for hiding this comment

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

refer to comment below

@fanpu fanpu force-pushed the python3-upgrade branch from ef20680 to 6398c7d Compare July 6, 2020 22:04
@fanpu
Copy link
Contributor Author

fanpu commented Jul 6, 2020

@victorhuangwq Thanks for your comments! I've rectified the issues you raised, do look at it again when you're available :D

Copy link
Contributor

@victorhuangwq victorhuangwq left a comment

Choose a reason for hiding this comment

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

There are still some issues with regards to the usage of TangoRemoteDictionary. Other than that it looks good.

return self.dict[str(id)]
else:
return None

def keys(self):
return self.dict.keys()
return list(self.dict.keys())
Copy link
Contributor

Choose a reason for hiding this comment

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

doesn't it return a list here?

Wouldn't calling list again on keys() be redundant in the other lines I have highlighted above? Such as in
if vmName not in list(self.machines.keys()):

unpickled_obj = self.r.hget(self.hash_name, str(id))
obj = pickle.loads(unpickled_obj)
return obj
else:
return None

def keys(self):
return self.r.hkeys(self.hash_name)
keys = map(lambda key : key.decode(), self.r.hkeys(self.hash_name))
return list(keys)
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems to be returning a list when keys are called on the TangoRemoteDictionary.

preallocator.py Outdated
@@ -29,7 +31,7 @@ def __init__(self, vmms):
def poolSize(self, vmName):
""" poolSize - returns the size of the vmName pool, for external callers
"""
if vmName not in self.machines.keys():
if vmName not in list(self.machines.keys()):
Copy link
Contributor

Choose a reason for hiding this comment

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

refer to comment below

@fanpu fanpu changed the title Python 3 Upgrade (WIP) Python 3 Upgrade Aug 14, 2020
@cg2v
Copy link
Member

cg2v commented Aug 15, 2020

This should not block the upgrade, since I believe the current code to be correct, but most if not all of the keys() calls in the code do not require the list form of the keys (you only need to listify the keys if you either want to use [] to access elements of the key list, or if you will alter the dict while iterating over the keys). Furthermore, a more readable way to do
if vmName in self.machines.keys():

would be to implement __contains__ in the Tango*Dictionary classes themselves and then call

if vmName in self.machines:

instead. TangoRemoteDictionary could use HEXISTS to implement __contains__ and not have to fetch everything.

jobManager.py Outdated
@@ -117,7 +129,7 @@ def __manage(self):
tango = TangoServer()
tango.log.debug("Resetting Tango VMs")
tango.resetTango(tango.preallocator.vmms)
for key in tango.preallocator.machines.keys():
for key in list(tango.preallocator.machines.keys()):
Copy link
Member

Choose a reason for hiding this comment

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

Another unnecessary list()

preallocator.py Outdated
@@ -44,7 +46,7 @@ def update(self, vm, num):
of machines as necessary.
"""
self.lock.acquire()
if vm.name not in self.machines.keys():
if vm.name not in list(self.machines.keys()):
Copy link
Member

Choose a reason for hiding this comment

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

another unnecessary list()

@fanpu
Copy link
Contributor Author

fanpu commented Aug 15, 2020

This should not block the upgrade, since I believe the current code to be correct, but most if not all of the keys() calls in the code do not require the list form of the keys (you only need to listify the keys if you either want to use [] to access elements of the key list, or if you will alter the dict while iterating over the keys). Furthermore, a more readable way to do
if vmName in self.machines.keys():

would be to implement __contains__ in the Tango*Dictionary classes themselves and then call

if vmName in self.machines:

instead. TangoRemoteDictionary could use HEXISTS to implement __contains__ and not have to fetch everything.

@cg2v This is a great suggestion, I will add it as a future enhancement instead of adding that to this PR to avoid making this PR bigger than it already is.

Thank you and really appreciate the spotting of other redundant wrappers of list as well!

Copy link
Contributor

@victorhuangwq victorhuangwq left a comment

Choose a reason for hiding this comment

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

Testing: Tested Tango3 branch by grading various assignments through Autolab, and it works as expected.

I have verified that:

  1. Patch from Autograding. Error message: 795: unexpected token at '---' #153 has been applied
  2. Unnecessary lists, as mentioned by both @cg2v and I, has been removed
  3. Dockerfile is now back on 18.04 (change removed)

This pull request LGTM :)

@victorhuangwq
Copy link
Contributor

victorhuangwq commented Aug 19, 2020

@fanpu Before you merge in however, please create an alternate Python 2 branch, preferably called master-python-2 to hold the old code.

At the same time, here are the list of things we should also do alongside this PR. I can help with it as well.

  • Update the description on the readme under the section Python 3 Upgrade. I do believe the wording that was used in the Autolab readme regarding rails 4 support is good.
  • Add a new release, marking this as a new version of Tango. (v2.0.0 maybe?)

@fanpu
Copy link
Contributor Author

fanpu commented Aug 19, 2020

  • Created master-python2 branch with updated README.
  • Updated the README on this branch to refer to master-python2 branch for legacy purposes.

I will draft a new release after I merge this to master. I think other TODO items would include update installation instructions on our docs too.

@fanpu fanpu merged commit 88fcf61 into master Aug 19, 2020
@oliverli oliverli deleted the python3-upgrade branch February 18, 2021 18:35
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.

Autograding. Error message: 795: unexpected token at '---' NoneType Exception When Queuing Jobs
3 participants