-
-
Notifications
You must be signed in to change notification settings - Fork 641
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
winVersion.isWin10: accept both int and str for Windows 10 version parameter #11796
Conversation
Until October 2020 Update, Windows 10 feature updates were of the form YYMM (year + finalized month e.g. 1909). This changed with October 2020 Update: YYHx (first/second half of year YY i.e. 20H2 = second half of 2020). Therefore convert Windows 10 version map keys to strings to support the old and new format, along with preparing for possible changes to version naming scheme in the future.
…meter. Re nvaccess#11795. For version parameter, accept both str and int, asserting if the supplied parameter is a string as Windows 10 version map keys are strings.
…consistency with more recent log output edits.
Union comes from typing module, therefore import the module in question. Also, string -> str.
source/winVersion.py
Outdated
@@ -1,10 +1,11 @@ | |||
# A part of NonVisual Desktop Access (NVDA) | |||
# Copyright (C) 2006-2020 NV Access Limited | |||
# Copyright (C) 2006-2020 NV Access Limited, Joseph Lee |
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.
Oops, must've forgotten about this one...
# Copyright (C) 2006-2020 NV Access Limited, Joseph Lee | |
# Copyright (C) 2006-2020 NV Access Limited, Bill Dengler, Joseph Lee | |
"1903": 18362, | ||
"1909": 18363, | ||
"2004": 19041, | ||
"20H2": 19042, |
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 don't like the sudden API change from build IDs to xxhx strings. Can we somehow support both? (in other words, 1903 is also 19H1)
try: | ||
if atLeast: | ||
return winVersion.build >= WIN10_VERSIONS_TO_BUILDS[version] | ||
else: | ||
return winVersion.build == WIN10_VERSIONS_TO_BUILDS[version] | ||
except KeyError: | ||
from logHandler import log | ||
log.error("Unknown Windows 10 version {}".format(version)) | ||
log.error(f"Unknown Windows 10 version {version}") |
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 like this
Hi, I’ve been meaning to ask if you wanted your name to be included in the copyright header, and now I have the answer. Regarding build ID’s, YYHx became a thing with 20H2, therefore 1903 is kept as is (besides, in enterprise-level documentation, May 2019 Update is listed as Windows 10, version 1903). We can potentially add several duplicate keys to deal with 190x and 2004 in the short term. Thanks.
|
@DHowett Any thoughts on how we should handle/refer to Windows versions? |
Hi, Although Bill's pull request proposes interesting solutions, I still think that we should go with public information from Microsoft. Thanks. |
} | ||
|
||
|
||
def isWin10(version: int = 1507, atLeast: bool = True): | ||
def isWin10(version: Union[int, str] = 1507, atLeast: bool = True): |
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 could become a mistake from and API sense. This will result in a very hard to untangle confusion between version and build.
It's also not clear on first glance (without reading the docs / implementation) that this function tells you if the OS is a particular version or greater or if it tells you that the versions string is a valid one for Windows 10.
To fix this it might be helpful to keep but deprecate the version
keyword, and introduce matchesVersionOrLater: str
and a matchesBuildOrLater: int
keywords. Alternatively have two separate public functions (which could share a private implementation if it is appropriate).
Another alternative, would be a new getWinVer()
function that returned a class type that handled comparison operators and could also be constructed by a build string / int. Allowing you to write code like"
if winVer('20H2') < getWinVer() < winVer('21H2'):
print("in expected range or releases")
Please could you also add unit tests as part of this PR. |
Hi, I think separate keyword arguments would be best given that sometimes we need a way to test NVDA inside Insider Preview builds. The “version” keyword could be deprecated in 2021.1 cycle. As for unit test request, I’ll do something about that. Thanks.
|
This function was originally added to NVDA to ease (what is now) #10964, but with microsoft/terminal#8182 we might not even use it for that case any more. However, it is used for a few other things in NVDA ( |
Hi, Windows 10 App Essentials add-on uses this function for feature update build checks, but I can instruct the add-on to check build range, which is way simpler than what we have now. Given this new information from Bill, I think a much better path forward would be deprecating and removing the entire Windows 10 check and versions to builds map altogether, reducing headache for everyone. If deprecation and removal is adopted by NV Access and contributors, I think we should do it in 2021 or 2022. Thanks.
|
I agree, but contingent on how #10964 works out. |
Hi, After thinking about Bill's comments, I'm wondering a much better approach would be detecting console host version? I know about a request to do this from Microsoft in terms of UIA Automation Id, but it breaks automated tests (Automation ID's are meant to be unique and it shines in code and tests where you need to look for a specific element). As a reference, winVersion.isWin10 function is employed in NVDA Core in:
By the way, as of yesterday, Windows 10 App Essentials add-on was edited to use winVersion.winVersion.build instead of winVersion.isWin10 function based on Bill's comments. Thanks. |
Hi, After reading Reef's comment more closely, I think a much better approach would be a new winVersion.getWinVer function that returns a 3-tuple with major, minor, and build fields. This will allow us to not only deprecate isWin10 function and Windows 10 feature update build map, it will help us make more code fragments readable such as:
In short, the new getWinVer function will be a glorified sys.getwindowsversion().platform_version tuple - platform version tuple is incorrect under 1909 and 20H2 because they change a flag while keeping ntoskrnl.exe file version intact. There are downsides and issues to consider:
As for follow-up activities, several possibilities come to my mind:
Of these, I'm torn between 1 and 3, the ideal outcome being 2 followed by 4. Thanks. |
For concise semantics when comparing windows versions, also to abstract the details of these comparisons. Allow the underlying details to change without requiring changes to already written code, eg during a transition from '2004' to '20H2' schemes.
This is one reason I was suggesting an abstraction. A type that creates a barrier between our internal windows version comparisons and the exact types returned by windows. I would be extremely surprised if older version schemes are ever modified, which means that if we have a type that can be created from any of the older version schemes, and be adapted to be created from any future version schemes, and it knows how these versions relate to each other, then we can be safe from API changes in the future.
If we decide there is a better way to do this, we should deprecate the current function and update all core usages. Then remove the deprecated function in the next API breaking release.
I think it makes sense to have a generic winVer type that can compare regardless of win 7, 8, 10 or other variants. One complication is thinking how the variants fit in, EG 10s and 10x. |
Hi, I think we can probe the registry to figure out edition differences (X, S mode, etc.). As for a WinVer type, I think a 3-tuple might be the best option for now. At this point, I think it would be best to create a different pull request, as continuing with this PR branch can create headaches due to changes made unless folks agree that we should continue the work via this PR. Thanks.
|
What data would be in this 3-tuple? How would it be constructed? Convenience of construction from either '21H2' or '2004' or 18363.1198'? I'd prefer a type where the underlying mechanism is not exposed, even if that underlying mechanism was a 3-tuple. |
Hi, The 3-tuple will consist of major, minor, build, all integers, mirroring what we get with sys.getwindowsversion().platform_version with tweaks:
Although some folks would ask us to include UBR (update build revision) data such as 19042.630, it is most useful if one wants to compare quality update level. And it turns out all the work is already done in Resource Monitor add-on: one can check Windows Registry to obtain this value, which could be included if people insist that UBR must be included. Besides, UBR is meaningless for Insider Preview builds, especially dev channel builds where UBR can either be 1 or 1000 (the former for release branch prep builds, the latter for true dev builds from rs_prerelease branch); even then, there is a way to determine if a build is a public stable build or not (again covered in Resource Monitor add-on, which probes another Windows Registry key that is only visible if one joins Windows Insider Program). The reason for going with a 3-tuple are:
Thanks. |
I'm still not convinced that exposing the tuple is a good idea:
|
Hi, in this case, I think the most sensible path would be defining a WinVersion class. In addition to creating magic methods, it then allows winVersion.isWin10 to become a method inside the new winVersion.WinVersion class, along with defining properties on Windows 10 X and S mode checks and such. Besides, there’s a much better way to tell if users are running a given feature update and/or a given version – all that’s needed is a registry key, freeing us from the burden of defining feature update build numbers every six months. In other words, I’m willing to donate part of Resource Monitor add-on code (repo: https://github.com/josephsl/resourcemonitor) to NVDA Core provided that the WinVersion class and registry-based feature update build check is acceptable.
Thanks.
|
Sorry about the quiet from my side on this. I know I've owed an update for quite some time. From the console host side, I can give the following advice: For now, and for the foreseeable future, the only traditional console host that people will be using will be versioned along with the rest of Windows. We expect that folks running OpenConsole are few and far between, but that it would be safe to treat OpenConsole as "the newest possible conhost". If there's a world where NVDA can make compatibility decisions based on individual application versions, that might make things a little easier. Conhost is versioned along with Windows, and so its
I consider this reason enough for us not to pollute its meaning by storing a version number in it 😄 Thanks. Speaking as somebody who is not on the app compatibility team, and who has nothing to do with version numbers, a three-tuple is going to be fine for detecting platform component needs. Servicing may make that complicated. I can't promise that you won't be caught out by leaving out the "UBR" version, but I can promise that determining what, if any, accessibility fixes went into a servicing version is going to be nigh-unto impossible. |
Hmmm: running @josephsl Is this the correct way to retrieve an app version? |
That's interesting. I wonder if appModule resolves to cmd/powershell (or whatever application has requested a console window?) We use a specific API that will change which process appears to own a window, which might impact tools that try to map windows to processes. (OpenConsole will only be 1.x or 2.x in release builds. Local builds will be unversioned!) |
Hi, In reply to the above comment: yes, when you run a console program, the app module will say "cmd.exe" or "powershell.exe" i.e. the name of the executable will not be conhost. Also, I'm working on a PR that will replace this one, and I hope to complete initial implementation by later today. Thanks. |
Joseph, if you don't mind, I think we should close this PR and start a new conversation for the new work. It can of course reference this one to refer to how decisions were made. |
Convenience methods and types have been added to the winVersion module for getting and comparing Windows versions. - isWin10 function found in winVersion module has been removed. - class winVersion.WinVersion is a comparable and order-able type encapsulating Windows version information. - Function winVersion.getWinVer has been added to get a winVersion.WinVersion representing the currently running OS. - Convenience constants have been added for known Windows releases, see winVersion.WIN* constants. Closes #11795 Closes #11837 Closes #11933 Replaces #11796 Replaces #11799
Link to issue number:
Fixes #11795
Summary of the issue:
Starting with Windows 10 October 2020 Update, version scheme is YYHx, not YYMM. This means going forward, integer version parameter will not work.
Description of how this pull request fixes the issue:
Windows 10 version map keys are now strings. As a result, isWin10 function can now accept either an integer or a string for version parameter. Also, edited log.error call to use formatted string literals.
Testing performed:
Tested in source code version under 20H2 with the following conditions:
Known issues with pull request:
None
Change log entry:
Changes for developers (optional):
winVersion.isWin10 function can now take a string denoting Windows 10 version.
Thanks.