import configparser
import os
import random

CONFIG_PATH = os.path.join(os.path.dirname(__file__), 'config.ini')
CONFIG = configparser.ConfigParser()
CONFIG.read(CONFIG_PATH)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
UA_PATH = os.path.join(os.path.dirname(__file__), 'user_agents.txt')

def get_db_args():
    """
    获取数据库配置信息
    """
    return dict(CONFIG.items('db_postgresql'))

def get_user_agents(filename=UA_PATH):
    ualist = []
    with open(filename, 'r') as f:
        for line in f.readlines():
            if line:
                ualist.append(line.strip()[1: -1])
    random.shuffle(ualist)
    return ualist

def get_proxies():
    proxies = {'http': 'http://119.29.158.87:80',
           'http': 'http://123.7.38.31:9999',
           'http': 'http://211.103.208.244:80',
           'http': 'http://27.219.38.130:81189',
           'http': 'http://61.135.217.7:80',
           'http': 'http://120.40.38.130:808',
           'http': 'http://221.211.221.34:80',
           'http': 'http://61.178.238.122:63000',
           'http': 'http://27.46.32.69:9797',
           'http': 'http://120.40.38.130:808'

           }
    return proxies

return CONFIG.get('bili_url', urlkey)

def get_key():
    return CONFIG.get('bili_key', 'key')


import configparser
import os
import random

CONFIG_PATH = os.path.join(os.path.dirname(__file__), 'config.ini')
CONFIG = configparser.ConfigParser()
CONFIG.read(CONFIG_PATH)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
UA_PATH = os.path.join(os.path.dirname(__file__), 'user_agents.txt')

def get_db_args():
    """
    获取数据库配置信息
    """
    return dict(CONFIG.items('db_postgresql'))

def get_user_agents(filename=UA_PATH):
    ualist = []
    with open(filename, 'r') as f:
        for line in f.readlines():
            if line:
                ualist.append(line.strip()[1: -1])
    random.shuffle(ualist)
    return ualist

def get_proxies():
    proxies = {'http': 'http://119.29.158.87:80',
           'http': 'http://123.7.38.31:9999',
           'http': 'http://211.103.208.244:80',
           'http': 'http://27.219.38.130:81189',
           'http': 'http://61.135.217.7:80',
           'http': 'http://120.40.38.130:808',
           'http': 'http://221.211.221.34:80',
           'http': 'http://61.178.238.122:63000',
           'http': 'http://27.46.32.69:9797',
           'http': 'http://120.40.38.130:808'

           }
    return proxies

def get_urls(urlkey):
    return CONFIG.get('bili_url', urlkey)

def get_key():


import configparser
import os
import random

CONFIG_PATH = os.path.join(os.path.dirname(__file__), 'config.ini')
CONFIG = configparser.ConfigParser()
CONFIG.read(CONFIG_PATH)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
UA_PATH = os.path.join(os.path.dirname(__file__), 'user_agents.txt')

def get_db_args():
    """
    获取数据库配置信息
    """
    return dict(CONFIG.items('db_postgresql'))

def get_user_agents(filename=UA_PATH):
    ualist = []
    with open(filename, 'r') as f:
        for line in f.readlines():
            if line:
                ualist.append(line.strip()[1: -1])
    random.shuffle(ualist)
    return ualist

def get_proxies():
    proxies = {'http': 'http://119.29.158.87:80',
           'http': 'http://123.7.38.31:9999',
           'http': 'http://211.103.208.244:80',
           'http': 'http://27.219.38.130:81189',
           'http': 'http://61.135.217.7:80',
           'http': 'http://120.40.38.130:808',
           'http': 'http://221.211.221.34:80',
           'http': 'http://61.178.238.122:63000',
           'http': 'http://27.46.32.69:9797',
           'http': 'http://120.40.38.130:808'

           }
    retu

def get_urls(urlkey):
    return CONFIG.get('bili_url', urlkey)

def get_key():
    return CONFIG.get('bili_key', 'key')


import configparser
import os
import random

CONFIG_PATH = os.path.join(os.path.dirname(__file__), 'config.ini')
CONFIG = configparser.ConfigParser()
CONFIG.read(CONFIG_PATH)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
UA_PATH = os.path.join(os.path.dirname(__file__), 'user_agents.txt')

def get_db_args():
    """
    获取数据库配置信息
    """


# @Author  : Lin Lan (example@nnthink.com)

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import logging

from ray.rllib.utils import merge_dicts

from maml.maml import MAMLAgent, DEFAULT_CONFIG

logger = logging.getLogger("ray.rllib.agents.maml.meta_sgd")

DEFAULT_CONFIG = merge_dicts(
    DEFAULT_CONFIG,
    {
        "adaptive_inner_lr": True
    }
)

class MetaSGDAgent(MAMLAgent):
    _agent_name = "MetaSGD"
    _default_config = DEFAULT_CONFIG

assert self.config["adaptive_inner_lr"]

if __name__ == "__main__":
    import time
    import ray
    import numpy as np
    import tensorflow as tf
    from ray.tune.registry import register_env
    from ray.rllib.models.catalog import ModelCatalog
    from ray.rllib.evaluation.sample_batch import DEFAULT_POLICY_ID
    from ray.rllib.evaluation.metrics import summarize_episodes
    from ray.tune.logger import pretty_print
    from models.rllib_mlp import RLlibMLP
    from envs.point_env import PointEnv
    from envs.reset_wrapper import ResetWrapper

    logger = logging.getLogger("ray.rllib.agents.maml")
    logger.setLevel(logging.DEBUG)

    ray.init()
    env_cls = PointEnv
    register_env(env_cls.__name__,
                 lambda env_config: ResetWrapper(env_cls(), env_config))
    ModelCatalog.register_custom_model("maml_mlp", RLlibMLP)

    config = {
        "num_workers": 1,
        "model": {
            "custom_model": "maml_mlp",
            "fcnet_hiddens": [100, 100],
            "fcnet_activation": "tanh",
            "custom_options": {"vf_share_layers": True},
        }
    }

    agent = MetaSGDAgent(config=config, env=env_cls.__name__)
    evaluator = agent.local_evaluator
    policy = evaluator.policy_map[DEFAULT_POLICY_ID]
    optimizer = agent.optimizer

    # only perform inner update in the local evaluator

    writer = tf.summary.FileWriter(logdir="./summary", graph=evaluator.tf_sess.graph)
    writer.flush()


# @Author  : Lin Lan (example@nnthink.com)

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import logging

from ray.rllib.utils import merge_dicts

from maml.maml import MAMLAgent, DEFAULT_CONFIG

logger = logging.getLogger("ray.rllib.agents.maml.meta_sgd")

DEFAULT_CONFIG = merge_dicts(
    DEFAULT_CONFIG,
    {
        "adaptive_inner_lr": True
    }
)

class MetaSGDAgent(MAMLAgent):
    _agent_name = "MetaSGD"
    _default_config = DEFAULT_CONFIG

    def _validate_config(self):

if __name__ == "__main__":
    import time
    import ray
    import numpy as np
    import tensorflow as tf
    from ray.tune.registry import register_env
    from ray.rllib.models.catalog import ModelCatalog
    from ray.rllib.evaluation.sample_batch import DEFAULT_POLICY_ID
    from ray.rllib.evaluation.metrics import summarize_episodes
    from ray.tune.logger import pretty_print
    from models.rllib_mlp import RLlibMLP
    from envs.point_env import PointEnv
    from envs.reset_wrapper import ResetWrapper

    logger = logging.getLogger("ray.rllib.agents.maml")
    logger.setLevel(logging.DEBUG)

    ray.init()
    env_cls = PointEnv
    register_env(env_cls.__name__,
                 lambda env_config: ResetWrapper(env_cls(), env_config))
    ModelCatalog.register_custom_model("maml_mlp", RLlibMLP)

    config = {
        "num_workers": 1,
        "model": {
            "custom_model": "maml_mlp",
            "fcnet_hiddens": [100, 100],
            "fcnet_activation": "tanh",
            "custom_options": {"vf_share_layers": True},
        }
    }

    agent = MetaSGDAgent(config=config, env=env_cls.__name__)
    evaluator = agent.local_evaluator
    policy = evaluator.policy_map[DEFAULT_POLICY_ID]
    optimizer = agent.optimizer

    # only perform inner update in the local evaluator

    writer = tf.summary.FileWriter(logdir="./summary", graph=evaluator.tf_sess.graph)
    writer.flush()


# @Author  : Lin Lan (example@nnthink.com)

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import logging

from ray.rllib.utils import merge_dicts

from maml.maml import MAMLAgent, DEFAULT_CONFIG

logger = logging.getLogger("ray.rllib.agents.maml.meta_sgd")

DEFAULT_CONFIG = merge_dicts(
    DEFAULT_CONFIG,
    {
        "adaptive_inner_lr": True
    }
)

class MetaSGDAgent(MAMLAgent):
    _agent_name = "MetaSGD"
    _default_config = DEFAULT_CONFIG

    def _validate_config(self):
        assert self.config["adaptive_inner_lr


from setuptools import setup
import io
import os
import re
import sys

if 'bdist_rpm' in sys.argv:
        # exclude changelog when building rpm
        return ""
    here = os.path.abspath(".")
    with io.open(os.path.join(here, 'CHANGELOG'), encoding="utf-8") as f:
        text = f.read()
    header_matches = list(re.finditer('^=+$', text, re.MULTILINE))
    # until fifth header
    if len(header_matches) > 5:
        text = text[:header_matches[5].start()]
        # all lines without fifth release number
        lines = text.splitlines()[:-1]
    else:
        lines = text.splitlines()
    return "=========\nChangelog\n=========\n\n" + "\n".join(lines)

README = io.open(os.path.abspath('README.rst'), encoding='utf-8').read()
CHANGELOG = get_changelog()

setup(
    name="devpi-postgresql",
    description="devpi-postgresql: a PostgreSQL storage backend for devpi-server",
    long_description="\n\n".join([README, CHANGELOG]),
    url="https://devpi.net",
    project_urls={
        'Bug Tracker': 'http://example.com',
        'Changelog': 'http://example.com',
        'Documentation': 'https://doc.devpi.net',
        'Source Code': 'http://example.com'
    },
    version='2.0.0',
    maintainer="Florian Schulze, Holger Krekel",
    maintainer_email="example@nnthink.com",
    license="MIT",
    classifiers=[
        "Development Status :: 4 - Beta",
        "Environment :: Web Environment",
        "Intended Audience :: Developers",
        "Intended Audience :: System Administrators",
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python :: 3 :: Only",
        "Topic :: Internet :: WWW/HTTP",
        "Programming Language :: Python :: Implementation :: PyPy",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application"] + [
            "Programming Language :: Python :: %s" % x
            for x in "3.6 3.7 3.8 3.9 3.10".split()],
    entry_points={
        'devpi_server': [
            "devpi-postgresql = devpi_postgresql.main"],
        'pytest11': [
            "pytest_devpi_postgresql = pytest_devpi_postgresql"]},
    install_requires=[
        'devpi-server>=3.0.0.dev2',
        'pg8000>=1.14.0'],
    include_package_data=True,
    python_requires='>=3.6',
    zip_safe=False,
    packages=['devpi_postgresql', 'pytest_devpi_postgresql'])


from setuptools import setup
import io
import os
import re
import sys

def get_changelog():
    if 'bdist_rpm' in sys.argv:
        # exclude changelog when building rpm
        return ""
    here =

    with io.open(os.path.join(here, 'CHANGELOG'), encoding="utf-8") as f:
        text = f.read()
    header_matches = list(re.finditer('^=+$', text, re.MULTILINE))
    # until fifth header
    if len(header_matches) > 5:
        text = text[:header_matches[5].start()]
        # all lines without fifth release number
        lines = text.splitlines()[:-1]
    else:
        lines = text.splitlines()
    return "=========\nChangelog\n=========\n\n" + "\n".join(lines)

README = io.open(os.path.abspath('README.rst'), encoding='utf-8').read()
CHANGELOG = get_changelog()

setup(
    name="devpi-postgresql",
    description="devpi-postgresql: a PostgreSQL storage backend for devpi-server",
    long_description="\n\n".join([README, CHANGELOG]),
    url="https://devpi.net",
    project_urls={
        'Bug Tracker': 'http://example.com',
        'Changelog': 'http://example.com',
        'Documentation': 'https://doc.devpi.net',
        'Source Code': 'http://example.com'
    },
    version='2.0.0',
    maintainer="Florian Schulze, Holger Krekel",
    maintainer_email="example@nnthink.com",
    license="MIT",
    classifiers=[
        "Development Status :: 4 - Beta",
        "Environment :: Web Environment",
        "Intended Audience :: Developers",
        "Intended Audience :: System Administrators",
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python :: 3 :: Only",
        "Topic :: Internet :: WWW/HTTP",
        "Programming Language :: Python :: Implementation :: PyPy",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application"] + [
            "Programming Language :: Python :: %s" % x
            for x in "3.6 3.7 3.8 3.9 3.10".split()],
    entry_points={
        'devpi_server': [
            "devpi-postgresql = devpi_postgresql.main"],
        'pytest11': [
            "pytest_devpi_postgresql = pytest_devpi_postgresql"]},
    install_requires=[
        'devpi-server>=3.0.0.dev2',
        'pg8000>=1.14.0'],
    include_package_data=True,
    python_requires='>=3.6',
    zip_safe=False,
    packages=['devpi_postgresql', 'pytest_devpi_postgresql'])


    first = 0
    neg = False

    if base64[0] == '-':
        neg = True
        first = 1

    for i in xrange(first, len(base64)):
        value = value << 6
        value += base64_map[base64[i]]

    return -value if neg else value


###    This file is part of Pyffle BBS.

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relation, backref
from sqlalchemy import *
from sqlalchemy.dialects.postgresql import *
from sqlalchemy.orm import sessionmaker
from pyffle_tables import *
from pyffle_data import *
from pyffle_editor import Editor
from datetime import datetime
import sys
import getpass
import os
import tempfile

def getIdentity():
	return "pyffle_boards v0.01"

## Returns True if the version of pyffle is compatible this version of module
def confirmVersion(version):
	return True

class PyffleModule:
	currentUser = None
	data = None

	def eventDispatched(self, event):
		pass

	def displayMessage(self,msgid):
		instance = self.data.getMessage(msgid)
		for msgtext in self.data.getMessagetexts(msgid):
			self.data.util.println(msgtext)
		self.data.util.printraw(" ")

	def plan(self):
		board = self.data.getBoardByName('__pyffle_plan')
		if self.data.srmcheck(board.aclid,self.currentUser.username,"POST",minlevel=board.minpostlevel):
			## Retrieve the existing plan, if any
			messageIds = self.data.getMessagesByBoardByUsername(board,currentUser.username)
			s = None
			for msgid in messageIds:
				for msgtext in self.data.getMessagetexts(msgid):
					s = s + msgtext
			## Pass any existing message text to the editor
			editor = Editor()
			theText = editor.getText(text=s)
			confirm = self.data.util.yesnoprompt("Proceed? ")
			if confirm:
				## delete any old plans
				for msgid in messageIds:
					self.data.deleteMessage(msgid)
				## post the new plan
				sentId = self.data.createMessage(self.currentUser.username,currentUser.username,subject.strip(),theText,board=board)
				self.data.util.println("Plan posted.")
		else:
			self.data.util.println("Sorry, you are not allowed to post a plan.")

command = command.strip()
		if command == "plan":
			self.plan()
		if command == "finger":
			pass


###    This file is part of Pyffle BBS.

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relation, backref
from sqlalchemy import *
from sqlalchemy.dialects.postgresql import *
from sqlalchemy.orm import sessionmaker
from pyffle_tables import *
from pyffle_data import *
from pyffle_editor import Editor
from datetime import datetime
import sys
import getpass
import os
import tempfile

def getIdentity():

## Returns True if the version of pyffle is compatible this version of module
def confirmVersion(version):
	return True

class PyffleModule:
	currentUser = None
	data = None

	def eventDispatched(self, event):
		pass

	def displayMessage(self,msgid):
		instance = self.data.getMessage(msgid)
		for msgtext in self.data.getMessagetexts(msgid):
			self.data.util.println(msgtext)
		self.data.util.printraw(" ")

	def plan(self):
		board = self.data.getBoardByName('__pyffle_plan')
		if self.data.srmcheck(board.aclid,self.currentUser.username,"POST",minlevel=board.minpostlevel):
			## Retrieve the existing plan, if any
			messageIds = self.data.getMessagesByBoardByUsername(board,currentUser.username)
			s = None
			for msgid in messageIds:
				for msgtext in self.data.getMessagetexts(msgid):
					s = s + msgtext
			## Pass any existing message text to the editor
			editor = Editor()
			theText = editor.getText(text=s)
			confirm = self.data.util.yesnoprompt("Proceed? ")
			if confirm:
				## delete any old plans
				for msgid in messageIds:
					self.data.deleteMessage(msgid)
				## post the new plan
				sentId = self.data.createMessage(self.currentUser.username,currentUser.username,subject.strip(),theText,board=board)
				self.data.util.println("Plan posted.")
		else:
			self.data.util.println("Sorry, you are not allowed to post a plan.")

	def go(self, command):
		command = command.strip()
		if command == "plan":
			self.plan()
		if command == "finger":
			pass


###    This file is part of Pyffle BBS.

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relation, backref
from sqlalchemy import *
from sqlalchemy.dialects.postgresql import *
from sqlalchemy.orm import sessionmaker
from pyffle_tables import *
from pyffle_data import *
from pyffle_editor import Editor
from datetime import datetime
import sys
import getpass
import os
import tempfile

def getIdentity():
	return "pyffl


def parse_single_result(self, single_result, return_type=ReturnType.FULL, **kwargs):

"""@desc
		Parser for google news search results
"""

from search_engine_parser.core.base import BaseSearch, ReturnType, SearchItem

class Search(BaseSearch):
    """
    Searches Google News for string
    """
    name = "GoogleNews"
    search_url = "http://example.com?"
    summary = "\tGoogle News is a news aggregator app developed by Google. It presents a "\
        "continuous, customizable flow of articles organized from thousands of publishers "\
        "and magazines. Google News is available as an app on Android, iOS, and the Web. "\
        "Google released a beta version in September 2002 and the official app in January 2006."

    def get_params(self, query=None, offset=None, page=None, **kwargs):
        params = {}
        params["num"] = 10
        params["start"] = page
        params["q"] = query
        params["client"] = "ubuntu"
        params["tbm"] = "nws"
        return params

    def parse_soup(self, soup):
        """
        Parses Google News Search Soup for results
        """
        return soup.find_all('div', class_='g')

"""
        Parses the source code to return

        :param single_result: single result found in <div class="g">
        :type single_result: `bs4.element.ResultSet`
        :return: parsed title, link, description, imge link, news source, date of single result
        :rtype: dict
        """
        rdict = SearchItem()

        if return_type in (ReturnType.FULL, return_type.TITLE):
            title_tag = single_result.find('h3')
            title = title_tag.text
            rdict["titles"] = title

        if return_type in (ReturnType.FULL, ReturnType.LINK):
            link_tag = single_result.find('a')
            rdict["links"] = link_tag.get('href')

        if return_type in (ReturnType.FULL, ReturnType.DESCRIPTION):
            desc_tag = single_result.find('div', class_='st')
            rdict["descriptions"] = desc_tag.text

        if return_type in (ReturnType.FULL,):
            img_tag = single_result.find('img', class_='th')
            news_source_tag = single_result.find('span', class_='e8fRJf')
            date_tag = single_result.find('span', class_='f')

            rdict["image_url"] = img_tag.get('src')
            rdict["news_source"] = news_source_tag.text
            rdict["date"] = date_tag.text
        return rdict


params = {}
        params["num"] = 10
        params["start"] = page
        params["q"] = query
        params["client"] = "ubuntu"
        params["tbm"] = "nws"
        return params

"""@desc
		Parser for google news search results
"""

from search_engine_parser.core.base import BaseSearch, ReturnType, SearchItem

class Search(BaseSearch):
    """
    Searches Google News for string
    """
    name = "GoogleNews"
    search_url = "http://example.com?"
    summary = "\tGoogle News is a news aggregator app developed by Google. It presents a "\
        "continuous, customizable flow of articles organized from thousands of publishers "\
        "and magazines. Google News is available as an app on Android, iOS, and the Web. "\
        "Google released a beta version in September 2002 and the official app in January 2006."

    def get_params(self, query=None, offset=None, page=None, **kwargs):

    def parse_soup(self, soup):
        """
        Parses Google News Search Soup for results
        """
        return soup.find_all('div', class_='g')

    def parse_single_result(self, single_result, return_type=ReturnType.FULL, **kwargs):
        """
        Parses the source code to return

        :param single_result: single result found in <div class="g">
        :type single_result: `bs4.element.ResultSet`
        :return: parsed title, link, description, imge link, news source, date of single result
        :rtype: dict
        """
        rdict = SearchItem()

        if return_type in (ReturnType.FULL, return_type.TITLE):
            title_tag = single_result.find('h3')
            title = title_tag.text
            rdict["titles"] = title

        if return_type in (ReturnType.FULL, ReturnType.LINK):
            link_tag = single_result.find('a')
            rdict["links"] = link_tag.get('href')

        if return_type in (ReturnType.FULL, ReturnType.DESCRIPTION):
            desc_tag = single_result.find('div', class_='st')
            rdict["descriptions"] = desc_tag.text

        if return_type in (ReturnType.FULL,):
            img_tag = single_result.find('img', class_='th')
            news_source_tag = single_result.find('span', class_='e8fRJf')
            date_tag = single_result.find('span', class_='f')

            rdict["image_url"] = img_tag.get('src')
            rdict["news_source"] = news_source_tag.text
            rdict["date"] = date_tag.text
        return rdict


"""@desc
		Parser for google news search results
"""

from search_engine_parser.core.base import BaseSearch, ReturnType, SearchItem

class Search(BaseSearch):
    """
    Searches Google News for string
    """
    name = "GoogleNews"
    search_url = "http://example.com?"
    summary = "\tGoogle News is a news aggregator app developed by Google. It presents a "\
        "continuous, customizable flow of articles organized from thousands of publishers "\
        "and magazines. Google News is available as an app on Android, iOS, and the Web. "\
        "Google released a beta version in September 2002 and the official app in January 2006."

    def get_params(self, query=None, offset=None, page=None, **kwargs):
        params = {}
        params["num"] = 10
        params["start"] = page
        params["q"] = qu

        params["client"] = "ubuntu"
        params["tbm"] = "nws"
        return params

    def parse_soup(self, soup):
        """
        Parses Google News Search Soup for results
        """
        return soup.find_all('div', class_='g')

    def parse_single_result(self, single_result, return_type=ReturnType.FULL, **kwargs):
        """
        Parses the source code to return

        :param single_result: single result found in <div class="g">
        :type single_result: `bs4.element.ResultSet`
        :return: parsed title, link, description, imge link, news source, date of single result
        :rtype: dict
        """
        rdict = SearchItem()

        if return_type in (ReturnType.FULL, return_type.TITLE):
            title_tag = single_result.find('h3')
            title = title_tag.text
            rdict["titles"] = title

        if return_type in (ReturnType.FULL, ReturnType.LINK):
            link_tag = single_result.find('a')
            rdict["links"] = link_tag.get('href')

        if return_type in (ReturnType.FULL, ReturnType.DESCRIPTION):
            desc_tag = single_result.find('div', class_='st')
            rdict["descriptions"] = desc_tag.text

        if return_type in (ReturnType.FULL,):
            img_tag = single_result.find('img', class_='th')
            news_source_tag = single_result.find('span', class_='e8fRJf')
            date_tag = single_result.find('span', class_='f')

            rdict["image_url"] = img_tag.get('src')
            rdict["news_source"] = news_source_tag.text
            rdict["date"] = date_tag.text
        return rdict


"""@desc
		Parser for google news search results
"""

from search_engine_parser.core.base import BaseSearch, ReturnType, SearchItem

class Search(BaseSearch):
    """
    Searches Google News for string
    """
    name = "GoogleNews"
    search_url = "http://example.com?"
    summary = "\tGoogle News is a news aggregator app developed by Google. It presents a "\
        "continuous, customizable flow of articles organized from thousands of publishers "\
        "and magazines. Google News is available as an app on Android, iOS, and the Web. "\
        "Google released a beta version in September 2002 and the official app in January 2006."

    def get_params(self, query=None, offset=None, page=None, **kwargs):
        params = {}
        params["num"] = 10
        params["start"] = page
        params["q"] = query
        params["client"] = "ubuntu"
        params["tbm"] = "nws"
        return params

    def parse_soup(self, soup):
        """
        Parses Google News Search Soup for results
        """

    def parse_single_result(self, single_result, return_type=ReturnType.FULL, **kwargs):
        """
        Parses the source code to return

        :param single_result: single result found in <div class="g">
        :type single_result: `bs4.element.ResultSet`
        :return: parsed title, link, description, imge link, news source, date of single result
        :rtype: dict
        """
        rdict = SearchItem()

        if return_type in (ReturnType.FULL, return_type.TITLE):
            title_tag = single_result.find('h3')
            title = title_tag.text
            rdict["titles"] = title

        if return_type in (ReturnType.FULL, ReturnType.LINK):
            link_tag = single_result.find('a')
            rdict["links"] = link_tag.get('href')

        if return_type in (ReturnType.FULL, ReturnType.DESCRIPTION):
            desc_tag = single_result.find('div', class_='st')
            rdict["descriptions"] = desc_tag.text

        if return_type in (ReturnType.FULL,):
            img_tag = single_result.find('img', class_='th')
            news_source_tag = single_result.find('span', class_='e8fRJf')
            date_tag = single_result.find('span', class_='f')

            rdict["image_url"] = img_tag.get('src')
            rdict["news_source"] = news_source_tag.text
            rdict["date"] = date_tag.text
        return rdict


import torch.nn as nn

class SharedActorCritic(nn.Module):
    def __init__(self,
                shared_architecture,
                action_space_size,
                shared_architecture_out_size,
                h_common2actor,
                h_common2value,
                policy_class,
                hidden_non_linearity=nn.ReLU):
        """
        Implements a shared Actor Critic achitecture.
        where the main trunk of the network is shared
        :param shared_architecture: the shared trunk of the two networks
        :param action_space: the size of the action space
        :param shared_architecture_out_size: the size of the output layer
                            in the shared archtecture (@TODO: find out a way to automatically figure this out)
        :param h_common2actor: the hidden layer between the common architecture and the actor
        :param h_common2value: the hidden layer between the common architecture and the value function
        :param policy_class: a pg_methods.utils.policies.Policy class that has not been instantiated yet
        :param hidden_non_linearity: the nonlinearity to use in the branched out approximator
        """
        super().__init__()
        # self.common_architecture = shared_architecture
        self.actor_fn_approximator = nn.Sequential(
                                        shared_architecture,
                                        hidden_non_linearity(),
                                        nn.Linear(shared_architecture_out_size, h_common2actor),
                                        hidden_non_linearity(),
                                        nn.Linear(h_common2actor, action_space_size))
        self.actor = policy_class(self.actor_fn_approximator)
        self.value_fn_approximator = nn.Sequential(
                                        shared_architecture,
                                        hidden_non_linearity(),
                                        nn.Linear(shared_architecture_out_size, h_common2value),
                                        hidden_non_linearity(),
                                        nn.Linear(h_common2value, 1))

action, log_probs = self.actor(state)
        value = self.value_fn_approximator(state)
        return value, action, log_probs

    def evaluate_actor_log_prob(self, states, actions):
        return self.actor.log_prob(states, actions)


import torch.nn as nn

class SharedActorCritic(nn.Module):
    def __init__(self,
                shared_architecture,
                action_space_size,
                shared_architecture_out_size,
                h_common2actor,
                h_common2value,
                policy_class,
                hidden_non_linearity=nn.ReLU):
        """
        Implements a shared Actor Critic achitecture.
        where the main trunk of the network is shared
        :param shared_architecture: the shared trunk of the two networks
        :param action_space: the size of the action space
        :param shared_architecture_out_size: the size of the output layer
                            in the shared archtecture (@TODO: find out a way to automatically figure this out)
        :param h_common2actor: the hidden layer between the common architecture and the actor
        :param h_common2value: the hidden layer between the common architecture and the value function
        :param policy_class: a pg_methods.utils.policies.Policy class that has not been instantiated yet
        :param hidden_non_linearity: the nonlinearity to use in the branched out approximator
        """
        super().__init__()
        # self.common_architecture = shared_architecture
        self.actor_fn_approximator = nn.Sequential(
                                        shared_architecture,
                                        hidden_non_linearity(),
                                        nn.Linear(shared_architecture_out_size, h_common2actor),
                                        hidden_non_linearity(),
                                        nn.Linear(h_common2actor, action_space_size))
        self.actor = policy_class(self.actor_fn_approximator)
        self.value_fn_approximator = nn.Sequential(
                                        shared_architecture,
                                        hidden_non_linearity(),
                                        nn.Linear(shared_architecture_out_size, h_common2value),
                                        hidden_non_linearity(),
                                        nn.Linear(h_common2value, 1))

    def forward(self, state):
        action, log_probs = self.actor(state)
        value = self.value_fn_approximator(state)
        return value, action, log_probs

    def evaluate_actor_log_prob(self, states, actions):


import torch.nn as nn

class SharedActorCritic(nn.Module):
    def __init__(self,
                shared_architecture,
                action_space_size,
                shared_architecture_out_size,
                h_common2actor,
                h_common2value,
                policy_class,
                hidden_non_linearity=nn.ReLU):
        """
        Implements a shared Actor Critic achitecture.
        where the main trunk of the network is shared
        :param shared_architecture: the shared trunk of the two networks
        :param action_space: the size of the action space
        :param shared_architecture_out_size: the size of the output layer
                            in the shared archtecture (@TODO: find out a way to automatically figure this out)
        :param h_common2actor: the hidden layer between the common architecture and the actor
        :param h_common2value: the hidden layer between the common architecture and the value function
        :param policy_class: a pg_methods.utils.policies.Policy class that has not been instantiated yet
        :param hidden_non_linearity: the nonlinearity to use in the branched out approximator
        """
        super().__i

        # self.common_architecture = shared_architecture
        self.actor_fn_approximator = nn.Sequential(
                                        shared_architecture,
                                        hidden_non_linearity(),
                                        nn.Linear(shared_architecture_out_size, h_common2actor),
                                        hidden_non_linearity(),
                                        nn.Linear(h_common2actor, action_space_size))
        self.actor = policy_class(self.actor_fn_approximator)
        self.value_fn_approximator = nn.Sequential(
                                        shared_architecture,
                                        hidden_non_linearity(),
                                        nn.Linear(shared_architecture_out_size, h_common2value),
                                        hidden_non_linearity(),
                                        nn.Linear(h_common2value, 1))

    def forward(self, state):
        action, log_probs = self.actor(state)
        value = self.value_fn_approximator(state)
        return value, action, log_probs

    def evaluate_actor_log_prob(self, states, actions):
        return self.actor.log_prob(states, actions)


def _normalize_scale(T: int, sis: Tensor) -> Tensor:

from dataclasses import dataclass
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch import Tensor

# noinspection PyPep8Naming
def project_lengths_softmax(T: int, L: Tensor) -> Tensor:
    """

    :param T: 1:int
    :param L: [1 x T']:float
    :return: [1 x T']:float
    """
    return T * F.softmax(L, dim=0)

class Fu(nn.Module):
    """
    Abstract class for the fu(A,L): upsamples the action probabilities A w.r.t.
    estimated actions' temporal lengths L
    """

    # noinspection PyPep8Naming
    def forward(self, A: Tensor, L: Tensor, T: int) -> Tensor:
        raise NotImplementedError

class TemporalSamplingUpSampler(Fu):
    def __init__(self):
        super().__init__()
        self.temp_width = 100

    # noinspection PyPep8Naming
    @staticmethod
    def _normalize_location(T: int, pis: Tensor, sis: Tensor) -> Tensor:
        """
        Normalizes the absolute value of z_where to the range that is appropriate for the network.
        :param T:
        :param pis:
        :param sis: unnormalized z_size
        :return:
        """
        x = pis.clone()
        x += sis / 2
        x -= T / 2
        x /= -(sis / 2)

        return x

    @staticmethod
    def _create_params_matrix(sis: Tensor, pis: Tensor) -> Tensor:
        n = sis.size(0)
        theta = sis.new_zeros(torch.Size([n, 3]))

        s = sis.clone()
        x = pis.clone()

        theta[:, 0] = s.view(-1)
        theta[:, 1] = x.view(-1)
        theta[:, 2] = 0
        return theta.float()

    @staticmethod
    def _create_theta(params: Tensor) -> Tensor:
        # Takes 3-dimensional vectors, and massages them into 2x3 matrices with elements like so:
        n = params.size(0)
        expansion_indices = torch.LongTensor([1, 0, 2, 0, 1, 3]).to(params.device)
        out = torch.cat((params.new_zeros([1, 1]).expand(n, 1), params), 1)
        return torch.index_select(out, 1, expansion_indices).view(n, 2, 3)

    # noinspection PyPep8Naming
    @staticmethod

return T / sis

    # noinspection PyPep8Naming
    def forward(self, A: Tensor, L: Tensor, T: int) -> Tensor:
        """
        Given a set of predicted actions probabilities A_{i}s, upsamples them w.r.t. the given projected L_{i}s.
        :param L: [K] The projected lengths.
        :param A: [K x C] The predicted actions' probabilities.
        :return: [1 x C x ~T] Upsampled A_{k}s.
        """

        A = A.squeeze().permute(1, 0)  # [K x C]
        L = L.squeeze()  # [K]
        L_prime = project_lengths_softmax(T=T, L=L)
        K = A.shape[0]
        C = A.shape[1]
        l_max = int(L_prime.max() + 0.5)  # round to the nearest int
        pis = torch.zeros_like(L_prime)  # [K]

        normalized_l = self._normalize_scale(l_max, L_prime)
        normalized_p = self._normalize_location(l_max, pis, L_prime)

        params_mat = self._create_params_matrix(normalized_l, normalized_p)  # [K x 3]
        theta = self._create_theta(params_mat)  # [K x 2 x 3]

        grid = F.affine_grid(theta, torch.Size((K, C, 1, l_max)))

        temp_A = A.view(K, C, 1, 1).expand(-1, -1, -1, self.temp_width)
        upsampled_probs = F.grid_sample(temp_A, grid, mode="bilinear")
        upsampled_probs = upsampled_probs.view(K, C, l_max)  # [K x C x l_max]
        upsampled_cropped = []
        for i, prob in enumerate(upsampled_probs):
            prob_cropped = prob[:, 0 : round(L_prime[i].item())]
            upsampled_cropped.append(prob_cropped)

        out = torch.cat(upsampled_cropped, dim=1).unsqueeze(dim=0)  # [1 x C x ~T]
        out = F.interpolate(input=out, size=T)  # [1 x C x T]
        return out  # [1 x C x T]


super().__init__()
        self.temp_width = 100

from dataclasses import dataclass
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch import Tensor

# noinspection PyPep8Naming
def project_lengths_softmax(T: int, L: Tensor) -> Tensor:
    """

    :param T: 1:int
    :param L: [1 x T']:float
    :return: [1 x T']:float
    """
    return T * F.softmax(L, dim=0)

class Fu(nn.Module):
    """
    Abstract class for the fu(A,L): upsamples the action probabilities A w.r.t.
    estimated actions' temporal lengths L
    """

    # noinspection PyPep8Naming
    def forward(self, A: Tensor, L: Tensor, T: int) -> Tensor:
        raise NotImplementedError

class TemporalSamplingUpSampler(Fu):
    def __init__(self):

    # noinspection PyPep8Naming
    @staticmethod
    def _normalize_location(T: int, pis: Tensor, sis: Tensor) -> Tensor:
        """
        Normalizes the absolute value of z_where to the range that is appropriate for the network.
        :param T:
        :param pis:
        :param sis: unnormalized z_size
        :return:
        """
        x = pis.clone()
        x += sis / 2
        x -= T / 2
        x /= -(sis / 2)

        return x

    @staticmethod
    def _create_params_matrix(sis: Tensor, pis: Tensor) -> Tensor:
        n = sis.size(0)
        theta = sis.new_zeros(torch.Size([n, 3]))

        s = sis.clone()
        x = pis.clone()

        theta[:, 0] = s.view(-1)
        theta[:, 1] = x.view(-1)
        theta[:, 2] = 0
        return theta.float()

    @staticmethod
    def _create_theta(params: Tensor) -> Tensor:
        # Takes 3-dimensional vectors, and massages them into 2x3 matrices with elements like so:
        n = params.size(0)
        expansion_indices = torch.LongTensor([1, 0, 2, 0, 1, 3]).to(params.device)
        out = torch.cat((params.new_zeros([1, 1]).expand(n, 1), params), 1)
        return torch.index_select(out, 1, expansion_indices).view(n, 2, 3)

    # noinspection PyPep8Naming
    @staticmethod
    def _normalize_scale(T: int, sis: Tensor) -> Tensor:
        return T / sis

    # noinspection PyPep8Naming
    def forward(self, A: Tensor, L: Tensor, T: int) -> Tensor:
        """
        Given a set of predicted actions probabilities A_{i}s, upsamples them w.r.t. the given projected L_{i}s.
        :param L: [K] The projected lengths.
        :param A: [K x C] The predicted actions' probabilities.
        :return: [1 x C x ~T] Upsampled A_{k}s.
        """

        A = A.squeeze().permute(1, 0)  # [K x C]
        L = L.squeeze()  # [K]
        L_prime = project_lengths_softmax(T=T, L=L)
        K = A.shape[0]
        C = A.shape[1]
        l_max = int(L_prime.max() + 0.5)  # round to the nearest int
        pis = torch.zeros_like(L_prime)  # [K]

        normalized_l = self._normalize_scale(l_max, L_prime)
        normalized_p = self._normalize_location(l_max, pis, L_prime)

        params_mat = self._create_params_matrix(normalized_l, normalized_p)  # [K x 3]
        theta = self._create_theta(params_mat)  # [K x 2 x 3]

        grid = F.affine_grid(theta, torch.Size((K, C, 1, l_max)))

        temp_A = A.view(K, C, 1, 1).expand(-1, -1, -1, self.temp_width)
        upsampled_probs = F.grid_sample(temp_A, grid, mode="bilinear")
        upsampled_probs = upsampled_probs.view(K, C, l_max)  # [K x C x l_max]
        upsampled_cropped = []
        for i, prob in enumerate(upsampled_probs):
            prob_cropped = prob[:, 0 : round(L_prime[i].item())]
            upsampled_cropped.append(prob_cropped)

        out = torch.cat(upsampled_cropped, dim=1).unsqueeze(dim=0)  # [1 x C x ~T]
        out = F.interpolate(input=out, size=T)  # [1 x C x T]
        return out  # [1 x C x T]


from dataclasses import dataclass
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch import Tensor

# noinspection PyPep8Naming
def project_lengths_softmax(T: int, L: Tensor) -> Tensor:
    """

    :param T: 1:int
    :param L: [1 x T']:float
    :return: [1 x T']:float
    """
    return T * F.softmax(L, dim=0)

class Fu(nn.Module):
    """
    Abstract class for the fu(A,L): upsamples the action probabilities A w.r.t.
    estimated actions' temporal lengths L
    """

    # noinspection PyPep8Naming
    def forward(self, A: Tensor, L: Tensor, T: int) -> Tensor:

class TemporalSamplingUpSampler(Fu):
    def __init__(self):
        super().__init__()
        self.temp_width = 100

    # noinspection PyPep8Naming
    @staticmethod
    def _normalize_location(T: int, pis: Tensor, sis: Tensor) -> Tensor:
        """
        Normalizes the absolute value of z_where to the range that is appropriate for the network.
        :param T:
        :param pis:
        :param sis: unnormalized z_size
        :return:
        """
        x = pis.clone()
        x += sis / 2
        x -= T / 2
        x /= -(sis / 2)

        return x

    @staticmethod
    def _create_params_matrix(sis: Tensor, pis: Tensor) -> Tensor:
        n = sis.size(0)
        theta = sis.new_zeros(torch.Size([n, 3]))

        s = sis.clone()
        x = pis.clone()

        theta[:, 0] = s.view(-1)
        theta[:, 1] = x.view(-1)
        theta[:, 2] = 0
        return theta.float()

    @staticmethod
    def _create_theta(params: Tensor) -> Tensor:
        # Takes 3-dimensional vectors, and massages them into 2x3 matrices with elements like so:
        n = params.size(0)
        expansion_indices = torch.LongTensor([1, 0, 2, 0, 1, 3]).to(params.device)
        out = torch.cat((params.new_zeros([1, 1]).expand(n, 1), params), 1)
        return torch.index_select(out, 1, expansion_indices).view(n, 2, 3)

    # noinspection PyPep8Naming
    @staticmethod
    def _normalize_scale(T: int, sis: Tensor) -> Tensor:
        return T / sis

    # noinspection PyPep8Naming
    def forward(self, A: Tensor, L: Tensor, T: int) -> Tensor:
        """
        Given a set of predicted actions probabilities A_{i}s, upsamples them w.r.t. the given projected L_{i}s.
        :param L: [K] The projected lengths.
        :param A: [K x C] The predicted actions' probabilities.
        :return: [1 x C x ~T] Upsampled A_{k}s.
        """

        A = A.squeeze().permute(1, 0)  # [K x C]
        L = L.squeeze()  # [K]
        L_prime = project_lengths_softmax(T=T, L=L)
        K = A.shape[0]
        C = A.shape[1]
        l_max = int(L_prime.max() + 0.5)  # round to the nearest int
        pis = torch.zeros_like(L_prime)  # [K]

        normalized_l = self._normalize_scale(l_max, L_prime)
        normalized_p = self._normalize_location(l_max, pis, L_prime)

        params_mat = self._create_params_matrix(normalized_l, normalized_p)  # [K x 3]
        theta = self._create_theta(params_mat)  # [K x 2 x 3]

        grid = F.affine_grid(theta, torch.Size((K, C, 1, l_max)))

        temp_A = A.view(K, C, 1, 1).expand(-1, -1, -1, self.temp_width)
        upsampled_probs = F.grid_sample(temp_A, grid, mode="bilinear")
        upsampled_probs = upsampled_probs.view(K, C, l_max)  # [K x C x l_max]
        upsampled_cropped = []
        for i, prob in enumerate(upsampled_probs):
            prob_cropped = prob[:, 0 : round(L_prime[i].item())]
            upsampled_cropped.append(prob_cropped)

        out = torch.cat(upsampled_cropped, dim=1).unsqueeze(dim=0)  # [1 x C x ~T]
        out = F.interpolate(input=out, size=T)  # [1 x C x T]
        return out  # [1 x C x T]


        x = pis.clone()
        x += sis / 2
        x -= T / 2
        x /= -(sis / 2)

        return x

from dataclasses import dataclass
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch import Tensor

# noinspection PyPep8Naming
def project_lengths_softmax(T: int, L: Tensor) -> Tensor:
    """

    :param T: 1:int
    :param L: [1 x T']:float
    :return: [1 x T']:float
    """
    return T * F.softmax(L, dim=0)

class Fu(nn.Module):
    """
    Abstract class for the fu(A,L): upsamples the action probabilities A w.r.t.
    estimated actions' temporal lengths L
    """

    # noinspection PyPep8Naming
    def forward(self, A: Tensor, L: Tensor, T: int) -> Tensor:
        raise NotImplementedError

class TemporalSamplingUpSampler(Fu):
    def __init__(self):
        super().__init__()
        self.temp_width = 100

    # noinspection PyPep8Naming
    @staticmethod
    def _normalize_location(T: int, pis: Tensor, sis: Tensor) -> Tensor:
        """
        Normalizes the absolute value of z_where to the range that is appropriate for the network.
        :param T:
        :param pis:
        :param sis: unnormalized z_size
        :return:
        """

    @staticmethod
    def _create_params_matrix(sis: Tensor, pis: Tensor) -> Tensor:
        n = sis.size(0)
        theta = sis.new_zeros(torch.Size([n, 3]))

        s = sis.clone()
        x = pis.clone()

        theta[:, 0] = s.view(-1)
        theta[:, 1] = x.view(-1)
        theta[:, 2] = 0
        return theta.float()

    @staticmethod
    def _create_theta(params: Tensor) -> Tensor:
        # Takes 3-dimensional vectors, and massages them into 2x3 matrices with elements like so:
        n = params.size(0)
        expansion_indices = torch.LongTensor([1, 0, 2, 0, 1, 3]).to(params.device)
        out = torch.cat((params.new_zeros([1, 1]).expand(n, 1), params), 1)
        return torch.index_select(out, 1, expansion_indices).view(n, 2, 3)

    # noinspection PyPep8Naming
    @staticmethod
    def _normalize_scale(T: int, sis: Tensor) -> Tensor:
        return T / sis

    # noinspection PyPep8Naming
    def forward(self, A: Tensor, L: Tensor, T: int) -> Tensor:
        """
        Given a set of predicted actions probabilities A_{i}s, upsamples them w.r.t. the given projected L_{i}s.
        :param L: [K] The projected lengths.
        :param A: [K x C] The predicted actions' probabilities.
        :return: [1 x C x ~T] Upsampled A_{k}s.
        """

        A = A.squeeze().permute(1, 0)  # [K x C]
        L = L.squeeze()  # [K]
        L_prime = project_lengths_softmax(T=T, L=L)
        K = A.shape[0]
        C = A.shape[1]
        l_max = int(L_prime.max() + 0.5)  # round to the nearest int
        pis = torch.zeros_like(L_prime)  # [K]

        normalized_l = self._normalize_scale(l_max, L_prime)
        normalized_p = self._normalize_location(l_max, pis, L_prime)

        params_mat = self._create_params_matrix(normalized_l, normalized_p)  # [K x 3]
        theta = self._create_theta(params_mat)  # [K x 2 x 3]

        grid = F.affine_grid(theta, torch.Size((K, C, 1, l_max)))

        temp_A = A.view(K, C, 1, 1).expand(-1, -1, -1, self.temp_width)
        upsampled_probs = F.grid_sample(temp_A, grid, mode="bilinear")
        upsampled_probs = upsampled_probs.view(K, C, l_max)  # [K x C x l_max]
        upsampled_cropped = []
        for i, prob in enumerate(upsampled_probs):
            prob_cropped = prob[:, 0 : round(L_prime[i].item())]
            upsampled_cropped.append(prob_cropped)

        out = torch.cat(upsampled_cropped, dim=1).unsqueeze(dim=0)  # [1 x C x ~T]
        out = F.interpolate(input=out, size=T)  # [1 x C x T]
        return out  # [1 x C x T]


def __exit__(self, exc_type, exc_value, traceback):

from cli.helpers.Step import Step
from cli.engine.providers.aws.APIProxy import APIProxy
from cli.helpers.doc_list_helpers import select_single, select_first

class InfrastructureConfigCollector(Step):

    def __init__(self, docs):
        super().__init__(__name__)
        self.cluster_model = select_single(docs, lambda x: x.kind == 'epiphany-cluster')
        self.docs = docs

    def __enter__(self):
        super().__enter__()
        return self

pass

    def run(self):
        with APIProxy(self.cluster_model, self.docs) as proxy:
            self.apply_efs_filesystem_id_for_k8s_pv(proxy)

    def apply_efs_filesystem_id_for_k8s_pv(self, proxy):
        efs_storage_config = select_first(self.docs, lambda x: x.kind == 'infrastructure/efs-storage')
        kubernetes_config = select_first(self.docs, lambda x: x.kind == 'configuration/kubernetes-master')

        if self.should_apply_storage_settings(efs_storage_config, kubernetes_config):
            fs_id = proxy.get_efs_id_for_given_token(efs_storage_config.specification.token)
            kubernetes_config.specification.storage.data = {'server': self.get_efs_server_url(fs_id)}

    def should_apply_storage_settings(self, efs_storage_config, kubernetes_config):
        return efs_storage_config is not None and kubernetes_config is not None and \
               len(efs_storage_config.specification.mount_targets) > 0

    def get_efs_server_url(self, filesystem_id):
        return filesystem_id+'.efs.'+self.cluster_model.specification.cloud.region+'.amazonaws.com'


efs_storage_config = select_first(self.docs, lambda x: x.kind == 'infrastructure/efs-storage')
        kubernetes_config = select_first(self.docs, lambda x: x.kind == 'configuration/kubernetes-master')

        if self.should_apply_storage_settings(efs_storage_config, kubernetes_config):
            fs_id = proxy.get_efs_id_for_given_token(efs_storage_config.specification.token)
            kubernetes_config.specification.storage.data = {'server': self.get_efs_server_url(fs_id)}

from cli.helpers.Step import Step
from cli.engine.providers.aws.APIProxy import APIProxy
from cli.helpers.doc_list_helpers import select_single, select_first

class InfrastructureConfigCollector(Step):

    def __init__(self, docs):
        super().__init__(__name__)
        self.cluster_model = select_single(docs, lambda x: x.kind == 'epiphany-cluster')
        self.docs = docs

    def __enter__(self):
        super().__enter__()
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        pass

    def run(self):
        with APIProxy(self.cluster_model, self.docs) as proxy:
            self.apply_efs_filesystem_id_for_k8s_pv(proxy)

    def apply_efs_filesystem_id_for_k8s_pv(self, proxy):

    def should_apply_storage_settings(self, efs_storage_config, kubernetes_config):
        return efs_storage_config is not None and kubernetes_config is not None and \
               len(efs_storage_config.specification.mount_targets) > 0

    def get_efs_server_url(self, filesystem_id):
        return filesystem_id+'.efs.'+self.cluster_model.specification.cloud.region+'.amazonaws.com'


from cli.helpers.Step import Step
from cli.engine.providers.aws.APIProxy import APIProxy
from cli.helpers.doc_list_helpers import select_single, select_first

class InfrastructureConfigCollector(Step):

    def __init__(self, docs):
        super().__init__(__name__)
        self.cluster_model = select_single(docs, lambda x: x.kind == 'epiphany-cluster')
        self.docs = docs

    def __enter__(self):
        super().__enter__()
        return s

    def __exit__(self, exc_type, exc_value, traceback):
        pass

    def run(self):
        with APIProxy(self.cluster_model, self.docs) as proxy:
            self.apply_efs_filesystem_id_for_k8s_pv(proxy)

    def apply_efs_filesystem_id_for_k8s_pv(self, proxy):
        efs_storage_config = select_first(self.docs, lambda x: x.kind == 'infrastructure/efs-storage')
        kubernetes_config = select_first(self.docs, lambda x: x.kind == 'configuration/kubernetes-master')

        if self.should_apply_storage_settings(efs_storage_config, kubernetes_config):
            fs_id = proxy.get_efs_id_for_given_token(efs_storage_config.specification.token)
            kubernetes_config.specification.storage.data = {'server': self.get_efs_server_url(fs_id)}

    def should_apply_storage_settings(self, efs_storage_config, kubernetes_config):
        return efs_storage_config is not None and kubernetes_config is not None and \
               len(efs_storage_config.specification.mount_targets) > 0

    def get_efs_server_url(self, filesystem_id):
        return filesystem_id+'.efs.'+self.cluster_model.specification.cloud.region+'.amazonaws.com'


def test_simple_insert(self, session, Product):

import pytest
import sqlalchemy as sa

from sqlalchemy_utils.observer import observes

@pytest.mark.usefixtures('postgresql_dsn')
class TestObservesForColumn(object):

    @pytest.fixture
    def Product(self, Base):
        class Product(Base):
            __tablename__ = 'product'
            id = sa.Column(sa.Integer, primary_key=True)
            price = sa.Column(sa.Integer)

            @observes('price')
            def product_price_observer(self, price):
                self.price = price * 2
        return Product

    @pytest.fixture
    def init_models(self, Product):
        pass

product = Product(price=100)
        session.add(product)
        session.flush()
        assert product.price == 200

@pytest.mark.usefixtures('postgresql_dsn')
class TestObservesForColumnWithoutActualChanges(object):

    @pytest.fixture
    def Product(self, Base):
        class Product(Base):
            __tablename__ = 'product'
            id = sa.Column(sa.Integer, primary_key=True)
            price = sa.Column(sa.Integer)

            @observes('price')
            def product_price_observer(self, price):
                raise Exception('Trying to change price')
        return Product

    @pytest.fixture
    def init_models(self, Product):
        pass

    def test_only_notifies_observer_on_actual_changes(self, session, Product):
        product = Product()
        session.add(product)
        session.flush()

        with pytest.raises(Exception) as e:
            product.price = 500
            session.commit()
        assert str(e.value) == 'Trying to change price'

@pytest.mark.usefixtures('postgresql_dsn')
class TestObservesForMultipleColumns(object):

    @pytest.fixture
    def Order(self, Base):
        class Order(Base):
            __tablename__ = 'order'
            id = sa.Column(sa.Integer, primary_key=True)
            unit_price = sa.Column(sa.Integer)
            amount = sa.Column(sa.Integer)
            total_price = sa.Column(sa.Integer)

            @observes('amount', 'unit_price')
            def total_price_observer(self, amount, unit_price):
                self.total_price = amount * unit_price
        return Order

    @pytest.fixture
    def init_models(self, Order):
        pass

    def test_only_notifies_observer_on_actual_changes(self, session, Order):
        order = Order()
        order.amount = 2
        order.unit_price = 10
        session.add(order)
        session.flush()

        order.amount = 1
        session.flush()
        assert order.total_price == 10

        order.unit_price = 100
        session.flush()
        assert order.total_price == 100

@pytest.mark.usefixtures('postgresql_dsn')
class TestObservesForMultipleColumnsFiresOnlyOnce(object):

    @pytest.fixture
    def Order(self, Base):
        class Order(Base):
            __tablename__ = 'order'
            id = sa.Column(sa.Integer, primary_key=True)
            unit_price = sa.Column(sa.Integer)
            amount = sa.Column(sa.Integer)

            @observes('amount', 'unit_price')
            def total_price_observer(self, amount, unit_price):
                self.call_count = self.call_count + 1
        return Order

    @pytest.fixture
    def init_models(self, Order):
        pass

    def test_only_notifies_observer_on_actual_changes(self, session, Order):
        order = Order()
        order.amount = 2
        order.unit_price = 10
        order.call_count = 0
        session.add(order)
        session.flush()
        assert order.call_count == 1

        order.amount = 1
        order.unit_price = 100
        session.flush()
        assert order.call_count == 2


product = Product()
        session.add(product)
        session.flush()

        with pytest.raises(Exception) as e:
            product.price = 500
            session.commit()
        assert str(e.value) == 'Trying to change price'

import pytest
import sqlalchemy as sa

from sqlalchemy_utils.observer import observes

@pytest.mark.usefixtures('postgresql_dsn')
class TestObservesForColumn(object):

    @pytest.fixture
    def Product(self, Base):
        class Product(Base):
            __tablename__ = 'product'
            id = sa.Column(sa.Integer, primary_key=True)
            price = sa.Column(sa.Integer)

            @observes('price')
            def product_price_observer(self, price):
                self.price = price * 2
        return Product

    @pytest.fixture
    def init_models(self, Product):
        pass

    def test_simple_insert(self, session, Product):
        product = Product(price=100)
        session.add(product)
        session.flush()
        assert product.price == 200

@pytest.mark.usefixtures('postgresql_dsn')
class TestObservesForColumnWithoutActualChanges(object):

    @pytest.fixture
    def Product(self, Base):
        class Product(Base):
            __tablename__ = 'product'
            id = sa.Column(sa.Integer, primary_key=True)
            price = sa.Column(sa.Integer)

            @observes('price')
            def product_price_observer(self, price):
                raise Exception('Trying to change price')
        return Product

    @pytest.fixture
    def init_models(self, Product):
        pass

    def test_only_notifies_observer_on_actual_changes(self, session, Product):

@pytest.mark.usefixtures('postgresql_dsn')
class TestObservesForMultipleColumns(object):

    @pytest.fixture
    def Order(self, Base):
        class Order(Base):
            __tablename__ = 'order'
            id = sa.Column(sa.Integer, primary_key=True)
            unit_price = sa.Column(sa.Integer)
            amount = sa.Column(sa.Integer)
            total_price = sa.Column(sa.Integer)

            @observes('amount', 'unit_price')
            def total_price_observer(self, amount, unit_price):
                self.total_price = amount * unit_price
        return Order

    @pytest.fixture
    def init_models(self, Order):
        pass

    def test_only_notifies_observer_on_actual_changes(self, session, Order):
        order = Order()
        order.amount = 2
        order.unit_price = 10
        session.add(order)
        session.flush()

        order.amount = 1
        session.flush()
        assert order.total_price == 10

        order.unit_price = 100
        session.flush()
        assert order.total_price == 100

@pytest.mark.usefixtures('postgresql_dsn')
class TestObservesForMultipleColumnsFiresOnlyOnce(object):

    @pytest.fixture
    def Order(self, Base):
        class Order(Base):
            __tablename__ = 'order'
            id = sa.Column(sa.Integer, primary_key=True)
            unit_price = sa.Column(sa.Integer)
            amount = sa.Column(sa.Integer)

            @observes('amount', 'unit_price')
            def total_price_observer(self, amount, unit_price):
                self.call_count = self.call_count + 1
        return Order

    @pytest.fixture
    def init_models(self, Order):
        pass

    def test_only_notifies_observer_on_actual_changes(self, session, Order):
        order = Order()
        order.amount = 2
        order.unit_price = 10
        order.call_count = 0
        session.add(order)
        session.flush()
        assert order.call_count == 1

        order.amount = 1
        order.unit_price = 100
        session.flush()
        assert order.call_count == 2


import pytest
import sqlalchemy as sa

from sqlalchemy_utils.observer import observes

@pytest.mark.usefixtures('postgresql_dsn')
class TestObservesForColumn(object):

    @pytest.fixture
    def Product(self, Base):
        class Product(Base):
            __tablename__ = 'product'
            id = sa.Column(sa.Integer, primary_key=True)
            price = sa.Column(sa.Integer)

            @observes('price')
            def product_price_observer(self, price):
                self.price = price * 2
        return Product

    @pytest.fixture
    def init_models(self, Product):
        pass

    def test_simple_insert(self, session, Product):
        product = Product(price=100)
        session.add(product)
        session.flush()
        assert product.price == 200

@pytest.mark.usefixtures('postgresql_dsn')
class TestObservesForColumnWithoutActualChanges(object):

    @pytest.fixture
    def Product(self, Base):
        class Product(Base):
            __tablename__ = 'product'
            id = sa.Column(sa.Integer, primary_key=True)
            price = sa.Column(sa.Integer)

            @observes('price')
            def product_price_observer(self, price):
                raise Exception('Trying to change price')
        return Product

    @pytest.fixture
    def init_models(self, Product):
        pass

    def test_only_notifies_observer_on_actual_changes(self, session, Product):
        product = Product()
        session.add(product)
        session.flush()

        with pytest.raises(Exception) as e:
            product.price = 500
            session.commit()
        assert str(e.value) == 'Trying to


#  Authors:             Thomas Larsson
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,

import math

from .flags import *

class CConstraint:
    def __init__(self, type, name, flags, inf):
        self.constraint = None
        self.name = name
        self.type = type
        self.influence = inf
        self.active = (flags & C_ACT == 0)
        self.expanded = (flags & C_EXP != 0)

        ow = flags & C_OW_MASK
        if ow == 0:
            self.ownsp = 'WORLD'
        elif ow == C_OW_LOCAL:
            self.ownsp = 'LOCAL'
        elif ow == C_OW_LOCPAR:
            self.ownsp = 'LOCAL_WITH_PARENT'
        elif ow == C_OW_POSE:
            self.ownsp = 'POSE'

        tg = flags & C_TG_MASK
        if tg == 0:
            self.targsp = 'WORLD'
        elif tg == C_TG_LOCAL:
            self.targsp = 'LOCAL'
        elif tg == C_TG_LOCPAR:
            self.targsp = 'LOCAL_WITH_PARENT'
        elif tg == C_TG_POSE:
            self.targsp = 'POSE'

    def update(self, parser, bone):
        return
        raise NameError("Unknown constraint: bone %s cns %s type %s" % (bone.name, self.name, self.type))

    def __repr__(self):
        return ("<CConstraint %s %s>" % (self.name, self.type))

    def build(self, pb, rig, parser):
        cns = self.constraint = pb.constraints.new(self.type)
        cns.name = self.name
        cns.influence = self.influence
        cns.active = self.active
        cns.show_expanded = self.expanded
        cns.target_space = self.targsp
        cns.owner_space = self.ownsp
        return cns

#   Constraint subclasses

class CIkConstraint(CConstraint):
    def __init__(self, flags, inf, data, lockLoc, lockRot):
        CConstraint.__init__(self, "IK", data[0], flags, inf)
        self.subtar = data[1]
        self.chainlen = data[2]
        self.pole = data[3]
        if self.pole:
            (self.angle, self.ptar) = self.pole
        else:
            (self.angle, self.ptar) = (0, None)
        (self.useLoc, self.useRot, self.useStretch) = data[4]
        if len(data) > 5:
            self.useTail = data[5]
        else:
            self.useTail = True
        self.lockLoc = lockLoc
        self.lockRot = lockRot
        (lockRotX, lockRotY, lockRotZ) = lockRot

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        cns.target = rig
        cns.subtarget = self.subtar
        cns.use_tail = self.useTail

        cns.reference_axis = 'BONE'
        cns.chain_count =  self.chainlen
        cns.ik_type = 'COPY_POSE'
        cns.iterations = 500
        cns.limit_mode = 'LIMITDIST_INSIDE'
        cns.orient_weight = 1

        if self.pole:
            cns.pole_angle = self.angle*D
            cns.pole_subtarget = self.ptar
            cns.pole_target = rig

        cns.use_location = self.useLoc
        cns.use_rotation = self.useRot
        cns.use_stretch = self.useStretch
        cns.weight = 1

    def update(self, parser, bone):
        if self.chainlen == 1:
            target = parser.bones[self.subtar]
            head = bone.getHead()
            goal = target.getHead()
            vec = goal - head
            dist = math.sqrt(vec.dot(vec))
            goal = head + vec*(bone.length/dist)
            bone.stretchTo(goal, False)

            if self.ptar:
                pole = parser.bones[self.ptar].getHead()
                bone.poleTargetCorrect(head, goal, pole, self.angle)
        else:
            raise NameError("IK chainlen %d %s" % (self.chainlen, bone.name))

class CActionConstraint(CConstraint):
    def __init__(self, flags, inf, data):
        CConstraint.__init__(self, "ACTION", data[0], flags, inf)
        self.action = data[1]
        self.subtar = data[2]
        self.channel = data[3]
        (self.sframe, self.eframe) = data[4]
        (self.amin, self.amax) = data[5]

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        scale = parser.scale
        cns.target = rig
        cns.action = self.action
        cns.frame_start = self.sframe
        cns.frame_end = self.eframe
        if channel[0:3] == 'LOC':
            cns.maximum = self.amax*scale
            cns.minimum = self.amin*scale
        else:
            cns.maximum = self.amax
            cns.minimum = self.amin
        cns.subtarget = self.subtar
        cns.transform_channel = self.channel

class CCopyRotConstraint(CConstraint):
    def __init__(self, flags, inf, data):
        CConstraint.__init__(self, "COPY_ROTATION", data[0], flags, inf)
        self.subtar = data[1]
        self.use = data[2]
        self.invert = data[3]
        self.useOffs = data[4]

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        cns.target = rig
        cns.use_x,cns.use_y,cns.use_z = self.use
        cns.invert_x,cns.invert_y,cns.invert_z = self.invert
        if isinstance(self.subtar, tuple):
            bname1,bname2 = self.subtar
            if bname1 in rig.data.bones.keys():
                cns.subtarget = bname1
            else:
                cns.subtarget = bname2
        else:
            cns.subtarget = self.subtar
        cns.use_offset = self.useOffs

class CCopyLocConstraint(CConstraint):
    def __init__(self, flags, inf, data):
        CConstraint.__init__(self, "COPY_LOCATION", data[0], flags, inf)
        self.subtar = data[1]
        self.use = data[2]
        self.invert = data[3]
        self.head_tail = data[4]
        self.useOffs = data[5]

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        cns.target = rig
        cns.use_x,cns.use_y,cns.use_z = self.use
        cns.invert_x,cns.invert_y,cns.invert_z = self.invert
        cns.head_tail = self.head_tail
        cns.subtarget = self.subtar
        cns.use_offset = self.useOffs

class CCopyScaleConstraint(CConstraint):
    def __init__(self, flags, inf, data):
        CConstraint.__init__(self, "COPY_SCALE", data[0], flags, inf)
        self.subtar = data[1]
        self.use = data[2]
        self.useOffs = data[3]

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        cns.target = rig
        cns.use_x,cns.use_y,cns.use_z = self.use
        cns.subtarget = self.subtar
        cns.use_offset = self.useOffs

class CCopyTransConstraint(CConstraint):
    def __init__(self, flags, inf, data):
        CConstraint.__init__(self, "COPY_TRANSFORMS", data[0], flags, inf)
        self.subtar = data[1]
        self.head_tail = data[2]

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        cns.target = rig
        cns.head_tail = self.head_tail
        cns.subtarget = self.subtar

class CLimitRotConstraint(CConstraint):
    def __init__(self, flags, inf, data):
        CConstraint.__init__(self, "LIMIT_ROTATION", data[0], flags, inf)
        (self.xmin, self.xmax, self.ymin, self.ymax, self.zmin, self.zmax) = data[1]
        (self.usex, self.usey, self.usez) = data[2]
        self.ltra = (flags & C_LTRA != 0)

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        cns.use_transform_limit = self.ltra
        cns.max_x = self.xmax*D
        cns.max_y = self.ymax*D
        cns.max_z = self.zmax*D
        cns.min_x = self.xmin*D
        cns.min_y = self.ymin*D
        cns.min_z = self.zmin*D
        cns.use_limit_x = self.usex
        cns.use_limit_y = self.usey
        cns.use_limit_z = self.usez

class CLimitLocConstraint(CConstraint):
    def __init__(self, flags, inf, data):
        CConstraint.__init__(self, "LIMIT_LOCATION", data[0], flags, inf)
        (self.xmin, self.xmax, self.ymin, self.ymax, self.zmin, self.zmax) = data[1]
        (self.useminx, self.usemaxx, self.useminy, self.usemaxy, self.useminz, self.usemaxz) = data[2]

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        scale = parser.scale

        cns.use_transform_limit = True
        cns.max_x = self.xmax*scale
        cns.max_y = self.ymax*scale
        cns.max_z = self.zmax*scale
        cns.min_x = self.xmin*scale
        cns.min_y = self.ymin*scale
        cns.min_z = self.zmin*scale
        cns.use_max_x = self.usemaxx
        cns.use_max_y = self.usemaxy
        cns.use_max_z = self.usemaxz
        cns.use_min_x = self.useminx
        cns.use_min_y = self.useminy
        cns.use_min_z = self.useminz

class CLimitScaleConstraint(CConstraint):

CConstraint.__init__(self, "LIMIT_SCALE", data[0], flags, inf)
        (self.xmin, self.xmax, self.ymin, self.ymax, self.zmin, self.zmax) = data[1]
        (self.usex, self.usey, self.usez) = data[2]

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        cns.max_x = self.xmax
        cns.max_y = self.ymax
        cns.max_z = self.zmax
        cns.min_x = self.xmin
        cns.min_y = self.ymin
        cns.min_z = self.zmin
        cns.use_max_x = self.usex
        cns.use_max_y = self.usey
        cns.use_max_z = self.usez
        cns.use_min_x = self.usex
        cns.use_min_y = self.usey
        cns.use_min_z = self.usez

class CTransformConstraint(CConstraint):
    def __init__(self, flags, inf, data):
        CConstraint.__init__(self, "TRANSFORM", data[0], flags, inf)
        self.subtar = data[1]
        self.map_from = data[2]
        self.from_min = data[3]
        self.from_max = data[4]
        self.map_to_from = data[5]
        self.map_to = data[6]
        self.to_min = data[7]
        self.to_max = data[8]

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        cns.target = rig
        cns.subtarget = self.subtar
        cns.map_from = self.map_from
        cns.from_min_x = self.from_min[0]
        cns.from_min_y = self.from_min[1]
        cns.from_min_z = self.from_min[2]
        cns.from_max_x = self.from_max[0]
        cns.from_max_y = self.from_max[1]
        cns.from_max_z = self.from_max[2]
        cns.map_to = self.map_to
        cns.map_to_x_from = self.map_to_from[0]
        cns.map_to_y_from = self.map_to_from[1]
        cns.map_to_z_from = self.map_to_from[2]
        cns.to_min_x = self.to_min[0]
        cns.to_min_y = self.to_min[1]
        cns.to_min_z = self.to_min[2]
        cns.to_max_x = self.to_max[0]
        cns.to_max_y = self.to_max[1]
        cns.to_max_z = self.to_max[2]

class CDampedTrackConstraint(CConstraint):
    def __init__(self, flags, inf, data):
        CConstraint.__init__(self, "DAMPED_TRACK", data[0], flags, inf)
        self.subtar = data[1]
        self.track = data[2]
        self.headtail = data[3]

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        cns.target = parser.name
        cns.subtarget = self.subtar
        cns.head_tail = self.headtail
        cns.track_axis = self.track

class CLockedTrackConstraint(CConstraint):
    def __init__(self, flags, inf, data):
        CConstraint.__init__(self, "LOCKED_TRACK", data[0], flags, inf)
        self.subtar = data[1]
        self.trackAxis = data[2]

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        cns.target = rig
        cns.subtarget = self.subtar
        cns.track_axis = self.trackAxis

class CStretchToConstraint(CConstraint):
    def __init__(self, flags, inf, data, parser=None):
        CConstraint.__init__(self, "STRETCH_TO", data[0], flags, inf)
        self.subtar = data[1]
        self.head_tail = data[2]
        self.bulge = data[3]
        if (parser != None) and (len(data) > 4):
            if isinstance(data[4], tuple):
                start,end = data[4]
                self.rest_length = parser.parser.distance(start,end)
            else:
                self.rest_length = data[4]
        else:
            self.rest_length = None
        if flags & C_VOLXZ:
            self.volume = 'VOLUME_XZX'
        elif flags & C_VOLX:
            self.volume = 'VOLUME_X'
        elif flags & C_VOLZ:
            self.volume = 'VOLUME_Z'
        else:
            self.volume = 'NO_VOLUME'
        if flags & C_PLANEZ:
            self.axis = 'PLANE_Z'
        else:
            self.axis = 'PLANE_X'

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        scale = parser.scale
        cns.target = rig
        cns.bulge = self.bulge
        cns.head_tail = self.head_tail
        cns.keep_axis = self.axis
        cns.subtarget = self.subtar
        cns.volume = self.volume
        if self.rest_length != None:
            cns.rest_length = self.rest_length*scale

    def update(self, parser, bone):
        target = parser.bones[self.subtar]
        goal = (1-self.head_tail)*target.getHead() + self.head_tail*target.getTail()
        bone.stretchTo(goal, True)

class CTrackToConstraint(CConstraint):
    def __init__(self, flags, inf, data):
        CConstraint.__init__(self, "TRACK_TO", data[0], flags, inf)
        self.subtar = data[1]
        self.head_tail = data[2]
        self.track_axis = data[3]
        self.up_axis = data[4]
        self.use_target_z = data[5]

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        cns.target = rig
        cns.head_tail = self.head_tail
        cns.track_axis = self.track_axis
        cns.up_axis = self.up_axis
        cns.subtarget = self.subtar
        cns.use_target_z = self.use_target_z

class CLimitDistConstraint(CConstraint):
    def __init__(self, flags, inf, data):
        CConstraint.__init__(self, "LIMIT_DISTANCE", data[0], flags, inf)
        self.subtar = data[1]
        self.limit_mode = data[2]

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        cns.target = rig
        cns.limit_mode = self.limit_mode
        cns.subtarget = self.subtar

class CChildOfConstraint(CConstraint):
    def __init__(self, flags, inf, data):
        CConstraint.__init__(self, "CHILD_OF", data[0], flags, inf)
        self.subtar = data[1]
        (self.locx, self.locy, self.locz) = data[2]
        (self.rotx, self.roty, self.rotz) = data[3]
        (self.scalex, self.scaley, self.scalez) = data[4]

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        cns.target = rig
        cns.subtarget = self.subtar
        cns.use_location_x = self.locx
        cns.use_location_y = self.locy
        cns.use_location_z = self.locz
        cns.use_rotation_x = self.rotx
        cns.use_rotation_y = self.roty
        cns.use_rotation_z = self.rotz
        cns.use_scale_x = self.scalex
        cns.use_scale_y = self.scaley
        cns.use_scale_z = self.scalez

class CSplineIkConstraint(CConstraint):
    def __init__(self, flags, inf, data):
        CConstraint.__init__(self, "SPLINE_IK", data[0], flags, inf)
        self.target = data[1]
        self.count = data[2]

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        cns.target = rig
        cns.chain_count = self.count
        cns.use_chain_offset = False
        cns.use_curve_radius = True
        cns.use_even_divisions = False
        cns.use_y_stretch = True
        cns.xz_scale_mode = None

class CFloorConstraint(CConstraint):
    def __init__(self, flags, inf, data):
        CConstraint.__init__(self, "FLOOR", data[0], flags, inf)
        self.subtar = data[1]
        self.floor_location = data[2]
        self.offset = data[3]
        self.use_rotation = data[4]
        self.use_sticky = data[5]

    def build(self, pb, rig, parser):
        cns = CConstraint.build(self, pb, rig, parser)
        cns.target = rig
        cns.floor_location = self.floor_location
        cns.offset= self.offset
        cns.subtarget = self.subtar
        cns.use_rotation = self.use_rotation
        cns.use_sticky = self.use_sticky

def addConstraint(cdef, lockLoc=(False,False,False), lockRot=(False,False,False)):
    (type, flags, inf, data) = cdef
    if type == 'IK':
        return CIkConstraint(flags, inf, data, lockLoc, lockRot)
    elif type == 'Action':
        return CActionConstraint(flags, inf, data)
    elif type == 'CopyRot':
        return CCopyRotConstraint(flags, inf, data)
    elif type == 'CopyLoc':
        return CCopyLocConstraint(flags, inf, data)
    elif type == 'CopyScale':
        return CCopyScaleConstraint(flags, inf, data)
    elif type == 'CopyTrans':
        return CCopyTransConstraint(flags, inf, data)
    elif type == 'LimitRot':
        return CLimitRotConstraint(flags, inf, data)
    elif type == 'LimitLoc':
        return CLimitLocConstraint(flags, inf, data)
    elif type == 'LimitScale':
        return CLimitScaleConstraint(flags, inf, data)
    elif type == 'Transform':
        return CTransformConstraint(flags, inf, data)
    elif type == 'LockedTrack':
        return CLockedTrackConstraint(flags, inf, data)
    elif type == 'DampedTrack':
        return CDampedTrackConstraint(flags, inf, data)
    elif type == 'StretchTo':
        return CStretchToConstraint(flags, inf, data)
    elif type == 'TrackTo':
        return CTrackToConstraint(flags, inf, data)
    elif type == 'LimitDist':
        return CLimitDistConstraint(flags, inf, data)
    elif type == 'ChildOf':
        return CChildOfConstraint(flags, inf, data)
    elif type == 'SplineIK':
        return CSplineIkConstraint(flags, inf, data)
    elif type == 'Floor':
        return CFloorConstraint(flags, inf, data)
    else:
        raise RuntimeError("Unknown constraint type %s" % type)