try just using CaseSenssitiveDict from requests to see if it works (#5744)

* try just using CaseSenssitiveDict from requests to see if it works

* put the dependency back in pyproject.toml and ignore typing on import

* news

* code now passing tests locally.  I still need to write tests for the new Class

* tests for CaseInsensitiveDict
This commit is contained in:
Simon Billinge 2024-12-08 09:28:31 +01:00 committed by GitHub
parent 9ae14866de
commit 1d1e7a8827
Failed to generate hash of commit
4 changed files with 145 additions and 4 deletions

View file

@ -0,0 +1,24 @@
**Added:**
* <news item>
**Changed:**
* replaced `case_insensitive_dictionary` dependency with local
`CaseInsensitiveDict` class
**Deprecated:**
* <news item>
**Removed:**
* <news item>
**Fixed:**
* <news item>
**Security:**
* <news item>

View file

@ -15,9 +15,7 @@ authors = [{ name = "Anthony Scopatz" }, { email = "scopatz@gmail.com" }]
maintainers = [{ name = "Xonsh Community" }, { email = "xonsh@gil.forsyth.dev" }] maintainers = [{ name = "Xonsh Community" }, { email = "xonsh@gil.forsyth.dev" }]
license = { text = "BSD 2-Clause License" } license = { text = "BSD 2-Clause License" }
requires-python = ">=3.9" requires-python = ">=3.9"
dependencies = [ dependencies = []
"case-insensitive-dictionary; platform_system=='Windows'",
]
[tool.setuptools.dynamic] [tool.setuptools.dynamic]
version = {attr = "xonsh.__version__"} version = {attr = "xonsh.__version__"}

View file

@ -8,6 +8,7 @@ import pytest
from xonsh.commands_cache import ( from xonsh.commands_cache import (
SHELL_PREDICTOR_PARSER, SHELL_PREDICTOR_PARSER,
CaseInsensitiveDict,
CommandsCache, CommandsCache,
_Commands, _Commands,
executables_in, executables_in,
@ -306,3 +307,77 @@ def test_executables_in(xession):
else: else:
result = set(executables_in(test_path)) result = set(executables_in(test_path))
assert expected == result assert expected == result
def test_caseinsdict_constructor():
actual = CaseInsensitiveDict({"key1": "val1", "Key2": "Val2"})
assert isinstance(actual, CaseInsensitiveDict)
assert actual["key1"] == "val1"
assert actual["Key2"] == "Val2"
def test_caseinsdict_getitem():
actual = CaseInsensitiveDict({"Key1": "Val1"})
assert actual["Key1"] == "Val1"
assert actual["key1"] == "Val1"
def test_caseinsdict_setitem():
actual = CaseInsensitiveDict({"Key1": "Val1"})
actual["Key1"] = "Val2"
assert actual["Key1"] == "Val2"
assert actual["key1"] == "Val2"
actual["key1"] = "Val3"
assert actual["Key1"] == "Val3"
assert actual["key1"] == "Val3"
def test_caseinsdict_delitem():
actual = CaseInsensitiveDict({"Key1": "Val1", "Key2": "Val2"})
del actual["Key1"]
assert actual == CaseInsensitiveDict({"Key2": "Val2"})
del actual["key2"]
assert actual == CaseInsensitiveDict({})
def test_caseinsdict_contains():
actual = CaseInsensitiveDict({"Key1": "Val1"})
assert actual.__contains__("Key1")
assert actual.__contains__("key1")
assert not actual.__contains__("key2")
def test_caseinsdict_get():
actual = CaseInsensitiveDict({"Key1": "Val1"})
assert actual.get("Key1") == "Val1"
assert actual.get("key1") == "Val1"
assert actual.get("key2", "no val") == "no val"
assert actual.get("key1", "no val") == "Val1"
def test_caseinsdict_update():
actual = CaseInsensitiveDict({"Key1": "Val1"})
actual.update({"Key2": "Val2"})
assert actual["key2"] == "Val2"
def test_caseinsdict_keys():
actual = CaseInsensitiveDict({"Key1": "Val1"})
assert next(actual.keys()) == "Key1"
def test_caseinsdict_items():
actual = CaseInsensitiveDict({"Key1": "Val1"})
assert next(actual.items()) == ("Key1", "Val1")
def test_caseinsdict_repr():
actual = CaseInsensitiveDict({"Key1": "Val1"})
assert actual.__repr__() == "CaseInsensitiveDict({'Key1': 'Val1'})"
def test_caseinsdict_copy():
initial = CaseInsensitiveDict({"Key1": "Val1"})
actual = initial.copy()
assert actual == initial
assert id(actual) != id(initial)

View file

@ -23,8 +23,52 @@ from xonsh.procs.executables import (
is_executable_in_windows, is_executable_in_windows,
) )
class CaseInsensitiveDict(dict[tp.Any, tp.Any]):
def __init__(self, *args, **kwargs):
super().__init__()
self._store = {}
self.update(*args, **kwargs)
def __setitem__(self, key, value):
# Store the key in lowercase but preserve the original case for display
self._store[key.casefold()] = key
super().__setitem__(key.casefold(), value)
def __getitem__(self, key):
return super().__getitem__(key.casefold())
def __delitem__(self, key):
del self._store[key.casefold()]
super().__delitem__(key.casefold())
def __contains__(self, key):
return key.casefold() in self._store
def get(self, key, default=None):
return super().get(key.casefold(), default)
def update(self, *args, **kwargs):
for k, v in dict(*args, **kwargs).items():
self[k] = v
def keys(self):
# Return the original keys with their original casing
return (self._store[k] for k in self._store)
def items(self):
return ((self._store[k], self[k]) for k in self._store)
def __repr__(self):
return f"{self.__class__.__name__}({dict(self.items())})"
def copy(self):
return CaseInsensitiveDict(self.items())
CacheDict: tp.Union[type[CaseInsensitiveDict], type[dict]]
if ON_WINDOWS: if ON_WINDOWS:
from case_insensitive_dict import CaseInsensitiveDict as CacheDict CacheDict = CaseInsensitiveDict
else: else:
CacheDict = dict CacheDict = dict