Skip to content

Commit

Permalink
Merge pull request #6 from noisyboiler/v0.7
Browse files Browse the repository at this point in the history
V0.7
  • Loading branch information
noisyboiler authored Jan 9, 2017
2 parents ec85427 + 88412a3 commit c175785
Show file tree
Hide file tree
Showing 33 changed files with 1,095 additions and 1,176 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ python:
- "2.7"

script:
- pip install -r test_requirements.txt
- pip install --editable .[dev]
- py.test ./test -s -vv
20 changes: 11 additions & 9 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ For the quickeststart I suggest that you use Crossbar.io and start it up on the

::

$ pip install -r test_requirements.txt
$ pip install --editable .[dev]

$ crossbar start --config ./test/crossbar.config.json

Expand All @@ -44,10 +44,10 @@ Now open your preferred text editor and we'll write a few lies of Python constru

::

from wampy.peers import WebApplication
from wampy.peers.clients import Client
from wampy.roles import register_rpc

class BinaryNumberService(WebApplication):
class BinaryNumberService(Client):

@register_rpc
def get_binary_number(self, number):
Expand All @@ -63,27 +63,29 @@ For example, running a ``wampy`` example application.

::

$ wampy run docs.examples.services:DateService --router localhost:8080
$ wampy run docs.examples.services:DateService --router http://localhost:8080

Now, open a Python console in a new terminal, allowing the ``BinaryNumberService`` to run uninterupted in your original terminal (but once you're done with it ``Ctrl-C`` is required).

::

In [1]: from wampy.peers import WebClient
In [1]: from wampy.peers.clients import DefaultClient

In [2]: with WebClient(name="wampy") as client:
In [2]: with DefaultClient() as client:
result = client.rpc.get_binary_number(number=100)

In [3]: result
Out[3]: u'0b1100100'

Note that the `WebClient` here is connecting to `localhost` and `8080`, but you could just as easily have done:
Note that the `Client` here is connecting to `localhost` and `8080`, but you could also have done:

::

In [1]: from wampy.peers import WebClient
In [1]: from wampy.peers.clients import Client

In [2]: with WebClient(name="wampy", host="example.com", port=XXXX) as client:
In [2]: from wampy.peers.routers import Crossbar

In [2]: with Client(router=Crossbar()) as client:
result = client.rpc.get_binary_number(number=100)

Please check out the full documentation at ReadTheDocs_ for more patterns.
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/services.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import datetime

from wampy.peers import WebApplication
from wampy.peers.clients import DefaultClient
from wampy.roles import register_rpc


class DateService(WebApplication):
class DateService(DefaultClient):
""" A web service that returns the current date.
usage ::
Expand Down
16 changes: 15 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

setup(
name='wampy',
version='0.6.0',
version='0.7.0',
description='WAMP RPC and Pub/Sub for python apps and microservices',
long_description=long_description,
url='https://github.com/noisyboiler/wampy',
Expand All @@ -31,9 +31,23 @@
install_requires=[
"eventlet==0.18.4",
],
extras_require={
'dev': [
"crossbar==0.15.0",
"pytest==2.9.1",
"mock==1.3.0",
"pytest-capturelog",
"colorlog",
"flake8",
]
},
entry_points={
'console_scripts': [
'wampy=wampy.cli.main:main',
],
# pytest looks up the pytest11 entrypoint to discover its plugins
'pytest11': [
'pytest_wampy=wampy.testing.pytest_plugin',
]
},
)
207 changes: 23 additions & 184 deletions test/conftest.py
Original file line number Diff line number Diff line change
@@ -1,57 +1,35 @@
import json
import logging
import os
import signal
import socket
import subprocess
import sys
from contextlib import closing
from time import time as now, sleep

import colorlog
import pytest

from wampy.constants import DEFAULT_HOST, DEFAULT_PORT
from wampy.networking.connection import WampWebConnection

from wampy.errors import ConnectionError


logger = logging.getLogger('wampy.testing')

logging_level_map = {
'DEBUG': logging.DEBUG,
'INFO': logging.INFO,
}


class ConfigurationError(Exception):
pass


class PytestConfigurationError(Exception):
pass


class TCPConnection(object):
def __init__(self, host, port):
self.host = host
self.port = port

def connect(self):
_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
_socket.connect((self.host, self.port))

def pytest_addoption(parser):
parser.addoption(
'--logging-level',
type=str,
action='store',
dest='logging_level',
help='configure the logging level',
)

def add_file_logging():
root = logging.getLogger()
fhandler = logging.FileHandler(filename='test-runner-log.log', mode='a')
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
parser.addoption(
'--file-logging',
type=bool,
action='store',
dest='file_logging',
help='optionally log to file',
default=False,
)
fhandler.setFormatter(formatter)
root.addHandler(fhandler)
root.setLevel(logging.DEBUG)


def pytest_configure(config):
Expand Down Expand Up @@ -91,151 +69,12 @@ def pytest_configure(config):
add_file_logging()


def pytest_addoption(parser):
parser.addoption(
'--logging-level',
type=str,
action='store',
dest='logging_level',
help='configure the logging level',
)

parser.addoption(
'--file-logging',
type=bool,
action='store',
dest='file_logging',
help='optionally log to file',
default=False,
)


class Crossbar(object):
""" Wrapper around a Crossbar.io CrossBar instance described by
``Crossbar.config``.
"""

def __init__(
self, host, port, config_path, crossbar_directory):

with open(config_path) as data_file:
config_data = json.load(data_file)

self.config = config_data
self.config_path = config_path
self.crossbar_directory = crossbar_directory

self.name = "Test Runner Crossbar"
self.host = host
self.port = port
self.realms = self.config['workers'][0]['realms']
self.roles = self.realms[0]['roles']

self.proc = None

def _wait_until_ready(self, timeout=7, raise_if_not_ready=True):
# we're only ready when it's possible to connect to the CrossBar
# over TCP - so let's just try it.
connection = TCPConnection(host=self.host, port=self.port)
end = now() + timeout

ready = False

while not ready:
timeout = end - now()
if timeout < 0:
if raise_if_not_ready:
raise ConnectionError(
'Failed to connect to CrossBar: {}:{}'.format(
self.host, self.port)
)
else:
return ready

try:
connection.connect()
except socket.error:
pass
else:
ready = True

return ready

def start(self):
""" Start Crossbar.io in a subprocess.
"""
# will attempt to connect or start up the CrossBar
crossbar_config_path = self.config_path
cbdir = self.crossbar_directory

# starts the process from the root of the test namespace
cmd = [
'crossbar', 'start',
'--cbdir', cbdir,
'--config', crossbar_config_path,
]

self.proc = subprocess.Popen(cmd, preexec_fn=os.setsid)

self._wait_until_ready()

def stop(self):
logger.info('sending SIGTERM to %s', self.proc.pid)

try:
os.killpg(os.getpgid(self.proc.pid), signal.SIGTERM)
except Exception as exc:
logger.exception(exc)
logger.warning('could not kill process group')

try:
self.proc.kill()
except:
logger.execption('Failed to kill parent')
sys.exit()
else:
logger.info('killed parent process instead')

# let the shutdown happen
sleep(2)
logger.info('crossbar shut down')


def check_socket(host, port):
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
if sock.connect_ex((host, port)) is None:
raise ConfigurationError(
'{}:{} not available - is crossbar already running?'.format(
host, port
)
)


@pytest.yield_fixture
def router():
crossbar = Crossbar(
host=DEFAULT_HOST,
port=DEFAULT_PORT,
config_path='./test/crossbar.config.json',
crossbar_directory='./',
def add_file_logging():
root = logging.getLogger()
fhandler = logging.FileHandler(filename='test-runner-log.log', mode='a')
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

check_socket(DEFAULT_HOST, DEFAULT_PORT)
crossbar.start()

yield crossbar

crossbar.stop()
check_socket(DEFAULT_HOST, DEFAULT_PORT)


@pytest.fixture
def connection(CrossBar):
connection = WampWebConnection(host=DEFAULT_HOST, port=DEFAULT_PORT)
connection.connect()

assert connection.status == 101 # websocket success status
assert connection.headers['upgrade'] == 'websocket'

return connection
fhandler.setFormatter(formatter)
root.addHandler(fhandler)
root.setLevel(logging.DEBUG)
Loading

0 comments on commit c175785

Please sign in to comment.