<commit_before># Copyright (c) Alex Ponomarev.
# Distributed under the terms of the MIT License.

import tkinter
from math import sqrt, sin, cos
from math import atan as ctg
from math import tan as tg
from point import point
from drawing import draw

WIDTH = 1485     # 210 mm
HEIGHT = 1050    # 297 mm
PRECISION = 10

# Parsing function
def func(x, function):
    function.replace('x', str(x))
    return eval(function)

# Creating graphic
def create_graphic(function, x_pos, y_pos, SCALE, path):
    graphic = []
    min_x = int(-(WIDTH / (2 * SCALE)) - 1)
    max_x = int(WIDTH / (2 * SCALE) + 1)
    for i in range(min_x * PRECISION, max_x * PRECISION + 1):
        j = i / PRECISION
        try:
            p = point(j * SCALE + WIDTH / 2,
                      -func(j, function) * SCALE + HEIGHT / 2)
            graphic.append(p)
        except:
            continue

    draw(graphic, path, "graphic", SCALE)

# Creating GUI
def main(path, function, x_pos, y_pos, SCALE):
    global PRECISIOM
    PRECISION = SCALE / 10

    graphic = []
    create_graphic(function, x_pos, y_pos, SCALE, path)    <commit_msg>commit<commit_after># Copyright (c) Alex Ponomarev.
# Distributed under the terms of the MIT License.

import tkinter
from math import sqrt, sin, cos
from math import atan as ctg
from math import tan as tg
from point import point
from drawing import draw

WIDTH = 1485     # 210 mm
HEIGHT = 1050    # 297 mm
PRECISION = 10

# Parsing function
def func(x, function):
    function.replace('x', str(x))
    return eval(function)

# Creating graphic
def create_graphic(function, x_pos, y_pos, SCALE, path):
    graphic = []
    min_x = int(-(WIDTH / (2 * SCALE)) - 1)
    max_x = int(WIDTH / (2 * SCALE) + 1)
    for i in range(min_x * PRECISION, max_x * PRECISION + 1):
        j = i / PRECISION
        try:
            p = point(j * SCALE + WIDTH / 2,
                -func(j, function) * SCALE + HEIGHT / 2)
            graphic.append(p)
        except:
            continue

    draw(graphic, path, "graphic", SCALE)

# Creating GUI
def main(path, function, x_pos, y_pos, SCALE):
    global PRECISION
    PRECISION = int(SCALE // 10)

    graphic = []
    create_graphic(function, x_pos, y_pos, SCALE, path)    <|endoftext|>


<commit_before>##
# Copyright (c) 2007-2014 Apple Inc. All rights reserved.
#
# 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 re
import sys
import base64

from subprocess import Popen, PIPE, STDOUT
from hashlib import md5, sha1

from twisted.internet import ssl, reactor
from twisted.web import client
from twisted.python import failure
from twext.python.log import Logger

log = Logger()
from twext.internet.gaiendpoint import GAIEndpoint

##
# System Resources (Memory size and processor count)
##

try:
    from ctypes import (
        cdll,
        c_int, c_uint64, c_ulong,
        c_char_p, c_void_p,
        addressof, sizeof, c_size_t,
        connect,
    )
    from ctypes.util import find_library
    hasCtypes = True
except ImportError:
    hasCtypes = False

if sys.platform == "darwin" and hasCtypes:
    libc = cdll.LoadLibrary(find_library("libc"))

    def getNCPU():
        """
        Returns the number of processors detected
        """
        ncpu = c_int(0)
        size = c_size_t(sizeof(ncpu))

        libc.sysctlbyname.argtypes = [
            c_char_p, c_void_p, c_void_p, c_void_p, c_ulong
        ]
        libc.sysctlbyname(
            "hw.ncpu",
            c_void_p(addressof(ncpu)),
            c_void_p(addressof(size)),
            None,
            0
        )

        return int(ncpu.value)

    def getMemorySize():
        """
        Returns the physical amount of RAM installed, in bytes
        """
        memsize = c_uint64(0)
        size = c_size_t(sizeof(memsize))

        libc.sysctlbyname.argtypes = [
            c_char_p, c_void_p, c_void_p, c_void_p, c_ulong
        ]
        libc.sysctlbyname(
            "hw.memsize",
            c_void_p(addressof(memsize)),
            c_void_p(addressof(size)),
            None,
            0
        )

        return int(memsize.value)

elif sys.platform == "linux2" and hasCtypes:
    libc = cdll.LoadLibrary(find_library("libc"))

    def getNCPU():
        return libc.get_nprocs()

    def getMemorySize():
        return libc.getpagesize() * libc.get_phys_pages()

else:
    def getNCPU():
        if not hasCtypes:
            msg = " without ctypes"
        else:
            msg = ""

        raise NotImplementedError("getNCPU not supported on %s%s" % (sys.platform, msg))

    def getMemorySize():
        raise NotImplementedError("getMemorySize not yet supported on %s" % (sys.platform))

def computeProcessCount(minimum, perCPU, perGB, cpuCount=None, memSize=None):
    """
    Determine how many process to spawn based on installed RAM and CPUs,
    returning at least "mininum"
    """

    if cpuCount is None:
        try:
            cpuCount = getNCPU()
        except NotImplementedError, e:
            log.error("Unable to detect number of CPUs: %s" % (str(e),))
            return minimum

    if memSize is None:
        try:
            memSize = getMemorySize()
        except NotImplementedError, e:
            log.error("Unable to detect amount of installed RAM: %s" % (str(e),))
            return minimum

    countByCore = perCPU * cpuCount
    countByMemory = perGB * (memSize / (1024 * 1024 * 1024))

    # Pick the smaller of the two:
    count = min(countByCore, countByMemory)

    # ...but at least "minimum"
    return max(count, minimum)

##
# Module management
##

def submodule(module, name):
    fullname = module.__name__ + "." + name

    try:
        submodule = __import__(fullname)
    except ImportError, e:
        raise ImportError("Unable to import submodule %s from module %s: %s" % (name, module, e))

    for m in fullname.split(".")[1:]:
        submodule = getattr(submodule, m)

    return submodule

##
# Tracebacks
##

from twisted.python.failure import Failure

def printTracebacks(f):
    def wrapper(*args, **kwargs):
        try:
            return f(*args, **kwargs)
        except:
            Failure().printTraceback()
            raise
    return wrapper

##
# Helpers
##

class Alternator (object):
    """
    Object that alternates between True and False states.
    """
    def __init__(self, state=False):
        self._state = bool(state)

    def state(self):
        """
        @return: the current state
        """
        state = self._state
        self._state = not state
        return state

def utf8String(s):
    if isinstance(s, unicode):
        s = s.encode("utf-8")
    return s

##
# Keychain access
##

class KeychainPasswordNotFound(Exception):
    """
    Exception raised when the password does not exist
    """

class KeychainAccessError(Exception):
    """
    Exception raised when not able to access keychain
    """

passwordRegExp = re.compile(r'password: "(.*)"')

def getPasswordFromKeychain(account):
    if os.path.isfile("/usr/bin/security"):
        child = Popen(
            args=[
                "/usr/bin/security", "find-generic-password",
                "-a", account, "-g",
            ],
            stdout=PIPE, stderr=STDOUT,
        )
        output, error = child.communicate()

        if child.returncode:
            raise KeychainPasswordNotFound(error)
        else:
            match = passwordRegExp.search(output)
            if not match:
                error = "Password for %s not found in keychain" % (account,)
                raise KeychainPasswordNotFound(error)
            else:
                return match.group(1)

    else:
        error = "Keychain access utility ('security') not found"
        raise KeychainAccessError(error)

##
# Digest/Basic-capable HTTP GET factory
##

algorithms = {
    'md5': md5,
    'md5-sess': md5,
    'sha': sha1,
}

# DigestCalcHA1
def calcHA1(
    pszAlg,
    pszUserName,
    pszRealm,
    pszPassword,
    pszNonce,
    pszCNonce,
    preHA1=None
):
    """
    @param pszAlg: The name of the algorithm to use to calculate the digest.
        Currently supported are md5 md5-sess and sha.

    @param pszUserName: The username
    @param pszRealm: The realm
    @param pszPassword: The password
    @param pszNonce: The nonce
    @param pszCNonce: The cnonce

    @param preHA1: If available this is a str containing a previously
       calculated HA1 as a hex string. If this is given then the values for
       pszUserName, pszRealm, and pszPassword are ignored.
    """

    if (preHA1 and (pszUserName or pszRealm or pszPassword)):
        raise TypeError(("preHA1 is incompatible with the pszUserName, "
                         "pszRealm, and pszPassword arguments"))

    if preHA1 is None:
        # We need to calculate the HA1 from the username:realm:password
        m = algorithms[pszAlg]()
        m.update(pszUserName)
        m.update(":")
        m.update(pszRealm)
        m.update(":")
        m.update(pszPassword)
        HA1 = m.digest()
    else:
        # We were given a username:realm:password
        HA1 = preHA1.decode('hex')

    if pszAlg == "md5-sess":
        m = algorithms[pszAlg]()
        m.update(HA1)
        m.update(":")
        m.update(pszNonce)
        m.update(":")
        m.update(pszCNonce)
        HA1 = m.digest()

    return HA1.encode('hex')

# DigestCalcResponse
def calcResponse(
    HA1,
    algo,
    pszNonce,
    pszNonceCount,
    pszCNonce,
    pszQop,
    pszMethod,
    pszDigestUri,
    pszHEntity,
):
    m = algorithms[algo]()
    m.update(pszMethod)
    m.update(":")
    m.update(pszDigestUri)
    if pszQop == "auth-int":
        m.update(":")
        m.update(pszHEntity)
    HA2 = m.digest().encode('hex')

    m = algorithms[algo]()
    m.update(HA1)
    m.update(":")
    m.update(pszNonce)
    m.update(":")
    if pszNonceCount and pszCNonce and pszQop:
        m.update(pszNonceCount)
        m.update(":")
        m.update(pszCNonce)
        m.update(":")
        m.update(pszQop)
        m.update(":")
    m.update(HA2)
    respHash = m.digest().encode('hex')
    return respHash

class Unauthorized(Exception):
    pass

class AuthorizedHTTPGetter(client.HTTPPageGetter):
    log = Logger()

    def handleStatus_401(self):

        self.quietLoss = 1
        self.transport.loseConnection()

        if not hasattr(self.factory, "username"):
            self.factory.deferred.errback(failure.Failure(Unauthorized("Authentication required")))
            return self.factory.deferred

        if hasattr(self.factory, "retried"):
            self.factory.deferred.errback(failure.Failure(Unauthorized("Could not authenticate user %s with calendar server" % (self.factory.username,))))
            return self.factory.deferred

        self.factory.retried = True

        # self.log.debug("Got a 401 trying to inject [%s]" % (self.headers,))
        details = {}
        basicAvailable = digestAvailable = False
        wwwauth = self.headers.get("www-authenticate")
        for item in wwwauth:
            if item.startswith("basic "):
                basicAvailable = True
            if item.startswith("digest "):
                digestAvailable = True
                wwwauth = item[7:]
                def unq(s):
                    if s[0] == s[-1] == '"':
                        return s[1:-1]
                    return s
                parts = wwwauth.split(',')
                for (k, v) in [p.split('=', 1) for p in parts]:
                    details[k.strip()] = unq(v.strip())

        user = self.factory.username
        pswd = self.factory.password

        if digestAvailable and details:
            digest = calcResponse(
                calcHA1(
                    details.get('algorithm'),
                    user,
                    details.get('realm'),
                    pswd,
                    details.get('nonce'),
                    details.get('cnonce')
                ),
                details.get('algorithm'),
                details.get('nonce'),
                details.get('nc'),
                details.get('cnonce'),
                details.get('qop'),
                self.factory.method,
                self.factory.url,
                None
            )

            if details.get('qop'):
                response = (
                    'Digest username="%s", realm="%s", nonce="%s", uri="%s", '
                    'response=%s, algorithm=%s, cnonce="%s", qop=%s, nc=%s' %
                    (
                        user,
                        details.get('realm'),
                        details.get('nonce'),
                        self.factory.url,
                        digest,
                        details.get('algorithm'),
                        details.get('cnonce'),
                        details.get('qop'),
                        details.get('nc'),
                    )
                )
            else:
                response = (
                    'Digest username="%s", realm="%s", nonce="%s", uri="%s", '
                    'response=%s, algorithm=%s' %
                    (
                        user,
                        details.get('realm'),
                        details.get('nonce'),
                        self.factory.url,
                        digest,
                        details.get('algorithm'),
                    )
                )

            self.factory.headers['Authorization'] = response

            if self.factory.scheme == 'https':
                connect(
                    GAIEndpoint(reactor, self.factory.host, self.factory.port,
                                ssl.ClientContextFactory()),
                    self.factory)
            else:
                connect(
                    GAIEndpoint(reactor, self.factory.host, self.factory.port),
                    self.factory)
            # self.log.debug("Retrying with digest after 401")

            return self.factory.deferred

        elif basicAvailable:
            basicauth = "%s:%s" % (user, pswd)
            basicauth = "Basic " + base64.encodestring(basicauth)
            basicauth = basicauth.replace("\n", "")

            self.factory.headers['Authorization'] = basicauth

            if self.factory.scheme == 'https':
                connect(
                    GAIEndpoint(reactor, self.factory.host, self.factory.port,
                                ssl.ClientContextFactory()),
                    self.factory)
            else:
                connect(
                    GAIEndpoint(reactor, self.factory.host, self.factory.port),
                    self.factory)
            # self.log.debug("Retrying with basic after 401")

            return self.factory.deferred

        else:
            self.factory.deferred.errback(failure.Failure(Unauthorized("Mail gateway not able to process reply; calendar server returned 401 and doesn't support basic or digest")))
            return self.factory.deferred

def normalizationLookup(cuaddr, principalFunction, config):
    """
    Lookup function to be passed to ical.normalizeCalendarUserAddresses.
    Returns a tuple of (Full name, guid, and calendar user address list)
    for the given cuaddr.  The principalFunction is called to retrieve the
    principal for the cuaddr.
    """
    try:
        principal = principalFunction(cuaddr)
    except Exception, e:
        log.debug("Lookup of %s failed: %s" % (cuaddr, e))
        principal = None

    if principal is None:
        return (None, None, None)
    else:
        rec = principal.record

        # RFC5545 syntax does not allow backslash escaping in
        # parameter values. A double-quote is thus not allowed
        # in a parameter value except as the start/end delimiters.
        # Single quotes are allowed, so we convert any double-quotes
        # to single-quotes.
        fullName = rec.fullName.replace('"', "'")

        cuas = principal.record.calendarUserAddresses

        return (fullName, rec.guid, cuas)

def bestAcceptType(accepts, allowedTypes):
    """
    Given a set of Accept headers and the set of types the server can return, determine the best choice
    of format to return to the client.

    @param accepts: parsed accept headers
    @type accepts: C{dict}
    @param allowedTypes: list of allowed types in server preferred order
    @type allowedTypes: C{list}
    """

    # If no Accept present just use the first allowed type - the server's preference
    if not accepts:
        return allowedTypes[0]

    # Get mapping for ordered top-level types for use in subtype wildcard match
    toptypes = {}
    for allowed in allowedTypes:
        mediaType = allowed.split("/")[0]
        if mediaType not in toptypes:
            toptypes[mediaType] = allowed

    result = None
    result_qval = 0.0
    for content_type, qval in accepts.items():
        # Exact match
        ctype = "%s/%s" % (content_type.mediaType, content_type.mediaSubtype,)
        if ctype in allowedTypes:
            if qval > result_qval:
                result = ctype
                result_qval = qval

        # Subtype wildcard match
        elif content_type.mediaType != "*" and content_type.mediaSubtype == "*":
            if content_type.mediaType in toptypes:
                if qval > result_qval:
                    result = toptypes[content_type.mediaType]
                    result_qval = qval

        # Full wildcard match
        elif content_type.mediaType == "*" and content_type.mediaSubtype == "*":
            if qval > result_qval:
                result = allowedTypes[0]
                result_qval = qval

    return result
<commit_msg>Fix bug introduced in r12093 which caused getNCput to be skipped.<commit_after>##
# Copyright (c) 2007-2014 Apple Inc. All rights reserved.
#
# 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 re
import sys
import base64

from subprocess import Popen, PIPE, STDOUT
from hashlib import md5, sha1

from twisted.internet import ssl, reactor
from twisted.web import client
from twisted.python import failure
from twext.python.log import Logger

log = Logger()
from twext.internet.gaiendpoint import GAIEndpoint
from twext.internet.adaptendpoint import connect

##
# System Resources (Memory size and processor count)
##

try:
    from ctypes import (
        cdll,
        c_int, c_uint64, c_ulong,
        c_char_p, c_void_p,
        addressof, sizeof, c_size_t,
    )
    from ctypes.util import find_library
    hasCtypes = True
except ImportError:
    hasCtypes = False

if sys.platform == "darwin" and hasCtypes:
    libc = cdll.LoadLibrary(find_library("libc"))

    def getNCPU():
        """
        Returns the number of processors detected
        """
        ncpu = c_int(0)
        size = c_size_t(sizeof(ncpu))

        libc.sysctlbyname.argtypes = [
            c_char_p, c_void_p, c_void_p, c_void_p, c_ulong
        ]
        libc.sysctlbyname(
            "hw.ncpu",
            c_void_p(addressof(ncpu)),
            c_void_p(addressof(size)),
            None,
            0
        )

        return int(ncpu.value)

    def getMemorySize():
        """
        Returns the physical amount of RAM installed, in bytes
        """
        memsize = c_uint64(0)
        size = c_size_t(sizeof(memsize))

        libc.sysctlbyname.argtypes = [
            c_char_p, c_void_p, c_void_p, c_void_p, c_ulong
        ]
        libc.sysctlbyname(
            "hw.memsize",
            c_void_p(addressof(memsize)),
            c_void_p(addressof(size)),
            None,
            0
        )

        return int(memsize.value)

elif sys.platform == "linux2" and hasCtypes:
    libc = cdll.LoadLibrary(find_library("libc"))

    def getNCPU():
        return libc.get_nprocs()

    def getMemorySize():
        return libc.getpagesize() * libc.get_phys_pages()

else:
    def getNCPU():
        if not hasCtypes:
            msg = " without ctypes"
        else:
            msg = ""

        raise NotImplementedError("getNCPU not supported on %s%s" % (sys.platform, msg))

    def getMemorySize():
        raise NotImplementedError("getMemorySize not yet supported on %s" % (sys.platform))

def computeProcessCount(minimum, perCPU, perGB, cpuCount=None, memSize=None):
    """
    Determine how many process to spawn based on installed RAM and CPUs,
    returning at least "mininum"
    """

    if cpuCount is None:
        try:
            cpuCount = getNCPU()
        except NotImplementedError, e:
            log.error("Unable to detect number of CPUs: %s" % (str(e),))
            return minimum

    if memSize is None:
        try:
            memSize = getMemorySize()
        except NotImplementedError, e:
            log.error("Unable to detect amount of installed RAM: %s" % (str(e),))
            return minimum

    countByCore = perCPU * cpuCount
    countByMemory = perGB * (memSize / (1024 * 1024 * 1024))

    # Pick the smaller of the two:
    count = min(countByCore, countByMemory)

    # ...but at least "minimum"
    return max(count, minimum)

##
# Module management
##

def submodule(module, name):
    fullname = module.__name__ + "." + name

    try:
        submodule = __import__(fullname)
    except ImportError, e:
        raise ImportError("Unable to import submodule %s from module %s: %s" % (name, module, e))

    for m in fullname.split(".")[1:]:
        submodule = getattr(submodule, m)

    return submodule

##
# Tracebacks
##

from twisted.python.failure import Failure

def printTracebacks(f):
    def wrapper(*args, **kwargs):
        try:
            return f(*args, **kwargs)
        except:
            Failure().printTraceback()
            raise
    return wrapper

##
# Helpers
##

class Alternator (object):
    """
    Object that alternates between True and False states.
    """
    def __init__(self, state=False):
        self._state = bool(state)

    def state(self):
        """
        @return: the current state
        """
        state = self._state
        self._state = not state
        return state

def utf8String(s):
    if isinstance(s, unicode):
        s = s.encode("utf-8")
    return s

##
# Keychain access
##

class KeychainPasswordNotFound(Exception):
    """
    Exception raised when the password does not exist
    """

class KeychainAccessError(Exception):
    """
    Exception raised when not able to access keychain
    """

passwordRegExp = re.compile(r'password: "(.*)"')

def getPasswordFromKeychain(account):
    if os.path.isfile("/usr/bin/security"):
        child = Popen(
            args=[
                "/usr/bin/security", "find-generic-password",
                "-a", account, "-g",
            ],
            stdout=PIPE, stderr=STDOUT,
        )
        output, error = child.communicate()

        if child.returncode:
            raise KeychainPasswordNotFound(error)
        else:
            match = passwordRegExp.search(output)
            if not match:
                error = "Password for %s not found in keychain" % (account,)
                raise KeychainPasswordNotFound(error)
            else:
                return match.group(1)

    else:
        error = "Keychain access utility ('security') not found"
        raise KeychainAccessError(error)

##
# Digest/Basic-capable HTTP GET factory
##

algorithms = {
    'md5': md5,
    'md5-sess': md5,
    'sha': sha1,
}

# DigestCalcHA1
def calcHA1(
    pszAlg,
    pszUserName,
    pszRealm,
    pszPassword,
    pszNonce,
    pszCNonce,
    preHA1=None
):
    """
    @param pszAlg: The name of the algorithm to use to calculate the digest.
        Currently supported are md5 md5-sess and sha.

    @param pszUserName: The username
    @param pszRealm: The realm
    @param pszPassword: The password
    @param pszNonce: The nonce
    @param pszCNonce: The cnonce

    @param preHA1: If available this is a str containing a previously
       calculated HA1 as a hex string. If this is given then the values for
       pszUserName, pszRealm, and pszPassword are ignored.
    """

    if (preHA1 and (pszUserName or pszRealm or pszPassword)):
        raise TypeError(("preHA1 is incompatible with the pszUserName, "
                         "pszRealm, and pszPassword arguments"))

    if preHA1 is None:
        # We need to calculate the HA1 from the username:realm:password
        m = algorithms[pszAlg]()
        m.update(pszUserName)
        m.update(":")
        m.update(pszRealm)
        m.update(":")
        m.update(pszPassword)
        HA1 = m.digest()
    else:
        # We were given a username:realm:password
        HA1 = preHA1.decode('hex')

    if pszAlg == "md5-sess":
        m = algorithms[pszAlg]()
        m.update(HA1)
        m.update(":")
        m.update(pszNonce)
        m.update(":")
        m.update(pszCNonce)
        HA1 = m.digest()

    return HA1.encode('hex')

# DigestCalcResponse
def calcResponse(
    HA1,
    algo,
    pszNonce,
    pszNonceCount,
    pszCNonce,
    pszQop,
    pszMethod,
    pszDigestUri,
    pszHEntity,
):
    m = algorithms[algo]()
    m.update(pszMethod)
    m.update(":")
    m.update(pszDigestUri)
    if pszQop == "auth-int":
        m.update(":")
        m.update(pszHEntity)
    HA2 = m.digest().encode('hex')

    m = algorithms[algo]()
    m.update(HA1)
    m.update(":")
    m.update(pszNonce)
    m.update(":")
    if pszNonceCount and pszCNonce and pszQop:
        m.update(pszNonceCount)
        m.update(":")
        m.update(pszCNonce)
        m.update(":")
        m.update(pszQop)
        m.update(":")
    m.update(HA2)
    respHash = m.digest().encode('hex')
    return respHash

class Unauthorized(Exception):
    pass

class AuthorizedHTTPGetter(client.HTTPPageGetter):
    log = Logger()

    def handleStatus_401(self):

        self.quietLoss = 1
        self.transport.loseConnection()

        if not hasattr(self.factory, "username"):
            self.factory.deferred.errback(failure.Failure(Unauthorized("Authentication required")))
            return self.factory.deferred

        if hasattr(self.factory, "retried"):
            self.factory.deferred.errback(failure.Failure(Unauthorized("Could not authenticate user %s with calendar server" % (self.factory.username,))))
            return self.factory.deferred

        self.factory.retried = True

        # self.log.debug("Got a 401 trying to inject [%s]" % (self.headers,))
        details = {}
        basicAvailable = digestAvailable = False
        wwwauth = self.headers.get("www-authenticate")
        for item in wwwauth:
            if item.startswith("basic "):
                basicAvailable = True
            if item.startswith("digest "):
                digestAvailable = True
                wwwauth = item[7:]
                def unq(s):
                    if s[0] == s[-1] == '"':
                        return s[1:-1]
                    return s
                parts = wwwauth.split(',')
                for (k, v) in [p.split('=', 1) for p in parts]:
                    details[k.strip()] = unq(v.strip())

        user = self.factory.username
        pswd = self.factory.password

        if digestAvailable and details:
            digest = calcResponse(
                calcHA1(
                    details.get('algorithm'),
                    user,
                    details.get('realm'),
                    pswd,
                    details.get('nonce'),
                    details.get('cnonce')
                ),
                details.get('algorithm'),
                details.get('nonce'),
                details.get('nc'),
                details.get('cnonce'),
                details.get('qop'),
                self.factory.method,
                self.factory.url,
                None
            )

            if details.get('qop'):
                response = (
                    'Digest username="%s", realm="%s", nonce="%s", uri="%s", '
                    'response=%s, algorithm=%s, cnonce="%s", qop=%s, nc=%s' %
                    (
                        user,
                        details.get('realm'),
                        details.get('nonce'),
                        self.factory.url,
                        digest,
                        details.get('algorithm'),
                        details.get('cnonce'),
                        details.get('qop'),
                        details.get('nc'),
                    )
                )
            else:
                response = (
                    'Digest username="%s", realm="%s", nonce="%s", uri="%s", '
                    'response=%s, algorithm=%s' %
                    (
                        user,
                        details.get('realm'),
                        details.get('nonce'),
                        self.factory.url,
                        digest,
                        details.get('algorithm'),
                    )
                )

            self.factory.headers['Authorization'] = response

            if self.factory.scheme == 'https':
                connect(
                    GAIEndpoint(reactor, self.factory.host, self.factory.port,
                                ssl.ClientContextFactory()),
                    self.factory)
            else:
                connect(
                    GAIEndpoint(reactor, self.factory.host, self.factory.port),
                    self.factory)
            # self.log.debug("Retrying with digest after 401")

            return self.factory.deferred

        elif basicAvailable:
            basicauth = "%s:%s" % (user, pswd)
            basicauth = "Basic " + base64.encodestring(basicauth)
            basicauth = basicauth.replace("\n", "")

            self.factory.headers['Authorization'] = basicauth

            if self.factory.scheme == 'https':
                connect(
                    GAIEndpoint(reactor, self.factory.host, self.factory.port,
                                ssl.ClientContextFactory()),
                    self.factory)
            else:
                connect(
                    GAIEndpoint(reactor, self.factory.host, self.factory.port),
                    self.factory)
            # self.log.debug("Retrying with basic after 401")

            return self.factory.deferred

        else:
            self.factory.deferred.errback(failure.Failure(Unauthorized("Mail gateway not able to process reply; calendar server returned 401 and doesn't support basic or digest")))
            return self.factory.deferred

def normalizationLookup(cuaddr, principalFunction, config):
    """
    Lookup function to be passed to ical.normalizeCalendarUserAddresses.
    Returns a tuple of (Full name, guid, and calendar user address list)
    for the given cuaddr.  The principalFunction is called to retrieve the
    principal for the cuaddr.
    """
    try:
        principal = principalFunction(cuaddr)
    except Exception, e:
        log.debug("Lookup of %s failed: %s" % (cuaddr, e))
        principal = None

    if principal is None:
        return (None, None, None)
    else:
        rec = principal.record

        # RFC5545 syntax does not allow backslash escaping in
        # parameter values. A double-quote is thus not allowed
        # in a parameter value except as the start/end delimiters.
        # Single quotes are allowed, so we convert any double-quotes
        # to single-quotes.
        fullName = rec.fullName.replace('"', "'")

        cuas = principal.record.calendarUserAddresses

        return (fullName, rec.guid, cuas)

def bestAcceptType(accepts, allowedTypes):
    """
    Given a set of Accept headers and the set of types the server can return, determine the best choice
    of format to return to the client.

    @param accepts: parsed accept headers
    @type accepts: C{dict}
    @param allowedTypes: list of allowed types in server preferred order
    @type allowedTypes: C{list}
    """

    # If no Accept present just use the first allowed type - the server's preference
    if not accepts:
        return allowedTypes[0]

    # Get mapping for ordered top-level types for use in subtype wildcard match
    toptypes = {}
    for allowed in allowedTypes:
        mediaType = allowed.split("/")[0]
        if mediaType not in toptypes:
            toptypes[mediaType] = allowed

    result = None
    result_qval = 0.0
    for content_type, qval in accepts.items():
        # Exact match
        ctype = "%s/%s" % (content_type.mediaType, content_type.mediaSubtype,)
        if ctype in allowedTypes:
            if qval > result_qval:
                result = ctype
                result_qval = qval

        # Subtype wildcard match
        elif content_type.mediaType != "*" and content_type.mediaSubtype == "*":
            if content_type.mediaType in toptypes:
                if qval > result_qval:
                    result = toptypes[content_type.mediaType]
                    result_qval = qval

        # Full wildcard match
        elif content_type.mediaType == "*" and content_type.mediaSubtype == "*":
            if qval > result_qval:
                result = allowedTypes[0]
                result_qval = qval

    return result
<|endoftext|>


<commit_before>import math
import sublime
import sublime_plugin

class GruvboxSelect(sublime_plugin.TextCommand):
    def run(self, action):
        color_schemes = sublime.find_resources("gruvbox*.sublime-color-scheme")
        color_themes = sublime.find_resources("gruvbox*.sublime-theme")

        temp_schemes = []
        self.themes = []
        self.schemes = []

        for scheme in color_schemes:
            if 'Packages/gruvbox/' in scheme:
                temp_schemes.append(scheme[17:-8])

        for i in range(len(temp_schemes)):
            if (i % 2) == 0:
                self.schemes.insert(i + 1, temp_schemes[i])
            else:
                self.schemes.insert(i - 1, temp_schemes[i])

        for theme in color_themes:
            if 'Packages/gruvbox/' in theme:
                self.themes.append(theme[17:])

        self.show_panel()

    def show_panel(self):
        self.view.window().show_quick_panel(self.schemes, self.on_done, on_highlight=self.on_highlighted)

    def on_done(self, index):
        self.set_scheme('Packages/gruvbox/' + self.schemes[index] + '.sublime-color-scheme')
        self.set_theme(self.themes[self.find_index(index)])
        self.save_settings(self.schemes[index])

    def on_highlighted(self, index):
        self.set_scheme('Packages/gruvbox/' + self.schemes[index] + '.sublime-color-scheme')
        self.set_theme(self.themes[self.find_index(index)])

    def find_index(self, index):
        if index == 0 or index == 1:
            return 0
        else:
            return int(math.floor((index / 2)))

    def set_scheme(self, scheme):
        self.get_settings().set('color_scheme', scheme)

    def set_theme(self, theme):
        self.get_settings().set('theme', theme)

    def get_settings(self):
        return sublime.load_settings('Preferences.sublime-settings')

    def save_settings(self, theme):
        sublime.save_settings('Preferences.sublime-settings')
        sublime.status_message('gruvbox: ' + theme)
        print('')
        print('[gruvbox] ' +  theme)
        print('')
<commit_msg>fix select theme slice to handle sublime-color-scheme<commit_after>import math
import sublime
import sublime_plugin

class GruvboxSelect(sublime_plugin.TextCommand):
    def run(self, action):
        color_schemes = sublime.find_resources("gruvbox*.sublime-color-scheme")
        color_themes = sublime.find_resources("gruvbox*.sublime-theme")

        temp_schemes = []
        self.themes = []
        self.schemes = []

        for scheme in color_schemes:
            if 'Packages/gruvbox/' in scheme:
                temp_schemes.append(scheme[17:-21])

        for i in range(len(temp_schemes)):
            if (i % 2) == 0:
                self.schemes.insert(i + 1, temp_schemes[i])
            else:
                self.schemes.insert(i - 1, temp_schemes[i])

        for theme in color_themes:
            if 'Packages/gruvbox/' in theme:
                self.themes.append(theme[17:])

        self.show_panel()

    def show_panel(self):
        self.view.window().show_quick_panel(self.schemes, self.on_done, on_highlight=self.on_highlighted)

    def on_done(self, index):
        self.set_scheme('Packages/gruvbox/' + self.schemes[index] + '.sublime-color-scheme')
        self.set_theme(self.themes[self.find_index(index)])
        self.save_settings(self.schemes[index])

    def on_highlighted(self, index):
        self.set_scheme('Packages/gruvbox/' + self.schemes[index] + '.sublime-color-scheme')
        self.set_theme(self.themes[self.find_index(index)])

    def find_index(self, index):
        if index == 0 or index == 1:
            return 0
        else:
            return int(math.floor((index / 2)))

    def set_scheme(self, scheme):
        self.get_settings().set('color_scheme', scheme)

    def set_theme(self, theme):
        self.get_settings().set('theme', theme)

    def get_settings(self):
        return sublime.load_settings('Preferences.sublime-settings')

    def save_settings(self, theme):
        sublime.save_settings('Preferences.sublime-settings')
        sublime.status_message('gruvbox: ' + theme)
        print('')
        print('[gruvbox] ' +  theme)
        print('')
<|endoftext|>


<commit_before># This should be extended for each Python release.
# The product code must change whenever the name of the MSI file
# changes, and when new component codes are issued for existing
# components. See "Changing the Product Code". As we change the
# component codes with every build, we need a new product code
# each time. For intermediate (snapshot) releases, they are automatically
# generated. For official releases, we record the product codes,
# so people can refer to them.
product_codes = {
    '2.4.101': '{0e9b4d8e-6cda-446e-a208-7b92f3ddffa0}', # 2.4a1, released as a snapshot
    '2.4.102': '{1b998745-4901-4edb-bc52-213689e1b922}', # 2.4a2
    '2.4.103': '{33fc8bd2-1e8f-4add-a40a-ade2728d5942}', # 2.4a3
    '2.4.111': '{51a7e2a8-2025-4ef0-86ff-e6aab742d1fa}', # 2.4b1
    '2.4.112': '{4a5e7c1d-c659-4fe3-b8c9-7c65bd9c95a5}', # 2.4b2
    '2.4.121': '{75508821-a8e9-40a8-95bd-dbe6033ddbea}', # 2.4c1
    '2.4.122': '{83a9118b-4bdd-473b-afc3-bcb142feca9e}', # 2.4c2
    '2.4.150': '{82d9302e-f209-4805-b548-52087047483a}', # 2.4.0
    '2.4.1121':'{be027411-8e6b-4440-a29b-b07df0690230}', # 2.4.1c1
    '2.4.1122':'{02818752-48bf-4074-a281-7a4114c4f1b1}', # 2.4.1c2
    '2.4.1150':'{4d4f5346-7e4a-40b5-9387-fdb6181357fc}', # 2.4.1
    '2.4.2121':'{5ef9d6b6-df78-45d2-ab09-14786a3c5a99}', # 2.4.2c1
    '2.4.2150':'{b191e49c-ea23-43b2-b28a-14e0784069b8}', # 2.4.2
    '2.4.3121':'{f669ed4d-1dce-41c4-9617-d985397187a1}', # 2.4.3c1
    '2.4.3150':'{75e71add-042c-4f30-bfac-a9ec42351313}', # 2.4.3
    '2.4.4121':'{cd2862db-22a4-4688-8772-85407ea21550}', # 2.4.4c1
    '2.4.4150':'{60e2c8c9-6cf3-4b1a-9618-e304946c94e6}', # 2.4.4
    '2.5.101': '{bc14ce3e-5e72-4a64-ac1f-bf59a571898c}', # 2.5a1
    '2.5.102': '{5eed51c1-8e9d-4071-94c5-b40de5d49ba5}', # 2.5a2
    '2.5.103': '{73dcd966-ffec-415f-bb39-8342c1f47017}', # 2.5a3
    '2.5.111': '{c797ecf8-a8e6-4fec-bb99-526b65f28626}', # 2.5b1
    '2.5.112': '{32beb774-f625-439d-b587-7187487baf15}', # 2.5b2
    '2.5.113': '{89f23918-11cf-4f08-be13-b9b2e6463fd9}', # 2.5b3
    '2.5.121': '{8e9321bc-6b24-48a3-8fd4-c95f8e531e5f}', # 2.5c1
    '2.5.122': '{a6cd508d-9599-45da-a441-cbffa9f7e070}', # 2.5c2
    '2.5.150': '{0a2c5854-557e-48c8-835a-3b9f074bdcaa}', # 2.5.0
    '2.5.1121':'{0378b43e-6184-4c2f-be1a-4a367781cd54}', # 2.5.1c1
    '2.5.1150':'{31800004-6386-4999-a519-518f2d78d8f0}', # 2.5.1
    '2.5.2150':'{6304a7da-1132-4e91-a343-a296269eab8a}', # 2.5.2c1
    '2.5.2150':'{6b976adf-8ae8-434e-b282-a06c7f624d2f}', # 2.5.2
    '2.6.101': '{0ba82e1b-52fd-4e03-8610-a6c76238e8a8}', # 2.6a1
    '2.6.102': '{3b27e16c-56db-4570-a2d3-e9a26180c60b}', # 2.6a2
    '2.6.103': '{cd06a9c5-bde5-4bd7-9874-48933997122a}', # 2.6a3
    '2.6.104': '{dc6ed634-474a-4a50-a547-8de4b7491e53}', # 2.6a4
    '2.6.111': '{3f82079a-5bee-4c4a-8a41-8292389e24ae}', # 2.6b1
    '2.6.112': '{8a0e5970-f3e6-4737-9a2b-bc5ff0f15fb5}', # 2.6b2
    '2.6.113': '{df4f5c21-6fcc-4540-95de-85feba634e76}', # 2.6b3
    '2.6.121': '{bbd34464-ddeb-4028-99e5-f16c4a8fbdb3}', # 2.6c1
    '2.6.122': '{8f64787e-a023-4c60-bfee-25d3a3f592c6}', # 2.6c2
    '2.6.150': '{110eb5c4-e995-4cfb-ab80-a5f315bea9e8}', # 2.6.0
    '2.6.1150':'{9cc89170-000b-457d-91f1-53691f85b223}', # 2.6.1
    '2.6.2121':'{adac412b-b209-4c15-b6ab-dca1b6e47144}', # 2.6.2c1
    '2.6.2150':'{24aab420-4e30-4496-9739-3e216f3de6ae}', # 2.6.2
    '3.0.101': '{8554263a-3242-4857-9359-aa87bc2c58c2}', # 3.0a1
    '3.0.102': '{692d6e2c-f0ac-40b8-a133-7191aeeb67f9}', # 3.0a2
    '3.0.103': '{49cb2995-751a-4753-be7a-d0b1bb585e06}', # 3.0a3
    '3.0.104': '{87cb019e-19fd-4238-b1c7-85751437d646}', # 3.0a4
    '3.0.105': '{cf2659af-19ec-43d2-8c35-0f6a09439d42}', # 3.0a5
    '3.0.111': '{36c26f55-837d-45cf-848c-5f5c0fb47a28}', # 3.0b1
    '3.0.112': '{056a0fbc-c8fe-4c61-aade-c4411b70c998}', # 3.0b2
    '3.0.113': '{2b2e89a9-83af-43f9-b7d5-96e80c5a3f26}', # 3.0b3
    '3.0.114': '{e95c31af-69be-4dd7-96e6-e5fc85e660e6}', # 3.0b4
    '3.0.121': '{d0979c5e-cd3c-42ec-be4c-e294da793573}', # 3.0c1
    '3.0.122': '{f707b8e9-a257-4045-818e-4923fc20fbb6}', # 3.0c2
    '3.0.123': '{5e7208f1-8643-4ea2-ab5e-4644887112e3}', # 3.0c3
    '3.0.150': '{e0e56e21-55de-4f77-a109-1baa72348743}', # 3.0.0
    '3.0.1121':'{d35b1ea5-3d70-4872-bf7e-cd066a77a9c9}', # 3.0.1c1
    '3.0.1150':'{de2f2d9c-53e2-40ee-8209-74da63cb060e}', # 3.0.1
    '3.0.2121':'{cef79e7f-9809-49e2-afd2-e24148d7c855}', # 3.0.2c1
    '3.0.2150':'{0cf3b95a-8382-4607-9779-c36407ff362c}', # 3.0.2
    '3.1.101': '{c423eada-c498-4d51-9eb4-bfeae647e0a0}', # 3.1a1
    '3.1.102': '{f6e199bf-dc64-42f3-87d4-1525991a013e}', # 3.1a2
    '3.1.111': '{c3c82893-69b2-4676-8554-1b6ee6c191e9}', # 3.1b1
    '3.1.121': '{da2b5170-12f3-4d99-8a1f-54926cca7acd}', # 3.1c1
    '3.1.122': '{bceb5133-e2ee-4109-951f-ac7e941a1692}', # 3.1c2
    '3.1.150': '{3ad61ee5-81d2-4d7e-adef-da1dd37277d1}', # 3.1.0
    '3.1.1121':'{5782f957-6d49-41d4-bad0-668715dfd638}', # 3.1.1c1
    '3.1.1150':'{7ff90460-89b7-435b-b583-b37b2815ccc7}', # 3.1.1
    '3.1.2121':'{ec45624a-378c-43be-91f3-3f7a59b0d90c}', # 3.1.2c1
    '3.1.2150':'{d40af016-506c-43fb-a738-bd54fa8c1e85}', # 3.1.2
}
<commit_msg>Add 3.1.3 UUIDs.<commit_after># This should be extended for each Python release.
# The product code must change whenever the name of the MSI file
# changes, and when new component codes are issued for existing
# components. See "Changing the Product Code". As we change the
# component codes with every build, we need a new product code
# each time. For intermediate (snapshot) releases, they are automatically
# generated. For official releases, we record the product codes,
# so people can refer to them.
product_codes = {
    '2.4.101': '{0e9b4d8e-6cda-446e-a208-7b92f3ddffa0}', # 2.4a1, released as a snapshot
    '2.4.102': '{1b998745-4901-4edb-bc52-213689e1b922}', # 2.4a2
    '2.4.103': '{33fc8bd2-1e8f-4add-a40a-ade2728d5942}', # 2.4a3
    '2.4.111': '{51a7e2a8-2025-4ef0-86ff-e6aab742d1fa}', # 2.4b1
    '2.4.112': '{4a5e7c1d-c659-4fe3-b8c9-7c65bd9c95a5}', # 2.4b2
    '2.4.121': '{75508821-a8e9-40a8-95bd-dbe6033ddbea}', # 2.4c1
    '2.4.122': '{83a9118b-4bdd-473b-afc3-bcb142feca9e}', # 2.4c2
    '2.4.150': '{82d9302e-f209-4805-b548-52087047483a}', # 2.4.0
    '2.4.1121':'{be027411-8e6b-4440-a29b-b07df0690230}', # 2.4.1c1
    '2.4.1122':'{02818752-48bf-4074-a281-7a4114c4f1b1}', # 2.4.1c2
    '2.4.1150':'{4d4f5346-7e4a-40b5-9387-fdb6181357fc}', # 2.4.1
    '2.4.2121':'{5ef9d6b6-df78-45d2-ab09-14786a3c5a99}', # 2.4.2c1
    '2.4.2150':'{b191e49c-ea23-43b2-b28a-14e0784069b8}', # 2.4.2
    '2.4.3121':'{f669ed4d-1dce-41c4-9617-d985397187a1}', # 2.4.3c1
    '2.4.3150':'{75e71add-042c-4f30-bfac-a9ec42351313}', # 2.4.3
    '2.4.4121':'{cd2862db-22a4-4688-8772-85407ea21550}', # 2.4.4c1
    '2.4.4150':'{60e2c8c9-6cf3-4b1a-9618-e304946c94e6}', # 2.4.4
    '2.5.101': '{bc14ce3e-5e72-4a64-ac1f-bf59a571898c}', # 2.5a1
    '2.5.102': '{5eed51c1-8e9d-4071-94c5-b40de5d49ba5}', # 2.5a2
    '2.5.103': '{73dcd966-ffec-415f-bb39-8342c1f47017}', # 2.5a3
    '2.5.111': '{c797ecf8-a8e6-4fec-bb99-526b65f28626}', # 2.5b1
    '2.5.112': '{32beb774-f625-439d-b587-7187487baf15}', # 2.5b2
    '2.5.113': '{89f23918-11cf-4f08-be13-b9b2e6463fd9}', # 2.5b3
    '2.5.121': '{8e9321bc-6b24-48a3-8fd4-c95f8e531e5f}', # 2.5c1
    '2.5.122': '{a6cd508d-9599-45da-a441-cbffa9f7e070}', # 2.5c2
    '2.5.150': '{0a2c5854-557e-48c8-835a-3b9f074bdcaa}', # 2.5.0
    '2.5.1121':'{0378b43e-6184-4c2f-be1a-4a367781cd54}', # 2.5.1c1
    '2.5.1150':'{31800004-6386-4999-a519-518f2d78d8f0}', # 2.5.1
    '2.5.2150':'{6304a7da-1132-4e91-a343-a296269eab8a}', # 2.5.2c1
    '2.5.2150':'{6b976adf-8ae8-434e-b282-a06c7f624d2f}', # 2.5.2
    '2.6.101': '{0ba82e1b-52fd-4e03-8610-a6c76238e8a8}', # 2.6a1
    '2.6.102': '{3b27e16c-56db-4570-a2d3-e9a26180c60b}', # 2.6a2
    '2.6.103': '{cd06a9c5-bde5-4bd7-9874-48933997122a}', # 2.6a3
    '2.6.104': '{dc6ed634-474a-4a50-a547-8de4b7491e53}', # 2.6a4
    '2.6.111': '{3f82079a-5bee-4c4a-8a41-8292389e24ae}', # 2.6b1
    '2.6.112': '{8a0e5970-f3e6-4737-9a2b-bc5ff0f15fb5}', # 2.6b2
    '2.6.113': '{df4f5c21-6fcc-4540-95de-85feba634e76}', # 2.6b3
    '2.6.121': '{bbd34464-ddeb-4028-99e5-f16c4a8fbdb3}', # 2.6c1
    '2.6.122': '{8f64787e-a023-4c60-bfee-25d3a3f592c6}', # 2.6c2
    '2.6.150': '{110eb5c4-e995-4cfb-ab80-a5f315bea9e8}', # 2.6.0
    '2.6.1150':'{9cc89170-000b-457d-91f1-53691f85b223}', # 2.6.1
    '2.6.2121':'{adac412b-b209-4c15-b6ab-dca1b6e47144}', # 2.6.2c1
    '2.6.2150':'{24aab420-4e30-4496-9739-3e216f3de6ae}', # 2.6.2
    '3.0.101': '{8554263a-3242-4857-9359-aa87bc2c58c2}', # 3.0a1
    '3.0.102': '{692d6e2c-f0ac-40b8-a133-7191aeeb67f9}', # 3.0a2
    '3.0.103': '{49cb2995-751a-4753-be7a-d0b1bb585e06}', # 3.0a3
    '3.0.104': '{87cb019e-19fd-4238-b1c7-85751437d646}', # 3.0a4
    '3.0.105': '{cf2659af-19ec-43d2-8c35-0f6a09439d42}', # 3.0a5
    '3.0.111': '{36c26f55-837d-45cf-848c-5f5c0fb47a28}', # 3.0b1
    '3.0.112': '{056a0fbc-c8fe-4c61-aade-c4411b70c998}', # 3.0b2
    '3.0.113': '{2b2e89a9-83af-43f9-b7d5-96e80c5a3f26}', # 3.0b3
    '3.0.114': '{e95c31af-69be-4dd7-96e6-e5fc85e660e6}', # 3.0b4
    '3.0.121': '{d0979c5e-cd3c-42ec-be4c-e294da793573}', # 3.0c1
    '3.0.122': '{f707b8e9-a257-4045-818e-4923fc20fbb6}', # 3.0c2
    '3.0.123': '{5e7208f1-8643-4ea2-ab5e-4644887112e3}', # 3.0c3
    '3.0.150': '{e0e56e21-55de-4f77-a109-1baa72348743}', # 3.0.0
    '3.0.1121':'{d35b1ea5-3d70-4872-bf7e-cd066a77a9c9}', # 3.0.1c1
    '3.0.1150':'{de2f2d9c-53e2-40ee-8209-74da63cb060e}', # 3.0.1
    '3.0.2121':'{cef79e7f-9809-49e2-afd2-e24148d7c855}', # 3.0.2c1
    '3.0.2150':'{0cf3b95a-8382-4607-9779-c36407ff362c}', # 3.0.2
    '3.1.101': '{c423eada-c498-4d51-9eb4-bfeae647e0a0}', # 3.1a1
    '3.1.102': '{f6e199bf-dc64-42f3-87d4-1525991a013e}', # 3.1a2
    '3.1.111': '{c3c82893-69b2-4676-8554-1b6ee6c191e9}', # 3.1b1
    '3.1.121': '{da2b5170-12f3-4d99-8a1f-54926cca7acd}', # 3.1c1
    '3.1.122': '{bceb5133-e2ee-4109-951f-ac7e941a1692}', # 3.1c2
    '3.1.150': '{3ad61ee5-81d2-4d7e-adef-da1dd37277d1}', # 3.1.0
    '3.1.1121':'{5782f957-6d49-41d4-bad0-668715dfd638}', # 3.1.1c1
    '3.1.1150':'{7ff90460-89b7-435b-b583-b37b2815ccc7}', # 3.1.1
    '3.1.2121':'{ec45624a-378c-43be-91f3-3f7a59b0d90c}', # 3.1.2c1
    '3.1.2150':'{d40af016-506c-43fb-a738-bd54fa8c1e85}', # 3.1.2
    '3.1.3121':'{a1e436f8-92fc-4ddb-af18-a12529c57aaf}', # 3.1.3rc1
    '3.1.3122':'{2fc19026-a3e5-493e-92a0-c1f3b4a272ae}', # 3.1.3rc2
    '3.1.3150':'{f719d8a6-46fc-4d71-94c6-ffd17a8c9f35}', # 3.1.3
}
<|endoftext|>


<commit_before># Copyright (c) 2015 Ultimaker B.V.
# Uranium is released under the terms of the AGPLv3 or higher.

import copy
import numpy
import time

from UM.Job import Job
from UM.Math.Float import Float #For fuzzy comparison of edge cases.
from UM.Math.LineSegment import LineSegment #For line-line intersections for computing polygon intersections.
from UM.Math.Vector2 import Vector2 #For constructing line segments for polygon intersections.

try:
    import scipy.spatial
    has_scipy = True
except ImportError:
    has_scipy = False

##  A class representing an arbitrary 2-dimensional polygon.
class Polygon:
    def __init__(self, points = None):
        self._points = points

    def isValid(self):
        return self._points is not None and len(self._points)

    def getPoints(self):
        return self._points

    def setPoints(self, points):
        self._points = points

    ##  Project this polygon on a line described by a normal.
    #
    #   \param normal The normal to project on.
    #   \return A tuple describing the line segment of this Polygon projected on to the infinite line described by normal.
    #           The first element is the minimum value, the second the maximum.
    def project(self, normal):
        projection_min = numpy.dot(normal, self._points[0])
        projection_max = projection_min
        for point in self._points:
            projection = numpy.dot(normal, point)
            projection_min = min(projection_min, projection)
            projection_max = max(projection_max, projection)

        return (projection_min, projection_max)

    ##  Mirrors this polygon across the specified axis.
    #
    #   \param point_on_axis A point on the axis to mirror across.
    #   \param axis_direction The direction vector of the axis to mirror across.
    def mirror(self, point_on_axis, axis_direction):
        #Input checking.
        if axis_direction == [0,0,0]:
            return #Axis has no direction. Can't expect us to mirror anything!
        axis_direction /= numpy.linalg.norm(axis_direction) #Normalise the direction.

        #In order to be able to mirror points around an arbitrary axis, we have to normalize the axis and all points such that the axis goes through the origin.
        point_matrix = numpy.matrix(self._points)
        point_matrix -= point_on_axis #Moves all points such that the axis origin is at [0,0].

        #To mirror a coordinate, we have to add the projection of the point to the axis twice (where v is the vector to reflect):
        #  reflection(v) = 2 * projection(v) - v
        #Writing out the projection, this becomes (where l is the normalised direction of the line):
        #  reflection(v) = 2 * (l . v) l - v
        #With Snell's law this can be simplified to the Householder transformation matrix:
        #  reflection(v) = R v
        #  R = 2 l l^T - I
        #This simplifies the entire reflection to one big matrix transformation.
        axis_matrix = numpy.matrix(axis_direction)
        reflection = 2 * numpy.transpose(axis_matrix) * axis_matrix - numpy.identity(2)
        point_matrix = point_matrix * reflection #Apply the actual transformation.

        #Shift the points back to the original coordinate space before the axis was normalised to the origin.
        point_matrix += point_on_axis
        self._points = point_matrix.getA()[::-1]

    ##  Computes the intersection of the convex hulls of this and another
    #   polygon.
    #
    #   This is an implementation of O'Rourke's "Chase" algorithm. For a more
    #   detailed description of why the algorithm works the way it does, please
    #   consult the book "Computational Geometry in C", second edition, chapter
    #   7.6.
    #
    #   \param other The other polygon to intersect convex hulls with.
    #   \return The intersection of the two polygons' convex hulls.
    def intersectionConvexHulls(self, other):
        me = self.getConvexHull()
        him = other.getConvexHull()

        if len(me._points) <= 2 or len(him._points) <= 2: #If either polygon has no surface area, then the intersection is empty.
            return Polygon()

        index_me = 0 #The current vertex index.
        index_him = 0
        advances_me = 0 #How often we've advanced.
        advances_him = 0
        who_is_inside = "unknown" #Which of the two polygons is currently on the inside.
        directions_me = numpy.subtract(numpy.roll(me._points, -1, axis = 0), me._points) #Pre-compute the difference between consecutive points to get a direction for each point.
        directions_him = numpy.subtract(numpy.roll(him._points, -1, axis = 0), him._points)
        result = []

        #Iterate through both polygons until we've made a loop through both polygons.
        while advances_me <= len(me._points) or advances_him <= len(him._points):
            vertex_me = me._points[index_me]
            vertex_him = him._points[index_him]
            if advances_me > len(me._points) * 2 or advances_him > len(him._points) * 2: #Also, if we've looped twice through either polygon, the boundaries of the polygons don't intersect.
                if len(result) > 2:
                    return result
                if me.isInside(vertex_him): #Other polygon is inside this one.
                    return him
                if him.isInside(vertex_me): #This polygon is inside the other.
                    return me
                #Polygons are disjunct.
                return Polygon()

            me_start = Vector2(data = vertex_me)
            me_end = Vector2(data = vertex_me + directions_me[index_me])
            him_start = Vector2(data = vertex_him)
            him_end = Vector2(data = vertex_him + directions_him[index_him])

            me_in_him_halfplane = (me_end - him_start).cross(him_end - him_start) #Cross gives positive if him_end is to the left of me_end (as seen from him_start).
            him_in_me_halfplane = (him_end - me_start).cross(me_end - me_start) #Arr, I's got him in me halfplane, cap'n.
            intersection = LineSegment(me_start, me_end).intersection(LineSegment(him_start, him_end))

            if intersection:
                result.append(intersection.getData()) #The intersection is always in the hull.
                if me_in_him_halfplane > 0: #At the intersection, who was inside changes.
                    who_is_inside = "me"
                elif him_in_me_halfplane > 0:
                    who_is_inside = "him"
                else:
                    pass #Otherwise, whoever is inside remains the same (or unknown).
                advances_me += 1
                index_me = (index_me + 1) % len(me._points)
                advances_him += 1
                index_him = (index_him + 1) % len(him._points)
                continue

            cross = (Vector2(data = directions_me[index_me]).cross(Vector2(data = directions_him[index_him])))

            #Edge case: Two exactly opposite edges facing away from each other.
            if Float.fuzzyCompare(cross, 0) and me_in_him_halfplane <= 0 and him_in_me_halfplane <= 0:
                # The polygons must be disjunct then.
                return Polygon()

            if Float.fuzzyCompare(cross, 0) and directions_me[index_me].dot(directions_him[index_him]) < 0 and me_in_him_halfplane > 0:
                #Just advance the inside.
                if who_is_inside == "him":
                    advances_him += 1
                    index_him = (index_him + 1) % len(him._points)
                else: #him OR unknown! If it's unknown, it doesn't matter which one is advanced, since it only happens when the starting edge was already colinear.
                    advances_me += 1
                    index_me = (index_me + 1) % len(me._points)
                continue

            #Edge case: Two colinear edges.
            if Float.fuzzyCompare(cross, 0): #Two edges overlap.
                #Just advance the outside.
                if who_is_inside == "me":
                    advances_him += 1
                    index_him = (index_him + 1) % len(him._points)
                else: #him OR unknown! If it's unknown, it doesn't matter which one is advanced, since it only happens when the starting edge was already colinear.
                    advances_me += 1
                    index_me = (index_me + 1) % len(me._points)
                continue

            #Generic case: Advance whichever polygon is on the outside.
            if cross >= 0: #This polygon is going faster towards the inside.
                if him_in_me_halfplane > 0:
                    advances_me += 1
                    index_me = (index_me + 1) % len(me._points)
                    if who_is_inside == "him":
                        result.append(vertex_him)
                else:
                    advances_him += 1
                    index_him = (index_him + 1) % len(him._points)
                    if who_is_inside == "me":
                        result.append(vertex_me)
            else: #The other polygon is going faster towards the inside.
                if me_in_him_halfplane > 0:
                    advances_him += 1
                    index_him = (index_him + 1) % len(him._points)
                    if who_is_inside == "me":
                        result.append(vertex_me)
                else:
                    advances_me += 1
                    index_me = (index_me + 1) % len(me._points)
                    if who_is_inside == "him":
                        result.append(vertex_him)
        return Polygon(points = result)

    ##  Check to see whether this polygon intersects with another polygon.
    #
    #   \param other \type{Polygon} The polygon to check for intersection.
    #   \return A tuple of the x and y distance of intersection, or None if no intersection occured.
    def intersectsPolygon(self, other):
        retSize = 10000000.0
        ret = None

        for n in range(0, len(self._points)):
            p0 = self._points[n-1]
            p1 = self._points[n]

            normal = (p1 - p0)[::-1]
            normal[1] = -normal[1]
            normal /= numpy.linalg.norm(normal)

            aMin, aMax = self.project(normal)
            bMin, bMax = other.project(normal)
            if aMin > bMax:
                return None
            if bMin > aMax:
                return None
            size = min(aMax, bMax) - max(aMin, bMin)
            if size < retSize:
                if aMin < bMin:
                    ret = normal * -size
                else:
                    ret = normal * size
                retSize = size

        for n in range(0, len(other._points)):
            p0 = other._points[n-1]
            p1 = other._points[n]

            normal = (p1 - p0)[::-1]
            normal[1] = -normal[1]
            normal /= numpy.linalg.norm(normal)

            aMin, aMax = self.project(normal)
            bMin, bMax = other.project(normal)
            if aMin > bMax:
                return None
            if bMin > aMax:
                return None
            size = min(aMax, bMax) - max(aMin, bMin)
            if size < retSize:
                if aMin < bMin:
                    ret = normal * -size
                else:
                    ret = normal * size
                retSize = size

        if ret is not None:
            return (ret[0], ret[1])
        else:
            return None

    ##  Calculate the convex hull around the set of points of this polygon.
    #
    #   \return \type{Polygon} The convex hull around the points of this polygon.
    if has_scipy:
        def getConvexHull(self):
            hull = scipy.spatial.ConvexHull(self._points)
            return Polygon(numpy.flipud(self._points[hull.vertices]))
    else:
        def getConvexHull(self):
            unique = {}
            for p in self._points:
                unique[p[0], p[1]] = 1

            points = list(unique.keys())
            points.sort()
            if len(points) < 1:
                return Polygon(numpy.zeros((0, 2), numpy.float32))
            if len(points) < 2:
                return Polygon(numpy.array(points, numpy.float32))

            # Build upper half of the hull.
            upper = [points[0], points[1]]
            for p in points[2:]:
                upper.append(p)
                while len(upper) > 2 and self._isRightTurn(*upper[-3:]) != 1:
                    del upper[-2]

            # Build lower half of the hull.
            points = points[::-1]
            lower = [points[0], points[1]]
            for p in points[2:]:
                lower.append(p)
                while len(lower) > 2 and self._isRightTurn(*lower[-3:]) != 1:
                    del lower[-2]

            # Remove duplicates.
            del lower[0]
            del lower[-1]

            return Polygon(numpy.array(upper + lower, numpy.float32))

    ##  Perform a Minkowski sum of this polygon with another polygon.
    #
    #   \param other The polygon to perform a Minkowski sum with.
    #   \return \type{Polygon} The Minkowski sum of this polygon with other.
    def getMinkowskiSum(self, other):
        points = numpy.zeros((len(self._points) * len(other._points), 2))
        for n in range(0, len(self._points)):
            for m in range(0, len(other._points)):
                points[n * len(other._points) + m] = self._points[n] + other._points[m]

                time.sleep(0.00001)

        return Polygon(points)

    ##  Create a Minkowski hull from this polygon and another polygon.
    #
    #   The Minkowski hull is the convex hull around the Minkowski sum of this
    #   polygon with other.
    #
    #   \param other \type{Polygon} The Polygon to do a Minkowski addition with.
    #   \return The convex hull around the Minkowski sum of this Polygon with other
    def getMinkowskiHull(self, other):
        sum = self.getMinkowskiSum(other)
        return sum.getConvexHull()

    ##  Whether the specified point is inside this polygon.
    #
    #   If the point is exactly on the border or on a vector, it does not count
    #   as being inside the polygon.
    #
    #   \param point The point to check of whether it is inside.
    #   \return True if it is inside, or False otherwise.
    def isInside(self, point):
        for i in range(0,len(self._points)):
            if self._isRightTurn(self._points[i], self._points[(i + 1) % len(self._points)], point) == -1: #Outside this halfplane!
                return False
        return True

    def _isRightTurn(self, p, q, r):
        sum1 = q[0] * r[1] + p[0] * q[1] + r[0] * p[1]
        sum2 = q[0] * p[1] + r[0] * q[1] + p[0] * r[1]

        if sum1 - sum2 < 0:
            return 1
        elif sum1 == sum2:
            return 0
        else:
            return -1<commit_msg>Show warning if mirroring over zero-axis<commit_after># Copyright (c) 2015 Ultimaker B.V.
# Uranium is released under the terms of the AGPLv3 or higher.

import copy
import numpy
import time

from UM.Job import Job
from UM.Math.Float import Float #For fuzzy comparison of edge cases.
from UM.Math.LineSegment import LineSegment #For line-line intersections for computing polygon intersections.
from UM.Math.Vector2 import Vector2 #For constructing line segments for polygon intersections.

try:
    import scipy.spatial
    has_scipy = True
except ImportError:
    has_scipy = False

##  A class representing an arbitrary 2-dimensional polygon.
class Polygon:
    def __init__(self, points = None):
        self._points = points

    def isValid(self):
        return self._points is not None and len(self._points)

    def getPoints(self):
        return self._points

    def setPoints(self, points):
        self._points = points

    ##  Project this polygon on a line described by a normal.
    #
    #   \param normal The normal to project on.
    #   \return A tuple describing the line segment of this Polygon projected on to the infinite line described by normal.
    #           The first element is the minimum value, the second the maximum.
    def project(self, normal):
        projection_min = numpy.dot(normal, self._points[0])
        projection_max = projection_min
        for point in self._points:
            projection = numpy.dot(normal, point)
            projection_min = min(projection_min, projection)
            projection_max = max(projection_max, projection)

        return (projection_min, projection_max)

    ##  Mirrors this polygon across the specified axis.
    #
    #   \param point_on_axis A point on the axis to mirror across.
    #   \param axis_direction The direction vector of the axis to mirror across.
    def mirror(self, point_on_axis, axis_direction):
        #Input checking.
        if axis_direction == [0, 0, 0]:
            Logger.log("w", "Tried to mirror a polygon over an axis with direction [0, 0, 0].")
            return #Axis has no direction. Can't expect us to mirror anything!
        axis_direction /= numpy.linalg.norm(axis_direction) #Normalise the direction.

        #In order to be able to mirror points around an arbitrary axis, we have to normalize the axis and all points such that the axis goes through the origin.
        point_matrix = numpy.matrix(self._points)
        point_matrix -= point_on_axis #Moves all points such that the axis origin is at [0,0].

        #To mirror a coordinate, we have to add the projection of the point to the axis twice (where v is the vector to reflect):
        #  reflection(v) = 2 * projection(v) - v
        #Writing out the projection, this becomes (where l is the normalised direction of the line):
        #  reflection(v) = 2 * (l . v) l - v
        #With Snell's law this can be simplified to the Householder transformation matrix:
        #  reflection(v) = R v
        #  R = 2 l l^T - I
        #This simplifies the entire reflection to one big matrix transformation.
        axis_matrix = numpy.matrix(axis_direction)
        reflection = 2 * numpy.transpose(axis_matrix) * axis_matrix - numpy.identity(2)
        point_matrix = point_matrix * reflection #Apply the actual transformation.

        #Shift the points back to the original coordinate space before the axis was normalised to the origin.
        point_matrix += point_on_axis
        self._points = point_matrix.getA()[::-1]

    ##  Computes the intersection of the convex hulls of this and another
    #   polygon.
    #
    #   This is an implementation of O'Rourke's "Chase" algorithm. For a more
    #   detailed description of why the algorithm works the way it does, please
    #   consult the book "Computational Geometry in C", second edition, chapter
    #   7.6.
    #
    #   \param other The other polygon to intersect convex hulls with.
    #   \return The intersection of the two polygons' convex hulls.
    def intersectionConvexHulls(self, other):
        me = self.getConvexHull()
        him = other.getConvexHull()

        if len(me._points) <= 2 or len(him._points) <= 2: #If either polygon has no surface area, then the intersection is empty.
            return Polygon()

        index_me = 0 #The current vertex index.
        index_him = 0
        advances_me = 0 #How often we've advanced.
        advances_him = 0
        who_is_inside = "unknown" #Which of the two polygons is currently on the inside.
        directions_me = numpy.subtract(numpy.roll(me._points, -1, axis = 0), me._points) #Pre-compute the difference between consecutive points to get a direction for each point.
        directions_him = numpy.subtract(numpy.roll(him._points, -1, axis = 0), him._points)
        result = []

        #Iterate through both polygons until we've made a loop through both polygons.
        while advances_me <= len(me._points) or advances_him <= len(him._points):
            vertex_me = me._points[index_me]
            vertex_him = him._points[index_him]
            if advances_me > len(me._points) * 2 or advances_him > len(him._points) * 2: #Also, if we've looped twice through either polygon, the boundaries of the polygons don't intersect.
                if len(result) > 2:
                    return result
                if me.isInside(vertex_him): #Other polygon is inside this one.
                    return him
                if him.isInside(vertex_me): #This polygon is inside the other.
                    return me
                #Polygons are disjunct.
                return Polygon()

            me_start = Vector2(data = vertex_me)
            me_end = Vector2(data = vertex_me + directions_me[index_me])
            him_start = Vector2(data = vertex_him)
            him_end = Vector2(data = vertex_him + directions_him[index_him])

            me_in_him_halfplane = (me_end - him_start).cross(him_end - him_start) #Cross gives positive if him_end is to the left of me_end (as seen from him_start).
            him_in_me_halfplane = (him_end - me_start).cross(me_end - me_start) #Arr, I's got him in me halfplane, cap'n.
            intersection = LineSegment(me_start, me_end).intersection(LineSegment(him_start, him_end))

            if intersection:
                result.append(intersection.getData()) #The intersection is always in the hull.
                if me_in_him_halfplane > 0: #At the intersection, who was inside changes.
                    who_is_inside = "me"
                elif him_in_me_halfplane > 0:
                    who_is_inside = "him"
                else:
                    pass #Otherwise, whoever is inside remains the same (or unknown).
                advances_me += 1
                index_me = (index_me + 1) % len(me._points)
                advances_him += 1
                index_him = (index_him + 1) % len(him._points)
                continue

            cross = (Vector2(data = directions_me[index_me]).cross(Vector2(data = directions_him[index_him])))

            #Edge case: Two exactly opposite edges facing away from each other.
            if Float.fuzzyCompare(cross, 0) and me_in_him_halfplane <= 0 and him_in_me_halfplane <= 0:
                # The polygons must be disjunct then.
                return Polygon()

            if Float.fuzzyCompare(cross, 0) and directions_me[index_me].dot(directions_him[index_him]) < 0 and me_in_him_halfplane > 0:
                #Just advance the inside.
                if who_is_inside == "him":
                    advances_him += 1
                    index_him = (index_him + 1) % len(him._points)
                else: #him OR unknown! If it's unknown, it doesn't matter which one is advanced, since it only happens when the starting edge was already colinear.
                    advances_me += 1
                    index_me = (index_me + 1) % len(me._points)
                continue

            #Edge case: Two colinear edges.
            if Float.fuzzyCompare(cross, 0): #Two edges overlap.
                #Just advance the outside.
                if who_is_inside == "me":
                    advances_him += 1
                    index_him = (index_him + 1) % len(him._points)
                else: #him OR unknown! If it's unknown, it doesn't matter which one is advanced, since it only happens when the starting edge was already colinear.
                    advances_me += 1
                    index_me = (index_me + 1) % len(me._points)
                continue

            #Generic case: Advance whichever polygon is on the outside.
            if cross >= 0: #This polygon is going faster towards the inside.
                if him_in_me_halfplane > 0:
                    advances_me += 1
                    index_me = (index_me + 1) % len(me._points)
                    if who_is_inside == "him":
                        result.append(vertex_him)
                else:
                    advances_him += 1
                    index_him = (index_him + 1) % len(him._points)
                    if who_is_inside == "me":
                        result.append(vertex_me)
            else: #The other polygon is going faster towards the inside.
                if me_in_him_halfplane > 0:
                    advances_him += 1
                    index_him = (index_him + 1) % len(him._points)
                    if who_is_inside == "me":
                        result.append(vertex_me)
                else:
                    advances_me += 1
                    index_me = (index_me + 1) % len(me._points)
                    if who_is_inside == "him":
                        result.append(vertex_him)
        return Polygon(points = result)

    ##  Check to see whether this polygon intersects with another polygon.
    #
    #   \param other \type{Polygon} The polygon to check for intersection.
    #   \return A tuple of the x and y distance of intersection, or None if no intersection occured.
    def intersectsPolygon(self, other):
        retSize = 10000000.0
        ret = None

        for n in range(0, len(self._points)):
            p0 = self._points[n-1]
            p1 = self._points[n]

            normal = (p1 - p0)[::-1]
            normal[1] = -normal[1]
            normal /= numpy.linalg.norm(normal)

            aMin, aMax = self.project(normal)
            bMin, bMax = other.project(normal)
            if aMin > bMax:
                return None
            if bMin > aMax:
                return None
            size = min(aMax, bMax) - max(aMin, bMin)
            if size < retSize:
                if aMin < bMin:
                    ret = normal * -size
                else:
                    ret = normal * size
                retSize = size

        for n in range(0, len(other._points)):
            p0 = other._points[n-1]
            p1 = other._points[n]

            normal = (p1 - p0)[::-1]
            normal[1] = -normal[1]
            normal /= numpy.linalg.norm(normal)

            aMin, aMax = self.project(normal)
            bMin, bMax = other.project(normal)
            if aMin > bMax:
                return None
            if bMin > aMax:
                return None
            size = min(aMax, bMax) - max(aMin, bMin)
            if size < retSize:
                if aMin < bMin:
                    ret = normal * -size
                else:
                    ret = normal * size
                retSize = size

        if ret is not None:
            return (ret[0], ret[1])
        else:
            return None

    ##  Calculate the convex hull around the set of points of this polygon.
    #
    #   \return \type{Polygon} The convex hull around the points of this polygon.
    if has_scipy:
        def getConvexHull(self):
            hull = scipy.spatial.ConvexHull(self._points)
            return Polygon(numpy.flipud(self._points[hull.vertices]))
    else:
        def getConvexHull(self):
            unique = {}
            for p in self._points:
                unique[p[0], p[1]] = 1

            points = list(unique.keys())
            points.sort()
            if len(points) < 1:
                return Polygon(numpy.zeros((0, 2), numpy.float32))
            if len(points) < 2:
                return Polygon(numpy.array(points, numpy.float32))

            # Build upper half of the hull.
            upper = [points[0], points[1]]
            for p in points[2:]:
                upper.append(p)
                while len(upper) > 2 and self._isRightTurn(*upper[-3:]) != 1:
                    del upper[-2]

            # Build lower half of the hull.
            points = points[::-1]
            lower = [points[0], points[1]]
            for p in points[2:]:
                lower.append(p)
                while len(lower) > 2 and self._isRightTurn(*lower[-3:]) != 1:
                    del lower[-2]

            # Remove duplicates.
            del lower[0]
            del lower[-1]

            return Polygon(numpy.array(upper + lower, numpy.float32))

    ##  Perform a Minkowski sum of this polygon with another polygon.
    #
    #   \param other The polygon to perform a Minkowski sum with.
    #   \return \type{Polygon} The Minkowski sum of this polygon with other.
    def getMinkowskiSum(self, other):
        points = numpy.zeros((len(self._points) * len(other._points), 2))
        for n in range(0, len(self._points)):
            for m in range(0, len(other._points)):
                points[n * len(other._points) + m] = self._points[n] + other._points[m]

                time.sleep(0.00001)

        return Polygon(points)

    ##  Create a Minkowski hull from this polygon and another polygon.
    #
    #   The Minkowski hull is the convex hull around the Minkowski sum of this
    #   polygon with other.
    #
    #   \param other \type{Polygon} The Polygon to do a Minkowski addition with.
    #   \return The convex hull around the Minkowski sum of this Polygon with other
    def getMinkowskiHull(self, other):
        sum = self.getMinkowskiSum(other)
        return sum.getConvexHull()

    ##  Whether the specified point is inside this polygon.
    #
    #   If the point is exactly on the border or on a vector, it does not count
    #   as being inside the polygon.
    #
    #   \param point The point to check of whether it is inside.
    #   \return True if it is inside, or False otherwise.
    def isInside(self, point):
        for i in range(0,len(self._points)):
            if self._isRightTurn(self._points[i], self._points[(i + 1) % len(self._points)], point) == -1: #Outside this halfplane!
                return False
        return True

    def _isRightTurn(self, p, q, r):
        sum1 = q[0] * r[1] + p[0] * q[1] + r[0] * p[1]
        sum2 = q[0] * p[1] + r[0] * q[1] + p[0] * r[1]

        if sum1 - sum2 < 0:
            return 1
        elif sum1 == sum2:
            return 0
        else:
            return -1<|endoftext|>


<commit_before>'''
ALPHABETICAL SUBSTRINGS  (15.0/15.0 points)
Assume s is a string of lower case characters.

Write a program that prints the longest substring of s in which the letters occur in alphabetical order.
For example, if s = 'azcbobobegghakl', then your program should print

Longest substring in alphabetical order is: beggh

In the case of ties, print the first substring. For example, if s = 'abcbcd', then your program should print

Longest substring in alphabetical order is: abc

For problems such as these, do not include raw_input statements or define the variable s in any way.
Our automating testing will provide a value of s for you -
so the code you submit in the following box should assume s is already defined.
If you are confused by this instruction, please review L4 Problems 10 and 11 before you begin this problem set.

Note: This problem is fairly challenging. We encourage you to work smart.
If you've spent more than a few hours on this problem, we suggest that you move on to a different part of the course.
If you have time, come back to this problem after you've had a break and cleared your head.

'''
s = 'azcbobobegghakl'
first,last = 0,0
long_string = []
for letter in range(len(s)+1):
    if  letter !=(len(s)) and ord(s[letter])>= ord(s[letter-1]):
            last = letter
    else:
            long_string.append(s[first:last+1])
            first,last = letter, letter
print "Longest substring in alphabetical order is: "  + max(long_string, key=len)

<commit_msg>Update problem3.py<commit_after>'''
ALPHABETICAL SUBSTRINGS  (15.0/15.0 points)
Assume s is a string of lower case characters.

Write a program that prints the longest substring of s in which the letters occur in alphabetical order.
For example, if s = 'azcbobobegghakl', then your program should print

Longest substring in alphabetical order is: beggh

In the case of ties, print the first substring. For example, if s = 'abcbcd', then your program should print

Longest substring in alphabetical order is: abc

For problems such as these, do not include raw_input statements or define the variable s in any way.
Our automating testing will provide a value of s for you -
so the code you submit in the following box should assume s is already defined.
If you are confused by this instruction, please review L4 Problems 10 and 11 before you begin this problem set.

Note: This problem is fairly challenging. We encourage you to work smart.
If you've spent more than a few hours on this problem, we suggest that you move on to a different part of the course.
If you have time, come back to this problem after you've had a break and cleared your head.

'''
s = 'azcbobobegghakl'
first,last = 0,0
long_string= []
for letter in range(len(s)+1):
    if  letter !=(len(s)) and ord(s[letter-1]) <= ord(s[letter]):
            last = letter
    else:
            long_string.append(s[first:last+1])
            first,last = letter, letter
print "Longest substring in alphabetical order is: "  + max(long_string, key=len)
<|endoftext|>


<commit_before>import csv

with open('monthly_payslip.csv') as csvfile:
    pay = csv.reader(csvfile)
    for item in pay:
        a = item[0]
        b = item[1]
        name = a + " " + b
        c = int(item[2])
        d = int(item[3].rstrip('%')) * 0.001
        e = item[4]
        grossIncome = round(c / 12)
        incomeTax = round((3572 + (c - 37000) * 0.325) / 12)
        netIncome = grossIncome - incomeTax
        _super = round(grossIncome * d)
        print(name + "," + e + "," + str(grossIncome) + "," + str(netIncome) + "," + str(_super))
<commit_msg>added an annoying amount of if/elifs. Need to get rid of some of that repeated code.<commit_after>import csv

with open('monthly_payslip.csv') as csvfile:
    pay = csv.reader(csvfile)
    for item in pay:
        a = item[0]
        b = item[1]
        name = a + " " + b
        c = int(item[2])
        d = int(item[3].rstrip('%')) * 0.001
        e = item[4]
        grossIncome = round(c / 12)
        if c <= 18200:
            incomeTax = 0
        elif 18201 <= c <= 37000:
            incomeTax = round(((c - 18200) * 0.19) / 12)
            netIncome = grossIncome - incomeTax
            _super = round(grossIncome * d)
            print(name + "," + e + "," + str(grossIncome) + "," + str(netIncome) + "," + str(_super))
        elif 37001 <= c <= 80000:
            incomeTax = round((3572 + (c - 37000) * 0.325) / 12)
            netIncome = grossIncome - incomeTax
            _super = round(grossIncome * d)
            print(name + "," + e + "," + str(grossIncome) + "," + str(netIncome) + "," + str(_super))
        elif 80001 <= c <= 180000:
            incomeTax = round((17547 + (c - 80000) * 0.37) / 12)
            netIncome = grossIncome - incomeTax
            _super = round(grossIncome * d)
            print(name + "," + e + "," + str(grossIncome) + "," + str(netIncome) + "," + str(_super))
        elif c >= 180001:
            incomeTax = round((54547 + (c - 180000) * 0.45) / 12)
            netIncome = grossIncome - incomeTax
            _super = round(grossIncome * d)
            print(name + "," + e + "," + str(grossIncome) + "," + str(netIncome) + "," + str(_super))
<|endoftext|>


<commit_before>import sys
if not (2, 6) <= sys.version_info < (3,):
    sys.exit(u'Mopidy requires Python >= 2.6, < 3')

import os
import platform
from subprocess import PIPE, Popen

import glib

__version__ = '0.8.0'

DATA_PATH = os.path.join(str(glib.get_user_data_dir()), 'mopidy')
CACHE_PATH = os.path.join(str(glib.get_user_cache_dir()), 'mopidy')
SETTINGS_PATH = os.path.join(str(glib.get_user_config_dir()), 'mopidy')
SETTINGS_FILE = os.path.join(SETTINGS_PATH, 'settings.py')

def get_version():
    try:
        return get_git_version()
    except EnvironmentError:
        return __version__

def get_git_version():
    process = Popen(['git', 'describe'], stdout=PIPE, stderr=PIPE)
    if process.wait() != 0:
        raise EnvironmentError('Execution of "git describe" failed')
    version = process.stdout.read().strip()
    if version.startswith('v'):
        version = version[1:]
    return version

def get_platform():
    return platform.platform()

def get_python():
    implementation = platform.python_implementation()
    version = platform.python_version()
    return u' '.join([implementation, version])

class MopidyException(Exception):
    def __init__(self, message, *args, **kwargs):
        super(MopidyException, self).__init__(message, *args, **kwargs)
        self._message = message

    @property
    def message(self):
        """Reimplement message field that was deprecated in Python 2.6"""
        return self._message

    @message.setter
    def message(self, message):
        self._message = message

class SettingsError(MopidyException):
    pass

class OptionalDependencyError(MopidyException):
    pass

from mopidy import settings as default_settings_module
from mopidy.utils.settings import SettingsProxy
settings = SettingsProxy(default_settings_module)
<commit_msg>Check Pykka version on startup<commit_after># pylint: disable = E0611,F0401
from distutils.version import StrictVersion as SV
# pylint: enable = E0611,F0401
import sys

import pykka

if not (2, 6) <= sys.version_info < (3,):
    sys.exit(
        u'Mopidy requires Python >= 2.6, < 3, but found %s' %
        '.'.join(map(str, sys.version_info[:3])))

if (isinstance(pykka.__version__, basestring)
        and not SV('1.0') <= SV(pykka.__version__) < SV('2.0')):
    sys.exit(
        u'Mopidy requires Pykka >= 1.0, < 2, but found %s' % pykka.__version__)

import os
import platform
from subprocess import PIPE, Popen

import glib

__version__ = '0.8.0'

DATA_PATH = os.path.join(str(glib.get_user_data_dir()), 'mopidy')
CACHE_PATH = os.path.join(str(glib.get_user_cache_dir()), 'mopidy')
SETTINGS_PATH = os.path.join(str(glib.get_user_config_dir()), 'mopidy')
SETTINGS_FILE = os.path.join(SETTINGS_PATH, 'settings.py')

def get_version():
    try:
        return get_git_version()
    except EnvironmentError:
        return __version__

def get_git_version():
    process = Popen(['git', 'describe'], stdout=PIPE, stderr=PIPE)
    if process.wait() != 0:
        raise EnvironmentError('Execution of "git describe" failed')
    version = process.stdout.read().strip()
    if version.startswith('v'):
        version = version[1:]
    return version

def get_platform():
    return platform.platform()

def get_python():
    implementation = platform.python_implementation()
    version = platform.python_version()
    return u' '.join([implementation, version])

class MopidyException(Exception):
    def __init__(self, message, *args, **kwargs):
        super(MopidyException, self).__init__(message, *args, **kwargs)
        self._message = message

    @property
    def message(self):
        """Reimplement message field that was deprecated in Python 2.6"""
        return self._message

    @message.setter
    def message(self, message):
        self._message = message

class SettingsError(MopidyException):
    pass

class OptionalDependencyError(MopidyException):
    pass

from mopidy import settings as default_settings_module
from mopidy.utils.settings import SettingsProxy
settings = SettingsProxy(default_settings_module)
<|endoftext|>