DKey - Deprecating Dict Keys¶
The dkey
module allows you to deprecate the use of selected keys in a given dictionary thus making API changes involving
dictionaries less disruptive. To learn more about how to use it head over to the Documentation.
Usage example¶
Let’s say we have a dict with an old key that we want to replace with a new one.

Behaviour of wrapped dictionary¶
There are different ways items can be accessed in dicts. dkey
tries to
find the best warning solution for each case.
Single item access¶
When accessing a single item in a dict, dkey
warns only, when the associated
key is deprecated. So if key A is deprecated, all of these operation warn:
my_dict['A']
my_dict['A'] = 12
my_dict.get('A')
del my_dict['A']
my_dict.pop('A')
Setting or removing a deprecated (key,value) pair will also remove the warning:
my_dict['A'] = 12 # warns
my_dict['A'] # does not warn
This is to make sure that warnings do not propagate completely out of context.
Multi item access¶
Due to the special view classes dict uses to give access to its internal structure
via the functions dict.values
, dict.keys
, and dict.items
,
these functions return all warnings directly when called. For all other functions
like normal iteration:
for key in my_dict: # warns when key is 'A'
print(key)
or dict.popitem
, the warning is instead generated, when the deprecated element
is accessed.
Configuration Options¶
To deprecate a key in a dict, it has to be wrapped using dkey.deprecate_keys
.
dkey
offers two different ways to deprecate a key. Either, the key is deprecated
as it will be replace by a different one, or it will be removed completely in the future.
In both scenarios it is important, that during the deprecation period, the old keys
must still work the same way as before.
Removing a key¶
To deprecate a key and warn that it will be removed in the future, you wrap
your dict using dkey.deprecate_keys
and pass it the deprecated key
using dkey.dkey
:
from dkey import deprecate_keys, dkey
def customer_info():
return deprecate_keys({
'name': 'Smith',
'age': 24,
'cleartext password': 'password'
},
dkey('cleartext password'))
Should someone now try to access the cleartext password
key, a DeprecationWarning
is generated:
print(customer_info()['cleartext password'])
# Wil warn with a DeprecationWarning:
# Key `cleartext password` is deprecated. It shouldn't be used anymore.
An automatically generated deprecation warning is used that warns developers to no longer use this key in the future.
Note
A DeprecationWarning
is only shown when you set your warning filters appropriately.
For other warning types that are shown by default, check this section.
Replacing a key¶
Another scenario you might run into is that you want to rename a key (for various reasons), and again you want to give people time to adapt. For this you can do the following:
from dkey import deprecate_keys, dkey
def customer_info():
return deprecate_keys({
'first name': 'Adam',
'last name': 'Smith',
'age': 24,
},
dkey('name', 'last name'))
Again we use the deprecate_keys
function. This time we pass two string to dkey.dkey
: The old
key and the new key people should be using. Both keys will point to the same object.
The result is again a warning if people use the old key:
print(customer['name'])
# Wil raise a DeprecationWarning:
# Key `name` is deprecated. Use `first name` from now on.
And again an automatically generated deprecation warning is used that also informs developers about which key to use instead.
More configuration options¶
In case the default way warnings are generated are not what you need, dkey
offers
several ways to customise how deprecated keys are treated:
- A version number can be given to indicate since when a key is deprecated
- A version number can be given to indicate when a key is definitively removed
- A custom message can be given to add more information about why the change happend and how to adapt
- A custom warning type can be given to align the deprecation warnings to an existing project
Version numbers¶
If you have a well organised code project, you will normally also want to communicate since when a feature is
deprecated and when it finally will be removed. You can pass those details to dkey.dkey
:
from dkey import deprecate_keys, dkey
def customer_info():
return deprecate_keys({
'first name': 'Adam',
'last name': 'Smith',
'age': 24,
},
dkey('name', 'last name', deprecated_in='1.1.12', removed_in='2.0.0'))
Which will result in the warning:
Key name is deprecated since version 1.1.12. It will be removed in version 2.0.0. Use first name from now on.
Custom message¶
Sometimes, changes are not as simple as a was replaced with b. In these scenarios, you can provide a custom message with more information:
def customer_info():
return deprecate_keys({
'first name': 'Adam',
'last name': 'Smith',
'age': 24,
},
dkey('name', 'last name',
details='`name` has been replaced by the two keys `first name` and `last name`.'))
Which will result in the warning:
Key name is deprecated. name has been replaced by the two keys first name and last name.
Custom warning type¶
By default, a DeprecationWarning
is used. This warning does not appear for end users. If you have
deprecation warnings that are actually meant for end users and not just for developers, you can change
the warning type:
from dkey import deprecate_keys, dkey
def customer_info():
return deprecate_keys({
'name': 'Smith',
'age': 24,
'cleartext password': 'password'
},
dkey('cleartext password', warning_type='end user'))
Which will generate a FutureWarning
. FutureWarning
is a warning type that is shown
to end users by default. If you want to show your own warning type, this is also possible.
Just hand your warning type to warning_type
instead of the string ‘end user’ and it
will be used to spawn the warning:
from dkey import deprecate_keys, dkey
class UltimateWarning(FutureWarning):
pass
def customer_info():
return deprecate_keys({
'name': 'Smith',
'age': 24,
'cleartext password': 'password'
},
dkey('cleartext password', warning_type=UltimateWarning))
Note
In order for your custom warning type to work it has to be compatible with the warnings.warn
function.
Limitations¶
- No automatic doc-string adaptations are possible as of now
deprecate_keys¶
-
class
dkey.
deprecate_keys
(dictionary, *args)[source]¶ Wrapper for dicts that allows to set certain keys as deprecated.
-
__init__
(dictionary, *args)[source]¶ Construct the wrapper class.
Internally, the items are stored in the same order as the given dictionary (CPython >=3.6). The deprecated old keys that were replaced with new ones are positioned just before their respective new keys.
Parameters:
-
__contains__
(key)[source]¶ Return True if the given key key is in this dict, else False.
Warns if the given key is deprecated.
Parameters: key – The key to search in this dict. Returns: IsInDict – True if the given key is in this dict. False, otherwise. Return type: bool Warns: CustomWarning – Warns with the warning stored for the given key if the key is deprecated.
-
__delitem__
(key)[source]¶ Remove the item with key key and its associated value.
Warns if the given key is deprecated.
Parameters: key – The key of the item which to remove. Raises: KeyError
– Raises aKeyError
if the given key does not existWarns: CustomWarning – Warns with the warning stored for the given key if the key is deprecated. Further access to the given key will not spawn additional warnings.
-
__eq__
(other)[source]¶ Return True if identical to other.
Warns if either this or other contains deprecated keys.
Parameters: other – The other object to compare this one to Returns: True if they are equal, False otherwise Return type: bool Warns: CustomWarning – Warns with the warnings stored for all contained keys.
-
__getitem__
(key)[source]¶ Get the value of the item of the given key key.
Warns if the given key is deprecated. If the key does not exist, it will behave the same as a normal dict, i.e. it will raise a
KeyError
.Parameters: key – The key for which to return the value Returns: The value stored for the given key Return type: value Raises: KeyError
– If the key is not foundWarns: CustomWarning – Warns with the warning stored for the given key if the key is deprecated.
-
__iter__
()[source]¶ Return an iterator over the keys of the dictionary.
Warns for each deprecated item accessed.
Returns: Iterator – An iterator over the wrapped dict Return type: iterator Warns: CustomWarning – Warns whenever a deprecated item in the dict is returned. Each item will warn with its set warning type and message.
-
__len__
()[source]¶ Return the number of items in the dict.
Will raise warnings, if the dict contains deprecated values. One for each deprecated value.
Returns: The number of items in the dict Return type: int Warns: CustomWarning – Warns for each deprecated item in the dictionary before returning.
-
__ne__
(other)[source]¶ Return True if not identical to other.
Warns if either this or other contains deprecated keys.
Parameters: other – The other object to compare this one to Returns: True if they are not equal, False otherwise Return type: bool Warns: CustomWarning – Warns with the warnings stored for all contained keys.
-
__setitem__
(key, value)[source]¶ Set the value of the item of the given key key to value.
Warns if the given key is deprecated.
Parameters: - key – The key under which to store the given value
- value – The value to store
Warns: CustomWarning – Warns with the warning stored for the given key if the key is deprecated. Further access to the given key will not spawn additional warnings.
-
clear
()[source]¶ Remove all entries from the dict.
Will also remove all deprecation warnings and all keys.
-
copy
()[source]¶ Return a shallow copy of this wrapped dict.
Will return a wrapped dict that, as the original, will warn with the deprecation warnings set for this dict.
Returns: copy – A shallow copy of the underlying dict and a shallow copy of the underlying deprecation key structure. Return type: deprecate_keys
-
get
(key, default=None)[source]¶ Get the value stored under key or default if this key doesn’t exist.
This function is the same as
deprecate_keys.__getitem__
except that it does not throw for non existing keys, but returns the given default value instead.Parameters: - key – The key for which to return the value
- optional (default,) – The value to return, if the given key is not stored in the dict. Defaults
to
None
if not given.
Returns: The value stored for key or default if key is not in the dict.
Return type: value
-
items
()[source]¶ Return a new view of the dictionary’s items: iterator of (key, value) pairs.
Works the same as the plain
dict.items
function except that it warns about all deprecated keys contained before returning.Returns: Basically an iterator over (key, value) pairs of the dict. For more information about dict views see: dictionary view Return type: dict_items Warns: CustomWarning – Warns for each deprecated item in the dictionary before returning.
-
keys
()[source]¶ Return a new view of the dictionary’s keys.
Works the same as the plain
dict.keys
function except that it warns about all deprecated keys before returning the view.Returns: Basically an iterator over the contained keys of the dict. For more information about dict views see: dictionary view Return type: dict_keys Warns: CustomWarning – Warns for each deprecated item in the dictionary before returning.
-
pop
(key, default=<object object>)[source]¶ Remove and return the item with key key.
If the key is not in the dict and no default value is set, this function will raise an exception. If a default value is given, this value will be returned instead.
Parameters: - key – The key to pop
- default (optional) – The value to return if the given key is not in the dict. If non is given, an exception is raised instead.
Returns: The value of the key given or the given default value, or if no default value is given, an exception is raised.
Return type: value
Raises: KeyError
– If key is not in the dict and no default value is given, this function raises aKeyError
.Warns: CustomWarning – Warns if the popped item is a deprecated key. The deprecation information for this key is removed.
-
popitem
()[source]¶ Pop an item from the dict.
This function has the same behaviour as
dict.popitem
. Therefore, for Python < 3.6 this function will pop an arbitrary item, whereas for Python >= 3.6 this function will raise the last item added to this dict. If the dict is empty, this function will raise aKeyError
.Returns: - key – The key popped
- value – The associated value of the popped key
Raises: KeyError
– If the dict is empty.Warns: CustomWarning – Warns if the popped item is a deprecated key. The deprecation information for this key is removed.
-
values
()[source]¶ Return a new view of the dictionary’s values.
Works the same as the plain
dict.values
function except that it warns about all deprecated keys associated with returned values before returning the view.Returns: Basically an iterator over the contained values of the dict. For more information about dict views see: dictionary view Return type: dict_values Warns: CustomWarning – Warns for each deprecated item in the dictionary before returning.
-
dkey¶
-
dkey.
dkey
(*args, deprecated_in=None, removed_in=None, details=None, warning_type='developer')[source]¶ Convert a key into a deprecation lookup dict.
To use the
dkey.deprecate_keys
function it is easiest to generate its input with this function. This function generates:- A key removed deprecation warning object if one key is provided
- A key replaced deprecation warning object if two keys are provided
Parameters: - *args – One or two keys. If one key is passed, it is assumed that this key will be removed in the future. If two keys are passed, it is assumed that the second key is the replacement for the first one.
- deprecated_in (str, optional) – Version in which this key was deprecated. If given, will appear in the warning message.
- removed_in (str, optional) – Version in which this key will be removed and will no longer work. If given, will appear in the warning message.
- details (str, optional) – Will remove the default final sentence (do no longer use, or use xxx from now on).
- warning_type ({'developer', 'end user', ArbitraryWarning}, optional) –
The warning type to use when the old key is accessed
By default, deprecation warnings are intended for developers only which means a any:DeprecationWarning is used which isn’t shown to end users. If it should be shown to end users, this can be done by passing ‘end user’ which will raise
FutureWarning
. If you want to use your custom warning type this is also possible.Note
Your custom warning must work with
warnings.warn
Returns: A dict that can be used as a deprecated key input for
dkey.deprecate_keys
.Return type: Raises: ValueError
– If zero or more than two keys are passed to this function.