Skip to main content

pyiron_snippets - Short, dependency-free python snippets.

Project description

Binder License Coverage Status Documentation Status

Anaconda Last Updated Platform Downloads

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:

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

Deprecate

Easily indicate that some functionality is being deprecated

>> > 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.

>> > 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

>> > 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

>> > 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.

>> > 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.

>> > 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

>> > 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.

>> > from pyiron_snippets.singleton import Singleton
>> >
>> >

class Foo(metaclass=Singleton):


    ...
pass
>> >
>> > foo1 = Foo()
>> > foo2 = Foo()
>> > foo1 is foo2
True

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyiron_snippets-0.1.1.tar.gz (20.9 kB view details)

Uploaded Source

Built Distribution

pyiron_snippets-0.1.1-py3-none-any.whl (26.9 kB view details)

Uploaded Python 3

File details

Details for the file pyiron_snippets-0.1.1.tar.gz.

File metadata

  • Download URL: pyiron_snippets-0.1.1.tar.gz
  • Upload date:
  • Size: 20.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for pyiron_snippets-0.1.1.tar.gz
Algorithm Hash digest
SHA256 6734b89ea6964f3706613595f16321dcf8b4d0a6624c8a51a84e7b5e81b48e16
MD5 20b91a50e63c161152cc668ce2114368
BLAKE2b-256 3349d7bc04b579f281144172551bfeef6cedef0a0df99ccb7417f0c6bcffd01b

See more details on using hashes here.

File details

Details for the file pyiron_snippets-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for pyiron_snippets-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9b804e7708d94d0275d4da827fb2ecdd8bd1562b90aa7ea91a73e9e88400ea13
MD5 f2223623d6f223cd00e842ff028a149f
BLAKE2b-256 f67ed66e595c9407d6a7587d93c834a9b64c97b9cc6e190d5063fb8cb1a23821

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page