Create dicts from variables in scope
Project description
dictvars
Create dicts from variables in scope.
Why?
In python it is very common to create a dict from variables already defined, for example when returning a context dict from a view function that will be passed to a serializer or a template render.
Code like this:
return dict(user=user, form=form, comments=comments)
With varsdict
you can get rid of the redundancy of having all
variables named twice in the code.
The above code can be replaced for this:
return dictvars(user, form, comments)
Alternatively, variable names can be passed as strings with varsnamed
:
return varsnamed('form', 'comments', 'myapp')
Install
pip install dictvars
Example
Global variables can be passed to varsdict
as well.
The following example is a complete code to illustrate how
a "real" code looks like when using and not using varsdict
and varsnamed
.
from dictvars import dictvars, varsnamed
myapp = 'MyApp' # a global var
def somefunc_regular_python():
# pretend this is a controller code that makes sense
user = dict(some='very', complex_='expression')
permission = user.get('permission', False)
user_has_permission = bool(permission)
form = dict(another='object', perm=user_has_permission)
comments = []
for values in [d.values() for d in [user, form]]:
comments.extend([v for v in values if isinstance(v, str)])
return dict(form=form, comments=comments, myapp=myapp)
def somefunc_dictvars():
# pretend this is a controller code that makes sense
user = dict(some='very', complex_='expression')
permission = user.get('permission', False)
user_has_permission = bool(permission)
form = dict(another='object', perm=user_has_permission)
comments = []
for values in [d.values() for d in [user, form]]:
comments.extend([v for v in values if isinstance(v, str)])
return dictvars(form, comments, myapp)
def somefunc_varsnamed():
# pretend this is a controller code that makes sense
user = dict(some='very', complex_='expression')
permission = user.get('permission', False)
user_has_permission = bool(permission)
form = dict(another='object', perm=user_has_permission)
comments = []
for values in [d.values() for d in [user, form]]:
comments.extend([v for v in values if isinstance(v, str)])
return varsnamed('form', 'comments', 'myapp')
if __name__ == '__main__':
from pprint import pprint
pprint(somefunc_regular_python())
pprint(somefunc_dictvars())
pprint(somefunc_varsnamed())
Output is the same in all versions:
{'comments': ['very', 'expression', 'object'],
'form': {'another': 'object', 'perm': False},
'myapp': 'MyApp'}
{'comments': ['very', 'expression', 'object'],
'form': {'another': 'object', 'perm': False},
'myapp': 'MyApp'}
{'comments': ['very', 'expression', 'object'],
'form': {'another': 'object', 'perm': False},
'myapp': 'MyApp'}
Renaming variables
The standard kwargs syntax of dict
is also supported by dictvars
.
Suppose you have a variable current_user
but you want to use only user
on your dict:
def somefunc_dictvars(current_user):
form = dict(some='very', complex_='expression')
comments = ['bla', 'bla']
return dictvars(form, comments, app=myapp, user=current_user)
Works as expected:
{'app': 'MyApp',
'comments': ['bla', 'bla'],
'form': {'some': 'very', 'complex_': 'expression'},
'user': 'John Do'}
Limitations
To create a dict from the passed variables, some "magic" is done to obtain the original variables names: the variables list from the scope is traversed looking for variables that are the same (same reference, same id).
This implementation detail can lead to unintended leak of variables when an object is referenced more then one time.
An example:
def somefunc():
a = '1'
b = '2'
c = '3'
leak = b
return dictvars(a, b)
print(somefunc())
Returns:
{'a': '1',
'b': '2',
'leak': '2'}
Please note that no new value or object is leaked, only the name of an object that was already in the dict.
I find that this is rare enough to not be a problem most of the time, additional variables returned usually can just be ignored.
I'm not sure how to fix this yet. Open to suggestions.
If this is a problem on a specific context, one can just pass the offending variable with a explicit name, just like a regular dict:
def somefunc():
a = '1'
b = '2'
c = '3'
no_leaks_now = b
return dictvars(a, b=b)
print(somefunc())
Returns:
{'a': '1',
'b': '2'}
Yet another alternative in such cases would be to swap dictvars
for
varsnamed
:
return varsnamed('a', 'b')
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file dictvars-0.2.0.tar.gz
.
File metadata
- Download URL: dictvars-0.2.0.tar.gz
- Upload date:
- Size: 7.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.0.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.6.0 requests-toolbelt/0.9.1 tqdm/4.38.0 CPython/3.8.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1170c1eb26e952682c46e9dfc7149f4401753ff83667bb6d8f21f45ede083cb5 |
|
MD5 | c6dad54a77ae5fdc87154f17aad5c824 |
|
BLAKE2b-256 | 04b5c99f5423dad80e5b70c338a35d0f46d97ac50ea922ec07945708f7660d67 |
File details
Details for the file dictvars-0.2.0-py3-none-any.whl
.
File metadata
- Download URL: dictvars-0.2.0-py3-none-any.whl
- Upload date:
- Size: 4.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.0.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.6.0 requests-toolbelt/0.9.1 tqdm/4.38.0 CPython/3.8.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8ea1d7c4621ed7f6805c1e980e44bae03c8e317ddcafd8f57f92ea387bb128aa |
|
MD5 | 1a0b02e42449c3792fb52fb9f69efac8 |
|
BLAKE2b-256 | a234d730ff6d5b330ae6ca2ca2de3a68b4af4f037eb1dcc370fb1c56928fed1a |