gh-73965: New environment variable PYTHON_HISTORY (#13208)

It can be used to set the location of a .python_history file

---------

Co-authored-by: Levi Sabah <0xl3vi@gmail.com>
Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
This commit is contained in:
Zackery Spytz 2024-01-06 22:30:12 -08:00 committed by GitHub
parent 541c5dbb81
commit f19b93fce0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 50 additions and 3 deletions

View File

@ -1139,6 +1139,14 @@ conflict.
.. versionadded:: 3.13 .. versionadded:: 3.13
.. envvar:: PYTHON_HISTORY
This environment variable can be used to set the location of a
``.python_history`` file (by default, it is ``.python_history`` in the
user's home directory).
.. versionadded:: 3.13
Debug-mode variables Debug-mode variables
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~

View File

@ -132,6 +132,11 @@ Other Language Changes
equivalent of the :option:`-X frozen_modules <-X>` command-line option. equivalent of the :option:`-X frozen_modules <-X>` command-line option.
(Contributed by Yilei Yang in :gh:`111374`.) (Contributed by Yilei Yang in :gh:`111374`.)
* The new :envvar:`PYTHON_HISTORY` environment variable can be used to change
the location of a ``.python_history`` file.
(Contributed by Levi Sabah, Zackery Spytz and Hugo van Kemenade in
:gh:`73965`.)
New Modules New Modules
=========== ===========

View File

@ -433,6 +433,20 @@ def setcopyright():
def sethelper(): def sethelper():
builtins.help = _sitebuiltins._Helper() builtins.help = _sitebuiltins._Helper()
def gethistoryfile():
"""Check if the PYTHON_HISTORY environment variable is set and define
it as the .python_history file. If PYTHON_HISTORY is not set, use the
default .python_history file.
"""
if not sys.flags.ignore_environment:
history = os.environ.get("PYTHON_HISTORY")
if history:
return history
return os.path.join(os.path.expanduser('~'),
'.python_history')
def enablerlcompleter(): def enablerlcompleter():
"""Enable default readline configuration on interactive prompts, by """Enable default readline configuration on interactive prompts, by
registering a sys.__interactivehook__. registering a sys.__interactivehook__.
@ -467,13 +481,13 @@ def enablerlcompleter():
pass pass
if readline.get_current_history_length() == 0: if readline.get_current_history_length() == 0:
# If no history was loaded, default to .python_history. # If no history was loaded, default to .python_history,
# or PYTHON_HISTORY.
# The guard is necessary to avoid doubling history size at # The guard is necessary to avoid doubling history size at
# each interpreter exit when readline was already configured # each interpreter exit when readline was already configured
# through a PYTHONSTARTUP hook, see: # through a PYTHONSTARTUP hook, see:
# http://bugs.python.org/issue5845#msg198636 # http://bugs.python.org/issue5845#msg198636
history = os.path.join(os.path.expanduser('~'), history = gethistoryfile()
'.python_history')
try: try:
readline.read_history_file(history) readline.read_history_file(history)
except OSError: except OSError:

View File

@ -7,6 +7,7 @@ executing have not been removed.
import unittest import unittest
import test.support import test.support
from test import support from test import support
from test.support.script_helper import assert_python_ok
from test.support import os_helper from test.support import os_helper
from test.support import socket_helper from test.support import socket_helper
from test.support import captured_stderr from test.support import captured_stderr
@ -338,6 +339,19 @@ class HelperFunctionsTests(unittest.TestCase):
mock_addsitedir.assert_not_called() mock_addsitedir.assert_not_called()
self.assertFalse(known_paths) self.assertFalse(known_paths)
def test_gethistoryfile(self):
filename = 'file'
rc, out, err = assert_python_ok('-c',
f'import site; assert site.gethistoryfile() == "{filename}"',
PYTHON_HISTORY=filename)
self.assertEqual(rc, 0)
# Check that PYTHON_HISTORY is ignored in isolated mode.
rc, out, err = assert_python_ok('-I', '-c',
f'import site; assert site.gethistoryfile() != "{filename}"',
PYTHON_HISTORY=filename)
self.assertEqual(rc, 0)
def test_trace(self): def test_trace(self):
message = "bla-bla-bla" message = "bla-bla-bla"
for verbose, out in (True, message + "\n"), (False, ""): for verbose, out in (True, message + "\n"), (False, ""):

View File

@ -0,0 +1,2 @@
Add a new :envvar:`PYTHON_HISTORY` environment variable to set the location
of a ``.python_history`` file.

View File

@ -604,6 +604,9 @@ can be set to the callable of your debugger of choice.
.IP PYTHON_COLORS .IP PYTHON_COLORS
If this variable is set to 1, the interpreter will colorize various kinds of If this variable is set to 1, the interpreter will colorize various kinds of
output. Setting it to 0 deactivates this behavior. output. Setting it to 0 deactivates this behavior.
.IP PYTHON_HISTORY
This environment variable can be used to set the location of a history file
(on Unix, it is \fI~/.python_history\fP by default).
.SS Debug-mode variables .SS Debug-mode variables
Setting these variables only has an effect in a debug build of Python, that is, Setting these variables only has an effect in a debug build of Python, that is,
if Python was configured with the if Python was configured with the

View File

@ -296,6 +296,7 @@ static const char usage_envvars[] =
"PYTHON_COLORS : If this variable is set to 1, the interpreter will" "PYTHON_COLORS : If this variable is set to 1, the interpreter will"
" colorize various kinds of output. Setting it to 0 deactivates this behavior.\n" " colorize various kinds of output. Setting it to 0 deactivates this behavior.\n"
"These variables have equivalent command-line parameters (see --help for details):\n" "These variables have equivalent command-line parameters (see --help for details):\n"
"PYTHON_HISTORY: the location of a .python_history file.\n"
"PYTHONDEBUG : enable parser debug mode (-d)\n" "PYTHONDEBUG : enable parser debug mode (-d)\n"
"PYTHONDONTWRITEBYTECODE : don't write .pyc files (-B)\n" "PYTHONDONTWRITEBYTECODE : don't write .pyc files (-B)\n"
"PYTHONINSPECT : inspect interactively after running script (-i)\n" "PYTHONINSPECT : inspect interactively after running script (-i)\n"