{"id":15445062,"url":"https://github.com/hachibeedi/masala","last_synced_at":"2025-06-14T14:34:19.796Z","repository":{"id":17321951,"uuid":"20092883","full_name":"hachibeeDI/masala","owner":"hachibeeDI","description":"some metaprogramming spice for Python","archived":false,"fork":false,"pushed_at":"2016-11-21T04:58:17.000Z","size":63,"stargazers_count":5,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-05-26T11:17:08.057Z","etag":null,"topics":["functional-programming","metaprogramming","monad","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hachibeeDI.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-05-23T08:47:12.000Z","updated_at":"2019-08-13T15:42:17.000Z","dependencies_parsed_at":"2022-09-26T21:21:39.210Z","dependency_job_id":null,"html_url":"https://github.com/hachibeeDI/masala","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/hachibeeDI/masala","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hachibeeDI%2Fmasala","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hachibeeDI%2Fmasala/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hachibeeDI%2Fmasala/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hachibeeDI%2Fmasala/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hachibeeDI","download_url":"https://codeload.github.com/hachibeeDI/masala/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hachibeeDI%2Fmasala/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259831521,"owners_count":22918532,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["functional-programming","metaprogramming","monad","python"],"created_at":"2024-10-01T19:43:54.703Z","updated_at":"2025-06-14T14:34:19.760Z","avatar_url":"https://github.com/hachibeeDI.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n=================================================================\nMasala\n=================================================================\n\nAmuse a Python syntax.\nSupports short hand lambda and monad types and null safe method calling kinda things with abuse operator overload.\n\n\nmaster:\n\n.. image:: https://travis-ci.org/hachibeeDI/masala.svg?branch=master\n    :target: https://travis-ci.org/hachibeeDI/masala\n\n\nInstall\n=================================================================\n\n.. code-block:: bash\n\n   $ pip install masala\n\n\nExample\n=================================================================\n\n\ncurry\n-----------------------------------------------------------------\n\n\n.. code-block:: python\n\n   \u003e\u003e\u003e from __future__ import (print_function, division, absolute_import, unicode_literals, )\n   \u003e\u003e\u003e from masala import CurryContainer as cc\n   \u003e\u003e\u003e cur = cc(lambda a, b, c: [a, b, c])\n   \u003e\u003e\u003e cur = cur \u003c\u003c 'aaa' \u003c\u003c 'bbb'\n   \u003e\u003e\u003e cur('ccc')\n   ['aaa', 'bbb', 'ccc']\n\n   \u003e\u003e\u003e cur = cc(lambda a, b='hogeeee', c='foooo': [a, b, c])\n   \u003e\u003e\u003e cur = cur \u003c\u003c 'a' \u003c\u003c ('c', 'c')\n   \u003e\u003e\u003e cur('b')\n   ['a', 'b', 'c']\n\n   \u003e\u003e\u003e from masala import curried\n   \u003e\u003e\u003e @curried\n   ... def sum5(a, b, c, d, e):\n   ...     return a + b + c + d + e\n   ...\n   \u003e\u003e\u003e sum0 = sum5 \u003c\u003c 1 \u003c\u003c 2 \u003c\u003c 3 \u003c\u003c 4 \u003c\u003c 5\n   \u003e\u003e\u003e assert sum0() == sum5(1, 2, 3, 4, 5)\n\n\n\nshort hands\n-----------------------------------------------------------------\n\nlambda\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code-block:: python\n\n   \u003e\u003e\u003e from masala import lambd as _\n   \u003e\u003e\u003e from masala.datatype import Either\n   \u003e\u003e\u003e Either.right('hachi') \u003e\u003e _.title()\n   'Hachi'\n   \u003e\u003e\u003e replacer = _.replace(_, _)\n   \u003e\u003e\u003e replacer('hachi', 'chi', 'chiboee')\n   'hachiboee'\n   \u003e\u003e\u003e list(map(_ + 2, range(3)))\n   [2, 3, 4]\n   \u003e\u003e\u003e from six.moves import reduce\n   \u003e\u003e\u003e reduce(_ + _, range(5))\n   10\n\n\nmethod chaining\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n\n.. code-block:: python\n\n   \u003e\u003e\u003e from masala import BuilderAllowsMethodChaining as __\n   \u003e\u003e\u003e Either.right('hachi') \u003e\u003e __.title().replace('i', 'U').replace('c', 'z')\n   'HazhU'\n   \u003e\u003e\u003e foolambda = __.title().replace('i', 'U').replace('c', 'z')\n   \u003e\u003e\u003e foolambda('hachi')\n   'HazhU'\n\n   \u003e\u003e\u003e Either.right(4) \u003e\u003e ((__ + 4) * 'py'.title())\n   'PyPyPyPyPyPyPyPy'\n   \u003e\u003e\u003e (__ + 1 + 2 + 3 + 4 + 5)(0)\n   15\n   \u003e\u003e\u003e (__ + 1 + 2 + 3 + 4 + 5).apply__(0)\n   15\n\n\nlist processing\n-----------------------------------------------------------------\n\n\n.. code-block:: python\n\n   \u003e\u003e\u003e from masala import (apply as a, lambd as _, )\n   \u003e\u003e\u003e from masala.datatype import Stream\n   \u003e\u003e\u003e # extends linq like methods to Stream.\n   \u003e\u003e\u003e # but I reccomend to use itertools extention is also prepared as `from masala.datatype.stream import itertools_ext`\n   \u003e\u003e\u003e from masala.datatype.stream import linq_ext\n   \u003e\u003e\u003e Stream([1, 2, 3]).select(_ * 2).to_list()\n   [2, 4, 6]\n   \u003e\u003e\u003e # support lazy evaluation\n   \u003e\u003e\u003e Stream([1, 2, 3]).select(_ * 2)  # doctest:+ELLIPSIS\n   Stream: \u003c \u003cfunction ...\n\n   \u003e\u003e\u003e Stream(range(0, 15)).select(_ + 1).where(__ % 2 == 0).to_list()\n   [2, 4, 6, 8, 10, 12, 14]\n\n   \u003e\u003e\u003e Stream(range(0, 100)).select(_ * 2).where(_ \u003e 1000).first()  # doctest:+ELLIPSIS\n   Empty: \u003c None \u003e reason =\u003e \u003cclass 'masala.datatype.stream.error.NoContentStreamError'\u003e:\n\n   \u003e\u003e\u003e Stream(range(0, 100)).select(_ * 2).any(_ \u003e 1000)\n   False\n   \u003e\u003e\u003e Stream(111111).select(_ * 2).to_list()\n   Empty: \u003c None \u003e reason =\u003e \u003cclass 'masala.datatype.stream.error.NotIterableError'\u003e: 'int' object is not iterable\n\n   \u003e\u003e\u003e # you can extend the method by yourself\n   \u003e\u003e\u003e from masala.datatype.stream import dispatch_stream\n   \u003e\u003e\u003e @dispatch_stream\n   ... def my_select(xs, x_to_y):\n   ...     for x in xs:\n   ...         yield x_to_y(x)\n   \u003e\u003e\u003e Stream([1, 2, 3]).my_select(_ * 2).to_list()\n   [2, 4, 6]\n   \u003e\u003e\u003e from masala.datatype.stream import delete_dispatchedmethods\n   \u003e\u003e\u003e # you can clean extentions.\n   \u003e\u003e\u003e delete_dispatchedmethods(['my_select'])\n\n   \u003e\u003e\u003e # other cases\n   \u003e\u003e\u003e twicer = Stream().select(_ * 2)\n   \u003e\u003e\u003e twiced = twicer \u003c\u003c [1, 2, 3]\n   \u003e\u003e\u003e list(twiced)\n   [2, 4, 6]\n   \u003e\u003e\u003e twiced2 = twicer \u003c\u003c [2, 3, 4]\n   \u003e\u003e\u003e list(twiced2)\n   [4, 6, 8]\n\n   \u003e\u003e\u003e delete_dispatchedmethods(linq_ext.__all__)\n\n\n\nPattern Match\n-----------------------------------------------------------------\n\n\n.. code-block:: python\n\n   \u003e\u003e\u003e from masala import Match\n\n   \u003e\u003e\u003e match = Match(10)\n   \u003e\u003e\u003e if match.when(1):\n   ...    print('boo')\n   ... elif match.when(10):\n   ...    print('yieeeee')\n   yieeeee\n\n\n   \u003e\u003e\u003e from masala import Wildcard as _\n\n   \u003e\u003e\u003e match = Match([1, 2, 3])\n   \u003e\u003e\u003e @match.when([2, 2, 2], let_=('one', 'two', 'thr'))\n   ... def case1(one, two, thr):\n   ...     return 'case1'\n   \u003e\u003e\u003e @match.when([_, 2, 3], let_=('one', '_', 'thr'))\n   ... def case2(one, thr):\n   ...    return 'case2'\n   \u003e\u003e\u003e assert match.end == 'case2'\n\n   \u003e\u003e\u003e match = Match('python')\n   \u003e\u003e\u003e @match.when(_.isdigit(), let_='moo')\n   ... def case1(moo):\n   ...     return one\n   \u003e\u003e\u003e @match.when(_ == 'python', let_=('a'))\n   ... def case2(a):\n   ...     return a\n   \u003e\u003e\u003e assert match.end == 'python'\n\n\n   \u003e\u003e\u003e # with datatype\n\n   \u003e\u003e\u003e from masala.datatype import Right, Left\n\n   \u003e\u003e\u003e match = Match(Either.right('python'))\n   \u003e\u003e\u003e @match.when(Right)\n   ... def case_right(v):\n   ...     return v + ' is right!'\n   \u003e\u003e\u003e @match.when(Left)\n   ... def case_left(v):\n   ...     assert False\n   \u003e\u003e\u003e assert match.end == 'python is right!'\n\n\n\ncall method with optional values\n-----------------------------------------------------------------\n\n.. code-block:: python\n\n   \u003e\u003e\u003e from masala import Perhaps\n\n   \u003e\u003e\u003e p = Perhaps('hoge huga foo')\n   \u003e\u003e\u003e p._.replace('huga', 'muoo')._.upper().get()\n   'HOGE MUOO FOO'\n   \u003e\u003e\u003e p \u003e\u003e (lambda st: len(st))\n   13\n\n   \u003e\u003e\u003e nonecase = Perhaps(None)._.replace('huga', 'muoo')._.upper()\n   \u003e\u003e\u003e nonecase.get()\n\n   \u003e\u003e\u003e nonecase.get_or('nnnnn')\n   'nnnnn'\n\n\nSupport\n=================================================================\n\ntested version of Python is\n\n- 2.7\n- 3.4\n\n\nLICENCE\n=================================================================\n\nMIT\n\nAuthor\n=================================================================\n\n`OGURA_Daiki \u003chttps://github.com/hachibeeDI\u003e`_\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhachibeedi%2Fmasala","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhachibeedi%2Fmasala","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhachibeedi%2Fmasala/lists"}