按合同编程
deal的Python项目详细描述
deal–用于design by contract(dbc)编程的python库。
这是很好的assertdecorators风格的语句,可以验证函数输入、输出、可用操作和对象状态。目标是使测试更加容易,并检测代码中偶尔在测试中丢失的错误。
功能
- 功能声明。
- 自定义例外。
- 提出合同的例外。
- django表单样式验证程序。
- 属性设置不变验证。
- 动态分配属性和方法不变验证。
- 用于控制可用资源的修饰程序:禁止输入/输出、网络操作、引发异常
可用的装饰器
安装
pip3 install --user deal
快速启动
importreimportattrimportdealREX_LOGIN=re.compile(r'^[a-zA-Z][a-zA-Z0-9]+$')classPostAlreadyLiked(Exception):pass@deal.inv(lambdapost:post.visits>=0)classPost:visits:int=attr.ib(default=0)likes:set=attr.ib(factory=set)@deal.pre(lambdauser:REX_LOGIN.match(user),message='invalid username format')@deal.raises(PostAlreadyLiked)@deal.chain(deal.offline,deal.silent)deflike(self,user:str)->None:ifuserinself.likes:raisePostAlreadyLikedlikes.add(user)@deal.post(lambdaresult:'visits'inresult)@deal.post(lambdaresult:'likes'inresult)@deal.post(lambdaresult:result['likes']>0)@deal.puredefget_state(self):returndict(visits=self.visits,likes=len(self.likes))
现在,deal在运行时控制对象的条件和状态:
- @deal.inv在post中访问计数的控件总是非负的。
- @deal.pre检查用户名格式。我们假设它应该在以前的某个地方被一些漂亮的表单验证,这些表单带有用户友好的错误消息。所以,如果我们在这里传递了无效的登录名,那肯定是开发人员的错误。
- @deal.raises表示,唯一可能引发的异常是PostAlreadyLiked。
- @deal.chain(deal.offline, deal.silent)控制该函数没有网络请求,并且在stderr或stdout中没有输出。所以,如果我们在内部某处发出意外的网络请求,请让我们知道。
- deal.post检查get_state的结果格式。因此,所有外部代码都可以确保字段likes和visits始终在结果中表示,并且总是为正值。
如果代码违反某些条件,将引发deal.ContractError的子异常:
p=Post()p.visits=-1# InvContractError: