Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Constraints -//- first release -//- Flexible abstract class based validation for attributes, functions and code blocks

10 views
Skip to first unread message

Nathan Rice

unread,
Jan 26, 2012, 2:36:29 PM1/26/12
to python-list, python-ann...@python.org
PyPi name: constraintslib (you'll be dissapointed if you get
constraints by accident)
Docs: http://packages.python.org/constraintslib/
Github: https://github.com/nathan-rice/Constraints

>From the docs:

Constraints - Sleek contract-style validation tools
===================================================

Constraints provides flexible validation tools for a variety of circumstances.
All validation in constraints is done by type checking. Constraints provides
a special abstract base class (Constraints) which facilitates on the fly
construction of validation types. Constraints also provides a special class
(Symbol) which can be used to generate natural, easy to read
constraint expressions.

for example::

>>> from constraints.proxy import Symbol
>>> from constraints.constraints import Constraints
>>> X = Symbol()
>>> SizeConstraint = Constraints(X * 2 + 1 >= 5)
>>> ModuloConstraint = Constraints(X % 2 != 0, X != 3)
>>> CharacterConstraint = Constraints(X[-1] == "h")
# My apologies for the lambda spam. I provide some functions in
# constraints.util for this purpose...
>>> callable_expr = lambda x: all(lambda x: isinstance(x, SizeConstraint), x)
>>> CollectionConstraint = Constraint(callable_expr)
>>> isinstance(1, SizeConstraint)
False
>>> isinstance(2, SizeConstraint)
True
>>> isinstance(1, ModuloConstraint)
True
>>> isinstance("blah", CharacterConstraint)
True
>>> isinstance([2, 3, 4, 5], CollectionConstraint)
True

Constraint instances also provide descriptors which will verify values at set
time. For example::

>>> class Foo(object):
... x = Constraints(X > 2)
...
>>> bar = Foo()
>>> bar.x = 1
Traceback (most recent call last):
...
AssertionError: Specified value (1) does not satisfy this constraint

Design by contract style preconditions, postconditions and invariants are also
supported, and can be used either as context managers or function decorators::

>>> x_pre = SizeConstraint.precondition("x")
>>> x_post = SizeConstraint.postcondition("x")
>>> x = 1
>>> with x_pre:
... do_stuff()
...
Traceback (most recent call last):
...
AssertionError: The value (1) did not meet the specified pre-condition
>>> x = 5
>>> with x_post:
... x -= 4
...
Traceback (most recent call last):
...
AssertionError: The value (1) did not meet the specified post-condition
>>> @x_pre
... def foo(x):
... return x
...
>>> foo(1)
Traceback (most recent call last):
...
AssertionError: The value (1) did not meet the specified pre-condition
>>> @x_post
... def foo(x):
... return x - 5
...
>>> foo(6)
Traceback (most recent call last):
...
AssertionError: The value (1) did not meet the specified post-condition

Symbol objects are very flexible, and provide a nice
way to specify your constraints without resorting to a domain specific language.
Symbol objects are fairly simple; whenever an operation is performed on them,
they capture it and return a new Symbol object wrapping the operation so that
it can be performed with concrete input at a later time. There are exceptions
to this, for example isinstance, which uses the metaclass method, and the type
constructors (str, int, bool, etc) which throw an error if the correct type is
not returned.

Devin Jeanpierre

unread,
Jan 26, 2012, 2:51:30 PM1/26/12
to Nathan Rice, python-list
Ooh, runtime turing-complete dependent-types. :)

I'm not sure if you're aware of the literature on this sort of thing.
It's nice reading. A library such as this that's designed for it could
be used for static checks as well.

Probably deserves a better name than "constraintslib", that makes one
think of constraint satisfaction.

On Thu, Jan 26, 2012 at 2:36 PM, Nathan Rice
<nathan.ale...@gmail.com> wrote:
> Design by contract style preconditions, postconditions and invariants are also
> supported, and can be used either as context managers or function decorators::

Any way to get them to raise a different error, such as ValueError (in
particular for preconditions)?

-- Devin

Nathan Rice

unread,
Jan 26, 2012, 3:24:09 PM1/26/12
to python-list
On Thu, Jan 26, 2012 at 2:51 PM, Devin Jeanpierre
<jeanpi...@gmail.com> wrote:
> Ooh, runtime turing-complete dependent-types. :)
>
> I'm not sure if you're aware of the literature on this sort of thing.
> It's nice reading. A library such as this that's designed for it could
> be used for static checks as well.

Actually, that is kind of the direction I was going :)

One of the nice things about Haskell is that the language is designed
in a way that is conducive to
proving things about your code. A side benefit of being able to prove
things about your code is that
in some cases you will be able to derive code just from well crafted
specifications (like higher order
Prolog). This isn't a game changer yet, but with advances in theorem
proving software and a thoughtful
language ontology, I could see it taking off very soon. Dijkstra was
focused primarily on this area for the
last 25 years of his life.

> Probably deserves a better name than "constraintslib", that makes one
> think of constraint satisfaction.

As you can probably tell from my other projects, I'm bad at coming up
with snappy names.

> Any way to get them to raise a different error, such as ValueError (in
> particular for preconditions)?

Currently, no. I would like to add an event mechanism, or some kind
of function hooks (ala Enthought Traits but much lighter). I'm sure
I'll come up with something soon :)

Nathan

Devin Jeanpierre

unread,
Jan 26, 2012, 6:24:53 PM1/26/12
to Nathan Rice, python-list
On Thu, Jan 26, 2012 at 3:24 PM, Nathan Rice
<nathan.ale...@gmail.com> wrote:
> One of the nice things about Haskell is that the language is designed
> in a way that is conducive to
> proving things about your code.  A side benefit of being able to prove
> things about your code is that
> in some cases you will be able to derive code just from well crafted
> specifications (like higher order
> Prolog).  This isn't a game changer yet, but with advances in theorem
> proving software and a thoughtful
> language ontology, I could see it taking off very soon.  Dijkstra was
> focused primarily on this area for the
> last 25 years of his life.

May I suggest a look at languages such as ATS and Epigram? They use
types that constrain values specifically to prove things about your
program. Haskell is a step, but as far as proving goes, it's less
powerful than it could be. ATS allows you to, at compile-time, declare
that isinstance(x, 0 <= Symbol() < len(L)) for some list L. So it
might align well with your ideas.

>> Probably deserves a better name than "constraintslib", that makes one
>> think of constraint satisfaction.
>
> As you can probably tell from my other projects, I'm bad at coming up
> with snappy names.

I'm bad at doing research on previous projects ;)

I'm sure another name will come up as the goals mature/solidify.

-- Devin

Nathan Rice

unread,
Jan 27, 2012, 1:38:44 AM1/27/12
to python-list
> May I suggest a look at languages such as ATS and Epigram? They use
> types that constrain values specifically to prove things about your
> program. Haskell is a step, but as far as proving goes, it's less
> powerful than it could be. ATS allows you to, at compile-time, declare
> that isinstance(x, 0 <= Symbol() < len(L)) for some list L. So it
> might align well with your ideas.

Thanks for the tip.

>>> Probably deserves a better name than "constraintslib", that makes one
>>> think of constraint satisfaction.
>>
>> As you can probably tell from my other projects, I'm bad at coming up
>> with snappy names.
>
> I'm bad at doing research on previous projects ;)

I guess I'm not plugging my other projects enough... You should check
out elementwise.

Thanks,

Nathan

Jon Clements

unread,
Jan 27, 2012, 4:59:44 PM1/27/12
to
On Jan 27, 6:38 am, Nathan Rice <nathan.alexander.r...@gmail.com>
wrote:
I love elementwise and this one - thanks.

If I can be so bold, I would call it 'contracts'. Or, if you want to
be more imaginative and esoteric - 'judge'/'barrister'/'solicitor'.

Thanks again,

Jon.
0 new messages