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

Windows version: introduce winVersion.WinVersion class to serve as a hub of Windows version information for the system #11837

Closed
josephsl opened this issue Nov 18, 2020 · 4 comments · Fixed by #11909
Milestone

Comments

@josephsl
Copy link
Collaborator

Hi,

Stemming from PR #11796 discussion:

Background

Python provides sys.getwindowsversion(), returning Windows version information as a named tuple. By default, the first five fields (major, minor, build, platform, service pack) are printed. NVDA uses this name tuple in a variety of places, including Windows version text (log output), build checks in various places, and more recently, winVersion.isWin10 function returning if the system is running a given Windows 10 release or later.

Is your feature request related to a problem? Please describe.

Until early 2020, Windows 10 feature updates can be represented as integers, such as 2004 for May 2020 Update (build 19041). This changed officially with October 2020 Update when the feature update version is designated "20H2". For an extensive discussion surrounding this, see #11795

In addition, Microsoft released Windows 10 in S mode (formerly Windows 10 S), which was optimized for schools. Among other things, it does not allow installation of third-party classic (Win32/desktop) apps apart from repackaged apps published to Microsoft Store (NVDA is one of them now). Although NVDA will know about running as a converted desktop app, it doesn't know if it is truly running on regular or S mode of Windows 10. Making matters complicated is upcoming Windows 10 X, which will try to use virtualization to run desktop apps, impacting NVDA and accessibility.

Describe the solution you'd like

To help mitigate #11795 and to support detection of specific editions and feature sets, introduce WinVersion structure as part of winVersion module. This class will serve as a hub of Windows version information for the system NVDA is running on. Attributes can include whether or not this is a Windows 10 system, if it is a server running Desktop Experience (servers only), sub-edition in use (S mode, X, etc.) and so on.

The biggest benefits are:

  • Allowing NVDA to truly detect if it is running on Windows 10 in S mode or as a virtualized app under Windows 10 X.
  • Eases comparison between ideal and actual Windows 10 feature updates, useful for checking if the system is running a specific feature update.

Required attributes and methods

  • Major (integer property): major version of Windows
  • Minor (integer property): the minor Windows version
  • Build (integer property): the current build number
  • Platform (integer property): what kind of platform the system is presenting as (client, server, etc.)
  • Service pack (integer property): service pack level
  • isWin10 (method): a boolean method, replacing winVersion.isWin10 function
  • Windows 10 feature update to build map (map): transfer the dictionary defined in winVersion module to the class
  • win10Release (string property): the actual feature update version in use by the system (either look up Windows Registry or use feature update to build map)
  • isWin10S (boolean property): if the system is running Windows 10 in S mode
  • isWin10X (boolean property): same principle as isWin10S
  • Comparison operators (magic methods): useful for comparing current Windows version with an arbitrary WinVersion class instance

The constructor can take an optional "versionn" argument (string). It can accept:

  • Nothing, in which case WinVersion will construct version information for the current system.
  • "7", "8", "8.1": will set appropriate major/minor/build/service pack info and such.
  • "10" or any feature update string (such as "1507" and "20H2"): set major to 10, minor to 0, look up the build from feature update to build map, throwing errors if the build is not present.

At a minimum, comparison operators must check major, minor, build, and service pack.

Describe alternatives you've considered

Either:

Additional context

See #11795

Thanks.

@feerrenrut
Copy link
Contributor

This looks good, but I think more thought should be put into the construction:

  • Rather than creating a WinVersion for the running OS when no args provided (an implicit behavior), I'd prefer an explicit behaviour, Eg a method on the module getRunningWinVersion() or getActiveWinVersion() or getOSWinVersion().
  • I'd prefer dedicated keyword arguments in order to construct from the different types of version information. Otherwise it could become really painful when there is some ambiguous case. We could add a helper to the module to construct from string and raise on ambiguous cases. When this happens it's good to be able to fall back on the explicit version with multiple keyword args.

@josephsl
Copy link
Collaborator Author

josephsl commented Nov 18, 2020 via email

@feerrenrut
Copy link
Contributor

I'd leave the tricky part as a "nice to have". It could be added subsequently. Getting the core of this in place is more important.

@josephsl
Copy link
Collaborator Author

josephsl commented Nov 20, 2020 via email

josephsl added a commit to josephsl/nvda that referenced this issue Dec 2, 2020
Introduce winVersion.WinVersion class to serve as a hub of Windows version information for the system. The class (wrapped inside functools.total_ordering) will record version major, minor, build, and service pack information if present. It will also include a way to check for specific Windows 10 releases i.e. transplant winVersion.isWin10 function to winVersion.WinVersion.isWin10 method (later commit), as well as preparing for other checks such as Windows 10 X, Windows 10 on S mode, server, and others in the future. The class itself is wrapped inside functools.total_ordering decorator so that instnaces (Windows version data) can be compared easily.
josephsl added a commit to josephsl/nvda that referenced this issue Dec 2, 2020
Introduce winVersion.getWinVer function to return a WinVersion object representing the version info for the curretn system (version major, minor, build, service pack). This can be used to check for specific Windows releases (including Windows 10 feature updates) and eases comparisons among version info objects.
josephsl added a commit to josephsl/nvda that referenced this issue Dec 2, 2020
…nvaccess#11837.

winversion.getWinVerFromVersionText function can be used to construct WinVersion class instance from the Windows version string of the form major.minor.build i.e. '10.0.19041' will return a WinVersion class instance with major=10, minor=0, build=19041. This is the text counterpart to getWinVer function and is meant to prepare for a future scenario where an add-on or other NVDA components can perform actions based on a specific version text given.
josephsl added a commit to josephsl/nvda that referenced this issue Dec 7, 2020
Add unit tests for the following:
* winVersion.getWinVer (compared against what Python returns through sys.getwindowsversion)
* Convert a string representation of a Windows release to WinVersion class instance
* See if a specific major.minor.build is returned for a given release
josephsl added a commit to josephsl/nvda that referenced this issue Dec 7, 2020
…ally, greater than or equal i.e. newer Windows version). Re nvaccess#11837
josephsl added a commit to josephsl/nvda that referenced this issue Dec 7, 2020
… Re nvaccess#11837.

Transfer the mechanism behind winversion.isWin10 function as a WinVersion class method. The new method takes string argument for release to properly recognize 20H2 (October 2020 Update). In order to guarantee compatibility for up to a year, '2009' will be transformed into '20H2' inside the new class method. Also, raise an exception instead of returning False if a given release is not a publicly released version of Windows 10.
josephsl added a commit to josephsl/nvda that referenced this issue Dec 7, 2020
…nstead. Re nvaccess#11837.

Deprecate winVersion.isWin10, replaced by calling getWinVer().isWin10 function. Because the latter takes strings, convert version integers into strings before calling the WinVersion class method.
josephsl added a commit to josephsl/nvda that referenced this issue Dec 7, 2020
…11837.

Test two aspects of isWin10 class method:
* Testing to see if running on Windows 10. On Windows 7 and 8.x, it will say 'False' by calling assertFalse.
* Test if the method raises ValueError if a nonexistent version such as '2003' is passed in.
josephsl added a commit to josephsl/nvda that referenced this issue Dec 8, 2020
… getWinVer when checking operators. Re nvaccess#11837.

An important reminder from Reef Turner (NV Access): make unit tests system-independent i.e. do not use winVersion.getWinVer function when testing operators. Instead, test 'Windows 8' a.k.a. first version to support audio ducking.
josephsl added a commit to josephsl/nvda that referenced this issue Dec 11, 2020
nvaccess#11837.

Define constants representing Windows releases to WinVersion instances (i.e. WIN7_SP1 = WinVersion(major,6, minor=1, build=7601, servicePack='1')). This eases comparisons from other NVDA modules and add-ons, along with removing the ned for a dedicated Windows 10 feature update checks. Note that server releases are not specified to avoid complicating release mappings, especially more so for Windows Server 2016 and later which are based on specific Windows 10 releases with server components added. Also, Windows 7 original release (build 7600) was added for sake of completeness.
josephsl added a commit to josephsl/nvda that referenced this issue Dec 11, 2020
…inVer, removing the need to look up old winVersion tuple. Re nvaccess#11837.

Rather than using now old winVersion tuple, call sys.getwindowsversion function directly from getWinVer function.
josephsl added a commit to josephsl/nvda that referenced this issue Dec 11, 2020
…ccess#11837.

Rather than using winVersion.isWin10, check Windows 10 release constants (e.g. sinWversion.WIN10_1607) directly, as these constants will record major, minor, build. Specifically:
* UIA handler and OneCore synthesizer: check winVersion.WIN10
* Windows Console support: check winVersion.WIN10_1607
* Emoji panel in May 2019 Update: check winVersion.WIN10_1903
josephsl added a commit to josephsl/nvda that referenced this issue Dec 11, 2020
…s#11837.

Remove winVersion.isWin10 function, both from the module and from WinVersion class, as it is now possible to compare releases via constants. Also, remove unit tests associated with this function.
josephsl added a commit to josephsl/nvda that referenced this issue Dec 12, 2020
…11837.

Remove 'release' from constructor argument and add 'product type' to mirror old winVersion.winVersion tuple data. The bulk of the old constructor (namely definig major.minor.build for a specific release) will be transferred to a new static method (next commit).
josephsl added a commit to josephsl/nvda that referenced this issue Dec 12, 2020
… map. Re nvaccess#11837.

Suggested by Reef Turner (NV Access): clarify that Windows 10 versions to builds map clearly records release names.
josephsl added a commit to josephsl/nvda that referenced this issue Dec 12, 2020
…ion instance based on version string and release name. Re nvaccess#11837.

Add two static methods to WinVersion class:
* fromVersionText: transfer the module-level function to this static method.
* fromReleaseName: return an instance of WinVersion class based on release (publicly documented) name.
josephsl added a commit to josephsl/nvda that referenced this issue Dec 12, 2020
Add repr method to be used to print Windows version information to the console and to announce it at startup (future commit). It uses a helper function to obtain release name, then adds version string, service pack (if any), and product type. In essence, the work of old winVersionText was transfered to repr.
josephsl added a commit to josephsl/nvda that referenced this issue Dec 12, 2020
…ion. Re nvaccess#11837.

Old: Using Windows version major.minor.build productType
New: Windows version: releaseName (major.minor.build) productType
Include service pack version between major.minor.build and product type if a service pack is installed (Windows 7/Server 2008 R2 only).
josephsl added a commit to josephsl/nvda that referenced this issue Dec 12, 2020
…11837.

With the introduction of winVersion.WinVersion class, there is no need to keep winVersion.winVersion/winVersionText around. Therefore remove these from NVDA.
feerrenrut pushed a commit that referenced this issue Mar 25, 2021
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
@nvaccessAuto nvaccessAuto added this to the 2021.1 milestone Mar 25, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants