Skip to content

Commit a0cc505

Browse files
authored
Merge pull request #91 from gramaziokohler/validate_time_input
Validate time input
2 parents 715be2c + f5fe263 commit a0cc505

File tree

7 files changed

+98
-32
lines changed

7 files changed

+98
-32
lines changed

.editorconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,9 @@ trim_trailing_whitespace = false
2020
indent_style = tab
2121
indent_size = 4
2222

23+
[*.yml]
24+
indent_style = space
25+
indent_size = 2
26+
2327
[LICENSE]
2428
insert_final_newline = false

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Unreleased
2121

2222
* Fixed #87 where a goal could be marked as terminal on result alone rather
2323
than both result and status.
24+
* Ensure input of ``Time`` is always two integers.
2425

2526
**Deprecated**
2627

requirements-dev.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
attrs>=19.2.0
2-
bump2version
2+
autopep8
3+
bump2version >=1.0.1
34
check-manifest>=0.36
5+
doc8
46
flake8
57
invoke>=0.14
68
isort>=4.3.21
9+
pydocstyle
710
pytest
8-
sphinx>=1.5
11+
sphinx >=3.4
912
twine
1013
-e .

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ line_length = 180
2727
known_first_party = roslibpy
2828
default_section = THIRDPARTY
2929
forced_separate = test_roslibpy
30-
skip = migrations
30+
skip = migrations, __init__.py

src/roslibpy/__init__.py

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -90,24 +90,50 @@ class and are passed around via :class:`Topics <Topic>` using a **publish/subscr
9090
9191
"""
9292

93-
from .__version__ import __author__
94-
from .__version__ import __author_email__
95-
from .__version__ import __copyright__
96-
from .__version__ import __description__
97-
from .__version__ import __license__
98-
from .__version__ import __title__
99-
from .__version__ import __url__
100-
from .__version__ import __version__
101-
from .core import Header
102-
from .core import Message
103-
from .core import Param
104-
from .core import Service
105-
from .core import ServiceRequest
106-
from .core import ServiceResponse
107-
from .core import Time
108-
from .core import Topic
109-
from .ros import Ros
110-
from .ros import set_rosapi_timeout
111-
112-
__all__ = ['Ros', 'set_rosapi_timeout', 'Message', 'Header', 'Time', 'Param', 'Service', 'ServiceRequest', 'ServiceResponse', 'Topic',
113-
'__author__', '__author_email__', '__copyright__', '__description__', '__license__', '__title__', '__url__', '__version__']
93+
from .__version__ import (
94+
__author__,
95+
__author_email__,
96+
__copyright__,
97+
__description__,
98+
__license__,
99+
__title__,
100+
__url__,
101+
__version__
102+
)
103+
from .core import (
104+
Header,
105+
Message,
106+
Param,
107+
Service,
108+
ServiceRequest,
109+
ServiceResponse,
110+
Time,
111+
Topic
112+
)
113+
from .ros import (
114+
set_rosapi_timeout,
115+
Ros
116+
)
117+
118+
__all__ = [
119+
'__author__',
120+
'__author_email__',
121+
'__copyright__',
122+
'__description__',
123+
'__license__',
124+
'__title__',
125+
'__url__',
126+
'__version__',
127+
128+
'Header',
129+
'Message',
130+
'Param',
131+
'Service',
132+
'ServiceRequest',
133+
'ServiceResponse',
134+
'Time',
135+
'Topic',
136+
137+
'set_rosapi_timeout',
138+
'Ros',
139+
]

src/roslibpy/core.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@
1212

1313
LOGGER = logging.getLogger('roslibpy')
1414

15-
__all__ = ['Message',
16-
'ServiceRequest',
17-
'ServiceResponse',
18-
'Topic',
19-
'Service',
20-
'Param']
15+
__all__ = [
16+
'Header',
17+
'Message',
18+
'Param',
19+
'Service',
20+
'ServiceRequest',
21+
'ServiceResponse',
22+
'Time',
23+
'Topic'
24+
]
2125

2226

2327
class Message(UserDict):
@@ -44,8 +48,15 @@ class Time(UserDict):
4448
"""Represents ROS time with two integers: seconds since epoch and nanoseconds since seconds."""
4549
def __init__(self, secs, nsecs):
4650
self.data = {}
47-
self.data['secs'] = secs
48-
self.data['nsecs'] = nsecs
51+
self.data['secs'] = self._ensure_int(secs)
52+
self.data['nsecs'] = self._ensure_int(nsecs)
53+
54+
def _ensure_int(self, n):
55+
if isinstance(n, int):
56+
return n
57+
if isinstance(n, float) and n.is_integer():
58+
return int(n)
59+
raise ValueError('argument must be an integer')
4960

5061
@property
5162
def secs(self):

tests/test_core.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import pytest
2+
13
from roslibpy import Header
24
from roslibpy import Time
35

@@ -37,3 +39,22 @@ def test_header_ctor_supports_dict():
3739
assert header['stamp']['secs'] == 1610122759
3840
assert header['stamp']['secs'] == header['stamp'].secs
3941
assert header['stamp'].to_sec() == REF_FLOAT_SECS_TIME
42+
43+
44+
def test_time_accepts_only_ints():
45+
with pytest.raises(ValueError):
46+
Time(1.3, 1.0)
47+
with pytest.raises(ValueError):
48+
Time(100.0, 3.1)
49+
50+
t = Time(110.0, 0.0)
51+
assert t.secs == 110
52+
assert t.nsecs == 0
53+
54+
55+
def test_time_properties_are_readonly():
56+
t = Time.now()
57+
with pytest.raises(AttributeError):
58+
t.secs = 10
59+
with pytest.raises(AttributeError):
60+
t.nsecs = 10

0 commit comments

Comments
 (0)