Skip to content

Commit

Permalink
Merge pull request #222 from onefinestay/mandatory-service-name
Browse files Browse the repository at this point in the history
Mandatory service name
  • Loading branch information
davidszotten committed Mar 25, 2015
2 parents 766d7f4 + e02a7ee commit 995fb1b
Show file tree
Hide file tree
Showing 46 changed files with 171 additions and 32 deletions.
4 changes: 2 additions & 2 deletions docs/built_in_extensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Nameko's HTTP entrypoint supports simple GET and POST:
.. code-block:: shell
$ nameko run http
starting services: httpservice
starting services: http_service
.. code-block:: shell
Expand Down Expand Up @@ -88,7 +88,7 @@ The HTTP entrypoint is built on top of `werkzeug <http://werkzeug.pocoo.org/>`_.
.. code-block:: shell
$ nameko run advanced_http
starting services: advancedhttpservice
starting services: advanced_http_service
.. code-block:: shell
Expand Down
1 change: 1 addition & 0 deletions docs/examples/advanced_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from werkzeug.wrappers import Response

class Service(object):
name = "advanced_http_service"

@http('GET', '/privileged')
def forbidden(self):
Expand Down
1 change: 1 addition & 0 deletions docs/examples/example.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from nameko.rpc import rpc, RpcProxy

class Service(object):
name = "service"

# we depend on the RPC interface of "another_service"
other_rpc = RpcProxy("another_service")
Expand Down
1 change: 1 addition & 0 deletions docs/examples/fibonacci.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def get_dependency(self, worker_ctx):


class Fibonacci(object):
name = "fibonacci"

store = DataStore()

Expand Down
4 changes: 2 additions & 2 deletions docs/examples/helloworld.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from nameko.rpc import rpc


class HelloWorld(object):
class GreetingService(object):
name = "greeting_service"

@rpc
def hello(self, name):
Expand Down
1 change: 1 addition & 0 deletions docs/examples/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from nameko.web.handlers import http

class HttpService(object):
name = "http_service"

@http('GET', '/get/<int:value>')
def get_method(self, value):
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/service_container.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from nameko.containers import ServiceContainer

class Service(object):
pass
name = "service"

# create a container
container = ServiceContainer(Service, config={})
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/service_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
from nameko.utils import get_container

class ServiceA(object):
pass
name = "service_a"

class ServiceB(object):
pass
name = "service_b"

# create a runner for ServiceA and ServiceB
runner = ServiceRunner(config={})
Expand Down
1 change: 1 addition & 0 deletions docs/examples/testing/entrypoint_hook.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
class HelloService(object):
""" Service under test
"""
name = "hello_service"

language = Language()

Expand Down
4 changes: 4 additions & 0 deletions docs/examples/testing/large_integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def __iter__(self):


class AcmeShopService(object):
name = "acmeshopservice"

user_basket = ShoppingBasket()
stock_rpc = RpcProxy('stockservice')
Expand Down Expand Up @@ -140,6 +141,7 @@ def get_dependency(self, worker_ctx):


class StockService(object):
name = "stockservice"

warehouse = Warehouse()

Expand Down Expand Up @@ -205,6 +207,7 @@ def get_user_details():


class InvoiceService(object):
name = "invoiceservice"

get_user_details = AddressBook()

Expand All @@ -227,6 +230,7 @@ def prepare_invoice(self, amount):


class PaymentService(object):
name = "paymentservice"

@rpc
def take_payment(self, invoice):
Expand Down
2 changes: 2 additions & 0 deletions docs/examples/testing/unit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
class ConversionService(object):
""" Service under test
"""
name = "conversions"

maths_rpc = RpcProxy("maths")

@rpc
Expand Down
2 changes: 2 additions & 0 deletions docs/examples/testing/unit_test_alternative_dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class Result(Base):
class Service(object):
""" Service under test
"""
name = "service"

db = Session(Base)

@rpc
Expand Down
1 change: 1 addition & 0 deletions docs/examples/timer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from nameko.timer import timer

class Service(object):
name ="service"

@timer(interval=5)
def ping(self):
Expand Down
1 change: 1 addition & 0 deletions docs/examples/travis.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def get_dependency(self, worker_ctx):


class Travis(object):
name = "travis_service"

webservice = TravisWebservice()

Expand Down
1 change: 1 addition & 0 deletions docs/examples/websocket_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from nameko.web.websocket import rpc, WebSocketHubProvider

class WebsocketRpc(object):
name = "websocket_rpc_service"

websocket_hub = WebSocketHubProvider()

Expand Down
7 changes: 4 additions & 3 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ A nameko service is just a class:
from nameko.rpc import rpc
class HelloWorld(object):
class GreetingService(object):
name = "greeting_service"
@rpc
def hello(self, name):
Expand All @@ -29,15 +30,15 @@ You can run it in a shell:
.. code-block:: shell
$ nameko run helloworld
starting services: helloworld
starting services: greeting_service
...
And play with it from another:

.. code-block:: pycon
$ nameko shell
>>> n.rpc.helloworld.hello(name="Matt")
>>> n.rpc.greeting_service.hello(name="Matt")
u'Hello, Matt!'
Expand Down
4 changes: 2 additions & 2 deletions nameko/cli/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import argparse

from nameko.exceptions import CommandError
from nameko.exceptions import CommandError, ConfigurationError
from . import backdoor, run, shell


Expand All @@ -22,5 +22,5 @@ def main():
args = parser.parse_args()
try:
args.main(args)
except CommandError as exc:
except (CommandError, ConfigurationError) as exc:
print "Error: {}".format(exc)
13 changes: 11 additions & 2 deletions nameko/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

from nameko.extensions import (
is_dependency, ENTRYPOINT_EXTENSIONS_ATTR, iter_extensions)
from nameko.exceptions import ContainerBeingKilled
from nameko.exceptions import ContainerBeingKilled, ConfigurationError
from nameko.log_helpers import make_timing_logger
from nameko.utils import repr_safe_str, SpawningSet

Expand All @@ -29,7 +29,16 @@


def get_service_name(service_cls):
return getattr(service_cls, "name", service_cls.__name__.lower())
service_name = getattr(service_cls, 'name', None)
if service_name is None:
raise ConfigurationError(
'Service class must define a `name` attribute ({}.{})'.format(
service_cls.__module__, service_cls.__name__))
if not isinstance(service_name, basestring):
raise ConfigurationError(
'Service name attribute must be a string ({}.{}.name)'.format(
service_cls.__module__, service_cls.__name__))
return service_name


def new_call_id():
Expand Down
4 changes: 4 additions & 0 deletions nameko/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ def __str__(self):
return "Unserializable value: `{}`".format(self.repr_value)


class ConfigurationError(Exception):
pass


class CommandError(Exception):
"""Raise from subcommands to report error back to the user"""

Expand Down
5 changes: 5 additions & 0 deletions nameko/testing/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ def worker_factory(service_cls, **dependencies):
from nameko.rpc import RpcProxy, rpc
class ConversionService(object):
name = "conversions"
maths_rpc = RpcProxy("maths")
@rpc
Expand Down Expand Up @@ -239,6 +241,8 @@ def replace_dependencies(container, *dependencies):
from nameko.standalone.rpc import ServiceRpcProxy
class ConversionService(object):
name = "conversions"
maths_rpc = RpcProxy("maths")
@rpc
Expand Down Expand Up @@ -304,6 +308,7 @@ def restrict_entrypoints(container, *entrypoints):
.. code-block:: python
class Service(object):
name = "service"
@timer(interval=1)
def foo(self, arg):
Expand Down
1 change: 1 addition & 0 deletions nameko/timer.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def __init__(self, interval):
timer = Timer.decorator
class Service(object):
name = "service"
@timer(interval=5)
def tick(self):
Expand Down
7 changes: 4 additions & 3 deletions test/cli/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import pytest

from nameko.cli.main import main, setup_parser
from nameko.exceptions import CommandError
from nameko.exceptions import CommandError, ConfigurationError


@pytest.yield_fixture(autouse=True)
Expand All @@ -31,9 +31,10 @@ def test_run():
assert args.broker == 'my_broker'


def test_error(capsys):
@pytest.mark.parametrize('exception', (CommandError, ConfigurationError))
def test_error(exception, capsys):
with patch('nameko.cli.main.run.main') as run:
run.side_effect = CommandError('boom')
run.side_effect = exception('boom')
main()
out, _ = capsys.readouterr()
assert out.strip() == 'Error: boom'
Expand Down
21 changes: 14 additions & 7 deletions test/cli/test_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from nameko.cli.main import setup_parser
from nameko.cli.run import import_service, setup_backdoor, main, run
from nameko.exceptions import CommandError
from nameko.runners import ServiceRunner
from nameko.standalone.rpc import ClusterRpcProxy

from test.sample import Service
Expand Down Expand Up @@ -114,7 +115,7 @@ def test_stopping(rabbit_config):
KeyboardInterrupt,
None, # second wait, after stop() which returns normally
]
gt = eventlet.spawn(run, [object], rabbit_config)
gt = eventlet.spawn(run, [Service], rabbit_config)
gt.wait()
# should complete

Expand All @@ -131,7 +132,7 @@ def test_stopping_twice(rabbit_config):
runner.stop.side_effect = KeyboardInterrupt
runner.kill.return_value = None

gt = eventlet.spawn(run, [object], rabbit_config)
gt = eventlet.spawn(run, [Service], rabbit_config)
gt.wait()


Expand All @@ -142,8 +143,11 @@ def test_os_error_for_signal(rabbit_config):
OSError(errno.EINTR, ''),
None, # second wait, after stop() which returns normally
]
gt = eventlet.spawn(run, [object], rabbit_config)
gt.wait()
# don't actually start the service -- we're not firing a real signal
# so the signal handler won't stop it again
with patch.object(ServiceRunner, 'start'):
gt = eventlet.spawn(run, [Service], rabbit_config)
gt.wait()
# should complete


Expand All @@ -154,6 +158,9 @@ def test_other_errors_propagate(rabbit_config):
OSError(0, ''),
None, # second wait, after stop() which returns normally
]
gt = eventlet.spawn(run, [object], rabbit_config)
with pytest.raises(OSError):
gt.wait()
# don't actually start the service -- there's no real OSError that
# would otherwise kill the whole process
with patch.object(ServiceRunner, 'start'):
gt = eventlet.spawn(run, [Service], rabbit_config)
with pytest.raises(OSError):
gt.wait()
2 changes: 2 additions & 0 deletions test/sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@


class Service(object):
name = "service"

@rpc
def ping(self):
pass
2 changes: 2 additions & 0 deletions test/standalone/test_rpc_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ def test_multiple_calls_to_result(container_factory, rabbit_config):


class ExampleService(object):
name = "exampleservice"

def callback(self):
# to be patched out with mock
pass
Expand Down
3 changes: 3 additions & 0 deletions test/test_broker.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def logger():


class ExampleService(object):
name = "exampleservice"

@rpc
def echo(self, arg):
Expand All @@ -66,6 +67,8 @@ def handle(self, evt_data):


class ProxyService(object):
name = "proxyservice"

example_rpc = RpcProxy('exampleservice')

@dummy
Expand Down

0 comments on commit 995fb1b

Please sign in to comment.