pyiron-snippets


Namepyiron-snippets JSON
Version 0.1.4 PyPI version JSON
download
home_pageNone
Summarypyiron_snippets - Short, dependency-free python snippets.
upload_time2024-08-08 03:51:00
maintainerNone
docs_urlNone
authorNone
requires_python<3.13,>=3.9
licenseBSD 3-Clause License Copyright (c) 2024, Max-Planck-Institut für Nachhaltige Materialien GmbH - Computational Materials Design (CM) Department All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
keywords pyiron
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage
            [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/pyiron/pyiron_snippets/HEAD)
[![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
[![Coverage Status](https://coveralls.io/repos/github/pyiron/pyiron_snippets/badge.svg?branch=main)](https://coveralls.io/github/pyiron/pyiron_snippets?branch=main)
[![Documentation Status](https://readthedocs.org/projects/pyiron-snippets/badge/?version=latest)](https://pyiron-snippets.readthedocs.io/en/latest/?badge=latest)

[![Anaconda](https://anaconda.org/conda-forge/pyiron_snippets/badges/version.svg)](https://anaconda.org/conda-forge/pyiron_snippets)
[![Last Updated](https://anaconda.org/conda-forge/pyiron_snippets/badges/latest_release_date.svg
)](https://anaconda.org/conda-forge/pyiron_snippets)
[![Platform](https://anaconda.org/conda-forge/pyiron_snippets/badges/platforms.svg)](https://anaconda.org/conda-forge/pyiron_snippets)
[![Downloads](https://anaconda.org/conda-forge/pyiron_snippets/badges/downloads.svg)](https://anaconda.org/conda-forge/pyiron_snippets)

# pyiron_snippets

This is a collection of independent python snippets which we in the pyiron project find generically useful.

To qualify for inclusion, a snippet must not have any dependencies outside the python standard library, and should fit reasonably inside a single file.

(Note that the _tests_ may have non-standard dependencies, e.g. to ensure the snippets work in various edge cases we care about, but the actual snippets themselves must be able to behave well in a clean environment.)


# Summary

The snippets may have more functionality that this -- taking a look at the test suite is the best way to get an exhaustive sense of their functionality -- but these examples will give you the gist of things.

## Colors

Just a shortcut to the `seaborn.color_palette()` of colors in hex:

```python
>>> from pyiron_snippets.colors import SeabornColors
>>> SeabornColors.white
'#ffffff'

```

## Deprecate

Easily indicate that some functionality is being deprecated

```python
>>> from pyiron_snippets.deprecate import deprecate
>>>
>>> @deprecate(message="Use `bar(a, b)` instead", version="0.5.0")
... def foo(a, b):
...     pass
>>> 
>>> foo(1, 2)

```

Raises a warning like `DeprecationWarning: __main__.foo is deprecated: Use bar(a, b) instead. It is not guaranteed to be in service in vers. 0.5.0 foo(1, 2)`


## DotDict

A dictionary that allows dot-access. Has `.items()` etc.

```python
>>> from pyiron_snippets.dotdict import DotDict
>>>
>>> d = DotDict({"a": 1})
>>> d.b = 2
>>> print(d.a, d.b)
1 2

```

## Factory

Make dynamic classes that are still pickle-able

```python
>>> from abc import ABC
>>> import pickle
>>>
>>> from pyiron_snippets.factory import classfactory
>>>
>>> class HasN(ABC):
...     '''Some class I want to make dynamically subclass.'''
...     def __init_subclass__(cls, /, n=0, s="foo", **kwargs):
...         super(HasN, cls).__init_subclass__(**kwargs)
...         cls.n = n
...         cls.s = s
...
...     def __init__(self, x, y=0):
...         self.x = x
...         self.y = y
>>>
>>> @classfactory
... def has_n_factory(n, s="wrapped_function", /):
...     return (
...         f"{HasN.__name__}{n}{s}",  # New class name
...         (HasN, ),  # Base class(es)
...         {},  # Class attributes dictionary
...         {"n": n, "s": s}
...  # dict of `builtins.type` kwargs (passed to `__init_subclass__`)
...     )
>>>
>>> Has2 = has_n_factory(2, "my_dynamic_class")
>>>
>>> foo = Has2(42, y=-1)
>>> print(foo.n, foo.s, foo.x, foo.y)
2 my_dynamic_class 42 -1
>>> reloaded = pickle.loads(pickle.dumps(foo))  # doctest: +SKIP
>>> print(reloaded.n, reloaded.s, reloaded.x, reloaded.y)  # doctest: +SKIP
2 my_dynamic_class 42 -1  # doctest: +SKIP

```

(Pickle doesn't play well with testing the docs -- you can't run `pickle.dumps(pickle.loads(5))` either!)


## Files

Shortcuts for filesystem manipulation

```python
>>> from pyiron_snippets.files import DirectoryObject, FileObject
>>>
>>> d = DirectoryObject("some_dir")
>>> d.write(file_name="my_filename.txt", content="Some content")
>>> f = FileObject("my_filename.txt", directory=d)
>>> f.is_file()
True
>>> f2 = f.copy("new_filename.txt", directory=d.create_subdirectory("sub"))
>>> f2.read()
'Some content'
>>> d.file_exists("sub/new_filename.txt")
True
>>> d.delete()

```


## Has post

A meta-class introducing a `__post__` dunder which runs after the `__init__` of _everything_ in the MRO.

```python
>>> from pyiron_snippets.has_post import HasPost
>>>
>>> class Foo(metaclass=HasPost):
...     def __init__(self, x=0):
...         self.x = x
...         print(f"Foo.__init__: x = {self.x}")
>>>
>>> class Bar(Foo):
...     def __init__(self, x=0, post_extra=2):
...         super().__init__(x)
...         self.x += 1
...         print(f"Bar.__init__: x = {self.x}")
...
...     def __post__(self, *args, post_extra=2, **kwargs):
...         self.x += post_extra
...         print(f"Bar.__post__: x = {self.x}")
>>>
>>> Bar().x
Foo.__init__: x = 0
Bar.__init__: x = 1
Bar.__post__: x = 3
3

```

Honestly, try thinking if there's another way to solve your problem; this is a dark magic.

## Import alarm

Fail gracefully when optional dependencies are missing for (optional) functionality.

```python
>>> from pyiron_snippets.import_alarm import ImportAlarm
>>>
>>> with ImportAlarm(
...     "Some functionality unavailable: `magic` dependency missing"
... ) as my_magic_alarm:
...     import magic
>>>
>>> with ImportAlarm("This warning won't show up") as datetime_alarm:
...     import datetime
>>>
>>> class Foo:
...     @my_magic_alarm
...     @datetime_alarm
...     def __init__(self, x):
...         self.x = x
...
...     @property
...     def magical(self):
...         return magic.method(self.x)
...
...     def a_space_odyssey(self):
...         print(datetime.date(2001, 1, 1))
>>>
>>> foo = Foo(0)
>>>  # Raises a warning re `magic` (since that does not exist)
>>>  # but not re `datetime` (since it does and we certainly have it)
>>> foo.a_space_odyssey()
2001-01-01

>>> try:
...     foo.magical(0)
... except NameError as e:
...     print("ERROR:", e)
ERROR: name 'magic' is not defined

```

## Logger

Configures the logger and writes to `pyiron.log`

## Retry

If at first you don't succeed

```python
>>> from time import time
>>>
>>> from pyiron_snippets.retry import retry
>>>
>>> def at_most_three_seconds():
...     t = int(time())
...     if t % 3 != 0:
...         raise ValueError("Not yet!")
...     return t
>>>
>>> retry(at_most_three_seconds, msg="Tried and failed...", error=ValueError) % 3
0

```

Depending on the system clock at invokation, this simple example may give warnings like `UserWarning: Tried and failed... Trying again in 1.0s. Tried 1 times so far...` up to two times.


## Singleton

A metaclass for the [singleton pattern](https://en.wikipedia.org/wiki/Singleton_pattern).

```python
>>> from pyiron_snippets.singleton import Singleton
>>>
>>> class Foo(metaclass=Singleton):
...     pass
>>>
>>> foo1 = Foo()
>>> foo2 = Foo()
>>> foo1 is foo2
True

```

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "pyiron-snippets",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<3.13,>=3.9",
    "maintainer_email": null,
    "keywords": "pyiron",
    "author": null,
    "author_email": "Liam Huber <liamhuber@greyhavensolutions.com>, Sam Waseda <o.waseda@mpie.de>",
    "download_url": "https://files.pythonhosted.org/packages/b9/9a/5305c2959dbb9104e7fc8b02df4de4159395d9ca28184df9e7a28cd5189e/pyiron_snippets-0.1.4.tar.gz",
    "platform": null,
    "description": "[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/pyiron/pyiron_snippets/HEAD)\n[![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)\n[![Coverage Status](https://coveralls.io/repos/github/pyiron/pyiron_snippets/badge.svg?branch=main)](https://coveralls.io/github/pyiron/pyiron_snippets?branch=main)\n[![Documentation Status](https://readthedocs.org/projects/pyiron-snippets/badge/?version=latest)](https://pyiron-snippets.readthedocs.io/en/latest/?badge=latest)\n\n[![Anaconda](https://anaconda.org/conda-forge/pyiron_snippets/badges/version.svg)](https://anaconda.org/conda-forge/pyiron_snippets)\n[![Last Updated](https://anaconda.org/conda-forge/pyiron_snippets/badges/latest_release_date.svg\n)](https://anaconda.org/conda-forge/pyiron_snippets)\n[![Platform](https://anaconda.org/conda-forge/pyiron_snippets/badges/platforms.svg)](https://anaconda.org/conda-forge/pyiron_snippets)\n[![Downloads](https://anaconda.org/conda-forge/pyiron_snippets/badges/downloads.svg)](https://anaconda.org/conda-forge/pyiron_snippets)\n\n# pyiron_snippets\n\nThis is a collection of independent python snippets which we in the pyiron project find generically useful.\n\nTo qualify for inclusion, a snippet must not have any dependencies outside the python standard library, and should fit reasonably inside a single file.\n\n(Note that the _tests_ may have non-standard dependencies, e.g. to ensure the snippets work in various edge cases we care about, but the actual snippets themselves must be able to behave well in a clean environment.)\n\n\n# Summary\n\nThe snippets may have more functionality that this -- taking a look at the test suite is the best way to get an exhaustive sense of their functionality -- but these examples will give you the gist of things.\n\n## Colors\n\nJust a shortcut to the `seaborn.color_palette()` of colors in hex:\n\n```python\n>>> from pyiron_snippets.colors import SeabornColors\n>>> SeabornColors.white\n'#ffffff'\n\n```\n\n## Deprecate\n\nEasily indicate that some functionality is being deprecated\n\n```python\n>>> from pyiron_snippets.deprecate import deprecate\n>>>\n>>> @deprecate(message=\"Use `bar(a, b)` instead\", version=\"0.5.0\")\n... def foo(a, b):\n...     pass\n>>> \n>>> foo(1, 2)\n\n```\n\nRaises a warning like `DeprecationWarning: __main__.foo is deprecated: Use bar(a, b) instead. It is not guaranteed to be in service in vers. 0.5.0 foo(1, 2)`\n\n\n## DotDict\n\nA dictionary that allows dot-access. Has `.items()` etc.\n\n```python\n>>> from pyiron_snippets.dotdict import DotDict\n>>>\n>>> d = DotDict({\"a\": 1})\n>>> d.b = 2\n>>> print(d.a, d.b)\n1 2\n\n```\n\n## Factory\n\nMake dynamic classes that are still pickle-able\n\n```python\n>>> from abc import ABC\n>>> import pickle\n>>>\n>>> from pyiron_snippets.factory import classfactory\n>>>\n>>> class HasN(ABC):\n...     '''Some class I want to make dynamically subclass.'''\n...     def __init_subclass__(cls, /, n=0, s=\"foo\", **kwargs):\n...         super(HasN, cls).__init_subclass__(**kwargs)\n...         cls.n = n\n...         cls.s = s\n...\n...     def __init__(self, x, y=0):\n...         self.x = x\n...         self.y = y\n>>>\n>>> @classfactory\n... def has_n_factory(n, s=\"wrapped_function\", /):\n...     return (\n...         f\"{HasN.__name__}{n}{s}\",  # New class name\n...         (HasN, ),  # Base class(es)\n...         {},  # Class attributes dictionary\n...         {\"n\": n, \"s\": s}\n...  # dict of `builtins.type` kwargs (passed to `__init_subclass__`)\n...     )\n>>>\n>>> Has2 = has_n_factory(2, \"my_dynamic_class\")\n>>>\n>>> foo = Has2(42, y=-1)\n>>> print(foo.n, foo.s, foo.x, foo.y)\n2 my_dynamic_class 42 -1\n>>> reloaded = pickle.loads(pickle.dumps(foo))  # doctest: +SKIP\n>>> print(reloaded.n, reloaded.s, reloaded.x, reloaded.y)  # doctest: +SKIP\n2 my_dynamic_class 42 -1  # doctest: +SKIP\n\n```\n\n(Pickle doesn't play well with testing the docs -- you can't run `pickle.dumps(pickle.loads(5))` either!)\n\n\n## Files\n\nShortcuts for filesystem manipulation\n\n```python\n>>> from pyiron_snippets.files import DirectoryObject, FileObject\n>>>\n>>> d = DirectoryObject(\"some_dir\")\n>>> d.write(file_name=\"my_filename.txt\", content=\"Some content\")\n>>> f = FileObject(\"my_filename.txt\", directory=d)\n>>> f.is_file()\nTrue\n>>> f2 = f.copy(\"new_filename.txt\", directory=d.create_subdirectory(\"sub\"))\n>>> f2.read()\n'Some content'\n>>> d.file_exists(\"sub/new_filename.txt\")\nTrue\n>>> d.delete()\n\n```\n\n\n## Has post\n\nA meta-class introducing a `__post__` dunder which runs after the `__init__` of _everything_ in the MRO.\n\n```python\n>>> from pyiron_snippets.has_post import HasPost\n>>>\n>>> class Foo(metaclass=HasPost):\n...     def __init__(self, x=0):\n...         self.x = x\n...         print(f\"Foo.__init__: x = {self.x}\")\n>>>\n>>> class Bar(Foo):\n...     def __init__(self, x=0, post_extra=2):\n...         super().__init__(x)\n...         self.x += 1\n...         print(f\"Bar.__init__: x = {self.x}\")\n...\n...     def __post__(self, *args, post_extra=2, **kwargs):\n...         self.x += post_extra\n...         print(f\"Bar.__post__: x = {self.x}\")\n>>>\n>>> Bar().x\nFoo.__init__: x = 0\nBar.__init__: x = 1\nBar.__post__: x = 3\n3\n\n```\n\nHonestly, try thinking if there's another way to solve your problem; this is a dark magic.\n\n## Import alarm\n\nFail gracefully when optional dependencies are missing for (optional) functionality.\n\n```python\n>>> from pyiron_snippets.import_alarm import ImportAlarm\n>>>\n>>> with ImportAlarm(\n...     \"Some functionality unavailable: `magic` dependency missing\"\n... ) as my_magic_alarm:\n...     import magic\n>>>\n>>> with ImportAlarm(\"This warning won't show up\") as datetime_alarm:\n...     import datetime\n>>>\n>>> class Foo:\n...     @my_magic_alarm\n...     @datetime_alarm\n...     def __init__(self, x):\n...         self.x = x\n...\n...     @property\n...     def magical(self):\n...         return magic.method(self.x)\n...\n...     def a_space_odyssey(self):\n...         print(datetime.date(2001, 1, 1))\n>>>\n>>> foo = Foo(0)\n>>>  # Raises a warning re `magic` (since that does not exist)\n>>>  # but not re `datetime` (since it does and we certainly have it)\n>>> foo.a_space_odyssey()\n2001-01-01\n\n>>> try:\n...     foo.magical(0)\n... except NameError as e:\n...     print(\"ERROR:\", e)\nERROR: name 'magic' is not defined\n\n```\n\n## Logger\n\nConfigures the logger and writes to `pyiron.log`\n\n## Retry\n\nIf at first you don't succeed\n\n```python\n>>> from time import time\n>>>\n>>> from pyiron_snippets.retry import retry\n>>>\n>>> def at_most_three_seconds():\n...     t = int(time())\n...     if t % 3 != 0:\n...         raise ValueError(\"Not yet!\")\n...     return t\n>>>\n>>> retry(at_most_three_seconds, msg=\"Tried and failed...\", error=ValueError) % 3\n0\n\n```\n\nDepending on the system clock at invokation, this simple example may give warnings like `UserWarning: Tried and failed... Trying again in 1.0s. Tried 1 times so far...` up to two times.\n\n\n## Singleton\n\nA metaclass for the [singleton pattern](https://en.wikipedia.org/wiki/Singleton_pattern).\n\n```python\n>>> from pyiron_snippets.singleton import Singleton\n>>>\n>>> class Foo(metaclass=Singleton):\n...     pass\n>>>\n>>> foo1 = Foo()\n>>> foo2 = Foo()\n>>> foo1 is foo2\nTrue\n\n```\n",
    "bugtrack_url": null,
    "license": "BSD 3-Clause License  Copyright (c) 2024, Max-Planck-Institut f\u00fcr Nachhaltige Materialien GmbH - Computational Materials Design (CM) Department All rights reserved.  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:  * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.  * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ",
    "summary": "pyiron_snippets - Short, dependency-free python snippets.",
    "version": "0.1.4",
    "project_urls": {
        "Documentation": "https://pyiron-snippets.readthedocs.io",
        "Homepage": "https://github.com/pyiron/pyiron_snippets",
        "Repository": "https://github.com/pyiron/pyiron_snippets"
    },
    "split_keywords": [
        "pyiron"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "11f2d8a1c91c861429cf1a293a545874b3010d3d1b5481a524c89c0f66cc3973",
                "md5": "4799f395cc33d3a039b31c147ecbd400",
                "sha256": "710ced8400541276bebfa742f97521757be23aebec37b559d259743e1a3dffaf"
            },
            "downloads": -1,
            "filename": "pyiron_snippets-0.1.4-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4799f395cc33d3a039b31c147ecbd400",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<3.13,>=3.9",
            "size": 31285,
            "upload_time": "2024-08-08T03:50:59",
            "upload_time_iso_8601": "2024-08-08T03:50:59.305061Z",
            "url": "https://files.pythonhosted.org/packages/11/f2/d8a1c91c861429cf1a293a545874b3010d3d1b5481a524c89c0f66cc3973/pyiron_snippets-0.1.4-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b99a5305c2959dbb9104e7fc8b02df4de4159395d9ca28184df9e7a28cd5189e",
                "md5": "ea65e9f5fbfc5219ad232a0180f9e112",
                "sha256": "5664f54e8326d4e2ba4ee03467754bccd58dcd81a17f358a297dff58f082c1f0"
            },
            "downloads": -1,
            "filename": "pyiron_snippets-0.1.4.tar.gz",
            "has_sig": false,
            "md5_digest": "ea65e9f5fbfc5219ad232a0180f9e112",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<3.13,>=3.9",
            "size": 24579,
            "upload_time": "2024-08-08T03:51:00",
            "upload_time_iso_8601": "2024-08-08T03:51:00.853258Z",
            "url": "https://files.pythonhosted.org/packages/b9/9a/5305c2959dbb9104e7fc8b02df4de4159395d9ca28184df9e7a28cd5189e/pyiron_snippets-0.1.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-08-08 03:51:00",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "pyiron",
    "github_project": "pyiron_snippets",
    "travis_ci": false,
    "coveralls": true,
    "github_actions": true,
    "lcname": "pyiron-snippets"
}
        
Elapsed time: 0.27237s