X Tutup
The Wayback Machine - https://web.archive.org/web/20221223194109/https://github.com/python/cpython/pull/25538/files
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

bpo-43538: Add extra arguments to os.startfile #25538

Merged
merged 3 commits into from Apr 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -4155,7 +4155,7 @@ written in Python, such as a mail server's external command delivery program.
.. availability:: Windows.


.. function:: startfile(path[, operation])
.. function:: startfile(path, [operation], [arguments], [cwd], [show_cmd])

Start a file with its associated application.

@@ -4169,22 +4169,40 @@ written in Python, such as a mail server's external command delivery program.
``'print'`` and ``'edit'`` (to be used on files) as well as ``'explore'`` and
``'find'`` (to be used on directories).

When launching an application, specify *arguments* to be passed as a single
string. This argument may have no effect when using this function to launch a
document.

The default working directory is inherited, but may be overridden by the *cwd*
argument. This should be an absolute path. A relative *path* will be resolved
against this argument.

Use *show_cmd* to override the default window style. Whether this has any
effect will depend on the application being launched. Values are integers as
supported by the Win32 :c:func:`ShellExecute` function.

:func:`startfile` returns as soon as the associated application is launched.
There is no option to wait for the application to close, and no way to retrieve
the application's exit status. The *path* parameter is relative to the current
directory. If you want to use an absolute path, make sure the first character
is not a slash (``'/'``); the underlying Win32 :c:func:`ShellExecute` function
doesn't work if it is. Use the :func:`os.path.normpath` function to ensure that
the path is properly encoded for Win32.
directory or *cwd*. If you want to use an absolute path, make sure the first
character is not a slash (``'/'``) Use :mod:`pathlib` or the
:func:`os.path.normpath` function to ensure that paths are properly encoded for
Win32.

To reduce interpreter startup overhead, the Win32 :c:func:`ShellExecute`
function is not resolved until this function is first called. If the function
cannot be resolved, :exc:`NotImplementedError` will be raised.

.. audit-event:: os.startfile path,operation os.startfile

.. audit-event:: os.startfile/2 path,operation,arguments,cwd,show_cmd os.startfile

.. availability:: Windows.

.. versionchanged:: 3.10
Added the *arguments*, *cwd* and *show_cmd* arguments, and the
``os.startfile/2`` audit event.


.. function:: system(command)

@@ -18,11 +18,11 @@
startfile = support.get_attribute(os, 'startfile')


@unittest.skipIf(platform.win32_is_iot(), "starting files is not supported on Windows IoT Core or nanoserver")
class TestCase(unittest.TestCase):
def test_nonexisting(self):
self.assertRaises(OSError, startfile, "nonexisting.vbs")

@unittest.skipIf(platform.win32_is_iot(), "starting files is not supported on Windows IoT Core or nanoserver")
def test_empty(self):
# We need to make sure the child process starts in a directory
# we're not about to delete. If we're running under -j, that
@@ -32,6 +32,14 @@ def test_empty(self):
empty = path.join(path.dirname(__file__), "empty.vbs")
startfile(empty)
startfile(empty, "open")
startfile(empty, cwd=path.dirname(sys.executable))

def test_python(self):
# Passing "-V" ensures that it closes quickly, though still not
# quickly enough that we can run in the test directory
cwd, name = path.split(sys.executable)
startfile(name, arguments="-V", cwd=cwd)
startfile(name, arguments="-V", cwd=cwd, show_cmd=0)

if __name__ == "__main__":
unittest.main()
@@ -0,0 +1 @@
Adds additional arguments to :func:`os.startfile` function.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

@@ -12485,6 +12485,9 @@ check_ShellExecute()
os.startfile
filepath: path_t
operation: Py_UNICODE = NULL
arguments: Py_UNICODE = NULL
cwd: path_t(nullable=True) = None
show_cmd: int = 1

Start a file with its associated application.

@@ -12495,6 +12498,16 @@ application (if any) its extension is associated.
When another "operation" is given, it specifies what should be done with
the file. A typical operation is "print".

"arguments" is passed to the application, but should be omitted if the
file is a document.

"cwd" is the working directory for the operation. If "filepath" is
relative, it will be resolved against this directory. This argument
should usually be an absolute path.

"show_cmd" can be used to override the recommended visibility option.
See the Windows ShellExecute documentation for values.

startfile returns as soon as the associated application is launched.
There is no option to wait for the application to close, and no way
to retrieve the application's exit status.
@@ -12506,8 +12519,9 @@ the underlying Win32 ShellExecute function doesn't work if it is.

static PyObject *
os_startfile_impl(PyObject *module, path_t *filepath,
const Py_UNICODE *operation)
/*[clinic end generated code: output=66dc311c94d50797 input=c940888a5390f039]*/
const Py_UNICODE *operation, const Py_UNICODE *arguments,
path_t *cwd, int show_cmd)
/*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/
{
HINSTANCE rc;

@@ -12521,10 +12535,15 @@ os_startfile_impl(PyObject *module, path_t *filepath,
if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
return NULL;
}
if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
arguments, cwd->object ? cwd->object : Py_None,
show_cmd) < 0) {
return NULL;
}

Py_BEGIN_ALLOW_THREADS
rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
NULL, NULL, SW_SHOWNORMAL);
arguments, cwd->wide, show_cmd);
Py_END_ALLOW_THREADS

if (rc <= (HINSTANCE)32) {
X Tutup