Skip to main content

Create dicts from variables in scope

Project description

Build Status Coverage Status PyPI - Wheel PyPI - Python Version GitHub

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dictvars-0.2.0.tar.gz (7.4 kB view details)

Uploaded Source

Built Distribution

dictvars-0.2.0-py3-none-any.whl (4.8 kB view details)

Uploaded Python 3

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

Hashes for dictvars-0.2.0.tar.gz
Algorithm Hash digest
SHA256 1170c1eb26e952682c46e9dfc7149f4401753ff83667bb6d8f21f45ede083cb5
MD5 c6dad54a77ae5fdc87154f17aad5c824
BLAKE2b-256 04b5c99f5423dad80e5b70c338a35d0f46d97ac50ea922ec07945708f7660d67

See more details on using hashes here.

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

Hashes for dictvars-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8ea1d7c4621ed7f6805c1e980e44bae03c8e317ddcafd8f57f92ea387bb128aa
MD5 1a0b02e42449c3792fb52fb9f69efac8
BLAKE2b-256 a234d730ff6d5b330ae6ca2ca2de3a68b4af4f037eb1dcc370fb1c56928fed1a

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page