CodeQL queries 1.23

Skip to end of metadata
Go to start of metadata

Name: Property in old-style class

Description: Using property descriptors in old-style classes does not work from Python 2.1 onward.

ID: py/property-in-old-style-class

Kind: problem

Severity: error

Precision: very-high

Query: PropertyInOldStyleClass.ql
/**
 * @name Property in old-style class
 * @description Using property descriptors in old-style classes does not work from Python 2.1 onward.
 * @kind problem
 * @tags portability
 *       correctness
 * @problem.severity error
 * @sub-severity low
 * @precision very-high
 * @id py/property-in-old-style-class
 */

import python

from PropertyObject prop, ClassObject cls
where cls.declaredAttribute(_) = prop and not cls.failedInference() and not cls.isNewStyle()
select prop, "Property " + prop.getName() + " will not work properly, as class " + cls.getName() + " is an old-style class."

Property descriptors are only supported for the new-style classes that were introduced in Python 2.1. Property descriptors should only be used in new-style classes.

Recommendation

If you want to define properties in a class, then ensure that the class is a new-style class. You can convert an old-style class to a new-style class by inheriting from object.

Example

In the following example all the classes attempt to set a property for x. However, only the third and fourth classes are new-style classes. Consequently, the x property is only available for the NewStyle and InheritNewStyle classes.

If you define the OldStyle class as inheriting from a new-style class, then the x property would be available for both the OldStyle and InheritOldStyle classes.

class OldStyle:

    def __init__(self, x):
        self._x = x

    # Incorrect: 'OldStyle' is not a new-style class and '@property' is not supported
    @property
    def x(self):
        return self._x


class InheritOldStyle(OldStyle):

    def __init__(self, x):
        self._x = x

    # Incorrect: 'InheritOldStyle' is not a new-style class and '@property' is not supported
    @property
    def x(self):
        return self._x


class NewStyle(object):

    def __init__(self, x):
        self._x = x

    # Correct: 'NewStyle' is a new-style class and '@property' is supported
    @property
    def x(self):
        return self._x

class InheritNewStyle(NewStyle):

    def __init__(self, x):
        self._x = x

    # Correct: 'InheritNewStyle' inherits from a new-style class and '@property' is supported
    @property
    def x(self):
        return self._x

References