Skip to content

Commit

Permalink
replacing "stringcase" python package with internal implementation + …
Browse files Browse the repository at this point in the history
…generated java and kotlin code (#34949)

* changing matter_idl functions

* changing yaml runner functions

* removing stringcase from config and requirement files

* restyle

* improve string handling

* fixing generated java and kotlin code

* regenerate idl golden image for test_generators.py

* adding unit test

* restyle

* adding unit test to build.GN
  • Loading branch information
Alami-Amine authored and pull[bot] committed Jan 10, 2025
1 parent b4f4d74 commit 1717340
Show file tree
Hide file tree
Showing 145 changed files with 1,437 additions and 1,311 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# codegen.py build requirements
Jinja2==3.1.3
lark==1.1.7
stringcase==1.2.0
# Sphinx dependencies (for slc-cli)
linkify-it-py==2.0.2
myst-parser==2.0.0
Expand Down
1 change: 1 addition & 0 deletions scripts/py_matter_idl/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ pw_python_package("matter_idl") {

tests = [
"matter_idl/test_backwards_compatibility.py",
"matter_idl/test_case_conversion.py",
"matter_idl/test_data_model_xml.py",
"matter_idl/test_matter_idl_parser.py",
"matter_idl/test_generators.py",
Expand Down
83 changes: 76 additions & 7 deletions scripts/py_matter_idl/matter_idl/generators/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import stringcase
import re


def normalize_acronyms(s: str) -> str:
Expand Down Expand Up @@ -49,6 +49,75 @@ def lowfirst_except_acronym(s: str) -> str:
return lowfirst(s)


def to_snake_case(s: str) -> str:
"""convert to snake case; all words are seperated by underscore and are lower case
examples:
FooBarBaz --> foo_bar_baz
foo BarBaz --> foo_bar_baz
FOOBarBaz --> foo_bar_baz
_fooBar_Baz_ --> foo_bar_baz
"""
s = "" if s is None else str(s)

s = re.sub(r'([A-Z]+)([A-Z][a-z])', r'\1_\2', s)
s = re.sub(r'([a-z\d])([A-Z])', r'\1_\2', s)
s = re.sub(r'[\s\-]+', '_', s)

snake_case = s.lower()
return snake_case.strip('_')


def to_constant_case(s: str) -> str:
"""convert to constant case; all words are seperated by underscore and are upper case
similar to a snake case but with upper case
examples:
FooBarBaz --> FOO_BAR_BAZ
foo BarBaz --> FOO_BAR_BAZ
FOOBarBaz --> FOO_BAR_BAZ
"""
snake_case = to_snake_case(s)
constant_case = snake_case.upper()
return constant_case


def to_spinal_case(s: str) -> str:
"""convert to spinal case; all words sperated by hypen and are lower case
similar to a snake case but with hyphen seperator instead of underscore
examples:
FooBarBaz --> foo-bar-baz
foo BarBaz --> foo-bar-baz
FOOBarBaz --> foo-bar-baz
"""
snake_case = to_snake_case(s)
return snake_case.replace('_', '-')


def to_pascal_case(s: str) -> str:
"""convert to pascal case; with no spaces or underscore between words, first letter of all words is uppercase
examples:
fooBarBaz --> FooBarBaz
foo BarBaz --> FooBarBaz
FOOBar_Baz --> FooBarBaz
"""

snake_case = to_snake_case(s)
snake_case_split = snake_case.split('_')
pascal_case = ''.join(word.capitalize() for word in snake_case_split)

return pascal_case


def to_camel_case(s) -> str:
"""convert to camel case; with no spaces or underscore between words, first word all lowercase and following words are uppercase
same as pascal case but first letter is lower case
examples:
FooBarBaz --> fooBarBaz
foo BarBaz --> fooBarBaz
FOOBarBaz --> fooBarBaz
"""
return lowfirst(to_pascal_case(s))


def RegisterCommonFilters(filtermap):
"""
Register filters that are NOT considered platform-generator specific.
Expand All @@ -59,12 +128,12 @@ def RegisterCommonFilters(filtermap):
"""

# General casing for output naming
filtermap['camelcase'] = stringcase.camelcase
filtermap['capitalcase'] = stringcase.capitalcase
filtermap['constcase'] = stringcase.constcase
filtermap['pascalcase'] = stringcase.pascalcase
filtermap['snakecase'] = stringcase.snakecase
filtermap['spinalcase'] = stringcase.spinalcase
filtermap['camelcase'] = to_camel_case
filtermap['capitalcase'] = upfirst
filtermap['constcase'] = to_constant_case
filtermap['pascalcase'] = to_pascal_case
filtermap['snakecase'] = to_snake_case
filtermap['spinalcase'] = to_spinal_case

filtermap['normalize_acronyms'] = normalize_acronyms
filtermap['lowfirst'] = lowfirst
Expand Down
14 changes: 7 additions & 7 deletions scripts/py_matter_idl/matter_idl/generators/java/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
from typing import List, Optional, Set

from matter_idl.generators import CodeGenerator, GeneratorStorage
from matter_idl.generators.filters import upfirst
from matter_idl.generators.type_definitions import (BasicInteger, BasicString, FundamentalType, IdlBitmapType, IdlEnumType, IdlType,
ParseDataType, TypeLookupContext)
from matter_idl.matter_idl_types import (Attribute, Cluster, Command, DataType, Field, FieldQuality, Idl, Struct, StructQuality,
StructTag)
from stringcase import capitalcase


@dataclasses.dataclass
Expand Down Expand Up @@ -199,7 +199,7 @@ def DelegatedCallbackName(attr: Attribute, context: TypeLookupContext) -> str:
if global_name:
return 'Delegated{}AttributeCallback'.format(GlobalNameToJavaName(global_name))

return 'Delegated{}Cluster{}AttributeCallback'.format(context.cluster.name, capitalcase(attr.definition.name))
return 'Delegated{}Cluster{}AttributeCallback'.format(context.cluster.name, upfirst(attr.definition.name))


def ChipClustersCallbackName(attr: Attribute, context: TypeLookupContext) -> str:
Expand All @@ -212,7 +212,7 @@ def ChipClustersCallbackName(attr: Attribute, context: TypeLookupContext) -> str
if global_name:
return 'ChipClusters.{}AttributeCallback'.format(GlobalNameToJavaName(global_name))

return 'ChipClusters.{}Cluster.{}AttributeCallback'.format(context.cluster.name, capitalcase(attr.definition.name))
return 'ChipClusters.{}Cluster.{}AttributeCallback'.format(context.cluster.name, upfirst(attr.definition.name))


def CallbackName(attr: Attribute, context: TypeLookupContext) -> str:
Expand All @@ -228,11 +228,11 @@ def CallbackName(attr: Attribute, context: TypeLookupContext) -> str:
global_name = FieldToGlobalName(attr.definition, context)

if global_name:
return 'CHIP{}AttributeCallback'.format(capitalcase(global_name))
return 'CHIP{}AttributeCallback'.format(upfirst(global_name))

return 'CHIP{}{}AttributeCallback'.format(
capitalcase(context.cluster.name),
capitalcase(attr.definition.name)
upfirst(context.cluster.name),
upfirst(attr.definition.name)
)


Expand Down Expand Up @@ -262,7 +262,7 @@ def JavaAttributeCallbackName(attr: Attribute, context: TypeLookupContext) -> st
if global_name:
return '{}AttributeCallback'.format(GlobalNameToJavaName(global_name))

return '{}AttributeCallback'.format(capitalcase(attr.definition.name))
return '{}AttributeCallback'.format(upfirst(attr.definition.name))


def IsFieldGlobalName(field: Field, context: TypeLookupContext) -> bool:
Expand Down
14 changes: 7 additions & 7 deletions scripts/py_matter_idl/matter_idl/generators/kotlin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
from typing import List, Optional, Set

from matter_idl.generators import CodeGenerator, GeneratorStorage
from matter_idl.generators.filters import upfirst
from matter_idl.generators.type_definitions import (BasicInteger, BasicString, FundamentalType, IdlBitmapType, IdlEnumType, IdlType,
ParseDataType, TypeLookupContext)
from matter_idl.matter_idl_types import (Attribute, Cluster, Command, DataType, Field, FieldQuality, Idl, Struct, StructQuality,
StructTag)
from stringcase import capitalcase


@dataclasses.dataclass
Expand Down Expand Up @@ -160,7 +160,7 @@ def DelegatedCallbackName(attr: Attribute, context: TypeLookupContext) -> str:
if global_name:
return 'Delegated{}AttributeCallback'.format(GlobalNameToJavaName(global_name))

return 'Delegated{}Cluster{}AttributeCallback'.format(context.cluster.name, capitalcase(attr.definition.name))
return 'Delegated{}Cluster{}AttributeCallback'.format(context.cluster.name, upfirst(attr.definition.name))


def ChipClustersCallbackName(attr: Attribute, context: TypeLookupContext) -> str:
Expand All @@ -173,7 +173,7 @@ def ChipClustersCallbackName(attr: Attribute, context: TypeLookupContext) -> str
if global_name:
return 'ChipClusters.{}AttributeCallback'.format(GlobalNameToJavaName(global_name))

return 'ChipClusters.{}Cluster.{}AttributeCallback'.format(context.cluster.name, capitalcase(attr.definition.name))
return 'ChipClusters.{}Cluster.{}AttributeCallback'.format(context.cluster.name, upfirst(attr.definition.name))


def CallbackName(attr: Attribute, context: TypeLookupContext) -> str:
Expand All @@ -189,11 +189,11 @@ def CallbackName(attr: Attribute, context: TypeLookupContext) -> str:
global_name = FieldToGlobalName(attr.definition, context)

if global_name:
return 'CHIP{}AttributeCallback'.format(capitalcase(global_name))
return 'CHIP{}AttributeCallback'.format(upfirst(global_name))

return 'CHIP{}{}AttributeCallback'.format(
capitalcase(context.cluster.name),
capitalcase(attr.definition.name)
upfirst(context.cluster.name),
upfirst(attr.definition.name)
)


Expand Down Expand Up @@ -223,7 +223,7 @@ def JavaAttributeCallbackName(attr: Attribute, context: TypeLookupContext) -> st
if global_name:
return '{}'.format(GlobalNameToJavaName(global_name))

return '{}Attribute'.format(capitalcase(attr.definition.name))
return '{}Attribute'.format(upfirst(attr.definition.name))


def IsFieldGlobalName(field: Field, context: TypeLookupContext) -> bool:
Expand Down
61 changes: 61 additions & 0 deletions scripts/py_matter_idl/matter_idl/test_case_conversion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

import unittest

import matter_idl.generators.filters as case_convert

'''
This file contains tests for checking five of the case conversion functions, notably: snake_case, CONSTANT_CASE, spinal-case, PascalCase and camelCase.
'''
inputs = [
"FooBarBaz",
"FOOBarBaz",
"FOOBarBAZ",
"fooBARBaz",
"fooBarBAZ",
"foo BarBaz",
" FooBarBaz ",
"foo_bar_baz",
"FOO-bar-baz",
"FOO_BAR_BAZ",
"__FooBarBaz__",
"_fooBar_Baz_",
"foo_Bar Baz"
]


class TestSnakeCase(unittest.TestCase):
def test_snake_case(self):
expected = "foo_bar_baz"
for input in inputs:
converted = case_convert.to_snake_case(input)
self.assertEqual(converted, expected, "they are not equal")

def test_constant_case(self):
expected = "FOO_BAR_BAZ"
for input in inputs:
converted = case_convert.to_constant_case(input)
self.assertEqual(converted, expected, "they are not equal")

def test_spinal_case(self):
expected = "foo-bar-baz"
for input in inputs:
converted = case_convert.to_spinal_case(input)
self.assertEqual(converted, expected, "they are not equal")

def test_pascal_case(self):
expected = "FooBarBaz"
for input in inputs:
converted = case_convert.to_pascal_case(input)
self.assertEqual(converted, expected, "they are not equal")

def test_camel_case(self):
expected = "fooBarBaz"
for input in inputs:
converted = case_convert.to_camel_case(input)
self.assertEqual(converted, expected, "they are not equal")


if __name__ == '__main__':
unittest.main()
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ public static class SecondClusterFabricDescriptorStruct {
public String label;
public Integer fabricIndex;
private static final long ROOT_PUBLIC_KEY_ID = 1L;
private static final long VENDOR_I_D_ID = 2L;
private static final long FABRIC_I_D_ID = 3L;
private static final long NODE_I_D_ID = 4L;
private static final long VENDOR_ID_ID = 2L;
private static final long FABRIC_ID_ID = 3L;
private static final long NODE_ID_ID = 4L;
private static final long LABEL_ID = 5L;
private static final long FABRIC_INDEX_ID = 254L;

Expand All @@ -57,9 +57,9 @@ public SecondClusterFabricDescriptorStruct(
public StructType encodeTlv() {
ArrayList<StructElement> values = new ArrayList<>();
values.add(new StructElement(ROOT_PUBLIC_KEY_ID, new ByteArrayType(rootPublicKey)));
values.add(new StructElement(VENDOR_I_D_ID, new UIntType(vendorID)));
values.add(new StructElement(FABRIC_I_D_ID, new UIntType(fabricID)));
values.add(new StructElement(NODE_I_D_ID, new UIntType(nodeID)));
values.add(new StructElement(VENDOR_ID_ID, new UIntType(vendorID)));
values.add(new StructElement(FABRIC_ID_ID, new UIntType(fabricID)));
values.add(new StructElement(NODE_ID_ID, new UIntType(nodeID)));
values.add(new StructElement(LABEL_ID, new StringType(label)));
values.add(new StructElement(FABRIC_INDEX_ID, new UIntType(fabricIndex)));

Expand All @@ -82,17 +82,17 @@ public static SecondClusterFabricDescriptorStruct decodeTlv(BaseTLVType tlvValue
ByteArrayType castingValue = element.value(ByteArrayType.class);
rootPublicKey = castingValue.value(byte[].class);
}
} else if (element.contextTagNum() == VENDOR_I_D_ID) {
} else if (element.contextTagNum() == VENDOR_ID_ID) {
if (element.value(BaseTLVType.class).type() == TLVType.UInt) {
UIntType castingValue = element.value(UIntType.class);
vendorID = castingValue.value(Integer.class);
}
} else if (element.contextTagNum() == FABRIC_I_D_ID) {
} else if (element.contextTagNum() == FABRIC_ID_ID) {
if (element.value(BaseTLVType.class).type() == TLVType.UInt) {
UIntType castingValue = element.value(UIntType.class);
fabricID = castingValue.value(Long.class);
}
} else if (element.contextTagNum() == NODE_I_D_ID) {
} else if (element.contextTagNum() == NODE_ID_ID) {
if (element.value(BaseTLVType.class).type() == TLVType.UInt) {
UIntType castingValue = element.value(UIntType.class);
nodeID = castingValue.value(Long.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ class SecondClusterFabricDescriptorStruct (
tlvWriter.apply {
startStructure(tlvTag)
put(ContextSpecificTag(TAG_ROOT_PUBLIC_KEY), rootPublicKey)
put(ContextSpecificTag(TAG_VENDOR_I_D), vendorID)
put(ContextSpecificTag(TAG_FABRIC_I_D), fabricID)
put(ContextSpecificTag(TAG_NODE_I_D), nodeID)
put(ContextSpecificTag(TAG_VENDOR_ID), vendorID)
put(ContextSpecificTag(TAG_FABRIC_ID), fabricID)
put(ContextSpecificTag(TAG_NODE_ID), nodeID)
put(ContextSpecificTag(TAG_LABEL), label)
put(ContextSpecificTag(TAG_FABRIC_INDEX), fabricIndex)
endStructure()
Expand All @@ -59,18 +59,18 @@ class SecondClusterFabricDescriptorStruct (

companion object {
private const val TAG_ROOT_PUBLIC_KEY = 1
private const val TAG_VENDOR_I_D = 2
private const val TAG_FABRIC_I_D = 3
private const val TAG_NODE_I_D = 4
private const val TAG_VENDOR_ID = 2
private const val TAG_FABRIC_ID = 3
private const val TAG_NODE_ID = 4
private const val TAG_LABEL = 5
private const val TAG_FABRIC_INDEX = 254

fun fromTlv(tlvTag: Tag, tlvReader: TlvReader) : SecondClusterFabricDescriptorStruct {
tlvReader.enterStructure(tlvTag)
val rootPublicKey = tlvReader.getByteArray(ContextSpecificTag(TAG_ROOT_PUBLIC_KEY))
val vendorID = tlvReader.getUInt(ContextSpecificTag(TAG_VENDOR_I_D))
val fabricID = tlvReader.getULong(ContextSpecificTag(TAG_FABRIC_I_D))
val nodeID = tlvReader.getULong(ContextSpecificTag(TAG_NODE_I_D))
val vendorID = tlvReader.getUInt(ContextSpecificTag(TAG_VENDOR_ID))
val fabricID = tlvReader.getULong(ContextSpecificTag(TAG_FABRIC_ID))
val nodeID = tlvReader.getULong(ContextSpecificTag(TAG_NODE_ID))
val label = tlvReader.getString(ContextSpecificTag(TAG_LABEL))
val fabricIndex = tlvReader.getUInt(ContextSpecificTag(TAG_FABRIC_INDEX))

Expand Down
1 change: 0 additions & 1 deletion scripts/py_matter_idl/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ zip_safe = False
install_requires=
lark
jinja2
stringcase

[options.package_data]
matter_idl =
Expand Down
2 changes: 0 additions & 2 deletions scripts/setup/constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,6 @@ six==1.16.0
# requests-file
stack-data==0.6.2
# via ipython
stringcase==1.2.0
# via -r requirements.build.txt
tabulate==0.9.0
# via -r requirements.memory.txt
tornado==6.2
Expand Down
1 change: 0 additions & 1 deletion scripts/setup/requirements.build.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,3 @@ click
# scripts/py_matter_idl/matter_idl
jinja2
lark
stringcase
Loading

0 comments on commit 1717340

Please sign in to comment.