<commit_before># -*- coding: utf-8 -*-
#
# Copyright (C) 2015-2016 Hewlett Packard Enterprise Development LP
#
# 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.

"""
Debug platform engine module for topology.
"""

from __future__ import unicode_literals, absolute_import
from __future__ import print_function, division

import logging

from .base import BasePlatform, CommonNode

log = logging.getLogger(__name__)

class DebugPlatform(BasePlatform):
    """
    Plugin to build a topology for debugging.

    See :class:`topology.platforms.base.BasePlatform` for more information.
    """

    def __init__(self, timestamp, nmlmanager):
        super(DebugPlatform, self).__init__(timestamp, nmlmanager)

    def pre_build(self):
        """
        See :meth:`BasePlatform.pre_build` for more information.
        """
        log.debug('[HOOK] pre_build')

    def add_node(self, node):
        """
        See :meth:`BasePlatform.add_node` for more information.
        """
        log.debug('[HOOK] add_node({})'.format(
            node
        ))
        return DebugNode(node.identifier, name=node.name, **node.metadata)

    def add_biport(self, node, biport):
        """
        See :meth:`BasePlatform.add_biport` for more information.
        """
        log.debug('[HOOK] add_biport({}, {})'.format(
            node, biport
        ))
        return biport.metadata.get('label', biport.identifier)

    def add_bilink(self, nodeport_a, nodeport_b, bilink):
        """
        See :meth:`BasePlatform.add_bilink` for more information.
        """
        log.debug('[HOOK] add_bilink({}, {}, {})'.format(
            nodeport_a, nodeport_b, bilink
        ))

    def post_build(self):
        """
        See :meth:`BasePlatform.post_build` for more information.
        """
        log.debug('[HOOK] post_build()')

    def destroy(self):
        """
        See :meth:`BasePlatform.destroy` for more information.
        """
        log.debug('[HOOK] destroy()')

    def rollback(self, stage, enodes, exception):
        """
        See :meth:`BasePlatform.rollback` for more information.
        """
        log.debug('[HOOK] rollback({}, {}, {})'.format(
            stage, enodes, exception
        ))

    def relink(self, link_id):
        """
        See :meth:`BasePlatform.relink` for more information.
        """
        log.debug('[CALL] relink({})'.format(
            link_id
        ))

    def unlink(self, link_id):
        """
        See :meth:`BasePlatform.unlink` for more information.
        """
        log.debug('[CALL] unlink({})'.format(
            link_id
        ))

class DebugNode(CommonNode):
    """
    Engine Node for debugging.
    """

    def __init__(self, identifier, **kwargs):
        super(DebugNode, self).__init__(identifier, **kwargs)

    def send_command(self, cmd, shell=None, silent=False):
        """
        Implementation of the ``send_command`` interface.

        This test node will just echo the command.

        See :meth:`topology.platforms.base.CommonNode.send_command` for more
        information.
        """
        log.debug('{}.send_command({}, shell={})'.format(
            str(self), cmd, shell
        ))
        return cmd

    def available_shells(self):
        """
        Implementation of the ``available_shells`` interface.

        This test node has no shells available.

        See :meth:`topology.platforms.base.CommonNode.available_shells` for
        more information.
        """
        log.debug('{}.available_shells()'.format(str(self)))
        return []

    def __str__(self):
        return 'DebugNode(identifier={}, metadata={})'.format(
            self.identifier, self.metadata
        )

__all__ = ['DebugPlatform', 'DebugNode']
<commit_msg>fix: dev: Logging the command in the debug platform in the same way as in CommonNode.<commit_after># -*- coding: utf-8 -*-
#
# Copyright (C) 2015-2016 Hewlett Packard Enterprise Development LP
#
# 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.

"""
Debug platform engine module for topology.
"""

from __future__ import unicode_literals, absolute_import
from __future__ import print_function, division

import logging
from datetime import datetime

from .base import BasePlatform, CommonNode

log = logging.getLogger(__name__)

class DebugPlatform(BasePlatform):
    """
    Plugin to build a topology for debugging.

    See :class:`topology.platforms.base.BasePlatform` for more information.
    """

    def __init__(self, timestamp, nmlmanager):
        super(DebugPlatform, self).__init__(timestamp, nmlmanager)

    def pre_build(self):
        """
        See :meth:`BasePlatform.pre_build` for more information.
        """
        log.debug('[HOOK] pre_build')

    def add_node(self, node):
        """
        See :meth:`BasePlatform.add_node` for more information.
        """
        log.debug('[HOOK] add_node({})'.format(
            node
        ))
        return DebugNode(node.identifier, name=node.name, **node.metadata)

    def add_biport(self, node, biport):
        """
        See :meth:`BasePlatform.add_biport` for more information.
        """
        log.debug('[HOOK] add_biport({}, {})'.format(
            node, biport
        ))
        return biport.metadata.get('label', biport.identifier)

    def add_bilink(self, nodeport_a, nodeport_b, bilink):
        """
        See :meth:`BasePlatform.add_bilink` for more information.
        """
        log.debug('[HOOK] add_bilink({}, {}, {})'.format(
            nodeport_a, nodeport_b, bilink
        ))

    def post_build(self):
        """
        See :meth:`BasePlatform.post_build` for more information.
        """
        log.debug('[HOOK] post_build()')

    def destroy(self):
        """
        See :meth:`BasePlatform.destroy` for more information.
        """
        log.debug('[HOOK] destroy()')

    def rollback(self, stage, enodes, exception):
        """
        See :meth:`BasePlatform.rollback` for more information.
        """
        log.debug('[HOOK] rollback({}, {}, {})'.format(
            stage, enodes, exception
        ))

    def relink(self, link_id):
        """
        See :meth:`BasePlatform.relink` for more information.
        """
        log.debug('[CALL] relink({})'.format(
            link_id
        ))

    def unlink(self, link_id):
        """
        See :meth:`BasePlatform.unlink` for more information.
        """
        log.debug('[CALL] unlink({})'.format(
            link_id
        ))

class DebugNode(CommonNode):
    """
    Engine Node for debugging.
    """

    def __init__(self, identifier, **kwargs):
        super(DebugNode, self).__init__(identifier, **kwargs)

    def send_command(self, cmd, shell=None, silent=False):
        """
        Implementation of the ``send_command`` interface.

        This test node will just echo the command.

        See :meth:`topology.platforms.base.CommonNode.send_command` for more
        information.
        """
        log.debug('{} [{}].send_command(\'{}\', shell=\'{}\') ::'.format(
            datetime.now().isoformat(), str(self), cmd, shell
        ))
        return cmd

    def available_shells(self):
        """
        Implementation of the ``available_shells`` interface.

        This test node has no shells available.

        See :meth:`topology.platforms.base.CommonNode.available_shells` for
        more information.
        """
        log.debug('{}.available_shells()'.format(str(self)))
        return []

    def __str__(self):
        return 'DebugNode(identifier={}, metadata={})'.format(
            self.identifier, self.metadata
        )

__all__ = ['DebugPlatform', 'DebugNode']
<|endoftext|>


<commit_before># Copyright 2014, Ansible, Inc.
# Luke Sneeringer <lsneeringer@ansible.com>
#
# 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.

from tower_cli import models
from tower_cli.utils import types

class Resource(models.Resource):
    cli_help = 'Manage hosts belonging to a group within an inventory.'
    endpoint = '/hosts/'

    name = models.Field(unique=True)
    description = models.Field(required=False, display=False)
    inventory = models.Field(type=types.Related('inventory'))
    enabled = models.Field(type=bool)
    variables = models.Field(type=types.File('r'), required=False,
                             display=False)
<commit_msg>Hosts are now enabled by default.<commit_after># Copyright 2014, Ansible, Inc.
# Luke Sneeringer <lsneeringer@ansible.com>
#
# 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.

from tower_cli import models
from tower_cli.utils import types

class Resource(models.Resource):
    cli_help = 'Manage hosts belonging to a group within an inventory.'
    endpoint = '/hosts/'

    name = models.Field(unique=True)
    description = models.Field(required=False, display=False)
    inventory = models.Field(type=types.Related('inventory'))
    enabled = models.Field(type=bool, required=False)
    variables = models.Field(type=types.File('r'), required=False,
                             display=False)
<|endoftext|>


<commit_before>#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Authors:
# Caner Candan <caner@candan.fr>, http://caner.candan.fr
#

__all__ = ['api']

__author__      = 'Caner Candan'
__version__     = '0.11.0'
__nonsense__    = 'uCoin'

PROTOCOL_VERSION = "1"

import aiohttp, asyncio, logging, json

logger = logging.getLogger("ucoin")

class ConnectionHandler(object):
    """Helper class used by other API classes to ease passing server connection information."""

    def __init__(self, server, port):
        """
        Arguments:
        - `server`: server hostname
        - `port`: port number
        """

        self.server = server
        self.port = port
        self.connector = None

    def __str__(self):
        return 'connection info: %s:%d' % (self.server, self.port)

class API(object):
    """APIRequest is a class used as an interface. The intermediate derivated classes are the modules and the leaf classes are the API requests."""

    aiohttp_connector = None

    def __init__(self, connection_handler, module):
        """
        Asks a module in order to create the url used then by derivated classes.

        Arguments:
        - `module`: module name
        - `connection_handler`: connection handler
        """

        self.module = module
        self.connection_handler = connection_handler
        self.headers = {}

    def reverse_url(self, path):
        """
        Reverses the url using self.url and path given in parameter.

        Arguments:
        - `path`: the request path
        """

        server, port = self.connection_handler.server, self.connection_handler.port

        url = 'http://%s:%d/%s' % (server, port, self.module)
        return url + path

    def get(self, **kwargs):
        """wrapper of overloaded __get__ method."""

        return self.__get__(**kwargs)

    def post(self, **kwargs):
        """wrapper of overloaded __post__ method."""

        logger.debug('do some work with')

        data = self.__post__(**kwargs)

        logger.debug('and send back')

        return data

    def __get__(self, **kwargs):
        """interface purpose for GET request"""
        pass

    def __post__(self, **kwargs):
        """interface purpose for POST request"""
        pass

    @asyncio.coroutine
    def requests_get(self, path, **kwargs):
        """
        Requests GET wrapper in order to use API parameters.

        Arguments:
        - `path`: the request path
        """
        logging.debug("Request : {0}".format(self.reverse_url(path)))
        response = yield from asyncio.wait_for(aiohttp.get(self.reverse_url(path), params=kwargs,
                                headers=self.headers, connector=API.aiohttp_connector), timeout=15)

        if response.status != 200:
            raise ValueError('status code != 200 => %d (%s)' % (response.status, (yield from response.text())))

        return response

    def requests_post(self, path, **kwargs):
        """
        Requests POST wrapper in order to use API parameters.

        Arguments:
        - `path`: the request path
        """
        if 'self_' in kwargs:
            kwargs['self'] = kwargs.pop('self_')

        logging.debug("POST : {0}".format(kwargs))
        response = yield from asyncio.wait_for(
            aiohttp.post(self.reverse_url(path), data=kwargs, headers=self.headers,
                         connector=API.aiohttp_connector),
                                 timeout=15)
        return response

from . import network, blockchain, tx, wot, node, ud
<commit_msg>Longer timeout<commit_after>#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Authors:
# Caner Candan <caner@candan.fr>, http://caner.candan.fr
#

__all__ = ['api']

__author__      = 'Caner Candan'
__version__     = '0.11.0'
__nonsense__    = 'uCoin'

PROTOCOL_VERSION = "1"

import aiohttp, asyncio, logging, json

logger = logging.getLogger("ucoin")

class ConnectionHandler(object):
    """Helper class used by other API classes to ease passing server connection information."""

    def __init__(self, server, port):
        """
        Arguments:
        - `server`: server hostname
        - `port`: port number
        """

        self.server = server
        self.port = port
        self.connector = None

    def __str__(self):
        return 'connection info: %s:%d' % (self.server, self.port)

class API(object):
    """APIRequest is a class used as an interface. The intermediate derivated classes are the modules and the leaf classes are the API requests."""

    aiohttp_connector = None

    def __init__(self, connection_handler, module):
        """
        Asks a module in order to create the url used then by derivated classes.

        Arguments:
        - `module`: module name
        - `connection_handler`: connection handler
        """

        self.module = module
        self.connection_handler = connection_handler
        self.headers = {}

    def reverse_url(self, path):
        """
        Reverses the url using self.url and path given in parameter.

        Arguments:
        - `path`: the request path
        """

        server, port = self.connection_handler.server, self.connection_handler.port

        url = 'http://%s:%d/%s' % (server, port, self.module)
        return url + path

    def get(self, **kwargs):
        """wrapper of overloaded __get__ method."""

        return self.__get__(**kwargs)

    def post(self, **kwargs):
        """wrapper of overloaded __post__ method."""

        logger.debug('do some work with')

        data = self.__post__(**kwargs)

        logger.debug('and send back')

        return data

    def __get__(self, **kwargs):
        """interface purpose for GET request"""
        pass

    def __post__(self, **kwargs):
        """interface purpose for POST request"""
        pass

    @asyncio.coroutine
    def requests_get(self, path, **kwargs):
        """
        Requests GET wrapper in order to use API parameters.

        Arguments:
        - `path`: the request path
        """

        logging.debug("Request : {0}".format(self.reverse_url(path)))
        response = yield from asyncio.wait_for(aiohttp.get(self.reverse_url(path), params=kwargs,
                                headers=self.headers, connector=API.aiohttp_connector), timeout=30)

        if response.status != 200:
            raise ValueError('status code != 200 => %d (%s)' % (response.status, (yield from response.text())))

        return response

    def requests_post(self, path, **kwargs):
        """
        Requests POST wrapper in order to use API parameters.

        Arguments:
        - `path`: the request path
        """
        if 'self_' in kwargs:
            kwargs['self'] = kwargs.pop('self_')

        logging.debug("POST : {0}".format(kwargs))
        response = yield from asyncio.wait_for(
            aiohttp.post(self.reverse_url(path), data=kwargs, headers=self.headers,
                         connector=API.aiohttp_connector),
                                 timeout=30)
        return response

from . import network, blockchain, tx, wot, node, ud
<|endoftext|>


<commit_before># Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# libcloud.org licenses this file to You 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.
# Copyright 2009 RedRata Ltd
"""
RimuHosting Driver
"""
from libcloud.types import Provider, NodeState, InvalidCredsException
from libcloud.base import ConnectionKey, Response, NodeAuthPassword,
from libcloud.base import NodeDriver, NodeSize, Node, NodeLocation
from libcloud.base import NodeImage

# JSON is included in the standard library starting with Python 2.6.  For 2.5
# and 2.4, there's a simplejson egg at: http://pypi.python.org/pypi/simplejson
try: import json
except: import simplejson as json

# Defaults
API_CONTEXT = '/r'
API_HOST = 'api.rimuhosting.com'
API_PORT = (80,443)
API_SECURE = True

class RimuHostingException(Exception):
    def __str__(self):
        return self.args[0]

    def __repr__(self):
        return "<RimuHostingException '%s'>" % (self.args[0])

class RimuHostingResponse(Response):
    def __init__(self, response):
        self.body = response.read()
        self.status = response.status
        self.headers = dict(response.getheaders())
        self.error = response.reason

        if self.success():
          self.object = self.parse_body()

    def success(self):
        if self.status == 403:
          raise InvalidCredsException()
        return True
    def parse_body(self):
        try:
            js = json.loads(self.body)
            if js[js.keys()[0]]['response_type'] == "ERROR":
                raise RimuHostingException(
                    js[js.keys()[0]]['human_readable_message']
                )
            return js[js.keys()[0]]
        except ValueError:
            raise RimuHostingException('Could not parse body: %s'
                                       % (self.body))
        except KeyError:
            raise RimuHostingException('Could not parse body: %s'
                                       % (self.body))

class RimuHostingConnection(ConnectionKey):

    api_context = API_CONTEXT
    host = API_HOST
    port = API_PORT
    responseCls = RimuHostingResponse

    def __init__(self, key, secure=True):
        # override __init__ so that we can set secure of False for testing
        ConnectionKey.__init__(self,key,secure)

    def add_default_headers(self, headers):
        # We want JSON back from the server. Could be application/xml
        # (but JSON is better).
        headers['Accept'] = 'application/json'
        # Must encode all data as json, or override this header.
        headers['Content-Type'] = 'application/json'

        headers['Authorization'] = 'rimuhosting apikey=%s' % (self.key)
        return headers;

    def request(self, action, params={}, data='', headers={}, method='GET'):
        # Override this method to prepend the api_context
        return ConnectionKey.request(self, self.api_context + action,
                                     params, data, headers, method)

class RimuHostingNodeDriver(NodeDriver):
    type = Provider.RIMUHOSTING
    name = 'RimuHosting'
    connectionCls = RimuHostingConnection

    def __init__(self, key, host=API_HOST, port=API_PORT,
                 api_context=API_CONTEXT, secure=API_SECURE):
        # Pass in some extra vars so that
        self.key = key
        self.secure = secure
        self.connection = self.connectionCls(key ,secure)
        self.connection.host = host
        self.connection.api_context = api_context
        self.connection.port = port
        self.connection.driver = self
        self.connection.connect()

    def _order_uri(self, node,resource):
        # Returns the order uri with its resourse appended.
        return "/orders/%s/%s" % (node.id,resource)

    # TODO: Get the node state.
    def _to_node(self, order):
        n = Node(id=order['slug'],
                name=order['domain_name'],
                state=NodeState.RUNNING,
                public_ip=(
                    [order['allocated_ips']['primary_ip']]
                    + order['allocated_ips']['secondary_ips']
                ),
                private_ip=[],
                driver=self.connection.driver,
                extra={'order_oid': order['order_oid']})
        return n

    def _to_size(self,plan):
        return NodeSize(
            id=plan['pricing_plan_code'],
            name=plan['pricing_plan_description'],
            ram=plan['minimum_memory_mb'],
            disk=plan['minimum_disk_gb'],
            bandwidth=plan['minimum_data_transfer_allowance_gb'],
            price=plan['monthly_recurring_amt']['amt_usd'],
            driver=self.connection.driver
        )

    def _to_image(self,image):
        return NodeImage(id=image['distro_code'],
            name=image['distro_description'],
            driver=self.connection.driver)

    def list_sizes(self):
        # Returns a list of sizes (aka plans)
        # Get plans. Note this is really just for libcloud.
        # We are happy with any size.
        res = self.connection.request('/pricing-plans;server-type=VPS').object
        return map(lambda x : self._to_size(x), res['pricing_plan_infos'])

    def list_nodes(self):
        # Returns a list of Nodes
        # Will only include active ones.
        res = self.connection.request('/orders;include_inactive=N').object
        return map(lambda x : self._to_node(x), res['about_orders'])

    def list_images(self):
        # Get all base images.
        # TODO: add other image sources. (Such as a backup of a VPS)
        res = self.connection.request('/distributions').object
        return map(lambda x : self._to_image(x), res['distro_infos'])

    def reboot_node(self, node):
        # Reboot
        # PUT the state of RESTARTING to restart a VPS.
        # All data is encoded as JSON
        data = {'reboot_request':{'running_state':'RESTARTING'}}
        uri = self._order_uri(node,'vps/running-state')
        self.connection.request(uri,data=json.dumps(data),method='PUT')
        # XXX check that the response was actually successful
        return True

    def destroy_node(self, node):
        # Shutdown a VPS.
        uri = self._order_uri(node,'vps')
        self.connection.request(uri,method='DELETE')
        # XXX check that the response was actually successful
        return True

    def create_node(self, **kwargs):
        # Creates a RimuHosting instance
        #
        #   name    Must be a FQDN. e.g example.com.
        #   image   NodeImage from list_images
        #   size    NodeSize from list_sizes
        #
        # Keyword arguements supported:
        #
        #   billing_oid        If not set, a billing method is automatically
        #                      picked.
        #
        #   host_server_oid         The host server to set the VPS up on.
        #   vps_order_oid_to_clone  Clone another VPS to use as the image
        #                           for the new VPS.
        #
        #   num_ips = 1        Number of IPs to allocate. Defaults to 1.
        #   extra_ip_reason    Reason for needing the extra IPS.
        #
        #   memory_mb          Memory to allocate to the VPS.
        #   disk_space_mb      Diskspace to allocate to the VPS.
        #                      Defaults to 4096 (4GB).
        #   disk_space_2_mb    Secondary disk size allocation.
        #                      Disabled by default.
        #
        #   pricing_plan_code  Plan from list_sizes
        #
        #   control_panel      Control panel to install on the VPS.
        #
        #
        # Note we don't do much error checking in this because we
        # expect the API to error out if there is a problem.
        name = kwargs['name']
        image = kwargs['image']
        size = kwargs['size']

        data = {
            'instantiation_options':{
                'domain_name': name, 'distro': image.id
            },
            'pricing_plan_code': size.id,
        }

        if kwargs.has_key('control_panel'):
            (data['instantiation_options']['control_panel']
             = kwargs['control_panel'])

        if kwargs.has_key('auth'):
            auth = kwargs['auth']
            if not isinstance(auth, NodeAuthPassword):
                raise ValueError('auth must be of NodeAuthPassword type')
            data['instantiation_options']['password'] = auth.password

        if kwargs.has_key('billing_oid'):
            #TODO check for valid oid.
            data['billing_oid'] = kwargs['billing_oid']

        if kwargs.has_key('host_server_oid'):
            data['host_server_oid'] = kwargs['host_server_oid']

        if kwargs.has_key('vps_order_oid_to_clone'):
            data['vps_order_oid_to_clone'] = kwargs['vps_order_oid_to_clone']

        if kwargs.has_key('num_ips') and int(kwargs['num_ips']) > 1:
            if not kwargs.has_key('extra_ip_reason'):
                raise RimuHostingException('Need an reason for having an extra IP')
            else:
                if not data.has_key('ip_request'):
                    data['ip_request'] = {}
                data['ip_request']['num_ips'] = int(kwargs['num_ips'])
                data['ip_request']['extra_ip_reason'] =
                    kwargs['extra_ip_reason']

        if kwargs.has_key('memory_mb'):
            if not data.has_key('vps_parameters'):
                data['vps_parameters'] = {}
            data['vps_parameters']['memory_mb'] = kwargs['memory_mb']

        if kwargs.has_key('disk_space_mb'):
            if not data.has_key('vps_parameters'):
                data['vps_parameters'] = {}
            data['vps_parameters']['disk_space_mb'] = kwargs['disk_space_mb']

        if kwargs.has_key('disk_space_2_mb'):
            if not data.has_key('vps_parameters'):
                data['vps_parameters'] = {}
            data['vps_parameters']['disk_space_2_mb'] =
                kwargs['disk_space_2_mb']

        res = self.connection.request(
            '/orders/new-vps',
            method='POST',
            data=json.dumps({"new-vps":data})
        ).object
        node = self._to_node(res['about_order'])
        node.extra['password'] =
            res['new_order_request']['instantiation_options']['password']
        return node

    def list_locations(self):
        return [
            NodeLocation(0, "RimuHosting Auckland", 'NZ', self),
            NodeLocation(0, "RimuHosting Dallas", 'US', self),
            NodeLocation(0, "RimuHosting London", 'GB', self),
            NodeLocation(0, "RimuHosting Sydney", 'AU', self),
        ]

    features = {"create_node": ["password"]}

<commit_msg>Fixed syntax error in rimuhosting.py<commit_after># Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# libcloud.org licenses this file to You 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.
# Copyright 2009 RedRata Ltd
"""
RimuHosting Driver
"""
from libcloud.types import Provider, NodeState, InvalidCredsException
from libcloud.base import ConnectionKey, Response, NodeAuthPassword,
from libcloud.base import NodeDriver, NodeSize, Node, NodeLocation
from libcloud.base import NodeImage

# JSON is included in the standard library starting with Python 2.6.  For 2.5
# and 2.4, there's a simplejson egg at: http://pypi.python.org/pypi/simplejson
try: import json
except: import simplejson as json

# Defaults
API_CONTEXT = '/r'
API_HOST = 'api.rimuhosting.com'
API_PORT = (80,443)
API_SECURE = True

class RimuHostingException(Exception):
    def __str__(self):
        return self.args[0]

    def __repr__(self):
        return "<RimuHostingException '%s'>" % (self.args[0])

class RimuHostingResponse(Response):
    def __init__(self, response):
        self.body = response.read()
        self.status = response.status
        self.headers = dict(response.getheaders())
        self.error = response.reason

        if self.success():
          self.object = self.parse_body()

    def success(self):
        if self.status == 403:
          raise InvalidCredsException()
        return True
    def parse_body(self):
        try:
            js = json.loads(self.body)
            if js[js.keys()[0]]['response_type'] == "ERROR":
                raise RimuHostingException(
                    js[js.keys()[0]]['human_readable_message']
                )
            return js[js.keys()[0]]
        except ValueError:
            raise RimuHostingException('Could not parse body: %s'
                                       % (self.body))
        except KeyError:
            raise RimuHostingException('Could not parse body: %s'
                                       % (self.body))

class RimuHostingConnection(ConnectionKey):

    api_context = API_CONTEXT
    host = API_HOST
    port = API_PORT
    responseCls = RimuHostingResponse

    def __init__(self, key, secure=True):
        # override __init__ so that we can set secure of False for testing
        ConnectionKey.__init__(self,key,secure)

    def add_default_headers(self, headers):
        # We want JSON back from the server. Could be application/xml
        # (but JSON is better).
        headers['Accept'] = 'application/json'
        # Must encode all data as json, or override this header.
        headers['Content-Type'] = 'application/json'

        headers['Authorization'] = 'rimuhosting apikey=%s' % (self.key)
        return headers;

    def request(self, action, params={}, data='', headers={}, method='GET'):
        # Override this method to prepend the api_context
        return ConnectionKey.request(self, self.api_context + action,
                                     params, data, headers, method)

class RimuHostingNodeDriver(NodeDriver):
    type = Provider.RIMUHOSTING
    name = 'RimuHosting'
    connectionCls = RimuHostingConnection

    def __init__(self, key, host=API_HOST, port=API_PORT,
                 api_context=API_CONTEXT, secure=API_SECURE):
        # Pass in some extra vars so that
        self.key = key
        self.secure = secure
        self.connection = self.connectionCls(key ,secure)
        self.connection.host = host
        self.connection.api_context = api_context
        self.connection.port = port
        self.connection.driver = self
        self.connection.connect()

    def _order_uri(self, node,resource):
        # Returns the order uri with its resourse appended.
        return "/orders/%s/%s" % (node.id,resource)

    # TODO: Get the node state.
    def _to_node(self, order):
        n = Node(id=order['slug'],
                name=order['domain_name'],
                state=NodeState.RUNNING,
                public_ip=(
                    [order['allocated_ips']['primary_ip']]
                    + order['allocated_ips']['secondary_ips']
                ),
                private_ip=[],
                driver=self.connection.driver,
                extra={'order_oid': order['order_oid']})
        return n

    def _to_size(self,plan):
        return NodeSize(
            id=plan['pricing_plan_code'],
            name=plan['pricing_plan_description'],
            ram=plan['minimum_memory_mb'],
            disk=plan['minimum_disk_gb'],
            bandwidth=plan['minimum_data_transfer_allowance_gb'],
            price=plan['monthly_recurring_amt']['amt_usd'],
            driver=self.connection.driver
        )

    def _to_image(self,image):
        return NodeImage(id=image['distro_code'],
            name=image['distro_description'],
            driver=self.connection.driver)

    def list_sizes(self):
        # Returns a list of sizes (aka plans)
        # Get plans. Note this is really just for libcloud.
        # We are happy with any size.
        res = self.connection.request('/pricing-plans;server-type=VPS').object
        return map(lambda x : self._to_size(x), res['pricing_plan_infos'])

    def list_nodes(self):
        # Returns a list of Nodes
        # Will only include active ones.
        res = self.connection.request('/orders;include_inactive=N').object
        return map(lambda x : self._to_node(x), res['about_orders'])

    def list_images(self):
        # Get all base images.
        # TODO: add other image sources. (Such as a backup of a VPS)
        res = self.connection.request('/distributions').object
        return map(lambda x : self._to_image(x), res['distro_infos'])

    def reboot_node(self, node):
        # Reboot
        # PUT the state of RESTARTING to restart a VPS.
        # All data is encoded as JSON
        data = {'reboot_request':{'running_state':'RESTARTING'}}
        uri = self._order_uri(node,'vps/running-state')
        self.connection.request(uri,data=json.dumps(data),method='PUT')
        # XXX check that the response was actually successful
        return True

    def destroy_node(self, node):
        # Shutdown a VPS.
        uri = self._order_uri(node,'vps')
        self.connection.request(uri,method='DELETE')
        # XXX check that the response was actually successful
        return True

    def create_node(self, **kwargs):
        # Creates a RimuHosting instance
        #
        #   name    Must be a FQDN. e.g example.com.
        #   image   NodeImage from list_images
        #   size    NodeSize from list_sizes
        #
        # Keyword arguements supported:
        #
        #   billing_oid        If not set, a billing method is automatically
        #                      picked.
        #
        #   host_server_oid         The host server to set the VPS up on.
        #   vps_order_oid_to_clone  Clone another VPS to use as the image
        #                           for the new VPS.
        #
        #   num_ips = 1        Number of IPs to allocate. Defaults to 1.
        #   extra_ip_reason    Reason for needing the extra IPS.
        #
        #   memory_mb          Memory to allocate to the VPS.
        #   disk_space_mb      Diskspace to allocate to the VPS.
        #                      Defaults to 4096 (4GB).
        #   disk_space_2_mb    Secondary disk size allocation.
        #                      Disabled by default.
        #
        #   pricing_plan_code  Plan from list_sizes
        #
        #   control_panel      Control panel to install on the VPS.
        #
        #
        # Note we don't do much error checking in this because we
        # expect the API to error out if there is a problem.
        name = kwargs['name']
        image = kwargs['image']
        size = kwargs['size']

        data = {
            'instantiation_options':{
                'domain_name': name, 'distro': image.id
            },
            'pricing_plan_code': size.id,
        }

        if kwargs.has_key('control_panel'):
            data['instantiation_options']['control_panel'] = kwargs['control_panel']

        if kwargs.has_key('auth'):
            auth = kwargs['auth']
            if not isinstance(auth, NodeAuthPassword):
                raise ValueError('auth must be of NodeAuthPassword type')
            data['instantiation_options']['password'] = auth.password

        if kwargs.has_key('billing_oid'):
            #TODO check for valid oid.
            data['billing_oid'] = kwargs['billing_oid']

        if kwargs.has_key('host_server_oid'):
            data['host_server_oid'] = kwargs['host_server_oid']

        if kwargs.has_key('vps_order_oid_to_clone'):
            data['vps_order_oid_to_clone'] = kwargs['vps_order_oid_to_clone']

        if kwargs.has_key('num_ips') and int(kwargs['num_ips']) > 1:
            if not kwargs.has_key('extra_ip_reason'):
                raise RimuHostingException('Need an reason for having an extra IP')
            else:
                if not data.has_key('ip_request'):
                    data['ip_request'] = {}
                data['ip_request']['num_ips'] = int(kwargs['num_ips'])
                data['ip_request']['extra_ip_reason'] =
                    kwargs['extra_ip_reason']

        if kwargs.has_key('memory_mb'):
            if not data.has_key('vps_parameters'):
                data['vps_parameters'] = {}
            data['vps_parameters']['memory_mb'] = kwargs['memory_mb']

        if kwargs.has_key('disk_space_mb'):
            if not data.has_key('vps_parameters'):
                data['vps_parameters'] = {}
            data['vps_parameters']['disk_space_mb'] = kwargs['disk_space_mb']

        if kwargs.has_key('disk_space_2_mb'):
            if not data.has_key('vps_parameters'):
                data['vps_parameters'] = {}
            data['vps_parameters']['disk_space_2_mb'] =
                kwargs['disk_space_2_mb']

        res = self.connection.request(
            '/orders/new-vps',
            method='POST',
            data=json.dumps({"new-vps":data})
        ).object
        node = self._to_node(res['about_order'])
        node.extra['password'] =
            res['new_order_request']['instantiation_options']['password']
        return node

    def list_locations(self):
        return [
            NodeLocation(0, "RimuHosting Auckland", 'NZ', self),
            NodeLocation(0, "RimuHosting Dallas", 'US', self),
            NodeLocation(0, "RimuHosting London", 'GB', self),
            NodeLocation(0, "RimuHosting Sydney", 'AU', self),
        ]

    features = {"create_node": ["password"]}

<|endoftext|>


<commit_before># Main class for StatusBarExtended

from fman import DirectoryPaneCommand, DirectoryPaneListener, \
 show_status_message, load_json, save_json, show_alert
from os import stat, path, getenv
import json
import glob
from byteconverter import ByteConverter
#from PyQt5.QtWidgets import QApplication

def convert_bytes(n):
    for x in ['B', 'KB', 'MB', 'GB', 'TB']:
        if n < 1024.0:
            return "%3.1f %s" % (n, x)
        n /= 1024.0

class StatusBarExtended(DirectoryPaneListener):

    def refresh(self):

        pane = self.pane.id
        statusbar_pane = ""

        pane_show_hidden_files = load_json('Panes.json')[pane]['show_hidden_files']
        pane_show_hidden_files = "✓" if pane_show_hidden_files == True else "X"

        current_dir = self.pane.get_path()
        dir_folders = 0
        dir_files = 0
        dir_filesize = 0
        dir_files_in_dir = glob.glob(current_dir + "/*")
        if dir_files_in_dir:
            for f in dir_files_in_dir:
                if path.isdir(f):
                    dir_folders += 1
                else:
                    dir_files += 1
                    try:
                        dir_filesize += stat(f).st_size
                    except Exception as e:
                        continue

        bc = ByteConverter(dir_filesize)
        if(pane == self.pane.window.get_panes()[0].id):
            statusbar_pane += "Pane: Left     "
        else:
            statusbar_pane += "Pane: Right     "
        statusbar_pane += "" + pane_show_hidden_files + "     "
        statusbar_pane += "Dirs: " + str(dir_folders) + "     "
        if dir_files > 0:
            statusbar_pane += "Files: " + str(dir_files) + "     "
            statusbar_pane += "Size: " + str(bc.calc()) + "     "

        show_status_message(statusbar_pane, 5000)

    def show_selected_files(self):
        selected = self.pane.get_selected_files()
        dir_folders = 0
        dir_files = 0
        dir_filesize = 0

        if selected:
            for f in selected:
                if path.isdir(f):
                    dir_folders += 1
                else:
                    dir_files += 1
                    dir_filesize += stat(f).st_size

            bc = ByteConverter(dir_filesize)
            statusbar = str(dir_folders) + " directories, "
            statusbar += str(dir_files) + " files "
            statusbar += "selected - "
            statusbar += "total filesize: " + str(bc.calc())
            show_status_message(statusbar)

        else:
            StatusBarExtended.refresh(self)

    def on_path_changed(self):
        statusBarExtendedEnabled = load_json('StatusBarExtended.json')
        if statusBarExtendedEnabled:
            statusBarExtendedEnabledJson = json.loads(statusBarExtendedEnabled)
            if statusBarExtendedEnabledJson['enabled'] == True:
                StatusBarExtended.refresh(self)
<commit_msg>Make plugin compatible with fman 0.3.6<commit_after># Main class for StatusBarExtended

from fman import DirectoryPaneCommand, DirectoryPaneListener, \
 show_status_message, load_json, save_json, show_alert
from os import stat, path, getenv
import json
import glob
from byteconverter import ByteConverter
#from PyQt5.QtWidgets import QApplication

def convert_bytes(n):
    for x in ['B', 'KB', 'MB', 'GB', 'TB']:
        if n < 1024.0:
            return "%3.1f %s" % (n, x)
        n /= 1024.0

class StatusBarExtended(DirectoryPaneListener):

    def refresh(self):

        pane = self.pane.window.get_panes().index(self.pane)
        statusbar_pane = ""

        pane_show_hidden_files = load_json('Panes.json')[pane]['show_hidden_files']
        pane_show_hidden_files = "✓" if pane_show_hidden_files == True else "X"

        current_dir = self.pane.get_path()
        dir_folders = 0
        dir_files = 0
        dir_filesize = 0
        dir_files_in_dir = glob.glob(current_dir + "/*")
        if dir_files_in_dir:
            for f in dir_files_in_dir:
                if path.isdir(f):
                    dir_folders += 1
                else:
                    dir_files += 1
                    try:
                        dir_filesize += stat(f).st_size
                    except Exception as e:
                        continue

        bc = ByteConverter(dir_filesize)
        if(self.pane == self.pane.window.get_panes()[0]):
            statusbar_pane += "Pane: Left     "
        else:
            statusbar_pane += "Pane: Right     "
        statusbar_pane += "" + pane_show_hidden_files + "     "
        statusbar_pane += "Dirs: " + str(dir_folders) + "     "
        if dir_files > 0:
            statusbar_pane += "Files: " + str(dir_files) + "     "
            statusbar_pane += "Size: " + str(bc.calc()) + "     "

        show_status_message(statusbar_pane, 5000)

    def show_selected_files(self):
        selected = self.pane.get_selected_files()
        dir_folders = 0
        dir_files = 0
        dir_filesize = 0

        if selected:
            for f in selected:
                if path.isdir(f):
                    dir_folders += 1
                else:
                    dir_files += 1
                    dir_filesize += stat(f).st_size

            bc = ByteConverter(dir_filesize)
            statusbar = str(dir_folders) + " directories, "
            statusbar += str(dir_files) + " files "
            statusbar += "selected - "
            statusbar += "total filesize: " + str(bc.calc())
            show_status_message(statusbar)

        else:
            StatusBarExtended.refresh(self)

    def on_path_changed(self):
        statusBarExtendedEnabled = load_json('StatusBarExtended.json')
        if statusBarExtendedEnabled:
            statusBarExtendedEnabledJson = json.loads(statusBarExtendedEnabled)
            if statusBarExtendedEnabledJson['enabled'] == True:
                StatusBarExtended.refresh(self)
<|endoftext|>


<commit_before>from contests.models import Contest, Submission

class CurrentContestMiddleware(object):
    def process_request(self, request):
        request.contests = Contest.objects.order_by('-number')
        for contest in request.contests:
            contest.can_vote = (request.user.is_authenticated() and Submission.objects.filter(user=request.user).count() > 0)

        current_contest = request.contests[0]
        request.current_contest = current_contest
<commit_msg>Website now works if there are no contests<commit_after>from contests.models import Contest, Submission

class CurrentContestMiddleware(object):
    def process_request(self, request):
        request.contests = Contest.objects.order_by('-number')
        for contest in request.contests:
            contest.can_vote = (request.user.is_authenticated() and Submission.objects.filter(user=request.user).count() > 0)
        try:
            request.current_contest = request.contests[0]
        except:
            request.current_contest = None
<|endoftext|>


<commit_before>#!/usr/bin/python3

"""
created_by:         John Fang
created_date:       3/4/2015
last_modified_by:   John Fang
last_modified_date: 3/4/2015
"""

# imports
import constants
import json
from sql.user import User
from sql.topic import Topic
from sql.session import Session

#Format of answer
#created: TIME_STAMP
#created_by: int
#name: "string"
#active: boolean

def iChooseU(json):
    ipAddress = self.client_address[0]
    session = Session.get(json["session"], ipAddress)[0]
    thisUser = User.get(session[0])[0]
    if DEBUG > 1:
        print(thisUser)

    name = json("name")

    newTopic = Topic.noID(TIME_STAMP, thisUser.id, name, ACTIVE)
    newTopic.add()

    successJson = json.dumps({"success":True, "session":session.toJson()})
    return successJson
<commit_msg>fixed addTopic<commit_after>#!/usr/bin/python3

"""
created_by:         John Fang
created_date:       3/4/2015
last_modified_by:   John Fang
last_modified_date: 3/4/2015
"""

# imports
import constants
import json
from sql.user import User
from sql.topic import Topic
from sql.session import Session

#Format of answer
#name: "string"
#active: boolean

def iChooseU(json):
    ipAddress = self.client_address[0]
    session = Session.get(json["session"], ipAddress)[0]
    thisUser = User.get(session[0])[0]
    if DEBUG > 1:
        print(thisUser)

    name = json("name")

    newTopic = Topic.noID(TIME_STAMP, thisUser.id, name, ACTIVE)
    newTopic.add()

    successJson = json.dumps({"success":True, "session":session.toJson()})
    return successJson
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# this file is released under public domain and you can use without limitations

#########################################################################
# # This is a sample controller
# # - index is the default action of any application
# # - user is required for authentication and authorization
# # - download is for downloading files uploaded in the db (does streaming)
# # - call exposes all registered services (none by default)
#########################################################################
from datetime import date, datetime, timedelta
import json

@auth.requires_login()
def index():
    delivery = get_next_delivery()
    return dict(delivery=delivery)

@auth.requires_login()
def make_dish():
    weightURL = URL('default', 'add_weights')
    db.dish.category.requires = IS_IN_SET(['Appetizer', 'Entree', 'Dessert'])

    form = SQLFORM(db.dish, fields = ['name', 'description', 'price', 'ingredients',
                                       'category', 'vegetarian', 'vegan', 'gluten_free'])
    if form.process().accepted:
        response.flash = 'Your dish has been created'
        redirect(URL('default', 'view_dish',args=[form.vars.id]))
    return dict(form=form, menu="yolo")

    return dict(form=form,weightURL=weightURL)

@auth.requires_login()
def add_weights():
    weightArray = eval(request.vars.array)
    dishid = int(request.vars.id)
    dish = db.dish(dishid)
    for i in range(len(weightArray)):
        if (((i+2)%2) == 0):
            dish.ingredientWeights.insert(weightArray[i])
        else:
            dish.weightsMeasurements.insert(weightArray[i])

    return response.json(dict(result=weightArray))

def about_us():
    return dict()

@auth.requires_login()
#method to view single dishes
def view_dish():
    dish = db.dish(db.dish.id==request.args(0))
    if dish is None:
        session.flash = 'invalid request'
        redirect(URL('default', 'index'))
    return dict(dish=dish)

@auth.requires_login()
def all_dishes():
    q = db.dish
    grid = SQLFORM.grid(q,
           fields = [db.dish.name],
           csv = False
           )
    return dict(grid=grid)

@auth.requires_login()
def schedule():
    email = get_email()
    rows = db(db.menu.user_id == email).select()
    return dict(rows=rows)

@auth.requires_login()
def set_schedule():
    #date = json.load(request.vars)
    email = get_email()
    date = get_date_from_json(request.vars['datetime'])
    name = request.vars['name']
    frequency = int(request.vars['frequency'])
    end = date + timedelta(30)

    menu = db((db.menu.name == name) & (db.menu.user_id == email)).select().first()
    if menu == None:
        return json.dumps({'success':False})

    deliveries = db(db.deliveries.menu == menu.id).select()
    timeout = 0

    #gets the dates to add to the calendar
    while date < end:
        timeframe = query_by_date(date)
        t = db.deliveries
        query = (t.menu==menu.id) & (t.delivery_time >= timeframe[0]) & (t.delivery_time < timeframe[1]) & (t.user_id==email)
        overwrittenSet = db(query)
        overwrittendelivery = overwrittenSet.select().first()
        if overwrittendelivery is None:
            db.deliveries.insert(menu=menu, delivery_time=date)
        else:
            overwrittenSet.update(delivery_time=date)

        if frequency <= 0:
            break

        date = date + timedelta(frequency*7)

        timeout+=1
        if timeout > 60:
            return json.dumps({'success':frequency})

    return  json.dumps({'success':True})

def move_delivery():
    newDate = get_date_from_json(request.vars['newDate'])
    oldDate = newDate - timedelta(int(request.vars['dayDelta']))
    name = request.vars['name']
    email = get_email()
    menu = db((db.menu.name == name) & (db.menu.user_id == email)).select().first()
    if menu is None:
        return {'success':False, 'reload':False}

    timeframe = query_by_date(oldDate)
    t = db.deliveries
    query = (t.menu==menu.id) & (t.delivery_time >= timeframe[0]) & (t.delivery_time < timeframe[1]) & (t.user_id==email)
    deliverySet = db(query)
    delivery = deliverySet.select().first()
    if delivery is None:
        return json.dumps({'success':False, 'error':"Could not find original record", 'reload':False})
    else:
        #check if an event of the same name already exists in that location, if so overwrite it
        timeframe = query_by_date(newDate)
        t = db.deliveries
        query = (t.menu==menu.id) & (t.delivery_time >= timeframe[0]) & (t.delivery_time < timeframe[1]) & (t.user_id==email)
        overwrittenSet = db(query)
        overwrittenDelivery = overwrittenSet.select().first()
        if overwrittenDelivery is None:
            deliverySet.update(delivery_time=newDate)
        else:
            overwrittenSet.update(delivery_time=newDate)
            deliverySet.delete()
            response.flash = 'Meal Overwritten'
            return  json.dumps({'success':True, 'reload':True})

    return  json.dumps({'success':True, 'reload':False})

@auth.requires_login()
def create_menu():
    db.menu.appetizer.requires = IS_IN_DB(db(db.dish.category=="Appetizer"), db.dish.id, '%(name)s')
    db.menu.entree.requires = IS_IN_DB(db(db.dish.category=="Entree"), db.dish.id, '%(name)s')
    db.menu.dessert.requires = IS_IN_DB(db(db.dish.category=="Dessert"), db.dish.id, '%(name)s')
    form = SQLFORM(db.menu, fields = ['name', 'appetizer', 'entree', 'dessert',
                                       'serving_number'],)
    if form.process().accepted:
        response.flash = 'Your menu has been created'
        redirect(URL('default', 'view_menu',args=[form.vars.id]))
    elif form.errors:
        response.flash = 'form has errors'
    else:
       response.flash = 'Please fill out the form'
    return dict(form=form)

def get_dish_name(id):
    name = db.dish(id).name
    return name

@auth.requires_login()
def my_menus():
    email = auth.user.email
    mymenus = db(db.menu.user_id == email).select()
    return dict(mymenus=mymenus)

@auth.requires_login()
def view_menu():
    menu = db.menu(request.args(0))
    if menu is None:
        session.flash = 'invalid request'
        redirect(URL('default', 'index'))
    email = auth.user.email
    if menu.user_id == email:
        return dict(menu=menu, app=menu.appetizer)
    else:
        session.flash = 'invalid request'
        redirect(URL('default', 'index'))

@auth.requires_login()
def all_menus():
   menus = SQLFORM.grid(db.menu)
   return dict(menus=menus)

@auth.requires_login()
def get_next_delivery():
    email = auth.user.email
    myMenus = db(db.menu.user_id == email).select()
    start = datetime.today()
    end = start + timedelta(31)
    date = datetime.today() - timedelta(1)

    nextDelivery = db( (db.deliveries.delivery_time >= start) & (db.deliveries.delivery_time < end) & (db.deliveries.user_id==email)).select(orderby=db.deliveries.delivery_time).first()
    return nextDelivery

@auth.requires_login()
def get_json_schedule():
    email = auth.user.email
    myMenus = db(db.menu.user_id == email).select()
    if myMenus is None:
        return json.dumps([])

    start = datetime.fromtimestamp(long(request.vars['start']))
    end = datetime.fromtimestamp(long(request.vars['end']))
    data = []
    deliveries = db( (db.deliveries.delivery_time <= end) & (db.deliveries.delivery_time >= start) & (db.deliveries.user_id == email)).select()

    for delivery in deliveries:
        date = delivery.delivery_time
        if date is None:
            continue
        color = '#FFDEAD' if date < datetime.today() else '#C2B280'
        event = {'title':delivery.menu.name, 'start':date.strftime('%Y-%m-%dT%H:%M:%S'), 'color':color};
        data.append(event)

    return json.dumps(data)

def query_by_date(dt):
    date_start = dt.date()
    date_end = date_start + timedelta(days=1)
    return date_start, date_end

def get_date_from_json(dateString):
    newDate = str.join(' ', dateString.split(' ')[0:5])
    date = datetime.strptime(newDate, '%a %b %d %Y %H:%M:%S')
    return date

def user():
    """
    exposes:
    http://..../[app]/default/user/login
    http://..../[app]/default/user/logout
    http://..../[app]/default/user/register
    http://..../[app]/default/user/profile
    http://..../[app]/default/user/retrieve_password
    http://..../[app]/default/user/change_password
    http://..../[app]/default/user/manage_users (requires membership in
    use @auth.requires_login()
        @auth.requires_membership('group name')
        @auth.requires_permission('read','table name',record_id)
    to decorate functions that need access control
    """
    return dict(form=auth())

def construction():
    return dict(message="Under Construction")

@cache.action()
def download():
    """
    allows downloading of uploaded files
    http://..../[app]/default/download/[filename]
    """
    return response.download(request, db)

def call():
    """
    exposes services. for example:
    http://..../[app]/default/call/jsonrpc
    decorate with @services.jsonrpc the functions to expose
    supports xml, json, xmlrpc, jsonrpc, amfrpc, rss, csv
    """
    return service()

@auth.requires_signature()
def data():
    """
    http://..../[app]/default/data/tables
    http://..../[app]/default/data/create/[table]
    http://..../[app]/default/data/read/[table]/[id]
    http://..../[app]/default/data/update/[table]/[id]
    http://..../[app]/default/data/delete/[table]/[id]
    http://..../[app]/default/data/select/[table]
    http://..../[app]/default/data/search/[table]
    but URLs must be signed, i.e. linked with
      A('table',_href=URL('data/tables',user_signature=True))
    or with the signed load operator
      LOAD('default','data.load',args='tables',ajax=True,user_signature=True)
    """
    return dict(form=crud())
<commit_msg>fixed break<commit_after># -*- coding: utf-8 -*-
# this file is released under public domain and you can use without limitations

#########################################################################
# # This is a sample controller
# # - index is the default action of any application
# # - user is required for authentication and authorization
# # - download is for downloading files uploaded in the db (does streaming)
# # - call exposes all registered services (none by default)
#########################################################################
from datetime import date, datetime, timedelta
import json

@auth.requires_login()
def index():
    delivery = get_next_delivery()
    return dict(delivery=delivery)

@auth.requires_login()
def make_dish():
    weightURL = URL('default', 'add_weights')
    db.dish.category.requires = IS_IN_SET(['Appetizer', 'Entree', 'Dessert'])

    form = SQLFORM(db.dish, fields = ['name', 'description', 'price', 'ingredients',
                                       'category', 'vegetarian', 'vegan', 'gluten_free'])
    if form.process().accepted:
        response.flash = 'Your dish has been created'
        redirect(URL('default', 'view_dish',args=[form.vars.id]))
    return dict(form=form,weightURL=weightURL)

@auth.requires_login()
def add_weights():
    weightArray = eval(request.vars.array)
    dishid = int(request.vars.id)
    dish = db.dish(dishid)
    for i in range(len(weightArray)):
        if (((i+2)%2) == 0):
            dish.ingredientWeights.insert(weightArray[i])
        else:
            dish.weightsMeasurements.insert(weightArray[i])

    return response.json(dict(result=weightArray))

def about_us():
    return dict()

@auth.requires_login()
#method to view single dishes
def view_dish():
    dish = db.dish(db.dish.id==request.args(0))
    if dish is None:
        session.flash = 'invalid request'
        redirect(URL('default', 'index'))
    return dict(dish=dish)

@auth.requires_login()
def all_dishes():
    q = db.dish
    grid = SQLFORM.grid(q,
           fields = [db.dish.name],
           csv = False
           )
    return dict(grid=grid)

@auth.requires_login()
def schedule():
    email = get_email()
    rows = db(db.menu.user_id == email).select()
    return dict(rows=rows)

@auth.requires_login()
def set_schedule():
    #date = json.load(request.vars)
    email = get_email()
    date = get_date_from_json(request.vars['datetime'])
    name = request.vars['name']
    frequency = int(request.vars['frequency'])
    end = date + timedelta(30)

    menu = db((db.menu.name == name) & (db.menu.user_id == email)).select().first()
    if menu == None:
        return json.dumps({'success':False})

    deliveries = db(db.deliveries.menu == menu.id).select()
    timeout = 0

    #gets the dates to add to the calendar
    while date < end:
        timeframe = query_by_date(date)
        t = db.deliveries
        query = (t.menu==menu.id) & (t.delivery_time >= timeframe[0]) & (t.delivery_time < timeframe[1]) & (t.user_id==email)
        overwrittenSet = db(query)
        overwrittendelivery = overwrittenSet.select().first()
        if overwrittendelivery is None:
            db.deliveries.insert(menu=menu, delivery_time=date)
        else:
            overwrittenSet.update(delivery_time=date)

        if frequency <= 0:
            break

        date = date + timedelta(frequency*7)

        timeout+=1
        if timeout > 60:
            return json.dumps({'success':frequency})

    return  json.dumps({'success':True})

def move_delivery():
    newDate = get_date_from_json(request.vars['newDate'])
    oldDate = newDate - timedelta(int(request.vars['dayDelta']))
    name = request.vars['name']
    email = get_email()
    menu = db((db.menu.name == name) & (db.menu.user_id == email)).select().first()
    if menu is None:
        return {'success':False, 'reload':False}

    timeframe = query_by_date(oldDate)
    t = db.deliveries
    query = (t.menu==menu.id) & (t.delivery_time >= timeframe[0]) & (t.delivery_time < timeframe[1]) & (t.user_id==email)
    deliverySet = db(query)
    delivery = deliverySet.select().first()
    if delivery is None:
        return json.dumps({'success':False, 'error':"Could not find original record", 'reload':False})
    else:
        #check if an event of the same name already exists in that location, if so overwrite it
        timeframe = query_by_date(newDate)
        t = db.deliveries
        query = (t.menu==menu.id) & (t.delivery_time >= timeframe[0]) & (t.delivery_time < timeframe[1]) & (t.user_id==email)
        overwrittenSet = db(query)
        overwrittenDelivery = overwrittenSet.select().first()
        if overwrittenDelivery is None:
            deliverySet.update(delivery_time=newDate)
        else:
            overwrittenSet.update(delivery_time=newDate)
            deliverySet.delete()
            response.flash = 'Meal Overwritten'
            return  json.dumps({'success':True, 'reload':True})

    return  json.dumps({'success':True, 'reload':False})

@auth.requires_login()
def create_menu():
    db.menu.appetizer.requires = IS_IN_DB(db(db.dish.category=="Appetizer"), db.dish.id, '%(name)s')
    db.menu.entree.requires = IS_IN_DB(db(db.dish.category=="Entree"), db.dish.id, '%(name)s')
    db.menu.dessert.requires = IS_IN_DB(db(db.dish.category=="Dessert"), db.dish.id, '%(name)s')
    form = SQLFORM(db.menu, fields = ['name', 'appetizer', 'entree', 'dessert',
                                       'serving_number'],)
    if form.process().accepted:
        response.flash = 'Your menu has been created'
        redirect(URL('default', 'view_menu',args=[form.vars.id]))
    elif form.errors:
        response.flash = 'form has errors'
    else:
       response.flash = 'Please fill out the form'
    return dict(form=form)

def get_dish_name(id):
    name = db.dish(id).name
    return name

@auth.requires_login()
def my_menus():
    email = auth.user.email
    mymenus = db(db.menu.user_id == email).select()
    return dict(mymenus=mymenus)

@auth.requires_login()
def view_menu():
    menu = db.menu(request.args(0))
    if menu is None:
        session.flash = 'invalid request'
        redirect(URL('default', 'index'))
    email = auth.user.email
    if menu.user_id == email:
        return dict(menu=menu, app=menu.appetizer)
    else:
        session.flash = 'invalid request'
        redirect(URL('default', 'index'))

@auth.requires_login()
def all_menus():
   menus = SQLFORM.grid(db.menu)
   return dict(menus=menus)

@auth.requires_login()
def get_next_delivery():
    email = auth.user.email
    myMenus = db(db.menu.user_id == email).select()
    start = datetime.today()
    end = start + timedelta(31)
    date = datetime.today() - timedelta(1)

    nextDelivery = db( (db.deliveries.delivery_time >= start) & (db.deliveries.delivery_time < end) & (db.deliveries.user_id==email)).select(orderby=db.deliveries.delivery_time).first()
    return nextDelivery

@auth.requires_login()
def get_json_schedule():
    email = auth.user.email
    myMenus = db(db.menu.user_id == email).select()
    if myMenus is None:
        return json.dumps([])

    start = datetime.fromtimestamp(long(request.vars['start']))
    end = datetime.fromtimestamp(long(request.vars['end']))
    data = []
    deliveries = db( (db.deliveries.delivery_time <= end) & (db.deliveries.delivery_time >= start) & (db.deliveries.user_id == email)).select()

    for delivery in deliveries:
        date = delivery.delivery_time
        if date is None:
            continue
        color = '#FFDEAD' if date < datetime.today() else '#C2B280'
        event = {'title':delivery.menu.name, 'start':date.strftime('%Y-%m-%dT%H:%M:%S'), 'color':color};
        data.append(event)

    return json.dumps(data)

def query_by_date(dt):
    date_start = dt.date()
    date_end = date_start + timedelta(days=1)
    return date_start, date_end

def get_date_from_json(dateString):
    newDate = str.join(' ', dateString.split(' ')[0:5])
    date = datetime.strptime(newDate, '%a %b %d %Y %H:%M:%S')
    return date

def user():
    """
    exposes:
    http://..../[app]/default/user/login
    http://..../[app]/default/user/logout
    http://..../[app]/default/user/register
    http://..../[app]/default/user/profile
    http://..../[app]/default/user/retrieve_password
    http://..../[app]/default/user/change_password
    http://..../[app]/default/user/manage_users (requires membership in
    use @auth.requires_login()
        @auth.requires_membership('group name')
        @auth.requires_permission('read','table name',record_id)
    to decorate functions that need access control
    """
    return dict(form=auth())

def construction():
    return dict(message="Under Construction")

@cache.action()
def download():
    """
    allows downloading of uploaded files
    http://..../[app]/default/download/[filename]
    """
    return response.download(request, db)

def call():
    """
    exposes services. for example:
    http://..../[app]/default/call/jsonrpc
    decorate with @services.jsonrpc the functions to expose
    supports xml, json, xmlrpc, jsonrpc, amfrpc, rss, csv
    """
    return service()

@auth.requires_signature()
def data():
    """
    http://..../[app]/default/data/tables
    http://..../[app]/default/data/create/[table]
    http://..../[app]/default/data/read/[table]/[id]
    http://..../[app]/default/data/update/[table]/[id]
    http://..../[app]/default/data/delete/[table]/[id]
    http://..../[app]/default/data/select/[table]
    http://..../[app]/default/data/search/[table]
    but URLs must be signed, i.e. linked with
      A('table',_href=URL('data/tables',user_signature=True))
    or with the signed load operator
      LOAD('default','data.load',args='tables',ajax=True,user_signature=True)
    """
    return dict(form=crud())
<|endoftext|>


<commit_before>import os
import time
import json
import hashlib
import github_client
from pprint import pprint
from github import Github

def index():
    def GET():
        return locals()

@request.restful()
def api():
    response.view = 'generic.json'

    def GET(resource,resource_id,jsoncallback=None,callback=None,_=None,**kwargs):
        if not resource=='study': raise HTTP(400, 'resource != study [GET]')

        # support JSONP request from another domain
        if jsoncallback or callback:
            response.view = 'generic.jsonp'

        # fetch using the GitHub API auth-token for a logged-in curator
        auth_token = kwargs.get('auth_token', 'ANONYMOUS')
        if auth_token == 'ANONYMOUS':
            # non-web callers might be using an HTTP header ("Authorization: token abc123def456")
            auth_header = request.env.get('http_authorization', None) or request.wsgi.environ.get('HTTP_AUTHORIZATION', None)
            if auth_header:
                auth_token = auth_header.split()[1]

        # return the correct nexson of study_id, using the specified view
        try:
            # TODO: use readlines() in some way, to handle humongous files?
            return dict(FULL_RESPONSE=github_client.fetch_study(resource_id, auth_token))
        except Exception, e:
            return 'ERROR fetching study:\n%s' % e

    def POST(resource, resource_id=None, **kwargs):
        # support JSONP request from another domain
        if kwargs.get('jsoncallback',None) or kwargs.get('callback',None):
            response.view = 'generic.jsonp'

        if not resource=='study': raise HTTP(400, 'resource != study')

        # TODO: use presence or absence of resource_id as a cue to creation vs.
        # updates? Or better yet, support method overrides (on POST requests)
        # for PUT, PATCH, DELETE and redirect as needed:
        # http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api#method-override
        #
        if False:
            if resource_id:
                # this is an update(?) of an existing study, use code below
                pass
            else:
                # we're creating a new study (possibly with import instructions in the payload)
                cc0_agreement = kwargs.get('cc0_agreement', '')
                import_option = kwargs.get('import_option', '')
                treebase_id = kwargs.get('treebase_id', '')
                dryad_DOI = kwargs.get('dryad_DOI', '')
                import_option = kwargs.get('import_option', '')

                return kwargs
                # TODO: assign a new ID for this study, create its folder in repo(?)

                # forward ID and info to treemachine, expect to get study JSON back

                # IF treemachine returns JSON, save as {ID}.json and return URL as '201 Created'
                # or perhaps '303 See other' w/ redirect?
                # (should we do this on a WIP branch? save empty folder in 'master'?)

                # IF treemachine throws an error, return error info as '500 Internal Server Error'

        if resource_id < 0 : raise HTTP(400, 'invalid resource_id: must be a postive integer')

        author_name  = kwargs.get('author_name','')
        author_email = kwargs.get('author_email','')
        # this is the GitHub API auth-token for a logged-in curator
        auth_token   = kwargs.get('auth_token','')

        if not auth_token:
            raise HTTP(400,"You must authenticate to before updating via the OTOL API")

        # Connect to the Github v3 API via with this OAuth token
        gh = Github(oauth_token)

        try:
            nexson        = json.loads( kwargs.get('nexson','{}') )
        except:
            raise HTTP(400, 'NexSON must be valid JSON')

        # sort the keys of the POSTed NexSON and indent 4 spaces
        nexson = json.dumps(nexson, sort_keys=True, indent=4)

        _update_treenexus()

        # We compare sha1's instead of the actual data to reduce memory use
        # when comparing large studies
        posted_nexson_sha1 = hashlib.sha1(nexson).hexdigest()
        nexson_sha1        = hashlib.sha1( _get_nexson(resource_id, auth_token) ).hexdigest()

        # the POSTed data is the same as what we have on disk, do nothing and return successfully
        if posted_nexson_sha1 == nexson_sha1:
            return { error: 0, description: "success" };
        else:
            # we have new data
            # TODO: Use http://jacquev6.github.io/PyGithub/github_objects/Repository.html#github.Repository.Repository.create_git_commit
            return dict()
    return locals()

def _update_treenexus():
    """Update the treenexus git submodule"""
    # submodule update must be run from the top-level dir of our repo
    rc = os.system("cd ..; git submodule update")
    if rc:
        raise HTTP(400,"Unable to update local treenexus.git")

def _study_id_to_filename(study_id):
    """Return the filename of a given study_id"""
    this_dir  = os.path.dirname(os.path.abspath(__file__))
    filename  = this_dir + "/../treenexus/study/" + study_id + "/" + study_id + ".json"
    return filename

<commit_msg>Rename api->index to improve URLs, remove dead code<commit_after>import os
import time
import json
import hashlib
import github_client
from pprint import pprint
from github import Github

@request.restful()
def index():
    response.view = 'generic.json'

    def GET(resource,resource_id,jsoncallback=None,callback=None,_=None,**kwargs):
        if not resource=='study': raise HTTP(400, 'resource != study [GET]')

        # support JSONP request from another domain
        if jsoncallback or callback:
            response.view = 'generic.jsonp'

        # fetch using the GitHub API auth-token for a logged-in curator
        auth_token = kwargs.get('auth_token', 'ANONYMOUS')
        if auth_token == 'ANONYMOUS':
            # non-web callers might be using an HTTP header ("Authorization: token abc123def456")
            auth_header = request.env.get('http_authorization', None) or request.wsgi.environ.get('HTTP_AUTHORIZATION', None)
            if auth_header:
                auth_token = auth_header.split()[1]

        # return the correct nexson of study_id, using the specified view
        try:
            # TODO: use readlines() in some way, to handle humongous files?
            return dict(FULL_RESPONSE=github_client.fetch_study(resource_id, auth_token))
        except Exception, e:
            return 'ERROR fetching study:\n%s' % e

    def POST(resource, resource_id=None, **kwargs):
        # support JSONP request from another domain
        if kwargs.get('jsoncallback',None) or kwargs.get('callback',None):
            response.view = 'generic.jsonp'

        if not resource=='study': raise HTTP(400, 'resource != study')

        # TODO: use presence or absence of resource_id as a cue to creation vs.
        # updates? Or better yet, support method overrides (on POST requests)
        # for PUT, PATCH, DELETE and redirect as needed:
        # http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api#method-override
        #
        if False:
            if resource_id:
                # this is an update(?) of an existing study, use code below
                pass
            else:
                # we're creating a new study (possibly with import instructions in the payload)
                cc0_agreement = kwargs.get('cc0_agreement', '')
                import_option = kwargs.get('import_option', '')
                treebase_id = kwargs.get('treebase_id', '')
                dryad_DOI = kwargs.get('dryad_DOI', '')
                import_option = kwargs.get('import_option', '')

                return kwargs
                # TODO: assign a new ID for this study, create its folder in repo(?)

                # forward ID and info to treemachine, expect to get study JSON back

                # IF treemachine returns JSON, save as {ID}.json and return URL as '201 Created'
                # or perhaps '303 See other' w/ redirect?
                # (should we do this on a WIP branch? save empty folder in 'master'?)

                # IF treemachine throws an error, return error info as '500 Internal Server Error'

        if resource_id < 0 : raise HTTP(400, 'invalid resource_id: must be a postive integer')

        author_name  = kwargs.get('author_name','')
        author_email = kwargs.get('author_email','')
        # this is the GitHub API auth-token for a logged-in curator
        auth_token   = kwargs.get('auth_token','')

        if not auth_token:
            raise HTTP(400,"You must authenticate to before updating via the OTOL API")

        # Connect to the Github v3 API via with this OAuth token
        gh = Github(oauth_token)

        try:
            nexson        = json.loads( kwargs.get('nexson','{}') )
        except:
            raise HTTP(400, 'NexSON must be valid JSON')

        # sort the keys of the POSTed NexSON and indent 4 spaces
        nexson = json.dumps(nexson, sort_keys=True, indent=4)

        _update_treenexus()

        # We compare sha1's instead of the actual data to reduce memory use
        # when comparing large studies
        posted_nexson_sha1 = hashlib.sha1(nexson).hexdigest()
        nexson_sha1        = hashlib.sha1( _get_nexson(resource_id, auth_token) ).hexdigest()

        # the POSTed data is the same as what we have on disk, do nothing and return successfully
        if posted_nexson_sha1 == nexson_sha1:
            return { error: 0, description: "success" };
        else:
            # we have new data
            # TODO: Use http://jacquev6.github.io/PyGithub/github_objects/Repository.html#github.Repository.Repository.create_git_commit
            return dict()
    return locals()

def _update_treenexus():
    """Update the treenexus git submodule"""
    # submodule update must be run from the top-level dir of our repo
    rc = os.system("cd ..; git submodule update")
    if rc:
        raise HTTP(400,"Unable to update local treenexus.git")

<|endoftext|>


<commit_before># encoding: utf-8
from okscraper_django.management.base_commands import NoArgsDbLogCommand
from optparse import make_option
import sys
import csv
from datetime import datetime
from committees.models import Committee
from mks.models import Member, Knesset

class Command(NoArgsDbLogCommand):
    help = "Get committees data in csv format"

    option_list = NoArgsDbLogCommand.option_list + (
        make_option('--members-attendance', dest='membersattendance', default=False, action='store_true',
                    help='get members attendance data'),
        make_option('--from-date', dest='fromdate', default='', type=str,
                    help='get data from the given date (yyyy-mm-dd)'),
        make_option('--output-file', dest='outputfile', default='', type=str,
                    help='the output file name')
    )

    def _handle_members_attendance(self, fromdate):
        committees = Committee.objects.exclude(type='plenum').exclude(hide=True)
        since_title = fromdate.strftime('%d/%m/%Y') if fromdate else u'תחילת כנסת נוכחית'
        self.csvwriter.writerow(
            [u'ועדה'.encode('utf-8'), u'ח"כ'.encode('utf-8'), (u'אחוז נוכחות מ%s' % since_title).encode('utf-8')])
        member_ids = Member.objects.filter(current_party__knesset=Knesset.objects.current_knesset()).values_list('pk',
                                                                                flat=True)
        for committee in committees:
            self._log_debug('processing committee %s' % committee.pk)
            members = committee.members_by_presence(ids=member_ids, from_date=fromdate)
            for member in members:
                self.csvwriter.writerow(
                    [committee.name.encode('utf-8'), member.name.encode('utf-8'), member.meetings_percentage])

    def _handle_noargs(self, **options):
        if options.get('outputfile', '') == '':
            out = sys.stdout
        else:
            out = open(options['outputfile'], 'wb')
        self.csvwriter = csv.writer(out)
        if options.get('membersattendance'):
            fromdate = options.get('fromdate')
            if fromdate != '':
                fromdate = datetime.strptime(fromdate, '%Y-%m-%d').date()
            else:
                fromdate = None
            self._handle_members_attendance(fromdate)
        else:
            raise Exception('invalid args')
<commit_msg>delete get_committees_data management command - moved to knesset_data<commit_after><|endoftext|>


<commit_before>import base64
import json
import logging
import re
import urllib

import tornado.auth
import tornado.escape
import tornado.web

from base import BaseHandler
from logic import content_remote

# This monkeypatches tornado to do sync instead of async
class TwitterHandler(BaseHandler,
                     tornado.auth.TwitterMixin):
  def get(self):
    if not self.authenticate(author=True):
      return

    if self.get_argument("get_feed", None):
      self.user = self.get_author_user()
      access_token = json.loads(self.user.twitter)
      self.twitter_request(
            "/statuses/home_timeline",
            self.timeline_result,
            access_token=access_token)
      return
    elif self.get_argument("oauth_token", None):
      self.get_sync_authenticated_user(self._on_auth)
      return
    self.authorize_redirect()

  def timeline_result(self, tweets):
    for tweet in tweets:
      exists = self.models.content_remote.get(to_username=self.user.username, post_id=tweet['id'])[0]

      if exists:
        continue
      else:
        new_entry = self.models.content_remote()

      new_entry.to_username = self.user.username
      new_entry.username = entry['screen_name']
      new_entry.from_user = 'http://twitter.com/' + entry['screen_name']
      new_entry.avatar = entry['profile_image_url']

      parsed_date = re.compile(r'\+.....').sub('', entry['created_at'])
      parsed_date = datetime.datetime.strptime(parsed_date, '%a %b %d %H:%M:%S %Y')

      # we don't keep items that are over 30 days old
      if parsed_date < datetime.datetime.utcnow() - datetime.timedelta(days=max_days_old):
        continue

      new_entry.date_created = parsed_date
      new_entry.date_updated = None
      new_entry.comments_count = 0
      new_entry.comments_updated = None
      new_entry.type = 'twitter'
      new_entry.title = ''
      new_entry.post_id = entry['id']
      new_entry.link = 'http://twitter.com/' + entry['screen_name'] + '/status/' + entry['id']
      new_entry.view = entry['text']
      new_entry.save()

    count = self.models.content_remote.get(to_username=user.username, type='twitter', deleted=False).count()
    json = json.dumps({ 'count': count })
    self.write(json)

  def twitter_request(self, path, callback, access_token=None,
                      post_args=None, **args):
    """Fetches the given API path, e.g., "/statuses/user_timeline/btaylor"

    The path should not include the format (we automatically append
    ".json" and parse the JSON output).

    If the request is a POST, post_args should be provided. Query
    string arguments should be given as keyword arguments.

    All the Twitter methods are documented at
    http://apiwiki.twitter.com/Twitter-API-Documentation.

    Many methods require an OAuth access token which you can obtain
    through authorize_redirect() and get_authenticated_user(). The
    user returned through that process includes an 'access_token'
    attribute that can be used to make authenticated requests via
    this method. Example usage::

        class MainHandler(tornado.web.RequestHandler,
                          tornado.auth.TwitterMixin):
            @tornado.web.authenticated
            @tornado.web.asynchronous
            def get(self):
                self.twitter_request(
                    "/statuses/update",
                    post_args={"status": "Testing Tornado Web Server"},
                    access_token=user["access_token"],
                    callback=self.async_callback(self._on_post))

            def _on_post(self, new_entry):
                if not new_entry:
                    # Call failed; perhaps missing permission?
                    self.authorize_redirect()
                    return
                self.finish("Posted a message!")

    """
    if path.startswith('http:') or path.startswith('https:'):
      # Raw urls are useful for e.g. search which doesn't follow the
      # usual pattern: http://search.twitter.com/search.json
      url = path
    else:
      url = "http://api.twitter.com/1" + path + ".json"
    # Add the OAuth resource request signature if we have credentials
    if access_token:
      all_args = {}
      all_args.update(args)
      all_args.update(post_args or {})
      method = "POST" if post_args is not None else "GET"
      oauth = self._oauth_request_parameters(
          url, access_token, all_args, method=method)
      args.update(oauth)
    if args:
      url += "?" + urllib.urlencode(args)

    response = content_remote.get_url(url, post=(post_args is not None))
    self._on_twitter_request(callback, response)

  def authorize_redirect(self, callback_uri=None, extra_params=None,
                         http_client=None):
    """Redirects the user to obtain OAuth authorization for this service.

    Twitter and FriendFeed both require that you register a Callback
    URL with your application. You should call this method to log the
    user in, and then call get_authenticated_user() in the handler
    you registered as your Callback URL to complete the authorization
    process.

    This method sets a cookie called _oauth_request_token which is
    subsequently used (and cleared) in get_authenticated_user for
    security purposes.
    """
    if callback_uri and getattr(self, "_OAUTH_NO_CALLBACKS", False):
      raise Exception("This service does not support oauth_callback")

    if getattr(self, "_OAUTH_VERSION", "1.0a") == "1.0a":
      response = content_remote.get_url(self._oauth_request_token_url(callback_uri=callback_uri, extra_params=extra_params))
      self._on_request_token(self._OAUTH_AUTHORIZE_URL, callback_uri, response)
    else:
      response = content_remote.get_url(self._oauth_request_token_url())
      self._on_request_token(self._OAUTH_AUTHORIZE_URL, callback_uri, response)

  def get_sync_authenticated_user(self, callback, http_client=None):
    """Gets the OAuth authorized user and access token on callback.

    This method should be called from the handler for your registered
    OAuth Callback URL to complete the registration process. We call
    callback with the authenticated user, which in addition to standard
    attributes like 'name' includes the 'access_key' attribute, which
    contains the OAuth access you can use to make authorized requests
    to this service on behalf of the user.

    """
    request_key = tornado.escape.utf8(self.get_argument("oauth_token"))
    oauth_verifier = self.get_argument("oauth_verifier", None)
    request_cookie = self.get_cookie("_oauth_request_token")
    if not request_cookie:
      logging.warning("Missing OAuth request token cookie")
      callback(None)
      return
    self.clear_cookie("_oauth_request_token")
    cookie_key, cookie_secret = [base64.b64decode(tornado.escape.utf8(i)) for i in request_cookie.split("|")]
    if cookie_key != request_key:
      logging.info((cookie_key, request_key, request_cookie))
      logging.warning("Request token does not match cookie")
      callback(None)
      return
    token = dict(key=cookie_key, secret=cookie_secret)
    if oauth_verifier:
      token["verifier"] = oauth_verifier

    response = content_remote.get_url(self._oauth_access_token_url(token))
    self._on_access_token(callback, response)

  def _on_access_token(self, callback, response):
    if response.error:
      logging.warning("Could not fetch access token")
      callback(None)
      return

    access_token = tornado.auth._oauth_parse_response(response.body)
    callback(access_token)

  def _on_auth(self, access_token):
    if not access_token:
      raise tornado.web.HTTPError(500, "Twitter auth failed")

    user = self.get_author_user()
    user.twitter = json.dumps(access_token)
    user.save()

    self.redirect(self.nav_url(section='dashboard'))
<commit_msg>twitter read<commit_after>import base64
import json
import logging
import re
import urllib

import tornado.auth
import tornado.escape
import tornado.web

from base import BaseHandler
from logic import content_remote

# This monkeypatches tornado to do sync instead of async
class TwitterHandler(BaseHandler,
                     tornado.auth.TwitterMixin):
  def get(self):
    if not self.authenticate(author=True):
      return

    if self.get_argument("get_feed", None):
      self.user = self.get_author_user()
      access_token = json.loads(self.user.twitter)
      self.twitter_request(
            "/statuses/home_timeline",
            self.timeline_result,
            access_token=access_token)
      return
    elif self.get_argument("oauth_token", None):
      self.get_sync_authenticated_user(self._on_auth)
      return
    self.authorize_redirect()

  def timeline_result(self, tweets):
    for tweet in tweets:
      exists = self.models.content_remote.get(to_username=self.user.username, post_id=tweet['id'])[0]

      if exists:
        continue
      else:
        new_tweet = self.models.content_remote()

      new_tweet.to_username = self.user.username
      new_tweet.username = tweet['screen_name']
      new_tweet.from_user = 'http://twitter.com/' + tweet['screen_name']
      new_tweet.avatar = tweet['profile_image_url']

      parsed_date = re.compile(r'\+.....').sub('', tweet['created_at'])
      parsed_date = datetime.datetime.strptime(parsed_date, '%a %b %d %H:%M:%S %Y')

      # we don't keep items that are over 30 days old
      if parsed_date < datetime.datetime.utcnow() - datetime.timedelta(days=max_days_old):
        continue

      new_tweet.date_created = parsed_date
      new_tweet.date_updated = None
      new_tweet.comments_count = 0
      new_tweet.comments_updated = None
      new_tweet.type = 'twitter'
      new_tweet.title = ''
      new_tweet.post_id = tweet['id']
      new_tweet.link = 'http://twitter.com/' + tweet['screen_name'] + '/status/' + tweet['id']
      new_tweet.view = tweet['text']
      new_tweet.save()

    count = self.models.content_remote.get(to_username=user.username, type='twitter', deleted=False).count()
    json = json.dumps({ 'count': count })
    self.write(json)

  def twitter_request(self, path, callback, access_token=None,
                      post_args=None, **args):
    """Fetches the given API path, e.g., "/statuses/user_timeline/btaylor"

    The path should not include the format (we automatically append
    ".json" and parse the JSON output).

    If the request is a POST, post_args should be provided. Query
    string arguments should be given as keyword arguments.

    All the Twitter methods are documented at
    http://apiwiki.twitter.com/Twitter-API-Documentation.

    Many methods require an OAuth access token which you can obtain
    through authorize_redirect() and get_authenticated_user(). The
    user returned through that process includes an 'access_token'
    attribute that can be used to make authenticated requests via
    this method. Example usage::

        class MainHandler(tornado.web.RequestHandler,
                          tornado.auth.TwitterMixin):
            @tornado.web.authenticated
            @tornado.web.asynchronous
            def get(self):
                self.twitter_request(
                    "/statuses/update",
                    post_args={"status": "Testing Tornado Web Server"},
                    access_token=user["access_token"],
                    callback=self.async_callback(self._on_post))

            def _on_post(self, new_entry):
                if not new_entry:
                    # Call failed; perhaps missing permission?
                    self.authorize_redirect()
                    return
                self.finish("Posted a message!")

    """
    if path.startswith('http:') or path.startswith('https:'):
      # Raw urls are useful for e.g. search which doesn't follow the
      # usual pattern: http://search.twitter.com/search.json
      url = path
    else:
      url = "http://api.twitter.com/1" + path + ".json"
    # Add the OAuth resource request signature if we have credentials
    if access_token:
      all_args = {}
      all_args.update(args)
      all_args.update(post_args or {})
      method = "POST" if post_args is not None else "GET"
      oauth = self._oauth_request_parameters(
          url, access_token, all_args, method=method)
      args.update(oauth)
    if args:
      url += "?" + urllib.urlencode(args)

    response = content_remote.get_url(url, post=(post_args is not None))
    self._on_twitter_request(callback, response)

  def authorize_redirect(self, callback_uri=None, extra_params=None,
                         http_client=None):
    """Redirects the user to obtain OAuth authorization for this service.

    Twitter and FriendFeed both require that you register a Callback
    URL with your application. You should call this method to log the
    user in, and then call get_authenticated_user() in the handler
    you registered as your Callback URL to complete the authorization
    process.

    This method sets a cookie called _oauth_request_token which is
    subsequently used (and cleared) in get_authenticated_user for
    security purposes.
    """
    if callback_uri and getattr(self, "_OAUTH_NO_CALLBACKS", False):
      raise Exception("This service does not support oauth_callback")

    if getattr(self, "_OAUTH_VERSION", "1.0a") == "1.0a":
      response = content_remote.get_url(self._oauth_request_token_url(callback_uri=callback_uri, extra_params=extra_params))
      self._on_request_token(self._OAUTH_AUTHORIZE_URL, callback_uri, response)
    else:
      response = content_remote.get_url(self._oauth_request_token_url())
      self._on_request_token(self._OAUTH_AUTHORIZE_URL, callback_uri, response)

  def get_sync_authenticated_user(self, callback, http_client=None):
    """Gets the OAuth authorized user and access token on callback.

    This method should be called from the handler for your registered
    OAuth Callback URL to complete the registration process. We call
    callback with the authenticated user, which in addition to standard
    attributes like 'name' includes the 'access_key' attribute, which
    contains the OAuth access you can use to make authorized requests
    to this service on behalf of the user.

    """
    request_key = tornado.escape.utf8(self.get_argument("oauth_token"))
    oauth_verifier = self.get_argument("oauth_verifier", None)
    request_cookie = self.get_cookie("_oauth_request_token")
    if not request_cookie:
      logging.warning("Missing OAuth request token cookie")
      callback(None)
      return
    self.clear_cookie("_oauth_request_token")
    cookie_key, cookie_secret = [base64.b64decode(tornado.escape.utf8(i)) for i in request_cookie.split("|")]
    if cookie_key != request_key:
      logging.info((cookie_key, request_key, request_cookie))
      logging.warning("Request token does not match cookie")
      callback(None)
      return
    token = dict(key=cookie_key, secret=cookie_secret)
    if oauth_verifier:
      token["verifier"] = oauth_verifier

    response = content_remote.get_url(self._oauth_access_token_url(token))
    self._on_access_token(callback, response)

  def _on_access_token(self, callback, response):
    if response.error:
      logging.warning("Could not fetch access token")
      callback(None)
      return

    access_token = tornado.auth._oauth_parse_response(response.body)
    callback(access_token)

  def _on_auth(self, access_token):
    if not access_token:
      raise tornado.web.HTTPError(500, "Twitter auth failed")

    user = self.get_author_user()
    user.twitter = json.dumps(access_token)
    user.save()

    self.redirect(self.nav_url(section='dashboard'))
<|endoftext|>