<commit_before># LISP-like cons structures

def cons(a, b):
    return (a, b)

def is_cons(c):
    return isinstance(c, tuple) and len(c) == 2

def car(c):
    return c[0]

def cdr(c):
    return c[1]

# helper function for creating nested cons out of lists

def l(*lst):
    if len(lst) == 1:
        return cons(lst[0], ())
    if len(lst) == 2:
        return cons(*lst)
    else:
        return cons(lst[0], l(*lst[1:]))

# same as I did with minikanren
#
# (var c) becomes var(c)
# (var? x) becomes isinstance(x, var)
# (var=? x_1 x_2) becomes x_1 == x_2

class var:
    def __init__(self, index):
        self.index = index

    def __eq__(self, other):
        return isinstance(other, var) and self.index == other.index

    def __hash__(self):
        return hash(self.index)

    def __repr__(self):
        return "<%s>" % self.index

def is_var(v):
    return isinstance(v, var)

# this also stays the same as the python for minikanren, using a dictionary
# for substitutions

def walk(u, s):
    if isinstance(u, var):
        a = s.get(u)
        if a:
            return walk(a, s)
        else:
            return u
    else:
        return u

def ext_s(x, v, s):
    s = s.copy()
    s[x] = v
    return s

# again, unify stays the same as the python for minikanren

def unify(u, v, s):
    u = walk(u, s)
    v = walk(v, s)
    if is_var(u) and is_var(v) and u == v:
        return s
    elif is_var(u):
        return ext_s(u, v, s)
    elif is_var(v):
        return ext_s(v, u, s)
    elif is_cons(u) and is_cons(v):
        s = unify(car(u), car(v), s)
        t = unify(cdr(u), cdr(v), s)
        return t if t is not False else s
    elif u == v:
        return s
    else:
        return False

# for now we're going to treat mzero as () and (unit x) as (x, ())

def eq(u, v):
    def goal(state):
        s = unify(u, v, car(state))
        if s is not False:
            return ((s, cdr(state)), ())
        else:
            return ()

    return goal

def call_fresh(f):
    def goal(state):
        c = state[1]
        return f(var(c))((car(state), c + 1))

    return goal

EMPTY_STATE = cons({}, 0)

def mplus(stream1, stream2):
    if stream1 == ():
        return stream2
    elif callable(stream1):
        return lambda: mplus(stream2, stream1())
    else:
        return cons(car(stream1), mplus(cdr(stream1), stream2))

def bind(stream, goal):
    if stream == ():
        return ()
    elif callable(stream):
        return lambda: bind(stream(), goal)
    else:
        return mplus(goal(car(stream)), bind(cdr(stream), goal))

def disj(goal_1, goal_2):
    def goal(state):
        return mplus(goal_1(state), goal_2(state))
    return goal

def conj(goal_1, goal_2):
    def goal(state):
        return bind(goal_1(state), goal_2)
    return goal

if __name__ == "__main__":

    s1 = {var(0): 5, var(1): True}
    s2 = {var(1): 5, var(0): var(1)}

    assert walk(var(0), s1) == 5
    assert walk(var(0), s2) == 5

    assert unify(None, 1, {}) == False
    assert unify(None, var(0), {}) == {var(0): None}
    assert unify(None, [1, var(0)], {}) == False
    assert unify(1, None, {}) == False
    assert unify(1, 1, {}) == {}
    assert unify(1, 2, {}) == False
    assert unify(1, var(0), {}) == {var(0): 1}
    assert unify(1, [], {}) == False
    assert unify(var(0), 1, {}) == {var(0): 1}
    assert unify(var(0), var(1), {}) == {var(0): var(1)}
    assert unify(var(0), [], {}) == {var(0): []}
    assert unify(var(0), l(1, 2, 3), {}) == {var(0): l(1, 2, 3)}
    assert unify(l(1, 2, 3), l(1, 2, 3), {}) == {}
    assert unify(l(1, 2, 3), l(3, 2, 1), {}) == False
    assert unify(l(var(0), var(1)), l(1, 2), {}) == {var(0): 1, var(1): 2}
    assert unify(l(l(1, 2), l(3, 4)), l(l(1, 2), l(3, 4)), {}) == {}
    assert unify(l(l(var(0), 2), l(3, 4)), l(l(1, 2), l(3, 4)), {}) == {var(0): 1}

    assert unify((1, (2, (3, 4))), (1, (2, var(0))), {}) == {var(0): (3, 4)}

    assert unify({}, {}, {}) == {}

    assert eq(1,1)(EMPTY_STATE) == (EMPTY_STATE, ())
    assert eq(1,2)(EMPTY_STATE) == ()

    assert call_fresh(lambda q: eq(q, 5))(EMPTY_STATE) == (({var(0): 5}, 1), ())

    assert EMPTY_STATE == ({}, 0)

    assert conj(
        call_fresh(lambda a: eq(a, 7)),
        call_fresh(lambda b: disj(eq(b, 5), eq(b, 6)))
    )(EMPTY_STATE) == (({var(0): 7, var(1): 5}, 2), (({var(0): 7, var(1): 6}, 2), ()))
<commit_msg>more tests from original microKanren (with tweaks to make them work)<commit_after># LISP-like cons structures

def cons(a, b):
    return (a, b)

def is_cons(c):
    return isinstance(c, tuple) and len(c) == 2

def car(c):
    return c[0]

def cdr(c):
    return c[1]

# helper function for creating nested cons out of lists

def l(*lst):
    if len(lst) == 1:
        return cons(lst[0], ())
    else:
        return cons(lst[0], l(*lst[1:]))

# same as I did with minikanren
#
# (var c) becomes var(c)
# (var? x) becomes isinstance(x, var)
# (var=? x_1 x_2) becomes x_1 == x_2

class var:
    def __init__(self, index):
        self.index = index

    def __eq__(self, other):
        return isinstance(other, var) and self.index == other.index

    def __hash__(self):
        return hash(self.index)

    def __repr__(self):
        return "<%s>" % self.index

def is_var(v):
    return isinstance(v, var)

# this also stays the same as the python for minikanren, using a dictionary
# for substitutions

def walk(u, s):
    if isinstance(u, var):
        a = s.get(u)
        if a:
            return walk(a, s)
        else:
            return u
    else:
        return u

def ext_s(x, v, s):
    s = s.copy()
    s[x] = v
    return s

# again, unify stays the same as the python for minikanren

def unify(u, v, s):
    u = walk(u, s)
    v = walk(v, s)
    if is_var(u) and is_var(v) and u == v:
        return s
    elif is_var(u):
        return ext_s(u, v, s)
    elif is_var(v):
        return ext_s(v, u, s)
    elif is_cons(u) and is_cons(v):
        s = unify(car(u), car(v), s)
        t = unify(cdr(u), cdr(v), s)
        return t if t is not False else s
    elif u == v:
        return s
    else:
        return False

# for now we're going to treat mzero as () and (unit x) as (x, ())

def eq(u, v):
    def goal(state):
        s = unify(u, v, car(state))
        if s is not False:
            return ((s, cdr(state)), ())
        else:
            return ()

    return goal

def call_fresh(f):
    def goal(state):
        c = state[1]
        return f(var(c))((car(state), c + 1))

    return goal

EMPTY_STATE = cons({}, 0)

def mplus(stream1, stream2):
    if stream1 == ():
        return stream2
    elif callable(stream1):
        return lambda: mplus(stream2, stream1())
    else:
        return cons(car(stream1), mplus(cdr(stream1), stream2))

def bind(stream, goal):
    if stream == ():
        return ()
    elif callable(stream):
        return lambda: bind(stream(), goal)
    else:
        return mplus(goal(car(stream)), bind(cdr(stream), goal))

def disj(goal_1, goal_2):
    def goal(state):
        return mplus(goal_1(state), goal_2(state))
    return goal

def conj(goal_1, goal_2):
    def goal(state):
        return bind(goal_1(state), goal_2)
    return goal

if __name__ == "__main__":

    s1 = {var(0): 5, var(1): True}
    s2 = {var(1): 5, var(0): var(1)}

    assert walk(var(0), s1) == 5
    assert walk(var(0), s2) == 5

    assert unify(None, 1, {}) == False
    assert unify(None, var(0), {}) == {var(0): None}
    assert unify(None, [1, var(0)], {}) == False
    assert unify(1, None, {}) == False
    assert unify(1, 1, {}) == {}
    assert unify(1, 2, {}) == False
    assert unify(1, var(0), {}) == {var(0): 1}
    assert unify(1, [], {}) == False
    assert unify(var(0), 1, {}) == {var(0): 1}
    assert unify(var(0), var(1), {}) == {var(0): var(1)}
    assert unify(var(0), [], {}) == {var(0): []}
    assert unify(var(0), l(1, 2, 3), {}) == {var(0): l(1, 2, 3)}
    assert unify(l(1, 2, 3), l(1, 2, 3), {}) == {}
    assert unify(l(1, 2, 3), l(3, 2, 1), {}) == False
    assert unify(l(var(0), var(1)), l(1, 2), {}) == {var(0): 1, var(1): 2}
    assert unify(l(l(1, 2), l(3, 4)), l(l(1, 2), l(3, 4)), {}) == {}
    assert unify(l(l(var(0), 2), l(3, 4)), l(l(1, 2), l(3, 4)), {}) == {var(0): 1}

    assert unify((1, (2, (3, 4))), (1, (2, var(0))), {}) == {var(0): (3, 4)}

    assert unify({}, {}, {}) == {}

    assert eq(1,1)(EMPTY_STATE) == (EMPTY_STATE, ())
    assert eq(1,2)(EMPTY_STATE) == ()

    # take function

    def take(n, stream):
        if n == 0:
            return ()
        else:
            return cons(car(stream), take(n - 1, cdr(stream)))

    assert take(0, l(1, 2, 3)) == ()
    assert take(1, l(1, 2, 3)) == (1, ())
    assert take(2, l(1, 2, 3)) == (1, (2, ()))
    assert take(3, l(1, 2, 3)) == (1, (2, (3, ())))

    def take_all(stream):
        # for now, because we're not using true streams
        return stream

    # microKanren test programs

    a_and_b = conj(
        call_fresh(lambda a: eq(a, 7)),
        call_fresh(lambda b: disj(eq(b, 5), eq(b, 6)))
    )

    fives = lambda x: disj(
        eq(x, 5),
        lambda a_c: lambda: fives(x)(a_c)
    )

    appendo = lambda l, s, out: disj(
        conj(
            eq([], l),
            eq(s, out),
        ),
        call_fresh(
            lambda a: call_fresh(
                lambda d: conj(
                    eq((a, d), l),
                    call_fresh(
                        lambda res: conj(
                            eq((a, res), out),
                            lambda s_c: lambda: appendo(d, s, res)(s_c)
                        )
                    )
                )
            )
        )

    )

    # microKanren tests

    # second-set t1
    assert car(call_fresh(lambda q: eq(q, 5))(EMPTY_STATE)) == ({var(0): 5}, 1)

    # second-set t2
    assert cdr(call_fresh(lambda q: eq(q, 5))(EMPTY_STATE)) == ()

    # second-set t3
    assert car(a_and_b(EMPTY_STATE)) == ({var(0): 7, var(1): 5}, 2)

    # second-set t3, take
    assert take(1, a_and_b(EMPTY_STATE)) == (({var(0): 7, var(1): 5}, 2), ())

    # second-set t4
    assert car(cdr(a_and_b(EMPTY_STATE))) == ({var(0): 7, var(1): 6}, 2)

    # second-set t5
    assert cdr(cdr(a_and_b(EMPTY_STATE))) == ()

    # who cards
    assert take(1, call_fresh(lambda q: fives(q))(EMPTY_STATE)) == (({var(0): 5}, 1), ())

    # take 2 a-and-b stream
    assert take(2, a_and_b(EMPTY_STATE)) == (({var(0): 7, var(1): 5}, 2), (({var(0): 7, var(1): 6}, 2), ()))

    # take-all a-and-b stream
    assert take_all(a_and_b(EMPTY_STATE)) == (({var(0): 7, var(1): 5}, 2), (({var(0): 7, var(1): 6}, 2), ()))
<|endoftext|>


<commit_before>"""distutils.command.clean

Implements the Distutils 'clean' command."""

# contributed by Bastian Kleineidam <calvin@cs.uni-sb.de>, added 2000-03-18

__revision__ = "$Id$"

import os
from distutils.core import Command
from distutils.util import remove_tree

class clean (Command):

    description = "clean up output of 'build' command"
    user_options = [
        ('build-base=', 'b',
         "base build directory (default: 'build.build-base')"),
        ('build-lib=', None,
         "build directory for all modules (default: 'build.build-lib')"),
        ('build-temp=', 't',
         "temporary build directory (default: 'build.build-temp')"),
        ('bdist-base=', None,
         "temporary directory for built distributions"),
        ('all', 'a',
         "remove all build output, not just temporary by-products")
    ]

    def initialize_options(self):
        self.build_base = None
        self.build_lib = None
        self.build_temp = None
        self.bdist_base = None
        self.all = None

    def finalize_options(self):
        if self.build_lib and not os.path.exists (self.build_lib):
            self.warn ("'%s' does not exist -- can't clean it" %
                       self.build_lib)
        if self.build_temp and not os.path.exists (self.build_temp):
            self.warn ("'%s' does not exist -- can't clean it" %
                       self.build_temp)

        self.set_undefined_options('build',
                                   ('build_base', 'build_base'),
                                   ('build_lib', 'build_lib'),
                                   ('build_temp', 'build_temp'))
        self.set_undefined_options('bdist',
                                   ('bdist_base', 'bdist_base'))

    def run(self):
        # remove the build/temp.<plat> directory (unless it's already
        # gone)
        if os.path.exists (self.build_temp):
            remove_tree (self.build_temp, self.verbose, self.dry_run)

        if self.all:
            # remove the module build directory (unless already gone)
            if os.path.exists (self.build_lib):
                remove_tree (self.build_lib, self.verbose, self.dry_run)
            # remove the temporary directory used for creating built
            # distributions (default "build/bdist") -- eg. type of
            # built distribution will have its own subdirectory under
            # "build/bdist", but they'll be taken care of by
            # 'remove_tree()'.
            if os.path.exists (self.bdist_base):
                remove_tree (self.bdist_base, self.verbose, self.dry_run)

        # just for the heck of it, try to remove the base build directory:
        # we might have emptied it right now, but if not we don't care
        if not self.dry_run:
            try:
                os.rmdir (self.build_base)
                self.announce ("removing '%s'" % self.build_base)
            except OSError:
                pass

# class clean
<commit_msg>Moved warnings out of 'finalize_options()' into 'run()'. Added a warning for 'bdist_base' directory.<commit_after>"""distutils.command.clean

Implements the Distutils 'clean' command."""

# contributed by Bastian Kleineidam <calvin@cs.uni-sb.de>, added 2000-03-18

__revision__ = "$Id$"

import os
from distutils.core import Command
from distutils.util import remove_tree

class clean (Command):

    description = "clean up output of 'build' command"
    user_options = [
        ('build-base=', 'b',
         "base build directory (default: 'build.build-base')"),
        ('build-lib=', None,
         "build directory for all modules (default: 'build.build-lib')"),
        ('build-temp=', 't',
         "temporary build directory (default: 'build.build-temp')"),
        ('bdist-base=', None,
         "temporary directory for built distributions"),
        ('all', 'a',
         "remove all build output, not just temporary by-products")
    ]

    def initialize_options(self):
        self.build_base = None
        self.build_lib = None
        self.build_temp = None
        self.bdist_base = None
        self.all = None

    def finalize_options(self):
        self.set_undefined_options('build',
                                   ('build_base', 'build_base'),
                                   ('build_lib', 'build_lib'),
                                   ('build_temp', 'build_temp'))
        self.set_undefined_options('bdist',
                                   ('bdist_base', 'bdist_base'))

    def run(self):
        # remove the build/temp.<plat> directory (unless it's already
        # gone)
        if os.path.exists (self.build_temp):
            remove_tree (self.build_temp, self.verbose, self.dry_run)
        else:
            self.warn ("'%s' does not exist -- can't clean it" %
                       self.build_temp)

        if self.all:
            # remove the module build directory (unless already gone)
            if os.path.exists (self.build_lib):
                remove_tree (self.build_lib, self.verbose, self.dry_run)
            else:
                self.warn ("'%s' does not exist -- can't clean it" %
                           self.build_lib)

            # remove the temporary directory used for creating built
            # distributions (default "build/bdist") -- eg. type of
            # built distribution will have its own subdirectory under
            # "build/bdist", but they'll be taken care of by
            # 'remove_tree()'.
            if os.path.exists (self.bdist_base):
                remove_tree (self.bdist_base, self.verbose, self.dry_run)
            else:
                self.warn ("'%s' does not exist -- can't clean it" %
                           self.bdist_base)

        # just for the heck of it, try to remove the base build directory:
        # we might have emptied it right now, but if not we don't care
        if not self.dry_run:
            try:
                os.rmdir (self.build_base)
                self.announce ("removing '%s'" % self.build_base)
            except OSError:
                pass

# class clean
<|endoftext|>


<commit_before>import lxml.html, feedparser, peewee, json, datetime, bottle
import xml.etree.ElementTree as ET
from bottle import route, run, view, install
from peewee import *

class CustomJsonEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return str(obj.strftime("%Y-%m-%d %H:%M:%S"))
        return json.JSONEncoder.default(self, obj)

install(bottle.JSONPlugin(json_dumps=lambda s: json.dumps(s, cls=CustomJsonEncoder)))

db = peewee.SqliteDatabase('database.db')

class BaseModel(Model):
	class Meta:
		database = db

class Channel(BaseModel):
	title = CharField()
	updated = DateTimeField(default = datetime.datetime.now())
	url = CharField(unique = True)

class Item(BaseModel):
	title = CharField()
	description = CharField()
	url = CharField(unique = True)
	read = BooleanField(default = False)
	starred = BooleanField(default = False)
	channel = peewee.ForeignKeyField(Channel)

db.connect()
Channel.create_table(fail_silently = True)
Item.create_table(fail_silently = True)
db.close()

@route('/api/items/<url:re:.+>')
def items(url = ''):
	items = {'items' : [], 'url' : url}

	urls = []
	if url: urls.append(url)
	else:
		for channel in channels()['channels']:
			urls.append(channel['url'])

	for url in urls:
		feed = feedparser.parse(url)
		for item in feed.entries:
			items['items'].append({'title': item.title,
							       'description' : item.description,
							       'link' : item.link})
			#i = Item.create(title = item.title, description = item.description, url = item.link)
	return items

@route('/api/channels')
def channels():
	return {'channels' : [c for c in Channel.select().dicts()]}

@route("/channels")
@route("/channels/<url:re:.+>")
@view('index')
def index(url = ''):
	index = dict(items(url),**channels())
	return index

run(host='localhost', port=3000, reloader = True, debug = True)
<commit_msg>Refactor.<commit_after>import lxml.html, feedparser, peewee, json, datetime, bottle
import xml.etree.ElementTree as ET
from bottle import route, run, view, install
from peewee import *
from time import mktime

class CustomJsonEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return str(obj.strftime("%Y-%m-%d %H:%M:%S"))
        return json.JSONEncoder.default(self, obj)

install(bottle.JSONPlugin(json_dumps=lambda s: json.dumps(s, cls=CustomJsonEncoder)))

db = peewee.SqliteDatabase('database.db')

class BaseModel(Model):
	class Meta:
		database = db

class Channel(BaseModel):
	title = CharField()
	updated = DateTimeField(default = datetime.datetime(1900, 1, 1))
	url = CharField(unique = True)

	def update_feed(self):
			feed = feedparser.parse(self.url)
			feed_updated = datetime.datetime.fromtimestamp(mktime(feed.updated_parsed))
			if (feed_updated> self.updated):
				for item in feed.entries:
					try: Item.get(Item.url == item.link)
					except Item.DoesNotExist:
						Item.create(title = item.title, description = item.description, url = item.link, channel = self)

				self.updated = feed_updated
				self.save()

class Item(BaseModel):
	title = CharField()
	description = CharField()
	url = CharField(unique = True)
	read = BooleanField(default = False)
	starred = BooleanField(default = False)
	channel = peewee.ForeignKeyField(Channel)

# TODO: Do this in a before/after hook.
db.connect()
#db.drop_table(Channel, fail_silently=True)
#db.drop_table(Item, fail_silently=True)
#Channel.create_table(fail_silently = True)
#Item.create_table(fail_silently = True)
#Channel.create(title = 'Slashdot', url = 'http://rss.slashdot.org/Slashdot/slashdot')
db.close()

@route('/api/items/<url:re:.+>')
def items(url = ''):
	c = Channel.get(Channel.url == url)
	c.update_feed()
	return {'items' : [i for i in Item.select().where(Item.channel == c).dicts()], 'url' : url}

@route('/api/channels')
def channels():
	return {'channels' : [c for c in Channel.select().dicts()]}

@route("/channels")
@route("/channels/<url:re:.+>")
@view('index')
def index(url = ''):
	index = dict(items(url),**channels())
	return index

run(host='localhost', port=3000, reloader = True, debug = True)
<|endoftext|>


<commit_before># coding: UTF-8
"""
Copyright (c) 2008 Marian Tietz
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
"""

import gtk
import gtk.glade
import gobject
from time import localtime
import os
import codecs
import re

import config
import com
import gui_control as gui
from helper.searchToolbar import SearchBar

widgets = None
date_pattern = re.compile(r"(\d{4})-(\d{2})-(\d{2})")

def _rsplit_generator(text, substring, start=None):
	# TODO: test performance
	if start == None:
		next = len(text)
	else:
		next = start

	while True:
		stext = text[0:next]
		split = stext.rsplit(substring, 1)

		if next <= 0 or len(split) == 1:
			break

		next -= len(substring)+len(split[1])
		yield next, split[1]
	else:
		raise StopIteration

class HistorySearchBar(SearchBar):

	def set_search_term(self, val):
		if self.search_entry.get_text() != val:
			self.last = ()
		self.search_entry.set_text(val)
	search_term = property(lambda s: s.search_entry.get_text(),
		set_search_term)

	def __init__(self):
		SearchBar.__init__(self, None, autohide = False)

		# the last fileand offset (file,offset)
		self.last = ()

	def _get_date(self, text, index):
		""" return (year, month, day) if line
			has [yyyy-mm-dd] in it """

		for subindex, substring in _rsplit_generator(text, " ", index):
			split = substring.split("\n")

			if len(split) == 1:
				date = split[0]
			else:
				date = split[-1]

			match = date_pattern.match(date)
			if match:
				return match.groups()
			continue

		return None

	def search_button_clicked_cb(self, button):
		if not self.search_term or not self.textview or not self.calendar:
			return

		"""
		ueber files iterieren:
		  wenn textiterator besteht:
		    textiteratorsuche auf suchstring
			wenn kein ergebnis:
			  textiterator loeschen
			ansonsten:
			  speichern des textiterator
			  abbruch der iteration

		  zum letzt bekannten offset springen;

		  wenn suchstring in text gefunden:
		    datum herausfinden
			datum in view laden
			textiterator erstellen
			textiteratorsuche auf suchstring

		wenn gar kein ergebnis:
		  meldung
		"""
		success = False
		file_index = 0
		offset = 0L
		textiter = None

		if self.last:
			file, offset, textiter = self.last
			try:
				file_index = self.calendar.files.index(file)
			except ValueError:
				pass

		for file in self.calendar.files[file_index:]:

			if textiter:
				search_result = textiter.forward_search(
					self.search_term,
					gtk.TEXT_SEARCH_TEXT_ONLY)

				if not search_result:
					print "Not found with iter, continue."
					textiter = None

				else:
					print "Found by textiter."
					success = True
					self.last = (file, offset, search_result[1])

					self.textview.get_buffer().select_range(*search_result)
					self.textview.scroll_to_iter(search_result[0], 0.0)
					break

			fd = calendar_open_file(self.calendar, file)
			print "In file %s" % (file)

			if not fd:
				self.last = ()
				break

			fd.seek(offset)
			text = fd.read()

			print "offset for file = %d" % (offset)

			index = text.find(self.search_term)

			if index >= 0:
				print "Term found at %d." % (index)

				calendar_set_file(self.calendar, file)

				date = self._get_date(text, index)

				if not date:
					print "Could not find date for index %d on file %s" %(
						index, file)
					print "textdump: %s" % (text[index-45:index+len(self.search_term)])
					break

				year, month, day = date
				year, month, day = int(year), int(month), int(day)

				print "Found date %d-%d-%d" % (year, month, day)

				(d_start, d_end) = get_calendar_offsets(
					self.calendar, year, month-1, day)
				print "Calendar offsets: %s" % (self.calendar.offsets.keys())
				print "Request: %d-%d-%d" % (year, month, day)

				self.calendar.select_month(month-1, year)
				self.calendar.select_day(day)

				textiter = self.textview.get_buffer().get_start_iter()

				search_result = textiter.forward_search(
					self.search_term,
					gtk.TEXT_SEARCH_TEXT_ONLY)

				if not search_result:
					# This should definitively not happen..
					print "No search result with textiter for '%s'" % (
						self.search_term)
					break

				self.textview.get_buffer().select_range(*search_result)

				def scroll(tv,search_result):
					tv.scroll_to_iter(search_result, 0.0)
					return False

				gobject.idle_add(scroll, self.textview, search_result[0])

				self.last = (
					file,
					offset+d_end,
					search_result[1])
				success = True
				break

			# new file, new offset/textiter
			offset = 0L
			textiter = None
			print "Next file!"

		if not success:
			print "NO RESULTS"

def calendar_open_file(calendar, file):
	try:
		fd = codecs.open(os.path.join(calendar.log_dir, file), "r", "utf-8")
	except IOError,e:
		print "Failed to open file %s: %s" % (file, e)
		return None
	return fd

def calendar_set_file(calendar, file):
	fd = calendar_open_file(calendar, file)
	if fd == None:
		return

	calendar.offsets = calendar_parse_offsets(fd)
	calendar.fd = fd

def calendar_parse_offsets(fd):
	global date_pattern
	dateOffsets = {}
	lastDate = ""
	offset = 0
	startOffset = 0L

	for line in fd:
		date = line.split(" ")[0]

		if not date_pattern.match(date):
			offset += len(line)
			continue

		if not lastDate:
			lastDate = date

		if lastDate != date:
			# close lastDate
			print "NEW DATE: %s (%d - %d)" % (lastDate, startOffset, offset)

			dateOffsets[lastDate] = (startOffset, offset)

			lastDate = date
			startOffset = offset

		offset += len(line)

	dateOffsets[lastDate] = (startOffset, offset)

	return dateOffsets

def dialog_response_cb(dialog, responseID):
	"""
	destroy the dialog and close the fd on gtk.RESPONSE_CANCEL
	"""
	if responseID == gtk.RESPONSE_CANCEL:
		dialog.destroy()

def readLog(calendar):
	(year, month) = calendar.get_properties("year","month")
	try:
		i = calendar.files.index("%04d-%02d.txt" % (year, month+1))
	except ValueError:
		return

	name = calendar.files[i]

	calendar_set_file(calendar, name)

def fillCalendar(calendar):
	(year, month) = calendar.get_properties("year","month")
	mkey = "%02d-%02d-%%02d" % (year, month+1)

	calendar.clear_marks()
	for day in range(1,32):
		key = mkey % day

		if calendar.offsets.has_key(key):
			calendar.mark_day(day)

def calendar_realize_cb(calendar):
	"""
		initial fill.
	"""
	calendar_month_changed_cb(calendar)
	calendar_day_selected_cb(calendar)

def calendar_month_changed_cb(calendar):
	"""
		get all days which have a history and
		highlight them.
	"""
	if calendar.fd:
		calendar.fd.close()

		calendar.fd = None
		calendar.offsets = {}

	readLog(calendar)
	fillCalendar(calendar)

def get_calendar_offsets(calendar, year, month, day):
	key = "%02d-%02d-%02d" % (year, month+1, day)
	try:
		return calendar.offsets[key]
	except KeyError:
		return None, None
	return None, None

def calendar_day_selected_cb(calendar):
	"""
		get the history of calendar.day from maki.
	"""
	buffer = widgets.get_widget("historyView").get_buffer()

	(start, end) = get_calendar_offsets(calendar,
		*calendar.get_properties("year","month","day"))

	if None in (start, end):
		print "Missing start / end."
		buffer.set_text("")
		return

	calendar.fd.seek(start)
	# -1 eliminates trailing newline
	buffer.set_text(calendar.fd.read(end-start-1))

def run(tab):
	if tab.is_server():
		return

	log_dir = os.path.join(com.sushi.config_get("directories","logs"),
		tab.server, tab.name)
	try:
		file_list = os.listdir(log_dir)
	except OSError,e:
		print e
		return
	file_list.sort()

	calendar = widgets.get_widget("calendar")
	calendar.tab = tab
	calendar.files = file_list
	calendar.log_dir = log_dir
	calendar.fd = None
	calendar.offsets = {}

	ltime = localtime()

	calendar.select_month(ltime.tm_mon-1, ltime.tm_year)
	calendar.select_day(ltime.tm_mday)

	dialog = widgets.get_widget("historyDialog")

	dialog.set_title(tab.name)

	dialog.connect("response", dialog_response_cb)

	# non modal..
	dialog.show_all()

def custom_handler(glade, function_name, widget_name, *x):
	if widget_name == "searchBar":
		return HistorySearchBar()
	return None

def setup():
	global widgets

	if widgets and widgets.get_widget("calendar"):
		return

	path = config.get("gladefiles","dialogs") + "history.glade"

	gtk.glade.set_custom_handler(custom_handler)
	widgets = gtk.glade.XML(path)

	sigdic = {
		"calendar_month_changed_cb" : calendar_month_changed_cb,
		"calendar_day_selected_cb" : calendar_day_selected_cb
	}

	widgets.signal_autoconnect(sigdic)

	searchBar = widgets.get_widget("searchBar")
	searchBar.textview = widgets.get_widget("historyView")
	searchBar.calendar = widgets.get_widget("calendar")

	widgets.get_widget("calendar").connect("realize", calendar_realize_cb)

	gui.setFont(widgets.get_widget("historyView"), gui.get_font())

<commit_msg>Fixed history dialog<commit_after># coding: UTF-8
"""
Copyright (c) 2008 Marian Tietz
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
"""

import gtk
import gtk.glade
import gobject
from time import localtime
import os
import codecs
import re

import config
import com
import gui_control as gui
from helper.searchToolbar import SearchBar

widgets = None
date_pattern = re.compile(r"(\d{4})-(\d{2})-(\d{2})")

def _rsplit_generator(text, substring, start=None):
	# TODO: test performance
	if start == None:
		next = len(text)
	else:
		next = start

	while True:
		stext = text[0:next]
		split = stext.rsplit(substring, 1)

		if next <= 0 or len(split) == 1:
			break

		next -= len(substring)+len(split[1])
		yield next, split[1]
	else:
		raise StopIteration

class HistorySearchBar(SearchBar):

	def set_search_term(self, val):
		if self.search_entry.get_text() != val:
			self.last = ()
		self.search_entry.set_text(val)
	search_term = property(lambda s: s.search_entry.get_text(),
		set_search_term)

	def __init__(self):
		SearchBar.__init__(self, None, autohide = False)

		# the last fileand offset (file,offset)
		self.last = ()

	def _get_date(self, text, index):
		""" return (year, month, day) if line
			has [yyyy-mm-dd] in it """

		for subindex, substring in _rsplit_generator(text, " ", index):
			split = substring.split("\n")

			if len(split) == 1:
				date = split[0]
			else:
				date = split[-1]

			match = date_pattern.match(date)
			if match:
				return match.groups()
			continue

		return None

	def search_button_clicked_cb(self, button):
		if not self.search_term or not self.textview or not self.calendar:
			return

		"""
		ueber files iterieren:
		  wenn textiterator besteht:
		    textiteratorsuche auf suchstring
			wenn kein ergebnis:
			  textiterator loeschen
			ansonsten:
			  speichern des textiterator
			  abbruch der iteration

		  zum letzt bekannten offset springen;

		  wenn suchstring in text gefunden:
		    datum herausfinden
			datum in view laden
			textiterator erstellen
			textiteratorsuche auf suchstring

		wenn gar kein ergebnis:
		  meldung
		"""
		success = False
		file_index = 0
		offset = 0L
		textiter = None

		if self.last:
			file, offset, textiter = self.last
			try:
				file_index = self.calendar.files.index(file)
			except ValueError:
				pass

		for file in self.calendar.files[file_index:]:

			if textiter:
				search_result = textiter.forward_search(
					self.search_term,
					gtk.TEXT_SEARCH_TEXT_ONLY)

				if not search_result:
					print "Not found with iter, continue."
					textiter = None

				else:
					print "Found by textiter."
					success = True
					self.last = (file, offset, search_result[1])

					self.textview.get_buffer().select_range(*search_result)
					self.textview.scroll_to_iter(search_result[0], 0.0)
					break

			fd = calendar_open_file(self.calendar, file)
			print "In file %s" % (file)

			if not fd:
				self.last = ()
				break

			fd.seek(offset)
			text = fd.read()

			print "offset for file = %d" % (offset)

			index = text.find(self.search_term)

			if index >= 0:
				print "Term found at %d." % (index)

				calendar_set_file(self.calendar, file)

				date = self._get_date(text, index)

				if not date:
					print "Could not find date for index %d on file %s" %(
						index, file)
					print "textdump: %s" % (text[index-45:index+len(self.search_term)])
					break

				year, month, day = date
				year, month, day = int(year), int(month), int(day)

				print "Found date %d-%d-%d" % (year, month, day)

				(d_start, d_end) = get_calendar_offsets(
					self.calendar, year, month-1, day)
				print "Calendar offsets: %s" % (self.calendar.offsets.keys())
				print "Request: %d-%d-%d" % (year, month, day)

				self.calendar.select_month(month-1, year)
				self.calendar.select_day(day)

				textiter = self.textview.get_buffer().get_start_iter()

				search_result = textiter.forward_search(
					self.search_term,
					gtk.TEXT_SEARCH_TEXT_ONLY)

				if not search_result:
					# This should definitively not happen..
					print "No search result with textiter for '%s'" % (
						self.search_term)
					break

				self.textview.get_buffer().select_range(*search_result)

				def scroll(tv,search_result):
					tv.scroll_to_iter(search_result, 0.0)
					return False

				gobject.idle_add(scroll, self.textview, search_result[0])

				self.last = (
					file,
					offset+d_end,
					search_result[1])
				success = True
				break

			# new file, new offset/textiter
			offset = 0L
			textiter = None
			print "Next file!"

		if not success:
			print "NO RESULTS"
			self.last = ()

def calendar_open_file(calendar, file):
	try:
#		fd = codecs.open(os.path.join(calendar.log_dir, file), "r", "utf-8")
		fd = open(os.path.join(calendar.log_dir, file), "r")
	except IOError,e:
		print "Failed to open file %s: %s" % (file, e)
		return None
	return fd

def calendar_set_file(calendar, file):
	fd = calendar_open_file(calendar, file)
	if fd == None:
		return

	calendar.offsets = calendar_parse_offsets(fd)
	calendar.fd = fd

def calendar_parse_offsets(fd):
	global date_pattern
	dateOffsets = {}
	lastDate = ""
	offset = 0
	startOffset = 0L

	for line in fd:
		date = line.split(" ")[0]

		if not date_pattern.match(date):
			offset += len(line)
			continue

		if not lastDate:
			lastDate = date

		if lastDate != date:
			# close lastDate
			print "NEW DATE: %s (%d - %d)" % (lastDate, startOffset, offset)

			dateOffsets[lastDate] = (startOffset, offset)

			lastDate = date
			startOffset = offset

		offset += len(line)

	dateOffsets[lastDate] = (startOffset, offset)

	return dateOffsets

def dialog_response_cb(dialog, responseID):
	"""
	destroy the dialog and close the fd on gtk.RESPONSE_CANCEL
	"""
	if responseID == gtk.RESPONSE_CANCEL:
		dialog.destroy()

def readLog(calendar):
	(year, month) = calendar.get_properties("year","month")
	try:
		i = calendar.files.index("%04d-%02d.txt" % (year, month+1))
	except ValueError:
		return

	name = calendar.files[i]

	calendar_set_file(calendar, name)

def fillCalendar(calendar):
	(year, month) = calendar.get_properties("year","month")
	mkey = "%02d-%02d-%%02d" % (year, month+1)

	calendar.clear_marks()
	for day in range(1,32):
		key = mkey % day

		if calendar.offsets.has_key(key):
			calendar.mark_day(day)

def calendar_realize_cb(calendar):
	"""
		initial fill.
	"""
	calendar_month_changed_cb(calendar)
	calendar_day_selected_cb(calendar)

def calendar_month_changed_cb(calendar):
	"""
		get all days which have a history and
		highlight them.
	"""
	if calendar.fd:
		calendar.fd.close()

		calendar.fd = None
		calendar.offsets = {}

	readLog(calendar)
	fillCalendar(calendar)

def get_calendar_offsets(calendar, year, month, day):
	key = "%02d-%02d-%02d" % (year, month+1, day)
	try:
		return calendar.offsets[key]
	except KeyError:
		return None, None
	return None, None

def calendar_day_selected_cb(calendar):
	"""
		get the history of calendar.day from maki.
	"""
	buffer = widgets.get_widget("historyView").get_buffer()

	(start, end) = get_calendar_offsets(calendar,
		*calendar.get_properties("year","month","day"))

	if None in (start, end):
		print "Missing start / end."
		buffer.set_text("")
		return

	calendar.fd.seek(start)
	# -1 eliminates trailing newline
	buffer.set_text(calendar.fd.read(end-start-1))

def run(tab):
	if tab.is_server():
		return

	log_dir = os.path.join(com.sushi.config_get("directories","logs"),
		tab.server, tab.name)
	try:
		file_list = os.listdir(log_dir)
	except OSError,e:
		print e
		return
	file_list.sort()

	calendar = widgets.get_widget("calendar")
	calendar.tab = tab
	calendar.files = file_list
	calendar.log_dir = log_dir
	calendar.fd = None
	calendar.offsets = {}

	ltime = localtime()

	calendar.select_month(ltime.tm_mon-1, ltime.tm_year)
	calendar.select_day(ltime.tm_mday)

	dialog = widgets.get_widget("historyDialog")

	dialog.set_title(tab.name)

	dialog.connect("response", dialog_response_cb)

	# non modal..
	dialog.show_all()

def custom_handler(glade, function_name, widget_name, *x):
	if widget_name == "searchBar":
		return HistorySearchBar()
	return None

def setup():
	global widgets

	if widgets and widgets.get_widget("calendar"):
		return

	path = config.get("gladefiles","dialogs") + "history.glade"

	gtk.glade.set_custom_handler(custom_handler)
	widgets = gtk.glade.XML(path)

	sigdic = {
		"calendar_month_changed_cb" : calendar_month_changed_cb,
		"calendar_day_selected_cb" : calendar_day_selected_cb
	}

	widgets.signal_autoconnect(sigdic)

	searchBar = widgets.get_widget("searchBar")
	searchBar.textview = widgets.get_widget("historyView")
	searchBar.calendar = widgets.get_widget("calendar")

	widgets.get_widget("calendar").connect("realize", calendar_realize_cb)

	gui.setFont(widgets.get_widget("historyView"), gui.get_font())

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2013-Today OpenERP SA (<http://www.odoo.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/>.
#
##############################################################################

{
    "name": "GOODERP Warehouse Management",
    "version": "0.1",
    "author": 'ZhengXiang',
    "website": "http://www.osbzr.com",
    "category": "Generic Modules",
    "depends": ['core', 'goods', 'decimal_precision', 'web_sublist', 'web_float_limit', 'report_docx','finance'],
    "description": """
    """,
    "data": [
        'data/warehouse_data.xml',
        'security/groups.xml',
        'wizard/save_bom_view.xml',
        'wizard/stock_transceive_wizard_view.xml',
        'wizard/lot_track_wizard_view.xml',
        'wizard/non_active_report_wizard.xml',
        'view/assets_backend.xml',
        'view/warehouse_view.xml',
        'view/inventory_view.xml',
        'view/production_view.xml',
        'report/report_data.xml',
        'report/stock_balance_view.xml',
        'report/stock_transceive_view.xml',
        'report/lot_status_view.xml',
        'report/lot_track_view.xml',
        'action/warehouse_action.xml',
        'menu/warehouse_menu.xml',
        'data/sequence.xml',
        'security/ir.model.access.csv',
        'home_page_data.xml'
    ],
    'demo': [
        'data/warehouse_demo.xml',
     ],
    'installable': True,
    "active": False,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<commit_msg>home_page data数据放进data 目录里。<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2013-Today OpenERP SA (<http://www.odoo.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/>.
#
##############################################################################

{
    "name": "GOODERP Warehouse Management",
    "version": "0.1",
    "author": 'ZhengXiang',
    "website": "http://www.osbzr.com",
    "category": "Generic Modules",
    "depends": ['core', 'goods', 'decimal_precision', 'web_sublist', 'web_float_limit', 'report_docx','finance'],
    "description": """
    """,
    "data": [
        'data/warehouse_data.xml',
        'security/groups.xml',
        'wizard/save_bom_view.xml',
        'wizard/stock_transceive_wizard_view.xml',
        'wizard/lot_track_wizard_view.xml',
        'wizard/non_active_report_wizard.xml',
        'view/assets_backend.xml',
        'view/warehouse_view.xml',
        'view/inventory_view.xml',
        'view/production_view.xml',
        'report/report_data.xml',
        'report/stock_balance_view.xml',
        'report/stock_transceive_view.xml',
        'report/lot_status_view.xml',
        'report/lot_track_view.xml',
        'action/warehouse_action.xml',
        'menu/warehouse_menu.xml',
        'data/sequence.xml',
        'security/ir.model.access.csv',
        'data/home_page_data.xml'
    ],
    'demo': [
        'data/warehouse_demo.xml',
     ],
    'installable': True,
    "active": False,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import re
from itertools import chain

from dateutil import parser

from dateparser.timezone_parser import pop_tz_offset_from_string
from dateparser.utils import wrap_replacement_for_regex

from .dictionary import Dictionary, ALWAYS_KEEP_TOKENS
from .validation import LanguageValidator
from ..conf import settings

class Language(object):
    _dictionary = None
    _splitters = None
    _wordchars = None
    _cached = None

    def __init__(self, shortname, language_info):
        self.shortname = shortname
        self.info = language_info.copy()
        for simplification in self.info.get('simplifications', []):
            key, value = simplification.items()[0]
            if isinstance(value, int):
                simplification[key] = str(value)

        self._cached = self

    def validate_info(self, validator=None):
        if validator is None:
            validator = LanguageValidator

        return validator.validate_info(language_id=self.shortname, info=self._cached.info)

    def is_applicable(self, date_string, strip_timezone=False):
        tokens = self._cached._get_new_skip_tokens(settings.SKIP_TOKENS)

        if tokens:
            self._cached.info['skip'] += tokens
            self._cached = Language(self._cached.shortname, self._cached.info)

        if strip_timezone:
            date_string, timezone = pop_tz_offset_from_string(date_string, as_offset=False)

        date_string = self._cached._simplify(date_string)
        tokens = self._cached._split(date_string, keep_formatting=False)
        if self._cached._is_date_consists_of_digits_only(tokens):
            return True
        else:
            return self._cached._are_all_words_in_the_dictionary(tokens)

    def translate(self, date_string, keep_formatting=False):
        date_string = self._cached._simplify(date_string)
        words = self._cached._split(date_string, keep_formatting)

        dictionary = self._cached._get_dictionary()
        for i, word in enumerate(words):
            word = word.lower()
            if word in dictionary:
                words[i] = dictionary[word] or ''

        return self._cached._join(filter(bool, words), separator="" if keep_formatting else " ")

    def _get_new_skip_tokens(self, tokens):
        return [token for token in tokens if token not in self._cached.info.get('skip', [])]

    def _simplify(self, date_string):
        date_string = date_string.lower()
        for simplification in self._cached.info.get('simplifications', []):
            pattern, replacement = simplification.items()[0]
            if not self._cached.info.get('no_word_spacing', False):
                replacement = wrap_replacement_for_regex(replacement, pattern)
                pattern = ur'(\A|\d|_|\W)%s(\d|_|\W|\Z)' % pattern
            date_string = re.sub(pattern, replacement, date_string, flags=re.IGNORECASE | re.UNICODE).lower()
        return date_string

    def _is_date_consists_of_digits_only(self, tokens):
        for token in tokens:
            if not token.isdigit():
                return False
        else:
            return True

    def _are_all_words_in_the_dictionary(self, words):
        dictionary = self._cached._get_dictionary()
        for word in words:
            word = word.lower()
            if word.isdigit() or word in dictionary:
                continue
            else:
                return False
        else:
            return True

    def _split(self, date_string, keep_formatting):
        tokens = [date_string]
        tokens = self._cached._split_tokens_with_regex(tokens, "(\d+)")
        tokens = self._cached._split_tokens_by_known_words(tokens, keep_formatting)
        return tokens

    def _split_tokens_with_regex(self, tokens, regex):
        tokens = tokens[:]
        for i, token in enumerate(tokens):
            tokens[i] = re.split(regex, token)
        return filter(bool, chain(*tokens))

    def _split_tokens_by_known_words(self, tokens, keep_formatting):
        dictionary = self._cached._get_dictionary()
        for i, token in enumerate(tokens):
            tokens[i] = dictionary.split(token, keep_formatting)
        return list(chain(*tokens))

    def _join(self, tokens, separator=" "):
        if not tokens:
            return ""

        capturing_splitters = self._cached._get_splitters()['capturing']
        joined = tokens[0]
        for i in range(1, len(tokens)):
            left, right = tokens[i - 1], tokens[i]
            if left not in capturing_splitters and right not in capturing_splitters:
                joined += separator
            joined += right

        return joined

    def _get_dictionary(self):
        if self._cached._dictionary is None:
            self._cached._generate_dictionary()
        return self._cached._dictionary

    def _get_wordchars(self):
        if self._cached._wordchars is None:
            self._cached._set_wordchars()
        return self._cached._wordchars

    def _get_splitters(self):
        if self._cached._splitters is None:
            self._cached._set_splitters()
        return self._cached._splitters

    def _set_splitters(self):
        splitters = {
            'wordchars': set(),  # The ones that split string only if they are not surrounded by letters from both sides
            'capturing': set(),  # The ones that are not filtered out from tokens after split
        }
        splitters['capturing'] |= set(ALWAYS_KEEP_TOKENS)

        wordchars = self._cached._get_wordchars()
        skip = set(self._cached.info.get('skip', [])) | splitters['capturing']
        for token in skip:
            if not re.match('^\W+$', token, re.UNICODE):
                continue
            if token in wordchars:
                splitters['wordchars'].add(token)

        self._cached._splitters = splitters

    def _set_wordchars(self):
        wordchars = set()
        for word in self._cached._get_dictionary():
            if re.match('^[\W\d_]+$', word, re.UNICODE):
                continue
            for char in word:
                wordchars.add(char.lower())

        self._cached._wordchars = wordchars - {" "} | {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}

    def _generate_dictionary(self):
        self._cached._dictionary = Dictionary(self.info)

    def to_parserinfo(self, base_cls=parser.parserinfo):
        attributes = {
            'JUMP': self.info.get('skip', []),
            'PERTAIN': self.info.get('pertain', []),
            'WEEKDAYS': [self.info['monday'],
                         self.info['tuesday'],
                         self.info['wednesday'],
                         self.info['thursday'],
                         self.info['friday'],
                         self.info['saturday'],
                         self.info['sunday']],
            'MONTHS': [self.info['january'],
                       self.info['february'],
                       self.info['march'],
                       self.info['april'],
                       self.info['may'],
                       self.info['june'],
                       self.info['july'],
                       self.info['august'],
                       self.info['september'],
                       self.info['october'],
                       self.info['november'],
                       self.info['december']],
            'HMS': [self.info['hour'],
                    self.info['minute'],
                    self.info['second']],
        }
        name = '{language}ParserInfo'.format(language=self.info['name'])
        return type(name, bases=[base_cls], dict=attributes)
<commit_msg>Revert "Moved logic to add new skip tokens to is_applicable method"<commit_after># -*- coding: utf-8 -*-
import re
from itertools import chain

from dateutil import parser

from dateparser.timezone_parser import pop_tz_offset_from_string
from dateparser.utils import wrap_replacement_for_regex

from .dictionary import Dictionary, ALWAYS_KEEP_TOKENS
from .validation import LanguageValidator
from ..conf import settings

class Language(object):
    _dictionary = None
    _splitters = None
    _wordchars = None
    _cached = None

    def __init__(self, shortname, language_info):
        self.shortname = shortname
        self.info = language_info.copy()
        for simplification in self.info.get('simplifications', []):
            key, value = simplification.items()[0]
            if isinstance(value, int):
                simplification[key] = str(value)

        self._cached = self

    def validate_info(self, validator=None):
        if validator is None:
            validator = LanguageValidator

        return validator.validate_info(language_id=self.shortname, info=self._cached.info)

    def is_applicable(self, date_string, strip_timezone=False):
        if strip_timezone:
            date_string, timezone = pop_tz_offset_from_string(date_string, as_offset=False)

        date_string = self._cached._simplify(date_string)
        tokens = self._cached._split(date_string, keep_formatting=False)
        if self._cached._is_date_consists_of_digits_only(tokens):
            return True
        else:
            return self._cached._are_all_words_in_the_dictionary(tokens)

    def translate(self, date_string, keep_formatting=False):
        tokens = self._cached._get_new_skip_tokens(settings.SKIP_TOKENS)

        if tokens:
            self._cached.info['skip'] += tokens
            self._cached = Language(self._language_object.shortname, self._language_object.info)

        date_string = self._cached._simplify(date_string)
        words = self._cached._split(date_string, keep_formatting)

        dictionary = self._cached._get_dictionary()
        for i, word in enumerate(words):
            word = word.lower()
            if word in dictionary:
                words[i] = dictionary[word] or ''

        return self._cached._join(filter(bool, words), separator="" if keep_formatting else " ")

    def _get_new_skip_tokens(self, tokens):
        return [token for token in tokens if token not in self._cached.info.get('skip', [])]

    def _simplify(self, date_string):
        date_string = date_string.lower()
        for simplification in self._cached.info.get('simplifications', []):
            pattern, replacement = simplification.items()[0]
            if not self._cached.info.get('no_word_spacing', False):
                replacement = wrap_replacement_for_regex(replacement, pattern)
                pattern = ur'(\A|\d|_|\W)%s(\d|_|\W|\Z)' % pattern
            date_string = re.sub(pattern, replacement, date_string, flags=re.IGNORECASE | re.UNICODE).lower()
        return date_string

    def _is_date_consists_of_digits_only(self, tokens):
        for token in tokens:
            if not token.isdigit():
                return False
        else:
            return True

    def _are_all_words_in_the_dictionary(self, words):
        dictionary = self._cached._get_dictionary()
        for word in words:
            word = word.lower()
            if word.isdigit() or word in dictionary:
                continue
            else:
                return False
        else:
            return True

    def _split(self, date_string, keep_formatting):
        tokens = [date_string]
        tokens = self._cached._split_tokens_with_regex(tokens, "(\d+)")
        tokens = self._cached._split_tokens_by_known_words(tokens, keep_formatting)
        return tokens

    def _split_tokens_with_regex(self, tokens, regex):
        tokens = tokens[:]
        for i, token in enumerate(tokens):
            tokens[i] = re.split(regex, token)
        return filter(bool, chain(*tokens))

    def _split_tokens_by_known_words(self, tokens, keep_formatting):
        dictionary = self._cached._get_dictionary()
        for i, token in enumerate(tokens):
            tokens[i] = dictionary.split(token, keep_formatting)
        return list(chain(*tokens))

    def _join(self, tokens, separator=" "):
        if not tokens:
            return ""

        capturing_splitters = self._cached._get_splitters()['capturing']
        joined = tokens[0]
        for i in range(1, len(tokens)):
            left, right = tokens[i - 1], tokens[i]
            if left not in capturing_splitters and right not in capturing_splitters:
                joined += separator
            joined += right

        return joined

    def _get_dictionary(self):
        if self._cached._dictionary is None:
            self._cached._generate_dictionary()
        return self._cached._dictionary

    def _get_wordchars(self):
        if self._cached._wordchars is None:
            self._cached._set_wordchars()
        return self._cached._wordchars

    def _get_splitters(self):
        if self._cached._splitters is None:
            self._cached._set_splitters()
        return self._cached._splitters

    def _set_splitters(self):
        splitters = {
            'wordchars': set(),  # The ones that split string only if they are not surrounded by letters from both sides
            'capturing': set(),  # The ones that are not filtered out from tokens after split
        }
        splitters['capturing'] |= set(ALWAYS_KEEP_TOKENS)

        wordchars = self._cached._get_wordchars()
        skip = set(self._cached.info.get('skip', [])) | splitters['capturing']
        for token in skip:
            if not re.match('^\W+$', token, re.UNICODE):
                continue
            if token in wordchars:
                splitters['wordchars'].add(token)

        self._cached._splitters = splitters

    def _set_wordchars(self):
        wordchars = set()
        for word in self._cached._get_dictionary():
            if re.match('^[\W\d_]+$', word, re.UNICODE):
                continue
            for char in word:
                wordchars.add(char.lower())

        self._cached._wordchars = wordchars - {" "} | {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}

    def _generate_dictionary(self):
        self._cached._dictionary = Dictionary(self.info)

    def to_parserinfo(self, base_cls=parser.parserinfo):
        attributes = {
            'JUMP': self.info.get('skip', []),
            'PERTAIN': self.info.get('pertain', []),
            'WEEKDAYS': [self.info['monday'],
                         self.info['tuesday'],
                         self.info['wednesday'],
                         self.info['thursday'],
                         self.info['friday'],
                         self.info['saturday'],
                         self.info['sunday']],
            'MONTHS': [self.info['january'],
                       self.info['february'],
                       self.info['march'],
                       self.info['april'],
                       self.info['may'],
                       self.info['june'],
                       self.info['july'],
                       self.info['august'],
                       self.info['september'],
                       self.info['october'],
                       self.info['november'],
                       self.info['december']],
            'HMS': [self.info['hour'],
                    self.info['minute'],
                    self.info['second']],
        }
        name = '{language}ParserInfo'.format(language=self.info['name'])
        return type(name, bases=[base_cls], dict=attributes)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Copyright (C) 2016 KMEE (http://www.kmee.com.br)
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

from datetime import datetime

from openerp import api, fields, models

MES_DO_ANO = [
    (1, u'Janeiro'),
    (2, u'Fevereiro'),
    (3, u'Março'),
    (4, u'Abril'),
    (5, u'Maio'),
    (6, u'Junho'),
    (7, u'Julho'),
    (8, u'Agosto'),
    (9, u'Setembro'),
    (10, u'Outubro'),
    (11, u'Novembro'),
    (12, u'Dezembro'),
    (13, u'13º Salário')
]

TIPO_DE_FOLHA = [
    ('normal', u'Folha normal'),
    ('adiantamento_13', u'13º Salário - Adiantamento'),
    ('decimo_terceiro', u'13º Salário'),
    ('provisao_ferias', u'Provisão de Férias'),
    ('provisao_decimo_terceiro', u'Provisão de Décimo Terceiro (13º)'),
]

class HrPayslipRun(models.Model):
    _inherit = "hr.payslip.run"
    _order = "ano desc,mes_do_ano desc,tipo_de_folha asc, company_id asc"
    _sql_constraints = [
        ('lote_unico',
         'unique(ano, mes_do_ano, tipo_de_folha, company_id)',
         'Este Lote de Holerite já existe!')
    ]

    mes_do_ano = fields.Selection(
        selection=MES_DO_ANO,
        string=u'Mês',
        required=True,
        default=datetime.now().month,
    )
    ano = fields.Integer(
        string=u'Ano',
        default=datetime.now().year,
    )
    tipo_de_folha = fields.Selection(
        selection=TIPO_DE_FOLHA,
        string=u'Tipo de folha',
        default='normal',
    )
    contract_id = fields.Many2many(
        comodel_name='hr.contract',
        string='Contratos',
    )
    contract_id_readonly = fields.Many2many(
        comodel_name='hr.contract',
        string='Contratos',
    )
    departamento_id = fields.Many2one(
        comodel_name='hr.department',
        string='Departamento',
    )
    company_id = fields.Many2one(
        comodel_name='res.company',
        string='Empresa',
        default=lambda self: self.env.user.company_id or '',
    )

    @api.onchange('tipo_de_folha')
    def fixa_decimo_terceiro(self):
        if self.tipo_de_folha == 'adiantamento_13' and self.mes_do_ano == 12:
            self.tipo_de_folha = 'decimo_terceiro'
            self.mes_do_ano = 13
        else:
            if self.tipo_de_folha == 'decimo_terceiro':
                self.mes_do_ano = 13
            elif self.mes_do_ano == 13:
                self.mes_do_ano = datetime.now().month

    @api.onchange('mes_do_ano', 'ano')
    def buscar_datas_periodo(self):
        if not self.mes_do_ano:
            self.mes_do_ano = datetime.now().month

        if self.tipo_de_folha == 'adiantamento_13' and self.mes_do_ano == 12:
            self.tipo_de_folha = 'decimo_terceiro'
            self.mes_do_ano = 13

        mes = self.mes_do_ano
        if mes > 12:
            mes = 12
            self.tipo_de_folha = 'decimo_terceiro'
        elif self.tipo_de_folha == 'decimo_terceiro':
            self.tipo_de_folha = 'normal'

        ultimo_dia_do_mes = str(
            self.env['resource.calendar'].get_ultimo_dia_mes(
                mes, self.ano))

        primeiro_dia_do_mes = str(
            datetime.strptime(str(mes) + '-' +
                              str(self.ano), '%m-%Y'))

        self.date_start = primeiro_dia_do_mes
        self.date_end = ultimo_dia_do_mes

    @api.multi
    def verificar_holerites_gerados(self):
        for lote in self:
            dominio_contratos = [
                    ('date_start', '<=', lote.date_end),
                    ('company_id', '=', lote.company_id.id),
                ]
            if lote.tipo_de_folha != 'normal':
                dominio_contratos += [
                    ('categoria', 'not in', ['721', '722']),
                ]
            contracts_id = self.env['hr.contract'].search(dominio_contratos)

            payslips = self.env['hr.payslip'].search([
                ('tipo_de_folha', '=', self.tipo_de_folha),
                ('date_from', '>=', self.date_start),
                ('date_to', '<=', self.date_end),
                ('contract_id', 'in', contracts_id.ids)
            ])

            contratos_com_holerites = []
            for payslip in payslips:
                if payslip.contract_id.id not in contratos_com_holerites:
                    contratos_com_holerites.append(payslip.contract_id.id)

            contratos_sem_holerite = [
                contrato.id for contrato in contracts_id
                if (contrato.id not in contratos_com_holerites)
                   and (contrato.date_start <= lote.date_end)
                   and ((contrato.date_end >= lote.date_start)
                   or (not contrato.date_end))]

            lote.write({
                'contract_id': [(6, 0, contratos_sem_holerite)],
                'contract_id_readonly': [(6, 0, contratos_sem_holerite)],
            })

    @api.multi
    def gerar_holerites(self):
        self.verificar_holerites_gerados()
        for contrato in self.contract_id:
            try:
                payslip_obj = self.env['hr.payslip']
                payslip = payslip_obj.create({
                    'contract_id': contrato.id,
                    'mes_do_ano': self.mes_do_ano,
                    'mes_do_ano2': self.mes_do_ano,
                    'ano': self.ano,
                    'employee_id': contrato.employee_id.id,
                    'tipo_de_folha': self.tipo_de_folha,
                    'payslip_run_id': self.id,
                })
                payslip._compute_set_dates()
                payslip.compute_sheet()
            except:
                payslip.unlink()
                continue
        self.verificar_holerites_gerados()

    @api.multi
    def close_payslip_run(self):
        for lote in self:
            for holerite in lote.slip_ids:
                holerite.hr_verify_sheet()
        super(HrPayslipRun, self).close_payslip_run()
<commit_msg>[ADD] Validacao de exclusao do lote de holerites<commit_after># -*- coding: utf-8 -*-
# Copyright (C) 2016 KMEE (http://www.kmee.com.br)
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

from datetime import datetime

from openerp import api, fields, models, _
from openerp.exceptions import Warning as UserError

MES_DO_ANO = [
    (1, u'Janeiro'),
    (2, u'Fevereiro'),
    (3, u'Março'),
    (4, u'Abril'),
    (5, u'Maio'),
    (6, u'Junho'),
    (7, u'Julho'),
    (8, u'Agosto'),
    (9, u'Setembro'),
    (10, u'Outubro'),
    (11, u'Novembro'),
    (12, u'Dezembro'),
    (13, u'13º Salário')
]

TIPO_DE_FOLHA = [
    ('normal', u'Folha normal'),
    ('adiantamento_13', u'13º Salário - Adiantamento'),
    ('decimo_terceiro', u'13º Salário'),
    ('provisao_ferias', u'Provisão de Férias'),
    ('provisao_decimo_terceiro', u'Provisão de Décimo Terceiro (13º)'),
]

class HrPayslipRun(models.Model):
    _inherit = "hr.payslip.run"
    _order = "ano desc,mes_do_ano desc,tipo_de_folha asc, company_id asc"
    _sql_constraints = [
        ('lote_unico',
         'unique(ano, mes_do_ano, tipo_de_folha, company_id)',
         'Este Lote de Holerite já existe!')
    ]

    mes_do_ano = fields.Selection(
        selection=MES_DO_ANO,
        string=u'Mês',
        required=True,
        default=datetime.now().month,
    )
    ano = fields.Integer(
        string=u'Ano',
        default=datetime.now().year,
    )
    tipo_de_folha = fields.Selection(
        selection=TIPO_DE_FOLHA,
        string=u'Tipo de folha',
        default='normal',
    )
    contract_id = fields.Many2many(
        comodel_name='hr.contract',
        string='Contratos',
    )
    contract_id_readonly = fields.Many2many(
        comodel_name='hr.contract',
        string='Contratos',
    )
    departamento_id = fields.Many2one(
        comodel_name='hr.department',
        string='Departamento',
    )
    company_id = fields.Many2one(
        comodel_name='res.company',
        string='Empresa',
        default=lambda self: self.env.user.company_id or '',
    )

    @api.onchange('tipo_de_folha')
    def fixa_decimo_terceiro(self):
        if self.tipo_de_folha == 'adiantamento_13' and self.mes_do_ano == 12:
            self.tipo_de_folha = 'decimo_terceiro'
            self.mes_do_ano = 13
        else:
            if self.tipo_de_folha == 'decimo_terceiro':
                self.mes_do_ano = 13
            elif self.mes_do_ano == 13:
                self.mes_do_ano = datetime.now().month

    @api.onchange('mes_do_ano', 'ano')
    def buscar_datas_periodo(self):
        if not self.mes_do_ano:
            self.mes_do_ano = datetime.now().month

        if self.tipo_de_folha == 'adiantamento_13' and self.mes_do_ano == 12:
            self.tipo_de_folha = 'decimo_terceiro'
            self.mes_do_ano = 13

        mes = self.mes_do_ano
        if mes > 12:
            mes = 12
            self.tipo_de_folha = 'decimo_terceiro'
        elif self.tipo_de_folha == 'decimo_terceiro':
            self.tipo_de_folha = 'normal'

        ultimo_dia_do_mes = str(
            self.env['resource.calendar'].get_ultimo_dia_mes(
                mes, self.ano))

        primeiro_dia_do_mes = str(
            datetime.strptime(str(mes) + '-' +
                              str(self.ano), '%m-%Y'))

        self.date_start = primeiro_dia_do_mes
        self.date_end = ultimo_dia_do_mes

    @api.multi
    def verificar_holerites_gerados(self):
        for lote in self:
            dominio_contratos = [
                    ('date_start', '<=', lote.date_end),
                    ('company_id', '=', lote.company_id.id),
                ]
            if lote.tipo_de_folha != 'normal':
                dominio_contratos += [
                    ('categoria', 'not in', ['721', '722']),
                ]
            contracts_id = self.env['hr.contract'].search(dominio_contratos)

            payslips = self.env['hr.payslip'].search([
                ('tipo_de_folha', '=', self.tipo_de_folha),
                ('date_from', '>=', self.date_start),
                ('date_to', '<=', self.date_end),
                ('contract_id', 'in', contracts_id.ids)
            ])

            contratos_com_holerites = []
            for payslip in payslips:
                if payslip.contract_id.id not in contratos_com_holerites:
                    contratos_com_holerites.append(payslip.contract_id.id)

            contratos_sem_holerite = [
                contrato.id for contrato in contracts_id
                if (contrato.id not in contratos_com_holerites)
                   and (contrato.date_start <= lote.date_end)
                   and ((contrato.date_end >= lote.date_start)
                   or (not contrato.date_end))]

            lote.write({
                'contract_id': [(6, 0, contratos_sem_holerite)],
                'contract_id_readonly': [(6, 0, contratos_sem_holerite)],
            })

    @api.multi
    def gerar_holerites(self):
        self.verificar_holerites_gerados()
        for contrato in self.contract_id:
            try:
                payslip_obj = self.env['hr.payslip']
                payslip = payslip_obj.create({
                    'contract_id': contrato.id,
                    'mes_do_ano': self.mes_do_ano,
                    'mes_do_ano2': self.mes_do_ano,
                    'ano': self.ano,
                    'employee_id': contrato.employee_id.id,
                    'tipo_de_folha': self.tipo_de_folha,
                    'payslip_run_id': self.id,
                })
                payslip._compute_set_dates()
                payslip.compute_sheet()
            except:
                payslip.unlink()
                continue
        self.verificar_holerites_gerados()

    @api.multi
    def close_payslip_run(self):
        for lote in self:
            for holerite in lote.slip_ids:
                holerite.hr_verify_sheet()
        super(HrPayslipRun, self).close_payslip_run()

    @api.multi
    def unlink(self):
        """
        Validacao para exclusao de lote de holerites
        Nao permitir excluir o lote se ao menos um holerite nao estiver no
        state draft.vali
        """
        for lote in self:
            if any(l != 'draft' for l in lote.slip_ids.mapped('state')):
                raise UserError(
                    _('Não é permitido deletar um lote que contem holerites '
                      'com state diferente de rascunho!')
                )
        return super(HrPayslipRun, self).unlink()
<|endoftext|>