{ "info": { "author": "Bryan W. Berry", "author_email": "bryan.berry@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "======================================================================\nsmonad - a functional python package with some scala inspiration\n======================================================================\n\n\nIntroduction\n============\n\n\nWhat?\n-----\n\nMonads in python, with some helpful functions.\n\nThis package is a fork of Philip Xu's excellent `monad package `_.\nPhilip's package has been modified to be more approachable for Python developers. It\ntakes some inspiration from the excellent `lambda `_ library\nfor Java and Scala's `Try monad `_\n\nPython developers may find the Try monad particularly useful as it allows you to treat errors\nas values.\n\n\nWhy?\n----\n\nPython does not have a good builtin conventions for processing multiple\noperations in batch. Further, this library's authors found excessive reliance\non classes can lead to less composable code.\n\nThis library borrows some ideas from Haskell and other functional programming\nlanguage to better handle the aforementioned use case. While this library does\nhave 'monad' in its name, you do not need to know anything about the\nconcept of monads in order to use this library.\n\n\nTreating Errors as Values\n------------------------------\n\nPython does not have a built-in convention for treating errors as values\nother than try/except.\n\nsmonad introduces the Failure/Success convention of wrapping failed or\nsuccessful results in a container class.\n\n\nThe utility method ``attempt`` executes a callable and wraps a raised exception\nin a Failure class. If an exception was not raised, a Success is returned\n\n::\n\n >>> from smonad.actions import attempt\n >>> result = attempt(lambda: 1 / 0)\n >>> print result\n Failure(ZeroDivisionError('integer division or modulo by zero',))\n >>> exc = result.value\n >>> exc\n ZeroDivisionError('integer division or modulo by zero',)\n >>> # the following would fail as it does not catch the correct exception\n >>> # result = attempt(lambda: 1 / 0, exception=ValueError)\n >>> result = attempt(lambda: 1 / 1)\n >>> print result\n Success(1)\n >>> result.value\n 1\n\n\nYou can instantiate Failure or Success inside your own code to indicate\nwhether a computation was successful.\n\n\nHere is an example script to create AWS instances that uses Failure/Success\nto propagate failures to the highest possible level.\n\n\n::\n \n from collections import namedtuple\n from smonad.types.ftry import Success, Failure\n from smonad.utils import failed\n import sys\n import os\n\n\n CloudInstance = namedtuple('CloudInstance', ['name', 'provider', 'instance_type'])\n\n jenkins = CloudInstance(name='jenkins', provider='aws', instance_type='m3.medium')\n\n git = CloudInstance(name='git', provider='aws', instance_type='m3.xlarge')\n\n vault = CloudInstance(name='vault', provider='aws', instance_type='m3.xlarge')\n\n\n class TryAgainLaterError(Exception):\n pass\n\n\n def aws_create_instance(instance):\n if instance.name == 'jenkins':\n raise TryAgainLaterError(\"Can't create jenkins server right now\")\n\n return instance\n\n\n def create_cloud_instance(instance):\n try:\n created_instance = aws_create_instance(instance)\n return Success(created_instance)\n except TryAgainLaterError as e:\n return Failure(instance)\n\n\n def make_my_servers():\n server_results = []\n for server in [jenkins, git, vault]:\n server_results.append(create_cloud_instance(server))\n\n # if there are any errors, let's retry once more\n failed_servers = filter(lambda r: failed(r), server_results)\n retry_results = []\n for exc, instance in failed_servers:\n retry_results.append(aws_create_instance(instance))\n\n if any([failed(i) for i in retry_results]):\n failed_servers = \",\".join([i.value.name for i in retry_results if failed(i)])\n return Failure(\"Unable to create servers: %s\" % failed_servers)\n\n return Success(\"Successfully created all servers\")\n\n\n if __name__ == \"__main__\":\n result = make_my_servers()\n if failed(result):\n sys.stderr.write(\"Error: %s\\n\" % result.value)\n os.sys.exit(1)\n else:\n print result.value\n\n\nWe can simplify the ``make_my_servers`` function by taking advantage\nof the ``recover`` method of ``Try``. recover applies a recovery function\nto instances of Failure. It returns Success(V) unchanged.\n\n::\n\n \n def make_my_servers():\n server_results = []\n for server in [jenkins, git, vault]:\n server_results.append(create_cloud_instance(server))\n\n\n # The recover only applies ``create_cloud_instance`` to Failures, it returns the Success value otherwise\n server_results = map(lambda s: s.recover(create_cloud_instance), server_results)\n\n if any([failed(s) for s in server_results]):\n failed_servers = \",\".join([i.value.name for i in server_results if failed(i)])\n return Failure(\"Unable to create servers: %s\" % failed_servers)\n\n return Success(\"Successfully created all servers\")\n\n \n\nComposing Functions\n--------------------------\n\n\n::\n\n\n >>> from smonad.decorators import maybe\n >>> parse_int = maybe(int)\n >>> parse_int(42)\n Just(42)\n >>> parse_int('42')\n Just(42)\n >>> parse_int('42.2')\n Nothing\n\n >>> parse_float = maybe(float)\n >>> parse_float('42.2')\n Just(42.2)\n\n >>> from smonad.actions import tryout\n >>> parse_number = tryout(parse_int, parse_float)\n >>> tokens = [2, '0', '4', 'eight', '10.0']\n >>> [parse_number(token) for token in tokens]\n [Just(2), Just(0), Just(4), Nothing, Just(10.0)]\n\n >>> @maybe\n ... def reciprocal(n):\n ... return 1. / n\n >>> reciprocal(2)\n Just(0.5)\n >>> reciprocal(0)\n Nothing\n\n >>> process = parse_number >> reciprocal\n >>> process('4')\n Just(0.25)\n >>> process('0')\n Nothing\n >>> [process(token) for token in tokens]\n [Just(0.5), Nothing, Just(0.25), Nothing, Just(0.1)]\n >>> [parse_number(token) >> reciprocal for token in tokens]\n [Just(0.5), Nothing, Just(0.25), Nothing, Just(0.1)]\n >>> [parse_number(token) >> reciprocal >> reciprocal for token in tokens]\n [Just(2.0), Nothing, Just(4.0), Nothing, Just(10.0)]\n\n\n\nRequirements\n============\n\n- CPython >= 2.7\n\n\nInstallation\n============\n\nInstall from PyPI::\n\n pip install smonad\n\nInstall from source, download source package, decompress, then ``cd`` into source directory, run::\n\n make install\n\n\nLicense\n=======\n\nBSD New, see LICENSE for details.\n\n\nLinks\n=====\n\nDocumentation:\n http://smonad.readthedocs.org/\n\nIssue Tracker:\n https://github.com/bryanwb/smonad/issues/\n\nSource Package @ PyPI:\n https://pypi.python.org/pypi/smonad/\n\nGit Repository @ Github:\n https://github.com/bryanwb/smonad/", "description_content_type": null, "docs_url": null, "download_url": "https://github.com/bryanwb/smonad/archive/0.6.zip", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/bryanwb/smonad/", "keywords": null, "license": "BSD-New", "maintainer": null, "maintainer_email": null, "name": "smonad", "package_url": "https://pypi.org/project/smonad/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/smonad/", "project_urls": { "Download": "https://github.com/bryanwb/smonad/archive/0.6.zip", "Homepage": "https://github.com/bryanwb/smonad/" }, "release_url": "https://pypi.org/project/smonad/0.6/", "requires_dist": null, "requires_python": null, "summary": "smonad - a functional library", "version": "0.6" }, "last_serial": 2621735, "releases": { "0.3": [ { "comment_text": "", "digests": { "md5": "0126cd1f5f8d3168b2f0efbcf2342763", "sha256": "84bd05be5cf7dfb0f65310f95e6267adaf22cdd81feb92056c7808eb7cb731d3" }, "downloads": -1, "filename": "smonad-0.3.tar.gz", "has_sig": false, "md5_digest": "0126cd1f5f8d3168b2f0efbcf2342763", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23936, "upload_time": "2017-02-02T06:29:35", "url": "https://files.pythonhosted.org/packages/7f/eb/9fbeba0fa25d71790829fc0351dd076a8d7067582be03928c7c2a874d04f/smonad-0.3.tar.gz" } ], "0.5": [ { "comment_text": "", "digests": { "md5": "7bfcc535c55b43505597abc43ad425a3", "sha256": "18eb5e9e337c1bd9ba74e77d58b5efbbbf800a8d319095439e31ae6d5f283f58" }, "downloads": -1, "filename": "smonad-0.5.tar.gz", "has_sig": false, "md5_digest": "7bfcc535c55b43505597abc43ad425a3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 24212, "upload_time": "2017-02-02T14:05:14", "url": "https://files.pythonhosted.org/packages/a5/73/288f42720bd939bb8e118424bf78549617d886af374592b9a79bc5647184/smonad-0.5.tar.gz" } ], "0.6": [ { "comment_text": "", "digests": { "md5": "090400647b2bd9f36596dd848e22f0cb", "sha256": "5824076394ac91798d424bdec065c25f40c1065583ad0e223895338396b8ed62" }, "downloads": -1, "filename": "smonad-0.6.tar.gz", "has_sig": false, "md5_digest": "090400647b2bd9f36596dd848e22f0cb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26819, "upload_time": "2017-02-06T07:11:59", "url": "https://files.pythonhosted.org/packages/85/5e/fb078f262d56eecf722d8a18c1c265f5e293bfb41e21544a20b141629a13/smonad-0.6.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "090400647b2bd9f36596dd848e22f0cb", "sha256": "5824076394ac91798d424bdec065c25f40c1065583ad0e223895338396b8ed62" }, "downloads": -1, "filename": "smonad-0.6.tar.gz", "has_sig": false, "md5_digest": "090400647b2bd9f36596dd848e22f0cb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26819, "upload_time": "2017-02-06T07:11:59", "url": "https://files.pythonhosted.org/packages/85/5e/fb078f262d56eecf722d8a18c1c265f5e293bfb41e21544a20b141629a13/smonad-0.6.tar.gz" } ] }