Design by Contract funktioniert nicht
Verfasst: Freitag 21. Juli 2006, 12:24
Hallo Leute
ich bin gerade daran ein grösseres Programm zu schreiben und möchte dafür den Design by Contract Ansatz benutzen. Ich habe dazu von http://www.nongnu.org/pydbc/ eines der Module runtergeladen, die den Approach unter Python implementieren.
Der Testcode, der zu dem Projekt geliefert wird, sieht so aus:
Mein Code sieht so aus:
Eigentlich sollte ja der assert in dict2AML die Tatsache auffangen, dass ein Integer übergeben wird und nicht ein Dictionary, aber irgendwie funktioniert das ganze Modul in meinem Code nicht. Was habe ich übersehen (das ganze wurde mehr oder weniger 1 zu 1 vom Beispiel übernommen...)
ich bin gerade daran ein grösseres Programm zu schreiben und möchte dafür den Design by Contract Ansatz benutzen. Ich habe dazu von http://www.nongnu.org/pydbc/ eines der Module runtergeladen, die den Approach unter Python implementieren.
Der Testcode, der zu dem Projekt geliefert wird, sieht so aus:
Code: Alles auswählen
# The contents of this file may be used and copied without restriction
# Copyright (c) Daniel Arbuckle, 2002
import os
# if os.environ['PY_DBC'] is nonexistant or empty, no contract
# checking will be performed. The usual way to set this would be
# from the command shell as an environment variable.
# if contract checking is not enabled, it imposes NO overhead
# during the execution of your program
os.environ['PY_DBC'] = 'true'
import dbc
__metaclass__ = dbc.DBC
class Foo:
# You can also turn on DBC for a specific class by specifying the __metaclass__ attribute:
# __metaclass__ = dbc.DBC
# Postcondition on a special name
def __init____post(self, ret):
assert hasattr(self, 'a')
def __init__(self):
self.a = 1
# Class invariant, checked each time a member is called or an attribute accessed
def __invar(self):
assert self.a
# Precondition for function foo, checked just before foo
# Preconditions are passed the same arguments as the called function (including varargs and keyword args)
def foo__pre(self, b):
# If a condition fails, it should raise an exception of some sort. assert() is a good way to do that
assert not isinstance(b, str)
def foo(self, b):
self.a = b
# Postcondition for foo, checked just after foo
# Postconditions are passed the return value of the call
def foo__post(self, ret):
assert self.a < 5
f = Foo() # calls __init__, then calls __invar
f.foo(2) # calls foo__pre, foo, foo__post and __invar
# f.foo('bar') # would trigger the assert in foo__pre
# f.foo(10) # would trigger the assert in foo__post
# f.foo(0) # would trigger the assert in __invar
f.a = 3 # assigns the value, then checks __invar
f.a = 7 # __invar doesn't check the cap on a. be careful to put your obligations in the right place
# f.a = 0 # would trigger the assert in __invar
Code: Alles auswählen
#! /usr/bin/python
# -*- coding: utf8
import pexpect, os, string, re, codecs, dbc, os.path
from BeautifulSoup import BeautifulSoup
class CANXML:
"""This class provides all the functionality to read, write and extract information from CAN projects XML-Files."""
def __init__(self, STDENC=u"utf8", AMLENC=None, IMLENC=None, CMLENC=None):
self.stdenc = STDENC
if not AMLENC:
self.amlenc=self.stdenc
else:
self.amlenc=AMLENC
if not IMLENC:
self.imlenc=self.stdenc
else:
self.imlenc=IMLENC
if not CMLENC:
self.cmlenc=self.stdenc
else:
self.cmlenc=CMLENC
self.amltags = (u"zeitung", u"autor", u"datum", u"rubrik", u"seite", u"titel", u"text")
def __init____post(self, ret):
print "__init__post"
assert self.stdenc and isinstance(self.stdenc, unicode)
assert self.amlenc and isinstance(self.amlenc, unicode)
assert self.imlenc and isinstance(self.imlenc, unicode)
assert self.cmlenc and isinstance(self.cmlenc, unicode)
def __invar(self):
assert self.stdenc and isinstance(self.stdenc, unicode)
assert self.amlenc and isinstance(self.amlenc, unicode)
assert self.imlenc and isinstance(self.imlenc, unicode)
assert self.cmlenc and isinstance(self.cmlenc, unicode)
assert self.amltags and isinstance(self.amltags, (tuple. list))
def loadAML__pre(self, file):
assert isinstance(file, unicode)
def loadAML(self, file):
f = codecs.open(file, "r", self.amlenc)
self.aml = f.read()
f.close()
if isinstance(self.aml, unicode):
pass
else:
f = codecs.open(file, "r", self.stdenc)
self.aml = f.read()
f.close()
if isistance(self.aml, unicode):
pass
else:
raise "EncodingError: Set proper encoding for AML files!"
return self.aml
def loadAML__post(self, ret):
assert isinstance(self.aml, unicode)
def AML2dict__pre(self, aml):
# Implement dtd-validation here!
assert isinstance(aml, unicode)
def AML2dict(self, xml):
delpatterns = (u"<dl>.*?</dl>", u"<br />", u"<sm>.*?</sm>", u"<nt>.*?</nt>", u"<zt>.*?</zt>", u"<ut>", u"<ld>", u"</ld>")
patterns = u"<(.+?)>.*?</"
soup = BeautifulSoup(xml)
self.dictionary = {}
for tag in self.amltags:
if not tag == "text":
thing = unicode(soup(tag)[0])
remover = "</?%s>" % tag
thing = re.sub(remover, "", thing)
else:
thing = unicode(soup(tag)[0])
remover = "</?%s>" % tag
thing = re.sub(remover, "", thing)
## for d in delpatterns:
## thing = re.sub(d, u" ", thing)
## thing = re.sub(u"</ut>", u" . ", thing)
self.dictionary.update( { tag : thing.strip() } )
return self.dictionary
def AML2dict__post(self, ret):
assert isinstance(self.dictionary, dict)
for key in self.dictionary:
assert isinstance(self.dictionary[key], unicode)
def dict2AML__pre(self, dic, file, OUTENC=None):
print "doing dict2AML_pre"
assert isinstance(dic, dict)
assert isinstance(file, unicode)
assert isinstance(OUTENC, (unicode, None.__class__))
for key in self.amltags:
assert dic.has_key(key)
def dict2AML(self, dic, file, OUTENC=None):
xmlcode = """<?xml version="1.0" encoding="%(enc)s" standalone="yes"?>
<artikel>
<zeitung>
%(zeitung)s
</zeitung>
<autor>
%(autor)s
</autor>
<datum>
%(datum)s
</datum>
<rubrik>
%(rubrik)s
</rubrik>
<seite>
%(seite)s
</seite>
<titel>
%(titel)s
</titel>
<text>
%(text)s
</text>
</artikel>"""
self.amlfile = file
if not OUTENC:
enc = self.stdenc
else:
enc = OUTENC
dic["enc"] = enc
try:
f = codecs.open(self.amlfile, "w", enc)
code = xmlcode % dic
f.write(code)
f.close()
except "IOError":
raise "IOError: Could not write file"
except:
raise "dict2amlError: Something went wrong while writing the xml code"
def dict2aml__post(self, ret):
os.path.exists(self.amlfile)
# Implement some check for correct format here
if __name__ == "__main__":
os.environ['PY_DBC'] = 'true'
## os.system("echo $PY_DBC")
__metaclass__ = dbc.DBC
canxml = CANXML(AMLENC=u"latin_1")
stuff = canxml.loadAML(u"/home/william/Coding/can/Input/test/nzz_2003-08-18_0002772.xml")
dictionary = canxml.AML2dict(stuff)
canxml.dict2AML(1, "test.xml", "latin_1")
print dictionary