允许用户在一个较大的文本块中有效地指定多个值。
项目描述
快速输入
快速输入处理器允许用户在一个较大的文本块中高效地指定多个值。处理器使用插件动态定义要处理的命令。
此类输入并非针对普通用户,而是针对高级用户和可以接受培训的用户。语法被有意简化以最大化输入速度。这种方法在实际环境中已得到验证。
处理器插件
让我们首先看看处理器插件,它可以处理快速输入文本的一部分。第一种插件类型可以处理如下形式的字符串:
<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
执行插件
包的可选功能是插件能够将解析的数据直接应用于指定的上下文。这种最简单的情况是将属性设置在上下文中。为此,我们有一个混合类
>>> 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'
处理器
处理器收集了几个插件并处理了一块较大的快速输入文本。让我们使用默认空格字符作为字段分隔符创建一个用于上述插件的处理器
>>> 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'}
可选地,您还可以提供可以用于查找值(例如词汇表)的处理上下文
>>> 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)
执行处理器
这些处理器可以将所有插件应用于上下文。让我们将剩余的插件转换为可执行
>>> class ExecutingNamePlugin(NamePlugin, plugin.SetAttributeMixin): ... pass>>> class ExecutingPhonePlugin(PhonePlugin, plugin.SetAttributeMixin): ... pass
现在让我们创建一个新的用户并创建一个执行处理器
>>> 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'
变更
0.1 (2010-08-23)
初始公共发布。
项目详情
z3c.quickentry-0.1.tar.gz的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 65b5ce7596735ef2413a2448b55fcdfd913e2ab9581f30f6e34e0437d919d83f |
|
MD5 | 79d431a47255e1a96e6daa77c98cb7eb |
|
BLAKE2b-256 | 313a8d5f75304afde823840cbe07c33dace846a004eb57cb5386f77dc225d935 |