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

import numpy as np

def parent(i):
    return i // 2

def left(i):
    return 2 * i

def right(i):
    return 2 * i + 1

class MinPriorityQueue(object):
    """Min Priority Queue."""
    def __init__(self):
        self.heap_ls = [(0, 0)]
        self.heap_size = 0

    def show(self):
        print(self.heap_ls)

    def min_heapify(self, i):
        l = left(i)
        r = right(i)
        if l <= self.heap_size and self.heap_ls[l][0] < self.heap_ls[i][0]:
            min_i = l
        if r <= self.heap_size and self.heap_ls[r][0] < self.heap_ls[minimum][0]:
            min_i = r
        if min_i != i:
            self.heap_ls[i][1], self.heap_ls[min_i][1] = (
                self.heap_ls[min_i][1], self.heap_ls[i][1])
            self.min_heapify(min_i)

    def find_min(self):
        return self.heap_ls[1]

    def extract_min(self):
        if self.heap_size < 1:
            raise ValueError('Heap underflow.')
        minimum = self.heap_ls[1]
        self.heap_ls[1] = self.heap_ls.pop()
        self.heap_size -= 1
        self.min_heapify(1)
        return minimum

    # TODO.
    def decrease_key(self, i, key):
        if key > self.heap_ls[i]:
            raise ValueError('New key is larger than current key.')
        self.heap_ls[i] = key
        while i > 1 and self.heap_ls[parent(i)] > self.heap_ls[i]:
            self.heap_ls[i], self.heap_ls[parent(i)] = (
                self.heap_ls[parent(i)], self.heap_ls[i])
            i = parent(i)

    def insert(self, key):
        self.heap_size += 1
        self.heap_ls.append(np.inf)
        self.decrease_key(self.heap_size, key)

def main():
    min_pq = MinPriorityQueue()

    # Insert sequentially [16, 14, 10, 8, 7, 9, 3, 2, 6, 1]
    print('Insert 5')
    min_pq.insert(5)
    min_pq.show()

    print('Insert 7')
    min_pq.insert(7)
    min_pq.show()

    print('Insert 3')
    min_pq.insert(3)
    min_pq.show()

    print('Insert 1')
    min_pq.insert(1)
    min_pq.show()

    # Decrease key 7 at position 4 to 2.
    print('Decrease key 7 at position 4 to 2.')
    min_pq.decrease_key(4, 2)
    min_pq.show()

if __name__ == '__main__':
    main()
<commit_msg>Revise typo: minimum -> min_i and add missing min_i in else.<commit_after>from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import numpy as np

def parent(i):
    return i // 2

def left(i):
    return 2 * i

def right(i):
    return 2 * i + 1

class MinPriorityQueue(object):
    """Min Priority Queue."""
    def __init__(self):
        self.heap_ls = [(0, 0)]
        self.heap_size = 0

    def show(self):
        print(self.heap_ls)

    def min_heapify(self, i):
        l = left(i)
        r = right(i)
        if l <= self.heap_size and self.heap_ls[l][0] < self.heap_ls[i][0]:
            min_i = l
        else:
            min_i = i
        if r <= self.heap_size and self.heap_ls[r][0] < self.heap_ls[min_i][0]:
            min_i = r
        if min_i != i:
            self.heap_ls[i][1], self.heap_ls[min_i][1] = (
                self.heap_ls[min_i][1], self.heap_ls[i][1])
            self.min_heapify(min_i)

    def find_min(self):
        return self.heap_ls[1]

    def extract_min(self):
        if self.heap_size < 1:
            raise ValueError('Heap underflow.')
        minimum = self.heap_ls[1]
        self.heap_ls[1] = self.heap_ls.pop()
        self.heap_size -= 1
        self.min_heapify(1)
        return minimum

    # TODO.
    def decrease_key(self, i, key):
        if key > self.heap_ls[i]:
            raise ValueError('New key is larger than current key.')
        self.heap_ls[i] = key
        while i > 1 and self.heap_ls[parent(i)] > self.heap_ls[i]:
            self.heap_ls[i], self.heap_ls[parent(i)] = (
                self.heap_ls[parent(i)], self.heap_ls[i])
            i = parent(i)

    def insert(self, key):
        self.heap_size += 1
        self.heap_ls.append(np.inf)
        self.decrease_key(self.heap_size, key)

def main():
    min_pq = MinPriorityQueue()

    # Insert sequentially [16, 14, 10, 8, 7, 9, 3, 2, 6, 1]
    print('Insert 5')
    min_pq.insert(5)
    min_pq.show()

    print('Insert 7')
    min_pq.insert(7)
    min_pq.show()

    print('Insert 3')
    min_pq.insert(3)
    min_pq.show()

    print('Insert 1')
    min_pq.insert(1)
    min_pq.show()

    # Decrease key 7 at position 4 to 2.
    print('Decrease key 7 at position 4 to 2.')
    min_pq.decrease_key(4, 2)
    min_pq.show()

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


<commit_before>"""Configuration for Django system."""

__version__ = "0.16.1"
__version_info__ = tuple(
    [
        int(num) if num.isdigit() else num
        for num in __version__.replace("-", ".", 1).split(".")
    ]
)
<commit_msg>Increment version number<commit_after>"""Configuration for Django system."""

__version__ = "0.16.2"
__version_info__ = tuple(
    [
        int(num) if num.isdigit() else num
        for num in __version__.replace("-", ".", 1).split(".")
    ]
)
<|endoftext|>


<commit_before>#   Copyright (c) 2006-2007 Open Source Applications Foundation
#
#   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 windmill

from httplib import HTTPConnection
from urlparse import urlparse
import copy
import logging

logger = logging.getLogger(__name__)

# Note that hoppish conntains proxy-connection, which is pre-HTTP-1.1 and is somewhat nebulous
_hoppish = {
    'connection':1, 'keep-alive':1, 'proxy-authenticate':1,
    'proxy-authorization':1, 'te':1, 'trailers':1, 'transfer-encoding':1,
    'upgrade':1, 'proxy-connection':1,
    'p3p':1 #Not actually a hop-by-hop header, just really annoying
    }

def is_hop_by_hop(header):
    """check if the given header is hop_by_hop"""
    return _hoppish.has_key(header.lower())

initial_forwarding_registry = {}
forwarding_registry = {}

class IterativeResponse(object):
    def __init__(self, response_instance):
        self.response_instance = response_instance

    def __iter__(self):
        if self.response_instance.chunked:
            yield self.response_instance.read(1024)
            while self.response_instance.chunk_left is not None:
                if self.response_instance.chunk_left < 1024:
                    yield self.response_instance.read(self.response_instance.chunk_left)
                else:
                    yield self.response_instance.read(1024)
        else:
            yield self.response_instance.read()

class WindmillProxyApplication(object):
    """Application to handle requests that need to be proxied"""

    ConnectionClass = HTTPConnection

    def handler(self, environ, start_response):
        """Proxy for requests to the actual http server"""
        url = urlparse(environ['reconstructed_url'])

        def change_environ_domain(original_netloc, new_netloc, environ):
            """Swap out the domain for a given request environ"""
            new_environ = {}
            for key, value in environ.items():
                if ( type(value) is str ) and ( value.find(original_netloc) is not -1 ):
                    new_environ[key] = value.replace(original_netloc, new_netloc)
                else:
                    new_environ[key] = value
            return new_environ

        # Once FORWARDING_TEST_URL is set we should check for cross-domain forward
        # but we must disable for localhost as redirects to localhost will cause the browser
        # to error.
        if windmill.settings['FORWARDING_TEST_URL'] is not None and (
           not url.netloc.startswith('localhost') ) and (
           not url.netloc.startswith('127.0.0.1') ):
            # Do our domain change magic

            test_netloc = urlparse(windmill.settings['FORWARDING_TEST_URL']).netloc
            referer = environ.get('HTTP_REFERER', None)

            if ( url.netloc != test_netloc ):
                # if the url's network address is not the test URL that has been set we need to return
                # a forward
                initial_forwarding_registry[url.geturl().replace(url.netloc, test_netloc)] = url.netloc
                start_response("302 Found", [('Content-Type', 'text/plain'),
                                             ('Location', url.geturl().replace(url.netloc, test_netloc) )])
                logger.debug('New domain request, forwarded to '+url.geturl().replace(url.netloc, test_netloc))
                return ['Windmill is forwarding you to a new url at the proper test domain']

            elif ( url.geturl() in initial_forwarding_registry.keys() ):
                # This handles the first case where a forward is returned to the browser
                host_netloc = initial_forwarding_registry.get(url.geturl())
                forwarding_registry[url.geturl()] = host_netloc
                environ = change_environ_domain(url.netloc, host_netloc, environ)
                url = urlparse(url.geturl().replace(url.netloc, host_netloc))

            elif (referer is not None) and (referer in forwarding_registry.keys()):
                # This handles the case that the referer is a url we've already
                # done a cross-domain request for
                host_netloc = forwarding_registry[referer]
                forwarding_registry[url.geturl()] = host_netloc
                environ = change_environ_domain(url.netloc, host_netloc, environ)
                url = urlparse(url.geturl().replace(url.netloc, host_netloc))

        def make_remote_connection(url, environ):
            # Create connection object
            try:
                connection = self.ConnectionClass(url.netloc)
                # Build path
                path = url.geturl().replace(url.scheme+'://'+url.netloc, '')
            except Exception, e:
                logger.exception('Could not Connect')
                return [("501 Gateway error", [('Content-Type', 'text/html')],), '
Could not connect
']

            # Read in request body if it exists
            body = None
            if environ.get('CONTENT_LENGTH'):
                length = int(environ['CONTENT_LENGTH'])
                body = environ['wsgi.input'].read(length)

            # Build headers
            headers = {}
            logger.debug('Environ ; %s' % str(environ))
            for key in environ.keys():
                # Keys that start with HTTP_ are all headers
                if key.startswith('HTTP_'):
                    # This is a hacky way of getting the header names right
                    value = environ[key]
                    key = key.replace('HTTP_', '', 1).swapcase().replace('_', '-')
                    if is_hop_by_hop(key) is False:
                        headers[key] = value

            # Handler headers that aren't HTTP_ in environ
            if environ.get('CONTENT_TYPE'):
                headers['content-type'] = environ['CONTENT_TYPE']

            # Add our host if one isn't defined
            if not headers.has_key('host'):
                headers['host'] = environ['SERVER_NAME']

            # Make the remote request
            try:
                logger.debug('%s %s %s' % (environ['REQUEST_METHOD'], path, str(headers)))
                connection.request(environ['REQUEST_METHOD'], path, body=body, headers=headers)
                return connection
            except:
                # We need extra exception handling in the case the server fails in mid connection, it's an edge case but I've seen it
                logger.info('Could not fullfill proxy request to %s' % url.geturl())
                return [("501 Gateway error", [('Content-Type', 'text/html')],), '
Could not connect
']

        def retry_known_hosts(url, environ):
            # retry the given request against all the hosts the current session has run against
            hosts = copy.copy(initial_forwarding_registry.values())
            hosts.reverse()
            current_host = url.netloc
            for host in hosts:
                connection = make_remote_connection(urlparse(url.geturl().replace(current_host, host)),
                                                    change_environ_domain(current_host, host, environ))
                if isinstance(connection, HTTPConnection):
                    new_response = connection.getresponse()
                    if new_response.status > 199 and new_response.status < 399:
                        logger.debug('retry success, '+url.geturl()+' to '+host)
                        return new_response
            return None

        connection = make_remote_connection(url, environ)
        if not isinstance(connection, HTTPConnection):
            # if it's not an HTTPConnection object then the request failed so we should retry
            new_response = retry_known_hosts(url, environ)
            if new_response is not None:
                response = new_response
            else:
                start_response(*connection.pop(0))
                return [connection.pop(0)]
        else:
            response = connection.getresponse()

        if response.status == 404:
            # If the response is 404 we should retry against the known hosts
            # this is usually the case when the referrer is ommitted by the browser
            # for random reasons
            new_response = retry_known_hosts(url, environ)
            if new_response is not None:
                response = new_response

        # Remove hop by hop headers
        hopped_headers = response.getheaders()
        headers = copy.copy(hopped_headers)
        for header in hopped_headers:
            if is_hop_by_hop(header[0]):
                headers.remove(header)

        start_response(response.status.__str__()+' '+response.reason, headers)
        return IterativeResponse(response)

    def __call__(self, environ, start_response):
        return self.handler(environ, start_response)<commit_msg>Fix for proxy chunked reads.<commit_after>#   Copyright (c) 2006-2007 Open Source Applications Foundation
#
#   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 windmill

from httplib import HTTPConnection
from urlparse import urlparse
import copy
import logging

logger = logging.getLogger(__name__)

# Note that hoppish conntains proxy-connection, which is pre-HTTP-1.1 and is somewhat nebulous
_hoppish = {
    'connection':1, 'keep-alive':1, 'proxy-authenticate':1,
    'proxy-authorization':1, 'te':1, 'trailers':1, 'transfer-encoding':1,
    'upgrade':1, 'proxy-connection':1,
    'p3p':1 #Not actually a hop-by-hop header, just really annoying
    }

def is_hop_by_hop(header):
    """check if the given header is hop_by_hop"""
    return _hoppish.has_key(header.lower())

initial_forwarding_registry = {}
forwarding_registry = {}

class IterativeResponse(object):
    def __init__(self, response_instance):
        self.response_instance = response_instance

    def __iter__(self):
        if self.response_instance.chunked:
            yield self.response_instance.read(1024)
            while self.response_instance.chunk_left is not None:
                if self.response_instance.chunk_left < 1024:
                    yield self.response_instance.read()
                    self.response_instance.chunk_left = None
                else:
                    yield self.response_instance.read(1024)
        else:
            yield self.response_instance.read()

class WindmillProxyApplication(object):
    """Application to handle requests that need to be proxied"""

    ConnectionClass = HTTPConnection

    def handler(self, environ, start_response):
        """Proxy for requests to the actual http server"""
        url = urlparse(environ['reconstructed_url'])

        def change_environ_domain(original_netloc, new_netloc, environ):
            """Swap out the domain for a given request environ"""
            new_environ = {}
            for key, value in environ.items():
                if ( type(value) is str ) and ( value.find(original_netloc) is not -1 ):
                    new_environ[key] = value.replace(original_netloc, new_netloc)
                else:
                    new_environ[key] = value
            return new_environ

        # Once FORWARDING_TEST_URL is set we should check for cross-domain forward
        # but we must disable for localhost as redirects to localhost will cause the browser
        # to error.
        if windmill.settings['FORWARDING_TEST_URL'] is not None and (
           not url.netloc.startswith('localhost') ) and (
           not url.netloc.startswith('127.0.0.1') ):
            # Do our domain change magic

            test_netloc = urlparse(windmill.settings['FORWARDING_TEST_URL']).netloc
            referer = environ.get('HTTP_REFERER', None)

            if ( url.netloc != test_netloc ):
                # if the url's network address is not the test URL that has been set we need to return
                # a forward
                initial_forwarding_registry[url.geturl().replace(url.netloc, test_netloc)] = url.netloc
                start_response("302 Found", [('Content-Type', 'text/plain'),
                                             ('Location', url.geturl().replace(url.netloc, test_netloc) )])
                logger.debug('New domain request, forwarded to '+url.geturl().replace(url.netloc, test_netloc))
                return ['Windmill is forwarding you to a new url at the proper test domain']

            elif ( url.geturl() in initial_forwarding_registry.keys() ):
                # This handles the first case where a forward is returned to the browser
                host_netloc = initial_forwarding_registry.get(url.geturl())
                forwarding_registry[url.geturl()] = host_netloc
                environ = change_environ_domain(url.netloc, host_netloc, environ)
                url = urlparse(url.geturl().replace(url.netloc, host_netloc))

            elif (referer is not None) and (referer in forwarding_registry.keys()):
                # This handles the case that the referer is a url we've already
                # done a cross-domain request for
                host_netloc = forwarding_registry[referer]
                forwarding_registry[url.geturl()] = host_netloc
                environ = change_environ_domain(url.netloc, host_netloc, environ)
                url = urlparse(url.geturl().replace(url.netloc, host_netloc))

        def make_remote_connection(url, environ):
            # Create connection object
            try:
                connection = self.ConnectionClass(url.netloc)
                # Build path
                path = url.geturl().replace(url.scheme+'://'+url.netloc, '')
            except Exception, e:
                logger.exception('Could not Connect')
                return [("501 Gateway error", [('Content-Type', 'text/html')],), '
Could not connect
']

            # Read in request body if it exists
            body = None
            if environ.get('CONTENT_LENGTH'):
                length = int(environ['CONTENT_LENGTH'])
                body = environ['wsgi.input'].read(length)

            # Build headers
            headers = {}
            logger.debug('Environ ; %s' % str(environ))
            for key in environ.keys():
                # Keys that start with HTTP_ are all headers
                if key.startswith('HTTP_'):
                    # This is a hacky way of getting the header names right
                    value = environ[key]
                    key = key.replace('HTTP_', '', 1).swapcase().replace('_', '-')
                    if is_hop_by_hop(key) is False:
                        headers[key] = value

            # Handler headers that aren't HTTP_ in environ
            if environ.get('CONTENT_TYPE'):
                headers['content-type'] = environ['CONTENT_TYPE']

            # Add our host if one isn't defined
            if not headers.has_key('host'):
                headers['host'] = environ['SERVER_NAME']

            # Make the remote request
            try:
                logger.debug('%s %s %s' % (environ['REQUEST_METHOD'], path, str(headers)))
                connection.request(environ['REQUEST_METHOD'], path, body=body, headers=headers)
                return connection
            except:
                # We need extra exception handling in the case the server fails in mid connection, it's an edge case but I've seen it
                logger.info('Could not fullfill proxy request to %s' % url.geturl())
                return [("501 Gateway error", [('Content-Type', 'text/html')],), '
Could not connect
']

        def retry_known_hosts(url, environ):
            # retry the given request against all the hosts the current session has run against
            hosts = copy.copy(initial_forwarding_registry.values())
            hosts.reverse()
            current_host = url.netloc
            for host in hosts:
                connection = make_remote_connection(urlparse(url.geturl().replace(current_host, host)),
                                                    change_environ_domain(current_host, host, environ))
                if isinstance(connection, HTTPConnection):
                    new_response = connection.getresponse()
                    if new_response.status > 199 and new_response.status < 399:
                        logger.debug('retry success, '+url.geturl()+' to '+host)
                        return new_response
            return None

        connection = make_remote_connection(url, environ)
        if not isinstance(connection, HTTPConnection):
            # if it's not an HTTPConnection object then the request failed so we should retry
            new_response = retry_known_hosts(url, environ)
            if new_response is not None:
                response = new_response
            else:
                start_response(*connection.pop(0))
                return [connection.pop(0)]
        else:
            response = connection.getresponse()

        if response.status == 404:
            # If the response is 404 we should retry against the known hosts
            # this is usually the case when the referrer is ommitted by the browser
            # for random reasons
            new_response = retry_known_hosts(url, environ)
            if new_response is not None:
                response = new_response

        # Remove hop by hop headers
        hopped_headers = response.getheaders()
        headers = copy.copy(hopped_headers)
        for header in hopped_headers:
            if is_hop_by_hop(header[0]):
                headers.remove(header)

        start_response(response.status.__str__()+' '+response.reason, headers)
        return IterativeResponse(response)

    def __call__(self, environ, start_response):
        return self.handler(environ, start_response)<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from django.db import models
from django.core.exceptions import ValidationError
from choices_functional_trait import *
from choices_models import CHOICES_ALL_COUNTRIES, CHOICES_georefMethod
from choices_taxonomy import *
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.core.exceptions import NON_FIELD_ERRORS

class reference(models.Model):
    authorshortstring = models.CharField(max_length=100)
    year = models.IntegerField()
    journal = models.CharField(max_length=100, blank=True, null=True)
    volume = models.IntegerField(max_length=5, blank=True, null=True)
    issue = models.IntegerField(max_length=5, blank=True, null=True)
    pages = models.CharField(max_length=20, blank=True, null=True)
    doi = models.CharField(max_length=100, blank=True, null=True)
    dataEntryComplete = models.NullBooleanField(blank=True, default=False)

    def __unicode__(self):
        # if self.dataEntryComplete:
        #     name = self.authorshortstring + ", " + str(self.year) + " - Data Entry Complete"
        # else:
        #     name = self.authorshortstring + ", " + str(self.year)
        name = self.authorshortstring + ", " + str(self.year)
        return name

    class Meta:
        db_table = 'reference'

class taxonomy(models.Model):
    kingdom = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_KINGDOM, default="Animalia")
    phylum = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_PHYLUM, default="Chordata")
    tclass = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_CLASS, verbose_name="class")
    order = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_ORDER)
    family = models.CharField(max_length=100, null=True, blank=True)
    subfamily = models.CharField(max_length=100, null=True, blank=True)
    tribe = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_tribe)
    genus = models.CharField(max_length=100, null=True, blank=True, verbose_name = "genus")
    species = models.CharField(max_length=100, null=True, blank=True, verbose_name = "species")
    infraspecificEpithet = models.CharField(max_length=100, null=True, blank=True)
    identificationQualifier = models.CharField(max_length=100, null=True, blank=True)
    extant = models.BooleanField()
    commonName = models.CharField(max_length=100, null=True, blank=True)
    synonyms = models.CharField(max_length=2000, null=True, blank=True)
    taxonRank = models.CharField(max_length=100, null=True, blank=False, choices=CHOICES_RANK)
    ref = models.ForeignKey(reference)
    Fernandez_Vrba_2005_Name = models.CharField(max_length=255, null=True, blank=True)
    BinindaEmonds_2008_Name = models.CharField(max_length=255, null=True, blank=True)
    #habitat = models.CharField(max_length=25, null=True, blank=True, choices = CHOICES_HABITAT)
    #diet = models.CharField(max_length=25, null=True, blank=True, choices = CHOICES_DIET)

    class Meta:
        db_table = 'taxonomy'
        verbose_name = "taxon"
        verbose_name_plural = "taxa"
        unique_together = ['tclass','order','family','subfamily','tribe','genus','species','infraspecificEpithet','taxonRank','identificationQualifier']

    def __unicode__(self):
        if str(self.taxonRank).lower() == 'tclass':
            name =  self.tclass + " (class)"
        elif str(self.taxonRank).lower() == 'order':
            name =  self.order + " (" + self.taxonRank + ")"
        elif str(self.taxonRank).lower() == 'family':
            name =  self.family + " (" + self.taxonRank + ")"
        elif str(self.taxonRank).lower() == 'subfamily':
            name =   self.subfamily + " (" + self.taxonRank + ")"
        elif str(self.taxonRank).lower() == 'tribe':
            name =   self.tribe + " (" + self.taxonRank + ")"
        elif str(self.taxonRank).lower() == 'genus':
            name =   self.genus + " (" + self.taxonRank + ")"
        elif str(self.taxonRank).lower() == 'species':
            name =   self.genus + " " + self.species + " (" + self.taxonRank + ")"
        elif str(self.taxonRank).lower() == 'subspecies':
            name =  self.genus + " " + self.species + " " + self.infraspecificEpithet + " (" + self.taxonRank + ")"
        else:
            name =  " (" + self.taxonRank + ")"

        if self.identificationQualifier:
            name = self.identificationQualifier + " " + name

        if not self.extant:
            name += u" ✝"

        return name

    def validate_implied_taxon(self,rankString, **kwargs):
        modelFieldName = kwargs.keys()[0] #need to do some tests here!
        if getattr(self,modelFieldName):
            try:
                taxonomy.objects.get(taxonRank=rankString, **kwargs)
            except MultipleObjectsReturned:
                pass
                ## pass, because there may be good reasons for why there are multiple entries
                # raise ValidationError(
                #     "This taxon implies a single entry for '{0}' at rank of {1}, but there are multiple entries in the database".format(
                #         getattr(self, modelFieldName), rankString)
                # )
            except ObjectDoesNotExist:
                raise ValidationError(
                    "This taxon implies the existence of '{0}' at rank of {1}. You must add it first".format(getattr(self,modelFieldName), rankString)
                )

    def clean(self):
        if self.taxonRank == "species":
            self.validate_implied_taxon('order',order=self.order)
            self.validate_implied_taxon('family', family=self.family)
            self.validate_implied_taxon('subfamily', subfamily=self.subfamily)
            self.validate_implied_taxon('tribe', tribe=self.tribe)
            self.validate_implied_taxon('genus', genus=self.genus)
        if self.taxonRank == "genus":
            self.validate_implied_taxon('order', order=self.order)
            self.validate_implied_taxon('family', family=self.family)
            self.validate_implied_taxon('subfamily', subfamily=self.subfamily)
            self.validate_implied_taxon('tribe', tribe=self.tribe)
        if self.taxonRank == "tribe":
            self.validate_implied_taxon('order', order=self.order)
            self.validate_implied_taxon('family', family=self.family)
            self.validate_implied_taxon('subfamily', subfamily=self.subfamily)
        if self.taxonRank == "subfamily":
            self.validate_implied_taxon('order', order=self.order)
            self.validate_implied_taxon('family', family=self.family)
        if self.taxonRank == "family":
            self.validate_implied_taxon('order', order=self.order)

    def validate_unique(self, exclude=None):
        try:
            match = taxonomy.objects.filter(
                kingdom = self.kingdom,
                phylum = self.phylum,
                tclass = self.tclass,
                order = self.order,
                family = self.family,
                tribe = self.tribe,
                genus = self.genus,
                species = self.species,
                infraspecificEpithet = self.infraspecificEpithet,
                identificationQualifier=self.identificationQualifier,
                taxonRank=self.taxonRank
            ).exclude(pk=self.pk)
            if len(match) > 0:
                raise ValidationError({NON_FIELD_ERRORS:'Matching taxon already exists'})
        except ObjectDoesNotExist:
            super(taxonomy, self).validate_unique()

class censusLocation(models.Model):
    fullName = models.CharField(max_length=100)
    shortName = models.CharField(max_length=20, unique=True)
    country = models.CharField(max_length=100, choices=CHOICES_ALL_COUNTRIES)
    mmAveragePrecipitation = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
    minAltitude = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
    maxAltitude = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
    latitude = models.DecimalField(max_digits=25, decimal_places=10, null=True, blank=True)
    longitude = models.DecimalField(max_digits=25, decimal_places=10, null=True, blank=True)
    georefMethod = models.CharField(max_length=100, choices=CHOICES_georefMethod)
    datum = models.CharField(max_length=100, default="WGS84")
    WDPAID = models.IntegerField("ID from the World Database on Protected Areas", max_length=25, null=True, blank=True)

    class Meta:
        db_table = 'censusLocation'

    def __unicode__(self):
        return self.shortName

class fossilLocation(censusLocation):
    projectArea = member = models.CharField(max_length=100)
    formation = models.CharField(max_length=100)
    member = models.CharField(max_length=100, null=True, blank=True)
    submember = models.CharField(max_length=100, null=True, blank=True)
    minAgeMa = models.DecimalField(max_digits=10, decimal_places=5, null=True, blank=True)
    maxAgeMa = models.DecimalField(max_digits=10, decimal_places=5, null=True, blank=True)
    geologyRef = models.ForeignKey(reference)
    notes = models.TextField(null=True, blank=True)

    class Meta:
        db_table = 'fossilLocation'
    def __unicode__(self):
        return self.projectArea + " - " + self.member + " - " + self.submember

class occurrence(models.Model):
    ref = models.ForeignKey(reference, null=True, blank=False, )
    location = models.ForeignKey(censusLocation, null=True, blank=False)
    taxon = models.ForeignKey(taxonomy, null=True, blank=False)
    presenceAbsenceOnly = models.BooleanField(default=True, verbose_name="Present")
    abundance = models.IntegerField(max_length=100, null=True, blank=True)
    issue = models.NullBooleanField(default=False)
    notes = models.CharField(max_length=200, null=True, blank=True, )

    class Meta:
        db_table = 'occurrence'
        unique_together = ["location", "taxon", "ref"]

    def __unicode__(self):
        return str(self.location) + "_" + str(self.taxon) + "=" + str(self.abundance)

    def clean(self):
        if self.presenceAbsenceOnly and self.abundance:
            raise ValidationError("You cannot enter an abundance value and also indicate that the data is presence/absence only.")
        if self.presenceAbsenceOnly and self.abundance == 0:
            raise ValidationError("You indicated that the data is presence/absence only. You should enter a blank for abundance, not a zero.")
        if not self.presenceAbsenceOnly and not self.abundance:
            raise ValidationError("You must EITHER enter an abundance value OR indicate that the data is presence/absence only.")
        if self.issue and not self.notes:
            raise ValidationError("You said there was an issue with this data...so you must include some details in the notes field")

class functional_traits(models.Model):
    taxon = models.ForeignKey(taxonomy, null=False, blank=False, unique=True)
    browse_graze = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_BROWSEGRAZE)
    habitat = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_HABITAT)
    bodysize_brain_bunn = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_SIZE_BRAIN_BUNN)
    bodysize_lintulaakso = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_SIZE_LINTULAAKSO)
    bodysize_species_mean_kg = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
    locomotor_reed = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_LOCOMOTOR_REED)
    trophic_lintulaakso = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_TROPHIC_LINTULAAKSO)

    def __unicode__(self):
        return 'Traits of ' + self.taxon.__unicode__()
    class Meta:
        db_table = 'functional_traits'
        verbose_name = "functional trait"
        verbose_name_plural = "functional traits"
<commit_msg>special case for species that have no genus<commit_after># -*- coding: utf-8 -*-
from django.db import models
from django.core.exceptions import ValidationError
from choices_functional_trait import *
from choices_models import CHOICES_ALL_COUNTRIES, CHOICES_georefMethod
from choices_taxonomy import *
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.core.exceptions import NON_FIELD_ERRORS

class reference(models.Model):
    authorshortstring = models.CharField(max_length=100)
    year = models.IntegerField()
    journal = models.CharField(max_length=100, blank=True, null=True)
    volume = models.IntegerField(max_length=5, blank=True, null=True)
    issue = models.IntegerField(max_length=5, blank=True, null=True)
    pages = models.CharField(max_length=20, blank=True, null=True)
    doi = models.CharField(max_length=100, blank=True, null=True)
    dataEntryComplete = models.NullBooleanField(blank=True, default=False)

    def __unicode__(self):
        # if self.dataEntryComplete:
        #     name = self.authorshortstring + ", " + str(self.year) + " - Data Entry Complete"
        # else:
        #     name = self.authorshortstring + ", " + str(self.year)
        name = self.authorshortstring + ", " + str(self.year)
        return name

    class Meta:
        db_table = 'reference'

class taxonomy(models.Model):
    kingdom = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_KINGDOM, default="Animalia")
    phylum = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_PHYLUM, default="Chordata")
    tclass = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_CLASS, verbose_name="class")
    order = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_ORDER)
    family = models.CharField(max_length=100, null=True, blank=True)
    subfamily = models.CharField(max_length=100, null=True, blank=True)
    tribe = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_tribe)
    genus = models.CharField(max_length=100, null=True, blank=True, verbose_name = "genus")
    species = models.CharField(max_length=100, null=True, blank=True, verbose_name = "species")
    infraspecificEpithet = models.CharField(max_length=100, null=True, blank=True)
    identificationQualifier = models.CharField(max_length=100, null=True, blank=True)
    extant = models.BooleanField()
    commonName = models.CharField(max_length=100, null=True, blank=True)
    synonyms = models.CharField(max_length=2000, null=True, blank=True)
    taxonRank = models.CharField(max_length=100, null=True, blank=False, choices=CHOICES_RANK)
    ref = models.ForeignKey(reference)
    Fernandez_Vrba_2005_Name = models.CharField(max_length=255, null=True, blank=True)
    BinindaEmonds_2008_Name = models.CharField(max_length=255, null=True, blank=True)
    #habitat = models.CharField(max_length=25, null=True, blank=True, choices = CHOICES_HABITAT)
    #diet = models.CharField(max_length=25, null=True, blank=True, choices = CHOICES_DIET)

    class Meta:
        db_table = 'taxonomy'
        verbose_name = "taxon"
        verbose_name_plural = "taxa"
        unique_together = ['tclass','order','family','subfamily','tribe','genus','species','infraspecificEpithet','taxonRank','identificationQualifier']

    def __unicode__(self):
        if str(self.taxonRank).lower() == 'tclass':
            name =  self.tclass + " (class)"
        elif str(self.taxonRank).lower() == 'order':
            name =  self.order + " (" + self.taxonRank + ")"
        elif str(self.taxonRank).lower() == 'family':
            name =  self.family + " (" + self.taxonRank + ")"
        elif str(self.taxonRank).lower() == 'subfamily':
            name =   self.subfamily + " (" + self.taxonRank + ")"
        elif str(self.taxonRank).lower() == 'tribe':
            name =   self.tribe + " (" + self.taxonRank + ")"
        elif str(self.taxonRank).lower() == 'genus':
            name =   self.genus + " (" + self.taxonRank + ")"
        # special case for things like Alcelaphini sp. large of Reed 2008
        elif str(self.taxonRank).lower() == 'species' and self.genus == "":
            name = self.tribe + " " + self.species + " (" + self.taxonRank + ")"
        elif str(self.taxonRank).lower() == 'species':
            name =   self.genus + " " + self.species + " (" + self.taxonRank + ")"
        elif str(self.taxonRank).lower() == 'subspecies':
            name =  self.genus + " " + self.species + " " + self.infraspecificEpithet + " (" + self.taxonRank + ")"
        else:
            name =  " (" + self.taxonRank + ")"

        if self.identificationQualifier:
            name = self.identificationQualifier + " " + name

        if not self.extant:
            name += u" ✝"

        return name

    def validate_implied_taxon(self,rankString, **kwargs):
        modelFieldName = kwargs.keys()[0] #need to do some tests here!
        if getattr(self,modelFieldName):
            try:
                taxonomy.objects.get(taxonRank=rankString, **kwargs)
            except MultipleObjectsReturned:
                pass
                ## pass, because there may be good reasons for why there are multiple entries
                # raise ValidationError(
                #     "This taxon implies a single entry for '{0}' at rank of {1}, but there are multiple entries in the database".format(
                #         getattr(self, modelFieldName), rankString)
                # )
            except ObjectDoesNotExist:
                raise ValidationError(
                    "This taxon implies the existence of '{0}' at rank of {1}. You must add it first".format(getattr(self,modelFieldName), rankString)
                )

    def clean(self):
        if self.taxonRank == "species":
            self.validate_implied_taxon('order',order=self.order)
            self.validate_implied_taxon('family', family=self.family)
            self.validate_implied_taxon('subfamily', subfamily=self.subfamily)
            self.validate_implied_taxon('tribe', tribe=self.tribe)
            self.validate_implied_taxon('genus', genus=self.genus)
        if self.taxonRank == "genus":
            self.validate_implied_taxon('order', order=self.order)
            self.validate_implied_taxon('family', family=self.family)
            self.validate_implied_taxon('subfamily', subfamily=self.subfamily)
            self.validate_implied_taxon('tribe', tribe=self.tribe)
        if self.taxonRank == "tribe":
            self.validate_implied_taxon('order', order=self.order)
            self.validate_implied_taxon('family', family=self.family)
            self.validate_implied_taxon('subfamily', subfamily=self.subfamily)
        if self.taxonRank == "subfamily":
            self.validate_implied_taxon('order', order=self.order)
            self.validate_implied_taxon('family', family=self.family)
        if self.taxonRank == "family":
            self.validate_implied_taxon('order', order=self.order)

    def validate_unique(self, exclude=None):
        try:
            match = taxonomy.objects.filter(
                kingdom = self.kingdom,
                phylum = self.phylum,
                tclass = self.tclass,
                order = self.order,
                family = self.family,
                tribe = self.tribe,
                genus = self.genus,
                species = self.species,
                infraspecificEpithet = self.infraspecificEpithet,
                identificationQualifier=self.identificationQualifier,
                taxonRank=self.taxonRank
            ).exclude(pk=self.pk)
            if len(match) > 0:
                raise ValidationError({NON_FIELD_ERRORS:'Matching taxon already exists'})
        except ObjectDoesNotExist:
            super(taxonomy, self).validate_unique()

class censusLocation(models.Model):
    fullName = models.CharField(max_length=100)
    shortName = models.CharField(max_length=20, unique=True)
    country = models.CharField(max_length=100, choices=CHOICES_ALL_COUNTRIES)
    mmAveragePrecipitation = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
    minAltitude = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
    maxAltitude = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
    latitude = models.DecimalField(max_digits=25, decimal_places=10, null=True, blank=True)
    longitude = models.DecimalField(max_digits=25, decimal_places=10, null=True, blank=True)
    georefMethod = models.CharField(max_length=100, choices=CHOICES_georefMethod)
    datum = models.CharField(max_length=100, default="WGS84")
    WDPAID = models.IntegerField("ID from the World Database on Protected Areas", max_length=25, null=True, blank=True)

    class Meta:
        db_table = 'censusLocation'

    def __unicode__(self):
        return self.shortName

class fossilLocation(censusLocation):
    projectArea = member = models.CharField(max_length=100)
    formation = models.CharField(max_length=100)
    member = models.CharField(max_length=100, null=True, blank=True)
    submember = models.CharField(max_length=100, null=True, blank=True)
    minAgeMa = models.DecimalField(max_digits=10, decimal_places=5, null=True, blank=True)
    maxAgeMa = models.DecimalField(max_digits=10, decimal_places=5, null=True, blank=True)
    geologyRef = models.ForeignKey(reference)
    notes = models.TextField(null=True, blank=True)

    class Meta:
        db_table = 'fossilLocation'
    def __unicode__(self):
        return self.projectArea + " - " + self.member + " - " + self.submember

class occurrence(models.Model):
    ref = models.ForeignKey(reference, null=True, blank=False, )
    location = models.ForeignKey(censusLocation, null=True, blank=False)
    taxon = models.ForeignKey(taxonomy, null=True, blank=False)
    presenceAbsenceOnly = models.BooleanField(default=True, verbose_name="Present")
    abundance = models.IntegerField(max_length=100, null=True, blank=True)
    issue = models.NullBooleanField(default=False)
    notes = models.CharField(max_length=200, null=True, blank=True, )

    class Meta:
        db_table = 'occurrence'
        unique_together = ["location", "taxon", "ref"]

    def __unicode__(self):
        return str(self.location) + "_" + str(self.taxon) + "=" + str(self.abundance)

    def clean(self):
        if self.presenceAbsenceOnly and self.abundance:
            raise ValidationError("You cannot enter an abundance value and also indicate that the data is presence/absence only.")
        if self.presenceAbsenceOnly and self.abundance == 0:
            raise ValidationError("You indicated that the data is presence/absence only. You should enter a blank for abundance, not a zero.")
        if not self.presenceAbsenceOnly and not self.abundance:
            raise ValidationError("You must EITHER enter an abundance value OR indicate that the data is presence/absence only.")
        if self.issue and not self.notes:
            raise ValidationError("You said there was an issue with this data...so you must include some details in the notes field")

class functional_traits(models.Model):
    taxon = models.ForeignKey(taxonomy, null=False, blank=False, unique=True)
    browse_graze = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_BROWSEGRAZE)
    habitat = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_HABITAT)
    bodysize_brain_bunn = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_SIZE_BRAIN_BUNN)
    bodysize_lintulaakso = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_SIZE_LINTULAAKSO)
    bodysize_species_mean_kg = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
    locomotor_reed = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_LOCOMOTOR_REED)
    trophic_lintulaakso = models.CharField(max_length=100, null=True, blank=True, choices=CHOICES_TROPHIC_LINTULAAKSO)

    def __unicode__(self):
        return 'Traits of ' + self.taxon.__unicode__()
    class Meta:
        db_table = 'functional_traits'
        verbose_name = "functional trait"
        verbose_name_plural = "functional traits"
<|endoftext|>


<commit_before># cerbero - a multi-platform build system for Open Source software
# Copyright (C) 2012 Andoni Morales Alastruey <ylatuya@gmail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

import os

from cerbero.config import Platform, Architecture, Distro
from cerbero.utils import shell, to_unixpath
from cerbero.utils import messages as m
import shutil

class Build (object):
    '''
    Base class for build handlers

    @ivar recipe: the parent recipe
    @type recipe: L{cerbero.recipe.Recipe}
    @ivar config: cerbero's configuration
    @type config: L{cerbero.config.Config}
    '''

    _properties_keys = []

    def configure(self):
        '''
        Configures the module
        '''
        raise NotImplemented("'configure' must be implemented by subclasses")

    def compile(self):
        '''
        Compiles the module
        '''
        raise NotImplemented("'make' must be implemented by subclasses")

    def install(self):
        '''
        Installs the module
        '''
        raise NotImplemented("'install' must be implemented by subclasses")

    def check(self):
        '''
        Runs any checks on the module
        '''
        pass

class CustomBuild(Build):

    def configure(self):
        pass

    def compile(self):
        pass

    def install(self):
        pass

def modify_environment(func):
    ''' Decorator to modify the build environment '''
    def call(*args):
        self = args[0]
        append_env = self.append_env
        new_env = self.new_env.copy()
        if self.use_system_libs and self.config.allow_system_libs:
            self._add_system_libs(new_env)
        old_env = self._modify_env(append_env, new_env)
        res = func(*args)
        self._restore_env(old_env)
        return res

    call.func_name = func.func_name
    return call

class MakefilesBase (Build):
    '''
    Base class for makefiles build systems like autotools and cmake
    '''

    config_sh = ''
    configure_tpl = ''
    configure_options = ''
    force_configure = False
    make = 'make'
    make_install = 'make install'
    make_check = None
    make_clean = 'make clean'
    use_system_libs = False
    allow_parallel_build = True
    srcdir = '.'
    append_env = None
    new_env = None

    def __init__(self):
        Build.__init__(self)
        if self.append_env is None:
            self.append_env = {}
        if self.new_env is None:
            self.new_env = {}
        self.make_dir = os.path.abspath(os.path.join(self.build_dir,
                                                     self.srcdir))
        if self.config.allow_parallel_build and self.allow_parallel_build \
                and self.config.num_of_cpus > 1:
            self.make += ' -j%d' % self.config.num_of_cpus
        self._old_env = None

    @modify_environment
    def configure(self):
        shell.call(self.configure_tpl % {'config-sh': self.config_sh,
                                          'prefix': to_unixpath(self.config.prefix),
                                          'libdir': to_unixpath(self.config.libdir),
                                          'host': self.config.host,
                                          'target': self.config.target,
                                          'build': self.config.build,
                                          'options': self.configure_options},
                    self.make_dir)

    @modify_environment
    def compile(self):
        shell.call(self.make, self.make_dir)

    @modify_environment
    def install(self):
        shell.call(self.make_install, self.make_dir)

    @modify_environment
    def clean(self):
        shell.call(self.make_clean, self.make_dir)

    @modify_environment
    def check(self):
        if self.make_check:
            shell.call(self.make_check, self.build_dir)

    def _modify_env(self, append_env, new_env):
        '''
        Modifies the build environment appending the values in
        append_env or replacing the values in new_env
        '''
        if self._old_env is not None:
            return None

        self._old_env = {}
        for var in append_env.keys() + new_env.keys():
            self._old_env[var] = os.environ.get(var, None)

        for var, val in append_env.iteritems():
            os.environ[var] = os.environ.get(var, '') + val

        for var, val in new_env.iteritems():
            if val is None:
                del os.environ[var]
            else:
                os.environ[var] = val
        return self._old_env

    def _restore_env(self, old_env):
        ''' Restores the old environment '''
        if old_env is None:
            return

        for var, val in old_env.iteritems():
            if val is None:
                del os.environ[var]
            else:
                os.environ[var] = val
        self._old_env = None

    def _add_system_libs(self, new_env):
        '''
        Add /usr/lib/pkgconfig to PKG_CONFIG_PATH so the system's .pc file
        can be found.
        '''
        arch = self.config.target_arch
        libdir = 'lib'
        if arch == Architecture.X86:
            arch = 'i386'
        else:
            if self.config.distro == Distro.REDHAT:
                libdir = 'lib64'
        search_paths = [os.environ['PKG_CONFIG_LIBDIR'],
            '/usr/%s/pkgconfig' % libdir, '/usr/share/pkgconfig',
            '/usr/lib/%s-linux-gnu/pkgconfig' % arch]
        new_env['PKG_CONFIG_PATH'] = ':'.join(search_paths)

class Autotools (MakefilesBase):
    '''
    Build handler for autotools project
    '''

    autoreconf = False
    autoreconf_sh = 'autoreconf -f -i'
    config_sh = './configure'
    configure_tpl = "%(config-sh)s --prefix %(prefix)s "\
                    "--libdir %(libdir)s %(options)s"
    make_check = 'make check'
    add_host_build_target = True
    can_use_configure_cache = True
    supports_cache_variables = True

    def configure(self):
        if self.supports_non_src_build:
            self.config_sh = os.path.join(self.repo_dir, self.config_sh)
        # skip configure if we are already configured
        if os.path.exists(os.path.join(self.make_dir, 'configure')) and\
                os.path.exists(os.path.join(self.make_dir, 'Makefile')):
            if not self.force_configure and not self.force:
                return

        # Only use --disable-maintainer mode for real autotools based projects
        if os.path.exists(os.path.join(self.make_dir, 'configure.in')) or\
                os.path.exists(os.path.join(self.make_dir, 'configure.ac')):
            self.configure_tpl += " --disable-maintainer-mode --disable-silent-rules "

        if self.autoreconf:
            shell.call(self.autoreconf_sh, self.make_dir)

        files = shell.check_call('find %s -type f -name config.guess' % self.make_dir).split('\n')
        files.remove('')
        for f in files:
            o = os.path.join(self.config._relative_path ('data'), 'autotools', 'config.guess')
            m.action("copying %s to %s" % (o, f))
            shutil.copy(o, f)

        files = shell.check_call('find %s -type f -name config.sub' % self.make_dir).split('\n')
        files.remove('')
        for f in files:
            o = os.path.join(self.config._relative_path ('data'), 'autotools', 'config.sub')
            m.action("copying %s to %s" % (o, f))
            shutil.copy(o, f)

        if self.config.platform == Platform.WINDOWS and \
                self.supports_cache_variables:
            # On windows, environment variables are upperscase, but we still
            # need to pass things like am_cv_python_platform in lowercase for
            # configure and autogen.sh
            for k, v in os.environ.iteritems():
                if k[2:6] == '_cv_':
                    self.configure_tpl += ' %s="%s"' % (k, v)

        if self.add_host_build_target:
            if self.config.host is not None:
                self.configure_tpl += ' --host=%(host)s'
            if self.config.build is not None:
                self.configure_tpl += ' --build=%(build)s'
            if self.config.target is not None:
                self.configure_tpl += ' --target=%(target)s'

        use_configure_cache = self.config.use_configure_cache
        if self.use_system_libs and self.config.allow_system_libs:
            use_configure_cache = False

        if self.new_env is not None or self.append_env is not None:
            use_configure_cache = False

        if use_configure_cache and self.can_use_configure_cache:
            cache = os.path.join(self.config.prefix, '.configure.cache')
            self.config_sh += ' --cache-file=%s' % cache

        MakefilesBase.configure(self)

class CMake (MakefilesBase):
    '''
    Build handler for cmake projects
    '''

    config_sh = 'cmake'
    configure_tpl = '%(config-sh)s -DCMAKE_INSTALL_PREFIX=%(prefix)s '\
                    '-DCMAKE_LIBRARY_OUTPUT_PATH=%(libdir)s %(options)s '\
                    '-DCMAKE_BUILD_TYPE=Release '\
                    '-DCMAKE_FIND_ROOT_PATH=$CERBERO_PREFIX '

    @modify_environment
    def configure(self):
        cc = os.environ.get('CC', 'gcc')
        cxx = os.environ.get('CXX', 'g++')
        cflags = os.environ.get('CFLAGS', '')
        cxxflags = os.environ.get('CXXFLAGS', '')
        # FIXME: CMake doesn't support passing "ccache $CC"
        if self.config.use_ccache:
            cc = cc.replace('ccache ', '')
            cxx = cxx.replace('ccache ', '')

        if self.config.target_platform == Platform.WINDOWS:
            self.configure_options += ' -DCMAKE_C_COMPILER=%s '\
                                      ' -DCMAKE_CXX_COMPILER=%s '\
                                      ' -DCMAKE_SYSTEM_NAME=Windows '\
                                      % (cc, cxx)
        if self.config.platform == Platform.WINDOWS:
            self.configure_options += ' -G\\"Unix Makefiles\\"'
        self.configure_options += ' -DCMAKE_C_FLAGS="%s"' % cflags
        self.configure_options += ' -DCMAKE_CXX_FLAGS="%s"' % cxxflags
        self.configure_options += ' -DLIB_SUFFIX=%s ' % self.config.lib_suffix
        MakefilesBase.configure(self)

class BuildType (object):

    CUSTOM = CustomBuild
    MAKEFILE = MakefilesBase
    AUTOTOOLS = Autotools
    CMAKE = CMake
<commit_msg>build.py: do not check if None when we are working with empty dictionnary<commit_after># cerbero - a multi-platform build system for Open Source software
# Copyright (C) 2012 Andoni Morales Alastruey <ylatuya@gmail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

import os

from cerbero.config import Platform, Architecture, Distro
from cerbero.utils import shell, to_unixpath
from cerbero.utils import messages as m
import shutil

class Build (object):
    '''
    Base class for build handlers

    @ivar recipe: the parent recipe
    @type recipe: L{cerbero.recipe.Recipe}
    @ivar config: cerbero's configuration
    @type config: L{cerbero.config.Config}
    '''

    _properties_keys = []

    def configure(self):
        '''
        Configures the module
        '''
        raise NotImplemented("'configure' must be implemented by subclasses")

    def compile(self):
        '''
        Compiles the module
        '''
        raise NotImplemented("'make' must be implemented by subclasses")

    def install(self):
        '''
        Installs the module
        '''
        raise NotImplemented("'install' must be implemented by subclasses")

    def check(self):
        '''
        Runs any checks on the module
        '''
        pass

class CustomBuild(Build):

    def configure(self):
        pass

    def compile(self):
        pass

    def install(self):
        pass

def modify_environment(func):
    ''' Decorator to modify the build environment '''
    def call(*args):
        self = args[0]
        append_env = self.append_env
        new_env = self.new_env.copy()
        if self.use_system_libs and self.config.allow_system_libs:
            self._add_system_libs(new_env)
        old_env = self._modify_env(append_env, new_env)
        res = func(*args)
        self._restore_env(old_env)
        return res

    call.func_name = func.func_name
    return call

class MakefilesBase (Build):
    '''
    Base class for makefiles build systems like autotools and cmake
    '''

    config_sh = ''
    configure_tpl = ''
    configure_options = ''
    force_configure = False
    make = 'make'
    make_install = 'make install'
    make_check = None
    make_clean = 'make clean'
    use_system_libs = False
    allow_parallel_build = True
    srcdir = '.'
    append_env = None
    new_env = None

    def __init__(self):
        Build.__init__(self)
        if self.append_env is None:
            self.append_env = {}
        if self.new_env is None:
            self.new_env = {}
        self.make_dir = os.path.abspath(os.path.join(self.build_dir,
                                                     self.srcdir))
        if self.config.allow_parallel_build and self.allow_parallel_build \
                and self.config.num_of_cpus > 1:
            self.make += ' -j%d' % self.config.num_of_cpus
        self._old_env = None

    @modify_environment
    def configure(self):
        shell.call(self.configure_tpl % {'config-sh': self.config_sh,
                                          'prefix': to_unixpath(self.config.prefix),
                                          'libdir': to_unixpath(self.config.libdir),
                                          'host': self.config.host,
                                          'target': self.config.target,
                                          'build': self.config.build,
                                          'options': self.configure_options},
                    self.make_dir)

    @modify_environment
    def compile(self):
        shell.call(self.make, self.make_dir)

    @modify_environment
    def install(self):
        shell.call(self.make_install, self.make_dir)

    @modify_environment
    def clean(self):
        shell.call(self.make_clean, self.make_dir)

    @modify_environment
    def check(self):
        if self.make_check:
            shell.call(self.make_check, self.build_dir)

    def _modify_env(self, append_env, new_env):
        '''
        Modifies the build environment appending the values in
        append_env or replacing the values in new_env
        '''
        if self._old_env is not None:
            return None

        self._old_env = {}
        for var in append_env.keys() + new_env.keys():
            self._old_env[var] = os.environ.get(var, None)

        for var, val in append_env.iteritems():
            os.environ[var] = os.environ.get(var, '') + val

        for var, val in new_env.iteritems():
            if val is None:
                del os.environ[var]
            else:
                os.environ[var] = val
        return self._old_env

    def _restore_env(self, old_env):
        ''' Restores the old environment '''
        if old_env is None:
            return

        for var, val in old_env.iteritems():
            if val is None:
                del os.environ[var]
            else:
                os.environ[var] = val
        self._old_env = None

    def _add_system_libs(self, new_env):
        '''
        Add /usr/lib/pkgconfig to PKG_CONFIG_PATH so the system's .pc file
        can be found.
        '''
        arch = self.config.target_arch
        libdir = 'lib'
        if arch == Architecture.X86:
            arch = 'i386'
        else:
            if self.config.distro == Distro.REDHAT:
                libdir = 'lib64'
        search_paths = [os.environ['PKG_CONFIG_LIBDIR'],
            '/usr/%s/pkgconfig' % libdir, '/usr/share/pkgconfig',
            '/usr/lib/%s-linux-gnu/pkgconfig' % arch]
        new_env['PKG_CONFIG_PATH'] = ':'.join(search_paths)

class Autotools (MakefilesBase):
    '''
    Build handler for autotools project
    '''

    autoreconf = False
    autoreconf_sh = 'autoreconf -f -i'
    config_sh = './configure'
    configure_tpl = "%(config-sh)s --prefix %(prefix)s "\
                    "--libdir %(libdir)s %(options)s"
    make_check = 'make check'
    add_host_build_target = True
    can_use_configure_cache = True
    supports_cache_variables = True

    def configure(self):
        if self.supports_non_src_build:
            self.config_sh = os.path.join(self.repo_dir, self.config_sh)
        # skip configure if we are already configured
        if os.path.exists(os.path.join(self.make_dir, 'configure')) and\
                os.path.exists(os.path.join(self.make_dir, 'Makefile')):
            if not self.force_configure and not self.force:
                return

        # Only use --disable-maintainer mode for real autotools based projects
        if os.path.exists(os.path.join(self.make_dir, 'configure.in')) or\
                os.path.exists(os.path.join(self.make_dir, 'configure.ac')):
            self.configure_tpl += " --disable-maintainer-mode --disable-silent-rules "

        if self.autoreconf:
            shell.call(self.autoreconf_sh, self.make_dir)

        files = shell.check_call('find %s -type f -name config.guess' % self.make_dir).split('\n')
        files.remove('')
        for f in files:
            o = os.path.join(self.config._relative_path ('data'), 'autotools', 'config.guess')
            m.action("copying %s to %s" % (o, f))
            shutil.copy(o, f)

        files = shell.check_call('find %s -type f -name config.sub' % self.make_dir).split('\n')
        files.remove('')
        for f in files:
            o = os.path.join(self.config._relative_path ('data'), 'autotools', 'config.sub')
            m.action("copying %s to %s" % (o, f))
            shutil.copy(o, f)

        if self.config.platform == Platform.WINDOWS and \
                self.supports_cache_variables:
            # On windows, environment variables are upperscase, but we still
            # need to pass things like am_cv_python_platform in lowercase for
            # configure and autogen.sh
            for k, v in os.environ.iteritems():
                if k[2:6] == '_cv_':
                    self.configure_tpl += ' %s="%s"' % (k, v)

        if self.add_host_build_target:
            if self.config.host is not None:
                self.configure_tpl += ' --host=%(host)s'
            if self.config.build is not None:
                self.configure_tpl += ' --build=%(build)s'
            if self.config.target is not None:
                self.configure_tpl += ' --target=%(target)s'

        use_configure_cache = self.config.use_configure_cache
        if self.use_system_libs and self.config.allow_system_libs:
            use_configure_cache = False

        if self.new_env or self.append_env:
            use_configure_cache = False

        if use_configure_cache and self.can_use_configure_cache:
            cache = os.path.join(self.config.prefix, '.configure.cache')
            self.config_sh += ' --cache-file=%s' % cache

        MakefilesBase.configure(self)

class CMake (MakefilesBase):
    '''
    Build handler for cmake projects
    '''

    config_sh = 'cmake'
    configure_tpl = '%(config-sh)s -DCMAKE_INSTALL_PREFIX=%(prefix)s '\
                    '-DCMAKE_LIBRARY_OUTPUT_PATH=%(libdir)s %(options)s '\
                    '-DCMAKE_BUILD_TYPE=Release '\
                    '-DCMAKE_FIND_ROOT_PATH=$CERBERO_PREFIX '

    @modify_environment
    def configure(self):
        cc = os.environ.get('CC', 'gcc')
        cxx = os.environ.get('CXX', 'g++')
        cflags = os.environ.get('CFLAGS', '')
        cxxflags = os.environ.get('CXXFLAGS', '')
        # FIXME: CMake doesn't support passing "ccache $CC"
        if self.config.use_ccache:
            cc = cc.replace('ccache ', '')
            cxx = cxx.replace('ccache ', '')

        if self.config.target_platform == Platform.WINDOWS:
            self.configure_options += ' -DCMAKE_C_COMPILER=%s '\
                                      ' -DCMAKE_CXX_COMPILER=%s '\
                                      ' -DCMAKE_SYSTEM_NAME=Windows '\
                                      % (cc, cxx)
        if self.config.platform == Platform.WINDOWS:
            self.configure_options += ' -G\\"Unix Makefiles\\"'
        self.configure_options += ' -DCMAKE_C_FLAGS="%s"' % cflags
        self.configure_options += ' -DCMAKE_CXX_FLAGS="%s"' % cxxflags
        self.configure_options += ' -DLIB_SUFFIX=%s ' % self.config.lib_suffix
        MakefilesBase.configure(self)

class BuildType (object):

    CUSTOM = CustomBuild
    MAKEFILE = MakefilesBase
    AUTOTOOLS = Autotools
    CMAKE = CMake
<|endoftext|>


<commit_before>##
# Copyright (c) 2008-2010 Sprymix Inc.
# All rights reserved.
#
# See LICENSE for details.
##

import datetime
import dateutil.parser
import dateutil.relativedelta
import dateutil.tz
import re

from semantix.utils import config

@config.configurable
class DateTime(datetime.datetime):
    local_timezone = config.cvalue(type=str, default=None, doc='Default local time-zone')
    local_tz = None

    def __new__(cls, value=None):
        if isinstance(value, datetime.datetime):
            d = value
        elif isinstance(value, str):
            try:
                d = dateutil.parser.parse(value)
            except ValueError as e:
                raise ValueError("invalid value for DateTime object: %s" % value) from e
        else:
            raise ValueError("invalid value for DateTime object: %s" % value)

        tzinfo = d.tzinfo or cls.get_tz()

        return super().__new__(cls, d.year, d.month, d.day, d.hour, d.minute, d.second,
                                    d.microsecond, tzinfo)

    @classmethod
    def get_tz(cls):
        if cls.local_tz is None:
            cls.local_tz = dateutil.tz.gettz(name=cls.local_timezone)
        return cls.local_tz

    @classmethod
    def now(cls, tz=None):
        if not tz:
            tz = cls.get_tz()
        return cls(datetime.datetime.now(tz=tz))

class TimeDelta(dateutil.relativedelta.relativedelta):
    _interval_tokens = {'year': 'years', 'years': 'years',
                        'month': 'months', 'months': 'months',
                        'week': 'weeks', 'weeks': 'weeks',
                        'day': 'days', 'days': 'days',
                        'hour': 'hours', 'hours': 'hours',
                        'minute': 'minutes', 'minutes': 'minutes',
                        'second': 'seconds', 'seconds': 'seconds',
                        'microsecond': 'microseconds', 'microseconds': 'microseconds'}

    def __new__(cls, value=None, *, dt1=None, dt2=None, years=0, months=0, days=0, leapdays=0,
                      weeks=0, hours=0, minutes=0, seconds=0, microseconds=0, year=None,
                      month=None, day=None, weekday=None, yearday=None, nlyearday=None, hour=None,
                      minute=None, second=None, microsecond=None):

        if value is None:
            result = super().__new__(cls)
            super().__init__(result,
                             dt1=dt1, dt2=dt2, years=years, months=months, days=days,
                             hours=hours, minutes=minutes,
                             seconds=seconds, microseconds=microseconds,
                             leapdays=leapdays, year=year, weeks=weeks,
                             month=month, day=day, weekday=weekday,
                             hour=hour, minute=minute, second=second,
                             microsecond=microsecond)

        elif isinstance(value, dateutil.relativedelta.relativedelta):
            result = super().__new__(cls)
            super().__init__(result,
                             years=value.years, months=value.months, days=value.days,
                             hours=value.hours, minutes=value.minutes,
                             seconds=value.seconds, microseconds=value.microseconds,
                             leapdays=value.leapdays, year=value.year,
                             month=value.month, day=value.day, weekday=value.weekday,
                             hour=value.hour, minute=value.minute,
                             second=value.second, microsecond=value.microsecond)

        elif isinstance(value, datetime.timedelta):
            result = super().__new__(cls)
            super().__init__(result,
                             days=value.days, seconds=value.seconds,
                             microseconds=value.microseconds)

        elif isinstance(value, str):
            expecting_number = True

            intervals = {}
            interval_tokens = cls._interval_tokens

            try:
                number = None

                for token in re.split('\s+', value):
                    if expecting_number:
                        number = int(token)
                    else:
                        interval = interval_tokens[token]
                        if interval in intervals:
                            raise ValueError
                        intervals[interval] = number
                    expecting_number = not expecting_number
                if not expecting_number:
                    raise ValueError
            except (ValueError, KeyError):
                raise ValueError("invalid timedelta value: '%s'" % value)

            result = super().__new__(cls)
            super().__init__(result, **intervals)

        return result

    def __init__(self, *args, **kwargs):
        # We initialize in __new__, so nothing to do here
        pass

    def __str__(self):
        s = []
        for k in ('years', 'months', 'days', 'hours', 'minutes', 'seconds', 'microseconds'):
            v = getattr(self, k)
            if v:
                s.append('%s %s' % (v, k if v != 1 else k[:-1]))
        return ' '.join(s)

    def __hash__(self):
        return hash((self.weekday, self.year, self.months, self.days, self.hours,
                     self.minutes, self.seconds, self.leapdays, self.year, self.month,
                     self.day, self.hour, self.minute, self.second, self.microsecond))

    def __gt__(self, other):
        if not isinstance(other, TimeDelta):
            return NotImplemented

        if self.weekday or other.weekday:
            raise TypeError('TimeDeltas with non-empty weekday are not orderable')

        return self.years > other.years or self.years == other.years and \
               (self.months > other.months or self.months == other.months and \
               (self.days > other.days or self.days == other.days and \
               (self.hours > other.hours or self.hours == other.hours and \
               (self.minutes > other.minutes or self.minutes == other.minutes and \
               (self.seconds > other.seconds or self.seconds == other.seconds and \
               (self.microseconds > other.microseconds))))))

    def __ge__(self, other):
        return self == other or self > other

    def __lt__(self, other):
        return not self >= other

    def __le__(self, other):
        return not self > other

    def to_months_days_seconds_microseconds(self):
        months = self.months + self.years * 12
        days = self.days
        seconds = self.seconds + self.minutes * 60 + self.hours * 3600
        microseconds = self.microseconds
        return months, days, seconds, microseconds

class Time(TimeDelta):
    def __new__(cls, value=None, *, format=None):
        if isinstance(value, datetime.time):
            d = value
        elif isinstance(value, str):
            try:
                if format:
                    d = datetime.datetime.strptime(value, format)
                else:
                    d = dateutil.parser.parse(value)
            except ValueError as e:
                raise ValueError("invalid value for Time object: %s" % value) from e
        else:
            raise ValueError("invalid value for Time object: %s" % value)

        return super().__new__(cls, hour=d.hour, minute=d.minute, second=d.second,
                                    microsecond=d.microsecond)

    def __str__(self):
        return '%d:%d:%d.%d' % (self.hour, self.minute, self.second, self.microsecond)

    def __repr__(self):
        return "'%d:%d:%d.%d'" % (self.hour, self.minute, self.second, self.microsecond)
<commit_msg>utils.datetime: Ensure TimeDelta raises ValueError when constructed improperly<commit_after>##
# Copyright (c) 2008-2010 Sprymix Inc.
# All rights reserved.
#
# See LICENSE for details.
##

import datetime
import dateutil.parser
import dateutil.relativedelta
import dateutil.tz
import re

from semantix.utils import config

@config.configurable
class DateTime(datetime.datetime):
    local_timezone = config.cvalue(type=str, default=None, doc='Default local time-zone')
    local_tz = None

    def __new__(cls, value=None):
        if isinstance(value, datetime.datetime):
            d = value
        elif isinstance(value, str):
            try:
                d = dateutil.parser.parse(value)
            except ValueError as e:
                raise ValueError("invalid value for DateTime object: %s" % value) from e
        else:
            raise ValueError("invalid value for DateTime object: %s" % value)

        tzinfo = d.tzinfo or cls.get_tz()

        return super().__new__(cls, d.year, d.month, d.day, d.hour, d.minute, d.second,
                                    d.microsecond, tzinfo)

    @classmethod
    def get_tz(cls):
        if cls.local_tz is None:
            cls.local_tz = dateutil.tz.gettz(name=cls.local_timezone)
        return cls.local_tz

    @classmethod
    def now(cls, tz=None):
        if not tz:
            tz = cls.get_tz()
        return cls(datetime.datetime.now(tz=tz))

class TimeDelta(dateutil.relativedelta.relativedelta):
    _interval_tokens = {'year': 'years', 'years': 'years',
                        'month': 'months', 'months': 'months',
                        'week': 'weeks', 'weeks': 'weeks',
                        'day': 'days', 'days': 'days',
                        'hour': 'hours', 'hours': 'hours',
                        'minute': 'minutes', 'minutes': 'minutes',
                        'second': 'seconds', 'seconds': 'seconds',
                        'microsecond': 'microseconds', 'microseconds': 'microseconds'}

    def __new__(cls, value=None, *, dt1=None, dt2=None, years=0, months=0, days=0, leapdays=0,
                      weeks=0, hours=0, minutes=0, seconds=0, microseconds=0, year=None,
                      month=None, day=None, weekday=None, yearday=None, nlyearday=None, hour=None,
                      minute=None, second=None, microsecond=None):

        if value is None:
            result = super().__new__(cls)
            super().__init__(result,
                             dt1=dt1, dt2=dt2, years=years, months=months, days=days,
                             hours=hours, minutes=minutes,
                             seconds=seconds, microseconds=microseconds,
                             leapdays=leapdays, year=year, weeks=weeks,
                             month=month, day=day, weekday=weekday,
                             hour=hour, minute=minute, second=second,
                             microsecond=microsecond)

        elif isinstance(value, dateutil.relativedelta.relativedelta):
            result = super().__new__(cls)
            super().__init__(result,
                             years=value.years, months=value.months, days=value.days,
                             hours=value.hours, minutes=value.minutes,
                             seconds=value.seconds, microseconds=value.microseconds,
                             leapdays=value.leapdays, year=value.year,
                             month=value.month, day=value.day, weekday=value.weekday,
                             hour=value.hour, minute=value.minute,
                             second=value.second, microsecond=value.microsecond)

        elif isinstance(value, datetime.timedelta):
            result = super().__new__(cls)
            super().__init__(result,
                             days=value.days, seconds=value.seconds,
                             microseconds=value.microseconds)

        elif isinstance(value, str):
            expecting_number = True

            intervals = {}
            interval_tokens = cls._interval_tokens

            try:
                number = None

                for token in re.split('\s+', value):
                    if expecting_number:
                        number = int(token)
                    else:
                        interval = interval_tokens[token]
                        if interval in intervals:
                            raise ValueError
                        intervals[interval] = number
                    expecting_number = not expecting_number
                if not expecting_number:
                    raise ValueError
            except (ValueError, KeyError):
                raise ValueError("invalid timedelta value: '%s'" % value)

            result = super().__new__(cls)
            super().__init__(result, **intervals)

        else:
            raise ValueError("invalid timedelta value: '%s'" % value)

        return result

    def __init__(self, *args, **kwargs):
        # We initialize in __new__, so nothing to do here
        pass

    def __str__(self):
        s = []
        for k in ('years', 'months', 'days', 'hours', 'minutes', 'seconds', 'microseconds'):
            v = getattr(self, k)
            if v:
                s.append('%s %s' % (v, k if v != 1 else k[:-1]))
        return ' '.join(s)

    def __hash__(self):
        return hash((self.weekday, self.year, self.months, self.days, self.hours,
                     self.minutes, self.seconds, self.leapdays, self.year, self.month,
                     self.day, self.hour, self.minute, self.second, self.microsecond))

    def __gt__(self, other):
        if not isinstance(other, TimeDelta):
            return NotImplemented

        if self.weekday or other.weekday:
            raise TypeError('TimeDeltas with non-empty weekday are not orderable')

        return self.years > other.years or self.years == other.years and \
               (self.months > other.months or self.months == other.months and \
               (self.days > other.days or self.days == other.days and \
               (self.hours > other.hours or self.hours == other.hours and \
               (self.minutes > other.minutes or self.minutes == other.minutes and \
               (self.seconds > other.seconds or self.seconds == other.seconds and \
               (self.microseconds > other.microseconds))))))

    def __ge__(self, other):
        return self == other or self > other

    def __lt__(self, other):
        return not self >= other

    def __le__(self, other):
        return not self > other

    def to_months_days_seconds_microseconds(self):
        months = self.months + self.years * 12
        days = self.days
        seconds = self.seconds + self.minutes * 60 + self.hours * 3600
        microseconds = self.microseconds
        return months, days, seconds, microseconds

class Time(TimeDelta):
    def __new__(cls, value=None, *, format=None):
        if isinstance(value, datetime.time):
            d = value
        elif isinstance(value, str):
            try:
                if format:
                    d = datetime.datetime.strptime(value, format)
                else:
                    d = dateutil.parser.parse(value)
            except ValueError as e:
                raise ValueError("invalid value for Time object: %s" % value) from e
        else:
            raise ValueError("invalid value for Time object: %s" % value)

        return super().__new__(cls, hour=d.hour, minute=d.minute, second=d.second,
                                    microsecond=d.microsecond)

    def __str__(self):
        return '%d:%d:%d.%d' % (self.hour, self.minute, self.second, self.microsecond)

    def __repr__(self):
        return "'%d:%d:%d.%d'" % (self.hour, self.minute, self.second, self.microsecond)
<|endoftext|>