<commit_before>"""
remotes.py

The client and web server needed to control a car remotely.
"""

import time
from datetime import datetime
import json
import io
import os
import copy
import math
from threading import Thread
import numpy as np

import requests
import tornado.gen
import tornado.ioloop
import tornado.web

from PIL import Image

import donkey as dk

class RemoteClient():
    '''
    Class used by a vehicle to send (http post requests) driving data and
    recieve predictions from a remote webserver.
    '''

    def __init__(self, remote_url, vehicle_id='mycar'):

        self.control_url = remote_url + '/api/vehicles/control/' + vehicle_id + '/'
        self.last_milliseconds = 0
        self.session = requests.Session()

        self.log('time,lag\n', write_method='w')

        #initialize state variables (used for threading)
        state = {'img_arr': np.zeros(shape=(120,160)),
                 'angle': 0.0,
                 'throttle': 0.0,
                 'milliseconds': 0,
                 'drive_mode': 'user'}

        self.state = state
        self.start()

    def log(self, line, path='lag_log.csv', write_method='a'):
        with open('lag_log.csv', write_method) as f:
            f.write(line)

    def start(self):
        # start the thread send images to and updates from remote
        t = Thread(target=self.update, args=())
        t.daemon = True
        t.start()
        return self

    def update(self):
        '''
        Loop run in separate thread to request input from remote server.

        TODO: show the lag from the server to allow for safety stops, if
        running local pilot.
        '''

        while True:
            #get latest value from server
            resp  = self.decide(self.state['img_arr'],
                                self.state['angle'],
                                self.state['throttle'],
                                self.state['milliseconds'],)
            angle, throttle, drive_mode = resp

            #update sate with current values
            self.state['angle'] = angle
            self.state['throttle'] = throttle
            self.state['drive_mode'] = drive_mode
            time.sleep(.02)

    def decide_threaded(self, img_arr, angle, throttle, milliseconds):
        '''
        Return the last state given from the remote server.
        '''
        #update the state's image
        self.state['img_arr'] = img_arr

        #return last returned last remote response.
        return self.state['angle'], self.state['throttle'], self.state['drive_mode']

    def decide(self, img_arr, angle, throttle, milliseconds):
        '''
        Posts current car sensor data to webserver and returns
        angle and throttle recommendations.
        '''

        #load features
        data = {
                'angle': str(angle),
                'throttle': str(throttle),
                'milliseconds': str(milliseconds)
                }

        r = None
        while r == None:
            #Try connecting to server until connection is made.
            start = time.time()

            try:
                r = self.session.post(self.control_url,
                                files={'img': dk.utils.arr_to_binary(img_arr),
                                       'json': json.dumps(data)},
                                       timeout=0.25)

            except (requests.ConnectionError) as err:
                #try to reconnect every 3 seconds
                print("\n Vehicle could not connect to server. Make sure you've " +
                    "started your server and you're referencing the right port.")
                time.sleep(3)

            except (requests.exceptions.ReadTimeout) as err:
                #Lower throttle if their is a long lag.
                print("\n Request took too long. Retrying")
                return angle, throttle * .8, None

        end = time.time()
        lag = end-start
        self.log('{}, {} \n'.format(datetime.now().time() , lag ))
        #print('remote lag: %s' %lag)

        data = json.loads(r.text)
        angle = float(data['angle'])
        throttle = float(data['throttle'])
        drive_mode = str(data['drive_mode'])

        return angle, throttle, drive_mode

class DonkeyPilotApplication(tornado.web.Application):

    def __init__(self, mydonkey_path='~/mydonkey/'):
        '''
        Create and publish variables needed on many of
        the web handlers.
        '''

        print('hello')
        if not os.path.exists(os.path.expanduser(mydonkey_path)):
            raise ValueError('Could not find mydonkey folder. Please run "python scripts/setup.py"')

        self.vehicles = {}

        this_dir = os.path.dirname(os.path.realpath(__file__))
        self.static_file_path = os.path.join(this_dir, 'templates', 'static')

        self.mydonkey_path = os.path.expanduser(mydonkey_path)
        self.sessions_path = os.path.join(self.mydonkey_path, 'sessions')
        self.models_path = os.path.join(self.mydonkey_path, 'models')

        ph = dk.pilots.PilotHandler(self.models_path)
        self.pilots = ph.default_pilots()

        handlers = [

            #temporary redirect until vehicles is not a singleton
            (r"/", HomeView),

            (r"/vehicles/", VehicleListView),

            (r"/vehicles/?(?P<vehicle_id>[A-Za-z0-9-]+)?/",
                VehicleView),

            (r"/api/vehicles/?(?P<vehicle_id>[A-Za-z0-9-]+)?/",
                VehicleAPI),

            (r"/api/vehicles/drive/?(?P<vehicle_id>[A-Za-z0-9-]+)?/",
                DriveAPI),

            (r"/api/vehicles/video/?(?P<vehicle_id>[A-Za-z0-9-]+)?",
                VideoAPI
            ),

            (r"/api/vehicles/control/?(?P<vehicle_id>[A-Za-z0-9-]+)?/",
                ControlAPI),

            (r"/sessions/", SessionListView),

            (r"/sessions/?(?P<session_id>[^/]+)?/?(?P<page>[^/]+)?",
                SessionView),

            (r"/session_image/?(?P<session_id>[^/]+)?/?(?P<img_name>[^/]+)?",
                SessionImageView
            ),

            (r"/pilots/", PilotListView),

            (r"/static/(.*)", tornado.web.StaticFileHandler, {"path": self.static_file_path}),

            ]

        settings = {'debug': True}

        super().__init__(handlers, **settings)

    def start(self, port=8887):
        ''' Start the tornado webserver. '''
        print(port)
        self.port = int(port)
        self.listen(self.port)
        tornado.ioloop.IOLoop.instance().start()

    def get_vehicle(self, vehicle_id):
        ''' Returns vehicle if it exists or creates a new one '''

        if vehicle_id not in self.vehicles:
            print('new vehicle')
            sh = dk.sessions.SessionHandler(self.sessions_path)
            self.vehicles[vehicle_id] = dict({
                        'id': vehicle_id,
                        'user_angle': 0,
                        'user_throttle': 0,
                        'drive_mode':'user',
                        'milliseconds': 0,
                        'recording': False,
                        'pilot': dk.pilots.BasePilot(),
                        'session': sh.new()})

        #eprint(self.vehicles)
        return self.vehicles[vehicle_id]

#####################
#                   #
#      vehicles     #
#                   #
#####################

class HomeView(tornado.web.RequestHandler):
    def get(self):
        self.render("templates/home.html")

class VehicleListView(tornado.web.RequestHandler):
    def get(self):
        '''
        Serves a list of the vehicles posting requests to the server.
        '''
        data = {'vehicles':self.application.vehicles}

        self.render("templates/vehicle_list.html", **data)

class VehicleView(tornado.web.RequestHandler):
    def get(self, vehicle_id):
        '''
        Serves page for users to control the vehicle.
        '''

        V = self.application.get_vehicle(vehicle_id)
        pilots = self.application.pilots
        data = {'vehicle': V, 'pilots': pilots}
        self.render("templates/vehicle.html", **data)

class VehicleAPI(tornado.web.RequestHandler):

    def post(self, vehicle_id):
        '''
        Currently this only changes the pilot.
        '''

        V = self.application.get_vehicle(vehicle_id)

        data = tornado.escape.json_decode(self.request.body)
        print('pilot request')
        print(data)
        pilot = next(filter(lambda p: p.name == data['pilot'], self.application.pilots))
        pilot.load()
        V['pilot'] = pilot

class DriveAPI(tornado.web.RequestHandler):

    def post(self, vehicle_id):
        '''
        Receive post requests as user changes the angle
        and throttle of the vehicle on a the index webpage
        '''

        V = self.application.get_vehicle(vehicle_id)

        data = tornado.escape.json_decode(self.request.body)
        angle = data['angle']
        throttle = data['throttle']

        #set if vehicle is recording
        V['recording'] = data['recording']

        #update vehicle angel based on drive mode
        V['drive_mode'] = data['drive_mode']

        if angle is not "":
            V['user_angle'] = angle
        else:
            V['user_angle'] = 0

        if throttle is not "":
            V['user_throttle'] = throttle
        else:
            V['user_throttle'] = 0

class ControlAPI(tornado.web.RequestHandler):

    def post(self, vehicle_id):
        '''
        Receive post requests from a vehicle and returns
        the angle and throttle the car should use. Depending on
        the drive mode the values can come from the user or
        an autopilot.
        '''

        V = self.application.get_vehicle(vehicle_id)

        img = self.request.files['img'][0]['body']
        img = Image.open(io.BytesIO(img))
        img_arr = dk.utils.img_to_arr(img)

        #Get angle/throttle from pilot loaded by the server.
        if V['pilot'] is not None:
            pilot_angle, pilot_throttle = V['pilot'].decide(img_arr)
        else:
            print('no pilot')
            pilot_angle, pilot_throttle = 0.0, 0.0

        V['img'] = img
        V['pilot_angle'] = pilot_angle
        V['pilot_throttle'] = pilot_throttle

        #depending on the drive mode, return user or pilot values

        angle, throttle  = V['user_angle'], V['user_throttle']
        if V['drive_mode'] == 'auto_angle':
            angle, throttle  = V['pilot_angle'], V['user_throttle']
        elif V['drive_mode'] == 'auto':
            angle, throttle  = V['pilot_angle'], V['pilot_throttle']

        print('\r REMOTE: angle: {:+04.2f}   throttle: {:+04.2f}   drive_mode: {}'.format(angle, throttle, V['drive_mode']), end='')

        if V['recording'] == True:
            #save image with encoded angle/throttle values
            V['session'].put(img,
                             angle=angle,
                             throttle=throttle,
                             milliseconds=0.0)

        #retun angel/throttle values to vehicle with json response
        self.write(json.dumps({'angle': str(angle), 'throttle': str(throttle), 'drive_mode': str(V['drive_mode']) }))

class VideoAPI(tornado.web.RequestHandler):
    '''
    Serves a MJPEG of the images posted from the vehicle.
    '''
    @tornado.web.asynchronous
    @tornado.gen.coroutine
    def get(self, vehicle_id):

        ioloop = tornado.ioloop.IOLoop.current()
        self.set_header("Content-type", "multipart/x-mixed-replace;boundary=--boundarydonotcross")

        self.served_image_timestamp = time.time()
        my_boundary = "--boundarydonotcross"
        while True:

            interval = .2
            if self.served_image_timestamp + interval < time.time():

                img = self.application.vehicles[vehicle_id]['img']
                img = dk.utils.img_to_binary(img)

                self.write(my_boundary)
                self.write("Content-type: image/jpeg\r\n")
                self.write("Content-length: %s\r\n\r\n" % len(img))
                self.write(img)
                self.served_image_timestamp = time.time()
                yield tornado.gen.Task(self.flush)
            else:
                yield tornado.gen.Task(ioloop.add_timeout, ioloop.time() + interval)

#####################
#                   #
#      pilots       #
#                   #
#####################

class PilotListView(tornado.web.RequestHandler):
    def get(self):
        '''
        Render a list of pilots.
        '''
        ph = dk.pilots.PilotHandler(self.application.models_path)
        pilots = ph.default_pilots()
        data = {'pilots': pilots}
        self.render("templates/pilots_list.html", **data)

#####################
#                   #
#     sessions      #
#                   #
#####################

class SessionImageView(tornado.web.RequestHandler):
    def get(self, session_id, img_name):
        ''' Returns jpg images from a session folder '''

        sessions_path = self.application.sessions_path
        path = os.path.join(sessions_path, session_id, img_name)
        f = Image.open(path)
        o = io.BytesIO()
        f.save(o, format="JPEG")
        s = o.getvalue()

        self.set_header('Content-type', 'image/jpg')
        self.set_header('Content-length', len(s))

        self.write(s)

class SessionListView(tornado.web.RequestHandler):

    def get(self):
        '''
        Serves a page showing a list of all the session folders.
        TODO: Move this list creation to the session handler.
        '''

        session_dirs = [f for f in os.scandir(self.application.sessions_path) if f.is_dir() ]
        data = {'session_dirs': session_dirs}
        self.render("templates/session_list.html", **data)

class SessionView(tornado.web.RequestHandler):

    def get(self, session_id, page):
        '''
        Shows all the images saved in the session.
        TODO: Add pagination.
        '''
        from operator import itemgetter

        sessions_path = self.application.sessions_path
        path = os.path.join(sessions_path, session_id)
        imgs = [dk.utils.merge_two_dicts({'name':f.name}, dk.sessions.parse_img_filepath(f.path)) for f in os.scandir(path) if f.is_file() ]
        img_count = len(imgs)

        perpage = 500
        pages = math.ceil(img_count/perpage)
        if page is None:
            page = 1
        else:
            page = int(page)
        end = page * perpage
        start = end - perpage
        end = min(end, img_count)

        sorted_imgs = sorted(imgs, key=itemgetter('name'))
        page_list = [p+1 for p in range(pages)]
        session = {'name':session_id, 'imgs': sorted_imgs[start:end]}
        data = {'session': session, 'page_list': page_list, 'this_page':page}
        self.render("templates/session.html", **data)

    def post(self, session_id, page):
        '''
        Deletes selected images
        TODO: move this to an api cal. Page is not needed.
        '''

        data = tornado.escape.json_decode(self.request.body)

        if data['action'] == 'delete_images':
            sessions_path = self.application.sessions_path
            path = os.path.join(sessions_path, session_id)

            for i in data['imgs']:
                os.remove(os.path.join(path, i))
                print('%s removed' %i)

<commit_msg>Wrong module for requests.ReadTimeout?<commit_after>"""
remotes.py

The client and web server needed to control a car remotely.
"""

import time
from datetime import datetime
import json
import io
import os
import copy
import math
from threading import Thread
import numpy as np

import requests
import tornado.gen
import tornado.ioloop
import tornado.web

from PIL import Image

import donkey as dk

class RemoteClient():
    '''
    Class used by a vehicle to send (http post requests) driving data and
    recieve predictions from a remote webserver.
    '''

    def __init__(self, remote_url, vehicle_id='mycar'):

        self.control_url = remote_url + '/api/vehicles/control/' + vehicle_id + '/'
        self.last_milliseconds = 0
        self.session = requests.Session()

        self.log('time,lag\n', write_method='w')

        #initialize state variables (used for threading)
        state = {'img_arr': np.zeros(shape=(120,160)),
                 'angle': 0.0,
                 'throttle': 0.0,
                 'milliseconds': 0,
                 'drive_mode': 'user'}

        self.state = state
        self.start()

    def log(self, line, path='lag_log.csv', write_method='a'):
        with open('lag_log.csv', write_method) as f:
            f.write(line)

    def start(self):
        # start the thread send images to and updates from remote
        t = Thread(target=self.update, args=())
        t.daemon = True
        t.start()
        return self

    def update(self):
        '''
        Loop run in separate thread to request input from remote server.

        TODO: show the lag from the server to allow for safety stops, if
        running local pilot.
        '''

        while True:
            #get latest value from server
            resp  = self.decide(self.state['img_arr'],
                                self.state['angle'],
                                self.state['throttle'],
                                self.state['milliseconds'],)
            angle, throttle, drive_mode = resp

            #update sate with current values
            self.state['angle'] = angle
            self.state['throttle'] = throttle
            self.state['drive_mode'] = drive_mode
            time.sleep(.02)

    def decide_threaded(self, img_arr, angle, throttle, milliseconds):
        '''
        Return the last state given from the remote server.
        '''
        #update the state's image
        self.state['img_arr'] = img_arr

        #return last returned last remote response.
        return self.state['angle'], self.state['throttle'], self.state['drive_mode']

    def decide(self, img_arr, angle, throttle, milliseconds):
        '''
        Posts current car sensor data to webserver and returns
        angle and throttle recommendations.
        '''

        #load features
        data = {
                'angle': str(angle),
                'throttle': str(throttle),
                'milliseconds': str(milliseconds)
                }

        r = None
        while r == None:
            #Try connecting to server until connection is made.
            start = time.time()

            try:
                r = self.session.post(self.control_url,
                                files={'img': dk.utils.arr_to_binary(img_arr),
                                       'json': json.dumps(data)},
                                       timeout=0.25)

            except (requests.ConnectionError) as err:
                #try to reconnect every 3 seconds
                print("\n Vehicle could not connect to server. Make sure you've " +
                    "started your server and you're referencing the right port.")
                time.sleep(3)

            except (requests.ReadTimeout) as err:
                #Lower throttle if their is a long lag.
                print("\n Request took too long. Retrying")
                return angle, throttle * .8, None

        end = time.time()
        lag = end-start
        self.log('{}, {} \n'.format(datetime.now().time() , lag ))
        #print('remote lag: %s' %lag)

        data = json.loads(r.text)
        angle = float(data['angle'])
        throttle = float(data['throttle'])
        drive_mode = str(data['drive_mode'])

        return angle, throttle, drive_mode

class DonkeyPilotApplication(tornado.web.Application):

    def __init__(self, mydonkey_path='~/mydonkey/'):
        '''
        Create and publish variables needed on many of
        the web handlers.
        '''

        print('hello')
        if not os.path.exists(os.path.expanduser(mydonkey_path)):
            raise ValueError('Could not find mydonkey folder. Please run "python scripts/setup.py"')

        self.vehicles = {}

        this_dir = os.path.dirname(os.path.realpath(__file__))
        self.static_file_path = os.path.join(this_dir, 'templates', 'static')

        self.mydonkey_path = os.path.expanduser(mydonkey_path)
        self.sessions_path = os.path.join(self.mydonkey_path, 'sessions')
        self.models_path = os.path.join(self.mydonkey_path, 'models')

        ph = dk.pilots.PilotHandler(self.models_path)
        self.pilots = ph.default_pilots()

        handlers = [

            #temporary redirect until vehicles is not a singleton
            (r"/", HomeView),

            (r"/vehicles/", VehicleListView),

            (r"/vehicles/?(?P<vehicle_id>[A-Za-z0-9-]+)?/",
                VehicleView),

            (r"/api/vehicles/?(?P<vehicle_id>[A-Za-z0-9-]+)?/",
                VehicleAPI),

            (r"/api/vehicles/drive/?(?P<vehicle_id>[A-Za-z0-9-]+)?/",
                DriveAPI),

            (r"/api/vehicles/video/?(?P<vehicle_id>[A-Za-z0-9-]+)?",
                VideoAPI
            ),

            (r"/api/vehicles/control/?(?P<vehicle_id>[A-Za-z0-9-]+)?/",
                ControlAPI),

            (r"/sessions/", SessionListView),

            (r"/sessions/?(?P<session_id>[^/]+)?/?(?P<page>[^/]+)?",
                SessionView),

            (r"/session_image/?(?P<session_id>[^/]+)?/?(?P<img_name>[^/]+)?",
                SessionImageView
            ),

            (r"/pilots/", PilotListView),

            (r"/static/(.*)", tornado.web.StaticFileHandler, {"path": self.static_file_path}),

            ]

        settings = {'debug': True}

        super().__init__(handlers, **settings)

    def start(self, port=8887):
        ''' Start the tornado webserver. '''
        print(port)
        self.port = int(port)
        self.listen(self.port)
        tornado.ioloop.IOLoop.instance().start()

    def get_vehicle(self, vehicle_id):
        ''' Returns vehicle if it exists or creates a new one '''

        if vehicle_id not in self.vehicles:
            print('new vehicle')
            sh = dk.sessions.SessionHandler(self.sessions_path)
            self.vehicles[vehicle_id] = dict({
                        'id': vehicle_id,
                        'user_angle': 0,
                        'user_throttle': 0,
                        'drive_mode':'user',
                        'milliseconds': 0,
                        'recording': False,
                        'pilot': dk.pilots.BasePilot(),
                        'session': sh.new()})

        #eprint(self.vehicles)
        return self.vehicles[vehicle_id]

#####################
#                   #
#      vehicles     #
#                   #
#####################

class HomeView(tornado.web.RequestHandler):
    def get(self):
        self.render("templates/home.html")

class VehicleListView(tornado.web.RequestHandler):
    def get(self):
        '''
        Serves a list of the vehicles posting requests to the server.
        '''
        data = {'vehicles':self.application.vehicles}

        self.render("templates/vehicle_list.html", **data)

class VehicleView(tornado.web.RequestHandler):
    def get(self, vehicle_id):
        '''
        Serves page for users to control the vehicle.
        '''

        V = self.application.get_vehicle(vehicle_id)
        pilots = self.application.pilots
        data = {'vehicle': V, 'pilots': pilots}
        self.render("templates/vehicle.html", **data)

class VehicleAPI(tornado.web.RequestHandler):

    def post(self, vehicle_id):
        '''
        Currently this only changes the pilot.
        '''

        V = self.application.get_vehicle(vehicle_id)

        data = tornado.escape.json_decode(self.request.body)
        print('pilot request')
        print(data)
        pilot = next(filter(lambda p: p.name == data['pilot'], self.application.pilots))
        pilot.load()
        V['pilot'] = pilot

class DriveAPI(tornado.web.RequestHandler):

    def post(self, vehicle_id):
        '''
        Receive post requests as user changes the angle
        and throttle of the vehicle on a the index webpage
        '''

        V = self.application.get_vehicle(vehicle_id)

        data = tornado.escape.json_decode(self.request.body)
        angle = data['angle']
        throttle = data['throttle']

        #set if vehicle is recording
        V['recording'] = data['recording']

        #update vehicle angel based on drive mode
        V['drive_mode'] = data['drive_mode']

        if angle is not "":
            V['user_angle'] = angle
        else:
            V['user_angle'] = 0

        if throttle is not "":
            V['user_throttle'] = throttle
        else:
            V['user_throttle'] = 0

class ControlAPI(tornado.web.RequestHandler):

    def post(self, vehicle_id):
        '''
        Receive post requests from a vehicle and returns
        the angle and throttle the car should use. Depending on
        the drive mode the values can come from the user or
        an autopilot.
        '''

        V = self.application.get_vehicle(vehicle_id)

        img = self.request.files['img'][0]['body']
        img = Image.open(io.BytesIO(img))
        img_arr = dk.utils.img_to_arr(img)

        #Get angle/throttle from pilot loaded by the server.
        if V['pilot'] is not None:
            pilot_angle, pilot_throttle = V['pilot'].decide(img_arr)
        else:
            print('no pilot')
            pilot_angle, pilot_throttle = 0.0, 0.0

        V['img'] = img
        V['pilot_angle'] = pilot_angle
        V['pilot_throttle'] = pilot_throttle

        #depending on the drive mode, return user or pilot values

        angle, throttle  = V['user_angle'], V['user_throttle']
        if V['drive_mode'] == 'auto_angle':
            angle, throttle  = V['pilot_angle'], V['user_throttle']
        elif V['drive_mode'] == 'auto':
            angle, throttle  = V['pilot_angle'], V['pilot_throttle']

        print('\r REMOTE: angle: {:+04.2f}   throttle: {:+04.2f}   drive_mode: {}'.format(angle, throttle, V['drive_mode']), end='')

        if V['recording'] == True:
            #save image with encoded angle/throttle values
            V['session'].put(img,
                             angle=angle,
                             throttle=throttle,
                             milliseconds=0.0)

        #retun angel/throttle values to vehicle with json response
        self.write(json.dumps({'angle': str(angle), 'throttle': str(throttle), 'drive_mode': str(V['drive_mode']) }))

class VideoAPI(tornado.web.RequestHandler):
    '''
    Serves a MJPEG of the images posted from the vehicle.
    '''
    @tornado.web.asynchronous
    @tornado.gen.coroutine
    def get(self, vehicle_id):

        ioloop = tornado.ioloop.IOLoop.current()
        self.set_header("Content-type", "multipart/x-mixed-replace;boundary=--boundarydonotcross")

        self.served_image_timestamp = time.time()
        my_boundary = "--boundarydonotcross"
        while True:

            interval = .2
            if self.served_image_timestamp + interval < time.time():

                img = self.application.vehicles[vehicle_id]['img']
                img = dk.utils.img_to_binary(img)

                self.write(my_boundary)
                self.write("Content-type: image/jpeg\r\n")
                self.write("Content-length: %s\r\n\r\n" % len(img))
                self.write(img)
                self.served_image_timestamp = time.time()
                yield tornado.gen.Task(self.flush)
            else:
                yield tornado.gen.Task(ioloop.add_timeout, ioloop.time() + interval)

#####################
#                   #
#      pilots       #
#                   #
#####################

class PilotListView(tornado.web.RequestHandler):
    def get(self):
        '''
        Render a list of pilots.
        '''
        ph = dk.pilots.PilotHandler(self.application.models_path)
        pilots = ph.default_pilots()
        data = {'pilots': pilots}
        self.render("templates/pilots_list.html", **data)

#####################
#                   #
#     sessions      #
#                   #
#####################

class SessionImageView(tornado.web.RequestHandler):
    def get(self, session_id, img_name):
        ''' Returns jpg images from a session folder '''

        sessions_path = self.application.sessions_path
        path = os.path.join(sessions_path, session_id, img_name)
        f = Image.open(path)
        o = io.BytesIO()
        f.save(o, format="JPEG")
        s = o.getvalue()

        self.set_header('Content-type', 'image/jpg')
        self.set_header('Content-length', len(s))

        self.write(s)

class SessionListView(tornado.web.RequestHandler):

    def get(self):
        '''
        Serves a page showing a list of all the session folders.
        TODO: Move this list creation to the session handler.
        '''

        session_dirs = [f for f in os.scandir(self.application.sessions_path) if f.is_dir() ]
        data = {'session_dirs': session_dirs}
        self.render("templates/session_list.html", **data)

class SessionView(tornado.web.RequestHandler):

    def get(self, session_id, page):
        '''
        Shows all the images saved in the session.
        TODO: Add pagination.
        '''
        from operator import itemgetter

        sessions_path = self.application.sessions_path
        path = os.path.join(sessions_path, session_id)
        imgs = [dk.utils.merge_two_dicts({'name':f.name}, dk.sessions.parse_img_filepath(f.path)) for f in os.scandir(path) if f.is_file() ]
        img_count = len(imgs)

        perpage = 500
        pages = math.ceil(img_count/perpage)
        if page is None:
            page = 1
        else:
            page = int(page)
        end = page * perpage
        start = end - perpage
        end = min(end, img_count)

        sorted_imgs = sorted(imgs, key=itemgetter('name'))
        page_list = [p+1 for p in range(pages)]
        session = {'name':session_id, 'imgs': sorted_imgs[start:end]}
        data = {'session': session, 'page_list': page_list, 'this_page':page}
        self.render("templates/session.html", **data)

    def post(self, session_id, page):
        '''
        Deletes selected images
        TODO: move this to an api cal. Page is not needed.
        '''

        data = tornado.escape.json_decode(self.request.body)

        if data['action'] == 'delete_images':
            sessions_path = self.application.sessions_path
            path = os.path.join(sessions_path, session_id)

            for i in data['imgs']:
                os.remove(os.path.join(path, i))
                print('%s removed' %i)

<|endoftext|>


<commit_before>import json
import pkg_resources
import yaml

try:
    from yaml import CLoader as Loader
except ImportError:
    from yaml import Loader

def yml_load(stream, loader=Loader, close=False):
    if isinstance(stream, basestring):
        stream = open(stream)
        close = True
    try:
        return yaml.load_all(stream, loader=Loader)
    finally:
        if close is True:
            stream.close()

def resource_spec(spec):
    """
    Loads resource from a string specifier.

    >>> config.resource_spec('egg:monkeylib#data/languages.ini')
    '.../monkeylib/data/languages.ini'

    >>> config.resource_spec('file:data/languages.ini')
    'data/languages.ini'

    >>> config.resource_spec('data/languages.ini')
    'data/languages.ini'
    """
    filepath = spec
    if spec.startswith('egg:'):
        req, subpath = spec.split('egg:')[1].split('#')
        req = pkg_resources.Requirement.parse(req)
        filepath = res_filename(req, subpath)
    elif spec.startswith('file:'):
        filepath = spec.split('file:')[1]
    # Other specs could be added, but egg and file should be fine for
    # now
    return filepath

def res_stream(req, path):
    return pkg_resources.resource_stream(req, path)

def res_filename(req, path):
    return pkg_resources.resource_filename(req, path)

def res_json(req, path):
    return json.load(res_stream(req, path))
<commit_msg>simplify yml_load<commit_after>import json
import pkg_resources
import yaml

try:
    from yaml import CLoader as Loader
except ImportError:
    from yaml import Loader

def yml_load(stream, loader=Loader):
    return yaml.load_all(stream, loader)

def resource_spec(spec):
    """
    Loads resource from a string specifier.

    >>> config.resource_spec('egg:monkeylib#data/languages.ini')
    '.../monkeylib/data/languages.ini'

    >>> config.resource_spec('file:data/languages.ini')
    'data/languages.ini'

    >>> config.resource_spec('data/languages.ini')
    'data/languages.ini'
    """
    filepath = spec
    if spec.startswith('egg:'):
        req, subpath = spec.split('egg:')[1].split('#')
        req = pkg_resources.Requirement.parse(req)
        filepath = res_filename(req, subpath)
    elif spec.startswith('file:'):
        filepath = spec.split('file:')[1]
    # Other specs could be added, but egg and file should be fine for
    # now
    return filepath

def res_stream(req, path):
    return pkg_resources.resource_stream(req, path)

def res_filename(req, path):
    return pkg_resources.resource_filename(req, path)

def res_json(req, path):
    return json.load(res_stream(req, path))
<|endoftext|>


<commit_before>"""

Updated on 19.12.2009

@author: alen, pinda
Inspired by:
    http://github.com/leah/python-oauth/blob/master/oauth/example/client.py
    http://github.com/facebook/tornado/blob/master/tornado/auth.py
"""
import time
import base64
import urllib
import urllib2

# parse_qsl was moved from the cgi namespace to urlparse in Python2.6.
# this allows backwards compatibility
try:
    from urlparse import parse_qsl
except ImportError:
    from cgi import parse_qsl

from xml.dom import minidom

import oauth2 as oauth
from openid.consumer import consumer as openid
from openid.consumer.discover import DiscoveryFailure
from openid.store.interface import OpenIDStore as OIDStore
from openid.association import Association as OIDAssociation

from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.utils.translation import gettext as _

from django.conf import settings
from django.utils import simplejson

from django.contrib.sites.models import Site

from socialregistration.models import OpenIDStore as OpenIDStoreModel, OpenIDNonce
from urlparse import urlparse

USE_HTTPS = bool(getattr(settings, 'SOCIALREGISTRATION_USE_HTTPS', False))

def _https():
    if USE_HTTPS:
        return 's'
    else:
        return ''

class OpenIDStore(OIDStore):
    max_nonce_age = 6 * 60 * 60

    def storeAssociation(self, server_url, assoc=None):
        stored_assoc = OpenIDStoreModel.objects.create(
            server_url=server_url,
            handle=assoc.handle,
            secret=base64.encodestring(assoc.secret),
            issued=assoc.issued,
            lifetime=assoc.issued,
            assoc_type=assoc.assoc_type
        )

    def getAssociation(self, server_url, handle=None):
        stored_assocs = OpenIDStoreModel.objects.filter(
            server_url=server_url
        )
        if handle:
            stored_assocs = stored_assocs.filter(handle=handle)

        stored_assocs.order_by('-issued')

        if stored_assocs.count() == 0:
            return None

        return_val = None

        for stored_assoc in stored_assocs:
            assoc = OIDAssociation(
                stored_assoc.handle, base64.decodestring(stored_assoc.secret),
                stored_assoc.issued, stored_assoc.lifetime, stored_assoc.assoc_type
            )

            if assoc.getExpiresIn() == 0:
                stored_assoc.delete()
            else:
                if return_val is None:
                    return_val = assoc

        return return_val

    def removeAssociation(self, server_url, handle):
        stored_assocs = OpenIDStoreModel.objects.filter(
            server_url=server_url
        )
        if handle:
            stored_assocs = stored_assocs.filter(handle=handle)

        stored_assocs.delete()

    def useNonce(self, server_url, timestamp, salt):
        try:
            nonce = OpenIDNonce.objects.get(
                server_url=server_url,
                timestamp=timestamp,
                salt=salt
            )
        except OpenIDNonce.DoesNotExist:
            nonce = OpenIDNonce.objects.create(
                server_url=server_url,
                timestamp=timestamp,
                salt=salt
            )
            return True

        return False

class OpenID(object):
    def __init__(self, request, return_to, endpoint):
        """
        @param request: : django.http.HttpRequest object
        @param return_to: URL to redirect back to once the user authenticated
            the application on the OpenID provider
        @param endpoint: URL to the OpenID provider we're connecting to
        """
        self.request = request
        self.return_to = return_to
        self.endpoint = endpoint
        self.store = OpenIDStore()
        self.consumer = openid.Consumer(self.request.session, self.store)
        self.result = None

    def get_redirect(self):
        auth_request = self.consumer.begin(self.endpoint)
        redirect_url = auth_request.redirectURL(
            'http%s://%s/' % (_https(), Site.objects.get_current().domain),
            self.return_to
        )
        return HttpResponseRedirect(redirect_url)

    def complete(self):
        self.result = self.consumer.complete(
            dict(self.request.GET.items()),
            'http%s://%s%s' % (_https(), Site.objects.get_current(),
                self.request.path)
        )

    def is_valid(self):
        if self.result is None:
            self.complete()

        return self.result.status == openid.SUCCESS

def get_token_prefix(url):
    """
    Returns a prefix for the token to store in the session so we can hold
    more than one single oauth provider's access key in the session.

    Example:

        The request token url ``http://twitter.com/oauth/request_token``
        returns ``twitter.com``

    """
    try:
        return urllib2.urlparse.urlparse(url).netloc
    except AttributeError:
        return urllib2.rulparse.urlparse(url)[1]

class OAuthError(Exception):
    pass

class OAuthClient(object):

    def __init__(self, request, consumer_key, consumer_secret, request_token_url,
        access_token_url, authorization_url, callback_url, parameters=None):

        self.request = request

        self.request_token_url = request_token_url
        self.access_token_url = access_token_url
        self.authorization_url = authorization_url

        self.consumer_key = consumer_key
        self.consumer_secret = consumer_secret

        self.consumer = oauth.Consumer(consumer_key, consumer_secret)
        self.client = oauth.Client(self.consumer)

        self.signature_method = oauth.SignatureMethod_HMAC_SHA1()

        self.parameters = parameters

        self.callback_url = callback_url

        self.errors = []
        self.request_token = None
        self.access_token = None

    def _get_request_token(self):
        """
        Obtain a temporary request token to authorize an access token and to
        sign the request to obtain the access token
        """
        if self.request_token is None:
            if self.callback_url is not None:
                params = urllib.urlencode([
                    ('oauth_callback', 'http://%s%s' % (Site.objects.get_current(),
                        reverse(self.callback_url))),
                ])
                request_token_url = '%s?%s' % (self.request_token_url, params)
            else:
                request_token_url = self.request_token_url
            response, content = self.client.request(request_token_url, "GET")
            if response['status'] != '200':
                raise OAuthError(
                    _('Invalid response while obtaining request token from "%s".') % get_token_prefix(self.request_token_url))
            self.request_token = dict(parse_qsl(content))
            self.request.session['oauth_%s_request_token' % get_token_prefix(self.request_token_url)] = self.request_token
        return self.request_token

    def _get_access_token(self):
        """
        Obtain the access token to access private resources at the API endpoint.
        """
        if self.access_token is None:
            request_token = self._get_rt_from_session()
            token = oauth.Token(request_token['oauth_token'], request_token['oauth_token_secret'])
            if self.callback_url is not None:
                # If a callback_url is provided, the callback has to include a verifier.
                token.set_verifier(self.request.GET.get('oauth_verifier'))
            self.client = oauth.Client(self.consumer, token)
            response, content = self.client.request(self.access_token_url, "GET")
            if response['status'] != '200':
                raise OAuthError(
                    _('Invalid response while obtaining access token from "%s".') % get_token_prefix(self.request_token_url))
            self.access_token = dict(parse_qsl(content))

            self.request.session['oauth_%s_access_token' % get_token_prefix(self.request_token_url)] = self.access_token
        return self.access_token

    def _get_rt_from_session(self):
        """
        Returns the request token cached in the session by ``_get_request_token``
        """
        try:
            return self.request.session['oauth_%s_request_token' % get_token_prefix(self.request_token_url)]
        except KeyError:
            raise OAuthError(_('No request token saved for "%s".') % get_token_prefix(self.request_token_url))

    def _get_authorization_url(self):
        request_token = self._get_request_token()
        return '%s?oauth_token=%s' % (self.authorization_url,
            request_token['oauth_token'])

    def is_valid(self):
        try:
            self._get_rt_from_session()
            self._get_access_token()
        except OAuthError, e:
            self.errors.append(e.args[0])
            return False
        return True

    def get_redirect(self):
        """
        Returns a ``HttpResponseRedirect`` object to redirect the user to the
        URL the OAuth provider handles authorization.
        """
        return HttpResponseRedirect(self._get_authorization_url())

class OAuth(object):
    """
    Base class to perform oauth signed requests from access keys saved in a user's
    session.
    See the ``OAuthTwitter`` class below for an example.
    """

    def __init__(self, request, consumer_key, secret_key, request_token_url):
        self.request = request

        self.consumer_key = consumer_key
        self.secret_key = secret_key
        self.consumer = oauth.Consumer(consumer_key, secret_key)

        self.request_token_url = request_token_url

    def _get_at_from_session(self):
        """
        Get the saved access token for private resources from the session.
        """
        try:
            return self.request.session['oauth_%s_access_token' % get_token_prefix(self.request_token_url)]
        except KeyError:
            raise OAuthError(
                _('No access token saved for "%s".') % get_token_prefix(self.request_token_url))

    def query(self, url, method="GET", params=dict(), headers=dict()):
        """
        Request a API endpoint at ``url`` with ``params`` being either the
        POST or GET data.
        """
        access_token = self._get_at_from_session()

        token = oauth.Token(access_token['oauth_token'], access_token['oauth_token_secret'])

        client = oauth.Client(self.consumer, token)

        body = urllib.urlencode(params)

        response, content = client.request(url, method=method, headers=headers,
            body=body)

        if response['status'] != '200':
            raise OAuthError(
                _('No access to private resources at "%s".') % get_token_prefix(self.request_token_url))

        return content

class OAuthTwitter(OAuth):
    """
    Verifying twitter credentials
    """
    url = 'https://twitter.com/account/verify_credentials.json'

    def get_user_info(self):
        user = simplejson.loads(self.query(self.url))
        return user
<commit_msg>changed getting request token method to POST<commit_after>"""

Updated on 19.12.2009

@author: alen, pinda
Inspired by:
    http://github.com/leah/python-oauth/blob/master/oauth/example/client.py
    http://github.com/facebook/tornado/blob/master/tornado/auth.py
"""
import time
import base64
import urllib
import urllib2

# parse_qsl was moved from the cgi namespace to urlparse in Python2.6.
# this allows backwards compatibility
try:
    from urlparse import parse_qsl
except ImportError:
    from cgi import parse_qsl

from xml.dom import minidom

import oauth2 as oauth
from openid.consumer import consumer as openid
from openid.consumer.discover import DiscoveryFailure
from openid.store.interface import OpenIDStore as OIDStore
from openid.association import Association as OIDAssociation

from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.utils.translation import gettext as _

from django.conf import settings
from django.utils import simplejson

from django.contrib.sites.models import Site

from socialregistration.models import OpenIDStore as OpenIDStoreModel, OpenIDNonce
from urlparse import urlparse

USE_HTTPS = bool(getattr(settings, 'SOCIALREGISTRATION_USE_HTTPS', False))

def _https():
    if USE_HTTPS:
        return 's'
    else:
        return ''

class OpenIDStore(OIDStore):
    max_nonce_age = 6 * 60 * 60

    def storeAssociation(self, server_url, assoc=None):
        stored_assoc = OpenIDStoreModel.objects.create(
            server_url=server_url,
            handle=assoc.handle,
            secret=base64.encodestring(assoc.secret),
            issued=assoc.issued,
            lifetime=assoc.issued,
            assoc_type=assoc.assoc_type
        )

    def getAssociation(self, server_url, handle=None):
        stored_assocs = OpenIDStoreModel.objects.filter(
            server_url=server_url
        )
        if handle:
            stored_assocs = stored_assocs.filter(handle=handle)

        stored_assocs.order_by('-issued')

        if stored_assocs.count() == 0:
            return None

        return_val = None

        for stored_assoc in stored_assocs:
            assoc = OIDAssociation(
                stored_assoc.handle, base64.decodestring(stored_assoc.secret),
                stored_assoc.issued, stored_assoc.lifetime, stored_assoc.assoc_type
            )

            if assoc.getExpiresIn() == 0:
                stored_assoc.delete()
            else:
                if return_val is None:
                    return_val = assoc

        return return_val

    def removeAssociation(self, server_url, handle):
        stored_assocs = OpenIDStoreModel.objects.filter(
            server_url=server_url
        )
        if handle:
            stored_assocs = stored_assocs.filter(handle=handle)

        stored_assocs.delete()

    def useNonce(self, server_url, timestamp, salt):
        try:
            nonce = OpenIDNonce.objects.get(
                server_url=server_url,
                timestamp=timestamp,
                salt=salt
            )
        except OpenIDNonce.DoesNotExist:
            nonce = OpenIDNonce.objects.create(
                server_url=server_url,
                timestamp=timestamp,
                salt=salt
            )
            return True

        return False

class OpenID(object):
    def __init__(self, request, return_to, endpoint):
        """
        @param request: : django.http.HttpRequest object
        @param return_to: URL to redirect back to once the user authenticated
            the application on the OpenID provider
        @param endpoint: URL to the OpenID provider we're connecting to
        """
        self.request = request
        self.return_to = return_to
        self.endpoint = endpoint
        self.store = OpenIDStore()
        self.consumer = openid.Consumer(self.request.session, self.store)
        self.result = None

    def get_redirect(self):
        auth_request = self.consumer.begin(self.endpoint)
        redirect_url = auth_request.redirectURL(
            'http%s://%s/' % (_https(), Site.objects.get_current().domain),
            self.return_to
        )
        return HttpResponseRedirect(redirect_url)

    def complete(self):
        self.result = self.consumer.complete(
            dict(self.request.GET.items()),
            'http%s://%s%s' % (_https(), Site.objects.get_current(),
                self.request.path)
        )

    def is_valid(self):
        if self.result is None:
            self.complete()

        return self.result.status == openid.SUCCESS

def get_token_prefix(url):
    """
    Returns a prefix for the token to store in the session so we can hold
    more than one single oauth provider's access key in the session.

    Example:

        The request token url ``http://twitter.com/oauth/request_token``
        returns ``twitter.com``

    """
    try:
        return urllib2.urlparse.urlparse(url).netloc
    except AttributeError:
        return urllib2.rulparse.urlparse(url)[1]

class OAuthError(Exception):
    pass

class OAuthClient(object):

    def __init__(self, request, consumer_key, consumer_secret, request_token_url,
        access_token_url, authorization_url, callback_url, parameters=None):

        self.request = request

        self.request_token_url = request_token_url
        self.access_token_url = access_token_url
        self.authorization_url = authorization_url

        self.consumer_key = consumer_key
        self.consumer_secret = consumer_secret

        self.consumer = oauth.Consumer(consumer_key, consumer_secret)
        self.client = oauth.Client(self.consumer)

        self.signature_method = oauth.SignatureMethod_HMAC_SHA1()

        self.parameters = parameters

        self.callback_url = callback_url

        self.errors = []
        self.request_token = None
        self.access_token = None

    def _get_request_token(self):
        """
        Obtain a temporary request token to authorize an access token and to
        sign the request to obtain the access token
        """
        if self.request_token is None:
            body = None
            if self.callback_url is not None:
                body = urllib.urlencode([
                    ('oauth_callback', 'http://%s%s' % (
                        Site.objects.get_current(), reverse(self.callback_url)))
                ])
            response, content = self.client.request(self.request_token_url,
                                                    "POST", body=body)
            if response['status'] != '200':
                raise OAuthError(
                    _('Invalid response while obtaining request token from "%s".') % get_token_prefix(self.request_token_url))
            self.request_token = dict(parse_qsl(content))
            self.request.session['oauth_%s_request_token' % get_token_prefix(self.request_token_url)] = self.request_token
        return self.request_token

    def _get_access_token(self):
        """
        Obtain the access token to access private resources at the API endpoint.
        """
        if self.access_token is None:
            request_token = self._get_rt_from_session()
            token = oauth.Token(request_token['oauth_token'], request_token['oauth_token_secret'])
            if self.callback_url is not None:
                # If a callback_url is provided, the callback has to include a verifier.
                token.set_verifier(self.request.GET.get('oauth_verifier'))
            self.client = oauth.Client(self.consumer, token)
            response, content = self.client.request(self.access_token_url, "GET")
            if response['status'] != '200':
                raise OAuthError(
                    _('Invalid response while obtaining access token from "%s".') % get_token_prefix(self.request_token_url))
            self.access_token = dict(parse_qsl(content))

            self.request.session['oauth_%s_access_token' % get_token_prefix(self.request_token_url)] = self.access_token
        return self.access_token

    def _get_rt_from_session(self):
        """
        Returns the request token cached in the session by ``_get_request_token``
        """
        try:
            return self.request.session['oauth_%s_request_token' % get_token_prefix(self.request_token_url)]
        except KeyError:
            raise OAuthError(_('No request token saved for "%s".') % get_token_prefix(self.request_token_url))

    def _get_authorization_url(self):
        request_token = self._get_request_token()
        return '%s?oauth_token=%s' % (self.authorization_url,
            request_token['oauth_token'])

    def is_valid(self):
        try:
            self._get_rt_from_session()
            self._get_access_token()
        except OAuthError, e:
            self.errors.append(e.args[0])
            return False
        return True

    def get_redirect(self):
        """
        Returns a ``HttpResponseRedirect`` object to redirect the user to the
        URL the OAuth provider handles authorization.
        """
        return HttpResponseRedirect(self._get_authorization_url())

class OAuth(object):
    """
    Base class to perform oauth signed requests from access keys saved in a user's
    session.
    See the ``OAuthTwitter`` class below for an example.
    """

    def __init__(self, request, consumer_key, secret_key, request_token_url):
        self.request = request

        self.consumer_key = consumer_key
        self.secret_key = secret_key
        self.consumer = oauth.Consumer(consumer_key, secret_key)

        self.request_token_url = request_token_url

    def _get_at_from_session(self):
        """
        Get the saved access token for private resources from the session.
        """
        try:
            return self.request.session['oauth_%s_access_token' % get_token_prefix(self.request_token_url)]
        except KeyError:
            raise OAuthError(
                _('No access token saved for "%s".') % get_token_prefix(self.request_token_url))

    def query(self, url, method="GET", params=dict(), headers=dict()):
        """
        Request a API endpoint at ``url`` with ``params`` being either the
        POST or GET data.
        """
        access_token = self._get_at_from_session()

        token = oauth.Token(access_token['oauth_token'], access_token['oauth_token_secret'])

        client = oauth.Client(self.consumer, token)

        body = urllib.urlencode(params)

        response, content = client.request(url, method=method, headers=headers,
            body=body)

        if response['status'] != '200':
            raise OAuthError(
                _('No access to private resources at "%s".') % get_token_prefix(self.request_token_url))

        return content

class OAuthTwitter(OAuth):
    """
    Verifying twitter credentials
    """
    url = 'https://twitter.com/account/verify_credentials.json'

    def get_user_info(self):
        user = simplejson.loads(self.query(self.url))
        return user
<|endoftext|>


<commit_before>"""

Updated on 19.12.2009

@author: alen, pinda
Inspired by:
    http://github.com/leah/python-oauth/blob/master/oauth/example/client.py
    http://github.com/facebook/tornado/blob/master/tornado/auth.py
"""
import time
import base64
import urllib
import urllib2
from xml.dom import minidom

from oauth import oauth
from openid.consumer import consumer as openid
from openid.store.interface import OpenIDStore as OIDStore
from openid.association import Association as OIDAssociation

from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.utils.translation import gettext as _

from django.conf import settings
from django.utils import simplejson

from django.contrib.sites.models import Site

from socialregistration.models import OpenIDStore as OpenIDStoreModel, OpenIDNonce

USE_HTTPS = bool(getattr(settings, 'SOCIALREGISTRATION_USE_HTTPS', False))

def _https():
    if USE_HTTPS:
        return 's'
    else:
        return ''

class OpenIDStore(OIDStore):
    max_nonce_age = 6 * 60 * 60

    def storeAssociation(self, server_url, assoc=None):
        stored_assoc = OpenIDStoreModel.objects.create(
            server_url=server_url,
            handle=assoc.handle,
            secret=base64.encodestring(assoc.secret),
            issued=assoc.issued,
            lifetime=assoc.issued,
            assoc_type=assoc.assoc_type
        )

    def getAssociation(self, server_url, handle=None):
        stored_assocs = OpenIDStoreModel.objects.filter(
            server_url=server_url
        )
        if handle:
            stored_assocs = stored_assocs.filter(handle=handle)

        stored_assocs.order_by('-issued')

        if stored_assocs.count() == 0:
            return None

        stored_assoc = stored_assocs[0]

        assoc = OIDAssociation(
            stored_assoc.handle, base64.decodestring(stored_assoc.secret),
            stored_assoc.issued, stored_assoc.lifetime, stored_assoc.assoc_type
        )

        return assoc

    def useNonce(self, server_url, timestamp, salt):
        try:
            nonce = OpenIDNonce.objects.get(
                server_url=server_url,
                timestamp=timestamp,
                salt=salt
            )
        except OpenIDNonce.DoesNotExist:
            nonce = OpenIDNonce.objects.create(
                server_url=server_url,
                timestamp=timestamp,
                salt=salt
            )
            return True

        return False

class OpenID(object):
    def __init__(self, request, return_to, endpoint):
        """
        @param request: : django.http.HttpRequest object
        @param return_to: URL to redirect back to once the user authenticated
            the application on the OpenID provider
        @param endpoint: URL to the OpenID provider we're connecting to
        """
        self.request = request
        self.return_to = return_to
        self.endpoint = endpoint
        self.store = OpenIDStore()
        self.consumer = openid.Consumer(self.request.session, self.store)

        self.result = None

    def get_redirect(self):
        auth_request = self.consumer.begin(self.endpoint)
        redirect_url = auth_request.redirectURL(
            'http%s://%s/' % (_https(), Site.objects.get_current().domain),
            self.return_to
        )
        return HttpResponseRedirect(redirect_url)

    def complete(self):
        self.result = self.consumer.complete(
            dict(self.request.GET.items()),
            'http%s://%s%s' % (_https(), Site.objects.get_current(),
                self.request.path)
        )

    def is_valid(self):
        if self.result is None:
            self.complete()

        return self.result.status == openid.SUCCESS

class OAuthClient(oauth.OAuthClient):
    """
    Simple OAuth client to perform OAuth requests
    ( primarily connect accounts - for other requests see class OAuth below )
    """

    def __init__(self, request, consumer_key, consumer_secret,
        request_token_url, access_token_url, authorization_url, callback_url, parameters=None):

        self.request = request

        self.request_token_url = request_token_url
        self.access_token_url = access_token_url
        self.authorization_url = authorization_url

        self.consumer = oauth.OAuthConsumer(consumer_key, consumer_secret)
        self.signature_method = oauth.OAuthSignatureMethod_HMAC_SHA1()

        self.parameters = parameters

        self.errors = []

        self.callback_url = callback_url

    def _get_response(self, oauth_request):
        try:
            return urllib2.urlopen(oauth_request.to_url()).read()
        except urllib2.HTTPError, e:
            raise Exception('%s on %s' % (e, oauth_request.to_url()))

    def get_request_token(self):
        """
        Get a request token
        """
        oauth_request = oauth.OAuthRequest.from_consumer_and_token(
            self.consumer, http_url=self.request_token_url,
            parameters=self.parameters
        )
        oauth_request.sign_request(self.signature_method, self.consumer, None)
        response = self._get_response(oauth_request)

        if response.startswith('{'):
            # Response is in json convert to string
            oauth_token = simplejson.loads(response)['oauth_token']
            oauth_token_secret = simplejson.loads(response)['oauth_token_secret']

            response = 'oauth_token=' + oauth_token + '&oauth_token_secret=' + oauth_token_secret

        return oauth.OAuthToken.from_string(response)

    def get_access_token(self):
        """
        Get an access token
        """
        oauth_request = oauth.OAuthRequest.from_consumer_and_token(
            self.consumer, http_url=self.access_token_url, token=self.token,
            parameters=self.parameters
        )
        oauth_request.sign_request(self.signature_method, self.consumer, self.token)
        response = self._get_response(oauth_request)

        if response.startswith('<?xml'):
            # Response is in xml convert to string
            xml = minidom.parseString(response)
            oauth_token = xml.getElementsByTagName('oauth_token')[0].childNodes[0].nodeValue
            oauth_token_secret = xml.getElementsByTagName('oauth_token_secret')[0].childNodes[0].nodeValue

            response = 'oauth_token=' + oauth_token + '&oauth_token_secret=' + oauth_token_secret

        return oauth.OAuthToken.from_string(response)

    def token_prefix(self):
        """
        Returns a prefix for the token to store in the session so we can hold
        more than one single oauth provider's access key in the session
        """
        if getattr(self, '_prefix', None) is None:
            self._prefix = urllib2.urlparse.urlparse(self.request_token_url).netloc
        return self._prefix

    @property
    def token(self):
        """ Short wrapper around get_request_token to cache the token """
        if getattr(self, '_token', None) is None:
            self._token = self.get_request_token()
        return self._token

    def session_token(self):
        """ Short wrapper around the token we've stored in the session """
        return self.request.session.get(
            'oauth_%s_unauthed_token' % self.token_prefix(),
            None
        )

    def get_authorization_url(self):
        """
        Returns the url to redirect the user to
        """
        oauth_request = oauth.OAuthRequest.from_consumer_and_token(
            self.consumer,
            http_url=self.authorization_url,
            token=self.token,
        )
        if self.callback_url:
            oauth_request.parameters['oauth_callback'] = Site.objects.get_current().domain + reverse(self.callback_url)

        oauth_request.sign_request(self.signature_method, self.consumer, self.token)
        return oauth_request.to_url()

    def get_redirect(self):
        """
        Returns a HttpResponseRedirect object to redirect the user to the url
        where authorization of the current application is handled.
        """
        self.request.session['oauth_%s_unauthed_token' % self.token_prefix()] = self.token.to_string()
        return HttpResponseRedirect(self.get_authorization_url())

    def is_valid(self):
        """
        Check if everything is valid after the user got redirected back to our
        site.
        """
        if not self.session_token():
            self.errors.append(_('No un-authorized token given.'))
            return False

        self._token = oauth.OAuthToken.from_string(self.session_token())

        if not self.token.key == self.request.GET.get('oauth_token', 'no-token-given'):
            self.errors.append(_('The given authorization tokens do not match.'))
            return False

        self._token = self.get_access_token()
        self.request.session['oauth_%s_access_token' % self.token_prefix()] = self.token.to_string()

        return True

class OAuth(object):
    """
    Base object to perform OAuth signed requests to a service provider
    """
    def __init__(self, request, consumer_key, secret_key, request_token_url):
        self.request = request
        self.consumer = oauth.OAuthConsumer(consumer_key, secret_key)
        self.signature_method = oauth.OAuthSignatureMethod_HMAC_SHA1()

        self.request_token_url = request_token_url

    def token_prefix(self):
        """
        Create a prefix for the token so we can hold multiple different oauth
        tokens in the session
        """
        return urllib2.urlparse.urlparse(self.request_token_url).netloc

    @property
    def access_token(self):
        if getattr(self, '_access_token', None) is None:
            self._access_token = oauth.OAuthToken.from_string(
                self.request.session['oauth_%s_access_token' % self.token_prefix()]
            )
        return self._access_token

    def get_request(self, url, parameters=None):
        """ Build a request object """
        oauth_request = oauth.OAuthRequest.from_consumer_and_token(
            self.consumer, http_url=url, token=self.access_token,
            parameters=parameters
        )
        oauth_request.sign_request(
            self.signature_method, self.consumer, self.access_token
        )
        return oauth_request

    def get_response(self, oauth_request):
        """ Submit the request and fetch the response body
        TODO: Add POST support"""
        try:
            return urllib2.urlopen(oauth_request.to_url()).read()
        except urllib2.HTTPError, e:
            raise Exception('%s on %s' % (e, oauth_request.to_url()))

    def query(self, url, parameters=None):
        return self.get_response(
            self.get_request(url, parameters)
        )

class OAuthTwitter(OAuth):
    """
    Verifying twitter credentials
    """
    url = 'https://twitter.com/account/verify_credentials.json'

    def get_user_info(self):
        user = simplejson.loads(self.query(self.url))
        return user
<commit_msg>Changed from the oauth library to oauth2 library.<commit_after>"""

Updated on 19.12.2009

@author: alen, pinda
Inspired by:
    http://github.com/leah/python-oauth/blob/master/oauth/example/client.py
    http://github.com/facebook/tornado/blob/master/tornado/auth.py
"""
import time
import base64
import urllib
import urllib2
from urlparse import parse_qsl
from xml.dom import minidom

import oauth2 as oauth
from openid.consumer import consumer as openid
from openid.store.interface import OpenIDStore as OIDStore
from openid.association import Association as OIDAssociation

from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.utils.translation import gettext as _

from django.conf import settings
from django.utils import simplejson

from django.contrib.sites.models import Site

from socialregistration.models import OpenIDStore as OpenIDStoreModel, OpenIDNonce
from urlparse import urlparse

USE_HTTPS = bool(getattr(settings, 'SOCIALREGISTRATION_USE_HTTPS', False))

def _https():
    if USE_HTTPS:
        return 's'
    else:
        return ''

class OpenIDStore(OIDStore):
    max_nonce_age = 6 * 60 * 60

    def storeAssociation(self, server_url, assoc=None):
        stored_assoc = OpenIDStoreModel.objects.create(
            server_url=server_url,
            handle=assoc.handle,
            secret=base64.encodestring(assoc.secret),
            issued=assoc.issued,
            lifetime=assoc.issued,
            assoc_type=assoc.assoc_type
        )

    def getAssociation(self, server_url, handle=None):
        stored_assocs = OpenIDStoreModel.objects.filter(
            server_url=server_url
        )
        if handle:
            stored_assocs = stored_assocs.filter(handle=handle)

        stored_assocs.order_by('-issued')

        if stored_assocs.count() == 0:
            return None

        stored_assoc = stored_assocs[0]

        assoc = OIDAssociation(
            stored_assoc.handle, base64.decodestring(stored_assoc.secret),
            stored_assoc.issued, stored_assoc.lifetime, stored_assoc.assoc_type
        )

        return assoc

    def useNonce(self, server_url, timestamp, salt):
        try:
            nonce = OpenIDNonce.objects.get(
                server_url=server_url,
                timestamp=timestamp,
                salt=salt
            )
        except OpenIDNonce.DoesNotExist:
            nonce = OpenIDNonce.objects.create(
                server_url=server_url,
                timestamp=timestamp,
                salt=salt
            )
            return True

        return False

class OpenID(object):
    def __init__(self, request, return_to, endpoint):
        """
        @param request: : django.http.HttpRequest object
        @param return_to: URL to redirect back to once the user authenticated
            the application on the OpenID provider
        @param endpoint: URL to the OpenID provider we're connecting to
        """
        self.request = request
        self.return_to = return_to
        self.endpoint = endpoint
        self.store = OpenIDStore()
        self.consumer = openid.Consumer(self.request.session, self.store)

        self.result = None

    def get_redirect(self):
        auth_request = self.consumer.begin(self.endpoint)
        redirect_url = auth_request.redirectURL(
            'http%s://%s/' % (_https(), Site.objects.get_current().domain),
            self.return_to
        )
        return HttpResponseRedirect(redirect_url)

    def complete(self):
        self.result = self.consumer.complete(
            dict(self.request.GET.items()),
            'http%s://%s%s' % (_https(), Site.objects.get_current(),
                self.request.path)
        )

    def is_valid(self):
        if self.result is None:
            self.complete()

        return self.result.status == openid.SUCCESS

def get_token_prefix(url):
    """
    Returns a prefix for the token to store in the session so we can hold
    more than one single oauth provider's access key in the session.

    Example:

        The request token url ``http://twitter.com/oauth/request_token``
        returns ``twitter.com``

    """
    return urllib2.urlparse.urlparse(url).netloc

class OAuthError(Exception):
    pass

class OAuthClient(object):

    def __init__(self, request, consumer_key, consumer_secret, request_token_url,
        access_token_url, authorization_url, callback_url, parameters=None):

        self.request = request

        self.request_token_url = request_token_url
        self.access_token_url = access_token_url
        self.authorization_url = authorization_url

        self.consumer_key = consumer_key
        self.consumer_secret = consumer_secret

        self.consumer = oauth.Consumer(consumer_key, consumer_secret)
        self.client = oauth.Client(self.consumer)

        self.signature_method = oauth.SignatureMethod_HMAC_SHA1()

        self.parameters = parameters

        self.callback_url = callback_url

        self.errors = []
        self.request_token = None
        self.access_token = None

    def _get_request_token(self):
        """
        Obtain a temporary request token to authorize an access token and to
        sign the request to obtain the access token
        """
        if self.request_token is None:
            response, content = self.client.request(self.request_token_url, "GET")
            if response['status'] != '200':
                raise OAuthError(
                    _('Invalid response while obtaining request token from "%s".') % get_token_prefix(self.request_token_url))
            self.request_token = dict(parse_qsl(content))
            self.request.session['oauth_%s_request_token' % get_token_prefix(self.request_token_url)] = self.request_token
        return self.request_token

    def _get_access_token(self):
        if self.access_token is None:
            request_token = self._get_rt_from_session()
            token = oauth.Token(request_token['oauth_token'], request_token['oauth_token_secret'])
            self.client = oauth.Client(self.consumer, token)
            response, content = self.client.request(self.access_token_url, "GET")
            if response['status'] != '200':
                raise OAuthError(
                    _('Invalid response while obtaining access token from "%s".') % get_token_prefix(self.request_token_url))
            self.access_token = dict(parse_qsl(content))

            self.request.session['oauth_%s_access_token' % get_token_prefix(self.request_token_url)] = self.access_token
        return self.access_token

    def _get_rt_from_session(self):
        """
        Returns the request token cached in the session by ``_get_request_token``
        """
        try:
            return self.request.session['oauth_%s_request_token' % get_token_prefix(self.request_token_url)]
        except KeyError:
            raise OAuthError(_('No request token saved for "%s".') % get_token_prefix(self.request_token_url))

    def _get_authorization_url(self):
        request_token = self._get_request_token()
        return '%s?oauth_token=%s&oauth_callback=%s' % (self.authorization_url,
            request_token['oauth_token'], '%s%s' % (Site.objects.get_current().domain,
                reverse(self.callback_url)))

    def is_valid(self):
        try:
            self._get_rt_from_session()
            self._get_access_token()
        except OAuthError, e:
            self.errors.append(e.args[0])
            return False
        return True

    def get_redirect(self):
        """
        Returns a ``HttpResponseRedirect`` object to redirect the user to the
        URL the OAuth provider handles authorization.
        """
        return HttpResponseRedirect(self._get_authorization_url())

class OAuth(object):
    def __init__(self, request, consumer_key, secret_key, request_token_url):
        self.request = request

        self.consumer_key = consumer_key
        self.secret_key = secret_key
        self.consumer = oauth.Consumer(consumer_key, secret_key)

        self.request_token_url = request_token_url

    def _get_at_from_session(self):
        """
        Get the saved access token for private resources from the session.
        """
        try:
            return self.request.session['oauth_%s_access_token' % get_token_prefix(self.request_token_url)]
        except KeyError:
            raise OAuthError(
                _('No access token saved for "%s".') % get_token_prefix(self.request_token_url))

    def query(self, url, method="GET", params=dict()):
        # TODO: Params

        at = self._get_at_from_session()

        token = oauth.Token(at['oauth_token'], at['oauth_token_secret'])

        client = oauth.Client(self.consumer, token)

        response, content = client.request(url, method=method)

        if response['status'] != '200':
            raise OAuthError(
                _('No access to private resources at "%s".') % get_token_prefix(self.request_token_url))

        return content

class OAuthTwitter(OAuth):
    """
    Verifying twitter credentials
    """
    url = 'https://twitter.com/account/verify_credentials.json'

    def get_user_info(self):
        user = simplejson.loads(self.query(self.url))
        return user
<|endoftext|>


<commit_before>"""Define various attributes and functions of the radio network."""

import signal
from RF24 import *

# TODO: share with scheduler, remove dummy data
colors = [(10, 10, 10), (20, 20, 20), (30, 30, 30), (40, 40, 40),
          (50, 50, 50), (60, 60, 60), (70, 70, 70), (80, 80, 80)]

# The hardcoded RF channel (for now)
RF_CHANNEL = 49

# The endpoint ID of the base station
BASE_STATION_ID = 0

# Radio GPIO pins
CE_PIN = RPI_V2_GPIO_P1_15  # Chip Enable pin
CSN_PIN = RPI_V2_GPIO_P1_24  # Chip Select pin

# Cap on the number of light updates per second
# TODO: read this from a config file
MAX_FPS = 120

def RF_ADDRESS(endpoint):
    """Return a 40-bit nRF address."""
    assert 0 <= endpoint < 256, "endpoint {0} is not between 0 and 255".format(endpoint)
    address_header = "SIGM"
    return int("0x" +
               "".join(["%0.2x" % ord(i) for i in address_header]) +
               "%0.2x" % endpoint,
               16)

class RadioNetwork:
    """Manage network operations on the radio.

    Each light is programmed with a unique 1-byte ID. Each has an
    nRF24L01+ radio module configured to listen on an address
    corresponding to its ID: the ASCII characters 'SIGM' followed by
    the ID. The Raspberry Pi base station also has an nRF24L01+ and
    follows the same address pattern with an ID of 0.

    The base station transmits an RGB value to each light, in order of
    ID, at a configurable frame rate. These messages are sent
    unreliably for minimal latency.

    """

    numLights = 8

    def __init__(self):
        """Initialize the network interface."""
        self._radio = RF24(CE_PIN, CSN_PIN)

        self._radio.begin()
        # 250kbps should be plenty. Lower speed decreases error rate.
        self._radio.setDataRate(RF24_250KBPS)
        # Higher power doesn't work on cheap eBay radios
        self._radio.setPALevel(RF24_PA_LOW)
        self._radio.setRetries(0, 0)
        self._radio.setAutoAck(False)
        self._radio.setCRCLength(RF24_CRC_16)
        self._radio.payloadSize = 3
        self._radio.setChannel(RF_CHANNEL)
        self._radio.openReadingPipe(1, RF_ADDRESS(BASE_STATION_ID))

        if __debug__:
            self._radio.printDetails()

    def start(self):
        """Start periodically transmitting frames."""
        # TODO: use sigwait loop to avoid locking mutex in signal handler
        signal.signal(signal.SIGALRM, self.transmitFrame)
        signal.setitimer(signal.ITIMER_REAL, 1.0/MAX_FPS, 1.0/MAX_FPS)

    def stop(self):
        """Stop periodically transmitting frames."""
        signal.setitimer(signal.ITIMER_REAL, 0)

    def transmitFrame(self, signum, frame):
        """Transmit the color of each light."""
        # TODO: mutex
        for i in range(self.numLights):
            msg = bytearray(colors[i])
            self._radio.openWritingPipe(RF_ADDRESS(i))
            self._radio.write(msg)
<commit_msg>Added colors mutex and improved debugging<commit_after>"""Define various attributes and functions of the radio network."""

import signal
import threading
from datetime import datetime

from RF24 import *

# TODO: share with scheduler, remove dummy data
colorsLock = threading.Lock()
colors = [(10, 10, 10), (20, 20, 20), (30, 30, 30), (40, 40, 40),
          (50, 50, 50), (60, 60, 60), (70, 70, 70), (80, 80, 80)]

# The hardcoded RF channel (for now)
RF_CHANNEL = 49

# The endpoint ID of the base station
BASE_STATION_ID = 0

# Radio GPIO pins
CE_PIN = RPI_V2_GPIO_P1_15  # Chip Enable pin
CSN_PIN = RPI_V2_GPIO_P1_24  # Chip Select pin

# Cap on the number of light updates per second
# TODO: read this from a config file
MAX_FPS = 1

def RF_ADDRESS(endpoint):
    """Return a 40-bit nRF address."""
    assert 0 <= endpoint < 256, "endpoint {0} is not between 0 and 255".format(endpoint)
    address_header = "SIGM"
    return int("0x" +
               "".join(["%0.2x" % ord(i) for i in address_header]) +
               "%0.2x" % endpoint,
               16)

class RadioNetwork:
    """Manage network operations on the radio.

    Each light is programmed with a unique 1-byte ID. Each has an
    nRF24L01+ radio module configured to listen on an address
    corresponding to its ID: the ASCII characters 'SIGM' followed by
    the ID. The Raspberry Pi base station also has an nRF24L01+ and
    follows the same address pattern with an ID of 0.

    The base station transmits an RGB value to each light, in order of
    ID, at a configurable frame rate. These messages are sent
    unreliably for minimal latency.

    """

    numLights = 8

    def __init__(self):
        """Initialize the network interface."""
        self._radio = RF24(CE_PIN, CSN_PIN)

        self._radio.begin()
        # 250kbps should be plenty. Lower speed decreases error rate.
        self._radio.setDataRate(RF24_250KBPS)
        # Higher power doesn't work on cheap eBay radios
        self._radio.setPALevel(RF24_PA_LOW)
        self._radio.setRetries(0, 0)
        self._radio.setAutoAck(False)
        self._radio.setCRCLength(RF24_CRC_16)
        self._radio.payloadSize = 3
        self._radio.setChannel(RF_CHANNEL)
        self._radio.openReadingPipe(1, RF_ADDRESS(BASE_STATION_ID))

        if __debug__:
            self._radio.printDetails()

    def start(self):
        """Start periodically transmitting frames."""
        # TODO: use sigwait loop to avoid locking mutex in signal handler
        signal.signal(signal.SIGALRM, self.transmitFrame)
        signal.setitimer(signal.ITIMER_REAL, 1.0/MAX_FPS, 1.0/MAX_FPS)

    def stop(self):
        """Stop periodically transmitting frames."""
        signal.setitimer(signal.ITIMER_REAL, 0)

    def transmitFrame(self, signum, frame):
        """Transmit the color of each light."""
        colorsLock.acquire()
        print(datetime.now())
        for i in range(self.numLights):
            # For now, just print values instead of transmitting
            print(colors[i])
            # msg = bytearray(colors[i])
            # self._radio.openWritingPipe(RF_ADDRESS(i))
            # self._radio.write(msg)
        colorsLock.release()<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

from dp_tornado.engine.engine import Engine as dpEngine
from dp_tornado.engine.bootstrap import Bootstrap as EngineBootstrap
from dp_tornado.engine.testing import Testing as dpTesting
from dp_tornado.version import __version_info__

class CliHandler(dpEngine):
    def __init__(self):
        import argparse

        parser = argparse.ArgumentParser()

        args = [
            ['action', {'nargs': 1}],
            ['options', {'nargs': '*'}],
            ['--identifier', {'help': 'Identifier'}],
            ['--dryrun', {'help': 'Dryrun, If this value specified `yes` then enabled.'}],
            ['--template', {'help': 'Template Name', 'default': 'helloworld'}],
            ['--path', {'help': 'App Path'}],
            ['--port', {'help': 'Binding port', 'type': int}]
        ]

        for e in args:
            parser.add_argument(e[0], **e[1])

        self.parser = parser
        self.args, self.args_unknown = parser.parse_known_args()
        self.cwd = self.helper.io.path.cwd()

    def main(self):
        self.logging.info('------------------------')
        self.logging.info('* dp for Python v%s' % '.'.join([str(e) for e in __version_info__]))
        self.logging.info('------------------------')

        for e in self.args.options:
            if not self.args.path:
                path = self.helper.io.path.join(self.cwd, e)

                if self.helper.io.path.is_file(path) or \
                        (self.helper.io.path.mkdir(path) and self.helper.io.path.is_dir(path)):
                    self.args.path = e

        if self.args.action and self.args.action[0] == 'init':
            self.command_init()

        elif self.args.action and self.args.action[0] == 'run':
            self.command_run()

        elif self.args.action and self.args.action[0] == 'test':
            self.command_test()

        else:
            self.logging.info('* dp4p finished, unrecognized action.')

            import sys
            self.logging.info('%s' % sys.argv)

            return exit(1)

        return exit(0)

    def command_init(self):
        installable = True
        init_path = self._pathified()

        self.logging.info('* Initializing app .. %s' % init_path)

        if self.helper.io.path.is_dir(init_path):
            browse = self.helper.io.path.browse(init_path)
            browse = [e for e in browse if not self.helper.io.path.split(e)[1].startswith('.')]

            if len(browse) > 0:
                status = 'Not Empty'
                installable = False
            else:
                status = 'Empty'

        elif self.helper.io.path.is_file(init_path):
            status = 'File'
            installable = False

        else:
            self.helper.io.path.mkdir(init_path)

            if not self.helper.io.path.is_dir(init_path):
                status = 'Permission Denied'
                installable = False
            else:
                status = 'Empty'

        if not installable:
            self.logging.info('* Initialization failed, %s' % status)
            return exit(1)

        engine_path = self.helper.io.path.dirname(__file__)
        application_path = init_path

        # template initialization.
        if not EngineBootstrap.init_template(
                engine_path=engine_path, application_path=application_path, template_name=self.args.template):
            self.logging.info('* Initialization failed.')
            return exit(1)

        self.logging.info('* Initialization succeed.')

    def command_run(self):
        init_path = self._pathified()

        init_py = init_path
        executable = True

        if self.helper.io.path.is_dir(init_py):
            init_py = '%s/__init__.py' % init_py

        self.logging.info('* Running app .. %s' % init_py)

        if not self.helper.io.path.is_file(init_py):
            executable = False

        if not executable:
            self.logging.info('* Running failed, Not executable path.')
            return exit(1)

        modules = []
        dirpath = init_path

        while True:
            dirpath, module = self.helper.io.path.split(dirpath)
            modules.append(module)

            if not self.helper.io.path.is_file(self.helper.io.path.join(dirpath, '__init__.py')):
                break

        app_module = '.'.join(modules[::-1])

        self.helper.io.path.sys.insert(0, dirpath)
        self.helper.io.path.sys.insert(1, init_path)

        import sys

        __import__(app_module)
        app = sys.modules[app_module] if app_module in sys.modules else None
        app_run = getattr(app, 'run', None) if app else None

        if not app_run:
            self.logging.info('* Running failed, Invalid app.')
            return exit(1)

        for i in range(len(self.args.options) + 1):
            sys.argv.pop(1)

        try:
            app_run(self)

        except KeyboardInterrupt:
            pass

        except Exception as e:
            self.logging.exception(e)

    def command_test(self):
        tester = dpTesting(self._pathified())
        tested = tester.run()

        if not tested:
            self.logging.info('* Testing failed, finished.')
            return exit(1)

        self.logging.info('* Testing succeed, done.')

    def _pathified(self):
        path = self.helper.io.path.join(self.cwd, self.args.path) if self.args.path else self.cwd
        path = path[:-1] if path.endswith('/') else path

        if path.endswith('__init__.py'):
            path = self.helper.io.path.dirname(path)

        return path

cli = CliHandler()

def main(as_module=False):
    cli.main()

if __name__ == '__main__':
    main(as_module=True)
<commit_msg>add method append_sys_path.<commit_after># -*- coding: utf-8 -*-

from dp_tornado.engine.engine import Engine as dpEngine
from dp_tornado.engine.bootstrap import Bootstrap as EngineBootstrap
from dp_tornado.engine.testing import Testing as dpTesting
from dp_tornado.version import __version_info__

class CliHandler(dpEngine):
    def __init__(self):
        import argparse

        parser = argparse.ArgumentParser()

        args = [
            ['action', {'nargs': 1}],
            ['options', {'nargs': '*'}],
            ['--identifier', {'help': 'Identifier'}],
            ['--dryrun', {'help': 'Dryrun, If this value specified `yes` then enabled.'}],
            ['--template', {'help': 'Template Name', 'default': 'helloworld'}],
            ['--path', {'help': 'App Path'}],
            ['--port', {'help': 'Binding port', 'type': int}]
        ]

        for e in args:
            parser.add_argument(e[0], **e[1])

        self.parser = parser
        self.args, self.args_unknown = parser.parse_known_args()
        self.cwd = self.helper.io.path.cwd()

    def main(self):
        self.logging.info('------------------------')
        self.logging.info('* dp for Python v%s' % '.'.join([str(e) for e in __version_info__]))
        self.logging.info('------------------------')

        for e in self.args.options:
            if not self.args.path:
                path = self.helper.io.path.join(self.cwd, e)

                if self.helper.io.path.is_file(path) or \
                        (self.helper.io.path.mkdir(path) and self.helper.io.path.is_dir(path)):
                    self.args.path = e

        if self.args.action and self.args.action[0] == 'init':
            self.command_init()

        elif self.args.action and self.args.action[0] == 'run':
            self.command_run()

        elif self.args.action and self.args.action[0] == 'test':
            self.command_test()

        else:
            self.logging.info('* dp4p finished, unrecognized action.')

            import sys
            self.logging.info('%s' % sys.argv)

            return exit(1)

        return exit(0)

    def command_init(self):
        installable = True
        init_path = self._pathified()

        self.logging.info('* Initializing app .. %s' % init_path)

        if self.helper.io.path.is_dir(init_path):
            browse = self.helper.io.path.browse(init_path)
            browse = [e for e in browse if not self.helper.io.path.split(e)[1].startswith('.')]

            if len(browse) > 0:
                status = 'Not Empty'
                installable = False
            else:
                status = 'Empty'

        elif self.helper.io.path.is_file(init_path):
            status = 'File'
            installable = False

        else:
            self.helper.io.path.mkdir(init_path)

            if not self.helper.io.path.is_dir(init_path):
                status = 'Permission Denied'
                installable = False
            else:
                status = 'Empty'

        if not installable:
            self.logging.info('* Initialization failed, %s' % status)
            return exit(1)

        engine_path = self.helper.io.path.dirname(__file__)
        application_path = init_path

        # template initialization.
        if not EngineBootstrap.init_template(
                engine_path=engine_path, application_path=application_path, template_name=self.args.template):
            self.logging.info('* Initialization failed.')
            return exit(1)

        self.logging.info('* Initialization succeed.')

    def command_run(self):
        init_path = self._pathified()

        init_py = init_path
        executable = True

        if self.helper.io.path.is_dir(init_py):
            init_py = '%s/__init__.py' % init_py

        self.logging.info('* Running app .. %s' % init_py)

        if not self.helper.io.path.is_file(init_py):
            executable = False

        if not executable:
            self.logging.info('* Running failed, Not executable path.')
            return exit(1)

        app_module = self._append_sys_path(init_path)

        import sys

        __import__(app_module)
        app = sys.modules[app_module] if app_module in sys.modules else None
        app_run = getattr(app, 'run', None) if app else None

        if not app_run:
            self.logging.info('* Running failed, Invalid app.')
            return exit(1)

        for i in range(len(self.args.options) + 1):
            sys.argv.pop(1)

        try:
            app_run(self)

        except KeyboardInterrupt:
            pass

        except Exception as e:
            self.logging.exception(e)

    def command_test(self):
        tester = dpTesting(self._pathified())
        tested = tester.run()

        if not tested:
            self.logging.info('* Testing failed, finished.')
            return exit(1)

        self.logging.info('* Testing succeed, done.')

    def _append_sys_path(self, init_path):
        dirpath = init_path
        modules = []

        while True:
            dirpath, module = self.helper.io.path.split(dirpath)
            modules.append(module)

            if not self.helper.io.path.is_file(self.helper.io.path.join(dirpath, '__init__.py')):
                break

        app_module = '.'.join(modules[::-1])

        self.helper.io.path.sys.insert(0, dirpath)
        self.helper.io.path.sys.insert(1, init_path)

        return app_module

    def _pathified(self):
        path = self.helper.io.path.join(self.cwd, self.args.path) if self.args.path else self.cwd
        path = path[:-1] if path.endswith('/') else path

        if path.endswith('__init__.py'):
            path = self.helper.io.path.dirname(path)

        return path

cli = CliHandler()

def main(as_module=False):
    cli.main()

if __name__ == '__main__':
    main(as_module=True)
<|endoftext|>