Permalink
Browse files

0.2 release

  • Loading branch information...
0 parents commit f6319005a570fd45b8076d8c90e3d623eb14d975 hltbra committed Apr 26, 2009
Showing with 323 additions and 0 deletions.
  1. +12 −0 INSTALL
  2. +21 −0 LICENSE
  3. +24 −0 README
  4. +22 −0 setup.py
  5. +1 −0 src/__init__.py
  6. +18 −0 src/doctests/equal_to.txt
  7. +14 −0 src/doctests/false.txt
  8. +15 −0 src/doctests/have.txt
  9. +16 −0 src/doctests/into.txt
  10. +17 −0 src/doctests/none.txt
  11. +20 −0 src/doctests/thrown_by.txt
  12. +13 −0 src/doctests/true.txt
  13. +11 −0 src/run_all_doctests.py
  14. +119 −0 src/should_dsl.py
12 INSTALL
@@ -0,0 +1,12 @@
+To install should_dsl you just need to have setuptools installed (it's a dependency).
+
+There is just a little step to install should_dsl, and it is:
+$ python setup.py install # maybe you must be root
+
+Now you can use should_dsl!
+
+If you don't have setuptools installed or don't want to download it, you can just copy the should_dsl.py file to your python site-packages directory.
+For example:
+$ cp should_dsl.py /usr/lib/python2.5/lib/site-packages
+
+Enjoy it!
21 LICENSE
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2009 Hugo Lopes Tavares
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
24 README
@@ -0,0 +1,24 @@
+Should DSL implemented in Python
+
+The goal is to write a "should" DSL in Python to be as clear as possible.
+
+It would be good to be as close as:
+
+ SOME_VALUE should be equal to ANOTHER VALUE
+ or
+ SOME_EXCEPTION should be thrown by SOME_CALLABLE
+ or
+ SOME_VALUE should not be into SOME_CONTAINER
+
+
+Nowadays, the closer it's got is to import DSLObject as _ (underscode) to make it more "invisible".
+
+For example:
+
+_(1).should_be.equal_to(1), will be true
+_('should').should_have('oul'), will also be true
+
+A nice example of exceptions would be:
+def raise_zerodivisionerror():
+ return 1/0
+_(ZeroDivisionError).should_be.thrown_by(raise_zero_divisionerror)
@@ -0,0 +1,22 @@
+from setuptools import setup, find_packages
+import sys, os
+
+version = '0.2'
+
+setup(name='should_dsl',
+ version=version,
+ description="Should DSL",
+ long_description="",
+ classifiers=[],
+ keywords='bdd dsl python',
+ author='Hugo Lopes Tavares',
+ author_email='hltbra@gmail.com',
+ url='http://code.google.com/p/should-dsl/',
+ license='MIT License',
+ packages=['should_dsl'],
+ package_dir={'should_dsl': 'src'},
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=['setuptools'],
+ entry_points="",
+ )
@@ -0,0 +1 @@
+from should_dsl import *
@@ -0,0 +1,18 @@
+>>> from should_dsl import DSLObject as _
+
+>>> _(1).should_be.equal_to(1)
+True
+>>> _(2).should_be.equal_to(3)
+Traceback (most recent call last):
+ ...
+ShouldNotSatisfied: 2 is not equal to 3
+>>> _(1).should_not_be.equal_to(2)
+True
+>>> name = 'dsl'
+>>> _(name).should_be.equal_to('dsl')
+True
+>>> _(name).should_not_be.equal_to('dsl')
+Traceback (most recent call last):
+ ...
+ShouldNotSatisfied: dsl is equal to dsl
+
@@ -0,0 +1,14 @@
+>>> from should_dsl import DSLObject as _
+
+>>> _('spec' is not 'SPEC').should_not_be.false
+True
+
+>>> _(True).should_be.false
+Traceback (most recent call last):
+ ...
+ShouldNotSatisfied: True is not False
+
+>>> _(False).should_not_be.false
+Traceback (most recent call last):
+ ...
+ShouldNotSatisfied: False is False
@@ -0,0 +1,15 @@
+>>> from should_dsl import DSLObject as _
+
+>>> _([1,2,3]).should_have(1)
+True
+>>> _([1,2]).should_have(3)
+Traceback (most recent call last):
+ ...
+ShouldNotSatisfied: [1, 2] does not have 3
+>>> _([1,2]).should_not_have(3)
+True
+
+>>> _('should').should_not_have('oul')
+Traceback (most recent call last):
+ ...
+ShouldNotSatisfied: should does have oul
@@ -0,0 +1,16 @@
+>>> from should_dsl import DSLObject as _
+
+>>> _(1).should_be.into([1,2,3])
+True
+>>> _(1).should_not_be.into([1,2,3])
+Traceback (most recent call last):
+ ...
+ShouldNotSatisfied: 1 is into [1, 2, 3]
+
+>>> _(5).should_not_be.into([1,2,3])
+True
+
+>>> _(1).should_be.into([2])
+Traceback (most recent call last):
+ ...
+ShouldNotSatisfied: 1 is not into [2]
@@ -0,0 +1,17 @@
+>>> from should_dsl import DSLObject as _
+
+>>> _(None).should_be.none
+True
+>>> _(None).should_not_be.none
+Traceback (most recent call last):
+ ...
+ShouldNotSatisfied: None is None
+
+>>> _('Specification').should_not_be.none
+True
+
+>>> _('spec').should_be.equal_to('spec2')
+Traceback (most recent call last):
+ ...
+ShouldNotSatisfied: spec is not equal to spec2
+
@@ -0,0 +1,20 @@
+>>> from should_dsl import DSLObject as _
+
+>>> def divide_one_by_zero():
+... return 1 / 0
+>>> def divide_x_by_y(x, y):
+... return x / y
+>>> _(ZeroDivisionError).should_be.thrown_by(divide_one_by_zero)
+True
+>>> _(ZeroDivisionError).should_not_be.thrown_by(divide_one_by_zero)
+Traceback (most recent call last):
+ ...
+ShouldNotSatisfied: ...ZeroDivisionError... is thrown by <function divide_one_by_zero at ...>
+
+>>> _(ZeroDivisionError).should_be.thrown_by(divide_x_by_y, 5, 0)
+True
+
+>>> _(ZeroDivisionError).should_be.thrown_by(divide_x_by_y, 2, 1)
+Traceback (most recent call last):
+ ...
+ShouldNotSatisfied: ...ZeroDivisionError... is not thrown by <function divide_x_by_y at ...>
@@ -0,0 +1,13 @@
+>>> from should_dsl import DSLObject as _
+
+>>> _('spec' is not 'SPEC').should_be.true
+True
+>>> _('spec' is not 'SPEC').should_not_be.true
+Traceback (most recent call last):
+ ...
+ShouldNotSatisfied: True is True
+
+>>> _('spec' is 'SPEC').should_be.true
+Traceback (most recent call last):
+ ...
+ShouldNotSatisfied: False is not True
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+import doctest
+import os
+
+if __name__ == '__main__':
+ doctests_path = os.path.join(os.path.dirname(__file__), 'doctests')
+ for doctest_file in os.listdir(doctests_path):
+ if not doctest_file.endswith('.txt'):
+ continue
+ doctest.testfile(os.path.join(doctests_path, doctest_file),
+ optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS)
@@ -0,0 +1,119 @@
+'''
+ This is a simple experiment with internal DSLs
+ using Python Language.
+ The goal is to write some kind of BDD.
+
+
+ Here is the point to try make everything
+ as transparent as possible
+ ``from should_dsl import DSLObject as _``
+
+ Take a look at the doctests (doctests folder)
+'''
+
+class DSLCommon(object):
+ def __init__(self, value, negate=False):
+ self._value = value
+ self._negate = negate
+
+ def _negate_or_not(self, value):
+ if self._negate:
+ return not value
+ return value
+
+
+class DSLObject(object):
+ def __init__(self, value):
+ self._value = value
+
+ @property
+ def should_be(self):
+ return Should(self._value, negate=False)
+
+ @property
+ def should_not_be(self):
+ return Should(self._value, negate=True)
+
+ def should_have(self, value):
+ return Should(self._value, negate=False).have(value)
+
+ def should_not_have(self, value):
+ return Should(self._value, negate=True).have(value)
+
+
+class ShouldNotSatisfied(Exception):
+ '''it's raised when some should is not satisfied'''
+
+
+class Should(DSLCommon):
+ @property
+ def success(self):
+ return True
+
+ def fail(self, message):
+ raise ShouldNotSatisfied(message)
+ return False
+
+ @property
+ def none(self):
+ if self._negate_or_not(self._value == None):
+ return self.success
+ negate = ''
+ if self._negate == False:
+ negate = 'not '
+ return self.fail("%s is %sNone" % (self._value, negate))
+
+ @property
+ def true(self):
+ if self._negate_or_not(self._value):
+ return self.success
+ negate = ''
+ if self._negate == False:
+ negate = 'not '
+ return self.fail("%s is %sTrue" % (self._value, negate))
+
+ @property
+ def false(self):
+ if self._negate_or_not(self._value) == False:
+ return self.success
+ negate = ''
+ if self._negate == False:
+ negate = 'not '
+ return self.fail("%s is %sFalse" % (self._value, negate))
+
+ def equal_to(self, value):
+ if self._negate_or_not(value == self._value):
+ return self.success
+ negate = ''
+ if self._negate == False:
+ negate = 'not '
+ return self.fail("%s is %sequal to %s" % (self._value, negate, value))
+
+ def into(self, container):
+ if self._negate_or_not(self._value in container):
+ return self.success
+ negate = ''
+ if self._negate == False:
+ negate = 'not '
+ return self.fail("%s is %sinto %s" % (self._value, negate, container))
+
+ def have(self, value):
+ if self._negate_or_not(value in self._value):
+ return self.success
+ negate = ''
+ if self._negate == False:
+ negate = 'not '
+ return self.fail("%s does %shave %s" % (self._value, negate, value))
+
+ def thrown_by(self, callable_object, *args, **kw):
+ try:
+ callable_object(*args, **kw)
+ if self._negate == False:
+ return self.fail("%s is not thrown by %s" % (str(self._value),
+ callable_object))
+ except self._value:
+ if self._negate == True:
+ return self.fail("%s is thrown by %s" % (str(self._value),
+ callable_object))
+ return True
+

0 comments on commit f631900

Please sign in to comment.