Fix: detype None env-vars to '' to fix #4600 (#4649)

* detype untyped and path env-vars to ""; path_to_str("") == None

* update env-var-tutorial, add news

* update test_expandvars, test_expand_path, test_register_custom_var_str

* trigger CI-rerun since unrelated osx test failed

Co-authored-by: Alexander Firbas <alexander.firbas@gmail.com>
This commit is contained in:
dev2718 2022-01-21 10:16:50 +01:00 committed by GitHub
parent 360933fb69
commit 1aefbf3b35
Failed to generate hash of commit
5 changed files with 43 additions and 13 deletions

View file

@ -211,12 +211,20 @@ simple:
* ``\w*PATH``: any variable whose name ends in PATH is a list of strings. * ``\w*PATH``: any variable whose name ends in PATH is a list of strings.
* ``\w*DIRS``: any variable whose name ends in DIRS is a list of strings. * ``\w*DIRS``: any variable whose name ends in DIRS is a list of strings.
* ``XONSH_HISTORY_SIZE``: this variable is an int.
* ``CASE_SENSITIVE_COMPLETIONS``: this variable is a boolean. Futhermore, a number of predefined environment variables listed `here <envvars.html>`_ have a static type.
For example,
* ``XONSH_HISTORY_SIZE``: is an int, and
* ``CASE_SENSITIVE_COMPLETIONS``: is a boolean.
xonsh will automatically convert back and forth to untyped (string-only) xonsh will automatically convert back and forth to untyped (string-only)
representations of the environment as needed (mostly by subprocess commands). representations of the environment as needed (mostly by subprocess commands).
When in xonsh, you'll always have the typed version. Here are a couple of When in xonsh, you'll always have the typed version.
Variables that do not match the rules above are converted to strings using ``str``,
except they are ``None``. In this case the empty string is used.
Here are a couple of
PATH examples: PATH examples:
.. code-block:: xonshcon .. code-block:: xonshcon

23
news/fix_env_None.rst Normal file
View file

@ -0,0 +1,23 @@
**Added:**
* <news item>
**Changed:**
* Environment-variables of no predefined type or path environment variables are now represented as strings via the empty string.
**Deprecated:**
* <news item>
**Removed:**
* <news item>
**Fixed:**
* <news item>
**Security:**
* <news item>

View file

@ -443,7 +443,7 @@ def test_register_custom_var_bool(val, converted):
(32, "32"), (32, "32"),
(0, "0"), (0, "0"),
(27.0, "27.0"), (27.0, "27.0"),
(None, "None"), (None, ""),
("lol", "lol"), ("lol", "lol"),
("false", "false"), ("false", "false"),
("no", "no"), ("no", "no"),

View file

@ -1627,8 +1627,8 @@ def test_expand_case_matching(inp, exp):
("$unk $foo $unk $spam $unk", "$unk bar $unk eggs $unk"), ("$unk $foo $unk $spam $unk", "$unk bar $unk eggs $unk"),
("$an_int$spam$a_bool", "42eggsTrue"), ("$an_int$spam$a_bool", "42eggsTrue"),
("$unk$an_int$spam$a_bool", "$unk42eggsTrue"), ("$unk$an_int$spam$a_bool", "$unk42eggsTrue"),
("bar$foo$spam$foo $an_int $none", "barbareggsbar 42 None"), ("bar$foo$spam$foo $an_int $none", "barbareggsbar 42 "),
("$unk bar$foo$spam$foo $an_int $none", "$unk barbareggsbar 42 None"), ("$unk bar$foo$spam$foo $an_int $none", "$unk barbareggsbar 42 "),
("$foo/bar", "bar/bar"), ("$foo/bar", "bar/bar"),
("$unk/$foo/bar", "$unk/bar/bar"), ("$unk/$foo/bar", "$unk/bar/bar"),
("${'foo'} $spam", "bar eggs"), ("${'foo'} $spam", "bar eggs"),
@ -1688,7 +1688,7 @@ def test_ensure_timestamp(inp, fmt, exp, xession):
("~/$foo", True, "/bar"), ("~/$foo", True, "/bar"),
("~/test/$a_bool", True, "/test/True"), ("~/test/$a_bool", True, "/test/True"),
("~/test/$an_int", True, "/test/42"), ("~/test/$an_int", True, "/test/42"),
("~/test/$none", True, "/test/None"), ("~/test/$none", True, "/test/"),
("~/$foo", False, "/$foo"), ("~/$foo", False, "/$foo"),
], ],
) )

View file

@ -1226,8 +1226,8 @@ def always_none(x):
def ensure_string(x): def ensure_string(x):
"""Returns a string if x is not a string, and x if it already is.""" """Returns a string if x is not a string, and x if it already is. If x is None, the empty string is returned."""
return str(x) return str(x) if x is not None else ""
def is_path(x): def is_path(x):
@ -1242,11 +1242,10 @@ def is_env_path(x):
def str_to_path(x): def str_to_path(x):
"""Converts a string to a path.""" """Converts a string to a path."""
if x is None: if x is None or x == "":
return None return None
elif isinstance(x, str): elif isinstance(x, str):
# checking x is needed to avoid uncontrolled converting empty string to Path('.') return pathlib.Path(x)
return pathlib.Path(x) if x else None
elif isinstance(x, pathlib.Path): elif isinstance(x, pathlib.Path):
return x return x
elif isinstance(x, EnvPath) and len(x) == 1: elif isinstance(x, EnvPath) and len(x) == 1:
@ -1267,7 +1266,7 @@ def str_to_env_path(x):
def path_to_str(x): def path_to_str(x):
"""Converts a path to a string.""" """Converts a path to a string."""
return str(x) return str(x) if x is not None else ""
def env_path_to_str(x): def env_path_to_str(x):