-
Notifications
You must be signed in to change notification settings - Fork 95
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
Windows support #951
Windows support #951
Conversation
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, @mataton!!! This is super helpful, and glad to see the changes seem relatively minor! The primary comments are capturing the tmp filename for unlinking in tearDown
fh.write(biom1) | ||
fh.flush() | ||
self.biom_table1 = biom.load_table(fh.name) | ||
os.unlink(fh.name) |
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.
Could self.temporary_fh_name
be set within the scope of the context manager, and move the os.unlink
to tearDown
? The reason for the former is the current approach relies on scope creep which works but borders on surprising behavior. The latter is important as, if a test fails, cleanup will only reliably occur if the unlink
is performed by tearDown
.
fh.write(biom1) | ||
fh.flush() | ||
self.biom1 = load_table(fh.name) | ||
os.unlink(fh.name) |
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.
Same here per comment above
fh.write(biom1) | ||
fh.flush() | ||
self.biom_table1 = load_table(fh.name) | ||
fh.close() |
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.
Was it necessary to close
here but not in the other TestCase
s? And same here re unlink
ing. If it's viable to just unlink within the context manager than that may be easier than the tearDown
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.
If you close
the file before unlink
ing within the context manager, then it works. Otherwise you get a PermissionError
at the unlink
ing step. Looking at the code now, I think the idea of setting self.temporary_fh_name
in the context manager and putting the unlink
in tearDown
is the best solution.
biom/tests/test_parse.py
Outdated
save_table(t, tmpfile.name) | ||
obs = load_table(tmpfile.name) | ||
self.assertEqual(obs, t) | ||
os.unlink(tmpfile.name) |
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.
Same here
biom/tests/test_table.py
Outdated
h5 = h5py.File(tmpfile.name, 'w') | ||
t.to_hdf5(h5, 'tests') | ||
h5.close() | ||
|
||
h5 = h5py.File(tmpfile.name, 'r') | ||
obs = Table.from_hdf5(h5) | ||
h5.close() | ||
os.unlink(tmpfile.name) |
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.
same here
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.
These tests are creating the temporary files outside of a setUp
/tearDown
context, so the solution involving putting the unlink
in tearDown
won't work here. The reason the close
s are necessary within the context manager is that without them unlink
will throw PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\Users\\me\\AppData\\Local\\Temp\\tmpg4pk3ink'
. My understanding is that the context manager will close tmpfile
when it is finished, but it won't close h5
. Exactly why this is the case I'm unsure of.
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 think this is the case because I set delete=False
during the file creation, so a file will not be deleted when it is closed. But it seems on windows that file handles must be closed before the file may be deleted.
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.
So this solution works because it closes all file handles, including tmpfile
and h5
, and then deletes the file using unlink
. I'm not sure of a better solution for this particular case and the other similar cases.
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.
Issue is edge case if test excepts prior to unlink
. A common strategy for this type of stuff:
def setUp(self):
self.temp_files = []
def tearDown(self):
for f in self.temp_files:
os.unlink(f)
def test_some_test(self):
...
self.temp_files.append(blah)
...
biom/tests/test_table.py
Outdated
h5 = h5py.File(tmpfile.name, 'w') | ||
t.to_hdf5(h5, 'tests', creation_date=current) | ||
h5.close() | ||
|
||
h5 = h5py.File(tmpfile.name, 'r') | ||
obs = Table.from_hdf5(h5) | ||
self.assertEqual(obs.create_date, current) | ||
h5.close() | ||
os.unlink(tmpfile.name) |
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.
same here
biom/tests/test_table.py
Outdated
h5 = h5py.File(tmpfile.name, 'w') | ||
t.to_hdf5(h5, 'tests') | ||
h5.close() | ||
os.unlink(tmpfile.name) |
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.
same here
biom/tests/test_table.py
Outdated
h5 = h5py.File(tmpfile.name, 'w') | ||
t.to_hdf5(h5, 'tests') | ||
h5.close() | ||
os.unlink(tmpfile.name) |
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.
same here
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'll stop flagging on these
biom/tests/test_table.py
Outdated
'generated-by', | ||
'creation-date', | ||
'shape', 'nnz'])) | ||
'format-url', |
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 change in indent here looks incorrect as it should be aligned with the [
?
@wasade Essentially it looks like there are two scenarios. One where all the tests in whichever The other scenario is that not all of the tests within the |
- name: Build wheels (py ${{ matrix.pyver }}) Windows | ||
if: matrix.os == 'windows-latest' | ||
env: | ||
CIBW_ARCHS_WINDOWS: "amd64 win32 arm64" |
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.
Is that 32-bit windows? If so, does the build actually work?
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 repository does not need to support 32-bit architectures
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 believe it is 32 bit windows and that it works, although @qiyunzhu wrote this section of the code so he may know more than me.
biom/tests/test_table.py
Outdated
h5 = h5py.File(tmpfile.name, 'w') | ||
t.to_hdf5(h5, 'tests') | ||
h5.close() | ||
|
||
h5 = h5py.File(tmpfile.name, 'r') | ||
obs = Table.from_hdf5(h5) | ||
h5.close() | ||
os.unlink(tmpfile.name) |
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.
Issue is edge case if test excepts prior to unlink
. A common strategy for this type of stuff:
def setUp(self):
self.temp_files = []
def tearDown(self):
for f in self.temp_files:
os.unlink(f)
def test_some_test(self):
...
self.temp_files.append(blah)
...
Thanks, @mataton. I still think we do want |
@wasade Your suggested changes make sense, and there was actually already a |
Will merge once aarch64 completes |
...thank you @mataton, this is super helpful!!! One last request, could you add a changelog note? |
Happy to contribute! |
A continuation of PR #949, this PR adds support for Windows.
All issues revolve around two things:
/
vs.\
The first issue is solved with a straightforward fix using
os.join()
andos.path.sep
.The second issue is more complex. In Windows, the name of a
NamedTemporaryFile
object cannot be used to open the file a second time, while the named temporary file is still open. See this SO, and the Python docs. The strategy is to use thedelete=False
parameter to prevent the temporary file from being deleted when it is closed, and then manually delete the file when the test is done using it.