AndreaCensi / contracts

PyContracts is a Python package that allows to declare constraints on function parameters and return values. Contracts can be specified using Python3 annotations, or inside a docstring. PyContracts supports a basic type system, variables binding, arithmetic constraints, and has several specialized contracts and an extension API.
http://andreacensi.github.io/contracts/
Other
398 stars 62 forks source link

When declaring a class, I cannot refer to the class in a contract...? #34

Open beetleb opened 9 years ago

beetleb commented 9 years ago

The following code doesn't work:

class CommodityType(object):
    """
    A generic commodity type.
    """
    def __init__(self, symbol):
    self.symbol = symbol

    # @contract(other=CommodityType)
    def __eq__(self, other):
    return self.symbol == other.symbol

It complains that CommodityType is not defined. Is there any way around this problem? I was trying to avoid having an isinstance check inside.

Thanks,

AndreaCensi commented 9 years ago

No, this is a limitation of Python. You cannot refer to the class being defined.

On Saturday, February 14, 2015, beetleb notifications@github.com wrote:

The following code doesn't work:

class CommodityType(object): """ A generic commodity type. """ def init(self, symbol): self.symbol = symbol

# @contract(other=CommodityType)
def __eq__(self, other):
return self.symbol == other.symbol

It complains that CommodityType is not defined. Is there any way around this problem? I was trying to avoid having an isinstance check inside.

Thanks,

— Reply to this email directly or view it on GitHub https://github.com/AndreaCensi/contracts/issues/34.

(sent from mobile device, please pardon typos and brevity)

AndreaCensi commented 9 years ago

I'm leaving this open, because we need to find some workaround, as this is a very common case.

AndreaCensi commented 9 years ago

I'm still not sure about this could be implemented. It seems it is a limitation of Python and the workaround would be very complicated. We would need to defer the evaluation of the contracts.

timClicks commented 7 years ago

I believe SQLAlchemy shares this issue and they resolve it by using strings.

That is, this..

class CommodityType(object):
    """
    A generic commodity type.
    """
    def __init__(self, symbol):
         self.symbol = symbol

    @contract(other=CommodityType)
    def __eq__(self, other):
        return self.symbol == other.symbol

..would become

class CommodityType(object):
    """
    A generic commodity type.
    """
    def __init__(self, symbol):
         self.symbol = symbol

    @contract(other='CommodityType')
    def __eq__(self, other):
        return self.symbol == other.symbol