Python继承导致非法属性错误

时间:2019-07-23 18:48:15

标签: python

我的vuln.py低于一类

<View style={{backgroundColor: "#fff",padding: 10, flex:1}}>
                 <Image source={require('./chnIcon.png')} style={{marginLeft: -10}}></Image>
                 <TouchableOpacity  onPress={() => this.backArrow()} style={styles.signoutContainer}> 
                    <Image source={require('./calendar_icon.png')} style={styles.signOutImage}></Image>
                 </TouchableOpacity>
             </View> 

并调用程序rep.py

from reportlab.graphics.shapes import Drawing, String, Rect

class vuln(Drawing):
    def __init__(self, width=300, height=150, report_type=None, *args, **kw):
        Drawing.__init__(self, width, height, *args, **kw)
        self.report_type = report_type

    def print_report(self):
        print self.report_type

执行此操作后会提示错误,

import vuln

obj = vuln.vuln(report_type="abc")
obj.print_report()

请帮助了解错误的全部原因。

2 个答案:

答案 0 :(得分:3)

长话短说,他们的开发人员正在给您带来痛苦,并做了他们不应该在python中做的事情。幸运的是,它是开源的。您正在使用的API动态检查从Shape继承的类的属性,或者如它们在/reportlab/graphics/shapes.py, line 359中所说的那样:

if shapeChecking:
        """This adds the ability to check every attribute assignment as it is made.
        It slows down shapes but is a big help when developing. It does not
        get defined if rl_config.shapeChecking = 0"""
        def __setattr__(self, attr, value):
            """By default we verify.  This could be off
            in some parallel base classes."""
            validateSetattr(self,attr,value)    #from reportlab.lib.attrmap

继续浏览代码,在attrmap source code的第99行,您可以看到导致问题的原因:

def validateSetattr(obj,name,value):
    '''validate setattr(obj,name,value)'''
    if rl_config.shapeChecking:
        map = obj._attrMap
        if map and name[0]!= '_':
            #we always allow the inherited values; they cannot
            #be checked until draw time.
            if isinstance(value, DerivedValue):
                #let it through
                pass
            else:            
                try:
                    validate = map[name].validate
                    if not validate(value):
                        raise AttributeError("Illegal assignment of '%s' to '%s' in class %s" % (value, name, obj.__class__.__name__))
                except KeyError:
                    raise AttributeError("Illegal attribute '%s' in class %s" % (name, obj.__class__.__name__))
    obj.__dict__[name] = value

请注意,他们不会检查以___开头的属性,这些属性是python用来表示“私有”变量的;这样,您可以按以下步骤修改代码:

from reportlab.graphics.shapes import Drawing, String, Rect

class vuln(Drawing):
    def __init__(self, width=300, height=150, report_type=None, *args, **kw):
        Drawing.__init__(self, width, height, *args, **kw)
        self._report_type = report_type

    def print_report(self):
        print self._report_type

然后一切都会正常进行。

答案 1 :(得分:0)

您的堆栈跟踪提供了一些线索,在this documentation (see page 35)中搜索attrmap提供了更多信息。实际上,最有用的信息来自调用help()类上的Drawing

 ...
 |  Methods inherited from reportlab.graphics.shapes.Shape:
 |  
 |  __setattr__(self, attr, value)
 |      By default we verify.  This could be off
 |      in some parallel base classes.
 ...

这似乎与文档有关。

这里的潜在问题是,无论出于何种原因,reportlab对象都需要验证参数是否“预期”。通过inspect模块查看源代码会得出以下结果:

>>> print(inspect.getsource(Drawing.__setattr__))
        def __setattr__(self, attr, value):
            """By default we verify.  This could be off
            in some parallel base classes."""
            validateSetattr(self,attr,value)    #from reportlab.lib.attrmap

>>> print(inspect.getsource(reportlab.lib.attrmap.validateSetattr))
def validateSetattr(obj,name,value):
    '''validate setattr(obj,name,value)'''
    if rl_config.shapeChecking:
        map = obj._attrMap
        if map and name[0]!= '_':
            #we always allow the inherited values; they cannot
            #be checked until draw time.
            if isinstance(value, DerivedValue):
                #let it through
                pass
            else:            
                try:
                    validate = map[name].validate
                    if not validate(value):
                        raise AttributeError("Illegal assignment of '%s' to '%s' in class %s" % (value, name, obj.__class__.__name__))
                except KeyError:
                    raise AttributeError("Illegal attribute '%s' in class %s" % (name, obj.__class__.__name__))
    obj.__dict__[name] = value

由此我们可以得出结论,有解决方案。首先,您可以覆盖__setattr__()以不调用validateSetattr()-只需将以下方法添加到您的课程中即可:

def __setattr__(self, name, value):
    # use the `object` class's __setattr__ instead of the superclass's
    # thus avoiding calling validateSetattr()
    object.__setattr__(self, name, value) 

或者,您也可以执行上述@ErrorSyntacticalRemorse所说的操作,并在变量名的开头添加一个_。或者,您可以尝试使用self._attrMap变量,但实际上我不确定如何以适合该功能的方式执行该操作。