{ "info": { "author": "Aaron Griffith", "author_email": "aargri@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3" ], "description": "parameterize\n============\n\n*a Python implementation of [SRFI 39][]*\n\n [SRFI 39]: http://srfi.schemers.org/srfi-39/srfi-39.html\n \n[![Build Status](https://travis-ci.org/agrif/parameterize.svg)](https://travis-ci.org/agrif/parameterize)\n\n*parameterize* implements optional dynamic scope and parameter objects\nin Python. It's a spiritual implementation of parameters from Scheme,\nas outlined in [SRFI 39][]. If you know what that means, awesome! If\nnot, read on.\n\n### Requirements\n\n*parameterize* should work, by itself, on Python 2.7 or later\n (including Python 3).\n\nParameter Objects\n-----------------\n\nBasically, parameter objects hold a single value. They are meant to be\ndeclared as global variables, so that the values they contain can be\naccessed anywhere. However, parameter objects have a neat trick: they\nhave a context manager, `parameterize()`, that lets you override the\nparameter's value for a single piece of code. Any changes to the\nparameter that happen within this code block can't escape it, and\ncan't affect other threads of execution.\n\nSo, parameters are sort of halfway between global variables and local\nvariables. They're accessable from anywhere, and modifiable from\nanywhere, but modifications are always contained completely within\ntheir `parameterize()` block.\n\nMotivating Example\n------------------\n\nIn Python, the `sys.stdout` global variable can be overridden to point\nto any file-like object to redirect output from built-in output\nprimitives like `print()`. So, there's a nice hacky way to redirect\nthe output of a function:\n\n~~~~{.py}\nwith open('output.txt', 'w') as f:\n oldstdout = sys.stdout\n sys.stdout = f\n\tsomething_that_prints_a_lot()\n\tsys.stdout = oldstdout\n~~~~\n\nThis is definitely a hack, though. It can be made a little bit nicer\nby wrapping the replacement code into a context manager, but it's hard\nto write a context manager that works for any variable like this (what\nif we wanted to redirect `sys.stderr` instead?). Also, this has issues\nwith threading: if another thread tries to write to `stdout` while\n`something_that_prints_a_lot()` is running, it'll end up in\n`output.txt`.\n\n*parameterize* and Parameter objects solve all these little problems\n for you. All we need to do is create an `stdout` parameter (with the\n initial value of `sys.stdout`), and replace `sys.stdout` with a proxy\n object that always points to the value of this parameter:\n\n~~~~{.py}\nimport parameterize\nimport sys\n\n# create our parameter and proxy object\nstdoutp = parameterize.Parameter(sys.stdout)\nsys.stdout = stdoutp.proxy()\n\nprint('before')\nwith open('output.txt', 'w') as f:\n with stdoutp.parameterize(f):\n\t print('inside')\nprint('after')\n~~~~\n\nThis code will print \"before\" and \"after\" to the console, and \"inside\"\nto `output.txt`. The mutation of `sys.stdout` only appears within the\n`with stdoutp.parameterize` block, and plays nicely with other\nthreads.\n\nThis sort of pattern (where there's some global context that affects\npossibly deeply-nested functions, without passing this context through\nthe call chain) is also very common in web frameworks, where code\nhandling a response needs access to the request data, but may not have\nbeen passed it directly. Werkzeug calls them\n[context locals][werkzeug], and Flask calls it an\n[application context][flask]. *parameterize* is a stand-alone way to\ndo this outside of these frameworks.\n\n [werkzeug]: http://werkzeug.pocoo.org/docs/local/\n [flask]: http://flask.pocoo.org/docs/appcontext/#app-context\n\nIncidentally, the above example about replacing `sys.stdout` with a\nparameter is exactly how R7RS Scheme handles IO redirection.\n\nAPI\n---\n\n*parameterize* is a small module. To create a parameter object, use\n `Parameter(default, converter)`. `default` sets the initial value,\n and defaults to `None` when not provided. `converter` is a function\n that is called whenever the parameter is set, and should return a\n validated or converted value. If `converter` is not supplied, it\n defaults to doing nothing.\n\nParameter objects have a `get()` method, and a `set(v)` method, to get\nand set the value contained by the object. As a convenience, if you\nhave a parameter object `p`, `p()` is the same as `p.get()`, and\n`p(v)` is the same as `p.set(v)`.\n\nParameter objects also have `parameterize(v)`, a context manager that\nsets the parameter to `v` within its block, and prevents all changes\nto the parameter within that block from escaping. This is *the big\ndeal* about *parameterize*, and what seperates parameters from normal\nglobal variables.\n\nIf the parameter value is an object, you can call `proxy()` to get an\nobject that will act like the object contained within the parameter,\nand track any changes made to that value. This proxying mechanism is a\nwork in progress, and is probably more magic than you need. Still, it\nis useful sometimes. Patches *very* welcome.\n\nLicense\n-------\n\n*parameterize* is distributed under the MIT License. See `LICENSE.txt`\nfor details.\n", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/agrif/parameterize", "keywords": "parameters,parameterize,dynamic scope", "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "parameterize", "package_url": "https://pypi.org/project/parameterize/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/parameterize/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/agrif/parameterize" }, "release_url": "https://pypi.org/project/parameterize/0.2/", "requires_dist": null, "requires_python": null, "summary": "a Python implementation of parameterize and SRFI 39", "version": "0.2" }, "last_serial": 1347871, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "6a3c6dbf852645590bb701dfc27b1bcc", "sha256": "567195e1f946548e2b09a9cc5be9840076ce9555ea111c7de2498ab1175a5295" }, "downloads": -1, "filename": "parameterize-0.1.tar.gz", "has_sig": false, "md5_digest": "6a3c6dbf852645590bb701dfc27b1bcc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9685, "upload_time": "2014-04-22T03:20:53", "url": "https://files.pythonhosted.org/packages/42/30/0c23600b152e040b0cc0761bb20e73d199f7774555da1ef542bea14f49be/parameterize-0.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "2d3feddec4bd6439b1a54617b8c1afe1", "sha256": "f3d8dcc50995b54ef9ff44fdca5a96fb15e57df0c77d622f87d483060a270928" }, "downloads": -1, "filename": "parameterize-0.2.tar.gz", "has_sig": false, "md5_digest": "2d3feddec4bd6439b1a54617b8c1afe1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9766, "upload_time": "2014-12-17T15:19:42", "url": "https://files.pythonhosted.org/packages/e3/3a/c55ed9653bdb52c7df0c08568b596d5ae200326f47b05badbcbc920c0ffa/parameterize-0.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "2d3feddec4bd6439b1a54617b8c1afe1", "sha256": "f3d8dcc50995b54ef9ff44fdca5a96fb15e57df0c77d622f87d483060a270928" }, "downloads": -1, "filename": "parameterize-0.2.tar.gz", "has_sig": false, "md5_digest": "2d3feddec4bd6439b1a54617b8c1afe1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9766, "upload_time": "2014-12-17T15:19:42", "url": "https://files.pythonhosted.org/packages/e3/3a/c55ed9653bdb52c7df0c08568b596d5ae200326f47b05badbcbc920c0ffa/parameterize-0.2.tar.gz" } ] }