implicit-globals


Nameimplicit-globals JSON
Version 1.0.1 PyPI version JSON
download
home_pagehttps://github.com/sebdevine/implicit_globals
SummaryA decorator that provides a way to override a function's global variables
upload_time2023-06-03 13:49:45
maintainer
docs_urlNone
authorSebastien Devine
requires_python>=3.6
licenseMIT
keywords implicit globals decorator functional
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI
coveralls test coverage
            # implicit-globals
[![Build Status](https://travis-ci.com/sebdevine/implicit_globals.svg?branch=master)](https://travis-ci.com/sebdevine/implicit_globals)
[![codecov](https://codecov.io/gh/sebdevine/implicit_globals/branch/master/graph/badge.svg)](https://codecov.io/gh/sebdevine/implicit_globals)
[![PyPI license](https://img.shields.io/pypi/l/implicit-globals.svg)](https://pypi.python.org/pypi/implicit-globals/)
[![PyPI version shields.io](https://img.shields.io/pypi/v/implicit-globals.svg)](https://pypi.python.org/pypi/implicit-globals/)
[![PyPI pyversions](https://img.shields.io/pypi/pyversions/implicit-globals.svg)](https://pypi.python.org/pypi/implicit-globals/)


**TL;DR: A Python decorator that allow you to modify at runtime a function's 
implicit global variables or default variables.**

## Goals
The _implicit_ adjective refers to all variables that are not explicit to a function call,
either from the function (or method) 's global variables or any parameter with a default value.
It is heavily inspired from Scala's own implicit types, but obviously not the same, Scala solves implicitly at compile time.

Using "pure" functions is not always possible, using an external variable/function is
quite easy in Python, but then when it comes to changing those dependencies, it is quite difficult:
think about testing, dependency injection, etc. So people often resort to "objects" as an easy way to override things, class attributes/methods replace global variables/functions. This way can make the code quite complex as `self` becomes the global repository with overrides all over the place.

The idea is to keep some sort of "functional approach" but keep things manageable with an explicit "global' memory" that manipulates global variables without changing the function's call graph.
And also without resorting on the "heavy artillery" of functional programming patterns.

The main issue of this approach is to know in advance which are the global variables used and their
type. Obviously Python duck typing makes things easier, but still we cannot statically know
the dependencies in advances, so there is no check and control over the overrides.

## Install
```
pip install implicit-globals
```

## Usage

You can use either :
- The default decorator `implicit`, **but beware, then all functions 
decorated will share the same overrides !** 
- Or you can create your own local decorator using the class `ImplicitGlobals` : `my_implicit_decorator = ImplicitGlobals()`

The instances of `ImplicitGlobals` act like a mutable `dict` where the global names and their values can be set. 

Please note that :
- It is developed & tested on Python 3.6+, no older versions support.
- It is not thread-safe (concurent changes can lead to unexpect behaviour)
- It does not support (yet) coroutines
- Only decorated functions can be changed, others are left untouched.  

```python
import sys
#Use the default decorator
from implicit_globals import implicit


AAA = "FRE"


def load():
    return "Hello"


@implicit
def foo(a, b, c=1, *, d=None):
    print("foo : ", a, b, c, d, AAA, load())


@implicit
def bar(a, b):
    print("bar : ", a, b, AAA)
    foo(a, b)


@implicit
def qux(a, b=4):
    print("qux : ", a, b, AAA)
    bar(a, b)


class Foo:

    @implicit
    def toto(self, a, b):
        print('TOTO: ', a, b)
        bar(a, b)


qux(3, 4)
# qux :  3 4 FRE
# bar :  3 4 FRE
# foo :  3 4 1 None FRE Hello

implicit["AAA"] = "BAZ"
implicit["print"] = lambda *_: sys.stdout.write("YO-- " + ', '.join(map(str, _)) + '\n')
implicit["load"] = lambda: "New Hello"
implicit["d"] = 333

qux(3, 4)
# YO-- qux : , 3, 4, BAZ
# YO-- bar : , 3, 4, BAZ
# YO-- foo : , 3, 4, 1, 333, BAZ, New Hello

Foo().toto(7, 8)
# YO-- TOTO: , 7, 8
# YO-- bar : , 7, 8, BAZ
# YO-- foo : , 7, 8, 1, 333, BAZ, New Hello

del implicit["AAA"]
foo(4, 5)
# YO-- foo : , 4, 5, 1, 333, FRE, New Hello
```

## Development / Testing
To install local a development version :
```
pip install -e .
```

To launch the tests, you will need `pytest` :
```
pytest test_implicit_globals.py
```

To build and deploy, you will need these packages : `wheel`, `twine`, `setuptools`
```
python setup.py bdist_wheel
python -m twine upload --repository pypi dist/*
```



            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/sebdevine/implicit_globals",
    "name": "implicit-globals",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": "",
    "keywords": "implicit globals decorator functional",
    "author": "Sebastien Devine",
    "author_email": "sebdevine@users.noreply.github.com",
    "download_url": "",
    "platform": null,
    "description": "# implicit-globals\n[![Build Status](https://travis-ci.com/sebdevine/implicit_globals.svg?branch=master)](https://travis-ci.com/sebdevine/implicit_globals)\n[![codecov](https://codecov.io/gh/sebdevine/implicit_globals/branch/master/graph/badge.svg)](https://codecov.io/gh/sebdevine/implicit_globals)\n[![PyPI license](https://img.shields.io/pypi/l/implicit-globals.svg)](https://pypi.python.org/pypi/implicit-globals/)\n[![PyPI version shields.io](https://img.shields.io/pypi/v/implicit-globals.svg)](https://pypi.python.org/pypi/implicit-globals/)\n[![PyPI pyversions](https://img.shields.io/pypi/pyversions/implicit-globals.svg)](https://pypi.python.org/pypi/implicit-globals/)\n\n\n**TL;DR: A Python decorator that allow you to modify at runtime a function's \nimplicit global variables or default variables.**\n\n## Goals\nThe _implicit_ adjective refers to all variables that are not explicit to a function call,\neither from the function (or method) 's global variables or any parameter with a default value.\nIt is heavily inspired from Scala's own implicit types, but obviously not the same, Scala solves implicitly at compile time.\n\nUsing \"pure\" functions is not always possible, using an external variable/function is\nquite easy in Python, but then when it comes to changing those dependencies, it is quite difficult:\nthink about testing, dependency injection, etc. So people often resort to \"objects\" as an easy way to override things, class attributes/methods replace global variables/functions. This way can make the code quite complex as `self` becomes the global repository with overrides all over the place.\n\nThe idea is to keep some sort of \"functional approach\" but keep things manageable with an explicit \"global' memory\" that manipulates global variables without changing the function's call graph.\nAnd also without resorting on the \"heavy artillery\" of functional programming patterns.\n\nThe main issue of this approach is to know in advance which are the global variables used and their\ntype. Obviously Python duck typing makes things easier, but still we cannot statically know\nthe dependencies in advances, so there is no check and control over the overrides.\n\n## Install\n```\npip install implicit-globals\n```\n\n## Usage\n\nYou can use either :\n- The default decorator `implicit`, **but beware, then all functions \ndecorated will share the same overrides !** \n- Or you can create your own local decorator using the class `ImplicitGlobals` : `my_implicit_decorator = ImplicitGlobals()`\n\nThe instances of `ImplicitGlobals` act like a mutable `dict` where the global names and their values can be set. \n\nPlease note that :\n- It is developed & tested on Python 3.6+, no older versions support.\n- It is not thread-safe (concurent changes can lead to unexpect behaviour)\n- It does not support (yet) coroutines\n- Only decorated functions can be changed, others are left untouched.  \n\n```python\nimport sys\n#Use the default decorator\nfrom implicit_globals import implicit\n\n\nAAA = \"FRE\"\n\n\ndef load():\n    return \"Hello\"\n\n\n@implicit\ndef foo(a, b, c=1, *, d=None):\n    print(\"foo : \", a, b, c, d, AAA, load())\n\n\n@implicit\ndef bar(a, b):\n    print(\"bar : \", a, b, AAA)\n    foo(a, b)\n\n\n@implicit\ndef qux(a, b=4):\n    print(\"qux : \", a, b, AAA)\n    bar(a, b)\n\n\nclass Foo:\n\n    @implicit\n    def toto(self, a, b):\n        print('TOTO: ', a, b)\n        bar(a, b)\n\n\nqux(3, 4)\n# qux :  3 4 FRE\n# bar :  3 4 FRE\n# foo :  3 4 1 None FRE Hello\n\nimplicit[\"AAA\"] = \"BAZ\"\nimplicit[\"print\"] = lambda *_: sys.stdout.write(\"YO-- \" + ', '.join(map(str, _)) + '\\n')\nimplicit[\"load\"] = lambda: \"New Hello\"\nimplicit[\"d\"] = 333\n\nqux(3, 4)\n# YO-- qux : , 3, 4, BAZ\n# YO-- bar : , 3, 4, BAZ\n# YO-- foo : , 3, 4, 1, 333, BAZ, New Hello\n\nFoo().toto(7, 8)\n# YO-- TOTO: , 7, 8\n# YO-- bar : , 7, 8, BAZ\n# YO-- foo : , 7, 8, 1, 333, BAZ, New Hello\n\ndel implicit[\"AAA\"]\nfoo(4, 5)\n# YO-- foo : , 4, 5, 1, 333, FRE, New Hello\n```\n\n## Development / Testing\nTo install local a development version :\n```\npip install -e .\n```\n\nTo launch the tests, you will need `pytest` :\n```\npytest test_implicit_globals.py\n```\n\nTo build and deploy, you will need these packages : `wheel`, `twine`, `setuptools`\n```\npython setup.py bdist_wheel\npython -m twine upload --repository pypi dist/*\n```\n\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A decorator that provides a way to override a function's global variables",
    "version": "1.0.1",
    "project_urls": {
        "Homepage": "https://github.com/sebdevine/implicit_globals"
    },
    "split_keywords": [
        "implicit",
        "globals",
        "decorator",
        "functional"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "2af965248fb5bef0cc3bcc7c6d3d5538a71d554d90109b558f04823d490b4f1c",
                "md5": "bb41ef4d5a51fb5cb17bbac4aec62013",
                "sha256": "51e50e2262efe460d6acd92bd70a2113382cd57e63e91339d03327ef08c003d1"
            },
            "downloads": -1,
            "filename": "implicit_globals-1.0.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "bb41ef4d5a51fb5cb17bbac4aec62013",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 6451,
            "upload_time": "2023-06-03T13:49:45",
            "upload_time_iso_8601": "2023-06-03T13:49:45.529731Z",
            "url": "https://files.pythonhosted.org/packages/2a/f9/65248fb5bef0cc3bcc7c6d3d5538a71d554d90109b558f04823d490b4f1c/implicit_globals-1.0.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-06-03 13:49:45",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "sebdevine",
    "github_project": "implicit_globals",
    "travis_ci": true,
    "coveralls": true,
    "github_actions": false,
    "lcname": "implicit-globals"
}
        
Elapsed time: 0.08880s