Skip to content

Commit

Permalink
Fix many more pytype changes for matter_idl (#26371)
Browse files Browse the repository at this point in the history
* Several pytype fixes on matter idl

* Fix some import logic for tests to pass

* Restyled by autopep8

* Restyled by isort

* flak8 warnings fixed

---------

Co-authored-by: Andrei Litvin <[email protected]>
Co-authored-by: Restyled.io <[email protected]>
  • Loading branch information
3 people authored May 4, 2023
1 parent dbcf1dd commit a59ffbd
Show file tree
Hide file tree
Showing 13 changed files with 118 additions and 90 deletions.
27 changes: 13 additions & 14 deletions scripts/py_matter_idl/matter_idl/generators/bridge/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
import os
import re
from typing import Tuple, Union

from matter_idl.generators import CodeGenerator, GeneratorStorage
from matter_idl.generators.types import (BasicInteger, BasicString, FundamentalType, IdlBitmapType, IdlEnumType, IdlType,
Expand All @@ -38,40 +38,39 @@ def create_lookup_context(idl: Idl, cluster: Cluster) -> TypeLookupContext:
return TypeLookupContext(idl, cluster)


def get_field_info(definition: Field, cluster: Cluster, idl: Idl):
def get_field_info(definition: Field, cluster: Cluster, idl: Idl) -> Tuple[str, str, Union[str, int, None], str]:
context = create_lookup_context(idl, cluster)
actual = ParseDataType(definition.data_type, context)

if type(actual) == IdlEnumType or type(actual) == IdlBitmapType:
if isinstance(actual, (IdlEnumType, IdlBitmapType)):
actual = actual.base_type

if type(actual) == BasicString:
if isinstance(actual, BasicString):
return 'OctetString', 'char', actual.max_length, \
'ZCL_%s_ATTRIBUTE_TYPE' % actual.idl_name.upper()

if type(actual) == BasicInteger:
if isinstance(actual, BasicInteger):
name = actual.idl_name.upper()
ty = "int%d_t" % actual.power_of_two_bits
if not actual.is_signed:
ty = "u" + ty
return "", ty, actual.byte_count, "ZCL_%s_ATTRIBUTE_TYPE" % name
if type(actual) == FundamentalType:
if isinstance(actual, FundamentalType):
if actual == FundamentalType.BOOL:
return "", "bool", 1, "ZCL_BOOLEAN_ATTRIBUTE_TYPE"
if actual == FundamentalType.FLOAT:
elif actual == FundamentalType.FLOAT:
return "", "float", 4, "ZCL_SINGLE_ATTRIBUTE_TYPE"
if actual == FundamentalType.DOUBLE:
elif actual == FundamentalType.DOUBLE:
return "", "double", 8, "ZCL_DOUBLE_ATTRIBUTE_TYPE"
logging.warn('Unknown fundamental type: %r' % actual)
return None
if type(actual) == IdlType:
else:
raise Exception('Unknown fundamental type: %r' % actual)
if isinstance(actual, IdlType):
return '', actual.idl_name, 'sizeof(%s)' % actual.idl_name, \
'ZCL_STRUCT_ATTRIBUTE_TYPE'
logging.warn('Unknown type: %r' % actual)
return None
raise Exception('UNKNOWN TYPE: %s' % actual)


def get_raw_size_and_type(attr: Attribute, cluster: Cluster, idl: Idl):
def get_raw_size_and_type(attr: Attribute, cluster: Cluster, idl: Idl) -> str:
container, cType, size, matterType = get_field_info(
attr.definition, cluster, idl)
if attr.definition.is_list:
Expand Down
38 changes: 18 additions & 20 deletions scripts/py_matter_idl/matter_idl/generators/java/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import enum
import logging
import os
from typing import List, Set, Union
from typing import List, Optional, Set

from matter_idl.generators import CodeGenerator, GeneratorStorage
from matter_idl.generators.types import (BasicInteger, BasicString, FundamentalType, IdlBitmapType, IdlEnumType, IdlType,
Expand Down Expand Up @@ -57,24 +57,22 @@ class GlobalType:
]


def _UnderlyingType(field: Field, context: TypeLookupContext) -> Union[str, None]:
def _UnderlyingType(field: Field, context: TypeLookupContext) -> Optional[str]:
actual = ParseDataType(field.data_type, context)
if type(actual) == IdlEnumType:
actual = actual.base_type
elif type(actual) == IdlBitmapType:
if isinstance(actual, (IdlEnumType, IdlBitmapType)):
actual = actual.base_type

if type(actual) == BasicString:
if isinstance(actual, BasicString):
if actual.is_binary:
return 'OctetString'
else:
return 'CharString'
elif type(actual) == BasicInteger:
elif isinstance(actual, BasicInteger):
if actual.is_signed:
return "Int{}s".format(actual.power_of_two_bits)
else:
return "Int{}u".format(actual.power_of_two_bits)
elif type(actual) == FundamentalType:
elif isinstance(actual, FundamentalType):
if actual == FundamentalType.BOOL:
return 'Boolean'
elif actual == FundamentalType.FLOAT:
Expand All @@ -87,7 +85,7 @@ def _UnderlyingType(field: Field, context: TypeLookupContext) -> Union[str, None
return None


def FieldToGlobalName(field: Field, context: TypeLookupContext) -> Union[str, None]:
def FieldToGlobalName(field: Field, context: TypeLookupContext) -> Optional[str]:
"""Global names are used for generic callbacks shared across
all clusters (e.g. for bool/float/uint32 and similar)
"""
Expand Down Expand Up @@ -246,7 +244,7 @@ def attributesWithSupportedCallback(attrs, context: TypeLookupContext):
# except non-list structures
if not attr.definition.is_list:
underlying = ParseDataType(attr.definition.data_type, context)
if type(underlying) == IdlType:
if isinstance(underlying, IdlType):
continue

yield attr
Expand Down Expand Up @@ -419,7 +417,7 @@ def get_underlying_enum(self):
def boxed_java_type(self):
t = ParseDataType(self.data_type, self.context)

if type(t) == FundamentalType:
if isinstance(t, FundamentalType):
if t == FundamentalType.BOOL:
return "Boolean"
elif t == FundamentalType.FLOAT:
Expand All @@ -428,23 +426,23 @@ def boxed_java_type(self):
return "Double"
else:
raise Exception("Unknown fundamental type")
elif type(t) == BasicInteger:
elif isinstance(t, BasicInteger):
# the >= 3 will include int24_t to be considered "long"
if t.byte_count >= 3:
return "Long"
else:
return "Integer"
elif type(t) == BasicString:
elif isinstance(t, BasicString):
if t.is_binary:
return "byte[]"
else:
return "String"
elif type(t) == IdlEnumType:
elif isinstance(t, IdlEnumType):
if t.base_type.byte_count >= 3:
return "Long"
else:
return "Integer"
elif type(t) == IdlBitmapType:
elif isinstance(t, IdlBitmapType):
if t.base_type.byte_count >= 3:
return "Long"
else:
Expand All @@ -463,7 +461,7 @@ def boxed_java_signature(self):

t = ParseDataType(self.data_type, self.context)

if type(t) == FundamentalType:
if isinstance(t, FundamentalType):
if t == FundamentalType.BOOL:
return "Ljava/lang/Boolean;"
elif t == FundamentalType.FLOAT:
Expand All @@ -472,22 +470,22 @@ def boxed_java_signature(self):
return "Ljava/lang/Double;"
else:
raise Exception("Unknown fundamental type")
elif type(t) == BasicInteger:
elif isinstance(t, BasicInteger):
if t.byte_count >= 3:
return "Ljava/lang/Long;"
else:
return "Ljava/lang/Integer;"
elif type(t) == BasicString:
elif isinstance(t, BasicString):
if t.is_binary:
return "[B"
else:
return "Ljava/lang/String;"
elif type(t) == IdlEnumType:
elif isinstance(t, IdlEnumType):
if t.base_type.byte_count >= 3:
return "Ljava/lang/Long;"
else:
return "Ljava/lang/Integer;"
elif type(t) == IdlBitmapType:
elif isinstance(t, IdlBitmapType):
if t.base_type.byte_count >= 3:
return "Ljava/lang/Long;"
else:
Expand Down
10 changes: 5 additions & 5 deletions scripts/py_matter_idl/matter_idl/generators/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,11 @@ class IdlEnumType:

@property
def byte_count(self):
return self.base_type.byte_count()
return self.base_type.byte_count

@property
def bits(self):
return self.base_type.bits()
return self.base_type.bits


@dataclass
Expand All @@ -129,11 +129,11 @@ class IdlBitmapType:

@property
def byte_count(self):
return self.base_type.byte_count()
return self.base_type.byte_count

@property
def bits(self):
return self.base_type.bits()
return self.base_type.bits


class IdlItemType(enum.Enum):
Expand Down Expand Up @@ -353,7 +353,7 @@ def is_bitmap_type(self, name: str):
return any(map(lambda s: s.name == name, self.all_bitmaps))


def ParseDataType(data_type: DataType, lookup: TypeLookupContext) -> Union[BasicInteger, BasicString, FundamentalType, IdlType]:
def ParseDataType(data_type: DataType, lookup: TypeLookupContext) -> Union[BasicInteger, BasicString, FundamentalType, IdlType, IdlEnumType, IdlBitmapType]:
"""
Given a AST data type and a lookup context, match it to a type that can be later
be used for generation.
Expand Down
30 changes: 22 additions & 8 deletions scripts/py_matter_idl/matter_idl/lint/lint_rules_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import os
import xml.etree.ElementTree
from dataclasses import dataclass
from typing import List, Mapping
from typing import List, MutableMapping

from lark import Lark
from lark.visitors import Discard, Transformer, v_args
Expand All @@ -21,7 +21,12 @@
RequiredCommandsRule)


def parseNumberString(n):
class ElementNotFoundError(Exception):
def __init__(self, name):
super().__init__(f"Could not find {name}")


def parseNumberString(n: str) -> int:
if n.startswith('0x'):
return int(n[2:], 16)
else:
Expand Down Expand Up @@ -59,7 +64,11 @@ def DecodeClusterFromXml(element: xml.etree.ElementTree.Element):
# - attribute with side, code and optional attributes

try:
name = element.find('name').text.replace(' ', '')
name = element.find('name')
if not name or not name.text:
raise ElementNotFoundError('name')

name = name.text.replace(' ', '')
required_attributes = []
required_commands = []

Expand All @@ -75,8 +84,9 @@ def DecodeClusterFromXml(element: xml.etree.ElementTree.Element):
# or
# <attribute ...><description>myName</description><access .../>...</attribute>
attr_name = attr.text
if attr.find('description') is not None:
attr_name = attr.find('description').text
description = attr.find('description')
if description is not None:
attr_name = description.text

required_attributes.append(
RequiredAttribute(
Expand All @@ -94,9 +104,13 @@ def DecodeClusterFromXml(element: xml.etree.ElementTree.Element):
required_commands.append(RequiredCommand(
name=cmd.attrib["name"], code=parseNumberString(cmd.attrib['code'])))

code = element.find('code')
if not code:
raise Exception("Failed to find cluster code")

return DecodedCluster(
name=name,
code=parseNumberString(element.find('code').text),
code=parseNumberString(code.text),
required_attributes=required_attributes,
required_commands=required_commands
)
Expand Down Expand Up @@ -132,7 +146,7 @@ def __init__(self):
"Required commands")

# Map cluster names to the underlying code
self._cluster_codes: Mapping[str, int] = {}
self._cluster_codes: MutableMapping[str, int] = {}

def GetLinterRules(self):
return [self._required_attributes_rule, self._required_commands_rule]
Expand Down Expand Up @@ -300,7 +314,7 @@ def CreateParser(file_name: str):
@click.option(
'--log-level',
default='INFO',
type=click.Choice(__LOG_LEVELS__.keys(), case_sensitive=False),
type=click.Choice(list(__LOG_LEVELS__.keys()), case_sensitive=False),
help='Determines the verbosity of script output.')
@click.argument('filename')
def main(log_level, filename=None):
Expand Down
26 changes: 20 additions & 6 deletions scripts/py_matter_idl/matter_idl/lint/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,21 @@

from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from typing import List, Mapping, Optional
from typing import List, MutableMapping, Optional

from matter_idl.matter_idl_types import ClusterSide, Idl, ParseMetaData


class MissingIdlError(Exception):
def __init__(self):
super().__init__("Missing IDL data")


@dataclass
class LocationInFile:
file_name: str
line: int
column: int
line: Optional[int]
column: Optional[int]

def __init__(self, file_name: str, meta: ParseMetaData):
self.file_name = file_name
Expand Down Expand Up @@ -91,7 +96,7 @@ def _AddLintError(self, text, location):

def _ParseLocation(self, meta: Optional[ParseMetaData]) -> Optional[LocationInFile]:
"""Create a location in the current file that is being parsed. """
if not meta or not self._idl.parse_file_name:
if not meta or not self._idl or not self._idl.parse_file_name:
return None
return LocationInFile(self._idl.parse_file_name, meta)

Expand Down Expand Up @@ -145,6 +150,9 @@ def _ServerClusterDefinition(self, name: str, location: Optional[LocationInFile]
On error returns None and _lint_errors is updated internlly
"""
if not self._idl:
raise MissingIdlError()

cluster_definition = [
c for c in self._idl.clusters if c.name == name and c.side == ClusterSide.SERVER
]
Expand All @@ -161,6 +169,9 @@ def _ServerClusterDefinition(self, name: str, location: Optional[LocationInFile]
return cluster_definition[0]

def _LintImpl(self):
if not self._idl:
raise MissingIdlError()

for endpoint in self._idl.endpoints:

cluster_codes = set()
Expand Down Expand Up @@ -223,8 +234,8 @@ def __init__(self, name):
super(RequiredCommandsRule, self).__init__(name)

# Maps cluster id to mandatory cluster requirement
self._mandatory_commands: Mapping[int,
List[ClusterCommandRequirement]] = {}
self._mandatory_commands: MutableMapping[int,
List[ClusterCommandRequirement]] = {}

def __repr__(self):
result = "RequiredCommandsRule{\n"
Expand All @@ -248,6 +259,9 @@ def RequireCommand(self, cmd: ClusterCommandRequirement):
self._mandatory_commands[cmd.cluster_code] = [cmd]

def _LintImpl(self):
if not self._idl:
raise MissingIdlError()

for cluster in self._idl.clusters:
if cluster.side != ClusterSide.SERVER:
continue # only validate server-side:
Expand Down
Loading

0 comments on commit a59ffbd

Please sign in to comment.