<commit_before># coding: utf-8
"""
Flask-OAuthlib
--------------

Implemnts OAuth1 and OAuth2 support for Flask.

:copyright: (c) 2013 by Hsiaoming Yang.
"""

import urllib2
import oauthlib.oauth1
import oauthlib.oauth2
from functools import wraps
from oauthlib.common import to_unicode
from urlparse import urljoin
from flask import request, redirect, json, session
from werkzeug import url_quote, url_decode, url_encode, parse_options_header

__all__ = [
    'OAuth', 'OAuthRemoteApp', 'OAuthResponse', 'OAuthException',
    'twitter_urls', 'facebook_urls', 'google_urls',
    'weibo_urls', 'douban_urls',
]

class OAuth(object):
    """Registry for remote applications.

    :param app: the app instance of Flask

    Create an instance with Flask::

        oauth = OAuth(app)
    """

    def __init__(self, app=None):
        self.remote_apps = {}

        if app:
            self.init_app(app)

    def init_app(self, app):
        """
        You can also pass the instance of Flask later::

            oauth = OAuth()
            oauth.init_app(app)
        """

        self.app = app
        app.extensions = getattr(app, 'extensions', {})
        app.extensions['oauth-client'] = self

    def remote_app(self, name, register=True, **kwargs):
        """Registers a new remote application.

        :param name: the name of the remote application
        :param register: whether the remote app will be registered

        Find more parameters from :class:`OAuthRemoteApp`.
        """

        app = OAuthRemoteApp(self, name, **kwargs)
        if register:
            assert name not in self.remote_apps
            self.remote_apps[name] = app
        return app

    def __getattr__(self, key):
        try:
            return object.__getattribute__(self, key)
        except AttributeError:
            app = self.remote_apps.get(key)
            if app:
                return app
            raise AttributeError('No such app: %s' % key)

_etree = None

def get_etree():
    global _etree
    if _etree is not None:
        return _etree
    try:
        from lxml import etree as _etree
    except ImportError:
        try:
            from xml.etree import cElementTree as _etree
        except ImportError:
            try:
                from xml.etree import ElementTree as _etree
            except ImportError:
                raise TypeError('lxml or etree not found')
    return _etree

def parse_response(resp, content, strict=False, content_type=None):
    """
    Parse the response returned by :meth:`make_request`.
    """
    if not content_type:
        content_type = resp.headers.get('content-type', 'application/json')
    ct, options = parse_options_header(content_type)

    if ct in ('application/json', 'text/javascript'):
        return json.loads(content)

    if ct in ('application/xml', 'text/xml'):
        charset = options.get('charset', 'utf-8')
        return get_etree().fromstring(content.decode(charset))

    if ct != 'application/x-www-form-urlencoded' and strict:
        return content
    charset = options.get('charset', 'utf-8')
    return url_decode(content, charset=charset).to_dict()

def make_request(uri, headers, data=None, method='GET'):
    req = urllib2.Request(uri, headers=headers, data=data)

    if data and method == 'GET':
        method = 'POST'

    req.get_method = lambda: method.upper()
    resp = urllib2.urlopen(req)
    content = resp.read()
    resp.close()
    return resp, content

def add_query(url, args):
    if not args:
        return url
    return url + ('?' in url and '&' or '?') + url_encode(args)

def encode_request_data(data, format):
    if format is None:
        return data, None
    if format == 'json':
        return json.dumps(data or {}), 'application/json'
    if format == 'urlencoded':
        return url_encode(data or {}), 'application/x-www-form-urlencoded'
    raise TypeError('Unknown format %r' % format)

class OAuthResponse(object):
    def __init__(self, resp, content, content_type=None):
        self._resp = resp
        self.raw_data = content
        self.data = parse_response(
            resp, content, strict=True,
            content_type=content_type,
        )

    @property
    def status(self):
        """The status code of the response."""
        return self._resp.code

class OAuthException(RuntimeError):
    def __init__(self, message, type=None, data=None):
        self.message = message
        self.type = type
        self.data = data

    def __str__(self):
        return self.message.encode('utf-8')

    def __unicode__(self):
        return self.message

class OAuthRemoteApp(object):
    """Represents a remote application.

    :param oauth: the associated :class:`OAuth` object
    :param name: the name of the remote application
    :param base_url: the base url for every request
    :param request_token_url: the url for requesting new tokens
    :param access_token_url: the url for token exchange
    :param authorize_url: the url for authorization
    :param consumer_key: the application specific consumer key
    :param consumer_secret: the application specific consumer secret
    :param request_token_params: an optional dictionary of parameters
                                 to forward to the request token url
                                 or authorize url depending on oauth
                                 version
    :param access_token_params: an optional dictionary of parameters to
                                forward to the access token url
    :param access_token_method: the HTTP method that should be used for
                                the access_token_url. Default is ``GET``
    :param content_type: force to parse the content with this content_type,
                         usually used when the server didn't return the
                         right content type.
    """
    def __init__(
        self, oauth, name,
        base_url, request_token_url,
        access_token_url, authorize_url,
        consumer_key, consumer_secret,
        request_token_params=None,
        access_token_params=None,
        access_token_method='GET',
        content_type=None,
        encoding='utf-8',
    ):

        self.oauth = oauth
        self.base_url = base_url
        self.name = name
        self.request_token_url = request_token_url
        self.access_token_url = access_token_url
        self.authorize_url = authorize_url
        self.consumer_key = consumer_key
        self.consumer_secret = consumer_secret
        self.tokengetter_func = None
        self.request_token_params = request_token_params or {}
        self.access_token_params = access_token_params or {}
        self.access_token_method = access_token_method
        self.content_type = content_type
        self.encoding = encoding

    def make_client(self, token=None):
        # request_token_url is for oauth1
        if self.request_token_url:
            client = oauthlib.oauth1.Client(
                self.consumer_key, self.consumer_secret
            )
            if token and isinstance(token, (tuple, list)):
                client.resource_owner_key, client.resource_owner_secret = token
        else:
            client = oauthlib.oauth2.WebApplicationClient(self.consumer_key)
        return client

    def get(self, *args, **kwargs):
        """Sends a ``GET`` request. Accepts the same paramters as
        :meth:`request`.
        """
        kwargs['method'] = 'GET'
        return self.request(*args, **kwargs)

    def post(self, *args, **kwargs):
        """Sends a ``POST`` request. Accepts the same paramters as
        :meth:`request`.
        """
        kwargs['method'] = 'POST'
        return self.request(*args, **kwargs)

    def put(self, *args, **kwargs):
        """Sends a ``PUT`` request. Accepts the same paramters as
        :meth:`request`.
        """
        kwargs['method'] = 'PUT'
        return self.request(*args, **kwargs)

    def delete(self, *args, **kwargs):
        """Sends a ``DELETE`` request. Accepts the same paramters as
        :meth:`request`.
        """
        kwargs['method'] = 'DELETE'
        return self.request(*args, **kwargs)

    def request(self, url, data=None, headers=None, format='urlencoded',
                method='GET', content_type=None, token=None):
        """
        Sends a request to the remote server with OAuth tokens attached.

        :param data: the data to be sent to the server.
        :param headers: an optional dictionary of headers.
        :param format: the format for the `data`. Can be `urlencoded` for
                       URL encoded data or `json` for JSON.
        :param method: the HTTP request method to use.
        :param content_type: an optional content type. If a content type
                             is provided, the data is passed as it, and
                             the `format` is ignored.
        :param token: an optional token to pass, if it is None, token will
                      be generated be tokengetter.
        """

        headers = dict(headers or {})
        if not token:
            token = self.get_request_token()

        client = self.make_client(token)
        url = self.expand_url(url)
        if method == 'GET':
            assert format == 'urlencoded'
            if data:
                url = add_query(url, data)
                data = None
        else:
            if content_type is None:
                data, content_type = encode_request_data(data, format)
            if content_type is not None:
                headers['Content-Type'] = content_type

        uri, headers, body = client.sign(
            url, http_method=method, body=data, headers=headers
        )
        resp, content = make_request(
            uri, headers, data=body, method=method
        )
        return OAuthResponse(resp, content, self.content_type)

    def authorize(self, callback=None):
        """
        Returns a redirect response to the remote authorization URL with
        the signed callback given.
        """
        if self.request_token_url:
            token = self.generate_request_token(callback)[0]
            url = '%s?oauth_token=%s' % (
                self.expand_url(self.authorize_url), url_quote(token)
            )
        else:
            assert callback is not None, 'Callback is required OAuth2'

        return redirect(url)

    def tokengetter(self, f):
        """
        Register a function as token getter.
        """
        self.tokengetter_func = f
        return f

    def expand_url(self, url):
        return urljoin(self.base_url, url)

    def generate_request_token(self, callback=None):
        # for oauth1 only
        if callback is not None:
            callback = urljoin(request.url, callback)

        client = self.make_client()
        client.callback_uri = _encode(callback, self.encoding)
        uri, headers, _ = client.sign(
            self.expand_url(self.request_token_url)
        )
        resp, content = make_request(uri, headers)
        if resp.code not in (200, 201):
            raise OAuthException(
                'Failed to generate request token',
                type='token_generation_failed'
            )
        data = parse_response(resp, content)
        if data is None:
            raise OAuthException(
                'Invalid token response from %s' % self.name,
                type='token_generation_failed'
            )
        tup = (data['oauth_token'], data['oauth_token_secret'])
        session['%s_oauthtok' % self.name] = tup
        return tup

    def get_request_token(self):
        assert self.tokengetter_func is not None, 'missing tokengetter'
        rv = self.tokengetter_func()
        if rv is None:
            raise OAuthException('No token available', type='token_missing')
        return rv

    def handle_oauth1_response(self):
        """Handles an oauth1 authorization response."""
        client = self.make_client()
        client.verifier = request.args.get('oauth_verifier')
        tup = session.get('%s_oauthtok' % self.name)
        client.resource_owner_key = tup[0]
        client.resource_owner_secret = tup[1]

        uri, headers, data = client.sign(
            self.expand_url(self.access_token_url),
            _encode(self.access_token_method)
        )

        resp, content = make_request(uri, headers, data)
        data = parse_response(resp, content)
        if resp.code not in (200, 201):
            raise OAuthException(
                'Invalid response from %s' % self.name,
                type='invalid_response', data=data
            )
        return data

    def handle_oauth2_response(self):
        pass

    def authorized_handler(self, f):
        @wraps(f)
        def decorated(*args, **kwargs):
            if 'oauth_verifier' in request.args:
                data = self.handle_oauth1_response()
            elif 'code' in request.args:
                data = self.handle_oauth2_response()
            else:
                data = self.handle_unknown_response()

            # free request token
            session.pop('%s_oauthtok' % self.name, None)
            return f(*((data,) + args), **kwargs)
        return decorated

def _encode(text, encoding='utf-8'):
    if encoding:
        return to_unicode(text, encoding)
    return text

# some common services
twitter_urls = dict(
    base_url='https://api.twitter.com/1/',
    request_token_url='https://api.twitter.com/oauth/request_token',
    access_token_url='https://api.twitter.com/oauth/access_token',
    authorize_url='https://api.twitter.com/oauth/authenticate',
)
facebook_urls = dict(
    base_url='https://graph.facebook.com',
    request_token_url=None,
    access_token_url='/oauth/access_token',
    authorize_url='https://www.facebook.com/dialog/oauth'
)
google_urls = dict(
    base_url='https://www.google.com/accounts/',
    authorize_url='https://accounts.google.com/o/oauth2/auth',
    request_token_url=None,
    access_token_url='https://accounts.google.com/o/oauth2/token',
)
weibo_urls = dict(
)
douban_urls = dict(
)
<commit_msg>facebook works<commit_after># coding: utf-8
"""
Flask-OAuthlib
--------------

Implemnts OAuth1 and OAuth2 support for Flask.

:copyright: (c) 2013 by Hsiaoming Yang.
"""

import urllib2
import oauthlib.oauth1
import oauthlib.oauth2
from functools import wraps
from oauthlib.common import to_unicode
from urlparse import urljoin
from flask import request, redirect, json, session
from werkzeug import url_quote, url_decode, url_encode, parse_options_header

__all__ = [
    'OAuth', 'OAuthRemoteApp', 'OAuthResponse', 'OAuthException',
    'twitter_urls', 'facebook_urls', 'google_urls',
    'weibo_urls', 'douban_urls',
]

class OAuth(object):
    """Registry for remote applications.

    :param app: the app instance of Flask

    Create an instance with Flask::

        oauth = OAuth(app)
    """

    def __init__(self, app=None):
        self.remote_apps = {}

        if app:
            self.init_app(app)

    def init_app(self, app):
        """
        You can also pass the instance of Flask later::

            oauth = OAuth()
            oauth.init_app(app)
        """

        self.app = app
        app.extensions = getattr(app, 'extensions', {})
        app.extensions['oauth-client'] = self

    def remote_app(self, name, register=True, **kwargs):
        """Registers a new remote application.

        :param name: the name of the remote application
        :param register: whether the remote app will be registered

        Find more parameters from :class:`OAuthRemoteApp`.
        """

        app = OAuthRemoteApp(self, name, **kwargs)
        if register:
            assert name not in self.remote_apps
            self.remote_apps[name] = app
        return app

    def __getattr__(self, key):
        try:
            return object.__getattribute__(self, key)
        except AttributeError:
            app = self.remote_apps.get(key)
            if app:
                return app
            raise AttributeError('No such app: %s' % key)

_etree = None

def get_etree():
    global _etree
    if _etree is not None:
        return _etree
    try:
        from lxml import etree as _etree
    except ImportError:
        try:
            from xml.etree import cElementTree as _etree
        except ImportError:
            try:
                from xml.etree import ElementTree as _etree
            except ImportError:
                raise TypeError('lxml or etree not found')
    return _etree

def parse_response(resp, content, strict=False, content_type=None):
    """
    Parse the response returned by :meth:`make_request`.
    """
    if not content_type:
        content_type = resp.headers.get('content-type', 'application/json')
    ct, options = parse_options_header(content_type)

    if ct in ('application/json', 'text/javascript'):
        return json.loads(content)

    if ct in ('application/xml', 'text/xml'):
        charset = options.get('charset', 'utf-8')
        return get_etree().fromstring(content.decode(charset))

    if ct != 'application/x-www-form-urlencoded' and strict:
        return content
    charset = options.get('charset', 'utf-8')
    return url_decode(content, charset=charset).to_dict()

def make_request(uri, headers=None, data=None, method='GET'):
    if headers is None:
        headers = {}

    req = urllib2.Request(uri, headers=headers, data=data)

    if data and method == 'GET':
        method = 'POST'

    req.get_method = lambda: method.upper()
    resp = urllib2.urlopen(req)
    content = resp.read()
    resp.close()
    return resp, content

def add_query(url, args):
    if not args:
        return url
    return url + ('?' in url and '&' or '?') + url_encode(args)

def encode_request_data(data, format):
    if format is None:
        return data, None
    if format == 'json':
        return json.dumps(data or {}), 'application/json'
    if format == 'urlencoded':
        return url_encode(data or {}), 'application/x-www-form-urlencoded'
    raise TypeError('Unknown format %r' % format)

class OAuthResponse(object):
    def __init__(self, resp, content, content_type=None):
        self._resp = resp
        self.raw_data = content
        self.data = parse_response(
            resp, content, strict=True,
            content_type=content_type,
        )

    @property
    def status(self):
        """The status code of the response."""
        return self._resp.code

class OAuthException(RuntimeError):
    def __init__(self, message, type=None, data=None):
        self.message = message
        self.type = type
        self.data = data

    def __str__(self):
        return self.message.encode('utf-8')

    def __unicode__(self):
        return self.message

class OAuthRemoteApp(object):
    """Represents a remote application.

    :param oauth: the associated :class:`OAuth` object
    :param name: the name of the remote application
    :param base_url: the base url for every request
    :param request_token_url: the url for requesting new tokens
    :param access_token_url: the url for token exchange
    :param authorize_url: the url for authorization
    :param consumer_key: the application specific consumer key
    :param consumer_secret: the application specific consumer secret
    :param request_token_params: an optional dictionary of parameters
                                 to forward to the request token url
                                 or authorize url depending on oauth
                                 version
    :param access_token_params: an optional dictionary of parameters to
                                forward to the access token url
    :param access_token_method: the HTTP method that should be used for
                                the access_token_url. Default is ``GET``
    :param content_type: force to parse the content with this content_type,
                         usually used when the server didn't return the
                         right content type.
    """
    def __init__(
        self, oauth, name,
        base_url, request_token_url,
        access_token_url, authorize_url,
        consumer_key, consumer_secret,
        request_token_params=None,
        access_token_params=None,
        access_token_method='GET',
        content_type=None,
        encoding='utf-8',
    ):

        self.oauth = oauth
        self.base_url = base_url
        self.name = name
        self.request_token_url = request_token_url
        self.access_token_url = access_token_url
        self.authorize_url = authorize_url
        self.consumer_key = consumer_key
        self.consumer_secret = consumer_secret
        self.tokengetter_func = None
        self.request_token_params = request_token_params or {}
        self.access_token_params = access_token_params or {}
        self.access_token_method = access_token_method
        self.content_type = content_type
        self.encoding = encoding

    def make_client(self, token=None):
        # request_token_url is for oauth1
        if self.request_token_url:
            client = oauthlib.oauth1.Client(
                self.consumer_key, self.consumer_secret
            )
            if token and isinstance(token, (tuple, list)):
                client.resource_owner_key, client.resource_owner_secret = token
        else:
            if token and isinstance(token, (tuple, list)):
                token = {'access_token': token[0]}
            client = oauthlib.oauth2.WebApplicationClient(
                self.consumer_key, token=token
            )
        return client

    def get(self, *args, **kwargs):
        """Sends a ``GET`` request. Accepts the same paramters as
        :meth:`request`.
        """
        kwargs['method'] = 'GET'
        return self.request(*args, **kwargs)

    def post(self, *args, **kwargs):
        """Sends a ``POST`` request. Accepts the same paramters as
        :meth:`request`.
        """
        kwargs['method'] = 'POST'
        return self.request(*args, **kwargs)

    def put(self, *args, **kwargs):
        """Sends a ``PUT`` request. Accepts the same paramters as
        :meth:`request`.
        """
        kwargs['method'] = 'PUT'
        return self.request(*args, **kwargs)

    def delete(self, *args, **kwargs):
        """Sends a ``DELETE`` request. Accepts the same paramters as
        :meth:`request`.
        """
        kwargs['method'] = 'DELETE'
        return self.request(*args, **kwargs)

    def request(self, url, data=None, headers=None, format='urlencoded',
                method='GET', content_type=None, token=None):
        """
        Sends a request to the remote server with OAuth tokens attached.

        :param data: the data to be sent to the server.
        :param headers: an optional dictionary of headers.
        :param format: the format for the `data`. Can be `urlencoded` for
                       URL encoded data or `json` for JSON.
        :param method: the HTTP request method to use.
        :param content_type: an optional content type. If a content type
                             is provided, the data is passed as it, and
                             the `format` is ignored.
        :param token: an optional token to pass, if it is None, token will
                      be generated be tokengetter.
        """

        headers = dict(headers or {})
        if not token:
            token = self.get_request_token()

        client = self.make_client(token)
        url = self.expand_url(url)
        if method == 'GET':
            assert format == 'urlencoded'
            if data:
                url = add_query(url, data)
                data = None
        else:
            if content_type is None:
                data, content_type = encode_request_data(data, format)
            if content_type is not None:
                headers['Content-Type'] = content_type

        if self.request_token_url:
            # oauth1
            uri, headers, body = client.sign(
                url, http_method=method, body=data, headers=headers
            )
        else:
            # oauth2
            uri, headers, body = client.add_token(
                url, http_method=method, body=data, headers=headers
            )
        resp, content = make_request(
            uri, headers, data=body, method=method
        )
        return OAuthResponse(resp, content, self.content_type)

    def authorize(self, callback=None):
        """
        Returns a redirect response to the remote authorization URL with
        the signed callback given.
        """
        if self.request_token_url:
            token = self.generate_request_token(callback)[0]
            url = '%s?oauth_token=%s' % (
                self.expand_url(self.authorize_url), url_quote(token)
            )
        else:
            assert callback is not None, 'Callback is required OAuth2'

            params = dict(self.request_token_params)
            client = self.make_client()

            scope = params.pop('scope')
            if isinstance(scope, str):
                scope = _encode(scope, self.encoding)

            session['%s_oauthredir' % self.name] = callback
            url = client.prepare_request_uri(
                self.expand_url(self.authorize_url),
                redirect_uri=callback,
                scope=scope,
                **params
            )
        return redirect(url)

    def tokengetter(self, f):
        """
        Register a function as token getter.
        """
        self.tokengetter_func = f
        return f

    def expand_url(self, url):
        return urljoin(self.base_url, url)

    def generate_request_token(self, callback=None):
        # for oauth1 only
        if callback is not None:
            callback = urljoin(request.url, callback)

        client = self.make_client()
        client.callback_uri = _encode(callback, self.encoding)
        uri, headers, _ = client.sign(
            self.expand_url(self.request_token_url)
        )
        resp, content = make_request(uri, headers)
        if resp.code not in (200, 201):
            raise OAuthException(
                'Failed to generate request token',
                type='token_generation_failed'
            )
        data = parse_response(resp, content)
        if data is None:
            raise OAuthException(
                'Invalid token response from %s' % self.name,
                type='token_generation_failed'
            )
        tup = (data['oauth_token'], data['oauth_token_secret'])
        session['%s_oauthtok' % self.name] = tup
        return tup

    def get_request_token(self):
        assert self.tokengetter_func is not None, 'missing tokengetter'
        rv = self.tokengetter_func()
        if rv is None:
            raise OAuthException('No token available', type='token_missing')
        return rv

    def handle_oauth1_response(self):
        """Handles an oauth1 authorization response."""
        client = self.make_client()
        client.verifier = request.args.get('oauth_verifier')
        tup = session.get('%s_oauthtok' % self.name)
        client.resource_owner_key = tup[0]
        client.resource_owner_secret = tup[1]

        uri, headers, data = client.sign(
            self.expand_url(self.access_token_url),
            _encode(self.access_token_method)
        )

        resp, content = make_request(uri, headers, data)
        data = parse_response(resp, content)
        if resp.code not in (200, 201):
            raise OAuthException(
                'Invalid response from %s' % self.name,
                type='invalid_response', data=data
            )
        return data

    def handle_oauth2_response(self):
        """Handles an oauth2 authorization response."""

        client = self.make_client()
        remote_args = {
            'code': request.args.get('code'),
            'client_secret': self.consumer_secret,
            'redirect_uri': session.get('%s_oauthredir' % self.name)
        }
        remote_args.update(self.access_token_params)
        if self.access_token_method == 'POST':
            body = client.prepare_request_body(**remote_args)
            resp, content = make_request(
                self.expand_url(self.access_token_url),
                data=url_decode(body),
                method=self.access_token_method
            )
        elif self.access_token_method == 'GET':
            url = client.prepare_request_uri(
                self.expand_url(self.access_token_url), **remote_args
            )
            resp, content = make_request(url, method=self.access_token_method)
        else:
            raise OAuthException(
                'Unsupported access_token_method: %s' % \
                self.access_token_method
            )

        data = parse_response(resp, content, content_type=self.content_type)
        if resp.code not in (200, 201):
            raise OAuthException(
                'Invalid response from %s' % self.name,
                type='invalid_response', data=data
            )
        return data

    def authorized_handler(self, f):
        @wraps(f)
        def decorated(*args, **kwargs):
            if 'oauth_verifier' in request.args:
                data = self.handle_oauth1_response()
            elif 'code' in request.args:
                data = self.handle_oauth2_response()
            else:
                data = self.handle_unknown_response()

            # free request token
            session.pop('%s_oauthtok' % self.name, None)
            session.pop('%s_oauthredir' % self.name, None)
            return f(*((data,) + args), **kwargs)
        return decorated

def _encode(text, encoding='utf-8'):
    if encoding:
        return to_unicode(text, encoding)
    return text

# some common services
twitter_urls = dict(
    base_url='https://api.twitter.com/1/',
    request_token_url='https://api.twitter.com/oauth/request_token',
    access_token_url='https://api.twitter.com/oauth/access_token',
    authorize_url='https://api.twitter.com/oauth/authenticate',
)
facebook_urls = dict(
    base_url='https://graph.facebook.com',
    request_token_url=None,
    access_token_url='/oauth/access_token',
    authorize_url='https://www.facebook.com/dialog/oauth'
)
google_urls = dict(
    base_url='https://www.google.com/accounts/',
    authorize_url='https://accounts.google.com/o/oauth2/auth',
    request_token_url=None,
    access_token_url='https://accounts.google.com/o/oauth2/token',
)
weibo_urls = dict(
)
douban_urls = dict(
)
<|endoftext|>


<commit_before>import random

### DATA ###

data = {
	"APPLE" : {
			"sentences" :

				[

				{"string": "It is MOD DESC", "type": 0}, {"string": "Oh, it's MOD DESC", "type": 0}, {"string": "Gosh, that's MOD DESC", "type": 0}, {"string": "MOD DESC now", "type": 0}, {"string": "Well, that's MOD DESC", "type": 0}, {"string": "I am MOD DESC", "type": 1}, {"string": "Am I DESC?", "type": 2}, {"string": "Is it DESC?", "type": 3}

				]

			,

			"descriptors" :

				[

				["light", 0, lambda m: m > 0.5 and m < 1.0], ["bright", 0, lambda m: m > 0.6 and m < 1.0], ["beaming", 0, lambda m: m > 0.8 and m < 1.0], ["dark", 0, lambda m: m > 0.0 and m < 0.5], ["murky", 0, lambda m: m > 0.0 and m < 0.5], ["shadowy", 0, lambda m: m > 0.0 and m < 0.5], ["basking", 1, lambda m: m > 0.5 and m < 1.0], ["shaded", 1, lambda m: m > 0.0 and m < 0.5], ["ripening", 1, lambda m: m > 0.5 and m < 1.0], ["ripe", 2, lambda m: m > 0.0 and m < 1.0], ["night", 3, lambda m: m > 0.0 and m < 0.5], ["daytime", 3, lambda m: m > 0.5 and m < 1.0], ["bathed in light", 4, lambda m: m > 0.5 and m < 1.0], ["illuminated", 4, lambda m: m > 0.6 and m < 1.0]

				]

	},
	"MUG" : {
			"sentences" :

				[

				{"string": "It is MOD DESC", "type": 0}, {"string": "It is MOD DESC now, would you like some DRINK?", "type": 0}, {"string": "Oh, it's getting MOD DESC. Might be time for DRINK.", "type": 0}, {"string": "Aren't you MOD DESC now? Some DRINK might be a good idea.", "type": 0}

				]

			,

			"descriptors" :

				[

				["warm", 0, lambda m: m > 0.5 and m < 1.0], ["temperate", 0, lambda m: m > 0.4 and m < 0.6], ["cozy", 0, lambda m: m > 0.5 and m < 0.7], ["hot", 0, lambda m: m > 0.7 and m < 1.0], ["sweltering", 0, lambda m: m > 0.8 and m < 1.0], ["cool", 0, lambda m: m > 0.2 and m < 0.5], ["cold", 0, lambda m: m > 0.0 and m < 0.3], ["chilly", 0, lambda m: m > 0.0 and m < 0.3], ["freezing", 0, lambda m: m > 0.0 and m < 0.3], ["brisk", 0, lambda m: m > 0.2 and m < 0.5], ["lukewarm", 0, lambda m: m > 0.4 and m < 0.6]

				]
			,
			"drinks" :

				[

				["tea", lambda m: m > 0.0 and m < 0.5], ["coffee", lambda m: m > 0.0 and m < 0.5], ["cocoa", lambda m: m > 0.0 and m < 0.5], ["hot toddy", lambda m: m > 0.0 and m < 0.5], ["warm milk", lambda m: m > 0.0 and m < 0.5], ["hot cider", lambda m: m > 0.0 and m < 0.5], ["lemonade", lambda m: m > 0.5 and m < 1.0], ["water", lambda m: m > 0.5 and m < 1.0], ["iced tea", lambda m: m > 0.5 and m < 1.0], ["iced coffee", lambda m: m > 0.5 and m < 1.0], ["soda", lambda m: m > 0.5 and m < 1.0], ["seltzer", lambda m: m > 0.5 and m < 1.0], ["cold drink", lambda m: m > 0.5 and m < 1.0], ["hot or cold beverage", lambda m: m > 0.4 and m < 0.6]

				]

	},
	"BLOCKS" : {
			"sentences" :

				[

				{"string": "It is DESC", "type": 0}, {"string": "DESC here", "type": 1}, {"string": "DESC with us now", "type": 1}, {"string": "DESC present", "type": 1}, {"string": "DESC near", "type": 1}, {"string": "We see DESC", "type": 2}, {"string": "We see DESC has arrived", "type": 3}, {"string": "We see DESC is present", "type": 3}, {"string": "We see DESC has come", "type": 3}, {"string": "Oh, DESC now", "type": 4}, {"string": "Hello", "type": 5}, {"string": "Have you been here long?", "type": 5}, {"string": "Are you here to play with us?", "type": 5}, {"string": "Will we be one on top of the other again?", "type": 5}, {"string": "Will we be separated again?", "type": 5}

				]

			,

			"descriptors" :

				[

				["busy", 0, lambda m: m > 0.5 and m < 1.0], ["crowded", 0, lambda m: m > 0.8 and m < 1.0], ["packed", 0, lambda m: m > 0.8 and m < 1.0], ["teeming", 0, lambda m: m > 0.8 and m < 1.0], ["populated", 0, lambda m: m > 0.5 and m < 1.0], ["not empty", 0, lambda m: m > 0.2 and m < 1.0], ["empty", 0, lambda m: m > 0.0 and m < 0.3], ["idle", 0, lambda m: m > 0.0 and m < 0.2], ["clear of people", 0, lambda m: m > 0.0 and m < 0.2], ["devoid of people", 0, lambda m: m > 0.0 and m < 0.2], ["someone is", 1, lambda m: m > 0.3 and m < 1.0], ["people are", 1, lambda m: m > 0.3 and m < 1.0], ["a person is", 1, lambda m: m > 0.3 and m < 1.0], ["nobody is", 1, lambda m: m > 0.0 and m < 0.3], ["some people are", 0, lambda m: m > 0.3 and m < 1.0], ["few people are", 1, lambda m: m > 0.0 and m < 0.3], ["no one", 2, lambda m: m > 0.0 and m < 0.2], ["someone", 2, lambda m: m > 0.2 and m < 1.0], ["people", 2, lambda m: m > 0.2 and m < 1.0], ["you", 2, lambda m: m > 0.2 and m < 1.0], ["a group of people", 2, lambda m: m > 0.4 and m < 1.0], ["an assembly of people", 2, lambda m: m > 0.4 and m < 1.0], ["someone", 3, lambda m: m > 0.3 and m < 1.0], ["no one", 3, lambda m: m > 0.0 and m < 0.3], ["you are here", 4, lambda m: m > 0.3 and m < 1.0], ["we have company", 4, lambda m: m > 0.3 and m < 1.0], ["you have gone", 4, lambda m: m > 0.0 and m < 0.3], ["nobody is here", 4, lambda m: m > 0.0 and m < 0.3], ["", 5, lambda m: m > 0.0 and m < 1.0]

				]

	},
	"modifiers" :

				[

					["a tiny bit", lambda m: m > 0.0 and m < 0.2], ["a bit", lambda m: m > 0.0 and m < 0.5], ["a little", lambda m: m > 0.0 and m < 0.5], ["quite", lambda m: m > 0.5 and m < 1.0], ["very", lambda m: m > 0.5 and m < 1.0], ["extremely", lambda m: m > 0.8 and m < 1.0], ["somewhat", lambda m: m > 0.3 and m < 0.6], ["fairly", lambda m: m > 0.3 and m < 0.6], ["rather", lambda m: m > 0.5 and m < 0.7]

				]
}

###  FUNCTION ###
def generate(obj, reading, diff, dream=False):
	print 'received %s %s %s %s' % (obg, reading, diff, dream)
	sentence = data[obj]["sentences"][random.randint(0,len(data[obj]["sentences"])-1)]
	type = sentence["type"]
	descriptor = None
	modifier = ""

	while descriptor is None:
		d = data[obj]["descriptors"][random.randint(0,len(data[obj]["descriptors"])-1)]
		if d[1] == type:
			if d[2](reading):
				descriptor = d[0]

	if obj == "APPLE" or obj == "MUG":
		if random.random() > 0.5:
			while modifier is "":
				m = data["modifiers"][random.randint(0,len(data["modifiers"])-1)]
				if m[1](reading):
					modifier = m[0]

	if obj == "MUG":
		drink = None
		while drink is None:
			d = data[obj]["drinks"][random.randint(0,len(data[obj]["drinks"])-1)]
			if d[1](reading):
				drink = d[0]
		output = sentence["string"].replace("DESC", descriptor).replace("MOD", modifier).replace("DRINK", drink).lstrip()

	elif obj == "APPLE":
		output = sentence["string"].replace("DESC", descriptor).replace("MOD", modifier).lstrip()

	elif obj == "BLOCKS":
		if "DESC" in sentence["string"]:
			output = sentence["string"].replace("DESC", descriptor).lstrip()
		else:
			output = sentence["string"].lstrip()

	return output[0].upper() + output[1:]

### EXAMPLE ###
#sentence = generate("BLOCKS", random.random(), random.random())<commit_msg>sentence_generator hangs indefinitely, now debugging<commit_after>import random

### DATA ###

data = {
	"APPLE" : {
			"sentences" :

				[

				{"string": "It is MOD DESC", "type": 0}, {"string": "Oh, it's MOD DESC", "type": 0}, {"string": "Gosh, that's MOD DESC", "type": 0}, {"string": "MOD DESC now", "type": 0}, {"string": "Well, that's MOD DESC", "type": 0}, {"string": "I am MOD DESC", "type": 1}, {"string": "Am I DESC?", "type": 2}, {"string": "Is it DESC?", "type": 3}

				]

			,

			"descriptors" :

				[

				["light", 0, lambda m: m > 0.5 and m < 1.0], ["bright", 0, lambda m: m > 0.6 and m < 1.0], ["beaming", 0, lambda m: m > 0.8 and m < 1.0], ["dark", 0, lambda m: m > 0.0 and m < 0.5], ["murky", 0, lambda m: m > 0.0 and m < 0.5], ["shadowy", 0, lambda m: m > 0.0 and m < 0.5], ["basking", 1, lambda m: m > 0.5 and m < 1.0], ["shaded", 1, lambda m: m > 0.0 and m < 0.5], ["ripening", 1, lambda m: m > 0.5 and m < 1.0], ["ripe", 2, lambda m: m > 0.0 and m < 1.0], ["night", 3, lambda m: m > 0.0 and m < 0.5], ["daytime", 3, lambda m: m > 0.5 and m < 1.0], ["bathed in light", 4, lambda m: m > 0.5 and m < 1.0], ["illuminated", 4, lambda m: m > 0.6 and m < 1.0]

				]

	},
	"MUG" : {
			"sentences" :

				[

				{"string": "It is MOD DESC", "type": 0}, {"string": "It is MOD DESC now, would you like some DRINK?", "type": 0}, {"string": "Oh, it's getting MOD DESC. Might be time for DRINK.", "type": 0}, {"string": "Aren't you MOD DESC now? Some DRINK might be a good idea.", "type": 0}

				]

			,

			"descriptors" :

				[

				["warm", 0, lambda m: m > 0.5 and m < 1.0], ["temperate", 0, lambda m: m > 0.4 and m < 0.6], ["cozy", 0, lambda m: m > 0.5 and m < 0.7], ["hot", 0, lambda m: m > 0.7 and m < 1.0], ["sweltering", 0, lambda m: m > 0.8 and m < 1.0], ["cool", 0, lambda m: m > 0.2 and m < 0.5], ["cold", 0, lambda m: m > 0.0 and m < 0.3], ["chilly", 0, lambda m: m > 0.0 and m < 0.3], ["freezing", 0, lambda m: m > 0.0 and m < 0.3], ["brisk", 0, lambda m: m > 0.2 and m < 0.5], ["lukewarm", 0, lambda m: m > 0.4 and m < 0.6]

				]
			,
			"drinks" :

				[

				["tea", lambda m: m > 0.0 and m < 0.5], ["coffee", lambda m: m > 0.0 and m < 0.5], ["cocoa", lambda m: m > 0.0 and m < 0.5], ["hot toddy", lambda m: m > 0.0 and m < 0.5], ["warm milk", lambda m: m > 0.0 and m < 0.5], ["hot cider", lambda m: m > 0.0 and m < 0.5], ["lemonade", lambda m: m > 0.5 and m < 1.0], ["water", lambda m: m > 0.5 and m < 1.0], ["iced tea", lambda m: m > 0.5 and m < 1.0], ["iced coffee", lambda m: m > 0.5 and m < 1.0], ["soda", lambda m: m > 0.5 and m < 1.0], ["seltzer", lambda m: m > 0.5 and m < 1.0], ["cold drink", lambda m: m > 0.5 and m < 1.0], ["hot or cold beverage", lambda m: m > 0.4 and m < 0.6]

				]

	},
	"BLOCKS" : {
			"sentences" :

				[

				{"string": "It is DESC", "type": 0}, {"string": "DESC here", "type": 1}, {"string": "DESC with us now", "type": 1}, {"string": "DESC present", "type": 1}, {"string": "DESC near", "type": 1}, {"string": "We see DESC", "type": 2}, {"string": "We see DESC has arrived", "type": 3}, {"string": "We see DESC is present", "type": 3}, {"string": "We see DESC has come", "type": 3}, {"string": "Oh, DESC now", "type": 4}, {"string": "Hello", "type": 5}, {"string": "Have you been here long?", "type": 5}, {"string": "Are you here to play with us?", "type": 5}, {"string": "Will we be one on top of the other again?", "type": 5}, {"string": "Will we be separated again?", "type": 5}

				]

			,

			"descriptors" :

				[

				["busy", 0, lambda m: m > 0.5 and m < 1.0], ["crowded", 0, lambda m: m > 0.8 and m < 1.0], ["packed", 0, lambda m: m > 0.8 and m < 1.0], ["teeming", 0, lambda m: m > 0.8 and m < 1.0], ["populated", 0, lambda m: m > 0.5 and m < 1.0], ["not empty", 0, lambda m: m > 0.2 and m < 1.0], ["empty", 0, lambda m: m > 0.0 and m < 0.3], ["idle", 0, lambda m: m > 0.0 and m < 0.2], ["clear of people", 0, lambda m: m > 0.0 and m < 0.2], ["devoid of people", 0, lambda m: m > 0.0 and m < 0.2], ["someone is", 1, lambda m: m > 0.3 and m < 1.0], ["people are", 1, lambda m: m > 0.3 and m < 1.0], ["a person is", 1, lambda m: m > 0.3 and m < 1.0], ["nobody is", 1, lambda m: m > 0.0 and m < 0.3], ["some people are", 0, lambda m: m > 0.3 and m < 1.0], ["few people are", 1, lambda m: m > 0.0 and m < 0.3], ["no one", 2, lambda m: m > 0.0 and m < 0.2], ["someone", 2, lambda m: m > 0.2 and m < 1.0], ["people", 2, lambda m: m > 0.2 and m < 1.0], ["you", 2, lambda m: m > 0.2 and m < 1.0], ["a group of people", 2, lambda m: m > 0.4 and m < 1.0], ["an assembly of people", 2, lambda m: m > 0.4 and m < 1.0], ["someone", 3, lambda m: m > 0.3 and m < 1.0], ["no one", 3, lambda m: m > 0.0 and m < 0.3], ["you are here", 4, lambda m: m > 0.3 and m < 1.0], ["we have company", 4, lambda m: m > 0.3 and m < 1.0], ["you have gone", 4, lambda m: m > 0.0 and m < 0.3], ["nobody is here", 4, lambda m: m > 0.0 and m < 0.3], ["", 5, lambda m: m > 0.0 and m < 1.0]

				]

	},
	"modifiers" :

				[

					["a tiny bit", lambda m: m > 0.0 and m < 0.2], ["a bit", lambda m: m > 0.0 and m < 0.5], ["a little", lambda m: m > 0.0 and m < 0.5], ["quite", lambda m: m > 0.5 and m < 1.0], ["very", lambda m: m > 0.5 and m < 1.0], ["extremely", lambda m: m > 0.8 and m < 1.0], ["somewhat", lambda m: m > 0.3 and m < 0.6], ["fairly", lambda m: m > 0.3 and m < 0.6], ["rather", lambda m: m > 0.5 and m < 0.7]

				]
}

###  FUNCTION ###
def generate(obj, reading, diff, dream=False):
	print 'received %s %s %s %s' % (obj, reading, diff, dream)
	sentence = data[obj]["sentences"][random.randint(0,len(data[obj]["sentences"])-1)]
	type = sentence["type"]
	descriptor = None
	modifier = ""

	while descriptor is None:
		d = data[obj]["descriptors"][random.randint(0,len(data[obj]["descriptors"])-1)]
		if d[1] == type:
			if d[2](reading):
				descriptor = d[0]

	if obj == "APPLE" or obj == "MUG":
		if random.random() > 0.5:
			while modifier is "":
				m = data["modifiers"][random.randint(0,len(data["modifiers"])-1)]
				if m[1](reading):
					modifier = m[0]

	if obj == "MUG":
		drink = None
		while drink is None:
			d = data[obj]["drinks"][random.randint(0,len(data[obj]["drinks"])-1)]
			if d[1](reading):
				drink = d[0]
		output = sentence["string"].replace("DESC", descriptor).replace("MOD", modifier).replace("DRINK", drink).lstrip()

	elif obj == "APPLE":
		output = sentence["string"].replace("DESC", descriptor).replace("MOD", modifier).lstrip()

	elif obj == "BLOCKS":
		if "DESC" in sentence["string"]:
			output = sentence["string"].replace("DESC", descriptor).lstrip()
		else:
			output = sentence["string"].lstrip()

	return output[0].upper() + output[1:]

### EXAMPLE ###
#sentence = generate("BLOCKS", random.random(), random.random())<|endoftext|>


<commit_before>########
# Copyright (c) 2014 GigaSpaces Technologies Ltd. All rights reserved
#
# 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.

__author__ = 'dan'

import shutil

from cosmo_tester.framework.testenv import TestCase
from cosmo_tester.framework.util import get_blueprint_path, YamlPatcher
from cosmo_tester.framework.openstack_api import openstack_clients

class NeutronGaloreTest(TestCase):

    flavor_name = 'm1.small'
    host_name = 'novaservertest'
    image_name = 'Ubuntu-NP'
    security_groups = ['neutron_test_security_group_dst']

    def test_neutron_galore(self):
        self.security_groups.append(self.env.agents_security_group)

        blueprint_path = self.copy_blueprint('neutron-galore')
        self.blueprint_yaml = blueprint_path / 'blueprint.yaml'
        self.modify_blueprint()

        before, after = self.upload_deploy_and_execute_install()

        self.post_install_assertions(before, after)

        self.execute_uninstall()

        self.post_uninstall_assertions()

    def copy_python_webserver_blueprint(self, target):
        shutil.copytree(get_blueprint_path('neutron-galore'), target)

    def modify_blueprint(self):
        with YamlPatcher(self.blueprint_yaml) as patch:
            vm_path = 'blueprint.nodes[0].properties'
            patch.set_value('{0}.management_network_name'.format(vm_path),
                            self.env.management_network_name)
            patch.set_value('{0}.worker_config.key'.format(vm_path),
                            self.env.agent_key_path)
            patch.merge_obj('{0}.server'.format(vm_path), {
                'name': self.host_name,
                'image_name': self.image_name,
                'flavor_name': self.flavor_name,
                'key_name': self.env.agent_keypair_name,
                'security_groups': self.security_groups,
            })

            router_path = 'blueprint.nodes[3].properties.router.'\
                          'external_gateway_info.network_name'
            patch.set_value(router_path, self.env.external_network_name)

            ip_path = 'blueprint.nodes[7].properties.floatingip.'\
                      'floating_network_name'
            patch.set_value(ip_path, self.env.external_network_name)

    def post_install_assertions(self, before_state, after_state):
        delta = self.get_manager_state_delta(before_state, after_state)
        node_states = self.get_node_states(delta['node_state'])
        openstack = self.get_openstack_components(node_states)

        self.assertEqual(openstack['server']['addresses']
                                  ['dank-cloudify-admin-network']
                                  [0]['OS-EXT-IPS:type'], 'fixed')
        self.assertEqual(openstack['server']['addresses']
                         ['dank-cloudify-admin-network']
                         [1]['OS-EXT-IPS:type'], 'fixed')
        floatingip_address = openstack['server']['addresses'][
            'dank-cloudify-admin-network'][0]['addr']
        self.assertEqual(openstack['server']['addresses']
                         ['neutron_network_test']
                         [0]['OS-EXT-IPS:type'], 'fixed')
        self.assertEqual(openstack['server']['addresses']
                         ['neutron_network_test']
                         [0]['version'], 4)
        port_assigned_addr = openstack['server']['addresses'][
            'neutron_network_test'][0]['addr']
        self.assertTrue(port_assigned_addr.startswith('10.10.10.'))
        self.assert_obj_list_contains_subset(
            openstack['server']['security_groups'],
            {'name': 'neutron_test_security_group_dst'})
        self.assert_obj_list_contains_subset(
            openstack['server']['security_groups'],
            {'name': 'dank-cloudify-sg-agents'})
        self.assert_obj_list_contains_subset(
            openstack['server']['security_groups'],
            {'name': 'neutron_test_security_group_src'})
        self.assertEqual(openstack['server']['name'], 'novaservertest')
        self.assertEqual(openstack['port']['name'], 'neutron_test_port')
        port_security_group_id = openstack['port']['security_groups'][0]
        port_fixed_ip = openstack['port']['fixed_ips'][0]['ip_address']
        self.assertEqual(port_fixed_ip, port_assigned_addr)
        port_network_id = openstack['port']['network_id']
        port_subnet_id = openstack['port']['fixed_ips'][0]['subnet_id']
        self.assertEqual(openstack['floatingip']['floating_ip_address'],
                         floatingip_address)
        self.assertEqual(openstack['router']['name'], 'neutron_router_test')
        router_network_id = openstack['router']['external_gateway_info'][
            'network_id']
        self.assertEqual(openstack['sg_src']['name'],
                         'neutron_test_security_group_src')
        sg_src_id = openstack['sg_src']['id']
        self.assertEqual(port_security_group_id, sg_src_id)
        self.assertEqual(openstack['network']['name'], 'neutron_network_test')
        network_subnet_id = openstack['network']['subnets'][0]
        self.assertEqual(router_network_id, openstack['network']['id'])
        self.assertEqual(port_network_id, openstack['network']['id'])
        self.assertEqual(openstack['subnet']['name'], 'neutron_subnet_test')
        self.assertEqual(openstack['subnet']['cidr'], '10.10.10.0/24')
        self.assertEqual(network_subnet_id, openstack['subnet']['id'])
        self.assertEqual(port_subnet_id, openstack['subnet']['id'])
        self.assertEqual(openstack['sg_dst']['name'],
                         'neutron_test_security_group_dst')
        self.assertEqual(4, len(openstack['sg_dst']['security_group_rules']))
        self.assert_obj_list_contains_subset(
            openstack['sg_dst']['security_group_rules'],
            {'remote_ip_prefix': '1.2.3.0/24',
             'port_range_min': 80,
             'port_range_max': 80,
             'direction': 'ingress'})
        self.assert_obj_list_contains_subset(
            openstack['sg_dst']['security_group_rules'],
            {'remote_ip_prefix': '2.3.4.0/24',
             'port_range_min': 65500,
             'port_range_max': 65510,
             'direction': 'ingress'})
        self.assert_obj_list_contains_subset(
            openstack['sg_dst']['security_group_rules'],
            {'remote_group_id': sg_src_id,
             'port_range_min': 65521,
             'port_range_max': 65521,
             'direction': 'ingress'})
        self.assert_obj_list_contains_subset(
            openstack['sg_dst']['security_group_rules'],
            {'remote_ip_prefix': '3.4.5.0/24',
             'port_range_min': 443,
             'port_range_max': 443,
             'direction': 'egress'})
        self.assertEqual(node_states['floatingip']['floating_ip_address'],
                         floatingip_address)
        self.assertEqual(openstack['server']['addresses']
                                  ['dank-cloudify-admin-network'][0]['addr'],
                         node_states['server']['networks']
                         ['dank-cloudify-admin-network'][0])
        self.assertEqual(openstack['server']['addresses']
                         ['neutron_network_test'][0]['addr'],
                         node_states['server']['networks']
                         ['neutron_network_test'][0])
        self.assertEqual(node_states['server']['ip'],
                         openstack['server']['addresses']
                         ['dank-cloudify-admin-network'][0]['addr'])

    def post_uninstall_assertions(self):
        pass

    def get_node_states(self, node_states):
        return {
            'server': self._node_state('nova_server', node_states),
            'network': self._node_state('neutron_network', node_states),
            'subnet': self._node_state('neutron_subnet', node_states),
            'router': self._node_state('neutron_router', node_states),
            'port': self._node_state('neutron_port', node_states),
            'sg_src': self._node_state('security_group_src', node_states),
            'sg_dst': self._node_state('security_group_dst', node_states),
            'floatingip': self._node_state('floatingip', node_states)
        }

    def get_openstack_components(self, states):
        nova, neutron = openstack_clients(self.env.cloudify_config)
        sid = 'openstack_server_id'
        eid = 'external_id'
        sg = 'security_group'
        i = 'floatingip'
        return {
            'server': nova.servers.get(states['server'][sid]).to_dict(),
            'network': neutron.show_network(states['network'][eid])['network'],
            'subnet': neutron.show_subnet(states['subnet'][eid])['subnet'],
            'router': neutron.show_router(states['router'][eid])['router'],
            'port': neutron.show_port(states['port'][eid])['port'],
            'sg_src': neutron.show_security_group(states['sg_src'][eid])[sg],
            'sg_dst': neutron.show_security_group(states['sg_dst'][eid])[sg],
            'floatingip': neutron.show_floatingip(states['floatingip'][eid])[i]
        }

    def _node_state(self, starts_with, node_states):
        node_states = node_states.values()[0].values()
        state = [state for state in node_states
                 if state['id'].startswith(starts_with)][0]
        self.assertEqual(state['state'], 'started')
        return state['runtimeInfo']

    def assert_obj_list_contains_subset(self, obj_list, subset):
        for obj in obj_list:
            if set(subset.keys()) <= set(obj.keys()) and \
               all([obj[key] == value for key, value in subset.items()]):
                    return
        self.fail('Could not find {0} in {1}'.format(subset, obj_list))
<commit_msg>CFY-3 code cleanup<commit_after>########
# Copyright (c) 2014 GigaSpaces Technologies Ltd. All rights reserved
#
# 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.

__author__ = 'dan'

from cosmo_tester.framework.testenv import TestCase
from cosmo_tester.framework.util import YamlPatcher
from cosmo_tester.framework.openstack_api import openstack_clients

class NeutronGaloreTest(TestCase):

    flavor_name = 'm1.small'
    host_name = 'novaservertest'
    image_name = 'Ubuntu-NP'
    security_groups = ['neutron_test_security_group_dst']

    def test_neutron_galore(self):
        self.security_groups.append(self.env.agents_security_group)

        blueprint_path = self.copy_blueprint('neutron-galore')
        self.blueprint_yaml = blueprint_path / 'blueprint.yaml'
        self.modify_blueprint()

        before, after = self.upload_deploy_and_execute_install()

        self.post_install_assertions(before, after)

        self.execute_uninstall()

        self.post_uninstall_assertions()

    def modify_blueprint(self):
        with YamlPatcher(self.blueprint_yaml) as patch:
            vm_path = 'blueprint.nodes[0].properties'
            patch.set_value('{0}.management_network_name'.format(vm_path),
                            self.env.management_network_name)
            patch.set_value('{0}.worker_config.key'.format(vm_path),
                            self.env.agent_key_path)
            patch.merge_obj('{0}.server'.format(vm_path), {
                'name': self.host_name,
                'image_name': self.image_name,
                'flavor_name': self.flavor_name,
                'key_name': self.env.agent_keypair_name,
                'security_groups': self.security_groups,
            })

            router_path = 'blueprint.nodes[3].properties.router.'\
                          'external_gateway_info.network_name'
            patch.set_value(router_path, self.env.external_network_name)

            ip_path = 'blueprint.nodes[7].properties.floatingip.'\
                      'floating_network_name'
            patch.set_value(ip_path, self.env.external_network_name)

    def post_install_assertions(self, before_state, after_state):
        delta = self.get_manager_state_delta(before_state, after_state)
        node_states = self.get_node_states(delta['node_state'])
        openstack = self.get_openstack_components(node_states)

        self.assertEqual(openstack['server']['addresses']
                                  ['dank-cloudify-admin-network']
                                  [0]['OS-EXT-IPS:type'], 'fixed')
        self.assertEqual(openstack['server']['addresses']
                         ['dank-cloudify-admin-network']
                         [1]['OS-EXT-IPS:type'], 'fixed')
        floatingip_address = openstack['server']['addresses'][
            'dank-cloudify-admin-network'][0]['addr']
        self.assertEqual(openstack['server']['addresses']
                         ['neutron_network_test']
                         [0]['OS-EXT-IPS:type'], 'fixed')
        self.assertEqual(openstack['server']['addresses']
                         ['neutron_network_test']
                         [0]['version'], 4)
        port_assigned_addr = openstack['server']['addresses'][
            'neutron_network_test'][0]['addr']
        self.assertTrue(port_assigned_addr.startswith('10.10.10.'))
        self.assert_obj_list_contains_subset(
            openstack['server']['security_groups'],
            {'name': 'neutron_test_security_group_dst'})
        self.assert_obj_list_contains_subset(
            openstack['server']['security_groups'],
            {'name': 'dank-cloudify-sg-agents'})
        self.assert_obj_list_contains_subset(
            openstack['server']['security_groups'],
            {'name': 'neutron_test_security_group_src'})
        self.assertEqual(openstack['server']['name'], 'novaservertest')
        self.assertEqual(openstack['port']['name'], 'neutron_test_port')
        port_security_group_id = openstack['port']['security_groups'][0]
        port_fixed_ip = openstack['port']['fixed_ips'][0]['ip_address']
        self.assertEqual(port_fixed_ip, port_assigned_addr)
        port_network_id = openstack['port']['network_id']
        port_subnet_id = openstack['port']['fixed_ips'][0]['subnet_id']
        self.assertEqual(openstack['floatingip']['floating_ip_address'],
                         floatingip_address)
        self.assertEqual(openstack['router']['name'], 'neutron_router_test')
        router_network_id = openstack['router']['external_gateway_info'][
            'network_id']
        self.assertEqual(openstack['sg_src']['name'],
                         'neutron_test_security_group_src')
        sg_src_id = openstack['sg_src']['id']
        self.assertEqual(port_security_group_id, sg_src_id)
        self.assertEqual(openstack['network']['name'], 'neutron_network_test')
        network_subnet_id = openstack['network']['subnets'][0]
        self.assertEqual(router_network_id, openstack['network']['id'])
        self.assertEqual(port_network_id, openstack['network']['id'])
        self.assertEqual(openstack['subnet']['name'], 'neutron_subnet_test')
        self.assertEqual(openstack['subnet']['cidr'], '10.10.10.0/24')
        self.assertEqual(network_subnet_id, openstack['subnet']['id'])
        self.assertEqual(port_subnet_id, openstack['subnet']['id'])
        self.assertEqual(openstack['sg_dst']['name'],
                         'neutron_test_security_group_dst')
        self.assertEqual(4, len(openstack['sg_dst']['security_group_rules']))
        self.assert_obj_list_contains_subset(
            openstack['sg_dst']['security_group_rules'],
            {'remote_ip_prefix': '1.2.3.0/24',
             'port_range_min': 80,
             'port_range_max': 80,
             'direction': 'ingress'})
        self.assert_obj_list_contains_subset(
            openstack['sg_dst']['security_group_rules'],
            {'remote_ip_prefix': '2.3.4.0/24',
             'port_range_min': 65500,
             'port_range_max': 65510,
             'direction': 'ingress'})
        self.assert_obj_list_contains_subset(
            openstack['sg_dst']['security_group_rules'],
            {'remote_group_id': sg_src_id,
             'port_range_min': 65521,
             'port_range_max': 65521,
             'direction': 'ingress'})
        self.assert_obj_list_contains_subset(
            openstack['sg_dst']['security_group_rules'],
            {'remote_ip_prefix': '3.4.5.0/24',
             'port_range_min': 443,
             'port_range_max': 443,
             'direction': 'egress'})
        self.assertEqual(node_states['floatingip']['floating_ip_address'],
                         floatingip_address)
        self.assertEqual(openstack['server']['addresses']
                                  ['dank-cloudify-admin-network'][0]['addr'],
                         node_states['server']['networks']
                         ['dank-cloudify-admin-network'][0])
        self.assertEqual(openstack['server']['addresses']
                         ['neutron_network_test'][0]['addr'],
                         node_states['server']['networks']
                         ['neutron_network_test'][0])
        self.assertEqual(node_states['server']['ip'],
                         openstack['server']['addresses']
                         ['dank-cloudify-admin-network'][0]['addr'])

    def post_uninstall_assertions(self):
        pass

    def get_node_states(self, node_states):
        return {
            'server': self._node_state('nova_server', node_states),
            'network': self._node_state('neutron_network', node_states),
            'subnet': self._node_state('neutron_subnet', node_states),
            'router': self._node_state('neutron_router', node_states),
            'port': self._node_state('neutron_port', node_states),
            'sg_src': self._node_state('security_group_src', node_states),
            'sg_dst': self._node_state('security_group_dst', node_states),
            'floatingip': self._node_state('floatingip', node_states)
        }

    def get_openstack_components(self, states):
        nova, neutron = openstack_clients(self.env.cloudify_config)
        sid = 'openstack_server_id'
        eid = 'external_id'
        sg = 'security_group'
        i = 'floatingip'  # sorry, must fit short line :\
        return {
            'server': nova.servers.get(states['server'][sid]).to_dict(),
            'network': neutron.show_network(states['network'][eid])['network'],
            'subnet': neutron.show_subnet(states['subnet'][eid])['subnet'],
            'router': neutron.show_router(states['router'][eid])['router'],
            'port': neutron.show_port(states['port'][eid])['port'],
            'sg_src': neutron.show_security_group(states['sg_src'][eid])[sg],
            'sg_dst': neutron.show_security_group(states['sg_dst'][eid])[sg],
            'floatingip': neutron.show_floatingip(states['floatingip'][eid])[i]
        }

    def _node_state(self, starts_with, node_states):
        node_states = node_states.values()[0].values()
        state = [state for state in node_states
                 if state['id'].startswith(starts_with)][0]
        self.assertEqual(state['state'], 'started')
        return state['runtimeInfo']

    def assert_obj_list_contains_subset(self, obj_list, subset):
        for obj in obj_list:
            if all([obj.get(key) == value for key, value in subset.items()]):
                    return
        self.fail('Could not find {0} in {1}'.format(subset, obj_list))
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals, division

import collections
import logging
import os

from pignacio_scripts.terminal.color import (bright_blue, bright_cyan,
                                             bright_green, bright_magenta,
                                             bright_red, red)

from ..constants import DATA_DIR
from ..conversions import CantConvert
from ..ingredient import IngredientMap
from ..objects import NutritionalValue, LogData
from ..parse import parse_log_data, ParseError
from ..serialization import load_ingredients
from ..utils import base_argument_parser, get_terminal_size

logger = logging.getLogger(__name__)  # pylint: disable=invalid-name

_DEFAULT_FORMAT = (
    '%(calories)s kCal (%(carbs)4s c, %(protein)4s p, %(fat)4s f) '
    '[%(fiber)4s df]')

_DEFAULT_COLORS = [bright_green, bright_blue, bright_magenta, bright_cyan, red]

def main(options):
    ingredients = IngredientMap(load_ingredients(os.path.join(DATA_DIR,
                                                              'ingredients')))

    log = process_log(options.file, ingredients)
    if log is None:
        print "The log was empty :("
        return
    width = get_terminal_size()[0]
    if options.by_ingredient:
        log = group_by_ingredient(log, ingredients)
    print_log(log, max_levels=options.depth, width=width)

def get_argument_parser():
    parser = base_argument_parser()
    parser.add_argument('file', help='file/directory to process')
    parser.add_argument('-d', '--depth',
                        default=None,
                        type=int,
                        help="Max depth to show.")
    parser.add_argument(
        '--by-ingredient',
        action='store_true',
        default=False,
        help="Report the nutritional value grouped by ingredient.")
    return parser

def _log_values(nut_value):
    return {
        f: "???" if v is None else "{:.1f}".format(v)
        for f, v in nut_value._asdict().items()
    }

# pylint: disable=too-many-arguments,redefined-builtin
def print_log(log,
              format=_DEFAULT_FORMAT,
              level=0,
              width=100,
              colors=None,
              max_levels=None):
    colors = colors or _DEFAULT_COLORS
    right_part = format % _log_values(log.nutritional_value)
    left_part = '{}{}:'.format(' ' * level, log.name)
    right_size = max(0, width - len(left_part) - 2)
    format_str = '{}{:>' + str(right_size) + '}'

    try:
        color = colors[level]
    except IndexError:
        color = lambda s: s

    incomplete_marker = bright_red("!") if log.incomplete else " "
    unknown_marker = bright_red("*") if "???" in right_part else " "

    print(color(format_str.format(left_part, right_part)) + unknown_marker +
          incomplete_marker)

    if log.parts and (max_levels is None or level < max_levels):
        for part in log.parts:
            print_log(part, format, level + 1,
                      colors=colors,
                      max_levels=max_levels,
                      width=width)
        print

def process_log(path, ingredients):
    path = path.rstrip("/")
    if os.path.isfile(path):
        parts = get_log_file_parts(path, ingredients)
    else:
        log_parts = sorted(os.listdir(path))

        if '__init__' in log_parts:
            log_parts.remove('__init__')
            init = process_log(os.path.join(path, '__init__'), ingredients)
            init_parts = init.parts if init else []
        else:
            init_parts = []

        parts = [process_log(os.path.join(path, p), ingredients)
                 for p in log_parts]
        parts.extend(init_parts)

    parts = [p for p in parts if p]

    if not parts:
        return None
    return LogData.from_parts(os.path.basename(path), parts)

def get_log_file_parts(path, ingredients):
    with open(path) as fin:
        lines = (l for l in fin if l.strip() and not l.strip().startswith('#'))

        return [make_log_data(l, ingredients, path, ln)
                for ln, l in enumerate(lines)]

def make_log_data(line, ingredients, path, line_num):
    try:
        return parse_log_data(line, ingredients)
    except ParseError as err:
        logging.warning("%s (%s:%s)", err, path, line_num)
        return LogData(name=line.strip(),
                       nutritional_value=NutritionalValue.UNKNOWN,
                       incomplete=True)

def extract_leaf_log_datas(log):
    lines = []
    if not log.parts:
        lines.append(log)
    for part in log.parts:
        lines.extend(extract_leaf_log_datas(part))
    return lines

def group_by_ingredient(log, ingredients):
    leafs = extract_leaf_log_datas(log)

    grouped = collections.defaultdict(lambda: collections.defaultdict(int))
    no_ingredient = []

    for log_data in leafs:
        log_line = log_data.log_line
        if log_line and log_line.ingredient:
            grouped[log_line.ingredient.name][log_line.unit] += log_line.amount
        else:
            no_ingredient.append(log_data)

    log_datas = []

    for ingredient_name, amounts in grouped.items():
        ingredient = ingredients[ingredient_name]
        parts = []
        for unit, amount in amounts.items():
            try:
                nut_value = ingredient.get_nutritional_value(amount, unit)
            except CantConvert as err:
                logger.warning(str(err))
                nut_value = NutritionalValue.UNKNOWN
            parts.append(LogData(
                name="{} ({} {})".format(ingredient.name, amount, unit),
                nutritional_value=nut_value))
        parts.sort(key=lambda x: x.nutritional_value.calories, reverse=True)

        if len(parts) == 1:
            log_datas.append(parts[0]._replace(ingredient=ingredient))
        else:
            name = "{} ({})".format(ingredient.name,
                                    " + ".join("{:.2f} {}".format(v, k)
                                               for k, v in amounts.items()))
            log_datas.append(LogData.from_parts(name, parts,
                                                ingredient=ingredient))

    log_datas.extend(no_ingredient)

    log_datas.sort(key=lambda x: x.nutritional_value.calories, reverse=True)

    return LogData.from_parts('By ingredient', log_datas)
<commit_msg>report: add --by-category option<commit_after># -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals, division

import collections
import logging
import os

from pignacio_scripts.terminal.color import (bright_blue, bright_cyan,
                                             bright_green, bright_magenta,
                                             bright_red, red)

from ..constants import DATA_DIR
from ..conversions import CantConvert
from ..ingredient import IngredientMap
from ..objects import NutritionalValue, LogData
from ..parse import parse_log_data, ParseError
from ..serialization import load_ingredients
from ..utils import base_argument_parser, get_terminal_size

logger = logging.getLogger(__name__)  # pylint: disable=invalid-name

_DEFAULT_FORMAT = (
    '%(calories)s kCal (%(carbs)4s c, %(protein)4s p, %(fat)4s f) '
    '[%(fiber)4s df]')

_DEFAULT_COLORS = [bright_green, bright_blue, bright_magenta, bright_cyan, red]

def main(options):
    ingredients = IngredientMap(load_ingredients(os.path.join(DATA_DIR,
                                                              'ingredients')))

    log = process_log(options.file, ingredients)
    if log is None:
        print "The log was empty :("
        return
    width = get_terminal_size()[0]
    if options.by_ingredient:
        log = group_by_ingredient(log, ingredients)
    elif options.by_category:
        log = group_by_category(log, ingredients)
    print_log(log, max_levels=options.depth, width=width)

def get_argument_parser():
    parser = base_argument_parser()
    parser.add_argument('file', help='file/directory to process')
    parser.add_argument('-d', '--depth',
                        default=None,
                        type=int,
                        help="Max depth to show.")
    parser.add_argument(
        '--by-ingredient',
        action='store_true',
        default=False,
        help="Report the nutritional value grouped by ingredient.")
    parser.add_argument(
        '--by-category',
        action='store_true',
        default=False,
        help="Report the nutritional value grouped by category.")
    return parser

def _log_values(nut_value):
    return {
        f: "???" if v is None else "{:.1f}".format(v)
        for f, v in nut_value._asdict().items()
    }

# pylint: disable=too-many-arguments,redefined-builtin
def print_log(log,
              format=_DEFAULT_FORMAT,
              level=0,
              width=100,
              colors=None,
              max_levels=None):
    colors = colors or _DEFAULT_COLORS
    right_part = format % _log_values(log.nutritional_value)
    left_part = '{}{}:'.format(' ' * level, log.name)
    right_size = max(0, width - len(left_part) - 2)
    format_str = '{}{:>' + str(right_size) + '}'

    try:
        color = colors[level]
    except IndexError:
        color = lambda s: s

    incomplete_marker = bright_red("!") if log.incomplete else " "
    unknown_marker = bright_red("*") if "???" in right_part else " "

    print(color(format_str.format(left_part, right_part)) + unknown_marker +
          incomplete_marker)

    if log.parts and (max_levels is None or level < max_levels):
        for part in log.parts:
            print_log(part, format, level + 1,
                      colors=colors,
                      max_levels=max_levels,
                      width=width)
        print

def process_log(path, ingredients):
    path = path.rstrip("/")
    if os.path.isfile(path):
        parts = get_log_file_parts(path, ingredients)
    else:
        log_parts = sorted(os.listdir(path))

        if '__init__' in log_parts:
            log_parts.remove('__init__')
            init = process_log(os.path.join(path, '__init__'), ingredients)
            init_parts = init.parts if init else []
        else:
            init_parts = []

        parts = [process_log(os.path.join(path, p), ingredients)
                 for p in log_parts]
        parts.extend(init_parts)

    parts = [p for p in parts if p]

    if not parts:
        return None
    return LogData.from_parts(os.path.basename(path), parts)

def get_log_file_parts(path, ingredients):
    with open(path) as fin:
        lines = (l for l in fin if l.strip() and not l.strip().startswith('#'))

        return [make_log_data(l, ingredients, path, ln)
                for ln, l in enumerate(lines)]

def make_log_data(line, ingredients, path, line_num):
    try:
        return parse_log_data(line, ingredients)
    except ParseError as err:
        logging.warning("%s (%s:%s)", err, path, line_num)
        return LogData(name=line.strip(),
                       nutritional_value=NutritionalValue.UNKNOWN,
                       incomplete=True)

def extract_leaf_log_datas(log):
    lines = []
    if not log.parts:
        lines.append(log)
    for part in log.parts:
        lines.extend(extract_leaf_log_datas(part))
    return lines

def group_by_ingredient(log, ingredients):
    leafs = extract_leaf_log_datas(log)

    grouped = collections.defaultdict(lambda: collections.defaultdict(int))
    no_ingredient = []

    for log_data in leafs:
        log_line = log_data.log_line
        if log_line and log_line.ingredient:
            grouped[log_line.ingredient.name][log_line.unit] += log_line.amount
        else:
            no_ingredient.append(log_data)

    log_datas = []

    for ingredient_name, amounts in grouped.items():
        ingredient = ingredients[ingredient_name]
        parts = []
        for unit, amount in amounts.items():
            try:
                nut_value = ingredient.get_nutritional_value(amount, unit)
            except CantConvert as err:
                logger.warning(str(err))
                nut_value = NutritionalValue.UNKNOWN
            parts.append(LogData(
                name="{} ({} {})".format(ingredient.name, amount, unit),
                nutritional_value=nut_value))
        parts.sort(key=lambda x: x.nutritional_value.calories, reverse=True)

        if len(parts) == 1:
            log_datas.append(parts[0]._replace(ingredient=ingredient))
        else:
            name = "{} ({})".format(ingredient.name,
                                    " + ".join("{:.2f} {}".format(v, k)
                                               for k, v in amounts.items()))
            log_datas.append(LogData.from_parts(name, parts,
                                                ingredient=ingredient))

    log_datas.extend(no_ingredient)

    log_datas.sort(key=lambda x: x.nutritional_value.calories, reverse=True)

    return LogData.from_parts('By ingredient', log_datas)

def group_by_category(log, ingredients):
    by_ingredient = group_by_ingredient(log, ingredients)
    by_category = collections.defaultdict(list)

    for part in by_ingredient.parts:
        try:
            category = part.ingredient.categories[0]
        except (IndexError, AttributeError):
            category = 'unknown'

        by_category[category.strip().lower()].append(part)

    categories = [LogData.from_parts(category.capitalize(), parts)
                  for category, parts in by_category.items()]

    categories.sort(key=lambda d: d.nutritional_value.calories, reverse=True)

    return LogData.from_parts('By categories', categories)
<|endoftext|>