[英]Enthought traits.api TraitList() doesn't seem to support an item_validator
In some applications, I've found that Enthought Traits.api is a helpful addition to support static variable types in python.在某些应用程序中,我发现Enthought Traits.api对支持 python 中的 static 变量类型很有帮助。
I'm trying to use the TraitList()
item_validator
keyword, but using the item_validator
keyword threw an error... I tried this...我正在尝试使用
TraitList()
item_validator
关键字,但使用item_validator
关键字会引发错误...我试过这个...
from traits.api import HasTraits, HasRequiredTraits, TraitList, TraitError
from traits.api import Regex, Enum
def garage_item_validator(item):
"""Validate item adjectives and reject pink or floral items"""
try:
if isinstance(item, Tool):
if item.adjective!="pink" or item.adjective!="floral":
return item
else:
raise ValueError()
except ValueError():
raise TraitError(f"Cannot put {item} in the Garage()")
class Tool(HasRequiredTraits):
name = Regex(regex=r"[Ww]rench|[Ll]awnmower", required=True)
adjective = Enum(*["brown", "rusty", "pink", "floral"], required=True)
def __init__(self, name, adjective):
self.name = name
self.adjective = adjective
def __repr__(self):
return """<Tool: {}>""".format(self.name)
class Garage(HasTraits):
things = TraitList(Tool, item_validator=garage_item_validator) # <---- TraitList() doesn't work
def __init__(self):
self.things = list()
if __name__=="__main__":
my_garage = Garage()
my_garage.things.append(Tool("Lawnmower", "brown"))
my_garage.things.append(Tool("wrench", "pink"))
print(my_garage)
This throws: TypeError: __init__() got an unexpected keyword argument 'item_validator'
although the TraitList docs clearly say item_validator
is supported.这会抛出:
TypeError: __init__() got an unexpected keyword argument 'item_validator'
尽管TraitList 文档明确表示支持item_validator
。
I also tried to use a traits.api List()
, but it just silently ignores the item_validator
keyword.我还尝试使用traits.api
List()
,但它只是默默地忽略了item_validator
关键字。
What should I use to validate the contents of a traits list?我应该使用什么来验证特征列表的内容?
TraitList
isn't a Trait
, but rather a subclass of list
that performs validation and fires events. TraitList
不是Trait
,而是执行验证和触发事件的list
的子类。 It is used internally by the List
trait:它由
List
特征在内部使用:
>>> from traits.api import HasStrictTraits, List, Int
>>> class Example(HasStrictTraits):
... x = List(Int)
...
>>> example = Example()
>>> example.x
[]
>>> type(example.x)
<class 'traits.trait_list_object.TraitListObject'>
>>> type(example.x).mro()
[<class 'traits.trait_list_object.TraitListObject'>, <class 'traits.trait_list_object.TraitList'>, <class 'list'>, <class 'object'>]
and it gets its item_validator
set by the List
trait:并通过
List
特征获取其item_validator
设置:
>>> example.x.item_validator
<bound method TraitListObject._item_validator of []>
So although there is no hook to change this validator, it does use the validator from the Trait used as the trait
argument the List
( Int
in the above example, so the list will only hold integer items).因此,尽管没有钩子来更改此验证器,但它确实使用了 Trait 中的验证器,用作
List
的trait
参数(在上例中为Int
,因此列表将仅包含 integer 项)。
>>> example.x.append("five")
Traceback (most recent call last):
...
traits.trait_errors.TraitError: Each element of the 'x' trait of an Example instance must be an integer, but a value of 'five' <class 'str'> was specified.
So you can achieve your goal by writing a custom trait that validates the way that you want.因此,您可以通过编写一个验证您想要的方式的自定义特征来实现您的目标。
In your example you want the items to be instances of Tool
with certain properties for the adjective
, so an Instance trait is a good starting point:在您的示例中,您希望这些项目是
Tool
具有adjective
某些属性的实例,因此 Instance 特征是一个很好的起点:
from traits.api import BaseInstance, HasTraits, List
class GarageTool(BaseInstance):
def __init__(self, **metadata):
super().__init__(klass=Tool, allow_none=False, **metadata)
def validate(self, object, name, value):
# validate it is an instance of Tool
value = super().validate(object, name, value)
if value.adjective in {"pink", "floral"}:
self.error(object, name, value)
return value
def info(self):
# give better error messages
return "a Tool which is neither pink nor floral"
class Garage(HasTraits):
things = List(GarageTool())
if __name__ == "__main__":
my_garage = Garage()
my_garage.things.append(Tool("Lawnmower", "brown"))
# now, pink correctly fails in garage_item_validator()
my_garage.things.append(Tool("wrench", "pink")) # <-- pink fails
which gives an error as desired:根据需要给出错误:
TraitError: Each element of the 'things' trait of a Garage instance must be a Tool which is neither pink nor floral, but a value of <__main__.Tool object at 0x7f899ad89830> <class '__main__.Tool'> was specified.
I made a mistake in my previous attempts...我在之前的尝试中犯了一个错误......
This is wrong... Tool
should be Tool()
...这是错误的...
Tool
应该是Tool()
...
class Garage(HasTraits):
things = TraitList(Tool, item_validator=garage_item_validator)
This is correct...这是对的...
class Garage(HasTraits):
things = TraitList(Tool(), item_validator=garage_item_validator)
Additionally, I found that I can manually assign self.things.item_validator
after initializing the Garage()
此外,我发现我可以在初始化
Garage()
之后手动分配self.things.item_validator
This also runs correctly...这也可以正确运行...
from traits.api import HasTraits, HasRequiredTraits, TraitList, TraitError
from traits.api import Regex, List, Enum, Either
def garage_item_validator(item):
try:
if isinstance(item, Tool):
if item.adjective!="pink" and item.adjective!="floral":
return item
else:
raise ValueError(item.adjective, item.name)
else:
raise ValueError(item.adjective, item.name)
except Exception:
raise ValueError(item.adjective, item.name)
class Tool(HasRequiredTraits):
name = Regex(regex=r"[Ww]rench|[Ll]awnmower", required=True)
adjective = Enum(*["brown", "rusty", "pink", "floral"])
def __init__(self, name=None, adjective=None):
self.name = name
self.adjective = adjective
def __repr__(self):
return """<Tool: {}>""".format(self.name)
class Garage(HasTraits):
things = TraitList(Tool())
def __init__(self):
self.things = list()
self.things.item_validator = garage_item_validator
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Manually assign item_validator attr **after initializing self.things**
if __name__=="__main__":
my_garage = Garage()
my_garage.things.append(Tool("Lawnmower", "brown"))
# now, pink correctly fails in garage_item_validator()
my_garage.things.append(Tool("wrench", "pink")) # <-- pink fails
print(my_garage)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.