<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Proxy models for augmenting our source data tables with methods useful for processing.
"""
from __future__ import unicode_literals
import re
from datetime import date
from django.utils import timezone
from calaccess_processed import special_elections
from calaccess_scraped.models import CandidateElection, IncumbentElection
from .electionsbase import ElectionProxyMixin
from ..opencivicdata.elections import OCDElectionProxy

class ScrapedCandidateElectionProxy(ElectionProxyMixin, CandidateElection):
    """
    A proxy for the CandidateElection model in calaccess_scraped.
    """
    class Meta:
        """
        Make this a proxy model.
        """
        proxy = True

    def get_ocd_election(self):
        """
        Returns an OCD Election object for this record, if it exists.
        """
        # First, try getting the record via election's scraped_id
        try:
            return OCDElectionProxy.objects.get(
                identifiers__scheme='calaccess_election_id',
                identifiers__identifier=self.scraped_id,
            )
        except OCDElectionProxy.DoesNotExist:
            # If that doesn't exist, try getting it by date
            if self.date:
                return OCDElectionProxy.objects.get(date=self.date)
            else:
                # If that fails raise the DoesNotExist error
                raise

    def guess_election_date(self, year, election_type):
        """
        Get the date of the election in the given year and type.

        Raise an exception if year is not even or if election_type is not "PRIMARY" or "GENERAL".

        Return a date object.
        """
        # Rules defined here:
        # https://leginfo.legislature.ca.gov/faces/codes_displayText.xhtml?lawCode=ELEC&division=1.&title=&part=&chapter=1.&article= # noqa

        # Parse out the data we need from the name
        parsed_year = self.parsed_name['year']

        # Make sure it's a regular election year
        if parsed_year % 2 != 0:
            raise Exception("Regular elections occur in even years.")
        elif self.is_primary:
            # Primary elections are in June
            month = 6
        elif self.is_general == 'GENERAL':
            # General elections are in November
            month = 11
        else:
            raise Exception("election_type must 'PRIMARY' or 'GENERAL'.")

        # get the first weekday
        # zero-indexed starting with monday
        first_weekday = date(parsed_year, month, 1).weekday()
        # calculate day or first tuesday after first monday
        day_or_month = (7 - first_weekday) % 7 + 2
        # Pass it out
        return date(year, month, day_or_month)

    @property
    def election_type(self):
        """
        Return the scraped incumbent election's type.

        (e.g., "GENERAL", "PRIMARY", "SPECIAL ELECTION", "SPECIAL RUNOFF")
        """
        return self.parsed_name['type']

    @property
    def date(self):
        """
        Use a scraped candidate election name to look up the election date.

        Return a timezone aware date object, if found, else None.
        """
        # If this is the 2008, we have a hacked out edge case solution
        if self.name == '2008 PRIMARY':
            return date(2008, 6, 3)

        try:
            # Check if the date is in our hardcoded list of special election
            dt = special_elections.names_to_dates_dict[self.name]
            return timezone.datetime.strptime(dt, '%Y-%m-%d').date()
        except KeyError:
            pass

        # If not check the alternative list kept by the scraped IncumbentElection model
        try:
            incumbent = IncumbentElection.objects.get(
                date__year=self.parsed_name['year'],
                name__icontains=self.parsed_name['type'],
            )
            return incumbent.date
        except (IncumbentElection.DoesNotExist, IncumbentElection.MultipleObjectsReturned):
            pass

        # If that doesn't work either, try parsing the election date from the name
        try:
            return self.guess_election_date()
        except:
            # If that fails, just give up and return None
            return None

    @property
    def parsed_name(self):
        """
        Parse a scraped candidate election name into its constituent parts.

        Parts include:
        * Four-digit year (int)
        * Type (str), e.g., "GENERAL", "PRIMARY", "SPECIAL ELECTION", "SPECIAL RUNOFF"
        * Office (optional str)
        * District (optional int)

        Returns a dict with year, type, office and district as keys.
        """
        # Parse out the data
        pattern = r'^(?P<year>\d{4}) (?P<type>\b(?:[A-Z]| )+)(?: \((?P<office>(?:[A-Z]| )+)(?P<district>\d+)?\))?$' # NOQA
        parsed_name = re.match(pattern, self.name).groupdict()

        # Clean up the contents
        parsed_name['year'] = int(parsed_name['year'])
        parsed_name['type'] = parsed_name['type'].strip()
        if parsed_name['office']:
            parsed_name['office'] = parsed_name['office'].strip()
        if parsed_name['district']:
            parsed_name['district'] = int(parsed_name['district'])

        # Pass it out
        return parsed_name

class ScrapedIncumbentElectionProxy(ElectionProxyMixin, IncumbentElection):
    """
    A proxy for the IncumbentElection model in calaccess_scraped.
    """
    class Meta:
        """
        Make this a proxy model.
        """
        proxy = True

    def get_ocd_election(self):
        """
        Returns an OCD Election object for this record, if it exists.
        """
        try:
            ocd_election = OCDElectionProxy.objects.get(
                name=self.ocd_name,
                date=self.date,
            )
        except OCDElectionProxy.DoesNotExist:
            # If that doesn't exist, try getting it by date
            try:
                ocd_election = OCDElectionProxy.objects.get(date=self.date)
            except (
                OCDElectionProxy.DoesNotExist,
                OCDElectionProxy.MultipleObjectsReturned
            ):
                raise

        return ocd_election

    @property
    def election_type(self):
        """
        Return the scraped incumbent election's type.

        (e.g., "GENERAL", "PRIMARY", "SPECIAL ELECTION", "SPECIAL RUNOFF")
        """
        if self.name == 'SPECIAL ELECTION':
            election_type = self.name
        else:
            election_type = self.name.replace('ELECTION', '').strip()

        return election_type
<commit_msg>Remove .guess_election_date() (redundant w/ get_expected_election_date)<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Proxy models for augmenting our source data tables with methods useful for processing.
"""
from __future__ import unicode_literals
import re
from datetime import date
from django.utils import timezone
from calaccess_processed import get_expected_election_date, special_elections
from calaccess_scraped.models import CandidateElection, IncumbentElection
from .electionsbase import ElectionProxyMixin
from ..opencivicdata.elections import OCDElectionProxy

class ScrapedCandidateElectionProxy(ElectionProxyMixin, CandidateElection):
    """
    A proxy for the CandidateElection model in calaccess_scraped.
    """
    class Meta:
        """
        Make this a proxy model.
        """
        proxy = True

    def get_ocd_election(self):
        """
        Returns an OCD Election object for this record, if it exists.
        """
        # First, try getting the record via election's scraped_id
        try:
            return OCDElectionProxy.objects.get(
                identifiers__scheme='calaccess_election_id',
                identifiers__identifier=self.scraped_id,
            )
        except OCDElectionProxy.DoesNotExist:
            # If that doesn't exist, try getting it by date
            if self.date:
                return OCDElectionProxy.objects.get(date=self.date)
            else:
                # If that fails raise the DoesNotExist error
                raise

    @property
    def election_type(self):
        """
        Return the scraped incumbent election's type.

        (e.g., "GENERAL", "PRIMARY", "SPECIAL ELECTION", "SPECIAL RUNOFF")
        """
        return self.parsed_name['type']

    @property
    def date(self):
        """
        Use a scraped candidate election name to look up the election date.

        Return a timezone aware date object, if found, else None.
        """
        # If this is the 2008, we have a hacked out edge case solution
        if self.name == '2008 PRIMARY':
            return date(2008, 6, 3)

        try:
            # Check if the date is in our hardcoded list of special election
            dt = special_elections.names_to_dates_dict[self.name]
            return timezone.datetime.strptime(dt, '%Y-%m-%d').date()
        except KeyError:
            pass

        # If not check the alternative list kept by the scraped IncumbentElection model
        try:
            incumbent = IncumbentElection.objects.get(
                date__year=self.parsed_name['year'],
                name__icontains=self.parsed_name['type'],
            )
            return incumbent.date
        except (IncumbentElection.DoesNotExist, IncumbentElection.MultipleObjectsReturned):
            pass

        # If that doesn't work either, try parsing the election date from the name
        try:
            return get_expected_election_date(
                self.date.year, self.election_type
            )
        except:
            # If that fails, just give up and return None
            return None

    @property
    def parsed_name(self):
        """
        Parse a scraped candidate election name into its constituent parts.

        Parts include:
        * Four-digit year (int)
        * Type (str), e.g., "GENERAL", "PRIMARY", "SPECIAL ELECTION", "SPECIAL RUNOFF"
        * Office (optional str)
        * District (optional int)

        Returns a dict with year, type, office and district as keys.
        """
        # Parse out the data
        pattern = r'^(?P<year>\d{4}) (?P<type>\b(?:[A-Z]| )+)(?: \((?P<office>(?:[A-Z]| )+)(?P<district>\d+)?\))?$' # NOQA
        parsed_name = re.match(pattern, self.name).groupdict()

        # Clean up the contents
        parsed_name['year'] = int(parsed_name['year'])
        parsed_name['type'] = parsed_name['type'].strip()
        if parsed_name['office']:
            parsed_name['office'] = parsed_name['office'].strip()
        if parsed_name['district']:
            parsed_name['district'] = int(parsed_name['district'])

        # Pass it out
        return parsed_name

class ScrapedIncumbentElectionProxy(ElectionProxyMixin, IncumbentElection):
    """
    A proxy for the IncumbentElection model in calaccess_scraped.
    """
    class Meta:
        """
        Make this a proxy model.
        """
        proxy = True

    def get_ocd_election(self):
        """
        Returns an OCD Election object for this record, if it exists.
        """
        try:
            ocd_election = OCDElectionProxy.objects.get(
                name=self.ocd_name,
                date=self.date,
            )
        except OCDElectionProxy.DoesNotExist:
            # If that doesn't exist, try getting it by date
            try:
                ocd_election = OCDElectionProxy.objects.get(date=self.date)
            except (
                OCDElectionProxy.DoesNotExist,
                OCDElectionProxy.MultipleObjectsReturned
            ):
                raise

        return ocd_election

    @property
    def election_type(self):
        """
        Return the scraped incumbent election's type.

        (e.g., "GENERAL", "PRIMARY", "SPECIAL ELECTION", "SPECIAL RUNOFF")
        """
        if self.name == 'SPECIAL ELECTION':
            election_type = self.name
        else:
            election_type = self.name.replace('ELECTION', '').strip()

        return election_type
<|endoftext|>


<commit_before>#!/bin/env python

import argparse
import thread
import json
import irc.bot
import logging
import sys

from flask import Flask, request
from get_alerts import get_alerts

app = Flask(__name__)

class GrafanaIRCAlertBot(irc.bot.SingleServerIRCBot):
    def __init__(self, grafana_host, grafana_key):
        irc.bot.SingleServerIRCBot.__init__(
                self,
                [('irc.freenode.net', 6667)],
                'ruck-rover-alert', 'Openstack triplo ci alert bot')
        self.channel = '#tripleo-ci'
        self.grafana_host = grafana_host
        self.grafana_key = grafana_key

    def on_welcome(self, connection, event):
        connection.join(self.channel)

    def on_privmsg(self, c, e):
        self.do_command(e, e.arguments[0])

    def on_pubmsg(self, c, e):
        a = e.arguments[0].split(":", 1)
        if len(a) > 1 and irc.strings.lower(a[0]) == irc.strings.lower(
                self.connection.get_nickname()):
            self.do_command(e, a[1].strip())
        return

    def send_message(self, message):
        self.connection.privmsg(self.channel, message)

    def send_alert(self, alert):
        if alert['state'] != 'ok':
            self.send_message("{title}: {message}".format(**alert))

    def do_command(self, e, cmd):
        nick = e.source.nick
        c = self.connection

        if cmd == "alerts":
            alerts = get_alerts(
                    self.grafana_host, self.grafana_key)
            for alert in alerts:
                self.send_alert(
                    {'title': alert['name'],
                     'message': alert['Message'],
                     'state' : 'alerting'})
        else:
            self.send_message("Not understood: " + cmd)

@app.route('/',methods=['POST'])
def alert():
   irc_alert.send_alert(json.loads(request.data))
   return "OK"

if __name__ == '__main__':

    parser = argparse.ArgumentParser(
        description="Export grafana as json files")

    parser.add_argument('--grafana-host', required=True)
    parser.add_argument('--grafana-key', required=True)

    args = parser.parse_args()

    irc_alert = GrafanaIRCAlertBot(args.grafana_host, args.grafana_key)
    thread.start_new_thread(app.run, ())
    irc_alert.start()
<commit_msg>[RR Cockpit] Add filter to alert system<commit_after>#!/bin/env python

import argparse
import thread
import json
import irc.bot
import logging
import sys

from flask import Flask, request
from get_alerts import get_alerts

app = Flask(__name__)

class GrafanaIRCAlertBot(irc.bot.SingleServerIRCBot):
    def __init__(self, grafana_host, grafana_key):
        irc.bot.SingleServerIRCBot.__init__(
                self,
                [('chat.freenode.net', 6667)],
                'ruck-rover-alert', 'Openstack triplo ci alert bot')
        self.channel = '#tripleo-ci'
        self.grafana_host = grafana_host
        self.grafana_key = grafana_key

    def on_welcome(self, connection, event):
        connection.join(self.channel)

    def on_privmsg(self, c, e):
        self.do_command(e, e.arguments[0])

    def on_pubmsg(self, c, e):
        line = e.arguments[0]
        a = line.split(":", 1)
        if len(a) <= 1:
            a = line.split(",", 1)
        if len(a) > 1 and irc.strings.lower(a[0]) == irc.strings.lower(
                self.connection.get_nickname()):
            self.do_command(e, a[1].strip())
        return

    def send_message(self, message):
        self.connection.privmsg(self.channel, message)

    def send_alert(self, alert):
        if alert['state'] != 'ok':
            self.send_message("[{title}] {message}".format(**alert))

    def filter_alerts(self, alerts, command):
        filtered_alerts = []

        if len(command) <= 1:
            filtered_alerts = alerts
        else:
            for alert in alerts:
                filters = command[1:]
                name = alert['name'].lower()
                message = alert['Message'].lower()
                if any(filter.lower() in name + message for filter in filters):
                    filtered_alerts.append(alert)
        return filtered_alerts

    def do_command(self, e, cmd):
        nick = e.source.nick
        c = self.connection

        splitted_cmd = cmd.split()
        action = splitted_cmd[0]
        if action == "alerts":
            alerts = self.filter_alerts(get_alerts(
                      self.grafana_host, self.grafana_key), splitted_cmd)
            if alerts:
                for alert in alerts:
                    self.send_alert(
                        {'title': alert['name'],
                         'message': alert['Message'],
                         'state' : 'alerting'})
            else:
                self.send_message("No alerts")
        else:
            self.send_message("Not understood: " + cmd)

@app.route('/',methods=['POST'])
def alert():
   irc_alert.send_alert(json.loads(request.data))
   return "OK"

if __name__ == '__main__':

    parser = argparse.ArgumentParser(
        description="Export grafana as json files")

    parser.add_argument('--grafana-host', required=True)
    parser.add_argument('--grafana-key', required=True)

    args = parser.parse_args()

    irc_alert = GrafanaIRCAlertBot(args.grafana_host, args.grafana_key)
    thread.start_new_thread(app.run, ())
    irc_alert.start()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    Author: Guewen Baconnier
#    Copyright 2013 Camptocamp SA
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from datetime import datetime
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
from openerp.addons.connector.connector import Binder
from ..backend import magento

class MagentoBinder(Binder):
    """ Generic Binder for Magento """

@magento
class MagentoModelBinder(MagentoBinder):
    """
    Bindings are done directly on the binding model.

    Binding models are models called ``magento.{normal_model}``,
    like ``magento.res.partner`` or ``magento.product.product``.
    They are ``_inherits`` of the normal models and contains
    the Magento ID, the ID of the Magento Backend and the additional
    fields belonging to the Magento instance.
    """
    _model_name = [
            'magento.website',
            'magento.store',
            'magento.storeview',
            'magento.res.partner',
            'magento.address',
            'magento.res.partner.category',
            'magento.product.category',
            'magento.product.product',
            'magento.stock.picking.out',
            'magento.sale.order',
            'magento.sale.order.line',
            'magento.account.invoice',
        ]

    def to_openerp(self, external_id, unwrap=False):
        """ Give the OpenERP ID for an external ID

        :param external_id: external ID for which we want the OpenERP ID
        :param unwrap: if True, returns the openerp_id of the magento_xxxx record,
                       else return the id (binding id) of that record
        :return: a record ID, depending on the value of unwrap,
                 or None if the external_id is not mapped
        :rtype: int
        """
        binding_ids = self.session.search(
                self.model._name,
                [('magento_id', '=', str(external_id)),
                 ('backend_id', '=', self.backend_record.id)])
        if not binding_ids:
            return None
        assert len(binding_ids) == 1, "Several records found: %s" % binding_ids
        binding_id = binding_ids[0]
        if unwrap:
            return self.session.read(self.model._name,
                                     binding_id,
                                     ['openerp_id'])['openerp_id'][0]
        else:
            return binding_id

    def to_backend(self, record_id, wrap=False):
        """ Give the external ID for an OpenERP ID

        :param record_id: OpenERP ID for which we want the external id
        :param wrap: if False, record_id is the ID of the binding,
            if True, record_id is the ID of the normal record, the
            method will search the corresponding binding and returns
            the backend id of the binding
        :return: backend identifier of the record
        """
        if wrap:
            erp_id = self.session.search(self.model._name, [
                ['openerp_id', '=', record_id],
                ['backend_id', '=', self.backend_record.id]
            ])
            if erp_id:
                record_id = erp_id[0]
            else:
                return None
        magento_record = self.session.read(self.model._name,
                                           record_id,
                                           ['magento_id'])
        assert magento_record
        return magento_record['magento_id']

    def bind(self, external_id, binding_id):
        """ Create the link between an external ID and an OpenERP ID and
        update the last synchronization date.

        :param external_id: External ID to bind
        :param binding_id: OpenERP ID to bind
        :type binding_id: int
        """
        # avoid to trigger the export when we modify the `magento_id`
        context = self.session.context.copy()
        context['connector_no_export'] = True
        now_fmt = datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT)
        self.environment.model.write(
            self.session.cr,
            self.session.uid,
            binding_id,
            {'magento_id': str(external_id),
             'sync_date': now_fmt},
            context=context)

    def unwrap_binding(self, binding_id, browse=False):
        """ For a binding record, gives the normal record.

        Example: when called with a ``magento.product.product`` id,
        it will return the corresponding ``product.product`` id.

        :param browse: when True, returns a browse_record instance
                       rather than an ID
        """
        binding = self.session.read(self.model._name, binding_id,
                                    ['openerp_id'])
        openerp_id = binding['openerp_id'][0]
        if browse:
            return self.session.browse(self.unwrap_model(),
                                       openerp_id)
        return openerp_id

    def unwrap_model(self):
        """ For a binding model, gives the name of the normal model.

        Example: when called on a binder for ``magento.product.product``,
        it will return ``product.product``.

        This binder assumes that the normal model lays in ``openerp_id`` since
        this is the field we use in the ``_inherits`` bindings.
        """
        try:
            column = self.model._columns['openerp_id']
        except KeyError:
            raise ValueError('Cannot unwrap model %s, because it has '
                             'no openerp_id field' % self.model._name)
        return column._obj
<commit_msg>Binders should find records even if they are inactive<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    Author: Guewen Baconnier
#    Copyright 2013 Camptocamp SA
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from datetime import datetime
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
from openerp.addons.connector.connector import Binder
from ..backend import magento

class MagentoBinder(Binder):
    """ Generic Binder for Magento """

@magento
class MagentoModelBinder(MagentoBinder):
    """
    Bindings are done directly on the binding model.

    Binding models are models called ``magento.{normal_model}``,
    like ``magento.res.partner`` or ``magento.product.product``.
    They are ``_inherits`` of the normal models and contains
    the Magento ID, the ID of the Magento Backend and the additional
    fields belonging to the Magento instance.
    """
    _model_name = [
            'magento.website',
            'magento.store',
            'magento.storeview',
            'magento.res.partner',
            'magento.address',
            'magento.res.partner.category',
            'magento.product.category',
            'magento.product.product',
            'magento.stock.picking.out',
            'magento.sale.order',
            'magento.sale.order.line',
            'magento.account.invoice',
        ]

    def to_openerp(self, external_id, unwrap=False):
        """ Give the OpenERP ID for an external ID

        :param external_id: external ID for which we want the OpenERP ID
        :param unwrap: if True, returns the openerp_id of the magento_xxxx record,
                       else return the id (binding id) of that record
        :return: a record ID, depending on the value of unwrap,
                 or None if the external_id is not mapped
        :rtype: int
        """
        with self.session.change_context({'active_test': False}):
            binding_ids = self.session.search(
                self.model._name,
                [('magento_id', '=', str(external_id)),
                 ('backend_id', '=', self.backend_record.id)])
        if not binding_ids:
            return None
        assert len(binding_ids) == 1, "Several records found: %s" % binding_ids
        binding_id = binding_ids[0]
        if unwrap:
            return self.session.read(self.model._name,
                                     binding_id,
                                     ['openerp_id'])['openerp_id'][0]
        else:
            return binding_id

    def to_backend(self, record_id, wrap=False):
        """ Give the external ID for an OpenERP ID

        :param record_id: OpenERP ID for which we want the external id
        :param wrap: if False, record_id is the ID of the binding,
            if True, record_id is the ID of the normal record, the
            method will search the corresponding binding and returns
            the backend id of the binding
        :return: backend identifier of the record
        """
        if wrap:
            with self.session.change_context({'active_test': False}):
                erp_id = self.session.search(
                    self.model._name,
                    [('openerp_id', '=', record_id),
                     ('backend_id', '=', self.backend_record.id)
                     ])
            if erp_id:
                record_id = erp_id[0]
            else:
                return None
        magento_record = self.session.read(self.model._name,
                                           record_id,
                                           ['magento_id'])
        assert magento_record
        return magento_record['magento_id']

    def bind(self, external_id, binding_id):
        """ Create the link between an external ID and an OpenERP ID and
        update the last synchronization date.

        :param external_id: External ID to bind
        :param binding_id: OpenERP ID to bind
        :type binding_id: int
        """
        # avoid to trigger the export when we modify the `magento_id`
        context = self.session.context.copy()
        context['connector_no_export'] = True
        now_fmt = datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT)
        self.environment.model.write(
            self.session.cr,
            self.session.uid,
            binding_id,
            {'magento_id': str(external_id),
             'sync_date': now_fmt},
            context=context)

    def unwrap_binding(self, binding_id, browse=False):
        """ For a binding record, gives the normal record.

        Example: when called with a ``magento.product.product`` id,
        it will return the corresponding ``product.product`` id.

        :param browse: when True, returns a browse_record instance
                       rather than an ID
        """
        binding = self.session.read(self.model._name, binding_id,
                                    ['openerp_id'])
        openerp_id = binding['openerp_id'][0]
        if browse:
            return self.session.browse(self.unwrap_model(),
                                       openerp_id)
        return openerp_id

    def unwrap_model(self):
        """ For a binding model, gives the name of the normal model.

        Example: when called on a binder for ``magento.product.product``,
        it will return ``product.product``.

        This binder assumes that the normal model lays in ``openerp_id`` since
        this is the field we use in the ``_inherits`` bindings.
        """
        try:
            column = self.model._columns['openerp_id']
        except KeyError:
            raise ValueError('Cannot unwrap model %s, because it has '
                             'no openerp_id field' % self.model._name)
        return column._obj
<|endoftext|>


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

from openerp.tools.translate import _
from openerp import tools

from openerp import exceptions
from openerp import models, fields, api

class FetchMailServer(models.Model):
    _inherit = 'fetchmail.server'
    _name = 'fetchmail.server'

    _last_updated = None

    run_time = fields.Datetime(string="Launch time", compute='_run_time', store=False)

    @classmethod
    def _update_time(cls):

        cls._last_updated = tools.datetime.now()

    @api.one
    def _run_time(self):
        if not self._last_updated:

            self._last_updated = tools.datetime.now()

        src_tstamp_str = self._last_updated.strftime(tools.misc.DEFAULT_SERVER_DATETIME_FORMAT)
        src_format = tools.misc.DEFAULT_SERVER_DATETIME_FORMAT
        dst_format = tools.misc.DEFAULT_SERVER_DATETIME_FORMAT
        dst_tz_name = self.env.user.tz
        _now = tools.misc.server_to_local_timestamp(src_tstamp_str, src_format, dst_format, dst_tz_name)

        self.run_time = _now

    @api.model
    def _fetch_mails(self):

        if self._context.get('run_fetchmail_manually'):
            # if interval less than 5 seconds
            if self._last_updated and (datetime.datetime.now() - self._last_updated) < datetime.timedelta(0, 5):
                raise exceptions.Warning(_('Error'), _('Task can be started no earlier than 5 seconds.'))

        super(FetchMailServer, self)._fetch_mails()
        self._update_time()

class FetchMailImmediately(models.AbstractModel):

    _name = 'fetch_mail.imm'

    @api.model
    def get_last_update_time(self):
        res = self.env['fetchmail.server'].sudo().search([('state', '=', 'done')])
        array = [r.run_time for r in res]
        if array:
            return array[0]
        else:
            return None

    @api.model
    def run_fetchmail_manually(self):

        fetchmail_task = self.env.ref('fetchmail.ir_cron_mail_gateway_action')
        fetchmail_task_id = fetchmail_task.id
        fetchmail_model = self.env['fetchmail.server'].sudo()

        fetchmail_task._try_lock()
        fetchmail_model.with_context(run_fetchmail_manually=True)._fetch_mails()
<commit_msg>[FIX] tz of admin was used instead of current user<commit_after># -*- coding: utf-8 -*-
import datetime

from openerp.tools.translate import _
from openerp import tools

from openerp import exceptions
from openerp import models, fields, api

class FetchMailServer(models.Model):
    _inherit = 'fetchmail.server'
    _name = 'fetchmail.server'

    _last_updated = None

    run_time = fields.Datetime(string="Launch time", compute='_run_time', store=False)

    @classmethod
    def _update_time(cls):

        cls._last_updated = tools.datetime.now()

    @api.one
    def _run_time(self):
        if not self._last_updated:

            self._last_updated = tools.datetime.now()

        src_tstamp_str = self._last_updated.strftime(tools.misc.DEFAULT_SERVER_DATETIME_FORMAT)
        src_format = tools.misc.DEFAULT_SERVER_DATETIME_FORMAT
        dst_format = tools.misc.DEFAULT_SERVER_DATETIME_FORMAT
        dst_tz_name = self._context.get('tz') or self.env.user.tz
        _now = tools.misc.server_to_local_timestamp(src_tstamp_str, src_format, dst_format, dst_tz_name)

        self.run_time = _now

    @api.model
    def _fetch_mails(self):

        if self._context.get('run_fetchmail_manually'):
            # if interval less than 5 seconds
            if self._last_updated and (datetime.datetime.now() - self._last_updated) < datetime.timedelta(0, 5):
                raise exceptions.Warning(_('Error'), _('Task can be started no earlier than 5 seconds.'))

        super(FetchMailServer, self)._fetch_mails()
        self._update_time()

class FetchMailImmediately(models.AbstractModel):

    _name = 'fetch_mail.imm'

    @api.model
    def get_last_update_time(self):
        res = self.env['fetchmail.server'].sudo().with_context(tz=self.env.user.tz).search([('state', '=', 'done')])
        array = [r.run_time for r in res]
        if array:
            return array[0]
        else:
            return None

    @api.model
    def run_fetchmail_manually(self):

        fetchmail_task = self.env.ref('fetchmail.ir_cron_mail_gateway_action')
        fetchmail_task_id = fetchmail_task.id
        fetchmail_model = self.env['fetchmail.server'].sudo()

        fetchmail_task._try_lock()
        fetchmail_model.with_context(run_fetchmail_manually=True)._fetch_mails()
<|endoftext|>


<commit_before>import sys, os, getopt, subprocess, copy
import numpy as np
from collections import OrderedDict
from pprint import pformat
import matplotlib.pyplot as plt
import matplotlib

try:
  from escape.nffg_lib.nffg import NFFG
except ImportError:
  import sys, os
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),
                                  "../pox/ext/escape/nffg_lib/")))
  from nffg import NFFG

helpmsg="""
Decompresses the NFFG-s given in command line, sorts them base on test level,
and calculates the average and deviation of link/node resources for all
resource types. Prints them in ascending order of test levels in CSV format.
Removes the uncompressed NFFG after it is finished with its processing.
   -h                               Print this help message.
   -l <<NFFG.tgz location>>         Location of the *.nffg.tgz files.
   --hist=<<aggregation size>>      If given, draws the histogram
                                    for the utilization of resource
                                    components aggregating the values by the
                                    given size.
   --add_hist_values                If set, non-zero values are written above the
                                    bars on the histogram.
   --hist_format=<<pdf|png|...>>    The format of the saved histograms.
                                    PNG by default
   --starting_lvl=i                 Start the analyzation only after the given
                                    test level.
   --one                            Exit after one NFFG processing
"""

def increment_util_counter(d, u, aggr_size):
  # coudl be binary search...
  prev_aggr = aggr_size
  for aggr in d:
    if aggr > u:
      d[prev_aggr] += 1
      return
    prev_aggr = aggr

def autolabel(rects, ax):
  # attach some text labels
  for rect in rects:
    height = rect.get_height()
    if height > 0.0:
      ax.text(rect.get_x() + rect.get_width()/2., 1.05*height,
              '%.2f' % height,
              ha='center', va='bottom')

def main(argv):
  try:
    opts, args = getopt.getopt(argv, "hl:", ["hist=", "add_hist_values",
                                             "hist_format=", "starting_lvl=",
                                             "one"])
  except getopt.GetoptError as goe:
    print helpmsg
    raise
  loc_tgz = ""
  draw_hist = False
  reskeys = ['cpu', 'mem', 'storage', 'bandwidth']
  add_hist_values = False
  hist_format = "png"
  starting_lvl = 0
  process_only_one = False
  for opt, arg in opts:
    if opt == "-h":
      print helpmsg
      sys.exit()
    elif opt == "-l":
      loc_tgz = arg
    elif opt == "--hist":
      draw_hist = True
      hist_aggr_size = float(arg)
      hist = {}
      for res in reskeys + ['link_bw']:
        hist[res] = OrderedDict()
        for aggr in np.arange(hist_aggr_size, 1.0, hist_aggr_size):
          hist[res][float("%.4f"%aggr)] = 0
        hist[res][1.0] = 0
    elif opt == "--add_hist_values":
      add_hist_values = True
    elif opt == "--hist_format":
      hist_format = arg
    elif opt == "--starting_lvl":
      starting_lvl=int(arg)
    elif opt == "--one":
      process_only_one = True
  nffg_num_list = []
  bashCommand = "ls -x "+loc_tgz
  process = subprocess.Popen(bashCommand.split(), stdout=subprocess.PIPE)
  tgz_files =  process.communicate()[0]
  for filen in tgz_files.replace("\n", " ").split(" "):
    if 'test_lvl' in filen:
      nffg_num_list.append(int(filen.split('-')[1].split('.')[0]))
  nffg_num_list = sorted(filter(lambda x: x>=starting_lvl, nffg_num_list))

  print "test_lvl, avg(link_bw), ",", ".join(["".join(["avg(",noderes,")"]) \
                                              for noderes in reskeys])

  if draw_hist:
    empty_hist = copy.deepcopy(hist)
  for test_lvl in nffg_num_list:
    filename = "test_lvl-%s.nffg.tgz"%test_lvl
    os.system("".join(["tar -xf ",loc_tgz,"/",filename])) # decompress
    # after decompression nffg-s end up two folder deep.
    nffg_prefix = "nffgs-batch_tests/"+loc_tgz.split("/")[-1]+"/"
    with open("".join([nffg_prefix,"test_lvl-",str(test_lvl), ".nffg"]),
              "r") as f:
      nffg = NFFG.parse(f.read())
      nffg.calculate_available_node_res()
      nffg.calculate_available_link_res([])
      # calculate avg. res utils by resource types.
      avgs = {}
      cnts = {}
      if draw_hist:
        hist = copy.deepcopy(empty_hist)
      for noderes in reskeys:
        avgs[noderes] = 0.0
        cnts[noderes] = 0
        for i in nffg.infras:
          # only count nodes which had these resources initially
          if i.resources[noderes] > 1e-10:
            util = float(i.resources[noderes] - i.availres[noderes]) / \
                   i.resources[noderes]
            avgs[noderes] += util
            cnts[noderes] += 1
            if draw_hist:
              increment_util_counter(hist[noderes], util, hist_aggr_size)
        avgs[noderes] /= cnts[noderes]
      avg_linkutil = 0.0
      linkcnt = 0
      for l in nffg.links:
        if l.type == 'STATIC':
          link_util = float(l.bandwidth - l.availbandwidth) / l.bandwidth
          avg_linkutil += link_util
          linkcnt += 1
          if draw_hist:
            increment_util_counter(hist['link_bw'], link_util, hist_aggr_size)
      avg_linkutil /= linkcnt
      to_print = [test_lvl, avg_linkutil]
      to_print.extend([avgs[res] for res in reskeys])
      print ",".join(map(str, to_print))
    # delete the NFFG and its parent folders
    os.system("rm -rf nffgs-batch_tests/")

    if draw_hist:
      # normalize the histogram to [0,1], so the resource types could be plotted
      # on the same bar chart
      for res in hist:
        sum_util_cnt = sum([hist[res][util_range] for util_range in hist[res]])
        for util_range in hist[res]:
          hist[res][util_range] = float(hist[res][util_range]) / sum_util_cnt
      print "test_lvl", test_lvl, pformat(hist),"\n"

      # plot the histograms.
      fig, ax = plt.subplots()
      range_seq = np.array([float("%.4f"%(aggr/hist_aggr_size)) for aggr in \
                            np.arange(hist_aggr_size, 1.0, hist_aggr_size)])
      range_seq = np.append(range_seq, [1.0/hist_aggr_size])
      width = range_seq[-1] / (len(hist)+2) / len(range_seq)
      colors = iter(['r', 'g', 'b', 'c', 'y'])
      i = 0
      rects = []
      for res in hist:
        rect = ax.bar((range_seq - 1)* (len(hist)+2) * width + \
                      (i+4.5) * width,
                      [hist[res][util_range] for util_range in hist[res]],
                      width, color = next(colors))
        rects.append((res, rect))
        i += 1
        if add_hist_values:
          autolabel(rect, ax)
      # ax.set_aspect(10)
      ax.set_ylabel("Ratio of network element counts to total count")
      ax.set_xlabel("Resource utiliztaion intervals [%]")
      ax.set_xticks(range_seq * (len(hist)+2) * width)
      ax.set_xticklabels([str(int(100*util_range)) for util_range in hist['cpu']])
      ax.legend([r[0] for r in zip(*rects)[1]], zip(*rects)[0], ncol=5,
                loc='upper left', fontsize=8)
      plt.savefig('plots/test_lvl-%s-hist.%s'%(test_lvl, hist_format),
                  bbox_inches='tight')
      plt.close(fig)
    if process_only_one:
      break

if __name__ == '__main__':
  main(sys.argv[1:])
<commit_msg>Add CDF generating feature to NFFG processing script.<commit_after>import sys, os, getopt, subprocess, copy
import numpy as np
from collections import OrderedDict
from pprint import pformat
import matplotlib.pyplot as plt
import matplotlib

try:
  from escape.nffg_lib.nffg import NFFG
except ImportError:
  import sys, os
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),
                                  "../pox/ext/escape/nffg_lib/")))
  from nffg import NFFG

helpmsg="""
Decompresses the NFFG-s given in command line, sorts them base on test level,
and calculates the average and deviation of link/node resources for all
resource types. Prints them in ascending order of test levels in CSV format.
Removes the uncompressed NFFG after it is finished with its processing.
   -h                               Print this help message.
   -l <<NFFG.tgz location>>         Location of the *.nffg.tgz files.
   --hist=<<aggregation size>>      If given, draws the histogram
                                    for the utilization of resource
                                    components aggregating the values by the
                                    given size.
   --add_hist_values                If set, non-zero values are written above the
                                    bars on the histogram.
   --hist_format=<<pdf|png|...>>    The format of the saved histograms.
                                    PNG by default
   --starting_lvl=i                 Start the analyzation only after the given
                                    test level.
   --one                            Exit after one NFFG processing
   --cdf_format=<<pdf|png|...>>     The format of the saved CDF, PNG by default.
   --cdf                            Produces images of Cumulative Distribution
                                    Function in the format specified by
                                    --cdf_formatoption for each resource type.
"""

def increment_util_counter(d, u, aggr_size):
  # coudl be binary search...
  prev_aggr = aggr_size
  for aggr in d:
    if aggr > u:
      d[prev_aggr] += 1
      return
    prev_aggr = aggr

def autolabel(rects, ax):
  # attach some text labels
  for rect in rects:
    height = rect.get_height()
    if height > 0.0:
      ax.text(rect.get_x() + rect.get_width()/2., 1.05*height,
              '%.2f' % height,
              ha='center', va='bottom')

def main(argv):
  try:
    opts, args = getopt.getopt(argv, "hl:", ["hist=", "add_hist_values",
                                             "hist_format=", "starting_lvl=",
                                             "one", "cdf_format=", "cdf"])
  except getopt.GetoptError as goe:
    print helpmsg
    raise
  loc_tgz = ""
  draw_hist = False
  reskeys = ['cpu', 'mem', 'storage', 'bandwidth']
  add_hist_values = False
  hist_format = "png"
  starting_lvl = 0
  process_only_one = False
  draw_cdf = False
  cdf_format = "png"
  for opt, arg in opts:
    if opt == "-h":
      print helpmsg
      sys.exit()
    elif opt == "-l":
      loc_tgz = arg
    elif opt == "--hist":
      draw_hist = True
      hist_aggr_size = float(arg)
      hist = {}
      for res in reskeys + ['link_bw']:
        hist[res] = OrderedDict()
        for aggr in np.arange(hist_aggr_size, 1.0, hist_aggr_size):
          hist[res][float("%.4f"%aggr)] = 0
        hist[res][1.0] = 0
    elif opt == "--add_hist_values":
      add_hist_values = True
    elif opt == "--hist_format":
      hist_format = arg
    elif opt == "--starting_lvl":
      starting_lvl=int(arg)
    elif opt == "--one":
      process_only_one = True
    elif opt == "--cdf":
      draw_cdf = True
      cdf = {}
      for res in reskeys + ['link_bw']:
        cdf[res] = []
    elif opt == "--cdf_format":
      cdf_format = arg

  nffg_num_list = []
  bashCommand = "ls -x "+loc_tgz
  process = subprocess.Popen(bashCommand.split(), stdout=subprocess.PIPE)
  tgz_files =  process.communicate()[0]
  for filen in tgz_files.replace("\n", " ").split(" "):
    if 'test_lvl' in filen:
      nffg_num_list.append(int(filen.split('-')[1].split('.')[0]))
  nffg_num_list = sorted(filter(lambda x: x>=starting_lvl, nffg_num_list))

  print "test_lvl, avg(link_bw), ",", ".join(["".join(["avg(",noderes,")"]) \
                                              for noderes in reskeys])

  if draw_hist:
    empty_hist = copy.deepcopy(hist)
  if draw_cdf:
    empty_cdf = copy.deepcopy(cdf)
  for test_lvl in nffg_num_list:
    filename = "test_lvl-%s.nffg.tgz"%test_lvl
    os.system("".join(["tar -xf ",loc_tgz,"/",filename])) # decompress
    # after decompression nffg-s end up two folder deep.
    nffg_prefix = "nffgs-batch_tests/"+loc_tgz.split("/")[-1]+"/"
    with open("".join([nffg_prefix,"test_lvl-",str(test_lvl), ".nffg"]),
              "r") as f:
      nffg = NFFG.parse(f.read())
      nffg.calculate_available_node_res()
      nffg.calculate_available_link_res([])
      # calculate avg. res utils by resource types.
      avgs = {}
      cnts = {}
      if draw_hist:
        hist = copy.deepcopy(empty_hist)
      if draw_cdf:
        cdf = copy.deepcopy(empty_cdf)
      for noderes in reskeys:
        avgs[noderes] = 0.0
        cnts[noderes] = 0
        for i in nffg.infras:
          # only count nodes which had these resources initially
          if i.resources[noderes] > 1e-10:
            util = float(i.resources[noderes] - i.availres[noderes]) / \
                   i.resources[noderes]
            avgs[noderes] += util
            cnts[noderes] += 1
            if draw_hist:
              increment_util_counter(hist[noderes], util, hist_aggr_size)
            if draw_cdf:
              cdf[noderes].append(util)
        avgs[noderes] /= cnts[noderes]
      avg_linkutil = 0.0
      linkcnt = 0
      for l in nffg.links:
        if l.type == 'STATIC':
          link_util = float(l.bandwidth - l.availbandwidth) / l.bandwidth
          avg_linkutil += link_util
          linkcnt += 1
          if draw_hist:
            increment_util_counter(hist['link_bw'], link_util, hist_aggr_size)
          if draw_cdf:
            cdf['link_bw'].append(link_util)
      avg_linkutil /= linkcnt
      to_print = [test_lvl, avg_linkutil]
      to_print.extend([avgs[res] for res in reskeys])
      print ",".join(map(str, to_print))
    # delete the NFFG and its parent folders
    os.system("rm -rf nffgs-batch_tests/")

    if draw_hist:
      # normalize the histogram to [0,1], so the resource types could be plotted
      # on the same bar chart
      for res in hist:
        sum_util_cnt = sum([hist[res][util_range] for util_range in hist[res]])
        for util_range in hist[res]:
          hist[res][util_range] = float(hist[res][util_range]) / sum_util_cnt
      # print "test_lvl", test_lvl, pformat(hist),"\n"

      # plot the histograms.
      fig, ax = plt.subplots()
      ax.set_ylim((0.00, 1.10))
      range_seq = np.array([float("%.4f"%(aggr/hist_aggr_size)) for aggr in \
                            np.arange(hist_aggr_size, 1.0, hist_aggr_size)])
      range_seq = np.append(range_seq, [1.0/hist_aggr_size])
      width = range_seq[-1] / (len(hist)+2) / len(range_seq)
      colors = iter(['r', 'g', 'b', 'c', 'y'])
      i = 0
      rects = []
      for res in hist:
        rect = ax.bar((range_seq - 1)* (len(hist)+2) * width + \
                      (i+4.5) * width,
                      [hist[res][util_range] for util_range in hist[res]],
                      width, color = next(colors))
        rects.append((res, rect))
        i += 1
        if add_hist_values:
          autolabel(rect, ax)
      # ax.set_aspect(10)
      ax.set_ylabel("Ratio of network element counts to total count")
      ax.set_xlabel("Resource utilization intervals [%]")
      ax.set_xticks(range_seq * (len(hist)+2) * width)
      ax.set_xticklabels([str(int(100*util_range)) for util_range in hist['cpu']])
      ax.legend([r[0] for r in zip(*rects)[1]], zip(*rects)[0], ncol=5,
                loc='upper left', fontsize=8, bbox_to_anchor=(0,1))
      plt.savefig('plots/hist-test_lvl-%s.%s'%(test_lvl, hist_format),
                  bbox_inches='tight')
      plt.close(fig)

    if draw_cdf:
      # sort util values incrementing in each resource type
      for res in cdf:
        cdf[res] = sorted(cdf[res])
      fig, ax = plt.subplots()
      ax.set_xlim((-0.05, 1.05))
      ax.set_ylim((-0.05, 1.10))
      colors = iter(['r', 'g', 'b', 'c', 'y'])
      for res in cdf:
        last_point = (0, 0)
        vertical_step = 1.0/len(cdf[res])
        rescolor = next(colors)
        reslab = res
        for point in zip(cdf[res],
                         np.append(np.arange(vertical_step, 1.0, vertical_step),
                                   [1.0])):
          plt.plot((last_point[0], point[0]), (last_point[1], point[1]),
                   color=rescolor, lw=3, label=reslab)
          reslab = None
          last_point = point
        plt.plot((last_point[0], 1.0), (last_point[1], 1.0),
                 color=rescolor, lw=3)
      ax.set_ylabel("Ratio of network element counts to total count")
      ax.set_xlabel("Resource utilization interval from 0 to x [%]")
      ax.set_xticks([float(i)/100 for i in xrange(0,101, 5)])
      ax.set_xticklabels([str(i) for i in xrange(0,101, 5)])
      ax.legend(bbox_to_anchor=(0,1), loc='upper left', ncol=5, fontsize=8)
      plt.savefig('plots/cdf-test_lvl-%s.%s'%(test_lvl, cdf_format),
                  bbox_inches='tight')
      plt.close(fig)

    # maybe finish after one iteration
    if process_only_one:
      break

if __name__ == '__main__':
  main(sys.argv[1:])
<|endoftext|>


<commit_before>"""Execute notebooks as tests, reporting an error if cell throws an exception.

Adapted from MDTraj https://github.com/mdtraj/mdtraj/pull/1130 which adapted
from https://gist.github.com/minrk/2620876.
"""

import glob
import os
import sys

from jupyter_client import KernelManager
import nbformat
import pytest

EXAMPLE_NOTEBOOKS = [f for f in glob.glob('mbuild/examples/*/*.ipynb')]

@pytest.mark.skipif(sys.platform in ['win32'],
                    reason="Not testing examples on Appveyor")
@pytest.mark.parametrize("filepath", EXAMPLE_NOTEBOOKS)
def test_examples(filepath):
    check_one_notebook(filepath)

def check_one_notebook(filepath):
    folder, filename = os.path.split(filepath)
    os.chdir(folder)
    with open(filename) as f:
        nb = nbformat.reads(f.read(), nbformat.NO_CONVERT)
    run_notebook(nb)
    os.chdir('../../../')

def run_notebook(nb):
    km = KernelManager()
    km.start_kernel(stderr=open(os.devnull, 'w'))
    kc = km.client()
    kc.start_channels()
    shell = kc.shell_channel
    # simple ping:
    kc.execute("pass")
    shell.get_msg()

    failures = 0
    for cell in nb.cells:
        if cell.cell_type != 'code':
            continue
        kc.execute(cell.source)
        # wait for finish, maximum 20s
        reply = shell.get_msg(timeout=20)['content']
        if reply['status'] == 'error':
            failures += 1
            print("\nFAILURE:")
            print('\n'.join(reply['traceback']))
            print()

    kc.stop_channels()
    km.shutdown_kernel()
    del km
    if failures > 0:
        raise Exception()
<commit_msg>Increase timeout for examples tests to 60 seconds<commit_after>"""Execute notebooks as tests, reporting an error if cell throws an exception.

Adapted from MDTraj https://github.com/mdtraj/mdtraj/pull/1130 which adapted
from https://gist.github.com/minrk/2620876.
"""

import glob
import os
import sys

from jupyter_client import KernelManager
import nbformat
import pytest

EXAMPLE_NOTEBOOKS = [f for f in glob.glob('mbuild/examples/*/*.ipynb')]

@pytest.mark.skipif(sys.platform in ['win32'],
                    reason="Not testing examples on Appveyor")
@pytest.mark.parametrize("filepath", EXAMPLE_NOTEBOOKS)
def test_examples(filepath):
    check_one_notebook(filepath)

def check_one_notebook(filepath):
    folder, filename = os.path.split(filepath)
    os.chdir(folder)
    with open(filename) as f:
        nb = nbformat.reads(f.read(), nbformat.NO_CONVERT)
    run_notebook(nb)
    os.chdir('../../../')

def run_notebook(nb):
    km = KernelManager()
    km.start_kernel(stderr=open(os.devnull, 'w'))
    kc = km.client()
    kc.start_channels()
    shell = kc.shell_channel
    # simple ping:
    kc.execute("pass")
    shell.get_msg()

    failures = 0
    for cell in nb.cells:
        if cell.cell_type != 'code':
            continue
        kc.execute(cell.source)
        # wait for finish, maximum 60s
        reply = shell.get_msg(timeout=60)['content']
        if reply['status'] == 'error':
            failures += 1
            print("\nFAILURE:")
            print('\n'.join(reply['traceback']))
            print()

    kc.stop_channels()
    km.shutdown_kernel()
    del km
    if failures > 0:
        raise Exception()
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2014-08-25
# @Author  : Scholer (scholer_l@live.com)
# @Link    :
# @Version : 0.2

# sublime plugin packages
import sublime
import sublime_plugin

# import os
# import sys
import hashlib
import time
import urllib.parse
from html.parser import HTMLParser
import cgi
import base64

class EncodingBase(sublime_plugin.TextCommand):

    def timeFormat(self,string):
        if string.isdigit():
            timeArray = time.localtime(int(string))
            return time.strftime("%Y-%m-%d %H:%M:%S", timeArray)
        else :
            try:
                if len(string) < 11:
                    timeArray = time.strptime(string, "%Y-%m-%d")
                else :
                    timeArray = time.strptime(string, "%Y-%m-%d %H:%M:%S")
            except (ValueError):
                return sublime.message_dialog('[Warning] time data ' + string + ' does not match format.')
            return str(int(time.mktime(timeArray)))

    def urlTrans(self,string):
        if string.find('%') >= 0:
            return urllib.parse.unquote(string)
        else:
            return urllib.parse.quote(string,"-._")

    def htmlEscape(self,string):
        if string.find('&') >= 0:
            if string.find(";") >= 0:
                return HTMLParser().unescape(string)
        return cgi.escape(string)

    def unicodeTrans(self,string):
        if string.find("\\u") >= 0:
            return str(string.encode("utf-8").decode("unicode-escape"))
        else:
            return str(string.encode("unicode-escape"))[2:-1].replace("\\\\u","\\u")

    def base64Encode(self, string):
        bString = string.encode(encoding="utf-8")
        return base64.b64encode(bString).decode()

    def base64Decode(self, string):
        bString = string.encode(encoding="utf-8")
        return base64.b64decode(bString).decode()

    def encode(self,type,string):
        if not string:
            return
        if type == "md5":
            return hashlib.md5(string.encode("utf-8")).hexdigest()
        elif type == "timeformat":
            return self.timeFormat(string)
        elif type == "urltrans":
            return self.urlTrans(string)
        elif type == "htmlescape":
            return self.htmlEscape(string)
        elif type == "unicode":
            return self.unicodeTrans(string)
        elif type == "base64Encode":
            return self.base64Encode(string)
        elif type == "base64Decode":
            return self.base64Decode(string)

    def encodeCommand(self,type,edit):
        for region in self.view.sel():
            if not region.empty():
                selection = self.view.substr(region)
                self.view.replace(edit, region, self.encode(type,selection))

# md5 encode
class Md5EncodingCommand(EncodingBase):
    def run(self,edit):
        self.encodeCommand("md5",edit)

# time format transition
class TimeFormatCommand(EncodingBase):
    def run(self,edit):
        self.encodeCommand("timeformat",edit)

# URL encode/decode
class UrlTransCommand(EncodingBase):
    def run(self,edit):
        self.encodeCommand("urltrans",edit)

#HTML escape sequence
class HtmlEscapeCommand(EncodingBase):
    def run(self,edit):
        self.encodeCommand("htmlescape",edit)

# Unicode transition
class UnicodeTransCommand(EncodingBase):
    def run(self,edit):
        self.encodeCommand("unicode",edit)

# base64 encode
class base64EncodeCommand(EncodingBase):
    def run(self, edit):
        self.encodeCommand("base64Encode",edit)

# base64 decode
class base64DecodeCommand(EncodingBase):
    def run(self, edit):
        self.encodeCommand("base64Decode",edit)

# insert unix time
class InsertUinxTimeCommand(sublime_plugin.TextCommand):
    def run(self,edit):
        postion = self.view.sel()[0].begin()
        self.view.insert(edit, postion, str(int(time.time())))

# insert locale date
class InsertDateCommand(sublime_plugin.TextCommand):
    def run(self,edit):
        now = int(time.time())
        timeArray = time.localtime(now)
        postion = self.view.sel()[0].begin()
        self.view.insert(edit, postion, time.strftime("%Y-%m-%d %H:%M:%S", timeArray))

# copy line of selected region to new flie
class PointLineToNewFileCommand(sublime_plugin.TextCommand):
    def run(self,edit):
        allRegion = []
        for region in self.view.sel():
            allRegion.append(self.view.substr(self.view.full_line(region.begin())))
        win = self.view.window()
        tab = win.new_file()
        row = 0
        for string in allRegion:
            postion = tab.text_point(row,0)
            tab.insert(edit,postion,string)
            row+=1

# this will be called when the API is ready to use
def plugin_loaded():
    pass
<commit_msg>pep8 style<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2014-08-25
# @Author  : Scholer (scholer_l@live.com)
# @Link    :
# @Version : 0.1

# sublime plugin packages
import sublime
import sublime_plugin

# import os
# import sys
import hashlib
import time
import urllib.parse
from html.parser import HTMLParser
import cgi
import base64

class EncodingBase(sublime_plugin.TextCommand):
    def timeFormat(self, string):
        if string.isdigit():
            timeArray = time.localtime(int(string))
            return time.strftime("%Y-%m-%d %H:%M:%S", timeArray)
        else:
            try:
                if len(string) < 11:
                    timeArray = time.strptime(string, "%Y-%m-%d")
                else:
                    timeArray = time.strptime(string, "%Y-%m-%d %H:%M:%S")
            except (ValueError):
                return sublime.message_dialog('[Warning] time data ' + string + ' does not match format.')
            return str(int(time.mktime(timeArray)))

    def urlTrans(self, string):
        if string.find('%') >= 0:
            return urllib.parse.unquote(string)
        else:
            return urllib.parse.quote(string, "-._")

    def htmlEscape(self, string):
        if string.find('&') >= 0:
            if string.find(";") >= 0:
                return HTMLParser().unescape(string)
        return cgi.escape(string)

    def unicodeTrans(self, string):
        if string.find("\\u") >= 0:
            return str(string.encode("utf-8").decode("unicode-escape"))
        else:
            return str(string.encode("unicode-escape"))[2:-1].replace("\\\\u", "\\u")

    def base64Encode(self, string):
        bString = string.encode(encoding="utf-8")
        return base64.b64encode(bString).decode()

    def base64Decode(self, string):
        bString = string.encode(encoding="utf-8")
        return base64.b64decode(bString).decode()

    def encode(self, type, string):
        if not string:
            return
        if type == "md5":
            return hashlib.md5(string.encode("utf-8")).hexdigest()
        elif type == "timeformat":
            return self.timeFormat(string)
        elif type == "urltrans":
            return self.urlTrans(string)
        elif type == "htmlescape":
            return self.htmlEscape(string)
        elif type == "unicode":
            return self.unicodeTrans(string)
        elif type == "base64Encode":
            return self.base64Encode(string)
        elif type == "base64Decode":
            return self.base64Decode(string)

    def encodeCommand(self, type, edit):
        for region in self.view.sel():
            if not region.empty():
                selection = self.view.substr(region)
                self.view.replace(edit, region, self.encode(type, selection))

# md5 encode
class Md5EncodingCommand(EncodingBase):
    def run(self, edit):
        self.encodeCommand("md5", edit)

# time format transition
class TimeFormatCommand(EncodingBase):
    def run(self, edit):
        self.encodeCommand("timeformat", edit)

# URL encode/decode
class UrlTransCommand(EncodingBase):
    def run(self, edit):
        self.encodeCommand("urltrans", edit)

# HTML escape sequence
class HtmlEscapeCommand(EncodingBase):
    def run(self, edit):
        self.encodeCommand("htmlescape", edit)

# Unicode transition
class UnicodeTransCommand(EncodingBase):
    def run(self, edit):
        self.encodeCommand("unicode", edit)

# base64 encode
class base64EncodeCommand(EncodingBase):
    def run(self, edit):
        self.encodeCommand("base64Encode", edit)

# base64 decode
class base64DecodeCommand(EncodingBase):
    def run(self, edit):
        self.encodeCommand("base64Decode", edit)

# insert unix time
class InsertUinxTimeCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        postion = self.view.sel()[0].begin()
        self.view.insert(edit, postion, str(int(time.time())))

# insert locale date
class InsertDateCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        now = int(time.time())
        timeArray = time.localtime(now)
        postion = self.view.sel()[0].begin()
        self.view.insert(edit, postion, time.strftime("%Y-%m-%d %H:%M:%S", timeArray))

# copy line of selected region to new flie
class PointLineToNewFileCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        allRegion = []
        for region in self.view.sel():
            allRegion.append(self.view.substr(self.view.full_line(region.begin())))
        win = self.view.window()
        tab = win.new_file()
        row = 0
        for string in allRegion:
            postion = tab.text_point(row, 0)
            tab.insert(edit, postion, string)
            row += 1

# this will be called when the API is ready to use
def plugin_loaded():
    pass
<|endoftext|>


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

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    url(r'^$', 'apps.registro.views.index', name='home'),
    url(r'^establecimiento$', 'apps.registro.views.establecimiento.index', name='establecimiento'),
    url(r'^establecimiento/create', 'apps.registro.views.establecimiento.create', name='establecimientoCreate'),
    url(r'^establecimiento/([0-9]+)/delete', 'apps.registro.views.establecimiento.delete', name='establecimientoDelete'),
    # completar datos del establecimiento
    url(r'^establecimiento/completar_datos/', 'apps.registro.views.establecimiento.completar_datos', name='establecimientoCompletarDatos'),
    url(r'^establecimiento/([0-9]+)/completar_datos_basicos/', 'apps.registro.views.establecimiento.completar_datos_basicos', name='establecimientoCompletarDatosBasicos'),
    url(r'^establecimiento/([0-9]+)/completar_contacto/', 'apps.registro.views.establecimiento.completar_contacto', name='establecimientoCompletarContacto'),
    url(r'^establecimiento/([0-9]+)/completar_alcances/', 'apps.registro.views.establecimiento.completar_alcances', name='establecimientoCompletarAlcances'),
    url(r'^establecimiento/([0-9]+)/completar_turnos/', 'apps.registro.views.establecimiento.completar_turnos', name='establecimientoCompletarTurnos'),
    url(r'^establecimiento/([0-9]+)/completar_funciones/', 'apps.registro.views.establecimiento.completar_funciones', name='establecimientoCompletarFunciones'),
    url(r'^establecimiento/([0-9]+)/completar_informacion_edilicia/', 'apps.registro.views.establecimiento.completar_informacion_edilicia', name='establecimientoCompletarInformacionEdilicia'),
    url(r'^establecimiento/([0-9]+)/completar_conexion_internet/', 'apps.registro.views.establecimiento.completar_conexion_internet', name='establecimientoCompletarConexionInternet'),
    url(r'^establecimiento/([0-9]+)/registrar', 'apps.registro.views.establecimiento.registrar', name='establecimientoRegistrar'),
    url(r'^establecimiento/datos$', 'apps.registro.views.establecimiento.datos_establecimiento', name='establecimientoDatos'),
    url(r'^establecimiento/([0-9]+)/detalle$', 'apps.registro.views.establecimiento.detalle', name='establecimientoDetalle'),
    url(r'^establecimiento/([0-9]+)/ajaxVerificarDato', 'apps.registro.views.establecimiento.verificar_dato', name='establecimientoVerificarDato'),

    # establecimiento domicilios
    url(r'^establecimiento/([0-9]+)/domicilios$', 'apps.registro.views.establecimiento_domicilio.index', name='establecimientoDomiciliosIndex'),
    url(r'^establecimiento/([0-9]+)/agregar_domicilio$', 'apps.registro.views.establecimiento_domicilio.create', name='establecimientoDomicilioCreate'),
    url(r'^establecimiento/domicilios/([0-9]+)/edit$', 'apps.registro.views.establecimiento_domicilio.edit', name='establecimientoDomicilioEdit'),
    url(r'^establecimiento/domicilios/([0-9]+)/delete$', 'apps.registro.views.establecimiento_domicilio.delete', name='establecimientoDomicilioDelete'),
    # establecimiento autoridades
    url(r'^establecimiento/([0-9]+)/autoridades$', 'apps.registro.views.establecimiento_autoridad.index', name='establecimientoAutoridadesIndex'),
    url(r'^establecimiento/([0-9]+)/agregar_autoridad$', 'apps.registro.views.establecimiento_autoridad.create', name='establecimientoAutoridadCreate'),
    url(r'^establecimiento/autoridades/([0-9]+)/edit$', 'apps.registro.views.establecimiento_autoridad.edit', name='establecimientoAutoridadEdit'),
    url(r'^establecimiento/autoridades/([0-9]+)/delete$', 'apps.registro.views.establecimiento_autoridad.delete', name='establecimientoAutoridadDelete'),
    # establecimiento turnos
    url(r'^establecimiento/([0-9]+)/turnos$', 'apps.registro.views.establecimiento_turno.index', name='establecimientoTurnosIndex'),
    url(r'^establecimiento/([0-9]+)/agregar_turno$', 'apps.registro.views.establecimiento_turno.create', name='establecimientoTurnosCreate'),
    url(r'^establecimiento/turnos/([0-9]+)/edit$', 'apps.registro.views.establecimiento_turno.edit', name='establecimientoTurnoEdit'),
    url(r'^establecimiento/turnos/([0-9]+)/delete$', 'apps.registro.views.establecimiento_turno.delete', name='establecimientoTurnoDelete'),
    # anexo
    url(r'^anexo$', 'apps.registro.views.anexo.index', name='anexo'),
    url(r'^anexo/create', 'apps.registro.views.anexo.create', name='anexoCreate'),
    url(r'^anexo/([0-9]+)/baja', 'apps.registro.views.anexo.baja', name='anexoBaja'),
    url(r'^anexo/([0-9]+)/delete', 'apps.registro.views.anexo.delete', name='anexoDelete'),
    url(r'^anexo/([0-9]+)/completar_datos_basicos/', 'apps.registro.views.anexo.completar_datos_basicos', name='anexoCompletarDatosBasicos'),
    url(r'^anexo/([0-9]+)/completar_contacto/', 'apps.registro.views.anexo.completar_contacto', name='anexoCompletarContacto'),
    url(r'^anexo/([0-9]+)/completar_turnos/', 'apps.registro.views.anexo.completar_turnos', name='anexoCompletarTurnos'),
    url(r'^anexo/([0-9]+)/completar_alcances/', 'apps.registro.views.anexo.completar_alcances', name='anexoCompletarAlcances'),
    url(r'^anexo/([0-9]+)/completar_funciones/', 'apps.registro.views.anexo.completar_funciones', name='anexoCompletarFunciones'),
    url(r'^anexo/([0-9]+)/completar_informacion_edilicia/', 'apps.registro.views.anexo.completar_informacion_edilicia', name='anexoCompletarInformacionEdilicia'),
    url(r'^anexo/([0-9]+)/completar_conexion_internet/', 'apps.registro.views.anexo.completar_conexion_internet', name='anexoCompletarConexionInternet'),
    url(r'^anexo/([0-9]+)/registrar', 'apps.registro.views.anexo.registrar', name='anexoRegistrar'),
    url(r'^anexo/([0-9]+)/ajaxVerificarDato', 'apps.registro.views.anexo.verificar_dato', name='anexoVerificarDato'),
    # anexo domicilios
    url(r'^anexo/([0-9]+)/domicilios$', 'apps.registro.views.anexo_domicilio.index', name='anexoDomiciliosIndex'),
    url(r'^anexo/([0-9]+)/agregar_domicilio$', 'apps.registro.views.anexo_domicilio.create', name='anexoDomicilioCreate'),
    url(r'^anexo/domicilios/([0-9]+)/edit$', 'apps.registro.views.anexo_domicilio.edit', name='anexoDomicilioEdit'),
    url(r'^anexo/domicilios/([0-9]+)/delete$', 'apps.registro.views.anexo_domicilio.delete', name='anexoDomicilioDelete'),
    # anexo autoridades
    url(r'^anexo/([0-9]+)/autoridades$', 'apps.registro.views.anexo_autoridad.index', name='anexoAutoridadesIndex'),
    url(r'^anexo/([0-9]+)/agregar_autoridad$', 'apps.registro.views.anexo_autoridad.create', name='anexoAutoridadCreate'),
    url(r'^anexo/autoridades/([0-9]+)/edit$', 'apps.registro.views.anexo_autoridad.edit', name='anexoAutoridadEdit'),
    url(r'^anexo/autoridades/([0-9]+)/delete$', 'apps.registro.views.anexo_autoridad.delete', name='anexoAutoridadDelete'),
    # extensiones aulicas
    url(r'^extension_aulica$', 'apps.registro.views.extension_aulica.index', name='extensionAulica'),
    url(r'^extension_aulica/create', 'apps.registro.views.extension_aulica.create', name='extensionAulicaCreate'),
    url(r'^extension_aulica/([0-9]+)/baja', 'apps.registro.views.extension_aulica.baja', name='extensionAulicaBaja'),
    url(r'^extension_aulica/([0-9]+)/delete', 'apps.registro.views.extension_aulica.delete', name='extensionAulicaDelete'),
    url(r'^extension_aulica/([0-9]+)/completar_datos_basicos/', 'apps.registro.views.extension_aulica.completar_datos_basicos', name='extensionAulicaCompletarDatosBasicos'),
    url(r'^extension_aulica/([0-9]+)/completar_contacto/', 'apps.registro.views.extension_aulica.completar_contacto', name='extensionAulicaCompletarContacto'),
    url(r'^extension_aulica/([0-9]+)/completar_turnos/', 'apps.registro.views.extension_aulica.completar_turnos', name='extensionAulicaCompletarTurnos'),
    url(r'^extension_aulica/([0-9]+)/completar_alcances/', 'apps.registro.views.extension_aulica.completar_alcances', name='extensionAulicaCompletarAlcances'),
    url(r'^extension_aulica/([0-9]+)/completar_funciones/', 'apps.registro.views.extension_aulica.completar_funciones', name='extensionAulicaCompletarFunciones'),
    url(r'^extension_aulica/([0-9]+)/completar_informacion_edilicia/', 'apps.registro.views.extension_aulica.completar_informacion_edilicia', name='extensionAulicaCompletarInformacionEdilicia'),
    url(r'^extension_aulica/([0-9]+)/completar_conexion_internet/', 'apps.registro.views.extension_aulica.completar_conexion_internet', name='extensionAulicaCompletarConexionInternet'),
    url(r'^extension_aulica/([0-9]+)/domicilios$', 'apps.registro.views.extension_aulica_domicilio.index', name='extensionAulicaDomiciliosIndex'),
    url(r'^extension_aulica/([0-9]+)/agregar_domicilio$', 'apps.registro.views.extension_aulica_domicilio.create', name='extensionAulicaDomicilioCreate'),
    url(r'^extension_aulica/domicilios/([0-9]+)/edit$', 'apps.registro.views.extension_aulica_domicilio.edit', name='extensionAulicaDomicilioEdit'),
    url(r'^extension_aulica/domicilios/([0-9]+)/delete$', 'apps.registro.views.extension_aulica_domicilio.delete', name='extensionAulicaDomicilioDelete'),
    url(r'^extension_aulica/([0-9]+)/registrar', 'apps.registro.views.extension_aulica.registrar', name='extensionAulicaRegistrar'),
    url(r'^extension_aulica/([0-9]+)/ajaxVerificarDato', 'apps.registro.views.extension_aulica.verificar_dato', name='extensionAulicaVerificarDato'),
    # dependencias funcionales
    url(r'^dependencia_funcional$', 'apps.registro.views.dependencia_funcional.index', name='dependenciaFuncional'),
    url(r'^dependencia_funcional/([0-9]+)/edit', 'apps.registro.views.dependencia_funcional.edit', name='dependenciaFuncionalEdit'),
    url(r'^dependencia_funcional/create', 'apps.registro.views.dependencia_funcional.create', name='dependenciaFuncionalCreate'),
    url(r'^dependencia_funcional/([0-9]+)/delete', 'apps.registro.views.dependencia_funcional.delete', name='dependenciaFuncionalDelete'),
    # AJAX
    url(r'^ajax/get_localidades_por_departamento/(?P<departamento_id>[0-9]+)', 'apps.registro.views.ajax.get_localidades_por_departamento', name='ajaxGetLocalidadesPorTipo'),
    url(r'^ajax/get_departamentos_por_jurisdiccion/(?P<jurisdiccion_id>[0-9]+)', 'apps.registro.views.ajax.get_departamentos_por_jurisdiccion', name='ajaxGetDepartamentosPorJurisdiccion'),
    url(r'^ajax/get_cue_parts_from_sede/(?P<sede_id>[0-9]+)', 'apps.registro.views.ajax.get_cue_parts_from_sede', name='ajaxGetCuePartsFromSede'),
   )
<commit_msg>fix a urls.py de registro<commit_after># -*- coding: UTF-8 -*-

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    url(r'^$', 'apps.registro.views.index', name='home'),
    url(r'^establecimiento$', 'apps.registro.views.establecimiento.index', name='establecimiento'),
    url(r'^establecimiento/create', 'apps.registro.views.establecimiento.create', name='establecimientoCreate'),
    url(r'^establecimiento/([0-9]+)/delete', 'apps.registro.views.establecimiento.delete', name='establecimientoDelete'),
    # completar datos del establecimiento
    url(r'^establecimiento/completar_datos/', 'apps.registro.views.establecimiento.completar_datos', name='establecimientoCompletarDatos'),
    url(r'^establecimiento/([0-9]+)/completar_datos_basicos/', 'apps.registro.views.establecimiento.completar_datos_basicos', name='establecimientoCompletarDatosBasicos'),
    url(r'^establecimiento/([0-9]+)/completar_contacto/', 'apps.registro.views.establecimiento.completar_contacto', name='establecimientoCompletarContacto'),
    url(r'^establecimiento/([0-9]+)/completar_alcances/', 'apps.registro.views.establecimiento.completar_alcances', name='establecimientoCompletarAlcances'),
    url(r'^establecimiento/([0-9]+)/completar_funciones/', 'apps.registro.views.establecimiento.completar_funciones', name='establecimientoCompletarFunciones'),
    url(r'^establecimiento/([0-9]+)/completar_informacion_edilicia/', 'apps.registro.views.establecimiento.completar_informacion_edilicia', name='establecimientoCompletarInformacionEdilicia'),
    url(r'^establecimiento/([0-9]+)/completar_conexion_internet/', 'apps.registro.views.establecimiento.completar_conexion_internet', name='establecimientoCompletarConexionInternet'),
    url(r'^establecimiento/([0-9]+)/registrar', 'apps.registro.views.establecimiento.registrar', name='establecimientoRegistrar'),
    url(r'^establecimiento/datos$', 'apps.registro.views.establecimiento.datos_establecimiento', name='establecimientoDatos'),
    url(r'^establecimiento/([0-9]+)/detalle$', 'apps.registro.views.establecimiento.detalle', name='establecimientoDetalle'),
    url(r'^establecimiento/([0-9]+)/ajaxVerificarDato', 'apps.registro.views.establecimiento.verificar_dato', name='establecimientoVerificarDato'),

    # establecimiento domicilios
    url(r'^establecimiento/([0-9]+)/domicilios$', 'apps.registro.views.establecimiento_domicilio.index', name='establecimientoDomiciliosIndex'),
    url(r'^establecimiento/([0-9]+)/agregar_domicilio$', 'apps.registro.views.establecimiento_domicilio.create', name='establecimientoDomicilioCreate'),
    url(r'^establecimiento/domicilios/([0-9]+)/edit$', 'apps.registro.views.establecimiento_domicilio.edit', name='establecimientoDomicilioEdit'),
    url(r'^establecimiento/domicilios/([0-9]+)/delete$', 'apps.registro.views.establecimiento_domicilio.delete', name='establecimientoDomicilioDelete'),
    # establecimiento autoridades
    url(r'^establecimiento/([0-9]+)/autoridades$', 'apps.registro.views.establecimiento_autoridad.index', name='establecimientoAutoridadesIndex'),
    url(r'^establecimiento/([0-9]+)/agregar_autoridad$', 'apps.registro.views.establecimiento_autoridad.create', name='establecimientoAutoridadCreate'),
    url(r'^establecimiento/autoridades/([0-9]+)/edit$', 'apps.registro.views.establecimiento_autoridad.edit', name='establecimientoAutoridadEdit'),
    url(r'^establecimiento/autoridades/([0-9]+)/delete$', 'apps.registro.views.establecimiento_autoridad.delete', name='establecimientoAutoridadDelete'),
    # establecimiento turnos
    url(r'^establecimiento/([0-9]+)/turnos$', 'apps.registro.views.establecimiento_turno.index', name='establecimientoTurnosIndex'),
    url(r'^establecimiento/([0-9]+)/agregar_turno$', 'apps.registro.views.establecimiento_turno.create', name='establecimientoTurnosCreate'),
    url(r'^establecimiento/turnos/([0-9]+)/edit$', 'apps.registro.views.establecimiento_turno.edit', name='establecimientoTurnoEdit'),
    url(r'^establecimiento/turnos/([0-9]+)/delete$', 'apps.registro.views.establecimiento_turno.delete', name='establecimientoTurnoDelete'),
    # anexo
    url(r'^anexo$', 'apps.registro.views.anexo.index', name='anexo'),
    url(r'^anexo/create', 'apps.registro.views.anexo.create', name='anexoCreate'),
    url(r'^anexo/([0-9]+)/baja', 'apps.registro.views.anexo.baja', name='anexoBaja'),
    url(r'^anexo/([0-9]+)/delete', 'apps.registro.views.anexo.delete', name='anexoDelete'),
    url(r'^anexo/([0-9]+)/completar_datos_basicos/', 'apps.registro.views.anexo.completar_datos_basicos', name='anexoCompletarDatosBasicos'),
    url(r'^anexo/([0-9]+)/completar_contacto/', 'apps.registro.views.anexo.completar_contacto', name='anexoCompletarContacto'),
    url(r'^anexo/([0-9]+)/completar_turnos/', 'apps.registro.views.anexo.completar_turnos', name='anexoCompletarTurnos'),
    url(r'^anexo/([0-9]+)/completar_alcances/', 'apps.registro.views.anexo.completar_alcances', name='anexoCompletarAlcances'),
    url(r'^anexo/([0-9]+)/completar_funciones/', 'apps.registro.views.anexo.completar_funciones', name='anexoCompletarFunciones'),
    url(r'^anexo/([0-9]+)/completar_informacion_edilicia/', 'apps.registro.views.anexo.completar_informacion_edilicia', name='anexoCompletarInformacionEdilicia'),
    url(r'^anexo/([0-9]+)/completar_conexion_internet/', 'apps.registro.views.anexo.completar_conexion_internet', name='anexoCompletarConexionInternet'),
    url(r'^anexo/([0-9]+)/registrar', 'apps.registro.views.anexo.registrar', name='anexoRegistrar'),
    url(r'^anexo/([0-9]+)/ajaxVerificarDato', 'apps.registro.views.anexo.verificar_dato', name='anexoVerificarDato'),
    # anexo domicilios
    url(r'^anexo/([0-9]+)/domicilios$', 'apps.registro.views.anexo_domicilio.index', name='anexoDomiciliosIndex'),
    url(r'^anexo/([0-9]+)/agregar_domicilio$', 'apps.registro.views.anexo_domicilio.create', name='anexoDomicilioCreate'),
    url(r'^anexo/domicilios/([0-9]+)/edit$', 'apps.registro.views.anexo_domicilio.edit', name='anexoDomicilioEdit'),
    url(r'^anexo/domicilios/([0-9]+)/delete$', 'apps.registro.views.anexo_domicilio.delete', name='anexoDomicilioDelete'),
    # anexo autoridades
    url(r'^anexo/([0-9]+)/autoridades$', 'apps.registro.views.anexo_autoridad.index', name='anexoAutoridadesIndex'),
    url(r'^anexo/([0-9]+)/agregar_autoridad$', 'apps.registro.views.anexo_autoridad.create', name='anexoAutoridadCreate'),
    url(r'^anexo/autoridades/([0-9]+)/edit$', 'apps.registro.views.anexo_autoridad.edit', name='anexoAutoridadEdit'),
    url(r'^anexo/autoridades/([0-9]+)/delete$', 'apps.registro.views.anexo_autoridad.delete', name='anexoAutoridadDelete'),
    # extensiones aulicas
    url(r'^extension_aulica$', 'apps.registro.views.extension_aulica.index', name='extensionAulica'),
    url(r'^extension_aulica/create', 'apps.registro.views.extension_aulica.create', name='extensionAulicaCreate'),
    url(r'^extension_aulica/([0-9]+)/baja', 'apps.registro.views.extension_aulica.baja', name='extensionAulicaBaja'),
    url(r'^extension_aulica/([0-9]+)/delete', 'apps.registro.views.extension_aulica.delete', name='extensionAulicaDelete'),
    url(r'^extension_aulica/([0-9]+)/completar_datos_basicos/', 'apps.registro.views.extension_aulica.completar_datos_basicos', name='extensionAulicaCompletarDatosBasicos'),
    url(r'^extension_aulica/([0-9]+)/completar_contacto/', 'apps.registro.views.extension_aulica.completar_contacto', name='extensionAulicaCompletarContacto'),
    url(r'^extension_aulica/([0-9]+)/completar_turnos/', 'apps.registro.views.extension_aulica.completar_turnos', name='extensionAulicaCompletarTurnos'),
    url(r'^extension_aulica/([0-9]+)/completar_alcances/', 'apps.registro.views.extension_aulica.completar_alcances', name='extensionAulicaCompletarAlcances'),
    url(r'^extension_aulica/([0-9]+)/completar_funciones/', 'apps.registro.views.extension_aulica.completar_funciones', name='extensionAulicaCompletarFunciones'),
    url(r'^extension_aulica/([0-9]+)/completar_informacion_edilicia/', 'apps.registro.views.extension_aulica.completar_informacion_edilicia', name='extensionAulicaCompletarInformacionEdilicia'),
    url(r'^extension_aulica/([0-9]+)/completar_conexion_internet/', 'apps.registro.views.extension_aulica.completar_conexion_internet', name='extensionAulicaCompletarConexionInternet'),
    url(r'^extension_aulica/([0-9]+)/domicilios$', 'apps.registro.views.extension_aulica_domicilio.index', name='extensionAulicaDomiciliosIndex'),
    url(r'^extension_aulica/([0-9]+)/agregar_domicilio$', 'apps.registro.views.extension_aulica_domicilio.create', name='extensionAulicaDomicilioCreate'),
    url(r'^extension_aulica/domicilios/([0-9]+)/edit$', 'apps.registro.views.extension_aulica_domicilio.edit', name='extensionAulicaDomicilioEdit'),
    url(r'^extension_aulica/domicilios/([0-9]+)/delete$', 'apps.registro.views.extension_aulica_domicilio.delete', name='extensionAulicaDomicilioDelete'),
    url(r'^extension_aulica/([0-9]+)/registrar', 'apps.registro.views.extension_aulica.registrar', name='extensionAulicaRegistrar'),
    url(r'^extension_aulica/([0-9]+)/ajaxVerificarDato', 'apps.registro.views.extension_aulica.verificar_dato', name='extensionAulicaVerificarDato'),
    # dependencias funcionales
    url(r'^dependencia_funcional$', 'apps.registro.views.dependencia_funcional.index', name='dependenciaFuncional'),
    url(r'^dependencia_funcional/([0-9]+)/edit', 'apps.registro.views.dependencia_funcional.edit', name='dependenciaFuncionalEdit'),
    url(r'^dependencia_funcional/create', 'apps.registro.views.dependencia_funcional.create', name='dependenciaFuncionalCreate'),
    url(r'^dependencia_funcional/([0-9]+)/delete', 'apps.registro.views.dependencia_funcional.delete', name='dependenciaFuncionalDelete'),
    # AJAX
    url(r'^ajax/get_localidades_por_departamento/(?P<departamento_id>[0-9]+)', 'apps.registro.views.ajax.get_localidades_por_departamento', name='ajaxGetLocalidadesPorTipo'),
    url(r'^ajax/get_departamentos_por_jurisdiccion/(?P<jurisdiccion_id>[0-9]+)', 'apps.registro.views.ajax.get_departamentos_por_jurisdiccion', name='ajaxGetDepartamentosPorJurisdiccion'),
    url(r'^ajax/get_cue_parts_from_sede/(?P<sede_id>[0-9]+)', 'apps.registro.views.ajax.get_cue_parts_from_sede', name='ajaxGetCuePartsFromSede'),
   )
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals

import frappe
import unittest
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import delete_accounting_dimension

class TestAccountingDimension(unittest.TestCase):
	def setUp(self):
		frappe.set_user("Administrator")

		if not frappe.db.exists("Accounting Dimension", {"document_type": "Department"}):
			dimension = frappe.get_doc({
				"doctype": "Accounting Dimension",
				"document_type": "Department",
			}).insert()
		else:
			dimension1 = frappe.get_doc("Accounting Dimension", "Department")
			dimension1.disabled = 0
			dimension1.save()

		if not frappe.db.exists("Accounting Dimension", {"document_type": "Location"}):
			dimension1 = frappe.get_doc({
				"doctype": "Accounting Dimension",
				"document_type": "Location",
				"mandatory_for_pl": 1
			}).insert()
		else:
			dimension1 = frappe.get_doc("Accounting Dimension", "Location")
			dimension1.disabled = 0
			dimension1.mandatory_for_pl = 1
			dimension1.save()

	def test_dimension_against_sales_invoice(self):
		si = create_sales_invoice(do_not_save=1)

		si.location = "Block 1"
		si.append("items", {
			"item_code": "_Test Item",
			"warehouse": "_Test Warehouse - _TC",
			"qty": 1,
			"rate": 100,
			"income_account": "Sales - _TC",
			"expense_account": "Cost of Goods Sold - _TC",
			"cost_center": "_Test Cost Center - _TC",
			"department": "_Test Department - _TC",
			"location": "Block 1"
		})

		si.save()
		si.submit()

		gle = frappe.get_doc("GL Entry", {"voucher_no": si.name, "account": "Sales - _TC"})

		self.assertEqual(gle.get('department'), "_Test Department - _TC")

	def test_dimension_against_journal_entry(self):
		je = make_journal_entry("Sales - _TC", "Sales Expenses - _TC", 500, save=False)
		je.accounts[0].update({"department": "_Test Department - _TC"})
		je.accounts[1].update({"department": "_Test Department - _TC"})

		je.accounts[0].update({"location": "Block 1"})
		je.accounts[1].update({"location": "Block 1"})

		je.save()
		je.submit()

		gle = frappe.get_doc("GL Entry", {"voucher_no": je.name, "account": "Sales - _TC"})
		gle1 = frappe.get_doc("GL Entry", {"voucher_no": je.name, "account": "Sales Expenses - _TC"})
		self.assertEqual(gle.get('department'), "_Test Department - _TC")
		self.assertEqual(gle1.get('department'), "_Test Department - _TC")

	def test_mandatory(self):
		si = create_sales_invoice(do_not_save=1)
		si.append("items", {
			"item_code": "_Test Item",
			"warehouse": "_Test Warehouse - _TC",
			"qty": 1,
			"rate": 100,
			"income_account": "Sales - _TC",
			"expense_account": "Cost of Goods Sold - _TC",
			"cost_center": "_Test Cost Center - _TC",
			"location": ""
		})

		si.save()
		self.assertRaises(frappe.ValidationError, si.submit)

	def tearDown(self):
		disable_dimension()

def disable_dimension():
	dimension1 = frappe.get_doc("Accounting Dimension", "Department")
	dimension1.disabled = 1
	dimension1.save()

	dimension2 = frappe.get_doc("Accounting Dimension", "Location")
	dimension2.mandatory_for_pl = 0
	dimension2.disabled = 1
	dimension2.save()

<commit_msg>fix: Test Cases for accounting dimensions<commit_after># -*- coding: utf-8 -*-
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals

import frappe
import unittest
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import delete_accounting_dimension

class TestAccountingDimension(unittest.TestCase):
	def setUp(self):
		frappe.set_user("Administrator")

		if not frappe.db.exists("Accounting Dimension", {"document_type": "Department"}):
			dimension = frappe.get_doc({
				"doctype": "Accounting Dimension",
				"document_type": "Department",
			}).insert()
		else:
			dimension1 = frappe.get_doc("Accounting Dimension", "Department")
			dimension1.disabled = 0
			dimension1.save()

		if not frappe.db.exists("Accounting Dimension", {"document_type": "Location"}):
			dimension1 = frappe.get_doc({
				"doctype": "Accounting Dimension",
				"document_type": "Location",
				"mandatory_for_pl": 1
			})

			dimension1.append("dimension_defaults", {
				"company": "_Test Company",
				"reference_document": "Location",
				"default_dimension": "Block 1",
				"mandatory_for_pl": 1
			})

			dimension1.insert()
			dimension1.save()
		else:
			dimension1 = frappe.get_doc("Accounting Dimension", "Location")
			dimension1.disabled = 0
			dimension1.save()

	def test_dimension_against_sales_invoice(self):
		si = create_sales_invoice(do_not_save=1)

		si.location = "Block 1"
		si.append("items", {
			"item_code": "_Test Item",
			"warehouse": "_Test Warehouse - _TC",
			"qty": 1,
			"rate": 100,
			"income_account": "Sales - _TC",
			"expense_account": "Cost of Goods Sold - _TC",
			"cost_center": "_Test Cost Center - _TC",
			"department": "_Test Department - _TC",
			"location": "Block 1"
		})

		si.save()
		si.submit()

		gle = frappe.get_doc("GL Entry", {"voucher_no": si.name, "account": "Sales - _TC"})

		self.assertEqual(gle.get('department'), "_Test Department - _TC")

	def test_dimension_against_journal_entry(self):
		je = make_journal_entry("Sales - _TC", "Sales Expenses - _TC", 500, save=False)
		je.accounts[0].update({"department": "_Test Department - _TC"})
		je.accounts[1].update({"department": "_Test Department - _TC"})

		je.accounts[0].update({"location": "Block 1"})
		je.accounts[1].update({"location": "Block 1"})

		je.save()
		je.submit()

		gle = frappe.get_doc("GL Entry", {"voucher_no": je.name, "account": "Sales - _TC"})
		gle1 = frappe.get_doc("GL Entry", {"voucher_no": je.name, "account": "Sales Expenses - _TC"})
		self.assertEqual(gle.get('department'), "_Test Department - _TC")
		self.assertEqual(gle1.get('department'), "_Test Department - _TC")

	def test_mandatory(self):
		si = create_sales_invoice(do_not_save=1)
		si.append("items", {
			"item_code": "_Test Item",
			"warehouse": "_Test Warehouse - _TC",
			"qty": 1,
			"rate": 100,
			"income_account": "Sales - _TC",
			"expense_account": "Cost of Goods Sold - _TC",
			"cost_center": "_Test Cost Center - _TC",
			"location": ""
		})

		si.save()
		self.assertRaises(frappe.ValidationError, si.submit)

	def tearDown(self):
		disable_dimension()

def disable_dimension():
	dimension1 = frappe.get_doc("Accounting Dimension", "Department")
	dimension1.disabled = 1
	dimension1.save()

	dimension2 = frappe.get_doc("Accounting Dimension", "Location")
	dimension2.mandatory_for_pl = 0
	dimension2.disabled = 1
	dimension2.save()

<|endoftext|>