{
"info": {
"author": "Peter Fein",
"author_email": "pfein@pobox.com",
"bugtrack_url": null,
"classifiers": [],
"description": "Overview\n========\nFactory is an object-oriented approach to partial function application, also known as currying. The Factory module is a more powerful implementation of this pattern. Some improvements include:\n\n- safer, as invalid arguments are detected immediately, instead of at call time\n- intelligent support for classes, instance methods & all other callables\n- bound arguments can be inspected and modified as attributes\n- several convenient methods for (re)binding arguments\n- no \"Russian dolls\" of nested lambdas\n\nUsing Factories can:\n\n- simplify writing callbacks\n- reduce bugs in concurrent applications\n- provide easy lazy evaluation\n\nInstallation\n============\nThe Factory module is available from the `Cheeseshop `_. The source code is available from the `Google Code project page `_.\n\nThe Factory module can be installed like any other pure Python module. Setuptools is supported but not required. You may also include the ``Factory.py`` file directly in your project's source tree, but you must retain the copyright notice and version and attribution information.\n\nTo run tests for the module, execute the following commands in the ``Factory/`` directory:\n\n- ``python doctest_Factory.py``\n- ``nosetests test_Factory.py``\n\nAbout Currying\n==============\nCurrying creates a new function from an existing one by binding some of the original's arguments:\n\n>>> def adder(x, y):\n... return x + y\n>>> add_lambda = lambda y: adder(1, y)\n>>> add_lambda(10)\n11\n\nAs of Python 2.5, this pattern is built in with the `partial `_ function.\n\n>>> add_partial = functools.partial(adder, 1)\n>>> add_partial(y=10)\n11\n\nFactories\n=========\nFactories are better implementation of the currying pattern:\n\n>>> from Factory import *\n>>> add_factory = Factory(adder, x=1)\n>>> add_factory #doctest: +ELLIPSIS\n) at ...>\n>>> add_factory(y=10)\n11\n\nUnlike lambdas and partial, factories can be inspected and modified:\n\n>>> add_factory.x\n1\n>>> add_factory.x = 2\n>>> add_factory(y=10)\n12\n\nThe arguments that would be passed to the function can be examined, which\nis sometimes helpful in debugging:\n\n>>> import pprint\n>>> args, kwargs = add_factory.generateArgs(y=10)\n>>> pprint.pprint(kwargs)\n{'x': 2, 'y': 10}\n>>> args\n[]\n\nUsage\n=====\nIn the following examples, we mix in **FactoryMixin** to provide a\n``factory`` classmethod on the base class.\n\n>>> class Foo(FactoryMixin):\n... def __init__(self, foo):\n... self.foo = foo\n...\n>>> foo_factory = Foo.factory()\n>>> foo_factory.foo = 66\n\nThis is equivalent to:\n\n>>> Factory(Foo) #doctest:+ELLIPSIS\n) at ...>\n\nUsing the mixin isn't strictly necessary, but looks nice and is easier to spell.\n\nFactories have a **bind** method that can be used to set several attributes\nat once and returns the factory. It's useful for binding arguments\nwithout assigning the factory to a local variable.\n\n>>> def doStuff(foo_factory):\n... return foo_factory.foo\n>>> doStuff(foo_factory.bind(foo=11))\n11\n>>> foo_factory2 = foo_factory.bind(foo=42)\n>>> foo_factory2 is foo_factory\nTrue\n>>> foo_factory.foo\n42\n\nYou can also bind attributes when constructing the factory:\n\n>>> foo_factory = Factory(Foo, foo=11)\n>>> foo_factory.foo\n11\n\nFactories ensure that attributes match up with arguments; this makes\nfinding errors easier (instead of raising a ``unexpected keyword argument``\nlater):\n\n>>> foo_factory.bar = 42 #doctest: +IGNORE_EXCEPTION_DETAIL\nTraceback (most recent call last):\n File \"\", line 1, in \nAttributeError: 'No such argument bar'\n\nWhen calling the factory, arguments override attributes:\n\n>>> foo = foo_factory(foo=1111)\n>>> foo.foo\n1111\n\nEach call returns a new instance:\n\n>>> foo2 = foo_factory()\n>>> foo2 is foo\nFalse\n\nThe set of valid attributes is the union of all ``__init__`` arguments in the\ninheritance chain:\n\n>>> class Bar(Foo):\n... def __init__(self, bar, **kwargs):\n... super(Bar, self).__init__(**kwargs)\n... self.bar = bar\n...\n>>> bar_factory = Bar.factory()\n>>> bar_factory.foo = 11\n>>> bar_factory.bar = 42\n>>> bar_factory.quux = 666 #doctest: +IGNORE_EXCEPTION_DETAIL\nTraceback (most recent call last):\n File \"\", line 1, in \nAttributeError: 'No such argument quux'\n>>> bar = bar_factory()\n>>> bar.foo\n11\n>>> bar.bar\n42\n\nBe sure to pass Factory a callable object (a class, not an an instance):\n\n>>> Factory(bar) #doctest:+ELLIPSIS, +IGNORE_EXCEPTION_DETAIL\nTraceback (most recent call last):\n File \"\", line 1, in \nTypeError: must provide known callable type, not \n\nCallable objects are fine, of course:\n\n>>> class CallMe(object):\n... def __init__(self, x):\n... self.x = x\n... def __call__(self, y):\n... return self.x + y\n>>> Factory(CallMe(1))(1)\n2\n\nAn existing factory can be passed as the ``callee`` of a new factory.\n\n>>> bar_factory = Bar.factory(bar=2)\n>>> bar_factory2 = Factory(bar_factory, foo = 1)\n>>> bar_factory is not bar_factory2\nTrue\n>>> bar_factory2.bar\n2\n>>> bar_factory2.bar = 4\n>>> bar_factory.bar\n2\n\nUnlike using lambdas, this does not create nested \"Russian dolls\":\n\n>>> bar_factory2.getCallable()\n\n\nDecorators\n==========\n**returnFactory** is a decorator which *replaces* a function with its Factory-producing equivalent:\n\n>>> @returnFactory\n... def mult(x, y):\n... return x * y\n>>> fac = mult(x=10, y=5)\n>>> isinstance(fac, Factory)\nTrue\n>>> fac()\n50\n\n**factoryAttribute** adds a ``factory`` attribute to the decorated function:\n\n>>> @factoryAttribute\n... def adder(x, y):\n... return x + y\n>>> fac = adder.factory(x=10)\n>>> isinstance(fac, Factory)\nTrue\n>>> fac2 = adder.factory()\n>>> fac is not fac2\nTrue\n>>> fac(y=42)\n52\n\n**factoryDescriptor** produces instance methods with a ``factory`` attribute. Inside classes, use this descriptor instead of factoryAttribute. This class may be used as a decorator:\n\n>>> class Quux(object):\n... @factoryDescriptor\n... def doStuff(self, whatnot):\n... pass\n>>> quux = Quux()\n>>> fac = quux.doStuff.factory(whatnot=42)\n>>> isinstance(fac, Factory)\nTrue\n>>> fac.whatnot\n42\n\nObjectTemplates\n================\nObjectTemplates are a template for creating objects. They work well with Factories.\n\nA **Bunch** is simply a bunch of attributes. Keyword arguments to a Bunch are turned into attributes:\n\n>>> b = Bunch(pants=42, shirt=15)\n>>> b.pants\n42\n>>> b.shirt\n15\n\nCalling a bunch returns a new copy:\n\n>>> c = b()\n>>> c.__dict__ == b.__dict__\nTrue\n>>> c is b\nFalse\n\nWhen called, an **ObjectTemplate** instance produces a new instance\nof ``bunchClass``. Attributes on the template are passed as kwargs\nto the bunch. However, if an attribute is callable, it is called\nand the return value is used instead:\n\n>>> counter = itertools.count(1).next # an incrementing counter\n>>> def color():\n... return \"blue\"\n>>> template = ObjectTemplate(size=42,\n... color=color,\n... count=counter,\n... bunchClass=Bunch)\n>>> bunch = template()\n>>> isinstance(bunch, Bunch)\nTrue\n>>> bunch.size\n42\n>>> bunch.color\n'blue'\n>>> bunch.count\n1\n\nEach call to the template produces a new bunch. Any functions will\nbe called again:\n\n>>> bunch2 = template()\n>>> bunch2.count\n2\n\nIf you want to pass a callable object to the bunch, wrap it in a lambda:\n\n>>> template = ObjectTemplate()\n>>> template.return_val = color\n>>> template.a_function = lambda: color\n>>> bunch = template()\n>>> bunch.return_val\n'blue'\n>>> bunch.a_function #doctest:+ELLIPSIS\n\n\nBugs\n====\nBugs, feature requests and praise may be sent directly to `the author `_.",
"description_content_type": null,
"docs_url": null,
"download_url": "UNKNOWN",
"downloads": {
"last_day": -1,
"last_month": -1,
"last_week": -1
},
"home_page": "http://code.google.com/p/python-factory/",
"keywords": null,
"license": "UNKNOWN",
"maintainer": null,
"maintainer_email": null,
"name": "Factory",
"package_url": "https://pypi.org/project/Factory/",
"platform": "UNKNOWN",
"project_url": "https://pypi.org/project/Factory/",
"project_urls": {
"Download": "UNKNOWN",
"Homepage": "http://code.google.com/p/python-factory/"
},
"release_url": "https://pypi.org/project/Factory/1.2/",
"requires_dist": null,
"requires_python": null,
"summary": "Object Oriented Currying",
"version": "1.2"
},
"last_serial": 784232,
"releases": {
"1.0": [
{
"comment_text": "",
"digests": {
"md5": "90cc1b5451b1f4d740fa6a733c4a4e54",
"sha256": "74f48d24492fa89b0a530ead6501e9b025aa26454af72882885c56703bc9aa8b"
},
"downloads": -1,
"filename": "Factory-1.0.tar.gz",
"has_sig": true,
"md5_digest": "90cc1b5451b1f4d740fa6a733c4a4e54",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 7621,
"upload_time": "2008-11-07T19:48:11",
"url": "https://files.pythonhosted.org/packages/6d/73/e6498aea9b7b6a188b5569126e0a39928ffc1d7bf37eafa511ea9cc81b18/Factory-1.0.tar.gz"
}
],
"1.1": [
{
"comment_text": "",
"digests": {
"md5": "27e1ddf9ddcdc176567818eb36afbc00",
"sha256": "2a83eb836b9e929fd8682575a8ee700e4012d8e32c826895db3044aedab96006"
},
"downloads": -1,
"filename": "Factory-1.1.tar.gz",
"has_sig": true,
"md5_digest": "27e1ddf9ddcdc176567818eb36afbc00",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 8880,
"upload_time": "2008-11-10T22:05:51",
"url": "https://files.pythonhosted.org/packages/20/bf/6845c17765bced37a0032e22fb3f8f4fcc30b90617250c445413e1e6a2d8/Factory-1.1.tar.gz"
}
],
"1.2": [
{
"comment_text": "",
"digests": {
"md5": "a1e0c5d326cea1c4e7a588f28ce9c5de",
"sha256": "c0af96e123ac9164ca7d1b9905de749f94e819c8e85341c8fb9f1dd2e349c8cc"
},
"downloads": -1,
"filename": "Factory-1.2.tar.gz",
"has_sig": true,
"md5_digest": "a1e0c5d326cea1c4e7a588f28ce9c5de",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 8944,
"upload_time": "2008-12-23T22:07:01",
"url": "https://files.pythonhosted.org/packages/18/7b/342e9c93d32b21deaaded9fb929413b71c37187079bbdce4b6bae4568f47/Factory-1.2.tar.gz"
}
]
},
"urls": [
{
"comment_text": "",
"digests": {
"md5": "a1e0c5d326cea1c4e7a588f28ce9c5de",
"sha256": "c0af96e123ac9164ca7d1b9905de749f94e819c8e85341c8fb9f1dd2e349c8cc"
},
"downloads": -1,
"filename": "Factory-1.2.tar.gz",
"has_sig": true,
"md5_digest": "a1e0c5d326cea1c4e7a588f28ce9c5de",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 8944,
"upload_time": "2008-12-23T22:07:01",
"url": "https://files.pythonhosted.org/packages/18/7b/342e9c93d32b21deaaded9fb929413b71c37187079bbdce4b6bae4568f47/Factory-1.2.tar.gz"
}
]
}