<commit_before>import random
from Vect2 import *
import pyglet
#Constant to tune for ship's acceleration per frame
SHIP_ACC = 1;
SHIP_TURN = 5 * math.pi/180
MAX_VELOCITY = 300
#Score and game init constants
HIT_POINTS=100
INIT_LIVES=3

#Helper function to create batch-friendly line loops for GL_LINES primatives
def loop_lines(points):
     #test if points are even
    out = []
    if len(points) % 2 != 0:
        raise ValueError("Uneven list of points")
    i = 0
    while i < len(points) - 3:
        out.extend(points[i:i+4])
        i += 2
    out.extend(points[-2::])
    out.extend(points[0:2])
    return tuple(out)

class Entity(object):
    #Process user input, if relevant.
    def input(self, controller):
        pass

    #Update whatever changes in this object over time
    def update(self, dt):
        pass

    #Render the object, if applicable.
    def draw(self):
        pass

    def isAlive(self):
        #Meant to be overriden on mortal objects
        return True

#An entity that can move with basic physics
class Movable(Entity):
    def __init__(self, position=Vect2(0,0), velocity=Vect2(0,0), acceleration=Vect2(0,0), angle=0, bounds= ( 0, 0, 800, 400 )) :
        self.pos = position
        self.vel = velocity
        self.acc = acceleration
        self.angle = angle
        self.bounds = bounds

    #generate new position and velocity.  Let DT be the time since the last update.
    def update(self, dt):
        self.vel += self.acc
        self.acc *= 0 #Acceleration must be added each time.
        self.pos += (self.vel * dt)
        #Add bounds checking
        if self.pos.x < self.bounds[0]:
            self.pos.x = self.bounds[2]
        elif self.pos.x > self.bounds[2]:
            self.pos.x = self.bounds[0]
        if self.pos.y < self.bounds[1]:
            self.pos.y = self.bounds[3]
        elif self.pos.y > self.bounds[3]:
            self.pos.y = self.bounds[1]

    def addAcc(self, acc):
        self.acc += acc

    def overlaps(self, hitRadius, hitPos):
        #if this entity is inside the other entity's radius, return true
        return (self.pos.getDistance(hitPos) < hitRadius)

class Inertial(Movable):
    def __init__(self, mass=1.0, **kwargs):
        super(Inertial, self).__init__(**kwargs)
        self.mass=mass

    def addForce(self, fVect):
        self.acc += (fVect.getCopy() * (1.0/self.mass))

#Player is an object with movement, controlled by user input
class Player(Inertial):
    def __init__(self, pos=Vect2(0,0)):
        super(Player, self).__init__(mass = 1, position=pos)
        self.firing = False
        self.FIRE_DELAY = 1
        self.cooldown = self.FIRE_DELAY
        self.alive = True
        self.invuln = 3 #3 seconds of invulnerability on spawning

    #Controller is a dict containing the state of the controls
    def input(self, controller):
        if (controller["fire"] and self.cooldown >= self.FIRE_DELAY):
            self.firing = True
            self.cooldown = 0
        if (controller["acc"]):
            #There's a bit going on here.  We create a normal vector pointing at the ship's heading
            #And then we scale it to the acceleration per frame constant.
            self.acc += Vect2.fromAngle(self.angle) * SHIP_ACC
        if (controller["left"]):
            self.angle += SHIP_TURN
        if (controller["right"]):
            self.angle -= SHIP_TURN

    #Check if player is firing for the main loop to determine if it should spawn bullets
    def isFiring(self):
        if(self.firing):
            self.firing = False
            return True
        else:
            return False

    def draw(self):
        #Return a "data object" for pyglet's graphics.draw command.
        #front of the ship
        bow = ( Vect2.fromAngle(self.angle) * 10 ) + self.pos
        port = (Vect2.fromAngle(self.angle + (120 * math.pi/180)) * 5) + self.pos
        starboard = (Vect2.fromAngle(self.angle - (120 * math.pi/180)) *5) + self.pos
        points = (bow.x, bow.y, port.x, port.y, starboard.x, starboard.y)
        points = loop_lines(points)
        return len(points)//2, pyglet.gl.GL_LINES, None, ( 'v2f', points )

    def update(self, dt):
        super().update(dt)
        if self.vel.mag() > MAX_VELOCITY:
            self.vel = self.vel.normalize() * MAX_VELOCITY
        if self.cooldown < self.FIRE_DELAY:
            self.cooldown += dt
        if self.invuln > 0:
            self.invuln -= dt
            #print(self.invuln)

    def kill(self):
        #ignore call if in respawn period
        if self.invuln < 0:
            self.alive = False

    def isAlive(self):
        return self.alive

class Asteroid(Inertial):
    def __init__(self, size=3, position=Vect2(0,0)):
        #Asteroids come in 3 sizes: 3 is biggest, one is smallest.
        super(Asteroid, self).__init__(mass=size, position=position)
        #FIXME: Magic constant
        self.addForce(Vect2.random()* 100)
        self.hit_radius = size*10
        self.size = size
        #property to check on deletion loop
        self.alive = True
        self.angleV = random.uniform(-1, 1)
        #Consider making angular velocity a property of spawning/velocity
        self.shape = []
        for i in range(0, 16):
            radius = self.hit_radius * random.uniform(.75, 1.25)
            self.shape.append(math.cos(2*math.pi*i/15)*radius)
            self.shape.append(math.sin(2*math.pi*i/15)*radius)

    def update(self, dt):
        super().update(dt)
        self.angle += self.angleV
    def isAlive(self):
        return self.alive

    def draw(self):
        points = []
        radius = self.hit_radius
        for i, e in enumerate(self.shape):
            if i % 2 == 0:
                points.append(e + self.pos.x)
            else:
                points.append(e + self.pos.y)
        points = loop_lines(points)
        return (len(points)//2, pyglet.gl.GL_LINES, None, ('v2f', points ))

    def kill(self):
        self.alive = False

class Bullet(Movable):
    def __init__(self, pos, angle, lifespan=4, speed=200):
        vel = Vect2(math.cos(angle)*speed, math.sin(angle)*speed)
        super(Bullet, self).__init__(position=pos, angle=angle, velocity=vel)
        self.life=lifespan

    def update(self, dt):
        super().update(dt)
        self.life -= dt

    def isAlive(self):
        return (self.life > 0)

    def draw(self):
        points = [math.cos(self.angle)*-5 + self.pos.x, math.sin(self.angle)*-5 + self.pos.y, math.cos(self.angle) + self.pos.x, math.sin(self.angle) + self.pos.y]
        return 2, pyglet.gl.GL_LINES, None, ('v2f', tuple(points)), ('c3B', (255,0,0,255,0,0))

    def kill(self):
        self.life = 0

class ParticleSpawner(Entity):
    def __init__(self, pos, angle, spread, rate, particlefactory, active=False):
        self.pos = pos
        self.angle = angle
        self.spread = spread
        self.active = active
        self.rate = rate
        self.timer = rate
        self.particlefactory = particlefactory
        self.children = []

    def update(self, dt):
        if(self.timer < 0 and self.active):
            self.timer = self.rate
            self.children.append(self.particlefactory.spawn(self.pos, self._make_angle()))
        else:
            self.timer -= dt
        for child in self.children:
            child.update(dt)
        self.children[:] = [child for child in self.children if child.isAlive()]

    def _make_angle(self):
        return random.uniform(self.angle-(self.spread/2), self.angle+(self.spread/2))

    def draw(self):
        merged_out = [0, pyglet.gl.GL_POINTS, None,['v2f', []], ['c3B', []]]
        for child_ in self.children:
            child = child_.draw()
            merged_out[0]+=1
            merged_out[3][1].extend(child[3][1])
            merged_out[4][1].extend(child[4][1])
        merged_out[3][1] = tuple( merged_out[3][1] )
        merged_out[3] = tuple( merged_out[3] )
        merged_out[4][1] = tuple( merged_out[4][1] )
        merged_out[4] = tuple( merged_out[4])
        return tuple(merged_out)

"""
ParticleFactory defines particles for ParticleSpawner to emit.
"""
class ParticleFactory(object):
    def __init__(self, speed=1, lifespan=3, color=(255,255,255)):
        self.speed = speed
        self.lifespan = lifespan
        self.color = color

    def spawn(self, pos, angle):
        return ParticleFactory.Particle(pos=pos, angle=angle, speed=self.speed, color=self.color, lifespan=self.lifespan)

    class Particle(Movable):
        def __init__(self, pos, angle, speed, color, lifespan):
            super(ParticleFactory.Particle, self).__init__(position=pos, velocity=( ( Vect2.fromAngle(angle) ) * speed))
            self.color = color
            self.lifespan=lifespan

        def draw(self):
            return 1, pyglet.gl.GL_POINTS, None, ('v2f', (self.pos.x, self.pos.y)), ('c3b', self.color)

        def update(self, dt):
            super().update(dt)
            self.lifespan -= dt

        def isAlive(self):
            return (self.lifespan > 0)

#Particle spawner that dies after given time
class MortalEmitter(ParticleSpawner):
    def __init__(self, pos, angle, spread, rate, particlefactory, lifespan, active=True):
        super(MortalEmitter, self).__init__(pos, angle, spread, rate, particlefactory, active)
        self.lifespan = lifespan

    def update(self, dt):
        super().update(dt)
        self.lifespan -= dt
        #Stop emitting new particles if the system will die in less time than the particles' lifespan
        if (self.lifespan < self.particlefactory.lifespan):
            self.active = False

    def isAlive(self):
        return ( self.lifespan > 0 )

#Model for asteroid debris
class AsteroidDebris(MortalEmitter):
    def __init__(self, pos):
        super(AsteroidDebris, self).__init__(pos, 0, 2*math.pi, 0.01, ParticleFactory(speed=60, color=(255,255,0), lifespan=.3), 1, active=True)
<commit_msg>Change ship color on respawn<commit_after>import random
from Vect2 import *
import pyglet
#Constant to tune for ship's acceleration per frame
SHIP_ACC = 1;
SHIP_TURN = 5 * math.pi/180
MAX_VELOCITY = 300
#Score and game init constants
HIT_POINTS=100
INIT_LIVES=3

#Helper function to create batch-friendly line loops for GL_LINES primatives
def loop_lines(points):
     #test if points are even
    out = []
    if len(points) % 2 != 0:
        raise ValueError("Uneven list of points")
    i = 0
    while i < len(points) - 3:
        out.extend(points[i:i+4])
        i += 2
    out.extend(points[-2::])
    out.extend(points[0:2])
    return tuple(out)

class Entity(object):
    #Process user input, if relevant.
    def input(self, controller):
        pass

    #Update whatever changes in this object over time
    def update(self, dt):
        pass

    #Render the object, if applicable.
    def draw(self):
        pass

    def isAlive(self):
        #Meant to be overriden on mortal objects
        return True

#An entity that can move with basic physics
class Movable(Entity):
    def __init__(self, position=Vect2(0,0), velocity=Vect2(0,0), acceleration=Vect2(0,0), angle=0, bounds= ( 0, 0, 800, 400 )) :
        self.pos = position
        self.vel = velocity
        self.acc = acceleration
        self.angle = angle
        self.bounds = bounds

    #generate new position and velocity.  Let DT be the time since the last update.
    def update(self, dt):
        self.vel += self.acc
        self.acc *= 0 #Acceleration must be added each time.
        self.pos += (self.vel * dt)
        #Add bounds checking
        if self.pos.x < self.bounds[0]:
            self.pos.x = self.bounds[2]
        elif self.pos.x > self.bounds[2]:
            self.pos.x = self.bounds[0]
        if self.pos.y < self.bounds[1]:
            self.pos.y = self.bounds[3]
        elif self.pos.y > self.bounds[3]:
            self.pos.y = self.bounds[1]

    def addAcc(self, acc):
        self.acc += acc

    def overlaps(self, hitRadius, hitPos):
        #if this entity is inside the other entity's radius, return true
        return (self.pos.getDistance(hitPos) < hitRadius)

class Inertial(Movable):
    def __init__(self, mass=1.0, **kwargs):
        super(Inertial, self).__init__(**kwargs)
        self.mass=mass

    def addForce(self, fVect):
        self.acc += (fVect.getCopy() * (1.0/self.mass))

#Player is an object with movement, controlled by user input
class Player(Inertial):
    def __init__(self, pos=Vect2(0,0)):
        super(Player, self).__init__(mass = 1, position=pos)
        self.firing = False
        self.FIRE_DELAY = 1
        self.cooldown = self.FIRE_DELAY
        self.alive = True
        self.invuln = 3 #3 seconds of invulnerability on spawning

    #Controller is a dict containing the state of the controls
    def input(self, controller):
        if (controller["fire"] and self.cooldown >= self.FIRE_DELAY):
            self.firing = True
            self.cooldown = 0
        if (controller["acc"]):
            #There's a bit going on here.  We create a normal vector pointing at the ship's heading
            #And then we scale it to the acceleration per frame constant.
            self.acc += Vect2.fromAngle(self.angle) * SHIP_ACC
        if (controller["left"]):
            self.angle += SHIP_TURN
        if (controller["right"]):
            self.angle -= SHIP_TURN

    #Check if player is firing for the main loop to determine if it should spawn bullets
    def isFiring(self):
        if(self.firing):
            self.firing = False
            return True
        else:
            return False

    def draw(self):
        #Return a "data object" for pyglet's graphics.draw command.
        #front of the ship
        if (self.invuln > 0):
            color = (0,0,255);
        else:
            color = (255,255,255);
        bow = ( Vect2.fromAngle(self.angle) * 10 ) + self.pos
        port = (Vect2.fromAngle(self.angle + (120 * math.pi/180)) * 5) + self.pos
        starboard = (Vect2.fromAngle(self.angle - (120 * math.pi/180)) *5) + self.pos
        points = (bow.x, bow.y, port.x, port.y, starboard.x, starboard.y)
        points = loop_lines(points)
        return len(points)//2, pyglet.gl.GL_LINES, None, ( 'v2f', points ), ('c3B', color * ( len(points)//2) )

    def update(self, dt):
        super().update(dt)
        if self.vel.mag() > MAX_VELOCITY:
            self.vel = self.vel.normalize() * MAX_VELOCITY
        if self.cooldown < self.FIRE_DELAY:
            self.cooldown += dt
        if self.invuln > 0:
            self.invuln -= dt
            #print(self.invuln)

    def kill(self):
        #ignore call if in respawn period
        if self.invuln < 0:
            self.alive = False

    def isAlive(self):
        return self.alive

class Asteroid(Inertial):
    def __init__(self, size=3, position=Vect2(0,0)):
        #Asteroids come in 3 sizes: 3 is biggest, one is smallest.
        super(Asteroid, self).__init__(mass=size, position=position)
        self.addForce(Vect2.random()* 100)
        self.hit_radius = size*10
        self.size = size
        #property to check on deletion loop
        self.alive = True
        self.angleV = random.uniform(-1, 1)
        #Consider making angular velocity a property of spawning/velocity
        self.shape = []
        for i in range(0, 16):
            radius = self.hit_radius * random.uniform(.75, 1.25)
            self.shape.append(math.cos(2*math.pi*i/15)*radius)
            self.shape.append(math.sin(2*math.pi*i/15)*radius)

    def update(self, dt):
        super().update(dt)
        self.angle += self.angleV
    def isAlive(self):
        return self.alive

    def draw(self):
        points = []
        radius = self.hit_radius
        for i, e in enumerate(self.shape):
            if i % 2 == 0:
                points.append(e + self.pos.x)
            else:
                points.append(e + self.pos.y)
        points = loop_lines(points)
        return (len(points)//2, pyglet.gl.GL_LINES, None, ('v2f', points ))

    def kill(self):
        self.alive = False

class Bullet(Movable):
    def __init__(self, pos, angle, lifespan=4, speed=200):
        vel = Vect2(math.cos(angle)*speed, math.sin(angle)*speed)
        super(Bullet, self).__init__(position=pos, angle=angle, velocity=vel)
        self.life=lifespan

    def update(self, dt):
        super().update(dt)
        self.life -= dt

    def isAlive(self):
        return (self.life > 0)

    def draw(self):
        points = [math.cos(self.angle)*-5 + self.pos.x, math.sin(self.angle)*-5 + self.pos.y, math.cos(self.angle) + self.pos.x, math.sin(self.angle) + self.pos.y]
        return 2, pyglet.gl.GL_LINES, None, ('v2f', tuple(points)), ('c3B', (255,0,0,255,0,0))

    def kill(self):
        self.life = 0

class ParticleSpawner(Entity):
    def __init__(self, pos, angle, spread, rate, particlefactory, active=False):
        self.pos = pos
        self.angle = angle
        self.spread = spread
        self.active = active
        self.rate = rate
        self.timer = rate
        self.particlefactory = particlefactory
        self.children = []

    def update(self, dt):
        if(self.timer < 0 and self.active):
            self.timer = self.rate
            self.children.append(self.particlefactory.spawn(self.pos, self._make_angle()))
        else:
            self.timer -= dt
        for child in self.children:
            child.update(dt)
        self.children[:] = [child for child in self.children if child.isAlive()]

    def _make_angle(self):
        return random.uniform(self.angle-(self.spread/2), self.angle+(self.spread/2))

    def draw(self):
        merged_out = [0, pyglet.gl.GL_POINTS, None,['v2f', []], ['c3B', []]]
        for child_ in self.children:
            child = child_.draw()
            merged_out[0]+=1
            merged_out[3][1].extend(child[3][1])
            merged_out[4][1].extend(child[4][1])
        merged_out[3][1] = tuple( merged_out[3][1] )
        merged_out[3] = tuple( merged_out[3] )
        merged_out[4][1] = tuple( merged_out[4][1] )
        merged_out[4] = tuple( merged_out[4])
        return tuple(merged_out)

"""
ParticleFactory defines particles for ParticleSpawner to emit.
"""
class ParticleFactory(object):
    def __init__(self, speed=1, lifespan=3, color=(255,255,255)):
        self.speed = speed
        self.lifespan = lifespan
        self.color = color

    def spawn(self, pos, angle):
        return ParticleFactory.Particle(pos=pos, angle=angle, speed=self.speed, color=self.color, lifespan=self.lifespan)

    class Particle(Movable):
        def __init__(self, pos, angle, speed, color, lifespan):
            super(ParticleFactory.Particle, self).__init__(position=pos, velocity=( ( Vect2.fromAngle(angle) ) * speed))
            self.color = color
            self.lifespan=lifespan

        def draw(self):
            return 1, pyglet.gl.GL_POINTS, None, ('v2f', (self.pos.x, self.pos.y)), ('c3b', self.color)

        def update(self, dt):
            super().update(dt)
            self.lifespan -= dt

        def isAlive(self):
            return (self.lifespan > 0)

#Particle spawner that dies after given time
class MortalEmitter(ParticleSpawner):
    def __init__(self, pos, angle, spread, rate, particlefactory, lifespan, active=True):
        super(MortalEmitter, self).__init__(pos, angle, spread, rate, particlefactory, active)
        self.lifespan = lifespan

    def update(self, dt):
        super().update(dt)
        self.lifespan -= dt
        #Stop emitting new particles if the system will die in less time than the particles' lifespan
        if (self.lifespan < self.particlefactory.lifespan):
            self.active = False

    def isAlive(self):
        return ( self.lifespan > 0 )

#Model for asteroid debris
class AsteroidDebris(MortalEmitter):
    def __init__(self, pos):
        super(AsteroidDebris, self).__init__(pos, 0, 2*math.pi, 0.01, ParticleFactory(speed=60, color=(255,255,0), lifespan=.3), 1, active=True)
<|endoftext|>


<commit_before>import json
from parser import ParserError
from yaml.error import MarkedYAMLError
from future.builtins import (  # noqa
    bytes, dict, int, list, object, range, str,
    ascii, chr, hex, input, next, oct, open,
    pow, round, filter, map, zip)
import copy
import types
from jinja2 import TemplateSyntaxError
from jinja2.environment import get_spontaneous_environment
from jsonschema import validate, ValidationError
from repoze.lru import lru_cache
from conf.appconfig import CONFIG_PROVIDERS, CONFIG_PROVIDER_LIST, \
    BOOLEAN_TRUE_VALUES, DEFAULT_DEPLOYER_CONFIG, API_PORT, CONFIG_NAMES
from orchestrator.cluster_config.default import DefaultConfigProvider
from orchestrator.cluster_config.effective import MergedConfigProvider
from orchestrator.cluster_config.etcd import EtcdConfigProvider
from orchestrator.cluster_config.s3 import S3ConfigProvider
from orchestrator.jinja import conditions
from orchestrator.services.errors import ConfigProviderNotFound
from orchestrator.services.exceptions import ConfigValueError, \
    ConfigValidationError, ConfigParseError
from orchestrator.util import dict_merge

__author__ = 'sukrit'

def get_providers():
    for provider_type in CONFIG_PROVIDER_LIST:
        provider_type = provider_type.strip()
        if provider_type in CONFIG_PROVIDERS:
            yield provider_type
    yield 'effective'

def _get_effective_provider():
    """
    Gets the effective config provider.

    :return: Effective Config provider.
    :rtype: orchestrator.cluster_config.effective.MergedConfigProvider
    """
    providers = list()
    for provider_type in get_providers():
        if provider_type != 'effective':
            provider = get_provider(provider_type)
            if provider:
                providers.append(provider)

    if CONFIG_PROVIDERS['effective']['cache']['enabled']:
        cache_provider = _get_etcd_provider(
            ttl=CONFIG_PROVIDERS['effective']['cache']['ttl'])
    else:
        cache_provider = None
    return MergedConfigProvider(*providers, cache_provider=cache_provider)

def _get_etcd_provider(ttl=None):
    """
    Gets the etcd config provider.

    :keyword ttl: time to live in seconds
    :type ttl: number
    :return: Instance of EtcdConfigProvider
    :rtype: EtcdConfigProvider
    """
    return EtcdConfigProvider(
        etcd_host=CONFIG_PROVIDERS['etcd']['host'],
        etcd_port=CONFIG_PROVIDERS['etcd']['port'],
        config_base=CONFIG_PROVIDERS['etcd']['base']+'/config',
        ttl=ttl
    )

def _get_s3_provider():
    """
    Gets S3 Config Provider

    :return: Instance of S3ConfigProvider
    :rtype: S3ConfigProvider
    """
    return S3ConfigProvider(
        bucket=CONFIG_PROVIDERS['s3']['bucket'],
        config_base=CONFIG_PROVIDERS['s3']['base']
    )

def _get_default_provider():
    return DefaultConfigProvider()

@lru_cache(1)
def _load_job_schema():
    """
    Helper function that loads given schema

    :param schema_name:
    :return:
    """
    base_url = 'http://localhost:%d' % API_PORT
    fname = 'schemas/job-config-v1.json'
    with open(fname) as file:
        data = file.read().replace('${base_url}', base_url)
        return json.loads(data)

def get_provider(provider_type):
    """
    Factory method to create config provider instance.

    :param provider_type:
    :type provider_type: str
    :param args: Arguments for the provider
    :param kwargs: Keyword arguments for the provider.
    :return: AbstractConfigProvider instance.
    :rtype: AbstractConfigProvider
    """
    if provider_type not in get_providers():
        raise ConfigProviderNotFound(provider_type)

    locator = '_get_%s_provider' % (provider_type)
    if locator in globals():
        return globals()[locator]()

def validate_schema(config):
    """
    Validates schema for given configuration.

    :param config: Config dictionary
    :type config: dict
    :return: config if validation passes
    :rtype: dict
    """
    schema = _load_job_schema()
    try:
        validate(config, schema)
    except ValidationError as ex:
        message = 'Failed to validate config against schema job-config-v1. ' \
                  'Reason: %s' % ex.message
        raise ConfigValidationError(message, '/'.join(ex.schema_path),
                                    ex.schema)
    return config

def load_config(*paths, **kwargs):
    """
    Loads config for given path and provider type.

    :param paths: Tuple consisting of nested level path
    :type paths: tuple
    :keyword default_variables: Variables to be applied during template
    evaluation
    :type default_variables: dict
    :keyword provider_type: Type of provider
    :type provider_type: str
    :keyword config_names: List of config names to be loaded. Defaults to
        CONFIG_NAMES defined in appconfig
    :type config_names: list
    :return: Parsed configuration
    :rtype: dict
    """
    default_variables = kwargs.get('default_variables', {})
    provider_type = kwargs.get('provider_type', 'effective')
    config_names = kwargs.get('config_names', CONFIG_NAMES)
    provider = get_provider(provider_type)
    try:
        unified_config = dict_merge(
            *[provider.load(name, *paths) for name in config_names])
        return evaluate_config(
            validate_schema(unified_config),
            default_variables)

    except (MarkedYAMLError, ParserError) as yaml_error:
        raise ConfigParseError(yaml_error, paths)

def write_config(name, config, *paths, **kwargs):
    """
    Writes config for given path

    :param config: Dictionary based configuration
    :type config: dict
    :param provider_type: Type of provider
    :type provider_type: str
    :return: None
    """
    provider_type = kwargs.get('provider_type', 'effective')
    provider = get_provider(provider_type)
    if provider:
        provider.write(name, config, *paths)

def _get_jinja_environment():
    """
    Creates Jinja env for evaluating config

    :return: Jinja Environment
    """
    env = get_spontaneous_environment()
    env.line_statement_prefix = '#'
    return conditions.apply_conditions(env)

def evaluate_template(template_value, variables={}):
    env = _get_jinja_environment()
    return env.from_string(str(template_value)).render(**variables).strip()

def evaluate_variables(variables, default_variables={}):

    merged_vars = dict_merge({}, default_variables)

    def get_sort_key(item):
        return item[1]['priority']

    def as_tuple(vars):
        for variable_name, variable_val in vars.items():
            variable_val = copy.deepcopy(variable_val)
            if not hasattr(variable_val, 'items'):
                variable_val = {
                    'value': variable_val,
                    'template': False,
                    'priority': 0
                }
            variable_val.setdefault('template', True)
            variable_val.setdefault('priority', 1)
            variable_val.setdefault('value', '')
            val = variable_val['value']
            if isinstance(val, bool):
                variable_val['value'] = str(val).lower()
            yield (variable_name, variable_val)

    def expand(var_name, var_value):
        try:
            merged_vars[var_name] = evaluate_template(
                var_value['value'], merged_vars) if var_value['template'] \
                else var_value['value']
        except Exception as exc:
            raise ConfigValueError('/variables/%s/' % var_name, var_value,
                                   str(exc))

    sorted_vars = sorted(as_tuple(variables), key=get_sort_key)
    for sorted_var_name, sorted_var_value in sorted_vars:
        expand(sorted_var_name, sorted_var_value)

    return merged_vars

def evaluate_value(value, variables={}, location='/'):
    """
    Renders tokenized values (using nested strategy)

    :param value: Value that needs to be evaluated (str , list, dict, int etc)
    :param variables: Variables to be used for Jinja2 templates
    :param identifier: Identifier used to identify tokenized values. Only str
        values that begin with identifier are evaluated.
    :return: Evaluated object.
    """
    value = copy.deepcopy(value)
    if hasattr(value, 'items'):
        if 'variables' in value:
            variables = evaluate_variables(value['variables'], variables)
            del(value['variables'])

        if 'value' in value:
            value.setdefault('encrypted', False)
            value.setdefault('template', True)
            if value['template']:
                try:
                    value['value'] = evaluate_template(value['value'],
                                                       variables)
                except TemplateSyntaxError as error:
                    raise ConfigValueError(location, value['value'],
                                           reason=error.message)
            del(value['template'])
            if not value['encrypted']:
                value = value['value']
            return value

        else:
            for each_k, each_v in value.items():
                value[each_k] = evaluate_value(each_v, variables,
                                               '%s%s/' % (location, each_k))
            return {
                each_k: evaluate_value(each_v, variables)
                for each_k, each_v in value.items()
            }

    elif isinstance(value, (list, tuple, set, types.GeneratorType)):
        return [evaluate_value(each_v, variables, '%s[]/' % (location, ))
                for each_v in value]

    return value.strip() if isinstance(value, (str,)) else value

def evaluate_config(config, default_variables={}, var_key='variables'):
    """
    Performs rendering of all template values defined in config. Also takes
    user defined variables nd default variables for substitution in the config
    .
    :param config:
    :param default_variables:
    :param var_key:
    :return: Evaluated config
    :rtype: dict
    """
    updated_config = copy.deepcopy(config)
    updated_config.setdefault(var_key, {})
    updated_config.setdefault('deployers', {})

    for deployer_name, deployer in updated_config.get('deployers').items():
        if deployer.get('enabled', True):
            updated_config['deployers'][deployer_name] = dict_merge(
                deployer, DEFAULT_DEPLOYER_CONFIG)
        else:
            del(updated_config['deployers'][deployer_name])
    return transform_string_values(
        evaluate_value(updated_config, default_variables))

def transform_string_values(config):
    """
    Transforms the string values to appropriate type in config

    :param config: dictionary configuration with evaluated template parameters
    :type config: dict
    :return: transformed config
    :rtype: dict
    """
    new_config = copy.deepcopy(config)

    # Convert 'enabled' keys to boolean
    def convert_enabled_keys(use_config, location='/'):
        if hasattr(use_config, 'items'):
            for each_k, each_v in use_config.items():
                try:
                    if each_v is None:
                        continue
                    elif each_k == 'enabled' and isinstance(each_v, str):
                        use_config[each_k] = each_v.lower() in \
                            BOOLEAN_TRUE_VALUES
                    elif each_k in ('port', 'nodes', 'min-nodes') and \
                            isinstance(each_v, str):
                        use_config[each_k] = int(each_v)
                    elif hasattr(each_v, 'items'):
                        convert_enabled_keys(each_v, '%s%s/' %
                                             (location, each_k))
                    elif isinstance(each_v,
                                    (list, tuple, set, types.GeneratorType)):
                        for idx, val in enumerate(each_v):
                            convert_enabled_keys(
                                val, '%s%s[%d]/' % (location, each_k, idx))
                except ValueError as error:
                    raise ConfigValueError(location + each_k, each_v,
                                           error.message)

    convert_enabled_keys(new_config)
    return new_config
<commit_msg>Python3 compatibility fix<commit_after>import json
from parser import ParserError
from yaml.error import MarkedYAMLError
from future.builtins import (  # noqa
    bytes, dict, int, list, object, range, str,
    ascii, chr, hex, input, next, oct, open,
    pow, round, filter, map, zip)
import copy
import types
from jinja2 import TemplateSyntaxError
from jinja2.environment import get_spontaneous_environment
from jsonschema import validate, ValidationError
from repoze.lru import lru_cache
from conf.appconfig import CONFIG_PROVIDERS, CONFIG_PROVIDER_LIST, \
    BOOLEAN_TRUE_VALUES, DEFAULT_DEPLOYER_CONFIG, API_PORT, CONFIG_NAMES
from orchestrator.cluster_config.default import DefaultConfigProvider
from orchestrator.cluster_config.effective import MergedConfigProvider
from orchestrator.cluster_config.etcd import EtcdConfigProvider
from orchestrator.cluster_config.s3 import S3ConfigProvider
from orchestrator.jinja import conditions
from orchestrator.services.errors import ConfigProviderNotFound
from orchestrator.services.exceptions import ConfigValueError, \
    ConfigValidationError, ConfigParseError
from orchestrator.util import dict_merge

__author__ = 'sukrit'

def get_providers():
    for provider_type in CONFIG_PROVIDER_LIST:
        provider_type = provider_type.strip()
        if provider_type in CONFIG_PROVIDERS:
            yield provider_type
    yield 'effective'

def _get_effective_provider():
    """
    Gets the effective config provider.

    :return: Effective Config provider.
    :rtype: orchestrator.cluster_config.effective.MergedConfigProvider
    """
    providers = list()
    for provider_type in get_providers():
        if provider_type != 'effective':
            provider = get_provider(provider_type)
            if provider:
                providers.append(provider)

    if CONFIG_PROVIDERS['effective']['cache']['enabled']:
        cache_provider = _get_etcd_provider(
            ttl=CONFIG_PROVIDERS['effective']['cache']['ttl'])
    else:
        cache_provider = None
    return MergedConfigProvider(*providers, cache_provider=cache_provider)

def _get_etcd_provider(ttl=None):
    """
    Gets the etcd config provider.

    :keyword ttl: time to live in seconds
    :type ttl: number
    :return: Instance of EtcdConfigProvider
    :rtype: EtcdConfigProvider
    """
    return EtcdConfigProvider(
        etcd_host=CONFIG_PROVIDERS['etcd']['host'],
        etcd_port=CONFIG_PROVIDERS['etcd']['port'],
        config_base=CONFIG_PROVIDERS['etcd']['base']+'/config',
        ttl=ttl
    )

def _get_s3_provider():
    """
    Gets S3 Config Provider

    :return: Instance of S3ConfigProvider
    :rtype: S3ConfigProvider
    """
    return S3ConfigProvider(
        bucket=CONFIG_PROVIDERS['s3']['bucket'],
        config_base=CONFIG_PROVIDERS['s3']['base']
    )

def _get_default_provider():
    return DefaultConfigProvider()

@lru_cache(1)
def _load_job_schema():
    """
    Helper function that loads given schema

    :param schema_name:
    :return:
    """
    base_url = 'http://localhost:%d' % API_PORT
    fname = 'schemas/job-config-v1.json'
    with open(fname) as file:
        data = file.read().replace('${base_url}', base_url)
        return json.loads(data)

def get_provider(provider_type):
    """
    Factory method to create config provider instance.

    :param provider_type:
    :type provider_type: str
    :param args: Arguments for the provider
    :param kwargs: Keyword arguments for the provider.
    :return: AbstractConfigProvider instance.
    :rtype: AbstractConfigProvider
    """
    if provider_type not in get_providers():
        raise ConfigProviderNotFound(provider_type)

    locator = '_get_%s_provider' % (provider_type)
    if locator in globals():
        return globals()[locator]()

def validate_schema(config):
    """
    Validates schema for given configuration.

    :param config: Config dictionary
    :type config: dict
    :return: config if validation passes
    :rtype: dict
    """
    schema = _load_job_schema()
    try:
        validate(config, schema)
    except ValidationError as ex:
        message = 'Failed to validate config against schema job-config-v1. ' \
                  'Reason: %s' % ex.message
        raise ConfigValidationError(message, '/'.join(ex.schema_path),
                                    ex.schema)
    return config

def load_config(*paths, **kwargs):
    """
    Loads config for given path and provider type.

    :param paths: Tuple consisting of nested level path
    :type paths: tuple
    :keyword default_variables: Variables to be applied during template
    evaluation
    :type default_variables: dict
    :keyword provider_type: Type of provider
    :type provider_type: str
    :keyword config_names: List of config names to be loaded. Defaults to
        CONFIG_NAMES defined in appconfig
    :type config_names: list
    :return: Parsed configuration
    :rtype: dict
    """
    default_variables = kwargs.get('default_variables', {})
    provider_type = kwargs.get('provider_type', 'effective')
    config_names = kwargs.get('config_names', CONFIG_NAMES)
    provider = get_provider(provider_type)
    try:
        unified_config = dict_merge(
            *[provider.load(name, *paths) for name in config_names])
        return evaluate_config(
            validate_schema(unified_config),
            default_variables)

    except (MarkedYAMLError, ParserError) as yaml_error:
        raise ConfigParseError(yaml_error, paths)

def write_config(name, config, *paths, **kwargs):
    """
    Writes config for given path

    :param config: Dictionary based configuration
    :type config: dict
    :param provider_type: Type of provider
    :type provider_type: str
    :return: None
    """
    provider_type = kwargs.get('provider_type', 'effective')
    provider = get_provider(provider_type)
    if provider:
        provider.write(name, config, *paths)

def _get_jinja_environment():
    """
    Creates Jinja env for evaluating config

    :return: Jinja Environment
    """
    env = get_spontaneous_environment()
    env.line_statement_prefix = '#'
    return conditions.apply_conditions(env)

def evaluate_template(template_value, variables={}):
    env = _get_jinja_environment()
    return env.from_string(str(template_value)).render(**variables).strip()

def evaluate_variables(variables, default_variables={}):

    merged_vars = dict_merge({}, default_variables)

    def get_sort_key(item):
        return item[1]['priority']

    def as_tuple(vars):
        for variable_name, variable_val in vars.items():
            variable_val = copy.deepcopy(variable_val)
            if not hasattr(variable_val, 'items'):
                variable_val = {
                    'value': variable_val,
                    'template': False,
                    'priority': 0
                }
            variable_val.setdefault('template', True)
            variable_val.setdefault('priority', 1)
            variable_val.setdefault('value', '')
            val = variable_val['value']
            if isinstance(val, bool):
                variable_val['value'] = str(val).lower()
            yield (variable_name, variable_val)

    def expand(var_name, var_value):
        try:
            merged_vars[var_name] = evaluate_template(
                var_value['value'], merged_vars) if var_value['template'] \
                else var_value['value']
        except Exception as exc:
            raise ConfigValueError('/variables/%s/' % var_name, var_value,
                                   str(exc))

    sorted_vars = sorted(as_tuple(variables), key=get_sort_key)
    for sorted_var_name, sorted_var_value in sorted_vars:
        expand(sorted_var_name, sorted_var_value)

    return merged_vars

def evaluate_value(value, variables={}, location='/'):
    """
    Renders tokenized values (using nested strategy)

    :param value: Value that needs to be evaluated (str , list, dict, int etc)
    :param variables: Variables to be used for Jinja2 templates
    :param identifier: Identifier used to identify tokenized values. Only str
        values that begin with identifier are evaluated.
    :return: Evaluated object.
    """
    value = copy.deepcopy(value)
    if hasattr(value, 'items'):
        if 'variables' in value:
            variables = evaluate_variables(value['variables'], variables)
            del(value['variables'])

        if 'value' in value:
            value.setdefault('encrypted', False)
            value.setdefault('template', True)
            if value['template']:
                try:
                    value['value'] = evaluate_template(value['value'],
                                                       variables)
                except TemplateSyntaxError as error:
                    raise ConfigValueError(location, value['value'],
                                           reason=error.message)
            del(value['template'])
            if not value['encrypted']:
                value = value['value']
            return value

        else:
            for each_k, each_v in value.items():
                value[each_k] = evaluate_value(each_v, variables,
                                               '%s%s/' % (location, each_k))
            return {
                each_k: evaluate_value(each_v, variables)
                for each_k, each_v in value.items()
            }

    elif isinstance(value, (list, tuple, set, types.GeneratorType)):
        return [evaluate_value(each_v, variables, '%s[]/' % (location, ))
                for each_v in value]

    return value.strip() if isinstance(value, (str,)) else value

def evaluate_config(config, default_variables={}, var_key='variables'):
    """
    Performs rendering of all template values defined in config. Also takes
    user defined variables nd default variables for substitution in the config
    .
    :param config:
    :param default_variables:
    :param var_key:
    :return: Evaluated config
    :rtype: dict
    """
    updated_config = copy.deepcopy(config)
    updated_config.setdefault(var_key, {})
    updated_config.setdefault('deployers', {})

    for deployer_name, deployer in \
            list(updated_config.get('deployers').items()):
        if deployer.get('enabled', True):
            updated_config['deployers'][deployer_name] = dict_merge(
                deployer, DEFAULT_DEPLOYER_CONFIG)
        else:
            del(updated_config['deployers'][deployer_name])
    return transform_string_values(
        evaluate_value(updated_config, default_variables))

def transform_string_values(config):
    """
    Transforms the string values to appropriate type in config

    :param config: dictionary configuration with evaluated template parameters
    :type config: dict
    :return: transformed config
    :rtype: dict
    """
    new_config = copy.deepcopy(config)

    # Convert 'enabled' keys to boolean
    def convert_enabled_keys(use_config, location='/'):
        if hasattr(use_config, 'items'):
            for each_k, each_v in use_config.items():
                try:
                    if each_v is None:
                        continue
                    elif each_k == 'enabled' and isinstance(each_v, str):
                        use_config[each_k] = each_v.lower() in \
                            BOOLEAN_TRUE_VALUES
                    elif each_k in ('port', 'nodes', 'min-nodes') and \
                            isinstance(each_v, str):
                        use_config[each_k] = int(each_v)
                    elif hasattr(each_v, 'items'):
                        convert_enabled_keys(each_v, '%s%s/' %
                                             (location, each_k))
                    elif isinstance(each_v,
                                    (list, tuple, set, types.GeneratorType)):
                        for idx, val in enumerate(each_v):
                            convert_enabled_keys(
                                val, '%s%s[%d]/' % (location, each_k, idx))
                except ValueError as error:
                    raise ConfigValueError(location + each_k, each_v,
                                           error.message)

    convert_enabled_keys(new_config)
    return new_config
<|endoftext|>


<commit_before>from __future__ import absolute_import, print_function, unicode_literals
from builtins import dict, str
import pickle
import itertools
from copy import deepcopy
from os.path import join as pjoin
from pysb import Observable
from pysb.export.kappa import KappaExporter
from indra.tools import assemble_corpus as ac
from indra.tools.gene_network import GeneNetwork
from indra.assemblers import IndexCardAssembler
from indra.statements import *
from indra.assemblers import PysbAssembler, SifAssembler, CxAssembler

import process_data, process_r3, process_sparser, process_trips
from read_phosphosite import read_phosphosite

def build_prior(genes, out_file):
    gn = GeneNetwork(genes, 'korkut')
    stmts = gn.get_statements(filter=False)
    ac.dump_statements(stmts, out_file)
    return stmts

def read_sources():
    trips_stmts = process_trips.read_stmts(process_trips.base_folder)
    sparser_stmts = process_sparser.read_stmts(process_sparser.base_folder)
    r3_stmts = process_r3.read_stmts(process_r3.active_forms_file)
    stmts = trips_stmts + sparser_stmts + r3_stmts
    return stmts

def assemble_index_cards(stmts):
    counter = 1
    for st in stmts:
        if isinstance(st, Modification) and st.enz is None:
            continue
        pmids = [ev.pmid for ev in st.evidence if ev.pmid is not None]
        if pmids:
            pmids = ','.join(['PMID%s' % pm for pm in list(set(pmids))])
        else:
            pmids = 'N/A'
        ica = IndexCardAssembler([st], pmc_override=pmids)
        ica.make_model()
        if ica.cards:
            ica.save_model('output/index_cards/index_card_%d.json' % counter)
            counter += 1

def assemble_pysb(stmts, data_genes, out_file):
    """Return an assembled PySB model."""
    stmts = ac.filter_direct(stmts)
    stmts = ac.filter_belief(stmts, 0.95)
    stmts = ac.filter_top_level(stmts)
    stmts = ac.filter_gene_list(stmts, data_genes, 'all')
    stmts = ac.reduce_activities(stmts)
    pa = PysbAssembler()
    pa.add_statements(stmts)
    model = pa.make_model()
    # Add observables
    o = Observable('MAPK1p', model.monomers['MAPK1'](T185='p', Y187='p'))
    model.add_component(o)
    o = Observable('MAPK3p', model.monomers['MAPK3'](T202='p', Y204='p'))
    model.add_component(o)
    o = Observable('GSK3Ap', model.monomers['GSK3A'](S21='p'))
    model.add_component(o)
    o = Observable('GSK3Bp', model.monomers['GSK3B'](S9='p'))
    model.add_component(o)
    o = Observable('RPS6p', model.monomers['RPS6'](S235='p'))
    model.add_component(o)
    o = Observable('EIF4EBP1p', model.monomers['EIF4EBP1'](S65='p'))
    model.add_component(o)
    o = Observable('JUNp', model.monomers['JUN'](S73='p'))
    model.add_component(o)
    o = Observable('FOXO3p', model.monomers['FOXO3'](S315='p'))
    model.add_component(o)
    o = Observable('AKT1p', model.monomers['AKT1'](S473='p'))
    model.add_component(o)
    o = Observable('AKT2p', model.monomers['AKT2'](S474='p'))
    model.add_component(o)
    o = Observable('AKT3p', model.monomers['AKT3'](S='p'))
    model.add_component(o)
    o = Observable('ELK1', model.monomers['ELK1'](S383='p'))
    model.add_component(o)
    # Set context
    pa.set_context('SKMEL28_SKIN')
    pa.save_model(out_file)
    return model

def assemble_sif(stmts, data, out_file):
    """Return an assembled SIF."""
    # Filter for high-belief statements
    stmts = ac.filter_belief(stmts, 0.99)
    stmts = ac.filter_top_level(stmts)
    # Filter for Activation / Inhibition
    stmts_act = ac.filter_by_type(stmts, Activation)
    stmts_inact = ac.filter_by_type(stmts, Inhibition)
    stmts = stmts_act + stmts_inact
    # Get the drugs inhibiting their targets as INDRA
    # statements
    def get_drug_statements():
        drug_targets = process_data.get_drug_targets()
        drug_stmts = []
        for dn, tns in drug_targets.items():
            da = Agent(dn + ':Drugs')
            for tn in tns:
                ta = Agent(tn)
                drug_stmt = Inhibition(da, ta)
                drug_stmts.append(drug_stmt)
        return drug_stmts
    drug_stmts = get_drug_statements()
    stmts = stmts + drug_stmts
    # Because of a bug in CNO, node names containing AND
    # need to be replaced
    def rename_and_nodes(st):
        for s in st:
            for a in s.agent_list():
                if a is not None:
                    if a.name.find('AND') != -1:
                        a.name = a.name.replace('AND', 'A_ND')
    rename_and_nodes(stmts)
    # Rewrite statements to replace genes with their corresponding
    # antibodies when possible
    stmts = rewrite_ab_stmts(stmts, data)
    def filter_ab_edges(st, policy='all'):
        st_out = []
        for s in st:
            if policy == 'all':
                all_ab = True
                for a in s.agent_list():
                    if a is not None:
                        if a.name.find('_p') == -1 and \
                            a.name.find('Drugs') == -1:
                            all_ab = False
                            break
                if all_ab:
                    st_out.append(s)
            elif policy == 'one':
                any_ab = False
                for a in s.agent_list():
                    if a is not None and a.name.find('_p') != -1:
                        any_ab = True
                        break
                if any_ab:
                    st_out.append(s)
        return st_out
    stmts = filter_ab_edges(stmts, 'one')
    # Get a list of the AB names that end up being covered in the prior network
    # This is important because other ABs will need to be taken out of the
    # MIDAS file to work.
    def get_ab_names(st):
        prior_abs = set()
        for s in st:
            for a in s.agent_list():
                if a is not None:
                    if a.name.find('_p') != -1:
                        prior_abs.add(a.name)
        return sorted(list(prior_abs))
    pkn_abs = get_ab_names(stmts)
    print('Boolean PKN contains these antibodies: %s' % ', '.join(pkn_abs))
    # Make the SIF model
    sa = SifAssembler(stmts)
    sa.make_model(use_name_as_key=True)
    sif_str = sa.print_model()
    with open(out_file, 'wb') as fh:
        fh.write(sif_str.encode('utf-8'))
    # Make the MIDAS data file used for training the model
    midas_data = process_data.get_midas_data(data, pkn_abs)
    return sif_str

def assemble_cx(stmts, out_file):
    """Return a CX assembler."""
    stmts = ac.filter_belief(stmts, 0.95)
    stmts = ac.filter_top_level(stmts)
    stmts = ac.strip_agent_context(stmts)
    ca = CxAssembler()
    ca.add_statements(stmts)
    model = ca.make_model()
    ca.save_model(out_file)
    return ca

def get_prior_genes(fname):
    """Get the list of prior genes."""
    with open(fname, 'rt') as fh:
        genes = fh.read().strip().split('\n')
        return genes

def rewrite_ab_stmts(stmts_in, data):
    """Replace corresponding Agent names to AB names.

    This is used for logical model building.
    """
    # Build AB <-> Gene maps
    ab_phos = process_data.get_phos_antibodies(data)
    ab_dict = {}
    ab_dict_rev = {}
    for ab in ab_phos:
        up_ids = process_data.get_antibody_genes(data, ab)
        for up_id in up_ids:
            agent = process_data.get_agent_from_upid(up_id)
            if ab in ab_dict:
                ab_dict[ab].append(agent)
            else:
                ab_dict[ab] = [agent]
            if agent.name in ab_dict_rev:
                ab_dict_rev[agent.name].append(ab)
            else:
                ab_dict_rev[agent.name] = [ab]
    stmts_out = []
    for stmt in stmts_in:
        new_agents = []
        for agent in stmt.agent_list():
            if agent is not None:
                ab_names = ab_dict_rev.get(agent.name)
                if not ab_names:
                    new_agents.append([agent])
                else:
                    new_agents.append([Agent(ab) for ab in ab_names])
            else:
                new_agents.append([None])
        for na in itertools.product(*new_agents):
            stmt_new = deepcopy(stmt)
            stmt_new.set_agent_list(na)
            stmts_out.append(stmt_new)
    return stmts_out

if __name__ == '__main__':
    outf = 'output/'
    data = process_data.read_data(process_data.data_file)
    data_genes = process_data.get_all_gene_names(data)
    reassemble = False
    if not reassemble:
        stmts = ac.load_statements(pjoin(outf, 'preassembled.pkl'))
        #stmts = ac.load_statements(pjoin(outf, 'prior.pkl'))
    else:
        #prior_stmts = build_prior(data_genes, pjoin(outf, 'prior.pkl'))
        prior_stmts = ac.load_statements(pjoin(outf, 'prior.pkl'))
        prior_stmts = ac.map_grounding(prior_stmts,
                                       save=pjoin(outf, 'gmapped_prior.pkl'))
        reading_stmts = ac.load_statements(pjoin(outf, 'phase3_stmts.pkl'))
        reading_stmts = ac.map_grounding(reading_stmts,
                                    save=pjoin(outf, 'gmapped_reading.pkl'))
        stmts = prior_stmts + reading_stmts

        stmts = ac.filter_grounded_only(stmts)
        stmts = ac.filter_genes_only(stmts, specific_only=False)
        stmts = ac.filter_human_only(stmts)
        stmts = ac.expand_families(stmts)
        stmts = ac.filter_gene_list(stmts, data_genes, 'one')
        stmts = ac.map_sequence(stmts, save=pjoin(outf, 'smapped.pkl'))
        stmts = ac.run_preassembly(stmts, return_toplevel=False,
                                   save=pjoin(outf, 'preassembled.pkl'))

    assemble_models = []
    assemble_models.append('sif')
    assemble_models.append('pysb')
    assemble_models.append('cx')

    ### PySB assembly
    if 'pysb' in assemble_models:
        pysb_model = assemble_pysb(stmts, data_genes,
                                   pjoin(outf, 'korkut_model_pysb.py'))
        ke = KappaExporter(pysb_model)
        with open(pjoin(outf, 'korkut_model_v3.ka'), 'wb') as fh:
            fh.write(ke.export().encode('utf-8'))
    ### SIF assembly
    if 'sif' in assemble_models:
        sif_str = assemble_sif(stmts, data, pjoin(outf, 'PKN-korkut_one_ab.sif'))
    ### CX assembly
    if 'cx' in assemble_models:
        cxa = assemble_cx(stmts, pjoin(outf, 'korkut_full_high_belief.cx'))
<commit_msg>Filter sif file on ras genes and ab only<commit_after>from __future__ import absolute_import, print_function, unicode_literals
from builtins import dict, str
import pickle
import itertools
from copy import deepcopy
from os.path import join as pjoin
from pysb import Observable
from pysb.export.kappa import KappaExporter
from indra.tools import assemble_corpus as ac
from indra.tools.gene_network import GeneNetwork
from indra.assemblers import IndexCardAssembler
from indra.statements import *
from indra.assemblers import PysbAssembler, SifAssembler, CxAssembler

import process_data, process_r3, process_sparser, process_trips
from read_phosphosite import read_phosphosite

def build_prior(genes, out_file):
    gn = GeneNetwork(genes, 'korkut')
    stmts = gn.get_statements(filter=False)
    ac.dump_statements(stmts, out_file)
    return stmts

def read_sources():
    trips_stmts = process_trips.read_stmts(process_trips.base_folder)
    sparser_stmts = process_sparser.read_stmts(process_sparser.base_folder)
    r3_stmts = process_r3.read_stmts(process_r3.active_forms_file)
    stmts = trips_stmts + sparser_stmts + r3_stmts
    return stmts

def assemble_index_cards(stmts):
    counter = 1
    for st in stmts:
        if isinstance(st, Modification) and st.enz is None:
            continue
        pmids = [ev.pmid for ev in st.evidence if ev.pmid is not None]
        if pmids:
            pmids = ','.join(['PMID%s' % pm for pm in list(set(pmids))])
        else:
            pmids = 'N/A'
        ica = IndexCardAssembler([st], pmc_override=pmids)
        ica.make_model()
        if ica.cards:
            ica.save_model('output/index_cards/index_card_%d.json' % counter)
            counter += 1

def assemble_pysb(stmts, data_genes, out_file):
    """Return an assembled PySB model."""
    stmts = ac.filter_direct(stmts)
    stmts = ac.filter_belief(stmts, 0.95)
    stmts = ac.filter_top_level(stmts)
    stmts = ac.filter_gene_list(stmts, data_genes, 'all')
    stmts = ac.reduce_activities(stmts)
    pa = PysbAssembler()
    pa.add_statements(stmts)
    model = pa.make_model()
    # Add observables
    o = Observable('MAPK1p', model.monomers['MAPK1'](T185='p', Y187='p'))
    model.add_component(o)
    o = Observable('MAPK3p', model.monomers['MAPK3'](T202='p', Y204='p'))
    model.add_component(o)
    o = Observable('GSK3Ap', model.monomers['GSK3A'](S21='p'))
    model.add_component(o)
    o = Observable('GSK3Bp', model.monomers['GSK3B'](S9='p'))
    model.add_component(o)
    o = Observable('RPS6p', model.monomers['RPS6'](S235='p'))
    model.add_component(o)
    o = Observable('EIF4EBP1p', model.monomers['EIF4EBP1'](S65='p'))
    model.add_component(o)
    o = Observable('JUNp', model.monomers['JUN'](S73='p'))
    model.add_component(o)
    o = Observable('FOXO3p', model.monomers['FOXO3'](S315='p'))
    model.add_component(o)
    o = Observable('AKT1p', model.monomers['AKT1'](S473='p'))
    model.add_component(o)
    o = Observable('AKT2p', model.monomers['AKT2'](S474='p'))
    model.add_component(o)
    o = Observable('AKT3p', model.monomers['AKT3'](S='p'))
    model.add_component(o)
    o = Observable('ELK1', model.monomers['ELK1'](S383='p'))
    model.add_component(o)
    # Set context
    pa.set_context('SKMEL28_SKIN')
    pa.save_model(out_file)
    return model

def assemble_sif(stmts, data, out_file):
    """Return an assembled SIF."""
    # Filter for high-belief statements
    stmts = ac.filter_belief(stmts, 0.99)
    stmts = ac.filter_top_level(stmts)
    # Filter for Activation / Inhibition
    stmts_act = ac.filter_by_type(stmts, Activation)
    stmts_inact = ac.filter_by_type(stmts, Inhibition)
    stmts = stmts_act + stmts_inact
    # get Ras227 and filter statments
    ras_genes = process_data.get_ras227_genes()
    ras_genes = [x for x in ras_genes if x not in ['YAP1']]
    stmts = ac.filter_gene_list(stmts, ras_genes, 'all')
    # Get the drugs inhibiting their targets as INDRA
    # statements
    def get_drug_statements():
        drug_targets = process_data.get_drug_targets()
        drug_stmts = []
        for dn, tns in drug_targets.items():
            da = Agent(dn + ':Drugs')
            for tn in tns:
                ta = Agent(tn)
                drug_stmt = Inhibition(da, ta)
                drug_stmts.append(drug_stmt)
        return drug_stmts
    drug_stmts = get_drug_statements()
    stmts = stmts + drug_stmts
    # Because of a bug in CNO, node names containing AND
    # need to be replaced
    def rename_and_nodes(st):
        for s in st:
            for a in s.agent_list():
                if a is not None:
                    if a.name.find('AND') != -1:
                        a.name = a.name.replace('AND', 'A_ND')
    rename_and_nodes(stmts)
    # Rewrite statements to replace genes with their corresponding
    # antibodies when possible
    stmts = rewrite_ab_stmts(stmts, data)
    def filter_ab_edges(st, policy='all'):
        st_out = []
        for s in st:
            if policy == 'all':
                all_ab = True
                for a in s.agent_list():
                    if a is not None:
                        if a.name.find('_p') == -1 and \
                            a.name.find('Drugs') == -1:
                            all_ab = False
                            break
                if all_ab:
                    st_out.append(s)
            elif policy == 'one':
                any_ab = False
                for a in s.agent_list():
                    if a is not None and a.name.find('_p') != -1:
                        any_ab = True
                        break
                if any_ab:
                    st_out.append(s)
        return st_out
    stmts = filter_ab_edges(stmts, 'all')
    # Get a list of the AB names that end up being covered in the prior network
    # This is important because other ABs will need to be taken out of the
    # MIDAS file to work.
    def get_ab_names(st):
        prior_abs = set()
        for s in st:
            for a in s.agent_list():
                if a is not None:
                    if a.name.find('_p') != -1:
                        prior_abs.add(a.name)
        return sorted(list(prior_abs))
    pkn_abs = get_ab_names(stmts)
    print('Boolean PKN contains these antibodies: %s' % ', '.join(pkn_abs))
    # Make the SIF model
    sa = SifAssembler(stmts)
    sa.make_model(use_name_as_key=True)
    sif_str = sa.print_model()
    with open(out_file, 'wb') as fh:
        fh.write(sif_str.encode('utf-8'))
    # Make the MIDAS data file used for training the model
    midas_data = process_data.get_midas_data(data, pkn_abs)
    return sif_str

def assemble_cx(stmts, out_file):
    """Return a CX assembler."""
    stmts = ac.filter_belief(stmts, 0.95)
    stmts = ac.filter_top_level(stmts)
    stmts = ac.strip_agent_context(stmts)
    ca = CxAssembler()
    ca.add_statements(stmts)
    model = ca.make_model()
    ca.save_model(out_file)
    return ca

def get_prior_genes(fname):
    """Get the list of prior genes."""
    with open(fname, 'rt') as fh:
        genes = fh.read().strip().split('\n')
        return genes

def rewrite_ab_stmts(stmts_in, data):
    """Replace corresponding Agent names to AB names.

    This is used for logical model building.
    """
    # Build AB <-> Gene maps
    ab_phos = process_data.get_phos_antibodies(data)
    ab_dict = {}
    ab_dict_rev = {}
    for ab in ab_phos:
        up_ids = process_data.get_antibody_genes(data, ab)
        for up_id in up_ids:
            agent = process_data.get_agent_from_upid(up_id)
            if ab in ab_dict:
                ab_dict[ab].append(agent)
            else:
                ab_dict[ab] = [agent]
            if agent.name in ab_dict_rev:
                ab_dict_rev[agent.name].append(ab)
            else:
                ab_dict_rev[agent.name] = [ab]
    stmts_out = []
    for stmt in stmts_in:
        new_agents = []
        for agent in stmt.agent_list():
            if agent is not None:
                ab_names = ab_dict_rev.get(agent.name)
                if not ab_names:
                    new_agents.append([agent])
                else:
                    new_agents.append([Agent(ab) for ab in ab_names])
            else:
                new_agents.append([None])
        for na in itertools.product(*new_agents):
            stmt_new = deepcopy(stmt)
            stmt_new.set_agent_list(na)
            stmts_out.append(stmt_new)
    return stmts_out

if __name__ == '__main__':
    outf = 'output/'
    data = process_data.read_data(process_data.data_file)
    data_genes = process_data.get_all_gene_names(data)
    reassemble = False
    if not reassemble:
        stmts = ac.load_statements(pjoin(outf, 'preassembled.pkl'))
        #stmts = ac.load_statements(pjoin(outf, 'prior.pkl'))
    else:
        #prior_stmts = build_prior(data_genes, pjoin(outf, 'prior.pkl'))
        '''
        prior_stmts = ac.load_statements(pjoin(outf, 'prior.pkl'))
        prior_stmts = ac.map_grounding(prior_stmts,
                                       save=pjoin(outf, 'gmapped_prior.pkl'))
        reading_stmts = ac.load_statements(pjoin(outf, 'phase3_stmts.pkl'))
        reading_stmts = ac.map_grounding(reading_stmts,
                                    save=pjoin(outf, 'gmapped_reading.pkl'))
        stmts = prior_stmts + reading_stmts

        stmts = ac.filter_grounded_only(stmts)
        stmts = ac.filter_genes_only(stmts, specific_only=False)
        stmts = ac.filter_human_only(stmts)
        stmts = ac.expand_families(stmts)
        stmts = ac.filter_gene_list(stmts, data_genes, 'one')
        stmts = ac.map_sequence(stmts, save=pjoin(outf, 'smapped.pkl'))
        '''
        stmts = ac.run_preassembly(stmts, return_toplevel=False,
                                   save=pjoin(outf, 'preassembled.pkl'))

    assemble_models = []
    assemble_models.append('sif')
    #assemble_models.append('pysb')
    #assemble_models.append('cx')

    ### PySB assembly
    if 'pysb' in assemble_models:
        pysb_model = assemble_pysb(stmts, data_genes,
                                   pjoin(outf, 'korkut_model_pysb.py'))
        ke = KappaExporter(pysb_model)
        with open(pjoin(outf, 'korkut_model_v3.ka'), 'wb') as fh:
            fh.write(ke.export().encode('utf-8'))
    ### SIF assembly
    if 'sif' in assemble_models:
        sif_str = assemble_sif(stmts, data, pjoin(outf, 'PKN-korkut_one_ab.sif'))
    ### CX assembly
    if 'cx' in assemble_models:
        cxa = assemble_cx(stmts, pjoin(outf, 'korkut_full_high_belief.cx'))
<|endoftext|>


<commit_before>from requests_oauthlib import OAuth2Session
from flask import request, redirect, session, url_for, render_template, flash
from werkzeug.urls import iri_to_uri
from config import client_id, client_secret, authorization_base_url, \
    token_url, scope, redirect_uri, MEMBER_API_FORM_BASE_URL, \
    NEW_CREDENTIALS, NOTE_ORCID, CRED_TYPE_PREMIUM, APP_NAME, APP_DESCRIPTION, APP_URL
import json
from application import app, db, mail
from models import User, Role, Organisation, UserOrg
from urllib.parse import quote
from flask_login import login_user, current_user
from registrationForm import OrgRegistrationForm
from flask_mail import Message
from tokenGeneration import generate_confirmation_token, confirm_token
from registrationForm import OrgConfirmationForm
from flask_login import login_required, logout_user
from login_provider import roles_required
from os import environ
from urllib.parse import urlencode

@app.route("/index")
@app.route("/login")
@app.route("/")
def login():
    """
    Main landing page.
    """
    _next = request.args.get('next')
    return render_template("index.html", _next=_next)

@app.route("/Tuakiri/login")
def shib_login():

    _next = request.args.get('_next')
    token = request.headers.get("Auedupersonsharedtoken")
    last_name = request.headers['Sn']
    first_name = request.headers['Givenname']
    email = request.headers['Mail']
    session["shib_O"] = shib_org_name = request.headers['O']
    name = request.headers.get('Displayname')

    try:
        org = Organisation.get(name=shib_org_name)
    except Organisation.DoesNotExist:
        org = None

    try:
        user = User.get(User.email == email)
        if org is not None and org not in user.organisations:
            UserOrg.create(user=user, org=org)

            # TODO: need to find out a simple way of tracking
            # the organization user is logged in from:
            if org != user.organisation:
                user.organisation = org

        # Add Shibboleth meta data if they are missing
        if not user.edu_person_shared_token:
            user.edu_person_shared_token = token
        if not user.name or org is not None and user.name == org.name and name:
            user.name = name
        if not user.first_name and first_name:
            user.firts_name = first_name
        if not user.last_name and last_name:
            user.last_name = last_name
        if not user.confirmed:
            user.confirmed = True
        # TODO: keep login auditing (last_loggedin_at... etc)

    except User.DoesNotExist:
        user = User.create(
            email=email,
            name=name,
            first_name=first_name,
            last_name=last_name,
            confirmed=True,
            roles=Role.RESEARCHER,
            organisation=org,
            edu_person_shared_token=token)

    user.save()
    login_user(user)

    if _next:
        return redirect(_next)
    elif user.is_superuser:
        return redirect(url_for("invite_organisation"))
    elif org and org.confirmed:
        return redirect(url_for("link"))
    else:
        flash("Your organisation (%s) is not onboarded" % shib_org_name, "danger")

    return redirect(url_for("login"))

@app.route("/link")
@login_required
def link():
    """
    Links the user's account with ORCiD (i.e. affiliates user with his/her org on ORCID)
    """
    client = OAuth2Session(client_id, scope=scope, redirect_uri=redirect_uri)
    authorization_url, state = client.authorization_url(authorization_base_url)
    session['oauth_state'] = state
    # Check if user details are already in database
    if current_user.orcid:
        flash("You have already affilated '%s' with your ORCiD %s" % (
            current_user.organisation.name, current_user.orcid), "warning")
        return redirect(url_for("profile"))

    orcid_url = iri_to_uri(authorization_url) + urlencode(dict(
        family_names=current_user.last_name, given_names=current_user.first_name, email=current_user.email))

    return render_template("linking.html", orcid_url=orcid_url)

# Step 2: User authorization, this happens on the provider.
@app.route("/auth", methods=["GET"])
@login_required
def orcid_callback():
    """ Step 3: Retrieving an access token.
    The user has been redirected back from the provider to your registered
    callback URL. With this redirection comes an authorization code included
    in the redirect URL. We will use that to obtain an access token.
    """
    client = OAuth2Session(client_id)
    token = client.fetch_token(token_url, client_secret=client_secret,
                               authorization_response=request.url)
    # #print(token)
    # At this point you can fetch protected resources but lets save
    # the token and show how this is done from a persisted token
    # in /profile.
    session['oauth_token'] = token
    app.logger.info("* TOKEN: %s", token)
    orcid = token['orcid']
    name = token["name"]
    access_token = token["access_token"]
    user = current_user
    user.orcid = orcid
    if not user.name and name:
        user.name = name
    user.access_token = access_token
    user.save()

    flash("Your account was linked to ORCiD %s" % orcid, "success")

    return redirect(url_for("profile"))

@app.route("/profile", methods=["GET"])
@login_required
def profile():
    """Fetching a protected resource using an OAuth 2 token.
    """
    user = current_user
    if user.orcid is None:
        flash("You need to link your ORCiD with your account", "warning")
        return redirect(url_for("link"))

    client = OAuth2Session(client_id, token={"access_token": user.access_token})

    headers = {'Accept': 'application/json'}
    resp = client.get("https://api.sandbox.orcid.org/v1.2/" +
                      user.orcid + "/orcid-works", headers=headers)
    return render_template(
        "profile.html",
        user=user,
        data=json.loads(resp.text))

@app.route("/invite/user", methods=["GET"])  # /invite/user
@roles_required(Role.SUPERUSER, Role.ADMIN)
def invite_user():
    # For now on boarding of researcher is not supported
    return "Work in Progress!!!"

# TODO: user can be admin for multiple org and org can have multiple admins:
# TODO: user shoud be assigned exclicitly organization
# TODO: OrgAdmin ...
# TODO: gracefully handle all exceptions (repeated infitation, user is already an admin for the organization etc.)
@app.route("/invite/organisation", methods=["GET", "POST"])
@roles_required(Role.SUPERUSER)
def invite_organisation():
    form = OrgRegistrationForm()
    if request.method == "POST":
        if not form.validate():
            flash("Please fill in all fields and try again.", "danger")
        else:
            email = form.orgEmailid.data
            org_name = form.orgName.data
            try:
                User.get(User.email == form.orgEmailid.data)
                flash("This Email address is already an Admin for one of the organisation", "warning")
            except User.DoesNotExist:
                pass
            finally:
                # TODO: organisation can have mutiple admins:
                # TODO: user OrgAdmin
                try:
                    org = Organisation.get(name=org_name)
                    # TODO: fix it!
                    org.email = email
                except Organisation.DoesNotExist:
                    org = Organisation(name=org_name, email=email)
                org.save()

                try:
                    user = User.get(email=email)
                    user.roles |= Role.ADMIN
                    user.organisation = org
                except User.DoesNotExist:
                    user = User(
                        name=form.orgName.data,
                        email=form.orgEmailid.data,
                        confirmed=True,  # In order to let the user in...
                        roles=Role.ADMIN,
                        organisation=org)
                user.save()
                # Note: Using app context due to issue: https://github.com/mattupstate/flask-mail/issues/63
                with app.app_context():
                    msg = Message("Welcome to OrcidhHub",
                                  recipients=[str(form.orgEmailid.data)])
                    token = generate_confirmation_token(form.orgEmailid.data)
                    # TODO: do it with templates
                    msg.body = "Your organisation is just one step behind to get onboarded" \
                               " please click on following link to get onboarded " \
                               "https://" + environ.get("ENV", "dev") + ".orcidhub.org.nz" + \
                               url_for("confirm_organisation", token=token)
                    mail.send(msg)
                    flash(
                        "Organisation Onboarded Successfully!!! Email Communication has been sent to Admin",
                        "success")

    return render_template('registration.html', form=form)

@app.route("/confirm/organisation/<token>", methods=["GET", "POST"])
@login_required
def confirm_organisation(token):
    clientSecret_url = None
    email = confirm_token(token)
    user = current_user

    if not email:
        app.error("token '%s'", token)
        app.login_manager.unauthorized()
    if user.email != email:
        flash("The invitation to on-board the organisation wasn't sent to your email address...", "danger")
        return redirect(url_for("login"))

    # TODO: support for mutliple orgs and admins
    # TODO: admin role asigning to an exiting user
    # TODO: support for org not participating in Tuakiri
    form = OrgConfirmationForm()

    # For now only GET method is implemented will need post method for organisation
    # to enter client secret and client key for orcid
    if request.method == 'POST':
        if not form.validate():
            flash('Please fill in all fields and try again!', "danger")
        else:
            organisation = Organisation.get(email=email)
            if (not (user is None) and (not (organisation is None))):
                # Update Organisation
                organisation.confirmed = True
                organisation.orcid_client_id = form.orgOricdClientId.data
                organisation.orcid_secret = form.orgOrcidClientSecret.data
                organisation.save()

                # Update Orcid User
                user.confirmed = True
                user.save()
                with app.app_context():
                    msg = Message("Welcome to OrcidhHub", recipients=[email])
                    msg.body = "Congratulations your emailid has been confirmed and " \
                               "organisation onboarded successfully."
                    mail.send(msg)
                    flash("Your Onboarding is Completed!!!", "success")
                return redirect(url_for("login"))

    elif request.method == 'GET':

        form.orgEmailid.data = email
        form.orgName.data = user.organisation.name

        flash("""If you currently don't know Client id and Client Secret,
        Please request those by clicking on link 'Take me to ORCiD to obtain Client iD and Client Secret'
        and come back to this same place once you have them within 15 days""", "warning")

        clientSecret_url = iri_to_uri(MEMBER_API_FORM_BASE_URL) + "?" + urlencode(dict(
            new_existing=NEW_CREDENTIALS, note=NOTE_ORCID + " " + user.organisation.name,
            contact_email=email, contact_name=user.name, org_name=user.organisation.name,
            cred_type=CRED_TYPE_PREMIUM, app_name=APP_NAME + " at " + user.organisation.name,
            app_description=APP_DESCRIPTION + " at " + user.organisation.name,
            app_url=APP_URL, redirect_uri_1=redirect_uri))

    return render_template('orgconfirmation.html', clientSecret_url=clientSecret_url, form=form)

@app.after_request
def remove_if_invalid(response):
    """
    Removes stale session...
    """
    if "__invalidate__" in session:
        response.delete_cookie(app.session_cookie_name)
        session.clear()
    return response

@app.route("/logout")
def logout():
    org_name = session.get("shib_O")
    try:
        logout_user()
    except Exception as ex:
        app.logger.error("Failed to logout: %s", ex)

    session.clear()
    session["__invalidate__"] = True
    return redirect(
        "/Shibboleth.sso/Logout?return=" +
        quote(url_for("uoa_slo" if org_name and org_name == "University of Auckland" else "login")))

@app.route("/uoa-slo")
def uoa_slo():
    """
    Shows the logout info for UoA users.
    """
    flash("""You had logged in from 'The University of Auckland'.
You have to close all open browser tabs and windows in order
in order to complete the log-out.""", "warning")
    return render_template("uoa-slo.html")

# NB! Disable for the production!!!
@app.route("/reset_db")
@login_required
def reset_db():
    """
    Resets the DB for testing cycle
    """
    db.session.execute("DELETE FROM user WHERE name NOT LIKE '%Royal%'")
    db.session.execute("DELETE FROM organisation WHERE name NOT LIKE '%Royal%'")
    db.session.commit()
    return redirect(url_for("logout"))
<commit_msg>fixed raw SQL execution (#12)<commit_after>from requests_oauthlib import OAuth2Session
from flask import request, redirect, session, url_for, render_template, flash
from werkzeug.urls import iri_to_uri
from config import client_id, client_secret, authorization_base_url, \
    token_url, scope, redirect_uri, MEMBER_API_FORM_BASE_URL, \
    NEW_CREDENTIALS, NOTE_ORCID, CRED_TYPE_PREMIUM, APP_NAME, APP_DESCRIPTION, APP_URL
import json
from application import app, db, mail
from models import User, Role, Organisation, UserOrg
from urllib.parse import quote
from flask_login import login_user, current_user
from registrationForm import OrgRegistrationForm
from flask_mail import Message
from tokenGeneration import generate_confirmation_token, confirm_token
from registrationForm import OrgConfirmationForm
from flask_login import login_required, logout_user
from login_provider import roles_required
from os import environ
from urllib.parse import urlencode

@app.route("/index")
@app.route("/login")
@app.route("/")
def login():
    """
    Main landing page.
    """
    _next = request.args.get('next')
    return render_template("index.html", _next=_next)

@app.route("/Tuakiri/login")
def shib_login():

    _next = request.args.get('_next')
    token = request.headers.get("Auedupersonsharedtoken")
    last_name = request.headers['Sn']
    first_name = request.headers['Givenname']
    email = request.headers['Mail']
    session["shib_O"] = shib_org_name = request.headers['O']
    name = request.headers.get('Displayname')

    try:
        org = Organisation.get(name=shib_org_name)
    except Organisation.DoesNotExist:
        org = None

    try:
        user = User.get(User.email == email)
        if org is not None and org not in user.organisations:
            UserOrg.create(user=user, org=org)

            # TODO: need to find out a simple way of tracking
            # the organization user is logged in from:
            if org != user.organisation:
                user.organisation = org

        # Add Shibboleth meta data if they are missing
        if not user.edu_person_shared_token:
            user.edu_person_shared_token = token
        if not user.name or org is not None and user.name == org.name and name:
            user.name = name
        if not user.first_name and first_name:
            user.firts_name = first_name
        if not user.last_name and last_name:
            user.last_name = last_name
        if not user.confirmed:
            user.confirmed = True
        # TODO: keep login auditing (last_loggedin_at... etc)

    except User.DoesNotExist:
        user = User.create(
            email=email,
            name=name,
            first_name=first_name,
            last_name=last_name,
            confirmed=True,
            roles=Role.RESEARCHER,
            organisation=org,
            edu_person_shared_token=token)

    user.save()
    login_user(user)

    if _next:
        return redirect(_next)
    elif user.is_superuser:
        return redirect(url_for("invite_organisation"))
    elif org and org.confirmed:
        return redirect(url_for("link"))
    else:
        flash("Your organisation (%s) is not onboarded" % shib_org_name, "danger")

    return redirect(url_for("login"))

@app.route("/link")
@login_required
def link():
    """
    Links the user's account with ORCiD (i.e. affiliates user with his/her org on ORCID)
    """
    client = OAuth2Session(client_id, scope=scope, redirect_uri=redirect_uri)
    authorization_url, state = client.authorization_url(authorization_base_url)
    session['oauth_state'] = state
    # Check if user details are already in database
    if current_user.orcid:
        flash("You have already affilated '%s' with your ORCiD %s" % (
            current_user.organisation.name, current_user.orcid), "warning")
        return redirect(url_for("profile"))

    orcid_url = iri_to_uri(authorization_url) + urlencode(dict(
        family_names=current_user.last_name, given_names=current_user.first_name, email=current_user.email))

    return render_template("linking.html", orcid_url=orcid_url)

# Step 2: User authorization, this happens on the provider.
@app.route("/auth", methods=["GET"])
@login_required
def orcid_callback():
    """ Step 3: Retrieving an access token.
    The user has been redirected back from the provider to your registered
    callback URL. With this redirection comes an authorization code included
    in the redirect URL. We will use that to obtain an access token.
    """
    client = OAuth2Session(client_id)
    token = client.fetch_token(token_url, client_secret=client_secret,
                               authorization_response=request.url)
    # #print(token)
    # At this point you can fetch protected resources but lets save
    # the token and show how this is done from a persisted token
    # in /profile.
    session['oauth_token'] = token
    app.logger.info("* TOKEN: %s", token)
    orcid = token['orcid']
    name = token["name"]
    access_token = token["access_token"]
    user = current_user
    user.orcid = orcid
    if not user.name and name:
        user.name = name
    user.access_token = access_token
    user.save()

    flash("Your account was linked to ORCiD %s" % orcid, "success")

    return redirect(url_for("profile"))

@app.route("/profile", methods=["GET"])
@login_required
def profile():
    """Fetching a protected resource using an OAuth 2 token.
    """
    user = current_user
    if user.orcid is None:
        flash("You need to link your ORCiD with your account", "warning")
        return redirect(url_for("link"))

    client = OAuth2Session(client_id, token={"access_token": user.access_token})

    headers = {'Accept': 'application/json'}
    resp = client.get("https://api.sandbox.orcid.org/v1.2/" +
                      user.orcid + "/orcid-works", headers=headers)
    return render_template(
        "profile.html",
        user=user,
        data=json.loads(resp.text))

@app.route("/invite/user", methods=["GET"])  # /invite/user
@roles_required(Role.SUPERUSER, Role.ADMIN)
def invite_user():
    # For now on boarding of researcher is not supported
    return "Work in Progress!!!"

# TODO: user can be admin for multiple org and org can have multiple admins:
# TODO: user shoud be assigned exclicitly organization
# TODO: OrgAdmin ...
# TODO: gracefully handle all exceptions (repeated infitation, user is already an admin for the organization etc.)
@app.route("/invite/organisation", methods=["GET", "POST"])
@roles_required(Role.SUPERUSER)
def invite_organisation():
    form = OrgRegistrationForm()
    if request.method == "POST":
        if not form.validate():
            flash("Please fill in all fields and try again.", "danger")
        else:
            email = form.orgEmailid.data
            org_name = form.orgName.data
            try:
                User.get(User.email == form.orgEmailid.data)
                flash("This Email address is already an Admin for one of the organisation", "warning")
            except User.DoesNotExist:
                pass
            finally:
                # TODO: organisation can have mutiple admins:
                # TODO: user OrgAdmin
                try:
                    org = Organisation.get(name=org_name)
                    # TODO: fix it!
                    org.email = email
                except Organisation.DoesNotExist:
                    org = Organisation(name=org_name, email=email)
                org.save()

                try:
                    user = User.get(email=email)
                    user.roles |= Role.ADMIN
                    user.organisation = org
                except User.DoesNotExist:
                    user = User(
                        name=form.orgName.data,
                        email=form.orgEmailid.data,
                        confirmed=True,  # In order to let the user in...
                        roles=Role.ADMIN,
                        organisation=org)
                user.save()
                # Note: Using app context due to issue: https://github.com/mattupstate/flask-mail/issues/63
                with app.app_context():
                    msg = Message("Welcome to OrcidhHub",
                                  recipients=[str(form.orgEmailid.data)])
                    token = generate_confirmation_token(form.orgEmailid.data)
                    # TODO: do it with templates
                    msg.body = "Your organisation is just one step behind to get onboarded" \
                               " please click on following link to get onboarded " \
                               "https://" + environ.get("ENV", "dev") + ".orcidhub.org.nz" + \
                               url_for("confirm_organisation", token=token)
                    mail.send(msg)
                    flash(
                        "Organisation Onboarded Successfully!!! Email Communication has been sent to Admin",
                        "success")

    return render_template('registration.html', form=form)

@app.route("/confirm/organisation/<token>", methods=["GET", "POST"])
@login_required
def confirm_organisation(token):
    clientSecret_url = None
    email = confirm_token(token)
    user = current_user

    if not email:
        app.error("token '%s'", token)
        app.login_manager.unauthorized()
    if user.email != email:
        flash("The invitation to on-board the organisation wasn't sent to your email address...", "danger")
        return redirect(url_for("login"))

    # TODO: support for mutliple orgs and admins
    # TODO: admin role asigning to an exiting user
    # TODO: support for org not participating in Tuakiri
    form = OrgConfirmationForm()

    # For now only GET method is implemented will need post method for organisation
    # to enter client secret and client key for orcid
    if request.method == 'POST':
        if not form.validate():
            flash('Please fill in all fields and try again!', "danger")
        else:
            organisation = Organisation.get(email=email)
            if (not (user is None) and (not (organisation is None))):
                # Update Organisation
                organisation.confirmed = True
                organisation.orcid_client_id = form.orgOricdClientId.data
                organisation.orcid_secret = form.orgOrcidClientSecret.data
                organisation.save()

                # Update Orcid User
                user.confirmed = True
                user.save()
                with app.app_context():
                    msg = Message("Welcome to OrcidhHub", recipients=[email])
                    msg.body = "Congratulations your emailid has been confirmed and " \
                               "organisation onboarded successfully."
                    mail.send(msg)
                    flash("Your Onboarding is Completed!!!", "success")
                return redirect(url_for("login"))

    elif request.method == 'GET':

        form.orgEmailid.data = email
        form.orgName.data = user.organisation.name

        flash("""If you currently don't know Client id and Client Secret,
        Please request those by clicking on link 'Take me to ORCiD to obtain Client iD and Client Secret'
        and come back to this same place once you have them within 15 days""", "warning")

        clientSecret_url = iri_to_uri(MEMBER_API_FORM_BASE_URL) + "?" + urlencode(dict(
            new_existing=NEW_CREDENTIALS, note=NOTE_ORCID + " " + user.organisation.name,
            contact_email=email, contact_name=user.name, org_name=user.organisation.name,
            cred_type=CRED_TYPE_PREMIUM, app_name=APP_NAME + " at " + user.organisation.name,
            app_description=APP_DESCRIPTION + " at " + user.organisation.name,
            app_url=APP_URL, redirect_uri_1=redirect_uri))

    return render_template('orgconfirmation.html', clientSecret_url=clientSecret_url, form=form)

@app.after_request
def remove_if_invalid(response):
    """
    Removes stale session...
    """
    if "__invalidate__" in session:
        response.delete_cookie(app.session_cookie_name)
        session.clear()
    return response

@app.route("/logout")
def logout():
    org_name = session.get("shib_O")
    try:
        logout_user()
    except Exception as ex:
        app.logger.error("Failed to logout: %s", ex)

    session.clear()
    session["__invalidate__"] = True
    return redirect(
        "/Shibboleth.sso/Logout?return=" +
        quote(url_for("uoa_slo" if org_name and org_name == "University of Auckland" else "login")))

@app.route("/uoa-slo")
def uoa_slo():
    """
    Shows the logout info for UoA users.
    """
    flash("""You had logged in from 'The University of Auckland'.
You have to close all open browser tabs and windows in order
in order to complete the log-out.""", "warning")
    return render_template("uoa-slo.html")

# NB! Disable for the production!!!
@app.route("/reset_db")
@login_required
def reset_db():
    """
    Resets the DB for testing cycle
    """
    db.execute_sql("DELETE FROM \"user\" WHERE name !~ 'Royal' AND name != 'The Root' RETURNING id")
    db.execute_sql("DELETE FROM organisation WHERE name !~ 'Royal'")
    db.commit()
    return redirect(url_for("logout"))
<|endoftext|>


<commit_before><commit_msg>added google login<commit_after><|endoftext|>


<commit_before>from braces.views import GroupRequiredMixin
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.exceptions import ObjectDoesNotExist

import crud.base
from crud.base import Crud
from scp.settings import LOGIN_REDIRECT_URL
from usuarios.models import Usuario

from .forms import ConsultaForm
from .models import Consulta

class ConsultaCrud(Crud):
    model = Consulta
    help_path = ''

    class BaseMixin(GroupRequiredMixin,
                    LoginRequiredMixin,
                    crud.base.CrudBaseMixin):

        list_field_names = ['medico', 'paciente']
        login_url = LOGIN_REDIRECT_URL
        raise_exception = True
        group_required = ['Administrador', 'Médico', 'Paciente']

    class CreateView(crud.base.CrudCreateView):
        form_class = ConsultaForm

    class UpdateView(crud.base.CrudUpdateView):
        form_class = ConsultaForm

    class ListView(crud.base.CrudListView):
        def get_queryset(self):
            qs = super().get_queryset()
            try:
                usuario = Usuario.objects.get(user_id=self.request.user.id)
            except ObjectDoesNotExist:
                return qs
            else:
                if usuario.tipo.descricao == 'Médico':
                    return qs.filter(medico=usuario)
                elif usuario.tipo.descricao == 'Paciente':
                    return qs.filter(paciente=usuario)
                else:
                    return qs
<commit_msg>Adiciona médico se for um médico logado na hora da consulta<commit_after>from braces.views import GroupRequiredMixin
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist

import crud.base
from crud.base import Crud
from scp.settings import LOGIN_REDIRECT_URL
from usuarios.models import Usuario

from .forms import ConsultaForm
from .models import Consulta

class ConsultaCrud(Crud):
    model = Consulta
    help_path = ''

    class BaseMixin(GroupRequiredMixin,
                    LoginRequiredMixin,
                    crud.base.CrudBaseMixin):

        list_field_names = ['medico', 'paciente']
        login_url = LOGIN_REDIRECT_URL
        raise_exception = True
        group_required = ['Administrador', 'Médico', 'Paciente']

    class CreateView(crud.base.CrudCreateView):
        form_class = ConsultaForm

        def get_initial(self):
            user = User.objects.get(id=self.request.user.id)
            try:
                usuario = Usuario.objects.get(user_id=user.id)
            except ObjectDoesNotExist:
                pass
            else:
                tipo = usuario.tipo

                if tipo.descricao == 'Médico':
                    self.initial['medico'] = usuario

            return self.initial.copy()

    class UpdateView(crud.base.CrudUpdateView):
        form_class = ConsultaForm

    class ListView(crud.base.CrudListView):
        def get_queryset(self):
            qs = super().get_queryset()
            try:
                usuario = Usuario.objects.get(user_id=self.request.user.id)
            except ObjectDoesNotExist:
                return qs
            else:
                if usuario.tipo.descricao == 'Médico':
                    return qs.filter(medico=usuario)
                elif usuario.tipo.descricao == 'Paciente':
                    return qs.filter(paciente=usuario)
                else:
                    return qs
<|endoftext|>


<commit_before>""":mod:`settei.version` --- Version data
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

"""

#: (:class:`typing.Tuple`[:class:`int`, :class:`int`, :class:`int`])
#: The triple of version numbers e.g. ``(1, 2, 3)``.
VERSION_INFO = (0, 2, 2)

#: (:class:`str`) The version string e.g. ``'1.2.3'``.
VERSION = '{}.{}.{}'.format(*VERSION_INFO)

if __name__ == '__main__':
    print(VERSION)
<commit_msg>Version bump<commit_after>""":mod:`settei.version` --- Version data
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

"""

#: (:class:`typing.Tuple`\ [:class:`int`, :class:`int`, :class:`int`])
#: The triple of version numbers e.g. ``(1, 2, 3)``.
VERSION_INFO = (0, 3, 0)

#: (:class:`str`) The version string e.g. ``'1.2.3'``.
VERSION = '{}.{}.{}'.format(*VERSION_INFO)

if __name__ == '__main__':
    print(VERSION)
<|endoftext|>


<commit_before>"""
Generic functions.
"""

import subprocess
import sys

_PY3 = sys.version_info >= (3, 0)

def read_file(filepath, encoding='utf-8'):
    """Reads file's contents and returns unicode."""
    open_func = open
    if _PY3:
        open_func = lambda f, mode: open(f, mode, encoding=encoding)

    with open_func(filepath, 'r') as f:
        content = f.read()

    if not _PY3:
        content = content.decode(encoding, errors='replace')

    return content

def write_file(text, filepath, encoding='utf-8'):
    """Writes unicode to file with specified encoding."""
    open_func = open
    if _PY3:
        open_func = lambda f, mode: open(f, mode, encoding=encoding)
    else:
        text = text.encode(encoding, errors='replace')

    with open_func(filepath, 'w') as f:
        f.write(text)

def run_command(command):
    """Runs an command and returns the stdout and stderr as a string.

    Args:
        command: Command to execute in Popen's list format.
                 E.g. ['ls', '..']

    Returns:
        tuple. (return_value, stdout, stderr), where return_value is the
        numerical exit code of process and stdout/err are strings containing
        the output. stdout/err is None if nothing has been output.
    """
    p = subprocess.Popen(command, stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)
    stdout, stderr = p.communicate()
    return_value = p.wait()
    return return_value, stdout, stderr

def indent(text, indent=4):
    """Indents text with spaces."""
    return '\n'.join([u' ' * indent + x for x in text.splitlines()])

<commit_msg>Fix str encode and decode errors parameter for python2.6<commit_after>"""
Generic functions.
"""

import subprocess
import sys

_PY3 = sys.version_info >= (3, 0)

def read_file(filepath, encoding='utf-8'):
    """Reads file's contents and returns unicode."""
    open_func = open
    if _PY3:
        open_func = lambda f, mode: open(f, mode, encoding=encoding)

    with open_func(filepath, 'r') as f:
        content = f.read()

    if not _PY3:
        content = content.decode(encoding, 'replace')

    return content

def write_file(text, filepath, encoding='utf-8'):
    """Writes unicode to file with specified encoding."""
    open_func = open
    if _PY3:
        open_func = lambda f, mode: open(f, mode, encoding=encoding)
    else:
        text = text.encode(encoding, 'replace')

    with open_func(filepath, 'w') as f:
        f.write(text)

def run_command(command):
    """Runs an command and returns the stdout and stderr as a string.

    Args:
        command: Command to execute in Popen's list format.
                 E.g. ['ls', '..']

    Returns:
        tuple. (return_value, stdout, stderr), where return_value is the
        numerical exit code of process and stdout/err are strings containing
        the output. stdout/err is None if nothing has been output.
    """
    p = subprocess.Popen(command, stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)
    stdout, stderr = p.communicate()
    return_value = p.wait()
    return return_value, stdout, stderr

def indent(text, indent=4):
    """Indents text with spaces."""
    return '\n'.join([u' ' * indent + x for x in text.splitlines()])

<|endoftext|>