commerce: Python3 fixes, + composer (.base, .schema)

This commit is contained in:
Helmut Merz 2024-09-21 22:36:59 +02:00
parent c5fe028756
commit 87ca77df45
12 changed files with 83 additions and 254 deletions

View file

@ -15,18 +15,18 @@ Shops and Products
Let's start with two shops:
>>> shop1 = manager.shops.create(u'shop1', title=u'PC up Ltd')
>>> shop2 = manager.shops.create(u'shop2', title=u'Video up Ltd')
>>> shop1 = manager.shops.create('shop1', title='PC up Ltd')
>>> shop2 = manager.shops.create('shop2', title='Video up Ltd')
>>> len(list(manager.shops))
2
Now we add products to the shops.
>>> p001 = manager.products.create(u'001', title=u'Silent Case')
>>> p002 = manager.products.create(u'002', title=u'Portable Projector')
>>> p003 = manager.products.create(u'003', title=u'HD Flatscreen Monitor')
>>> p004 = manager.products.create(u'004', title=u'Giga Mainboard')
>>> p001 = manager.products.create('001', title='Silent Case')
>>> p002 = manager.products.create('002', title='Portable Projector')
>>> p003 = manager.products.create('003', title='HD Flatscreen Monitor')
>>> p004 = manager.products.create('004', title='Giga Mainboard')
>>> shop1.products.add(p001)
>>> shop1.products.add(p003)
@ -35,30 +35,30 @@ Now we add products to the shops.
>>> shop2.products.add(p003)
>>> sorted((p.productId, p.title) for p in shop1.products)
[(u'001', u'Silent Case'), (u'003', u'HD Flatscreen Monitor'),
(u'004', u'Giga Mainboard')]
[('001', 'Silent Case'), ('003', 'HD Flatscreen Monitor'),
('004', 'Giga Mainboard')]
Let's have a look at the product - it should correctly reference the shops
it belongs to.
>>> sorted((s.name, s.title) for s in p003.shops)
[(u'shop1', u'PC up Ltd'), (u'shop2', u'Video up Ltd')]
[('shop1', 'PC up Ltd'), ('shop2', 'Video up Ltd')]
We can also create a manufacturer and set it for a product.
>>> mf001 = manager.manufacturers.create(u'001', title=u'Global Electronics')
>>> mf001 = manager.manufacturers.create('001', title='Global Electronics')
>>> p001.manufacturer = mf001
>>> [p.title for p in mf001.products]
[u'Silent Case']
['Silent Case']
Customers
=========
>>> c001 = manager.customers.create(u'001', title=u'Your Local Computer Store')
>>> c002 = manager.customers.create(u'002', title=u'Speedy Gonzales')
>>> c003 = manager.customers.create(u'003', title=u'TeeVee')
>>> c004 = manager.customers.create(u'004', title=u'MacVideo')
>>> c001 = manager.customers.create('001', title='Your Local Computer Store')
>>> c002 = manager.customers.create('002', title='Speedy Gonzales')
>>> c003 = manager.customers.create('003', title='TeeVee')
>>> c004 = manager.customers.create('004', title='MacVideo')
>>> shop1.customers.add(c001)
>>> shop1.customers.add(c002)
@ -68,11 +68,11 @@ Customers
>>> shop2.customers.add(c004)
>>> sorted((c.customerId, c.title) for c in shop1.customers)
[(u'001', u'Your Local Computer Store'), (u'002', u'Speedy Gonzales'),
(u'004', u'MacVideo')]
[('001', 'Your Local Computer Store'), ('002', 'Speedy Gonzales'),
('004', 'MacVideo')]
>>> sorted((s.name, s.title) for s in c002.shops)
[(u'shop1', u'PC up Ltd'), (u'shop2', u'Video up Ltd')]
[('shop1', 'PC up Ltd'), ('shop2', 'Video up Ltd')]
Carts and Orders
@ -84,16 +84,16 @@ A cart is just a collection of order items belonging to a certain customer
>>> orderItems = manager.orderItems
>>> orderItems.add(p001, c001, shop=shop1, quantity=3)
<OrderItem [2, 1, 7, '... ...', '???']: {'shop': 0, 'quantity': 3}>
<OrderItem [2, 1, 7, '... ...', -1]: {'quantity': 3, 'shop': 0}>
>>> orderItems.getCart(c001)
[<OrderItem [2, 1, 7, '... ...', '???']: {'shop': 0, 'quantity': 3}>]
[<OrderItem [2, 1, 7, '... ...', -1]: {'quantity': 3, 'shop': 0}>]
>>> item1 = orderItems.getCart(c001, shop=shop1, product=p001)[0]
>>> item1
<OrderItem [2, 1, 7, '... ...', '???']: {'shop': 0, 'quantity': 3}>
<OrderItem [2, 1, 7, '... ...', -1]: {'quantity': 3, 'shop': 0}>
>>> orderItems.add(p003, c001, shop=shop1, quantity=1)
<OrderItem [4, 2, 7, '... ...', '???']: {'shop': 0, 'quantity': 1}>
<OrderItem [4, 2, 7, '... ...', -1]: {'quantity': 1, 'shop': 0}>
>>> len(orderItems.getCart(c001))
2
@ -102,7 +102,7 @@ If we add the same product again to the cart no new item is created but
the quantity is added to the existing item.
>>> orderItems.add(p003, c001, shop=shop1, quantity=1)
<OrderItem [4, 2, 7, '... ...', '???']: {'shop': 0, 'quantity': 2}>
<OrderItem [4, 2, 7, '... ...', -1]: {'quantity': 2, 'shop': 0}>
>>> len(orderItems.getCart(c001))
2
@ -127,4 +127,4 @@ retrieving the order items.
>>> orderItems.getCart(c001)
[]
>>> orderItems.getCart(c001, ord001)
[<OrderItem [4, 2, 7, '... ...', 11]: {'shop': 0, 'quantity': 2}>]
[<OrderItem [4, 2, 7, '... ...', 11]: {'quantity': 2, 'shop': 0}>]

View file

@ -1,37 +1,17 @@
#
# Copyright (c) 2009 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# cybertools.commerce.customer
"""
Customer classes.
$Id$
""" Customer classes.
"""
from zope.interface import implements, Interface
from zope.interface import implementer, Interface
from cybertools.commerce.common import RelationSet, BaseObject
from cybertools.commerce.interfaces import ICustomer, IAddress
@implementer(ICustomer)
class Customer(BaseObject):
implements(ICustomer)
def __init__(self, customerId, title=None, client=None):
self.name = self.customerId = customerId
self.title = title or u'unknown'
@ -40,7 +20,8 @@ class Customer(BaseObject):
self.orders = self.collection(self, 'customer')
@implementer(IAddress)
class Address(BaseObject):
implements(IAddress)
pass

View file

@ -1,28 +1,9 @@
#
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# cybertools.commerce.manager
"""
The commerce manager (container, registry, ...).
$Id$
""" The commerce manager (container, registry, ...).
"""
from zope.interface import implements
from zope.interface import implementer
from cybertools.commerce.common import ContainerAttribute
from cybertools.commerce.customer import Customer
@ -33,10 +14,9 @@ from cybertools.commerce.shop import Shop
from cybertools.tracking.btree import TrackingStorage
@implementer(IManager)
class Manager(object):
implements(IManager)
def __init__(self):
self.shops = ContainerAttribute(Shop)
self.products = ContainerAttribute(Product, 'productId')

View file

@ -1,20 +1,4 @@
#
# Copyright (c) 2015 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# cybertools.commerce.order
"""
Order and order item classes.
@ -23,7 +7,7 @@ Order and order item classes.
from zope.cachedescriptors.property import Lazy
from zope import component
from zope.component import adapts
from zope.interface import implements, Interface
from zope.interface import implementer, Interface
from zope.intid.interfaces import IIntIds
from cybertools.commerce.common import getUidForObject, getObjectForUid
@ -33,10 +17,9 @@ from cybertools.tracking.btree import Track
from cybertools.tracking.interfaces import ITrackingStorage
@implementer(IOrder)
class Order(BaseObject):
implements(IOrder)
customer = Relation('_customer', 'orders')
def __init__(self, orderId, shop=None, customer=None):
@ -45,10 +28,9 @@ class Order(BaseObject):
self.customer = customer
@implementer(IOrderItem)
class OrderItem(Track):
implements(IOrderItem)
metadata_attributes = Track.metadata_attributes + ('order',)
index_attributes = metadata_attributes
typeName = 'OrderItem'
@ -85,11 +67,11 @@ class OrderItem(Track):
parent.context.indexTrack(0, self, 'order')
@implementer(IOrderItems)
class OrderItems(object):
""" A tracking storage adapter managing order items.
"""
implements(IOrderItems)
adapts(ITrackingStorage)
def __init__(self, context):
@ -114,7 +96,7 @@ class OrderItems(object):
criteria['runId'] = criteria.pop('run')
return self.context.query(**criteria)
def add(self, product, party, shop, order='???', run=0, **kw):
def add(self, product, party, shop, order=-1, run=0, **kw):
kw['shop'] = self.getUid(shop)
existing = self.getCart(party, order, shop, run, product=product)
options = kw.get('options')
@ -132,7 +114,7 @@ class OrderItems(object):
self.context.indexTrack(0, track, 'order')
return track
def getCart(self, party=None, order='???', shop=None, run=None, **kw):
def getCart(self, party=None, order=-1, shop=None, run=None, **kw):
if run:
kw['run'] = run
result = self.query(party=party, order=order, **kw)

View file

@ -1,38 +1,18 @@
#
# Copyright (c) 2009 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# cybertools.commerce.product
"""
Product classes.
$Id$
""" Product classes.
"""
from zope.interface import implements, Interface
from zope.interface import implementer, Interface
from cybertools.commerce.common import Relation, RelationSet, BaseObject
from cybertools.commerce.interfaces import IProduct, ICategory
from cybertools.commerce.interfaces import IManufacturer, ISupplier
@implementer(IProduct)
class Product(BaseObject):
implements(IProduct)
manufacturer = Relation('_manufacturer', 'products')
def __init__(self, productId, title=None):
@ -44,10 +24,9 @@ class Product(BaseObject):
self.suppliers = self.collection(self, 'products')
@implementer(ICategory)
class Category(BaseObject):
implements(ICategory)
def __init__(self, name, title=None):
self.name = name
self.title = title or u'unknown'
@ -58,20 +37,18 @@ class Category(BaseObject):
self.parentCategories = self.collection(self, 'subCategories')
@implementer(IManufacturer)
class Manufacturer(BaseObject):
implements(IManufacturer)
def __init__(self, name, title=None):
self.name = name
self.title = title or u'unknown'
self.products = self.collection(self, 'manufacturer')
@implementer(ISupplier)
class Supplier(BaseObject):
implements(ISupplier)
def __init__(self, name, title=None):
self.name = name
self.title = title or u'unknown'

View file

@ -1,37 +1,17 @@
#
# Copyright (c) 2009 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# cybertools.commerce.shop
"""
Base classes.
$Id$
""" Base classes.
"""
from zope.interface import implements
from zope.interface import implementer
from cybertools.commerce.common import RelationSet, BaseObject
from cybertools.commerce.interfaces import IShop
@implementer(IShop)
class Shop(BaseObject):
implements(IShop)
collection = RelationSet
def __init__(self, name, title=None):

View file

@ -7,16 +7,16 @@ Tests for the 'cybertools.commerce' package.
import unittest, doctest
from zope import component
from zope.interface import implements
from zope.interface import implementer
from zope.intid.interfaces import IIntIds
from cybertools.commerce.order import OrderItems
from cybertools.commerce.product import Product
@implementer(IIntIds)
class IntIdsStub(object):
"""A testing stub (mock utility) for IntIds."""
implements(IIntIds)
def __init__(self):
self.objs = []
@ -37,7 +37,7 @@ class IntIdsStub(object):
self.objs[id] = None
def __iter__(self):
return iter(xrange(len(self.objs)))
return iter(range(len(self.objs)))
def setUp(testCase):

View file

@ -1,58 +1,39 @@
#
# Copyright (c) 2007 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# cybertools.composer.base
"""
Basic classes for complex template structures.
$Id$
""" Basic classes for complex template structures.
"""
from zope.interface import implements
from zope.interface import implementer
from cybertools.composer.interfaces import IComponent, IElement, ICompound
from cybertools.composer.interfaces import ITemplate
from cybertools.util.jeep import Jeep
@implementer(IComponent)
class Component(object):
implements(IComponent)
pass
@implementer(IElement)
class Element(Component):
implements(IElement)
pass
@implementer(ICompound)
class Compound(Component):
implements(ICompound)
componentStorage = Jeep
def __init__(self):
self.parts = self.componentStorage()
@implementer(ITemplate)
class Template(object):
implements(ITemplate)
componentStorage = Jeep
components = None

View file

@ -1,27 +1,10 @@
#
# Copyright (c) 2016 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# cybertools.composer.schema.factory
"""
Schema factory stuff.
""" Schema factory stuff.
"""
from zope.component import adapts
from zope.interface import implements
from zope.interface import implementer
from zope.interface import Interface
from zope import schema
@ -43,12 +26,12 @@ schema.Float.__typeInfo__ = ('decimal',)
schema.Choice.__typeInfo__ = ('dropdown',)
@implementer(ISchemaFactory)
class SchemaFactory(object):
""" Creates a cybertools.composer schema from an
interface (a zope.schema schema).
"""
implements(ISchemaFactory)
adapts(Interface)
fieldMapping = {

View file

@ -1,31 +1,14 @@
#
# Copyright (c) 2016 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# cybertools.composer.schema.field
"""
Schema fields and related classes.
""" Schema fields and related classes.
"""
from datetime import datetime
from logging import getLogger
from time import strptime, strftime
from zope.app.form.browser.interfaces import ITerms
from zope.browser.interfaces import ITerms
from zope.i18n.locales import locales
from zope.interface import implements
from zope.interface import implementer
from zope.cachedescriptors.property import Lazy
from zope.component import adapts
from zope import component
@ -50,10 +33,9 @@ class FieldGroup(object):
self.sublabels = sublabels
@implementer(IField)
class Field(Component):
implements(IField)
visible = True
required = False
readonly = False
@ -104,7 +86,7 @@ class Field(Component):
ctx = Context(Engine, self.getContextProperties())
try:
return expr(ctx)
except AttributeError, KeyError:
except (AttributeError, KeyError):
return u''
return self.default
def setDefaultValue(self, value):
@ -190,9 +172,9 @@ class Field(Component):
return dict(context=self, user=None)
@implementer(IFieldInstance)
class FieldInstance(object):
implements(IFieldInstance)
adapts(IField)
clientInstance = None
@ -361,7 +343,7 @@ class DateFieldInstance(NumberFieldInstance):
'DateFieldInstance: year out of range: %s, %s' %
(value, e))
self.setError('invalid_datetime')
except (TypeError, ValueError, DateTimeParseError), e:
except ((TypeError, ValueError, DateTimeParseError), e):
getLogger('cybertools').warn(
'DateFieldInstance: invalid datetime: %s, %s' % (value, e))
self.setError('invalid_datetime')

View file

@ -1,27 +1,10 @@
#
# Copyright (c) 2014 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# cybertools.composer.schema.schema
"""
Basic classes for schemas, i.e. sets of fields that may be used for creating
""" Basic classes for schemas, i.e. sets of fields that may be used for creating
editing forms or display views for objects.
"""
from zope.interface import implements
from zope.interface import implementer
from cybertools.composer.base import Component, Element, Compound
from cybertools.composer.base import Template
@ -29,10 +12,9 @@ from cybertools.composer.schema.interfaces import ISchema, IFormState
from cybertools.util.jeep import Jeep
@implementer(ISchema)
class Schema(Template):
implements(ISchema)
name = u''
labelWidth = 'auto'
manager = None
@ -63,10 +45,9 @@ class Schema(Template):
return self.manager
@implementer(IFormState)
class FormState(object):
implements(IFormState)
def __init__(self, fieldInstances=None, changed=False, severity=0):
if fieldInstances is None:
fieldInstances = []

View file

@ -20,10 +20,12 @@ dependencies = [
"zope.app.rotterdam",
"zope.app.testing",
"zope.authentication",
"zope.browser",
"zope.browserpage",
"zope.catalog",
"zope.component",
"zope.container",
"zope.formlib",
"zope.i18nmessageid",
"zope.index",
"zope.interface",