Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions dkey/_dkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def __ne__(self, other):
return super().__ne__(other)


def __getitem__(self, key):
def __getitem__(self, key, **kwargs):
"""
Get the value of the item of the given key `key`.

Expand Down Expand Up @@ -143,7 +143,7 @@ def __getitem__(self, key):
Warns with the warning stored for the given key if the key is deprecated.

"""
self._check_deprecated(key)
self._check_deprecated(key, additional_stacklevel=kwargs.get('stacklevel', 0))

return super().__getitem__(key)

Expand Down Expand Up @@ -195,7 +195,7 @@ def __delitem__(self, key):
Further access to the given key will not spawn additional warnings.

"""
self.pop(key)
self.pop(key, stacklevel=1)

def __contains__(self, key):
"""
Expand Down Expand Up @@ -297,11 +297,11 @@ def get(self, key, default=None):

"""
try:
return self.__getitem__(key)
return self.__getitem__(key,stacklevel=1)
except KeyError:
return default

def pop(self, key, default=_DEFAULT):
def pop(self, key, default=_DEFAULT, **kwargs):
"""
Remove and return the item with key `key`.

Expand Down Expand Up @@ -336,7 +336,7 @@ def pop(self, key, default=_DEFAULT):
information for this key is removed.

"""
if self._check_deprecated(key):
if self._check_deprecated(key, additional_stacklevel=kwargs.get('stacklevel', 0)):
del self._key_mappings[key]

if default is _DEFAULT:
Expand Down Expand Up @@ -475,7 +475,7 @@ def __len__(self):

return super().__len__()

def _check_deprecated(self, key):
def _check_deprecated(self, key, additional_stacklevel=0):
"""
Check if the given key is deprecated and warn if it is.

Expand All @@ -487,6 +487,10 @@ def _check_deprecated(self, key):
key
The key to look up in the dict of deprecated keys

additional_stacklevel : int, optional
Additional stacklevels to remove to make sure that the shown warning
shows the place of usage and not some internal dkey line.

Returns
-------
deprecated : bool
Expand All @@ -495,14 +499,14 @@ def _check_deprecated(self, key):
"""
try:
mapping = self._key_mappings[key]
self._warn_deprecation(mapping)
self._warn_deprecation(mapping, additional_stacklevel=additional_stacklevel)

return True
except KeyError:
return False

@staticmethod
def _warn_deprecation(mapping):
def _warn_deprecation(mapping, additional_stacklevel=0):
"""
Warn with the given deprecated key mapping.

Expand All @@ -517,13 +521,17 @@ def _warn_deprecation(mapping):
which should be a :any:`str`, and `'warning type'` which needs
to be a valid subclass of :any:`Exception`.

additional_stacklevel : int, optional
Additional stacklevels to remove to make sure that the shown warning
shows the place of usage and not some internal dkey line.

Warns
-----
CustomWarning
Warns with the given message and warning type.

"""
_warn(mapping['warning message'], mapping['warning type'])
_warn(mapping['warning message'], mapping['warning type'], stacklevel=4+additional_stacklevel)


def dkey(*args, deprecated_in=None, removed_in=None, details=None, warning_type='developer'):
Expand Down
13 changes: 12 additions & 1 deletion tests/test_dkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import warnings
import unittest
from contextlib import contextmanager
import re
from subprocess import check_output, STDOUT, CalledProcessError
import sys
from tempfile import NamedTemporaryFile

from dkey import deprecate_keys, dkey

Expand All @@ -25,8 +29,15 @@ def assertNotWarns(self, warning):
else:
self.assertTrue(True)

@contextmanager
def assertWarnsHere(self, warning):
with self.assertWarns(warning) as w:
yield

self.assertIn('test_dkey.py', w.filename)

def get_key_assertions(self):
return ((key, self.assertWarns if self.is_deprecated(key) else self.assertNotWarns) for key in (x[0] for x in self.example_case['items']))
return ((key, self.assertWarnsHere if self.is_deprecated(key) else self.assertNotWarns) for key in (x[0] for x in self.example_case['items']))

def is_deprecated(self, key):
return (key == self.example_case['removed key']) or (key == self.example_case['replaced key'][0])
Expand Down