1.1. satchless.item — abstract priceables¶
1.1.1. Available Types¶
All of the following types are abstract and meant to be subclassed to implement their missing methods.
Note
Implementations provided by Satchless expect to work with price objects as implemented by the prices library.
-
class
satchless.item.Item A priceable item. Usually a single product or a single product variant.
-
class
satchless.item.ItemRange A range of priceables that vary in price. An example is a product with multiple variants.
-
class
satchless.item.ItemLine A certain amount of an
Item. Contains a priceable and its quantity. An example is a cart line.
-
class
satchless.item.ItemSet A collection of
ItemLineobjects that have a total price. Examples include a bundle, an order or a shopping cart.
-
class
satchless.item.ItemList An
ItemSetthat subclasses the Pythonlist.
-
class
satchless.item.Partitioner An object capable of partitioning an
ItemSetinto multiple sets for purposes such as split delivery.
-
class
satchless.item.ClassifyingPartitioner A
Partitionerthat automatically splits based on a classifying function.
-
class
satchless.item.StockedItem A stocked
Item. Introduces the concept of stock quantities.
-
class
satchless.item.InsufficientStock Exception class that is raised by
StockedItemwhen trying to exceed the stock quantity.
1.1.2. Available functions¶
-
satchless.item.partition(subject, keyfunc[, partition_class=ItemList])¶ Returns a
Partitionerobjects that splits subject based on the result of keyfunc(item).
1.1.3. Item Objects¶
Instance methods:
-
Item.get_price(**kwargs)¶ Returns a
prices.Priceobject representing the price of the priceable.The default implementation passes all keyword arguments to
get_price_per_item(). Override to implement discounts and such.
For subclassing:
-
Item.get_price_per_item(**kwargs)¶ Returns a
prices.Priceobject representing the price for a single piece of the priceable.The default implementation will raise a
NotImplementedErrorexception.
Example use:
>>> import prices
>>> from satchless.item import Item
>>> class Coconut(Item):
... def get_price_per_item(self): return prices.Price(10, currency='USD')
...
>>> coconut = Coconut()
>>> coconut.get_price()
Price('10', currency='USD')
1.1.4. ItemRange Objects¶
Instance methods:
-
ItemRange.__iter__()¶ Returns an iterator yielding priceable objects that implement a
get_price()method.The default implementation will raise a
NotImplementedErrorexception.
-
ItemRange.get_price_range(**kwargs)¶ Returns a
prices.PriceRangeobject representing the price range of the priceables included in the range object. Keyword arguments are passed toget_price_per_item().Calling this method on an empty range will raise an
AttributeErrorexception.
For subclassing:
-
ItemRange.get_price_per_item(item, **kwargs)¶ Return a
prices.Priceobject representing the price of a given item.The default implementation will pass all keyword arguments to
item.get_price(). Override to implement discounts or caching.
Example use:
>>> import prices
>>> from satchless.item import Item, ItemRange
>>> class SpanishInquisition(Item):
... def get_price_per_item(self): return prices.Price(50, currency='BTC')
...
>>> class LaVache(Item):
... def get_price_per_item(self): return prices.Price(15, currency='BTC')
...
>>> class ThingsNobodyExpects(ItemRange):
... def __iter__(self):
... yield SpanishInquisition()
... yield LaVache()
...
>>> tne = ThingsNobodyExpects()
>>> tne.get_price_range()
PriceRange(Price('15', currency='BTC'), Price('50', currency='BTC'))
1.1.5. ItemLine Objects¶
-
class
satchless.item.ItemLine¶ An
ItemLineinstance represents a certain quantity of a particular priceable.
Instance methods:
-
ItemLine.get_total(**kwargs)¶ Return a
prices.Priceobject representing the total price of the line. Keyword arguments are passed to bothget_quantity()andget_price_per_item().
For subclassing:
-
ItemLine.get_quantity(**kwargs)¶ Returns an
intor adecimal.Decimalrepresenting the quantity of the item.The default implementation will ignore all keyword arguments and always return
1.
-
ItemLine.get_price_per_item(**kwargs)¶ Returns a
prices.Priceobject representing the price of a single piece of the item.The default implementation will raise a
NotImplementedErrorexception.
Example use:
>>> import prices
>>> from satchless.item import ItemLine
>>> class Shrubberies(ItemLine):
... def __init__(self, qty): self.qty = qty
... def get_quantity(self): return self.qty
... def get_price_per_item(self): return prices.Price(11, currency='GBP')
...
>>> shrubberies = Shrubberies(7)
>>> shrubberies.get_total()
Price('77', currency='GBP')
1.1.6. ItemSet Objects¶
-
class
satchless.item.ItemSet¶ An
ItemSetinstance represents a set ofItemLineor otherItemSetobjects that has a total price.
Instance methods:
-
ItemSet.__iter__()¶ Returns an iterator yielding objects that implement a
get_total()method. Good candidates include instances ofItemLineandItemSetitself.The default implementation will raise a
NotImplementedErrorexception.
-
ItemSet.get_total(**kwargs)¶ Return a
prices.Priceobject representing the total price of the set. Keyword arguments are passed toget_subtotal().Calling this method on an empty set will raise an
AttributeErrorexception.
For subclassing:
-
ItemSet.get_subtotal(item, **kwargs)¶ Returns a
prices.Priceobject representing the total price ofitem.The default implementation will pass keyword arguments to
item.get_total(). Override to implement discounts or caching.
Example use:
>>> import prices
>>> from satchless.item import Item, ItemLine, ItemSet
>>> class Product(Item):
... def get_price_per_item(self): return prices.Price(10, currency='EUR')
...
>>> class CartLine(ItemLine):
... def __init__(self, product, qty): self.product, self.qty = product, qty
... def get_price_per_item(self): return self.product.get_price()
... def get_quantity(self): return self.qty
...
>>> class Cart(ItemSet):
... def __iter__(self):
... yield CartLine(Product(), 5)
...
>>> cart = Cart()
>>> cart.get_total()
Price('50', currency='EUR')
1.1.7. Partitioner Objects¶
-
class
satchless.item.Partitioner(subject)¶ A
Partitionerinstance is an iterable view of thesubjectthat partitions it for purposes such as split delivery.
Instance methods:
-
Partitioner.__iter__()¶ Returns an iterator that yields
ItemSetobjects representing partitions ofself.subject.The default implementation will yield a single
ItemListcontaining all the elements ofself.subject. Override to implement your partitioning scheme.
Example use:
>>> from satchless.item import ItemList, Partitioner
>>> class EvenOddSplitter(Partitioner):
... def __iter__(self):
... yield ItemList(it for n, it in enumerate(self.subject) if not n % 2)
... yield ItemList(it for n, it in enumerate(self.subject) if n % 2)
...
>>> splitter = EvenOddSplitter(['a', 'b', 'c', 'd', 'e', 'f'])
>>> list(splitter)
[ItemList(['a', 'c', 'e']), ItemList(['b', 'd', 'f'])]
A more advanced example could split an imaginary cart object into groups of objects that can be delivered together:
from satchless.item import ItemList, Partitioner
class DeliveryPartitioner(Partitioner):
def __iter__(self):
"""
Yield single-product groups for products that need to be shipped
separately. Yield a separate group for digital products if present.
Everything else can be shipped together.
"""
digital = []
remaining = []
for it in self.subject:
if it.ship_separately:
yield ItemList([it])
elif it.is_digital:
digital.append(it)
else:
remaining.append(it)
if digital:
yield ItemList(digital)
if remaining:
yield ItemList(remaining)
1.1.8. ClassifyingPartitioner Objects¶
-
class
satchless.item.ClassifyingPartitioner(subject)¶ A
Partitionersubclass that splits the subject into groups based on the result of the classifying method.
Instance methods:
-
ClassifyingPartitioner.classify(item)¶ Returns a classification key that groups together items that are meant for the same group.
The default implementation will raise a
NotImplementedErrorexception.
Example use:
>>> from satchless.item import ItemList, ClassifyingPartitioner
>>> class ClassNameSplitter(ClassifyingPartitioner):
... def classify(self, item):
... return type(item).__name__
...
>>> splitter = ClassNameSplitter(['a', 'b', 1, ['one'], 2, ['two']])
>>> list(splitter)
[ItemList([1, 2]), ItemList([['one'], ['two']]), ItemList(['a', 'b'])]
1.1.9. StockedItem Objects¶
-
class
satchless.item.StockedItem¶ A
StockedItemobject is subclass ofItemthat allows you to track stock quantities and guard against excess allocation.
Instance methods:
-
ItemSet.get_stock()¶ Returns the current stock quantity of the item.
The default implementation will raise a
NotImplementedErrorexception.
-
StockedItem.check_quantity(quantity)¶ Makes sure that at least quantity of the object are in stock by comparing the value with the result of self.get_stock(). If there is not enough, an
InsufficientStockexception will be raised.
Example use:
>>> from satchless.item import InsufficientStock, StockedItem
>>> class LimitedShrubbery(StockedItem):
... def get_stock(self):
... return 1
...
>>> shrubbery = LimitedShrubbery()
>>> try:
... shrubbery.check_quantity(2)
... except InsufficientStock as e:
... print('only %d remaining!' % (e.item.get_stock(),))
...
only 1 remaining!
1.1.10. InsufficientStock Exception¶
-
class
satchless.item.InsufficientStock(item)¶ Informs you that a stock quantity check failed against item. Raised by
StockedItem.check_quantity().