classification
Title: platform: add a function to get the system version as tuple
Type: Stage:
Components: Versions: Python 3.3
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Arfrever, eric.araujo, lemburg, loewis, vstinner
Priority: normal Keywords: patch

Created on 2011-08-20 15:30 by vstinner, last changed 2011-08-22 14:23 by Arfrever. This issue is now closed.

Files
File name Uploaded Description Edit
platform_major.patch vstinner, 2011-08-20 15:30 review
Messages (14)
msg142538 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2011-08-20 15:30
#12326 proposes to remove the major version from sys.platform. If we remove it, we will need another easy way to get this information. I don't think that we need the version used to build Python, but the version at runtime. That's why the platform is a good candidate to add such information.

I propose to add platform.major(): major version of the system, or 0 if we cannot get it. I chose 0 instead of None or raising an error to be consistent with the other functions. Platform functions don't raise error and always return the same type. For example, platform.release() returns an empty string if the release string cannot be read.

Each system formats its full version (e.g. (2, 6, 28) for Linux 2.6.28) differently. It is easier and more reliable to only provide the major version.

If you would like to get more information (e.g. minor minor), you have to test the system name. See for example platform.mac_ver(), platform.win_ver(), and also test.support.requires_linux_version().

Attached patch implements platform.major().
msg142551 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2011-08-20 18:41
Can you please elaborate why we need it?
msg142557 - (view) Author: Marc-Andre Lemburg (lemburg) * (Python committer) Date: 2011-08-20 19:25
STINNER Victor wrote:
> 
> New submission from STINNER Victor <victor.stinner@haypocalc.com>:
> 
> #12326 proposes to remove the major version from sys.platform. If we remove it, we will need another easy way to get this information. I don't think that we need the version used to build Python, but the version at runtime. That's why the platform is a good candidate to add such information.
> 
> I propose to add platform.major(): major version of the system, or 0 if we cannot get it. I chose 0 instead of None or raising an error to be consistent with the other functions. Platform functions don't raise error and always return the same type. For example, platform.release() returns an empty string if the release string cannot be read.
> 
> Each system formats its full version (e.g. (2, 6, 28) for Linux 2.6.28) differently. It is easier and more reliable to only provide the major version.
> 
> If you would like to get more information (e.g. minor minor), you have to test the system name. See for example platform.mac_ver(), platform.win_ver(), and also test.support.requires_linux_version().
> 
> Attached patch implements platform.major().

I'm not sure I understand why platform.release() isn't sufficient
for this purpose. Note that some systems return alphanumeric
values for platform.release(), e.g. for Windows you get
'NT' or 'XP'.

What we could do is add a function that tries to find out the
true version number of the OS, e.g. for Windows 7 that would
be (6, 1, 7601) instead of the marketing name '7' returned by
platform.release().

Still, this won't help with the OS version used for the Python
build.

When Tarek was working on separating sysconfig from
distutils, we briefly discussed parsing the Makefile and pyconfig.h
files into a Python module. This would work around the issues
with the parsing overhead of using sysconfig and also prevent
the problems you currently find on some platforms that choose
to place the needed Makefile and pyconfig.h into a Python
development package.

However, even with those generated modules, access to the build
platform version would have to be provided through the sysconfig
module, not the platform module, since that's the more appropriate
module for such information.

That would be the full solution to the problem, but it would have
to go on a separate ticket.
msg142561 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2011-08-20 21:00
That other ticket is #9878.
msg142562 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2011-08-20 21:02
> Can you please elaborate why we need it?

platform.major() will be needed if we remove the major version for all platforms from sys.platform (issue #12795). See sys_platform_without_major.patch attached to issue #12795 see how it is used.
msg142566 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2011-08-20 21:19
> I'm not sure I understand why platform.release() isn't sufficient
> for this purpose. Note that some systems return alphanumeric
> values for platform.release(), e.g. for Windows you get
> 'NT' or 'XP'.

It's not easy to get 2 (int) from '2.6.38-8-generic' (str). For Windows, there *is* a major version:

 * Windows 3.1 : 3
 * Windows 95/98, NT 4 : 4
 * Windows XP, 2003 : 5
 * Vista, Seven : 6

The major version is maybe less revelant for Windows.

Anyway...

> platform.major() will be needed if we remove the major
> version for all platforms from sys.platform (issue #12795).

I just closed the issue #12795, and so I don't think that this issue is still needed and so I close it. Reopen it if you still see an use case.
msg142699 - (view) Author: Marc-Andre Lemburg (lemburg) * (Python committer) Date: 2011-08-22 08:43
STINNER Victor wrote:
> 
> STINNER Victor <victor.stinner@haypocalc.com> added the comment:
> 
>> I'm not sure I understand why platform.release() isn't sufficient
>> for this purpose. Note that some systems return alphanumeric
>> values for platform.release(), e.g. for Windows you get
>> 'NT' or 'XP'.
> 
> It's not easy to get 2 (int) from '2.6.38-8-generic' (str). For Windows, there *is* a major version:
> 
>  * Windows 3.1 : 3
>  * Windows 95/98, NT 4 : 4
>  * Windows XP, 2003 : 5
>  * Vista, Seven : 6
>
> The major version is maybe less revelant for Windows.

For Windows and Mac OS X, the minor version is relevant as well:

Windows 7 has the version number 6.1. For Mac OS X, there are major
changes happening for minor releases, e.g. see the architecture changes
between 10.4, 10.5 and 10.6.

> Anyway...
> 
>> platform.major() will be needed if we remove the major
>> version for all platforms from sys.platform (issue #12795).
> 
> I just closed the issue #12795, and so I don't think that this issue is still needed and so I close it. Reopen it if you still see an use case.
msg142705 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2011-08-22 08:54
Le 20/08/2011 21:25, Marc-Andre Lemburg a écrit :
> I'm not sure I understand why platform.release() isn't sufficient
> for this purpose.

You cannot write platform.release() >= (2, 28)  (Linux >= 2.28) or 
platform.release() >= 7  (FreeBSD 7 or later).

You may use int(platform.release()[0]) but it will fail after the major 
version 10, and I'm not sure that release() always starts with a digit.

> What we could do is add a function that tries to find out the
> true version number of the OS, e.g. for Windows 7 that would
> be (6, 1, 7601) instead of the marketing name '7' returned by
> platform.release().

Yes, it would be more pratical than release() and it would be possible 
to compare it using a tuple, like sys.version_info.

> Still, this won't help with the OS version used for the Python
> build.

I don't care of the OS version used to build. See my patch attached to 
#12795: only the version at runtime is important. The common use case is 
to check if the OS has a feature using its version, so the version at 
runtime.

> When Tarek was working on separating sysconfig from
> distutils, we briefly discussed parsing the Makefile and pyconfig.h
> files into a Python module.

This is now an issue: #9878. But it doesn't help if I need the version 
at runtime.
msg142708 - (view) Author: Marc-Andre Lemburg (lemburg) * (Python committer) Date: 2011-08-22 09:01
STINNER Victor wrote:
> 
>> What we could do is add a function that tries to find out the
>> true version number of the OS, e.g. for Windows 7 that would
>> be (6, 1, 7601) instead of the marketing name '7' returned by
>> platform.release().
> 
> Yes, it would be more pratical than release() and it would be possible 
> to compare it using a tuple, like sys.version_info.

Ok, changed the title accordingly.

>> Still, this won't help with the OS version used for the Python
>> build.
> 
> I don't care of the OS version used to build. See my patch attached to 
> #12795: only the version at runtime is important. The common use case is 
> to check if the OS has a feature using its version, so the version at 
> runtime.

Well, it is important to somehow get the build information for
Python, since that tells us which OS features were available
at the time of compilation.

>> When Tarek was working on separating sysconfig from
>> distutils, we briefly discussed parsing the Makefile and pyconfig.h
>> files into a Python module.
> 
> This is now an issue: #9878. But it doesn't help if I need the version 
> at runtime.

True, those two data points are different.
msg142713 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2011-08-22 09:24
> Well, it is important to somehow get the build information for
> Python, since that tells us which OS features were available
> at the time of compilation.

No, it doesn't (except for a bug that Matthias Klose pointed out).
The OS kernel version should have *zero* impact on the resulting Python
binary. What matters it the C compiler and the version of the C library.
The C library may or may not have features; features of the kernel used
to build Python are completely irrelevant.

(I think you misunderstood an earlier statement of me as
self-contradicting. It was not: The kernel *headers* may have an
impact during autoconf, not the running kernel. For Linux, the
kernel headers are part of the C library, and typically bear no
relationship with the running kernel - i.e. they may be either older
or newer than the running kernel).

Since there is no chance that we get the build environment captured
in a reasonable way (in particular not the version of the C library,
in a cross-platform manner), I strongly recommend to let this aspect
rest.
msg142715 - (view) Author: Marc-Andre Lemburg (lemburg) * (Python committer) Date: 2011-08-22 10:01
Martin v. Löwis wrote:
> 
> Martin v. Löwis <martin@v.loewis.de> added the comment:
> 
>> Well, it is important to somehow get the build information for
>> Python, since that tells us which OS features were available
>> at the time of compilation.
> 
> No, it doesn't (except for a bug that Matthias Klose pointed out).
> The OS kernel version should have *zero* impact on the resulting Python
> binary. What matters it the C compiler and the version of the C library.
> The C library may or may not have features; features of the kernel used
> to build Python are completely irrelevant.

We are now discussing the general case, not limited to Linux.

But even for Linux, the header information gets dumped into the
plat-linuxN directory files, and those change over time as well.
The kernel version also has an impact on certain features such
as real time clocks, timers or other kernel subsystems, which
autoconf then picks up at compile time.

Of course, you can check whether those features are available
one by one, but a version check is often a better way to see
whether your application has a chance of running on the Python
build in question.

For other OSes, the build version is much more important due
to the significant changes they make between releases, e.g.
Mac OS X.

> (I think you misunderstood an earlier statement of me as
> self-contradicting. It was not: The kernel *headers* may have an
> impact during autoconf, not the running kernel. For Linux, the
> kernel headers are part of the C library, and typically bear no
> relationship with the running kernel - i.e. they may be either older
> or newer than the running kernel).

I'm not talking about the runtime information. I'm talking
about the compile time build information which is available
via the Makefile and pyconfig.h file normally stored in the Python
installation and which is used by distutils.

The problem with those is that some distros choose to only
include those files in -dev packages and parsing them via
sysconfig just to get a quick look at the platform build
version is really a bit too much processing.

> Since there is no chance that we get the build environment captured
> in a reasonable way (in particular not the version of the C library,
> in a cross-platform manner), I strongly recommend to let this aspect
> rest.

We already do capture the build environment. This doesn't include
the C library version, but we could add that as well, if needed,
in a more direct way.

The platform module provides a way to determine the
lib C version required by the running Python binary on Linux
(and perhaps other OSes as well), but it's slow.
msg142717 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2011-08-22 10:18
>> No, it doesn't (except for a bug that Matthias Klose pointed out).
>> The OS kernel version should have *zero* impact on the resulting Python
>> binary. What matters it the C compiler and the version of the C library.
>> The C library may or may not have features; features of the kernel used
>> to build Python are completely irrelevant.
> 
> We are now discussing the general case, not limited to Linux.

And so was I. Read my statement as applying to the general case.

> But even for Linux, the header information gets dumped into the
> plat-linuxN directory files, 

Not in the build process, though...

> and those change over time as well.

What exactly changes over time? The plat-linuxN directory files?
Only if a developer updates them. For systems where the major
version indicates feature changes, the plat-OSn directory should
never change, since OS won't see any header changes until OSn+1
is released.

> The kernel version also has an impact on certain features such
> as real time clocks, timers or other kernel subsystems, which
> autoconf then picks up at compile time.

Which operating system specifically are you referring to here?
This should not happen.

> Of course, you can check whether those features are available
> one by one, but a version check is often a better way to see
> whether your application has a chance of running on the Python
> build in question.

That's a fragile approach, though. If the feature presence
varies with the OS kernel, you should rather check the version
of the kernel you are running on - it may be that support was
compiled in, but the system it runs on doesn't have that
support.

>> (I think you misunderstood an earlier statement of me as
>> self-contradicting. It was not: The kernel *headers* may have an
>> impact during autoconf, not the running kernel. For Linux, the
>> kernel headers are part of the C library, and typically bear no
>> relationship with the running kernel - i.e. they may be either older
>> or newer than the running kernel).
> 
> I'm not talking about the runtime information. I'm talking
> about the compile time build information which is available
> via the Makefile and pyconfig.h file normally stored in the Python
> installation and which is used by distutils.

And so am I. "running kernel" above refers to the kernel running
on the build system (i.e. what uname(1) gives you in autoconf,
and what currently gets into sys.platform).

> We already do capture the build environment. This doesn't include
> the C library version, but we could add that as well, if needed,
> in a more direct way.

No, we can't - that's impossible to implement in the general
case. Some systems may use static linking, or use a fixed version
number even as the library changes.
msg142719 - (view) Author: Marc-Andre Lemburg (lemburg) * (Python committer) Date: 2011-08-22 11:56
[This discussion is really off-topic for this issue, it should either
 be moved to issue12795 or a new ticket]

Martin v. Löwis wrote:
> 
> Martin v. Löwis <martin@v.loewis.de> added the comment:
> 
>>> No, it doesn't (except for a bug that Matthias Klose pointed out).
>>> The OS kernel version should have *zero* impact on the resulting Python
>>> binary. What matters it the C compiler and the version of the C library.
>>> The C library may or may not have features; features of the kernel used
>>> to build Python are completely irrelevant.
>>
>> We are now discussing the general case, not limited to Linux.
> 
> And so was I. Read my statement as applying to the general case.
> 
>> But even for Linux, the header information gets dumped into the
>> plat-linuxN directory files, 
> 
> Not in the build process, though...
>
>> and those change over time as well.
> 
> What exactly changes over time? The plat-linuxN directory files?
> Only if a developer updates them. For systems where the major
> version indicates feature changes, the plat-OSn directory should
> never change, since OS won't see any header changes until OSn+1
> is released.

I meant that the OS platform directories change over time,
i.e. new plat-<os><version> directories get created to
hold the updated OS information.

Since Python was build on a specific OS version, it will only
see the APIs available on that OS version. The OS build
version provides a quick way to check whether a certain
set of feature is available or not.

>> The kernel version also has an impact on certain features such
>> as real time clocks, timers or other kernel subsystems, which
>> autoconf then picks up at compile time.
> 
> Which operating system specifically are you referring to here?
> This should not happen.

This is meant to happen. The whole purpose of autoconf/configure is
to try to figure out which features are available on a platform
and those features change with the OS version.

See e.g. these documents on the incremental Linux kernel changes
between 2.2 and 3.0:

http://www.kniggit.net/wwol22.html
http://www.kniggit.net/wwol24.html
http://www.kniggit.net/wwol26.html
http://jpranevich.tripod.com/wwol30/wonderful-world-of-linux-3.0.html

Here's a similar list for FreeBSD:

http://ivoras.net/freebsd/freebsd9.html
http://ivoras.net/freebsd/freebsd8.html
http://ivoras.net/freebsd/freebsd7.html

On Mac OS X the situations is a little different: older Python
binaries simply won't run on newer OS versions at all due to the
architecture changes, so there's nothing much to check.

>> Of course, you can check whether those features are available
>> one by one, but a version check is often a better way to see
>> whether your application has a chance of running on the Python
>> build in question.
> 
> That's a fragile approach, though. If the feature presence
> varies with the OS kernel, you should rather check the version
> of the kernel you are running on - it may be that support was
> compiled in, but the system it runs on doesn't have that
> support.

True, the feature may still not work in the runtime OS environment,
but at least the Python binary knows about the feature set you're
interested in, so you can actively check whether it works or not,
since the APIs will be available.

>>> (I think you misunderstood an earlier statement of me as
>>> self-contradicting. It was not: The kernel *headers* may have an
>>> impact during autoconf, not the running kernel. For Linux, the
>>> kernel headers are part of the C library, and typically bear no
>>> relationship with the running kernel - i.e. they may be either older
>>> or newer than the running kernel).
>>
>> I'm not talking about the runtime information. I'm talking
>> about the compile time build information which is available
>> via the Makefile and pyconfig.h file normally stored in the Python
>> installation and which is used by distutils.
> 
> And so am I. "running kernel" above refers to the kernel running
> on the build system (i.e. what uname(1) gives you in autoconf,
> and what currently gets into sys.platform).

Please don't mix up the build time environment with the
runtime environment. Using "running kernel" to refer to
the build time kernel is a rather confusing way of naming
things when discussing build time vs. runtime.

>> We already do capture the build environment. This doesn't include
>> the C library version, but we could add that as well, if needed,
>> in a more direct way.
> 
> No, we can't - that's impossible to implement in the general
> case. Some systems may use static linking, or use a fixed version
> number even as the library changes.

The platform API libc_ver() actually checks the linker references
in the binary and also allows using a different binary
for the check in case the Python binary is not a suitable
candidate.

It is mainly meant to identify the minimum lib C requirement
for a binary.

Adding the lib C version constants would make this information
more directly accessible: __GLIBC__ and __GLIBC_MINOR__ for
glibc.

Regardless, the issue is about adding a runtime query function
to the platform module, not the build time OS version information
which we currently don't provide in an easily usable way. The latter
is being discussed on issue12795 and issue12326.
msg142724 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2011-08-22 12:57
> The whole purpose of autoconf/configure is
> to try to figure out which features are available on a platform
> and those features change with the OS version.

Hum, not exactly. autoconf checks if a function exists or if a constant exists in the C headers and in the C library. You have to check it or your program (C file) will not compile (missing function/constant).

But it's not enough. The GNU libc provides functions which are only available on some recent Linux kernels. Depending on the running kernel, the function may fail with something like "not implemented error".

See for example the discussion about accept4():
http://bugs.python.org/issue10115

At Python level, you need to know the running kernel version to check if accept4() if available or not. Knowing if the kernel used to compile Python has accept4() or not doesn't help.

(If you use the compiled Python on an older libc (e.g. on another computer), you have another problem, but it's the problem of OS vendors, not of Python.)
History
Date User Action Args
2011-08-22 14:23:30Arfreversettitle: platform: add a function to get the system version as tuple -> platform: add a function to get the system version as tuple
2011-08-22 12:57:53vstinnersetmessages: + msg142724
2011-08-22 11:56:01lemburgsetmessages: + msg142719
2011-08-22 10:18:27loewissetmessages: + msg142717
2011-08-22 10:01:53lemburgsetmessages: + msg142715
2011-08-22 09:24:44loewissetmessages: + msg142713
title: platform: add a function to get the system version as tuple -> platform: add a function to get the system version as tuple
2011-08-22 09:01:04lemburgsetmessages: + msg142708
title: platform: add a major function to get the system major version -> platform: add a function to get the system version as tuple
2011-08-22 08:54:35vstinnersetmessages: + msg142705
2011-08-22 08:43:49lemburgsetmessages: + msg142699
title: platform: add a major function to get the system major version -> platform: add a major function to get the system major version
2011-08-20 22:24:00vstinnersetstatus: open -> closed
resolution: not a bug
2011-08-20 21:19:44vstinnersetmessages: + msg142566
2011-08-20 21:02:36vstinnersetmessages: + msg142562
2011-08-20 21:00:11eric.araujosetnosy: + eric.araujo
messages: + msg142561
2011-08-20 19:29:25Arfreversettitle: platform: add a major function to get the system major version -> platform: add a major function to get the system major version
2011-08-20 19:25:29lemburgsetmessages: + msg142557
title: platform: add a major function to get the system major version -> platform: add a major function to get the system major version
2011-08-20 18:41:24loewissetnosy: + loewis
messages: + msg142551
2011-08-20 15:36:03Arfreversetnosy: + Arfrever
2011-08-20 15:30:39vstinnercreate