diff --git a/marconiclient/__init__.py b/marconiclient/__init__.py index c6df7ec6..e69de29b 100644 --- a/marconiclient/__init__.py +++ b/marconiclient/__init__.py @@ -1,19 +0,0 @@ -# Copyright (c) 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pbr.version - - -__version__ = pbr.version.VersionInfo("python-marconiclient").version_string() diff --git a/marconiclient/tests/__init__.py b/marconiclient/tests/__init__.py new file mode 100644 index 00000000..78f982ce --- /dev/null +++ b/marconiclient/tests/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013 Rackspace, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/marconiclient/tests/mock/__init__.py b/marconiclient/tests/mock/__init__.py new file mode 100644 index 00000000..78f982ce --- /dev/null +++ b/marconiclient/tests/mock/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013 Rackspace, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/marconiclient/tests/mock/message.py b/marconiclient/tests/mock/message.py new file mode 100644 index 00000000..e87e102a --- /dev/null +++ b/marconiclient/tests/mock/message.py @@ -0,0 +1,26 @@ +# Copyright (c) 2013 Rackspace, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Easy creation of mock Marconi message replies.""" + + +def message(href='/v1/queues/dgq/messages/w78sdwsqdsib', + ttl=0, age=0, body=None): + body = body or {} + return { + 'href': href, + 'ttl': ttl, + 'age': age, + 'body': body + } diff --git a/marconiclient/transport/__init__.py b/marconiclient/transport/__init__.py new file mode 100644 index 00000000..78f982ce --- /dev/null +++ b/marconiclient/transport/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013 Rackspace, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/marconiclient/transport/http/__init__.py b/marconiclient/transport/http/__init__.py new file mode 100644 index 00000000..78f982ce --- /dev/null +++ b/marconiclient/transport/http/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013 Rackspace, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/marconiclient/transport/http/message.py b/marconiclient/transport/http/message.py new file mode 100644 index 00000000..f810b939 --- /dev/null +++ b/marconiclient/transport/http/message.py @@ -0,0 +1,76 @@ +# Copyright (c) 2013 Rackspace, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Implements a message controller that understands Marconi messages.""" + + +def _args_from_dict(msg): + return { + 'href': msg['href'], + 'ttl': msg['ttl'], + 'age': msg['age'], + 'body': msg['body'] + } + + +def from_dict(msg, connection=None): + """from_dict(dict, Connection) => Message + :param msg: A dictionary created by decoding a Marconi message JSON reply + :param connection: A connection to a Marconi server. + :raises: KeyError If msg is missing fields + :raises: TypeError if msg is not a dict. + """ + return Message( + connection=connection, + **_args_from_dict(msg) + ) + + +class Message(object): + """A handler for Marconi server Message resources. + Attributes are only downloaded once - at creation time. + """ + def __init__(self, href, ttl, age, body, connection): + self.href = href + self.ttl = ttl + self.age = age + self.body = body + self._connection = connection + self._deleted = False + + def __repr__(self): + return '' % (self.ttl,) + + def _assert_not_deleted(self): + assert not self._deleted, 'Already deleted' + + def reload(self): + """Queries the server and updates all local attributes + with new values. + """ + self._assert_not_deleted() + msg = self._connection.get(self.href).json() + + self.href = msg['href'] + self.ttl = msg['ttl'] + self.age = msg['age'] + self.body = msg['body'] + + def delete(self): + """Deletes this resource from the server, but leaves the local + object intact. + """ + self._assert_not_deleted() + self._connection.delete(self.href) + self._deleted = True diff --git a/marconiclient/transport/zmq/__init__.py b/marconiclient/transport/zmq/__init__.py new file mode 100644 index 00000000..78f982ce --- /dev/null +++ b/marconiclient/transport/zmq/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013 Rackspace, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/marconiclient/version.py b/marconiclient/version.py new file mode 100644 index 00000000..38a5c8bd --- /dev/null +++ b/marconiclient/version.py @@ -0,0 +1,18 @@ +# Copyright (c) 2013 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pbr.version + +version_info = pbr.version.VersionInfo('marconi') diff --git a/requirements.txt b/requirements.txt index 064fd2af..b0256ad2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,6 @@ d2to1>=0.2.10,<0.3 pbr>=0.5.16,<0.6 +six>=1.3.0 + +-f http://tarballs.openstack.org/oslo.config/oslo.config-1.2.0a3.tar.gz#egg=oslo.config-1.2.0a3 +oslo.config>=1.2.0a3 diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py new file mode 100644 index 00000000..78f982ce --- /dev/null +++ b/tests/unit/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013 Rackspace, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/unit/common/__init__.py b/tests/unit/common/__init__.py new file mode 100644 index 00000000..78f982ce --- /dev/null +++ b/tests/unit/common/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013 Rackspace, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/unit/openstack/__init__.py b/tests/unit/openstack/__init__.py new file mode 100644 index 00000000..78f982ce --- /dev/null +++ b/tests/unit/openstack/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013 Rackspace, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/unit/openstack/common/__init__.py b/tests/unit/openstack/common/__init__.py new file mode 100644 index 00000000..78f982ce --- /dev/null +++ b/tests/unit/openstack/common/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013 Rackspace, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/unit/transport/__init__.py b/tests/unit/transport/__init__.py new file mode 100644 index 00000000..78f982ce --- /dev/null +++ b/tests/unit/transport/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013 Rackspace, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/unit/transport/http/__init__.py b/tests/unit/transport/http/__init__.py new file mode 100644 index 00000000..78f982ce --- /dev/null +++ b/tests/unit/transport/http/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013 Rackspace, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/unit/transport/http/test_message.py b/tests/unit/transport/http/test_message.py new file mode 100644 index 00000000..ac469630 --- /dev/null +++ b/tests/unit/transport/http/test_message.py @@ -0,0 +1,72 @@ +# Copyright (c) 2013 Rackspace, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import unittest + +import mock + +from marconiclient.tests.mock import message as mock_message +from marconiclient.transport.http import message + + +HREF = '/v1/queue/dgq/messages/my_msg_is_chocolate' +AGE = 100 +TTL = 120 + + +class TestSimpleMessage(unittest.TestCase): + def setUp(self): + msg_body = { + 'href': HREF, + 'ttl': TTL, + 'age': AGE, + 'body': {'name': 'chocolate'} + } + self.conn = mock.MagicMock() + self.msg = message.from_dict(msg_body, connection=self.conn) + + def _attr_check(self, xhref, xttl, xage, xbody): + self.assertEqual(self.msg.href, xhref) + self.assertEqual(self.msg.ttl, xttl) + self.assertEqual(self.msg.age, xage) + self.assertEqual(self.msg.body, xbody) + + def test_attributes_match_expected(self): + self._attr_check(xhref=HREF, xttl=TTL, xage=AGE, + xbody={'name': 'chocolate'}) + + def test_repr_matches_expected(self): + self.assertEqual(repr(self.msg), + '' % (self.msg.ttl,)) + + def test_delete_works(self): + self.msg.delete() + + def test_reload_works(self): + msg = mock_message.message( + href=HREF, ttl=TTL - 1, age=AGE + 1, + body={'name': 'vanilla'}) + self.conn.get.return_value = mock.MagicMock() + self.conn.get.return_value.json.return_value = msg + self.msg.reload() + self._attr_check(xhref=HREF, xttl=TTL - 1, xage=AGE + 1, + xbody={'name': 'vanilla'}) + + def test_reload_after_delete_throws(self): + self.msg.delete() + self.assertRaises(AssertionError, self.msg.reload) + + def test_delete_after_delete_throws(self): + self.msg.delete() + self.assertRaises(AssertionError, self.msg.delete) diff --git a/tests/unit/transport/zmq/__init__.py b/tests/unit/transport/zmq/__init__.py new file mode 100644 index 00000000..78f982ce --- /dev/null +++ b/tests/unit/transport/zmq/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013 Rackspace, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License.