<commit_before>import os
import StringIO
import vobject
from email.mime.text import MIMEText
from xhtml2pdf import pisa
from django.contrib import messages
from django.contrib.auth.decorators import permission_required
from django.shortcuts import redirect, render, get_object_or_404
from django.utils.translation import ugettext_lazy as _
from django.core.mail import EmailMessage
from django.template.loader import render_to_string
from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse

# TODO Swap with django.utils.lru_cache.lru_cache at Django 1.7
from django.utils.functional import memoize

from wagtail.wagtailadmin.edit_handlers import (
    ObjectList, extract_panel_definitions_from_model_class, get_form_for_model)
from wagtail.wagtailcore.models import Page

from ..models import get_invoiceindex_content_types

def get_invoice_edit_handler(Invoice):
    panels = extract_panel_definitions_from_model_class(
        Invoice, exclude=['invoiceindex'])
    EditHandler = ObjectList(panels).bind_to_model(Invoice)
    return EditHandler
get_invoice_edit_handler = memoize(get_invoice_edit_handler, {}, 1)

def notify_drivers(request, invoice):
    service_items = invoice.service_items.all()
    if invoice.notify_drivers is True:
        # Set Vars
        service_items = invoice.service_items.all()
        name = invoice.client_full_name
        number = invoice.client_phone_number
        organization = invoice.client_organization

        for item in service_items:
            if item.driver == "Not Applicable":
                pass
            else:
                if item.driver == "John Casimaty":
                    driver_email = 'john.casimaty@gmail.com'

                elif item.driver == "Colin Parramore":
                    driver_email = 'colinparramore@gmail.com'

                elif item.driver == "Allan Cerny":
                    driver_email = 'ab.cerny@bigpond.com'

                elif item.driver == "Barry Griffin":
                    driver_email = 'barrytg@netspace.net.au'

                driver_name = item.driver.split(" ")
                notification = render_to_string('emails/notify_driver.txt', {
                    'car_number': item.car_number,
                    'driver_name': driver_name[0],
                    'details': invoice.service_items.all(),
                    'email': driver_email,
                    'description': item.description,
                    'third_party_ref': item.third_party_ref,
                    'ref:': item.ref,
                    'date': item.date,
                    'name': name,
                    'number': number,
                    'organization': organization,
                    'flight_number': item.flight_number,
                })
                driver_notification = EmailMessage(
                    'Job Notification',
                    notification,
                    'admin@chauffuered-cars.com.au',
                    [driver_email])
                driver_notification.content_subtype = "html"
                driver_notification.send()
    else:
        pass

def send_invoice(request, invoice):
    # Set Variables
    name = invoice.client_full_name
    email = invoice.client_email
    organization = invoice.client_organization
    admin_to = invoice.admin_confirm_to_address
    service_items = invoice.service_items.all()

    def get_total(service_items):
        amount = 0
        for i in service_items:
            amount = amount + i.amount
        return amount
    total = get_total(invoice.service_items.all())
    gst = total / 11
    link = request.build_absolute_uri(invoice.url())
    id = str(invoice.id)
    ph_number = invoice.client_phone_number
    adminmessage = render_to_string('emails/admin_invoice_message.txt', {
        'name': name,
        'ph_number': ph_number,
        'email': email,
        'total': total,
        'gst': gst,
        'link': link,
        'invoice': invoice,
        'organization': organization,
        'id': id,
        'service_items': service_items,
    })
    # Email to business owner
    admin_email = EmailMessage(
        'Invoice #' + id,
        adminmessage,
        admin_to,
        [admin_to])
    admin_email.content_subtype = "html"
    admin_email.send()
    # Customer Email
    name = name.split(" ")
    invoicemessage = render_to_string('emails/invoice_message.txt', {
        'name': name[0],
        'total': total,
        'gst': gst,
        'link': link,
        'invoice': invoice,
        'id': id,
        'organization': organization,
        'service_items': service_items,
    })
    customer_email = EmailMessage(
        'Invoice #' + id,
        invoicemessage,
        "admin@tasmanianexclusivetours.com.au",
        [email])
    customer_email.content_subtype = "html"
    customer_email.send()

def serve_pdf(invoice, request):
    # Convert HTML URIs to absolute system paths so xhtml2pdf can access those resources

    def link_callback(uri, rel):
        # use short variable names
        sUrl = settings.STATIC_URL      # Typically /static/
        sRoot = settings.STATIC_ROOT    # Typically /home/userX/project_static/
        mUrl = settings.MEDIA_URL       # Typically /static/media/
        mRoot = settings.MEDIA_ROOT     # Typically /home/userX/project_static/media/

        # convert URIs to absolute system paths
        if uri.startswith(mUrl):
            path = os.path.join(mRoot, uri.replace(mUrl, ""))
        elif uri.startswith(sUrl):
            path = os.path.join(sRoot, uri.replace(sUrl, ""))

        # make sure that file exists
        if not os.path.isfile(path):
                raise Exception(
                        'media URI must start with %s or %s' % \
                        (sUrl, mUrl))
        return path

    # Set variables
    id = invoice.id
    total = invoice.total()
    gst = total / 11
    email = invoice.client_email
    name = invoice.client_full_name
    date = invoice.time
    address = invoice.client_address
    terms = invoice.days_due
    due = invoice.due()
    ph_number = invoice.client_phone_number
    status = invoice.job_status

    # Prepare context
    data = {
        'service_items': invoice.service_items.all(),
        'total': total,
        'id': id,
        'gst': gst,
        'name': name,
        'email': email,
        'date': date,
        'address': address,
        'terms': terms,
        'due': due,
        'ph_number': ph_number,
        'status': status,
    }

    # Render html content through html template with context
    template = get_template('invoicelist/invoice_pdf.html')
    html = template.render(Context(data))

    # Write PDF to file
    # file = open(os.path.join(settings.MEDIA_ROOT, 'Invoice #' + str(id) + '.pdf'), "w+b")
    file = StringIO.StringIO()
    pisaStatus = pisa.CreatePDF(html, dest=file,
            link_callback = link_callback)

    # Return PDF document through a Django HTTP response
    file.seek(0)
    # pdf = file.read()
    # file.close()            # Don't forget to close the file handle
    return HttpResponse(file, content_type='application/pdf')

@permission_required('wagtailadmin.access_admin')  # further permissions are enforced within the view
def create(request, pk):
    invoiceindex = get_object_or_404(Page, pk=pk, content_type__in=get_invoiceindex_content_types()).specific
    Invoice = invoiceindex.get_invoice_model()
    send_button_name = 'send_invoice'

    invoice = Invoice(invoiceindex=invoiceindex)
    EditHandler = get_invoice_edit_handler(Invoice)
    EditForm = EditHandler.get_form_class(Invoice)

    if request.method == 'POST':
        form = EditForm(request.POST, request.FILES, instance=invoice)
        invoice.service_items.all()

        if form.is_valid():
            invoice = form.save()
            notify_drivers(request, invoice)
            invoice.notify_drivers = False
            '''
            n = 0
            for item in invoice.service_items.all():
                n = n + 1
                item.ref = str(invoice.id) + '-' + str(n)
                item.save()
            '''
            invoice.save()

            def is_invoice_address_fault():
                if invoice.client_organization or invoice.client_full_name:
                    return False
                else:
                    return True

            if is_invoice_address_fault() is True:
                messages.error(request, _('You cannot create an invoice without providing a client organization or client full name!'))
                edit_handler = EditHandler(instance=invoice, form=form)

            elif send_button_name in request.POST:
                if not invoice.client_email:
                    messages.error(request, _('You cannot email an invoice without an email to send it to. Please save the invoice without emailing it!'))
                    edit_handler = EditHandler(instance=invoice, form=form)
                else:
                    send_invoice(request, invoice)
                    messages.success(request, _('The invoice "{0!s}" has been added').format(invoice))
                    return redirect('wagtailinvoices_index', pk=invoiceindex.pk)
            else:
                messages.success(request, _('The invoice "{0!s}" has been added').format(invoice))
                return redirect('wagtailinvoices_index', pk=invoiceindex.pk)
        else:
            messages.error(request, _('The invoice could not be created due to validation errors'))
            edit_handler = EditHandler(instance=invoice, form=form)

    else:
        form = EditForm(instance=invoice)
        edit_handler = EditHandler(instance=invoice, form=form)

    return render(request, 'wagtailinvoices/create.html', {
        'invoiceindex': invoiceindex,
        'form': form,
        'send_button_name': send_button_name,
        'edit_handler': edit_handler,
    })

@permission_required('wagtailadmin.access_admin')  # further permissions are enforced within the view
def edit(request, pk, invoice_pk):
    invoiceindex = get_object_or_404(Page, pk=pk, content_type__in=get_invoiceindex_content_types()).specific
    Invoice = invoiceindex.get_invoice_model()
    invoice = get_object_or_404(Invoice, invoiceindex=invoiceindex, pk=invoice_pk)
    send_button_name = 'send_invoice'
    print_button_name = 'serve_pdf'

    EditHandler = get_invoice_edit_handler(Invoice)
    EditForm = EditHandler.get_form_class(Invoice)

    if request.method == 'POST':
        form = EditForm(request.POST, request.FILES, instance=invoice)

        if form.is_valid():
            invoice = form.save()
            notify_drivers(request, invoice)
            invoice.notify_drivers = False
            '''
            n = 0
            for item in invoice.service_items.all():
                n = n + 1
                item.ref = str(invoice.id) + '-' + str(n)
                item.save()
            '''
            invoice.save()

            def is_invoice_address_fault():
                if invoice.client_organization or invoice.client_full_name:
                    return False
                else:
                    return True

            if is_invoice_address_fault() is True:
                messages.error(request, _('You cannot create an invoice without providing a client organization or client full name!'))
                edit_handler = EditHandler(instance=invoice, form=form)

            elif send_button_name in request.POST:
                if not invoice.client_email:
                    messages.error(request, _('You cannot email an invoice without an email to send it to. Please save the invoice without emailing it!'))
                    edit_handler = EditHandler(instance=invoice, form=form)
                else:
                    send_invoice(request, invoice)
                    messages.success(request, _('The invoice "{0!s}" has been updated').format(invoice))
                    return redirect('wagtailinvoices_index', pk=invoiceindex.pk)

            elif print_button_name in request.POST:
                serve_pdf(invoice, request)

            else:
                messages.success(request, _('The invoice "{0!s}" has been updated').format(invoice))
                return redirect('wagtailinvoices_index', pk=invoiceindex.pk)
        else:
            messages.error(request, _('The invoice could not be updated due to validation errors'))
            edit_handler = EditHandler(instance=invoice, form=form)
    else:
        form = EditForm(instance=invoice)
        edit_handler = EditHandler(instance=invoice, form=form)

    return render(request, 'wagtailinvoices/edit.html', {
        'invoiceindex': invoiceindex,
        'invoice': invoice,
        'send_button_name': send_button_name,
        'print_button_name': print_button_name,
        'form': form,
        'edit_handler': edit_handler,
    })

@permission_required('wagtailadmin.access_admin')  # further permissions are enforced within the view
def delete(request, pk, invoice_pk):
    invoiceindex = get_object_or_404(Page, pk=pk, content_type__in=get_invoiceindex_content_types()).specific
    Invoice = invoiceindex.get_invoice_model()
    invoice = get_object_or_404(Invoice, invoiceindex=invoiceindex, pk=invoice_pk)

    if request.method == 'POST':
        invoice.delete()
        return redirect('wagtailinvoices_index', pk=pk)

    return render(request, 'wagtailinvoices/delete.html', {
        'invoiceindex': invoiceindex,
        'invoice': invoice,
    })
<commit_msg>Fix conflict and remove unused imports<commit_after>import os
import StringIO
from xhtml2pdf import pisa
from django.contrib import messages
from django.contrib.auth.decorators import permission_required
from django.shortcuts import redirect, render, get_object_or_404
from django.utils.translation import ugettext_lazy as _
from django.core.mail import EmailMessage
from django.template.loader import render_to_string
from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse

# TODO Swap with django.utils.lru_cache.lru_cache at Django 1.7
from django.utils.functional import memoize

from wagtail.wagtailadmin.edit_handlers import (
    ObjectList, extract_panel_definitions_from_model_class, get_form_for_model)
from wagtail.wagtailcore.models import Page

from ..models import get_invoiceindex_content_types

def get_invoice_edit_handler(Invoice):
    panels = extract_panel_definitions_from_model_class(
        Invoice, exclude=['invoiceindex'])
    EditHandler = ObjectList(panels).bind_to_model(Invoice)
    return EditHandler
get_invoice_edit_handler = memoize(get_invoice_edit_handler, {}, 1)

def notify_drivers(request, invoice):
    service_items = invoice.service_items.all()
    if invoice.notify_drivers is True:
        # Set Vars
        service_items = invoice.service_items.all()
        name = invoice.client_full_name
        number = invoice.client_phone_number
        organization = invoice.client_organization

        for item in service_items:
            if item.driver == "Not Applicable":
                pass
            else:
                if item.driver == "John Casimaty":
                    driver_email = 'john.casimaty@gmail.com'

                elif item.driver == "Colin Parramore":
                    driver_email = 'colinparramore@gmail.com'

                elif item.driver == "Allan Cerny":
                    driver_email = 'ab.cerny@bigpond.com'

                elif item.driver == "Barry Griffin":
                    driver_email = 'barrytg@netspace.net.au'

                driver_name = item.driver.split(" ")
                notification = render_to_string('emails/notify_driver.txt', {
                    'car_number': item.car_number,
                    'driver_name': driver_name[0],
                    'details': invoice.service_items.all(),
                    'email': driver_email,
                    'description': item.description,
                    'third_party_ref': item.third_party_ref,
                    'ref:': item.ref,
                    'date': item.date,
                    'name': name,
                    'number': number,
                    'organization': organization,
                    'flight_number': item.flight_number,
                })
                driver_notification = EmailMessage(
                    'Job Notification',
                    notification,
                    'admin@chauffuered-cars.com.au',
                    [driver_email])
                driver_notification.content_subtype = "html"
                driver_notification.send()
    else:
        pass

def send_invoice(request, invoice, admin=False):
    # Set Variables
    name = invoice.client_full_name
    email = invoice.client_email
    organization = invoice.client_organization
    admin_to = invoice.admin_confirm_to_address
    service_items = invoice.service_items.all()

    def get_total(service_items):
        amount = 0
        for i in service_items:
            amount = amount + i.amount
        return amount
    total = get_total(invoice.service_items.all())
    gst = total / 11
    link = request.build_absolute_uri(invoice.url())
    id = str(invoice.id)
    ph_number = invoice.client_phone_number

    def admin_email():
        adminmessage = render_to_string('emails/admin_invoice_message.txt', {
            'name': name,
            'ph_number': ph_number,
            'email': email,
            'total': total,
            'gst': gst,
            'link': link,
            'invoice': invoice,
            'organization': organization,
            'id': id,
            'service_items': service_items,
        })
        # Email to business owner
        admin_email = EmailMessage('Invoice #' + id, adminmessage, admin_to,
            [admin_to])
        admin_email.content_subtype = "html"
        admin_email.send()

    # Customer Email
    name = name.split(" ")

    def customer_email():
        invoicemessage = render_to_string('emails/invoice_message.txt', {
            'name': name[0],
            'total': total,
            'gst': gst,
            'link': link,
            'invoice': invoice,
            'id': id,
            'organization': organization,
            'service_items': service_items,
        })
        customer_email = EmailMessage('Invoice #' + id, invoicemessage, "admin@chauffuered-cars.com.au",
                     [email])
        customer_email.content_subtype = "html"
        customer_email.send()
    customer_email()
    if admin is True:
        admin_email()

def serve_pdf(invoice, request):
    # Convert HTML URIs to absolute system paths so xhtml2pdf can access those resources

    def link_callback(uri, rel):
        # use short variable names
        sUrl = settings.STATIC_URL      # Typically /static/
        sRoot = settings.STATIC_ROOT    # Typically /home/userX/project_static/
        mUrl = settings.MEDIA_URL       # Typically /static/media/
        mRoot = settings.MEDIA_ROOT     # Typically /home/userX/project_static/media/

        # convert URIs to absolute system paths
        if uri.startswith(mUrl):
            path = os.path.join(mRoot, uri.replace(mUrl, ""))
        elif uri.startswith(sUrl):
            path = os.path.join(sRoot, uri.replace(sUrl, ""))

        # make sure that file exists
        if not os.path.isfile(path):
                raise Exception(
                        'media URI must start with %s or %s' % \
                        (sUrl, mUrl))
        return path

    # Set variables
    id = invoice.id
    total = invoice.total()
    gst = total / 11
    email = invoice.client_email
    name = invoice.client_full_name
    date = invoice.time
    address = invoice.client_address
    terms = invoice.days_due
    due = invoice.due()
    ph_number = invoice.client_phone_number
    status = invoice.job_status

    # Prepare context
    data = {
        'service_items': invoice.service_items.all(),
        'total': total,
        'id': id,
        'gst': gst,
        'name': name,
        'email': email,
        'date': date,
        'address': address,
        'terms': terms,
        'due': due,
        'ph_number': ph_number,
        'status': status,
    }

    # Render html content through html template with context
    template = get_template('invoicelist/invoice_pdf.html')
    html = template.render(Context(data))

    # Write PDF to file
    # file = open(os.path.join(settings.MEDIA_ROOT, 'Invoice #' + str(id) + '.pdf'), "w+b")
    file = StringIO.StringIO()
    pisaStatus = pisa.CreatePDF(html, dest=file,
            link_callback = link_callback)

    # Return PDF document through a Django HTTP response
    file.seek(0)
    # pdf = file.read()
    # file.close()            # Don't forget to close the file handle
    return HttpResponse(file, content_type='application/pdf')

@permission_required('wagtailadmin.access_admin')  # further permissions are enforced within the view
def create(request, pk):
    invoiceindex = get_object_or_404(Page, pk=pk, content_type__in=get_invoiceindex_content_types()).specific
    Invoice = invoiceindex.get_invoice_model()
    send_button_name = 'send_invoice'

    invoice = Invoice(invoiceindex=invoiceindex)
    EditHandler = get_invoice_edit_handler(Invoice)
    EditForm = EditHandler.get_form_class(Invoice)

    if request.method == 'POST':
        form = EditForm(request.POST, request.FILES, instance=invoice)
        invoice.service_items.all()

        if form.is_valid():
            invoice = form.save()
            notify_drivers(request, invoice)
            invoice.notify_drivers = False
            '''
            n = 0
            for item in invoice.service_items.all():
                n = n + 1
                item.ref = str(invoice.id) + '-' + str(n)
                item.save()
            '''
            invoice.save()

            def is_invoice_address_fault():
                if invoice.client_organization or invoice.client_full_name:
                    return False
                else:
                    return True

            if is_invoice_address_fault() is True:
                messages.error(request, _('You cannot create an invoice without providing a client organization or client full name!'))
                edit_handler = EditHandler(instance=invoice, form=form)

            elif send_button_name in request.POST:
                if not invoice.client_email:
                    messages.error(request, _('You cannot email an invoice without an email to send it to. Please save the invoice without emailing it!'))
                    edit_handler = EditHandler(instance=invoice, form=form)
                else:
                    send_invoice(request, invoice, admin=True)
                    messages.success(request, _('The invoice "{0!s}" has been added').format(invoice))
                    return redirect('wagtailinvoices_index', pk=invoiceindex.pk)
            else:
                messages.success(request, _('The invoice "{0!s}" has been added').format(invoice))
                return redirect('wagtailinvoices_index', pk=invoiceindex.pk)
        else:
            messages.error(request, _('The invoice could not be created due to validation errors'))
            edit_handler = EditHandler(instance=invoice, form=form)

    else:
        form = EditForm(instance=invoice)
        edit_handler = EditHandler(instance=invoice, form=form)

    return render(request, 'wagtailinvoices/create.html', {
        'invoiceindex': invoiceindex,
        'form': form,
        'send_button_name': send_button_name,
        'edit_handler': edit_handler,
    })

@permission_required('wagtailadmin.access_admin')  # further permissions are enforced within the view
def edit(request, pk, invoice_pk):
    invoiceindex = get_object_or_404(Page, pk=pk, content_type__in=get_invoiceindex_content_types()).specific
    Invoice = invoiceindex.get_invoice_model()
    invoice = get_object_or_404(Invoice, invoiceindex=invoiceindex, pk=invoice_pk)
    send_button_name = 'send_invoice'
    print_button_name = 'serve_pdf'

    EditHandler = get_invoice_edit_handler(Invoice)
    EditForm = EditHandler.get_form_class(Invoice)

    if request.method == 'POST':
        form = EditForm(request.POST, request.FILES, instance=invoice)

        if form.is_valid():
            invoice = form.save()
            notify_drivers(request, invoice)
            invoice.notify_drivers = False
            '''
            n = 0
            for item in invoice.service_items.all():
                n = n + 1
                item.ref = str(invoice.id) + '-' + str(n)
                item.save()
            '''
            invoice.save()

            def is_invoice_address_fault():
                if invoice.client_organization or invoice.client_full_name:
                    return False
                else:
                    return True

            if is_invoice_address_fault() is True:
                messages.error(request, _('You cannot create an invoice without providing a client organization or client full name!'))
                edit_handler = EditHandler(instance=invoice, form=form)

            elif send_button_name in request.POST:
                if not invoice.client_email:
                    messages.error(request, _('You cannot email an invoice without an email to send it to. Please save the invoice without emailing it!'))
                    edit_handler = EditHandler(instance=invoice, form=form)
                else:
                    send_invoice(request, invoice)
                    messages.success(request, _('The invoice "{0!s}" has been updated').format(invoice))
                    return redirect('wagtailinvoices_index', pk=invoiceindex.pk)

            elif print_button_name in request.POST:
                serve_pdf(invoice, request)

            else:
                messages.success(request, _('The invoice "{0!s}" has been updated').format(invoice))
                return redirect('wagtailinvoices_index', pk=invoiceindex.pk)
        else:
            messages.error(request, _('The invoice could not be updated due to validation errors'))
            edit_handler = EditHandler(instance=invoice, form=form)
    else:
        form = EditForm(instance=invoice)
        edit_handler = EditHandler(instance=invoice, form=form)

    return render(request, 'wagtailinvoices/edit.html', {
        'invoiceindex': invoiceindex,
        'invoice': invoice,
        'send_button_name': send_button_name,
        'print_button_name': print_button_name,
        'form': form,
        'edit_handler': edit_handler,
    })

@permission_required('wagtailadmin.access_admin')  # further permissions are enforced within the view
def delete(request, pk, invoice_pk):
    invoiceindex = get_object_or_404(Page, pk=pk, content_type__in=get_invoiceindex_content_types()).specific
    Invoice = invoiceindex.get_invoice_model()
    invoice = get_object_or_404(Invoice, invoiceindex=invoiceindex, pk=invoice_pk)

    if request.method == 'POST':
        invoice.delete()
        return redirect('wagtailinvoices_index', pk=pk)

    return render(request, 'wagtailinvoices/delete.html', {
        'invoiceindex': invoiceindex,
        'invoice': invoice,
    })
<|endoftext|>


<commit_before>## @file
# This file is used to define each component of tools_def.txt file
#
# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.

# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution.  The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#

##
# Import Modules
#
import Common.LongFilePathOs as os
import re
import EdkLogger

from Dictionary import *
from BuildToolError import *
from TargetTxtClassObject import *
from Common.LongFilePathSupport import OpenLongFilePath as open

##
# Static variables used for pattern
#
gMacroRefPattern = re.compile('(DEF\([^\(\)]+\))')
gEnvRefPattern = re.compile('(ENV\([^\(\)]+\))')
gMacroDefPattern = re.compile("DEFINE\s+([^\s]+)")
gDefaultToolsDefFile = "tools_def.txt"

## ToolDefClassObject
#
# This class defined content used in file tools_def.txt
#
# @param object:               Inherited from object class
# @param Filename:             Input value for full path of tools_def.txt
#
# @var ToolsDefTxtDictionary:  To store keys and values defined in target.txt
# @var MacroDictionary:        To store keys and values defined in DEFINE statement
#
class ToolDefClassObject(object):
    def __init__(self, FileName=None):
        self.ToolsDefTxtDictionary = {}
        self.MacroDictionary = {}
        for Env in os.environ:
            self.MacroDictionary["ENV(%s)" % Env] = os.environ[Env]

        if FileName != None:
            self.LoadToolDefFile(FileName)

    ## LoadToolDefFile
    #
    # Load target.txt file and parse it, return a set structure to store keys and values
    #
    # @param Filename:  Input value for full path of tools_def.txt
    #
    def LoadToolDefFile(self, FileName):
        FileContent = []
        if os.path.isfile(FileName):
            try:
                F = open(FileName, 'r')
                FileContent = F.readlines()
            except:
                EdkLogger.error("tools_def.txt parser", FILE_OPEN_FAILURE, ExtraData=FileName)
        else:
            EdkLogger.error("tools_def.txt parser", FILE_NOT_FOUND, ExtraData=FileName)

        self.ToolsDefTxtDatabase = {
            TAB_TOD_DEFINES_TARGET          :   [],
            TAB_TOD_DEFINES_TOOL_CHAIN_TAG  :   [],
            TAB_TOD_DEFINES_TARGET_ARCH     :   [],
            TAB_TOD_DEFINES_COMMAND_TYPE    :   []
        }

        for Index in range(len(FileContent)):
            Line = FileContent[Index].strip()
            if Line == "" or Line[0] == '#':
                continue
            NameValuePair = Line.split("=", 1)
            if len(NameValuePair) != 2:
                EdkLogger.warn("tools_def.txt parser", "Line %d: not correct assignment statement, skipped" % (Index + 1))
                continue

            Name = NameValuePair[0].strip()
            Value = NameValuePair[1].strip()

            if Name == "IDENTIFIER":
                EdkLogger.debug(EdkLogger.DEBUG_8, "Line %d: Found identifier statement, skipped: %s" % ((Index + 1), Value))
                continue

            MacroDefinition = gMacroDefPattern.findall(Name)
            if MacroDefinition != []:
                Done, Value = self.ExpandMacros(Value)
                if not Done:
                    EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,
                                    "Macro or Environment has not been defined",
                                ExtraData=Value[4:-1], File=FileName, Line=Index+1)

                MacroName = MacroDefinition[0].strip()
                self.MacroDictionary["DEF(%s)" % MacroName] = Value
                EdkLogger.debug(EdkLogger.DEBUG_8, "Line %d: Found macro: %s = %s" % ((Index + 1), MacroName, Value))
                continue

            Done, Value = self.ExpandMacros(Value)
            if not Done:
                EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,
                                "Macro or Environment has not been defined",
                                ExtraData=Value[4:-1], File=FileName, Line=Index+1)

            List = Name.split('_')
            if len(List) != 5:
                EdkLogger.verbose("Line %d: Not a valid name of definition: %s" % ((Index + 1), Name))
                continue
            elif List[4] == '*':
                EdkLogger.verbose("Line %d: '*' is not allowed in last field: %s" % ((Index + 1), Name))
                continue
            else:
                self.ToolsDefTxtDictionary[Name] = Value
                if List[0] != '*':
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] += [List[0]]
                if List[1] != '*':
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] += [List[1]]
                if List[2] != '*':
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] += [List[2]]
                if List[3] != '*':
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] += [List[3]]
                if List[4] == TAB_TOD_DEFINES_FAMILY and List[2] == '*' and List[3] == '*':
                    if TAB_TOD_DEFINES_FAMILY not in self.ToolsDefTxtDatabase:
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY] = {}
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] = Value
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY] = {}
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value
                    elif List[1] not in self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]:
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] = Value
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value
                    elif self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] != Value:
                        EdkLogger.verbose("Line %d: No override allowed for the family of a tool chain: %s" % ((Index + 1), Name))
                if List[4] == TAB_TOD_DEFINES_BUILDRULEFAMILY and List[2] == '*' and List[3] == '*':
                    if TAB_TOD_DEFINES_BUILDRULEFAMILY not in self.ToolsDefTxtDatabase \
                       or List[1] not in self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]:
                        EdkLogger.verbose("Line %d: The family is not specified, but BuildRuleFamily is specified for the tool chain: %s" % ((Index + 1), Name))
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value

        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET]))
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG]))
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH]))
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE]))

        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET].sort()
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG].sort()
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH].sort()
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE].sort()

        KeyList = [TAB_TOD_DEFINES_TARGET, TAB_TOD_DEFINES_TOOL_CHAIN_TAG, TAB_TOD_DEFINES_TARGET_ARCH, TAB_TOD_DEFINES_COMMAND_TYPE]
        for Index in range(3, -1, -1):
            for Key in dict(self.ToolsDefTxtDictionary):
                List = Key.split('_')
                if List[Index] == '*':
                    for String in self.ToolsDefTxtDatabase[KeyList[Index]]:
                        List[Index] = String
                        NewKey = '%s_%s_%s_%s_%s' % tuple(List)
                        if NewKey not in self.ToolsDefTxtDictionary:
                            self.ToolsDefTxtDictionary[NewKey] = self.ToolsDefTxtDictionary[Key]
                        continue
                    del self.ToolsDefTxtDictionary[Key]
                elif List[Index] not in self.ToolsDefTxtDatabase[KeyList[Index]]:
                    del self.ToolsDefTxtDictionary[Key]

    ## ExpandMacros
    #
    # Replace defined macros with real value
    #
    # @param Value:   The string with unreplaced macros
    #
    # @retval Value:  The string which has been replaced with real value
    #
    def ExpandMacros(self, Value):
        EnvReference = gEnvRefPattern.findall(Value)
        for Ref in EnvReference:
            if Ref not in self.MacroDictionary:
                Value = Value.replace(Ref, "")
            else:
                Value = Value.replace(Ref, self.MacroDictionary[Ref])

        MacroReference = gMacroRefPattern.findall(Value)
        for Ref in MacroReference:
            if Ref not in self.MacroDictionary:
                return False, Ref
            Value = Value.replace(Ref, self.MacroDictionary[Ref])

        return True, Value

## ToolDefDict
#
# Load tools_def.txt in input Conf dir
#
# @param ConfDir:  Conf dir
#
# @retval ToolDef An instance of ToolDefClassObject() with loaded tools_def.txt
#
def ToolDefDict(ConfDir):
    Target = TargetTxtDict(ConfDir)
    ToolDef = ToolDefClassObject()
    if DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF in Target.TargetTxtDictionary:
        ToolsDefFile = Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
        if ToolsDefFile:
            ToolDef.LoadToolDefFile(os.path.normpath(ToolsDefFile))
        else:
            ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(ConfDir, gDefaultToolsDefFile)))
    else:
        ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(ConfDir, gDefaultToolsDefFile)))
    return ToolDef

##
#
# This acts like the main() function for the script, unless it is 'import'ed into another
# script.
#
if __name__ == '__main__':
    ToolDef = ToolDefDict(os.getenv("WORKSPACE"))
    pass
<commit_msg>BaseTools: Fix comments about return value of 'LoadToolDefFile'<commit_after>## @file
# This file is used to define each component of tools_def.txt file
#
# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.

# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution.  The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#

##
# Import Modules
#
import Common.LongFilePathOs as os
import re
import EdkLogger

from Dictionary import *
from BuildToolError import *
from TargetTxtClassObject import *
from Common.LongFilePathSupport import OpenLongFilePath as open

##
# Static variables used for pattern
#
gMacroRefPattern = re.compile('(DEF\([^\(\)]+\))')
gEnvRefPattern = re.compile('(ENV\([^\(\)]+\))')
gMacroDefPattern = re.compile("DEFINE\s+([^\s]+)")
gDefaultToolsDefFile = "tools_def.txt"

## ToolDefClassObject
#
# This class defined content used in file tools_def.txt
#
# @param object:               Inherited from object class
# @param Filename:             Input value for full path of tools_def.txt
#
# @var ToolsDefTxtDictionary:  To store keys and values defined in target.txt
# @var MacroDictionary:        To store keys and values defined in DEFINE statement
#
class ToolDefClassObject(object):
    def __init__(self, FileName=None):
        self.ToolsDefTxtDictionary = {}
        self.MacroDictionary = {}
        for Env in os.environ:
            self.MacroDictionary["ENV(%s)" % Env] = os.environ[Env]

        if FileName != None:
            self.LoadToolDefFile(FileName)

    ## LoadToolDefFile
    #
    # Load target.txt file and parse it
    #
    # @param Filename:  Input value for full path of tools_def.txt
    #
    def LoadToolDefFile(self, FileName):
        FileContent = []
        if os.path.isfile(FileName):
            try:
                F = open(FileName, 'r')
                FileContent = F.readlines()
            except:
                EdkLogger.error("tools_def.txt parser", FILE_OPEN_FAILURE, ExtraData=FileName)
        else:
            EdkLogger.error("tools_def.txt parser", FILE_NOT_FOUND, ExtraData=FileName)

        self.ToolsDefTxtDatabase = {
            TAB_TOD_DEFINES_TARGET          :   [],
            TAB_TOD_DEFINES_TOOL_CHAIN_TAG  :   [],
            TAB_TOD_DEFINES_TARGET_ARCH     :   [],
            TAB_TOD_DEFINES_COMMAND_TYPE    :   []
        }

        for Index in range(len(FileContent)):
            Line = FileContent[Index].strip()
            if Line == "" or Line[0] == '#':
                continue
            NameValuePair = Line.split("=", 1)
            if len(NameValuePair) != 2:
                EdkLogger.warn("tools_def.txt parser", "Line %d: not correct assignment statement, skipped" % (Index + 1))
                continue

            Name = NameValuePair[0].strip()
            Value = NameValuePair[1].strip()

            if Name == "IDENTIFIER":
                EdkLogger.debug(EdkLogger.DEBUG_8, "Line %d: Found identifier statement, skipped: %s" % ((Index + 1), Value))
                continue

            MacroDefinition = gMacroDefPattern.findall(Name)
            if MacroDefinition != []:
                Done, Value = self.ExpandMacros(Value)
                if not Done:
                    EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,
                                    "Macro or Environment has not been defined",
                                ExtraData=Value[4:-1], File=FileName, Line=Index+1)

                MacroName = MacroDefinition[0].strip()
                self.MacroDictionary["DEF(%s)" % MacroName] = Value
                EdkLogger.debug(EdkLogger.DEBUG_8, "Line %d: Found macro: %s = %s" % ((Index + 1), MacroName, Value))
                continue

            Done, Value = self.ExpandMacros(Value)
            if not Done:
                EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,
                                "Macro or Environment has not been defined",
                                ExtraData=Value[4:-1], File=FileName, Line=Index+1)

            List = Name.split('_')
            if len(List) != 5:
                EdkLogger.verbose("Line %d: Not a valid name of definition: %s" % ((Index + 1), Name))
                continue
            elif List[4] == '*':
                EdkLogger.verbose("Line %d: '*' is not allowed in last field: %s" % ((Index + 1), Name))
                continue
            else:
                self.ToolsDefTxtDictionary[Name] = Value
                if List[0] != '*':
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] += [List[0]]
                if List[1] != '*':
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] += [List[1]]
                if List[2] != '*':
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] += [List[2]]
                if List[3] != '*':
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] += [List[3]]
                if List[4] == TAB_TOD_DEFINES_FAMILY and List[2] == '*' and List[3] == '*':
                    if TAB_TOD_DEFINES_FAMILY not in self.ToolsDefTxtDatabase:
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY] = {}
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] = Value
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY] = {}
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value
                    elif List[1] not in self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]:
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] = Value
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value
                    elif self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] != Value:
                        EdkLogger.verbose("Line %d: No override allowed for the family of a tool chain: %s" % ((Index + 1), Name))
                if List[4] == TAB_TOD_DEFINES_BUILDRULEFAMILY and List[2] == '*' and List[3] == '*':
                    if TAB_TOD_DEFINES_BUILDRULEFAMILY not in self.ToolsDefTxtDatabase \
                       or List[1] not in self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]:
                        EdkLogger.verbose("Line %d: The family is not specified, but BuildRuleFamily is specified for the tool chain: %s" % ((Index + 1), Name))
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value

        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET]))
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG]))
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH]))
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE]))

        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET].sort()
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG].sort()
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH].sort()
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE].sort()

        KeyList = [TAB_TOD_DEFINES_TARGET, TAB_TOD_DEFINES_TOOL_CHAIN_TAG, TAB_TOD_DEFINES_TARGET_ARCH, TAB_TOD_DEFINES_COMMAND_TYPE]
        for Index in range(3, -1, -1):
            for Key in dict(self.ToolsDefTxtDictionary):
                List = Key.split('_')
                if List[Index] == '*':
                    for String in self.ToolsDefTxtDatabase[KeyList[Index]]:
                        List[Index] = String
                        NewKey = '%s_%s_%s_%s_%s' % tuple(List)
                        if NewKey not in self.ToolsDefTxtDictionary:
                            self.ToolsDefTxtDictionary[NewKey] = self.ToolsDefTxtDictionary[Key]
                        continue
                    del self.ToolsDefTxtDictionary[Key]
                elif List[Index] not in self.ToolsDefTxtDatabase[KeyList[Index]]:
                    del self.ToolsDefTxtDictionary[Key]

    ## ExpandMacros
    #
    # Replace defined macros with real value
    #
    # @param Value:   The string with unreplaced macros
    #
    # @retval Value:  The string which has been replaced with real value
    #
    def ExpandMacros(self, Value):
        EnvReference = gEnvRefPattern.findall(Value)
        for Ref in EnvReference:
            if Ref not in self.MacroDictionary:
                Value = Value.replace(Ref, "")
            else:
                Value = Value.replace(Ref, self.MacroDictionary[Ref])

        MacroReference = gMacroRefPattern.findall(Value)
        for Ref in MacroReference:
            if Ref not in self.MacroDictionary:
                return False, Ref
            Value = Value.replace(Ref, self.MacroDictionary[Ref])

        return True, Value

## ToolDefDict
#
# Load tools_def.txt in input Conf dir
#
# @param ConfDir:  Conf dir
#
# @retval ToolDef An instance of ToolDefClassObject() with loaded tools_def.txt
#
def ToolDefDict(ConfDir):
    Target = TargetTxtDict(ConfDir)
    ToolDef = ToolDefClassObject()
    if DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF in Target.TargetTxtDictionary:
        ToolsDefFile = Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
        if ToolsDefFile:
            ToolDef.LoadToolDefFile(os.path.normpath(ToolsDefFile))
        else:
            ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(ConfDir, gDefaultToolsDefFile)))
    else:
        ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(ConfDir, gDefaultToolsDefFile)))
    return ToolDef

##
#
# This acts like the main() function for the script, unless it is 'import'ed into another
# script.
#
if __name__ == '__main__':
    ToolDef = ToolDefDict(os.getenv("WORKSPACE"))
    pass
<|endoftext|>


<commit_before>import topia.termextract.extract
keywordExtractor = topia.termextract.extract.TermExtractor()

def f7(seq):
    seen = set()
    seen_add = seen.add
    return [ x for x in seq if x not in seen and not seen_add(x)]

def getKeywords(str):
    # keyword tagging

    keywords0 = sorted(keywordExtractor(str))
    # var keywords1: all keywords
    keywords1 = map(lambda x: x[0], keywords0)
    # var keywords2: keywords appearing at least 2x
    keywords2 = map(lambda x: x[0], [y for y in keywords0 if y[1] > 1])
    keywords = keywords2
    if(len(keywords) < 3):
        keywords = keywords + keywords1[:5]

    return f7(keywords)
<commit_msg>html entity decoding and chracter filtering<commit_after># -*- coding: utf-8 -*-

import re
from htmlentitydefs import name2codepoint
import topia.termextract.extract
keywordExtractor = topia.termextract.extract.TermExtractor()

def htmlentitydecode(s):
    return re.sub('&(%s);' % '|'.join(name2codepoint),
        lambda m: unichr(name2codepoint[m.group(1)]), s)

def f7(seq):
    seen = set()
    seen_add = seen.add
    return [ x for x in seq if x not in seen and not seen_add(x)]

def getKeywords(str):
    # keyword tagging

    str = re.sub(u'[^a-zA-Z0-9áéíóúÁÉÍÓÚâêîôÂÊÎÔãõÃÕçÇ:/\+\-"\'&\.,; ]', ' ', str)
    str = htmlentitydecode(str)
    str = re.sub(u'[^a-zA-Z0-9áéíóúÁÉÍÓÚâêîôÂÊÎÔãõÃÕçÇ:/\+\-&\., ]', ' ', str)
    keywords0 = sorted(keywordExtractor(str))
    # var keywords1: all keywords
    keywords1 = map(lambda x: x[0], keywords0)
    # var keywords2: keywords appearing at least 2x
    keywords2 = map(lambda x: x[0], [y for y in keywords0 if y[1] > 1])
    keywords = keywords2
    if(len(keywords) < 3):
        keywords = keywords + keywords1[:5]

    return f7(keywords)
<|endoftext|>


<commit_before>"""
Predictions widget

"""

from collections import OrderedDict, namedtuple

import numpy
from PyQt4 import QtCore, QtGui

import Orange
from Orange.base import Model
from Orange.data import ContinuousVariable, DiscreteVariable
from Orange.widgets import widget, gui
from Orange.widgets.settings import Setting
from Orange.widgets.utils.sql import check_sql_input

# Input slot for the Predictors channel
PredictorSlot = namedtuple(
    "PredictorSlot",
    ["predictor",  # The `Model` instance
     "name",       # Predictor name
     "results"]    # Computed prediction results or None.
)

def pname(predictor):
    """Return a predictor name."""
    if hasattr(predictor, "name"):
        return predictor.name
    else:
        return type(predictor).__name__

class OWPredictions(widget.OWWidget):
    name = "Predictions"
    icon = "icons/Predictions.svg"
    priority = 200
    description = "Display predictions of models for an input data set."
    inputs = [("Data", Orange.data.Table, "set_data"),
              ("Predictors", Model,
               "set_predictor", widget.Multiple)]
    outputs = [("Predictions", Orange.data.Table),
               ("Evaluation Results", Orange.evaluation.Results)]

    show_attrs = Setting(True)
    show_predictions = Setting(True)
    show_probabilities = Setting(True)

    want_main_area = False
    resizing_enabled = False

    def __init__(self):
        super().__init__()

        box = gui.widgetBox(self.controlArea, "Info")
        self.infolabel = gui.widgetLabel(
            box, "No data on input\nPredictors: 0\nTask: N/A")
        self.infolabel.setMinimumWidth(150)

        box = gui.widgetBox(self.controlArea, "Output")
        self.checkbox_class = gui.checkBox(
            box, self, "show_attrs", "Original data", callback=self.commit)
        self.checkbox_class = gui.checkBox(
            box, self, "show_predictions", "Predictions", callback=self.commit)
        self.checkbox_prob = gui.checkBox(
            box, self, "show_probabilities", "Probabilities",
            callback=self.commit)

        #: input data
        self.data = None
        #: A dict mapping input ids to PredictorSlot
        self.predictors = OrderedDict()
        #: A class variable (prediction target)
        self.class_var = None

        # enforce fixed size but provide a sensible minimum width constraint.
        self.layout().activate()
        self.controlArea.setMinimumWidth(self.controlArea.sizeHint().width())
        self.layout().setSizeConstraint(QtGui.QLayout.SetFixedSize)

    @check_sql_input
    def set_data(self, data):
        self.data = data
        self.invalidate_predictions()

    def set_predictor(self, predictor=None, id=None):
        if id in self.predictors:
            self.predictors[id] = self.predictors[id]._replace(
                predictor=predictor, name=pname(predictor), results=None)
        else:
            self.predictors[id] = \
                PredictorSlot(predictor, pname(predictor), None)
        if predictor is not None:
            self.class_var = predictor.domain.class_var

    def handleNewSignals(self):
        self.error(0)
        for inputid, pred in list(self.predictors.items()):
            if pred.predictor is None:
                del self.predictors[inputid]
            elif pred.results is None or numpy.isnan(pred.results[0]).all():
                if self.data is not None:
                    try:
                        results = self.predict(pred.predictor, self.data)
                    except ValueError as err:
                        err_msg = '{}:\n'.format(pred.predictor.name) + str(err)
                        self.error(0, err_msg)
                        n, m = len(self.data), 1
                        if self.data.domain.has_discrete_class:
                            m = len(self.data.domain.class_var.values)
                        probabilities = numpy.full((n, m), numpy.nan)
                        results = (numpy.full(n, numpy.nan), probabilities)
                    self.predictors[inputid] = pred._replace(results=results)
        if not self.predictors:
            self.class_var = None

        # Check for prediction target consistency
        target_vars = set([p.predictor.domain.class_var
                           for p in self.predictors.values()])
        if len(target_vars) > 1:
            self.warning(0, "Inconsistent class variables")
        else:
            self.warning(0)

        # Update the Info box text.
        info = []
        if self.data is not None:
            info.append("Data: {} instances.".format(len(self.data)))
        else:
            info.append("Data: N/A")

        if self.predictors:
            info.append("Predictors: {}".format(len(self.predictors)))
        else:
            info.append("Predictors: N/A")

        if self.class_var is not None:
            if self.class_var.is_discrete:
                info.append("Task: Classification")
                self.checkbox_class.setEnabled(True)
                self.checkbox_prob.setEnabled(True)
            else:
                info.append("Task: Regression")
                self.checkbox_class.setEnabled(False)
                self.checkbox_prob.setEnabled(False)
        else:
            info.append("Task: N/A")

        self.infolabel.setText("\n".join(info))
        self.commit()

    def invalidate_predictions(self):
        for inputid, pred in list(self.predictors.items()):
            self.predictors[inputid] = pred._replace(results=None)

    def commit(self):
        if self.data is None or not self.predictors:
            self.send("Predictions", None)
            self.send("Evaluation Results", None)
            return

        predictor = next(iter(self.predictors.values())).predictor
        class_var = predictor.domain.class_var
        classification = class_var and class_var.is_discrete

        newattrs = []
        newcolumns = []
        slots = list(self.predictors.values())

        if classification:
            if self.show_predictions:
                mc = [DiscreteVariable(name=p.name, values=class_var.values)
                      for p in slots]
                newattrs.extend(mc)
                newcolumns.extend(p.results[0].reshape((-1, 1))
                                  for p in slots)

            if self.show_probabilities:
                for p in slots:
                    m = [ContinuousVariable(name="%s(%s)" % (p.name, value))
                         for value in class_var.values]
                    newattrs.extend(m)
                newcolumns.extend(p.results[1] for p in slots)

        else:
            # regression
            mc = [ContinuousVariable(name=p.name)
                  for p in self.predictors.values()]
            newattrs.extend(mc)
            newcolumns.extend(p.results[0].reshape((-1, 1))
                              for p in slots)

        if self.show_attrs:
            X = [self.data.X]
            attrs = list(self.data.domain.attributes) + newattrs
        else:
            X = []
            attrs = newattrs
        domain = Orange.data.Domain(attrs, self.data.domain.class_var,
                                    metas=self.data.domain.metas)

        if newcolumns:
            X.extend(numpy.atleast_2d(cols) for cols in newcolumns)
        if X:
            X = numpy.hstack(tuple(X))
        else:
            X = numpy.zeros((len(self.data), 0))

        predictions = Orange.data.Table.from_numpy(
            domain, X, self.data.Y, metas=self.data.metas)
        predictions.name = self.data.name

        results = None
        if self.data.domain.class_var == class_var:
            N = len(self.data)
            results = Orange.evaluation.Results(self.data, store_data=True)
            results.folds = None
            results.row_indices = numpy.arange(N)
            results.actual = self.data.Y.ravel()
            results.predicted = numpy.vstack(
                tuple(p.results[0] for p in slots))
            if classification:
                results.probabilities = numpy.array(
                    [p.results[1] for p in slots])
            results.learner_names = [pname(p.predictor) for p in slots]

        self.send("Predictions", predictions)
        self.send("Evaluation Results", results)

    @classmethod
    def predict(cls, predictor, data):
        class_var = predictor.domain.class_var
        if class_var:
            if class_var.is_discrete:
                return cls.predict_discrete(predictor, data)
            elif class_var.is_continuous:
                return cls.predict_continuous(predictor, data)

    @staticmethod
    def predict_discrete(predictor, data):
        return predictor(data, Model.ValueProbs)

    @staticmethod
    def predict_continuous(predictor, data):
        values = predictor(data, Model.Value)
        return values, [None] * len(data)

if __name__ == "__main__":
    app = QtGui.QApplication([])
    w = OWPredictions()
    data = Orange.data.Table("iris")
#    svm_clf = Orange.classification.SVMLearner(probability=True)(data)
#    lr_clf = Orange.classification.LogisticRegressionLearner()(data)
    svm_clf = Orange.regression.RidgeRegressionLearner(alpha=1.0)(data)
    lr_clf = Orange.regression.LinearRegressionLearner()(data)
    w.set_data(data)
    w.set_predictor(svm_clf, 0)
    w.set_predictor(lr_clf, 1)
    w.handleNewSignals()
    w.show()
    app.exec()
    w.saveSettings()
<commit_msg>OWPredictions: Move predictions to metas (again)<commit_after>"""
Predictions widget

"""

from collections import OrderedDict, namedtuple

import numpy
from PyQt4 import QtCore, QtGui

import Orange
from Orange.base import Model
from Orange.data import ContinuousVariable, DiscreteVariable
from Orange.widgets import widget, gui
from Orange.widgets.settings import Setting
from Orange.widgets.utils.sql import check_sql_input

# Input slot for the Predictors channel
PredictorSlot = namedtuple(
    "PredictorSlot",
    ["predictor",  # The `Model` instance
     "name",       # Predictor name
     "results"]    # Computed prediction results or None.
)

def pname(predictor):
    """Return a predictor name."""
    if hasattr(predictor, "name"):
        return predictor.name
    else:
        return type(predictor).__name__

class OWPredictions(widget.OWWidget):
    name = "Predictions"
    icon = "icons/Predictions.svg"
    priority = 200
    description = "Display predictions of models for an input data set."
    inputs = [("Data", Orange.data.Table, "set_data"),
              ("Predictors", Model,
               "set_predictor", widget.Multiple)]
    outputs = [("Predictions", Orange.data.Table),
               ("Evaluation Results", Orange.evaluation.Results)]

    show_attrs = Setting(True)
    show_predictions = Setting(True)
    show_probabilities = Setting(True)

    want_main_area = False
    resizing_enabled = False

    def __init__(self):
        super().__init__()

        box = gui.widgetBox(self.controlArea, "Info")
        self.infolabel = gui.widgetLabel(
            box, "No data on input\nPredictors: 0\nTask: N/A")
        self.infolabel.setMinimumWidth(150)

        box = gui.widgetBox(self.controlArea, "Output")
        self.checkbox_class = gui.checkBox(
            box, self, "show_attrs", "Original data", callback=self.commit)
        self.checkbox_class = gui.checkBox(
            box, self, "show_predictions", "Predictions", callback=self.commit)
        self.checkbox_prob = gui.checkBox(
            box, self, "show_probabilities", "Probabilities",
            callback=self.commit)

        #: input data
        self.data = None
        #: A dict mapping input ids to PredictorSlot
        self.predictors = OrderedDict()
        #: A class variable (prediction target)
        self.class_var = None

        # enforce fixed size but provide a sensible minimum width constraint.
        self.layout().activate()
        self.controlArea.setMinimumWidth(self.controlArea.sizeHint().width())
        self.layout().setSizeConstraint(QtGui.QLayout.SetFixedSize)

    @check_sql_input
    def set_data(self, data):
        self.data = data
        self.invalidate_predictions()

    def set_predictor(self, predictor=None, id=None):
        if id in self.predictors:
            self.predictors[id] = self.predictors[id]._replace(
                predictor=predictor, name=pname(predictor), results=None)
        else:
            self.predictors[id] = \
                PredictorSlot(predictor, pname(predictor), None)
        if predictor is not None:
            self.class_var = predictor.domain.class_var

    def handleNewSignals(self):
        self.error(0)
        for inputid, pred in list(self.predictors.items()):
            if pred.predictor is None:
                del self.predictors[inputid]
            elif pred.results is None or numpy.isnan(pred.results[0]).all():
                if self.data is not None:
                    try:
                        results = self.predict(pred.predictor, self.data)
                    except ValueError as err:
                        err_msg = '{}:\n'.format(pred.predictor.name) + str(err)
                        self.error(0, err_msg)
                        n, m = len(self.data), 1
                        if self.data.domain.has_discrete_class:
                            m = len(self.data.domain.class_var.values)
                        probabilities = numpy.full((n, m), numpy.nan)
                        results = (numpy.full(n, numpy.nan), probabilities)
                    self.predictors[inputid] = pred._replace(results=results)
        if not self.predictors:
            self.class_var = None

        # Check for prediction target consistency
        target_vars = set([p.predictor.domain.class_var
                           for p in self.predictors.values()])
        if len(target_vars) > 1:
            self.warning(0, "Inconsistent class variables")
        else:
            self.warning(0)

        # Update the Info box text.
        info = []
        if self.data is not None:
            info.append("Data: {} instances.".format(len(self.data)))
        else:
            info.append("Data: N/A")

        if self.predictors:
            info.append("Predictors: {}".format(len(self.predictors)))
        else:
            info.append("Predictors: N/A")

        if self.class_var is not None:
            if self.class_var.is_discrete:
                info.append("Task: Classification")
                self.checkbox_class.setEnabled(True)
                self.checkbox_prob.setEnabled(True)
            else:
                info.append("Task: Regression")
                self.checkbox_class.setEnabled(False)
                self.checkbox_prob.setEnabled(False)
        else:
            info.append("Task: N/A")

        self.infolabel.setText("\n".join(info))
        self.commit()

    def invalidate_predictions(self):
        for inputid, pred in list(self.predictors.items()):
            self.predictors[inputid] = pred._replace(results=None)

    def commit(self):
        if self.data is None or not self.predictors:
            self.send("Predictions", None)
            self.send("Evaluation Results", None)
            return

        predictor = next(iter(self.predictors.values())).predictor
        class_var = predictor.domain.class_var
        classification = class_var and class_var.is_discrete

        newmetas = []
        newcolumns = []
        slots = list(self.predictors.values())

        if classification:
            if self.show_predictions:
                mc = [DiscreteVariable(name=p.name, values=class_var.values)
                      for p in slots]
                newmetas.extend(mc)
                newcolumns.extend(p.results[0].reshape((-1, 1))
                                  for p in slots)

            if self.show_probabilities:
                for p in slots:
                    m = [ContinuousVariable(name="%s(%s)" % (p.name, value))
                         for value in class_var.values]
                    newmetas.extend(m)
                newcolumns.extend(p.results[1] for p in slots)

        else:
            # regression
            mc = [ContinuousVariable(name=p.name)
                  for p in self.predictors.values()]
            newmetas.extend(mc)
            newcolumns.extend(p.results[0].reshape((-1, 1))
                              for p in slots)

        if self.show_attrs:
            attrs = list(self.data.domain.attributes)
        else:
            attrs = []
        metas = list(self.data.domain.metas) + newmetas

        domain = Orange.data.Domain(attrs, self.data.domain.class_var,
                                    metas=metas)
        predictions = self.data.from_table(domain, self.data)

        if newcolumns:
            newcolumns = numpy.hstack(
                [numpy.atleast_2d(cols) for cols in newcolumns]
            )
            predictions.metas[:, -newcolumns.shape[1]:] = newcolumns

        results = None
        if self.data.domain.class_var == class_var:
            N = len(self.data)
            results = Orange.evaluation.Results(self.data, store_data=True)
            results.folds = None
            results.row_indices = numpy.arange(N)
            results.actual = self.data.Y.ravel()
            results.predicted = numpy.vstack(
                tuple(p.results[0] for p in slots))
            if classification:
                results.probabilities = numpy.array(
                    [p.results[1] for p in slots])
            results.learner_names = [pname(p.predictor) for p in slots]

        self.send("Predictions", predictions)
        self.send("Evaluation Results", results)

    @classmethod
    def predict(cls, predictor, data):
        class_var = predictor.domain.class_var
        if class_var:
            if class_var.is_discrete:
                return cls.predict_discrete(predictor, data)
            elif class_var.is_continuous:
                return cls.predict_continuous(predictor, data)

    @staticmethod
    def predict_discrete(predictor, data):
        return predictor(data, Model.ValueProbs)

    @staticmethod
    def predict_continuous(predictor, data):
        values = predictor(data, Model.Value)
        return values, [None] * len(data)

if __name__ == "__main__":
    app = QtGui.QApplication([])
    w = OWPredictions()
    data = Orange.data.Table("iris")
#    svm_clf = Orange.classification.SVMLearner(probability=True)(data)
#    lr_clf = Orange.classification.LogisticRegressionLearner()(data)
    svm_clf = Orange.regression.RidgeRegressionLearner(alpha=1.0)(data)
    lr_clf = Orange.regression.LinearRegressionLearner()(data)
    w.set_data(data)
    w.set_predictor(svm_clf, 0)
    w.set_predictor(lr_clf, 1)
    w.handleNewSignals()
    w.show()
    app.exec()
    w.saveSettings()
<|endoftext|>


<commit_before># coding: utf-8

import json
import logging
import requests
from werkzeug.wrappers import BaseRequest
try:
    import gevent
except ImportError:
    gevent = None
    logging.info('gevent is not available')

HOMEPAGE = 'https://github.com/lepture/tower-slack'

TOWER_ICON = (
    'https://tower.im/assets/mobile/icon/'
    'icon@512-84fa5f6ced2a1bd53a409013f739b7ba.png'
)

MESSAGES = {
    'created': u'创建了',
    'updated': u'更新了',
    'deleted': u'删除了',
    'commented': u'评论了',

    'archived': u'归档了',
    'unarchived': u'激活了',

    'started': u'开始处理',
    'paused': u'暂停处理',
    'reopen': u'重新打开了',
    'completed': u'完成了',
    'deadline_changed': u'更新截止时间',

    'sticked': u'置顶了',
    'unsticked': u'取消置顶',

    'recovered': u'恢复了',

    # special
    'assigned': u'指派',
    'unassigned': u'取消指派',

    'documents': u'文档',
    'topics': u'讨论',
    'todos': u'任务',
    'todolists': u'任务清单',
    'attachments': u'文件',
}

COLORS = {
    'created': '#439FE0',
    'updated': 'warning',
    'completed': 'good',
    'deleted': 'danger',
}

class TowerSlack(object):
    def __init__(self, name='Tower', icon=TOWER_ICON, timeout=2):
        self.name = name
        self.icon = icon
        self.timeout = timeout

    def send_payload(self, payload, url, channel=None):
        if self.name:
            payload['username'] = self.name
        if self.icon:
            payload['icon_url'] = self.icon
        if channel:
            payload['channel'] = channel

        kwargs = dict(
            data=json.dumps(payload),
            headers={'Content-Type': 'application/json'},
            timeout=self.timeout,
        )

        if gevent:
            gevent.spawn(http_post, url, **kwargs)
        else:
            http_post(url, **kwargs)

    @staticmethod
    def create_payload(body, event):
        action = body['action']
        data = body['data']

        attachment = {}
        color = COLORS.get(action)
        if color:
            attachment['color'] = color

        project = data.pop('project')
        project_url = 'https://tower.im/projects/%s/' % project['guid']

        keys = data.keys()
        if len(keys) == 1:
            subject = data.pop(keys[0])
        else:
            subject = data.pop(event[:-1])
        subject_url = get_subject_url(project_url, event, subject['guid'])

        author = subject.get('handler')
        if author:
            attachment['author_name'] = author['nickname']
            author_link = 'https://tower.im/members/%s/' % (author['guid'])
            attachment['author_link'] = author_link

        text = u'%s <%s|#%s> 的%s <%s|%s>' % (
            MESSAGES.get(action, action),
            project_url, project['name'],
            MESSAGES.get(event, event),
            subject_url, subject['title'],
        )
        if action in ['assigned', 'unassigned']:
            assignee = subject.get('assignee')
            if assignee:
                text = u'%s 给 *%s*' % (text, assignee['nickname'])

        comment = data.get('comment')
        if comment:
            text = u'%s\n> %s' % (text, comment['content'])

        attachment['text'] = text
        attachment['mrkdwn_in'] = ['text']
        return {'attachments': [attachment]}

    def __call__(self, environ, start_response):
        req = BaseRequest(environ)

        if req.path == '/ip':
            return response(start_response, body=str(req.remote_addr))

        if req.method != 'POST':
            return redirect_homepage(start_response)

        event = req.headers.get('X-Tower-Event')
        if not event:
            return bad_request(start_response)

        signature = req.headers.get('X-Tower-Signature')
        if signature and signature[0] not in ('@', '#'):
            signature = None

        payload = self.create_payload(json.load(req.stream), event)
        url = 'https://hooks.slack.com/services/%s' % (req.path.lstrip('/'))
        self.send_payload(payload, url, signature)
        return response(start_response)

def get_subject_url(project_url, event, guid):
    if event == 'topics':
        event = 'messages'
    elif event == 'documents':
        event = 'docs'
    return '%s%s/%s/' % (project_url, event, guid)

def response(start_response, code='200 OK', body='ok', headers=None):
    if headers is None:
        headers = []
    headers.extend([
        ('Content-Type', 'text/plain'),
        ('Content-Length', str(len(body))),
    ])
    start_response(code, headers)
    return [body]

def redirect_homepage(start_response):
    body = 'Redirect to %s' % HOMEPAGE
    headers = [('Location', HOMEPAGE)]
    code = '301 Moved Permanently'
    return response(start_response, code, body, headers)

def bad_request(start_response):
    return response(start_response, code='400 Bad Request', body='400')

def http_post(url, **kwargs):
    try:
        requests.post(url, **kwargs)
    except Exception as e:
        logging.exception(e)
<commit_msg>Use sys.stderr and sys.stdout for leancloud<commit_after># coding: utf-8

import sys
import json
import requests
from werkzeug.wrappers import BaseRequest

try:
    import gevent
except ImportError:
    gevent = None
    print('gevent is not available')

HOMEPAGE = 'https://github.com/lepture/tower-slack'

TOWER_ICON = (
    'https://tower.im/assets/mobile/icon/'
    'icon@512-84fa5f6ced2a1bd53a409013f739b7ba.png'
)

MESSAGES = {
    'created': u'创建了',
    'updated': u'更新了',
    'deleted': u'删除了',
    'commented': u'评论了',

    'archived': u'归档了',
    'unarchived': u'激活了',

    'started': u'开始处理',
    'paused': u'暂停处理',
    'reopen': u'重新打开了',
    'completed': u'完成了',
    'deadline_changed': u'更新截止时间',

    'sticked': u'置顶了',
    'unsticked': u'取消置顶',

    'recovered': u'恢复了',

    # special
    'assigned': u'指派',
    'unassigned': u'取消指派',

    'documents': u'文档',
    'topics': u'讨论',
    'todos': u'任务',
    'todolists': u'任务清单',
    'attachments': u'文件',
}

COLORS = {
    'created': '#439FE0',
    'updated': 'warning',
    'completed': 'good',
    'deleted': 'danger',
}

class TowerSlack(object):
    def __init__(self, name='Tower', icon=TOWER_ICON, timeout=2):
        self.name = name
        self.icon = icon
        self.timeout = timeout

    def send_payload(self, payload, url, channel=None):
        if self.name:
            payload['username'] = self.name
        if self.icon:
            payload['icon_url'] = self.icon
        if channel:
            payload['channel'] = channel

        kwargs = dict(
            data=json.dumps(payload),
            headers={'Content-Type': 'application/json'},
            timeout=self.timeout,
        )

        if gevent:
            gevent.spawn(http_post, url, **kwargs)
        else:
            http_post(url, **kwargs)

    @staticmethod
    def create_payload(body, event):
        action = body['action']
        data = body['data']

        attachment = {}
        color = COLORS.get(action)
        if color:
            attachment['color'] = color

        project = data.pop('project')
        project_url = 'https://tower.im/projects/%s/' % project['guid']

        keys = data.keys()
        if len(keys) == 1:
            subject = data.pop(keys[0])
        else:
            subject = data.pop(event[:-1])
        subject_url = get_subject_url(project_url, event, subject['guid'])

        author = subject.get('handler')
        if author:
            attachment['author_name'] = author['nickname']
            author_link = 'https://tower.im/members/%s/' % (author['guid'])
            attachment['author_link'] = author_link

        text = u'%s <%s|#%s> 的%s <%s|%s>' % (
            MESSAGES.get(action, action),
            project_url, project['name'],
            MESSAGES.get(event, event),
            subject_url, subject['title'],
        )
        if action in ['assigned', 'unassigned']:
            assignee = subject.get('assignee')
            if assignee:
                text = u'%s 给 *%s*' % (text, assignee['nickname'])

        comment = data.get('comment')
        if comment:
            text = u'%s\n> %s' % (text, comment['content'])

        attachment['text'] = text
        attachment['mrkdwn_in'] = ['text']
        return {'attachments': [attachment]}

    def __call__(self, environ, start_response):
        req = BaseRequest(environ)

        if req.path == '/ip':
            return response(start_response, body=str(req.remote_addr))

        if req.method != 'POST':
            return redirect_homepage(start_response)

        event = req.headers.get('X-Tower-Event')
        if not event:
            return bad_request(start_response)

        signature = req.headers.get('X-Tower-Signature')
        if signature and signature[0] not in ('@', '#'):
            signature = None

        payload = self.create_payload(json.load(req.stream), event)
        url = 'https://hooks.slack.com/services/%s' % (req.path.lstrip('/'))
        self.send_payload(payload, url, signature)
        return response(start_response)

def get_subject_url(project_url, event, guid):
    if event == 'topics':
        event = 'messages'
    elif event == 'documents':
        event = 'docs'
    return '%s%s/%s/' % (project_url, event, guid)

def response(start_response, code='200 OK', body='ok', headers=None):
    if headers is None:
        headers = []
    headers.extend([
        ('Content-Type', 'text/plain'),
        ('Content-Length', str(len(body))),
    ])
    start_response(code, headers)
    return [body]

def redirect_homepage(start_response):
    body = 'Redirect to %s' % HOMEPAGE
    headers = [('Location', HOMEPAGE)]
    code = '301 Moved Permanently'
    return response(start_response, code, body, headers)

def bad_request(start_response):
    return response(start_response, code='400 Bad Request', body='400')

def http_post(url, **kwargs):
    try:
        requests.post(url, **kwargs)
    except Exception as e:
        sys.stderr.write(str(e))
<|endoftext|>


<commit_before># coding: utf-8

import json
import requests
from werkzeug.wrappers import BaseRequest
try:
    import gevent
except ImportError:
    gevent = None

HOMEPAGE = 'https://github.com/lepture/tower-slack'

TOWER_ICON = (
    'https://tower.im/assets/mobile/icon/'
    'icon@512-84fa5f6ced2a1bd53a409013f739b7ba.png'
)

MESSAGES = {
    'created': u'创建了',
    'updated': u'更新了',
    'deleted': u'删除了',
    'commented': u'评论了',

    'archived': u'归档了',
    'unarchived': u'激活了',

    'started': u'开始处理',
    'paused': u'暂停处理',
    'reopen': u'重新打开了',
    'completed': u'完成了',
    'deadline_changed': u'更新截止时间',

    'sticked': u'置顶了',
    'unsticked': u'取消置顶',

    'recovered': u'恢复了',

    # special
    'assigned': u'指派',
    'unassigned': u'取消指派',

    'documents': u'文档',
    'topics': u'讨论',
    'todos': u'任务',
    'todolists': u'任务清单',
    'attachments': u'文件',
}

COLORS = {
    'created': '#439FE0',
    'updated': 'warning',
    'completed': 'good',
    'deleted': 'danger',
}

class TowerSlack(object):
    def __init__(self, name='Tower', icon=TOWER_ICON, timeout=2):
        self.name = name
        self.icon = icon
        self.timeout = timeout

    def send_payload(self, payload, url, channel=None):
        if self.name:
            payload['username'] = self.name
        if self.icon:
            payload['icon_url'] = self.icon
        if channel:
            payload['channel'] = channel

        kwargs = dict(
            data=json.dumps(payload),
            headers={'Content-Type': 'application/json'},
            timeout=self.timeout,
        )

        if gevent:
            gevent.spawn(requests.post, url, **kwargs)
        else:
            requests.post(url, **kwargs)

    @staticmethod
    def create_payload(body, event):
        action = body['action']
        data = body['data']

        attachment = {}
        color = COLORS.get(action)
        if color:
            attachment['color'] = color

        project = data.pop('project')
        project_url = 'https://tower.im/projects/%s/' % project['guid']

        keys = data.keys()
        if len(keys) == 1:
            subject = data.pop(keys[0])
        else:
            subject = data.pop(event[:-1])
        subject_url = get_subject_url(project_url, event, subject['guid'])

        author = subject.get('handler')
        if author:
            attachment['author_name'] = author['nickname']
            author_link = 'https://tower.im/members/%s/' % (author['guid'])
            attachment['author_link'] = author_link

        text = u'%s <%s|#%s> 的%s <%s|%s>' % (
            MESSAGES.get(action, action),
            project_url, project['name'],
            MESSAGES.get(event, event),
            subject_url, subject['title'],
        )
        if action in ['assigned', 'unassigned']:
            assignee = subject.get('assignee')
            if assignee:
                text = u'%s 给 **%s**' % (text, assignee['nickname'])

        comment = data.get('comment')
        if comment:
            text = u'%s\n> %s' % (text, comment['content'])

        attachment['text'] = text
        attachment['mrkdwn_in'] = ['text']
        return {'attachments': [attachment]}

    def __call__(self, environ, start_response):
        req = BaseRequest(environ)

        if req.path == '/ip':
            return response(start_response, body=str(req.remote_addr))

        if req.method != 'POST':
            return redirect_homepage(start_response)

        event = req.headers.get('X-Tower-Event')
        if not event:
            return bad_request(start_response)

        signature = req.headers.get('X-Tower-Signature')
        if signature and signature[0] not in ('@', '#'):
            signature = None

        payload = self.create_payload(json.load(req.stream), event)
        url = 'https://hooks.slack.com/services/%s' % (req.path.lstrip('/'))
        self.send_payload(payload, url, signature)
        return response(start_response)

def get_subject_url(project_url, event, guid):
    if event == 'topics':
        event = 'messages'
    elif event == 'documents':
        event = 'docs'
    return '%s%s/%s/' % (project_url, event, guid)

def response(start_response, code='200 OK', body='ok', headers=None):
    if headers is None:
        headers = []
    headers.extend([
        ('Content-Type', 'text/plain'),
        ('Content-Length', str(len(body))),
    ])
    start_response(code, headers)
    return [body]

def redirect_homepage(start_response):
    body = 'Redirect to %s' % HOMEPAGE
    headers = [('Location', HOMEPAGE)]
    code = '301 Moved Permanently'
    return response(start_response, code, body, headers)

def bad_request(start_response):
    return response(start_response, code='400 Bad Request', body='400')
<commit_msg>Slack use *bold*<commit_after># coding: utf-8

import json
import requests
from werkzeug.wrappers import BaseRequest
try:
    import gevent
except ImportError:
    gevent = None

HOMEPAGE = 'https://github.com/lepture/tower-slack'

TOWER_ICON = (
    'https://tower.im/assets/mobile/icon/'
    'icon@512-84fa5f6ced2a1bd53a409013f739b7ba.png'
)

MESSAGES = {
    'created': u'创建了',
    'updated': u'更新了',
    'deleted': u'删除了',
    'commented': u'评论了',

    'archived': u'归档了',
    'unarchived': u'激活了',

    'started': u'开始处理',
    'paused': u'暂停处理',
    'reopen': u'重新打开了',
    'completed': u'完成了',
    'deadline_changed': u'更新截止时间',

    'sticked': u'置顶了',
    'unsticked': u'取消置顶',

    'recovered': u'恢复了',

    # special
    'assigned': u'指派',
    'unassigned': u'取消指派',

    'documents': u'文档',
    'topics': u'讨论',
    'todos': u'任务',
    'todolists': u'任务清单',
    'attachments': u'文件',
}

COLORS = {
    'created': '#439FE0',
    'updated': 'warning',
    'completed': 'good',
    'deleted': 'danger',
}

class TowerSlack(object):
    def __init__(self, name='Tower', icon=TOWER_ICON, timeout=2):
        self.name = name
        self.icon = icon
        self.timeout = timeout

    def send_payload(self, payload, url, channel=None):
        if self.name:
            payload['username'] = self.name
        if self.icon:
            payload['icon_url'] = self.icon
        if channel:
            payload['channel'] = channel

        kwargs = dict(
            data=json.dumps(payload),
            headers={'Content-Type': 'application/json'},
            timeout=self.timeout,
        )

        if gevent:
            gevent.spawn(requests.post, url, **kwargs)
        else:
            requests.post(url, **kwargs)

    @staticmethod
    def create_payload(body, event):
        action = body['action']
        data = body['data']

        attachment = {}
        color = COLORS.get(action)
        if color:
            attachment['color'] = color

        project = data.pop('project')
        project_url = 'https://tower.im/projects/%s/' % project['guid']

        keys = data.keys()
        if len(keys) == 1:
            subject = data.pop(keys[0])
        else:
            subject = data.pop(event[:-1])
        subject_url = get_subject_url(project_url, event, subject['guid'])

        author = subject.get('handler')
        if author:
            attachment['author_name'] = author['nickname']
            author_link = 'https://tower.im/members/%s/' % (author['guid'])
            attachment['author_link'] = author_link

        text = u'%s <%s|#%s> 的%s <%s|%s>' % (
            MESSAGES.get(action, action),
            project_url, project['name'],
            MESSAGES.get(event, event),
            subject_url, subject['title'],
        )
        if action in ['assigned', 'unassigned']:
            assignee = subject.get('assignee')
            if assignee:
                text = u'%s 给 *%s*' % (text, assignee['nickname'])

        comment = data.get('comment')
        if comment:
            text = u'%s\n> %s' % (text, comment['content'])

        attachment['text'] = text
        attachment['mrkdwn_in'] = ['text']
        return {'attachments': [attachment]}

    def __call__(self, environ, start_response):
        req = BaseRequest(environ)

        if req.path == '/ip':
            return response(start_response, body=str(req.remote_addr))

        if req.method != 'POST':
            return redirect_homepage(start_response)

        event = req.headers.get('X-Tower-Event')
        if not event:
            return bad_request(start_response)

        signature = req.headers.get('X-Tower-Signature')
        if signature and signature[0] not in ('@', '#'):
            signature = None

        payload = self.create_payload(json.load(req.stream), event)
        url = 'https://hooks.slack.com/services/%s' % (req.path.lstrip('/'))
        self.send_payload(payload, url, signature)
        return response(start_response)

def get_subject_url(project_url, event, guid):
    if event == 'topics':
        event = 'messages'
    elif event == 'documents':
        event = 'docs'
    return '%s%s/%s/' % (project_url, event, guid)

def response(start_response, code='200 OK', body='ok', headers=None):
    if headers is None:
        headers = []
    headers.extend([
        ('Content-Type', 'text/plain'),
        ('Content-Length', str(len(body))),
    ])
    start_response(code, headers)
    return [body]

def redirect_homepage(start_response):
    body = 'Redirect to %s' % HOMEPAGE
    headers = [('Location', HOMEPAGE)]
    code = '301 Moved Permanently'
    return response(start_response, code, body, headers)

def bad_request(start_response):
    return response(start_response, code='400 Bad Request', body='400')
<|endoftext|>