useful-decorators


Nameuseful-decorators JSON
Version 0.0.3 PyPI version JSON
download
home_pageNone
SummarySome decorators for Python
upload_time2023-01-13 16:38:22
maintainerNone
docs_urlNone
authorNone
requires_python>=3.6
licenseNone
keywords decorator python extensions
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # UsefulDecorators
> Some Decorators I use for various purposes. Some more useful, some less.

This is a collection of some Decorators for Python you might find useful.
```
pip install usefull-decorators
```
## Programming Patterns

### Cache
The Cache Decorator will automatically cache the creation of an object of the decorated class. 
```py
from useful_decorators.patterns import Cache

def disable():
    return True

@Cache(disable=disable)
class Test:
  def __init__(self,q,p=False):
    self.q = q
    self.p = p
 
q1 = Test("test",True) #Create a new Object
q2 = Test("test",True) #This will return the SAME object form the cache
q3 = Test("test2") #This will create a new Object.
```

On each call of an `__init__` method, 
the cache will check if there ever was another call that used the same arguments, and if yes return that. If you really want a new Object ( ignore the cache )
you can use `<class>.__create_no_cache()` with the arguments you would usually pass to the `__init__` method. You can also reset the cache with `<class>.__clear_cache()`
You can also use the 'disable' property of the decorator. This allows you to specify a function which is called to check if the cache is enabled or disabled.
```py
Test.__create_no_cache("hello",True) #Always creates a new Object (will not be added to the cache)
#or
Test.__clear_cache()
Test("hello",True)
```
Note that cached objects are the __same__. If you change an attribute on one of the objects, the other will change too. In the example above changing
something in `q1` will also change `q2`. 
### Singleton
The Singleton decorator will change the class to only ever create one instance. This is done by injecting code in the `__init__` method which checks if an 
object of the class is already created. 
```py
from useful_decorators.patterns import Singleton

@Singleton(strict=False)
class Test:
    def __init__(self, q, p=False):
        self.q = q
        self.p = p


q1 = Test("test", True)  # Creates a new Object
q2 = Test("test", True)  # This is the same object as q1
q3 = Test("test2")  # If strict is disabled, this is ALSO the same objects as q1
```
There are basically two methods to handle calls to the `__init__` method after the original object was created. We can ignore the call no matter the arguments 
and return the singleton in all cases (default) or we can raise an error. 
It is __always__ better to use another method to get the instance because it is clearer to everybody who reads the code. So after you create an instance you can do the following
```py
q2 = Test.getInstance()
```
Which returns the instance. This is the only way when strict is set to true to obtain an instance. If strict is set to false, you can overwrite the current instance by using
```py
Test.resetInstance()
Test("hi",True)
#OR
Test.createNew("hi",True)
```
`createNew` is just a shortcut to reset and create at the same time.
### Observable
The Observable decorator allows to attach function calls to changes in the fields of the class.
```py
from useful_decorators.patterns import Observable

def changeling(q):
    print(q)


@Observable(attach=[("q", changeling)]) #Now changeling gets called with the new value everytime a new value is assigned to the field named 'q'
class Test:
    def __init__(self, q, p=False):
        self.q = q
        self.p = p


q1 = Test("hello")
q1.q = "world" #changeling gets called with 'world'
```
The decorator expects a list of tuples as the `attach` keyword. Each tuple must contain a name of a field in the class, and a method to call. 
This method must take exactly ONE argument (the updated value).
Currently, there is no function call if the field gets deleted with `del`.
### builder_function
The builder_function decorator is just a shortcut for a method returning the object it belongs to. So instead of
```py
class Test:
    def __init__(self):
        self.q = None
        self.p = None
        
    def set_q(self,q):
        self.q = q
        return self
```
you can write
```py
from useful_decorators.patterns import builder_function

class Test:
    def __init__(self):
        self.q = None
        self.p = None
        
    @builder_function    
    def set_q(self,q):
        self.q = q
```
This allows for easy construction of Objects that can be used like this `obj.setx(x).create_q(q,v=True)....`
## Functions
This repo provides some decorators for functions in general.
### infix
This decorator allows you to make a function (which takes two arguments) into an infix operator.
Your function name has to be surrounded by '|'.
```py
from useful_decorators.functions import infix
@infix
def test(q1, q2):
    return q1 + 2 * q2


print("Hello" | test | "World" | test | "1")
```
### attach
This decorator allows you to attach another function to the decorated function.
```py
from useful_decorators.functions import attach

def attached(q=1):
  print("world"*q)
 
@attach(attached)
def foo():
  print("hello")
 
foo() # hello world
```
You can also specify the arguments that shall be passed to the attached function like so
```py
from useful_decorators.functions import attach

def attached(q=1):
  print("world"*q)
 
@attach(attached,q=2)
def foo():
  print("hello")
 
foo() # hello worldworld
```
Of course, you can attach multiple methods as well. Just add more `@attach` decorators.
### prepend
this is _exactly_ the same as __attach__ but will execute the specified method __before__ the original method.
### chain
the chain decorator allows for chaining functions together and feeding ones output in another ones input. 
```py
from useful_decorators.functions import chain

def q1(q,h=2):
  print(q*h)

@chain(q1)
def q2(q):
  return q+1
  
@chain(q1,3) #same as @chain(q1,h=3)
def q3(q):
  return q+1
  
q2(1) # 4 because (1+1)*2 = 4
q3(1) # 6 because (1+1)*3 = 6
```
The input is always the FIRST argument of the chained function. The function with the decorator is always evaluated first and then fed into the function which is 
mentioned in the decorator. Of course the chain can be as long as you want.


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "useful-decorators",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": null,
    "keywords": "decorator,python,extensions",
    "author": null,
    "author_email": "Jannes M\u00fclller <jannes@mlrjs.de>",
    "download_url": "https://files.pythonhosted.org/packages/7f/0c/50cb11e8905b3c29ab00eea106a67c33376f8a85c00381236f8f5663ca72/useful-decorators-0.0.3.tar.gz",
    "platform": null,
    "description": "# UsefulDecorators\n> Some Decorators I use for various purposes. Some more useful, some less.\n\nThis is a collection of some Decorators for Python you might find useful.\n```\npip install usefull-decorators\n```\n## Programming Patterns\n\n### Cache\nThe Cache Decorator will automatically cache the creation of an object of the decorated class. \n```py\nfrom useful_decorators.patterns import Cache\n\ndef disable():\n    return True\n\n@Cache(disable=disable)\nclass Test:\n  def __init__(self,q,p=False):\n    self.q = q\n    self.p = p\n \nq1 = Test(\"test\",True) #Create a new Object\nq2 = Test(\"test\",True) #This will return the SAME object form the cache\nq3 = Test(\"test2\") #This will create a new Object.\n```\n\nOn each call of an `__init__` method, \nthe cache will check if there ever was another call that used the same arguments, and if yes return that. If you really want a new Object ( ignore the cache )\nyou can use `<class>.__create_no_cache()` with the arguments you would usually pass to the `__init__` method. You can also reset the cache with `<class>.__clear_cache()`\nYou can also use the 'disable' property of the decorator. This allows you to specify a function which is called to check if the cache is enabled or disabled.\n```py\nTest.__create_no_cache(\"hello\",True) #Always creates a new Object (will not be added to the cache)\n#or\nTest.__clear_cache()\nTest(\"hello\",True)\n```\nNote that cached objects are the __same__. If you change an attribute on one of the objects, the other will change too. In the example above changing\nsomething in `q1` will also change `q2`. \n### Singleton\nThe Singleton decorator will change the class to only ever create one instance. This is done by injecting code in the `__init__` method which checks if an \nobject of the class is already created. \n```py\nfrom useful_decorators.patterns import Singleton\n\n@Singleton(strict=False)\nclass Test:\n    def __init__(self, q, p=False):\n        self.q = q\n        self.p = p\n\n\nq1 = Test(\"test\", True)  # Creates a new Object\nq2 = Test(\"test\", True)  # This is the same object as q1\nq3 = Test(\"test2\")  # If strict is disabled, this is ALSO the same objects as q1\n```\nThere are basically two methods to handle calls to the `__init__` method after the original object was created. We can ignore the call no matter the arguments \nand return the singleton in all cases (default) or we can raise an error. \nIt is __always__ better to use another method to get the instance because it is clearer to everybody who reads the code. So after you create an instance you can do the following\n```py\nq2 = Test.getInstance()\n```\nWhich returns the instance. This is the only way when strict is set to true to obtain an instance. If strict is set to false, you can overwrite the current instance by using\n```py\nTest.resetInstance()\nTest(\"hi\",True)\n#OR\nTest.createNew(\"hi\",True)\n```\n`createNew` is just a shortcut to reset and create at the same time.\n### Observable\nThe Observable decorator allows to attach function calls to changes in the fields of the class.\n```py\nfrom useful_decorators.patterns import Observable\n\ndef changeling(q):\n    print(q)\n\n\n@Observable(attach=[(\"q\", changeling)]) #Now changeling gets called with the new value everytime a new value is assigned to the field named 'q'\nclass Test:\n    def __init__(self, q, p=False):\n        self.q = q\n        self.p = p\n\n\nq1 = Test(\"hello\")\nq1.q = \"world\" #changeling gets called with 'world'\n```\nThe decorator expects a list of tuples as the `attach` keyword. Each tuple must contain a name of a field in the class, and a method to call. \nThis method must take exactly ONE argument (the updated value).\nCurrently, there is no function call if the field gets deleted with `del`.\n### builder_function\nThe builder_function decorator is just a shortcut for a method returning the object it belongs to. So instead of\n```py\nclass Test:\n    def __init__(self):\n        self.q = None\n        self.p = None\n        \n    def set_q(self,q):\n        self.q = q\n        return self\n```\nyou can write\n```py\nfrom useful_decorators.patterns import builder_function\n\nclass Test:\n    def __init__(self):\n        self.q = None\n        self.p = None\n        \n    @builder_function    \n    def set_q(self,q):\n        self.q = q\n```\nThis allows for easy construction of Objects that can be used like this `obj.setx(x).create_q(q,v=True)....`\n## Functions\nThis repo provides some decorators for functions in general.\n### infix\nThis decorator allows you to make a function (which takes two arguments) into an infix operator.\nYour function name has to be surrounded by '|'.\n```py\nfrom useful_decorators.functions import infix\n@infix\ndef test(q1, q2):\n    return q1 + 2 * q2\n\n\nprint(\"Hello\" | test | \"World\" | test | \"1\")\n```\n### attach\nThis decorator allows you to attach another function to the decorated function.\n```py\nfrom useful_decorators.functions import attach\n\ndef attached(q=1):\n  print(\"world\"*q)\n \n@attach(attached)\ndef foo():\n  print(\"hello\")\n \nfoo() # hello world\n```\nYou can also specify the arguments that shall be passed to the attached function like so\n```py\nfrom useful_decorators.functions import attach\n\ndef attached(q=1):\n  print(\"world\"*q)\n \n@attach(attached,q=2)\ndef foo():\n  print(\"hello\")\n \nfoo() # hello worldworld\n```\nOf course, you can attach multiple methods as well. Just add more `@attach` decorators.\n### prepend\nthis is _exactly_ the same as __attach__ but will execute the specified method __before__ the original method.\n### chain\nthe chain decorator allows for chaining functions together and feeding ones output in another ones input. \n```py\nfrom useful_decorators.functions import chain\n\ndef q1(q,h=2):\n  print(q*h)\n\n@chain(q1)\ndef q2(q):\n  return q+1\n  \n@chain(q1,3) #same as @chain(q1,h=3)\ndef q3(q):\n  return q+1\n  \nq2(1) # 4 because (1+1)*2 = 4\nq3(1) # 6 because (1+1)*3 = 6\n```\nThe input is always the FIRST argument of the chained function. The function with the decorator is always evaluated first and then fed into the function which is \nmentioned in the decorator. Of course the chain can be as long as you want.\n\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Some decorators for Python",
    "version": "0.0.3",
    "split_keywords": [
        "decorator",
        "python",
        "extensions"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d839c16597fe457f1d4b9efac0f06f425351d3a3566fa5d7ed7905e430391754",
                "md5": "ee9ef98bf28142e92504e571f0cb1f06",
                "sha256": "f75eb744f1896420f27b34458c38c151c338a301bca4499422f646550d387576"
            },
            "downloads": -1,
            "filename": "useful_decorators-0.0.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "ee9ef98bf28142e92504e571f0cb1f06",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 6869,
            "upload_time": "2023-01-13T16:38:14",
            "upload_time_iso_8601": "2023-01-13T16:38:14.318502Z",
            "url": "https://files.pythonhosted.org/packages/d8/39/c16597fe457f1d4b9efac0f06f425351d3a3566fa5d7ed7905e430391754/useful_decorators-0.0.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "7f0c50cb11e8905b3c29ab00eea106a67c33376f8a85c00381236f8f5663ca72",
                "md5": "a8bbcc6edee3f9d8f1c32776885ace1b",
                "sha256": "5f890128bfbd1439062144cd03cc162d68131d9600195e853ae021d2bcc25f94"
            },
            "downloads": -1,
            "filename": "useful-decorators-0.0.3.tar.gz",
            "has_sig": false,
            "md5_digest": "a8bbcc6edee3f9d8f1c32776885ace1b",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6",
            "size": 6008,
            "upload_time": "2023-01-13T16:38:22",
            "upload_time_iso_8601": "2023-01-13T16:38:22.243036Z",
            "url": "https://files.pythonhosted.org/packages/7f/0c/50cb11e8905b3c29ab00eea106a67c33376f8a85c00381236f8f5663ca72/useful-decorators-0.0.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-01-13 16:38:22",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "lcname": "useful-decorators"
}
        
Elapsed time: 0.03174s