<commit_before>#!/usr/bin/python

# Copyright (c) 2016 Steven A. Bjornson
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all copies
# or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
# FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

## Info
# The goal of this software is to fascilitate the creation
# of complex light patterns using a large array of
# Philips Hue bulbs.
#
# An image is imported with PIL and the pixels are mapped
# to the bulbs.
# The x-axis being time and y-axis being bulb index

import argparse
import glob  # list all images
from time import sleep
from time import strftime
from time import time
import logging
import thread

import yaml
import netifaces

import os
import sys
import subprocess
import signal

from PIL import Image
import numpy as np
from scipy.misc import imresize

from phue import Bridge  # https://github.com/studioimaginaire/phue
# turns out Hue [0, 65535] and Saturation [0, 254] are available
# as properties of the lights
from hueColour import Converter

http_delay = .04 # average time of HTTP transmission per light

def hueMain():
    b = Bridge(args.ip)

    #not fully tested!
    if(args.username is None):
        b.connect()
        args.username = b.username
        logging.info("Username: {}".format(b.username))
    else:
        b.username = args.username

    # while True:
    #     try:
    #         lights = b.lights
    #     except:
    #         continue
    #     break

    conv = Converter()

    # make ordered list of images in directory
    imgs = []
    images = None
    if(config_flag):
        images = cfg['images']
        for k, v in images.items():
            imgs.append(v['filename'])
    else:
        imgs = glob.glob("{}/*.png".format(args.input))

    while True:
        try:
            lights = b.lights
        except:
            logging.info("can't connect to lights")
            sleep(1)
            continue
        break

    # all lights off
    for x in lights:
        x.on = False
    sleep(5)

    while True:
        for i, names in enumerate(imgs):
            logging.info(names)

            for t, x in enumerate(lights):
                if(t < args.numlights):
                    x.on = True
                    x.bri = 1

            try:
                img = Image.open(args.base+names)
                img = np.asarray(img)
            except:
                continue

            logging.info("playing img: {}".format(args.base+names))
            print "playing img: {}".format(args.base+names)

            if(config_flag):
                args.transition = images[i]['transition']  # to seconds?
                args.rate = ((http_delay * args.numlights) + (args.transition))

            for t, x in enumerate(lights):
                if(t < args.numlights):
                    x.transitiontime = int(args.transition * 10)

            x_step = int(img.shape[1] / float(images[i]['time']/args.rate))
            logging.info("x-step size: {0}".format(x_step))
            #shrink Y-axis to size of array
            y_step = 1
            if(img.shape[0] > args.numlights):
                y_step = img.shape[0] / args.numlights
            elif(img.shape[0] < args.numlights):
                img = imresize(img, (args.numlights, img.shape[1]))

            image_average = 0
            image_start_time = time()
            for x in np.arange(0, img.shape[1], x_step):
                start_time = time()
                for y in np.arange(0, args.numlights):
                    bri = int(np.average(img[y, x, :]))
                    lights[y].xy = conv.rgbToCIE(img[y*y_step, x, 0], img[y*y_step, x, 1], img[y*y_step, x, 2])
                    lights[y].bri = bri
                image_average += time() - start_time
                sleep(args.transition)
            logging.info("time elapsed average image {0}, {1}".format(i, image_average/(img.shape[1]/x_step)))
            logging.info("total image {0} elapsed time: {1}".format(i, time() - image_start_time))

            # image finished animation
            for m, light in enumerate(lights):
                light.transitiontime = 0
                light.on = False
                light.bri = 1

            sleep(10)

def audio(audio_file):
    if audio_file is not None:
        try:
            return subprocess.Popen(["omxplayer", "--loop", "--vol", "352", audio_file], preexec_fn=os.setsid)
        except Exception, e:
            logging.exception(e)
    else:
        return None

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--ip", type=str, default='192.168.1.100',
                        help='hue hub ip address')
    parser.add_argument("--username", "-u", type=str,
                        help="Hue hub username.")
    parser.add_argument("--input", "-i", type=str, default='./',
                        help='Input image directory')
    parser.add_argument("--rate", "--r", type=float, default=1/5.,
                        help='Rate in ms to step between pixel values')
    parser.add_argument("--transition", "--t", type=float, default=0,
                        help='Transition time in seconds')
    parser.add_argument("--numlights", "--n", type=float, default=30,
                        help='Number of active lights')
    parser.add_argument("--config", "-c", type=str,
                        help='run with config files')
    parser.add_argument("--base", "-b", type=str, default="./",
                        help='base directory of images')
    parser.add_argument("--log", "-l", type=str, default="/var/log",
                        help='log location')
    parser.add_argument("--audio", "-a", type=str,
                        help='Audio File to Play')

    args = parser.parse_args()
    logging.basicConfig(filename='{0}/hue_{1}.log'.format(args.log, strftime("%d-%m-%Y-%H-%M")), level=logging.INFO, format='%(asctime)s %(message)s')
    logging.info('Started')

    config_flag = args.config is not None
    cfg = None
    if(config_flag):
        try:
            with open(args.config, 'r') as ymlfile:
                cfg = yaml.load(ymlfile)
                config = cfg['config']
                args.numlights = config['lights']
                args.username = config['username']
                args.ip = config['ip']
                args.audio = config['audio']
        except IOError:
            logging.exception("Could not open file: {}".format(args.config))
            exit(1)
        except:
            logging.exception("Error in config file")
    try:
        proc = audio(args.audio)
        hueMain()
    except IOError as e:
        # an IOError exception occurred (socket.error is a subclass)
        # try is to make sure network is connected
        logging.exception(e)
        if (e.errno == 101):
            # now we had the error code 101, network unreachable
            # try is to make sure network is connected
            while True:
                addr = netifaces.ifaddresses("eth0")
                logging.info(addr)
                if(netifaces.AF_INET in addr):
                    break
                sleep(1)
        if e.errno == 113:
            logging.info("Error 113, sleeping for 10 seconds before attempting reconnect")
            sleep(10)
        else:
            logging.exception(e)
    except KeyboardInterrupt, e:
        #some sort of cleanup
        if proc is not None:
            os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
        logging.info("Keyboard Interrupt")
    except Exception, e:
        if proc is not None:
            os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
        logging.exception(e)

    logging.info('Finished')
<commit_msg>logging now prints to screen (systemd logs for us)<commit_after>#!/usr/bin/python

# Copyright (c) 2016 Steven A. Bjornson
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all copies
# or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
# FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

## Info
# The goal of this software is to fascilitate the creation
# of complex light patterns using a large array of
# Philips Hue bulbs.
#
# An image is imported with PIL and the pixels are mapped
# to the bulbs.
# The x-axis being time and y-axis being bulb index

import argparse
import glob  # list all images
from time import sleep
from time import strftime
from time import time
import logging
import thread

import yaml
import netifaces

import os
import sys
import subprocess
import signal

from PIL import Image
import numpy as np
from scipy.misc import imresize

from phue import Bridge  # https://github.com/studioimaginaire/phue
# turns out Hue [0, 65535] and Saturation [0, 254] are available
# as properties of the lights
from hueColour import Converter

http_delay = .04 # average time of HTTP transmission per light

def hueMain():
    b = Bridge(args.ip)

    #not fully tested!
    if(args.username is None):
        b.connect()
        args.username = b.username
        logging.info("Username: {}".format(b.username))
    else:
        b.username = args.username

    # while True:
    #     try:
    #         lights = b.lights
    #     except:
    #         continue
    #     break

    conv = Converter()

    # make ordered list of images in directory
    imgs = []
    images = None
    if(config_flag):
        images = cfg['images']
        for k, v in images.items():
            imgs.append(v['filename'])
    else:
        imgs = glob.glob("{}/*.png".format(args.input))

    while True:
        try:
            lights = b.lights
        except:
            logging.info("can't connect to lights")
            sleep(1)
            continue
        break

    # all lights off
    for x in lights:
        x.on = False
    sleep(5)

    while True:
        for i, names in enumerate(imgs):
            logging.info(names)

            for t, x in enumerate(lights):
                if(t < args.numlights):
                    x.on = True
                    x.bri = 1

            try:
                img = Image.open(args.base+names)
                img = np.asarray(img)
            except:
                continue

            logging.info("playing img: {}".format(args.base+names))
            print "playing img: {}".format(args.base+names)

            if(config_flag):
                args.transition = images[i]['transition']  # to seconds?
                args.rate = ((http_delay * args.numlights) + (args.transition))

            for t, x in enumerate(lights):
                if(t < args.numlights):
                    x.transitiontime = int(args.transition * 10)

            x_step = int(img.shape[1] / float(images[i]['time']/args.rate))
            logging.info("x-step size: {0}".format(x_step))
            #shrink Y-axis to size of array
            y_step = 1
            if(img.shape[0] > args.numlights):
                y_step = img.shape[0] / args.numlights
            elif(img.shape[0] < args.numlights):
                img = imresize(img, (args.numlights, img.shape[1]))

            image_average = 0
            image_start_time = time()
            for x in np.arange(0, img.shape[1], x_step):
                start_time = time()
                for y in np.arange(0, args.numlights):
                    bri = int(np.average(img[y, x, :]))
                    lights[y].xy = conv.rgbToCIE(img[y*y_step, x, 0], img[y*y_step, x, 1], img[y*y_step, x, 2])
                    lights[y].bri = bri
                image_average += time() - start_time
                sleep(args.transition)
            logging.info("time elapsed average image {0}, {1}".format(i, image_average/(img.shape[1]/x_step)))
            logging.info("total image {0} elapsed time: {1}".format(i, time() - image_start_time))

            # image finished animation
            for m, light in enumerate(lights):
                light.transitiontime = 0
                light.on = False
                light.bri = 1

            sleep(10)

def audio(audio_file):
    if audio_file is not None:
        try:
            return subprocess.Popen(["omxplayer", "--loop", "--vol", "352", audio_file], preexec_fn=os.setsid)
        except Exception, e:
            logging.exception(e)
    else:
        return None

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--ip", type=str, default='192.168.1.100',
                        help='hue hub ip address')
    parser.add_argument("--username", "-u", type=str,
                        help="Hue hub username.")
    parser.add_argument("--input", "-i", type=str, default='./',
                        help='Input image directory')
    parser.add_argument("--rate", "--r", type=float, default=1/5.,
                        help='Rate in ms to step between pixel values')
    parser.add_argument("--transition", "--t", type=float, default=0,
                        help='Transition time in seconds')
    parser.add_argument("--numlights", "--n", type=float, default=30,
                        help='Number of active lights')
    parser.add_argument("--config", "-c", type=str,
                        help='run with config files')
    parser.add_argument("--base", "-b", type=str, default="./",
                        help='base directory of images')
    parser.add_argument("--log", "-l", type=str, default="/var/log",
                        help='log location')
    parser.add_argument("--audio", "-a", type=str,
                        help='Audio File to Play')

    args = parser.parse_args()
    logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')
    logging.info('Started')

    config_flag = args.config is not None
    cfg = None
    if(config_flag):
        try:
            with open(args.config, 'r') as ymlfile:
                cfg = yaml.load(ymlfile)
                config = cfg['config']
                args.numlights = config['lights']
                args.username = config['username']
                args.ip = config['ip']
                args.audio = config['audio']
        except IOError:
            logging.exception("Could not open file: {}".format(args.config))
            exit(1)
        except:
            logging.exception("Error in config file")
    try:
        proc = audio(args.audio)
        hueMain()
    except IOError as e:
        # an IOError exception occurred (socket.error is a subclass)
        # try is to make sure network is connected
        logging.exception(e)
        if (e.errno == 101):
            # now we had the error code 101, network unreachable
            # try is to make sure network is connected
            while True:
                addr = netifaces.ifaddresses("eth0")
                logging.info(addr)
                if(netifaces.AF_INET in addr):
                    break
                sleep(1)
        if e.errno == 113:
            logging.info("Error 113, sleeping for 10 seconds before attempting reconnect")
            sleep(10)
        else:
            logging.exception(e)
    except KeyboardInterrupt, e:
        #some sort of cleanup
        if proc is not None:
            os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
        logging.info("Keyboard Interrupt")
    except Exception, e:
        if proc is not None:
            os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
        logging.exception(e)

    logging.info('Finished')
<|endoftext|>


<commit_before>#!/usr/bin/python

import os
import sys

# Extra deps not expressed in lsmod's list of dependent modules
extra_deps = {"lquota": set(["lov", "osc", "mgc", "mds", "mdc", "lmv"])}

class Module:
	def __init__(self, lsmod_line):
		parts = lsmod_line.split()
		self.name = parts[0]
		depcount = int(parts[2])
		try:
			self.dependents = set(parts[3].split(","))
		except IndexError:
			self.dependents = set([])
		#if depcount != len(self.dependents):
		#	print "Non-module dependencies on %s" % self.name
		#	sys.exit(-1)

def load_lsmod():
	modules = {}

	lines = os.popen("/sbin/lsmod").read().split("\n")[1:-1]
	for line in lines:
		m = Module(line.strip())
		modules[m.name] = m

	for name,module in modules.items():
		try:
			module.dependents |= (extra_deps[name] & set(modules.keys()))
		except KeyError:
			pass

	return modules

def remove_module(name, modules):
	m = modules[name]
	print "Removing %d dependents of %s : %s" % (len(m.dependents), name, m.dependents)
	while (len(m.dependents) > 0):
		remove_module(m.dependents.pop(), modules)

	print "Removing %s" % name
	rc = os.system("rmmod %s" % name)
	if rc != 0:
		raise "Failed to rmmod '%s'" % name

	modules.pop(name)
	for m in modules.values():
		if name in m.dependents:
			m.dependents.remove(name)

modules = load_lsmod()
remove_module(sys.argv[1], modules)
<commit_msg>Fix indentation<commit_after>#!/usr/bin/python

import os
import sys

# Extra deps not expressed in lsmod's list of dependent modules
extra_deps = {"lquota": set(["lov", "osc", "mgc", "mds", "mdc", "lmv"])}

class Module:
    def __init__(self, lsmod_line):
        parts = lsmod_line.split()
        self.name = parts[0]
        depcount = int(parts[2])
        try:
            self.dependents = set(parts[3].split(","))
        except IndexError:
            self.dependents = set([])
        #if depcount != len(self.dependents):
        #    print "Non-module dependencies on %s" % self.name
        #    sys.exit(-1)

def load_lsmod():
    modules = {}

    lines = os.popen("/sbin/lsmod").read().split("\n")[1:-1]
    for line in lines:
        m = Module(line.strip())
        modules[m.name] = m

    for name,module in modules.items():
        try:
            module.dependents |= (extra_deps[name] & set(modules.keys()))
        except KeyError:
            pass

    return modules

def remove_module(name, modules):
    try:
        m = modules[name]
    except KeyError:
        # It's not loaded, do nothing.
        return
    print "Removing %d dependents of %s : %s" % (len(m.dependents), name, m.dependents)
    while (len(m.dependents) > 0):
        remove_module(m.dependents.pop(), modules)

    print "Removing %s" % name
    rc = os.system("rmmod %s" % name)
    if rc != 0:
        raise "Failed to rmmod '%s'" % name

    modules.pop(name)
    for m in modules.values():
        if name in m.dependents:
            m.dependents.remove(name)

modules = load_lsmod()
remove_module(sys.argv[1], modules)
<|endoftext|>


<commit_before>import functools

import pandas as pd

_wrap_msg = """
.. note::

    The documentation following is of the class wrapped by this class. There
    are some changes, in particular:

        * A parameter ``X`` denotes a :class:`pandas.DataFrame`.

        * A parameter ``y`` denotes a :class:`pandas.Series`.

--------------------------------

"""

def verify_x_type(X):
    if not isinstance(X, pd.DataFrame):
        raise TypeError('Expected pandas.DataFrame; got %s' % type(X))

def verify_y_type(y):
    if y is None:
        return

    if not isinstance(y, (pd.DataFrame, pd.Series)):
        raise TypeError('Expected pandas.DataFrame or pandas.Series; got %s' % type(y))

def update_class_wrapper(new_class, orig_class):
    new_class.__doc__ = _wrap_msg + orig_class.__doc__

def update_method_wrapper(new_class, orig_class, method_name):
    functools.update_wrapper(getattr(new_class, method_name), getattr(orig_class, method_name))
    getattr(new_class, method_name).__doc__ = _wrap_msg + getattr(orig_class, method_name).__doc__
<commit_msg>py2 doc class updage bugfix<commit_after>import functools

import six
import pandas as pd

_wrap_msg = """
.. note::

    The documentation following is of the class wrapped by this class. There
    are some changes, in particular:

        * A parameter ``X`` denotes a :class:`pandas.DataFrame`.

        * A parameter ``y`` denotes a :class:`pandas.Series`.

--------------------------------

"""

def verify_x_type(X):
    if not isinstance(X, pd.DataFrame):
        raise TypeError('Expected pandas.DataFrame; got %s' % type(X))

def verify_y_type(y):
    if y is None:
        return

    if not isinstance(y, (pd.DataFrame, pd.Series)):
        raise TypeError('Expected pandas.DataFrame or pandas.Series; got %s' % type(y))

def update_class_wrapper(new_class, orig_class):
    if six.PY3:
        new_class.__doc__ = _wrap_msg + orig_class.__doc__

def update_method_wrapper(new_class, orig_class, method_name):
    functools.update_wrapper(getattr(new_class, method_name), getattr(orig_class, method_name))
    getattr(new_class, method_name).__doc__ = _wrap_msg + getattr(orig_class, method_name).__doc__
<|endoftext|>


<commit_before>from opencivicdata.models import (Jurisdiction, Organization, Person,
                                  Bill, VoteEvent, Event)
from .helpers import PublicListEndpoint, PublicDetailEndpoint, get_field_list
import copy
import pytz

def dout(obj):
    """
    Helper function to ensure that we're always printing internal
    datetime objects in a fully qualified UTC timezone. This will
    let 'None' values pass through untouched.
    """
    if obj is None:
        return
    return pytz.UTC.localize(obj).isoformat()

def sfilter(obj, blacklist):
    """
    Helper function to deep copy a dict, and pop elements off.
    """
    ret = copy.deepcopy(obj)
    for el in blacklist:
        ret.pop(el)
    return ret

#
#
#
# OK. This is where we define *what* we allow to be public.
#
#
#

DIVISION_SERIALIZE = dict([
    ("id", {}),
    ("display_name", {}),
])

SOURCES_SERIALIZE = {"note": {}, "url": {},}

JURISDICTION_SERIALIZE = dict([
    ("id", {}),
    ("name", {}),
    ("url", {}),
    ("classification", {}),
    ("extras", lambda x: x.extras),
    ("feature_flags", lambda x: x.feature_flags),
    ("division", DIVISION_SERIALIZE),
])

LEGISLATIVE_SESSION_SERIALIZE = dict([
    ('identifier', {}),
    ('classification', {}),
    ('jurisdiction', JURISDICTION_SERIALIZE),
])

CONTACT_DETAIL_SERIALIZE = dict([
    ("type", {}),
    ("value", {}),
    ("note", {}),
    ("label", {}),
])

LINK_SERALIZE = dict([
    ("note", {}),
    ("url", {}),
])

IDENTIFIERS_SERIALIZE = {
    "identifier": {},
    "scheme": {},
}

OTHER_NAMES_SERIALIZE = {
    "name": {},
    "note": {},
    "start_date": {},
    "end_date": {},
}

ORGANIZATION_SERIALIZE = dict([
    ("id", {}),
    ("name", {}),
    ("image", {}),
    ("identifiers", IDENTIFIERS_SERIALIZE),
    ("links", LINK_SERALIZE),
    ("contact_details", CONTACT_DETAIL_SERIALIZE),
    ("other_names", OTHER_NAMES_SERIALIZE),
    ("classification", {}),
    ("founding_date", {}),
    ("dissolution_date", {}),
    ("jurisdiction", JURISDICTION_SERIALIZE),
    ("sources", SOURCES_SERIALIZE),
])

ORGANIZATION_SERIALIZE['parent'] = ORGANIZATION_SERIALIZE
ORGANIZATION_SERIALIZE['children'] = sfilter(
    ORGANIZATION_SERIALIZE,
    blacklist=['parent']
)

ORGANIZATION_SERIALIZE['identifiers'] = {
    # Don't leak 'id'
    "identifier": {},
    # Don't allow recuse into our own org.
    "scheme": {},
}

PERSON_SERIALIZE = dict([
    ("id", {}),
    ("name", {}),
    ("sort_name", {}),
    ("image", {}),
    ("gender", {}),
    ("summary", {}),
    ("national_identity", {}),
    ("biography", {}),
    ("birth_date", {}),
    ("death_date", {}),

    ("created_at", {}),
    ("updated_at", {}),

    ("extras", lambda x: x.extras),

    ("identifiers", IDENTIFIERS_SERIALIZE),
    ("other_names", OTHER_NAMES_SERIALIZE),
    ("contact_details", CONTACT_DETAIL_SERIALIZE),
    ("links", LINK_SERALIZE),
    ("sources", SOURCES_SERIALIZE),
])

POST_SERIALIZE = dict([
    ("id", {}),
    ("label", {}),
    ("role", {}),
    ("start_date", {}),
    ("end_date", {}),
    ("links", LINK_SERALIZE),
    ("contact_details", CONTACT_DETAIL_SERIALIZE),
    ("organization", ORGANIZATION_SERIALIZE),
    ("division", DIVISION_SERIALIZE),
])

ORGANIZATION_SERIALIZE['posts'] = sfilter(
    POST_SERIALIZE,
    blacklist=["organization"]
)

MEMBERSHIP_SERIALIZE = {
    # Explicit to avoid letting `id' leak out.
    "start_date": {},
    "end_date": {},
    "role": {},
    "label": {},
    "organization": ORGANIZATION_SERIALIZE,
    "person": PERSON_SERIALIZE,
    "post": POST_SERIALIZE,
    "on_behalf_of": ORGANIZATION_SERIALIZE,
}

ORGANIZATION_SERIALIZE['memberships'] = sfilter(
    # Avoid org->memberships->org loop
    MEMBERSHIP_SERIALIZE,
    blacklist=['organization']
)
ORGANIZATION_SERIALIZE['memberships']['post'] = sfilter(
    # Avoid org->memberships->post->org loop
    POST_SERIALIZE,
    blacklist=['organization']
)

PERSON_SERIALIZE['memberships'] = sfilter(
    # Avoid person->memberships->person loop
    MEMBERSHIP_SERIALIZE,
    blacklist=['person']
)

POST_SERIALIZE['memberships'] = sfilter(
    MEMBERSHIP_SERIALIZE,
    blacklist=['post']
)

LINK_BASE = {
    'media_type': {},
    'url': {},
}

BILL_SERIALIZE = dict([
    ('id', {}),
    ('identifier', {}),
    ('legislative_session', LEGISLATIVE_SESSION_SERIALIZE),
    ('legislative_session_id', {}),

    ('title', {}),
    ("extras", lambda x: x.extras),

    ('from_organization', ORGANIZATION_SERIALIZE),
    ('from_organization_id', {}),

    ('created_at', lambda x: dout(x.created_at)),
    ('updated_at', lambda x: dout(x.updated_at)),

    ('classification', lambda x: x.classification),
    ('subject', lambda x: x.classification),

    ('abstracts', {
        "abstract": {},
        "note": {},
    }),

    ('other_titles', {
        "title": {},
        "note": {},
    }),

    ('other_identifiers', {
        "note": {},
        "identifier": {},
        "scheme": {},
    }),

    ('related_bills', {
        "identifier": {},
        "legislative_session": LEGISLATIVE_SESSION_SERIALIZE,
        "relation_type": {},
    }),

    ('actions', {
        'organization': ORGANIZATION_SERIALIZE,
        'description': {},
        'date': {},
        'classification': lambda x: x.classification,
        'order': {},
    }),

    ('sponsorships', {
        "primary": {},
        "classification": {},
        "entity_name": {},
        "entity_type": {},
        "entity_id": {},
    }),

    ('documents', {
        "note": {},
        "date": {},
        "links": LINK_BASE,
    }),

    ('versions', {
        "note": {},
        "date": {},
        "links": LINK_BASE,
    }),

    ("sources", SOURCES_SERIALIZE),
])

BILL_SERIALIZE['related_bills']['bill'] = BILL_SERIALIZE

VOTE_SERIALIZE = dict([
    ("id", {}),
    ("identifier", {}),
    ("motion_text", {}),
    ("motion_classification", {}),

    ('created_at', lambda x: dout(x.created_at)),
    ('updated_at', lambda x: dout(x.updated_at)),

    ('start_date', {}),
    ('end_date', {}),

    ("extras", lambda x: x.extras),

    ("result", {}),
    ("legislative_session", LEGISLATIVE_SESSION_SERIALIZE),

    ('organization_id', {}),
    ("organization", ORGANIZATION_SERIALIZE),

    ('bill_id', {}),
    ("bill", BILL_SERIALIZE),
    ("counts", {
        "option": {},
        "value": {},
    }),
    ("votes", {
        "option": {},
        "voter_name": {},
        "voter": {},
        "note": {},
    }),
    ("sources", SOURCES_SERIALIZE),
])

BILL_SERIALIZE['votes'] = sfilter(
    VOTE_SERIALIZE,
    blacklist=['bill'],
)

EVENT_AGENDA_ITEM = dict([
    ('description', {}),
    ('order', {}),
    ('subjects', lambda x: x.subjects),
    ('notes', {}),

    ('related_entities', {
        "note": {},
        "entity_name": {},
        "entity_type": {},
        "entity_id": {},
    }),
])

EVENT_SERIALIZE = dict([
    ('id', {}),
    ('name', {}),
    ('jurisdiction', JURISDICTION_SERIALIZE),
    ('jurisdiction_id', {}),
    ('description', {}),
    ('classification', {}),

    ('participants', {
        'note': {},
        "entity_name": {},
        "entity_type": {},
        "entity_id": {},
    }),

    ('documents', {
        "note": {},
        "date": {},
        "links": LINK_BASE,
    }),

    ('media', {
        "note": {},
        "date": {},
        "offset": {},
        "links": LINK_SERALIZE,
    }),

    ("links", LINK_SERALIZE),

    ('created_at', {}),
    ('updated_at', {}),

    ('start_time', lambda x: dout(x.start_time)),
    ('end_time', lambda x: dout(x.end_time)),
    ('timezone', {}),

    ('all_day', {}),
    ('status', {}),

    ('location', {
        "name": {},
        "url": {},
    }),

    ('agenda', EVENT_AGENDA_ITEM),
    ('extras', lambda x: x.extras),

    ("sources", SOURCES_SERIALIZE),
])

#
#
#
# OK. This is where we define the actuall class-based views.
#
#
#

class JurisdictionList(PublicListEndpoint):
    model = Jurisdiction
    serialize_config = JURISDICTION_SERIALIZE
    default_fields = ['id', 'name', 'url', 'classification', 'feature_flags',
                      'division.id', 'division.display_name']

    def adjust_filters(self, params):
        if 'name' in params:
            params['name__icontains'] = params.pop('name')
        return params

class JurisdictionDetail(PublicDetailEndpoint):
    model = Jurisdiction
    serialize_config = JURISDICTION_SERIALIZE
    default_fields = get_field_list(model, without=[
        'event_locations',
        'events',
        'organizations',
        'division',
    ]) + [
        'division.id', 'division.display_name'
    ]

class OrganizationList(PublicListEndpoint):
    model = Organization
    serialize_config = ORGANIZATION_SERIALIZE
    default_fields = ['id', 'name', 'image', 'classification',
                      'jurisdiction.id', 'parent.id', 'parent.name',
                      'memberships.person.id', 'memberships.person.name',
                      'memberships.post.id', 'memberships.post.label',
                      'memberships.post.role',]

class OrganizationDetail(PublicDetailEndpoint):
    model = Organization
    serialize_config = ORGANIZATION_SERIALIZE
    default_fields = get_field_list(model, without=[
        'memberships_on_behalf_of',
        'billactionrelatedentity',
        'eventrelatedentity',
        'eventparticipant',
        'billsponsorship',
        'memberships',  # Below.
        'parent_id',  # Present as parent.id
        'children',
        'actions',
        'parent',  # Below.
        'posts',
        'bills',
        'votes',
    ]) + [
        'parent.id',
        'parent.name',

        'memberships.start_date',
        'memberships.end_date',
        'memberships.person.id',
        'memberships.person.name',
        'memberships.post.id',

        'children.id',
        'children.name',

        'jurisdiction.id',
        'jurisdiction.name',
        'jurisdiction.division.id',
        'jurisdiction.division.display_name',

        'posts.id',
        'posts.label',
        'posts.role',
    ]

class PeopleList(PublicListEndpoint):
    model = Person
    serialize_config = PERSON_SERIALIZE
    default_fields = [
        'name', 'id', 'sort_name', 'image', 'gender',

        'memberships.organization.id',
        'memberships.organization.name',
        'memberships.organization.classification',
        'memberships.organization.jurisdiction.id',
        'memberships.organization.jurisdiction.name',

        'memberships.post.id',
        'memberships.post.label',
        'memberships.post.role',
    ]

class PersonDetail(PublicDetailEndpoint):
    model = Person
    serialize_config = PERSON_SERIALIZE
    default_fields = get_field_list(model, without=[
        'votes',
        'billactionrelatedentity',
        'eventparticipant',
        'billsponsorship',
        'eventrelatedentity',
        'memberships',
    ]) + [
        'memberships.label',
        'memberships.role',
        'memberships.start_date',
        'memberships.end_date',
        'memberships.post.label',
        'memberships.post.role',
        'memberships.post.id',
        'memberships.post.division.id',
        'memberships.post.division.display_name',
        'memberships.organization.id',
        'memberships.organization.name',
        'memberships.organization.jurisdiction.id',
    ]

class BillList(PublicListEndpoint):
    model = Bill
    serialize_config = BILL_SERIALIZE
    default_fields = [
        'id', 'identifier', 'title', 'classification',

        'from_organization.name',
        'from_organization.id',

        'from_organization.jurisdiction.id',
        'from_organization.jurisdiction.name',
    ]

class VoteList(PublicListEndpoint):
    model = VoteEvent
    serialize_config = VOTE_SERIALIZE
    default_fields = [
        'result', 'motion_text', 'created_at', 'start_date', 'updated_at',
        'motion_classification', 'extras', 'id',

        'counts',

        'bill.identifier', 'bill.id',
        'organization.id', 'organization.name',
    ]

class VoteDetail(PublicDetailEndpoint):
    model = VoteEvent
    serialize_config = VOTE_SERIALIZE
    default_fields = get_field_list(model, without=[
        'eventrelatedentity',
        'legislative_session_id',
        'bill',
        'legislative_session',
        'organization',
        'organization_id',
        'bill_id',
    ]) + [
        'bill.id',
        'bill.identifier',
        'bill.legislative_session.identifier',

        'organization.id',
        'organization.name',
        'organization.classification',
    ]

class BillDetail(PublicDetailEndpoint):
    model = Bill
    serialize_config = BILL_SERIALIZE
    default_fields = get_field_list(model, without=[
        'from_organization_id',
        'eventrelatedentity',
        'related_bills_reverse',
        'legislative_session_id',
        'actions.organization',
        'votes'
    ]) + [
        'from_organization.id',
        'from_organization.name',
        'legislative_session.identifier',

        'actions.organization.id',
        'actions.organization.name',
        'actions.organization.jurisdiction.id',
        'actions.organization.jurisdiction.classification',
        'actions.organization.jurisdiction.name',
        'actions.organization.jurisdiction.division.id',
        'actions.organization.jurisdiction.division.display_name',

        'votes.result',
        'votes.motion_text',
        'votes.start_date',
        'votes.motion_classification',
        'votes.id',
        'votes.counts',
    ]

class EventList(PublicListEndpoint):
    model = Event
    serialize_config = EVENT_SERIALIZE
    default_fields = [
        'id', 'name', 'description', 'classification', 'start_time',
        'timezone', 'end_time', 'all_day', 'status',

        'agenda.description', 'agenda.order', 'agenda.subjects',
        'agenda.related_entities.note',
        'agenda.related_entities.entity_name',
        'agenda.related_entities.entity_id',
        'agenda.related_entities.entity_type',
    ]

class EventDetail(PublicDetailEndpoint):
    model = Event
    serialize_config = EVENT_SERIALIZE
    default_fields = get_field_list(model, without=[
        'location_id',
    ])
<commit_msg>cleanup jurisdiction view<commit_after>from opencivicdata.models import (Jurisdiction, Organization, Person,
                                  Bill, VoteEvent, Event)
from .helpers import PublicListEndpoint, PublicDetailEndpoint, get_field_list
import copy
import pytz

def dout(obj):
    """
    Helper function to ensure that we're always printing internal
    datetime objects in a fully qualified UTC timezone. This will
    let 'None' values pass through untouched.
    """
    if obj is None:
        return
    return pytz.UTC.localize(obj).isoformat()

def sfilter(obj, blacklist):
    """
    Helper function to deep copy a dict, and pop elements off.
    """
    ret = copy.deepcopy(obj)
    for el in blacklist:
        ret.pop(el)
    return ret

#
#
#
# OK. This is where we define *what* we allow to be public.
#
#
#

DIVISION_SERIALIZE = dict([
    ("id", {}),
    ("display_name", {}),
])

SOURCES_SERIALIZE = {"note": {}, "url": {},}

JURISDICTION_SERIALIZE = dict([
    ("id", {}),
    ("name", {}),
    ("url", {}),

    ("updated_at", {}),
    ("created_at", {}),

    ("classification", {}),
    ("extras", lambda x: x.extras),
    ("feature_flags", lambda x: x.feature_flags),

    ("division", DIVISION_SERIALIZE),
    ("division_id", {}),
])

LEGISLATIVE_SESSION_SERIALIZE = dict([
    ('identifier', {}),
    ('classification', {}),
    ('jurisdiction', JURISDICTION_SERIALIZE),
])

JURISDICTION_SERIALIZE['legislative_sessions'] = sfilter(
    LEGISLATIVE_SESSION_SERIALIZE,
    blacklist=['jurisdiction']
)

CONTACT_DETAIL_SERIALIZE = dict([
    ("type", {}),
    ("value", {}),
    ("note", {}),
    ("label", {}),
])

LINK_SERALIZE = dict([
    ("note", {}),
    ("url", {}),
])

IDENTIFIERS_SERIALIZE = {
    "identifier": {},
    "scheme": {},
}

OTHER_NAMES_SERIALIZE = {
    "name": {},
    "note": {},
    "start_date": {},
    "end_date": {},
}

ORGANIZATION_SERIALIZE = dict([
    ("id", {}),
    ("name", {}),
    ("image", {}),

    ("created_at", {}),
    ("updated_at", {}),

    ("extras", lambda x: x.extras),

    ("identifiers", IDENTIFIERS_SERIALIZE),
    ("links", LINK_SERALIZE),
    ("contact_details", CONTACT_DETAIL_SERIALIZE),
    ("other_names", OTHER_NAMES_SERIALIZE),
    ("classification", {}),
    ("founding_date", {}),
    ("dissolution_date", {}),
    ("jurisdiction_id", {}),
    ("jurisdiction", JURISDICTION_SERIALIZE),
    ("sources", SOURCES_SERIALIZE),
])

ORGANIZATION_SERIALIZE['parent'] = ORGANIZATION_SERIALIZE
ORGANIZATION_SERIALIZE['children'] = sfilter(
    ORGANIZATION_SERIALIZE,
    blacklist=['parent']
)

ORGANIZATION_SERIALIZE['identifiers'] = {
    # Don't leak 'id'
    "identifier": {},
    # Don't allow recuse into our own org.
    "scheme": {},
}

PERSON_SERIALIZE = dict([
    ("id", {}),
    ("name", {}),
    ("sort_name", {}),
    ("image", {}),
    ("gender", {}),
    ("summary", {}),
    ("national_identity", {}),
    ("biography", {}),
    ("birth_date", {}),
    ("death_date", {}),

    ("created_at", {}),
    ("updated_at", {}),

    ("extras", lambda x: x.extras),

    ("identifiers", IDENTIFIERS_SERIALIZE),
    ("other_names", OTHER_NAMES_SERIALIZE),
    ("contact_details", CONTACT_DETAIL_SERIALIZE),
    ("links", LINK_SERALIZE),
    ("sources", SOURCES_SERIALIZE),
])

POST_SERIALIZE = dict([
    ("id", {}),
    ("label", {}),
    ("role", {}),
    ("start_date", {}),
    ("end_date", {}),
    ("links", LINK_SERALIZE),
    ("contact_details", CONTACT_DETAIL_SERIALIZE),
    ("organization", ORGANIZATION_SERIALIZE),
    ("division", DIVISION_SERIALIZE),
])

ORGANIZATION_SERIALIZE['posts'] = sfilter(
    POST_SERIALIZE,
    blacklist=["organization"]
)

MEMBERSHIP_SERIALIZE = {
    # Explicit to avoid letting `id' leak out.
    "start_date": {},
    "end_date": {},
    "role": {},
    "label": {},
    "organization": ORGANIZATION_SERIALIZE,
    "person": PERSON_SERIALIZE,
    "post": POST_SERIALIZE,
    "on_behalf_of": ORGANIZATION_SERIALIZE,
}

ORGANIZATION_SERIALIZE['memberships'] = sfilter(
    # Avoid org->memberships->org loop
    MEMBERSHIP_SERIALIZE,
    blacklist=['organization']
)
ORGANIZATION_SERIALIZE['memberships']['post'] = sfilter(
    # Avoid org->memberships->post->org loop
    POST_SERIALIZE,
    blacklist=['organization']
)

PERSON_SERIALIZE['memberships'] = sfilter(
    # Avoid person->memberships->person loop
    MEMBERSHIP_SERIALIZE,
    blacklist=['person']
)

POST_SERIALIZE['memberships'] = sfilter(
    MEMBERSHIP_SERIALIZE,
    blacklist=['post']
)

LINK_BASE = {
    'media_type': {},
    'url': {},
}

BILL_SERIALIZE = dict([
    ('id', {}),
    ('identifier', {}),
    ('legislative_session', LEGISLATIVE_SESSION_SERIALIZE),
    ('legislative_session_id', {}),

    ('title', {}),
    ("extras", lambda x: x.extras),

    ('from_organization', ORGANIZATION_SERIALIZE),
    ('from_organization_id', {}),

    ('created_at', lambda x: dout(x.created_at)),
    ('updated_at', lambda x: dout(x.updated_at)),

    ('classification', lambda x: x.classification),
    ('subject', lambda x: x.classification),

    ('abstracts', {
        "abstract": {},
        "note": {},
    }),

    ('other_titles', {
        "title": {},
        "note": {},
    }),

    ('other_identifiers', {
        "note": {},
        "identifier": {},
        "scheme": {},
    }),

    ('related_bills', {
        "identifier": {},
        "legislative_session": LEGISLATIVE_SESSION_SERIALIZE,
        "relation_type": {},
    }),

    ('actions', {
        'organization': ORGANIZATION_SERIALIZE,
        'description': {},
        'date': {},
        'classification': lambda x: x.classification,
        'order': {},
    }),

    ('sponsorships', {
        "primary": {},
        "classification": {},
        "entity_name": {},
        "entity_type": {},
        "entity_id": {},
    }),

    ('documents', {
        "note": {},
        "date": {},
        "links": LINK_BASE,
    }),

    ('versions', {
        "note": {},
        "date": {},
        "links": LINK_BASE,
    }),

    ("sources", SOURCES_SERIALIZE),
])

BILL_SERIALIZE['related_bills']['bill'] = BILL_SERIALIZE

VOTE_SERIALIZE = dict([
    ("id", {}),
    ("identifier", {}),
    ("motion_text", {}),
    ("motion_classification", {}),

    ('created_at', lambda x: dout(x.created_at)),
    ('updated_at', lambda x: dout(x.updated_at)),

    ('start_date', {}),
    ('end_date', {}),

    ("extras", lambda x: x.extras),

    ("result", {}),
    ("legislative_session", LEGISLATIVE_SESSION_SERIALIZE),

    ('organization_id', {}),
    ("organization", ORGANIZATION_SERIALIZE),

    ('bill_id', {}),
    ("bill", BILL_SERIALIZE),
    ("counts", {
        "option": {},
        "value": {},
    }),
    ("votes", {
        "option": {},
        "voter_name": {},
        "voter": {},
        "note": {},
    }),
    ("sources", SOURCES_SERIALIZE),
])

BILL_SERIALIZE['votes'] = sfilter(
    VOTE_SERIALIZE,
    blacklist=['bill'],
)

EVENT_AGENDA_ITEM = dict([
    ('description', {}),
    ('order', {}),
    ('subjects', lambda x: x.subjects),
    ('notes', {}),

    ('related_entities', {
        "note": {},
        "entity_name": {},
        "entity_type": {},
        "entity_id": {},
    }),
])

EVENT_SERIALIZE = dict([
    ('id', {}),
    ('name', {}),
    ('jurisdiction', JURISDICTION_SERIALIZE),
    ('jurisdiction_id', {}),
    ('description', {}),
    ('classification', {}),

    ('participants', {
        'note': {},
        "entity_name": {},
        "entity_type": {},
        "entity_id": {},
    }),

    ('documents', {
        "note": {},
        "date": {},
        "links": LINK_BASE,
    }),

    ('media', {
        "note": {},
        "date": {},
        "offset": {},
        "links": LINK_SERALIZE,
    }),

    ("links", LINK_SERALIZE),

    ('created_at', {}),
    ('updated_at', {}),

    ('start_time', lambda x: dout(x.start_time)),
    ('end_time', lambda x: dout(x.end_time)),
    ('timezone', {}),

    ('all_day', {}),
    ('status', {}),

    ('location', {
        "name": {},
        "url": {},
    }),

    ('agenda', EVENT_AGENDA_ITEM),
    ('extras', lambda x: x.extras),

    ("sources", SOURCES_SERIALIZE),
])

#
#
#
# OK. This is where we define the actuall class-based views.
#
#
#

class JurisdictionList(PublicListEndpoint):
    model = Jurisdiction
    serialize_config = JURISDICTION_SERIALIZE
    default_fields = ['id', 'name', 'url', 'classification', 'feature_flags',
                      'division.id', 'division.display_name']

    def adjust_filters(self, params):
        if 'name' in params:
            params['name__icontains'] = params.pop('name')
        return params

class JurisdictionDetail(PublicDetailEndpoint):
    model = Jurisdiction
    serialize_config = JURISDICTION_SERIALIZE
    default_fields = get_field_list(model, without=[
        'event_locations',
        'events',
        'organizations',
        'division',
    ]) + [
        'division.id', 'division.display_name'
    ]

class OrganizationList(PublicListEndpoint):
    model = Organization
    serialize_config = ORGANIZATION_SERIALIZE
    default_fields = ['id', 'name', 'image', 'classification',
                      'jurisdiction.id', 'parent.id', 'parent.name',
                      'memberships.person.id', 'memberships.person.name',
                      'memberships.post.id', 'memberships.post.label',
                      'memberships.post.role',]

class OrganizationDetail(PublicDetailEndpoint):
    model = Organization
    serialize_config = ORGANIZATION_SERIALIZE
    default_fields = get_field_list(model, without=[
        'memberships_on_behalf_of',
        'billactionrelatedentity',
        'eventrelatedentity',
        'eventparticipant',
        'jurisdiction_id',
        'billsponsorship',
        'memberships',  # Below.
        'parent_id',  # Present as parent.id
        'children',
        'actions',
        'parent',  # Below.
        'posts',
        'bills',
        'votes',
    ]) + [
        'parent.id',
        'parent.name',

        'memberships.start_date',
        'memberships.end_date',
        'memberships.person.id',
        'memberships.person.name',
        'memberships.post.id',

        'children.id',
        'children.name',

        'jurisdiction.id',
        'jurisdiction.name',
        'jurisdiction.division.id',
        'jurisdiction.division.display_name',

        'posts.id',
        'posts.label',
        'posts.role',
    ]

class PeopleList(PublicListEndpoint):
    model = Person
    serialize_config = PERSON_SERIALIZE
    default_fields = [
        'name', 'id', 'sort_name', 'image', 'gender',

        'memberships.organization.id',
        'memberships.organization.name',
        'memberships.organization.classification',
        'memberships.organization.jurisdiction.id',
        'memberships.organization.jurisdiction.name',

        'memberships.post.id',
        'memberships.post.label',
        'memberships.post.role',
    ]

class PersonDetail(PublicDetailEndpoint):
    model = Person
    serialize_config = PERSON_SERIALIZE
    default_fields = get_field_list(model, without=[
        'votes',
        'billactionrelatedentity',
        'eventparticipant',
        'billsponsorship',
        'eventrelatedentity',
        'memberships',
    ]) + [
        'memberships.label',
        'memberships.role',
        'memberships.start_date',
        'memberships.end_date',
        'memberships.post.label',
        'memberships.post.role',
        'memberships.post.id',
        'memberships.post.division.id',
        'memberships.post.division.display_name',
        'memberships.organization.id',
        'memberships.organization.name',
        'memberships.organization.jurisdiction.id',
    ]

class BillList(PublicListEndpoint):
    model = Bill
    serialize_config = BILL_SERIALIZE
    default_fields = [
        'id', 'identifier', 'title', 'classification',

        'from_organization.name',
        'from_organization.id',

        'from_organization.jurisdiction.id',
        'from_organization.jurisdiction.name',
    ]

class VoteList(PublicListEndpoint):
    model = VoteEvent
    serialize_config = VOTE_SERIALIZE
    default_fields = [
        'result', 'motion_text', 'created_at', 'start_date', 'updated_at',
        'motion_classification', 'extras', 'id',

        'counts',

        'bill.identifier', 'bill.id',
        'organization.id', 'organization.name',
    ]

class VoteDetail(PublicDetailEndpoint):
    model = VoteEvent
    serialize_config = VOTE_SERIALIZE
    default_fields = get_field_list(model, without=[
        'eventrelatedentity',
        'legislative_session_id',
        'bill',
        'legislative_session',
        'organization',
        'organization_id',
        'bill_id',
    ]) + [
        'bill.id',
        'bill.identifier',
        'bill.legislative_session.identifier',

        'organization.id',
        'organization.name',
        'organization.classification',
    ]

class BillDetail(PublicDetailEndpoint):
    model = Bill
    serialize_config = BILL_SERIALIZE
    default_fields = get_field_list(model, without=[
        'from_organization_id',
        'eventrelatedentity',
        'related_bills_reverse',
        'legislative_session_id',
        'actions.organization',
        'votes'
    ]) + [
        'from_organization.id',
        'from_organization.name',
        'legislative_session.identifier',

        'actions.organization.id',
        'actions.organization.name',
        'actions.organization.jurisdiction.id',
        'actions.organization.jurisdiction.classification',
        'actions.organization.jurisdiction.name',
        'actions.organization.jurisdiction.division.id',
        'actions.organization.jurisdiction.division.display_name',

        'votes.result',
        'votes.motion_text',
        'votes.start_date',
        'votes.motion_classification',
        'votes.id',
        'votes.counts',
    ]

class EventList(PublicListEndpoint):
    model = Event
    serialize_config = EVENT_SERIALIZE
    default_fields = [
        'id', 'name', 'description', 'classification', 'start_time',
        'timezone', 'end_time', 'all_day', 'status',

        'agenda.description', 'agenda.order', 'agenda.subjects',
        'agenda.related_entities.note',
        'agenda.related_entities.entity_name',
        'agenda.related_entities.entity_id',
        'agenda.related_entities.entity_type',
    ]

class EventDetail(PublicDetailEndpoint):
    model = Event
    serialize_config = EVENT_SERIALIZE
    default_fields = get_field_list(model, without=[
        'location_id',
    ])
<|endoftext|>


<commit_before>#!/usr/bin/python
import ctypes as c
import random
import ecdsa
import hashlib
import subprocess
import binascii
import pytest
import os

def bytes2num(s):
    res = 0
    for i, b in enumerate(reversed(bytearray(s))):
        res += b << (i * 8)
    return res

curves = {
    'nist256p1': ecdsa.curves.NIST256p,
    'secp256k1': ecdsa.curves.SECP256k1
}

random_iters = int(os.environ.get('ITERS', 1))

scons_file = '''
srcs = 'ecdsa bignum secp256k1 nist256p1 sha2 rand hmac ripemd160 base58'
srcs = [(s + '.c') for s in srcs.split()]
flags = ('-O3 -g -W -Wall -Wextra -Wimplicit-function-declaration '
         '-Wredundant-decls -Wstrict-prototypes -Wundef -Wshadow '
         '-Wpointer-arith -Wformat -Wreturn-type -Wsign-compare -Wmultichar '
         '-Wformat-nonliteral -Winit-self -Wuninitialized -Wformat-security '
         '-Werror -Wno-sequence-point ')
SharedLibrary('ecdsa', srcs, CCFLAGS=flags)
'''
open('SConstruct', 'w').write(scons_file)

subprocess.check_call('scons -s', shell=True)
lib = c.cdll.LoadLibrary('./libecdsa.so')

lib.get_curve_by_name.restype = c.c_void_p

BIGNUM = c.c_uint32 * 9

class Random(random.Random):
    def randbytes(self, n):
        buf = (c.c_uint8 * n)()
        for i in range(n):
            buf[i] = self.randrange(0, 256)
        return buf

    def randpoint(self, curve):
        k = self.randrange(0, curve.order)
        return k * curve.generator

def int2bn(x, bn_type=BIGNUM):
    b = bn_type()
    b._int = x
    for i in range(len(b)):
        b[i] = x % (1 << 30)
        x = x >> 30
    return b

def bn2int(b):
    x = 0
    for i in range(len(b)):
        x += (b[i] << (30 * i))
    return x

@pytest.fixture(params=range(random_iters))
def r(request):
    seed = request.param
    return Random(seed + int(os.environ.get('SEED', 0)))

@pytest.fixture(params=list(sorted(curves)))
def curve(request):
    name = request.param
    curve_ptr = lib.get_curve_by_name(name)
    assert curve_ptr, 'curve {} not found'.format(name)
    curve_obj = curves[name]
    curve_obj.ptr = c.c_void_p(curve_ptr)
    curve_obj.p = curve_obj.curve.p()  # shorthand
    return curve_obj

def test_inverse(curve, r):
    x = r.randrange(1, curve.p)
    y = int2bn(x)
    lib.bn_inverse(y, int2bn(curve.p))
    y = bn2int(y)
    y_ = ecdsa.numbertheory.inverse_mod(x, curve.p)
    assert y == y_

def test_inverse(curve, r):
    x = r.randrange(0, 2*curve.p)
    y = int2bn(x)
    lib.bn_mult_half(y, int2bn(curve.p))
    y = bn2int(y)
    if y > curve.p:
        y -= curve.p
    half = ecdsa.numbertheory.inverse_mod(2, curve.p)
    assert y == (x * half) % curve.p

def test_subtractmod(curve, r):
    x = r.randrange(0, 2 ** 256)
    y = r.randrange(0, 2 ** 256)
    z = int2bn(0)
    lib.bn_subtractmod(int2bn(x), int2bn(y), z, int2bn(curve.p))
    z = bn2int(z)
    z_ = x + 2*curve.p - y
    assert z == z_

def test_subtract2(r):
    x = r.randrange(0, 2 ** 256)
    y = r.randrange(0, 2 ** 256)
    x, y = max(x, y), min(x, y)
    z = int2bn(0)
    lib.bn_subtract(int2bn(x), int2bn(y), z)
    z = bn2int(z)
    z_ = x - y
    assert z == z_

def test_addmod(curve, r):
    x = r.randrange(0, 2 ** 256)
    y = r.randrange(0, 2 ** 256)
    z_ = (x + y) % curve.p
    z = int2bn(x)
    lib.bn_addmod(z, int2bn(y), int2bn(curve.p))
    z = bn2int(z)

    assert z == z_

def test_multiply(curve, r):
    k = r.randrange(0, 2 * curve.p)
    x = r.randrange(0, 2 * curve.p)
    z = (k * x) % curve.p
    k = int2bn(k)
    z_ = int2bn(x)
    p_ = int2bn(curve.p)
    lib.bn_multiply(k, z_, p_)
    z_ = bn2int(z_)
    assert z_ < 2*curve.p
    if z_ >= curve.p:
        z_ = z_ - curve.p
    assert z_ == z

def test_multiply1(curve, r):
    k = r.randrange(0, 2 * curve.p)
    x = r.randrange(0, 2 * curve.p)
    kx = k * x
    res = int2bn(0, bn_type=(c.c_uint32 * 18))
    lib.bn_multiply_long(int2bn(k), int2bn(x), res)
    res = bn2int(res)
    assert res == kx

def test_multiply2(curve, r):
    x = int2bn(0)
    s = r.randrange(0, 2 ** 526)
    res = int2bn(s, bn_type=(c.c_uint32 * 18))
    prime = int2bn(curve.p)
    lib.bn_multiply_reduce(x, res, prime)

    x = bn2int(x)
    x_ = s % curve.p

    assert x == x_

def test_fast_mod(curve, r):
    x = r.randrange(0, 128*curve.p)
    y = int2bn(x)
    lib.bn_fast_mod(y, int2bn(curve.p))
    y = bn2int(y)
    assert y < 2*curve.p
    if y >= curve.p:
        y -= curve.p
    assert x % curve.p == y

def test_mod(curve, r):
    x = r.randrange(0, 2*curve.p)
    y = int2bn(x)
    lib.bn_mod(y, int2bn(curve.p))
    assert bn2int(y) == x % curve.p

POINT = BIGNUM * 2
to_POINT = lambda p: POINT(int2bn(p.x()), int2bn(p.y()))
from_POINT = lambda p: (bn2int(p[0]), bn2int(p[1]))

JACOBIAN = BIGNUM * 3
to_JACOBIAN = lambda jp: JACOBIAN(int2bn(jp[0]), int2bn(jp[1]), int2bn(jp[2]))
from_JACOBIAN = lambda p: (bn2int(p[0]), bn2int(p[1]), bn2int(p[2]))

def test_point_multiply(curve, r):
    p = r.randpoint(curve)
    k = r.randrange(0, 2 ** 256)
    kp = k * p
    res = POINT(int2bn(0), int2bn(0))
    lib.point_multiply(curve.ptr, int2bn(k), to_POINT(p), res)
    res = from_POINT(res)
    assert res == (kp.x(), kp.y())

def test_point_add(curve, r):
    p1 = r.randpoint(curve)
    p2 = r.randpoint(curve)
    #print '-' * 80
    q = p1 + p2
    q1 = to_POINT(p1)
    q2 = to_POINT(p2)
    lib.point_add(curve.ptr, q1, q2)
    q_ = from_POINT(q2)
    assert q_ == (q.x(), q.y())

def test_point_double(curve, r):
    p = r.randpoint(curve)
    q = p.double()
    q_ = to_POINT(p)
    lib.point_double(curve.ptr, q_)
    q_ = from_POINT(q_)
    assert q_ == (q.x(), q.y())

def test_point_to_jacobian(curve, r):
	p = r.randpoint(curve)
	jp = JACOBIAN()
	lib.curve_to_jacobian(to_POINT(p), jp, int2bn(curve.p))
	jx, jy, jz = from_JACOBIAN(jp)
	assert jx == (p.x() * jz ** 2) % curve.p
	assert jy == (p.y() * jz ** 3) % curve.p

	q = POINT()
	lib.jacobian_to_curve(jp, q, int2bn(curve.p))
	q = from_POINT(q)
	assert q == (p.x(), p.y())

def test_cond_negate(curve, r):
    x = r.randrange(0, curve.p)
    a = int2bn(x)
    lib.conditional_negate(0, a, int2bn(curve.p))
    assert bn2int(a) == x
    lib.conditional_negate(-1, a, int2bn(curve.p))
    assert bn2int(a) == curve.p - x

def test_jacobian_add(curve, r):
    p1 = r.randpoint(curve)
    p2 = r.randpoint(curve)
    prime = int2bn(curve.p)
    q = POINT()
    jp2 = JACOBIAN()
    lib.curve_to_jacobian(to_POINT(p2), jp2, prime)
    lib.point_jacobian_add(to_POINT(p1), jp2, prime)
    lib.jacobian_to_curve(jp2, q, prime)
    q = from_POINT(q)
    p_ = p1 + p2
    assert (p_.x(), p_.y()) == q

def test_jacobian_double(curve, r):
    p = r.randpoint(curve)
    p2 = p.double()
    prime = int2bn(curve.p)
    q = POINT()
    jp = JACOBIAN()
    lib.curve_to_jacobian(to_POINT(p), jp, prime)
    lib.point_jacobian_double(jp, curve.ptr)
    lib.jacobian_to_curve(jp, q, prime)
    q = from_POINT(q)
    assert (p2.x(), p2.y()) == q

def sigdecode(sig, _):
    return map(bytes2num, [sig[:32], sig[32:]])

def test_sign(curve, r):
    priv = r.randbytes(32)
    digest = r.randbytes(32)
    sig = r.randbytes(64)

    lib.ecdsa_sign_digest(curve.ptr, priv, digest, sig, c.c_void_p(0))

    exp = bytes2num(priv)
    sk = ecdsa.SigningKey.from_secret_exponent(exp, curve,
                                               hashfunc=hashlib.sha256)
    vk = sk.get_verifying_key()

    sig_ref = sk.sign_digest_deterministic(digest, hashfunc=hashlib.sha256)
    assert binascii.hexlify(sig) == binascii.hexlify(sig_ref)

    assert vk.verify_digest(sig, digest, sigdecode)
<commit_msg>test_curves: fix test case name typo<commit_after>#!/usr/bin/python
import ctypes as c
import random
import ecdsa
import hashlib
import subprocess
import binascii
import pytest
import os

def bytes2num(s):
    res = 0
    for i, b in enumerate(reversed(bytearray(s))):
        res += b << (i * 8)
    return res

curves = {
    'nist256p1': ecdsa.curves.NIST256p,
    'secp256k1': ecdsa.curves.SECP256k1
}

random_iters = int(os.environ.get('ITERS', 1))

scons_file = '''
srcs = 'ecdsa bignum secp256k1 nist256p1 sha2 rand hmac ripemd160 base58'
srcs = [(s + '.c') for s in srcs.split()]
flags = ('-O3 -g -W -Wall -Wextra -Wimplicit-function-declaration '
         '-Wredundant-decls -Wstrict-prototypes -Wundef -Wshadow '
         '-Wpointer-arith -Wformat -Wreturn-type -Wsign-compare -Wmultichar '
         '-Wformat-nonliteral -Winit-self -Wuninitialized -Wformat-security '
         '-Werror -Wno-sequence-point ')
SharedLibrary('ecdsa', srcs, CCFLAGS=flags)
'''
open('SConstruct', 'w').write(scons_file)

subprocess.check_call('scons -s', shell=True)
lib = c.cdll.LoadLibrary('./libecdsa.so')

lib.get_curve_by_name.restype = c.c_void_p

BIGNUM = c.c_uint32 * 9

class Random(random.Random):
    def randbytes(self, n):
        buf = (c.c_uint8 * n)()
        for i in range(n):
            buf[i] = self.randrange(0, 256)
        return buf

    def randpoint(self, curve):
        k = self.randrange(0, curve.order)
        return k * curve.generator

def int2bn(x, bn_type=BIGNUM):
    b = bn_type()
    b._int = x
    for i in range(len(b)):
        b[i] = x % (1 << 30)
        x = x >> 30
    return b

def bn2int(b):
    x = 0
    for i in range(len(b)):
        x += (b[i] << (30 * i))
    return x

@pytest.fixture(params=range(random_iters))
def r(request):
    seed = request.param
    return Random(seed + int(os.environ.get('SEED', 0)))

@pytest.fixture(params=list(sorted(curves)))
def curve(request):
    name = request.param
    curve_ptr = lib.get_curve_by_name(name)
    assert curve_ptr, 'curve {} not found'.format(name)
    curve_obj = curves[name]
    curve_obj.ptr = c.c_void_p(curve_ptr)
    curve_obj.p = curve_obj.curve.p()  # shorthand
    return curve_obj

def test_inverse(curve, r):
    x = r.randrange(1, curve.p)
    y = int2bn(x)
    lib.bn_inverse(y, int2bn(curve.p))
    y = bn2int(y)
    y_ = ecdsa.numbertheory.inverse_mod(x, curve.p)
    assert y == y_

def test_mult_half(curve, r):
    x = r.randrange(0, 2*curve.p)
    y = int2bn(x)
    lib.bn_mult_half(y, int2bn(curve.p))
    y = bn2int(y)
    if y > curve.p:
        y -= curve.p
    half = ecdsa.numbertheory.inverse_mod(2, curve.p)
    assert y == (x * half) % curve.p

def test_subtractmod(curve, r):
    x = r.randrange(0, 2 ** 256)
    y = r.randrange(0, 2 ** 256)
    z = int2bn(0)
    lib.bn_subtractmod(int2bn(x), int2bn(y), z, int2bn(curve.p))
    z = bn2int(z)
    z_ = x + 2*curve.p - y
    assert z == z_

def test_subtract2(r):
    x = r.randrange(0, 2 ** 256)
    y = r.randrange(0, 2 ** 256)
    x, y = max(x, y), min(x, y)
    z = int2bn(0)
    lib.bn_subtract(int2bn(x), int2bn(y), z)
    z = bn2int(z)
    z_ = x - y
    assert z == z_

def test_addmod(curve, r):
    x = r.randrange(0, 2 ** 256)
    y = r.randrange(0, 2 ** 256)
    z_ = (x + y) % curve.p
    z = int2bn(x)
    lib.bn_addmod(z, int2bn(y), int2bn(curve.p))
    z = bn2int(z)

    assert z == z_

def test_multiply(curve, r):
    k = r.randrange(0, 2 * curve.p)
    x = r.randrange(0, 2 * curve.p)
    z = (k * x) % curve.p
    k = int2bn(k)
    z_ = int2bn(x)
    p_ = int2bn(curve.p)
    lib.bn_multiply(k, z_, p_)
    z_ = bn2int(z_)
    assert z_ < 2*curve.p
    if z_ >= curve.p:
        z_ = z_ - curve.p
    assert z_ == z

def test_multiply1(curve, r):
    k = r.randrange(0, 2 * curve.p)
    x = r.randrange(0, 2 * curve.p)
    kx = k * x
    res = int2bn(0, bn_type=(c.c_uint32 * 18))
    lib.bn_multiply_long(int2bn(k), int2bn(x), res)
    res = bn2int(res)
    assert res == kx

def test_multiply2(curve, r):
    x = int2bn(0)
    s = r.randrange(0, 2 ** 526)
    res = int2bn(s, bn_type=(c.c_uint32 * 18))
    prime = int2bn(curve.p)
    lib.bn_multiply_reduce(x, res, prime)

    x = bn2int(x)
    x_ = s % curve.p

    assert x == x_

def test_fast_mod(curve, r):
    x = r.randrange(0, 128*curve.p)
    y = int2bn(x)
    lib.bn_fast_mod(y, int2bn(curve.p))
    y = bn2int(y)
    assert y < 2*curve.p
    if y >= curve.p:
        y -= curve.p
    assert x % curve.p == y

def test_mod(curve, r):
    x = r.randrange(0, 2*curve.p)
    y = int2bn(x)
    lib.bn_mod(y, int2bn(curve.p))
    assert bn2int(y) == x % curve.p

POINT = BIGNUM * 2
to_POINT = lambda p: POINT(int2bn(p.x()), int2bn(p.y()))
from_POINT = lambda p: (bn2int(p[0]), bn2int(p[1]))

JACOBIAN = BIGNUM * 3
to_JACOBIAN = lambda jp: JACOBIAN(int2bn(jp[0]), int2bn(jp[1]), int2bn(jp[2]))
from_JACOBIAN = lambda p: (bn2int(p[0]), bn2int(p[1]), bn2int(p[2]))

def test_point_multiply(curve, r):
    p = r.randpoint(curve)
    k = r.randrange(0, 2 ** 256)
    kp = k * p
    res = POINT(int2bn(0), int2bn(0))
    lib.point_multiply(curve.ptr, int2bn(k), to_POINT(p), res)
    res = from_POINT(res)
    assert res == (kp.x(), kp.y())

def test_point_add(curve, r):
    p1 = r.randpoint(curve)
    p2 = r.randpoint(curve)
    #print '-' * 80
    q = p1 + p2
    q1 = to_POINT(p1)
    q2 = to_POINT(p2)
    lib.point_add(curve.ptr, q1, q2)
    q_ = from_POINT(q2)
    assert q_ == (q.x(), q.y())

def test_point_double(curve, r):
    p = r.randpoint(curve)
    q = p.double()
    q_ = to_POINT(p)
    lib.point_double(curve.ptr, q_)
    q_ = from_POINT(q_)
    assert q_ == (q.x(), q.y())

def test_point_to_jacobian(curve, r):
	p = r.randpoint(curve)
	jp = JACOBIAN()
	lib.curve_to_jacobian(to_POINT(p), jp, int2bn(curve.p))
	jx, jy, jz = from_JACOBIAN(jp)
	assert jx == (p.x() * jz ** 2) % curve.p
	assert jy == (p.y() * jz ** 3) % curve.p

	q = POINT()
	lib.jacobian_to_curve(jp, q, int2bn(curve.p))
	q = from_POINT(q)
	assert q == (p.x(), p.y())

def test_cond_negate(curve, r):
    x = r.randrange(0, curve.p)
    a = int2bn(x)
    lib.conditional_negate(0, a, int2bn(curve.p))
    assert bn2int(a) == x
    lib.conditional_negate(-1, a, int2bn(curve.p))
    assert bn2int(a) == curve.p - x

def test_jacobian_add(curve, r):
    p1 = r.randpoint(curve)
    p2 = r.randpoint(curve)
    prime = int2bn(curve.p)
    q = POINT()
    jp2 = JACOBIAN()
    lib.curve_to_jacobian(to_POINT(p2), jp2, prime)
    lib.point_jacobian_add(to_POINT(p1), jp2, prime)
    lib.jacobian_to_curve(jp2, q, prime)
    q = from_POINT(q)
    p_ = p1 + p2
    assert (p_.x(), p_.y()) == q

def test_jacobian_double(curve, r):
    p = r.randpoint(curve)
    p2 = p.double()
    prime = int2bn(curve.p)
    q = POINT()
    jp = JACOBIAN()
    lib.curve_to_jacobian(to_POINT(p), jp, prime)
    lib.point_jacobian_double(jp, curve.ptr)
    lib.jacobian_to_curve(jp, q, prime)
    q = from_POINT(q)
    assert (p2.x(), p2.y()) == q

def sigdecode(sig, _):
    return map(bytes2num, [sig[:32], sig[32:]])

def test_sign(curve, r):
    priv = r.randbytes(32)
    digest = r.randbytes(32)
    sig = r.randbytes(64)

    lib.ecdsa_sign_digest(curve.ptr, priv, digest, sig, c.c_void_p(0))

    exp = bytes2num(priv)
    sk = ecdsa.SigningKey.from_secret_exponent(exp, curve,
                                               hashfunc=hashlib.sha256)
    vk = sk.get_verifying_key()

    sig_ref = sk.sign_digest_deterministic(digest, hashfunc=hashlib.sha256)
    assert binascii.hexlify(sig) == binascii.hexlify(sig_ref)

    assert vk.verify_digest(sig, digest, sigdecode)
<|endoftext|>


<commit_before>from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import six
from six.moves import zip
from matplotlib.cycler import cycler
from nose.tools import assert_equal, assert_raises
from itertools import product
from operator import add, iadd, mul, imul

def _cycler_helper(c, length, keys, values):
    assert_equal(len(c), length)
    assert_equal(len(c), len(list(c)))
    assert_equal(c.keys, set(keys))

    for k, vals in zip(keys, values):
        for v, v_target in zip(c, vals):
            assert_equal(v[k], v_target)

def _cycles_equal(c1, c2):
    assert_equal(list(c1), list(c2))

def test_creation():
    c = cycler('c', 'rgb')
    yield _cycler_helper, c, 3, ['c'], [['r', 'g', 'b']]
    c = cycler('c', list('rgb'))
    yield _cycler_helper, c, 3, ['c'], [['r', 'g', 'b']]

def test_compose():
    c1 = cycler('c', 'rgb')
    c2 = cycler('lw', range(3))
    c3 = cycler('lw', range(15))
    # addition
    yield _cycler_helper, c1+c2, 3, ['c', 'lw'], [list('rgb'), range(3)]
    yield _cycler_helper, c2+c1, 3, ['c', 'lw'], [list('rgb'), range(3)]
    # miss-matched add lengths
    yield _cycler_helper, c1+c3, 3, ['c', 'lw'], [list('rgb'), range(3)]
    yield _cycler_helper, c3+c1, 3, ['c', 'lw'], [list('rgb'), range(3)]

    # multiplication
    target = zip(*product(list('rgb'), range(3)))
    yield (_cycler_helper, c1 * c2, 9, ['c', 'lw'], target)

    target = zip(*product(range(3), list('rgb')))
    yield (_cycler_helper, c2 * c1, 9, ['lw', 'c'], target)

    target = zip(*product(range(15), list('rgb')))
    yield (_cycler_helper, c3 * c1, 45, ['lw', 'c'], target)

def test_inplace():
    c1 = cycler('c', 'rgb')
    c2 = cycler('lw', range(3))
    c2 += c1
    yield _cycler_helper, c2, 3, ['c', 'lw'], [list('rgb'), range(3)]

    c3 = cycler('c', 'rgb')
    c4 = cycler('lw', range(3))
    c3 *= c4
    target = zip(*product(list('rgb'), range(3)))
    yield (_cycler_helper, c3, 9, ['c', 'lw'], target)

def test_constructor():
    c1 = cycler('c', 'rgb')
    c2 = cycler('ec', c1)
    yield _cycler_helper, c1+c2, 3, ['c', 'ec'], [['r', 'g', 'b']]*2
    c3 = cycler('c', c1)
    yield _cycler_helper, c3+c2, 3, ['c', 'ec'], [['r', 'g', 'b']]*2

def test_failures():
    c1 = cycler('c', 'rgb')
    c2 = cycler('c', c1)
    assert_raises(ValueError, add, c1, c2)
    assert_raises(ValueError, iadd, c1, c2)
    assert_raises(ValueError, mul, c1, c2)
    assert_raises(ValueError, imul, c1, c2)

    c3 = cycler('ec', c1)

    assert_raises(ValueError, cycler, 'c', c2 + c3)

def test_simplify():
    c1 = cycler('c', 'rgb')
    c2 = cycler('ec', c1)
    for c in [c1 * c2, c2 * c1, c1 + c2]:
        yield _cycles_equal, c, c.simplify()

def test_multiply():
    c1 = cycler('c', 'rgb')
    yield _cycler_helper, 2*c1, 6, ['c'], ['rgb'*2]

    c2 = cycler('ec', c1)
    c3 = c1 * c2

    yield _cycles_equal, 2*c3, c3*2

def test_mul_fails():
    c1 = cycler('c', 'rgb')
    assert_raises(TypeError, mul, c1,  2.0)
    assert_raises(TypeError, mul, c1,  'a')
    assert_raises(TypeError, mul, c1,  [])
<commit_msg>TST : test commutativity of cycler addition<commit_after>from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import six
from six.moves import zip
from matplotlib.cycler import cycler
from nose.tools import assert_equal, assert_raises
from itertools import product
from operator import add, iadd, mul, imul

def _cycler_helper(c, length, keys, values):
    assert_equal(len(c), length)
    assert_equal(len(c), len(list(c)))
    assert_equal(c.keys, set(keys))

    for k, vals in zip(keys, values):
        for v, v_target in zip(c, vals):
            assert_equal(v[k], v_target)

def _cycles_equal(c1, c2):
    assert_equal(list(c1), list(c2))

def test_creation():
    c = cycler('c', 'rgb')
    yield _cycler_helper, c, 3, ['c'], [['r', 'g', 'b']]
    c = cycler('c', list('rgb'))
    yield _cycler_helper, c, 3, ['c'], [['r', 'g', 'b']]

def test_compose():
    c1 = cycler('c', 'rgb')
    c2 = cycler('lw', range(3))
    c3 = cycler('lw', range(15))
    # addition
    yield _cycler_helper, c1+c2, 3, ['c', 'lw'], [list('rgb'), range(3)]
    yield _cycler_helper, c2+c1, 3, ['c', 'lw'], [list('rgb'), range(3)]
    yield _cycles_equal, c2+c1, c1+c2
    # miss-matched add lengths
    yield _cycler_helper, c1+c3, 3, ['c', 'lw'], [list('rgb'), range(3)]
    yield _cycler_helper, c3+c1, 3, ['c', 'lw'], [list('rgb'), range(3)]
    yield _cycles_equal, c3+c1, c1+c3

    # multiplication
    target = zip(*product(list('rgb'), range(3)))
    yield (_cycler_helper, c1 * c2, 9, ['c', 'lw'], target)

    target = zip(*product(range(3), list('rgb')))
    yield (_cycler_helper, c2 * c1, 9, ['lw', 'c'], target)

    target = zip(*product(range(15), list('rgb')))
    yield (_cycler_helper, c3 * c1, 45, ['lw', 'c'], target)

def test_inplace():
    c1 = cycler('c', 'rgb')
    c2 = cycler('lw', range(3))
    c2 += c1
    yield _cycler_helper, c2, 3, ['c', 'lw'], [list('rgb'), range(3)]

    c3 = cycler('c', 'rgb')
    c4 = cycler('lw', range(3))
    c3 *= c4
    target = zip(*product(list('rgb'), range(3)))
    yield (_cycler_helper, c3, 9, ['c', 'lw'], target)

def test_constructor():
    c1 = cycler('c', 'rgb')
    c2 = cycler('ec', c1)
    yield _cycler_helper, c1+c2, 3, ['c', 'ec'], [['r', 'g', 'b']]*2
    c3 = cycler('c', c1)
    yield _cycler_helper, c3+c2, 3, ['c', 'ec'], [['r', 'g', 'b']]*2

def test_failures():
    c1 = cycler('c', 'rgb')
    c2 = cycler('c', c1)
    assert_raises(ValueError, add, c1, c2)
    assert_raises(ValueError, iadd, c1, c2)
    assert_raises(ValueError, mul, c1, c2)
    assert_raises(ValueError, imul, c1, c2)

    c3 = cycler('ec', c1)

    assert_raises(ValueError, cycler, 'c', c2 + c3)

def test_simplify():
    c1 = cycler('c', 'rgb')
    c2 = cycler('ec', c1)
    for c in [c1 * c2, c2 * c1, c1 + c2]:
        yield _cycles_equal, c, c.simplify()

def test_multiply():
    c1 = cycler('c', 'rgb')
    yield _cycler_helper, 2*c1, 6, ['c'], ['rgb'*2]

    c2 = cycler('ec', c1)
    c3 = c1 * c2

    yield _cycles_equal, 2*c3, c3*2

def test_mul_fails():
    c1 = cycler('c', 'rgb')
    assert_raises(TypeError, mul, c1,  2.0)
    assert_raises(TypeError, mul, c1,  'a')
    assert_raises(TypeError, mul, c1,  [])
<|endoftext|>