-
Notifications
You must be signed in to change notification settings - Fork 52
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 #640
Windows support #640
Conversation
The main.js file from conda-store-ui contains an emoji character that cannot be encoded correctly unless the encoding is set to utf-8, which is not always the default on Windows.
Windows uses a different type of permissions system than Unix. For now, using None will cause action_set_conda_prefix_permissions to do nothing.
1000 hits the sqlite3 max expression depth and results in an error.
This disables --beat on Windows and sets FORKED_BY_MULTIPROCESSING=1, which is required to make the default celery pool work on Windows.
os.path.join is incorrect for constructing a URL on Windows because URLs should always use forward slashes regardless of platform.
The cookie length was incorrectly using .seconds instead of .total_seconds(). This was only a problem on Windows because Windows has a ~16 ms precision for timedeltas, meaning the .seconds attribute for the difference was sometimes being set to 0.
This reverts commit d753976.
This is needed for uses with --json, because otherwise any stderr breaks the json.
Note: Windows test takes 25 min. macOS: 14 min. Ubuntu: 10 min. I wonder why that is. E.g., the post set up env on Windows takes 3 mins, while it takes 4 secs on macOS. Is this disk/fs perf? Other phases are also slower by 2 mins on average. |
95d6213
to
4e006f6
Compare
test_file2.write_text("b"*1000) | ||
# Test hard links | ||
test_file_hardlink = test_dir / "test_file_hardlink" | ||
test_file_hardlink.hardlink_to(test_file) |
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.
Note for reviewers: this is tested where test_dir size is tested as a whole.
encoding="utf-8", | ||
) | ||
self.stdout.write(result.stdout) | ||
if not redirect_stderr: | ||
self.stderr.write(result.stderr) | ||
return result |
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.
See #559 (comment) for context on redirects.
max_age=(authentication_token.exp - datetime.datetime.utcnow()).seconds, | ||
max_age=int( | ||
(authentication_token.exp - datetime.datetime.utcnow()).total_seconds() | ||
), |
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.
See https://github.com/conda-incubator/conda-store/pull/559/files#r1364084772 for context on this.
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.
A fun bug 😄 glad we got to the bottom of this one.
@@ -73,6 +73,10 @@ conda-unpack | |||
|
|||
### Docker Registry | |||
|
|||
```{note} |
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.
Not sure if {note} syntax is supported. It seems to be ignored if not, so seems harmless.
Manually tested this env via the admin UI:
Building, rebuilding, and deletion work. |
@costrouc This is Aaron's Windows PR with some minor changes from me. PTAL and merge if OK. |
You can do |
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.
Overall these changes do not look controversial and I'm surprised that the windows fixes were actually smaller than I expected. I was really expecting issues with pathlib etc but it looks like most of those bugs didn't exist.
@@ -513,10 +513,11 @@ def update_packages(self, db, subdirs=None): | |||
package_builds[package_key].append(new_package_build_dict) | |||
logger.info("CondaPackageBuild objects created") | |||
|
|||
batch_size = 1000 | |||
# sqlite3 has a max expression depth of 1000 | |||
batch_size = 990 |
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 bet there is an interesting story here? Is this only something that showed up on Windows?
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 haven't seen this personally, but it's mentioned in one of the Aaron's commits:
Lower the batch size for updating packages from 1000 to 990
1000 hits the sqlite3 max expression depth and results in an error.
Seems harmless, so I decided to keep it.
@@ -302,21 +302,24 @@ def _default_celery_results_backend(self): | |||
) | |||
|
|||
default_uid = Integer( | |||
os.getuid(), | |||
None if sys.platform == "win32" else os.getuid(), |
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 see sys.platform == "win32"
in many places. Should we have a constant that we create for this? Since much of our code only has a special path for Windows?
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.
More I think about it I don't think this is necessary to have a constant
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.
There was a constant in Aaron's original code. Well, two constants, in different files. Since you need to share this between multiple files, you'd have to put it in __init__
to avoid import issues. But we don't do this for any other platforms, so I decided to simply use sys.platform
, as everywhere else, to avoid introducing new entities.
openapi_url=os.path.join(self.url_prefix, "openapi.json"), | ||
docs_url=os.path.join(self.url_prefix, "docs"), | ||
redoc_url=os.path.join(self.url_prefix, "redoc"), | ||
openapi_url=posixpath.join(self.url_prefix, "openapi.json"), |
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 admit using os.path...
for urls is a hack and I should have used something like yarl for example. Thoughts? Since url paths are not the same as file paths? Maybe posixpath is the right thing to use here. It certainly seems better than os.path.
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.
A separate entity for URLs would be better, yes. But I'm not going to block this PR just because of this issue, since everything seems to work fine.
max_age=(authentication_token.exp - datetime.datetime.utcnow()).seconds, | ||
max_age=int( | ||
(authentication_token.exp - datetime.datetime.utcnow()).total_seconds() | ||
), |
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.
A fun bug 😄 glad we got to the bottom of this one.
cmd = ["du", "-sb", str(path)] | ||
else: | ||
return str(du(path)) |
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 to see the fallback is this approach 👍 If they are using cygwin or https://learn.microsoft.com/en-us/sysinternals/downloads/du it may still be possible they have du.
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.
We've already looked at du from sysinternals. Besides being a separate tool, it also produces slightly different results. And the output format is also different. As for cygwin, the context for this work is to be able to use native Windows tooling.
output = subprocess.check_output(cmd, encoding="utf-8").split()[0] | ||
if sys.platform == "darwin": | ||
# mac du does not have the -b option to return bytes | ||
output = str(int(output) * 512) |
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.
Why 512? This is a weird size since it is a half a kb.
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.
A comment from a discussion on the original PR: "Note that the numbers will be off a little bit (by less than 512) on Mac because du rounds up to the nearest multiple of 512 when converting bytes to blocks."
I'm still not certain that macOS code is correct here, but it does pass this new test (where we check all three platforms), so I'm going to keep this and will take a look later.
] | ||
|
||
# The default Celery pool requires this on Windows. See | ||
# https://stackoverflow.com/questions/37255548/how-to-run-celery-on-windows |
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.
Great glad this fix was minimal.
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.
It's still not clear whether it means that Celery works as intended, since it's not officially supported on Windows. But it does run, so we'll just use this for now.
val = disk_usage(test_dir) | ||
assert isinstance(val, str) | ||
assert 2000 + dir_size <= int(val) <= 2700 + dir_size | ||
assert 2000 + dir_size <= du(test_dir) <= 2700 + dir_size |
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 exact values depend on the block size and other details
Oh yeah this is a fun detail 😄 guess you can't be smaller than the blocksize and also can only take up an integer number of block sizes.
See #507. Original PR: #559.