[Zope3-checkins] CVS: zopeproducts/pypgsqlda/pgtypes - __init__.py:1.1.2.1 _geometry.py:1.1.2.1 _null.py:1.1.2.1
Christian 'Tiran' Heimes
heimes@faho.rwth-aachen.de
Mon, 7 Apr 2003 12:18:51 -0400
Update of /cvs-repository/zopeproducts/pypgsqlda/pgtypes
In directory cvs.zope.org:/tmp/cvs-serv6910/pgtypes
Added Files:
Tag: tiran-pypgsql_types-branch
__init__.py _geometry.py _null.py
Log Message:
* first test release of pgtypes
=== Added File zopeproducts/pypgsqlda/pgtypes/__init__.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""special types for the pyPgSQL Database Adapter
$Id: __init__.py,v 1.1.2.1 2003/04/07 16:18:50 tiran Exp $
"""
from _null import Null
from _geometry import Point2d, Box2d, Circle2d, OpenPath, ClosedPath, \
isOpenPath, isClosedPath
=== Added File zopeproducts/pypgsqlda/pgtypes/_geometry.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Geometric object implementation
$Id: _geometry.py,v 1.1.2.1 2003/04/07 16:18:50 tiran Exp $
"""
from zope.proxy.context import ContextMethod
from interface import geometric
import re
from math import pi
# matching an open path e.g. [(0,0),(1,1)]
openPath = re.compile(r"^\[\(.*\)\]$")
# matching a closed path e.g. ((0,0),(1,1))
closedPath = re.compile(r"^\(\(.*\)\)$")
# group a circle e.g. <(1,1),0.5> into (1.0,1.0) as the middle point
# and 0.5 as the radius
groupCircle = re.compile(r"^<(\([\d.]+,[\d.]+\)),([\d.]+)>$")
# group a single point e.g. (0,1) into 0 as the x value and 1 as the y value
groupPoint = re.compile(r"^\(([\d.]+),([\d.]+)\)$")
# group a path or a box e.g.((0,0),(1,1)) or [(0,0),(1,1)] into a
# list of points
groupPointList = re.compile(r"(\([\d.]+,[\d.]+\))")
def isOpenPath(data):
return openPath.match(unicode(data))
def isClosedPath(data):
return closedPath.match(unicode(data))
class GeometricError(Exception):
"""XXX
"""
pass
class GeometricInfinite(object):
"""
"""
def __str__(self):
return u"INF"
__str__ = ContextMethod(__str__)
def __call__(self):
return self.__str__
__call__ = ContextMethod(__call__)
def __repr__(self):
return self.__str__()
__repr__ = ContextMethod(__repr__)
class Geometric2d(object):
__implements__ = geometric.IGeometric2d
def __init__(self):
self._data = None
return NotImplemented
isClosed = property(lambda: False, None, None)
isOpen = property(lambda: False, None, None)
length = property(lambda: 0, None, None)
def __str__(self):
return unicode(self._data)
__str__ = ContextMethod(__str__)
def __call__(self):
return self.__str__
__call__ = ContextMethod(__call__)
def __repr__(self):
return self.__str__()
__repr__ = ContextMethod(__repr__)
def __iter__(self):
return self
def next(self):
"""iterator function
"""
return StopIteration
def __len__(self):
return 0
class Shape2d(Geometric2d):
__implements__ = geometric.IShape2d, Geometric2d.__implements__
area = property(lambda: 0, None, None, None)
class Point2d(Geometric2d):
"""Simple geometric point
"""
__implements__ = geometric.IPoint2d, Geometric2d.__implements__
def __init__(self, data):
self._data = data
self._x = None
self._y = None
self._iter = 0
def _convert(self):
"""
"""
if self._x and self._y: return # already converted data
point = groupPoint.match(unicode(self._data)).groups()
if len(point) != 2:
raise GeometricError, u"'%s' has wrong size" % data
self.x = point[0]
self.y = point[1]
def _getX(self):
self._convert()
return self._x
def _setX(self, value):
self._x = float(value)
x = property(_getX, _setX, None, 'x coordinate as float')
def _getY(self):
self._convert()
return self._y
def _setY(self, value):
self._y = float(value)
y = property(_getY, _setY, None, 'y coordinate as float')
def next(self):
"""next() support for iterator"""
if self._iter == 0:
self._iter = 1
return self
else:
raise StopIteration
def __len__(self):
return 1
class Box2d(Shape2d):
__implements__ = geometric.IBox2d, Shape2d.__implements__
def __init__(self, data):
self._data = data
self._points = []
self._iter = 0
def _convert(self):
if self._points: return
box = groupPointList.findall(unicode(data))
if len(box) != 2:
raise GeometricError, u"'%s' has wrong size" % data
for p in box:
self._points.append(Point2d(p))
def _getUR(self):
self._convert()
return self._points[0]
def _setUR(self, value):
if not isinstance(value, Point2d):
raise TypeError, u"type must be Point2d"
self._points[0] = value
upperRight = property(_getUR, _setUR, None)
def _getLL(self):
self._convert()
return self._points[1]
def _setLL(self, value):
if not isinstance(value, Point2d):
raise TypeError, u"type must be Point2d"
self._points[1] = value
lowerLeft = property(_getLL, _setLL, None)
def _getArea(self):
return (upperRight.x - lowerLeft.x) * (upperRight.y - lowerLeft.y)
area = property(_getArea, None, None)
def _getLength(self):
return 2*((upperRight.x - lowerLeft.x) + (upperRight.y - lowerLeft.y))
length = property(_getLength, None, None)
isClosed = property(lambda: True, None, None)
def __len__(self):
return 2
def next(self):
if self._iter < 2:
return self._points[self._iter]
self._iter += 1
else:
raise StopIteration
class Circle2d(Shape2d):
__implements__ = geometric.ICircle2d, Shape2d.__implements__
def __init__(self, data):
self._data = data
self._center = None
self._radius = None
def _convert(self):
if self._center and self._radius: return
circle = groupCircle.match(unicode(data)).groups()
if len(circle) != 2:
raise GeometricError, u"'%s' has wrong size" % data
self._center = Point2d(circle[0])
self._radius = float(circle[1])
def _getCenter(self):
self._convert()
return self._center
def _setCenter(self, value):
if not isinstance(value, Point2d):
return TypeError, u"type must be Point2d"
self._center = value
center = property(_getCenter, _setCenter, None)
def _getRadius(self):
self._convert()
return self._radius
def _setRadius(self, value):
self._radius = float(value)
radius = property(_getRadius, _setRadius, None)
def _getArea(self):
return pi*self.radius**2
area = property(_getArea, None, None)
def _getLength(self):
return 2*pi*self.radius
length = property(_getLength, None, None)
isClosed = property(lambda: True, None, None)
def __len__(self):
return 1
def next(self):
if self._iter == 0:
self._iter = 1
return self.center
else:
raise StopIteration
class OpenPath(Geometric2d):
__implements__ = geometric.IBox2d, Geometric2d.__implements__
def __init__(self, data):
self._data = data
self._iter = 0
self._points = None
class ClosedPath(Geometric2d):
__implements__ = geometric.IBox2d, Geometric2d.__implements__
def __init__(self, data):
self._data = data
self._iter = 0
self._points = None
=== Added File zopeproducts/pypgsqlda/pgtypes/_null.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""
$Id: _null.py,v 1.1.2.1 2003/04/07 16:18:50 tiran Exp $
taken from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/68205
>From the original documentation:
********************************
This is a sample implementation of the 'Null Object' design pattern.
Roughly, the goal with Null objects is to provide an 'intelligent'
replacement for the often used primitive data type None in Python or
Null (or Null pointers) in other languages. These are used for many
purposes including the important case where one member of some group
of otherwise similar elements is special for whatever reason. Most
often this results in conditional statements to distinguish between
ordinary elements and the primitive Null value.
Among the advantages of using Null objects are the following:
- Superfluous conditional statements can be avoided
by providing a first class object alternative for
the primitive value None.
- Code readability is improved.
- Null objects can act as a placeholder for objects
with behaviour that is not yet implemented.
- Null objects can be replaced for any other class.
- Null objects are very predictable at what they do.
To cope with the disadvantage of creating large numbers of passive
objects that do nothing but occupy memory space Null objects are
often combined with the Singleton pattern.
For more information use any internet search engine and look for
combinations of these words: Null, object, design and pattern.
Dinu C. Gherman,
August 2001
"""
from interface.null import INull
from zope.proxy.context import ContextMethod
class Null(object):
"""Postgres NULL type
From the original documentation:
********************************
A class for implementing Null objects.
This class ignores all parameters passed when constructing or
calling instances and traps all attribute and method requests.
Instances of it always (and reliably) do 'nothing'.
The code might benefit from implementing some further special
Python methods depending on the context in which its instances
are used. Especially when comparing and coercing Null objects
the respective methods' implementation will depend very much
on the environment and, hence, these special methods are not
provided here.
"""
__implements__ = INull
def __init__(self, *args, **kwargs):
"Ignore parameters."
return None
def __call__(self, *args, **kwargs):
"Ignore method calls."
return self.__str__
__call__ = ContextMethod(__call__)
def __getattr__(self, mname):
"Ignore attribute requests."
return self
def __setattr__(self, name, value):
"Ignore attribute setting."
return self
def __delattr__(self, name):
"Ignore deleting attributes."
return self
def __repr__(self):
"Return a string representation."
return u"<NULL>"
def __str__(self):
"Convert to a string and return it."
return u"NULL"
__str__ = ContextMethod(__str__)
def __nonzero__(self):
"""
from the 'Python Cockbook', even Null() == Null() is false
"""
return 0