Skip to content

fix: python 2 Function interfaces recompatibility #2093

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 11 commits into from
Aug 12, 2017

Conversation

mgxd
Copy link
Member

@mgxd mgxd commented Jun 23, 2017

Fixes #2060 #2038 .

Changes proposed in this pull request

  • FIX: allow python 2 code in Function again

unicode in python 2 functions is a nono
@satra
Copy link
Member

satra commented Jun 24, 2017

@mgxd - this is not a good solution as we do want people to use print function everywhere. it's completely fine in python 2.

@codecov-io
Copy link

codecov-io commented Jun 24, 2017

Codecov Report

Merging #2093 into master will increase coverage by <.01%.
The diff coverage is 90.16%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2093      +/-   ##
==========================================
+ Coverage   72.19%   72.19%   +<.01%     
==========================================
  Files        1158     1160       +2     
  Lines       58032    58054      +22     
  Branches     8336     8336              
==========================================
+ Hits        41895    41912      +17     
- Misses      14815    14820       +5     
  Partials     1322     1322
Flag Coverage Δ
#smoketests 72.19% <90.16%> (ø) ⬆️
#unittests 69.84% <90.16%> (ø) ⬆️
Impacted Files Coverage Δ
nipype/pipeline/engine/workflows.py 76.27% <100%> (+0.04%) ⬆️
nipype/utils/tests/test_misc.py 100% <100%> (ø) ⬆️
nipype/utils/functions.py 100% <100%> (ø)
nipype/interfaces/utility/wrappers.py 86.11% <100%> (ø) ⬆️
nipype/utils/misc.py 80.35% <100%> (-3.11%) ⬇️
nipype/pipeline/engine/utils.py 78.72% <66.66%> (+0.02%) ⬆️
nipype/utils/tests/test_functions.py 82.75% <82.75%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4b587d6...d3ff652. Read the comment docs.

@mgxd
Copy link
Member Author

mgxd commented Jun 24, 2017

@satra hm, wouldn't we want to support all python 2 legacy code though? And then once 1.0 rolls around, drop py2 support altogether

@satra
Copy link
Member

satra commented Aug 9, 2017

@mgxd - i see a change but no specific test for the issue. could you please add a test?

@oesteban
Copy link
Contributor

oesteban commented Aug 9, 2017

@mgxd @satra I guess the issue here is that we have the from __future__ import ... only at the top of files, and since functions are serialized within the Function interface, those imports don't work anymore.

The "right" fix here would not be adding:

from __future__ import print_function, division, unicode_literals, absolute_import
from future import standard_library
standard_library.install_aliases()
from builtins import str, bytes, range, zip

right after the function definition in the string?

@mgxd
Copy link
Member Author

mgxd commented Aug 9, 2017

@oesteban To me, tt looks like the function wrapped in the Function interface does get the from __future__ imports applied - however by including unicode_literals, we are forcing any external packages imported within the function to be flexible enough to handle unicode by overwritting the default str.

Essentially, this seems to be the chain of events

# nipype/misc/utils
from __future__ import unicode_literals # and the others
# function code
import numpy as np
this_array = np.array(['1.1'])
np.savetxt('test.txt', this_array, fmt='%.6f')

resulting in ValueError: invalid fmt: u'%.6f'

Could you expand on what you meant be the "right" fix?

@oesteban
Copy link
Contributor

oesteban commented Aug 9, 2017

Well, I meant the "right" fix because Function interfaces are 2-3 incompatible islands at the moment. My suggestion would indeed require any wrapped function to be python 3 compliant.

@mgxd mgxd requested a review from satra August 9, 2017 21:06
assert is_string() == wrapped_func()

wrapped_func2 = create_function_from_source(getsource(print_statement))
wrapped_func2()
Copy link
Member

Choose a reason for hiding this comment

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

no test here?

Copy link
Member Author

Choose a reason for hiding this comment

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

will raise syntax error if print can't be done - is there a better way to do this?

Copy link
Member

Choose a reason for hiding this comment

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

with pytest.raises(SyntaxError): wrapped_func2()

Copy link
Member

Choose a reason for hiding this comment

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

ah but it doesn't error by default. so you should return something from the function call and check with assert.

@pytest.mark.skipif(sys.version_info[0] > 2, reason="breaks python 3")
def test_func_py2():
def is_string():
return isinstance('string', str)
Copy link
Member

Choose a reason for hiding this comment

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

why would this function break python 3?

Copy link
Member

Choose a reason for hiding this comment

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

perhaps separate out into two tests - the print statement which breaks python 3 and the function which should be fine for both.

Copy link
Member Author

Choose a reason for hiding this comment

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

@satra it'll raise an AssertionError - I've isolated the tests though

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.

4 participants