Skip to content

Commit

Permalink
Added md5sum to Message (fixes #165) (#169)
Browse files Browse the repository at this point in the history
* added stub _compute_md5

* added md5sum to Message

* don't treat md5 as a property

* outlined preprocessing

* added custom __str__ to Constant

* added __str__ to Field

* added without_package_name to Field

* implemented _compute_md5

* added test_md5sum

* bug fix: md5 -> md5sum

* bug fix: incorrect md5sum calculator, also moved to MsgFormat

* added extra cases to test_md5sum

* bug fix: corrected md5text calculation

* added additional test assertion
  • Loading branch information
ChrisTimperley authored Apr 12, 2019
1 parent c401665 commit b906175
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 3 deletions.
41 changes: 39 additions & 2 deletions src/roswire/definitions/msg.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from io import BytesIO
import logging
import functools
import hashlib
import struct
import re
import os
Expand All @@ -31,7 +32,7 @@
ConstantValue = Union[str, int, float]


@attr.s(frozen=True)
@attr.s(frozen=True, str=False)
class Constant:
typ = attr.ib(type=str)
name = attr.ib(type=str)
Expand All @@ -46,8 +47,11 @@ def to_dict(self) -> Dict[str, Any]:
'name': self.name,
'value': self.value}

def __str__(self) -> str:
return f"{self.typ} {self.name}={str(self.value)}"

@attr.s(frozen=True)

@attr.s(frozen=True, str=False)
class Field:
typ: str = attr.ib()
name: str = attr.ib()
Expand Down Expand Up @@ -85,6 +89,13 @@ def to_dict(self) -> Dict[str, str]:
return {'type': self.typ,
'name': self.name}

def without_package_name(self) -> 'Field':
typ = self.typ.partition('/')[2] if '/' in self.typ else self.typ
return Field(typ, self.name)

def __str__(self) -> str:
return f"{self.typ} {self.name}"


@attr.s(frozen=True)
class MsgFormat:
Expand Down Expand Up @@ -209,6 +220,27 @@ def flatten(self,
fmt = name_to_format[field.typ]
yield from fmt.flatten(name_to_format, ctx + (field.name,))

def md5text(self, name_to_msg: Mapping[str, 'MsgFormat']) -> str:
"""Computes the MD5 text for this format."""
lines: List[str] = []
lines += [str(c) for c in self.constants]
for f in self.fields:
if is_builtin(f.base_type):
lines += [str(f.without_package_name())]
else:
f_md5 = name_to_msg[f.base_type].md5sum(name_to_msg)
lines += [f'{f_md5} {f.name}']
return '\n'.join(lines)

def md5sum(self, name_to_msg: Mapping[str, 'MsgFormat']) -> str:
"""Computes the MD5 sum for this format."""
logger.debug("generating md5sum: %s", self.fullname)
txt = self.md5text(name_to_msg)
logger.debug("generated md5 text [%s]:\n%s", self.fullname, txt)
md5sum = hashlib.md5(txt.encode('utf-8')).hexdigest()
logger.debug("generated md5sum [%s]: %s", self.fullname, md5sum)
return md5sum


class Message:
"""Base class used by all messages."""
Expand Down Expand Up @@ -241,6 +273,11 @@ def to_dict(self) -> Dict[str, Any]:
d[name] = self._to_dict_value(val)
return d

@classmethod
def md5sum(cls) -> str:
"""Returns the md5sum for this message type."""
raise NotImplementedError

@classmethod
def read(cls, b: BinaryIO) -> 'Message':
raise NotImplementedError
Expand Down
4 changes: 3 additions & 1 deletion src/roswire/definitions/type_db.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
__all__ = ('TypeDatabase',)

from typing import (Collection, Type, Mapping, Iterator, Dict, ClassVar, Any,
Sequence, Callable, BinaryIO)
Sequence, Callable, BinaryIO, List)
from collections import OrderedDict

import attr
Expand Down Expand Up @@ -42,6 +42,8 @@ def build(cls, db_format: FormatDatabase) -> 'TypeDatabase':
ns['format'] = fmt
ns['read'] = classmethod(cls._build_read(name_to_type, fmt))
ns['write'] = cls._build_write(name_to_type, fmt)
md5 = fmt.md5sum(db_format.messages)
ns['md5sum'] = classmethod(lambda cls, md5=md5: md5)
t: Type[Message] = type(fmt.name, (Message,), ns)
t = attr.s(t, frozen=True, slots=True)
name_to_type[fmt.fullname] = t
Expand Down
21 changes: 21 additions & 0 deletions test/test_type_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
MsgFormat, Time)

from test_file import build_file_proxy
from test_bag import load_mavros_type_db


def test_build():
Expand Down Expand Up @@ -119,3 +120,23 @@ def test_to_and_from_dict():
'frame_id': 'foo'}
assert m.to_dict() == d
assert db_type.from_dict(fmt, d) == m


def test_md5sum():
db_type = load_mavros_type_db()

def check(name: str, md5sum_expected: str) -> None:
assert db_type[name].md5sum() == md5sum_expected

check('std_msgs/Header', '2176decaecbce78abc3b96ef049fabed')
check('std_msgs/Duration', '3e286caf4241d664e55f3ad380e2ae46')
check('mavros_msgs/CommandCode', 'f7e54ea3892a961cc44c9350fdb0855e')
check('geometry_msgs/Quaternion', 'a779879fadf0160734f906b8c19c7004')
check('geometry_msgs/Vector3', '4a842b65f413084dc2b10fb484ea7f17')
check('geometry_msgs/Wrench', '4f539cf138b23283b520fd271b567936')
check('geometry_msgs/Transform', 'ac9eff44abf714214112b05d54a3cf9b')
check('geometry_msgs/TransformStamped', 'b5764a33bfeb3588febc2682852579b0')
check('tf/tfMessage', '94810edda583a504dfda3829e70d7eec')
check('visualization_msgs/InteractiveMarkerPose', 'a6e6833209a196a38d798dadb02c81f8')
check('mavros_msgs/State', '9e3d873fae342c8f48a8bd64c53d991e')
check('mavros_msgs/Mavlink', '6dd71a38b8541fdc2de89a548c7dbc2f')

0 comments on commit b906175

Please sign in to comment.