<commit_before># -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals, with_statement

import logging
import os

from feedgenerator import Atom1Feed, Rss201rev2Feed, get_tag_uri

from jinja2 import Markup

import six

from pelican import signals
from pelican.paginator import Paginator
from pelican.utils import (get_relative_path, is_selected_for_writing,
                           path_to_url, sanitised_join, set_date_tzinfo)

if not six.PY3:
    from codecs import open

logger = logging.getLogger(__name__)

class Writer(object):

    def __init__(self, output_path, settings=None):
        self.output_path = output_path
        self.reminder = dict()
        self.settings = settings or {}
        self._written_files = set()
        self._overridden_files = set()

    def _create_new_feed(self, feed_type, feed_title, context):
        feed_class = Rss201rev2Feed if feed_type == 'rss' else Atom1Feed
        if feed_title:
            feed_title = context['SITENAME'] + ' - ' + feed_title
        else:
            feed_title = context['SITENAME']
        feed = feed_class(
            title=Markup(feed_title).striptags(),
            link=(self.site_url + '/'),
            feed_url=self.feed_url,
            description=context.get('SITESUBTITLE', ''))
        return feed

    def _add_item_to_the_feed(self, feed, item):

        title = Markup(item.title).striptags()
        link = '%s/%s' % (self.site_url, item.url)
        is_rss = isinstance(feed, Rss201rev2Feed)
        if not is_rss or self.settings.get('RSS_FEED_SUMMARY_ONLY'):
            description = item.summary
        else:
            description = item.get_content(self.site_url)
        feed.add_item(
            title=title,
            link=link,
            unique_id=get_tag_uri(link, item.date),
            description=description,
            content=item.get_content(self.site_url),
            categories=item.tags if hasattr(item, 'tags') else None,
            author_name=getattr(item, 'author', ''),
            pubdate=set_date_tzinfo(
                item.date, self.settings.get('TIMEZONE', None)),
            updateddate=set_date_tzinfo(
                item.modified, self.settings.get('TIMEZONE', None)
                ) if hasattr(item, 'modified') else None)

    def _open_w(self, filename, encoding, override=False):
        """Open a file to write some content to it.

        Exit if we have already written to that file, unless one (and no more
        than one) of the writes has the override parameter set to True.
        """
        if filename in self._overridden_files:
            if override:
                raise RuntimeError('File %s is set to be overridden twice'
                                   % filename)
            else:
                logger.info('Skipping %s', filename)
                filename = os.devnull
        elif filename in self._written_files:
            if override:
                logger.info('Overwriting %s', filename)
            else:
                raise RuntimeError('File %s is to be overwritten' % filename)
        if override:
            self._overridden_files.add(filename)
        self._written_files.add(filename)
        return open(filename, 'w', encoding=encoding)

    def write_feed(self, elements, context, path=None, feed_type='atom',
                   override_output=False, feed_title=None):
        """Generate a feed with the list of articles provided

        Return the feed. If no path or output_path is specified, just
        return the feed object.

        :param elements: the articles to put on the feed.
        :param context: the context to get the feed metadata.
        :param path: the path to output.
        :param feed_type: the feed type to use (atom or rss)
        :param override_output: boolean telling if we can override previous
            output with the same name (and if next files written with the same
            name should be skipped to keep that one)
        :param feed_title: the title of the feed.o
        """
        if not is_selected_for_writing(self.settings, path):
            return

        self.site_url = context.get(
            'SITEURL', path_to_url(get_relative_path(path)))

        self.feed_domain = context.get('FEED_DOMAIN')
        self.feed_url = '{}/{}'.format(self.feed_domain, path)

        feed = self._create_new_feed(feed_type, feed_title, context)

        max_items = len(elements)
        if self.settings['FEED_MAX_ITEMS']:
            max_items = min(self.settings['FEED_MAX_ITEMS'], max_items)
        for i in range(max_items):
            self._add_item_to_the_feed(feed, elements[i])

        signals.feed_generated.send(context, feed=feed)
        if path:
            complete_path = sanitised_join(self.output_path, path)

            try:
                os.makedirs(os.path.dirname(complete_path))
            except Exception:
                pass

            encoding = 'utf-8' if six.PY3 else None
            with self._open_w(complete_path, encoding, override_output) as fp:
                feed.write(fp, 'utf-8')
                logger.info('Writing %s', complete_path)

            signals.feed_written.send(
                complete_path, context=context, feed=feed)
        return feed

    def write_file(self, name, template, context, relative_urls=False,
                   paginated=None, override_output=False, **kwargs):
        """Render the template and write the file.

        :param name: name of the file to output
        :param template: template to use to generate the content
        :param context: dict to pass to the templates.
        :param relative_urls: use relative urls or absolutes ones
        :param paginated: dict of article list to paginate - must have the
            same length (same list in different orders)
        :param override_output: boolean telling if we can override previous
            output with the same name (and if next files written with the same
            name should be skipped to keep that one)
        :param **kwargs: additional variables to pass to the templates
        """

        if name is False or \
           name == "" or \
           not is_selected_for_writing(self.settings,
                                       os.path.join(self.output_path, name)):
            return
        elif not name:
            # other stuff, just return for now
            return

        def _write_file(template, localcontext, output_path, name, override):
            """Render the template write the file."""
            # set localsiteurl for context so that Contents can adjust links
            if localcontext['localsiteurl']:
                context['localsiteurl'] = localcontext['localsiteurl']
            output = template.render(localcontext)
            path = sanitised_join(output_path, name)

            try:
                os.makedirs(os.path.dirname(path))
            except Exception:
                pass

            with self._open_w(path, 'utf-8', override=override) as f:
                f.write(output)
            logger.info('Writing %s', path)

            # Send a signal to say we're writing a file with some specific
            # local context.
            signals.content_written.send(path, context=localcontext)

        def _get_localcontext(context, name, kwargs, relative_urls):
            localcontext = context.copy()
            localcontext['localsiteurl'] = localcontext.get(
                'localsiteurl', None)
            if relative_urls:
                relative_url = path_to_url(get_relative_path(name))
                localcontext['SITEURL'] = relative_url
                localcontext['localsiteurl'] = relative_url
            localcontext['output_file'] = name
            localcontext.update(kwargs)
            return localcontext

        # pagination
        if paginated:

            # pagination needed, init paginators
            paginators = {key: Paginator(name, val, self.settings)
                          for key, val in paginated.items()}

            # generated pages, and write
            for page_num in range(list(paginators.values())[0].num_pages):
                paginated_kwargs = kwargs.copy()
                for key in paginators.keys():
                    paginator = paginators[key]
                    previous_page = paginator.page(page_num) \
                        if page_num > 0 else None
                    page = paginator.page(page_num + 1)
                    next_page = paginator.page(page_num + 2) \
                        if page_num + 1 < paginator.num_pages else None
                    paginated_kwargs.update(
                        {'%s_paginator' % key: paginator,
                         '%s_page' % key: page,
                         '%s_previous_page' % key: previous_page,
                         '%s_next_page' % key: next_page})

                localcontext = _get_localcontext(
                    context, page.save_as, paginated_kwargs, relative_urls)
                _write_file(template, localcontext, self.output_path,
                            page.save_as, override_output)
        else:
            # no pagination
            localcontext = _get_localcontext(
                context, name, kwargs, relative_urls)
            _write_file(template, localcontext, self.output_path, name,
                        override_output)
<commit_msg>Make use of SITESUBTITLE setting also in Atom feeds.<commit_after># -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals, with_statement

import logging
import os

from feedgenerator import Atom1Feed, Rss201rev2Feed, get_tag_uri

from jinja2 import Markup

import six

from pelican import signals
from pelican.paginator import Paginator
from pelican.utils import (get_relative_path, is_selected_for_writing,
                           path_to_url, sanitised_join, set_date_tzinfo)

if not six.PY3:
    from codecs import open

logger = logging.getLogger(__name__)

class Writer(object):

    def __init__(self, output_path, settings=None):
        self.output_path = output_path
        self.reminder = dict()
        self.settings = settings or {}
        self._written_files = set()
        self._overridden_files = set()

    def _create_new_feed(self, feed_type, feed_title, context):
        feed_class = Rss201rev2Feed if feed_type == 'rss' else Atom1Feed
        if feed_title:
            feed_title = context['SITENAME'] + ' - ' + feed_title
        else:
            feed_title = context['SITENAME']
        feed = feed_class(
            title=Markup(feed_title).striptags(),
            link=(self.site_url + '/'),
            feed_url=self.feed_url,
            description=context.get('SITESUBTITLE', ''),
            subtitle=context.get('SITESUBTITLE', None))
        return feed

    def _add_item_to_the_feed(self, feed, item):

        title = Markup(item.title).striptags()
        link = '%s/%s' % (self.site_url, item.url)
        is_rss = isinstance(feed, Rss201rev2Feed)
        if not is_rss or self.settings.get('RSS_FEED_SUMMARY_ONLY'):
            description = item.summary
        else:
            description = item.get_content(self.site_url)
        feed.add_item(
            title=title,
            link=link,
            unique_id=get_tag_uri(link, item.date),
            description=description,
            content=item.get_content(self.site_url),
            categories=item.tags if hasattr(item, 'tags') else None,
            author_name=getattr(item, 'author', ''),
            pubdate=set_date_tzinfo(
                item.date, self.settings.get('TIMEZONE', None)),
            updateddate=set_date_tzinfo(
                item.modified, self.settings.get('TIMEZONE', None)
                ) if hasattr(item, 'modified') else None)

    def _open_w(self, filename, encoding, override=False):
        """Open a file to write some content to it.

        Exit if we have already written to that file, unless one (and no more
        than one) of the writes has the override parameter set to True.
        """
        if filename in self._overridden_files:
            if override:
                raise RuntimeError('File %s is set to be overridden twice'
                                   % filename)
            else:
                logger.info('Skipping %s', filename)
                filename = os.devnull
        elif filename in self._written_files:
            if override:
                logger.info('Overwriting %s', filename)
            else:
                raise RuntimeError('File %s is to be overwritten' % filename)
        if override:
            self._overridden_files.add(filename)
        self._written_files.add(filename)
        return open(filename, 'w', encoding=encoding)

    def write_feed(self, elements, context, path=None, feed_type='atom',
                   override_output=False, feed_title=None):
        """Generate a feed with the list of articles provided

        Return the feed. If no path or output_path is specified, just
        return the feed object.

        :param elements: the articles to put on the feed.
        :param context: the context to get the feed metadata.
        :param path: the path to output.
        :param feed_type: the feed type to use (atom or rss)
        :param override_output: boolean telling if we can override previous
            output with the same name (and if next files written with the same
            name should be skipped to keep that one)
        :param feed_title: the title of the feed.o
        """
        if not is_selected_for_writing(self.settings, path):
            return

        self.site_url = context.get(
            'SITEURL', path_to_url(get_relative_path(path)))

        self.feed_domain = context.get('FEED_DOMAIN')
        self.feed_url = '{}/{}'.format(self.feed_domain, path)

        feed = self._create_new_feed(feed_type, feed_title, context)

        max_items = len(elements)
        if self.settings['FEED_MAX_ITEMS']:
            max_items = min(self.settings['FEED_MAX_ITEMS'], max_items)
        for i in range(max_items):
            self._add_item_to_the_feed(feed, elements[i])

        signals.feed_generated.send(context, feed=feed)
        if path:
            complete_path = sanitised_join(self.output_path, path)

            try:
                os.makedirs(os.path.dirname(complete_path))
            except Exception:
                pass

            encoding = 'utf-8' if six.PY3 else None
            with self._open_w(complete_path, encoding, override_output) as fp:
                feed.write(fp, 'utf-8')
                logger.info('Writing %s', complete_path)

            signals.feed_written.send(
                complete_path, context=context, feed=feed)
        return feed

    def write_file(self, name, template, context, relative_urls=False,
                   paginated=None, override_output=False, **kwargs):
        """Render the template and write the file.

        :param name: name of the file to output
        :param template: template to use to generate the content
        :param context: dict to pass to the templates.
        :param relative_urls: use relative urls or absolutes ones
        :param paginated: dict of article list to paginate - must have the
            same length (same list in different orders)
        :param override_output: boolean telling if we can override previous
            output with the same name (and if next files written with the same
            name should be skipped to keep that one)
        :param **kwargs: additional variables to pass to the templates
        """

        if name is False or \
           name == "" or \
           not is_selected_for_writing(self.settings,
                                       os.path.join(self.output_path, name)):
            return
        elif not name:
            # other stuff, just return for now
            return

        def _write_file(template, localcontext, output_path, name, override):
            """Render the template write the file."""
            # set localsiteurl for context so that Contents can adjust links
            if localcontext['localsiteurl']:
                context['localsiteurl'] = localcontext['localsiteurl']
            output = template.render(localcontext)
            path = sanitised_join(output_path, name)

            try:
                os.makedirs(os.path.dirname(path))
            except Exception:
                pass

            with self._open_w(path, 'utf-8', override=override) as f:
                f.write(output)
            logger.info('Writing %s', path)

            # Send a signal to say we're writing a file with some specific
            # local context.
            signals.content_written.send(path, context=localcontext)

        def _get_localcontext(context, name, kwargs, relative_urls):
            localcontext = context.copy()
            localcontext['localsiteurl'] = localcontext.get(
                'localsiteurl', None)
            if relative_urls:
                relative_url = path_to_url(get_relative_path(name))
                localcontext['SITEURL'] = relative_url
                localcontext['localsiteurl'] = relative_url
            localcontext['output_file'] = name
            localcontext.update(kwargs)
            return localcontext

        # pagination
        if paginated:

            # pagination needed, init paginators
            paginators = {key: Paginator(name, val, self.settings)
                          for key, val in paginated.items()}

            # generated pages, and write
            for page_num in range(list(paginators.values())[0].num_pages):
                paginated_kwargs = kwargs.copy()
                for key in paginators.keys():
                    paginator = paginators[key]
                    previous_page = paginator.page(page_num) \
                        if page_num > 0 else None
                    page = paginator.page(page_num + 1)
                    next_page = paginator.page(page_num + 2) \
                        if page_num + 1 < paginator.num_pages else None
                    paginated_kwargs.update(
                        {'%s_paginator' % key: paginator,
                         '%s_page' % key: page,
                         '%s_previous_page' % key: previous_page,
                         '%s_next_page' % key: next_page})

                localcontext = _get_localcontext(
                    context, page.save_as, paginated_kwargs, relative_urls)
                _write_file(template, localcontext, self.output_path,
                            page.save_as, override_output)
        else:
            # no pagination
            localcontext = _get_localcontext(
                context, name, kwargs, relative_urls)
            _write_file(template, localcontext, self.output_path, name,
                        override_output)
<|endoftext|>


<commit_before>from kivy.clock import Clock

import time

#from defines import *

import random as rand_m

import pentai.base.human_player as h_m
import pentai.base.rules as r_m
import pentai.base.game as g_m
import pentai.ai.ai_genome as aig_m
import pentai.db.ai_factory as f_m
import pentai.db.players_mgr as pm_m
from pentai.base.pente_exceptions import *

import audio as a_m

def play_speech(part_num):
    a_m.instance.demo(part_num)

def sim_press(button):
    button.sim_press()
    Clock.schedule_once(button.sim_release, 0.2)

class Demo():
    def __init__(self, app, size):
        self.app = app
        self.size = size
        self.interrupted = False
        self.speed_factor = 0.65
        self.sleep_remaining = 0

        # TODO Save settings
        # for settings demo

        self.script_list = [self.rules_script1, self.rules_script2,
                self.rules_script3, self.rules_script4, self.rules_script5]
        self.script = None

    def start(self):
        a_m.instance.start_demo()
        self.play()

    def play(self, dt=None):
        if self.interrupted:
            self.script = None
            self.interrupted = False
            self.sleep_remaining = 0

        if self.sleep_remaining > 0:
            self.sleep_remaining -= 0.05
            Clock.schedule_once(self.play, 0.05)
            return

        if self.script is None:
            if len(self.script_list) == 0:
                self.finish()
                return
            self.script = self.script_list[0]()
            del self.script_list[0]

        try:
            self.sleep_remaining = self.script.next() / self.speed_factor
            self.sleep_remaining = (.8 + .4 * rand_m.random()) * self.sleep_remaining
        except (StopIteration, IllegalMoveException):
            self.script = None
            self.sleep_remaining = 0

        Clock.schedule_once(self.play, 0)

    def interrupt(self):
        self.interrupted = True

    def finish(self):
        self.app.finish_demo()

    def clean_up(self):
        Clock.unschedule(self.play)

    def rules_script1(self):
        play_speech("intersections")

        # We're already on the menu screen
        app = self.app
        ms = app.menu_screen

        yield(1)
        sim_press(ms.ids.new_game_id)
        yield(.2)

        app.show_new_game_screen()
        yield(.1)

        ss = app.setup_screen
        # TODO: Select white player type
        ss.ids.black_type_id.val = "Human"
        ss.ids.bpl_id.val = "You"
        #ss.ids.white_type_id.val = "AI"
        ss.ids.white_type_id.val = "Computer"
        # TODO: Select computer player somehow?
        ss.ids.wpl_id.val = "Killer"
        yield(2)

        sim_press(ss.ids.start_game_id)

    def mm(self, x,y):
        self.game.make_move((x,y))
        self.app.pente_screen.perform(0)
        self.app.pente_screen.refresh_all()

    def rules_script2(s):
        # Use most recent human player name
        pmgr = pm_m.PlayersMgr()
        human = pmgr.get_recent_player_names("Human", 1)[0]
        p1 = h_m.HumanPlayer(human)

        aif = f_m.AIFactory()
        genome = aig_m.AIGenome("PentAI")
        genome.use_openings_book = False
        p2 = aif.create_player(genome)

        # Create a game
        r = r_m.Rules(13, "standard")
        s.game = g_m.Game(r, p1, p2)

        # And start it...

        # demo flag: Disable prompting of players
        s.app.start_game(s.game, demo=True)
        s.ps = s.app.pente_screen
        yield(1.2) # Compensating for .7 wait at start?!

        play_speech("centre_first")
        yield(1.5)
        s.mm(3,4)
        yield(1)

        s.mm(6,8)
        yield(.5)
        s.mm(4,4)
        yield(.5)

        s.mm(6,7)
        yield(.5)
        s.mm(5,8)
        yield(.5)
        play_speech("line_5_wins")

        s.mm(6,9)
        yield(.5)
        s.mm(8,3)
        yield(.5)

        s.mm(6,10)
        yield(3)

        # Diagonal white win
        s.app.pente_screen.set_review_mode(False)
        s.game.go_to_the_beginning()
        yield(1)

        s.mm(6, 6)
        yield(.5)
        s.mm(5, 5)
        yield(.5)

        s.mm(4, 4)
        yield(.5)
        s.mm(3, 5)
        yield(.5)

        s.mm(6, 2)
        yield(.5)

        play_speech("diagonal_wins")

        s.mm(6, 4)
        yield(.5)

        s.mm(8, 0)
        yield(.5)
        s.mm(4, 5)
        yield(.5)

        s.mm(5, 3)
        yield(.5)
        s.mm(7, 5)
        yield(.8)

        s.mm(7, 1)
        yield(2.5)

    def rules_script3(s):
        # Captures
        s.app.pente_screen.set_review_mode(False)
        s.game.go_to_the_beginning()
        yield(1)

        s.mm(6, 6)
        yield(.5)
        s.mm(6, 7)
        yield(.5)

        play_speech("pair_captures")

        s.mm(6, 5)
        yield(1.5)
        s.mm(6, 4)
        yield(2.5)

        s.mm(5, 3)
        yield(.5)
        s.mm(7, 5)
        yield(1)

        play_speech("diag_capt")
        yield(1.5)

        s.mm(8, 6)
        yield(2.5)
        s.mm(6, 6)
        yield(1)

    def rules_script4(s):
        # Non captures
        ##############
        s.game.go_to_the_beginning()
        play_speech("non_capt")
        yield(2)

        # Length 1
        s.mm(0, 0)
        yield(.5)
        play_speech("single_stone")

        s.mm(0, 1)
        yield(1)
        s.mm(0, 2)
        yield(1)

        # Length 3
        s.mm(2, 1)
        yield(.5)
        s.mm(2, 0)
        yield(.5)
        play_speech("3_or_more")

        s.mm(2, 3)
        yield(.5)
        s.mm(8, 4)
        yield(.5)

        s.mm(2, 2)
        yield(1)
        s.mm(2, 4)
        yield(2)

        # Place inside the border
        s.mm(4, 1)
        yield(.5)
        s.mm(4, 0)
        yield(.5)

        play_speech("trigger_capt")

        s.mm(4, 10)
        yield(.5)
        s.mm(4, 3)
        yield(2)

        s.mm(4, 2) # Black places a piece inside, doesn't get taken
        yield(3)
        s.mm(6, 6)
        yield(1)

        # Gap
        play_speech("no_gaps")

        s.mm(6, 3)
        yield(.5)
        s.mm(6, 0)
        yield(.5)

        s.mm(6, 1)
        yield(1)
        s.mm(6, 4)
        yield(2)

        # Double capture
        s.mm(7, 6)
        yield(.5)

        play_speech("two_pairs")
        s.mm(5, 6)
        yield(.5)
        s.mm(7, 9)
        yield(.5)
        s.mm(5, 7)
        yield(.5)
        s.mm(0, 12)
        yield(.5)
        s.mm(6, 8)
        yield(.5)
        s.mm(4, 6)
        yield(2)

    def rules_script5(s):
        # 5 Pairs win the game
        s.game.go_to_the_beginning()
        play_speech("capt_win")
        yield(1)

        # 1
        s.mm(0, 1)
        yield(.3)
        s.mm(0, 0)
        yield(.3)

        s.mm(0, 2)
        yield(.3)
        s.mm(0, 3)
        yield(.3)

        # 2
        s.mm(2, 1)
        yield(.3)
        s.mm(2, 0)
        yield(.3)

        s.mm(2, 2)
        yield(.3)
        s.mm(2, 3)
        yield(.3)

        # 3
        s.mm(4, 2)
        yield(.3)
        s.mm(4, 3)
        yield(.3)

        s.mm(4, 1)
        yield(.3)
        s.mm(4, 0)
        yield(.3)

        # 4
        s.mm(7, 1)
        yield(.3)
        s.mm(6, 0)
        yield(.3)

        s.mm(8, 2)
        yield(.3)
        s.mm(9, 3)
        yield(.3)

        # 5
        s.mm(2, 10)
        yield(.3)
        s.mm(0, 12)
        yield(.3)

        s.mm(1, 11)
        yield(2)
        s.mm(3, 9)
        yield(0.5)
        play_speech("capt_no_win")
        yield(4)

        # Demonstrate review mode
        play_speech("review")

        # Click go to beginning
        beginning_button = s.ps.panel_buttons.ids.beginning_id
        sim_press(beginning_button)
        yield(.3)

        s.game.go_to_the_beginning()
        yield(.7)

        # Click forward a few times
        forward_button = s.ps.panel_buttons.ids.forward_id
        for i in range(8):
            sim_press(forward_button)
            yield(.2)

            s.game.go_forwards_one()
            yield(.5)

        yield(.2)
        play_speech("enjoy")

        yield(4)

        ########

<commit_msg>Remove "New Game" screen from demo for now<commit_after>from kivy.clock import Clock

import time

#from defines import *

import random as rand_m

import pentai.base.human_player as h_m
import pentai.base.rules as r_m
import pentai.base.game as g_m
import pentai.ai.ai_genome as aig_m
import pentai.db.ai_factory as f_m
import pentai.db.players_mgr as pm_m
from pentai.base.pente_exceptions import *

import audio as a_m

def play_speech(part_num):
    a_m.instance.demo(part_num)

def sim_press(button):
    button.sim_press()
    Clock.schedule_once(button.sim_release, 0.2)

class Demo():
    def __init__(self, app, size):
        self.app = app
        self.size = size
        self.interrupted = False
        self.speed_factor = 0.65
        self.sleep_remaining = 0

        # TODO Save settings
        # for settings demo

        self.script_list = [self.rules_script2,
                self.rules_script3, self.rules_script4, self.rules_script5]
        self.script = None

    def start(self):
        a_m.instance.start_demo()
        self.play()

    def play(self, dt=None):
        if self.interrupted:
            self.script = None
            self.interrupted = False
            self.sleep_remaining = 0

        if self.sleep_remaining > 0:
            self.sleep_remaining -= 0.05
            Clock.schedule_once(self.play, 0.05)
            return

        if self.script is None:
            if len(self.script_list) == 0:
                self.finish()
                return
            self.script = self.script_list[0]()
            del self.script_list[0]

        try:
            self.sleep_remaining = self.script.next() / self.speed_factor
            self.sleep_remaining = (.8 + .4 * rand_m.random()) * self.sleep_remaining
        except (StopIteration, IllegalMoveException):
            self.script = None
            self.sleep_remaining = 0

        Clock.schedule_once(self.play, 0)

    def interrupt(self):
        self.interrupted = True

    def finish(self):
        self.app.finish_demo()

    def clean_up(self):
        Clock.unschedule(self.play)

    def rules_script1(self):
        # I'll leave this dead code as an example for now
        '''
        play_speech("intersections")

        # We're already on the menu screen
        app = self.app
        ms = app.menu_screen

        yield(1)
        sim_press(ms.ids.new_game_id)
        yield(.2)

        app.show_new_game_screen()
        yield(.1)

        ss = app.setup_screen
        # TODO: Select white player type
        ss.ids.black_type_id.val = "Human"
        ss.ids.bpl_id.val = "You"
        #ss.ids.white_type_id.val = "AI"
        ss.ids.white_type_id.val = "Computer"
        # TODO: Select computer player somehow?
        ss.ids.wpl_id.val = "Killer"
        yield(2)

        sim_press(ss.ids.start_game_id)
        '''

    def mm(self, x,y):
        self.game.make_move((x,y))
        self.app.pente_screen.perform(0)
        self.app.pente_screen.refresh_all()

    def rules_script2(s):
        play_speech("intersections")

        # Use most recent human player name
        pmgr = pm_m.PlayersMgr()
        human = pmgr.get_recent_player_names("Human", 1)[0]
        p1 = h_m.HumanPlayer(human)

        aif = f_m.AIFactory()
        genome = aig_m.AIGenome("PentAI")
        genome.use_openings_book = False
        p2 = aif.create_player(genome)

        # Create a game
        r = r_m.Rules(13, "standard")
        s.game = g_m.Game(r, p1, p2)

        # And start it...

        # demo flag: Disable prompting of players
        s.app.start_game(s.game, demo=True)
        s.ps = s.app.pente_screen

        yield(1.2) # Compensating for .7 wait at start?!

        #
        yield(1.5)

        play_speech("centre_first")
        yield(1.5)
        s.mm(3,4)
        yield(1)

        s.mm(6,8)
        yield(.5)
        s.mm(4,4)
        yield(.5)

        s.mm(6,7)
        yield(.5)
        s.mm(5,8)
        yield(.5)
        play_speech("line_5_wins")

        s.mm(6,9)
        yield(.5)
        s.mm(8,3)
        yield(.5)

        s.mm(6,10)
        yield(3)

        # Diagonal white win
        s.app.pente_screen.set_review_mode(False)
        s.game.go_to_the_beginning()
        yield(1)

        s.mm(6, 6)
        yield(.5)
        s.mm(5, 5)
        yield(.5)

        s.mm(4, 4)
        yield(.5)
        s.mm(3, 5)
        yield(.5)

        s.mm(6, 2)
        yield(.5)

        play_speech("diagonal_wins")

        s.mm(6, 4)
        yield(.5)

        s.mm(8, 0)
        yield(.5)
        s.mm(4, 5)
        yield(.5)

        s.mm(5, 3)
        yield(.5)
        s.mm(7, 5)
        yield(.8)

        s.mm(7, 1)
        yield(2.5)

    def rules_script3(s):
        # Captures
        s.app.pente_screen.set_review_mode(False)
        s.game.go_to_the_beginning()
        yield(1)

        s.mm(6, 6)
        yield(.5)
        s.mm(6, 7)
        yield(.5)

        play_speech("pair_captures")

        s.mm(6, 5)
        yield(1.5)
        s.mm(6, 4)
        yield(2.5)

        s.mm(5, 3)
        yield(.5)
        s.mm(7, 5)
        yield(1)

        play_speech("diag_capt")
        yield(1.5)

        s.mm(8, 6)
        yield(2.5)
        s.mm(6, 6)
        yield(1)

    def rules_script4(s):
        # Non captures
        ##############
        s.game.go_to_the_beginning()
        play_speech("non_capt")
        yield(2)

        # Length 1
        s.mm(0, 0)
        yield(.5)
        play_speech("single_stone")

        s.mm(0, 1)
        yield(1)
        s.mm(0, 2)
        yield(1)

        # Length 3
        s.mm(2, 1)
        yield(.5)
        s.mm(2, 0)
        yield(.5)
        play_speech("3_or_more")

        s.mm(2, 3)
        yield(.5)
        s.mm(8, 4)
        yield(.5)

        s.mm(2, 2)
        yield(1)
        s.mm(2, 4)
        yield(2)

        # Place inside the border
        s.mm(4, 1)
        yield(.5)
        s.mm(4, 0)
        yield(.5)

        play_speech("trigger_capt")

        s.mm(4, 10)
        yield(.5)
        s.mm(4, 3)
        yield(2)

        s.mm(4, 2) # Black places a piece inside, doesn't get taken
        yield(3)
        s.mm(6, 6)
        yield(1)

        # Gap
        play_speech("no_gaps")

        s.mm(6, 3)
        yield(.5)
        s.mm(6, 0)
        yield(.5)

        s.mm(6, 1)
        yield(1)
        s.mm(6, 4)
        yield(2)

        # Double capture
        s.mm(7, 6)
        yield(.5)

        play_speech("two_pairs")
        s.mm(5, 6)
        yield(.5)
        s.mm(7, 9)
        yield(.5)
        s.mm(5, 7)
        yield(.5)
        s.mm(0, 12)
        yield(.5)
        s.mm(6, 8)
        yield(.5)
        s.mm(4, 6)
        yield(2)

    def rules_script5(s):
        # 5 Pairs win the game
        s.game.go_to_the_beginning()
        play_speech("capt_win")
        yield(1)

        # 1
        s.mm(0, 1)
        yield(.3)
        s.mm(0, 0)
        yield(.3)

        s.mm(0, 2)
        yield(.3)
        s.mm(0, 3)
        yield(.3)

        # 2
        s.mm(2, 1)
        yield(.3)
        s.mm(2, 0)
        yield(.3)

        s.mm(2, 2)
        yield(.3)
        s.mm(2, 3)
        yield(.3)

        # 3
        s.mm(4, 2)
        yield(.3)
        s.mm(4, 3)
        yield(.3)

        s.mm(4, 1)
        yield(.3)
        s.mm(4, 0)
        yield(.3)

        # 4
        s.mm(7, 1)
        yield(.3)
        s.mm(6, 0)
        yield(.3)

        s.mm(8, 2)
        yield(.3)
        s.mm(9, 3)
        yield(.3)

        # 5
        s.mm(2, 10)
        yield(.3)
        s.mm(0, 12)
        yield(.3)

        s.mm(1, 11)
        yield(2)
        s.mm(3, 9)
        yield(0.5)
        play_speech("capt_no_win")
        yield(4)

        # Demonstrate review mode
        play_speech("review")

        # Click go to beginning
        beginning_button = s.ps.panel_buttons.ids.beginning_id
        sim_press(beginning_button)
        yield(.3)

        s.game.go_to_the_beginning()
        yield(.7)

        # Click forward a few times
        forward_button = s.ps.panel_buttons.ids.forward_id
        for i in range(8):
            sim_press(forward_button)
            yield(.2)

            s.game.go_forwards_one()
            yield(.5)

        yield(.2)
        play_speech("enjoy")

        yield(4)

        ########

<|endoftext|>


<commit_before>import re
import os

from bs4 import BeautifulSoup

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.core.files import File

from pages.models import Page, Image

PEP_TEMPLATE = 'pages/pep-page.html'
pep_url = lambda num: 'dev/peps/pep-{}/'.format(num)

def check_paths():
    """ Checks to ensure our PEP_REPO_PATH is setup correctly """
    if not hasattr(settings, 'PEP_REPO_PATH'):
        raise ImproperlyConfigured("No PEP_REPO_PATH in settings")

    if not os.path.exists(settings.PEP_REPO_PATH):
        raise ImproperlyConfigured("PEP_REPO_PATH in settings does not exist")

def convert_pep0():
    """
    Take existing generated pep-0000.html and convert to something suitable
    for a Python.org Page returns the core body HTML necessary only
    """
    check_paths()

    pep0_path = os.path.join(settings.PEP_REPO_PATH, 'pep-0000.html')
    pep0_content = open(pep0_path).read()

    soup = BeautifulSoup(pep0_content)

    body_children = list(soup.body.children)

    # Grab header and PEP body
    header = body_children[3]
    pep_content = body_children[7]

    # Fix PEP links
    body_links = pep_content.find_all("a")

    pep_href_re = re.compile(r'pep-(\d+)\.html')

    for b in body_links:
        m = pep_href_re.search(b.attrs['href'])

        # Skip anything not matching 'pep-XXXX.html'
        if not m:
            continue

        b.attrs['href'] = '/dev/peps/pep-{}/'.format(m.group(1))

    # Remove Version from header
    header_rows = header.find_all('th')
    for t in header_rows:
        if 'Version:' in t.text and 'N/A' in t.next_sibling.text:
            t.parent.extract()

    return ''.join([header.prettify(), pep_content.prettify()])

def get_pep0_page(commit=True):
    """
    Using convert_pep0 above, create a CMS ready pep0 page and return it

    pep0 is used as the directory index, but it's also an actual pep, so we
    return both Page objects.
    """
    pep0_content = convert_pep0()
    pep0_page, _ = Page.objects.get_or_create(path='dev/peps/')
    pep0000_page, _ = Page.objects.get_or_create(path='dev/peps/pep-0000/')
    for page in [pep0_page, pep0000_page]:
        page.content = pep0_content
        page.content_markup_type = 'html'
        page.title = "PEP 0 -- Index of Python Enhancement Proposals (PEPs)"
        page.template_name = PEP_TEMPLATE

        if commit:
            page.save()

    return pep0_page, pep0000_page

def fix_headers(soup, data):
    """ Remove empty or unwanted headers and find our title """
    header_rows = soup.find_all('th')
    for t in header_rows:
        if 'Version:' in t.text:
            if t.next_sibling.text == '$Revision$':
                t.parent.extract()
            if t.next_sibling.text == '':
                t.parent.extract()
            print
        if 'Last-Modified:' in t.text:
            if '$Date$'in t.next_sibling.text:
                t.parent.extract()
            if t.next_sibling.text == '':
                t.parent.extract()
        if t.text == 'Title:':
            data['title'] = t.next_sibling.text
        if t.text == 'Content-Type:':
            t.parent.extract()
        if 'Version:' in t.text and 'N/A' in t.next_sibling.text:
            t.parent.extract()

    return soup, data

def convert_pep_page(pep_number, content):
    """
    Handle different formats that pep2html.py outputs
    """
    check_paths()
    data = {
        'title': None,
    }

    if '' in content:
        soup = BeautifulSoup(content)
        data['title'] = soup.title.text

        header = soup.body.find('div', class_="header")
        header, data = fix_headers(header, data)
        data['header'] = header.prettify()

        main_content = soup.body.find('div', class_="content")

        data['main_content'] = main_content.prettify()
        data['content'] = ''.join([
            data['header'],
            data['main_content']
        ])

    else:
        soup = BeautifulSoup(content)

        soup, data = fix_headers(soup, data)
        if not data['title']:
            data['title'] = "PEP {}".format(pep_number)

        data['content'] = soup.prettify()

    hg_link = "https://hg.python.org/peps/file/tip/pep-{0}.txt".format(pep_number)
    data['content'] += """Source: {0}""".format(hg_link)
    return data

def get_pep_page(pep_number, commit=True):
    """
    Given a pep_number retrieve original PEP source text, rst, or html.
    Get or create the associated Page and return it
    """
    pep_path = os.path.join(settings.PEP_REPO_PATH, 'pep-{}.html'.format(pep_number))
    if not os.path.exists(pep_path):
        print("PEP Path '{}' does not exist, skipping".format(pep_path))

    pep_content = convert_pep_page(pep_number, open(pep_path).read())

    pep_page, _ = Page.objects.get_or_create(path=pep_url(pep_number))

    # Remove leading zeros from PEP number for display purposes
    pep_number_string = str(pep_number)
    pep_number_string = re.sub(r'^0+', '', pep_number_string)

    pep_page.title = 'PEP {0} - {1}'.format(
        pep_number_string,
        pep_content['title']
    )

    pep_page.content = pep_content['content']
    pep_page.content_markup_type = 'html'
    pep_page.template_name = PEP_TEMPLATE

    if commit:
        pep_page.save()

    return pep_page

def add_pep_image(pep_number, path):
    image_path = os.path.join(settings.PEP_REPO_PATH, path)
    if not os.path.exists(image_path):
        print("Image Path '{}' does not exist, skipping".format(image_path))

    try:
        page = Page.objects.get(path=pep_url(pep_number))
    except Page.DoesNotExist:
        print("Could not find backing PEP {}".format(pep_number))
        return

    image, created = Image.objects.get_or_create(page=page)
    if created:
        with open(image_path, 'rb') as image_obj:
            image.image.save(path, File(image_obj))

        # Old images used to live alongside html, but now they're in different
        # places, so update the page accordingly.
        soup = BeautifulSoup(page.content.raw)
        for img_tag in soup.findAll('img'):
            if img_tag['src'] == path:
                img_tag['src'] = os.path.join(settings.MEDIA_URL, page.path, path)

        page.content.raw = soup.prettify()
        page.save()

    return image

def get_peps_rss():
    rss_feed = os.path.join(settings.PEP_REPO_PATH, 'peps.rss')
    if not os.path.exists(rss_feed):
        print("Could not find generated RSS feed. Skipping.")
        return

    page, _ = Page.objects.get_or_create(
        path="dev/peps/peps.rss",
        template_name="pages/raw.html",
    )

    with open(rss_feed, "r") as rss_content:
        content = rss_content.read()

    page.content = content
    page.is_published = True
    page.content_type = "application/rss+xml"
    page.save()

    return page
<commit_msg>Fixing PEP images again<commit_after>import re
import os

from bs4 import BeautifulSoup

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.core.files import File

from pages.models import Page, Image

PEP_TEMPLATE = 'pages/pep-page.html'
pep_url = lambda num: 'dev/peps/pep-{}/'.format(num)

def check_paths():
    """ Checks to ensure our PEP_REPO_PATH is setup correctly """
    if not hasattr(settings, 'PEP_REPO_PATH'):
        raise ImproperlyConfigured("No PEP_REPO_PATH in settings")

    if not os.path.exists(settings.PEP_REPO_PATH):
        raise ImproperlyConfigured("PEP_REPO_PATH in settings does not exist")

def convert_pep0():
    """
    Take existing generated pep-0000.html and convert to something suitable
    for a Python.org Page returns the core body HTML necessary only
    """
    check_paths()

    pep0_path = os.path.join(settings.PEP_REPO_PATH, 'pep-0000.html')
    pep0_content = open(pep0_path).read()

    soup = BeautifulSoup(pep0_content)

    body_children = list(soup.body.children)

    # Grab header and PEP body
    header = body_children[3]
    pep_content = body_children[7]

    # Fix PEP links
    body_links = pep_content.find_all("a")

    pep_href_re = re.compile(r'pep-(\d+)\.html')

    for b in body_links:
        m = pep_href_re.search(b.attrs['href'])

        # Skip anything not matching 'pep-XXXX.html'
        if not m:
            continue

        b.attrs['href'] = '/dev/peps/pep-{}/'.format(m.group(1))

    # Remove Version from header
    header_rows = header.find_all('th')
    for t in header_rows:
        if 'Version:' in t.text and 'N/A' in t.next_sibling.text:
            t.parent.extract()

    return ''.join([header.prettify(), pep_content.prettify()])

def get_pep0_page(commit=True):
    """
    Using convert_pep0 above, create a CMS ready pep0 page and return it

    pep0 is used as the directory index, but it's also an actual pep, so we
    return both Page objects.
    """
    pep0_content = convert_pep0()
    pep0_page, _ = Page.objects.get_or_create(path='dev/peps/')
    pep0000_page, _ = Page.objects.get_or_create(path='dev/peps/pep-0000/')
    for page in [pep0_page, pep0000_page]:
        page.content = pep0_content
        page.content_markup_type = 'html'
        page.title = "PEP 0 -- Index of Python Enhancement Proposals (PEPs)"
        page.template_name = PEP_TEMPLATE

        if commit:
            page.save()

    return pep0_page, pep0000_page

def fix_headers(soup, data):
    """ Remove empty or unwanted headers and find our title """
    header_rows = soup.find_all('th')
    for t in header_rows:
        if 'Version:' in t.text:
            if t.next_sibling.text == '$Revision$':
                t.parent.extract()
            if t.next_sibling.text == '':
                t.parent.extract()
            print
        if 'Last-Modified:' in t.text:
            if '$Date$'in t.next_sibling.text:
                t.parent.extract()
            if t.next_sibling.text == '':
                t.parent.extract()
        if t.text == 'Title:':
            data['title'] = t.next_sibling.text
        if t.text == 'Content-Type:':
            t.parent.extract()
        if 'Version:' in t.text and 'N/A' in t.next_sibling.text:
            t.parent.extract()

    return soup, data

def convert_pep_page(pep_number, content):
    """
    Handle different formats that pep2html.py outputs
    """
    check_paths()
    data = {
        'title': None,
    }

    if '' in content:
        soup = BeautifulSoup(content)
        data['title'] = soup.title.text

        header = soup.body.find('div', class_="header")
        header, data = fix_headers(header, data)
        data['header'] = header.prettify()

        main_content = soup.body.find('div', class_="content")

        data['main_content'] = main_content.prettify()
        data['content'] = ''.join([
            data['header'],
            data['main_content']
        ])

    else:
        soup = BeautifulSoup(content)

        soup, data = fix_headers(soup, data)
        if not data['title']:
            data['title'] = "PEP {}".format(pep_number)

        data['content'] = soup.prettify()

    hg_link = "https://hg.python.org/peps/file/tip/pep-{0}.txt".format(pep_number)
    data['content'] += """Source: {0}""".format(hg_link)
    return data

def get_pep_page(pep_number, commit=True):
    """
    Given a pep_number retrieve original PEP source text, rst, or html.
    Get or create the associated Page and return it
    """
    pep_path = os.path.join(settings.PEP_REPO_PATH, 'pep-{}.html'.format(pep_number))
    if not os.path.exists(pep_path):
        print("PEP Path '{}' does not exist, skipping".format(pep_path))

    pep_content = convert_pep_page(pep_number, open(pep_path).read())

    pep_page, _ = Page.objects.get_or_create(path=pep_url(pep_number))

    # Remove leading zeros from PEP number for display purposes
    pep_number_string = str(pep_number)
    pep_number_string = re.sub(r'^0+', '', pep_number_string)

    pep_page.title = 'PEP {0} - {1}'.format(
        pep_number_string,
        pep_content['title']
    )

    pep_page.content = pep_content['content']
    pep_page.content_markup_type = 'html'
    pep_page.template_name = PEP_TEMPLATE

    if commit:
        pep_page.save()

    return pep_page

def add_pep_image(pep_number, path):
    image_path = os.path.join(settings.PEP_REPO_PATH, path)
    if not os.path.exists(image_path):
        print("Image Path '{}' does not exist, skipping".format(image_path))

    try:
        page = Page.objects.get(path=pep_url(pep_number))
    except Page.DoesNotExist:
        print("Could not find backing PEP {}".format(pep_number))
        return

    # Find existing images, we have to loop here as we can't use the ORM
    # to query against image__path
    existing_images = Image.objects.filter(page=page)
    MISSING = False
    FOUND = False

    for image in existing_images:
        image_root_path = os.path.join(settings.MEDIA_ROOT, page.path, path)

        if image.image.path.endswith(path):
            FOUND = True
            # File is missing on disk, recreate
            if not os.path.exists(image_root_path):
                MISSING = image

            break

    if not FOUND or MISSING:
        image = None
        if MISSING:
            image = MISSING
        else:
            image = Image(page=page)

        with open(image_path, 'rb') as image_obj:
            image.image.save(path, File(image_obj))

        # Old images used to live alongside html, but now they're in different
        # places, so update the page accordingly.
        soup = BeautifulSoup(page.content.raw)
        for img_tag in soup.findAll('img'):
            if img_tag['src'] == path:
                img_tag['src'] = os.path.join(settings.MEDIA_URL, page.path, path)

        page.content.raw = soup.prettify()
        page.save()
        image.save()

    return image

def get_peps_rss():
    rss_feed = os.path.join(settings.PEP_REPO_PATH, 'peps.rss')
    if not os.path.exists(rss_feed):
        print("Could not find generated RSS feed. Skipping.")
        return

    page, _ = Page.objects.get_or_create(
        path="dev/peps/peps.rss",
        template_name="pages/raw.html",
    )

    with open(rss_feed, "r") as rss_content:
        content = rss_content.read()

    page.content = content
    page.is_published = True
    page.content_type = "application/rss+xml"
    page.save()

    return page
<|endoftext|>


<commit_before>"""
Tests for VARMAX models

Author: Chad Fulton
License: Simplified-BSD
"""
from __future__ import division, absolute_import, print_function

import numpy as np
import pandas as pd
import os

import warnings
from statsmodels.datasets import webuse
from statsmodels.tsa.statespace import dynamic_factor
from .results import results_varmax, results_dynamic_factor
from numpy.testing import assert_equal, assert_almost_equal, assert_raises, assert_allclose
from nose.exc import SkipTest

current_path = os.path.dirname(os.path.abspath(__file__))

output_path = 'results' + os.sep + 'results_dynamic_factor_stata.csv'
output_results = pd.read_csv(current_path + os.sep + output_path)

class CheckStaticFactor(object):
    def __init__(self, true, k_factors, factor_order, cov_type='oim',
                 included_vars=['dln_inv', 'dln_inc', 'dln_consump'],
                 **kwargs):
        self.true = true
        # 1960:Q1 - 1982:Q4
        dta = pd.DataFrame(
            results_varmax.lutkepohl_data, columns=['inv', 'inc', 'consump'],
            index=pd.date_range('1960-01-01', '1982-10-01', freq='QS'))

        dta['dln_inv'] = np.log(dta['inv']).diff()
        dta['dln_inc'] = np.log(dta['inc']).diff()
        dta['dln_consump'] = np.log(dta['consump']).diff()

        endog = dta.ix['1960-04-01':'1978-10-01', included_vars]

        self.model = dynamic_factor.StaticFactors(endog, k_factors=k_factors,
                                                  factor_order=factor_order,
                                                  **kwargs)

        self.results = self.model.filter(true['params'], cov_type=cov_type)

    def test_no_enforce(self):
        # Test that nothing goes wrong when we don't enforce stationarity
        params = self.model.untransform_params(self.true['params'])
        params[self.model._params_transition] = (
            self.true['params'][self.model._params_transition])
        self.model.enforce_stationarity = False
        results = self.model.filter(params, transformed=False)
        self.model.enforce_stationarity = True
        assert_allclose(results.llf, self.results.llf, rtol=1e-5)

    def test_mle(self):
        results = self.model.fit(maxiter=100, disp=False)
        results = self.model.fit(results.params, method='nm', maxiter=1000,
                                 disp=False)
        assert_allclose(results.llf, self.results.llf, rtol=1e-5)

    def test_loglike(self):
        assert_allclose(self.results.llf, self.true['loglike'], rtol=1e-6)

    def test_bse_oim(self):
        raise SkipTest('Known failure: standard errors do not match.')
        # assert_allclose(self.results.bse, self.true['bse_oim'], atol=1e-2)

    def test_aic(self):
        # We only get 3 digits from Stata
        assert_allclose(self.results.aic, self.true['aic'], atol=3)

    def test_bic(self):
        # We only get 3 digits from Stata
        assert_allclose(self.results.bic, self.true['bic'], atol=3)

    def test_predict(self):
        # Tests predict + forecast
        assert_allclose(
            self.results.predict(end='1982-10-01'),
            self.true['predict'].T,
            atol=1e-6)

    def test_dynamic_predict(self):
        # Tests predict + dynamic predict + forecast
        assert_allclose(
            self.results.predict(end='1982-10-01', dynamic='1961-01-01'),
            self.true['dynamic_predict'].T,
            atol=1e-6)

class TestStaticFactor(CheckStaticFactor):
    def __init__(self):
        true = results_dynamic_factor.lutkepohl_dfm.copy()
        true['predict'] = output_results.ix[1:, ['predict_dfm_1', 'predict_dfm_2', 'predict_dfm_3']]
        true['dynamic_predict'] = output_results.ix[1:, ['dyn_predict_dfm_1', 'dyn_predict_dfm_2', 'dyn_predict_dfm_3']]
        super(TestStaticFactor, self).__init__(true, k_factors=1, factor_order=2)

class TestStaticFactor2(CheckStaticFactor):
    def __init__(self):
        true = results_dynamic_factor.lutkepohl_dfm2.copy()
        true['predict'] = output_results.ix[1:, ['predict_dfm2_1', 'predict_dfm2_2', 'predict_dfm2_3']]
        true['dynamic_predict'] = output_results.ix[1:, ['dyn_predict_dfm2_1', 'dyn_predict_dfm2_2', 'dyn_predict_dfm2_3']]
        super(TestStaticFactor2, self).__init__(true, k_factors=2, factor_order=1)

    def test_mle(self):
        # Stata's MLE on this model doesn't converge, so no reason to check
        pass

    def test_bse(self):
        # Stata's MLE on this model doesn't converge, and four of their
        # params don't even have bse (possibly they are still at starting
        # values?), so no reason to check this
        pass

    def test_aic(self):
        # Stata uses 9 df (i.e. 9 params) here instead of 13, because since the
        # model didn't coverge, 4 of the parameters aren't fully estimated
        # (possibly they are still at starting values?) so the AIC is off
        pass

    def test_bic(self):
        # Stata uses 9 df (i.e. 9 params) here instead of 13, because since the
        # model didn't coverge, 4 of the parameters aren't fully estimated
        # (possibly they are still at starting values?) so the BIC is off
        pass
<commit_msg>TST: DFM: start_params, param_names, transforms<commit_after>"""
Tests for VARMAX models

Author: Chad Fulton
License: Simplified-BSD
"""
from __future__ import division, absolute_import, print_function

import numpy as np
import pandas as pd
import os

import warnings
from statsmodels.datasets import webuse
from statsmodels.tsa.statespace import dynamic_factor
from .results import results_varmax, results_dynamic_factor
from numpy.testing import assert_equal, assert_almost_equal, assert_raises, assert_allclose
from nose.exc import SkipTest

current_path = os.path.dirname(os.path.abspath(__file__))

output_path = 'results' + os.sep + 'results_dynamic_factor_stata.csv'
output_results = pd.read_csv(current_path + os.sep + output_path)

class CheckStaticFactor(object):
    def __init__(self, true, k_factors, factor_order, cov_type='oim',
                 included_vars=['dln_inv', 'dln_inc', 'dln_consump'],
                 **kwargs):
        self.true = true
        # 1960:Q1 - 1982:Q4
        dta = pd.DataFrame(
            results_varmax.lutkepohl_data, columns=['inv', 'inc', 'consump'],
            index=pd.date_range('1960-01-01', '1982-10-01', freq='QS'))

        dta['dln_inv'] = np.log(dta['inv']).diff()
        dta['dln_inc'] = np.log(dta['inc']).diff()
        dta['dln_consump'] = np.log(dta['consump']).diff()

        endog = dta.ix['1960-04-01':'1978-10-01', included_vars]

        self.model = dynamic_factor.StaticFactors(endog, k_factors=k_factors,
                                                  factor_order=factor_order,
                                                  **kwargs)

        self.results = self.model.filter(true['params'], cov_type=cov_type)

    def test_params(self):
        # Smoke test to make sure the start_params are well-defined and
        # lead to a well-defined model
        self.model.filter(self.model.start_params)
        # Similarly a smoke test for param_names
        assert_equal(len(self.model.start_params), len(self.model.param_names))
        # Finally make sure the transform and untransform do their job
        actual = self.model.transform_params(self.model.untransform_params(self.model.start_params))
        assert_allclose(actual, self.model.start_params)
        # Also in the case of enforce stationarity = False
        self.model.enforce_stationarity = False
        actual = self.model.transform_params(self.model.untransform_params(self.model.start_params))
        self.model.enforce_stationarity = True
        assert_allclose(actual, self.model.start_params)

    def test_no_enforce(self):
        # Test that nothing goes wrong when we don't enforce stationarity
        params = self.model.untransform_params(self.true['params'])
        params[self.model._params_transition] = (
            self.true['params'][self.model._params_transition])
        self.model.enforce_stationarity = False
        results = self.model.filter(params, transformed=False)
        self.model.enforce_stationarity = True
        assert_allclose(results.llf, self.results.llf, rtol=1e-5)

    def test_mle(self):
        results = self.model.fit(maxiter=100, disp=False)
        results = self.model.fit(results.params, method='nm', maxiter=1000,
                                 disp=False)
        assert_allclose(results.llf, self.results.llf, rtol=1e-5)

    def test_loglike(self):
        assert_allclose(self.results.llf, self.true['loglike'], rtol=1e-6)

    def test_bse_oim(self):
        raise SkipTest('Known failure: standard errors do not match.')
        # assert_allclose(self.results.bse, self.true['bse_oim'], atol=1e-2)

    def test_aic(self):
        # We only get 3 digits from Stata
        assert_allclose(self.results.aic, self.true['aic'], atol=3)

    def test_bic(self):
        # We only get 3 digits from Stata
        assert_allclose(self.results.bic, self.true['bic'], atol=3)

    def test_predict(self):
        # Tests predict + forecast
        assert_allclose(
            self.results.predict(end='1982-10-01'),
            self.true['predict'].T,
            atol=1e-6)

    def test_dynamic_predict(self):
        # Tests predict + dynamic predict + forecast
        assert_allclose(
            self.results.predict(end='1982-10-01', dynamic='1961-01-01'),
            self.true['dynamic_predict'].T,
            atol=1e-6)

class TestStaticFactor(CheckStaticFactor):
    def __init__(self):
        true = results_dynamic_factor.lutkepohl_dfm.copy()
        true['predict'] = output_results.ix[1:, ['predict_dfm_1', 'predict_dfm_2', 'predict_dfm_3']]
        true['dynamic_predict'] = output_results.ix[1:, ['dyn_predict_dfm_1', 'dyn_predict_dfm_2', 'dyn_predict_dfm_3']]
        super(TestStaticFactor, self).__init__(true, k_factors=1, factor_order=2)

class TestStaticFactor2(CheckStaticFactor):
    def __init__(self):
        true = results_dynamic_factor.lutkepohl_dfm2.copy()
        true['predict'] = output_results.ix[1:, ['predict_dfm2_1', 'predict_dfm2_2', 'predict_dfm2_3']]
        true['dynamic_predict'] = output_results.ix[1:, ['dyn_predict_dfm2_1', 'dyn_predict_dfm2_2', 'dyn_predict_dfm2_3']]
        super(TestStaticFactor2, self).__init__(true, k_factors=2, factor_order=1)

    def test_mle(self):
        # Stata's MLE on this model doesn't converge, so no reason to check
        pass

    def test_bse(self):
        # Stata's MLE on this model doesn't converge, and four of their
        # params don't even have bse (possibly they are still at starting
        # values?), so no reason to check this
        pass

    def test_aic(self):
        # Stata uses 9 df (i.e. 9 params) here instead of 13, because since the
        # model didn't coverge, 4 of the parameters aren't fully estimated
        # (possibly they are still at starting values?) so the AIC is off
        pass

    def test_bic(self):
        # Stata uses 9 df (i.e. 9 params) here instead of 13, because since the
        # model didn't coverge, 4 of the parameters aren't fully estimated
        # (possibly they are still at starting values?) so the BIC is off
        pass
<|endoftext|>


<commit_before>'''
Created on 04 nov. 2015

@author: arxit
'''

import json

from PyQt4.QtCore import QCoreApplication, QVariant, Qt, QDate
from PyQt4.QtGui import QCheckBox, QWidget, QHBoxLayout, QComboBox, QDoubleSpinBox, QDateTimeEdit, QLineEdit

from qgis.core import *

import PagLuxembourg.main

class Importer(object):
    '''
    Base class for the differents importers (GML, SHP, DXF)
    '''

    def _importLayer(self, src_layer, dst_layer, mapping):
        '''
        Launch the import
        '''

        src_dp = src_layer.dataProvider()
        dst_dp = dst_layer.dataProvider()
        dst_layer_fields = dst_dp.fields()
        newfeatures = list()
        imported_extent = None

        feature_request = None

        # Set layer filter if existing, for DXF
        if mapping.sourceLayerFilter() is None:
            feature_request = QgsFeatureRequest()
        else:
            expr = QgsExpression(mapping.sourceLayerFilter())
            feature_request = QgsFeatureRequest(expr)

        # Iterate source features
        for src_feature in src_dp.getFeatures(feature_request):
            dst_feature = QgsFeature(dst_layer_fields)
            for src_index, dst_index, constant_value, enabled in mapping.fieldMappings():
                value = constant_value if src_index is None else src_feature[src_index]

                # Check if numeric value needs to be casted
                if value == NULL or value is None:
                    dst_feature.setAttribute(dst_index, NULL)
                elif dst_feature.fields()[dst_index].type() == QVariant.String and not isinstance(value, basestring):
                    dst_feature.setAttribute(dst_index, str(value))
                else:
                    dst_feature.setAttribute(dst_index, value)

            if dst_layer.hasGeometryType():
                # Import closed polylines as polygon
                if dst_layer.geometryType() == QGis.Polygon and src_layer.geometryType() == QGis.Line:
                    src_polyline = src_feature.geometry().asPolyline()
                    if src_polyline[0] == src_polyline[-1]:
                        # It's a closed polyline
                        dst_feature.setGeometry(QgsGeometry.fromPolygon([src_polyline]))
                    else:
                        # It's a classical polyline, skip
                        del dst_feature
                        continue
                else:
                    dst_feature.setGeometry(src_feature.geometry())

                # Update imported extent
                if imported_extent is None:
                    imported_extent = src_feature.geometry().boundingBox()
                else:
                    imported_extent.combineExtentWith(src_feature.geometry().boundingBox())

            newfeatures.append(dst_feature)

        # Start editing session
        if not dst_layer.isEditable():
            dst_layer.startEditing()

        # Add features
        dst_layer.addFeatures(newfeatures, True)

        # Commit
        if not dst_layer.commitChanges():
            dst_layer.rollBack()
            PagLuxembourg.main.qgis_interface.messageBar().pushCritical(QCoreApplication.translate('Importer','Error'),
                                                                        QCoreApplication.translate('Importer','Commit error on layer {}').format(qgis_layer.name()))
            return None

        # Reload layer
        dst_layer.reload()

        # Return extent
        return imported_extent

    def _getCenteredCheckbox(self, checked = True):
        '''
        Get a centered checkbox to insert in a table widget

        :returns: A widget with a centered checkbox
        :rtype: QWidget
        '''

        widget = QWidget()
        checkBox = QCheckBox()
        checkBox.setChecked(checked)
        layout = QHBoxLayout(widget)
        layout.addWidget(checkBox);
        layout.setAlignment(Qt.AlignCenter);
        layout.setContentsMargins(0,0,0,0);
        widget.setLayout(layout);

        return widget

    def _getCombobox(self, values, selected_value = None, currentindex_changed_callback = None):
        '''
        Get a combobox filled with the given values

        :param values: The values as key = value, value = description or text
        :type values: Dict

        :returns: A combobox
        :rtype: QWidget
        '''

        widget = QWidget()
        combobox = QComboBox()
        layout = QHBoxLayout(widget)
        layout.addWidget(combobox, 1);
        layout.setAlignment(Qt.AlignCenter);
        layout.setContentsMargins(5,0,5,0);
        widget.setLayout(layout);

        current_item_index = 0
        selected_index = -1

        for key, value in values.iteritems():
            combobox.addItem(value, key)

            # Select layer
            if key == selected_value:
                selected_index = current_item_index

            current_item_index += 1

        if selected_value is not None:
            combobox.setCurrentIndex(selected_index)

        if currentindex_changed_callback is not None:
            combobox.currentIndexChanged.connect(currentindex_changed_callback)

        return widget

    def _getSpinbox(self, minvalue, maxvalue, step, value = 0):
        '''
        Get a combobox filled with the given values

        :param values: The values as key = value, value = description or text
        :type values: Dict

        :returns: A combobox
        :rtype: QWidget
        '''

        widget = QWidget()
        spinbox = QDoubleSpinBox()
        spinbox.setMinimum(minvalue)
        spinbox.setMaximum(maxvalue)
        spinbox.setSingleStep(step)
        spinbox.setDecimals(len(str(step).split('.')[1]) if len(str(step).split('.'))==2 else 0)
        if value is not None:
            spinbox.setValue(value)
        layout = QHBoxLayout(widget)
        layout.addWidget(spinbox, 1);
        layout.setAlignment(Qt.AlignCenter);
        layout.setContentsMargins(5,0,5,0);
        widget.setLayout(layout);

        return widget

    def _getCalendar(self, display_format, value = None):
        '''
        Get a combobox filled with the given values

        :param values: The values as key = value, value = description or text
        :type values: Dict

        :returns: A combobox
        :rtype: QWidget
        '''

        widget = QWidget()
        calendar = QDateTimeEdit()
        calendar.setCalendarPopup(True)
        calendar.setDisplayFormat(display_format)
        if value is not None:
            calendar.setDate(QDate.fromString(value, display_format))
        else:
            calendar.setDate(QDate.currentDate())
        layout = QHBoxLayout(widget)
        layout.addWidget(calendar, 1);
        layout.setAlignment(Qt.AlignCenter);
        layout.setContentsMargins(5,0,5,0);
        widget.setLayout(layout);

        return widget

    def _getTextbox(self, value = None):
        '''
        Get a combobox filled with the given values

        :param values: The values as key = value, value = description or text
        :type values: Dict

        :returns: A combobox
        :rtype: QWidget
        '''

        widget = QWidget()
        textbox = QLineEdit()
        textbox.setText(value)
        layout = QHBoxLayout(widget)
        layout.addWidget(textbox, 1);
        layout.setAlignment(Qt.AlignCenter);
        layout.setContentsMargins(5,0,5,0);
        widget.setLayout(layout);

        return widget

    def _getCellValue(self, table, row, column):
        '''
        Get the selected combobox text

        :param table: The table
        :type table: QTableWidget

        :param row: The row index
        :type row: Int

        :param column: The column index
        :type column: Int

        :returns: The selected QGIS field name
        :rtype: QString, str
        '''

        # Check whether it is an item
        item = table.item(row, column)
        if item is not None:
            text = item.text().strip()
            return text if not text == '' else None

        # It is a widget
        for child in table.cellWidget(row, column).children():
            if type(child) is QCheckBox:
                return child.isChecked()
            elif type(child) is QComboBox:
                return child.currentText(), child.itemData(child.currentIndex())
            elif type(child) is QLineEdit:
                text = child.text().strip()
                return text if not text == '' else None
            elif type(child) is QDoubleSpinBox:
                return child.value()
            elif type(child) is QDateTimeEdit:
                return child.date().toString(child.displayFormat())

        raise TypeError('No widget found')

class Mapping(object):
    '''
    Defines a complete mapping
    Contains one or more layer mapping
    '''

    def __init__(self):
        '''
        Constructor
        '''

        self._mappings = list()

    def layerMappings(self):
        return self._mappings

    def getLayerMappingForSource(self, source_layer):
        for mapping in self._mappings:
            if mapping.sourceLayerName() == source_layer:
                return mapping

        return None

    def addLayerMapping(self, mapping):
        self._mappings.append(mapping)

    def writeJson(self, filename):
        mappings = list()

        for mapping in self._mappings:
            mappings.append(mapping.asDictionary())

        file = open(filename, 'wb')
        file.write(json.dumps(mappings))
        file.close()

    def parseJson(self, filename):
        f = open(filename, 'r')
        content = f.read()
        f.close()
        mappings = json.loads(content)

        del self._mappings[:]

        for mapping in mappings:
            self._mappings.append(LayerMapping(mapping))

class LayerMapping(object):
    '''
    Defines a complete mapping
    Contains one or more layer mapping
    '''

    def __init__(self, mapping = None):
        '''
        Constructor
        '''

        if mapping is not None:
            self._mapping = mapping
            return

        self._mapping = dict()
        self.setSourceLayerName(None)
        self.setDestinationLayerName(None)
        self.setSourceLayerFilter(None)
        self.setEnabled(False)
        self.setValid(False)
        self._mapping['FieldMapping'] = list()

    def sourceLayerName(self):
        return self._mapping['SourceLayerName']

    def setSourceLayerName(self, name):
        self._mapping['SourceLayerName'] = name

    def destinationLayerName(self):
        return self._mapping['DestinationLayerName']

    def setDestinationLayerName(self, name):
        self._mapping['DestinationLayerName'] = name

    def sourceLayerFilter(self):
        return self._mapping['SourceLayerFilter']

    def setSourceLayerFilter(self, filter):
        self._mapping['SourceLayerFilter'] = filter

    def isEnabled(self):
        return self._mapping['Enabled']

    def setEnabled(self, enabled):
        self._mapping['Enabled'] = enabled

    def isValid(self):
        return self._mapping['Valid']

    def setValid(self, enabled):
        self._mapping['Valid'] = enabled

    def fieldMappings(self):
        return self._mapping['FieldMapping']

    def getFieldMappingForSource(self, source_fieldname):
        for source, destination, constant_value, enabled in self._mapping['FieldMapping']:
            if source == source_fieldname:
                return source, destination, constant_value, enabled

        return None, None, None, None

    def getFieldMappingForDestination(self, destination_fieldname):
        for source, destination, constant_value, enabled in self._mapping['FieldMapping']:
            if destination == destination_fieldname:
                return source, destination, constant_value, enabled

        return None, None, None, None

    def asIndexFieldMappings(self, destination_fields):
        mapping = LayerMapping()
        mapping.setSourceLayerName(self.sourceLayerName())
        mapping.setDestinationLayerName(self.destinationLayerName())
        mapping.setSourceLayerFilter(self.sourceLayerFilter())
        mapping.setEnabled(self.isEnabled())
        mapping.setValid(self.isValid())

        for source, destination, constant_value, enabled in self.fieldMappings():
            mapping.addFieldMapping(source, destination_fields.fieldNameIndex(destination), constant_value, enabled)

        return mapping

    def addFieldMapping(self, source, destination, constant_value, enabled):
        self._mapping['FieldMapping'].append((source, destination, constant_value, enabled))

    def clearFieldMapping(self):
        del self._mapping['FieldMapping'][:]

    def asDictionary(self):
        return self._mapping<commit_msg>Fix #48<commit_after>'''
Created on 04 nov. 2015

@author: arxit
'''

import json

from PyQt4.QtCore import QCoreApplication, QVariant, Qt, QDate
from PyQt4.QtGui import QCheckBox, QWidget, QHBoxLayout, QComboBox, QDoubleSpinBox, QDateTimeEdit, QLineEdit

from qgis.core import *

import PagLuxembourg.main

class Importer(object):
    '''
    Base class for the differents importers (GML, SHP, DXF)
    '''

    def _importLayer(self, src_layer, dst_layer, mapping):
        '''
        Launch the import
        '''

        src_dp = src_layer.dataProvider()
        dst_dp = dst_layer.dataProvider()
        dst_layer_fields = dst_dp.fields()
        newfeatures = list()
        imported_extent = None

        feature_request = None

        # Set layer filter if existing, for DXF
        if mapping.sourceLayerFilter() is None:
            feature_request = QgsFeatureRequest()
        else:
            expr = QgsExpression(mapping.sourceLayerFilter())
            feature_request = QgsFeatureRequest(expr)

        # Iterate source features
        for src_feature in src_dp.getFeatures(feature_request):
            dst_feature = QgsFeature(dst_layer_fields)
            for src_index, dst_index, constant_value, enabled in mapping.fieldMappings():
                value = constant_value if src_index is None else src_feature[src_index]

                # Check if numeric value needs to be casted
                if value == NULL or value is None:
                    dst_feature.setAttribute(dst_index, NULL)
                elif dst_feature.fields()[dst_index].type() == QVariant.String and not isinstance(value, basestring):
                    dst_feature.setAttribute(dst_index, str(value))
                else:
                    dst_feature.setAttribute(dst_index, value)

            if dst_layer.hasGeometryType():
                # Import closed polylines as polygon
                if dst_layer.geometryType() == QGis.Polygon and src_layer.geometryType() == QGis.Line:
                    src_polyline = src_feature.geometry().asPolyline()
                    if src_polyline[0] == src_polyline[-1]:
                        # It's a closed polyline
                        dst_feature.setGeometry(QgsGeometry.fromPolygon([src_polyline]))
                    else:
                        # It's a classical polyline, skip
                        del dst_feature
                        continue
                else:
                    dst_feature.setGeometry(src_feature.geometry())

                # Update imported extent
                if imported_extent is None:
                    imported_extent = src_feature.geometry().boundingBox()
                else:
                    imported_extent.combineExtentWith(src_feature.geometry().boundingBox())

            newfeatures.append(dst_feature)

        # Start editing session
        if not dst_layer.isEditable():
            dst_layer.startEditing()

        # Add features
        dst_layer.addFeatures(newfeatures, True)

        # Commit
        if not dst_layer.commitChanges():
            dst_layer.rollBack()
            PagLuxembourg.main.qgis_interface.messageBar().pushCritical(QCoreApplication.translate('Importer','Error'),
                                                                        QCoreApplication.translate('Importer','Commit error on layer {}').format(dst_layer.name()))
            errors = dst_layer.commitErrors()
            for error in errors:
                PagLuxembourg.main.qgis_interface.messageBar().pushCritical(QCoreApplication.translate('Importer','Error'), error)
            return None

        # Reload layer
        dst_layer.reload()

        # Return extent
        return imported_extent

    def _getCenteredCheckbox(self, checked = True):
        '''
        Get a centered checkbox to insert in a table widget

        :returns: A widget with a centered checkbox
        :rtype: QWidget
        '''

        widget = QWidget()
        checkBox = QCheckBox()
        checkBox.setChecked(checked)
        layout = QHBoxLayout(widget)
        layout.addWidget(checkBox);
        layout.setAlignment(Qt.AlignCenter);
        layout.setContentsMargins(0,0,0,0);
        widget.setLayout(layout);

        return widget

    def _getCombobox(self, values, selected_value = None, currentindex_changed_callback = None):
        '''
        Get a combobox filled with the given values

        :param values: The values as key = value, value = description or text
        :type values: Dict

        :returns: A combobox
        :rtype: QWidget
        '''

        widget = QWidget()
        combobox = QComboBox()
        layout = QHBoxLayout(widget)
        layout.addWidget(combobox, 1);
        layout.setAlignment(Qt.AlignCenter);
        layout.setContentsMargins(5,0,5,0);
        widget.setLayout(layout);

        current_item_index = 0
        selected_index = -1

        for key, value in values.iteritems():
            combobox.addItem(value, key)

            # Select layer
            if key == selected_value:
                selected_index = current_item_index

            current_item_index += 1

        if selected_value is not None:
            combobox.setCurrentIndex(selected_index)

        if currentindex_changed_callback is not None:
            combobox.currentIndexChanged.connect(currentindex_changed_callback)

        return widget

    def _getSpinbox(self, minvalue, maxvalue, step, value = 0):
        '''
        Get a combobox filled with the given values

        :param values: The values as key = value, value = description or text
        :type values: Dict

        :returns: A combobox
        :rtype: QWidget
        '''

        widget = QWidget()
        spinbox = QDoubleSpinBox()
        spinbox.setMinimum(minvalue)
        spinbox.setMaximum(maxvalue)
        spinbox.setSingleStep(step)
        spinbox.setDecimals(len(str(step).split('.')[1]) if len(str(step).split('.'))==2 else 0)
        if value is not None:
            spinbox.setValue(value)
        layout = QHBoxLayout(widget)
        layout.addWidget(spinbox, 1);
        layout.setAlignment(Qt.AlignCenter);
        layout.setContentsMargins(5,0,5,0);
        widget.setLayout(layout);

        return widget

    def _getCalendar(self, display_format, value = None):
        '''
        Get a combobox filled with the given values

        :param values: The values as key = value, value = description or text
        :type values: Dict

        :returns: A combobox
        :rtype: QWidget
        '''

        widget = QWidget()
        calendar = QDateTimeEdit()
        calendar.setCalendarPopup(True)
        calendar.setDisplayFormat(display_format)
        if value is not None:
            calendar.setDate(QDate.fromString(value, display_format))
        else:
            calendar.setDate(QDate.currentDate())
        layout = QHBoxLayout(widget)
        layout.addWidget(calendar, 1);
        layout.setAlignment(Qt.AlignCenter);
        layout.setContentsMargins(5,0,5,0);
        widget.setLayout(layout);

        return widget

    def _getTextbox(self, value = None):
        '''
        Get a combobox filled with the given values

        :param values: The values as key = value, value = description or text
        :type values: Dict

        :returns: A combobox
        :rtype: QWidget
        '''

        widget = QWidget()
        textbox = QLineEdit()
        textbox.setText(value)
        layout = QHBoxLayout(widget)
        layout.addWidget(textbox, 1);
        layout.setAlignment(Qt.AlignCenter);
        layout.setContentsMargins(5,0,5,0);
        widget.setLayout(layout);

        return widget

    def _getCellValue(self, table, row, column):
        '''
        Get the selected combobox text

        :param table: The table
        :type table: QTableWidget

        :param row: The row index
        :type row: Int

        :param column: The column index
        :type column: Int

        :returns: The selected QGIS field name
        :rtype: QString, str
        '''

        # Check whether it is an item
        item = table.item(row, column)
        if item is not None:
            text = item.text().strip()
            return text if not text == '' else None

        # It is a widget
        for child in table.cellWidget(row, column).children():
            if type(child) is QCheckBox:
                return child.isChecked()
            elif type(child) is QComboBox:
                return child.currentText(), child.itemData(child.currentIndex())
            elif type(child) is QLineEdit:
                text = child.text().strip()
                return text if not text == '' else None
            elif type(child) is QDoubleSpinBox:
                return child.value()
            elif type(child) is QDateTimeEdit:
                return child.date().toString(child.displayFormat())

        raise TypeError('No widget found')

class Mapping(object):
    '''
    Defines a complete mapping
    Contains one or more layer mapping
    '''

    def __init__(self):
        '''
        Constructor
        '''

        self._mappings = list()

    def layerMappings(self):
        return self._mappings

    def getLayerMappingForSource(self, source_layer):
        for mapping in self._mappings:
            if mapping.sourceLayerName() == source_layer:
                return mapping

        return None

    def addLayerMapping(self, mapping):
        self._mappings.append(mapping)

    def writeJson(self, filename):
        mappings = list()

        for mapping in self._mappings:
            mappings.append(mapping.asDictionary())

        file = open(filename, 'wb')
        file.write(json.dumps(mappings))
        file.close()

    def parseJson(self, filename):
        f = open(filename, 'r')
        content = f.read()
        f.close()
        mappings = json.loads(content)

        del self._mappings[:]

        for mapping in mappings:
            self._mappings.append(LayerMapping(mapping))

class LayerMapping(object):
    '''
    Defines a complete mapping
    Contains one or more layer mapping
    '''

    def __init__(self, mapping = None):
        '''
        Constructor
        '''

        if mapping is not None:
            self._mapping = mapping
            return

        self._mapping = dict()
        self.setSourceLayerName(None)
        self.setDestinationLayerName(None)
        self.setSourceLayerFilter(None)
        self.setEnabled(False)
        self.setValid(False)
        self._mapping['FieldMapping'] = list()

    def sourceLayerName(self):
        return self._mapping['SourceLayerName']

    def setSourceLayerName(self, name):
        self._mapping['SourceLayerName'] = name

    def destinationLayerName(self):
        return self._mapping['DestinationLayerName']

    def setDestinationLayerName(self, name):
        self._mapping['DestinationLayerName'] = name

    def sourceLayerFilter(self):
        return self._mapping['SourceLayerFilter']

    def setSourceLayerFilter(self, filter):
        self._mapping['SourceLayerFilter'] = filter

    def isEnabled(self):
        return self._mapping['Enabled']

    def setEnabled(self, enabled):
        self._mapping['Enabled'] = enabled

    def isValid(self):
        return self._mapping['Valid']

    def setValid(self, enabled):
        self._mapping['Valid'] = enabled

    def fieldMappings(self):
        return self._mapping['FieldMapping']

    def getFieldMappingForSource(self, source_fieldname):
        for source, destination, constant_value, enabled in self._mapping['FieldMapping']:
            if source == source_fieldname:
                return source, destination, constant_value, enabled

        return None, None, None, None

    def getFieldMappingForDestination(self, destination_fieldname):
        for source, destination, constant_value, enabled in self._mapping['FieldMapping']:
            if destination == destination_fieldname:
                return source, destination, constant_value, enabled

        return None, None, None, None

    def asIndexFieldMappings(self, destination_fields):
        mapping = LayerMapping()
        mapping.setSourceLayerName(self.sourceLayerName())
        mapping.setDestinationLayerName(self.destinationLayerName())
        mapping.setSourceLayerFilter(self.sourceLayerFilter())
        mapping.setEnabled(self.isEnabled())
        mapping.setValid(self.isValid())

        for source, destination, constant_value, enabled in self.fieldMappings():
            mapping.addFieldMapping(source, destination_fields.fieldNameIndex(destination), constant_value, enabled)

        return mapping

    def addFieldMapping(self, source, destination, constant_value, enabled):
        self._mapping['FieldMapping'].append((source, destination, constant_value, enabled))

    def clearFieldMapping(self):
        del self._mapping['FieldMapping'][:]

    def asDictionary(self):
        return self._mapping<|endoftext|>