Skip to main content

No project description provided

Project description

Lets you define attrs classes with a single non-keyword-only field that can be initialised using var-positional (i.e. star *) arguments.

Installation

pip install starfield

Usage

from attrs import define, field
from starfield import starfield


@define(field_transformer=starfield)
class SantaList:
    names: list = field(init="*")
    is_naughty_list: bool = field()


naughty_list = SantaList("Bob", "Alice", is_naughty_list=True)

Why?

Sometimes you want to define a class that behaves like a list with some extra fields. Without an initializer with var-positional arguments, you would have to explicitly pass a list to the initializer:

from attrs import define, field


@define
class SantaList:
    names: list = field()
    is_naughty_list: bool = field()


naughty_list = SantaList(["Bob", "Alice"], is_naughty_list=True)

This can get messy, especially if you have lots of nested fields.

attrs's documentation recommends explains why it's usually better to use a classmethod than to modify the initializer.

Passing complex objects into init and then using them to derive data for the class unnecessarily couples your new class with the old class which makes it harder to test and also will cause problems later.

Generally speaking, the moment you think that you need finer control over how your class is instantiated than what attrs offers, it’s usually best to use a classmethod factory or to apply the builder pattern.

Nested fields

To motivate starfield more strongly, let's look at a more complex example involving nested fields.

Suppose we want to create a data structure to represent a simple grammatical expression:

"I" ( "love" | "hate" ) ( "cats" | "dogs" )

We can define a class to represent this expression with attrs:

from attrs import define, field


@define
class And:
    children: list = field()


@define
class Or:
    children: list = field()


expr = And(["I", Or(["love", "hate"]), Or(["cats", "dogs"])])

This works but it's a bit awkward to have to manually pass the list at every level.

Using starfield we can define the same class but with a much simpler initializer:

from attrs import define, field
from starfield import starfield


@define(field_transformer=starfield)
class And:
    children: list = field(init="*")


@define(field_transformer=starfield)
class Or:
    children: list = field(init="*")


expr = And("I", Or("love", "hate"), Or("cats", "dogs"))

How?

The starfield adds to the class an __init__ method that accepts variadic positional arguments. The __init__ method calls __attrs_init__ with the variadic positional arguments passed as a tuple to the field with init="*".

String representation

To make the string representation of the class more readable, starfield also adds a __rich_repr__ method to the class. However, this only works if you're using rich to stringify your objects.

To add a __repr__ method as well, you can pass repr=True to starfield. However, its behaviour may be inconsistent with the attrs-generated __repr__ methods which are more complicated than one might expect (and may change without warning - hence why starfield doesn't touch it unless you explicitly ask it to).

Notes

  • starfield will make all non-star fields keyword-only.

  • You can still set the star field using a keyword argument (e.g. SantaList(names=["Bob", "Alice"], is_naughty_list=True)).

Similar projects

  • This feature has been requested and discussed here. The use of init="*" is also proposed.

  • pydantic's root types serve a similar purpose. Notable, however, a class with a root type cannot have any other fields.

Please let me know if I've missed any.

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

starfield-0.1.2.tar.gz (3.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

starfield-0.1.2-py3-none-any.whl (3.4 kB view details)

Uploaded Python 3

File details

Details for the file starfield-0.1.2.tar.gz.

File metadata

  • Download URL: starfield-0.1.2.tar.gz
  • Upload date:
  • Size: 3.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.3.1 CPython/3.11.1 Darwin/22.1.0

File hashes

Hashes for starfield-0.1.2.tar.gz
Algorithm Hash digest
SHA256 b2eac0646e563bdba0924c5bb35f4d143b5265ea060424e67ee4547b9dc6b9c7
MD5 3cf53e68cea0f51182713dd963c03018
BLAKE2b-256 21c9bf4b9fb3a5d64d35e36b43e028ab507afa055a8989ab99f89acc1fcbe117

See more details on using hashes here.

File details

Details for the file starfield-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: starfield-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 3.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.3.1 CPython/3.11.1 Darwin/22.1.0

File hashes

Hashes for starfield-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 516902a13f357aa668fbbcc711f5c8135a7981ac47df4c7e6f776177d432aaee
MD5 9ac49715f89bbdfca6b864854bfe7254
BLAKE2b-256 a7c820fe807526dafaeae485c969aed0e31317ade6f8c5de112233bc1714081f

See more details on using hashes here.

Supported by

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