<commit_before># No shebang line, this module is meant to be imported
#
# Copyright 2014 Oliver Palmer
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import time
from datetime import timedelta
from httplib import OK

import psutil
from twisted.web.server import NOT_DONE_YET
from pyfarm.core.enums import AgentState
from pyfarm.agent.config import config
from pyfarm.agent.http.core.resource import Resource
from pyfarm.agent.sysinfo import cpu, memory

def mb(value):
    if isinstance(value, float):
        value = int(value)
    return str(value) + "MB"

def seconds(value):
    if value is not None:
        return "%.2f seconds" % value

class Index(Resource):
    """serves request for the root, '/', target"""
    TEMPLATE = "index.html"

    def get(self, **kwargs):
        request = kwargs["request"]

        # write out the results from the template back
        # to the original request
        def cb(content):
            request.write(content)
            request.setResponseCode(OK)
            request.finish()

        # convert the state integer to a string
        for key, value in AgentState._asdict().iteritems():
            if config["state"] == value:
                state = key.title()
                break
        else:
            raise KeyError("failed to find state")

        total_swap = memory.total_swap()
        ram_allocated = (memory.ram_used() / float(config["agent_ram"])) * 100
        swap_allocated = (memory.swap_used() / total_swap) * 100

        if ram_allocated >= 100:
            ram_css = "danger"
        elif ram_allocated >= 75:
            ram_css = "warning"
        elif ram_allocated >= 50:
            ram_css = "info"
        else:
            ram_css = None

        if swap_allocated >= 20:
            swap_css = "danger"
        elif swap_allocated >= 10:
            swap_css = "warning"
        elif swap_allocated >= 5:
            swap_css = "info"
        else:
            swap_css = None

        memory_info = [
            ("RAM Used",
                "%.2f%% (%s of %s)" % (
                    ram_allocated,
                    int(memory.ram_used()),
                    mb((config["agent_ram"]))), ram_css),
            ("SWAP Used",
                "%.2f%% (%s of %s)" % (
                    swap_allocated,
                    int(memory.swap_used()), mb((total_swap))), swap_css),
            ("System RAM", mb(memory.total_ram()), None),
            ("System RAM (reported)", mb(config["agent_ram"]), None),
            ("Agent RAM Usage", mb(memory.process_memory()), None)]

        network_info = [
            ("Hostname", config["agent_hostname"]),
            ("Agent Port", config["agent_api_port"]),
            ("Master API", config["master_api"])]

        cpu_info = [
            ("CPUs", cpu.total_cpus()),
            ("CPUs (reported)", config["agent_cpus"]),
            ("System Time", seconds(cpu.system_time())),
            ("User Time", seconds(cpu.user_time())),
            ("Idle Time", seconds(cpu.idle_time())),
            ("IO Wait", seconds(cpu.iowait()) or "Not Supported")]

        agent_id = config["agent-id"] if "agent_id" in config else None

        miscellaneous = [
            ("Database ID", agent_id),
            ("Logged On User(s)",
             ", ".join(sorted(set(user.name for user in psutil.get_users())))),
            ("Host Uptime",
             str(timedelta(seconds=time.time() - psutil.boot_time()))),
            ("Agent Uptime",
             str(timedelta(seconds=time.time() - config["start"])))]

        deferred = self.template.render(
            memory_info=memory_info,
            network_info=network_info,
            cpu_info=cpu_info,
            miscellaneous=miscellaneous)
        deferred.addCallback(cb)

        return NOT_DONE_YET

# TODO: form submission
# TODO: make 'port' field editable (requires restart)
# TODO: add callbacks for any field that needs to update the db
class Configuration(Resource):
    TEMPLATE = "configuration.html"

    # fields which nobody can see
    HIDDEN_FIELDS = (
        "agent", "api-endpoint-prefix", "pretty-json")

    # fields that a user can edit
    EDITABLE_FIELDS = (
        "agent_cpus", "hostname", "http-retry-delays",
        "ip", "master_api", "memory-check-interval", "agent_ram",
        "agent_ram_report_delta", "agent_time_offset", "use-address", "state",
        "swap-report-delta", "http-retry-delay")

    def get(self, **kwargs):
        request = kwargs["request"]

        # write out the results from the template back
        # to the original request
        def cb(content):
            request.write(content)
            request.setResponseCode(OK)
            request.finish()

        editable_fields = []
        non_editable_fields = []
        for key, value in sorted(config.items()):
            if key in self.HIDDEN_FIELDS:
                pass
            elif key in self.EDITABLE_FIELDS:
                editable_fields.append((key, value))
            else:
                non_editable_fields.append((key, value))

        deferred = self.template.render(
            non_editable_fields=non_editable_fields,
            editable_fields=editable_fields)
        deferred.addCallback(cb)

        return NOT_DONE_YET
<commit_msg>misc. field fixes<commit_after># No shebang line, this module is meant to be imported
#
# Copyright 2014 Oliver Palmer
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import time
from datetime import timedelta
from httplib import OK

import psutil
from twisted.web.server import NOT_DONE_YET
from pyfarm.core.enums import AgentState
from pyfarm.agent.config import config
from pyfarm.agent.http.core.resource import Resource
from pyfarm.agent.sysinfo import cpu, memory

def mb(value):
    if isinstance(value, float):
        value = int(value)
    return str(value) + "MB"

def seconds(value):
    if value is not None:
        return "%.2f seconds" % value

class Index(Resource):
    """serves request for the root, '/', target"""
    TEMPLATE = "index.html"

    def get(self, **kwargs):
        request = kwargs["request"]

        # write out the results from the template back
        # to the original request
        def cb(content):
            request.write(content)
            request.setResponseCode(OK)
            request.finish()

        # convert the state integer to a string
        for key, value in AgentState._asdict().iteritems():
            if config["state"] == value:
                state = key.title()
                break
        else:
            raise KeyError("failed to find state")

        total_swap = memory.total_swap()
        ram_allocated = (memory.ram_used() / float(config["agent_ram"])) * 100
        swap_allocated = (memory.swap_used() / total_swap) * 100

        if ram_allocated >= 100:
            ram_css = "danger"
        elif ram_allocated >= 75:
            ram_css = "warning"
        elif ram_allocated >= 50:
            ram_css = "info"
        else:
            ram_css = None

        if swap_allocated >= 20:
            swap_css = "danger"
        elif swap_allocated >= 10:
            swap_css = "warning"
        elif swap_allocated >= 5:
            swap_css = "info"
        else:
            swap_css = None

        memory_info = [
            ("RAM Used",
                "%.2f%% (%s of %s)" % (
                    ram_allocated,
                    int(memory.ram_used()),
                    mb((config["agent_ram"]))), ram_css),
            ("SWAP Used",
                "%.2f%% (%s of %s)" % (
                    swap_allocated,
                    int(memory.swap_used()), mb((total_swap))), swap_css),
            ("System RAM", mb(memory.total_ram()), None),
            ("System RAM (reported)", mb(config["agent_ram"]), None),
            ("Agent RAM Usage", mb(memory.process_memory()), None)]

        network_info = [
            ("Hostname", config["agent_hostname"]),
            ("Agent Port", config["agent_api_port"]),
            ("Master API", config["master_api"])]

        cpu_info = [
            ("CPUs", cpu.total_cpus()),
            ("CPUs (reported)", config["agent_cpus"]),
            ("System Time", seconds(cpu.system_time())),
            ("User Time", seconds(cpu.user_time())),
            ("Idle Time", seconds(cpu.idle_time())),
            ("IO Wait", seconds(cpu.iowait()) or "Not Supported")]

        agent_id = config["agent-id"] if "agent_id" in config else None

        miscellaneous = [
            ("Database ID", agent_id),
            ("Logged On User(s)",
             ", ".join(sorted(set(user.name for user in psutil.get_users())))),
            ("Host Uptime",
             str(timedelta(seconds=time.time() - psutil.boot_time()))),
            ("Agent Uptime",
             str(timedelta(seconds=time.time() - config["start"])))]

        deferred = self.template.render(
            memory_info=memory_info,
            network_info=network_info,
            cpu_info=cpu_info,
            miscellaneous=miscellaneous)
        deferred.addCallback(cb)

        return NOT_DONE_YET

# TODO: form submission
# TODO: make 'port' field editable (requires restart)
# TODO: add callbacks for any field that needs to update the db
class Configuration(Resource):
    TEMPLATE = "configuration.html"

    # fields which nobody can see
    HIDDEN_FIELDS = (
        "agent", "agent_pretty_json")

    # fields that a user can edit
    EDITABLE_FIELDS = (
        "agent_cpus", "hostname", "agent_http_retry_delay",
        "ip", "master_api", "master", "agent_ram_check_interval", "agent_ram",
        "agent_ram_report_delta", "agent_time_offset", "state",
        "agent_http_retry_delay")

    def get(self, **kwargs):
        request = kwargs["request"]

        # write out the results from the template back
        # to the original request
        def cb(content):
            request.write(content)
            request.setResponseCode(OK)
            request.finish()

        editable_fields = []
        non_editable_fields = []
        for key, value in sorted(config.items()):
            if key in self.HIDDEN_FIELDS:
                pass
            elif key in self.EDITABLE_FIELDS:
                editable_fields.append((key, value))
            else:
                non_editable_fields.append((key, value))

        deferred = self.template.render(
            non_editable_fields=non_editable_fields,
            editable_fields=editable_fields)
        deferred.addCallback(cb)

        return NOT_DONE_YET
<|endoftext|>


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

import pygame

import os
import time

from multiprocessing import Process, Lock, Event
from datetime import datetime

import ConfigParser
config = ConfigParser.ConfigParser()
config.readfp(open('config.cfg'))

GPIO_ACTIVE = config.getboolean('System','gpio')

if GPIO_ACTIVE:
    import RPi.GPIO as GPIO
    GPIO.setmode(GPIO.BOARD)

    GPIO.setup(13, GPIO.OUT)
    GPIO.output(13, GPIO.HIGH)

    # GPIO.setup(15, GPIO.OUT)
    # GPIO.output(15, GPIO.HIGH)

    # GPIO.setup(29, GPIO.OUT)
    # GPIO.output(29, GPIO.HIGH)

    # GPIO.setup(31, GPIO.OUT)
    # GPIO.output(31, GPIO.HIGH)

    # GPIO.setup(33, GPIO.OUT)
    # GPIO.output(33, GPIO.HIGH)

    # GPIO.setup(35, GPIO.OUT)
    # GPIO.output(35, GPIO.HIGH)

from post_production import clearRecFolder, buildVideo, uploadToDropbox as upload, generateQrCode
from recorder import recordFrames

play_status_movie = True

frame = 1
stop_recording_event = Event()
rec_timestamps = [0]
first_rec_timestamp = -1

def postproduction(stop_recording_event, rec_timeout_flag, rec_truly_started_event, postproduction_flag, postproduction_finished_flag):
    stop_recording_event.set()
    rec_timeout_flag.clear()
    rec_truly_started_event.clear()

    print('{} - Start building video'.format(datetime.now()))
    buildVideo(RECORD_PATH, VIDEO_PATH, rec_timestamps, REC_FPS)
    print('{} - Finished building video'.format(datetime.now()))
    print('{} - Start uploading'.format(datetime.now()))
    url = upload(VIDEO_PATH)
    print('{} - Finished uploading'.format(datetime.now()))

    generateQrCode(url, os.path.join(ROOT_PATH,'img') )

    postproduction_finished_flag.set()

    return pygame.time.get_ticks()

def toggleRelais(pin):
    GPIO.output(pin, not GPIO.input(pin))

def changeVideo(path):
    movie = pygame.movie.Movie(path)
    movie_screen = pygame.Surface(movie.get_size()).convert()
    movie.set_display(movie_screen)
    movie.play()

    return movie, movie_screen

# not sure alexa stole this code from the internets
def scale(img,(bx,by)):
    """ Scales 'img' to fit into box bx/by.
     This method will retain the original image's aspect ratio """
    ix,iy = img.get_size()
    if ix > iy:
        # fit to width
        scale_factor = bx/float(ix)
        sy = scale_factor * iy
        if sy > by:
            scale_factor = by/float(iy)
            sx = scale_factor * ix
            sy = by
        else:
            sx = bx
    else:
        # fit to height
        scale_factor = by/float(iy)
        sx = scale_factor * ix
        if sx > bx:
            scale_factor = bx/float(ix)
            sx = bx
            sy = scale_factor * iy
        else:
            sy = by

    return pygame.transform.scale(img, (int(sx),int(sy)))

if __name__ == '__main__':

    WIDTH  = config.getint('Screen','width')
    HEIGHT = config.getint('Screen','height')
    FULLSCREEN = config.getboolean('Screen','fullscreen')

    ROOT_PATH = config.get('System', 'root_folder')
    RECORD_PATH = config.get('System', 'rec_folder')
    VIDEO_PATH = config.get('System','video_path')

    TIMEOUT = config.getint('System', 'timeout')
    QR_TIMEOUT = config.getint('System', 'qr_timeout')

    FRAMES_PATH = config.get('System','frames_folder')
    ALL_FRAMES = [os.path.join(FRAMES_PATH,f) for f in sorted(os.listdir(FRAMES_PATH))]

    path = os.path.join(ROOT_PATH, 'img', 'timer')
    TIMER_IMGS = [os.path.join(path,f) for f in sorted(os.listdir(path))]

    REC_PATH = config.get('System','rec_folder')
    REC_DURATION = config.getint('Recorder','rec_duration') # seconds
    REC_FPS = config.getint('Recorder','rec_fps')

    CLOCK_X = config.getint('Screen','clock_x')
    CLOCK_Y = config.getint('Screen','clock_y')

    rec_timestamps = [0]
    first_rec_timestamp = -1

    print('{} - start magicKurbelKamera\nresolution: {} x {}'.format(datetime.now(), WIDTH,HEIGHT))

    # Lock Object for recording, only one recording should take place at once
    rec_lock = Lock()
    recording_flag = Event()
    stop_recording_event = Event()
    rec_timeout_flag = Event()
    rec_truly_started_event = Event()
    reset_flag = Event()

    postproduction_flag = Event()
    postproduction_finished_flag = Event()

    # Playing movie state
    play_status_movie = True
    show_qr_code = False

    # pygame setup
    pygame.init()
    clock = pygame.time.Clock()
    pygame.display.set_caption('MagicKurbelKamera') # set a window title
    if FULLSCREEN:
        screen = pygame.display.set_mode((WIDTH,HEIGHT), pygame.FULLSCREEN)
        pygame.mouse.set_visible(0)
    else:
        screen = pygame.display.set_mode((WIDTH,HEIGHT))

    background = pygame.Surface(screen.get_size()) # dunno
    background.fill((0,0,0)) # black background
    background = background.convert() # dunno
    # end of pygame setup

    # load init video
    movie, movie_screen = changeVideo(os.path.join(ROOT_PATH,'img','magic.mp4'))

    frame = 1
    ticks = 0
    mainloop = True
    last_event = pygame.time.get_ticks()

    # magic ahead
    while mainloop:
        diff = pygame.time.get_ticks() - last_event

        # Normal timeout after some time
        if diff > (TIMEOUT * 1000) and not show_qr_code and not play_status_movie:
            reset_flag.set()
            last_event = pygame.time.get_ticks()

        # Recoding is timed out
        elif rec_timeout_flag.is_set():
            postproduction_flag.set()
            Process(target=postproduction,
                    args = (stop_recording_event,
                            rec_timeout_flag,
                            rec_truly_started_event,
                            postproduction_flag,
                            postproduction_finished_flag)).start()

        # A little longer timeout so you have time to scan the qr code
        elif diff > (QR_TIMEOUT * 1000) and show_qr_code:
            reset_flag.set()
            last_event = pygame.time.get_ticks()

        if (reset_flag.is_set()):
            movie, movie_screen = changeVideo(os.path.join(ROOT_PATH,'img','magic.mp4'))
            play_status_movie = True
            show_qr_code = False
            movie.stop()
            frame = 1
            stop_recording_event.set()
            rec_timestamps = []
            first_rec_timestamp = -1
            clearRecFolder(REC_PATH, rec_timestamps, REC_FPS)
            postproduction_finished_flag.clear()
            recording_flag.clear()
            if GPIO_ACTIVE:
                GPIO.setup( 7, GPIO.OUT)
                GPIO.setup( 11, GPIO.OUT)
                GPIO.output(7,GPIO.HIGH) # turn off rec-Button lamp
                GPIO.output(11,GPIO.HIGH) # turn off lighting box
            reset_flag.clear()

        # display video
        if play_status_movie:
            screen.blit(background,(0,0))
            screen.blit(movie_screen,(0,0))
            pygame.display.update()
            clock.tick(60)

            if movie.get_busy() == 0:
                movie.rewind()
                movie.play()

        # if we are not in postproduction state
        if not postproduction_flag.is_set() and not show_qr_code:

            for event in pygame.event.get():

                # pygame window closed by user
                if event.type == pygame.QUIT: mainloop = False

                # key is released
                elif event.type == pygame.KEYUP:
                    last_event = pygame.time.get_ticks()

                    # left and right arrow
                    if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:

                        play_status_movie = False

                        if GPIO_ACTIVE:
                            toggleRelais(13) # klick klack

                        # increment or decrement the actual frame number
                        if event.key == pygame.K_LEFT:   frame -= 1
                        elif event.key == pygame.K_RIGHT: frame += 1

                        frame = (frame % len(ALL_FRAMES))
                        if frame == 0: frame = len(ALL_FRAMES)

                        image = ALL_FRAMES[frame - 1]
                        img = scale(pygame.image.load(image), (WIDTH,HEIGHT))
                        screen.blit(img,(0,0))
                        # pygame.display.update() # pygame.display.flip()
                        # clock.tick(60)

                        # count ms since first tick
                        if recording_flag.is_set() and not first_rec_timestamp == -1:
                            rec_truly_started_event.set()
                            rec_timestamps.append(pygame.time.get_ticks() - first_rec_timestamp)
                        else:
                            first_rec_timestamp = pygame.time.get_ticks()
                            rec_timestamps = [0]

                        ticks += 1

                        if ticks % 50 == 5:
                            clearRecFolder(REC_PATH, rec_timestamps, REC_FPS)

                    # escape
                    elif event.key == pygame.K_ESCAPE:
                        mainloop = False # user pressed ESC

                    # Testing the timer
                    elif event.key == pygame.K_g:
                        if (recording_flag.is_set()):
                            recording_flag.clear()
                        else:
                            recording_flag.set()

                    # Record Button
                    elif event.key == pygame.K_r and config.getboolean('System','camera'):
                        if not recording_flag.is_set():

                            play_status_movie = False
                            stop_recording_event.clear()

                            first_rec_timestamp = pygame.time.get_ticks()
                            rec_timestamps = []

                            # show pre_rec screen
                            bg = pygame.image.load(os.path.join(ROOT_PATH,'img','pre_rec.png'))
                            screen.blit(bg,(0,0))
                            pygame.display.update()
                            clock.tick(60)

                            rec_timeout_flag.clear()
                            Process(target=recordFrames,
                                    args=(rec_lock,
                                          recording_flag,
                                          WIDTH, HEIGHT,
                                          REC_DURATION,
                                          REC_FPS,
                                          stop_recording_event,
                                          rec_timeout_flag,
                                          rec_truly_started_event)).start()

                        else:
                            # start postproduction
                            postproduction_flag.set()
                            Process(target=postproduction,
                                    args = (stop_recording_event,
                                            rec_timeout_flag,
                                            rec_truly_started_event,
                                            postproduction_flag,
                                            postproduction_finished_flag)).start()

                    # this is the bin button
                    elif event.key == pygame.K_e:
                        reset_flag.set()

        else:
            # ignore keyboard-Events while in postproduction
            for event in pygame.event.get():
                pass

            # here we are in postproduction state
            if not postproduction_finished_flag.is_set():

                if not play_status_movie:
                    movie, movie_screen = changeVideo(os.path.join(ROOT_PATH,'img','development.mp4'))
                    play_status_movie = True

            elif postproduction_finished_flag.is_set() and not show_qr_code:
                play_status_movie = False
                qr_code_path = os.path.join(ROOT_PATH,'img', 'code.png')
                bg = pygame.image.load(os.path.join(ROOT_PATH,'img','bg.png'))
                screen.blit(bg,(0,0))
                img = scale(pygame.image.load(qr_code_path), (111,111))
                screen.blit(img,(310,163))
                pygame.display.update()
                clock.tick(60)
                postproduction_flag.clear()
                last_event = pygame.time.get_ticks()
                show_qr_code = True

        # if in recoding state then update timer image
        if (recording_flag.is_set()):
            timespent = (pygame.time.get_ticks() - first_rec_timestamp)/1000
            image = TIMER_IMGS[(timespent-1)%11]
            img = scale(pygame.image.load(image), (50,50))
            screen.blit(img,(CLOCK_X,CLOCK_Y))

        # do this all the time
        pygame.display.update()
        clock.tick(60)

    if GPIO_ACTIVE:
        GPIO.cleanup()<commit_msg>some smaller changes/fixes for video development<commit_after># -*- coding: utf-8 -*-

import pygame

import os
import time

from multiprocessing import Process, Lock, Event
from datetime import datetime

import ConfigParser
config = ConfigParser.ConfigParser()
config.readfp(open('config.cfg'))

GPIO_ACTIVE = config.getboolean('System','gpio')

if GPIO_ACTIVE:
    import RPi.GPIO as GPIO
    GPIO.setmode(GPIO.BOARD)

    GPIO.setup(13, GPIO.OUT)
    GPIO.output(13, GPIO.HIGH)

    # GPIO.setup(15, GPIO.OUT)
    # GPIO.output(15, GPIO.HIGH)

    # GPIO.setup(29, GPIO.OUT)
    # GPIO.output(29, GPIO.HIGH)

    # GPIO.setup(31, GPIO.OUT)
    # GPIO.output(31, GPIO.HIGH)

    # GPIO.setup(33, GPIO.OUT)
    # GPIO.output(33, GPIO.HIGH)

    # GPIO.setup(35, GPIO.OUT)
    # GPIO.output(35, GPIO.HIGH)

from post_production import clearRecFolder, buildVideo, uploadToDropbox as upload, generateQrCode
from recorder import recordFrames

play_status_movie = True

frame = 1
stop_recording_event = Event()
rec_timestamps = [0]
first_rec_timestamp = -1

def postproduction(stop_recording_event, rec_timeout_flag, rec_truly_started_event, postproduction_flag, postproduction_finished_flag):
    stop_recording_event.set()
    rec_timeout_flag.clear()
    rec_truly_started_event.clear()

    print('{} - Start building video'.format(datetime.now()))
    buildVideo(RECORD_PATH, VIDEO_PATH, rec_timestamps, REC_FPS)
    print('{} - Finished building video'.format(datetime.now()))
    print('{} - Start uploading'.format(datetime.now()))
    url = upload(VIDEO_PATH)
    print('{} - Finished uploading'.format(datetime.now()))

    generateQrCode(url, os.path.join(ROOT_PATH,'img') )

    postproduction_finished_flag.set()

    return pygame.time.get_ticks()

def toggleRelais(pin):
    GPIO.output(pin, not GPIO.input(pin))

def changeVideo(path):
    movie = pygame.movie.Movie(path)
    movie_screen = pygame.Surface(movie.get_size()).convert()
    movie.set_display(movie_screen)
    movie.play()

    return movie, movie_screen

# not sure alexa stole this code from the internets
def scale(img,(bx,by)):
    """ Scales 'img' to fit into box bx/by.
     This method will retain the original image's aspect ratio """
    ix,iy = img.get_size()
    if ix > iy:
        # fit to width
        scale_factor = bx/float(ix)
        sy = scale_factor * iy
        if sy > by:
            scale_factor = by/float(iy)
            sx = scale_factor * ix
            sy = by
        else:
            sx = bx
    else:
        # fit to height
        scale_factor = by/float(iy)
        sx = scale_factor * ix
        if sx > bx:
            scale_factor = bx/float(ix)
            sx = bx
            sy = scale_factor * iy
        else:
            sy = by

    return pygame.transform.scale(img, (int(sx),int(sy)))

if __name__ == '__main__':

    WIDTH  = config.getint('Screen','width')
    HEIGHT = config.getint('Screen','height')
    FULLSCREEN = config.getboolean('Screen','fullscreen')

    ROOT_PATH = config.get('System', 'root_folder')
    RECORD_PATH = config.get('System', 'rec_folder')
    VIDEO_PATH = config.get('System','video_path')

    TIMEOUT = config.getint('System', 'timeout')
    QR_TIMEOUT = config.getint('System', 'qr_timeout')

    FRAMES_PATH = config.get('System','frames_folder')
    ALL_FRAMES = [os.path.join(FRAMES_PATH,f) for f in sorted(os.listdir(FRAMES_PATH))]

    path = os.path.join(ROOT_PATH, 'img', 'timer')
    TIMER_IMGS = [os.path.join(path,f) for f in sorted(os.listdir(path))]

    REC_PATH = config.get('System','rec_folder')
    REC_DURATION = config.getint('Recorder','rec_duration') # seconds
    REC_FPS = config.getint('Recorder','rec_fps')

    CLOCK_X = config.getint('Screen','clock_x')
    CLOCK_Y = config.getint('Screen','clock_y')

    rec_timestamps = [0]
    first_rec_timestamp = -1

    print('{} - start magicKurbelKamera\nresolution: {} x {}'.format(datetime.now(), WIDTH,HEIGHT))

    # Lock Object for recording, only one recording should take place at once
    rec_lock = Lock()
    recording_flag = Event()
    stop_recording_event = Event()
    rec_timeout_flag = Event()
    rec_truly_started_event = Event()
    reset_flag = Event()

    postproduction_flag = Event()
    postproduction_finished_flag = Event()

    # Playing movie state
    play_status_movie = True
    show_qr_code = False

    # pygame setup
    pygame.init()
    clock = pygame.time.Clock()
    pygame.display.set_caption('MagicKurbelKamera') # set a window title
    if FULLSCREEN:
        screen = pygame.display.set_mode((WIDTH,HEIGHT), pygame.FULLSCREEN)
        pygame.mouse.set_visible(0)
    else:
        screen = pygame.display.set_mode((WIDTH,HEIGHT))

    background = pygame.Surface(screen.get_size()) # dunno
    background.fill((0,0,0)) # black background
    background = background.convert() # dunno
    # end of pygame setup

    # load init video
    movie, movie_screen = changeVideo(os.path.join(ROOT_PATH,'img','magic.mp4'))

    frame = 1
    ticks = 0
    mainloop = True
    last_event = pygame.time.get_ticks()

    # magic ahead
    while mainloop:
        diff = pygame.time.get_ticks() - last_event

        # Normal timeout after some time
        if diff > (TIMEOUT * 1000) and not show_qr_code and not play_status_movie:
            reset_flag.set()
            last_event = pygame.time.get_ticks()

        # Recoding is timed out
        elif rec_timeout_flag.is_set():
            postproduction_flag.set()
            Process(target=postproduction,
                    args = (stop_recording_event,
                            rec_timeout_flag,
                            rec_truly_started_event,
                            postproduction_flag,
                            postproduction_finished_flag)).start()

        # A little longer timeout so you have time to scan the qr code
        elif diff > (QR_TIMEOUT * 1000) and show_qr_code:
            reset_flag.set()
            last_event = pygame.time.get_ticks()

        if (reset_flag.is_set()):
            movie, movie_screen = changeVideo(os.path.join(ROOT_PATH,'img','magic.mp4'))
            play_status_movie = True
            show_qr_code = False
            movie.stop()
            frame = 1
            stop_recording_event.set()
            rec_timestamps = []
            first_rec_timestamp = -1
            clearRecFolder(REC_PATH, rec_timestamps, REC_FPS)
            postproduction_finished_flag.clear()
            recording_flag.clear()
            if GPIO_ACTIVE:
                GPIO.setup( 7, GPIO.OUT)
                GPIO.setup( 11, GPIO.OUT)
                GPIO.output(7,GPIO.HIGH) # turn off rec-Button lamp
                GPIO.output(11,GPIO.HIGH) # turn off lighting box
            reset_flag.clear()

        # display video
        if play_status_movie:
            screen.blit(background,(0,0))
            screen.blit(movie_screen,(0,0))
            pygame.display.update()
            clock.tick(60)

            if movie.get_busy() == 0:
                movie.rewind()
                movie.play()

        # if we are not in postproduction state
        if not postproduction_flag.is_set() and not show_qr_code:

            for event in pygame.event.get():

                # pygame window closed by user
                if event.type == pygame.QUIT: mainloop = False

                # key is released
                elif event.type == pygame.KEYUP:
                    last_event = pygame.time.get_ticks()

                    # left and right arrow
                    if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:

                        play_status_movie = False

                        if GPIO_ACTIVE:
                            toggleRelais(13) # klick klack

                        # increment or decrement the actual frame number
                        if event.key == pygame.K_LEFT:   frame -= 1
                        elif event.key == pygame.K_RIGHT: frame += 1

                        frame = (frame % len(ALL_FRAMES))
                        if frame == 0: frame = len(ALL_FRAMES)

                        image = ALL_FRAMES[frame - 1]
                        img = scale(pygame.image.load(image), (WIDTH,HEIGHT))
                        screen.blit(img,(0,0))
                        # pygame.display.update() # pygame.display.flip()
                        # clock.tick(60)

                        # count ms since first tick
                        if recording_flag.is_set() and not first_rec_timestamp == -1:
                            rec_truly_started_event.set()
                            rec_timestamps.append(pygame.time.get_ticks() - first_rec_timestamp)
                        else:
                            first_rec_timestamp = pygame.time.get_ticks()
                            rec_timestamps = [0]

                        ticks += 1

                        if ticks % 50 == 5:
                            clearRecFolder(REC_PATH, rec_timestamps, REC_FPS)

                    # escape
                    elif event.key == pygame.K_ESCAPE:
                        mainloop = False # user pressed ESC

                    # Testing the timer
                    elif event.key == pygame.K_g:
                        if (recording_flag.is_set()):
                            recording_flag.clear()
                        else:
                            recording_flag.set()

                    # Record Button
                    elif event.key == pygame.K_r and config.getboolean('System','camera'):
                        if not recording_flag.is_set():

                            play_status_movie = False
                            stop_recording_event.clear()

                            first_rec_timestamp = pygame.time.get_ticks()
                            rec_timestamps = []

                            # show pre_rec screen
                            bg = pygame.image.load(os.path.join(ROOT_PATH,'img','pre_rec.png'))
                            screen.blit(bg,(0,0))
                            pygame.display.update()
                            clock.tick(60)

                            rec_timeout_flag.clear()
                            Process(target=recordFrames,
                                    args=(rec_lock,
                                          recording_flag,
                                          WIDTH, HEIGHT,
                                          REC_DURATION,
                                          REC_FPS,
                                          stop_recording_event,
                                          rec_timeout_flag,
                                          rec_truly_started_event)).start()

                        else:
                            # start postproduction
                            postproduction_flag.set()
                            Process(target=postproduction,
                                    args = (stop_recording_event,
                                            rec_timeout_flag,
                                            rec_truly_started_event,
                                            postproduction_flag,
                                            postproduction_finished_flag)).start()

                    # this is the bin button
                    elif event.key == pygame.K_e:
                        reset_flag.set()

        else:
            # ignore keyboard-Events while in postproduction
            for event in pygame.event.get():
                pass

            # here we are in postproduction state
            if not postproduction_finished_flag.is_set():

                if not play_status_movie:
                    movie, movie_screen = changeVideo(os.path.join(ROOT_PATH,'img','development.mp4'))
                    play_status_movie = True

            elif postproduction_finished_flag.is_set() and not show_qr_code:
                play_status_movie = False
                qr_code_path = os.path.join(ROOT_PATH,'img', 'code.png')
                bg = pygame.image.load(os.path.join(ROOT_PATH,'img','bg.png'))
                screen.blit(bg,(0,0))
                img = scale(pygame.image.load(qr_code_path), (111,111))
                screen.blit(img,(310,163))
                pygame.display.update()
                clock.tick(60)
                postproduction_flag.clear()
                last_event = pygame.time.get_ticks()
                show_qr_code = True

        # if in recoding state then update timer image
        if (recording_flag.is_set()):
            timespent = (pygame.time.get_ticks() - first_rec_timestamp)/1000
            image = TIMER_IMGS[(timespent-1)%11]
            img = scale(pygame.image.load(image), (50,50))
            screen.blit(img,(CLOCK_X,CLOCK_Y))

        # do this all the time
        pygame.display.update()
        clock.tick(60)

    if GPIO_ACTIVE:
        GPIO.cleanup()
<|endoftext|>


<commit_before># Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

class PyH5sh(PythonPackage):
    """Shell-like environment for HDF5."""

    homepage = "https://github.com/sethrj/h5sh"
    url      = "https://github.com/sethrj/h5sh/archive/v0.1.1.tar.gz"

    maintainers = ['sethrj']

    version('0.1.1', sha256='111989d8200d1da8e150aee637a907e524ca0f98d5005a55587cba0d94d9c4a0')

    depends_on('py-setuptools', type=('build', 'run'))
    depends_on('py-h5py', type=('build', 'run'))
    depends_on('py-numpy', type=('build', 'run'))
    depends_on('py-prompt-toolkit@2:', type=('build', 'run'))
    depends_on('py-pygments', type=('build', 'run'))
    depends_on('py-six', type=('build', 'run'))
<commit_msg>py-h5sh: replace github with pypi (#27409)<commit_after># Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

class PyH5sh(PythonPackage):
    """Shell-like environment for HDF5."""

    homepage = "https://github.com/sethrj/h5sh"
    pypi     = "h5sh/h5sh-0.1.1.tar.gz"

    maintainers = ['sethrj']

    version('0.1.1', sha256='ccd8fed532d479d297baef044265100a4fb9cd119bce6f43270f2ee9f63a2183')

    depends_on('py-setuptools', type=('build', 'run'))
    depends_on('py-h5py@2.7.1:', type=('build', 'run'))
    depends_on('py-numpy@1.15:', type=('build', 'run'))
    depends_on('py-prompt-toolkit@2:', type=('build', 'run'))
    depends_on('py-pygments', type=('build', 'run'))
    depends_on('py-six', type=('build', 'run'))
<|endoftext|>


<commit_before># Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

class Simgrid(CMakePackage):
    """To study the behavior of large-scale distributed systems such as Grids,
    Clouds, HPC or P2P systems."""

    homepage = "http://simgrid.org/"
    url      = "https://gforge.inria.fr/frs/download.php/file/37758/SimGrid-3.21.tar.gz"
    git      = 'https://scm.gforge.inria.fr/anonscm/git/simgrid/simgrid.git'

    version('3.21', sha256='d2a6e9021016dd39a2b6f8d5d18c8223f6885746c5269550d19ba29c47c0c6a0',
            url='https://gforge.inria.fr/frs/download.php/file/37758/SimGrid-3.21.tar.gz')
    version('3.20', sha256='4d4757eb45d87cf18d990d589c31d223b0ea8cf6fcd8c94fca4d38162193cef6',
            url='https://gforge.inria.fr/frs/download.php/file/37602/SimGrid-3.20.tar.gz')
    version('3.19', sha256='64a3b82fdf0a65bb8b7c8e9feb01694360edaf38070097bf28aa181eccb86ea7',
            url='https://gforge.inria.fr/frs/download.php/file/37452/SimGrid-3.19.tar.gz')
    version('3.18', sha256='dc8f6223d89326b6a21c99eabc90598fa153d6b0818a63ff5c3ec8726e2257b2',
            url='https://gforge.inria.fr/frs/download.php/file/37294/SimGrid-3.18.tar.gz')
    version('3.17', sha256='f5e44f41983e83f65261598ab0de1909d3a8a3feb77f28e37d38f04631dbb908',
            url='https://gforge.inria.fr/frs/download.php/file/37148/SimGrid-3.17.tar.gz')
    version('3.16', sha256='51782534fec87eed9da345319ead699b13d7dad4be7ac89984a0446cb385d3fa',
            url='https://gforge.inria.fr/frs/download.php/file/36900/SimGrid-3.16.tar.gz')
    version('3.15', sha256='d1e411cdbfa953c018411b842727339ede6b82efcd5d3f6adc13a24f182fa9e8',
            url='https://gforge.inria.fr/frs/download.php/file/36621/SimGrid-3.15.tar.gz')
    version('3.14.159', sha256='2d93db245c6ec8039ffe332a77531b836ad093d57f18ec3f7920fe98e3719f48',
            url='http://gforge.inria.fr/frs/download.php/file/36384/SimGrid-3.14.159.tar.gz')
    version('3.13', sha256='7bcedd19492f9a32cc431840ad2688d0d6e4121982d6d26e0174b5c92b086121',
            url='http://gforge.inria.fr/frs/download.php/file/35817/SimGrid-3.13.tar.gz')
    version('3.12', sha256='d397ee0273395dc687fbcd2601515e7142559801a3db387454d77e0e18cd7878',
            url='http://gforge.inria.fr/frs/download.php/file/35215/SimGrid-3.12.tar.gz')
    version('3.11', sha256='6efb006e028e37f74a34fc37d585a8cb296720020cabad361d65662533f1600b',
            url='http://gforge.inria.fr/frs/download.php/file/33683/SimGrid-3.11.tar.gz')
    version('git', branch='master')

    variant('doc', default=False, description='Build documentation')
    variant('smpi', default=True, description='SMPI provides MPI')
    variant('examples', default=False, description='Install examples')
    variant('mc', default=False, description='Model checker')

    # does not build correctly with some old compilers -> rely on packages
    depends_on('boost')

    def setup_dependent_package(self, module, dep_spec):

        if self.spec.satisfies('+smpi'):
            self.spec.smpicc  = join_path(self.prefix.bin, 'smpicc')
            self.spec.smpicxx = join_path(self.prefix.bin,
                                          'smpicxx -std=c++11')
            self.spec.smpifc  = join_path(self.prefix.bin, 'smpif90')
            self.spec.smpif77 = join_path(self.prefix.bin, 'smpiff')

    def cmake_args(self):

        spec = self.spec
        args = []

        if not spec.satisfies('+doc'):
            args.append("-Denable_documentation=OFF")
        if spec.satisfies('+mc'):
            args.append("-Denable_model-checking=ON")

        return args

    def install(self, spec, prefix):
        """Make the install targets"""
        with working_dir(self.build_directory):
            make("install")
            if spec.satisfies('+examples'):
                install_tree(join_path(self.build_directory, 'examples'),
                             prefix.examples)
<commit_msg>simgrid: add v3.27, update package (#24513)<commit_after># Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

class Simgrid(CMakePackage):
    """To study the behavior of large-scale distributed systems such as Grids,
    Clouds, HPC or P2P systems."""

    homepage = "http://simgrid.org/"
    url      = "https://github.com/simgrid/simgrid/releases/download/v3.27/simgrid-3.27.tar.gz"
    git      = 'https://framagit.org/simgrid/simgrid.git'

    version('3.27', sha256='51aeb9de0434066e5fec40e785f5ea9fa934afe7f6bfb4aa627246e765f1d6d7')
    version('3.26', sha256='ac50da1eacc5a53b094a988a8ecde09962c29320f346b45e74dd32ab9d9f3e96')
    version('3.25', sha256='0b5dcdde64f1246f3daa7673eb1b5bd87663c0a37a2c5dcd43f976885c6d0b46',
            url='https://github.com/simgrid/simgrid/releases/download/v3.25/SimGrid-3.25.tar.gz')
    version('3.24', sha256='c976ed1cbcc7ff136f6d1a8eda7d9ccf090e0e16d5239e6e631047ae9e592921',
            url='https://github.com/simgrid/simgrid/releases/download/v3.24/SimGrid-3.24.tar.gz')
    version('3.23', sha256='c3c86673abf0a2685337f1f520a7782d9611cd18d0374f35e1d98652fdbbaf86',
            url='https://github.com/simgrid/simgrid/releases/download/v3.23/SimGrid-3.23.tar.gz')
    version('3.22', sha256='4fdff0a8e4c81f8edf6f7eedfa32e19748abe688d156ea9240178c558c8bad33',
            url='https://github.com/simgrid/simgrid/releases/download/v3_22/SimGrid-3.22.tar.gz')
    version('3.21', sha256='d2a6e9021016dd39a2b6f8d5d18c8223f6885746c5269550d19ba29c47c0c6a0',
            url='https://github.com/simgrid/simgrid/releases/download/v3_21/SimGrid-3.21.tar.gz')
    version('3.20', sha256='4d4757eb45d87cf18d990d589c31d223b0ea8cf6fcd8c94fca4d38162193cef6',
            url='https://github.com/simgrid/simgrid/releases/download/v3.20/SimGrid-3.20.tar.gz')

    # gforge.inria.fr end of life https://gforge.inria.fr/forum/forum.php?forum_id=11543
    version('3.19', sha256='64a3b82fdf0a65bb8b7c8e9feb01694360edaf38070097bf28aa181eccb86ea7',
            deprecated=True,
            url='https://gforge.inria.fr/frs/download.php/file/37452/SimGrid-3.19.tar.gz')
    version('3.18', sha256='dc8f6223d89326b6a21c99eabc90598fa153d6b0818a63ff5c3ec8726e2257b2',
            deprecated=True,
            url='https://gforge.inria.fr/frs/download.php/file/37294/SimGrid-3.18.tar.gz')
    version('3.17', sha256='f5e44f41983e83f65261598ab0de1909d3a8a3feb77f28e37d38f04631dbb908',
            deprecated=True,
            url='https://gforge.inria.fr/frs/download.php/file/37148/SimGrid-3.17.tar.gz')
    version('3.16', sha256='51782534fec87eed9da345319ead699b13d7dad4be7ac89984a0446cb385d3fa',
            deprecated=True,
            url='https://gforge.inria.fr/frs/download.php/file/36900/SimGrid-3.16.tar.gz')
    version('3.15', sha256='d1e411cdbfa953c018411b842727339ede6b82efcd5d3f6adc13a24f182fa9e8',
            deprecated=True,
            url='https://gforge.inria.fr/frs/download.php/file/36621/SimGrid-3.15.tar.gz')
    version('3.14.159', sha256='2d93db245c6ec8039ffe332a77531b836ad093d57f18ec3f7920fe98e3719f48',
            deprecated=True,
            url='http://gforge.inria.fr/frs/download.php/file/36384/SimGrid-3.14.159.tar.gz')
    version('3.13', sha256='7bcedd19492f9a32cc431840ad2688d0d6e4121982d6d26e0174b5c92b086121',
            deprecated=True,
            url='http://gforge.inria.fr/frs/download.php/file/35817/SimGrid-3.13.tar.gz')
    version('3.12', sha256='d397ee0273395dc687fbcd2601515e7142559801a3db387454d77e0e18cd7878',
            deprecated=True,
            url='http://gforge.inria.fr/frs/download.php/file/35215/SimGrid-3.12.tar.gz')
    version('3.11', sha256='6efb006e028e37f74a34fc37d585a8cb296720020cabad361d65662533f1600b',
            deprecated=True,
            url='http://gforge.inria.fr/frs/download.php/file/33683/SimGrid-3.11.tar.gz')

    version('develop', branch='master')

    variant('doc', default=False, description='Build documentation')
    variant('smpi', default=True, description='SMPI provides MPI')
    variant('examples', default=False, description='Install examples')
    variant('mc', default=False, description='Model checker')

    # does not build correctly with some old compilers -> rely on packages
    depends_on('boost')
    depends_on('boost@:1.69.0', when='@:3.21')

    conflicts('%gcc@10:', when='@:3.23',
              msg='simgrid <= v3.23 cannot be built with gcc >= 10,'
                  ' please use an older release (e.g., %gcc@:9.99).')

    def setup_dependent_package(self, module, dep_spec):

        if self.spec.satisfies('+smpi'):
            self.spec.smpicc  = join_path(self.prefix.bin, 'smpicc')
            self.spec.smpicxx = join_path(self.prefix.bin,
                                          'smpicxx -std=c++11')
            self.spec.smpifc  = join_path(self.prefix.bin, 'smpif90')
            self.spec.smpif77 = join_path(self.prefix.bin, 'smpiff')

    def cmake_args(self):

        spec = self.spec
        args = []

        if not spec.satisfies('+doc'):
            args.append("-Denable_documentation=OFF")
        if spec.satisfies('+mc'):
            args.append("-Denable_model-checking=ON")

        return args

    def install(self, spec, prefix):
        """Make the install targets"""
        with working_dir(self.build_directory):
            make("install")
            if spec.satisfies('+examples'):
                install_tree(join_path(self.build_directory, 'examples'),
                             prefix.examples)
<|endoftext|>


<commit_before>import json
import logging
import requests
from datetime import datetime
from django.conf import settings
from optparse import make_option
from django.db import transaction, DEFAULT_DB_ALIAS
from django.core.management.base import BaseCommand
from requests.exceptions import SSLError, ConnectionError, RequestException
from varify.samples.models import Sample, ResultScore

log = logging.getLogger(__name__)

class Command(BaseCommand):
    args = '<sample_label sample_label ...>'
    option_list = BaseCommand.option_list + (
        make_option('--database', action='store', dest='database',
                    default=DEFAULT_DB_ALIAS,
                    help='Specifies the target database to load results.'),
        make_option('--force', action='store_true', dest='force',
                    default=False,
                    help='Forces recomputation of all gene rankings')
    )

    def handle(self, *args, **options):
        if not getattr(settings, 'PHENOTYPE_ENDPOINT', None):
            log.error('PHENOTYPE_ENDPOINT must be defined in settings for '
                      'gene rankings to be updated.')
            return

        if not getattr(settings, 'GENE_RANK_BASE_URL', None):
            log.error('GENE_RANK_BASE_URL must be defined in settings for '
                      'gene rankings to be updated.')
            return

        if (not getattr(settings, 'VARIFY_CERT', None) or
                not getattr(settings, 'VARIFY_KEY', None)):
            log.error('VARIFY_CERT and VARIFY_KEY must be defined in settings '
                      'for gene rankings to be updated.')
            return

        database = options.get('database')
        force = options.get('force')

        # Construct the cert from the setting to use in requests to the
        # phenotype endpoint.
        cert = (settings.VARIFY_CERT, settings.VARIFY_KEY)

        # We ignore all the samples that aren't published. They aren't visible
        # to the user so we don't bother updating related scores. If there
        # were sample labels supplied as arguments then we limit the rankings
        # updates to those samples, otherwise we process all samples.
        samples = Sample.objects.filter(published=True)

        if args:
            samples = samples.filter(label__in=args)

        updated_samples = 0
        total_samples = 0

        for sample in samples:
            total_samples += 1

            # Construct the URL from the setting and the sample label. The
            # sample label is used to retrieve the phenotype info on the remote
            # endpoint.
            url = settings.PHENOTYPE_ENDPOINT.format(sample.label)

            # Get the phenotype information for this sample. If the
            # phenotype is unavailable then we can skip this sample.
            try:
                response = requests.get(url, cert=cert, verify=False)
            except SSLError:
                log.exception('Skipping sample "{0}". An SSLError occurred '
                              'during phenotype retrieval request.'
                              .format(sample.label))
                continue
            except ConnectionError:
                log.exception('Skipping sample "{0}". A ConnectionError '
                              'occurred during phenotype retrieval request.'
                              .format(sample.label))
                continue
            except RequestException:
                log.exception('Skipping sample "{0}". The sample has no '
                              'phenotype data associated with it'
                              .format(sample.label))
                continue

            try:
                phenotype_data = json.loads(response.content)
            except ValueError:
                log.error("Could not parse response from {0}, skipping '{1}'."
                          .format(url, sample.label))
                continue

            try:
                phenotype_modified = datetime.strptime(
                    phenotype_data['last_modified'], "%Y-%m-%dT%H:%M:%S.%f")
            except ValueError:
                phenotype_modified = datetime.min
                log.warn("Could not parse 'last_modified' field on phenotype "
                         "data. Using datetime.min so that only unranked "
                         "samples will be ranked. If the 'force' flag was "
                         "used then all samples will be updated despite this "
                         "parsing failure.")

            # If the parsed response doesn't contain any HPO terms then we can
            # skip this sample since we cannot rank genes without HPO terms.
            if not phenotype_data.get('hpoAnnotations', []):
                log.error("Response from phenotype missing HPO Annotations, "
                          "skipping '{0}'.".format(sample.label))
                continue

            if (not force and sample.phenotype_modified and
                    sample.phenotype_modified > phenotype_modified):
                log.debug("Sample '{0}' is already up to date, skipping it."
                          .format(sample.label))
                continue

            # Extract the HPO terms from the data returned from the phenotype
            # endpoint. We need to modify the terms a bit because the phenotype
            # endpoint has terms in the form 'HP_0011263' and the gene ranking
            # enpoint expects them to be of the form 'HP:0011263'.
            hpo_terms = []
            for hpo_annotation in phenotype_data['hpoAnnotations']:
                try:
                    hpo_id = str(hpo_annotation.get('hpo_id', ''))
                except AttributeError:
                    continue

                if hpo_id:
                    hpo_terms.append(hpo_id.replace('_', ':'))

            # If there are no HPO terms then there will be no rankings so skip
            # this sample to avoid any more computations and requests.
            if not hpo_terms:
                log.warning('Skipping "{0}" because it has no HPO terms '
                            'associated with it.'.format(sample.label))
                continue

            # Compute the unique gene list for the entire sample
            genes = set(sample.results.values_list(
                'variant__effects__transcript__gene__symbol', flat=True))

            # Obviously, if there are no genes then the gene ranking endpoint
            # will have nothing to do so we can safely skip this sample.
            if not genes:
                log.warning('Skipping "{0}" because it has no genes '
                            'associated with it.'.format(sample.label))
                continue

            # We need to convert the genes to strings because the ranking
            # service is no prepared to handle the unicode format that the
            # gene symbols are in when we retrieve them from the models.
            gene_rank_url = "{0}?hpo={1}&genes={2}".format(
                settings.GENE_RANK_BASE_URL, ",".join(hpo_terms),
                ",".join([str(g) for g in genes]))

            try:
                gene_response = requests.get(gene_rank_url)
            except Exception:
                log.exception('Error retrieving gene rankings, skipping '
                              'sample "{0}".'.format(sample.label))
                continue

            gene_data = json.loads(gene_response.content)
            ranked_genes = gene_data['ranked_genes']

            updated_results = 0
            total_results = 0
            for result in sample.results.all():
                total_results += 1

                with transaction.commit_manually(database):
                    try:
                        # Get the gene for this result. Since a result can
                        # have more than one gene associated with it, we
                        # return the first gene symbol in the list. This is
                        # the same one that will be shown in the collapsed
                        # gene list on the variant row in the results table.
                        gene = result.variant.effects.values_list(
                            'transcript__gene__symbol', flat=True)[0]

                        # If there is no gene on this result or the gene is
                        # not found in the list of ranked genes then skip this
                        # result.
                        if not gene:
                            log.debug("Result with id {0} has no gene, "
                                      "skipping result.".format(result.id))
                            transaction.rollback()
                            continue

                        # Get the first item in the ranked gene list with a
                        # symbol matching the gene we looked up above for this
                        # result.
                        ranked_gene = next(
                            (r for r in ranked_genes if
                             r.get('symbol', '').lower() == gene.lower()),
                            None)

                        if not ranked_gene:
                            log.debug("Could not find '{0}' in ranked gene "
                                      "list, skipping result".format(gene))
                            transaction.rollback()
                            continue

                        try:
                            rs = ResultScore.objects.get(result=result)
                            rs.rank = ranked_gene.get('rank', None)
                            rs.score = ranked_gene.get('score', None)
                        except ResultScore.DoesNotExist:
                            rs = ResultScore(
                                result=result,
                                rank=ranked_gene.get('rank', None),
                                score=ranked_gene.get('score', None))
                        rs.save()

                        updated_results += 1

                    except Exception:
                        log.exception("Error saving gene ranks and scores for "
                                      "sample '{0}'".format(sample.label))
                        transaction.rollback()
                        continue

                    transaction.commit()

            sample.phenotype_modified = datetime.now()
            sample.save()

            log.info("Updated {0} and skipped {1} results in sample '{2}'"
                     .format(updated_results, total_results - updated_results,
                             sample.label))
            updated_samples += 1

        log.info("Updated {0} and skipped {1} samples"
                 .format(updated_samples, total_samples-updated_samples))
<commit_msg>Remove redundant default arguments on get methods<commit_after>import json
import logging
import requests
from datetime import datetime
from django.conf import settings
from optparse import make_option
from django.db import transaction, DEFAULT_DB_ALIAS
from django.core.management.base import BaseCommand
from requests.exceptions import SSLError, ConnectionError, RequestException
from varify.samples.models import Sample, ResultScore

log = logging.getLogger(__name__)

class Command(BaseCommand):
    args = '<sample_label sample_label ...>'
    option_list = BaseCommand.option_list + (
        make_option('--database', action='store', dest='database',
                    default=DEFAULT_DB_ALIAS,
                    help='Specifies the target database to load results.'),
        make_option('--force', action='store_true', dest='force',
                    default=False,
                    help='Forces recomputation of all gene rankings')
    )

    def handle(self, *args, **options):
        if not getattr(settings, 'PHENOTYPE_ENDPOINT', None):
            log.error('PHENOTYPE_ENDPOINT must be defined in settings for '
                      'gene rankings to be updated.')
            return

        if not getattr(settings, 'GENE_RANK_BASE_URL', None):
            log.error('GENE_RANK_BASE_URL must be defined in settings for '
                      'gene rankings to be updated.')
            return

        if (not getattr(settings, 'VARIFY_CERT', None) or
                not getattr(settings, 'VARIFY_KEY', None)):
            log.error('VARIFY_CERT and VARIFY_KEY must be defined in settings '
                      'for gene rankings to be updated.')
            return

        database = options.get('database')
        force = options.get('force')

        # Construct the cert from the setting to use in requests to the
        # phenotype endpoint.
        cert = (settings.VARIFY_CERT, settings.VARIFY_KEY)

        # We ignore all the samples that aren't published. They aren't visible
        # to the user so we don't bother updating related scores. If there
        # were sample labels supplied as arguments then we limit the rankings
        # updates to those samples, otherwise we process all samples.
        samples = Sample.objects.filter(published=True)

        if args:
            samples = samples.filter(label__in=args)

        updated_samples = 0
        total_samples = 0

        for sample in samples:
            total_samples += 1

            # Construct the URL from the setting and the sample label. The
            # sample label is used to retrieve the phenotype info on the remote
            # endpoint.
            url = settings.PHENOTYPE_ENDPOINT.format(sample.label)

            # Get the phenotype information for this sample. If the
            # phenotype is unavailable then we can skip this sample.
            try:
                response = requests.get(url, cert=cert, verify=False)
            except SSLError:
                log.exception('Skipping sample "{0}". An SSLError occurred '
                              'during phenotype retrieval request.'
                              .format(sample.label))
                continue
            except ConnectionError:
                log.exception('Skipping sample "{0}". A ConnectionError '
                              'occurred during phenotype retrieval request.'
                              .format(sample.label))
                continue
            except RequestException:
                log.exception('Skipping sample "{0}". The sample has no '
                              'phenotype data associated with it'
                              .format(sample.label))
                continue

            try:
                phenotype_data = json.loads(response.content)
            except ValueError:
                log.error("Could not parse response from {0}, skipping '{1}'."
                          .format(url, sample.label))
                continue

            try:
                phenotype_modified = datetime.strptime(
                    phenotype_data['last_modified'], "%Y-%m-%dT%H:%M:%S.%f")
            except ValueError:
                phenotype_modified = datetime.min
                log.warn("Could not parse 'last_modified' field on phenotype "
                         "data. Using datetime.min so that only unranked "
                         "samples will be ranked. If the 'force' flag was "
                         "used then all samples will be updated despite this "
                         "parsing failure.")

            # If the parsed response doesn't contain any HPO terms then we can
            # skip this sample since we cannot rank genes without HPO terms.
            if not phenotype_data.get('hpoAnnotations'):
                log.error("Response from phenotype missing HPO Annotations, "
                          "skipping '{0}'.".format(sample.label))
                continue

            if (not force and sample.phenotype_modified and
                    sample.phenotype_modified > phenotype_modified):
                log.debug("Sample '{0}' is already up to date, skipping it."
                          .format(sample.label))
                continue

            # Extract the HPO terms from the data returned from the phenotype
            # endpoint. We need to modify the terms a bit because the phenotype
            # endpoint has terms in the form 'HP_0011263' and the gene ranking
            # enpoint expects them to be of the form 'HP:0011263'.
            hpo_terms = []
            for hpo_annotation in phenotype_data['hpoAnnotations']:
                try:
                    hpo_id = str(hpo_annotation.get('hpo_id'))
                except AttributeError:
                    continue

                if hpo_id:
                    hpo_terms.append(hpo_id.replace('_', ':'))

            # If there are no HPO terms then there will be no rankings so skip
            # this sample to avoid any more computations and requests.
            if not hpo_terms:
                log.warning('Skipping "{0}" because it has no HPO terms '
                            'associated with it.'.format(sample.label))
                continue

            # Compute the unique gene list for the entire sample
            genes = set(sample.results.values_list(
                'variant__effects__transcript__gene__symbol', flat=True))

            # Obviously, if there are no genes then the gene ranking endpoint
            # will have nothing to do so we can safely skip this sample.
            if not genes:
                log.warning('Skipping "{0}" because it has no genes '
                            'associated with it.'.format(sample.label))
                continue

            # We need to convert the genes to strings because the ranking
            # service is no prepared to handle the unicode format that the
            # gene symbols are in when we retrieve them from the models.
            gene_rank_url = "{0}?hpo={1}&genes={2}".format(
                settings.GENE_RANK_BASE_URL, ",".join(hpo_terms),
                ",".join([str(g) for g in genes]))

            try:
                gene_response = requests.get(gene_rank_url)
            except Exception:
                log.exception('Error retrieving gene rankings, skipping '
                              'sample "{0}".'.format(sample.label))
                continue

            gene_data = json.loads(gene_response.content)
            ranked_genes = gene_data['ranked_genes']

            updated_results = 0
            total_results = 0
            for result in sample.results.all():
                total_results += 1

                with transaction.commit_manually(database):
                    try:
                        # Get the gene for this result. Since a result can
                        # have more than one gene associated with it, we
                        # return the first gene symbol in the list. This is
                        # the same one that will be shown in the collapsed
                        # gene list on the variant row in the results table.
                        gene = result.variant.effects.values_list(
                            'transcript__gene__symbol', flat=True)[0]

                        # If there is no gene on this result or the gene is
                        # not found in the list of ranked genes then skip this
                        # result.
                        if not gene:
                            log.debug("Result with id {0} has no gene, "
                                      "skipping result.".format(result.id))
                            transaction.rollback()
                            continue

                        # Get the first item in the ranked gene list with a
                        # symbol matching the gene we looked up above for this
                        # result.
                        ranked_gene = next(
                            (r for r in ranked_genes if
                             r.get('symbol').lower() == gene.lower()),
                            None)

                        if not ranked_gene:
                            log.debug("Could not find '{0}' in ranked gene "
                                      "list, skipping result".format(gene))
                            transaction.rollback()
                            continue

                        try:
                            rs = ResultScore.objects.get(result=result)
                            rs.rank = ranked_gene.get('rank')
                            rs.score = ranked_gene.get('score')
                        except ResultScore.DoesNotExist:
                            rs = ResultScore(
                                result=result,
                                rank=ranked_gene.get('rank'),
                                score=ranked_gene.get('score'))
                        rs.save()

                        updated_results += 1

                    except Exception:
                        log.exception("Error saving gene ranks and scores for "
                                      "sample '{0}'".format(sample.label))
                        transaction.rollback()
                        continue

                    transaction.commit()

            sample.phenotype_modified = datetime.now()
            sample.save()

            log.info("Updated {0} and skipped {1} results in sample '{2}'"
                     .format(updated_results, total_results - updated_results,
                             sample.label))
            updated_samples += 1

        log.info("Updated {0} and skipped {1} samples"
                 .format(updated_samples, total_samples-updated_samples))
<|endoftext|>


<commit_before>from scrapy.http import Request
from scrapy import log
from parser import Parser
from scrapy.selector import Selector
from FourmiCrawler.items import Result
import re

class WikipediaParser(Parser):

# General notes:
# Redirects seem to not matter as Wikipedia returns the page the redirect forwards to
# although this might lead to scraping both the original and the redirect with the same data.

    website = "http://en.wikipedia.org/wiki/*"
    __spider = None
    searched_compounds = []

    def __init__(self):
        pass

    def parse(self, response):
        print response.url
        log.msg('A response from %s just arrived!' % response.url, level=log.DEBUG)
        sel = Selector(response)
        compound = sel.xpath('//h1[@id="firstHeading"]//span/text()').extract()[0]
        if compound in self.searched_compounds:
            return None
        else:
            items = self.parse_infobox(sel)
            self.searched_compounds.append(compound)
            return items

    def parse_infobox(self, sel):

        items = []

        tr_list = sel.xpath('.//table[@class="infobox bordered"]//td[not(@colspan)]').xpath('normalize-space(string())')
        prop_names = tr_list[::2]
        prop_values = tr_list[1::2]
        for i, prop_name in enumerate(prop_names):
            item = Result({
                'attribute': prop_name.extract().encode('utf-8'),
                'value': prop_values[i].extract().encode('utf-8'),
                'source': "Wikipedia",
                'reliability': "",
                'conditions': ""
            })
            items.append(item)
            log.msg('Wiki prop: |%s| |%s| |%s|' % (item['attribute'], item['value'], item['source']), level=log.DEBUG)
        items = filter(lambda a: a['value'] != '', items)  # remove items with an empty value
        itemlist = self.cleanitems(items)

        # request=Request(self.getchemspider(sel))
        # itemlist.append(request)

        identifiers = self.get_identifiers(sel)
        # print identifiers

        for i, identifier in enumerate(identifiers):
            request = Request(identifier)
            print request

        # for identifier in self.get_identifiers(sel):
        #     request_identifier=Request(identifier)
        #     # print request_identifier
        #     itemlist.append(request_identifier)

        return itemlist

    def new_compound_request(self, compound):
        return Request(url=self.website[:-1] + compound, callback=self.parse)

    def cleanitems(self, items):
        for item in items:
            value = item['value']
            m = re.search('F;\s(\d+[\.,]?\d*)', value)
            if m:
                item['value'] = m.group(1) + " K"
            m = re.match('(\d+[\.,]?\d*)\sJ\sK.+mol', value)
            if m:
                print item['value']
                item['value'] = m.group(1) + " J/K/mol"
            print item['value']
        return items

    def get_identifiers(self, sel):
        links = sel.xpath('//span[contains(concat(" ",normalize-space(@class)," "),"reflink")]/a'
                          '[contains(concat(" ",normalize-space(@class)," "),"external")]/@href').extract()

        print links
        return links<commit_msg>Fixed problem with strange urls, now adds all external identifiers as requests<commit_after>from scrapy.http import Request
from scrapy import log
from parser import Parser
from scrapy.selector import Selector
from FourmiCrawler.items import Result
import re

class WikipediaParser(Parser):

# General notes:
# Redirects seem to not matter as Wikipedia returns the page the redirect forwards to
# although this might lead to scraping both the original and the redirect with the same data.

    website = "http://en.wikipedia.org/wiki/*"
    __spider = None
    searched_compounds = []

    def __init__(self):
        pass

    def parse(self, response):
        print response.url
        log.msg('A response from %s just arrived!' % response.url, level=log.DEBUG)
        sel = Selector(response)
        compound = sel.xpath('//h1[@id="firstHeading"]//span/text()').extract()[0]
        if compound in self.searched_compounds:
            return None
        else:
            items = self.parse_infobox(sel)
            self.searched_compounds.append(compound)
            return items

    def parse_infobox(self, sel):

        items = []

        tr_list = sel.xpath('.//table[@class="infobox bordered"]//td[not(@colspan)]').xpath('normalize-space(string())')
        prop_names = tr_list[::2]
        prop_values = tr_list[1::2]
        for i, prop_name in enumerate(prop_names):
            item = Result({
                'attribute': prop_name.extract().encode('utf-8'),
                'value': prop_values[i].extract().encode('utf-8'),
                'source': "Wikipedia",
                'reliability': "",
                'conditions': ""
            })
            items.append(item)
            log.msg('Wiki prop: |%s| |%s| |%s|' % (item['attribute'], item['value'], item['source']), level=log.DEBUG)
        items = filter(lambda a: a['value'] != '', items)  # remove items with an empty value
        itemlist = self.cleanitems(items)

        identifiers = self.get_identifiers(sel)

        for i, identifier in enumerate(identifiers):
            if re.match('//en\.wikipedia',identifier):
                pass
            elif re.match('/{2}',identifier):
                identifier = re.sub("/{2}", "http://", identifier)
                request = Request(identifier)
            else:
                request = Request(identifier)
            itemlist.append(request)

        return itemlist

    def new_compound_request(self, compound):
        return Request(url=self.website[:-1] + compound, callback=self.parse)

    def cleanitems(self, items):
        for item in items:
            value = item['value']
            m = re.search('F;\s(\d+[\.,]?\d*)', value)
            if m:
                item['value'] = m.group(1) + " K"
            m = re.match('(\d+[\.,]?\d*)\sJ\sK.+mol', value)
            if m:
                print item['value']
                item['value'] = m.group(1) + " J/K/mol"
            print item['value']
        return items

    def get_identifiers(self, sel):
        links = sel.xpath('//span[contains(concat(" ",normalize-space(@class)," "),"reflink")]/a'
                          '[contains(concat(" ",normalize-space(@class)," "),"external")]/@href').extract()
        return links<|endoftext|>


<commit_before>#! /usr/bin/env python3
"""
@name:      Install.add_user
@author:    D. Brian Kimmel
@contact:   D.BrianKimmel@gmail.com
@copyright: (c) 2015-2015 by D. Brian Kimmel
@license:   MIT License
@note:      Created Dec 8, 2015
@Summary:   Add a 'PyHouse' user.

"""

#  Import system stuff
import os
import platform
import pwd
import shutil
import subprocess

SUDOERS = '/etc/sudoers'
SUDO_DIR = ' /etc/sudoers.d/'

class AddUser(object):
    """
    """

    def _add_linux(self, p_username):
        subprocess.call(['sudo ', 'adduser ', '--disabled-login ', p_username])

    def _create_ssh(self):
        pass

    def add_one(self, p_username):
        l_sys = platform.system()
        print(l_sys)
        if l_sys == 'Linux':
            self._add_linux(p_username)

class User(object):
    """ Install the pyhouse user
    """

    @staticmethod
    def _create_workspace(p_user):
        print(' ')
        l_dir = '/home/' + p_user + '/workspace'
        l_user = pwd.getpwnam('pyhouse')
        if not os.path.isdir(l_dir):
            print('Creating a directory {}'.format(l_dir))
            subprocess.call(['sudo', 'mkdir', l_dir])
            #  os.makedirs(l_dir)
            subprocess.call(['sudo', 'chown', l_user.pw_uid + ':' + l_user.pw_gid, l_dir])
            #  os.chown(l_dir, l_user.pw_uid, l_user.pw_gid)

    @staticmethod
    def _update_sudoers(p_user):
        """Put new user into the /etc/sudoers.d
        """
        l_dir = 'PyHouse_Install/src/files'
        print(' Allowing user "{}" FULL access to the system via sudo.'.format(p_user))
        try:
            for l_file in os.listdir(l_dir):
                if l_file.startswith('sudo-'):
                    l_from = os.path.join(l_dir, l_file)
                    l_to = os.path.join(SUDO_DIR, l_file[5:])
                    print('--files "{}" -- "{}"'.format(l_from, l_to))
                    subprocess.call(['sudo', 'cp', l_from, l_to])
                    subprocess.call(['sudo', 'chmod', '440', l_to])
        except (OSError, IOError) as e_err:
            print(' ** ERROR ** {}'.format(e_err))
        print(' ')

    @staticmethod
    def _add_user(p_user):
        """
        """
        subprocess.call(['sudo', 'adduser', '--disabled-login', 'pyhouse'])
        subprocess.call(['sudo', 'usermod', '-a', '--groups', 'dialout', 'pyhouse'])
        print('  Added user "{}"'.format(p_user))
        print('  You MUST change that users password.\n')

    @staticmethod
    def _do_user_create(p_user):
        """ Do everything to add a pyhouse user.
        """
        print('  Creating user: "{}"'.format(p_user))
        try:
            pwd.getpwnam(p_user)
            print('*** User "{}" already exixts!  Skipping Add'.format(p_user))
        except KeyError:
            User._add_user(p_user)

    @staticmethod
    def add_one_user(p_user):
        """ This will add the pyhouse user from setup.py
        """
        print(' Adding user "{}" now.'.format(p_user))
        User._do_user_create(p_user)
        User._update_sudoers(p_user)
        User._create_workspace(p_user)

if __name__ == "__main__":
    print(' Running  Install/add_user.py ...')
    l_api = AddUser()
    l_api.add_one('pyhouse')
    print(' Finished add_user.py\n')

#  ## END DBK
<commit_msg>Debugging<commit_after>#! /usr/bin/env python3
"""
@name:      Install.add_user
@author:    D. Brian Kimmel
@contact:   D.BrianKimmel@gmail.com
@copyright: (c) 2015-2015 by D. Brian Kimmel
@license:   MIT License
@note:      Created Dec 8, 2015
@Summary:   Add a 'PyHouse' user.

"""

#  Import system stuff
import os
import platform
import pwd
import subprocess

SUDOERS = '/etc/sudoers'
SUDO_DIR = '/etc/sudoers.d/'

class AddUser(object):
    """
    """

    def _add_linux(self, p_username):
        subprocess.call(['sudo ', 'adduser ', '--disabled-login ', p_username])

    def _create_ssh(self):
        pass

    def add_one(self, p_username):
        l_sys = platform.system()
        print(l_sys)
        if l_sys == 'Linux':
            self._add_linux(p_username)

class User(object):
    """ Install the pyhouse user
    """

    @staticmethod
    def _create_workspace(p_user):
        print(' ')
        l_dir = '/home/' + p_user + '/workspace'
        #  l_user = pwd.getpwnam('pyhouse')
        if not os.path.isdir(l_dir):
            print('Creating a directory {}'.format(l_dir))
            subprocess.call(['sudo', 'mkdir', l_dir])
            #  os.makedirs(l_dir)
            subprocess.call(['sudo', 'chown', p_user + ':' + p_user, l_dir])
            #  os.chown(l_dir, l_user.pw_uid, l_user.pw_gid)

    @staticmethod
    def _update_sudoers(p_user):
        """Put new user into the /etc/sudoers.d
        """
        l_dir = './PyHouse_Install/src/files/'
        print(' Allowing user "{}" FULL access to the system via sudo.'.format(p_user))
        try:
            for l_file in os.listdir(l_dir):
                if l_file.startswith('sudo-'):
                    l_from = os.path.join(l_dir, l_file)
                    l_to = os.path.join(SUDO_DIR, l_file[5:])
                    print('--files "{}" -- "{}"'.format(l_from, l_to))
                    subprocess.call(['sudo', 'cp', l_from, l_to])
                    subprocess.call(['sudo', 'chmod', '440', l_to])
        except (OSError, IOError) as e_err:
            print(' ** ERROR ** {}'.format(e_err))
        print(' ')

    @staticmethod
    def _add_user(p_user):
        """
        """
        subprocess.call(['sudo', 'adduser', '--disabled-login', 'pyhouse'])
        subprocess.call(['sudo', 'usermod', '-a', '--groups', 'dialout', 'pyhouse'])
        print('  Added user "{}"'.format(p_user))
        print('  You MUST change that users password.\n')

    @staticmethod
    def _do_user_create(p_user):
        """ Do everything to add a pyhouse user.
        """
        print('  Creating user: "{}"'.format(p_user))
        try:
            pwd.getpwnam(p_user)
            print('*** User "{}" already exixts!  Skipping Add'.format(p_user))
        except KeyError:
            User._add_user(p_user)

    @staticmethod
    def add_one_user(p_user):
        """ This will add the pyhouse user from setup.py
        """
        print(' Adding user "{}" now.'.format(p_user))
        User._do_user_create(p_user)
        User._update_sudoers(p_user)
        User._create_workspace(p_user)

if __name__ == "__main__":
    print(' Running  Install/add_user.py ...')
    l_api = AddUser()
    l_api.add_one('pyhouse')
    print(' Finished add_user.py\n')

#  ## END DBK
<|endoftext|>