Skip to content

Commit

Permalink
Merge branch 'main' into ios-docs
Browse files Browse the repository at this point in the history
  • Loading branch information
ned-deily authored Mar 28, 2024
2 parents 71fe520 + f006338 commit 73b33b6
Show file tree
Hide file tree
Showing 48 changed files with 1,050 additions and 208 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -514,8 +514,7 @@ jobs:
strategy:
fail-fast: false
matrix:
# sanitizer: [address, undefined, memory] -- memory skipped temporarily until GH-116886 is solved.
sanitizer: [address, undefined]
sanitizer: [address, undefined, memory]
steps:
- name: Build fuzzers (${{ matrix.sanitizer }})
id: build
Expand Down
10 changes: 5 additions & 5 deletions Doc/library/doctest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ And so on, eventually ending with:
OverflowError: n too large
ok
2 items passed all tests:
1 tests in __main__
8 tests in __main__.factorial
9 tests in 2 items.
9 passed and 0 failed.
1 test in __main__
6 tests in __main__.factorial
7 tests in 2 items.
7 passed.
Test passed.
$
Expand Down Expand Up @@ -1933,7 +1933,7 @@ such a test runner::
optionflags=flags)
else:
fail, total = doctest.testmod(optionflags=flags)
print("{} failures out of {} tests".format(fail, total))
print(f"{fail} failures out of {total} tests")


.. rubric:: Footnotes
Expand Down
5 changes: 5 additions & 0 deletions Doc/library/os.rst
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,11 @@ process and user.
:func:`socket.gethostname` or even
``socket.gethostbyaddr(socket.gethostname())``.

On macOS, iOS and Android, this returns the *kernel* name and version (i.e.,
``'Darwin'`` on macOS and iOS; ``'Linux'`` on Android). :func:`platform.uname()`
can be used to get the user-facing operating system name and version on iOS and
Android.

.. availability:: Unix.

.. versionchanged:: 3.3
Expand Down
60 changes: 59 additions & 1 deletion Doc/library/platform.rst
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ Cross Platform
Returns the system/OS name, such as ``'Linux'``, ``'Darwin'``, ``'Java'``,
``'Windows'``. An empty string is returned if the value cannot be determined.

On iOS and Android, this returns the user-facing OS name (i.e, ``'iOS``,
``'iPadOS'`` or ``'Android'``). To obtain the kernel name (``'Darwin'`` or
``'Linux'``), use :func:`os.uname()`.

.. function:: system_alias(system, release, version)

Expand All @@ -161,6 +164,8 @@ Cross Platform
Returns the system's release version, e.g. ``'#3 on degas'``. An empty string is
returned if the value cannot be determined.

On iOS and Android, this is the user-facing OS version. To obtain the
Darwin or Linux kernel version, use :func:`os.uname()`.

.. function:: uname()

Expand Down Expand Up @@ -238,7 +243,6 @@ Windows Platform
macOS Platform
--------------


.. function:: mac_ver(release='', versioninfo=('','',''), machine='')

Get macOS version information and return it as tuple ``(release, versioninfo,
Expand All @@ -248,6 +252,24 @@ macOS Platform
Entries which cannot be determined are set to ``''``. All tuple entries are
strings.

iOS Platform
------------

.. function:: ios_ver(system='', release='', model='', is_simulator=False)

Get iOS version information and return it as a
:func:`~collections.namedtuple` with the following attributes:

* ``system`` is the OS name; either ``'iOS'`` or ``'iPadOS'``.
* ``release`` is the iOS version number as a string (e.g., ``'17.2'``).
* ``model`` is the device model identifier; this will be a string like
``'iPhone13,2'`` for a physical device, or ``'iPhone'`` on a simulator.
* ``is_simulator`` is a boolean describing if the app is running on a
simulator or a physical device.

Entries which cannot be determined are set to the defaults given as
parameters.


Unix Platforms
--------------
Expand Down Expand Up @@ -301,3 +323,39 @@ Linux Platforms
return ids

.. versionadded:: 3.10


Android Platform
----------------

.. function:: android_ver(release="", api_level=0, manufacturer="", \
model="", device="", is_emulator=False)

Get Android device information. Returns a :func:`~collections.namedtuple`
with the following attributes. Values which cannot be determined are set to
the defaults given as parameters.

* ``release`` - Android version, as a string (e.g. ``"14"``).

* ``api_level`` - API level of the running device, as an integer (e.g. ``34``
for Android 14). To get the API level which Python was built against, see
:func:`sys.getandroidapilevel`.

* ``manufacturer`` - `Manufacturer name
<https://developer.android.com/reference/android/os/Build#MANUFACTURER>`__.

* ``model`` - `Model name
<https://developer.android.com/reference/android/os/Build#MODEL>`__ –
typically the marketing name or model number.

* ``device`` - `Device name
<https://developer.android.com/reference/android/os/Build#DEVICE>`__ –
typically the model number or a codename.

* ``is_emulator`` - ``True`` if the device is an emulator; ``False`` if it's
a physical device.

Google maintains a `list of known model and device names
<https://storage.googleapis.com/play_public/supported_devices.html>`__.

.. versionadded:: 3.13
58 changes: 58 additions & 0 deletions Doc/library/statistics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,64 @@ The final prediction goes to the largest posterior. This is known as the
'female'


Sampling from kernel density estimation
***************************************

The :func:`kde()` function creates a continuous probability density
function from discrete samples. Some applications need a way to make
random selections from that distribution.

The technique is to pick a sample from a bandwidth scaled kernel
function and recenter the result around a randomly chosen point from
the input data. This can be done with any kernel that has a known or
accurately approximated inverse cumulative distribution function.

.. testcode::

from random import choice, random, seed
from math import sqrt, log, pi, tan, asin
from statistics import NormalDist

kernel_invcdfs = {
'normal': NormalDist().inv_cdf,
'logistic': lambda p: log(p / (1 - p)),
'sigmoid': lambda p: log(tan(p * pi/2)),
'rectangular': lambda p: 2*p - 1,
'triangular': lambda p: sqrt(2*p) - 1 if p < 0.5 else 1 - sqrt(2 - 2*p),
'cosine': lambda p: 2*asin(2*p - 1)/pi,
}

def kde_random(data, h, kernel='normal'):
'Return a function that samples from kde() smoothed data.'
kernel_invcdf = kernel_invcdfs[kernel]
def rand():
return h * kernel_invcdf(random()) + choice(data)
return rand

For example:

.. doctest::

>>> discrete_samples = [-2.1, -1.3, -0.4, 1.9, 5.1, 6.2]
>>> rand = kde_random(discrete_samples, h=1.5)
>>> seed(8675309)
>>> selections = [rand() for i in range(10)]
>>> [round(x, 1) for x in selections]
[4.7, 7.4, 1.2, 7.8, 6.9, -1.3, 5.8, 0.2, -1.4, 5.7]

.. testcode::
:hide:

from statistics import kde
from math import isclose

# Verify that cdf / invcdf will round trip
xarr = [i/100 for i in range(-100, 101)]
for kernel, invcdf in kernel_invcdfs.items():
cdf = kde([0.0], h=1.0, kernel=kernel, cumulative=True)
for x in xarr:
assert isclose(invcdf(cdf(x)), x, abs_tol=1E-9)

..
# This modelines must appear within the last ten lines of the file.
kate: indent-width 3; remove-trailing-space on; replace-tabs on; encoding utf-8;
4 changes: 3 additions & 1 deletion Doc/library/sys.rst
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,9 @@ always available.

.. function:: getandroidapilevel()

Return the build time API version of Android as an integer.
Return the build-time API level of Android as an integer. This represents the
minimum version of Android this build of Python can run on. For runtime
version information, see :func:`platform.android_ver`.

.. availability:: Android.

Expand Down
17 changes: 16 additions & 1 deletion Doc/library/webbrowser.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ allow the remote browser to maintain its own windows on the display. If remote
browsers are not available on Unix, the controlling process will launch a new
browser and wait.

On iOS, the :envvar:`BROWSER` environment variable, as well as any arguments
controlling autoraise, browser preference, and new tab/window creation will be
ignored. Web pages will *always* be opened in the user's preferred browser, in
a new tab, with the browser being brought to the foreground. The use of the
:mod:`webbrowser` module on iOS requires the :mod:`ctypes` module. If
:mod:`ctypes` isn't available, calls to :func:`.open` will fail.

The script :program:`webbrowser` can be used as a command-line interface for the
module. It accepts a URL as the argument. It accepts the following optional
parameters: ``-n`` opens the URL in a new browser window, if possible;
Expand Down Expand Up @@ -147,6 +154,8 @@ for the controller classes, all defined in this module.
+------------------------+-----------------------------------------+-------+
| ``'chromium-browser'`` | ``Chromium('chromium-browser')`` | |
+------------------------+-----------------------------------------+-------+
| ``'iosbrowser'`` | ``IOSBrowser`` | \(4) |
+------------------------+-----------------------------------------+-------+

Notes:

Expand All @@ -161,7 +170,10 @@ Notes:
Only on Windows platforms.

(3)
Only on macOS platform.
Only on macOS.

(4)
Only on iOS.

.. versionadded:: 3.2
A new :class:`!MacOSXOSAScript` class has been added
Expand All @@ -176,6 +188,9 @@ Notes:
Removed browsers include Grail, Mosaic, Netscape, Galeon,
Skipstone, Iceape, and Firefox versions 35 and below.

.. versionchanged:: 3.13
Support for iOS has been added.

Here are some simple examples::

url = 'https://docs.python.org/'
Expand Down
3 changes: 3 additions & 0 deletions Doc/library/zipimport.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ Any files may be present in the ZIP archive, but importers are only invoked for
corresponding :file:`.pyc` file, meaning that if a ZIP archive
doesn't contain :file:`.pyc` files, importing may be rather slow.

.. versionchanged:: 3.13
ZIP64 is supported

.. versionchanged:: 3.8
Previously, ZIP archives with an archive comment were not supported.

Expand Down
6 changes: 6 additions & 0 deletions Doc/whatsnew/3.13.rst
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,12 @@ xml.etree.ElementTree
:func:`~xml.etree.ElementTree.iterparse` for explicit cleaning up.
(Contributed by Serhiy Storchaka in :gh:`69893`.)

zipimport
---------

* Gains support for ZIP64 format files. Everybody loves huge code right?
(Contributed by Tim Hatch in :gh:`94146`.)


Optimizations
=============
Expand Down
1 change: 1 addition & 0 deletions Include/internal/pycore_compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ int _PyCompile_InstructionSequence_UseLabel(_PyCompile_InstructionSequence *seq,
int _PyCompile_InstructionSequence_Addop(_PyCompile_InstructionSequence *seq,
int opcode, int oparg,
_PyCompilerSrcLocation loc);
int _PyCompile_InstructionSequence_ApplyLabelMap(_PyCompile_InstructionSequence *seq);

typedef struct {
PyObject *u_name;
Expand Down
71 changes: 71 additions & 0 deletions Lib/_ios_support.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import sys
try:
from ctypes import cdll, c_void_p, c_char_p, util
except ImportError:
# ctypes is an optional module. If it's not present, we're limited in what
# we can tell about the system, but we don't want to prevent the module
# from working.
print("ctypes isn't available; iOS system calls will not be available")
objc = None
else:
# ctypes is available. Load the ObjC library, and wrap the objc_getClass,
# sel_registerName methods
lib = util.find_library("objc")
if lib is None:
# Failed to load the objc library
raise RuntimeError("ObjC runtime library couldn't be loaded")

objc = cdll.LoadLibrary(lib)
objc.objc_getClass.restype = c_void_p
objc.objc_getClass.argtypes = [c_char_p]
objc.sel_registerName.restype = c_void_p
objc.sel_registerName.argtypes = [c_char_p]


def get_platform_ios():
# Determine if this is a simulator using the multiarch value
is_simulator = sys.implementation._multiarch.endswith("simulator")

# We can't use ctypes; abort
if not objc:
return None

# Most of the methods return ObjC objects
objc.objc_msgSend.restype = c_void_p
# All the methods used have no arguments.
objc.objc_msgSend.argtypes = [c_void_p, c_void_p]

# Equivalent of:
# device = [UIDevice currentDevice]
UIDevice = objc.objc_getClass(b"UIDevice")
SEL_currentDevice = objc.sel_registerName(b"currentDevice")
device = objc.objc_msgSend(UIDevice, SEL_currentDevice)

# Equivalent of:
# device_systemVersion = [device systemVersion]
SEL_systemVersion = objc.sel_registerName(b"systemVersion")
device_systemVersion = objc.objc_msgSend(device, SEL_systemVersion)

# Equivalent of:
# device_systemName = [device systemName]
SEL_systemName = objc.sel_registerName(b"systemName")
device_systemName = objc.objc_msgSend(device, SEL_systemName)

# Equivalent of:
# device_model = [device model]
SEL_model = objc.sel_registerName(b"model")
device_model = objc.objc_msgSend(device, SEL_model)

# UTF8String returns a const char*;
SEL_UTF8String = objc.sel_registerName(b"UTF8String")
objc.objc_msgSend.restype = c_char_p

# Equivalent of:
# system = [device_systemName UTF8String]
# release = [device_systemVersion UTF8String]
# model = [device_model UTF8String]
system = objc.objc_msgSend(device_systemName, SEL_UTF8String).decode()
release = objc.objc_msgSend(device_systemVersion, SEL_UTF8String).decode()
model = objc.objc_msgSend(device_model, SEL_UTF8String).decode()

return system, release, model, is_simulator
Loading

0 comments on commit 73b33b6

Please sign in to comment.