允许用户在一个较大的文本块中高效地指定多个值。
z3c.quickentr的Python项目详细描述
Quick Entry
快速输入处理器允许用户有效地指定多个值 在一个较大的文本块中。处理器使用插件动态地定义 要处理的命令。
这种类型的输入不是针对普通用户,而是针对超级用户和 可以接受培训的用户。语法有目的地最小化到最大化。 输入速度。这种进入方式在现实生活中得到了验证 设置。
Processor Plugins
让我们先看看处理器插件,它可以处理 快速输入文本。第一个插件类型可以处理以下形式的字符串:
<shortName>=<value>
此插件的基本实现由包提供。让我们创造 可以处理名称的插件:
>>> from z3c.quickentry import plugin >>> class NamePlugin(plugin.ShortNamePlugin): ... shortName = 'nm' ... varName = 'name'
任何插件都是使用初始文本和可选位置实例化的 在错误报告期间使用:
>>> name = NamePlugin('nm=Stephan') >>> name <NamePlugin shortName='nm', varName='name'>>>> NamePlugin('nm=Stephan', 35) <NamePlugin shortName='nm', varName='name'>
现在您可以询问插件是否可以处理此文本:
>>> name.canProcess() True>>> NamePlugin('n=Stephan').canProcess() False >>> NamePlugin('Stephan').canProcess() False
有时处理器会在以后添加更多文本:
>>> name.text += ' Richter'
一旦快速输入处理器处理完所有工件,每个 实例化的插件被处理。此操作的结果是字典:
>>> name.process(None) {'name': u'Stephan Richter'}
第二种类型的插件与正则表达式匹配,以确定 可以处理一段文本。让我们创建一个电话号码插件:
>>> import re >>> class PhonePlugin(plugin.RegexPlugin): ... regex = re.compile('^[0-9]{3}-[0-9]{3}-[0-9]{4}$') ... varName = 'phone'
此插件还使用初始文本实例化:
>>> phone = PhonePlugin('978-555-5300') >>> phone <PhonePlugin varName='phone'>
现在您可以询问插件是否可以处理此文本:
>>> name.canProcess() True>>> PhonePlugin('(978) 555-5300').canProcess() False >>> PhonePlugin('+1-978-555-5300').canProcess() False
现在让我们处理插件:
>>> phone.process(None) {'phone': u'978-555-5300'}
如果文本发生更改,插件无法再分析文本,则 出现进程错误:
>>> phone.text += ' (ext. 2134)' >>> phone.process(None) Traceback (most recent call last): ... ProcessError: The regex did match anymore. Probably some text was added later that disrupted the pattern. (Position 0)
最后让我们看一个更高级的例子。我们希望能够 处理字符串“<;age>;<;gender>;”并将其解析为2个变量:
>>> from z3c.quickentry import interfaces>>> class AgeGenderPlugin(plugin.BasePlugin): ... regex = re.compile('([0-9]{1,3})([FM])') ... ... def canProcess(self): ... return self.regex.match(self.text) is not None ... ... def process(self, context): ... match = self.regex.match(self.text) ... if match is None: ... raise interfaces.ProcessError(self.position, u'Error here.') ... return {'age': int(match.groups()[0]), ... 'gender': unicode(match.groups()[1])}
现在让我们确保插件可以处理多个字符串:
>>> AgeGenderPlugin('27M').canProcess() True >>> AgeGenderPlugin('8F').canProcess() True >>> AgeGenderPlugin('101F').canProcess() True >>> AgeGenderPlugin('27N').canProcess() False >>> AgeGenderPlugin('M').canProcess() False >>> AgeGenderPlugin('18').canProcess() False
我们还要确保处理正确:
>>> from pprint import pprint >>> pprint(AgeGenderPlugin('27M').process(None)) {'age': 27, 'gender': u'M'} >>> pprint(AgeGenderPlugin('8F').process(None)) {'age': 8, 'gender': u'F'} >>> pprint(AgeGenderPlugin('101F').process(None)) {'age': 101, 'gender': u'F'}
当处理过程中的任何一点发生错误时,必须 提高:
>>> pprint(AgeGenderPlugin('27N').process(None)) Traceback (most recent call last): ... ProcessError: Error here. (Position 0)
上面的插件使用BasePlugin类来最小化 样板。基本插件要求您实现canProcess() 以及process():
>>> base = plugin.BasePlugin('some text')>>> base.canProcess() Traceback (most recent call last): ... NotImplementedError>>> base.process(None) Traceback (most recent call last): ... NotImplementedError
Executing Plugins
包的一个可选特性是插件能够应用 将数据直接解析到指定的上下文。最简单的例子是 只需在上下文上设置属性。对于这个用例,我们有一个混合 课程:
>>> class ExecutingAgeGenderPlugin(AgeGenderPlugin, plugin.SetAttributeMixin): ... pass
现在让我们创建一个可以存储属性的人:
>>> class Person(object): ... name = None ... phone = None ... age = None ... gender = None >>> stephan = Person()
现在我们将正在执行的年龄/性别插件应用到此人:
>>> stephan.age >>> stephan.gender>>> ExecutingAgeGenderPlugin('27M').apply(stephan)>>> stephan.age 27 >>> stephan.gender u'M'
Processors
处理器收集几个插件并处理一大块quick 输入文本。让我们为上面的插件创建一个处理器,使用默认的 空白字符作为字段分隔符:
>>> from z3c.quickentry import processor >>> info = processor.BaseProcessor() >>> info.plugins = (NamePlugin, PhonePlugin, AgeGenderPlugin)
处理器的最底层步骤是文本的解析;结果 是一系列插件实例:
>>> info.parse('nm=Stephan 27M') [<NamePlugin shortName='nm', varName='name'>, <AgeGenderPlugin '27M'>]
现在,让我们分析并处理使用部分或全部插件的简单文本:
>>> pprint(info.process('nm=Stephan 27M')) {'age': 27, 'gender': u'M', 'name': u'Stephan'}>>> pprint(info.process('978-555-5300 27M')) {'age': 27, 'gender': u'M', 'phone': u'978-555-5300'}>>> pprint(info.process('nm=Stephan 978-555-5300 27M')) {'age': 27, 'gender': u'M', 'name': u'Stephan', 'phone': u'978-555-5300'}
注意,您也可以使用包含空格的名称,因为姓氏 无法与其他插件匹配:
>>> pprint(info.process('nm=Stephan Richter 27M')) {'age': 27, 'gender': u'M', 'name': u'Stephan Richter'}
或者,您还可以提供一个处理上下文,用于 up值(例如词汇表):
>>> pprint(info.process('nm=Stephan Richter 27M', context=object())) {'age': 27, 'gender': u'M', 'name': u'Stephan Richter'}
现在我们将分隔字符改为逗号:
>>> info.separationCharacter = ',' >>> pprint(info.process('nm=Stephan Richter,27M', context=object())) {'age': 27, 'gender': u'M', 'name': u'Stephan Richter'}
但是如果找不到插件会发生什么。然后出现一个进程错误:
>>> info.process('err=Value', context=object()) Traceback (most recent call last): ... ProcessError: No matching plugin found. (Position 0)
Executing Processors
这些处理器可以在上下文中应用所有插件。让我们转换 其余可执行的插件:
^{bq号27}$现在,我们创建一个新用户并创建一个执行处理器:
>>> stephan = Person()>>> proc = processor.ExecutingBaseProcessor() >>> proc.plugins = ( ... ExecutingNamePlugin, ExecutingPhonePlugin, ExecutingAgeGenderPlugin)>>> proc.apply('nm=Stephan 978-555-5300 27M', stephan)>>> stephan.name u'Stephan' >>> stephan.phone u'978-555-5300' >>> stephan.age 27 >>> stephan.gender u'M'