<commit_before>#!/usr/bin/env python
#coding: utf-8

import os
import sys
import argparse

from util         import core
from util         import adjust
from util         import objects
from util.git     import *
from util.color   import *
from util.objects import Todo

from subprocess   import Popen, PIPE
from StringIO     import StringIO
from datetime     import datetime
from sys          import exit        as kill
from gettext      import gettext     as _

parser = argparse.ArgumentParser(description="You can manage to \
                        What you want to do on your git repository.")

subparsers = parser.add_subparsers(
        title="git-todo commands",
        dest="commands")

cmd_init = subparsers.add_parser(
        "init",
        help=_("Program prepare for maneging your todo."))

cmd_add = subparsers.add_parser(
        "add",
        help=_("You can add new task. \
                Please write task content to argument."))
cmd_add.add_argument(
        "content",
        action="store",
        help=_("your task content string. If you want to write \
                long string what contains spaces, please put \
                double-quotation(\") to left and right side of long string."))

cmd_ls = subparsers.add_parser(
        "ls",
        help=_("You can show all todo with any filter."))
cmd_ls.add_argument(
        "--filter",
        action="store",
        dest="filter:content",
        help=_("This is todo filter.\
                You can make the filter by string concatenate \
                the filter name and filter contents by colon. \
                (ex. date:2012/12/31, status:open, etc.)"))
cmd_ls.add_argument(
        "--sortby",
        action="store",
        dest="element:order",
        help=_("This option sort todo by sort element.\
                You can make the sort element by string concatenate \
                the sorter element name and sort order by colon. \
                (ex. date:ascending, index:Descending, etc.)"))

cmd_close = subparsers.add_parser(
        "close",
        help=_("You can close a task.\
                Please write the task index to argument. \
                If you close a task, this program put a tag \
                what name is 'Todo#(todo-index)_close' on git. \
                (ex. Todo#3_close, etc.) \
                And this program changes status to CLOSED."))
cmd_close.add_argument(
        "index",
        action="store",
        type=int,
        help=_("The task index. this is INT type only."))

cmd_reopen = subparsers.add_parser(
        "reopen",
        help=_("If you want to open a task again when you close a task by \
                mistake, You can use this option. \
                This option change task status to OPEN, and this option \
                don't change commit hash when a task opened. And, \
                This option delete git tag that put when you closed a task. \
                Please write the task index to argument."))
cmd_reopen.add_argument(
        "index",
        action="store",
        type=int,
        help=_("The task index. this is INT type only."))

cmd_print = subparsers.add_parser(
        "print",
        help=_("This program create the TODO file to write \
                                        only OPEN status tasks."))

class ArgumentNamespace(object):
    def __setattr__(self, key, value):

        if value != None:

            if key.find(":") != -1 and value.find(":") == -1:
                parser.error(_("'%s' does not follow the foramt." % value))

            if key == "filter:content":
                filter_name, filter_content = value.split(":")
                self.__dict__["filter-%s"%filter_name] = filter_content

            elif key == "element:order":
                sorter_name, sort_order = value.split(":")
                self.__dict__["sortby-%s"%sorter_name] = sort_order

            else:
                self.__dict__[key] = value

    def __repr__(self):
        return "ArgumentNamespace(%s)" % ", ".join([k+"='%s'"%v for k,v in vars(self).iteritems()])

if __name__ == "__main__":
    if len(sys.argv) == 1:
        parser.parse_args(["-h"])

    args = parser.parse_args(namespace=ArgumentNamespace())
    print args

<commit_msg>Created OriginalHelpFormatter class, and append attributes to argparse.HelpFormatter<commit_after>#!/usr/bin/env python
#coding: utf-8

import os
import sys
import argparse

from util         import core
from util         import adjust
from util         import objects
from util.git     import *
from util.color   import *
from util.objects import Todo

from subprocess   import Popen, PIPE
from StringIO     import StringIO
from datetime     import datetime
from sys          import exit        as kill
from gettext      import gettext     as _

class OriginalHelpFormatter(argparse.HelpFormatter):
    def _format_action(self, action):
        # determine the required width and the entry label
        help_position = min(self._action_max_length + 2,
                            self._max_help_position)
        help_width = self._width - help_position
        action_width = help_position - self._current_indent - 2
        action_header = self._format_action_invocation(action)

        # ho nelp; start on same line and add a final newline
        if not action.help:
            tup = self._current_indent, '', action_header
            action_header = '%*s%s\n' % tup

        # short action name; start on the same line and pad two spaces
        elif len(action_header) <= action_width:
            tup = self._current_indent, '', action_width, action_header
            action_header = '%*s%-*s  ' % tup
            indent_first = 0

        # long action name; start on the next line
        else:
            tup = self._current_indent, '', action_header
            action_header = '%*s%s\n' % tup
            indent_first = help_position

        # collect the pieces of the action help
        parts = [action_header]

        # if there was help for the action, add lines of help text
        if action.help:
            help_text = self._expand_help(action)
            help_lines = self._split_lines(help_text, help_width)
            parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))
            for line in help_lines[1:]:
                parts.append('%*s%s\n' % (help_position, '', line))

        # or add a newline if the description doesn't end with one
        elif not action_header.endswith('\n'):
            parts.append('\n')

        # if there are any sub-actions, add their help as well
        for subaction in self._iter_indented_subactions(action):
            parts.append(self._format_action(subaction))

            # Original Code
            parts.append("\n")

        # return a single string
        return self._join_parts(parts)

help_formatter = (lambda prog:
                    OriginalHelpFormatter(
                        prog,
                        indent_increment=4,
                        max_help_position=27,
                        width=int(core.terminal_width())
                    )
                 )

parser = argparse.ArgumentParser(
        prog="git todo",
        formatter_class=help_formatter,
        description="You can manage to What you want to do on your git repository.")

subparsers = parser.add_subparsers(
        title="git todo commands",
        dest="commands")

cmd_init = subparsers.add_parser(
        "init",
        help=_("Program prepare for maneging your todo."))

cmd_add = subparsers.add_parser(
        "add",
        help=_("You can add new task. \
                Please write task content to argument."))
cmd_add.add_argument(
        "content",
        action="store",
        help=_("your task content string. If you want to write \
                long string what contains spaces, please put \
                double-quotation(\") to left and right side of long string."))

cmd_ls = subparsers.add_parser(
        "ls",
        help=_("You can show all todo with any filter."))
cmd_ls.add_argument(
        "--filter",
        action="store",
        dest="filter:content",
        help=_("This is todo filter.\
                You can make the filter by string concatenate \
                the filter name and filter contents by colon. \
                (ex. date:2012/12/31, status:open, etc.)"))
cmd_ls.add_argument(
        "--sortby",
        action="store",
        dest="element:order",
        help=_("This option sort todo by sort element.\
                You can make the sort element by string concatenate \
                the sorter element name and sort order by colon. \
                (ex. date:ascending, index:Descending, etc.)"))

cmd_close = subparsers.add_parser(
        "close",
        help=_("You can close a task.\
                Please write the task index to argument. \
                If you close a task, this program put a tag \
                what name is 'Todo#(todo-index)_close' on git. \
                (ex. Todo#3_close, etc.) \
                And this program changes status to CLOSED."))
cmd_close.add_argument(
        "index",
        action="store",
        type=int,
        help=_("The task index. this is INT type only."))

cmd_reopen = subparsers.add_parser(
        "reopen",
        help=_("If you want to open a task again when you close a task by \
                mistake, You can use this option. \
                This option change task status to OPEN, and this option \
                don't change commit hash when a task opened. And, \
                This option delete git tag that put when you closed a task. \
                Please write the task index to argument."))
cmd_reopen.add_argument(
        "index",
        action="store",
        type=int,
        help=_("The task index. this is INT type only."))

cmd_print = subparsers.add_parser(
        "print",
        help=_("This program create the TODO file to write \
                                        only OPEN status tasks."))

class ArgumentNamespace(object):
    def __setattr__(self, key, value):

        if value != None:

            if key.find(":") != -1 and value.find(":") == -1:
                parser.error(_("'%s' does not follow the foramt." % value))

            if key == "filter:content":
                filter_name, filter_content = value.split(":")
                self.__dict__["filter-%s"%filter_name] = filter_content

            elif key == "element:order":
                sorter_name, sort_order = value.split(":")
                self.__dict__["sortby-%s"%sorter_name] = sort_order

            else:
                self.__dict__[key] = value

    def __repr__(self):
        return "ArgumentNamespace(%s)" % ", ".join([k+"='%s'"%v for k,v in vars(self).iteritems()])

if __name__ == "__main__":
    if len(sys.argv) == 1:
        parser.parse_args(["-h"])

    args = parser.parse_args(namespace=ArgumentNamespace())
    print args

<|endoftext|>


<commit_before>from collections import OrderedDict
import os
import random

from . import corpusdir

from .article_class import Article
from .plos_corpus import get_all_solr_dois
from .transformations import filename_to_doi

class Corpus():
    """A collection of PLOS articles.
    """

    def __init__(self, directory=corpusdir, plos_network=False, extension='.xml'):
        """Creation of an article corpus class."""
        self.directory = directory
        self.plos_network = plos_network
        self.extension = extension
        self.reset_memoized_attrs()

    def reset_memoized_attrs(self):
        """Reset attributes to None when instantiating a new corpus object.

        For corpus attributes that are memoized and specific to that particular corpus,
        reset them when creating a new corpus object.
        """
        self._file_doi = None

    @property
    def directory(self):
        """
        :returns: directory of corpus
        :rtype: {str}
        """
        return self._directory

    @directory.setter
    def directory(self, d):
        """
        Reset memoized info when changing the path to the corpus.
        """
        self.reset_memoized_attrs()
        self._directory = d

    def __repr__(self):
        """Value of a corpus object when you call it directly on the command line.

        Shows the directory location of the corpus
        :returns: directory
        :rtype: {str}
        """
        out = "Corpus location: {0}\nNumber of files: {1}".format(self.directory, len(self.files))
        return out

    @property
    def file_doi(self):
        """An ordered dict that maps every corpus file to its accompanying DOI.
        Used to generate both DOI and file lists for the corpus; both also ordered.
        """
        if self._file_doi is None:
            self._file_doi = OrderedDict((file_, filename_to_doi(file_)) for file_ in os.listdir(self.directory)
                                         if file_.endswith(self.extension) and 'DS_Store' not in file_)
        else:
            pass
        return self._file_doi

    @property
    def files(self):
        """List of article XML files in the corpus directory."""

        if self._files is None:
            if os.path.isdir(self.directory):
                file_list = [file_ for file_ in os.listdir(self.directory) if file_.endswith('.xml') and
                             'DS_Store' not in file_]
            else:
                # if directory doesn't exist, return empty list
                file_list = []
            self._files = file_list
        else:
            pass

        return self._files

    @property
    def dois(self):
        """List of DOIs of the articles in the corpus directory."""

        if self._dois is None:
            doi_list = [filename_to_doi(article) for article in self.files]
            return doi_list
        else:
            return self._dois

    def random_dois(self, count):
        """
        Gets a list of random DOIs. Construct from local files in
        corpusdir, otherwise tries Solr DOI list as backup.
        :param directory: directory of articles for class object
        :param count: specify how many DOIs are to be returned
        :return: a list of random DOIs for analysis
        """
        try:
            doi_list = self.dois
            sample_doi_list = random.sample(doi_list, count)
        except OSError:
            doi_list = get_all_solr_dois()
            sample_doi_list = random.sample(doi_list, count)

        return sample_doi_list

<commit_msg>rm call to plos_corpus<commit_after>from collections import OrderedDict
import os
import random

from . import corpusdir

from .article_class import Article
from .transformations import filename_to_doi, doi_to_path

class Corpus():
    """A collection of PLOS articles.
    """

    def __init__(self, directory=corpusdir, plos_network=False, extension='.xml'):
        """Creation of an article corpus class."""
        self.directory = directory
        self.plos_network = plos_network
        self.extension = extension
        self.reset_memoized_attrs()

    def reset_memoized_attrs(self):
        """Reset attributes to None when instantiating a new corpus object.

        For corpus attributes that are memoized and specific to that particular corpus,
        reset them when creating a new corpus object.
        """
        self._file_doi = None

    @property
    def directory(self):
        """
        :returns: directory of corpus
        :rtype: {str}
        """
        return self._directory

    @directory.setter
    def directory(self, d):
        """
        Reset memoized info when changing the path to the corpus.
        """
        self.reset_memoized_attrs()
        self._directory = d

    def __repr__(self):
        """Value of a corpus object when you call it directly on the command line.

        Shows the directory location of the corpus
        :returns: directory
        :rtype: {str}
        """
        out = "Corpus location: {0}\nNumber of files: {1}".format(self.directory, len(self.files))
        return out

    @property
    def file_doi(self):
        """An ordered dict that maps every corpus file to its accompanying DOI.
        Used to generate both DOI and file lists for the corpus; both also ordered.
        """
        if self._file_doi is None:
            self._file_doi = OrderedDict((file_, filename_to_doi(file_)) for file_ in os.listdir(self.directory)
                                         if file_.endswith(self.extension) and 'DS_Store' not in file_)
        else:
            pass
        return self._file_doi

    @property
    def files(self):
        """List of article XML files in the corpus directory."""

        if self._files is None:
            if os.path.isdir(self.directory):
                file_list = [file_ for file_ in os.listdir(self.directory) if file_.endswith('.xml') and
                             'DS_Store' not in file_]
            else:
                # if directory doesn't exist, return empty list
                file_list = []
            self._files = file_list
        else:
            pass

        return self._files

    @property
    def dois(self):
        """List of DOIs of the articles in the corpus directory."""

        if self._dois is None:
            doi_list = [filename_to_doi(article) for article in self.files]
            return doi_list
        else:
            return self._dois

    def random_dois(self, count):
        """
        Gets a list of random DOIs. Construct from local files in
        corpusdir.
        :param directory: directory of articles for class object
        :param count: specify how many DOIs are to be returned
        :return: a list of random DOIs for analysis
        """
        doi_list = self.dois
        sample_doi_list = random.sample(doi_list, count)

        return sample_doi_list

<|endoftext|>


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

WINE_CLASSIFICATIONS = {'1er Cru', '1er Cru Classé', '1er Grand Cru', '2ème Cru Classé', '2ème Vin',
                        '4ème Cru Classé', 'Cru Classé', 'Grand Cru', 'Non Classé'}
WINE_PACKING_TYPE = {'OCB06', 'OCB12', 'OWC06', 'OWC01', 'OWC02', 'OWC03', 'OWC06', 'OWC12'}
<commit_msg>update enum file<commit_after>from __future__ import absolute_import, division, print_function, unicode_literals

WINE_CLASSIFICATIONS = {'1er Cru', '1er Cru Classé', '1er Grand Cru', '2ème Cru Classé', '2ème Vin',
                        '4ème Cru Classé', 'Cru Classé', 'Grand Cru', 'Non Classé'}
WINE_PACKING_TYPE = {'OCB06', 'OCB12', 'OWC06', 'OWC01', 'OWC02', 'OWC03', 'OWC06', 'OWC12'}

CAR_COLOR_RECORD = {'White', 'Silver', 'Black', 'Grey', 'Blue', 'Red', 'Brown', 'Green'}
CAR_MAKE_RECORD = {'McLaren', 'Koenigsegg', 'Bugatti', 'Pagani', 'Aston Martin', 'Mercedes', 'Jaguar', 'Porsche',
            'Ferrari', 'Lamborghini', 'Rolls Royce', 'Bentley', 'Maybach', 'Audi', 'Maserati', 'Lexus', 'BMW', 'Cadillac'}
CAR_STYLE = {'R': 'Roadster', 'CV': 'Convertible', 'CP': 'Coupe', 'S': 'Sedan', 'SUV': 'Sport utility vehicle'}
CAR_GENRE = {'M': 'Modern', 'C': 'Classic', 'A': 'Antique', 'E': 'Exotic'}
CAR_RARITY = {'super rare', 'very rare', 'rare', 'fairly rare', None}
CAR_CONDITION = {'DC': 'Driving Condition', 'SS': 'Street Show Condition', 'SC': 'Show Car', 'CC': 'Concours Condition'}
CAR_PETROL_GRADE = {87: 'regular', 88: 'midgrade', 89: 'midgrade',
                    90: 'midgrade', 91: 'premium', 92: 'premium', 93: 'premium', 94: 'premium'}<|endoftext|>


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

import os
import StringIO
import testsuite
# Bootstrap the testsuite
testsuite.setup()

import testbase
from amiconfig import errors
from urllib2 import HTTPError

class AmiTest(testbase.TestCase):
    def testInstanceId(self):
        self.assertEquals(self.amicfg.id.getInstanceId(), 'i-decafbad')

    def testInstanceId_noec2(self):
        self._data['meta-data/instance-id'] = HTTPError("url",
                113, "No route to host", None, fp=StringIO.StringIO())
        e = self.assertRaises(errors.EC2DataRetrievalError,
            self.amicfg.id.getInstanceId)
        self.assertEquals(e.args, ('[113] url: No route to host', ))

        self._data['meta-data/instance-id'] = testbase.FakeResponse('url',
                'content', status=404, reason="Not found")
        e = self.assertRaises(errors.EC2DataRetrievalError,
            self.amicfg.id.getInstanceId)
        self.assertEquals(e.args, ('[404] url: Not found', ))

    def testConfig(self):
        from amiconfig import constants
        self.configPath = os.path.join(self.workDir, 'amiconfig.conf')
        self.configDPath = os.path.join(self.workDir, 'amiconfig.d')
        self.mkdirs(self.configDPath)

        self.amicfg.ud._cfgfn = self.configPath
        self.amicfg.ud._cfgdir = self.configDPath

        self.assertEquals(sorted(self.amicfg._getEnabledPlugins()),
                ['disablesshpasswdauth', 'rootsshkeys'])

        file(self.configPath, 'w').write('[amiconfig]\nplugins: blippy')
        self.amicfg.ud._init()
        self.assertEquals(sorted(self.amicfg._getEnabledPlugins()),
                ['blippy', 'disablesshpasswdauth', 'rootsshkeys'])

        # Disable one of the plugins, and add another one
        file(os.path.join(self.configDPath, "blargh.conf"), 'w').write(
                '[amiconfig]\nplugins: blargh\ndisabled_plugins: rootsshkeys')
        self.amicfg.ud._init()
        self.assertEquals(sorted(self.amicfg._getEnabledPlugins()),
                ['blargh', 'blippy', 'disablesshpasswdauth'])
        # Remove all default plugins
        file(os.path.join(self.configDPath, "acme.conf"), 'w').write(
                '[amiconfig]\nplugins: []')
        self.amicfg.ud._init()
        self.assertEquals(sorted(self.amicfg._getEnabledPlugins()),
                ['blargh'])

    def testWriteProperties(self):
        self._data.update({
            'user-data' : "Whee!",
            'meta-data/ami-id' : "ami-decafbad",
            'meta-data/ami-launch-index' : 1,
            'meta-data/ami-manifest-path' : '/aaa',
            'meta-data/hostname' : 'remotehost',
            'meta-data/instance-type' : 's3',
            'meta-data/kernel-id' : 'aki-decafbad',
            'meta-data/local-hostname' : 'local-hostname',
            'meta-data/local-ipv4' : '10.2.3.4',
            'meta-data/placement/availability-zone' : 'ec2.east',
            'meta-data/profile' : 'slim',
            'meta-data/public-hostname' : 'public-hostname',
            'meta-data/public-ipv4' : '1.2.3.4',
            'meta-data/public-keys/0/openssh-key' : 'ssh-key blah',
            'meta-data/reservation-id' : 'r-decafbad',
            'meta-data/security-groups' : 'secgroup1 secgroup2',
            })
        destDir = os.path.join(self.workDir, "ami")
        self.amicfg.id.writeProperties(destDir)
        for k, v in self._data.items():
            self.assertEqual(file(os.path.join(destDir, k)).read(), str(v))
<commit_msg>Update test for new metadata (APPENG-3426)<commit_after>#!/usr/bin/python
#
# Copyright (c) SAS Institute Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import os
import StringIO
import testsuite
# Bootstrap the testsuite
testsuite.setup()

import testbase
from amiconfig import errors
from urllib2 import HTTPError

class AmiTest(testbase.TestCase):
    def testInstanceId(self):
        self.assertEquals(self.amicfg.id.getInstanceId(), 'i-decafbad')

    def testInstanceId_noec2(self):
        self._data['meta-data/instance-id'] = HTTPError("url",
                113, "No route to host", None, fp=StringIO.StringIO())
        e = self.assertRaises(errors.EC2DataRetrievalError,
            self.amicfg.id.getInstanceId)
        self.assertEquals(e.args, ('[113] url: No route to host', ))

        self._data['meta-data/instance-id'] = testbase.FakeResponse('url',
                'content', status=404, reason="Not found")
        e = self.assertRaises(errors.EC2DataRetrievalError,
            self.amicfg.id.getInstanceId)
        self.assertEquals(e.args, ('[404] url: Not found', ))

    def testConfig(self):
        from amiconfig import constants
        self.configPath = os.path.join(self.workDir, 'amiconfig.conf')
        self.configDPath = os.path.join(self.workDir, 'amiconfig.d')
        self.mkdirs(self.configDPath)

        self.amicfg.ud._cfgfn = self.configPath
        self.amicfg.ud._cfgdir = self.configDPath

        self.assertEquals(sorted(self.amicfg._getEnabledPlugins()),
                ['disablesshpasswdauth', 'rootsshkeys'])

        file(self.configPath, 'w').write('[amiconfig]\nplugins: blippy')
        self.amicfg.ud._init()
        self.assertEquals(sorted(self.amicfg._getEnabledPlugins()),
                ['blippy', 'disablesshpasswdauth', 'rootsshkeys'])

        # Disable one of the plugins, and add another one
        file(os.path.join(self.configDPath, "blargh.conf"), 'w').write(
                '[amiconfig]\nplugins: blargh\ndisabled_plugins: rootsshkeys')
        self.amicfg.ud._init()
        self.assertEquals(sorted(self.amicfg._getEnabledPlugins()),
                ['blargh', 'blippy', 'disablesshpasswdauth'])
        # Remove all default plugins
        file(os.path.join(self.configDPath, "acme.conf"), 'w').write(
                '[amiconfig]\nplugins: []')
        self.amicfg.ud._init()
        self.assertEquals(sorted(self.amicfg._getEnabledPlugins()),
                ['blargh'])

    def testWriteProperties(self):
        self._data.update({
            'user-data' : "Whee!",
            'meta-data/ami-id' : "ami-decafbad",
            'meta-data/ami-launch-index' : 1,
            'meta-data/ami-manifest-path' : '/aaa',
            'meta-data/hostname' : 'remotehost',
            'meta-data/instance-type' : 's3',
            'meta-data/kernel-id' : 'aki-decafbad',
            'meta-data/local-hostname' : 'local-hostname',
            'meta-data/local-ipv4' : '10.2.3.4',
            'meta-data/placement/availability-zone' : 'ec2.east',
            'meta-data/product-codes' : 'foobar',
            'meta-data/profile' : 'slim',
            'meta-data/public-hostname' : 'public-hostname',
            'meta-data/public-ipv4' : '1.2.3.4',
            'meta-data/public-keys/0/openssh-key' : 'ssh-key blah',
            'meta-data/reservation-id' : 'r-decafbad',
            'meta-data/security-groups' : 'secgroup1 secgroup2',
            })
        destDir = os.path.join(self.workDir, "ami")
        self.amicfg.id.writeProperties(destDir)
        for k, v in self._data.items():
            self.assertEqual(file(os.path.join(destDir, k)).read(), str(v))
<|endoftext|>


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

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

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

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

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

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/1.8/howto/deployment/checklist/

# SECRET KEY: Generate unique key for new project
def generate_secret_key(filePath):
    from django.utils.crypto import get_random_string
    chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
    secret_key_str = "SECRET_KEY = '{}'".format(get_random_string(50, chars))
    with open(filePath, 'w') as f:
        f.write(secret_key_str)

try:
    from .secret_key import *
except ImportError:
    SETTINGS_DIR=os.path.abspath(os.path.dirname(__file__))
    generate_secret_key(os.path.join(SETTINGS_DIR, 'secret_key.py'))
    from .secret_key import *

# DEBUG: Disable if special isdevserver file does not exist
# This also controls static file deployment
STATIC_URL = '/static/'
STATIC_BASE = os.path.join(BASE_DIR, "static")
STATICFILES_DIRS = (STATIC_BASE,)

DEBUG_FILE=os.path.join(os.path.abspath(os.path.dirname(__file__)), 'isdevserver')
if os.path.exists(DEBUG_FILE):
    DEBUG = True
else:
    DEBUG = False
    STATIC_ROOT = STATIC_BASE

ALLOWED_HOSTS = ['localhost', '127.0.0.1', '192.168.*']

# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'main',
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
)

ROOT_URLCONF = 'ananke.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        '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 = 'ananke.wsgi.application'

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

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

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

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Logging
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['console'],
            'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
        },
    },
}
<commit_msg>Update allowed hosts<commit_after>"""
Django settings for ananke project.

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

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

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

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

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/1.8/howto/deployment/checklist/

# SECRET KEY: Generate unique key for new project
def generate_secret_key(filePath):
    from django.utils.crypto import get_random_string
    chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
    secret_key_str = "SECRET_KEY = '{}'".format(get_random_string(50, chars))
    with open(filePath, 'w') as f:
        f.write(secret_key_str)

try:
    from .secret_key import *
except ImportError:
    SETTINGS_DIR=os.path.abspath(os.path.dirname(__file__))
    generate_secret_key(os.path.join(SETTINGS_DIR, 'secret_key.py'))
    from .secret_key import *

# DEBUG: Disable if special isdevserver file does not exist
# This also controls static file deployment
STATIC_URL = '/static/'
STATIC_BASE = os.path.join(BASE_DIR, "static")
STATICFILES_DIRS = (STATIC_BASE,)

DEBUG_FILE=os.path.join(os.path.abspath(os.path.dirname(__file__)), 'isdevserver')
if os.path.exists(DEBUG_FILE):
    DEBUG = True
else:
    DEBUG = False
    STATIC_ROOT = STATIC_BASE

ALLOWED_HOSTS = ['*']

# Application definition
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'main',
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
)

ROOT_URLCONF = 'ananke.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        '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 = 'ananke.wsgi.application'

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

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

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

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Logging
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['console'],
            'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
        },
    },
}
<|endoftext|>


<commit_before>version="0.1.8dev"
db_version="0.0.4"
<commit_msg>version bump to 0.1.8<commit_after>version="0.1.8"
db_version="0.0.4"
<|endoftext|>


<commit_before>#!/usr/bin/env python
# encoding: utf-8
"""
Pipeline for analysis of hte PHAT six-color photometry.
"""

import os
from collections import namedtuple

import numpy as np
from astropy.table import Table
from m31hst import phat_v2_phot_path

from starfisher import ColorPlane

Lim = namedtuple('Lim', 'x y')
wfc3_bands = ['F475W', 'F814W', 'F110W', 'F160W']

class Catalog(object):
    """Brick data catalog."""
    def __init__(self, brick):
        super(Catalog, self).__init__()
        self.data = Table.read(phat_v2_phot_path(brick), format='fits')

    def written_path(self, band1, band2, data_root):
        """Path to the output data file."""
        ext = '{0}{1}'.format(band1.rstrip('w'), band2.rstrip('w'))
        path = data_root + ext
        return path

    def write(self, band1, band2, data_root):
        """Write a band1-band2 vs band2 photometry catalog."""
        bands = (band1, band2)
        keys = ['{0}_vega'.format(band) for band in bands]
        phot_dtype = np.dtype([('x', np.float), ('y', np.float)])
        photdata = np.empty(len(self.data), dtype=phot_dtype)
        photdata['x'][:] = self.data[keys[0]] - self.data[keys[1]]
        photdata['y'][:] = self.data[keys[1]]

        path = self.written_path(band1, band2, data_root)
        fit_dir = os.path.dirname(path)
        if not os.path.exists(fit_dir):
            os.makedirs(fit_dir)
        np.savetxt(path, photdata, delimiter=' ', fmt='%.4f')

class PhatPlanes(object):
    """Color planes for PHAT data."""
    def __init__(self):
        super(PhatPlanes, self).__init__()
        self._planes = {
            ('f475w', 'f814w'): make_f475w_f814w(),
        }

def make_f475w_f814w(dpix=0.05, mag_lim=30.):
    lim = Lim(x=(-1, 5), y=(25.5, 20))
    plane = ColorPlane((wfc3_bands.index('F475W'),
                        wfc3_bands.index('F814W')),
                       wfc3_bands.index('F814W'),
                       lim.x,
                       (min(lim.y), max(lim.y)),
                       mag_lim,
                       suffix='f475f814',
                       x_label=r'$\mathrm{F475W}-\mathrm{F814W}$',
                       y_label=r'$\mathrm{F814W}$',
                       dpix=dpix)
    plane.mask_region((3, 5), (28, 25))
    plane.mask_region((3.5, 5), (25, 23))
    plane.mask_region((4, 5), (23, 22.5))
    return plane

def make_f110w_f160w(dpix=0.05, mag_lim=30.):
    lim = Lim(x=(0.3, 1.3), y=(24, 16.5))
    plane = ColorPlane((wfc3_bands.index('F110W'),
                        wfc3_bands.index('F160W')),
                       wfc3_bands.index('F160W'),
                       lim.x,
                       (min(lim.y), max(lim.y)),
                       mag_lim,
                       suffix='f110f160',
                       x_label=r'$\mathrm{F110W}-\mathrm{F160W}$',
                       y_label=r'$\mathrm{F160W}$',
                       dpix=dpix)
    plane.mask_region((-1., 0.), (22., 16))
    plane.mask_region((0, 0.3), (22., 16))
    plane.mask_region((0.3, 0.7), (20., 16))
    plane.mask_region((0.7, 0.8), (19., 16))
    plane.mask_region((0.8, 0.9), (18., 16))
    plane.mask_region((1.1, 1.5), (28, 21))
    return plane

def make_f475w_f160w(dpix=0.05, mag_lim=30.):
    lim = Lim(x=(-0.8, 8), y=(25, 17.5))
    plane = ColorPlane((wfc3_bands.index('F475W'),
                        wfc3_bands.index('F160W')),
                       wfc3_bands.index('F160W'),
                       lim.x,
                       (min(lim.y), max(lim.y)),
                       mag_lim,
                       suffix='f475f160',
                       x_label=r'$\mathrm{F475W}-\mathrm{F160W}$',
                       y_label=r'$\mathrm{F110W}$',
                       dpix=dpix)
    return plane

def make_f475w_f110w(dpix=0.05, mag_lim=30.):
    lim = Lim(x=(-0.8, 7), y=(25, 18))
    plane = ColorPlane((wfc3_bands.index('F475W'),
                        wfc3_bands.index('F110W')),
                       wfc3_bands.index('F110W'),
                       lim.x,
                       (min(lim.y), max(lim.y)),
                       mag_lim,
                       suffix='f475f110',
                       x_label=r'$\mathrm{F475W}-\mathrm{F110W}$',
                       y_label=r'$\mathrm{F110W}$',
                       dpix=dpix)
    return plane

def make_f814w_f110w(dpix=0.05, mag_lim=30.):
    lim = Lim(x=(-0.1, 1.8), y=(25, 19))
    plane = ColorPlane((wfc3_bands.index('F814W'),
                        wfc3_bands.index('F110W')),
                       wfc3_bands.index('F110W'),
                       lim.x,
                       (min(lim.y), max(lim.y)),
                       mag_lim,
                       suffix='f814f110',
                       x_label=r'$\mathrm{F814W}-\mathrm{F110W}$',
                       y_label=r'$\mathrm{F110W}$',
                       dpix=dpix)
    return plane

def make_f814w_f160w(dpix=0.05, mag_lim=30.):
    lim = Lim(x=(-0.5, 3), y=(24, 17.5))
    plane = ColorPlane((wfc3_bands.index('F814W'),
                        wfc3_bands.index('F160W')),
                       wfc3_bands.index('F160W'),
                       lim.x,
                       (min(lim.y), max(lim.y)),
                       mag_lim,
                       suffix='f814f160',
                       x_label=r'$\mathrm{F814W}-\mathrm{F160W}$',
                       y_label=r'$\mathrm{F160W}$',
                       dpix=dpix)
    return plane
<commit_msg>Pipeline for PHAT six-color fitting<commit_after>#!/usr/bin/env python
# encoding: utf-8
"""
Pipeline for analysis of hte PHAT six-color photometry.
"""

import os
from glob import glob
from collections import namedtuple, OrderedDict

import numpy as np
from astropy.table import Table
from m31hst import phat_v2_phot_path

from astropy.coordinates import Distance
import astropy.units as u

from padova import AgeGridRequest

from starfisher import ColorPlane
from starfisher import SimHess
from starfisher import LibraryBuilder
from starfisher import Lockfile
from starfisher import Synth
from starfisher import ExtinctionDistribution
from starfisher import ExtantCrowdingTable
from m31hst.phatast import PhatAstTable

STARFISH = os.getenv("STARFISH")
Lim = namedtuple('Lim', 'x y')
wfc3_bands = ['F475W', 'F814W', 'F110W', 'F160W']

class Pipeline(object):
    """Pipeline for Multi-CMD fitting and comparison"""
    def __init__(self, brick, root_dir):
        super(Pipeline, self).__init__()
        self.isoc_dir = os.path.join(root_dir, 'isoc')
        self.lib_dir = os.path.join(root_dir, 'lib')
        self.synth_dir = os.path.join(root_dir, 'synth')

        self.z_grid = [0.015, 0.019, 0.024]

        self.get_isochrones()
        self.build_lockfile()
        self.planes = PhatPlanes()
        self.run_synth()

    def get_isochrones(self):
        if not os.path.exists(os.path.join(STARFISH, self.isoc_dir)):
            for z in self.z_grid:
                r = AgeGridRequest(z,
                                   min_log_age=6.6,
                                   max_log_age=10.13,
                                   delta_log_age=0.02,
                                   phot='wfc3', photsys_version='odfnew')
                for isoc in r.isochrone_set:
                    isoc.export_for_starfish(os.path.join(STARFISH,
                                                          self.isoc_dir),
                                             bands=wfc3_bands)

        d = Distance(785 * u.kpc)
        self.builder = LibraryBuilder(self.isoc_dir, self.lib_dir,
                                      nmag=len(wfc3_bands),
                                      dmod=d.distmod.value,
                                      iverb=3)
        if not os.path.exists(self.builder.full_isofile_path):
            self.builder.install()

    def build_lockfile(self):
        if not os.path.exists(os.path.join(STARFISH, self.synth_dir)):
            os.makedirs(os.path.join(STARFISH, self.synth_dir))

        self.lockfile = Lockfile(self.builder.read_isofile(), self.synth_dir,
                                 unbinned=False)

        # Bin young isochrones
        young_grid = np.linspace(6.5, 8.95, 10)
        for i, logage0 in enumerate(young_grid[:-1]):
            logage0 = logage0
            logage1 = young_grid[i + 1]
            z_str = "0019"
            mean_age = (logage0 + logage1) / 0.2
            name = "z{0}_{1:05.2f}".format(z_str, mean_age)
            self.lockfile.lock_box(name, (logage0, logage1), (0.014, 0.025))

        # Bin old isochrones
        old_grid = np.arange(1e9, 14 * 1e9, 1e9)
        for i, age0 in enumerate(old_grid[:-1]):
            logage0 = np.log10(age0 - 0.05 * 1e9)
            logage1 = np.log10(old_grid[i + 1])
            z_str = "0019"
            mean_age = (logage0 + logage1) / 0.2
            name = "z{0}_{1:05.2f}".format(z_str, mean_age)
            self.lockfile.lock_box(name, (logage0, logage1), (0.014, 0.025))

    def run_synth(self):
        full_synth_dir = os.path.join(STARFISH, self.synth_dir)
        if not os.path.exists(full_synth_dir):
            os.makedirs(full_synth_dir)

        # Use PHAT AST from the outer field (field 0)
        crowd_path = os.path.join(self.synth_dir, "crowding.dat")
        full_crowd_path = os.path.join(STARFISH, crowd_path)
        tbl = PhatAstTable()
        tbl.write_crowdfile_for_field(full_crowd_path, 0,
                                      bands=wfc3_bands)
        crowd = ExtantCrowdingTable(crowd_path)

        # No extinction, yet
        young_av = ExtinctionDistribution()
        old_av = ExtinctionDistribution()
        rel_extinction = np.ones(len(wfc3_bands), dtype=float)
        for av in (young_av, old_av):
            av.set_uniform(0.)

        self.synth = Synth(self.synth_dir, self.builder, self.lockfile, crowd,
                           rel_extinction,
                           young_extinction=young_av,
                           old_extinction=old_av,
                           planes=self.planes.all_planes,
                           mass_span=(0.08, 150.),
                           nstars=10000000)
        if len(glob(os.path.join(STARFISH, self.synth_dir, "z*"))) == 0:
            self.synth.run_synth(n_cpu=4)

class Catalog(object):
    """Brick data catalog."""
    def __init__(self, brick):
        super(Catalog, self).__init__()
        self.data = Table.read(phat_v2_phot_path(brick), format='fits')

    def written_path(self, band1, band2, data_root):
        """Path to the output data file."""
        ext = '{0}{1}'.format(band1.rstrip('w'), band2.rstrip('w'))
        path = data_root + ext
        return path

    def write(self, band1, band2, data_root):
        """Write a band1-band2 vs band2 photometry catalog."""
        bands = (band1, band2)
        keys = ['{0}_vega'.format(band) for band in bands]
        phot_dtype = np.dtype([('x', np.float), ('y', np.float)])
        photdata = np.empty(len(self.data), dtype=phot_dtype)
        photdata['x'][:] = self.data[keys[0]] - self.data[keys[1]]
        photdata['y'][:] = self.data[keys[1]]

        path = self.written_path(band1, band2, data_root)
        fit_dir = os.path.dirname(path)
        if not os.path.exists(fit_dir):
            os.makedirs(fit_dir)
        np.savetxt(path, photdata, delimiter=' ', fmt='%.4f')

class PhatPlanes(object):
    """Color planes for PHAT data."""
    def __init__(self):
        super(PhatPlanes, self).__init__()
        self._planes = OrderedDict([
            (('f475w', 'f814w'), make_f475w_f814w()),
            (('f475w', 'f110w'), make_f475w_f110w()),
            (('f475w', 'f160w'), make_f475w_f160w()),
            (('f814w', 'f110w'), make_f814w_f110w()),
            (('f814w', 'f160w'), make_f814w_f160w()),
            (('f110w', 'f160w'), make_f110w_f160w()),
        ])

        self._sim_hess_planes = {}

    def get_plane(self, band1, band2):
        return self._planes[(band1, band2)]

    def get_sim_hess(self, band1, band2, synth, lockfile):
        key = (band1, band2)
        if key not in self._sim_hess_planes:
            sh = SimHess(synth, self._planes[key],
                         np.ones(len(lockfile.active_groups)))
            self._sim_hess_planes[key] = sh
        return self._sim_hess_planes[key]

    @property
    def all_planes(self):
        return [p for k, p in self._planes.iteritems()]

def make_f475w_f814w(dpix=0.05, mag_lim=30.):
    lim = Lim(x=(-1, 5), y=(25.5, 20))
    plane = ColorPlane((wfc3_bands.index('F475W'),
                        wfc3_bands.index('F814W')),
                       wfc3_bands.index('F814W'),
                       lim.x,
                       (min(lim.y), max(lim.y)),
                       mag_lim,
                       suffix='f475f814',
                       x_label=r'$\mathrm{F475W}-\mathrm{F814W}$',
                       y_label=r'$\mathrm{F814W}$',
                       dpix=dpix)
    plane.mask_region((3, 5), (28, 25))
    plane.mask_region((3.5, 5), (25, 23))
    plane.mask_region((4, 5), (23, 22.5))
    return plane

def make_f110w_f160w(dpix=0.05, mag_lim=30.):
    lim = Lim(x=(0.3, 1.3), y=(24, 16.5))
    plane = ColorPlane((wfc3_bands.index('F110W'),
                        wfc3_bands.index('F160W')),
                       wfc3_bands.index('F160W'),
                       lim.x,
                       (min(lim.y), max(lim.y)),
                       mag_lim,
                       suffix='f110f160',
                       x_label=r'$\mathrm{F110W}-\mathrm{F160W}$',
                       y_label=r'$\mathrm{F160W}$',
                       dpix=dpix)
    plane.mask_region((-1., 0.), (22., 16))
    plane.mask_region((0, 0.3), (22., 16))
    plane.mask_region((0.3, 0.7), (20., 16))
    plane.mask_region((0.7, 0.8), (19., 16))
    plane.mask_region((0.8, 0.9), (18., 16))
    plane.mask_region((1.1, 1.5), (28, 21))
    return plane

def make_f475w_f160w(dpix=0.05, mag_lim=30.):
    lim = Lim(x=(-0.8, 8), y=(25, 17.5))
    plane = ColorPlane((wfc3_bands.index('F475W'),
                        wfc3_bands.index('F160W')),
                       wfc3_bands.index('F160W'),
                       lim.x,
                       (min(lim.y), max(lim.y)),
                       mag_lim,
                       suffix='f475f160',
                       x_label=r'$\mathrm{F475W}-\mathrm{F160W}$',
                       y_label=r'$\mathrm{F110W}$',
                       dpix=dpix)
    return plane

def make_f475w_f110w(dpix=0.05, mag_lim=30.):
    lim = Lim(x=(-0.8, 7), y=(25, 18))
    plane = ColorPlane((wfc3_bands.index('F475W'),
                        wfc3_bands.index('F110W')),
                       wfc3_bands.index('F110W'),
                       lim.x,
                       (min(lim.y), max(lim.y)),
                       mag_lim,
                       suffix='f475f110',
                       x_label=r'$\mathrm{F475W}-\mathrm{F110W}$',
                       y_label=r'$\mathrm{F110W}$',
                       dpix=dpix)
    return plane

def make_f814w_f110w(dpix=0.05, mag_lim=30.):
    lim = Lim(x=(-0.1, 1.8), y=(25, 19))
    plane = ColorPlane((wfc3_bands.index('F814W'),
                        wfc3_bands.index('F110W')),
                       wfc3_bands.index('F110W'),
                       lim.x,
                       (min(lim.y), max(lim.y)),
                       mag_lim,
                       suffix='f814f110',
                       x_label=r'$\mathrm{F814W}-\mathrm{F110W}$',
                       y_label=r'$\mathrm{F110W}$',
                       dpix=dpix)
    return plane

def make_f814w_f160w(dpix=0.05, mag_lim=30.):
    lim = Lim(x=(-0.5, 3), y=(24, 17.5))
    plane = ColorPlane((wfc3_bands.index('F814W'),
                        wfc3_bands.index('F160W')),
                       wfc3_bands.index('F160W'),
                       lim.x,
                       (min(lim.y), max(lim.y)),
                       mag_lim,
                       suffix='f814f160',
                       x_label=r'$\mathrm{F814W}-\mathrm{F160W}$',
                       y_label=r'$\mathrm{F160W}$',
                       dpix=dpix)
    return plane
<|endoftext|>


<commit_before>"""Database models for PUDL tables derived from EIA Form 923 Data."""

from sqlalchemy import Boolean, Integer, String, Float, Numeric, Date
from sqlalchemy import Column, ForeignKey, ForeignKeyConstraint
import pudl.models.entities

###########################################################################
# EIA Form 923 tables which represent constants or metadata
# (e.g. fuel types and fuel units)
###########################################################################

class CoalMineEIA923(pudl.models.entities.PUDLBase):
    """Information pertaining to individual coal mines listed in EIA 923."""

    __tablename__ = 'coalmine_eia923'
    id = Column(Integer, primary_key=True)  # surrogate key
    mine_name = Column(String)
    mine_type = Column(String, ForeignKey('coalmine_type_eia923.abbr'))
    state = Column(String, ForeignKey('coalmine_state_eia923.abbr'))
    # TODO check feasibility t add FK/constants or map to FIPS code used by EIA
    county_id_fips = Column(Integer)
    # TODO check feasibility to add FK/constants or map to MSHA ID# used by EIA
    mine_id_msha = Column(Integer)

class BoilersEIA923(pudl.models.entities.PUDLBase):
    """List of Boiler IDs specific to each plant in EIA Form 923 Page 3."""

    __tablename__ = 'boilers_eia923'
    #__table_args__ = (ForeignKeyConstraint(
    #    ['plant_id_eia', 'boiler_id'],
    #    ['boilers_entity_eia.plant_id_eia',
    #     'boilers_entity_eia.boiler_id']),)
    plant_id_eia = Column(Integer,
                          primary_key=True)
    boiler_id = Column(String, primary_key=True)
    prime_mover = Column(String,
                         ForeignKey('prime_movers_eia923.abbr'),
                         nullable=False)

class GeneratorEIA923(pudl.models.entities.PUDLBase):
    """List of Generator IDs specific to each plant in EIA Form 923 Page 4."""

    __tablename__ = 'generators_eia923'
    __table_args__ = (ForeignKeyConstraint(
        ['plant_id_eia', 'generator_id'],
        ['generators_entity_eia.plant_id_eia',
         'generators_entity_eia.generator_id']),)

    plant_id_eia = Column(Integer, primary_key=True)
    generator_id = Column(String, primary_key=True)
    prime_mover = Column(String,
                         ForeignKey('prime_movers_eia923.abbr'),
                         nullable=False)

class FuelUnitEIA923(pudl.models.entities.PUDLBase):
    """Static list of physical unit labels used by EIA in Form 923."""

    __tablename__ = 'fuel_units_eia923'
    abbr = Column(String, primary_key=True)
    unit = Column(String)

class FuelTypeEIA923(pudl.models.entities.PUDLBase):
    """
    Static list of fuel types used by EIA in Form 923.

    Enumerated on Page 7 of EIA Form 923.
    """

    __tablename__ = 'fuel_type_eia923'
    abbr = Column(String, primary_key=True)
    fuel_type = Column(String, nullable=False)
    fuel_unit = Column(String, ForeignKey('fuel_units_eia923.abbr'))

class FuelGroupEIA923(pudl.models.entities.PUDLBase):
    """Grouping of energy sources into fuel groups, used in EIA Form 923."""

    __tablename__ = 'fuel_group_eia923'
    group = Column(String, primary_key=True)

class RespondentFrequencyEIA923(pudl.models.entities.PUDLBase):
    """
    Plant reporting frequency in EIA Form 923.

    Used by EIA in Form 923, Page 5: Fuel Receipts and Costs
    """

    __tablename__ = 'respondent_frequency_eia923'
    abbr = Column(String, primary_key=True)
    unit = Column(String, nullable=False)

class ContractTypeEIA923(pudl.models.entities.PUDLBase):
    """Type of contract under which fuel receipt occured."""

    __tablename__ = 'contract_type_eia923'
    abbr = Column(String, primary_key=True)
    contract_type = Column(String, nullable=False)

class SectorEIA(pudl.models.entities.PUDLBase):
    """EIA’s internal consolidated NAICS sectors."""

    __tablename__ = 'sector_eia'
    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)

class FuelTypeAER(pudl.models.entities.PUDLBase):
    """Static list of fuel types using AER codes, reported in EIA Form 923."""

    __tablename__ = 'fuel_type_aer_eia923'
    abbr = Column(String, primary_key=True)
    fuel_type = Column(String, nullable=False)

class PrimeMoverEIA923(pudl.models.entities.PUDLBase):
    """Static list of prime movers used by EIA in Form 923."""

    __tablename__ = 'prime_movers_eia923'
    abbr = Column(String, primary_key=True)
    prime_mover = Column(String, nullable=False)

class EnergySourceEIA923(pudl.models.entities.PUDLBase):
    """Fuel code associated with fuel receipts in EIA Form 923."""

    __tablename__ = 'energy_source_eia923'
    abbr = Column(String, primary_key=True)
    source = Column(String, nullable=False)

class CoalMineTypeEIA923(pudl.models.entities.PUDLBase):
    """Type of coal mine, as used in EIA Form 923."""

    __tablename__ = 'coalmine_type_eia923'
    abbr = Column(String, primary_key=True)
    name = Column(String, nullable=False)

class CoalMineStateEIA923(pudl.models.entities.PUDLBase):
    """State and country abbreviations for coal mine locations."""

    __tablename__ = 'coalmine_state_eia923'
    abbr = Column(String, primary_key=True)
    state = Column(String, nullable=False)

class NaturalGasTransportEIA923(pudl.models.entities.PUDLBase):
    """Contract type for natural gas capacity service."""

    __tablename__ = 'natural_gas_transport_eia923'
    abbr = Column(String, primary_key=True)
    status = Column(String, nullable=False)

class TransportModeEIA923(pudl.models.entities.PUDLBase):
    """Mode used for longest & 2nd longest distance in EIA Form 923."""

    __tablename__ = 'transport_modes_eia923'
    abbr = Column(String, primary_key=True)
    mode = Column(String, nullable=False)

###########################################################################
# Tables which represent EIA Form 923 data. E.g. Fuel Receipts.
###########################################################################
class GenerationFuelEIA923(pudl.models.entities.PUDLBase):
    """
    Monthly fuel consumption and electricity generation by plant.

    Reported on Page 1 of EIA Form 923.
    """

    __tablename__ = 'generation_fuel_eia923'

    id = Column(Integer, autoincrement=True, primary_key=True)  # surrogate key
    plant_id_eia = Column(Integer,
                          ForeignKey('plants_entity_eia.plant_id_eia'),
                          nullable=False)
    report_date = Column(Date, nullable=False)
    # TODO: Should nuclear_unit_id really be here? It's kind of part of the
    # plant_id... but also unit_id.  Seems weird but necessary to uniquely
    # identify the records as reported.
    nuclear_unit_id = Column(Integer)
    fuel_type = Column(String,
                       ForeignKey('fuel_type_eia923.abbr'),
                       nullable=False)
    fuel_type_pudl = Column(String)
    aer_fuel_type = Column(String, ForeignKey('fuel_type_aer_eia923.abbr'))
    prime_mover = Column(String,
                         ForeignKey('prime_movers_eia923.abbr'),
                         nullable=False)
    fuel_consumed_total = Column(Float)
    fuel_consumed_for_electricity = Column(Float)
    fuel_mmbtu_per_unit = Column(Float)
    fuel_consumed_total_mmbtu = Column(Float)
    fuel_consumed_for_electricity_mmbtu = Column(Float)
    net_generation_mwh = Column(Float)

class BoilerFuelEIA923(pudl.models.entities.PUDLBase):
    """Monthly fuel consumption by boiler reported on Page 3 of EIA 923."""

    __tablename__ = 'boiler_fuel_eia923'
    #__table_args__ = (ForeignKeyConstraint(
    #    ['plant_id_eia', 'boiler_id'],
    #    ['boilers_entity_eia.plant_id_eia',
    #     'boilers_entity_eia.boiler_id']),)

    # Each month, for each unique combination of boiler id and prime mover and
    # fuel, there is one report for each boiler unit in each plant.

    id = Column(Integer, autoincrement=True, primary_key=True)  # surrogate key
    plant_id_eia = Column(Integer, nullable=False)
    boiler_id = Column(String, nullable=False)
    prime_mover = Column(String, ForeignKey('prime_movers_eia923.abbr'),
                         nullable=False)
    fuel_type = Column(String, ForeignKey('fuel_type_eia923.abbr'),
                       nullable=False)
    fuel_type_pudl = Column(String)
    report_date = Column(Date, nullable=False)
    fuel_qty_consumed = Column(Float)
    fuel_mmbtu_per_unit = Column(Float)
    sulfur_content_pct = Column(Float)
    ash_content_pct = Column(Float)

class GenerationEIA923(pudl.models.entities.PUDLBase):
    """Monthly electricity generation by generator from EIA923 Page 4."""

    __tablename__ = 'generation_eia923'
    __table_args__ = (ForeignKeyConstraint(
        ['plant_id_eia', 'generator_id'],
        ['generators_entity_eia.plant_id_eia',
         'generators_entity_eia.generator_id']),)

    # Each month, for each unique combination of generator id and prime mover
    # and fuel,there is one report for each generator unit in each plant.
    id = Column(Integer, autoincrement=True, primary_key=True)  # surrogate key
    plant_id_eia = Column(Integer, nullable=False)
    # TODO remove prime_mover since it's specific to generator_id?
    prime_mover = Column(String, ForeignKey('prime_movers_eia923.abbr'),
                         nullable=False)
    # TODO: Add FK constraint refering to (plant_id, generator_id) in the
    # generators_eia923 table.  Or at least give it a shot.
    generator_id = Column(String, nullable=False)
    report_date = Column(Date, nullable=False)
    net_generation_mwh = Column(Float)

class FuelReceiptsCostsEIA923(pudl.models.entities.PUDLBase):
    """Fuel receipts & costs by plant &purchase from Page 5 of EIA Form 923."""

    __tablename__ = 'fuel_receipts_costs_eia923'

    # surrogate key
    fuel_receipt_id = Column(Integer, primary_key=True, autoincrement=True)
    plant_id_eia = Column(Integer,
                          ForeignKey('plants_entity_eia.plant_id_eia'),
                          nullable=False)
    report_date = Column(Date, nullable=False)
    contract_type = Column(String, ForeignKey('contract_type_eia923.abbr'))
    contract_expiration_date = Column(Date)
    energy_source = Column(String, ForeignKey('energy_source_eia923.abbr'))
    fuel_type_pudl = Column(String)
    fuel_group = Column(String, ForeignKey('fuel_group_eia923.group'))
    fuel_group_simple = Column(String)
    mine_id_pudl = Column(Integer, ForeignKey('coalmine_eia923.id'))
    supplier = Column(String, nullable=False)  # TODO FK new table?
    fuel_quantity = Column(Float, nullable=False)
    heat_content_mmbtu_per_unit = Column(Float, nullable=False)
    sulfur_content_pct = Column(Float, nullable=False)
    ash_content_pct = Column(Float, nullable=False)
    mercury_content_ppm = Column(Float)
    fuel_cost_per_mmbtu = Column(Float)
    primary_transportation_mode = Column(
        String,
        ForeignKey('transport_modes_eia923.abbr'))
    secondary_transportation_mode = Column(
        String,
        ForeignKey('transport_modes_eia923.abbr'))
    natural_gas_transport = Column(
        String,
        ForeignKey('natural_gas_transport_eia923.abbr'))
    natural_gas_delivery_contract_type = Column(String)
<commit_msg>Removed unused Numeric type import<commit_after>"""Database models for PUDL tables derived from EIA Form 923 Data."""

from sqlalchemy import Boolean, Integer, String, Float, Date
from sqlalchemy import Column, ForeignKey, ForeignKeyConstraint
import pudl.models.entities

###########################################################################
# EIA Form 923 tables which represent constants or metadata
# (e.g. fuel types and fuel units)
###########################################################################

class CoalMineEIA923(pudl.models.entities.PUDLBase):
    """Information pertaining to individual coal mines listed in EIA 923."""

    __tablename__ = 'coalmine_eia923'
    id = Column(Integer, primary_key=True)  # surrogate key
    mine_name = Column(String)
    mine_type = Column(String, ForeignKey('coalmine_type_eia923.abbr'))
    state = Column(String, ForeignKey('coalmine_state_eia923.abbr'))
    # TODO check feasibility t add FK/constants or map to FIPS code used by EIA
    county_id_fips = Column(Integer)
    # TODO check feasibility to add FK/constants or map to MSHA ID# used by EIA
    mine_id_msha = Column(Integer)

class BoilersEIA923(pudl.models.entities.PUDLBase):
    """List of Boiler IDs specific to each plant in EIA Form 923 Page 3."""

    __tablename__ = 'boilers_eia923'
    # __table_args__ = (ForeignKeyConstraint(
    #    ['plant_id_eia', 'boiler_id'],
    #    ['boilers_entity_eia.plant_id_eia',
    #     'boilers_entity_eia.boiler_id']),)
    plant_id_eia = Column(Integer,
                          primary_key=True)
    boiler_id = Column(String, primary_key=True)
    prime_mover = Column(String,
                         ForeignKey('prime_movers_eia923.abbr'),
                         nullable=False)

class GeneratorEIA923(pudl.models.entities.PUDLBase):
    """List of Generator IDs specific to each plant in EIA Form 923 Page 4."""

    __tablename__ = 'generators_eia923'
    __table_args__ = (ForeignKeyConstraint(
        ['plant_id_eia', 'generator_id'],
        ['generators_entity_eia.plant_id_eia',
         'generators_entity_eia.generator_id']),)

    plant_id_eia = Column(Integer, primary_key=True)
    generator_id = Column(String, primary_key=True)
    prime_mover = Column(String,
                         ForeignKey('prime_movers_eia923.abbr'),
                         nullable=False)

class FuelUnitEIA923(pudl.models.entities.PUDLBase):
    """Static list of physical unit labels used by EIA in Form 923."""

    __tablename__ = 'fuel_units_eia923'
    abbr = Column(String, primary_key=True)
    unit = Column(String)

class FuelTypeEIA923(pudl.models.entities.PUDLBase):
    """
    Static list of fuel types used by EIA in Form 923.

    Enumerated on Page 7 of EIA Form 923.
    """

    __tablename__ = 'fuel_type_eia923'
    abbr = Column(String, primary_key=True)
    fuel_type = Column(String, nullable=False)
    fuel_unit = Column(String, ForeignKey('fuel_units_eia923.abbr'))

class FuelGroupEIA923(pudl.models.entities.PUDLBase):
    """Grouping of energy sources into fuel groups, used in EIA Form 923."""

    __tablename__ = 'fuel_group_eia923'
    group = Column(String, primary_key=True)

class RespondentFrequencyEIA923(pudl.models.entities.PUDLBase):
    """
    Plant reporting frequency in EIA Form 923.

    Used by EIA in Form 923, Page 5: Fuel Receipts and Costs
    """

    __tablename__ = 'respondent_frequency_eia923'
    abbr = Column(String, primary_key=True)
    unit = Column(String, nullable=False)

class ContractTypeEIA923(pudl.models.entities.PUDLBase):
    """Type of contract under which fuel receipt occured."""

    __tablename__ = 'contract_type_eia923'
    abbr = Column(String, primary_key=True)
    contract_type = Column(String, nullable=False)

class SectorEIA(pudl.models.entities.PUDLBase):
    """EIA’s internal consolidated NAICS sectors."""

    __tablename__ = 'sector_eia'
    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)

class FuelTypeAER(pudl.models.entities.PUDLBase):
    """Static list of fuel types using AER codes, reported in EIA Form 923."""

    __tablename__ = 'fuel_type_aer_eia923'
    abbr = Column(String, primary_key=True)
    fuel_type = Column(String, nullable=False)

class PrimeMoverEIA923(pudl.models.entities.PUDLBase):
    """Static list of prime movers used by EIA in Form 923."""

    __tablename__ = 'prime_movers_eia923'
    abbr = Column(String, primary_key=True)
    prime_mover = Column(String, nullable=False)

class EnergySourceEIA923(pudl.models.entities.PUDLBase):
    """Fuel code associated with fuel receipts in EIA Form 923."""

    __tablename__ = 'energy_source_eia923'
    abbr = Column(String, primary_key=True)
    source = Column(String, nullable=False)

class CoalMineTypeEIA923(pudl.models.entities.PUDLBase):
    """Type of coal mine, as used in EIA Form 923."""

    __tablename__ = 'coalmine_type_eia923'
    abbr = Column(String, primary_key=True)
    name = Column(String, nullable=False)

class CoalMineStateEIA923(pudl.models.entities.PUDLBase):
    """State and country abbreviations for coal mine locations."""

    __tablename__ = 'coalmine_state_eia923'
    abbr = Column(String, primary_key=True)
    state = Column(String, nullable=False)

class NaturalGasTransportEIA923(pudl.models.entities.PUDLBase):
    """Contract type for natural gas capacity service."""

    __tablename__ = 'natural_gas_transport_eia923'
    abbr = Column(String, primary_key=True)
    status = Column(String, nullable=False)

class TransportModeEIA923(pudl.models.entities.PUDLBase):
    """Mode used for longest & 2nd longest distance in EIA Form 923."""

    __tablename__ = 'transport_modes_eia923'
    abbr = Column(String, primary_key=True)
    mode = Column(String, nullable=False)

###########################################################################
# Tables which represent EIA Form 923 data. E.g. Fuel Receipts.
###########################################################################
class GenerationFuelEIA923(pudl.models.entities.PUDLBase):
    """
    Monthly fuel consumption and electricity generation by plant.

    Reported on Page 1 of EIA Form 923.
    """

    __tablename__ = 'generation_fuel_eia923'

    id = Column(Integer, autoincrement=True, primary_key=True)  # surrogate key
    plant_id_eia = Column(Integer,
                          ForeignKey('plants_entity_eia.plant_id_eia'),
                          nullable=False)
    report_date = Column(Date, nullable=False)
    # TODO: Should nuclear_unit_id really be here? It's kind of part of the
    # plant_id... but also unit_id.  Seems weird but necessary to uniquely
    # identify the records as reported.
    nuclear_unit_id = Column(Integer)
    fuel_type = Column(String,
                       ForeignKey('fuel_type_eia923.abbr'),
                       nullable=False)
    fuel_type_pudl = Column(String)
    aer_fuel_type = Column(String, ForeignKey('fuel_type_aer_eia923.abbr'))
    prime_mover = Column(String,
                         ForeignKey('prime_movers_eia923.abbr'),
                         nullable=False)
    fuel_consumed_total = Column(Float)
    fuel_consumed_for_electricity = Column(Float)
    fuel_mmbtu_per_unit = Column(Float)
    fuel_consumed_total_mmbtu = Column(Float)
    fuel_consumed_for_electricity_mmbtu = Column(Float)
    net_generation_mwh = Column(Float)

class BoilerFuelEIA923(pudl.models.entities.PUDLBase):
    """Monthly fuel consumption by boiler reported on Page 3 of EIA 923."""

    __tablename__ = 'boiler_fuel_eia923'
    # __table_args__ = (ForeignKeyConstraint(
    #    ['plant_id_eia', 'boiler_id'],
    #    ['boilers_entity_eia.plant_id_eia',
    #     'boilers_entity_eia.boiler_id']),)

    # Each month, for each unique combination of boiler id and prime mover and
    # fuel, there is one report for each boiler unit in each plant.

    id = Column(Integer, autoincrement=True, primary_key=True)  # surrogate key
    plant_id_eia = Column(Integer, nullable=False)
    boiler_id = Column(String, nullable=False)
    prime_mover = Column(String, ForeignKey('prime_movers_eia923.abbr'),
                         nullable=False)
    fuel_type = Column(String, ForeignKey('fuel_type_eia923.abbr'),
                       nullable=False)
    fuel_type_pudl = Column(String)
    report_date = Column(Date, nullable=False)
    fuel_qty_consumed = Column(Float)
    fuel_mmbtu_per_unit = Column(Float)
    sulfur_content_pct = Column(Float)
    ash_content_pct = Column(Float)

class GenerationEIA923(pudl.models.entities.PUDLBase):
    """Monthly electricity generation by generator from EIA923 Page 4."""

    __tablename__ = 'generation_eia923'
    __table_args__ = (ForeignKeyConstraint(
        ['plant_id_eia', 'generator_id'],
        ['generators_entity_eia.plant_id_eia',
         'generators_entity_eia.generator_id']),)

    # Each month, for each unique combination of generator id and prime mover
    # and fuel,there is one report for each generator unit in each plant.
    id = Column(Integer, autoincrement=True, primary_key=True)  # surrogate key
    plant_id_eia = Column(Integer, nullable=False)
    # TODO remove prime_mover since it's specific to generator_id?
    prime_mover = Column(String, ForeignKey('prime_movers_eia923.abbr'),
                         nullable=False)
    # TODO: Add FK constraint refering to (plant_id, generator_id) in the
    # generators_eia923 table.  Or at least give it a shot.
    generator_id = Column(String, nullable=False)
    report_date = Column(Date, nullable=False)
    net_generation_mwh = Column(Float)

class FuelReceiptsCostsEIA923(pudl.models.entities.PUDLBase):
    """Fuel receipts & costs by plant &purchase from Page 5 of EIA Form 923."""

    __tablename__ = 'fuel_receipts_costs_eia923'

    # surrogate key
    fuel_receipt_id = Column(Integer, primary_key=True, autoincrement=True)
    plant_id_eia = Column(Integer,
                          ForeignKey('plants_entity_eia.plant_id_eia'),
                          nullable=False)
    report_date = Column(Date, nullable=False)
    contract_type = Column(String, ForeignKey('contract_type_eia923.abbr'))
    contract_expiration_date = Column(Date)
    energy_source = Column(String, ForeignKey('energy_source_eia923.abbr'))
    fuel_type_pudl = Column(String)
    fuel_group = Column(String, ForeignKey('fuel_group_eia923.group'))
    fuel_group_simple = Column(String)
    mine_id_pudl = Column(Integer, ForeignKey('coalmine_eia923.id'))
    supplier = Column(String, nullable=False)  # TODO FK new table?
    fuel_quantity = Column(Float, nullable=False)
    heat_content_mmbtu_per_unit = Column(Float, nullable=False)
    sulfur_content_pct = Column(Float, nullable=False)
    ash_content_pct = Column(Float, nullable=False)
    mercury_content_ppm = Column(Float)
    fuel_cost_per_mmbtu = Column(Float)
    primary_transportation_mode = Column(
        String,
        ForeignKey('transport_modes_eia923.abbr'))
    secondary_transportation_mode = Column(
        String,
        ForeignKey('transport_modes_eia923.abbr'))
    natural_gas_transport = Column(
        String,
        ForeignKey('natural_gas_transport_eia923.abbr'))
    natural_gas_delivery_contract_type = Column(String)
<|endoftext|>


<commit_before>import copy
from .base import (BaseModel, SourceMixin, LinkMixin, ContactDetailMixin, OtherNameMixin,
                   IdentifierMixin)
from .schemas.post import schema as post_schema
from .schemas.person import schema as person_schema
from .schemas.membership import schema as membership_schema
from .schemas.organization import schema as org_schema
from ..utils import make_psuedo_id

# a copy of the org schema without sources
org_schema_no_sources = copy.deepcopy(org_schema)
org_schema_no_sources['properties'].pop('sources')

class Post(BaseModel, LinkMixin, ContactDetailMixin):
    """
    A popolo-style Post
    """

    _type = 'post'
    _schema = post_schema

    def __init__(self, *, label, role, organization_id=None, chamber=None,
                 start_date='', end_date=''):
        super(Post, self).__init__()
        self.label = label
        self.role = role
        self.organization_id = psuedo_organization(organization_id, chamber)
        self.start_date = start_date
        self.end_date = end_date

    def __str__(self):
        return self.label

class Membership(BaseModel, ContactDetailMixin, LinkMixin):
    """
    A popolo-style Membership.
    """

    _type = 'membership'
    _schema = membership_schema

    def __init__(self, *, person_id, organization_id, post_id=None, role='', label='',
                 start_date='', end_date='', on_behalf_of_id=None):
        """
        Constructor for the Membership object.

        We require a person ID and organization ID, as required by the
        popolo spec. Additional arguments may be given, which match those
        defined by popolo.
        """
        super(Membership, self).__init__()
        self.person_id = person_id
        self.organization_id = organization_id
        self.post_id = post_id
        self.start_date = start_date
        self.end_date = end_date
        self.role = role
        self.label = label
        self.on_behalf_of_id = on_behalf_of_id

    def __str__(self):
        return self.person_id + ' membership in ' + self.organization_id

class Person(BaseModel, SourceMixin, ContactDetailMixin, LinkMixin, IdentifierMixin,
             OtherNameMixin):
    """
    Details for a Person in Popolo format.
    """

    _type = 'person'
    _schema = person_schema

    def __init__(self, name, *, birth_date='', death_date='', biography='', summary='', image='',
                 gender='', national_identity='',
                 # specialty fields
                 district=None, party=None, primary_org='', start_date='', end_date=''):
        super(Person, self).__init__()
        self.name = name
        self.birth_date = birth_date
        self.death_date = death_date
        self.biography = biography
        self.summary = summary
        self.image = image
        self.gender = gender
        self.national_identity = national_identity
        if primary_org:
            self.add_term('member', primary_org, district=district,
                          start_date=start_date, end_date=end_date)
        if party:
            self.add_party(party)

    def add_membership(self, organization, role='member', **kwargs):
        """
            add a membership in an organization and return the membership
            object in case there are more details to add
        """
        membership = Membership(person_id=self._id, organization_id=organization._id,
                                role=role, **kwargs)
        self._related.append(membership)
        return membership

    def add_party(self, party, **kwargs):
        membership = Membership(
            person_id=self._id,
            organization_id=make_psuedo_id(classification="party", name=party),
            role='member', **kwargs)
        self._related.append(membership)

    def add_term(self, role, org_classification, *, district=None, start_date='', end_date=''):
        org_id = make_psuedo_id(classification=org_classification)
        if district:
            post_id = make_psuedo_id(label=district,
                                     organization__classification=org_classification)
        else:
            post_id = None
        membership = Membership(person_id=self._id, organization_id=org_id, post_id=post_id,
                                role=role, start_date=start_date, end_date=end_date)
        self._related.append(membership)

    def __str__(self):
        return self.name

class Organization(BaseModel, SourceMixin, ContactDetailMixin, LinkMixin, IdentifierMixin,
                   OtherNameMixin):
    """
    A single popolo-style Organization
    """

    _type = 'organization'
    _schema = org_schema

    def __init__(self, name, *, classification='', parent_id=None,
                 founding_date='', dissolution_date='', image='',
                 chamber=None):
        """
        Constructor for the Organization object.
        """
        super(Organization, self).__init__()
        self.name = name
        self.classification = classification
        self.founding_date = founding_date
        self.dissolution_date = dissolution_date
        self.parent_id = psuedo_organization(parent_id, chamber)
        self.image = image

    def __str__(self):
        return self.name

    def validate(self):
        schema = None
        # these are implicitly declared & do not require sources
        if self.classification in ('party', 'legislature', 'upper', 'lower', 'executive'):
            schema = org_schema_no_sources
        return super(Organization, self).validate(schema=schema)

    def add_post(self, label, role, **kwargs):
        post = Post(label=label, role=role, organization_id=self._id, **kwargs)
        self._related.append(post)
        return post

    def add_member(self, name_or_person, role='member', **kwargs):
        if isinstance(name_or_person, Person):
            membership = Membership(person_id=name_or_person._id, organization_id=self._id,
                                    role=role, **kwargs)
        else:
            membership = Membership(person_id=make_psuedo_id(name=name_or_person),
                                    organization_id=self._id, role=role, **kwargs)
        self._related.append(membership)
        return membership

def psuedo_organization(organization, classification, default=None):
    """ helper for setting an appropriate ID for organizations """
    if organization and classification:
        raise ValueError('cannot specify both classification and organization')
    elif classification:
        return make_psuedo_id(classification=classification)
    elif organization:
        if isinstance(organization, Organization):
            return organization._id
        elif isinstance(organization, str):
            return organization
        else:
            return make_psuedo_id(**organization)
    elif default is not None:
        return make_psuedo_id(classification=default)
    else:
        return None
<commit_msg>allow label argument for add_term<commit_after>import copy
from .base import (BaseModel, SourceMixin, LinkMixin, ContactDetailMixin, OtherNameMixin,
                   IdentifierMixin)
from .schemas.post import schema as post_schema
from .schemas.person import schema as person_schema
from .schemas.membership import schema as membership_schema
from .schemas.organization import schema as org_schema
from ..utils import make_psuedo_id

# a copy of the org schema without sources
org_schema_no_sources = copy.deepcopy(org_schema)
org_schema_no_sources['properties'].pop('sources')

class Post(BaseModel, LinkMixin, ContactDetailMixin):
    """
    A popolo-style Post
    """

    _type = 'post'
    _schema = post_schema

    def __init__(self, *, label, role, organization_id=None, chamber=None,
                 start_date='', end_date=''):
        super(Post, self).__init__()
        self.label = label
        self.role = role
        self.organization_id = psuedo_organization(organization_id, chamber)
        self.start_date = start_date
        self.end_date = end_date

    def __str__(self):
        return self.label

class Membership(BaseModel, ContactDetailMixin, LinkMixin):
    """
    A popolo-style Membership.
    """

    _type = 'membership'
    _schema = membership_schema

    def __init__(self, *, person_id, organization_id, post_id=None, role='', label='',
                 start_date='', end_date='', on_behalf_of_id=None):
        """
        Constructor for the Membership object.

        We require a person ID and organization ID, as required by the
        popolo spec. Additional arguments may be given, which match those
        defined by popolo.
        """
        super(Membership, self).__init__()
        self.person_id = person_id
        self.organization_id = organization_id
        self.post_id = post_id
        self.start_date = start_date
        self.end_date = end_date
        self.role = role
        self.label = label
        self.on_behalf_of_id = on_behalf_of_id

    def __str__(self):
        return self.person_id + ' membership in ' + self.organization_id

class Person(BaseModel, SourceMixin, ContactDetailMixin, LinkMixin, IdentifierMixin,
             OtherNameMixin):
    """
    Details for a Person in Popolo format.
    """

    _type = 'person'
    _schema = person_schema

    def __init__(self, name, *, birth_date='', death_date='', biography='', summary='', image='',
                 gender='', national_identity='',
                 # specialty fields
                 district=None, party=None, primary_org='', start_date='', end_date=''):
        super(Person, self).__init__()
        self.name = name
        self.birth_date = birth_date
        self.death_date = death_date
        self.biography = biography
        self.summary = summary
        self.image = image
        self.gender = gender
        self.national_identity = national_identity
        if primary_org:
            self.add_term('member', primary_org, district=district,
                          start_date=start_date, end_date=end_date)
        if party:
            self.add_party(party)

    def add_membership(self, organization, role='member', **kwargs):
        """
            add a membership in an organization and return the membership
            object in case there are more details to add
        """
        membership = Membership(person_id=self._id, organization_id=organization._id,
                                role=role, **kwargs)
        self._related.append(membership)
        return membership

    def add_party(self, party, **kwargs):
        membership = Membership(
            person_id=self._id,
            organization_id=make_psuedo_id(classification="party", name=party),
            role='member', **kwargs)
        self._related.append(membership)

    def add_term(self, role, org_classification, *, district=None, start_date='', end_date='',
                 label=''):
        org_id = make_psuedo_id(classification=org_classification)
        if district:
            post_id = make_psuedo_id(label=district,
                                     organization__classification=org_classification)
        else:
            post_id = None
        membership = Membership(person_id=self._id, organization_id=org_id, post_id=post_id,
                                role=role, start_date=start_date, end_date=end_date, label=label)
        self._related.append(membership)

    def __str__(self):
        return self.name

class Organization(BaseModel, SourceMixin, ContactDetailMixin, LinkMixin, IdentifierMixin,
                   OtherNameMixin):
    """
    A single popolo-style Organization
    """

    _type = 'organization'
    _schema = org_schema

    def __init__(self, name, *, classification='', parent_id=None,
                 founding_date='', dissolution_date='', image='',
                 chamber=None):
        """
        Constructor for the Organization object.
        """
        super(Organization, self).__init__()
        self.name = name
        self.classification = classification
        self.founding_date = founding_date
        self.dissolution_date = dissolution_date
        self.parent_id = psuedo_organization(parent_id, chamber)
        self.image = image

    def __str__(self):
        return self.name

    def validate(self):
        schema = None
        # these are implicitly declared & do not require sources
        if self.classification in ('party', 'legislature', 'upper', 'lower', 'executive'):
            schema = org_schema_no_sources
        return super(Organization, self).validate(schema=schema)

    def add_post(self, label, role, **kwargs):
        post = Post(label=label, role=role, organization_id=self._id, **kwargs)
        self._related.append(post)
        return post

    def add_member(self, name_or_person, role='member', **kwargs):
        if isinstance(name_or_person, Person):
            membership = Membership(person_id=name_or_person._id, organization_id=self._id,
                                    role=role, **kwargs)
        else:
            membership = Membership(person_id=make_psuedo_id(name=name_or_person),
                                    organization_id=self._id, role=role, **kwargs)
        self._related.append(membership)
        return membership

def psuedo_organization(organization, classification, default=None):
    """ helper for setting an appropriate ID for organizations """
    if organization and classification:
        raise ValueError('cannot specify both classification and organization')
    elif classification:
        return make_psuedo_id(classification=classification)
    elif organization:
        if isinstance(organization, Organization):
            return organization._id
        elif isinstance(organization, str):
            return organization
        else:
            return make_psuedo_id(**organization)
    elif default is not None:
        return make_psuedo_id(classification=default)
    else:
        return None
<|endoftext|>