@@ -1049,6 +1049,8 @@ def analyze_overload_sigs_and_impl(
1049
1049
else :
1050
1050
item .func .is_overload = True
1051
1051
types .append (callable )
1052
+ if item .var .is_property :
1053
+ self .fail ("An overload can not be a property" , item )
1052
1054
elif isinstance (item , FuncDef ):
1053
1055
if i == len (defn .items ) - 1 and not self .is_stub_file :
1054
1056
impl = item
@@ -1168,16 +1170,18 @@ def analyze_property_with_multi_part_definition(self, defn: OverloadedFuncDef) -
1168
1170
deleted_items = []
1169
1171
for i , item in enumerate (items [1 :]):
1170
1172
if isinstance (item , Decorator ):
1171
- if len (item .decorators ) = = 1 :
1173
+ if len (item .decorators ) > = 1 :
1172
1174
node = item .decorators [0 ]
1173
1175
if isinstance (node , MemberExpr ):
1174
1176
if node .name == "setter" :
1175
1177
# The first item represents the entire property.
1176
1178
first_item .var .is_settable_property = True
1177
1179
# Get abstractness from the original definition.
1178
1180
item .func .abstract_status = first_item .func .abstract_status
1179
- else :
1180
- self .fail ("Decorated property not supported" , item )
1181
+ else :
1182
+ self .fail (
1183
+ f"Only supported top decorator is @{ first_item .func .name } .setter" , item
1184
+ )
1181
1185
item .func .accept (self )
1182
1186
else :
1183
1187
self .fail (f'Unexpected definition for property "{ first_item .func .name } "' , item )
@@ -1258,6 +1262,7 @@ def visit_decorator(self, dec: Decorator) -> None:
1258
1262
d .accept (self )
1259
1263
removed : List [int ] = []
1260
1264
no_type_check = False
1265
+ could_be_decorated_property = False
1261
1266
for i , d in enumerate (dec .decorators ):
1262
1267
# A bunch of decorators are special cased here.
1263
1268
if refers_to_fullname (d , "abc.abstractmethod" ):
@@ -1288,8 +1293,6 @@ def visit_decorator(self, dec: Decorator) -> None:
1288
1293
elif refers_to_fullname (d , "functools.cached_property" ):
1289
1294
dec .var .is_settable_property = True
1290
1295
self .check_decorated_function_is_method ("property" , dec )
1291
- if len (dec .func .arguments ) > 1 :
1292
- self .fail ("Too many arguments" , dec .func )
1293
1296
elif refers_to_fullname (d , "typing.no_type_check" ):
1294
1297
dec .var .type = AnyType (TypeOfAny .special_form )
1295
1298
no_type_check = True
@@ -1304,15 +1307,21 @@ def visit_decorator(self, dec: Decorator) -> None:
1304
1307
removed .append (i )
1305
1308
else :
1306
1309
self .fail ("@final cannot be used with non-method functions" , d )
1310
+ elif not dec .var .is_property :
1311
+ # We have seen a "non-trivial" decorator before seeing @property, if
1312
+ # we will see a @property later, give an error, as we don't support this.
1313
+ could_be_decorated_property = True
1307
1314
for i in reversed (removed ):
1308
1315
del dec .decorators [i ]
1309
1316
if (not dec .is_overload or dec .var .is_property ) and self .type :
1310
1317
dec .var .info = self .type
1311
1318
dec .var .is_initialized_in_class = True
1312
1319
if not no_type_check and self .recurse_into_functions :
1313
1320
dec .func .accept (self )
1314
- if dec .decorators and dec .var .is_property :
1315
- self .fail ("Decorated property not supported" , dec )
1321
+ if could_be_decorated_property and dec .decorators and dec .var .is_property :
1322
+ self .fail ("Decorators on top of @property are not supported" , dec )
1323
+ if (dec .func .is_static or dec .func .is_class ) and dec .var .is_property :
1324
+ self .fail ("Only instance methods can be decorated with @property" , dec )
1316
1325
if dec .func .abstract_status == IS_ABSTRACT and dec .func .is_final :
1317
1326
self .fail (f"Method { dec .func .name } is both abstract and final" , dec )
1318
1327
0 commit comments