Bearings: Access Data Generically¶
A bearing details how to fetch or place data of a given name
on a target object.
E.g., you would fetch name
from a dict using dict[name]
, but for a dataclass
using data.name
.
Bearings are the building blocks of a Course
objects, which fetch/place a
sequence of bearings on a complex data structure.
BearingAbstract Base Type¶
BearingAbstract
outlines the methods and attributes that must/may be overridden
by implementations.
name |
type |
required? |
description |
---|---|---|---|
method |
yes |
Gets data from object at |
|
method |
yes |
Sets data on object at |
|
|
method |
yes |
String shorthand |
|
cls attribute |
encouraged |
Compatible |
|
cls attribute |
encouraged |
String shorthand pattern |
method |
no |
Can |
|
method |
no |
Converts string to |
|
method |
no |
Returns initialized factory_type |
-
class
gemma.
BearingAbstract
(name, factory=None)[source]¶ -
__init__
(name, factory=None)[source]¶ Abstract base class for
Course
bearings.inherits from:
Generic[_NameType]
- Parameters
name (
Union
[~_NameType,BearingAbstract
[~_NameType]]) – name of key/index/attribute/method/etc to act on.factory (
Optional
[Type
[~FactoryType]]) –type
to be used as default value ifCourse.place()
hits empty or non-existent value so structure can be built
- Class-level Attributes
REGEX: (
re.Pattern
) - Regex pattern to match string shorthandNAME_TYPES (
List[Union[Type, Any]]
) -type
( ortuple
of types ) thatname
can be.
-
property
factory_type
¶ Read-only property.
- Return type
Optional
[Type
[~FactoryType]]- Returns
factory
passed to__init__
.
>>> from gemma import Attr >>> attribute = Attr('a', factory=dict) >>> attribute.factory_type dict
-
fetch
(target)[source]¶ MUST BE IMPLEMENTED
Fetches value from target object by
BearingAbstract.name()
- Parameters
target (
Any
) – object to fetch value from- Return type
Any
- Returns
value to be fetched
- Raises
NullNameError – generic error when bearing cannot be found
TypeError – when
target
is wrong type for bearing
See documentation of the default Bearing implementations for examples:
-
init_factory
()[source]¶ MAY BE IMPLEMENTED
Returns an initialized version of
BearingAbstract.factory()
.- Return type
~FactoryType
- Returns
initialized data object
- Raises
TypeError – is factory is not callable
DEFAULT IMPLEMENTATION: initializes object with no parameters.
>>> from gemma import Attr >>> attribute = Attr('a', factory=dict) >>> attribute.init_factory() {}
-
classmethod
is_compatible
(name)[source]¶ MAY BE IMPLEMENTED
Checks whether the
name
can be cast to current type.- Parameters
name (
Any
) – value to be cast- Return type
bool
- Returns
True
: Can be cast.False
: Cannot be cast
DEFAULT IMPLEMENTATION: checks whether the type of
name
is incls.NAME_TYPES
.Most Bearing implementations will not need to override this method, instead supplying a list of acceptable types to
cls.NAME_TYPES
.However, some Bearings may depend on criteria other than type and override this method, possibly making
cls.NAME_TYPES
irrelevant.For example, a bearing used to fetch and set data from the
dataclasses
module might re-implementBearingAbstract.is_compatible()
as a wrapper fordataclasses.is_dataclass()
.
-
property
name
¶ Read-only property.
- Return type
~_NameType
- Returns
name
passed to__init__
.
>>> from gemma import Attr >>> attribute = Attr('a') >>> attribute.name a
-
classmethod
name_from_str
(text)[source]¶ MAY BE IMPLEMENTED
Casts string to appropriate type for
name
param of__init__
.- Parameters
text (
str
) – text to cast- Return type
Any
- Returns
cast value.
- Raises
ValueError – if
text
is not cast-able.
DEFAULT IMPLEMENTATION: Tests if the
text
matches to the regex pattern inBearingAbstract.REGEX
, then extracts name from pattern.Raises
ValueError
if no match.
-
place
(target, value, **kwargs)[source]¶ MUST BE IMPLEMENTED
Sets
value
atBearingAbstract.name()
of target object.- Parameters
target (
Any
) – target object to set valuevalue (
Any
) – value to set
- Returns None
method should not return anything
- Raises
NullNameError –
NullNameError
should be raised if bearing cannot be placedTypeError – When
target
is wrong type for Bearing
See documentation of the default Bearing implementations for examples.
- Return type
None
-
Bearing Shorthand¶
The default implementations of BearingAbstract
checks for the following
patterns when determining if a string can be cast to it’s type:
class |
shorthand |
note |
---|---|---|
@name |
||
[name] |
||
name() |
||
name |
accepts all values |
>>> from gemma import Attr
>>>
>>> attribute = Attr.from_string('name')
Traceback (most recent call last):
...
ValueError: text does not match regex
>>> attribute = Attr.from_string('@name')
>>> attribute.name
'name'
This is slightly different from instantiating the class directly, which does not check/parse the input value of a string, instead using whatever it is fed.
>>> attribute = Attr('name')
>>> attribute.name
'name'
>>> attribute = Attr('@name')
>>> attribute.name
'@name'
Likewise, str(BearingAbstract)
should return the properly formatted shorthand
through BearingAbstract.__str__
>>> from gemma import Attr, Item, Call, Bearing
>>>
>>> str(Attr("a"))
'@a'
>>> str(Item("a"))
'[a]'
>>> str(Call("a"))
'a()'
>>> str(Fallback("a"))
'a'
This allows for string-encoded bearings which can be easily cast by Course
objects. For example:
>>> from gemma import Course
>>>
>>> data = {'nested': {'a': 'a value', 'b': 'b value'}}
>>>
>>> to_fetch = Course() / '[nested]' / 'keys()'
>>> to_fetch.fetch(data)
dict_keys(['a', 'b'])
Course
auto-casts strings using a configurable factory method.
BearingAbstract.from_string()
can be overridden when implementing a
custom Bearing if more granularity is needed than setting the class’ REGEX
field.
Implementations¶
gemma
comes with four implementations of BearingAbstract
, covering most
basic data object API’s.
Attr Type¶
-
class
gemma.
Attr
(name, factory=None)[source]¶ Attr fetches and places data on a target’s attribute.
inherits from:
BearingAbstract
name types: Attr only accepts
str
asname
value.shorthand:
"@name"
-
fetch
(target)[source]¶ Fetches attribute of target.
- Parameters
target (
Any
) – Object to fetch attribute from- Return type
Any
- Returns
Value of attribute
- Raises
NullNameError – if attribute does not exist
Equivalent to:
>>> getattr(target, self.name)
Example:
>>> from gemma import Attr >>> from dataclasses import dataclass >>> >>> @dataclass ... class Data: ... a: str = 'value' ... >>> data = Data() >>> Attr('a').fetch(data) 'value'
If target does not have an attribute of bearing.name:
>>> Attr('b').fetch(data) Traceback (most recent call last): ... gemma._exceptions.NullNameError: @b>
-
place
(target, value, **kwargs)[source]¶ Sets Attribute of target to
value
.- Parameters
target (
Any
) – Object to set attribute onvalue (
Any
) – Value to set on attribute
- Return type
None
- Returns
None
- Raises
NullNameError – if attribute does not exist
Equivalent to:
>>> setattr(target, self.name, value)
Example, using
data
from the fetch example above:>>> data.a 'value' >>> Attr('a').place(data, 'changed') >>> data.a 'changed'
If target does not have an attribute of bearing.name:
>>> Attr('b').place(data, 'changed again') Traceback (most recent call last): ... gemma._exceptions.NullNameError: @b
Unlike
setattr()
,Attr.place()
cannot be used to declare arbitrary attributes. Non-existent attributes will raise a NullNameError.
-
Item Type¶
-
class
gemma.
Item
(name, factory=None)[source]¶ Item fetches and places data on a target’s index or mapping
inherits from:
BearingAbstract
name types:
Any
.shorthand:
"[name]"
-
fetch
(target)[source]¶ Fetches data at index or key of
target
- Parameters
target (
Any
) – object to fetch data from- Return type
Any
- Returns
value of index/key
- Raises
NullNameError – if index/key does not exist
TypeError – if Target does not have a valid
__getitem__
method
Fetch data from a list:
>>> from gemma import Item >>> >>> data_list = ["zero", "one", "two"] >>> item = Item(0) >>> item.fetch(data_list) 'zero'
Fetch data from a dict:
>>> data_dict = {"a": "a value", "b": "b value"} >>> item = Item("b") >>> item.fetch(data_dict) 'b value'
Fetching an Index / Item that does not exist raises
NullNameError
>>> out_of_index = Item(5) >>> out_of_index.fetch(data_list) Traceback (most recent call last): ... gemma._exceptions.NullNameError: [5] >>> >>> bad_key = Item("c") >>> bad_key.fetch(data_dict) Traceback (most recent call last): ... gemma._exceptions.NullNameError: [c]
An invalid name raises a
NullNameError
regardless of whether thetarget
object would normally raise aKeyError
orIndexError
.Fetching from a
target
which does not support__getitem__
raises aTypeError
.>>> no_get_item = int(1) >>> bad_key.fetch(no_get_item) Traceback (most recent call last): ... TypeError: 'int' object is not subscriptable
-
place
(target, value, **kwargs)[source]¶ Sets
value
at Index/Key oftarget
- Parameters
target (
Any
) – object to setvalue
on.value (
Any
) – value to set.
- Return type
None
- Returns
None
- Raises
NullNameError – When Index/Key cannot be set
TypeError – When
target
does not support__setitem__
Changing an existing dict key:
>>> from gemma import Item >>> >>> data_dict = {"a": "a value", "b": "b value"} >>> existing_item = Item("b") >>> >>> existing_item.place(data_dict, "changed") >>> data_dict {'a': 'a value', 'b': 'changed'}
Setting a new dict key:
>>> new_item = Item("c") >>> new_item.place(data_dict, "new") >>> data_dict {'a': 'a value', 'b': 'changed', 'c': 'new'}
Changing an existing list index:
>>> data_list = ["zero", "one", "two"] >>> item = Item(0) >>> >>> item.place(data_list, "changed") >>> data_list ['changed', 'one', 'two']
Changing an index out of range does not result in
NullNameError
, as it does withItem.fetch()
.>>> out_of_index = Item(5) >>> out_of_index.place(data_list, "new value") >>> data_list ['changed', 'one', 'two', None, None, 'new value']
None
is inserted in any missing indexes between the last existing index and the new index.Attempting to place a value on a
target
that does not support__setitem__
raises aTypeError
:>>> data_tuple = ("zero", "one", "two") >>> cannot_set = Item(0) >>> >>> cannot_set.place(data_tuple, "changed") Traceback (most recent call last): ... TypeError: 'tuple' object does not support item assignment
If the object would normally raise a
KeyError
orIndexError
, it is cast to aNullNameError
.Let us create a dict class that raises a
KeyError
when attempting to set any key that is not present upon initialization:>>> class StrictDict(dict): ... def __setitem__(self, item, value): ... if not item in self: ... raise KeyError ... super().__setitem__(item, value) ... >>> strict = StrictDict({"a": "a value", "b": "b value"}) >>> strict["c"] = "changed" Traceback (most recent call last): ... KeyError
Item
‘s place method will cast theKeyError
to aNullNameError
.>>> raises_key = Item("c") >>> raises_key.place(strict, "changed") Traceback (most recent call last): ... gemma._exceptions.NullNameError: [c]
-
Call Type¶
-
class
gemma.
Call
(name, func_args=None, func_kwargs=None)[source]¶ Call fetches and sets data through a target’s
target.name()
method.inherits from:
BearingAbstract
name types: Call only accepts
str
asname
values.shorthand:
"name()"
-
__init__
(name, func_args=None, func_kwargs=None)[source]¶ - Parameters
name (
str
) – method name to act onfunc_args (
Optional
[Iterable
]) –*args
to pass to method when fetching or placingfunc_kwargs (
Optional
[Dict
[str
,Any
]]) –**kwargs
to pass to method when fetching or placing
- Class Attributes:
VALUE_ARG (
Any
): object to act as placeholder infunc_args
andfunc_kwargs
-
fetch
(target)[source]¶ Fetches value from method of
target
- Parameters
target (
Any
) – Object to call method on.- Return type
Any
- Returns
return of method
Getting the keys of a dict:
>>> from gemma import Call >>> >>> data_dict = {"a": "a value", "b": "b value"} >>> method = Call("keys") >>> >>> method.fetch(data_dict) dict_keys(['a', 'b'])
If the method does not exist, a
NullNameError
is raised.>>> invalid_method = Call("does_not_exist") >>> invalid_method.fetch(data_dict) Traceback (most recent call last): ... gemma._exceptions.NullNameError: does_not_exist()
When fetching a value, call will pass the
func_args
andfunc_kwargs
passed to__init__
as*args
and*kwargs
>>> data_list = ["repeat", "one", "two", "repeat"] >>> method = Call("index", func_args=("repeat", 1)) >>> method.fetch(data_list) 3
This is equivalent to
>>> data_list.index("repeat", 1) 3
-
place
(target, value, **kwargs)[source]¶ Places value with method of
target
.- Parameters
target (
Any
) – Object to call method onvalue (
Any
) – value to pass
- Return type
None
- Returns
None
By default,
value
is passed as the first argument to the given method.Appending value at end of list:
>>> from gemma import Call >>> >>> data_list = ["zero", "one", "two"] >>> >>> adds_value = Call("append") >>> adds_value.place(data_list, "three") >>> >>> data_list ['zero', 'one', 'two', 'three']
Any additional args are passed as positional arguments, after
value
. Let us create a list class with a method that will attempt to cast a value to a given type before appending it to the list:>>> class MultiArg(list): ... def cast_append(self, value, cast_type=None): ... try: ... value = cast_type(value) ... except (TypeError, ValueError): ... pass ... self.append(value) ... ... def args_reversed(self, cast_type=None, value=None): ... self.cast_append(value, cast_type) ...
We can pass
str
to thecast_type
parameter by setting it as the first additional argument toCall
.>>> data_list = MultiArg(('zero', 'one', 'two')) >>> data_list ['zero', 'one', 'two'] >>> casts_str = Call('cast_append', func_args=(str,)) >>> casts_str.place(data_list, 3) >>> data_list ['zero', 'one', 'two', '3']
This is equivalent to:
>>> data_list.cast_append(3, str)
We can also pass
cast_type
as a keyword argument.>>> casts_str = Call('cast_append', func_kwargs={'cast_type': str}) >>> casts_str.place(data_list, 4) >>> data_list ['zero', 'one', 'two', '3', '4']
For most setter methods, it is likely that the value will be the first argument passed. However, this is not always the case. Take
list.insert()
– the first argument is the index where the value is inserted.>>> data_list = ["zero", "one", "two"] >>> data_list.insert(0, "new") >>> data_list ['new', 'zero', 'one', 'two']
In this case, if we want a bearing that places
value
at the head of alist
, we need to passvalue
as the second argument.We can use the
Call.VALUE_ARG
object to indicate that instead of being placed as the first argument,value
should replace theCall.VALUE_ARG
whenever a new value is passed to the bearing.>>> data_list = ["zero", "one", "two"] >>> >>> inserts_head = Call("insert", func_args=(0, Call.VALUE_ARG)) >>> inserts_head.place(data_list, "new") >>> >>> data_list ['new', 'zero', 'one', 'two']
This also works with
**kwarg values
. Using theMultiArg
, class from above:>>> data_list = MultiArg(('zero', 'one', 'two')) >>> >>> kwargs = {'value': Call.VALUE_ARG, 'cast_type': str} >>> inserts_head = Call("args_reversed", func_kwargs=kwargs) >>> >>> inserts_head.place(data_list, 3) >>> inserts_head ['zero', 'one', 'two', '3']
-
Fallback Type¶
-
class
gemma.
Fallback
(name)[source]¶ -
__init__
(name)[source]¶ Attempts to fetch or place data on a target using other bearing class’ methods.
- Parameters
name (
Any
) – name of bearing.
inherits from:
BearingAbstract
name types:
Any
.shorthand:
"name"
- Class Attributes:
BEARING_CLASSES (
List[Type[BearingAbstract]]
): bearing classes to cycle through when attempting to fetch or place data.
The available methods and order of attempts is determined by the list of types in
Fallback.BEARING_CLASSES
. This makes bearing less performant than invoking one of its test classes directly, but does make setting upCourse
objects easier and less tedious. The performance hit may or may not be worth it depending on your workflow.The default
BEARING_CLASSES
areItem
,Call
, andAttr
, though that can be extended by inheriting this classMeant as a generic class when the bearing type is not well defined in a string ( Allows for more compact, generic
Course
declarations ).
-
fetch
(target)[source]¶ Attempts to fetch data from
target
object.- Parameters
target (
Any
) – object to fetch data from.- Return type
Any
- Returns
value
Cycles through the classes in
Fallback.BEARING_CLASSES
, casting the current Bearing to each type, and invoking theirfetch()
method.If the cast or fetch results in a :class:
NullNameError
,TypeError
, orValueError
, the exception is caught and the next class is tried.By default,
Fallback
cycles throughfetch()
onItem
,Attr
, andCall
, in that order.With the default classes, if an attribute exists, it will be fetched.
>>> from gemma import Fallback >>> >>> class TestData: ... pass ... >>> test_data = TestData() >>> test_data.a = 'a value' >>> >>> to_fetch = Fallback('a') >>> to_fetch.fetch(test_data) 'a value'
Same with an Index.
>>> data_dict = {"a": "a dict"} >>> to_fetch.fetch(data_dict) 'a dict'
Same with a method.
>>> class FetchMethod: ... def a(self): ... return 'a method' ... >>> test_data = FetchMethod() >>> to_fetch.fetch(test_data) 'a method'
When an name has multiple compatible bearings, it takes the first method’s value that does not throw an exception.
>>> class TwoValid(dict): ... def a(self): ... return 'a method' ... >>> data_dict = TwoValid({'a': 'a item'}) >>> to_fetch.fetch(data_dict) 'a item'
Both
Item('a')
andCall('a')
would return valid values –"a method"
and"a item"
, respectively – but sinceItem
is tried first and gets a valid response, the key value is returned.
-
place
(target, value, **kwargs)[source]¶ Attempts to set
value
ontarget
.- Parameters
target (
Any
) – Object to setvalue
on.value (
Any
) – Value to set.
- Return type
None
- Returns
None
Attempts to place data on a given name of
target
by cycling through the classes inFallback.BEARING_CLASSES
, casting the current Bearing to each type, and invoking theirplace()
method.If the cast or place results in a
NullNameError
,TypeError
, orValueError
, the exception is caught and the next class is tried.By default,
Fallback
cycles throughplace()
onItem
,Attr
, andCall
, in that order.With the default classes, if an attribute exists, it will be placed.
>>> from gemma import Fallback >>> >>> class TestData: ... a = None ... >>> test_data = TestData() >>> >>> to_place = Fallback("a") >>> to_place.place(test_data, "a attr") >>> >>> test_data.a 'a attr'
Same with an Index.
>>> data_dict = dict() >>> to_place.place(data_dict, "a dict") >>> data_dict {'a': 'a dict'}
Same with a method.
>>> class FetchMethod: ... def a(self, value): ... self.a = value ... >>> test_data = FetchMethod() >>> to_place.place(test_data, "a method") >>> test_data.a 'a method'
When an name has multiple compatible bearings, it takes the first method’s value that does not throw an exception.
>>> class TwoValid(dict): ... def a(self, value): ... self.a = value ... >>> data_dict = TwoValid() >>> to_place.place(data_dict, 'a value') >>> data_dict {'a': 'a value'} >>> data_dict.a <Item: 'a'>
Both
Item('a')
andCall('a')
would set valid values – (to a key and attribute respectively) – but sinceItem
is tried first and does not return an error, it is set to the dict’s key rather than overriding it’sa
method.
-
Casting Bearings¶
When casting a bearing directly, formatting is not parsed, unlike the method that
bearing()
below uses.
>>> from gemma import Item
>>>
>>> Item("[has_brackets]")
<Item: '[has_brackets]'>
>>>
>>> Item("no_brackets")
<Item: 'no_brackets'>
Values must pass the class’ BearingAbstract.is_compatible()
, if it does
not, TypeError
is raised.
>>> from gemma import Attr
>>>
>>> Attr(10)
Traceback (most recent call last):
...
TypeError: type <class 'int'> not allowed as <class 'gemma._bearings.Attr'>
When passing a bearing to another bearing, the original’s
BearingAbstract.name()
value is extracted before casting.
>>> original = Item('key_name')
>>> Attr(original)
<Attr: 'key_name'>
Sorting Bearings¶
Bearings are sorted in the following order:
By class
type
:Custom classes are sorted by class
__name__
Each class group is sorted by it’s value type’s
__name__
Within each value type, values are sorted by their respective sort methods.
Lets look as how the following list of bearings is sorted:
>>> from gemma import Item, Attr, Call, Fallback, BearingAbstract
We’re going to make a couple custom bearings to demonstrate how they sort:
>>> class Alpha(BearingAbstract):
... pass
...
>>> class Beta(BearingAbstract):
... pass
...
Here are our unsorted values:
>>> bearing_unsorted = [
... Fallback("b"),
... Call("b"),
... Alpha("b"),
... Attr("b"),
... Fallback("a"),
... Item("b"),
... Call("a"),
... Beta("b"),
... Item(2),
... Alpha("a"),
... Attr("a"),
... Item("a"),
... Attr("a"),
... Beta("a"),
... Item(1)
... ]
...
Sort them:
>>> bearings_sorted = sorted(bearing_unsorted)
Print sorted list to check:
>>> for this_bearing in bearings_sorted:
... print(repr(this_bearing))
...
<Item: 1>
<Item: 2>
<Item: 'a'>
<Item: 'b'>
<Attr: 'a'>
<Attr: 'a'>
<Attr: 'b'>
<Call: 'a'>
<Call: 'b'>
<Alpha: 'a'>
<Alpha: 'b'>
<Beta: 'a'>
<Beta: 'b'>
<Fallback: 'a'>
<Fallback: 'b'>
Checking Bearing Equality¶
- Bearings of the same type and
BearingAbstract.name()
value are considered equal: >>> Attr('a') == Attr('a') True
- Bearings of the same type and
- Bearings with different
BearingAbstract.name()
values are unequal. >>> Attr('a') == Attr('b') False
- Bearings with different
- Bearings of different types are always unequal.
>>> Attr('a') == Item('a') False
- Except the
Fallback
class… sometimes The
Fallback
class is equal to any type loaded into itsBEARING_CLASSES
field. By default, this makes it equal to anyItem
,Attr
,Call
orFallback
with the sameBearingAbstract.name()
value.>>> Fallback('a') == Attr('a') True >>> >>> Fallback('a') == Item('a') True >>> >>> Fallback('a') == Call('a') True
However, if we define an arbitrary class named
Alpha
, it will not be equal to a bearing with the same name.>>> class Alpha(BearingAbstract): ... pass ... >>> Fallback('a') == Alpha('a') False
If we create a Bearing with the
bearing()
factory method detailed below, using Alpha as one of its possibilities, the two values will be equal.>>> from gemma import bearing >>> >>> new_bearing = Fallback('a', bearing_classes=[Attr, Fallback, Alpha]) >>> new_bearing <Fallback: 'a'> >>> new_bearing == Alpha("a") True
This is because
bearing()
loads any fallbackFallback
objects.BEARING_CLASSES
field with the classes passed tobearing_classes
.
- Except the
Bearing Factory Method¶
The factory method that most default gemma
objects use when casting name values
to a bearing is:
-
gemma.
bearing
(name, bearing_classes=None, bearing_classes_extra=None)[source]¶ Factory function for bearing classes.
- Parameters
name (
Any
) – value for Bearing.namebearing_classes (
Optional
[List
[Type
[BearingAbstract
]]]) – list and order of bearing classes to attempt castingbearing_classes_extra (
Optional
[List
[Type
[BearingAbstract
]]]) – additional classes to add to bearing classes. Used to add to defaults whenbearing_classes
is set toNone
.
- Return type
BearingAbstract
- Returns
Bearing object
If
name
is a string, bearing will attempt to cast using each class’BearingAbstract.from_string()
method.Otherwise, bearing attempts to cast to each class normally, passing
name
as a single argument to each__init__
method.The default list of classes to attempt are:
Item
,Call
,Attr
, andFallback
– in that order.Any bearing types passed to
bearing_classes_extra
are put ahead of the bearings inbearing_classes
.Casting formatted strings:
>>> from gemma import bearing >>> >>> bearing("[item_name]") <Item: 'item_name'> >>> >>> bearing("@attr_name") <Attr: 'attr_name'> >>> >>> bearing("call_name()") <Call: 'call_name'>
Passing a string which does not match any of the above class’ string conventions will result in a generic
Fallback
.>>> bearing("unknown_name") <Fallback: 'unknown_name'>
This Fallback class will be loaded with the methods of the other classes, if
bearing_classes
includes custom Bearings, those class’ methods will be added to the list. No need to make a custom subclass to extend the pool methods available toFallback
when using this factory.Passing a non-string will always result in an
Item
object with the default list, sinceItem
accepts all types, and is attempted first.>>> bearing(5) <Item: 5> >>> >>> bearing((5, 4)) <Item: (5, 4)>