Skip to content
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

Fixes some failing tests on windows #775

Merged

Conversation

willjp
Copy link
Contributor

@willjp willjp commented Oct 25, 2019

I took a stab at addressing some of the failing tests under python3+windows.

  • corrects failing tests in rez/tests/test_packages.py on windows
  • adds %SYSTEMROOT% envvar to Python(ActionInterpreter) so rez/tests/test_context.py tests pass on windows

filesystem.FileSystemPackageRepository.location is lowercased on
platforms with case-insensitive filesystems.

Note that these test failures did *not* appear when using `pytest` as a
testrunner.
…does not fail on windows.

python -m unittest src/rez/test_context.py test ``test_execute_command_environ``
failed under windows with python3.6. Subprocess failed printing the
following to stderr:

Fatal Python Error: failed to get random numbers to initialize Python

Problem only appears *if* %PATH% is configured with python on it,
but without %SYSTEMROOT%.

example:

    # Works
    Popen(['python', '-V'])

    # Works
    Popen(['python', '-V'], env={'PATH': 'C:\\Python-3.6.5',
                                 'SYSTEMROOT': 'C:\Windows'})

    # Fails
    Popen(['python', '-V'], env={'PATH': 'C:\\Python-3.6.5'})
@bfloch
Copy link
Contributor

bfloch commented Oct 25, 2019

Haven't tried your PR yet, but I think version and changelog are handled by @nerdvegas

@willjp
Copy link
Contributor Author

willjp commented Oct 25, 2019

oh! Sorry, I was trying to follow the directions in CONTRIBUTING.md . I can undo the commit though if it is a problem.

@bfloch
Copy link
Contributor

bfloch commented Oct 25, 2019

I think you might be right. It's just that this was recently updated and I misunderstood the change:
https://github.com/nerdvegas/rez/blob/master/RELEASE.md

@bfloch
Copy link
Contributor

bfloch commented Oct 25, 2019

Do you think you change can in future be represented by the mechanism proposed here:
#737

Not saying that we don't need the workaround for the time being, but just checking if the proposal
might miss a feature.

@willjp
Copy link
Contributor Author

willjp commented Oct 25, 2019

Oh that looks very nice! No sense hiding conditionals all over the place :)

If I have understood your proposal correctly:

  • The first commit's fixes would be addressed by your "modify_op": PlatformDependent({"windows": "windowspath"}) to format the path consistently. It would just need to be used on both ends, or have a special object that can be used to test equality.

  • The second commit is kind of weird, and specific python-3 on windows. I'm curious if it is even needed in later versions of python. A cleaner workaround within your proposal might define a whitelist of variables to inherit from the parent process unless they are assigned by the user?

Sorry, I got excited and wanted that green tests-passing badge across the board :)

@bfloch
Copy link
Contributor

bfloch commented Oct 25, 2019

Me, too. Other then your fix I am working towards fixing the other Windows tests in #773

@nerdvegas
Copy link
Contributor

nerdvegas commented Oct 25, 2019 via email

src/rez/rex.py Outdated
@@ -633,6 +634,7 @@ def error(self, value):
def subprocess(self, args, **subproc_kwargs):
if self.manager:
self.target_environ.update(self.manager.environ)
self.target_environ = self.adjust_env_for_platform(self.target_environ)
Copy link
Contributor

Choose a reason for hiding this comment

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

I would drop the return value, and avoid the unnecessary dict copy. adjust_env_for_platform should just alter self.target_environ in-place, asthe previous code already does

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed!

src/rez/rex.py Outdated
""" Make required platform-specific adjustments to env.
"""
if sys.platform.startswith('win'):
env = self._add_systemroot_to_env_win32(env)
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above, in-place rather than copy

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed!

src/rez/rex.py Outdated

"""
# 'SYSTEMROOT' only relevant on windows
if not sys.platform.startswith('win'):
Copy link
Contributor

Choose a reason for hiding this comment

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

this check is already done, and this is a non-public func, so this can be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed!

thank you, I'm never sure how much I should worry about accidents. this seems like a good rule of thumb.

src/rez/rex.py Outdated
if 'SYSTEMROOT' not in os.environ:
return env

new_env = env.copy()
Copy link
Contributor

Choose a reason for hiding this comment

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

as above, in-place rather than copy

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed!

# on case-insensitive platforms (eg windows)
base = os.path.join(self.py_packages_path, "variants_py", "2.0")
if not platform_.has_case_sensitive_filesystem:
base = base.lower()
Copy link
Contributor

Choose a reason for hiding this comment

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

should move _format_platformpath and reuse here instead

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, this sort of code already exists in another place, see https://github.com/nerdvegas/rez/blob/master/src/rezplugins/package_repository/filesystem.py#L473.

It would be good to add a utility function to rez.utils.filesystem, something like so:

def canonical_path(path, platform=None):
    if platform is None:
        from rez.utils.platform_ import platform_
        platform = platform_

    path = os.path.realpath(path)
    if not platform.has_case_sensitive_filesystem:
        path = path.lower()
    return path

I think this may also fix a potential bug currently, where two package repositories could be the same, but if one uses symlinks to the same path on disk, rez will think they are two different repos.

To give some context: The lower() is there to fix a previous bug that was caused by differing cases of the same path, on windows (non-case-sensitive), which then led rez to believe that there were two different packages that were in fact the same package ('foo' vs 'Foo' for eg).

At least if there's just the one utility function, this can be documented in one place.

Copy link
Contributor Author

@willjp willjp Oct 26, 2019

Choose a reason for hiding this comment

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

Thank you, I agree with this idea.

The FileSystemPackageRepository that you provided a link to is where I copied the logic from, and was the source of the test-failure under windows.

I wrote canonical_path in addition to tests for it.

There are some frustrating pain points here for testing however.

# python-3.6.5, windows-10
ntpath.realpath('/a/b/c')      #>> 'C:\\a\\b\\c'
posixpath.realpath('C:/a/b/c') #>> 'C:\\Users\\willjp/C:/a/b/c'

# python-3.7.4, windows-10
ntpath.realpath('/a/b/c')  #>> 'C:\\a\\b\\c'
posixpath.realpath('C:/a/b/c')  #>> 'C:\\Users\willjp/C:/a/b/c'
# python-3.7.4, linux
ntpath.realpath('/a/b/c')     #>> '\\a\\b\\c'
posixpath.realpath('/a/b/c')  #>> '/a/b/c'

This change in python is not represented in the docs, so I am uncertain when they were introduced: https://docs.python.org/3/library/os.path.html?highlight=realpath#os.path.realpath

@willjp
Copy link
Contributor Author

willjp commented Oct 26, 2019

Thank you very much for the code review!

I'm updating the code now, and I'll post again once I hve it fixed.

@willjp
Copy link
Contributor Author

willjp commented Oct 26, 2019

Firstly, thanks very much for the code-review! I really appreciate the help.

I updated the code:

  • new rez.utils.filesystem.canonical_path()
  • new test file rez.tests.test_utils.test_filesystem to test canonical_path
  • rez.tests.test_context uses canonical_path
  • rezplugins.package_repository.filesystem.FileSystemPackageRepository uses canonical_path

Unrelated to previously mentioned:

  • rez.utils.filesystem.to_nativepath() was broken (os.path.join requires an expanded list). I also adjusted it to use replace('\\', '/') .

Misc Questions:

  • I noticed from old imports that you previously had a rez.vendor.mock but removed it. None of the other tests use mocks, so I'm guessing that you made an intentional decision to use TestCase.skipTest() instead. I followed this pattern, but just wanted to confirm this is how I should be proceeding.

  • Out of curiosity, what is the goal ofrez.utils.filesystem.{to_nativepath, to_ntpath, to_posixpath} versus {os.path, ntpath, posixpath}.normpath ? I feel like the latter might accomplish more, but I didn't want to break anything you already have in place.

Finally:

Thanks for clearing up about CONTRIBUTING.md - In the future, I'll leave the version and changes files alone. :)

@bfloch
Copy link
Contributor

bfloch commented Oct 28, 2019

Together with this PR I get green tests on Windows via docker for all three python version.

@nerdvegas
Copy link
Contributor

nerdvegas commented Oct 28, 2019 via email

@bfloch bfloch mentioned this pull request Oct 30, 2019
@JeanChristopheMorinPerso
Copy link
Member

@willjp For the test file you added, instead of rez/tests/test_utils/test_filesystem.py, we will need a rez/tests/test_utils_filesystem.py. This is so that the test can be shown when using rez-selftest.

Adds header/footer so more consistent with other tests.
@willjp
Copy link
Contributor Author

willjp commented Oct 31, 2019

sure, fixed!

Actually while on the subject of tests - do you want this testfile? None of the other utils are tested directly, I wasn't sure if this was something you guys would want, or if this was unecessary.

@JeanChristopheMorinPerso
Copy link
Member

Tests are always welcome. We are lagging behind in terms of tests, so yes multiple parts of rez are not really tested. In general, I think we have about 43% of coverage. Thanks for the changes and adding the new tests :)

@willjp
Copy link
Contributor Author

willjp commented Oct 31, 2019

No problem! And that's good to know, I'll write tests as I go then :)

@willjp
Copy link
Contributor Author

willjp commented Oct 31, 2019

I'm failing on MacOS, I'll fix this

Addresses failing MacOS tests - `/var/tmp` is symlinked to `/private/var/tmp` on MacOS
@nerdvegas
Copy link
Contributor

Out of curiosity, what is the goal ofrez.utils.filesystem.{to_nativepath, to_ntpath, to_posixpath} versus {os.path, ntpath, posixpath}.normpath ? I feel like the latter might accomplish more, but I didn't want to break anything you already have in place.

Good question. I don't remember, it's worht investigating. Could be that py2.6 didn't have that support? Not sure.

Made a ticket: #783

@bfloch
Copy link
Contributor

bfloch commented Nov 5, 2019

@nerdvegas @willjp Wondering if we could make the test_utils_filesystem.py -> test_utils.py for now.
I have literally a single test from data_utils (HashableDict) and I did not want to open a new test suite for it.
Since you also have a couple of tests I wonder if we could share that namespace and rather diverge in future when we have more tests.

Thoughts?

@nerdvegas
Copy link
Contributor

nerdvegas commented Nov 5, 2019 via email

@willjp
Copy link
Contributor Author

willjp commented Nov 6, 2019

yeah absolutely, that sounds good to me. Give me a few minutes to finish up at work and I'll push an update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants