Skip to content

Commit 411fba9

Browse files
committed
Merge pull request aeron-io#278 from tfgm-bud/master
[python] Fixes and improvements to enum handling
2 parents 2d0af38 + 9038e30 commit 411fba9

File tree

1 file changed

+67
-63
lines changed

1 file changed

+67
-63
lines changed

main/java/uk/co/real_logic/sbe/generation/python/PythonGenerator.java

Lines changed: 67 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -314,12 +314,12 @@ private CharSequence generateVarData(final List<Token> tokens)
314314
" def get%1$s(self):\n" +
315315
" sizeOfLengthField = %3$d\n" +
316316
" lengthPosition = self.getPosition()\n" +
317-
" dataLength = struct.unpack_from('%5$s', self.buffer_, lengthPosition[0])[0]\n" +
318-
" self.setPosition(lengthPosition[0] + sizeOfLengthField)\n" +
317+
" dataLength = struct.unpack_from('%5$s', self.buffer_, lengthPosition)[0]\n" +
318+
" self.setPosition(lengthPosition + sizeOfLengthField)\n" +
319319
" pos = self.getPosition()\n" +
320-
" fmt = '" + byteOrder + "'+str(dataLength)+'c'\n" +
321-
" data = struct.unpack_from(fmt, self.buffer_, lengthPosition[0])\n" +
322-
" self.setPosition(pos[0] + dataLength)\n" +
320+
" fmt = '" + byteOrder + "' + str(dataLength) + 's'\n" +
321+
" data = struct.unpack_from(fmt, self.buffer_, pos)[0]\n" +
322+
" self.setPosition(pos + dataLength)\n" +
323323
" return data\n\n",
324324
propertyName,
325325
generateArrayFieldNotPresentCondition(token.version(), BASE_INDENT),
@@ -332,13 +332,12 @@ private CharSequence generateVarData(final List<Token> tokens)
332332
" def set%1$s(self, buffer):\n" +
333333
" sizeOfLengthField = %2$d\n" +
334334
" lengthPosition = self.getPosition()\n" +
335-
" struct.pack_into('%3$s', self.buffer_, lengthPosition[0], len(buffer))\n" +
336-
" self.setPosition(lengthPosition[0] + sizeOfLengthField)\n" +
335+
" struct.pack_into('%3$s', self.buffer_, lengthPosition, len(buffer))\n" +
336+
" self.setPosition(lengthPosition + sizeOfLengthField)\n" +
337337
" pos = self.getPosition()\n" +
338-
" fmt = '" + byteOrder + "c'\n" +
339-
" for i in range(0,len(buffer)):\n" +
340-
" struct.pack_into(fmt, self.buffer_, lengthPosition[0]+i, buffer[i])\n" +
341-
" self.setPosition(pos[0] + len(buffer))\n\n",
338+
" fmt = '" + byteOrder + "' + str(len(buffer)) + 's'\n" +
339+
" struct.pack_into(fmt, self.buffer_, pos, buffer)\n" +
340+
" self.setPosition(pos + len(buffer))\n\n",
342341
propertyName,
343342
sizeOfLengthField,
344343
lengthPythonType,
@@ -394,7 +393,7 @@ private void generateVarDataDescriptors(
394393

395394
sb.append(String.format(
396395
" def %1$sLength(self):\n" +
397-
" return struct.unpack_from('%4$s', self.buffer_, position())[0]\n\n",
396+
" return struct.unpack_from('%4$s', self.buffer_, getPosition())[0]\n\n",
398397
formatPropertyName(propertyName),
399398
generateArrayFieldNotPresentCondition(token.version(), BASE_INDENT),
400399
formatByteOrderEncoding(lengthToken.encoding().byteOrder(), lengthToken.encoding().primitiveType()),
@@ -432,9 +431,9 @@ private void generateEnum(final List<Token> tokens) throws IOException
432431
try (final Writer out = outputManager.createOutput(enumName))
433432
{
434433
out.append(generateFileHeader(ir.applicableNamespace().replace('.', '_'), null));
435-
out.append(generateEnumDeclaration(enumName));
434+
out.append(generateClassDeclaration(enumName));
436435
out.append(generateEnumValues(tokens.subList(1, tokens.size() - 1), enumToken));
437-
out.append(generateEnumLookupMethod(tokens.subList(1, tokens.size() - 1), enumToken));
436+
out.append(generateEnumMethods(enumName));
438437
}
439438
}
440439

@@ -514,55 +513,65 @@ private CharSequence generateEnumValues(final List<Token> tokens, final Token en
514513
final StringBuilder sb = new StringBuilder();
515514
final Encoding encoding = encodingToken.encoding();
516515

517-
sb.append(" class Value:\n");
516+
for (final Token token : tokens)
517+
{
518+
if (encoding.primitiveType() == PrimitiveType.CHAR)
519+
{
520+
final char constVal = (char) token.encoding().constValue().longValue();
521+
sb.append(" ").append(token.name()).append(" = '").append(constVal).append("'\n");
522+
}
523+
else
524+
{
525+
final CharSequence constVal = generateLiteral(
526+
token.encoding().primitiveType(), token.encoding().constValue().toString());
527+
sb.append(" ").append(token.name()).append(" = ").append(constVal).append("\n");
528+
}
529+
}
530+
531+
// generate the null value
518532

533+
if (encoding.primitiveType() == PrimitiveType.CHAR)
534+
{
535+
sb.append(" NULL_VALUE = '\\0'");
536+
}
537+
else
538+
{
539+
sb.append(String.format(
540+
" NULL_VALUE = %1$s",
541+
generateLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString())
542+
));
543+
}
544+
sb.append("\n\n");
545+
546+
sb.append(" VALID_VALUES = {\n");
519547
for (final Token token : tokens)
520548
{
521-
final CharSequence constVal = generateLiteral(
522-
token.encoding().primitiveType(), token.encoding().constValue().toString());
523-
sb.append(" ").append(token.name()).append(" = ").append(constVal).append("\n");
549+
sb.append(" ").append(token.name()).append(",\n");
524550
}
551+
sb.append(" NULL_VALUE,\n }\n\n");
525552

526-
sb.append(String.format(
527-
" NULL_VALUE = %1$s",
528-
generateLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString())
529-
));
553+
sb.append(" AS_TEXT = {\n");
530554

531-
sb.append("\n\n");
555+
for (final Token token : tokens)
556+
{
557+
sb.append(" ").append(token.name()).append(" : '").append(token.name()).append("',\n");
558+
}
559+
sb.append(" NULL_VALUE : 'NULL_VALUE',\n }\n\n");
532560

533561
return sb;
534562
}
535563

536-
private CharSequence generateEnumLookupMethod(final List<Token> tokens, final Token encodingToken)
564+
private CharSequence generateEnumMethods(final String name)
537565
{
538-
final String enumName = formatClassName(encodingToken.name());
539566
final StringBuilder sb = new StringBuilder();
540567

541-
sb.append(
542-
" @staticmethod\n" +
543-
" def get(value):\n" +
544-
" values = {\n");
545-
546-
for (final Token token : tokens)
547-
{
548-
sb.append(String.format(
549-
" %1$s : %3$s.Value.%2$s,\n",
550-
token.encoding().constValue().toString(),
551-
token.name(),
552-
enumName)
553-
);
554-
}
555-
556-
sb.append(String.format(
557-
" %1$s : %2$s.Value.NULL_VALUE\n" +
558-
" }\n" +
559-
" if type(value) is int:\n" +
560-
" return values[value]\n" +
561-
" else:\n" +
562-
" return values[ord(value)]\n",
563-
encodingToken.encoding().applicableNullValue().toString(),
564-
enumName
565-
));
568+
sb.append(" def __init__(self, value):\n");
569+
sb.append(" self.value = value\n");
570+
sb.append(" if self.value not in ").append(name).append(".VALID_VALUES:\n");
571+
sb.append(" raise ValueError('Invalid value for ").append(name).append(": {}'.format(value))\n");
572+
sb.append("\n");
573+
sb.append(" def __str__(self):\n");
574+
sb.append(" return ").append(name).append(".AS_TEXT[self.value]\n");
566575

567576
return sb;
568577
}
@@ -624,11 +633,6 @@ private CharSequence generateClassDeclaration(final String name)
624633
return "class " + name + ":\n";
625634
}
626635

627-
private CharSequence generateEnumDeclaration(final String name)
628-
{
629-
return "class " + name + ":\n";
630-
}
631-
632636
private CharSequence generatePrimitivePropertyEncodings(
633637
final String containingClassName, final List<Token> tokens, final String indent)
634638
{
@@ -784,12 +788,12 @@ private CharSequence generateArrayProperty(
784788
));
785789

786790
sb.append(String.format(
787-
indent + " def set%1$s(self, index, value):\n" +
791+
indent + " def set%2$s(self, index, value):\n" +
788792
indent + " if index < 0 or index >= %3$d:\n" +
789-
indent + " raise Exception('index out of range for %1$s')\n" +
790-
indent + " struct.pack_into('%2$s', self.buffer_, self.offset_ + %4$d + (index * %5$d), value)\n",
791-
propertyName,
792-
toUpperFirstChar(pythonTypeName),
793+
indent + " raise Exception('index out of range for %2$s')\n" +
794+
indent + " struct.pack_into('%1$s', self.buffer_, self.offset_ + %4$d + (index * %5$d), value)\n",
795+
pythonTypeName,
796+
toUpperFirstChar(propertyName),
793797
token.arrayLength(),
794798
offset,
795799
token.encoding().primitiveType().size(),
@@ -928,15 +932,15 @@ private CharSequence generateMessageFlyweightCode(final Token token)
928932
" return self\n\n" +
929933

930934
" def getPosition(self):\n" +
931-
" return self.position_\n\n" +
935+
" return self.position_[0]\n\n" +
932936

933937
" def setPosition(self, position):\n" +
934938
" if position > self.bufferLength_:\n" +
935939
" raise Exception('buffer too short')\n" +
936940
" self.position_[0] = position\n\n" +
937941

938942
" def encodedLength(self):\n" +
939-
" return self.position() - self.offset_\n\n" +
943+
" return self.getPosition() - self.offset_\n\n" +
940944

941945
" def buffer(self):\n" +
942946
" return self.buffer_\n\n" +
@@ -1054,7 +1058,7 @@ private CharSequence generateEnumProperty(
10541058
sb.append(String.format(
10551059
"\n" +
10561060
indent + " def get%2$s(self):\n" +
1057-
indent + " return %1$s.%1$s.get(struct.unpack_from( '%5$s', self.buffer_, self.offset_ + %6$d)[0])\n\n",
1061+
indent + " return %1$s.%1$s(struct.unpack_from( '%5$s', self.buffer_, self.offset_ + %6$d)[0])\n\n",
10581062
enumName,
10591063
toUpperFirstChar(propertyName),
10601064
generateEnumFieldNotPresentCondition(token.version(), enumName, indent),

0 commit comments

Comments
 (0)