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