-
Notifications
You must be signed in to change notification settings - Fork 11
Fix Failing Tests on Windows (WIP) #27
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
Reviewer's Guide by SourceryThis pull request addresses failing tests on Windows platforms, focusing on file permission and symlink-related issues. The changes primarily involve modifying the test suite to account for differences in file handling between UNIX and Windows systems. No diagrams generated as the changes look simple and do not need a visual representation. File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
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 @Chiemezuo - I've reviewed your changes - here's some feedback:
Overall Comments:
- While we appreciate the effort to fix Windows compatibility, bypassing permission checks on Windows is not the ideal solution. Consider finding Windows-equivalent ways to perform these security checks rather than removing them.
- This PR only addresses one of the six failing tests. Please continue working on the other failures, particularly the symlink tests and file access issues, to ensure full Windows compatibility.
- For cross-platform development, look into Windows-specific APIs or libraries that can provide functionality equivalent to what's being tested on Unix systems. This will lead to a more robust and secure solution across all platforms.
Here's what I looked at during the review
- 🟢 General issues: all looks good
- 🟢 Security: all looks good
- 🟡 Testing: 2 issues found
- 🟢 Complexity: all looks good
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
test/test_open.py
Outdated
# UNIX systems view and manipulate file permissions as bits | ||
if os.name is 'posix': | ||
assert mode in (0o100664, 0o100644), stat.filemode(mode) | ||
new_mode = mode & 0o100770 | ||
# disparity in Windows file handling | ||
elif os.name is 'nt': | ||
# instead, just check if its a regular file without permission bit specifics | ||
new_mode = mode |
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.
suggestion (testing): Consider adding specific Windows permission checks
While the current change allows the test to pass on Windows, it doesn't verify any specific permission attributes. Consider adding Windows-specific checks to ensure the file has appropriate permissions, such as checking if it's readable and writable.
if os.name == 'posix':
assert mode in (0o100664, 0o100644), stat.filemode(mode)
new_mode = mode & 0o100770
elif os.name == 'nt':
import win32security
import ntsecuritycon as con
sd = win32security.GetFileSecurity(filename, win32security.DACL_SECURITY_INFORMATION)
dacl = sd.GetSecurityDescriptorDacl()
assert dacl.GetEffectiveRightsFromAcl({win32security.ConvertSidToStringSid(win32security.GetTokenInformation(win32security.OpenProcessToken(win32api.GetCurrentProcess(), win32security.TOKEN_QUERY), win32security.TokenUser)[0]): con.FILE_GENERIC_READ | con.FILE_GENERIC_WRITE})
new_mode = mode
test/test_open.py
Outdated
if os.name is 'posix': | ||
assert mode in (0o100664, 0o100644), stat.filemode(mode) | ||
new_mode = mode & 0o100770 | ||
# disparity in Windows file handling | ||
elif os.name is 'nt': | ||
# instead, just check if its a regular file without permission bit specifics | ||
new_mode = mode |
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.
suggestion (testing): Consider using unittest.skipIf for OS-specific tests
Instead of using if-else statements in the test, consider using unittest.skipIf decorators to clearly separate OS-specific test cases. This would improve test readability and maintenance.
@unittest.skipIf(os.name != 'posix', "Test specific to POSIX systems")
def test_posix_file_mode(self):
assert mode in (0o100664, 0o100644), stat.filemode(mode)
new_mode = mode & 0o100770
@unittest.skipIf(os.name != 'nt', "Test specific to Windows systems")
def test_windows_file_mode(self):
new_mode = mode
@rec |
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.
Good stuff, only tiny quibbles here!
I'll take a look later today at the last two tests, I might be able to just guess.
test/test_open.py
Outdated
if os.name == 'nt': | ||
try: | ||
return ctypes.windll.shell32.IsUserAnAdmin() | ||
except: |
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.
Bare except
is a bad idea because you catch things that aren't actually Exception
- things like OutOfMemoryError
or KeyboardInterrupt
: https://stackoverflow.com/questions/54948548/what-is-wrong-with-using-a-bare-except
I think the CI (that I just enabled) will catch it, but if not, here's my general purpose lint that I use: https://github.com/rec/dotfiles/blob/master/bin/run-test
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.
Thanks for the review!
I'll get started on implementing your recommendations.
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.
Would except Exception as e
work just fine for this 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.
Yes, that would work much better!
Linting would reveal a tiny defect: you don't use the new variable e
.
Best is exception Exception:
.
On linting
The few years have seen a significant change in how people write Python. More and more, projects simply require you to run ruff
with all the features turned on, on your code.
I think this is great - the code gets standardized, common errors and defects are avoided, and ruff
is blazingly fast.
You should get into the habit of using ruff
with a lot of stuff turned on, and also mypy
, even on trivial code, because it catches so many bugs.
# disparity in Windows file handling | ||
elif os.name == 'nt': | ||
# instead, just check if its a regular file without permission bit specifics | ||
new_mode = mode |
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 AI had some sort of Windows-y test for modes here, I didn't look at it, you might try it...?
- You need another
else
to catch the other cases, whatever they might be:
else:
assert False, f'Do not understand os.name = {os.name}'
- Should be
# Instead, just check if it's a regular file without permission bit specifics
- capital I, apostrophe.
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.
For:
- I wanted a human opinion, first. 😅
- Spot on! I'll get to that.
- Thanks a bunch for that fix.
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.
Also, for the Windows-y mode, I'll have to go through the code in more detail and check docs, because a chunk of it was new to me. I'll give feedback in a couple of hours, though.
test/test_open.py
Outdated
@@ -184,6 +202,12 @@ def test_mode_t(self, safer_open): | |||
assert FILENAME.read_text() == 'hello' | |||
|
|||
def test_symlink_file(self, safer_open): | |||
# check if we are on Windows and have admin rights | |||
if os.name == 'nt' and not is_windows_admin(): |
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.
You should instead decorate this test case with https://docs.python.org/3/library/unittest.html#unittest.skipIf
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.
Thanks!
I've done this.
test/test_open.py
Outdated
@@ -196,6 +220,13 @@ def test_symlink_file(self, safer_open): | |||
|
|||
def test_symlink_directory(self, safer_open): | |||
FILENAME = Path('sub/test.txt') | |||
|
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 too...
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 too.
Looks good for another round of reviews PS: I'll look deeper into the Windows-y command. |
So it's very natural to demonstrate that you comprehend and are keeping up, but a magic secret to appearing to be a more senior programmer is only talking about operative or actionable questions. Overall, you don't need to respond to comments if you agree with them, or say what you are going to do, unless there's a question! :-D (Also, you should use the review feature to group together comments in one email, not that it's a big deal, particularly with such a small project.) Computer programming is a very noisy occupation so I spend extra care in only sending people messages which are actionable, i.e., ask them to do something, or ask a question, or give them information they asked for. Otherwise, people simply miss stuff in the traffic. This also leaves more time for actual chat. 🔈 As I said, it's extremely natural, so don't think it's some sort of sin. Mostly you discover this somewhat later, when you have multiple junior programmers each trying to out-volume the other in progress reports... 😈 |
@rec A pending workflow approval |
@@ -198,8 +198,8 @@ def test_wrapper_bug(): | |||
@tdir | |||
def test_wrapper_bug2(): | |||
with pytest.raises(NotImplementedError) as e: | |||
fp = open(FILENAME, 'w') | |||
safer.writer(fp, close_on_exit=True, temp_file=True) | |||
with open(FILENAME, 'w') as fp: |
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.
Aha, I'm pretty sure you've found the issue!
So this change needs two non-obvious tweaks.
I didn't accidentally forget to open
fp
in a context in these - I'm using the close_on_exit
flag, which should automatically close fp
.
In this first test, I think you have actually revealed an issue:
with safer.writer(fp, close_on_exit=True, temp_file=True) as writer:
might not be closing fp
if there's an exception. I need to fix that. (It doesn't get detected in the Linux tests because the file handle gets closed immediately it gets destructed.)
So I need to make this change, or verify the bug doesn't exist, and then the first piece of code needs to change to:
fp = open(FILENAME, 'w')
with safer.writer(fp, close_on_exit=True, temp_file=True):
pass
Probably the second code block should stay the same...
I'll make that change and let you know!
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.
Nice! Our bug hunt pays off. :)
test/test_open.py
Outdated
@@ -183,6 +203,11 @@ def test_mode_t(self, safer_open): | |||
fp.write('hello') | |||
assert FILENAME.read_text() == 'hello' | |||
|
|||
# Skip if we are on Windows and do not have admin rights | |||
@unittest.skipIf( |
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.
Quibble: extract the common variable!
IS_WINDOWS_USER = os.name == 'nt' and not is_windows_admin()
skip_windows = unittest.skipIf(
IS_WINDOWS_USER, 'This test requires admin privileges to create symlink files on Windows'
)
[....]
@skip_windows
def test_something():
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 definitely learned something new here!
Voila: #28 I'll add you as a reviewer once you've accepted my invitation on this repo... |
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.
Really just textual issues, nothing big.
This is in line with #8
I'm working on getting the test cases to pass for Windows.
Upon installation, 6 of the 70 existing tests were failing. Here's a short summary of them:
Fixed tests
Summary by Sourcery
Bug Fixes: