<commit_before># -*- coding: utf-8 -*-
# vim: set fileencoding=utf-8 :

import time
try:
    import queue
except ImportError:
    import Queue as queue

from tools.helper import is_array
import config
from tools.downloader import Downloader
from tools.stream import VideoInfo, flashExt
from tools.page import pages

import signal
import sys

log = config.logger['main']

def signal_handler(signal, frame):
    log.info('You pressed Ctrl+C - Goodbye')
    sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)

def main():
    link = config.link
    media = None
    streamHandler = None

    if not link:
        import tools.commandline as com
        com.usage()

    pageHandler = pages.getExtensionByRegexStringMatch(link)
    if not pageHandler:
        streamHandler = flashExt.getExtensionByRegexStringMatch(link)
        if not streamHandler:
            log.error('No handler for %s', link)
            sys.exit(1)
    else:
        pageHandler = pageHandler()
        log.info("use pagehandler: %s", pageHandler.name)
        media = pageHandler.get(link) # returns array of medias (extractAll) or just one media (download)
        if is_array(media):
            allPages = media
            from tools.db2 import persist
            persist(pageHandler, allPages)
            log.info("finished")
            sys.exit(0)
        if not media:
            log.error('Could not extract')
            return

    download_queue = queue.Queue()
    threads = []
    t = Downloader(download_queue)
    threads.append(t)
    t.start()

    if media:
        for part in media.getSubs():
            queueData = []
            for alt in part.getSubs():
                altPartsPinfo = []
                for altPart in alt.getSubs():
                    pinfo = altPart.pinfo
                    if not pinfo or not pinfo.title or not pinfo.stream_url:
                        # this must be called before flv_url, else it won't work (a fix for this would cost more performance and more code)
                        continue
                    log.info('added "%s" to downloadqueue with "%s"', pinfo.title, pinfo.url)
                    altPartsPinfo.append(pinfo)
                if altPartsPinfo != []:
                    queueData.append((media.name, altPartsPinfo, 0))
            download_queue.put(queueData)

    if streamHandler:
        name = "tmp"
        title = "tmp"
        if config.dl_name:
            name = config.dl_name
        if config.dl_title:
            title = config.dl_title
        pinfo = VideoInfo(link)
        pinfo.name = name
        pinfo.title = title
        download_queue.put([(name, [pinfo], 0)])

    try:
        time.sleep(999999999)
    except:
        log.info("Ctrl-c received!")
        for i in threads:
            i.end()
        for i in threads:
            i.join()
        sys.exit(0)
<commit_msg>reduce complexity of prog.py<commit_after># -*- coding: utf-8 -*-
# vim: set fileencoding=utf-8 :

import time
try:
    import queue
except ImportError:
    import Queue as queue

from tools.helper import is_array
import config
from tools.downloader import Downloader
from tools.stream import VideoInfo, flashExt
from tools.page import pages

import signal
import sys

log = config.logger['main']

def signal_handler(*dummy):
    log.info('You pressed Ctrl+C - Goodbye')
    sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)

def main():
    link = config.link
    media = None
    streamHandler = None

    if not link:
        import tools.commandline as com
        com.usage()

    pageHandler = pages.getExtensionByRegexStringMatch(link)
    if not pageHandler:
        streamHandler = flashExt.getExtensionByRegexStringMatch(link)
        if not streamHandler:
            log.error('No handler for %s', link)
            sys.exit(1)
    else:
        pageHandler = pageHandler()
        log.info("use pagehandler: %s", pageHandler.name)
        media = pageHandler.get(link) # returns array of medias (extractAll) or just one media (download)
        if is_array(media):
            allPages = media
            from tools.db2 import persist
            persist(pageHandler, allPages)
            log.info("finished")
            sys.exit(0)
        if not media:
            log.error('Could not extract')
            return

    download_queue = queue.Queue()
    downloadThread = Downloader(download_queue)
    downloadThread.start()

    if media:
        for part in media.getSubs():
            queueData = []
            for alt in part.getSubs():
                altPartsPinfo = []
                for altPart in alt.getSubs():
                    pinfo = altPart.pinfo
                    if not pinfo or not pinfo.title or not pinfo.stream_url:
                        # this must be called before flv_url, else it won't work (a fix for this would cost more performance and more code)
                        continue
                    log.info('added "%s" to downloadqueue with "%s"', pinfo.title, pinfo.url)
                    altPartsPinfo.append(pinfo)
                if altPartsPinfo != []:
                    queueData.append((media.name, altPartsPinfo, 0))
            download_queue.put(queueData)

    if streamHandler:
        name = "tmp"
        title = "tmp"
        if config.dl_name:
            name = config.dl_name
        if config.dl_title:
            title = config.dl_title
        pinfo = VideoInfo(link)
        pinfo.name = name
        pinfo.title = title
        download_queue.put([(name, [pinfo], 0)])

    try:
        time.sleep(999999999)
    except:
        log.info("Ctrl-c received!")
        downloadThread.end()
        downloadThread.join()
        sys.exit(0)
<|endoftext|>


<commit_before>import collections
from copy import deepcopy
import json
from django.core.management.base import LabelCommand
from couchdbkit import ResourceNotFound
import sqlite3
from casexml.apps.case.dbaccessors import get_total_case_count
from casexml.apps.case.xform import get_case_updates
from corehq.apps.hqcase.dbaccessors import get_number_of_cases_in_domain, \
    get_case_ids_in_domain
from corehq.apps.tzmigration import force_phone_timezones_should_be_processed
from corehq.apps.tzmigration.timezonemigration import json_diff
from corehq.util.dates import iso_string_to_datetime
from couchforms import convert_xform_to_json
from couchforms.models import XFormInstance
from couchforms.util import adjust_datetimes, scrub_meta
from dimagi.utils.couch.database import iter_docs
from couchforms.dbaccessors import get_form_ids_by_type

def is_datetime(string):
    if not isinstance(string, basestring):
        return False

    try:
        iso_string_to_datetime(string)
    except ValueError:
        return False
    else:
        return True

def get_submission_xml(xform_id):
    try:
        xml = XFormInstance.get_db().fetch_attachment(xform_id, 'form.xml')
    except ResourceNotFound:
        raise
    else:
        if isinstance(xml, unicode):
            xml = xml.encode('utf-8')
    return xml

def get_new_form_json(xml, xform_id):
    form_json = convert_xform_to_json(xml)
    with force_phone_timezones_should_be_processed():
        adjust_datetimes(form_json)
    # this is actually in-place because of how jsonobject works
    scrub_meta(XFormInstance.wrap({'form': form_json, '_id': xform_id}))
    return form_json

class CaseFormRelations(object):
    def __init__(self, db_filepath):
        self.db_filepath = db_filepath
        self._connection = None

    @property
    def connection(self):
        if not self._connection:
            self._connection = sqlite3.connect(self.db_filepath)
        return self._connection

    def setup(self):
        cursor = self.connection.cursor()
        cursor.execute("""
          CREATE TABLE commcare_form(
            uuid text CONSTRAINT commcare_form_pk PRIMARY KEY,
            form_json text
          )
        """)
        cursor.execute("""
          CREATE TABLE commcare_case(
            uuid text CONSTRAINT commcare_case_pk PRIMARY KEY
          )
        """)
        cursor.execute("""
          CREATE TABLE commcare_case_action(
            commcare_form INTEGER,
            commcare_case INTEGER,
            action text,
            FOREIGN KEY(commcare_form) REFERENCES commcare_form(uuid),
            FOREIGN KEY(commcare_case) REFERENCES commcare_case(uuid)
          )
        """)
        self.connection.commit()

    def add_form(self, xform_id, form_json):
        cursor = self.connection.cursor()
        cursor.execute(
            'INSERT INTO commcare_form(uuid, form_json) VALUES (?, ?)',
            (xform_id, json.dumps(form_json))
        )
        self.connection.commit()

    def ensure_case(self, case_id):
        cursor = self.connection.cursor()
        cursor.execute(
            'INSERT OR IGNORE INTO commcare_case(uuid) VALUES (?)',
            (case_id,)
        )
        self.connection.commit()

    def add_case_actions(self, case_id, case_actions):
        cursor = self.connection.cursor()
        cursor.executemany(
            'INSERT INTO commcare_case_action(commcare_form, commcare_case, action) VALUES (?, ?, ?)',
            [(xform_id, case_id, json.dumps(case_actions)) for xform_id, case_actions in case_actions]
        )
        self.connection.commit()

    def get_all_form_ids(self):
        cursor = self.connection.cursor()
        form_ids = {uuid for (uuid,) in
                    cursor.execute('SELECT uuid FROM commcare_form')}
        return form_ids

    def get_all_case_ids(self):
        cursor = self.connection.cursor()
        case_ids = {uuid for (uuid,) in
                    cursor.execute('SELECT uuid FROM commcare_case')}
        return case_ids

class Command(LabelCommand):
    def handle_label(self, domain, **options):
        case_form_relations = CaseFormRelations('wvindia2-tzmigration.db')
        # self.tzmigrationtest(domain, case_form_relations)
        self.valiate_forms_and_cases(domain, case_form_relations)

    def valiate_forms_and_cases(self, domain, case_form_relations):
        form_ids_in_couch = set(get_form_ids_by_type(domain, 'XFormInstance'))
        form_ids_in_sqlite = set(case_form_relations.get_all_form_ids())

        print 'Forms in Couch: {}'.format(len(form_ids_in_couch))
        print 'Forms in Sqlite: {}'.format(len(form_ids_in_sqlite))
        print 'In Couch only: {}'.format(list(form_ids_in_couch - form_ids_in_sqlite))

        case_ids_in_couch = set(get_case_ids_in_domain(domain))
        case_ids_in_sqlite = set(case_form_relations.get_all_case_ids())

        print 'Cases in Couch: {}'.format(len(case_ids_in_couch))
        print 'Cases in Sqlite: {}'.format(len(case_ids_in_sqlite))
        print 'In Couch only: {}'.format(list(case_ids_in_couch - case_ids_in_sqlite))

    def tzmigrationtest(self, domain, case_form_relations):
        case_form_relations.setup()
        xform_ids = get_form_ids_by_type(domain, 'XFormInstance')
        if not xform_ids:
            self.stderr('No XForms Found\n')
        diffs_by_xform_id = collections.defaultdict(list)

        for i, xform in enumerate(iter_docs(XFormInstance.get_db(), xform_ids)):
            xform_id = xform['_id']
            case_actions_by_case_id = collections.defaultdict(list)
            xml = get_submission_xml(xform_id)
            form_json = get_new_form_json(xml, xform_id)
            case_form_relations.add_form(xform_id, form_json)

            case_updates = get_case_updates(form_json)
            xform_copy = deepcopy(xform)
            xform_copy['form'] = form_json
            xformdoc = XFormInstance.wrap(xform_copy)

            case_actions = [
                (case_update.id, action.xform_id, action.to_json())
                for case_update in case_updates
                for action in case_update.get_case_actions(xformdoc)
            ]

            for case_id, xform_id, case_action in case_actions:
                case_actions_by_case_id[case_id].append((xform_id, case_action))

            for case_id, case_actions in case_actions_by_case_id.items():
                case_form_relations.ensure_case(case_id)
                case_form_relations.add_case_actions(case_id, case_actions)

            for type_, path, first, second in json_diff(xform['form'], form_json):

                diffs_by_xform_id[xform_id].append({
                    'type': type_,
                    'path': list(path),
                    'old': first,
                    'new': second
                })

            print {'xform_id': xform_id, 'diffs': diffs_by_xform_id[xform_id]}
<commit_msg>add spanning to tzmigrationtest<commit_after>import collections
from copy import deepcopy
import json
from django.core.management.base import LabelCommand
from couchdbkit import ResourceNotFound
import sqlite3
from casexml.apps.case.xform import get_case_updates
from corehq.apps.hqcase.dbaccessors import get_case_ids_in_domain
from corehq.apps.tzmigration import force_phone_timezones_should_be_processed
from corehq.apps.tzmigration.timezonemigration import json_diff
from corehq.util.dates import iso_string_to_datetime
from couchforms import convert_xform_to_json
from couchforms.models import XFormInstance
from couchforms.util import adjust_datetimes, scrub_meta
from dimagi.utils.couch.database import iter_docs
from couchforms.dbaccessors import get_form_ids_by_type

def is_datetime(string):
    if not isinstance(string, basestring):
        return False

    try:
        iso_string_to_datetime(string)
    except ValueError:
        return False
    else:
        return True

def get_submission_xml(xform_id):
    try:
        xml = XFormInstance.get_db().fetch_attachment(xform_id, 'form.xml')
    except ResourceNotFound:
        raise
    else:
        if isinstance(xml, unicode):
            xml = xml.encode('utf-8')
    return xml

def get_new_form_json(xml, xform_id):
    form_json = convert_xform_to_json(xml)
    with force_phone_timezones_should_be_processed():
        adjust_datetimes(form_json)
    # this is actually in-place because of how jsonobject works
    scrub_meta(XFormInstance.wrap({'form': form_json, '_id': xform_id}))
    return form_json

class CaseFormRelations(object):
    def __init__(self, db_filepath):
        self.db_filepath = db_filepath
        self._connection = None

    @property
    def connection(self):
        if not self._connection:
            self._connection = sqlite3.connect(self.db_filepath)
        return self._connection

    def setup(self):
        cursor = self.connection.cursor()
        cursor.execute("""
          CREATE TABLE commcare_form(
            uuid text CONSTRAINT commcare_form_pk PRIMARY KEY,
            form_json text
          )
        """)
        cursor.execute("""
          CREATE TABLE commcare_case(
            uuid text CONSTRAINT commcare_case_pk PRIMARY KEY
          )
        """)
        cursor.execute("""
          CREATE TABLE commcare_case_action(
            commcare_form INTEGER,
            commcare_case INTEGER,
            action text,
            FOREIGN KEY(commcare_form) REFERENCES commcare_form(uuid),
            FOREIGN KEY(commcare_case) REFERENCES commcare_case(uuid)
          )
        """)
        self.connection.commit()

    def add_form(self, xform_id, form_json):
        cursor = self.connection.cursor()
        cursor.execute(
            'INSERT INTO commcare_form(uuid, form_json) VALUES (?, ?)',
            (xform_id, json.dumps(form_json))
        )
        self.connection.commit()

    def ensure_case(self, case_id):
        cursor = self.connection.cursor()
        cursor.execute(
            'INSERT OR IGNORE INTO commcare_case(uuid) VALUES (?)',
            (case_id,)
        )
        self.connection.commit()

    def add_case_actions(self, case_id, case_actions):
        cursor = self.connection.cursor()
        cursor.executemany(
            'INSERT INTO commcare_case_action(commcare_form, commcare_case, action) VALUES (?, ?, ?)',
            [(xform_id, case_id, json.dumps(case_actions)) for xform_id, case_actions in case_actions]
        )
        self.connection.commit()

    def get_all_form_ids(self):
        cursor = self.connection.cursor()
        form_ids = {uuid for (uuid,) in
                    cursor.execute('SELECT uuid FROM commcare_form')}
        return form_ids

    def get_all_case_ids(self):
        cursor = self.connection.cursor()
        case_ids = {uuid for (uuid,) in
                    cursor.execute('SELECT uuid FROM commcare_case')}
        return case_ids

    def get_form_ids_by_cases(self, case_ids):
        cursor = self.connection.cursor()
        set_fragment = ','.join(['?'] * len(case_ids))
        return {form_id for (form_id, _) in cursor.execute("""
            SELECT commcare_form, commcare_case
              FROM commcare_case_action
              WHERE commcare_case IN ({})
            """.format(set_fragment), tuple(case_ids),
        )}

    def get_case_ids_by_forms(self, form_ids):
        cursor = self.connection.cursor()
        set_fragment = ','.join(['?'] * len(form_ids))
        return {case_id for (_, case_id) in cursor.execute("""
            SELECT commcare_form, commcare_case
              FROM commcare_case_action
              WHERE commcare_form IN ({})
            """.format(set_fragment), tuple(form_ids),
        )}

    def span_form_id(self, form_id):
        form_ids = {form_id}
        case_ids = set()
        new_forms = {form_id}
        new_cases = set()
        while new_forms or new_cases:
            new_cases = self.get_case_ids_by_forms(form_ids) - case_ids
            case_ids |= new_cases
            new_forms = self.get_form_ids_by_cases(case_ids) - form_ids
            form_ids |= new_forms
        return form_ids, case_ids

class Command(LabelCommand):
    def handle_label(self, domain, **options):
        case_form_relations = CaseFormRelations(
            '{}-tzmigration.db'.format(domain))
        # self.tzmigrationtest(domain, case_form_relations)
        # self.valiate_forms_and_cases(domain, case_form_relations)
        self.group_forms_and_cases(case_form_relations)

    def group_forms_and_cases(self, case_form_relations):
        all_form_ids = case_form_relations.get_all_form_ids()
        all_case_ids = case_form_relations.get_all_case_ids()
        groups = []
        i = 0
        while all_form_ids:
            i += 1
            form_id = all_form_ids.pop()
            form_ids, case_ids = case_form_relations.span_form_id(form_id)
            all_form_ids -= form_ids
            all_case_ids -= case_ids
            groups.append((form_ids, case_ids))

            print 'Group {}'.format(i)
            print 'Forms ({}): {}'.format(len(form_ids), form_ids)
            print 'Cases ({}): {}'.format(len(case_ids), case_ids)
        print "Left over cases: {}".format(all_case_ids)

    def valiate_forms_and_cases(self, domain, case_form_relations):
        form_ids_in_couch = set(get_form_ids_by_type(domain, 'XFormInstance'))
        form_ids_in_sqlite = set(case_form_relations.get_all_form_ids())

        print 'Forms in Couch: {}'.format(len(form_ids_in_couch))
        print 'Forms in Sqlite: {}'.format(len(form_ids_in_sqlite))
        print 'In Couch only: {}'.format(list(form_ids_in_couch - form_ids_in_sqlite))

        case_ids_in_couch = set(get_case_ids_in_domain(domain))
        case_ids_in_sqlite = set(case_form_relations.get_all_case_ids())

        print 'Cases in Couch: {}'.format(len(case_ids_in_couch))
        print 'Cases in Sqlite: {}'.format(len(case_ids_in_sqlite))
        print 'In Couch only: {}'.format(list(case_ids_in_couch - case_ids_in_sqlite))
        print 'In Sqlite only: {}'.format(list(case_ids_in_sqlite - case_ids_in_couch))

    def tzmigrationtest(self, domain, case_form_relations):
        case_form_relations.setup()
        xform_ids = get_form_ids_by_type(domain, 'XFormInstance')
        if not xform_ids:
            self.stderr('No XForms Found\n')
        diffs_by_xform_id = collections.defaultdict(list)

        for i, xform in enumerate(iter_docs(XFormInstance.get_db(), xform_ids)):
            xform_id = xform['_id']
            case_actions_by_case_id = collections.defaultdict(list)
            xml = get_submission_xml(xform_id)
            form_json = get_new_form_json(xml, xform_id)
            case_form_relations.add_form(xform_id, form_json)

            case_updates = get_case_updates(form_json)
            xform_copy = deepcopy(xform)
            xform_copy['form'] = form_json
            xformdoc = XFormInstance.wrap(xform_copy)

            case_actions = [
                (case_update.id, action.xform_id, action.to_json())
                for case_update in case_updates
                for action in case_update.get_case_actions(xformdoc)
            ]

            for case_id, xform_id, case_action in case_actions:
                case_actions_by_case_id[case_id].append((xform_id, case_action))

            for case_id, case_actions in case_actions_by_case_id.items():
                case_form_relations.ensure_case(case_id)
                case_form_relations.add_case_actions(case_id, case_actions)

            for type_, path, first, second in json_diff(xform['form'], form_json):

                diffs_by_xform_id[xform_id].append({
                    'type': type_,
                    'path': list(path),
                    'old': first,
                    'new': second
                })

            print {'xform_id': xform_id, 'diffs': diffs_by_xform_id[xform_id]}
<|endoftext|>


<commit_before>"""
Django settings for djmaterial project.

Generated by 'django-admin startproject' using Django 3.0.8.

For more information on this file, see
https://docs.djangoproject.com/en/3.0/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '78yuqwt_zvq=z9*z4o8+hjn53ok@yr)w_2azw%k$+&_r)ul%70'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []

# Application definition

INSTALLED_APPS = [
    'material.admin',
    'material.admin.default',
    #'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'djmaterial.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'djmaterial.wsgi.application'

# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/

STATIC_URL = '/static/'

MATERIAL_ADMIN_SITE = {
    'HEADER':  ('Your site header'),  # Admin site header
}
<commit_msg>update django secret key because git guardian thought i was actually using that one but wasnt<commit_after>"""
Django settings for djmaterial project.

Generated by 'django-admin startproject' using Django 3.0.8.

For more information on this file, see
https://docs.djangoproject.com/en/3.0/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'this is a secret key i dont actually use, change it'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []

# Application definition

INSTALLED_APPS = [
    'material.admin',
    'material.admin.default',
    #'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'djmaterial.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'djmaterial.wsgi.application'

# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/

STATIC_URL = '/static/'

MATERIAL_ADMIN_SITE = {
    'HEADER':  ('Your site header'),  # Admin site header
}
<|endoftext|>


<commit_before><commit_msg>Fix assert API usage (this could never have worked...)<commit_after><|endoftext|>


<commit_before><commit_msg>convert payment_line to related field<commit_after><|endoftext|>


<commit_before><commit_msg>Heffte: Add e4s testsuite-inspired smoke test (#23652)<commit_after><|endoftext|>


<commit_before>##############################################################################
# Copyright (c) 2013-2018, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
#
# This file is part of Spack.
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
# For details, see https://github.com/spack/spack
# Please also see the NOTICE and LICENSE files for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License (as
# published by the Free Software Foundation) version 2.1, February 1999.
#
# 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 terms and
# conditions of the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
from spack import *

class Tophat(AutotoolsPackage):
    """Spliced read mapper for RNA-Seq."""

    homepage = "http://ccb.jhu.edu/software/tophat/index.shtml"
    url      = "https://github.com/infphilo/tophat/archive/v2.1.1.tar.gz"

    version('2.1.1', 'ffd18de2f893a95eb7e9d0c5283d241f')

    depends_on('autoconf', type='build')
    depends_on('automake', type='build')
    depends_on('libtool',  type='build')
    depends_on('m4',       type='build')

    depends_on('boost@1.47:')
    depends_on('bowtie2', type='run')

    parallel = False

    def configure_args(self):
        return ["--with-boost={0}".format(self.spec['boost'].prefix)]
<commit_msg>Add Tophat v2.1.2, fixes automake issues (#8266)<commit_after>##############################################################################
# Copyright (c) 2013-2018, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
#
# This file is part of Spack.
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
# For details, see https://github.com/spack/spack
# Please also see the NOTICE and LICENSE files for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License (as
# published by the Free Software Foundation) version 2.1, February 1999.
#
# 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 terms and
# conditions of the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
from spack import *

class Tophat(AutotoolsPackage):
    """Spliced read mapper for RNA-Seq."""

    homepage = "http://ccb.jhu.edu/software/tophat/index.shtml"
    url      = "https://github.com/infphilo/tophat/archive/v2.1.1.tar.gz"

    version('2.1.2', 'db844fd7f53c519e716cd6222e6195b2')
    version('2.1.1', 'ffd18de2f893a95eb7e9d0c5283d241f')

    depends_on('autoconf', type='build')
    # 2.1.1 only builds with automake@1.15.1.  There's a patch here:
    # https://github.com/spack/spack/pull/8244, which was incorporated
    # upstream in 2.1.2, which is known to build with 1.16.1 and 1.15.1.
    depends_on('automake',                        type='build')
    depends_on('automake@1.15.1', when='@:2.1.1', type='build')
    depends_on('libtool',  type='build')
    depends_on('m4',       type='build')

    depends_on('boost@1.47:')
    depends_on('bowtie2', type='run')

    parallel = False

    def configure_args(self):
        return ["--with-boost={0}".format(self.spec['boost'].prefix)]
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import unicode_literals
import logging

from django.db import migrations

from django.conf import settings
from django.contrib.auth.models import User

logger = logging.getLogger(__name__)

def add_service_user(apps, schema_editor):
    """Add service user."""
    user, created = User.objects.get_or_create(username=settings.CREDENTIALS_SERVICE_USERNAME)
    if created:
        user.is_staff = True
        user.set_unusable_password()
        user.save()

def remove_service_user(apps, schema_editor):
    """Remove service user."""
    try:
        User.objects.get(username=settings.CREDENTIALS_SERVICE_USERNAME).delete()
    except Exception:  # pylint: disable=broad-except
        logger.exception('Unexpected error while attempting to delete credentials service user.')
        logger.warning('This service user account may need cleanup, but migrations can safely continue.')

class Migration(migrations.Migration):

    dependencies = [
        ('credentials', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(add_service_user, remove_service_user),
    ]
<commit_msg>Revert "Merge pull request #11311 from edx/jsa/fail-safe-reverse"<commit_after># -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models

from django.conf import settings
from django.contrib.auth.models import User

def add_service_user(apps, schema_editor):
    """Add service user."""
    user, created = User.objects.get_or_create(username=settings.CREDENTIALS_SERVICE_USERNAME)
    if created:
        user.is_staff = True
        user.set_unusable_password()
        user.save()

def remove_service_user(apps, schema_editor):
    """Remove service user."""
    try:
        User.objects.get(username=settings.CREDENTIALS_SERVICE_USERNAME).delete()
    except User.DoesNotExist:
        return

class Migration(migrations.Migration):

    dependencies = [
        ('credentials', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(add_service_user, remove_service_user),
    ]
<|endoftext|>


<commit_before>""" Defines the ColorBar class.
"""

from __future__ import with_statement

# Major library imports
from numpy import array, arange, ones, transpose, uint8

# Enthought library imports
from enthought.traits.api import Any, Bool, Enum, Instance, Property, \
                                 cached_property
from enthought.kiva.image import GraphicsContext

# Local imports
from base_xy_plot import BaseXYPlot
from abstract_plot_renderer import AbstractPlotRenderer
from abstract_mapper import AbstractMapper
from array_data_source import ArrayDataSource
from grid import PlotGrid
from axis import PlotAxis

class ColorBar(AbstractPlotRenderer):
    """ A color bar for a color-mapped plot.
    """
    # Screen mapper for index data.
    index_mapper = Instance(AbstractMapper)

    # Screen mapper for color data
    color_mapper = Property #Instance(ColorMapper)

    # Screen mapper for value data (synonym for color_mapper)
    value_mapper = Property(depends_on='color_mapper')

    # Optional index data source for generic tools to attach metadata to.
    index = Property

    # Optional color-mapped plot that this color bar references.  If specified,
    # the plot must have a **color_mapper** attribute.
    plot = Any

    # Is there a visible grid on the colorbar?
    grid_visible = Bool(True)

    # Is there a visible axis on the colorbar?
    axis_visible = Bool(True)

    # Corresponds to either **index_mapper** or None, depending on
    # the orientation of the plot.
    x_mapper = Property
    # Corresponds to either **index_mapper** or None, depending on
    # the orientation of the plot.
    y_mapper = Property

    #------------------------------------------------------------------------
    # Override default values of inherited traits
    #------------------------------------------------------------------------

    # The border is visible (overrides enable.Component).
    border_visible = True
    # The orientation of the index axis.
    orientation = Enum('v', 'h')
    # Should the bar go left-to-right or bottom-to-top (normal) or the reverse?
    direction = Enum('normal', 'flipped')
    # Overrides the default background color trait in PlotComponent.
    bgcolor = 'transparent'
    # Draw layers in "draw order"
    use_draw_order = True
    # Default width is 40 pixels (overrides enable.CoordinateBox)
    width = 40

    # Faux origin for the axis to look at
    origin = Enum('bottom left', 'top left', 'bottom right', 'top right')

    #------------------------------------------------------------------------
    # Private attributes
    #------------------------------------------------------------------------

    # The grid
    _grid = Instance(PlotGrid)

    # The axis
    _axis = Instance(PlotAxis)

    # Shadow attribute for color_mapper
    _color_mapper = Any

    # Shadow attribute for index
    _index = Instance(ArrayDataSource, args=())

    def __init__(self, *args, **kw):
        """ In creating an instance, this method ensures that the grid and the
        axis are created before setting their visibility.
        """
        grid_visible = kw.pop("grid_visible", True)
        axis_visible = kw.pop("axis_visible", True)

        super(ColorBar, self).__init__(*args, **kw)

        if self.orientation == 'h':
            if self.direction == 'normal':
                self.origin = 'bottom left'
            else:
                self.origin = 'bottom right'
            grid_orientation = 'vertical'
            axis_orientation = 'bottom'
        else:
            if self.direction == 'normal':
                self.origin = 'bottom left'
            else:
                self.origin = 'top left'
            grid_orientation = 'horizontal'
            axis_orientation = 'left'

        self._grid = PlotGrid(orientation=grid_orientation,
                              mapper=self.index_mapper,
                              component=self)
        self._axis = PlotAxis(orientation=axis_orientation,
                              mapper=self.index_mapper,
                              component=self)
        self.overlays.append(self._grid)
        self.overlays.append(self._axis)

        # Now that we have a grid and an axis, we can safely set the visibility
        self.grid_visible = grid_visible
        self.axis_visible = axis_visible
        return

    def _draw_plot(self, gc, view_bounds=None, mode='normal'):
        """ Draws the 'plot' layer.
        """
        self._update_mappers()
        with gc:
            if self.orientation == 'h':
                perpendicular_dim = 1
                axis_dim = 0
            else:
                perpendicular_dim = 0
                axis_dim = 1

            mapper = self.index_mapper

            scrn_points = arange(mapper.low_pos, mapper.high_pos+1)

            # Get the data values associated with the list of screen points.
            if mapper.range.low == mapper.range.high:
                # LogMapper.map_data() returns something unexpected if low==high,
                # so we'll handle that case here.
                data_points = array([mapper.range.high])
            else:
                data_points = mapper.map_data(scrn_points)

            if self.direction == 'flipped':
                data_points = data_points[::-1]

            # Get the colors associated with the data points.
            colors = self.color_mapper.map_screen(data_points)

            img = self._make_color_image(colors, self.bounds[perpendicular_dim],
                                                    self.orientation, self.direction)
            gc.draw_image(img, (self.x, self.y, self.width, self.height))

    def _make_color_image(self, color_values, width, orientation, direction):
        """
        Returns an image graphics context representing the array of color
        values (Nx3 or Nx4). The *width* parameter is the width of the
        colorbar, and *orientation* is the orientation of the plot.
        """
        bmparray = ones((width, color_values.shape[0],
                                    color_values.shape[1]))* color_values * 255

        if orientation == "v":
            bmparray = transpose(bmparray, axes=(1,0,2))[::-1]
        bmparray = bmparray.astype(uint8)
        img = GraphicsContext(bmparray, "rgba32")
        return img

    #------------------------------------------------------------------------
    # Trait events
    #------------------------------------------------------------------------

    def _update_mappers(self):
        if not self.index_mapper or not self.color_mapper:
            return
        if self.orientation == 'h' and 'left' in self.origin:
            self.index_mapper.low_pos = self.x
            self.index_mapper.high_pos = self.x2
        elif self.orientation == 'h' and 'right' in self.origin:
            self.index_mapper.low_pos = self.x2
            self.index_mapper.high_pos = self.x
        elif self.orientation == 'v' and 'bottom' in self.origin:
            self.index_mapper.low_pos = self.y
            self.index_mapper.high_pos = self.y2
        elif self.orientation == 'v' and 'top' in self.origin:
            self.index_mapper.low_pos = self.y2
            self.index_mapper.high_pos = self.y
        self.index_mapper.range = self.color_mapper.range

    def _bounds_changed(self, old, new):
        super(ColorBar, self)._bounds_changed(old, new)
        self._update_mappers()

    def _bounds_items_changed(self, event):
        super(ColorBar, self)._bounds_items_changed(event)
        self._update_mappers()

    def _position_changed(self, old, new):
        super(ColorBar, self)._position_changed(old, new)
        self._update_mappers()

    def _position_items_changed(self, event):
        super(ColorBar, self)._position_items_changed(event)
        self._update_mappers()

    def _updated_changed_for_index_mapper(self):
        self._update_mappers()

    def _updated_changed_for_color_mapper(self):
        self._update_mappers()

    def _either_mapper_changed(self):
        self.invalidate_draw()
        self.request_redraw()

    def _index_mapper_changed(self):
        # Keep the grid and axis index_mappers the same as our index_mapper.
        if self._grid is not None:
            self._grid.mapper = self.index_mapper
        if self._axis is not None:
            self._axis.mapper = self.index_mapper
        self._either_mapper_changed()

    def _color_mapper_changed(self):
        self._either_mapper_changed()

    def _value_mapper_changed(self):
        self._color_mapper_changed()

    def _plot_changed(self):
        self.request_redraw()

    def _grid_visible_changed(self, old, new):
        self._grid.visible = new
        self.request_redraw()

    def _axis_visible_changed(self, old, new):
        self._axis.visible = new
        self.request_redraw()

    #------------------------------------------------------------------------
    # Property setters and getters
    #------------------------------------------------------------------------

    def _get_x_mapper(self):
        if self.orientation == "h":
            return self.index_mapper
        else:
            return None

    def _get_y_mapper(self):
        if self.orientation == "h":
            return None
        else:
            return self.index_mapper

    def _get_color_mapper(self):
        if self.plot:
            return self.plot.color_mapper
        elif self._color_mapper:
            return self._color_mapper
        else:
            return None

    def _set_color_mapper(self, val):
        self._color_mapper = val

    @cached_property
    def _get_value_mapper(self):
        return self._get_color_mapper()

    def _set_value_mapper(self, val):
        self._set_color_mapper(val)

    def _get_index(self):
        if self.plot and hasattr(self.plot, "color_data"):
            return self.plot.color_data
        elif self.plot and isinstance(self.plot, BaseXYPlot):
            return self.plot.index
        elif self._index:
            return self._index
        else:
            return None

    def _set_index(self, val):
        self._index = val

# EOF
<commit_msg>redraw a ColorBar when any of its mappers' traits change<commit_after>""" Defines the ColorBar class.
"""

from __future__ import with_statement

# Major library imports
from numpy import array, arange, ones, transpose, uint8

# Enthought library imports
from enthought.traits.api import Any, Bool, Enum, Instance, Property, \
                                 cached_property, on_trait_change
from enthought.kiva.image import GraphicsContext

# Local imports
from base_xy_plot import BaseXYPlot
from abstract_plot_renderer import AbstractPlotRenderer
from abstract_mapper import AbstractMapper
from array_data_source import ArrayDataSource
from grid import PlotGrid
from axis import PlotAxis

class ColorBar(AbstractPlotRenderer):
    """ A color bar for a color-mapped plot.
    """
    # Screen mapper for index data.
    index_mapper = Instance(AbstractMapper)

    # Screen mapper for color data
    color_mapper = Property #Instance(ColorMapper)

    # Screen mapper for value data (synonym for color_mapper)
    value_mapper = Property(depends_on='color_mapper')

    # Optional index data source for generic tools to attach metadata to.
    index = Property

    # Optional color-mapped plot that this color bar references.  If specified,
    # the plot must have a **color_mapper** attribute.
    plot = Any

    # Is there a visible grid on the colorbar?
    grid_visible = Bool(True)

    # Is there a visible axis on the colorbar?
    axis_visible = Bool(True)

    # Corresponds to either **index_mapper** or None, depending on
    # the orientation of the plot.
    x_mapper = Property
    # Corresponds to either **index_mapper** or None, depending on
    # the orientation of the plot.
    y_mapper = Property

    #------------------------------------------------------------------------
    # Override default values of inherited traits
    #------------------------------------------------------------------------

    # The border is visible (overrides enable.Component).
    border_visible = True
    # The orientation of the index axis.
    orientation = Enum('v', 'h')
    # Should the bar go left-to-right or bottom-to-top (normal) or the reverse?
    direction = Enum('normal', 'flipped')
    # Overrides the default background color trait in PlotComponent.
    bgcolor = 'transparent'
    # Draw layers in "draw order"
    use_draw_order = True
    # Default width is 40 pixels (overrides enable.CoordinateBox)
    width = 40

    # Faux origin for the axis to look at
    origin = Enum('bottom left', 'top left', 'bottom right', 'top right')

    #------------------------------------------------------------------------
    # Private attributes
    #------------------------------------------------------------------------

    # The grid
    _grid = Instance(PlotGrid)

    # The axis
    _axis = Instance(PlotAxis)

    # Shadow attribute for color_mapper
    _color_mapper = Any

    # Shadow attribute for index
    _index = Instance(ArrayDataSource, args=())

    def __init__(self, *args, **kw):
        """ In creating an instance, this method ensures that the grid and the
        axis are created before setting their visibility.
        """
        grid_visible = kw.pop("grid_visible", True)
        axis_visible = kw.pop("axis_visible", True)

        super(ColorBar, self).__init__(*args, **kw)

        if self.orientation == 'h':
            if self.direction == 'normal':
                self.origin = 'bottom left'
            else:
                self.origin = 'bottom right'
            grid_orientation = 'vertical'
            axis_orientation = 'bottom'
        else:
            if self.direction == 'normal':
                self.origin = 'bottom left'
            else:
                self.origin = 'top left'
            grid_orientation = 'horizontal'
            axis_orientation = 'left'

        self._grid = PlotGrid(orientation=grid_orientation,
                              mapper=self.index_mapper,
                              component=self)
        self._axis = PlotAxis(orientation=axis_orientation,
                              mapper=self.index_mapper,
                              component=self)
        self.overlays.append(self._grid)
        self.overlays.append(self._axis)

        # Now that we have a grid and an axis, we can safely set the visibility
        self.grid_visible = grid_visible
        self.axis_visible = axis_visible
        return

    def _draw_plot(self, gc, view_bounds=None, mode='normal'):
        """ Draws the 'plot' layer.
        """
        self._update_mappers()
        with gc:
            if self.orientation == 'h':
                perpendicular_dim = 1
                axis_dim = 0
            else:
                perpendicular_dim = 0
                axis_dim = 1

            mapper = self.index_mapper

            scrn_points = arange(mapper.low_pos, mapper.high_pos+1)

            # Get the data values associated with the list of screen points.
            if mapper.range.low == mapper.range.high:
                # LogMapper.map_data() returns something unexpected if low==high,
                # so we'll handle that case here.
                data_points = array([mapper.range.high])
            else:
                data_points = mapper.map_data(scrn_points)

            if self.direction == 'flipped':
                data_points = data_points[::-1]

            # Get the colors associated with the data points.
            colors = self.color_mapper.map_screen(data_points)

            img = self._make_color_image(colors, self.bounds[perpendicular_dim],
                                                    self.orientation, self.direction)
            gc.draw_image(img, (self.x, self.y, self.width, self.height))

    def _make_color_image(self, color_values, width, orientation, direction):
        """
        Returns an image graphics context representing the array of color
        values (Nx3 or Nx4). The *width* parameter is the width of the
        colorbar, and *orientation* is the orientation of the plot.
        """
        bmparray = ones((width, color_values.shape[0],
                                    color_values.shape[1]))* color_values * 255

        if orientation == "v":
            bmparray = transpose(bmparray, axes=(1,0,2))[::-1]
        bmparray = bmparray.astype(uint8)
        img = GraphicsContext(bmparray, "rgba32")
        return img

    #------------------------------------------------------------------------
    # Trait events
    #------------------------------------------------------------------------

    def _update_mappers(self):
        if not self.index_mapper or not self.color_mapper:
            return
        if self.orientation == 'h' and 'left' in self.origin:
            self.index_mapper.low_pos = self.x
            self.index_mapper.high_pos = self.x2
        elif self.orientation == 'h' and 'right' in self.origin:
            self.index_mapper.low_pos = self.x2
            self.index_mapper.high_pos = self.x
        elif self.orientation == 'v' and 'bottom' in self.origin:
            self.index_mapper.low_pos = self.y
            self.index_mapper.high_pos = self.y2
        elif self.orientation == 'v' and 'top' in self.origin:
            self.index_mapper.low_pos = self.y2
            self.index_mapper.high_pos = self.y
        self.index_mapper.range = self.color_mapper.range

    def _bounds_changed(self, old, new):
        super(ColorBar, self)._bounds_changed(old, new)
        self._update_mappers()

    def _bounds_items_changed(self, event):
        super(ColorBar, self)._bounds_items_changed(event)
        self._update_mappers()

    def _position_changed(self, old, new):
        super(ColorBar, self)._position_changed(old, new)
        self._update_mappers()

    def _position_items_changed(self, event):
        super(ColorBar, self)._position_items_changed(event)
        self._update_mappers()

    def _updated_changed_for_index_mapper(self):
        self._update_mappers()

    def _updated_changed_for_color_mapper(self):
        self._update_mappers()

    @on_trait_change('[index_mapper,color_mapper].+')
    def _either_mapper_changed(self):
        self.invalidate_draw()
        self.request_redraw()

    def _index_mapper_changed(self):
        # Keep the grid and axis index_mappers the same as our index_mapper.
        if self._grid is not None:
            self._grid.mapper = self.index_mapper
        if self._axis is not None:
            self._axis.mapper = self.index_mapper
        self._either_mapper_changed()

    def _color_mapper_changed(self):
        self._either_mapper_changed()

    def _value_mapper_changed(self):
        self._color_mapper_changed()

    def _plot_changed(self):
        self.request_redraw()

    def _grid_visible_changed(self, old, new):
        self._grid.visible = new
        self.request_redraw()

    def _axis_visible_changed(self, old, new):
        self._axis.visible = new
        self.request_redraw()

    #------------------------------------------------------------------------
    # Property setters and getters
    #------------------------------------------------------------------------

    def _get_x_mapper(self):
        if self.orientation == "h":
            return self.index_mapper
        else:
            return None

    def _get_y_mapper(self):
        if self.orientation == "h":
            return None
        else:
            return self.index_mapper

    def _get_color_mapper(self):
        if self.plot:
            return self.plot.color_mapper
        elif self._color_mapper:
            return self._color_mapper
        else:
            return None

    def _set_color_mapper(self, val):
        self._color_mapper = val

    @cached_property
    def _get_value_mapper(self):
        return self._get_color_mapper()

    def _set_value_mapper(self, val):
        self._set_color_mapper(val)

    def _get_index(self):
        if self.plot and hasattr(self.plot, "color_data"):
            return self.plot.color_data
        elif self.plot and isinstance(self.plot, BaseXYPlot):
            return self.plot.index
        elif self._index:
            return self._index
        else:
            return None

    def _set_index(self, val):
        self._index = val

# EOF
<|endoftext|>


<commit_before>""" Defines the DataView class, and associated property traits and property
functions.
"""
from numpy import array, transpose

from enthought.traits.api import Enum, Instance, Property

from axis import PlotAxis
from base_1d_mapper import Base1DMapper
from base_2d_plot import Base2DPlot
from data_range_2d import DataRange2D
from grid import PlotGrid
from linear_mapper import LinearMapper
from log_mapper import LogMapper
from plot_containers import OverlayPlotContainer

#-----------------------------------------------------------------------------
# Define new traits to condense the definition of some convenience
# properties in the Plot class
#-----------------------------------------------------------------------------

def get_mapper(self, attr_name):
    """ Getter function used by OrientedMapperProperty.
    """
    if (attr_name,self.orientation) in [("x_mapper","h"), ("y_mapper","v")]:
        return self.index_mapper
    else:
        return self.value_mapper

def set_mapper(self, attr_name, new):
    """ Setter function used by OrientedMapperProperty.
    """
    if (attr_name,self.orientation) in [("x_mapper","h"), ("y_mapper","v")]:
        self.index_mapper = new
    else:
        self.value_mapper = new

# Property that represents a mapper for an orientation.
OrientedMapperProperty = Property(get_mapper, set_mapper)

def get_axis(self, attr_name):
    """ Getter function used by AxisProperty.
    """
    if (attr_name,self.orientation) in [("index_axis","h"), ("value_axis","v")]:
        return self.x_axis
    else:
        return self.y_axis

def set_axis(self, attr_name, new):
    """ Setter function used by AxisProperty.
    """
    if (attr_name,self.orientation) in [("index_axis","h"), ("value_axis","v")]:
        self.x_axis = new
    else:
        self.y_axis = new

# Property that represents an axis.
AxisProperty = Property(get_axis, set_axis)

def get_grid(self, attr_name):
    """ Getter function used by GridProperty.
    """
    if (attr_name,self.orientation) in [("index_grid","v"), ("value_grid","h")]:
        return self.y_grid
    else:
        return self.x_grid

def set_grid(self, attr_name, new):
    """ Setter function used by GridProperty.
    """
    if (attr_name,self.orientation) in [("index_grid","v"), ("value_grid","h")]:
        self.y_grid = new
    else:
        self.y_grid = new

# Property that represents a grid for a particular orientation.
GridProperty = Property(get_grid, set_grid)

class DataView(OverlayPlotContainer):
    """ Represents a mapping from 2-D data space into 2-D screen space.

    It can house renderers and other plot components, and otherwise behaves
    just like a normal PlotContainer.
    """

    # The orientation of the index axis.
    orientation = Enum("h", "v")

    # The default location of the origin  for new plots
    default_origin = Enum("bottom left", "top left",
                          "bottom right", "top right")

    # The origin reported to axes, etc
    origin = Property(depends_on='default_origin')

    # The mapper to use for the index data.
    index_mapper = Instance(Base1DMapper)

    # The mapper to use for value data.
    value_mapper = Instance(Base1DMapper)

    # For x-y plots, the scale of the index axis.
    index_scale = Enum("linear", "log")

    # For x-y plots, the scale of the index axis.
    value_scale = Enum("linear", "log")

    # The range used for the index data.
    index_range = Property

    # The range used for the value data.
    value_range = Property

    # The 2-D data range whose x- and y-ranges are exposed as the
    # **index_range** and **value_range** property traits. This allows
    # supporting both XY plots and 2-D (image) plots.
    range2d = Instance(DataRange2D)

    # Convenience property that offers access to whatever mapper corresponds
    # to the X-axis.
    x_mapper = OrientedMapperProperty

    # Convenience property that offers access to whatever mapper corresponds
    # to the Y-axis
    y_mapper = OrientedMapperProperty

    #------------------------------------------------------------------------
    # Axis and Grids
    #------------------------------------------------------------------------

    # The horizontal axis.  Its position relative to the plot
    # area can be "top", "bottom", or "float".  The default position for a new
    # x-axis is "bottom".
    x_axis = Instance(PlotAxis)

    # The vertical axis.  Its position relative to the plot
    # area can be "left", "right", or "float".  The default position for a new
    # y-axis is "left".
    y_axis = Instance(PlotAxis)

    # The grid that intersects the x-axis, i.e., a set of vertical lines.
    x_grid = Instance(PlotGrid)

    # The grid that intersects the y-axis, i.e., a set of horizontal lines.
    y_grid = Instance(PlotGrid)

    # Convenience property for accessing the index axis, which can be X or Y,
    # depending on **orientation**.
    index_axis = AxisProperty
    # Convenience property for accessing the value axis, which can be Y or X,
    # depending on **orientation**.
    value_axis = AxisProperty
    # Convenience property for accessing the index grid, which can be horizontal
    # or vertical, depending on **orientation**.
    index_grid = GridProperty
    # Convenience property for accessing the value grid, which can be vertical
    # or horizontal, depending on **orientation**.
    value_grid = GridProperty

    #------------------------------------------------------------------------
    # Appearance
    #------------------------------------------------------------------------

    # Background color (overrides Enable Component)
    bgcolor = "white"

    # Padding defaults.
    padding_top = 50
    padding_bottom = 50
    padding_left = 50
    padding_right = 50

    border_visible = True

    #------------------------------------------------------------------------
    # Public methods
    #------------------------------------------------------------------------

    def __init__(self, **kwtraits):
        super(DataView, self).__init__(**kwtraits)
        self._init_components()

        # If we are not resizable, we will not get a bounds update upon layout,
        # so we have to manually update our mappers
        if self.resizable == "":
            self._update_mappers()
        return

    def map_screen(self, data_array):
        """ Maps an array of data points to screen space and returns an array
        of screen space points.
        """
        # data_array is Nx2 array
        if len(data_array) == 0:
            return []
        x_ary, y_ary = transpose(data_array)
        sx = self.index_mapper.map_screen(x_ary)
        sy = self.value_mapper.map_screen(y_ary)
        if self.orientation == "h":
            return transpose(array((sx,sy)))
        else:
            return transpose(array((sy,sx)))

    def map_data(self, screen_pt):
        """ Maps a screen space point into the 2D data space of this plot.
        (Note that this differs from the BaseXYPlot implementation, which by
        default only maps into the 1D index space.)
        """
        # At some point it would be good to change the DataView to use
        # the GridMapper, and then use its map_data() method.
        x, y = screen_pt
        return array((self.index_mapper.map_data(x),
                      self.value_mapper.map_data(y)))

    #------------------------------------------------------------------------
    # Private methods
    #------------------------------------------------------------------------

    def _init_components(self):
        # Since this is called after the HasTraits constructor, we have to make
        # sure that we don't blow away any components that the caller may have
        # already set.

        if not self.range2d:
            self.range2d = DataRange2D()

        if not self.index_mapper:
            if self.index_scale == "linear":
                imap = LinearMapper(range=self.range2d.x_range)
            else:
                imap = LogMapper(range=self.range2d.x_range)
            self.index_mapper = imap

        if not self.value_mapper:
            if self.value_scale == "linear":
                vmap = LinearMapper(range=self.range2d.y_range)
            else:
                vmap = LogMapper(range=self.range2d.y_range)
            self.value_mapper = vmap

        if not self.x_grid:
            self.x_grid = PlotGrid(mapper=self.x_mapper, orientation="vertical",
                                  line_color="lightgray", line_style="dot",
                                  component=self)
        if not self.y_grid:
            self.y_grid = PlotGrid(mapper=self.y_mapper, orientation="horizontal",
                                  line_color="lightgray", line_style="dot",
                                  component=self)

        if not self.x_axis:
            self.x_axis = PlotAxis(mapper=self.x_mapper, orientation="bottom",
                                  component=self)

        if not self.y_axis:
            self.y_axis = PlotAxis(mapper=self.y_mapper, orientation="left",
                                  component=self)

    #-------------------------------------------------------------------------
    # Event handlers
    #-------------------------------------------------------------------------

    def _update_mappers(self):

        x = self.x
        x2 = self.x2
        y = self.y
        y2 = self.y2

        if self.x_mapper is not None:
            if "left" in self.origin:
                self.x_mapper.low_pos = x
                self.x_mapper.high_pos = x2
            else:
                self.x_mapper.low_pos = x2
                self.x_mapper.high_pos = x

        if self.y_mapper is not None:
            if "bottom" in self.origin:
                self.y_mapper.low_pos = y
                self.y_mapper.high_pos = y2
            else:
                self.y_mapper.low_pos = y2
                self.y_mapper.high_pos = y

        self.invalidate_draw()
        return

    def _bounds_changed(self, old, new):
        super(DataView, self)._bounds_changed(old, new)
        self._update_mappers()

    def _bounds_items_changed(self, event):
        super(DataView, self)._bounds_items_changed(event)
        self._update_mappers()

    def _position_changed(self, old, new):
        super(DataView, self)._position_changed(old, new)
        self._update_mappers()

    def _position_items_changed(self, event):
        super(DataView, self)._position_items_changed(event)
        self._update_mappers()

    def _origin_changed(self):
        self._update_mappers()

    def _orientation_changed(self):
        # Change our grid and axis mappers so that they correspond to the
        # new mapper configuration.  Using the self.x_mapper and self.y_mapper
        # properties will grab the correct mappers corresponding to our new
        # orientation.
        if self.x_grid is not None:
            self.x_grid.mapper = self.x_mapper
        if self.y_grid is not None:
            self.y_grid.mapper = self.y_mapper
        if self.x_axis is not None:
            self.x_axis.mapper = self.x_mapper
        if self.y_axis is not None:
            self.y_axis.mapper = self.y_mapper
        self._update_mappers()
        for renderer in self.components:
            if hasattr(renderer, "orientation"):
                renderer.orientation = self.orientation
        return

    def _index_mapper_changed(self, old, new):
        if new is not None:
            if new.range is not None:
                # Add the range's datasources to our range
                for source in new.range.sources:
                    self.index_range.add(source)
            new.range = self.index_range
        if self.index_axis:
            self.index_axis.mapper = new
        if self.index_grid:
            self.index_grid.mapper = new

    def _value_mapper_changed(self, old, new):
        if new is not None:
            if new.range is not None:
                # Add the range's datasources to our range
                for source in new.range.sources:
                    self.value_range.add(source)
            new.range = self.value_range
        if self.value_axis:
            self.value_axis.mapper = new
        if self.value_grid:
            self.value_grid.mapper = new

    def _bgcolor_changed(self):
        self.invalidate_draw()

    def _x_grid_changed(self, old, new):
        self._underlay_change_helper(old, new)

    def _y_grid_changed(self, old, new):
        self._underlay_change_helper(old, new)

    def _x_axis_changed(self, old, new):
        self._underlay_change_helper(old, new)

    def _y_axis_changed(self, old, new):
        self._underlay_change_helper(old, new)

    def _underlay_change_helper(self, old, new):
        if old in self.underlays:
            self.underlays.remove(old)
        if new is not None:
            self.underlays.append(new)

    def _overlay_change_helper(self, old, new):
        if old in self.overlays:
            self.overlays.remove(old)
        if new is not None:
            self.overlays.append(new)

    def _range2d_changed(self, old, new):
        if new is not None:
            if self.index_mapper is not None:
                self.index_mapper.range = new.x_range
            if self.value_mapper is not None:
                self.value_mapper.range = new.y_range
        else:
            self.index_mapper.range = None
            self.value_mapper.range = None
        if old is not None:
            for datasource in old.sources[:]:
                old.remove(datasource)
                if new is not None:
                    new.add(datasource)
        for renderer in self.components:
            if hasattr(renderer, 'range2d') or isinstance(renderer, Base2DPlot):
                setattr(renderer, 'range2d', new)
            else:
                if hasattr(renderer, 'index_range'):
                    setattr(renderer, 'index_range', self.index_range)
                if hasattr(renderer, 'value_range'):
                    setattr(renderer, 'value_range', self.value_range)
        return

    #------------------------------------------------------------------------
    # Property getters and setters
    #------------------------------------------------------------------------

    def _get_index_range(self):
        return self.range2d.x_range

    def _set_index_range(self, newrange):
        self._handle_range_changed("index", self.range2d.x_range, newrange)
        self.range2d.x_range = newrange

    def _get_value_range(self):
        return self.range2d.y_range

    def _set_value_range(self, newrange):
        self._handle_range_changed("value", self.range2d.y_range, newrange)
        self.range2d.y_range = newrange

    def _handle_range_changed(self, name, old, new):
        mapper = getattr(self, name+"_mapper")
        if mapper.range == old:
            mapper.range = new
        if old is not None:
            for datasource in old.sources[:]:
                old.remove(datasource)
                if new is not None:
                    new.add(datasource)
        range_name = name + "_range"
        for renderer in self.components:
            if hasattr(renderer, range_name):
                setattr(renderer, range_name, new)

    def _get_origin(self):
        # FIXME:
        return self.default_origin

<commit_msg>Adding _range2d_default  method: fixes the traceback that occurs when calling copy_traits on a DataView object.<commit_after>""" Defines the DataView class, and associated property traits and property
functions.
"""
from numpy import array, transpose

from enthought.traits.api import Enum, Instance, Property

from axis import PlotAxis
from base_1d_mapper import Base1DMapper
from base_2d_plot import Base2DPlot
from data_range_2d import DataRange2D
from grid import PlotGrid
from linear_mapper import LinearMapper
from log_mapper import LogMapper
from plot_containers import OverlayPlotContainer

#-----------------------------------------------------------------------------
# Define new traits to condense the definition of some convenience
# properties in the Plot class
#-----------------------------------------------------------------------------

def get_mapper(self, attr_name):
    """ Getter function used by OrientedMapperProperty.
    """
    if (attr_name,self.orientation) in [("x_mapper","h"), ("y_mapper","v")]:
        return self.index_mapper
    else:
        return self.value_mapper

def set_mapper(self, attr_name, new):
    """ Setter function used by OrientedMapperProperty.
    """
    if (attr_name,self.orientation) in [("x_mapper","h"), ("y_mapper","v")]:
        self.index_mapper = new
    else:
        self.value_mapper = new

# Property that represents a mapper for an orientation.
OrientedMapperProperty = Property(get_mapper, set_mapper)

def get_axis(self, attr_name):
    """ Getter function used by AxisProperty.
    """
    if (attr_name,self.orientation) in [("index_axis","h"), ("value_axis","v")]:
        return self.x_axis
    else:
        return self.y_axis

def set_axis(self, attr_name, new):
    """ Setter function used by AxisProperty.
    """
    if (attr_name,self.orientation) in [("index_axis","h"), ("value_axis","v")]:
        self.x_axis = new
    else:
        self.y_axis = new

# Property that represents an axis.
AxisProperty = Property(get_axis, set_axis)

def get_grid(self, attr_name):
    """ Getter function used by GridProperty.
    """
    if (attr_name,self.orientation) in [("index_grid","v"), ("value_grid","h")]:
        return self.y_grid
    else:
        return self.x_grid

def set_grid(self, attr_name, new):
    """ Setter function used by GridProperty.
    """
    if (attr_name,self.orientation) in [("index_grid","v"), ("value_grid","h")]:
        self.y_grid = new
    else:
        self.y_grid = new

# Property that represents a grid for a particular orientation.
GridProperty = Property(get_grid, set_grid)

class DataView(OverlayPlotContainer):
    """ Represents a mapping from 2-D data space into 2-D screen space.

    It can house renderers and other plot components, and otherwise behaves
    just like a normal PlotContainer.
    """

    # The orientation of the index axis.
    orientation = Enum("h", "v")

    # The default location of the origin  for new plots
    default_origin = Enum("bottom left", "top left",
                          "bottom right", "top right")

    # The origin reported to axes, etc
    origin = Property(depends_on='default_origin')

    # The mapper to use for the index data.
    index_mapper = Instance(Base1DMapper)

    # The mapper to use for value data.
    value_mapper = Instance(Base1DMapper)

    # For x-y plots, the scale of the index axis.
    index_scale = Enum("linear", "log")

    # For x-y plots, the scale of the index axis.
    value_scale = Enum("linear", "log")

    # The range used for the index data.
    index_range = Property

    # The range used for the value data.
    value_range = Property

    # The 2-D data range whose x- and y-ranges are exposed as the
    # **index_range** and **value_range** property traits. This allows
    # supporting both XY plots and 2-D (image) plots.
    range2d = Instance(DataRange2D)

    # Convenience property that offers access to whatever mapper corresponds
    # to the X-axis.
    x_mapper = OrientedMapperProperty

    # Convenience property that offers access to whatever mapper corresponds
    # to the Y-axis
    y_mapper = OrientedMapperProperty

    #------------------------------------------------------------------------
    # Axis and Grids
    #------------------------------------------------------------------------

    # The horizontal axis.  Its position relative to the plot
    # area can be "top", "bottom", or "float".  The default position for a new
    # x-axis is "bottom".
    x_axis = Instance(PlotAxis)

    # The vertical axis.  Its position relative to the plot
    # area can be "left", "right", or "float".  The default position for a new
    # y-axis is "left".
    y_axis = Instance(PlotAxis)

    # The grid that intersects the x-axis, i.e., a set of vertical lines.
    x_grid = Instance(PlotGrid)

    # The grid that intersects the y-axis, i.e., a set of horizontal lines.
    y_grid = Instance(PlotGrid)

    # Convenience property for accessing the index axis, which can be X or Y,
    # depending on **orientation**.
    index_axis = AxisProperty
    # Convenience property for accessing the value axis, which can be Y or X,
    # depending on **orientation**.
    value_axis = AxisProperty
    # Convenience property for accessing the index grid, which can be horizontal
    # or vertical, depending on **orientation**.
    index_grid = GridProperty
    # Convenience property for accessing the value grid, which can be vertical
    # or horizontal, depending on **orientation**.
    value_grid = GridProperty

    #------------------------------------------------------------------------
    # Appearance
    #------------------------------------------------------------------------

    # Background color (overrides Enable Component)
    bgcolor = "white"

    # Padding defaults.
    padding_top = 50
    padding_bottom = 50
    padding_left = 50
    padding_right = 50

    border_visible = True

    #------------------------------------------------------------------------
    # Public methods
    #------------------------------------------------------------------------

    def __init__(self, **kwtraits):
        super(DataView, self).__init__(**kwtraits)
        self._init_components()

        # If we are not resizable, we will not get a bounds update upon layout,
        # so we have to manually update our mappers
        if self.resizable == "":
            self._update_mappers()
        return

    def map_screen(self, data_array):
        """ Maps an array of data points to screen space and returns an array
        of screen space points.
        """
        # data_array is Nx2 array
        if len(data_array) == 0:
            return []
        x_ary, y_ary = transpose(data_array)
        sx = self.index_mapper.map_screen(x_ary)
        sy = self.value_mapper.map_screen(y_ary)
        if self.orientation == "h":
            return transpose(array((sx,sy)))
        else:
            return transpose(array((sy,sx)))

    def map_data(self, screen_pt):
        """ Maps a screen space point into the 2D data space of this plot.
        (Note that this differs from the BaseXYPlot implementation, which by
        default only maps into the 1D index space.)
        """
        # At some point it would be good to change the DataView to use
        # the GridMapper, and then use its map_data() method.
        x, y = screen_pt
        return array((self.index_mapper.map_data(x),
                      self.value_mapper.map_data(y)))

    #------------------------------------------------------------------------
    # Private methods
    #------------------------------------------------------------------------

    def _init_components(self):
        # Since this is called after the HasTraits constructor, we have to make
        # sure that we don't blow away any components that the caller may have
        # already set.

        if not self.range2d:
            self.range2d = DataRange2D()

        if not self.index_mapper:
            if self.index_scale == "linear":
                imap = LinearMapper(range=self.range2d.x_range)
            else:
                imap = LogMapper(range=self.range2d.x_range)
            self.index_mapper = imap

        if not self.value_mapper:
            if self.value_scale == "linear":
                vmap = LinearMapper(range=self.range2d.y_range)
            else:
                vmap = LogMapper(range=self.range2d.y_range)
            self.value_mapper = vmap

        if not self.x_grid:
            self.x_grid = PlotGrid(mapper=self.x_mapper, orientation="vertical",
                                  line_color="lightgray", line_style="dot",
                                  component=self)
        if not self.y_grid:
            self.y_grid = PlotGrid(mapper=self.y_mapper, orientation="horizontal",
                                  line_color="lightgray", line_style="dot",
                                  component=self)

        if not self.x_axis:
            self.x_axis = PlotAxis(mapper=self.x_mapper, orientation="bottom",
                                  component=self)

        if not self.y_axis:
            self.y_axis = PlotAxis(mapper=self.y_mapper, orientation="left",
                                  component=self)

    #-------------------------------------------------------------------------
    # Event handlers
    #-------------------------------------------------------------------------

    def _update_mappers(self):

        x = self.x
        x2 = self.x2
        y = self.y
        y2 = self.y2

        if self.x_mapper is not None:
            if "left" in self.origin:
                self.x_mapper.low_pos = x
                self.x_mapper.high_pos = x2
            else:
                self.x_mapper.low_pos = x2
                self.x_mapper.high_pos = x

        if self.y_mapper is not None:
            if "bottom" in self.origin:
                self.y_mapper.low_pos = y
                self.y_mapper.high_pos = y2
            else:
                self.y_mapper.low_pos = y2
                self.y_mapper.high_pos = y

        self.invalidate_draw()
        return

    def _bounds_changed(self, old, new):
        super(DataView, self)._bounds_changed(old, new)
        self._update_mappers()

    def _bounds_items_changed(self, event):
        super(DataView, self)._bounds_items_changed(event)
        self._update_mappers()

    def _position_changed(self, old, new):
        super(DataView, self)._position_changed(old, new)
        self._update_mappers()

    def _position_items_changed(self, event):
        super(DataView, self)._position_items_changed(event)
        self._update_mappers()

    def _origin_changed(self):
        self._update_mappers()

    def _orientation_changed(self):
        # Change our grid and axis mappers so that they correspond to the
        # new mapper configuration.  Using the self.x_mapper and self.y_mapper
        # properties will grab the correct mappers corresponding to our new
        # orientation.
        if self.x_grid is not None:
            self.x_grid.mapper = self.x_mapper
        if self.y_grid is not None:
            self.y_grid.mapper = self.y_mapper
        if self.x_axis is not None:
            self.x_axis.mapper = self.x_mapper
        if self.y_axis is not None:
            self.y_axis.mapper = self.y_mapper
        self._update_mappers()
        for renderer in self.components:
            if hasattr(renderer, "orientation"):
                renderer.orientation = self.orientation
        return

    def _index_mapper_changed(self, old, new):
        if new is not None:
            if new.range is not None:
                # Add the range's datasources to our range
                for source in new.range.sources:
                    self.index_range.add(source)
            new.range = self.index_range
        if self.index_axis:
            self.index_axis.mapper = new
        if self.index_grid:
            self.index_grid.mapper = new

    def _value_mapper_changed(self, old, new):
        if new is not None:
            if new.range is not None:
                # Add the range's datasources to our range
                for source in new.range.sources:
                    self.value_range.add(source)
            new.range = self.value_range
        if self.value_axis:
            self.value_axis.mapper = new
        if self.value_grid:
            self.value_grid.mapper = new

    def _bgcolor_changed(self):
        self.invalidate_draw()

    def _x_grid_changed(self, old, new):
        self._underlay_change_helper(old, new)

    def _y_grid_changed(self, old, new):
        self._underlay_change_helper(old, new)

    def _x_axis_changed(self, old, new):
        self._underlay_change_helper(old, new)

    def _y_axis_changed(self, old, new):
        self._underlay_change_helper(old, new)

    def _underlay_change_helper(self, old, new):
        if old in self.underlays:
            self.underlays.remove(old)
        if new is not None:
            self.underlays.append(new)

    def _overlay_change_helper(self, old, new):
        if old in self.overlays:
            self.overlays.remove(old)
        if new is not None:
            self.overlays.append(new)

    def _range2d_changed(self, old, new):
        if new is not None:
            if self.index_mapper is not None:
                self.index_mapper.range = new.x_range
            if self.value_mapper is not None:
                self.value_mapper.range = new.y_range
        else:
            self.index_mapper.range = None
            self.value_mapper.range = None
        if old is not None:
            for datasource in old.sources[:]:
                old.remove(datasource)
                if new is not None:
                    new.add(datasource)
        for renderer in self.components:
            if hasattr(renderer, 'range2d') or isinstance(renderer, Base2DPlot):
                setattr(renderer, 'range2d', new)
            else:
                if hasattr(renderer, 'index_range'):
                    setattr(renderer, 'index_range', self.index_range)
                if hasattr(renderer, 'value_range'):
                    setattr(renderer, 'value_range', self.value_range)
        return

    def _range2d_default(self):
        """ Default trait initializer for the range2d trait """
        return DataRange2D()

    #------------------------------------------------------------------------
    # Property getters and setters
    #------------------------------------------------------------------------

    def _get_index_range(self):
        return self.range2d.x_range

    def _set_index_range(self, newrange):
        self._handle_range_changed("index", self.range2d.x_range, newrange)
        self.range2d.x_range = newrange

    def _get_value_range(self):
        return self.range2d.y_range

    def _set_value_range(self, newrange):
        self._handle_range_changed("value", self.range2d.y_range, newrange)
        self.range2d.y_range = newrange

    def _handle_range_changed(self, name, old, new):
        mapper = getattr(self, name+"_mapper")
        if mapper.range == old:
            mapper.range = new
        if old is not None:
            for datasource in old.sources[:]:
                old.remove(datasource)
                if new is not None:
                    new.add(datasource)
        range_name = name + "_range"
        for renderer in self.components:
            if hasattr(renderer, range_name):
                setattr(renderer, range_name, new)

    def _get_origin(self):
        # FIXME:
        return self.default_origin

<|endoftext|>