<commit_before>#!/usr/bin/python
import os
import re
import sys
import os.path
import logging

from urlparse import urlparse, urlunparse
from HTMLParser import HTMLParser, HTMLParseError
from optparse import OptionParser
from contextlib import closing

from hanzo.warctools import ArchiveRecord, WarcRecord
from hanzo.httptools import RequestMessage, ResponseMessage

LEVELS = {'debug': logging.DEBUG,
          'info': logging.INFO,
          'warning': logging.WARNING,
          'error': logging.ERROR,
          'critical': logging.CRITICAL}

parser = OptionParser(usage="%prog [options] warc (warc ...)")

parser.add_option("-L", "--log-level", dest="log_level")

parser.set_defaults(log_level="info")

def parse_http_response(record):
    message = ResponseMessage(RequestMessage())
    remainder = message.feed(record.content[1])
    message.close()
    if remainder or not message.complete():
        if remainder:
            logging.warning('trailing data in http response for %s'% record.url)
        if not message.complete():
            logging.warning('truncated http response for %s'%record.url)

    header = message.header

    mime_type = [v for k,v in header.headers if k.lower() =='content-type']
    if mime_type:
        mime_type = mime_type[0].split(';')[0]
    else:
        mime_type = None

    return header.code, mime_type, message

def extract_links_from_warcfh(fh):
    for (offset, record, errors) in fh.read_records(limit=None):
        if record:
            try:
                content_type, content = record.content

                if record.type == WarcRecord.RESPONSE and content_type.startswith('application/http'):

                    code, mime_type, message = parse_http_response(record)

                    if 200 <= code < 300 and mime_type.find('html') > -1:
                        for link in extract_links_from_html(record.url, message.get_body()):
                            yield ("".join(c for c in link if c not in '\n\r\t'))

            except StandardError, e:
                logging.warning("error in handling record "+str(e))
                import traceback; traceback.print_exc()

        elif errors:
            logging.warning("warc error at %d: %s"%((offset if offset else 0), ", ".join(str(e) for e in errors)))
            import traceback; traceback.print_exc()

try:
    import lxml.html

    def extract_links_from_html(base, body):
        try:
            html = lxml.html.fromstring(body)
            html.make_links_absolute(base)

            for element, attribute, link, pos in html.iterlinks():
                yield link

        except StandardError:
            logging.warning("(lxml) html parse error")
            import traceback; traceback.print_exc()

except ImportError:
    logging.warning("using fallback parser")
    def extract_links_from_html(base, body):
        try:
            html = LinkParser(base)
            html.feed(body)
            html.close()
            for link in html.get_abs_links():
                yield link
        except HTMLParseError,ex:
            logging.warning("html parse error")

""" fallback link extractor """
def attr_extractor(*names):
        def _extractor(attrs):
            return [value for key,value in attrs if key in names and value]
        return _extractor

def meta_extractor(attrs):
    content = [value for key,value in attrs if key =="content" and value]
    urls = []
    for value in content:
        for pair in value.split(";"):
            bits = pair.split("=",2)
            if len(bits)>1 and bits[0].lower()=="url":
                urls.append(bits[1].strip())
    return urls

class LinkParser(HTMLParser):
    def __init__(self, base):
        HTMLParser.__init__(self)
        self.links = []
        self.base = base

        self.tag_extractor = {
            "a": attr_extractor("href"),
            "applet": attr_extractor("code"),
            "area": attr_extractor("href"),
            "bgsound": attr_extractor("src"),
            "body": attr_extractor("background"),
            "embed": attr_extractor("href","src"),
            "fig": attr_extractor("src"),
            "form": attr_extractor("action"),
            "frame": attr_extractor("src"),
            "iframe": attr_extractor("src"),
            "img": attr_extractor("href","src","lowsrc"),
            "input": attr_extractor("src"),
            "link": attr_extractor("href"),
            "layer": attr_extractor("src"),
            "object": attr_extractor("data"),
            "overlay": attr_extractor("src"),
            "script": attr_extractor("src"),
            "table": attr_extractor("background"),
            "td": attr_extractor("background"),
            "th": attr_extractor("background"),

            "meta": meta_extractor,
            "base": self.base_extractor,
        }

    def base_extractor(self, attrs):
        base = [value for key,value in attrs if key == "href" and value]
        if base:
            self.base = base[-1]
        return ()

    def handle_starttag(self, tag, attrs):
        extractor = self.tag_extractor.get(tag, None)
        if extractor:
            self.links.extend(extractor(attrs))

    def get_abs_links(self):
        full_urls = []
        root = urlparse(self.base)
        root_dir = os.path.split(root.path)[0]
        for link in self.links:
            parsed = urlparse(link)
            if not parsed.netloc: # does it have no protocol or host, i.e relative
                if parsed.path.startswith("/"):
                    parsed = root[0:2] + parsed[2:5] + (None,)
                else:
                    dir = root_dir
                    path = parsed.path
                    while True:
                        if path.startswith("../"):
                            path=path[3:]
                            dir=os.path.split(dir)[0]
                        elif path.startswith("./"):
                            path=path[2:]
                        else:
                            break

                    parsed = root[0:2] + (os.path.join(dir, path),) + parsed[3:5] + (None,)
                new_link = urlunparse(parsed)
                logging.debug("relative %s -> %s"%(link, new_link))
                link=new_link

            else:
                logging.debug("absolute %s"%link)
            full_urls.append(link)
        return full_urls

def main(argv):
    (options, warcs) = parser.parse_args(args=argv[1:])
    logging.basicConfig(level=LEVELS[options.log_level])

    if len(warcs) < 1:
        parser.error("missing warcs(s)")

    ret = 0

    for warc in warcs:
        try:
            with closing(ArchiveRecord.open_archive(filename=warc, gzip="auto")) as fh:
                for link in extract_links_from_warcfh(fh):
                    print link

        except StandardError as e:
            logging.error(str(e))
            ret -=1

    return ret

if __name__ == '__main__':
    sys.exit(main(sys.argv))

<commit_msg>unicode strip<commit_after>#!/usr/bin/python
import os
import re
import sys
import os.path
import logging

from urlparse import urlparse, urlunparse
from HTMLParser import HTMLParser, HTMLParseError
from optparse import OptionParser
from contextlib import closing

from hanzo.warctools import ArchiveRecord, WarcRecord
from hanzo.httptools import RequestMessage, ResponseMessage

LEVELS = {'debug': logging.DEBUG,
          'info': logging.INFO,
          'warning': logging.WARNING,
          'error': logging.ERROR,
          'critical': logging.CRITICAL}

parser = OptionParser(usage="%prog [options] warc (warc ...)")

parser.add_option("-L", "--log-level", dest="log_level")

parser.set_defaults(log_level="info")

def parse_http_response(record):
    message = ResponseMessage(RequestMessage())
    remainder = message.feed(record.content[1])
    message.close()
    if remainder or not message.complete():
        if remainder:
            logging.warning('trailing data in http response for %s'% record.url)
        if not message.complete():
            logging.warning('truncated http response for %s'%record.url)

    header = message.header

    mime_type = [v for k,v in header.headers if k.lower() =='content-type']
    if mime_type:
        mime_type = mime_type[0].split(';')[0]
    else:
        mime_type = None

    return header.code, mime_type, message

def extract_links_from_warcfh(fh):
    for (offset, record, errors) in fh.read_records(limit=None):
        if record:
            try:
                content_type, content = record.content

                if record.type == WarcRecord.RESPONSE and content_type.startswith('application/http'):

                    code, mime_type, message = parse_http_response(record)

                    if 200 <= code < 300 and mime_type.find('html') > -1:
                        for link in extract_links_from_html(record.url, message.get_body()):
                            yield ("".join(c for c in link if c not in '\n\r\t'))

            except StandardError, e:
                logging.warning("error in handling record "+str(e))
                import traceback; traceback.print_exc()

        elif errors:
            logging.warning("warc error at %d: %s"%((offset if offset else 0), ", ".join(str(e) for e in errors)))
            import traceback; traceback.print_exc()

try:
    import lxml.html

    def extract_links_from_html(base, body):
        try:
            html = lxml.html.fromstring(body)
            html.make_links_absolute(base)

            for element, attribute, link, pos in html.iterlinks():
                if isinstance(link, unicode):
                    link = link.encode('utf-8', 'ignore')
                yield link

        except StandardError:
            logging.warning("(lxml) html parse error")
            import traceback; traceback.print_exc()

except ImportError:
    logging.warning("using fallback parser")
    def extract_links_from_html(base, body):
        try:
            html = LinkParser(base)
            html.feed(body)
            html.close()
            for link in html.get_abs_links():
                yield link
        except HTMLParseError,ex:
            logging.warning("html parse error")

""" fallback link extractor """
def attr_extractor(*names):
        def _extractor(attrs):
            return [value for key,value in attrs if key in names and value]
        return _extractor

def meta_extractor(attrs):
    content = [value for key,value in attrs if key =="content" and value]
    urls = []
    for value in content:
        for pair in value.split(";"):
            bits = pair.split("=",2)
            if len(bits)>1 and bits[0].lower()=="url":
                urls.append(bits[1].strip())
    return urls

class LinkParser(HTMLParser):
    def __init__(self, base):
        HTMLParser.__init__(self)
        self.links = []
        self.base = base

        self.tag_extractor = {
            "a": attr_extractor("href"),
            "applet": attr_extractor("code"),
            "area": attr_extractor("href"),
            "bgsound": attr_extractor("src"),
            "body": attr_extractor("background"),
            "embed": attr_extractor("href","src"),
            "fig": attr_extractor("src"),
            "form": attr_extractor("action"),
            "frame": attr_extractor("src"),
            "iframe": attr_extractor("src"),
            "img": attr_extractor("href","src","lowsrc"),
            "input": attr_extractor("src"),
            "link": attr_extractor("href"),
            "layer": attr_extractor("src"),
            "object": attr_extractor("data"),
            "overlay": attr_extractor("src"),
            "script": attr_extractor("src"),
            "table": attr_extractor("background"),
            "td": attr_extractor("background"),
            "th": attr_extractor("background"),

            "meta": meta_extractor,
            "base": self.base_extractor,
        }

    def base_extractor(self, attrs):
        base = [value for key,value in attrs if key == "href" and value]
        if base:
            self.base = base[-1]
        return ()

    def handle_starttag(self, tag, attrs):
        extractor = self.tag_extractor.get(tag, None)
        if extractor:
            self.links.extend(extractor(attrs))

    def get_abs_links(self):
        full_urls = []
        root = urlparse(self.base)
        root_dir = os.path.split(root.path)[0]
        for link in self.links:
            parsed = urlparse(link)
            if not parsed.netloc: # does it have no protocol or host, i.e relative
                if parsed.path.startswith("/"):
                    parsed = root[0:2] + parsed[2:5] + (None,)
                else:
                    dir = root_dir
                    path = parsed.path
                    while True:
                        if path.startswith("../"):
                            path=path[3:]
                            dir=os.path.split(dir)[0]
                        elif path.startswith("./"):
                            path=path[2:]
                        else:
                            break

                    parsed = root[0:2] + (os.path.join(dir, path),) + parsed[3:5] + (None,)
                new_link = urlunparse(parsed)
                logging.debug("relative %s -> %s"%(link, new_link))
                link=new_link

            else:
                logging.debug("absolute %s"%link)
            full_urls.append(link)
        return full_urls

def main(argv):
    (options, warcs) = parser.parse_args(args=argv[1:])
    logging.basicConfig(level=LEVELS[options.log_level])

    if len(warcs) < 1:
        parser.error("missing warcs(s)")

    ret = 0

    for warc in warcs:
        try:
            with closing(ArchiveRecord.open_archive(filename=warc, gzip="auto")) as fh:
                for link in extract_links_from_warcfh(fh):
                    print link

        except StandardError as e:
            logging.error(str(e))
            ret -=1

    return ret

if __name__ == '__main__':
    sys.exit(main(sys.argv))

<|endoftext|>


<commit_before>#!/usr/bin/python
import os
import re
import sys
import os.path
import logging

from urlparse import urlparse, urlunparse
from HTMLParser import HTMLParser, HTMLParseError
from optparse import OptionParser
from contextlib import closing

from hanzo.warctools import ArchiveRecord, WarcRecord
from hanzo.httptools import RequestMessage, ResponseMessage

LEVELS = {'debug': logging.DEBUG,
          'info': logging.INFO,
          'warning': logging.WARNING,
          'error': logging.ERROR,
          'critical': logging.CRITICAL}

parser = OptionParser(usage="%prog [options] warc (warc ...)")

parser.add_option("-L", "--log-level", dest="log_level")

parser.set_defaults(log_level="info")

def extract_links(fh):
    for (offset, record, errors) in fh.read_records(limit=None):
        if record:
            try:
                content_type, content = record.content

                if record.type == WarcRecord.RESPONSE and content_type.startswith('application/http'):

                    code, mime_type, message = parse_http_response(record)

                    if 200 <= code < 300 and mime_type.find('html') > -1:
                        html = LinkParser()
                        try:
                            html.feed(message.get_body())
                        except HTMLParseError,ex:
                            logging.warning("html parse error")
                            continue
                        finally:
                            html.close()

                        for link in html.get_abs_links(record.url):
                            yield link

            except StandardError, e:
                logging.warning("error in handling record "+str(e))

        elif errors:
            logging.warning("warc error at %d: %s"%((offset if offset else 0), ", ".join(str(e) for e in errors)))

def parse_http_response(record):
    message = ResponseMessage(RequestMessage())
    remainder = message.feed(record.content[1])
    message.close()
    if remainder or not message.complete():
        if remainder:
            logging.warning('trailing data in http response for %s'% record.url)
        if not message.complete():
            logging.warning('truncated http response for %s'%record.url)

    header = message.header

    mime_type = [v for k,v in header.headers if k.lower() =='content-type']
    if mime_type:
        mime_type = mime_type[0].split(';')[0]
    else:
        mime_type = None

    return header.code, mime_type, message

def attr_extractor(*names):
        def _extractor(attrs):
            return [value for key,value in attrs if key in names and value]
        return _extractor

def meta_extractor(attrs):
    content = [value for key,value in attrs if key =="content" and value]
    urls = []
    for value in content:
        for pair in value.split(";"):
            bits = pair.split("=",2)
            if len(bits)>1 and bits[0].lower()=="url":
                urls.append(bits[1].strip())
    return urls

class LinkParser(HTMLParser):
    def __init__(self):
        self.links = []
        HTMLParser.__init__(self)
        self.base = None

        self.tag_extractor = {
            "a": attr_extractor("href"),
            "applet": attr_extractor("code"),
            "area": attr_extractor("href"),
            "bgsound": attr_extractor("src"),
            "body": attr_extractor("background"),
            "embed": attr_extractor("href","src"),
            "fig": attr_extractor("src"),
            "form": attr_extractor("action"),
            "frame": attr_extractor("src"),
            "iframe": attr_extractor("src"),
            "img": attr_extractor("href","src","lowsrc"),
            "input": attr_extractor("src"),
            "link": attr_extractor("href"),
            "layer": attr_extractor("src"),
            "object": attr_extractor("data"),
            "overlay": attr_extractor("src"),
            "script": attr_extractor("src"),
            "table": attr_extractor("background"),
            "td": attr_extractor("background"),
            "th": attr_extractor("background"),

            "meta": meta_extractor,
            "base": self.base_extractor,
        }

    def base_extractor(self, attrs):
        base = [value for key,value in attrs if key == "href" and value]
        if base:
            self.base = base[-1]
        return ()

    def handle_starttag(self, tag, attrs):
        extractor = self.tag_extractor.get(tag, None)
        if extractor:
            self.links.extend(extractor(attrs))

    def get_abs_links(self, url):
        if self.base:
            url = self.base
        full_urls = []
        root = urlparse(url)
        root_dir = os.path.split(root.path)[0]
        for link in self.links:
            parsed = urlparse(link)
            if not parsed.netloc: # does it have no protocol or host, i.e relative
                if parsed.path.startswith("/"):
                    parsed = root[0:2] + parsed[2:5] + (None,)
                else:
                    dir = root_dir
                    path = parsed.path
                    while True:
                        if path.startswith("../"):
                            path=path[3:]
                            dir=os.path.split(dir)[0]
                        elif path.startswith("./"):
                            path=path[2:]
                        else:
                            break

                    parsed = root[0:2] + (os.path.join(dir, path),) + parsed[3:5] + (None,)
                new_link = urlunparse(parsed)
                logging.debug("relative %s -> %s"%(link, new_link))
                link=new_link

            else:
                logging.debug("absolute %s"%link)
            full_urls.append(link)
        return full_urls

def main(argv):
    (options, warcs) = parser.parse_args(args=argv[1:])
    logging.basicConfig(level=LEVELS[options.log_level])

    if len(warcs) < 1:
        parser.error("missing warcs(s)")

    ret = 0

    for warc in warcs:
        try:
            with closing(ArchiveRecord.open_archive(filename=warc, gzip="auto")) as fh:
                for link in extract_links(fh):
                    print link

        except StandardError as e:
            logging.error(str(e))
            ret -=1

    return ret

if __name__ == '__main__':
    sys.exit(main(sys.argv))

<commit_msg>skip junk html<commit_after>#!/usr/bin/python
import os
import re
import sys
import os.path
import logging

from urlparse import urlparse, urlunparse
from HTMLParser import HTMLParser, HTMLParseError
from optparse import OptionParser
from contextlib import closing

from hanzo.warctools import ArchiveRecord, WarcRecord
from hanzo.httptools import RequestMessage, ResponseMessage

LEVELS = {'debug': logging.DEBUG,
          'info': logging.INFO,
          'warning': logging.WARNING,
          'error': logging.ERROR,
          'critical': logging.CRITICAL}

parser = OptionParser(usage="%prog [options] warc (warc ...)")

parser.add_option("-L", "--log-level", dest="log_level")

parser.set_defaults(log_level="info")

def extract_links(fh):
    for (offset, record, errors) in fh.read_records(limit=None):
        if record:
            try:
                content_type, content = record.content

                if record.type == WarcRecord.RESPONSE and content_type.startswith('application/http'):

                    code, mime_type, message = parse_http_response(record)

                    if 200 <= code < 300 and mime_type.find('html') > -1:
                        html = LinkParser()
                        try:
                            html.feed(message.get_body())
                            html.close()
                        except HTMLParseError,ex:
                            logging.warning("html parse error")
                            continue
                        finally:

                        for link in html.get_abs_links(record.url):
                            yield link

            except StandardError, e:
                logging.warning("error in handling record "+str(e))

        elif errors:
            logging.warning("warc error at %d: %s"%((offset if offset else 0), ", ".join(str(e) for e in errors)))

def parse_http_response(record):
    message = ResponseMessage(RequestMessage())
    remainder = message.feed(record.content[1])
    message.close()
    if remainder or not message.complete():
        if remainder:
            logging.warning('trailing data in http response for %s'% record.url)
        if not message.complete():
            logging.warning('truncated http response for %s'%record.url)

    header = message.header

    mime_type = [v for k,v in header.headers if k.lower() =='content-type']
    if mime_type:
        mime_type = mime_type[0].split(';')[0]
    else:
        mime_type = None

    return header.code, mime_type, message

def attr_extractor(*names):
        def _extractor(attrs):
            return [value for key,value in attrs if key in names and value]
        return _extractor

def meta_extractor(attrs):
    content = [value for key,value in attrs if key =="content" and value]
    urls = []
    for value in content:
        for pair in value.split(";"):
            bits = pair.split("=",2)
            if len(bits)>1 and bits[0].lower()=="url":
                urls.append(bits[1].strip())
    return urls

class LinkParser(HTMLParser):
    def __init__(self):
        self.links = []
        HTMLParser.__init__(self)
        self.base = None

        self.tag_extractor = {
            "a": attr_extractor("href"),
            "applet": attr_extractor("code"),
            "area": attr_extractor("href"),
            "bgsound": attr_extractor("src"),
            "body": attr_extractor("background"),
            "embed": attr_extractor("href","src"),
            "fig": attr_extractor("src"),
            "form": attr_extractor("action"),
            "frame": attr_extractor("src"),
            "iframe": attr_extractor("src"),
            "img": attr_extractor("href","src","lowsrc"),
            "input": attr_extractor("src"),
            "link": attr_extractor("href"),
            "layer": attr_extractor("src"),
            "object": attr_extractor("data"),
            "overlay": attr_extractor("src"),
            "script": attr_extractor("src"),
            "table": attr_extractor("background"),
            "td": attr_extractor("background"),
            "th": attr_extractor("background"),

            "meta": meta_extractor,
            "base": self.base_extractor,
        }

    def base_extractor(self, attrs):
        base = [value for key,value in attrs if key == "href" and value]
        if base:
            self.base = base[-1]
        return ()

    def handle_starttag(self, tag, attrs):
        extractor = self.tag_extractor.get(tag, None)
        if extractor:
            self.links.extend(extractor(attrs))

    def get_abs_links(self, url):
        if self.base:
            url = self.base
        full_urls = []
        root = urlparse(url)
        root_dir = os.path.split(root.path)[0]
        for link in self.links:
            parsed = urlparse(link)
            if not parsed.netloc: # does it have no protocol or host, i.e relative
                if parsed.path.startswith("/"):
                    parsed = root[0:2] + parsed[2:5] + (None,)
                else:
                    dir = root_dir
                    path = parsed.path
                    while True:
                        if path.startswith("../"):
                            path=path[3:]
                            dir=os.path.split(dir)[0]
                        elif path.startswith("./"):
                            path=path[2:]
                        else:
                            break

                    parsed = root[0:2] + (os.path.join(dir, path),) + parsed[3:5] + (None,)
                new_link = urlunparse(parsed)
                logging.debug("relative %s -> %s"%(link, new_link))
                link=new_link

            else:
                logging.debug("absolute %s"%link)
            full_urls.append(link)
        return full_urls

def main(argv):
    (options, warcs) = parser.parse_args(args=argv[1:])
    logging.basicConfig(level=LEVELS[options.log_level])

    if len(warcs) < 1:
        parser.error("missing warcs(s)")

    ret = 0

    for warc in warcs:
        try:
            with closing(ArchiveRecord.open_archive(filename=warc, gzip="auto")) as fh:
                for link in extract_links(fh):
                    print link

        except StandardError as e:
            logging.error(str(e))
            ret -=1

    return ret

if __name__ == '__main__':
    sys.exit(main(sys.argv))

<|endoftext|>


<commit_before>"""\
GistMail

Email gist@gistmail.com with a link and get a response with that article's summary.
"""

from mandrill import Mandrill
from flask import Flask, abort, json, render_template, request
from raven.contrib.flask import Sentry
from summarize import summarize_page

# Flask application
app = Flask(__name__)
# Configuration
app.config.from_object('settings')
app.config.from_envvar('SETTINGS_MODULE', silent=True)
app.config.from_pyfile('settings_local.py', silent=True)
# Email
mandrill = Mandrill(app.config['MANDRILL_API_KEY'])
# Error logging
sentry = Sentry(app) if not app.config['SENTRY_DISABLED'] else None

# Views
@app.route('/')
def index():
    return render_template('index.html')

@app.route('/admin')
def admin():
    if not bool(app.config['DEBUG']):
        abort(404)
    return render_template('admin.html', test_email_json=test_email_json())

@app.route('/incoming', methods=['GET', 'POST'])
def incoming():
    # Ignore initial Mandrill check
    if request.method == 'GET':
        return ''
    if not request.form['mandrill_events'] or request.form['mandrill_events'] == []:
        return ''

    # TODO: Check that this request is actually coming from Mandrill

    print ' * INCOMING EMAIL:',

    event = json.loads(request.form['mandrill_events'])[0]
    msg = event['msg']

    email = msg['from_email']
    subject = msg['subject']
    print email

    # Ignore Mandrill test
    if email == u'example.sender@mandrillapp.com':
        return ''

    # TODO: Use pattern matching to find the URL
    url = msg['text'].strip()
    print 'Summarizing:', url

    try:
        summary = summarize_page(url)
    except Exception as ex:
        if sentry:
            sentry.captureException()
        print ' * ERROR:', type(ex), ex
        subject = '[ERROR] ' + subject
        html = render_template('error_email.html', url=url)
    else:
        html = render_template('summary_email.html',
            title=summary.title, url=summary.url, summaries=summary.summaries)

    print 'Replying to:', email
    email_id = send_email(email, subject, html)

    print 'Reply ID:', email_id
    return ''

# Helpers
def send_email(to, subject, html):
    if isinstance(to, basestring):
        to = {'email': to}
    message = {
        'html': html,
        'subject': subject,
        'from_email': app.config['MANDRILL_EMAIL'],
        'from_name': app.config['MANDRILL_EMAIL_NAME'],
        'to': [to],
    }
    result = mandrill.messages.send(message=message)[0]
    return result['_id']

def test_email_json():
    return json.dumps([
        {
            'msg': {
                'from_email': app.config['ADMIN_EMAIL'],
                'subject': 'GistMail Test',
                'text': 'http://gistmail.com',
            },
        },
    ], indent=4, sort_keys=True)

# Run development server
if __name__ == '__main__':
    app.run(app.config['HOST'], app.config['PORT'], app.debug)
<commit_msg>Fix Sentry errors on some missing fields.<commit_after>"""\
GistMail

Email gist@gistmail.com with a link and get a response with that article's summary.
"""

from mandrill import Mandrill
from flask import Flask, abort, json, render_template, request
from raven.contrib.flask import Sentry
from summarize import summarize_page

# Flask application
app = Flask(__name__)
# Configuration
app.config.from_object('settings')
app.config.from_envvar('SETTINGS_MODULE', silent=True)
app.config.from_pyfile('settings_local.py', silent=True)
# Email
mandrill = Mandrill(app.config['MANDRILL_API_KEY'])
# Error logging
sentry = Sentry(app) if not app.config['SENTRY_DISABLED'] else None

# Views
@app.route('/')
def index():
    return render_template('index.html')

@app.route('/admin')
def admin():
    if not bool(app.config['DEBUG']):
        abort(404)
    return render_template('admin.html', test_email_json=test_email_json())

@app.route('/incoming', methods=['GET', 'POST'])
def incoming():
    # Ignore initial Mandrill check
    if request.method == 'GET':
        return ''
    if not request.form['mandrill_events'] or request.form['mandrill_events'] == []:
        return ''

    # TODO: Check that this request is actually coming from Mandrill

    print ' * INCOMING EMAIL:',

    # Get incoming message
    event = json.loads(request.form['mandrill_events'])[0]
    msg = event['msg'] if 'msg' in event else None
    if not msg:
        print ' * SKIPPING: No "msg" field found'
        return ''

    # Get message metadata
    email = msg['from_email']
    subject = msg['subject']
    if not email:
        print ' * SKIPPING: No "email" field found.'
        return ''
    if not subject:
        print ' * SKIPPING: No "subject" field found.'
        return ''

    # Ignore Mandrill test
    print 'Incoming email from:', email
    if email == u'example.sender@mandrillapp.com':
        print ' * Skipping incoming test email.'
        return ''

    # Ignore malformed message
    text = msg['text'] if 'text' in msg else None
    if text:
        print ' * SKIPPING: No "text" field found.'
        return ''

    # TODO: Use pattern matching to find the URL
    url = text.strip()
    print 'Summarizing:', url

    try:
        summary = summarize_page(url)
    except Exception as ex:
        if sentry:
            sentry.captureException()
        print ' * ERROR:', type(ex), ex
        subject = '[ERROR] ' + subject
        html = render_template('error_email.html', url=url)
    else:
        html = render_template('summary_email.html',
            title=summary.title, url=summary.url, summaries=summary.summaries)

    print 'Replying to:', email
    email_id = send_email(email, subject, html)

    print 'Reply ID:', email_id
    return ''

# Helpers
def send_email(to, subject, html):
    if isinstance(to, basestring):
        to = {'email': to}
    message = {
        'html': html,
        'subject': subject,
        'from_email': app.config['MANDRILL_EMAIL'],
        'from_name': app.config['MANDRILL_EMAIL_NAME'],
        'to': [to],
    }
    result = mandrill.messages.send(message=message)[0]
    return result['_id']

def test_email_json():
    return json.dumps([
        {
            'msg': {
                'from_email': app.config['ADMIN_EMAIL'],
                'subject': 'GistMail Test',
                'text': 'http://gistmail.com',
            },
        },
    ], indent=4, sort_keys=True)

# Run development server
if __name__ == '__main__':
    app.run(app.config['HOST'], app.config['PORT'], app.debug)
<|endoftext|>


<commit_before>import os, sys, re
from optparse import OptionParser
from socket import gethostname

from PerfLogParser import PerfLogParser
from ExcelWriter import ExcelWriter

import timeit, inspect, StringIO

class ExodiffException(Exception):
  pass

class TestHarness:
  # static variable so the helper functions can access the executable name
  # using only the class name (not an instance) from tools.py
  # this is cleaner than a global variable
  exec_name = ''

  def __init__(self, argv, app_name):
    # parse command line args
    self.options, self.leftovers, self.arg_string = self.getOptions(argv)

    # Determine the application name based on the libMesh naming scheme
    # Assume the application is in the current working directory
    # Order of importance, 1. command line args 2. environment 3. default is opt
    method = ''
    if self.options.method:
      method = self.options.method
    elif os.environ.has_key('METHOD'):
      method = os.environ['METHOD']
    else:
      method = 'opt'
    executable = os.getcwd() + '/' + app_name + '-' + method

    TestHarness.exec_name = executable

    # Emulate the standard Nose RegEx for consistency
    self.test_match = re.compile(r"(?:^|\b|[_-])[Tt]est")

    self.all_passed = True
    self.num_tests = 0
    self.num_passed = 0

    # map of tests to results
    self.results_table = {}

    # holds the string table dumped to the screen for easy printing
    self.text_results_table = ''

    # See if an Excel dump was requested
    if self.options.xlsFile:
      self.xls_writer = ExcelWriter(self.options.xlsFile)
    else:
      self.xls_writer = None

  # Call this function to run all tests and exit success or fail
  def runTestsAndExit(self, check_icestorm=True):
    # Check if this is icestorm before we run the tests
    host_name = gethostname()
    if check_icestorm and (host_name == 'service0' or host_name == 'service1'):
      print 'Testing not supported on Icestorm head node'
      sys.exit(0)

    # Call overridable functions to run and process the tests
    self.preRun()
    self.runAll()
    self.postRun()

    msg = self.getFailMessage()
    if msg:
      print msg
      sys.exit(1)
    sys.exit(0)

  # override this function if you need to do stuff before the tests are run
  def preRun(self):
    self.all_passed = True
    self.results_table = {}
    self.text_results_table = ''
    self.num_tests = 0

  # finds all the test py scripts and passes them to inspectAndTest
  def runAll(self):
    start = timeit.default_timer()

    for dirpath, dirnames, filenames in os.walk(os.getcwd()):
      if (self.test_match.search(dirpath)):
        for file in filenames:
          # See if there were other arguments (test names) passed on the command line
          if (file[-2:] == 'py' and
              self.test_match.search(file) and
              (len(self.leftovers) == 0 or len([item for item in self.leftovers if re.match(item, file)]) == 1)):

            module_name = file[:-3]
            self.inspectAndTest(dirpath, module_name)

    end = timeit.default_timer()
    self.testing_time = end - start

  # takes a module name (.py file) and runs all the tests in it
  def inspectAndTest(self, dirpath, module_name):
    saved_cwd = os.getcwd()
    sys.path.append(os.path.abspath(dirpath))
    os.chdir(dirpath)

    # dynamically load the module
    module = __import__(module_name)

    # inspect the routine and look for test functions
    for routine, address in inspect.getmembers(module, inspect.isroutine):
      if self.test_match.search(routine):

        supported_args = set(inspect.getargspec(address)[0])
        testname = module_name + '.' + routine
        # See if this test function supports benchmarking or parallel requests
        if ((self.arg_string.find('dofs') >= 0 and not 'dofs' in supported_args) or
            (self.arg_string.find('np') >=0 and not 'np' in supported_args) or
            (self.arg_string.find('n_threads') >=0 and not 'n_threads' in supported_args)):
          self.runTest(testname, address, True)
        else:
          self.runTest(testname, address)

    os.chdir(saved_cwd)
    sys.path.pop()

  # run a single test
  def runTest(self, test, address, override=False):
    result = ''
    try:
      try:
        s = test + " ..."
        self.text_results_table += '\n' + s
        sys.stdout.write(s)
	sys.stdout.flush()
        test_start = timeit.default_timer()

        # Capture stdout to a buffer object for the local function call
        saved_stdout = sys.stdout
        capture = StringIO.StringIO()
        sys.stdout = capture

        args = ''
        if override:
          args = ''
        else:
          args = self.arg_string

        eval('address(' + args + ')')

        test_end = timeit.default_timer()

        # confusing: if arg_string is populated it means we changed dofs/np so
        # we want to see the testing time, not just pass/fail
        if (args == ''):
          result = 'OK'
        else:
          result = str(round(test_end-test_start,3)) + 's'

      except AssertionError:
        self.all_passed = False
        result = 'FAILED'
      except ExodiffException:
        # A regular exception means that the program ran but produced different output
        self.all_passed = False
        result = 'FAILED (DIFF)'
    finally:
      sys.stdout = saved_stdout
      test_end = timeit.default_timer()
      output = capture.getvalue()

      # We can skip established tests with the "pass" keyword in our
      # python driver files in which case no output is produced.
      # In this case we want to notify the user that the test was actually
      # skipped not OK
      if output == '':
        result = 'skipped'
      else:
        self.num_tests += 1

      self.processOutput(test, result, capture.getvalue())

  # override in sub classes to process the output of each test
  def processOutput(self, test, result, output):
    if self.xls_writer:
      parser = PerfLogParser()
      parser.parse(output)
      parser.writeExcel(self.xls_writer, test)

    # print the result of this test in table form
    self.results_table[test] = result
    if result == 'OK':
      self.num_passed += 1
    cnt = 65 - len(test + result)
    s = '.'*cnt + " " + result
    self.text_results_table += s
    print s

    # print the output if verbose option is on or the test failed
    if self.options.verbose or result.find('FAILED') != -1:
      print '*'*100 + '\n' + '*'*41 + '  FAILED OUTPUT  ' + '*'*42 + '\n' + '*'*100 + '\n' + output
      #print s

  # return '' if all tests passed, or a message if some failed. Override if you
  # want more fail criteria
  def getFailMessage(self):
    if self.all_passed:
      return ''
    return 'FAILED '

  # override this function if you need to do stuff after the tests are run
  def postRun(self):
    if self.xls_writer:
      self.xls_writer.close()

    # if there was output before this the full table will be obscured, so
    # print it in it's entirety here at the bottom
    if self.options.verbose or not self.all_passed:
      print '\n\nFull Result Table:\n' + '-'*70
      print self.text_results_table

    print '-'*70
    print 'Ran ' + str(self.num_tests) + ' tests in ' + str(round(self.testing_time)) + 's (' + str(self.num_passed) + '/' + str(self.num_tests) + ' passed)\n'

  # deprecated because it violates the coding standard's naming scheme
  def run_tests_and_exit(self, check_icestorm=True):
    self.runTestsAndExit(check_icestorm)

  def getOptions(self, argv):
    # Callback function
    arg_vector = []
    def buildArgVector(option, opt_str, value, parser):
      arg_vector.append(option.dest + '=' +  str(value))

    parser = OptionParser()
    parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="show more output [default=FALSE]")
    parser.add_option("-x", "--xls", action="store", dest="xlsFile", metavar="FILE", help="write excel format performance data to FILE")
    parser.add_option("-d", "--dofs", action="callback", callback=buildArgVector, type="int", dest="dofs", help="refine each example to meet the minimum requested DOFS")
    parser.add_option("-n", "--np", action="callback", callback=buildArgVector, type="int", dest="np", help="specify the number of MPI processes launched")
    parser.add_option("--helios-only-after", action="store_true", dest="heliosOnly", help="The options after this option are only applied if hostname == helios")
    parser.add_option("--opt", action="store_const", dest="method", const="opt", help="test the app_name-opt binary")
    parser.add_option("--dbg", action="store_const", dest="method", const="dbg", help="test the app_name-dbg binary")
    parser.add_option("--dev", action="store_const", dest="method", const="dev", help="test the app_name-dev binary")
    parser.add_option("--n_threads", type="int", dest="n_threads", action="callback", callback=buildArgVector, help="specify the number of threads to be used")
    self.addOptions(parser)

    (options, args) = parser.parse_args(argv[1:])
    # Return the 'options' and leftover args returned from parse_args and
    # also the arg_string made from joining the arguments in the arg_vector
    return (options, args, ','.join(arg_vector))

  # override this method to add custom options to the parser
  def addOptions(self, parser):
    pass
<commit_msg>Color ./run_tests results<commit_after>import os, sys, re
from optparse import OptionParser
from socket import gethostname

from PerfLogParser import PerfLogParser
from ExcelWriter import ExcelWriter

import timeit, inspect, StringIO

class ExodiffException(Exception):
  pass

class TestHarness:
  # static variable so the helper functions can access the executable name
  # using only the class name (not an instance) from tools.py
  # this is cleaner than a global variable
  exec_name = ''

  def __init__(self, argv, app_name):
    # parse command line args
    self.options, self.leftovers, self.arg_string = self.getOptions(argv)

    # Determine the application name based on the libMesh naming scheme
    # Assume the application is in the current working directory
    # Order of importance, 1. command line args 2. environment 3. default is opt
    method = ''
    if self.options.method:
      method = self.options.method
    elif os.environ.has_key('METHOD'):
      method = os.environ['METHOD']
    else:
      method = 'opt'
    executable = os.getcwd() + '/' + app_name + '-' + method

    TestHarness.exec_name = executable

    # Emulate the standard Nose RegEx for consistency
    self.test_match = re.compile(r"(?:^|\b|[_-])[Tt]est")

    self.all_passed = True
    self.num_tests = 0
    self.num_passed = 0

    # map of tests to results
    self.results_table = {}

    # holds the string table dumped to the screen for easy printing
    self.text_results_table = ''

    # See if an Excel dump was requested
    if self.options.xlsFile:
      self.xls_writer = ExcelWriter(self.options.xlsFile)
    else:
      self.xls_writer = None

  # Call this function to run all tests and exit success or fail
  def runTestsAndExit(self, check_icestorm=True):
    # Check if this is icestorm before we run the tests
    host_name = gethostname()
    if check_icestorm and (host_name == 'service0' or host_name == 'service1'):
      print 'Testing not supported on Icestorm head node'
      sys.exit(0)

    # Call overridable functions to run and process the tests
    self.preRun()
    self.runAll()
    self.postRun()

    msg = self.getFailMessage()
    if msg:
      print BOLD + RED + msg + RESET
      sys.exit(1)
    sys.exit(0)

  # override this function if you need to do stuff before the tests are run
  def preRun(self):
    self.all_passed = True
    self.results_table = {}
    self.text_results_table = ''
    self.num_tests = 0

  # finds all the test py scripts and passes them to inspectAndTest
  def runAll(self):
    start = timeit.default_timer()

    for dirpath, dirnames, filenames in os.walk(os.getcwd()):
      if (self.test_match.search(dirpath)):
        for file in filenames:
          # See if there were other arguments (test names) passed on the command line
          if (file[-2:] == 'py' and
              self.test_match.search(file) and
              (len(self.leftovers) == 0 or len([item for item in self.leftovers if re.match(item, file)]) == 1)):

            module_name = file[:-3]
            self.inspectAndTest(dirpath, module_name)

    end = timeit.default_timer()
    self.testing_time = end - start

  # takes a module name (.py file) and runs all the tests in it
  def inspectAndTest(self, dirpath, module_name):
    saved_cwd = os.getcwd()
    sys.path.append(os.path.abspath(dirpath))
    os.chdir(dirpath)

    # dynamically load the module
    module = __import__(module_name)

    # inspect the routine and look for test functions
    for routine, address in inspect.getmembers(module, inspect.isroutine):
      if self.test_match.search(routine):

        supported_args = set(inspect.getargspec(address)[0])
        testname = module_name + '.' + routine
        # See if this test function supports benchmarking or parallel requests
        if ((self.arg_string.find('dofs') >= 0 and not 'dofs' in supported_args) or
            (self.arg_string.find('np') >=0 and not 'np' in supported_args) or
            (self.arg_string.find('n_threads') >=0 and not 'n_threads' in supported_args)):
          self.runTest(testname, address, True)
        else:
          self.runTest(testname, address)

    os.chdir(saved_cwd)
    sys.path.pop()

  # run a single test
  def runTest(self, test, address, override=False):
    result = ''
    try:
      try:
        s = test + " ..."
        self.text_results_table += '\n' + s
        sys.stdout.write(s)
        sys.stdout.flush()
        test_start = timeit.default_timer()

        # Capture stdout to a buffer object for the local function call
        saved_stdout = sys.stdout
        capture = StringIO.StringIO()
        sys.stdout = capture

        args = ''
        if override:
          args = ''
        else:
          args = self.arg_string

        eval('address(' + args + ')')

        test_end = timeit.default_timer()

        # confusing: if arg_string is populated it means we changed dofs/np so
        # we want to see the testing time, not just pass/fail
        if (args == ''):
          result = 'OK'
        else:
          result = str(round(test_end-test_start,3)) + 's'

      except AssertionError:
        self.all_passed = False
        result = 'FAILED'
      except ExodiffException:
        # A regular exception means that the program ran but produced different output
        self.all_passed = False
        result = 'FAILED (DIFF)'
    finally:
      sys.stdout = saved_stdout
      test_end = timeit.default_timer()
      output = capture.getvalue()

      # We can skip established tests with the "pass" keyword in our
      # python driver files in which case no output is produced.
      # In this case we want to notify the user that the test was actually
      # skipped not OK
      if output == '':
        result = 'skipped'
      else:
        self.num_tests += 1

      self.processOutput(test, result, capture.getvalue())

  # override in sub classes to process the output of each test
  def processOutput(self, test, result, output):
    if self.xls_writer:
      parser = PerfLogParser()
      parser.parse(output)
      parser.writeExcel(self.xls_writer, test)

    # print the result of this test in table form
    self.results_table[test] = result
    if result == 'OK':
      self.num_passed += 1
    cnt = 65 - len(test + result)
    s = '.'*cnt + ' ' + result
    self.text_results_table += s
    print self.colorify(s)

    # print the output if verbose option is on or the test failed
    if self.options.verbose or result.find('FAILED') != -1:
      print '*'*100 + '\n' + '*'*41 + '  FAILED OUTPUT  ' + '*'*42 + '\n' + '*'*100 + '\n' + output
      #print s

  # return '' if all tests passed, or a message if some failed. Override if you
  # want more fail criteria
  def getFailMessage(self):
    if self.all_passed:
      return ''
    return 'FAILED '

  # override this function if you need to do stuff after the tests are run
  def postRun(self):
    if self.xls_writer:
      self.xls_writer.close()

    # if there was output before this the full table will be obscured, so
    # print it in it's entirety here at the bottom
    if self.options.verbose or not self.all_passed:
      print '\n\nFull Result Table:\n' + '-'*70
      print self.colorify(self.text_results_table)

    print '-'*70
    print 'Ran ' + str(self.num_tests) + ' tests in ' + str(round(self.testing_time)) + 's (' + str(self.num_passed) + '/' + str(self.num_tests) + ' passed)\n'

  # deprecated because it violates the coding standard's naming scheme
  def run_tests_and_exit(self, check_icestorm=True):
    self.runTestsAndExit(check_icestorm)

  def getOptions(self, argv):
    # Callback function
    arg_vector = []
    def buildArgVector(option, opt_str, value, parser):
      arg_vector.append(option.dest + '=' +  str(value))

    parser = OptionParser()
    parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="show more output [default=FALSE]")
    parser.add_option("-x", "--xls", action="store", dest="xlsFile", metavar="FILE", help="write excel format performance data to FILE")
    parser.add_option("-d", "--dofs", action="callback", callback=buildArgVector, type="int", dest="dofs", help="refine each example to meet the minimum requested DOFS")
    parser.add_option("-n", "--np", action="callback", callback=buildArgVector, type="int", dest="np", help="specify the number of MPI processes launched")
    parser.add_option("--helios-only-after", action="store_true", dest="heliosOnly", help="The options after this option are only applied if hostname == helios")
    parser.add_option("--opt", action="store_const", dest="method", const="opt", help="test the app_name-opt binary")
    parser.add_option("--dbg", action="store_const", dest="method", const="dbg", help="test the app_name-dbg binary")
    parser.add_option("--dev", action="store_const", dest="method", const="dev", help="test the app_name-dev binary")
    parser.add_option("-c", "--colored", action="store_true", dest="colored", default=False, help="Show colored output")
    parser.add_option("--n_threads", type="int", dest="n_threads", action="callback", callback=buildArgVector, help="specify the number of threads to be used")
    self.addOptions(parser)

    (options, args) = parser.parse_args(argv[1:])
    # Return the 'options' and leftover args returned from parse_args and
    # also the arg_string made from joining the arguments in the arg_vector
    return (options, args, ','.join(arg_vector))

  # override this method to add custom options to the parser
  def addOptions(self, parser):
    pass

  def colorify(self, str):
    if self.options.colored:
      str = str.replace('OK', BOLD+GREEN+'OK'+RESET)
      str = str.replace('skipped', BOLD+'skipped'+RESET)
      str = str.replace('FAILED (DIFF)', BOLD+YELLOW+'FAILED (DIFF)'+RESET)
      str = str.replace('FAILED', BOLD+RED+'FAILED'+RESET)

    return str

# ANSI color codes for colored terminal output
RESET  = '\033[0m'
BOLD   = '\033[1m'
RED    = '\033[31m'
GREEN  = '\033[32m'
YELLOW = '\033[33m'
<|endoftext|>


<commit_before>##############################################################################
#
#    Copyright (C) 2015 Comunitea Servicios Tecnológicos All Rights Reserved
#    $Omar Castiñeira Saavedra <omar@pcomunitea.com>$
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published
#    by the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from odoo import models, fields, api

class ResPartner(models.Model):
    _inherit = 'res.partner'

    codice_destinatario = fields.Char(required=True)

    electronic_invoice_subjected = fields.Boolean(default=True)

    @api.onchange('prospective')
    def onchange_prospective(self):
        if self.prospective:
            self.electronic_invoice_subjected=False
            self.codice_destinatario = 'XXXXXXX'
        elif self.country_id.code == 'IT':
            self.electronic_invoice_subjected = True
            self.codice_destinatario = '0000000'

<commit_msg>[FIX] custom_partner_it: Arreglado error con campo pec en clientes italianos<commit_after>##############################################################################
#
#    Copyright (C) 2015 Comunitea Servicios Tecnológicos All Rights Reserved
#    $Omar Castiñeira Saavedra <omar@pcomunitea.com>$
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published
#    by the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from odoo import models, fields, api

class ResPartner(models.Model):
    _inherit = 'res.partner'

    codice_destinatario = fields.Char(required=True)

    electronic_invoice_subjected = fields.Boolean(default=False)

    @api.onchange('prospective', 'country_id')
    def onchange_prospective(self):
        self.electronic_invoice_subjected = False
        self.codice_destinatario = 'XXXXXXX'
        if not self.prospective and self.country_id.code == 'IT':
            self.electronic_invoice_subjected = True
            self.codice_destinatario = '0000000'

<|endoftext|>


<commit_before>##############################################################################
#
#    Copyright (C) 2014 Pexego Sistemas Informáticos All Rights Reserved
#    $Jesús Ventosinos Mayor <jesus@pexego.es>$
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published
#    by the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from odoo import models, fields, api, _
from odoo.exceptions import except_orm,UserError
from odoo.tools.float_utils import float_is_zero, float_compare

class PurchaseOrder(models.Model):

    _inherit = 'purchase.order'

    picking_created = fields.Boolean('Picking created', compute='is_picking_created')

    date_planned = fields.Datetime(string='Scheduled Date', compute='', store=True, index=True)

    total_no_disc = fields.Float(compute='_get_total', store=True, readonly=True, string='Amount without disc.')

    total_disc = fields.Float(compute='_get_amount_discount', store=True, readonly=True, string='Disc. amount')

    container_ids = fields.Many2many('stock.container', string='Containers', compute='_get_containers')

    @api.multi
    def _get_containers(self):
        for order in self:
            res = []
            for line in order.order_line:
                for move in line.move_ids:
                    if move.state != 'cancel':
                        res.append(move.container_id.id)
            order.container_ids = res

    @api.multi
    @api.depends('order_line.price_subtotal')
    def _get_total(self):
        for order in self:
            for line in order.order_line:
                order.total_no_disc += order.currency_id.round(line.product_qty * line.price_unit)

    @api.multi
    @api.depends('order_line.price_subtotal')
    def _get_amount_discount(self):
        for order in self:
            for line in order.order_line:
                order.total_disc += order.currency_id.round((line.product_qty * line.price_unit)) - line.price_subtotal

    @api.multi
    def test_moves_done(self):
        '''PO is done at the delivery side if all the incoming shipments
           are done'''
        for purchase in self:
            for line in purchase.order_line:
                for move in line.move_ids:
                    if move.state != 'done':
                        return False
        return True

    @api.multi
    def is_picking_created(self):
        for order in self:
            order.picking_created = order.picking_ids and True or False

    @api.multi
    def _create_picking(self):
        """
            Se sobreescribe la función para que no se cree el picking.
        """
        if self.env.context.get('bypass_override'):
            return super()._create_picking()
        for order in self:
            if any([ptype in ['product', 'consu'] for ptype in order.order_line.mapped('product_id.type')]):
                void_pick = self.env['stock.picking']
                moves = order.order_line._create_stock_moves(void_pick)
                seq = 0
                for move in sorted(moves, key=lambda move: move.date_expected):
                    seq += 5
                    move.sequence = seq
        return True

    @api.multi
    def move_lines_create_picking(self):
        self.ensure_one()
        result = self.env['ir.actions.act_window'].for_xml_id('purchase_picking', 'action_receive_move')
        move_lines = self.env['stock.move'].search([('origin', 'like', self.name + '%'),
                                   ('picking_id', '=', False)])
        if len(move_lines) < 1:
            raise except_orm(_('Warning'), _('There is any move line without associated picking'))

        result['context'] = []
        if len(move_lines) > 1:
            result['domain'] = "[('id','in',[" + ','.join(map(str, move_lines.ids)) + "])]"
        else:
            result['domain'] = "[('id','='," + str(move_lines[0].id) + ")]"
        return result

    @api.multi
    def _add_supplier_to_product(self):
        """Update the partner info in the supplier list of the product if the
        supplier is registered for this product."""
        super()._add_supplier_to_product()
        partner = self.partner_id if not self.partner_id.parent_id else \
            self.partner_id.parent_id
        for line in self.order_line:
            if line.price_unit > 0:
                seller = line.product_id._select_seller(
                    partner_id=partner,
                    quantity=line.product_qty,
                    date=line.order_id.date_order and
                    line.order_id.date_order[:10],
                    uom_id=line.product_uom)
                if seller:
                    currency = (
                        partner.property_purchase_currency_id or
                        self.env.user.company_id.currency_id)
                    seller.write({
                        'price': line.price_unit,
                        'currency_id': self.currency_id.id,
                    })

    @api.multi
    def delete_purchase_lines(self):
        for order in self:
            for line in order.order_line:
                if line.select_delete:
                    line.unlink()

class PurchaseOrderLine(models.Model):

    _inherit = 'purchase.order.line'

    select_delete = fields.Boolean(' ')

    @api.multi
    def _prepare_stock_moves(self, picking):
        res = super(PurchaseOrderLine, self)._prepare_stock_moves(picking)

        for move_dict in res:
            move_dict.pop('picking_id', None)
            move_dict.pop('product_uos_qty', None)
            move_dict.pop('product_uos', None)
            move_dict['partner_id'] = self.order_id.partner_id.id
            if self.order_id.partner_ref:
                move_dict['origin'] += ":" + self.order_id.partner_ref

        return res

    @api.multi
    def write(self, vals):
        res = super(PurchaseOrderLine, self).write(vals)
        for line in self:
            if line.move_ids and vals.get('date_planned', False):
                for move in line.move_ids:
                    if move.state not in ['cancel', u'done'] and \
                            not move.container_id:
                        move.date_expected = vals['date_planned']
        return res

    def create(self, vals):
        context = self._context
        if self._context.get('default_state', '') == 'reserve':
            context = dict(self._context)
            context.pop('default_state', False)
        return super(PurchaseOrderLine, self.with_context(context)).create(vals)
<commit_msg>[FIX]purchase_picking: quitamos el estado del contexto<commit_after>##############################################################################
#
#    Copyright (C) 2014 Pexego Sistemas Informáticos All Rights Reserved
#    $Jesús Ventosinos Mayor <jesus@pexego.es>$
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published
#    by the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from odoo import models, fields, api, _
from odoo.exceptions import except_orm,UserError
from odoo.tools.float_utils import float_is_zero, float_compare

class PurchaseOrder(models.Model):

    _inherit = 'purchase.order'

    picking_created = fields.Boolean('Picking created', compute='is_picking_created')

    date_planned = fields.Datetime(string='Scheduled Date', compute='', store=True, index=True)

    total_no_disc = fields.Float(compute='_get_total', store=True, readonly=True, string='Amount without disc.')

    total_disc = fields.Float(compute='_get_amount_discount', store=True, readonly=True, string='Disc. amount')

    container_ids = fields.Many2many('stock.container', string='Containers', compute='_get_containers')

    @api.multi
    def _get_containers(self):
        for order in self:
            res = []
            for line in order.order_line:
                for move in line.move_ids:
                    if move.state != 'cancel':
                        res.append(move.container_id.id)
            order.container_ids = res

    @api.multi
    @api.depends('order_line.price_subtotal')
    def _get_total(self):
        for order in self:
            for line in order.order_line:
                order.total_no_disc += order.currency_id.round(line.product_qty * line.price_unit)

    @api.multi
    @api.depends('order_line.price_subtotal')
    def _get_amount_discount(self):
        for order in self:
            for line in order.order_line:
                order.total_disc += order.currency_id.round((line.product_qty * line.price_unit)) - line.price_subtotal

    @api.multi
    def test_moves_done(self):
        '''PO is done at the delivery side if all the incoming shipments
           are done'''
        for purchase in self:
            for line in purchase.order_line:
                for move in line.move_ids:
                    if move.state != 'done':
                        return False
        return True

    @api.multi
    def is_picking_created(self):
        for order in self:
            order.picking_created = order.picking_ids and True or False

    @api.multi
    def _create_picking(self):
        """
            Se sobreescribe la función para que no se cree el picking.
        """
        if self.env.context.get('bypass_override'):
            return super()._create_picking()
        for order in self:
            if any([ptype in ['product', 'consu'] for ptype in order.order_line.mapped('product_id.type')]):
                void_pick = self.env['stock.picking']
                moves = order.order_line._create_stock_moves(void_pick)
                seq = 0
                for move in sorted(moves, key=lambda move: move.date_expected):
                    seq += 5
                    move.sequence = seq
        return True

    @api.multi
    def move_lines_create_picking(self):
        self.ensure_one()
        result = self.env['ir.actions.act_window'].for_xml_id('purchase_picking', 'action_receive_move')
        move_lines = self.env['stock.move'].search([('origin', 'like', self.name + '%'),
                                   ('picking_id', '=', False)])
        if len(move_lines) < 1:
            raise except_orm(_('Warning'), _('There is any move line without associated picking'))

        result['context'] = []
        if len(move_lines) > 1:
            result['domain'] = "[('id','in',[" + ','.join(map(str, move_lines.ids)) + "])]"
        else:
            result['domain'] = "[('id','='," + str(move_lines[0].id) + ")]"
        return result

    @api.multi
    def _add_supplier_to_product(self):
        """Update the partner info in the supplier list of the product if the
        supplier is registered for this product."""
        super()._add_supplier_to_product()
        partner = self.partner_id if not self.partner_id.parent_id else \
            self.partner_id.parent_id
        for line in self.order_line:
            if line.price_unit > 0:
                seller = line.product_id._select_seller(
                    partner_id=partner,
                    quantity=line.product_qty,
                    date=line.order_id.date_order and
                    line.order_id.date_order[:10],
                    uom_id=line.product_uom)
                if seller:
                    currency = (
                        partner.property_purchase_currency_id or
                        self.env.user.company_id.currency_id)
                    seller.write({
                        'price': line.price_unit,
                        'currency_id': self.currency_id.id,
                    })

    @api.multi
    def delete_purchase_lines(self):
        for order in self:
            for line in order.order_line:
                if line.select_delete:
                    line.unlink()

    @api.model
    def create(self, vals):
        context = self._context
        if self._context.get('default_state', '') == 'reserve':
            context = dict(self._context)
            context.pop('default_state', False)
        return super(PurchaseOrder, self.with_context(context)).create(vals)

class PurchaseOrderLine(models.Model):

    _inherit = 'purchase.order.line'

    select_delete = fields.Boolean(' ')

    @api.multi
    def _prepare_stock_moves(self, picking):
        res = super(PurchaseOrderLine, self)._prepare_stock_moves(picking)

        for move_dict in res:
            move_dict.pop('picking_id', None)
            move_dict.pop('product_uos_qty', None)
            move_dict.pop('product_uos', None)
            move_dict['partner_id'] = self.order_id.partner_id.id
            if self.order_id.partner_ref:
                move_dict['origin'] += ":" + self.order_id.partner_ref

        return res

    @api.multi
    def write(self, vals):
        res = super(PurchaseOrderLine, self).write(vals)
        for line in self:
            if line.move_ids and vals.get('date_planned', False):
                for move in line.move_ids:
                    if move.state not in ['cancel', u'done'] and \
                            not move.container_id:
                        move.date_expected = vals['date_planned']
        return res

    @api.model
    def create(self, vals):
        context = self._context
        if self._context.get('default_state', '') == 'reserve':
            context = dict(self._context)
            context.pop('default_state', False)
        return super(PurchaseOrderLine, self.with_context(context)).create(vals)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

from __future__ import absolute_import
from __future__ import division, print_function, unicode_literals

import math

try:
    import numpy
except ImportError:
    numpy = None

from ._summarizer import AbstractSummarizer

class TextRankSummarizer(AbstractSummarizer):
    """An implementation of TextRank algorithm for summarization.

    Source: https://web.eecs.umich.edu/~mihalcea/papers/mihalcea.emnlp04.pdf
    """
    epsilon = 1e-4
    damping = 0.85
    # small number to prevent zero-division error, see https://github.com/miso-belica/sumy/issues/112
    _delta = 1e-7
    _stop_words = frozenset()

    @property
    def stop_words(self):
        return self._stop_words

    @stop_words.setter
    def stop_words(self, words):
        self._stop_words = frozenset(map(self.normalize_word, words))

    def __call__(self, document, sentences_count):
        self._ensure_dependencies_installed()
        if not document.sentences:
            return ()

        ratings = self.rate_sentences(document)
        return self._get_best_sentences(document.sentences, sentences_count, ratings)

    @staticmethod
    def _ensure_dependencies_installed():
        if numpy is None:
            raise ValueError("LexRank summarizer requires NumPy. Please, install it by command 'pip install numpy'.")

    def rate_sentences(self, document):
        matrix = self._create_matrix(document)
        ranks = self.power_method(matrix, self.epsilon)
        return {sent: rank for sent, rank in zip(document.sentences, ranks)}

    def _create_matrix(self, document):
        """Create a stochastic matrix for TextRank.

        Element at row i and column j of the matrix corresponds to the similarity of sentence i
        and j, where the similarity is computed as the number of common words between them, divided
        by their sum of logarithm of their lengths. After such matrix is created, it is turned into
        a stochastic matrix by normalizing over columns i.e. making the columns sum to one. TextRank
        uses PageRank algorithm with damping, so a damping factor is incorporated as explained in
        TextRank's paper. The resulting matrix is a stochastic matrix ready for power method.
        """
        sentences_as_words = [self._to_words_set(sent) for sent in document.sentences]
        sentences_count = len(sentences_as_words)
        weights = numpy.zeros((sentences_count, sentences_count))

        for i, words_i in enumerate(sentences_as_words):
            for j, words_j in enumerate(sentences_as_words):
                weights[i, j] = self._rate_sentences_edge(words_i, words_j)
        weights /= (weights.sum(axis=1)[:, numpy.newaxis]+self._delta) # delta added to prevent zero-division error
        #(see issue https://github.com/miso-belica/sumy/issues/112 )

        # In the original paper, the probability of randomly moving to any of the vertices
        # is NOT divided by the number of vertices. Here we do divide it so that the power
        # method works; without this division, the stationary probability blows up. This
        # should not affect the ranking of the vertices so we can use the resulting stationary
        # probability as is without any postprocessing.
        return numpy.full((sentences_count, sentences_count), (1.-self.damping) / sentences_count) \
            + self.damping * weights

    def _to_words_set(self, sentence):
        words = map(self.normalize_word, sentence.words)
        return [self.stem_word(w) for w in words if w not in self._stop_words]

    @staticmethod
    def _rate_sentences_edge(words1, words2):
        rank = sum(words2.count(w) for w in words1)
        if rank == 0:
            return 0.0

        assert len(words1) > 0 and len(words2) > 0
        norm = math.log(len(words1)) + math.log(len(words2))
        if numpy.isclose(norm, 0.):
            # This should only happen when words1 and words2 only have a single word.
            # Thus, rank can only be 0 or 1.
            assert rank in (0, 1)
            return float(rank)
        else:
            return rank / norm

    @staticmethod
    def power_method(matrix, epsilon):
        transposed_matrix = matrix.T
        sentences_count = len(matrix)
        p_vector = numpy.array([1.0 / sentences_count] * sentences_count)
        lambda_val = 1.0

        while lambda_val > epsilon:
            next_p = numpy.dot(transposed_matrix, p_vector)
            lambda_val = numpy.linalg.norm(numpy.subtract(next_p, p_vector))
            p_vector = next_p

        return p_vector
<commit_msg>TextRank: make clear the constant's purpose<commit_after># -*- coding: utf-8 -*-

from __future__ import absolute_import
from __future__ import division, print_function, unicode_literals

import math

try:
    import numpy
except ImportError:
    numpy = None

from ._summarizer import AbstractSummarizer

class TextRankSummarizer(AbstractSummarizer):
    """An implementation of TextRank algorithm for summarization.

    Source: https://web.eecs.umich.edu/~mihalcea/papers/mihalcea.emnlp04.pdf
    """
    epsilon = 1e-4
    damping = 0.85
    # small number to prevent zero-division error, see https://github.com/miso-belica/sumy/issues/112
    _ZERO_DIVISION_PREVENTION = 1e-7
    _stop_words = frozenset()

    @property
    def stop_words(self):
        return self._stop_words

    @stop_words.setter
    def stop_words(self, words):
        self._stop_words = frozenset(map(self.normalize_word, words))

    def __call__(self, document, sentences_count):
        self._ensure_dependencies_installed()
        if not document.sentences:
            return ()

        ratings = self.rate_sentences(document)
        return self._get_best_sentences(document.sentences, sentences_count, ratings)

    @staticmethod
    def _ensure_dependencies_installed():
        if numpy is None:
            raise ValueError("LexRank summarizer requires NumPy. Please, install it by command 'pip install numpy'.")

    def rate_sentences(self, document):
        matrix = self._create_matrix(document)
        ranks = self.power_method(matrix, self.epsilon)
        return {sent: rank for sent, rank in zip(document.sentences, ranks)}

    def _create_matrix(self, document):
        """Create a stochastic matrix for TextRank.

        Element at row i and column j of the matrix corresponds to the similarity of sentence i
        and j, where the similarity is computed as the number of common words between them, divided
        by their sum of logarithm of their lengths. After such matrix is created, it is turned into
        a stochastic matrix by normalizing over columns i.e. making the columns sum to one. TextRank
        uses PageRank algorithm with damping, so a damping factor is incorporated as explained in
        TextRank's paper. The resulting matrix is a stochastic matrix ready for power method.
        """
        sentences_as_words = [self._to_words_set(sent) for sent in document.sentences]
        sentences_count = len(sentences_as_words)
        weights = numpy.zeros((sentences_count, sentences_count))

        for i, words_i in enumerate(sentences_as_words):
            for j, words_j in enumerate(sentences_as_words):
                weights[i, j] = self._rate_sentences_edge(words_i, words_j)
        weights /= (weights.sum(axis=1)[:, numpy.newaxis] + self._ZERO_DIVISION_PREVENTION)

        # In the original paper, the probability of randomly moving to any of the vertices
        # is NOT divided by the number of vertices. Here we do divide it so that the power
        # method works; without this division, the stationary probability blows up. This
        # should not affect the ranking of the vertices so we can use the resulting stationary
        # probability as is without any postprocessing.
        return numpy.full((sentences_count, sentences_count), (1.-self.damping) / sentences_count) \
            + self.damping * weights

    def _to_words_set(self, sentence):
        words = map(self.normalize_word, sentence.words)
        return [self.stem_word(w) for w in words if w not in self._stop_words]

    @staticmethod
    def _rate_sentences_edge(words1, words2):
        rank = sum(words2.count(w) for w in words1)
        if rank == 0:
            return 0.0

        assert len(words1) > 0 and len(words2) > 0
        norm = math.log(len(words1)) + math.log(len(words2))
        if numpy.isclose(norm, 0.):
            # This should only happen when words1 and words2 only have a single word.
            # Thus, rank can only be 0 or 1.
            assert rank in (0, 1)
            return float(rank)
        else:
            return rank / norm

    @staticmethod
    def power_method(matrix, epsilon):
        transposed_matrix = matrix.T
        sentences_count = len(matrix)
        p_vector = numpy.array([1.0 / sentences_count] * sentences_count)
        lambda_val = 1.0

        while lambda_val > epsilon:
            next_p = numpy.dot(transposed_matrix, p_vector)
            lambda_val = numpy.linalg.norm(numpy.subtract(next_p, p_vector))
            p_vector = next_p

        return p_vector
<|endoftext|>


<commit_before>import tingbot
from tingbot import *

import json
import random
import time

import helpers
# setup code here
state = {}
state['lastquotetime'] = time.time()-100
intervaltext = ""

#load quotes
with open('duke_nukem_quotes.json') as json_data:
    quotes = json.load(json_data)
    #print(quotes)

#define intervallist
intervalposition = 2
intervals=[0,1,3,5,10,20,30,40,50,60]
previousintervalposition = 1

state['backgroundcolor'] = helpers.get_random_named_color()
state['foregroundcolor'] = helpers.get_random_named_color()

#define 4 menuitems
menuitems = ["pause","slower","faster","random"]

#functions
def print_quote(quote):
    state['backgroundcolor'] = helpers.get_random_named_color()
    state['foregroundcolor'] = helpers.get_random_named_color()

    while state['backgroundcolor'] == state['foregroundcolor']:
        state['foregroundcolor'] = helpers.get_random_named_color()

    screen.fill(color=state['backgroundcolor'])
    screen.text(quote,color=state['foregroundcolor'],font='GibonBold.otf',font_size=25)

    helpers.draw_menu(screen,menuitems, state['backgroundcolor'],state['foregroundcolor'])

#buttons
@left_button.press
def pause():
    global intervalposition,previousintervalposition
    if intervalposition != 0:
        previousintervalposition = intervalposition
        intervalposition = 0
    else:
        intervalposition = previousintervalposition

@midleft_button.press
def slower():
    global intervalposition
    if intervalposition < len(intervals)-1:
        intervalposition +=1
        if intervalposition >= len(intervals) : intervalposition=len(intervals)-1
        state['lastquotetime'] = time.time()-100
        previousintervalposition = intervalposition

@midright_button.press
def faster():
    global intervalposition
    if intervalposition>1:
        intervalposition -=1
        if intervalposition <= 1: intervalposition=1
        state['lastquotetime'] = time.time()-100
        previousintervalposition = intervalposition

@right_button.press
def random_quote():
    quote = random.choice(quotes)
    print_quote(quote['quote'])
    state['lastquotetime'] = time.time()

#loop
@every(seconds=1/100)
def main():
    global intervaltext

    if intervals[intervalposition] != 0:
        if time.time() - state['lastquotetime'] > intervals[intervalposition]:
            quote = random.choice(quotes)
            print_quote(quote['quote'])
            state['lastquotetime'] = time.time()
        intervaltext = ("interval = %i seconds"% intervals[intervalposition])
    else:
        intervaltext = "Pause"

    screen.rectangle(xy=(0,helpers.screen_height()), size=(helpers.screen_width(),25), color=state['backgroundcolor'],align='bottomleft')
    screen.text(intervaltext,color=state['foregroundcolor'],xy=(0,helpers.screen_height()), font_size=20,align='bottomleft')
    #time.sleep(intervals[intervalposition])

tingbot.run()<commit_msg>adding lis screen<commit_after>import tingbot
from tingbot import *

import json
import random
import time

import helpers
# setup code here
state = {}
state['lastquotetime'] = time.time()-100

screen_list = {
    0: 'show_quotes',
    1: 'list_quotes'
}
current_screen = 0
state['screen'] = screen_list[current_screen]

intervaltext = ""
#load quotes
with open('duke_nukem_quotes.json') as json_data:
    quotes = json.load(json_data)
    #print(quotes)

#define intervallist
intervalposition = 2
intervals=[0,1,3,5,10,20,30,40,50,60]
previousintervalposition = 1

state['backgroundcolor'] = helpers.get_random_named_color()
state['foregroundcolor'] = helpers.get_random_named_color()

#define 4 menuitems
menuitems = ["pause","slower","faster","random"]

#functions
def print_quote(quote):
    state['backgroundcolor'] = helpers.get_random_named_color()
    state['foregroundcolor'] = helpers.get_random_named_color()

    while state['backgroundcolor'] == state['foregroundcolor']:
        state['foregroundcolor'] = helpers.get_random_named_color()

    screen.fill(color=state['backgroundcolor'])
    screen.text(quote,color=state['foregroundcolor'],font='GibonBold.otf',font_size=25)
    print(quote)

    helpers.draw_menu(screen,menuitems, state['backgroundcolor'],state['foregroundcolor'])

#buttons
@left_button.press
def pause():
    global intervalposition,previousintervalposition
    if intervalposition != 0:
        previousintervalposition = intervalposition
        intervalposition = 0
    else:
        intervalposition = previousintervalposition

@left_button.press
def switch_screen():
    global current_screen
    if current_screen == 1: current_screen = 0
    else: current_screen = 1
    state['screen'] = screen_list[current_screen]

@midleft_button.press
def slower():
    global intervalposition
    if intervalposition < len(intervals)-1:
        intervalposition +=1
        if intervalposition >= len(intervals) : intervalposition=len(intervals)-1
        state['lastquotetime'] = time.time()-100
        previousintervalposition = intervalposition

@midright_button.press
def faster():
    global intervalposition
    if intervalposition>1:
        intervalposition -=1
        if intervalposition <= 1: intervalposition=1
        state['lastquotetime'] = time.time()-100
        previousintervalposition = intervalposition

@right_button.press
def random_quote():
    quote = random.choice(quotes)
    print_quote(quote['quote'])
    state['lastquotetime'] = time.time()

#loop
@every(seconds=1/100)
def main():
    global intervaltext

    if state['screen'] == 'show_quotes':

        if intervals[intervalposition] != 0:
            if time.time() - state['lastquotetime'] > intervals[intervalposition]:
                quote = random.choice(quotes)
                print_quote(quote['quote'])
                state['lastquotetime'] = time.time()
            intervaltext = ("interval = %i seconds"% intervals[intervalposition])
        else:
            intervaltext = "Pause"

        screen.rectangle(xy=(0,helpers.screen_height()), size=(helpers.screen_width(),25), color=state['backgroundcolor'],align='bottomleft')
        screen.text(intervaltext,color=state['foregroundcolor'],xy=(0,helpers.screen_height()), font_size=20,align='bottomleft')
        #time.sleep(intervals[intervalposition])

    if state['screen'] == 'list_quotes':
        #show list with all the quotes
        screen.fill(color=state['foregroundcolor'])

tingbot.run()<|endoftext|>


<commit_before># -*- coding: utf-8  -*-
#
# Copyright (C) 2009-2012 Ben Kurtovic <ben.kurtovic@verizon.net>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from collections import defaultdict
from re import sub, UNICODE

__all__ = ["MarkovChain", "MarkovChainIntersection"]

class MarkovChain(object):
    """Implements a basic ngram Markov chain of words."""
    START = -1
    END = -2
    degree = 3  # 2 for bigrams, 3 for trigrams, etc.

    def __init__(self, text):
        self.text = text
        self.chain = defaultdict(lambda: defaultdict(lambda: 0))
        words = sub("[^\w\s-]", "", text.lower(), flags=UNICODE).split()

        padding = self.degree - 1
        words = ([self.START] * padding) + words + ([self.END] * padding)
        for i in range(len(words) - self.degree + 1):
            last = i + self.degree - 1
            self.chain[words[i:last]][last] += 1

    def __repr__(self):
        """Return the canonical string representation of the MarkovChain."""
        return "MarkovChain(text={0!r})".format(self.text)

    def __str__(self):
        """Return a nice string representation of the MarkovChain."""
        return "<MarkovChain of size {0}>".format(self.size())

    def size(self):
        """Return the size of the Markov chain: the total number of nodes."""
        count = 0
        for node in self.chain.itervalues():
            for hits in node.itervalues():
                count += hits
        return count

class MarkovChainIntersection(MarkovChain):
    """Implements the intersection of two chains (i.e., their shared nodes)."""

    def __init__(self, mc1, mc2):
        self.chain = defaultdict(lambda: defaultdict(lambda: 0))
        self.mc1, self.mc2 = mc1, mc2
        c1 = mc1.chain
        c2 = mc2.chain

        for word, nodes1 in c1.iteritems():
            if word in c2:
                nodes2 = c2[word]
                for node, count1 in nodes1.iteritems():
                    if node in nodes2:
                        count2 = nodes2[node]
                        self.chain[word][node] = min(count1, count2)

    def __repr__(self):
        """Return the canonical string representation of the intersection."""
        res = "MarkovChainIntersection(mc1={0!r}, mc2={1!r})"
        return res.format(self.mc1, self.mc2)

    def __str__(self):
        """Return a nice string representation of the intersection."""
        res = "<MarkovChainIntersection of size {0} ({1} ^ {2})>"
        return res.format(self.size(), self.mc1, self.mc2)
<commit_msg>Whoops, got the slicing wrong.<commit_after># -*- coding: utf-8  -*-
#
# Copyright (C) 2009-2012 Ben Kurtovic <ben.kurtovic@verizon.net>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from collections import defaultdict
from re import sub, UNICODE

__all__ = ["MarkovChain", "MarkovChainIntersection"]

class MarkovChain(object):
    """Implements a basic ngram Markov chain of words."""
    START = -1
    END = -2
    degree = 3  # 2 for bigrams, 3 for trigrams, etc.

    def __init__(self, text):
        self.text = text
        self.chain = defaultdict(lambda: defaultdict(lambda: 0))
        words = sub("[^\w\s-]", "", text.lower(), flags=UNICODE).split()

        padding = self.degree - 1
        words = ([self.START] * padding) + words + ([self.END] * padding)
        for i in range(len(words) - self.degree + 1):
            last = i + self.degree - 1
            self.chain[words[i:last]][words[last]] += 1

    def __repr__(self):
        """Return the canonical string representation of the MarkovChain."""
        return "MarkovChain(text={0!r})".format(self.text)

    def __str__(self):
        """Return a nice string representation of the MarkovChain."""
        return "<MarkovChain of size {0}>".format(self.size())

    def size(self):
        """Return the size of the Markov chain: the total number of nodes."""
        count = 0
        for node in self.chain.itervalues():
            for hits in node.itervalues():
                count += hits
        return count

class MarkovChainIntersection(MarkovChain):
    """Implements the intersection of two chains (i.e., their shared nodes)."""

    def __init__(self, mc1, mc2):
        self.chain = defaultdict(lambda: defaultdict(lambda: 0))
        self.mc1, self.mc2 = mc1, mc2
        c1 = mc1.chain
        c2 = mc2.chain

        for word, nodes1 in c1.iteritems():
            if word in c2:
                nodes2 = c2[word]
                for node, count1 in nodes1.iteritems():
                    if node in nodes2:
                        count2 = nodes2[node]
                        self.chain[word][node] = min(count1, count2)

    def __repr__(self):
        """Return the canonical string representation of the intersection."""
        res = "MarkovChainIntersection(mc1={0!r}, mc2={1!r})"
        return res.format(self.mc1, self.mc2)

    def __str__(self):
        """Return a nice string representation of the intersection."""
        res = "<MarkovChainIntersection of size {0} ({1} ^ {2})>"
        return res.format(self.size(), self.mc1, self.mc2)
<|endoftext|>