<commit_before>#!/usr/bin/python

"""
Testing Time Machine
--------------------
"""

from heapq import heappop

from bacpypes.debugging import bacpypes_debugging, ModuleLogger

import bacpypes.core as _core
from bacpypes.task import TaskManager as _TaskManager

# some debugging
_debug = 0
_log = ModuleLogger(globals())

# time machine
time_machine = None

# @bacpypes_debugging - implicit via metaclass
class TimeMachine(_TaskManager):

    def __init__(self):
        if _debug: TimeMachine._debug("__init__")
        global time_machine

        # pass along initialization
        _TaskManager.__init__(self)

        # initialize the time
        self.current_time = None
        self.time_limit = None

        # a little error checking
        if time_machine:
            raise RuntimeError("time machine already created")

        # save a reference
        time_machine = self

    def get_time(self):
        if _debug: TimeMachine._debug("get_time @ %r:", self.current_time)

        # return the fake time
        return self.current_time

    def install_task(self, task):
        if _debug: TimeMachine._debug("install_task @ %r: %r @ %r", self.current_time, task, task.taskTime)

        _TaskManager.install_task(self, task)

    def suspend_task(self, task):
        if _debug: TimeMachine._debug("suspend_task @ %r: %r", self.current_time, task)

        _TaskManager.suspend_task(self, task)

    def resume_task(self, task):
        if _debug: TimeMachine._debug("resume_task @ %r: %r", self.current_time, task)

        _TaskManager.resume_task(self, task)

    def more_to_do(self):
        """Get the next task if there's one that should be processed."""
        if _debug: TimeMachine._debug("more_to_do @ %r:", self.current_time)

        # check if there are deferred functions
        if _core.deferredFns:
            if _debug: TimeMachine._debug("    - deferred functions")
            return True

        if _debug: TimeMachine._debug("    - time_limit: %r", self.time_limit)
        if _debug: TimeMachine._debug("    - tasks: %r", self.tasks)

        if (self.time_limit is not None) and (self.current_time >= self.time_limit):
            if _debug: TimeMachine._debug("    - time limit reached")
            return False

        if not self.tasks:
            if _debug: TimeMachine._debug("    - no more tasks")
            return False

        # peek at the next task and see when it is supposed to run
        when, task = self.tasks[0]
        if when >= self.time_limit:
            if _debug: TimeMachine._debug("    - time limit reached")
            return False
        if _debug: TimeMachine._debug("    - task: %r", task)

        # there is a task to run
        return True

    def get_next_task(self):
        """get the next task if there's one that should be processed,
        and return how long it will be until the next one should be
        processed."""
        if _debug: TimeMachine._debug("get_next_task @ %r:", self.current_time)
        if _debug: TimeMachine._debug("    - time_limit: %r", self.time_limit)
        if _debug: TimeMachine._debug("    - tasks: %r", self.tasks)

        task = None
        delta = None

        if (self.time_limit is not None) and (self.current_time >= self.time_limit):
            if _debug: TimeMachine._debug("    - time limit reached")

        elif not self.tasks:
            if _debug: TimeMachine._debug("    - no more tasks")

        else:
            # peek at the next task and see when it is supposed to run
            when, _ = self.tasks[0]
            if when >= self.time_limit:
                if _debug: TimeMachine._debug("    - time limit reached")

                # bump up to the time limit
                self.current_time = self.time_limit

            else:
                # pull it off the list
                when, task = heappop(self.tasks)
                if _debug: TimeMachine._debug("    - when, task: %r, %s", when, task)

                # mark that it is no longer scheduled
                task.isScheduled = False

                # advance the time
                self.current_time = when

                # do not wait, time has moved
                delta = 0.0

        # return the task to run and how long to wait for the next one
        return (task, delta)

    def process_task(self, task):
        if _debug: TimeMachine._debug("process_task @ %r: %r", self.current_time, task)

        _TaskManager.process_task(self, task)

@bacpypes_debugging
def reset_time_machine():
    """This function is called to reset the clock before running a set
    of tests.
    """
    if _debug: reset_time_machine._debug("reset_time_machine")
    global time_machine

    # a little error checking
    if not time_machine:
        raise RuntimeError("no time machine")

    # begin time at the beginning
    time_machine.tasks = []
    time_machine.current_time = 0.0
    time_machine.time_limit = None

@bacpypes_debugging
def run_time_machine(time_limit):
    """This function is called after a set of tasks have been installed
    and they should run.  The machine will stop when the limit has been
    reached (maybe the middle of some tests) and can be called again to
    continue running.
    """
    if _debug: run_time_machine._debug("run_time_machine %r", time_limit)
    global time_machine

    # a little error checking
    if not time_machine:
        raise RuntimeError("no time machine")
    if time_limit <= 0.0:
        raise ValueError("time limit required")
    if time_machine.current_time is None:
        raise RuntimeError("reset the time machine before running")

    # pass the limit to the time machine
    time_machine.time_limit = time_machine.current_time + time_limit

    # check if there are deferred functions
    if _core.deferredFns:
        if _debug: run_time_machine._debug("    - deferred functions!")

    # run until there is nothing left to do
    while True:
        _core.run_once()
        if _debug: run_time_machine._debug("    - ran once")

        if not time_machine.more_to_do():
            if _debug: run_time_machine._debug("    - no more to do")
            break

<commit_msg>add a function that returns the current time from inside the time machine<commit_after>#!/usr/bin/python

"""
Testing Time Machine
--------------------
"""

from heapq import heappop

from bacpypes.debugging import bacpypes_debugging, ModuleLogger

import bacpypes.core as _core
from bacpypes.task import TaskManager as _TaskManager

# some debugging
_debug = 0
_log = ModuleLogger(globals())

# time machine
time_machine = None

# @bacpypes_debugging - implicit via metaclass
class TimeMachine(_TaskManager):

    def __init__(self):
        if _debug: TimeMachine._debug("__init__")
        global time_machine

        # pass along initialization
        _TaskManager.__init__(self)

        # initialize the time
        self.current_time = None
        self.time_limit = None

        # a little error checking
        if time_machine:
            raise RuntimeError("time machine already created")

        # save a reference
        time_machine = self

    def get_time(self):
        if _debug: TimeMachine._debug("get_time @ %r:", self.current_time)

        # return the fake time
        return self.current_time

    def install_task(self, task):
        if _debug: TimeMachine._debug("install_task @ %r: %r @ %r", self.current_time, task, task.taskTime)

        _TaskManager.install_task(self, task)

    def suspend_task(self, task):
        if _debug: TimeMachine._debug("suspend_task @ %r: %r", self.current_time, task)

        _TaskManager.suspend_task(self, task)

    def resume_task(self, task):
        if _debug: TimeMachine._debug("resume_task @ %r: %r", self.current_time, task)

        _TaskManager.resume_task(self, task)

    def more_to_do(self):
        """Get the next task if there's one that should be processed."""
        if _debug: TimeMachine._debug("more_to_do @ %r:", self.current_time)

        # check if there are deferred functions
        if _core.deferredFns:
            if _debug: TimeMachine._debug("    - deferred functions")
            return True

        if _debug: TimeMachine._debug("    - time_limit: %r", self.time_limit)
        if _debug: TimeMachine._debug("    - tasks: %r", self.tasks)

        if (self.time_limit is not None) and (self.current_time >= self.time_limit):
            if _debug: TimeMachine._debug("    - time limit reached")
            return False

        if not self.tasks:
            if _debug: TimeMachine._debug("    - no more tasks")
            return False

        # peek at the next task and see when it is supposed to run
        when, task = self.tasks[0]
        if when >= self.time_limit:
            if _debug: TimeMachine._debug("    - time limit reached")
            return False
        if _debug: TimeMachine._debug("    - task: %r", task)

        # there is a task to run
        return True

    def get_next_task(self):
        """get the next task if there's one that should be processed,
        and return how long it will be until the next one should be
        processed."""
        if _debug: TimeMachine._debug("get_next_task @ %r:", self.current_time)
        if _debug: TimeMachine._debug("    - time_limit: %r", self.time_limit)
        if _debug: TimeMachine._debug("    - tasks: %r", self.tasks)

        task = None
        delta = None

        if (self.time_limit is not None) and (self.current_time >= self.time_limit):
            if _debug: TimeMachine._debug("    - time limit reached")

        elif not self.tasks:
            if _debug: TimeMachine._debug("    - no more tasks")

        else:
            # peek at the next task and see when it is supposed to run
            when, _ = self.tasks[0]
            if when >= self.time_limit:
                if _debug: TimeMachine._debug("    - time limit reached")

                # bump up to the time limit
                self.current_time = self.time_limit

            else:
                # pull it off the list
                when, task = heappop(self.tasks)
                if _debug: TimeMachine._debug("    - when, task: %r, %s", when, task)

                # mark that it is no longer scheduled
                task.isScheduled = False

                # advance the time
                self.current_time = when

                # do not wait, time has moved
                delta = 0.0

        # return the task to run and how long to wait for the next one
        return (task, delta)

    def process_task(self, task):
        if _debug: TimeMachine._debug("process_task @ %r: %r", self.current_time, task)

        _TaskManager.process_task(self, task)

@bacpypes_debugging
def reset_time_machine():
    """This function is called to reset the clock before running a set
    of tests.
    """
    if _debug: reset_time_machine._debug("reset_time_machine")
    global time_machine

    # a little error checking
    if not time_machine:
        raise RuntimeError("no time machine")

    # begin time at the beginning
    time_machine.tasks = []
    time_machine.current_time = 0.0
    time_machine.time_limit = None

@bacpypes_debugging
def run_time_machine(time_limit):
    """This function is called after a set of tasks have been installed
    and they should run.  The machine will stop when the limit has been
    reached (maybe the middle of some tests) and can be called again to
    continue running.
    """
    if _debug: run_time_machine._debug("run_time_machine %r", time_limit)
    global time_machine

    # a little error checking
    if not time_machine:
        raise RuntimeError("no time machine")
    if time_limit <= 0.0:
        raise ValueError("time limit required")
    if time_machine.current_time is None:
        raise RuntimeError("reset the time machine before running")

    # pass the limit to the time machine
    time_machine.time_limit = time_machine.current_time + time_limit

    # check if there are deferred functions
    if _core.deferredFns:
        if _debug: run_time_machine._debug("    - deferred functions!")

    # run until there is nothing left to do
    while True:
        _core.run_once()
        if _debug: run_time_machine._debug("    - ran once")

        if not time_machine.more_to_do():
            if _debug: run_time_machine._debug("    - no more to do")
            break

def current_time():
    """Return the current time from the time machine."""
    global time_machine

    return time_machine.current_time

<|endoftext|>


<commit_before>from django.db import models
from django.dispatch import receiver
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from django.db.models.signals import post_save
from django.utils import timezone
from datetime import datetime, date, timedelta
import pytz
from dateutil.relativedelta import relativedelta

OUTCOME = 0
INCOME = 1
#Savings has it's own category because it must be grouped together
SAVINGS = 2
# System Categories are those not being accounted
SYSTEM_CATEGORIES = 3
TYPE_CATEGORY_CHOICES = ((OUTCOME, _('Outcome')),(INCOME, _('Income')), (SAVINGS, _('Savings')),
                         (SYSTEM_CATEGORIES, _('System Internals')))

INITIAL_BALANCE_SLUG = 'initial_balance'
UNSCHEDULED_DEBT_SLUG = 'unscheduled_debt'
UNSCHEDULED_CREDIT_SLUG = 'unscheduled_credit'

class Category(models.Model):
    name = models.CharField(max_length=50)
    type_category = models.IntegerField(choices=TYPE_CATEGORY_CHOICES)
    slug = models.SlugField(null=True)
    user = models.ForeignKey(User, blank=True, null=True)

    def __unicode__(self):
        return self.name

    class Meta:
        ordering = ('type_category','name')
        verbose_name_plural = _('Categories')

    # TODO: Prevent from changing the slug from System Categories

def tmz(naive_date):
        return naive_date.replace(tzinfo = pytz.utc)

def get_last_day_of_month(month, year):
    start_date = datetime(day=1, month=month, year=year)
    start_date = (start_date+relativedelta(months=1))-timedelta(days=1)
    return tmz(start_date)

class Record(models.Model):
    description = models.CharField(max_length=50, blank=True)
    category = models.ForeignKey(Category, help_text=_('Select the category for this record. This field is required'))
    amount = models.FloatField(default=0, verbose_name=_("How much?"),help_text=_("Please, use only the monthly amount. This field is required"))
    start_date = models.DateTimeField(default=timezone.now, verbose_name=_('Date'), help_text=_('This field is required'))
    day_of_month = models.SmallIntegerField(blank=True, null=True, verbose_name=_("Day of the month"), help_text=_('Use this field to set recurring bills. The day in which will you be billed every month'))
    number_payments = models.SmallIntegerField(blank=True, null=True, verbose_name=_("Number of Payments"), help_text=_('This is only used to generate the final payment date'))
    end_date = models.DateTimeField(blank=True, null=True, verbose_name=_('Last payment on'), help_text=_('This is the date when it will be the last payment for this record, after this date the record will not appear on the calculations'))
    is_paid_out = models.BooleanField(default=False, verbose_name=_('Is it totally paid?'), help_text=_('If checked, the record won\'t appear in the calculations anymore. Click it only to hide a record from your spreadsheet'))
    notes = models.TextField(blank=True, null=True)
    user = models.ForeignKey(User, blank=True, null=True)

    def __unicode__(self):
        return "%s %s %s" % (self.description,self.category,self.amount)

    def _get_valid_date_of_month(self, month, year):
        day = 1
        if self.day_of_month:
            if not(self.day_of_month in range(1,32)):
                # Invalid day, return 1
                day = 1

            # Avoid returning 31 of February for example
            last_day = get_last_day_of_month(month, year)
            if self.day_of_month > last_day.day:
                day = last_day.day
            else:
                day = self.day_of_month

        return tmz(datetime(day=day, month=month, year=year))

    def get_date_for_month(self, month=None, year=None):
        """
        Get date for the record, but when it's recurring, will get the date object for the month using the day_of_month
        For recurring objects, month and year are required
        """

        # Check if parameters are given, then if it's not
        # current month (and not same month in different year) and finally if there is a day of the month
        if month and year:
            if (((month != self.start_date.month) or
                    (month == self.start_date.month) and (year != self.start_date.year))
                and
                    self.day_of_month):
                return self._get_valid_date_of_month(month, year)

        return self.start_date

    def is_accountable(self, initial_date=None):
        """
        An accountable record is all records that are in the same day or after the initial balance for the month
        """
        record_date = self.get_date_for_month(initial_date.month, initial_date.year)
        return initial_date <= record_date

    # TODO: on saving System Categories, make sure invalid fields are not being saved like end_date

@receiver(post_save, sender=User)
def generate_default_categories(sender, instance, created, **kwargs):
    default_categories = (
        (_('Salary'),'salary', INCOME),
        (_('Food & Goods'),'food', OUTCOME),
        (_('House Expenses'),'house', OUTCOME),
        (_('Extra Income'),'extra_income', INCOME),
        (_('Extra Outcome'),'extra_outcome', OUTCOME),
        (_('Savings'),'savings', SAVINGS),
        (_('Monthly Balance'),INITIAL_BALANCE_SLUG, SYSTEM_CATEGORIES),
        (_('Unscheduled Debts'),UNSCHEDULED_DEBTS_SLUG, SYSTEM_CATEGORIES),
        (_('Unscheduled Credit'),UNSCHEDULED_CREDIT_SLUG, SYSTEM_CATEGORIES),
    )
    if created:
        # Create default categories for the new user
        for category in default_categories:
            Category.objects.create(
                name = category[0],
                slug = category[1],
                type_category = category[2],
                user = instance,
            )

        # Create initial balance for last month, otherwise goes into infinite loop
        Record.objects.create(
            description = _('Initial Balance'),
            category = Category.objects.get(slug=INITIAL_BALANCE_SLUG, type_category=SYSTEM_CATEGORIES, user=instance),
            amount = 0,
            start_date = timezone.now().replace(day=1),
            user = instance
        )
<commit_msg>Fixed slug variable<commit_after>from django.db import models
from django.dispatch import receiver
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from django.db.models.signals import post_save
from django.utils import timezone
from datetime import datetime, date, timedelta
import pytz
from dateutil.relativedelta import relativedelta

OUTCOME = 0
INCOME = 1
#Savings has it's own category because it must be grouped together
SAVINGS = 2
# System Categories are those not being accounted
SYSTEM_CATEGORIES = 3
TYPE_CATEGORY_CHOICES = ((OUTCOME, _('Outcome')),(INCOME, _('Income')), (SAVINGS, _('Savings')),
                         (SYSTEM_CATEGORIES, _('System Internals')))

INITIAL_BALANCE_SLUG = 'initial_balance'
UNSCHEDULED_DEBT_SLUG = 'unscheduled_debt'
UNSCHEDULED_CREDIT_SLUG = 'unscheduled_credit'

class Category(models.Model):
    name = models.CharField(max_length=50)
    type_category = models.IntegerField(choices=TYPE_CATEGORY_CHOICES)
    slug = models.SlugField(null=True)
    user = models.ForeignKey(User, blank=True, null=True)

    def __unicode__(self):
        return self.name

    class Meta:
        ordering = ('type_category','name')
        verbose_name_plural = _('Categories')

    # TODO: Prevent from changing the slug from System Categories

def tmz(naive_date):
        return naive_date.replace(tzinfo = pytz.utc)

def get_last_day_of_month(month, year):
    start_date = datetime(day=1, month=month, year=year)
    start_date = (start_date+relativedelta(months=1))-timedelta(days=1)
    return tmz(start_date)

class Record(models.Model):
    description = models.CharField(max_length=50, blank=True)
    category = models.ForeignKey(Category, help_text=_('Select the category for this record. This field is required'))
    amount = models.FloatField(default=0, verbose_name=_("How much?"),help_text=_("Please, use only the monthly amount. This field is required"))
    start_date = models.DateTimeField(default=timezone.now, verbose_name=_('Date'), help_text=_('This field is required'))
    day_of_month = models.SmallIntegerField(blank=True, null=True, verbose_name=_("Day of the month"), help_text=_('Use this field to set recurring bills. The day in which will you be billed every month'))
    number_payments = models.SmallIntegerField(blank=True, null=True, verbose_name=_("Number of Payments"), help_text=_('This is only used to generate the final payment date'))
    end_date = models.DateTimeField(blank=True, null=True, verbose_name=_('Last payment on'), help_text=_('This is the date when it will be the last payment for this record, after this date the record will not appear on the calculations'))
    is_paid_out = models.BooleanField(default=False, verbose_name=_('Is it totally paid?'), help_text=_('If checked, the record won\'t appear in the calculations anymore. Click it only to hide a record from your spreadsheet'))
    notes = models.TextField(blank=True, null=True)
    user = models.ForeignKey(User, blank=True, null=True)

    def __unicode__(self):
        return "%s %s %s" % (self.description,self.category,self.amount)

    def _get_valid_date_of_month(self, month, year):
        day = 1
        if self.day_of_month:
            if not(self.day_of_month in range(1,32)):
                # Invalid day, return 1
                day = 1

            # Avoid returning 31 of February for example
            last_day = get_last_day_of_month(month, year)
            if self.day_of_month > last_day.day:
                day = last_day.day
            else:
                day = self.day_of_month

        return tmz(datetime(day=day, month=month, year=year))

    def get_date_for_month(self, month=None, year=None):
        """
        Get date for the record, but when it's recurring, will get the date object for the month using the day_of_month
        For recurring objects, month and year are required
        """

        # Check if parameters are given, then if it's not
        # current month (and not same month in different year) and finally if there is a day of the month
        if month and year:
            if (((month != self.start_date.month) or
                    (month == self.start_date.month) and (year != self.start_date.year))
                and
                    self.day_of_month):
                return self._get_valid_date_of_month(month, year)

        return self.start_date

    def is_accountable(self, initial_date=None):
        """
        An accountable record is all records that are in the same day or after the initial balance for the month
        """
        record_date = self.get_date_for_month(initial_date.month, initial_date.year)
        return initial_date <= record_date

    # TODO: on saving System Categories, make sure invalid fields are not being saved like end_date

@receiver(post_save, sender=User)
def generate_default_categories(sender, instance, created, **kwargs):
    default_categories = (
        (_('Salary'),'salary', INCOME),
        (_('Food & Goods'),'food', OUTCOME),
        (_('House Expenses'),'house', OUTCOME),
        (_('Extra Income'),'extra_income', INCOME),
        (_('Extra Outcome'),'extra_outcome', OUTCOME),
        (_('Savings'),'savings', SAVINGS),
        (_('Monthly Balance'),INITIAL_BALANCE_SLUG, SYSTEM_CATEGORIES),
        (_('Unscheduled Debts'),UNSCHEDULED_DEBT_SLUG, SYSTEM_CATEGORIES),
        (_('Unscheduled Credit'),UNSCHEDULED_CREDIT_SLUG, SYSTEM_CATEGORIES),
    )
    if created:
        # Create default categories for the new user
        for category in default_categories:
            Category.objects.create(
                name = category[0],
                slug = category[1],
                type_category = category[2],
                user = instance,
            )

        # Create initial balance for last month, otherwise goes into infinite loop
        Record.objects.create(
            description = _('Initial Balance'),
            category = Category.objects.get(slug=INITIAL_BALANCE_SLUG, type_category=SYSTEM_CATEGORIES, user=instance),
            amount = 0,
            start_date = timezone.now().replace(day=1),
            user = instance
        )
<|endoftext|>


<commit_before>"""Test volume manipulation logic
"""
from __future__ import absolute_import, division, print_function

import types
import pytest
from traitlets.config import LoggingConfigurable

def test_binds(monkeypatch):
    import jupyterhub
    monkeypatch.setattr("jupyterhub.spawner.Spawner", _MockSpawner)
    from dockerspawner.dockerspawner import DockerSpawner
    d = DockerSpawner()
    d.user = types.SimpleNamespace(name='xyz')
    d.volumes = {
        'a': 'b',
        'c': {'bind': 'd', 'mode': 'Z'},
    }
    assert d.volume_binds == {
        'a': {'bind': 'b', 'mode': 'rw'},
        'c': {'bind': 'd', 'mode': 'Z'},
    }
    d.volumes = {'a': 'b', 'c': 'd', 'e': 'f'}
    assert d.volume_mount_points == ['b', 'd', 'f']
    d.volumes = {'/nfs/{username}': {'bind': '/home/{username}', 'mode': 'z'}}
    assert d.volume_binds == {'/nfs/xyz': {'bind': '/home/xyz', 'mode': 'z'}}
    assert d.volume_mount_points == ['/home/xyz']

def test_binds_with_email_as_username(monkeypatch):
    import jupyterhub
    monkeypatch.setattr("jupyterhub.spawner.Spawner", _MockSpawner)
    from dockerspawner.dockerspawner import DockerSpawner
    d2 = DockerSpawner()
    d2.user = types.SimpleNamespace(name='xyz@foo.bar')
    d2.volumes = {'/nfs/{username}': {'bind': '/home/{username}', 'mode': 'z'}}
    assert d2.volume_binds == {'/nfs/xyz_40foo_2Ebar': {'bind': '/home/xyz_40foo_2Ebar', 'mode': 'z'}}
    assert d2.volume_mount_points == ['/home/xyz_40foo_2Ebar']

class _MockSpawner(LoggingConfigurable):
    pass
<commit_msg>Revert "Test for email encoded usernames creates encoded volume name"<commit_after>"""Test volume manipulation logic
"""
from __future__ import absolute_import, division, print_function

import types
import pytest
from traitlets.config import LoggingConfigurable

def test_binds(monkeypatch):
    import jupyterhub
    monkeypatch.setattr("jupyterhub.spawner.Spawner", _MockSpawner)
    from dockerspawner.dockerspawner import DockerSpawner
    d = DockerSpawner()
    d.user = types.SimpleNamespace(name='xyz')
    d.volumes = {
        'a': 'b',
        'c': {'bind': 'd', 'mode': 'Z'},
    }
    assert d.volume_binds == {
        'a': {'bind': 'b', 'mode': 'rw'},
        'c': {'bind': 'd', 'mode': 'Z'},
    }
    d.volumes = {'a': 'b', 'c': 'd', 'e': 'f'}
    assert d.volume_mount_points == ['b', 'd', 'f']
    d.volumes = {'/nfs/{username}': {'bind': '/home/{username}', 'mode': 'z'}}
    assert d.volume_binds == {'/nfs/xyz': {'bind': '/home/xyz', 'mode': 'z'}}
    assert d.volume_mount_points == ['/home/xyz']

class _MockSpawner(LoggingConfigurable):
    pass
<|endoftext|>


<commit_before>#!/usr/bin/env python

import os
import re
import sys
import glob
import subprocess
from ctypes import c_int
from multiprocessing import Process, Lock, Value, BoundedSemaphore

#---------------------------------------------------------------------
# Extract scenarios from the specified test

def runTest(test):
    global dirname
    global results
    # test has the format of '.*/suites/<suite_name>/src/<test_name>(.erl)?'
    # Split the test in suite and name components using pattern matching
    rest1, name = os.path.split(test)
    rest2       = os.path.split(rest1)[0]
    suite       = os.path.split(rest2)[1]
    name = os.path.splitext(name)[0]
    if os.path.isdir(test):
        # Our test is a multi module directory
        dirn = test     # directory
        modn = "test"   # module name
        files = glob.glob(dirn + "/*.erl")
        files = [os.path.basename(f) for f in files]
    else:
        dirn = rest1
        modn = name
        files = [name + '.erl']
    # Create a dir to save the results
    try:
        os.makedirs(results + "/" + suite + "/results")
    except OSError:
        pass
    sema.acquire()
    # Compile it
    os.system("erlc -W0 -o %s %s/%s.erl" % (dirn, dirn, modn))
    # And extract scenarios from it
    pout = subprocess.Popen(
            ["erl -noinput -pa %s -pa %s -s scenarios extract %s -s init stop"
            % (dirname, dirn, modn)], stdout=subprocess.PIPE, shell=True)
    sema.release()
    procS = []
    for scenario in pout.stdout:
        # scenario has the format of {<mod_name>,<func_name>,<preb>}\n
        scen = scenario.strip("{}\n").split(",")
        # And run the test
        p = Process(target=runScenario,
                args=(suite, name, modn, scen[1], scen[2], scen[3], dirn, files))
        p.start()
        procS.append(p)
    pout.stdout.close()
    # Wait
    for p in procS:
        p.join()

#---------------------------------------------------------------------
# Run the specified scenario and print the results

def runScenario(suite, name, modn, funn, preb, flag, dirn, files):
    global concuerror
    global results
    global dirname
    global sema
    global lock
    global total_tests
    global total_failed
    if flag == "dpor":
        conc_flag = "--dpor"
        file_ext  = "-dpor"
    else:
        conc_flag = ""
        file_ext  = ""
    sema.acquire()
    # Run concuerror
    os.system(("cd %s && %s --target %s %s --files %s " +
               "--output %s/%s/results/%s-%s-%s%s.txt --preb %s --quiet %s")
            % (dirn, concuerror, modn, funn, ' '.join(files), results,
               suite, name, funn, preb, file_ext, preb, conc_flag))
    # Compare the results
    orig = ("%s/suites/%s/results/%s-%s-%s%s.txt"
            % (dirname, suite, name, funn, preb, file_ext))
    rslt = ("%s/%s/results/%s-%s-%s%s.txt"
            % (results, suite, name, funn, preb, file_ext))
    equalRes = equalResults(orig, rslt)
    sema.release()
    # Print the results
    lock.acquire()
    total_tests.value += 1
    if equalRes:
        # We don't need to keep the results file
        os.remove(rslt)
        print "%-10s %-20s %-50s  \033[01;32mok\033[00m" % \
                (suite, name, "("+funn+",  "+preb+",  "+flag+")")
    else:
        total_failed.value += 1
        print "%-10s %-20s %-50s  \033[01;31mfailed\033[00m" % \
                (suite, name, "("+funn+",  "+preb+",  "+flag+")")
    lock.release()

def equalResults(f1, f2):
    try:
        fp1 = open(f1, 'r')
    except IOError:
        return False
    try:
        fp2 = open(f2, 'r')
    except IOError:
        fp1.close()
        return False
    while True:
        l1 = fp1.readline()
        l2 = fp2.readline()
        if (l1 != l2) and (not ignoreLine(l1)):
            fp1.close(); fp2.close()
            return False
        if not l1:
            fp1.close(); fp2.close()
            return True

def ignoreLine(line):
    global ignore_matches
    for match in ignore_matches:
        if re.search(match, line):
            return True
    return False

#---------------------------------------------------------------------
# Main program

# Compile some regular expressions
match_pids = re.compile("<\d+\.\d+\.\d+>")
match_refs = re.compile("#Ref<[\d\.]+>")
#match_file = re.compile("suites/.+/src/.*\.erl")
ignore_matches = [match_pids, match_refs]

# Get the directory of Concuerror's testsuite
dirname = os.path.abspath(os.path.dirname(sys.argv[0]))
concuerror = os.path.abspath(dirname + "/../concuerror")
results = os.path.abspath(dirname + "/results")

# Cleanup temp files
# TODO: make it os independent
os.system("find %s \( -name '*.beam' -o -name '*.dump' \) -exec rm {} \;" % dirname)
os.system("rm -rf %s/*" % results)

# Compile scenarios.erl
os.system("erlc %s/scenarios.erl" % dirname)

# If we have arguments we should use them as tests,
# otherwise check them all
if len(sys.argv) > 1:
    tests = sys.argv[1:]
    tests = [os.path.abspath(item) for item in tests]
else:
    tests = glob.glob(dirname + "/suites/*/src/*")

# How many threads we want (default 4)
threads = os.getenv("THREADS", "")
if threads == "":
    threads = "4"

# Print header
print "Concuerror's Testsuite (%d threads)\n" % int(threads)
print "%-10s %-20s %-50s  %s" % \
        ("Suite", "Test", "(Function,  Preemption Bound,  Reduction)", "Result")
print "---------------------------------------------" + \
      "---------------------------------------------"

# Create share integers to count tests and
# a lock to protect printings
lock = Lock()
total_tests = Value(c_int, 0, lock=False)
total_failed = Value(c_int, 0, lock=False)

sema = BoundedSemaphore(int(threads))

# For every test do
procT = []
for test in tests:
    p = Process(target=runTest, args=(test,))
    p.start()
    procT.append(p)
# Wait
for p in procT:
    p.join()

# Print overview
print "\nOVERALL SUMMARY for test run"
print "  %d total tests, which gave rise to" % len(tests)
print "  %d test cases, of which" % total_tests.value
print "  %d caused unexpected failures!" % total_failed.value

# Cleanup temp files
os.system("find %s -name '*.beam' -exec rm {} \;" % dirname)
<commit_msg>Cosmetic changes (pep8) to runtests.py<commit_after>#!/usr/bin/env python

import os
import re
import sys
import glob
import subprocess
from ctypes import c_int
from multiprocessing import Process, Lock, Value, BoundedSemaphore

#---------------------------------------------------------------------
# Extract scenarios from the specified test
def runTest(test):
    global dirname
    global results
    # test has the format of '.*/suites/<suite_name>/src/<test_name>(.erl)?'
    # Split the test in suite and name components using pattern matching
    rest1, name = os.path.split(test)
    rest2 = os.path.split(rest1)[0]
    suite = os.path.split(rest2)[1]
    name = os.path.splitext(name)[0]
    if os.path.isdir(test):
        # Our test is a multi module directory
        dirn = test     # directory
        modn = "test"   # module name
        files = glob.glob(dirn + "/*.erl")
    else:
        dirn = rest1
        modn = name
        files = [test]
    # Create a dir to save the results
    try:
        os.makedirs(results + "/" + suite + "/results")
    except OSError:
        pass
    sema.acquire()
    # Compile it
    os.system("erlc -W0 -o %s %s/%s.erl" % (dirn, dirn, modn))
    # And extract scenarios from it
    pout = subprocess.Popen(
        ["erl -noinput -pa %s -pa %s -s scenarios extract %s -s init stop"
         % (dirname, dirn, modn)], stdout=subprocess.PIPE, shell=True)
    sema.release()
    procS = []
    for scenario in pout.stdout:
        # scenario has the format of {<mod_name>,<func_name>,<preb>}\n
        scen = scenario.strip("{}\n").split(",")
        # And run the test
        p = Process(
            target=runScenario,
            args=(suite, name, modn, scen[1], scen[2], scen[3], files))
        p.start()
        procS.append(p)
    pout.stdout.close()
    # Wait
    for p in procS:
        p.join()

#---------------------------------------------------------------------
# Run the specified scenario and print the results
def runScenario(suite, name, modn, funn, preb, flag, files):
    global concuerror
    global results
    global dirname
    global sema
    global lock
    global total_tests
    global total_failed
    if flag == "dpor":
        conc_flag = "--dpor"
        file_ext = "-dpor"
    else:
        conc_flag = ""
        file_ext = ""
    sema.acquire()
    # Run concuerror
    os.system(("%s --target %s %s --files %s " +
               "--output %s/%s/results/%s-%s-%s%s.txt --preb %s --quiet %s")
              % (concuerror, modn, funn, ' '.join(files), results,
                 suite, name, funn, preb, file_ext, preb, conc_flag))
    # Compare the results
    orig = ("%s/suites/%s/results/%s-%s-%s%s.txt"
            % (dirname, suite, name, funn, preb, file_ext))
    rslt = ("%s/%s/results/%s-%s-%s%s.txt"
            % (results, suite, name, funn, preb, file_ext))
    equalRes = equalResults(orig, rslt)
    sema.release()
    # Print the results
    lock.acquire()
    total_tests.value += 1
    if equalRes:
        # We don't need to keep the results file
        os.remove(rslt)
        print "%-10s %-20s %-50s  \033[01;32mok\033[00m" % \
              (suite, name, "("+funn+",  "+preb+",  "+flag+")")
    else:
        total_failed.value += 1
        print "%-10s %-20s %-50s  \033[01;31mfailed\033[00m" % \
              (suite, name, "("+funn+",  "+preb+",  "+flag+")")
    lock.release()

def equalResults(f1, f2):
    try:
        fp1 = open(f1, 'r')
    except IOError:
        return False
    try:
        fp2 = open(f2, 'r')
    except IOError:
        fp1.close()
        return False
    while True:
        l1 = fp1.readline()
        l2 = fp2.readline()
        if (l1 != l2) and (not ignoreLine(l1)):
            fp1.close()
            fp2.close()
            return False
        if not l1:
            fp1.close()
            fp2.close()
            return True

def ignoreLine(line):
    global ignore_matches
    for match in ignore_matches:
        if re.search(match, line):
            return True
    return False

#---------------------------------------------------------------------
# Main program

# Compile some regular expressions
match_pids = re.compile("<\d+\.\d+\.\d+>")
match_refs = re.compile("#Ref<[\d\.]+>")
#match_file = re.compile("suites/.+/src/.*\.erl")
ignore_matches = [match_pids, match_refs]

# Get the directory of Concuerror's testsuite
dirname = os.path.abspath(os.path.dirname(sys.argv[0]))
concuerror = os.path.abspath(dirname + "/../concuerror")
results = os.path.abspath(dirname + "/results")

# Cleanup temp files
# TODO: make it os independent
os.system("find %s \( -name '*.beam' -o -name '*.dump' \) -exec rm {} \;"
          % dirname)
os.system("rm -rf %s/*" % results)

# Compile scenarios.erl
os.system("erlc %s/scenarios.erl" % dirname)

# If we have arguments we should use them as tests,
# otherwise check them all
if len(sys.argv) > 1:
    tests = sys.argv[1:]
    tests = [os.path.abspath(item) for item in tests]
else:
    tests = glob.glob(dirname + "/suites/*/src/*")

# How many threads we want (default 4)
threads = os.getenv("THREADS", "")
if threads == "":
    threads = "4"

# Print header
print "Concuerror's Testsuite (%d threads)\n" % int(threads)
print "%-10s %-20s %-50s  %s" % \
      ("Suite", "Test", "(Function,  Preemption Bound,  Reduction)", "Result")
print "---------------------------------------------" + \
      "---------------------------------------------"

# Create share integers to count tests and
# a lock to protect printings
lock = Lock()
total_tests = Value(c_int, 0, lock=False)
total_failed = Value(c_int, 0, lock=False)

sema = BoundedSemaphore(int(threads))

# For every test do
procT = []
for test in tests:
    p = Process(target=runTest, args=(test,))
    p.start()
    procT.append(p)
# Wait
for p in procT:
    p.join()

# Print overview
print "\nOVERALL SUMMARY for test run"
print "  %d total tests, which gave rise to" % len(tests)
print "  %d test cases, of which" % total_tests.value
print "  %d caused unexpected failures!" % total_failed.value

# Cleanup temp files
os.system("find %s -name '*.beam' -exec rm {} \;" % dirname)
<|endoftext|>


<commit_before>from pathlib import Path
from hoover.site.settings.common import *

INSTALLED_APPS = INSTALLED_APPS + [
    'hoover.contrib.twofactor',
    'django_otp',
    'django_otp.plugins.otp_totp',
]

MIDDLEWARE = MIDDLEWARE + [
    'django_otp.middleware.OTPMiddleware',
    'hoover.contrib.twofactor.middleware.AutoLogout',
    'hoover.contrib.twofactor.middleware.RequireAuth',
]

testsuite_dir = Path(__file__).absolute().parent

del HOOVER_ELASTICSEARCH_URL
SECRET_KEY = 'testing secret key'
HOOVER_UPLOADS_ROOT = str(testsuite_dir / 'uploads')
HOOVER_UI_ROOT = str(testsuite_dir / 'mock_ui')
HOOVER_BASE_URL = 'http://testserver'
HOOVER_RATELIMIT_USER = (30, 60) # 30 per minute
HOOVER_TWOFACTOR_RATELIMIT = (3, 60) # 3 per minute

from hoover.site.settings.testing_local import *
<commit_msg>Remove some indirection, set db password<commit_after>from pathlib import Path
from hoover.site.settings.common import *

INSTALLED_APPS = INSTALLED_APPS + [
    'hoover.contrib.twofactor',
    'django_otp',
    'django_otp.plugins.otp_totp',
]

MIDDLEWARE = MIDDLEWARE + [
    'django_otp.middleware.OTPMiddleware',
    'hoover.contrib.twofactor.middleware.AutoLogout',
    'hoover.contrib.twofactor.middleware.RequireAuth',
]

testsuite_dir = Path(__file__).absolute().parent

SECRET_KEY = 'testing secret key'
HOOVER_UPLOADS_ROOT = str(testsuite_dir / 'uploads')
HOOVER_UI_ROOT = str(testsuite_dir / 'mock_ui')
HOOVER_BASE_URL = 'http://testserver'
HOOVER_RATELIMIT_USER = (30, 60) # 30 per minute
HOOVER_TWOFACTOR_RATELIMIT = (3, 60) # 3 per minute

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'search',
        'USER': 'search',
        'HOST': 'search-pg',
        'PORT': 5432,
    },
}

HOOVER_ELASTICSEARCH_URL = 'http://search-es:9200'
<|endoftext|>


<commit_before>import os
import codecs
from os.path import basename
from datetime import datetime
from collections import OrderedDict

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import dates
from pandas import DataFrame
from pandas.io.parsers import read_csv

import astropy.units as u
from astropy.time import TimeDelta

import sunpy.io
from sunpy.time import parse_time
from sunpy.timeseries.timeseriesbase import GenericTimeSeries
from sunpy.util.metadata import MetaDict

__all__ = ['EVESpWxTimeSeries', 'ESPTimeSeries']

class ESPTimeSeries(GenericTimeSeries):
    """
    SDO EVE/ESP Level 1 data.

    The Extreme ultraviolet Spectro-Photometer (ESP) is an irradiance instrument
    which is part of the Extreme ultraviolet Variability Experiment (EVE) onboard
    SDO. ESP provides high time cadence (0.25s) EUV irradiance measurements in five
    channels, one soft X-ray and 4 EUV. The first four orders of the diffraction grating
    gives measurements centered on 18nm, 26nm, 30nm and 36nm. The zeroth order (obtained
    by 4 photodiodes) provides the soft X-ray measurements from 0.1-7nm.

    The ESP level 1 fits files are fully calibrated. The TimeSeries object created from
    an ESP fits file will conatain 4 columns namely:

        * 'QD' - sum of 4 quad diodes, this is the soft X-ray measurements 0.1-7nm
        * 'CH_18' - EUV irradiance 18nm
        * 'CH_26' - EUV irradiance 26nm
        * 'CH_30' - EUV irradiance 30nm
        * 'CH_36' - EUV irradiance 36nm

    References
    ----------
    * `SDO Mission Homepage <https://sdo.gsfc.nasa.gov/>`__
    * `EVE Homepage <http://lasp.colorado.edu/home/eve/>`__
    * `README ESP data <http://lasp.colorado.edu/eve/data_access/evewebdata/products/level1/esp/EVE_ESP_L1_V6_README.pdf>`__
    * `ESP lvl1 data <http://lasp.colorado.edu/eve/data_access/evewebdata/misc/eve_calendars/calendar_level1_2018.html>`__
    * `ESP instrument paper <https://doi.org/10.1007/s11207-009-9485-8>`__

    Notes
    -----
    The 36nm channel demonstrates a significant noise and it is not recommended to be
    used for short-time observations of solar irradiance.
    """

    _source = 'esp'

    def peek(self, title='EVE/ESP Level1', **kwargs):

        self._validate_data_for_ploting()

        names = ('Flux \n 0.1-7nm', 'Flux \n 18nm', 'Flux \n 26nm', 'Flux \n 30nm', 'Flux \n 36nm')

        figure = plt.figure()
        axes = plt.gca()
        axes = self.data.plot(ax=axes, subplots=True, sharex=True, **kwargs)
        plt.xlim(self.data.index[0], self.data.index[-1])

        axes[0].set_title(title)
        for i, ax in enumerate(axes):
            ax.set_ylabel(names[i])
            ax.legend(loc='upper right')
        axes[-1].set_xlabel('Time (UT) ' + str(self.data.index[0])[0:11])
        axes[-1].xaxis.set_major_formatter(dates.DateFormatter('%H:%M'))
        plt.tight_layout()
        plt.subplots_adjust(hspace=0.05)

        figure.show()

    @classmethod
    def _parse_file(cls, filepath):
        """
        Parses a EVE ESP level 1 data.
        """
        hdus = sunpy.io.read_file(filepath)
        return cls._parse_hdus(hdus)

    @classmethod
    def _parse_hdus(cls, hdulist):
        header = MetaDict(OrderedDict(hdulist[0].header))
        # Adding telescope to MetaData
        header.update({'TELESCOP': hdulist[1].header['TELESCOP'].split()[0]})

        start_time = parse_time(hdulist[1].header['T_OBS'])
        times = start_time + TimeDelta(hdulist[1].data['SOD']*u.second)

        colnames = ['QD', 'CH_18', 'CH_26', 'CH_30', 'CH_36']

        all_data = [hdulist[1].data[x] for x in colnames]
        data = DataFrame(np.array(all_data).T, index=times.isot.astype('datetime64'), columns=colnames)
        data.sort_index(inplace=True)

        units = OrderedDict([('QD', u.W/u.m**2),
                             ('CH_18', u.W/u.m**2),
                             ('CH_26', u.W/u.m**2),
                             ('CH_30', u.W/u.m**2),
                             ('CH_36', u.W/u.m**2)])

        return data, header, units

    @classmethod
    def is_datasource_for(cls, **kwargs):
        """
        Determines if header corresponds to an EVE image.
        """
        if kwargs.get('source', ''):
            return kwargs.get('source', '').lower().startswith(cls._source)
        if 'meta' in kwargs.keys():
            return kwargs['meta'].get('TELESCOP', '').endswith('SDO/EVE')

class EVESpWxTimeSeries(GenericTimeSeries):
    """
    SDO EVE LightCurve for level 0CS data.

    The Extreme Ultraviolet Variability Experiment (EVE) is an instrument on board the Solar Dynamics Observatory (SDO).
    The EVE instrument is designed to measure the solar extreme ultraviolet (EUV) irradiance.
    The EUV radiation includes the 0.1-105 nm range, which provides the majority
    of the energy for heating Earth’s thermosphere and creating Earth’s ionosphere (charged plasma).

    EVE includes several irradiance instruments:

    * The Multiple EUV Grating Spectrographs (MEGS)-A is a grazing- incidence spectrograph
      that measures the solar EUV irradiance in the 5 to 37 nm range with 0.1-nm resolution,
    * The MEGS-B is a normal-incidence, dual-pass spectrograph that measures the solar EUV
      irradiance in the 35 to 105 nm range with 0.1-nm resolution.

    Level 0CS data is primarily used for space weather.
    It is provided near real-time and is crudely calibrated 1-minute averaged broadband irradiances from ESP and MEGS-P broadband.
    For other levels of EVE data, use `~sunpy.net.Fido`, with `sunpy.net.attrs.Instrument('eve')`.

    Data is available starting on 2010/03/01.

    Examples
    --------
    >>> import sunpy.timeseries
    >>> import sunpy.data.sample  # doctest: +REMOTE_DATA
    >>> eve = sunpy.timeseries.TimeSeries(sunpy.data.sample.EVE_TIMESERIES, source='EVE')  # doctest: +REMOTE_DATA
    >>> eve = sunpy.timeseries.TimeSeries("http://lasp.colorado.edu/eve/data_access/quicklook/quicklook_data/L0CS/LATEST_EVE_L0CS_DIODES_1m.txt", source='EVE')  # doctest: +REMOTE_DATA
    >>> eve.peek(subplots=True)  # doctest: +SKIP

    References
    ----------
    * `SDO Mission Homepage <https://sdo.gsfc.nasa.gov/>`__
    * `EVE Homepage <http://lasp.colorado.edu/home/eve/>`__
    * `Level 0CS Definition <http://lasp.colorado.edu/home/eve/data/>`__
    * `EVE Data Acess <http://lasp.colorado.edu/home/eve/data/data-access/>`__
    * `Instrument Paper <https://doi.org/10.1007/s11207-009-9487-6>`__
    """
    # Class attribute used to specify the source class of the TimeSeries.
    _source = 'eve'

    def peek(self, column=None, **kwargs):
        """
        Plots the time series in a new figure. An example is shown below:

        .. plot::

            import sunpy.timeseries
            from sunpy.data.sample import EVE_TIMESERIES
            eve = sunpy.timeseries.TimeSeries(EVE_TIMESERIES, source='eve')
            eve.peek(subplots=True)

        Parameters
        ----------
        column : `str`, optional
            The column to display. Defaults to `None`, so it will display all.
        **kwargs : `dict`
            Any additional plot arguments that should be used when plotting.
        """
        # Check we have a timeseries valid for plotting
        self._validate_data_for_ploting()

        figure = plt.figure()
        # Choose title if none was specified
        if "title" not in kwargs and column is None:
            if len(self.data.columns) > 1:
                kwargs['title'] = 'EVE (1 minute data)'
            else:
                if self._filename is not None:
                    base = self._filename.replace('_', ' ')
                    kwargs['title'] = os.path.splitext(base)[0]
                else:
                    kwargs['title'] = 'EVE Averages'

        if column is None:
            self.plot(**kwargs)
        else:
            data = self.data[column]
            if "title" not in kwargs:
                kwargs['title'] = 'EVE ' + column.replace('_', ' ')
            data.plot(**kwargs)
        figure.show()

    @classmethod
    def _parse_file(cls, filepath):
        """
        Parses an EVE CSV file.
        """
        cls._filename = basename(filepath)
        with codecs.open(filepath, mode='rb', encoding='ascii') as fp:
            # Determine type of EVE CSV file and parse
            line1 = fp.readline()
            fp.seek(0)

            if line1.startswith("Date"):
                return cls._parse_average_csv(fp)
            elif line1.startswith(";"):
                return cls._parse_level_0cs(fp)

    @staticmethod
    def _parse_average_csv(fp):
        """
        Parses an EVE Averages file.
        """
        print('\nin _parse_average_csv()')
        return "", read_csv(fp, sep=",", index_col=0, parse_dates=True)

    @staticmethod
    def _parse_level_0cs(fp):
        """
        Parses and EVE Level 0CS file.
        """
        is_missing_data = False  # boolean to check for missing data
        missing_data_val = np.nan
        header = []
        fields = []
        line = fp.readline()
        # Read header at top of file
        while line.startswith(";"):
            header.append(line)
            if '; Missing data:' in line:
                is_missing_data = True
                missing_data_val = line.split(':')[1].strip()

            line = fp.readline()

        meta = MetaDict()
        for hline in header:
            if hline == '; Format:\n' or hline == '; Column descriptions:\n':
                continue
            elif ('Created' in hline) or ('Source' in hline):
                meta[hline.split(':',
                                 1)[0].replace(';',
                                               ' ').strip()] = hline.split(':', 1)[1].strip()
            elif ':' in hline:
                meta[hline.split(':')[0].replace(';', ' ').strip()] = hline.split(':')[1].strip()

        fieldnames_start = False
        for hline in header:
            if hline.startswith("; Format:"):
                fieldnames_start = False
            if fieldnames_start:
                fields.append(hline.split(":")[0].replace(';', ' ').strip())
            if hline.startswith("; Column descriptions:"):
                fieldnames_start = True

        # Next line is YYYY DOY MM DD
        date_parts = line.split(" ")

        year = int(date_parts[0])
        month = int(date_parts[2])
        day = int(date_parts[3])

        def parser(x):
            # Parse date column (HHMM)
            return datetime(year, month, day, int(x[0:2]), int(x[2:4]))

        data = read_csv(fp, sep=r"\s+", names=fields,
                        index_col=0, date_parser=parser, header=None, engine='python')
        if is_missing_data:  # If missing data specified in header
            data[data == float(missing_data_val)] = np.nan

        # Add the units data
        units = OrderedDict([('XRS-B proxy', u.W/u.m**2),
                             ('XRS-A proxy', u.W/u.m**2),
                             ('SEM proxy', u.W/u.m**2),
                             ('0.1-7ESPquad', u.W/u.m**2),
                             ('17.1ESP', u.W/u.m**2),
                             ('25.7ESP', u.W/u.m**2),
                             ('30.4ESP', u.W/u.m**2),
                             ('36.6ESP', u.W/u.m**2),
                             ('darkESP', u.ct),
                             ('121.6MEGS-P', u.W/u.m**2),
                             ('darkMEGS-P', u.ct),
                             ('q0ESP', u.dimensionless_unscaled),
                             ('q1ESP', u.dimensionless_unscaled),
                             ('q2ESP', u.dimensionless_unscaled),
                             ('q3ESP', u.dimensionless_unscaled),
                             ('CMLat', u.deg),
                             ('CMLon', u.deg)])
        # Todo: check units used.
        return data, meta, units

    @classmethod
    def is_datasource_for(cls, **kwargs):
        """
        Determines if header corresponds to an EVE image.
        """
        if kwargs.get('source', ''):
            return kwargs.get('source', '').lower().startswith(cls._source)
<commit_msg>remove stray print<commit_after>import os
import codecs
from os.path import basename
from datetime import datetime
from collections import OrderedDict

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import dates
from pandas import DataFrame
from pandas.io.parsers import read_csv

import astropy.units as u
from astropy.time import TimeDelta

import sunpy.io
from sunpy.time import parse_time
from sunpy.timeseries.timeseriesbase import GenericTimeSeries
from sunpy.util.metadata import MetaDict

__all__ = ['EVESpWxTimeSeries', 'ESPTimeSeries']

class ESPTimeSeries(GenericTimeSeries):
    """
    SDO EVE/ESP Level 1 data.

    The Extreme ultraviolet Spectro-Photometer (ESP) is an irradiance instrument
    which is part of the Extreme ultraviolet Variability Experiment (EVE) onboard
    SDO. ESP provides high time cadence (0.25s) EUV irradiance measurements in five
    channels, one soft X-ray and 4 EUV. The first four orders of the diffraction grating
    gives measurements centered on 18nm, 26nm, 30nm and 36nm. The zeroth order (obtained
    by 4 photodiodes) provides the soft X-ray measurements from 0.1-7nm.

    The ESP level 1 fits files are fully calibrated. The TimeSeries object created from
    an ESP fits file will conatain 4 columns namely:

        * 'QD' - sum of 4 quad diodes, this is the soft X-ray measurements 0.1-7nm
        * 'CH_18' - EUV irradiance 18nm
        * 'CH_26' - EUV irradiance 26nm
        * 'CH_30' - EUV irradiance 30nm
        * 'CH_36' - EUV irradiance 36nm

    References
    ----------
    * `SDO Mission Homepage <https://sdo.gsfc.nasa.gov/>`__
    * `EVE Homepage <http://lasp.colorado.edu/home/eve/>`__
    * `README ESP data <http://lasp.colorado.edu/eve/data_access/evewebdata/products/level1/esp/EVE_ESP_L1_V6_README.pdf>`__
    * `ESP lvl1 data <http://lasp.colorado.edu/eve/data_access/evewebdata/misc/eve_calendars/calendar_level1_2018.html>`__
    * `ESP instrument paper <https://doi.org/10.1007/s11207-009-9485-8>`__

    Notes
    -----
    The 36nm channel demonstrates a significant noise and it is not recommended to be
    used for short-time observations of solar irradiance.
    """

    _source = 'esp'

    def peek(self, title='EVE/ESP Level1', **kwargs):

        self._validate_data_for_ploting()

        names = ('Flux \n 0.1-7nm', 'Flux \n 18nm', 'Flux \n 26nm', 'Flux \n 30nm', 'Flux \n 36nm')

        figure = plt.figure()
        axes = plt.gca()
        axes = self.data.plot(ax=axes, subplots=True, sharex=True, **kwargs)
        plt.xlim(self.data.index[0], self.data.index[-1])

        axes[0].set_title(title)
        for i, ax in enumerate(axes):
            ax.set_ylabel(names[i])
            ax.legend(loc='upper right')
        axes[-1].set_xlabel('Time (UT) ' + str(self.data.index[0])[0:11])
        axes[-1].xaxis.set_major_formatter(dates.DateFormatter('%H:%M'))
        plt.tight_layout()
        plt.subplots_adjust(hspace=0.05)

        figure.show()

    @classmethod
    def _parse_file(cls, filepath):
        """
        Parses a EVE ESP level 1 data.
        """
        hdus = sunpy.io.read_file(filepath)
        return cls._parse_hdus(hdus)

    @classmethod
    def _parse_hdus(cls, hdulist):
        header = MetaDict(OrderedDict(hdulist[0].header))
        # Adding telescope to MetaData
        header.update({'TELESCOP': hdulist[1].header['TELESCOP'].split()[0]})

        start_time = parse_time(hdulist[1].header['T_OBS'])
        times = start_time + TimeDelta(hdulist[1].data['SOD']*u.second)

        colnames = ['QD', 'CH_18', 'CH_26', 'CH_30', 'CH_36']

        all_data = [hdulist[1].data[x] for x in colnames]
        data = DataFrame(np.array(all_data).T, index=times.isot.astype('datetime64'), columns=colnames)
        data.sort_index(inplace=True)

        units = OrderedDict([('QD', u.W/u.m**2),
                             ('CH_18', u.W/u.m**2),
                             ('CH_26', u.W/u.m**2),
                             ('CH_30', u.W/u.m**2),
                             ('CH_36', u.W/u.m**2)])

        return data, header, units

    @classmethod
    def is_datasource_for(cls, **kwargs):
        """
        Determines if header corresponds to an EVE image.
        """
        if kwargs.get('source', ''):
            return kwargs.get('source', '').lower().startswith(cls._source)
        if 'meta' in kwargs.keys():
            return kwargs['meta'].get('TELESCOP', '').endswith('SDO/EVE')

class EVESpWxTimeSeries(GenericTimeSeries):
    """
    SDO EVE LightCurve for level 0CS data.

    The Extreme Ultraviolet Variability Experiment (EVE) is an instrument on board the Solar Dynamics Observatory (SDO).
    The EVE instrument is designed to measure the solar extreme ultraviolet (EUV) irradiance.
    The EUV radiation includes the 0.1-105 nm range, which provides the majority
    of the energy for heating Earth’s thermosphere and creating Earth’s ionosphere (charged plasma).

    EVE includes several irradiance instruments:

    * The Multiple EUV Grating Spectrographs (MEGS)-A is a grazing- incidence spectrograph
      that measures the solar EUV irradiance in the 5 to 37 nm range with 0.1-nm resolution,
    * The MEGS-B is a normal-incidence, dual-pass spectrograph that measures the solar EUV
      irradiance in the 35 to 105 nm range with 0.1-nm resolution.

    Level 0CS data is primarily used for space weather.
    It is provided near real-time and is crudely calibrated 1-minute averaged broadband irradiances from ESP and MEGS-P broadband.
    For other levels of EVE data, use `~sunpy.net.Fido`, with `sunpy.net.attrs.Instrument('eve')`.

    Data is available starting on 2010/03/01.

    Examples
    --------
    >>> import sunpy.timeseries
    >>> import sunpy.data.sample  # doctest: +REMOTE_DATA
    >>> eve = sunpy.timeseries.TimeSeries(sunpy.data.sample.EVE_TIMESERIES, source='EVE')  # doctest: +REMOTE_DATA
    >>> eve = sunpy.timeseries.TimeSeries("http://lasp.colorado.edu/eve/data_access/quicklook/quicklook_data/L0CS/LATEST_EVE_L0CS_DIODES_1m.txt", source='EVE')  # doctest: +REMOTE_DATA
    >>> eve.peek(subplots=True)  # doctest: +SKIP

    References
    ----------
    * `SDO Mission Homepage <https://sdo.gsfc.nasa.gov/>`__
    * `EVE Homepage <http://lasp.colorado.edu/home/eve/>`__
    * `Level 0CS Definition <http://lasp.colorado.edu/home/eve/data/>`__
    * `EVE Data Acess <http://lasp.colorado.edu/home/eve/data/data-access/>`__
    * `Instrument Paper <https://doi.org/10.1007/s11207-009-9487-6>`__
    """
    # Class attribute used to specify the source class of the TimeSeries.
    _source = 'eve'

    def peek(self, column=None, **kwargs):
        """
        Plots the time series in a new figure. An example is shown below:

        .. plot::

            import sunpy.timeseries
            from sunpy.data.sample import EVE_TIMESERIES
            eve = sunpy.timeseries.TimeSeries(EVE_TIMESERIES, source='eve')
            eve.peek(subplots=True)

        Parameters
        ----------
        column : `str`, optional
            The column to display. Defaults to `None`, so it will display all.
        **kwargs : `dict`
            Any additional plot arguments that should be used when plotting.
        """
        # Check we have a timeseries valid for plotting
        self._validate_data_for_ploting()

        figure = plt.figure()
        # Choose title if none was specified
        if "title" not in kwargs and column is None:
            if len(self.data.columns) > 1:
                kwargs['title'] = 'EVE (1 minute data)'
            else:
                if self._filename is not None:
                    base = self._filename.replace('_', ' ')
                    kwargs['title'] = os.path.splitext(base)[0]
                else:
                    kwargs['title'] = 'EVE Averages'

        if column is None:
            self.plot(**kwargs)
        else:
            data = self.data[column]
            if "title" not in kwargs:
                kwargs['title'] = 'EVE ' + column.replace('_', ' ')
            data.plot(**kwargs)
        figure.show()

    @classmethod
    def _parse_file(cls, filepath):
        """
        Parses an EVE CSV file.
        """
        cls._filename = basename(filepath)
        with codecs.open(filepath, mode='rb', encoding='ascii') as fp:
            # Determine type of EVE CSV file and parse
            line1 = fp.readline()
            fp.seek(0)

            if line1.startswith("Date"):
                return cls._parse_average_csv(fp)
            elif line1.startswith(";"):
                return cls._parse_level_0cs(fp)

    @staticmethod
    def _parse_average_csv(fp):
        """
        Parses an EVE Averages file.
        """
        return "", read_csv(fp, sep=",", index_col=0, parse_dates=True)

    @staticmethod
    def _parse_level_0cs(fp):
        """
        Parses and EVE Level 0CS file.
        """
        is_missing_data = False  # boolean to check for missing data
        missing_data_val = np.nan
        header = []
        fields = []
        line = fp.readline()
        # Read header at top of file
        while line.startswith(";"):
            header.append(line)
            if '; Missing data:' in line:
                is_missing_data = True
                missing_data_val = line.split(':')[1].strip()

            line = fp.readline()

        meta = MetaDict()
        for hline in header:
            if hline == '; Format:\n' or hline == '; Column descriptions:\n':
                continue
            elif ('Created' in hline) or ('Source' in hline):
                meta[hline.split(':',
                                 1)[0].replace(';',
                                               ' ').strip()] = hline.split(':', 1)[1].strip()
            elif ':' in hline:
                meta[hline.split(':')[0].replace(';', ' ').strip()] = hline.split(':')[1].strip()

        fieldnames_start = False
        for hline in header:
            if hline.startswith("; Format:"):
                fieldnames_start = False
            if fieldnames_start:
                fields.append(hline.split(":")[0].replace(';', ' ').strip())
            if hline.startswith("; Column descriptions:"):
                fieldnames_start = True

        # Next line is YYYY DOY MM DD
        date_parts = line.split(" ")

        year = int(date_parts[0])
        month = int(date_parts[2])
        day = int(date_parts[3])

        def parser(x):
            # Parse date column (HHMM)
            return datetime(year, month, day, int(x[0:2]), int(x[2:4]))

        data = read_csv(fp, sep=r"\s+", names=fields,
                        index_col=0, date_parser=parser, header=None, engine='python')
        if is_missing_data:  # If missing data specified in header
            data[data == float(missing_data_val)] = np.nan

        # Add the units data
        units = OrderedDict([('XRS-B proxy', u.W/u.m**2),
                             ('XRS-A proxy', u.W/u.m**2),
                             ('SEM proxy', u.W/u.m**2),
                             ('0.1-7ESPquad', u.W/u.m**2),
                             ('17.1ESP', u.W/u.m**2),
                             ('25.7ESP', u.W/u.m**2),
                             ('30.4ESP', u.W/u.m**2),
                             ('36.6ESP', u.W/u.m**2),
                             ('darkESP', u.ct),
                             ('121.6MEGS-P', u.W/u.m**2),
                             ('darkMEGS-P', u.ct),
                             ('q0ESP', u.dimensionless_unscaled),
                             ('q1ESP', u.dimensionless_unscaled),
                             ('q2ESP', u.dimensionless_unscaled),
                             ('q3ESP', u.dimensionless_unscaled),
                             ('CMLat', u.deg),
                             ('CMLon', u.deg)])
        # Todo: check units used.
        return data, meta, units

    @classmethod
    def is_datasource_for(cls, **kwargs):
        """
        Determines if header corresponds to an EVE image.
        """
        if kwargs.get('source', ''):
            return kwargs.get('source', '').lower().startswith(cls._source)
<|endoftext|>


<commit_before>""" Course Discovery API Service. """
import datetime

import jwt
from django.conf import settings
from edx_rest_api_client.client import EdxRestApiClient

from openedx.core.djangoapps.theming import helpers
from student.models import UserProfile, anonymous_id_for_user

def get_id_token(user):
    """
    Return a JWT for `user`, suitable for use with the course discovery service.

    Arguments:
        user (User): User for whom to generate the JWT.

    Returns:
        str: The JWT.
    """
    try:
        # Service users may not have user profiles.
        full_name = UserProfile.objects.get(user=user).name
    except UserProfile.DoesNotExist:
        full_name = None

    now = datetime.datetime.utcnow()
    expires_in = getattr(settings, 'OAUTH_ID_TOKEN_EXPIRATION', 30)

    payload = {
        'preferred_username': user.username,
        'name': full_name,
        'email': user.email,
        'administrator': user.is_staff,
        'iss': helpers.get_value('OAUTH_OIDC_ISSUER', settings.OAUTH_OIDC_ISSUER),
        'exp': now + datetime.timedelta(seconds=expires_in),
        'iat': now,
        'aud': helpers.get_value('JWT_AUTH', settings.JWT_AUTH)['JWT_AUDIENCE'],
        'sub': anonymous_id_for_user(user, None),
    }
    secret_key = helpers.get_value('JWT_AUTH', settings.JWT_AUTH)['JWT_SECRET_KEY']

    return jwt.encode(payload, secret_key)

def course_discovery_api_client(user):
    """ Returns a Course Discovery API client setup with authentication for the specified user. """
    return EdxRestApiClient(settings.COURSE_CATALOG_API_URL, jwt=get_id_token(user))
<commit_msg>Corrected JWT data type<commit_after>""" Course Discovery API Service. """
import datetime

import jwt
from django.conf import settings
from edx_rest_api_client.client import EdxRestApiClient

from openedx.core.djangoapps.theming import helpers
from student.models import UserProfile, anonymous_id_for_user

def get_id_token(user):
    """
    Return a JWT for `user`, suitable for use with the course discovery service.

    Arguments:
        user (User): User for whom to generate the JWT.

    Returns:
        str: The JWT.
    """
    try:
        # Service users may not have user profiles.
        full_name = UserProfile.objects.get(user=user).name
    except UserProfile.DoesNotExist:
        full_name = None

    now = datetime.datetime.utcnow()
    expires_in = getattr(settings, 'OAUTH_ID_TOKEN_EXPIRATION', 30)

    payload = {
        'preferred_username': user.username,
        'name': full_name,
        'email': user.email,
        'administrator': user.is_staff,
        'iss': helpers.get_value('OAUTH_OIDC_ISSUER', settings.OAUTH_OIDC_ISSUER),
        'exp': now + datetime.timedelta(seconds=expires_in),
        'iat': now,
        'aud': helpers.get_value('JWT_AUTH', settings.JWT_AUTH)['JWT_AUDIENCE'],
        'sub': anonymous_id_for_user(user, None),
    }
    secret_key = helpers.get_value('JWT_AUTH', settings.JWT_AUTH)['JWT_SECRET_KEY']

    return jwt.encode(payload, secret_key).decode('utf-8')

def course_discovery_api_client(user):
    """ Returns a Course Discovery API client setup with authentication for the specified user. """
    return EdxRestApiClient(settings.COURSE_CATALOG_API_URL, jwt=get_id_token(user))
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from openerp.tests.common import TransactionCase

class TestNode(TransactionCase):
    def test_node_crud(self):
        Node = self.env['suvit.system.node']

        root = Node.create({'name': 'Root1'})

        ch1 = Node.create({'name': 'Ch1', 'parent_id': root.id})
        ch2 = Node.create({'name': 'Ch3', 'parent_id': root.id})
        ch3 = Node.create({'name': 'Ch2', 'parent_id': root.id})

        ch2.write({'name': 'Ch3-last', 'sequence': 1000})

        self.assertEqual(len(root.child_ids), 3)
        # test change name and order of children
        self.assertEqual(root.child_ids.mapped('name'),
                         ['Ch1', 'Ch2', 'Ch3-last'])

        ch3.unlink()

        # create duplicate to ch2
        ch2.action_duplicate()

        # add children for ch2
        ch2_1 = Node.create({'name': 'Ch2-1', 'parent_id': ch2.id})
        ch2_2 = Node.create({'name': 'Ch2-2', 'parent_id': ch2.id})

        # add children for ch2_1
        ch2_1_1 = Node.create({'name': 'Ch2-1-1', 'parent_id': ch2_1.id})
        ch2_1_2 = Node.create({'name': 'Ch2-2-2', 'parent_id': ch2_1.id})

        # ch2.invalidate_cache()
        # self.assertEqual(len(ch2.all_child_ids), 4)
        self.assertEqual(ch2_1_1.full_name, 'Root1 / Ch2 / Ch2-1 / Ch2-1-1')
        self.assertEqual(ch2_1_1.all_parent_ids, root + ch2 + ch2_1)

    def test_copy_duplicate(self):
        Node = self.env['suvit.system.node']

        root = Node.create({'name': 'Root1'})

        root.action_duplicate()

        duplicates = Node.search([('name', 'like', Node._duplicate_prefix)])
        self.assertEqual(len(duplicates), 2) # original and duplicate
        duplicate = duplicates.sorted(lambda n: n.id)[-1:]
        self.assertEqual(duplicate.name, 'D_Root1')
        self.assertEqual(duplicate.shortcut_id, root)
        self.assertEqual(duplicate.self_id, root)
        self.assertEqual(root.self_id, root)

        # test copy of duplicate is a copy of original
        duplicate.action_copy()

        # root has one duplicate
        self.assertEqual(root.duplicate_ids.ids, [duplicate.id])
        self.assertEqual(Node.search([], count=True), 3)

        copy = Node.search([('name', 'like', Node._copy_suffix)])
        self.assertEqual(len(copy), 1)
        self.assertEqual(copy.name, u'D_Root1 Копия')
        self.assertEqual(copy.shortcut_id, Node)
        self.assertEqual(copy.self_id, copy)
<commit_msg>comment some asserts<commit_after># -*- coding: utf-8 -*-
from openerp.tests.common import TransactionCase

class TestNode(TransactionCase):
    def test_node_crud(self):
        Node = self.env['suvit.system.node']

        root = Node.create({'name': 'Root1'})

        ch1 = Node.create({'name': 'Ch1', 'parent_id': root.id})
        ch2 = Node.create({'name': 'Ch3', 'parent_id': root.id})
        ch3 = Node.create({'name': 'Ch2', 'parent_id': root.id})

        ch2.write({'name': 'Ch3-last', 'sequence': 1000})

        self.assertEqual(len(root.child_ids), 3)
        # test change name and order of children
        self.assertEqual(root.child_ids.mapped('name'),
                         ['Ch1', 'Ch2', 'Ch3-last'])

        ch3.unlink()

        # create duplicate to ch2
        ch2.action_duplicate()

        # add children for ch2
        ch2_1 = Node.create({'name': 'Ch2-1', 'parent_id': ch2.id})
        ch2_2 = Node.create({'name': 'Ch2-2', 'parent_id': ch2.id})

        # add children for ch2_1
        ch2_1_1 = Node.create({'name': 'Ch2-1-1', 'parent_id': ch2_1.id})
        ch2_1_2 = Node.create({'name': 'Ch2-2-2', 'parent_id': ch2_1.id})

        # ch2.invalidate_cache()
        # self.assertEqual(len(ch2.all_child_ids), 4)
        # self.assertEqual(ch2_1_1.full_name, 'Root1 / Ch2 / Ch2-1 / Ch2-1-1')
        # self.assertEqual(ch2_1_1.all_parent_ids, root + ch2 + ch2_1)

    def test_copy_duplicate(self):
        Node = self.env['suvit.system.node']

        root = Node.create({'name': 'Root1'})

        root.action_duplicate()

        duplicates = Node.search([('name', 'like', Node._duplicate_prefix)])
        self.assertEqual(len(duplicates), 2) # original and duplicate
        duplicate = duplicates.sorted(lambda n: n.id)[-1:]
        self.assertEqual(duplicate.name, 'D_Root1')
        self.assertEqual(duplicate.shortcut_id, root)
        self.assertEqual(duplicate.self_id, root)
        self.assertEqual(root.self_id, root)

        # test copy of duplicate is a copy of original
        duplicate.action_copy()

        # root has one duplicate
        self.assertEqual(root.duplicate_ids.ids, [duplicate.id])
        self.assertEqual(Node.search([], count=True), 3)

        copy = Node.search([('name', 'like', Node._copy_suffix)])
        self.assertEqual(len(copy), 1)
        self.assertEqual(copy.name, u'D_Root1 Копия')
        self.assertEqual(copy.shortcut_id, Node)
        self.assertEqual(copy.self_id, copy)
<|endoftext|>


<commit_before># Orca
#
# Copyright 2006 Sun Microsystems Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

"""Provides an HTTP server for Orca.  This currently serves mainly as
something that self-voicing applications can use as their speech
service."""

__id__        = "$Id$"
__version__   = "$Revision$"
__date__      = "$Date$"
__copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
__license__   = "LGPL"

import threading
import BaseHTTPServer

import debug
import platform
import settings
import speech

_httpRequestThread = None

class _HTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    """Provides support for communicating with Orca via HTTP.  This is
    mainly to support self-voicing applications that want to use Orca
    as a speech service.

    The protocol is simple: POST content is 'stop', 'speak:<text>',
    or 'isSpeaking'.

    To test this, run:

      wget --post-data='speak:hello world' localhost:20433

    """

    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()
        self.wfile.write("
Orca %s
" \
                         % platform.version)

    def do_POST(self):
        contentLength = self.headers.getheader('content-length')
        if contentLength:
            contentLength = int(contentLength)
            inputBody = self.rfile.read(contentLength)
            debug.println(debug.LEVEL_FINEST,
                          "httpserver._HTTPRequestHandler received %s" \
                          % inputBody)
            if inputBody.startswith("speak:"):
                speech.speak(inputBody[6:])
                self.send_response(200, 'OK')
            elif inputBody == "stop":
                speech.stop()
                self.send_response(200, 'OK')
            elif inputBody == "isSpeaking":
                self.send_response(200, 'OK')
                self.send_header("Content-type", "text/html")
                self.end_headers()
                self.wfile.write("%s" % speech.isSpeaking())
        else:
            debug.println(debug.LEVEL_FINEST,
                          "httpserver._HTTPRequestHandler received no data")

class _HTTPRequestThread(threading.Thread):
    """Runs a _HTTPRequestHandler in a separate thread."""

    def run(self):
        httpd = BaseHTTPServer.HTTPServer(('',
                                           settings.httpServerPort),
                                          _HTTPRequestHandler)
        httpd.serve_forever()

def init():
    """Creates an HTTP server that listens for speak commands from a
    separate port defined by settings.httpServerPort.  We run this
    as a daemon so it will die automatically when orca dies."""

    global _httpRequestThread

    if settings.httpServerPort and (not _httpRequestThread):
        try:
            _httpRequestThread = _httpRequestThread()
            _httpRequestThread.setDaemon(True)
            _httpRequestThread.start()
        except:
            debug.printException(debug.LEVEL_SEVERE)

def shutdown():
    """Stops the HTTP server.  [[[WDW - not implemented yet.]]]"""
    pass
<commit_msg>Remove deliberate bug.  :-(<commit_after># Orca
#
# Copyright 2006 Sun Microsystems Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

"""Provides an HTTP server for Orca.  This currently serves mainly as
something that self-voicing applications can use as their speech
service."""

__id__        = "$Id$"
__version__   = "$Revision$"
__date__      = "$Date$"
__copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
__license__   = "LGPL"

import threading
import BaseHTTPServer

import debug
import platform
import settings
import speech

_httpRequestThread = None

class _HTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    """Provides support for communicating with Orca via HTTP.  This is
    mainly to support self-voicing applications that want to use Orca
    as a speech service.

    The protocol is simple: POST content is 'stop', 'speak:<text>',
    or 'isSpeaking'.

    To test this, run:

      wget --post-data='speak:hello world' localhost:20433

    """

    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()
        self.wfile.write("
Orca %s
" \
                         % platform.version)

    def do_POST(self):
        contentLength = self.headers.getheader('content-length')
        if contentLength:
            contentLength = int(contentLength)
            inputBody = self.rfile.read(contentLength)
            debug.println(debug.LEVEL_FINEST,
                          "httpserver._HTTPRequestHandler received %s" \
                          % inputBody)
            if inputBody.startswith("speak:"):
                speech.speak(inputBody[6:])
                self.send_response(200, 'OK')
            elif inputBody == "stop":
                speech.stop()
                self.send_response(200, 'OK')
            elif inputBody == "isSpeaking":
                self.send_response(200, 'OK')
                self.send_header("Content-type", "text/html")
                self.end_headers()
                self.wfile.write("%s" % speech.isSpeaking())
        else:
            debug.println(debug.LEVEL_FINEST,
                          "httpserver._HTTPRequestHandler received no data")

class _HTTPRequestThread(threading.Thread):
    """Runs a _HTTPRequestHandler in a separate thread."""

    def run(self):
        httpd = BaseHTTPServer.HTTPServer(('',
                                           settings.httpServerPort),
                                          _HTTPRequestHandler)
        httpd.serve_forever()

def init():
    """Creates an HTTP server that listens for speak commands from a
    separate port defined by settings.httpServerPort.  We run this
    as a daemon so it will die automatically when orca dies."""

    global _httpRequestThread

    if settings.httpServerPort and (not _httpRequestThread):
        try:
            _httpRequestThread = _HTTPRequestThread()
            _httpRequestThread.setDaemon(True)
            _httpRequestThread.start()
        except:
            debug.printException(debug.LEVEL_SEVERE)

def shutdown():
    """Stops the HTTP server.  [[[WDW - not implemented yet.]]]"""
    pass
<|endoftext|>


<commit_before>"""
Languages and generators registration and discovery API.
"""
from __future__ import unicode_literals
import fnmatch
import pkg_resources

from textx.exceptions import TextXRegistrationError

class LanguageDesc:
    """
    A class used in language registration/discovery.

    Attributes:
        name (str): the name/ID of the language (must be unique)
        pattern (str): filename pattern for models (e.g. "*.data")
        description (str): A short description of the language
        metamodel (callable): A callable that returns configured meta-model
            or the metamodel itself (if a single specific instance is
            desired)
    """

    def __init__(self, name, pattern=None, description='', metamodel=None):
        self.name = name
        self.pattern = pattern
        self.description = description
        self.metamodel = metamodel

class GeneratorDesc:
    """
    A class used in generators registration/discovery.

    Attributes:
        language (str): The name/ID of the language this generator is for.
                        If the generators is generic (applicable to any model)
                        use "*".
        target (str): A short name of the target stack/technology.
        description (str): A short description of the generator.
        generator (callable): A callable of the form:
                              def generator(model, output_folder, overwrite)
    """
    def __init__(self, language, target, description='', generator=None):
        self.language = language
        self.target = target
        self.description = description
        self.generator = generator

metamodels = {}
languages = None
generators = None

def language_descriptions():
    """
    Return a dict of `LanguageDesc` instances keyed by language name.
    """
    global languages
    if languages is None:
        languages = {}
        for language in pkg_resources.iter_entry_points(
                group='textx_languages'):
            register_language(language.load())
    return languages

def generator_descriptions():
    """
    Return a dict of `GeneratorDesc` instances keyed by language name.
    """
    global generators
    if generators is None:
        generators = {}
        for generator in pkg_resources.iter_entry_points(
                group='textx_generators'):
            register_generator(generator.load())
    return generators

def language_description(language_name):
    """
    Return `LanguageDesc` for the given language name.
    """
    global languages
    language_name = language_name.lower()
    if languages is None:
        language_descriptions()
    try:
        return languages[language_name]
    except KeyError:
        raise TextXRegistrationError('Language "{}" not registered.'
                                     .format(language_name))

def generator_description(language_name, target_name):
    """
    Return `GeneratorDesc` instance for the given target and language name.
    """
    global generators
    language_name = language_name.lower()
    target_name = target_name.lower()
    if generators is None:
        generator_descriptions()
    try:
        generators_for_language = generators[language_name]
    except KeyError:
        raise TextXRegistrationError(
            'No generators registered for language "{}".'
            .format(language_name))
    try:
        return generators_for_language[target_name]
    except KeyError:
        raise TextXRegistrationError(
            'No generators registered for language "{}" and target "{}".'
            .format(language_name, target_name))

def generator_for_language_target(language_name, target_name):
    """
    Return generator callable for the given language name and target name.
    """
    generator_desc = generator_description(language_name, target_name)
    return generator_desc.generator

def register_language(language_desc_or_name, pattern=None, description='',
                      metamodel=None):
    """
    Programmatically register a language.

    Args:
        language_desc_or_name (LanguageDesc or str): If LanguageDesc is given
            other parameters are not used.
        For other parameters see `LanguageDesc`.
    """
    global languages
    if languages is None:
        language_descriptions()

    if type(language_desc_or_name) is not LanguageDesc:
        language_desc = LanguageDesc(
            name=language_desc_or_name,
            pattern=pattern,
            description=description,
            metamodel=metamodel
        )
    else:
        language_desc = language_desc_or_name

    if language_desc.name.lower() in languages:
        raise TextXRegistrationError(
            'Language "{}" already registered.'.format(language_desc.name))
    languages[language_desc.name.lower()] = language_desc

def clear_language_registrations():
    """
    Clear all registered languages.
    """
    global languages, metamodels
    languages = None
    metamodels = {}

def register_generator(generator_desc_or_language, target=None, description='',
                       generator=None):
    """
    Programmatically register a generator.

    Args:
        generator_desc_or_language (GeneratorDesc or str): If GeneratorDesc is
            given other parameters are not used.
        For other parameters see `GeneratorDesc`.
    """
    global generators
    if generators is None:
        generator_descriptions()

    if type(generator_desc_or_language) is not GeneratorDesc:
        generator_desc = GeneratorDesc(
            language=generator_desc_or_language,
            target=target,
            description=description,
            generator=generator
        )
    else:
        generator_desc = generator_desc_or_language

    lang_gens = generators.setdefault(generator_desc.language.lower(), {})
    if generator_desc.target.lower() in lang_gens:
        raise TextXRegistrationError(
            'Generator "{}->{}" already registered.'.format(
                generator_desc.language, generator_desc.target))
    lang_gens[generator_desc.target.lower()] = generator_desc

def clear_generator_registrations():
    """
    Clear all registered generators.
    """
    global generators
    generators = None

def metamodel_for_language(language_name):
    """
    Load and return the meta-model for the given language.
    Cache it for further use.
    """
    language_name = language_name.lower()
    if language_name not in metamodels:
        from textx.metamodel import TextXMetaModel, TextXMetaMetaModel
        language = language_description(language_name)
        if (isinstance(language.metamodel, TextXMetaModel)
                or isinstance(language.metamodel, TextXMetaMetaModel)):
            metamodels[language_name] = language.metamodel
        else:
            metamodel = language.metamodel()
            if not (isinstance(metamodel, TextXMetaModel) or
                    isinstance(metamodel, TextXMetaMetaModel)):
                raise TextXRegistrationError(
                    'Meta-model type for language "{}" is "{}".'
                    .format(language_name, type(metamodel).__name__))
            metamodels[language_name] = metamodel
    return metamodels[language_name]

def languages_for_file(file_name_or_pattern):
    """
    Return a list of `LanguageDesc` registered for the given file pattern.
    """
    file_languages = []
    for language in language_descriptions().values():
        if file_name_or_pattern == language.pattern \
                or fnmatch.fnmatch(file_name_or_pattern, language.pattern):
            file_languages.append(language)
    return file_languages

def language_for_file(file_or_pattern):
    """
    Return an instance of `LanguageDesc` that can parse the given file or raise
    `TextXRegistrationError` if more than one is registered.
    """
    languages = languages_for_file(file_or_pattern)
    if len(languages) > 1:
        raise TextXRegistrationError('Multiple languages can parse "{}".'
                                     .format(file_or_pattern))
    elif len(languages) == 0:
        raise TextXRegistrationError('No language registered that can parse'
                                     ' "{}".'.format(file_or_pattern))

    return languages[0]

def metamodels_for_file(file_name):
    """
    Return meta-models that can parse the given file.
    """
    return [metamodel_for_language(language.name)
            for language in languages_for_file(file_name)]

def metamodel_for_file(file_name):
    """
    Return a meta-model that can parse the given file or raise
    `TextXRegistrationError` if more than one is registered.
    """
    return metamodel_for_language(language_for_file(file_name).name)
<commit_msg>Fix inheritance for Python 2 in registration<commit_after>"""
Languages and generators registration and discovery API.
"""
from __future__ import unicode_literals
import fnmatch
import pkg_resources

from textx.exceptions import TextXRegistrationError

class LanguageDesc(object):
    """
    A class used in language registration/discovery.

    Attributes:
        name (str): the name/ID of the language (must be unique)
        pattern (str): filename pattern for models (e.g. "*.data")
        description (str): A short description of the language
        metamodel (callable): A callable that returns configured meta-model
            or the metamodel itself (if a single specific instance is
            desired)
    """

    def __init__(self, name, pattern=None, description='', metamodel=None):
        self.name = name
        self.pattern = pattern
        self.description = description
        self.metamodel = metamodel

class GeneratorDesc(object):
    """
    A class used in generators registration/discovery.

    Attributes:
        language (str): The name/ID of the language this generator is for.
                        If the generators is generic (applicable to any model)
                        use "*".
        target (str): A short name of the target stack/technology.
        description (str): A short description of the generator.
        generator (callable): A callable of the form:
                              def generator(model, output_folder, overwrite)
    """
    def __init__(self, language, target, description='', generator=None):
        self.language = language
        self.target = target
        self.description = description
        self.generator = generator

metamodels = {}
languages = None
generators = None

def language_descriptions():
    """
    Return a dict of `LanguageDesc` instances keyed by language name.
    """
    global languages
    if languages is None:
        languages = {}
        for language in pkg_resources.iter_entry_points(
                group='textx_languages'):
            register_language(language.load())
    return languages

def generator_descriptions():
    """
    Return a dict of `GeneratorDesc` instances keyed by language name.
    """
    global generators
    if generators is None:
        generators = {}
        for generator in pkg_resources.iter_entry_points(
                group='textx_generators'):
            register_generator(generator.load())
    return generators

def language_description(language_name):
    """
    Return `LanguageDesc` for the given language name.
    """
    global languages
    language_name = language_name.lower()
    if languages is None:
        language_descriptions()
    try:
        return languages[language_name]
    except KeyError:
        raise TextXRegistrationError('Language "{}" not registered.'
                                     .format(language_name))

def generator_description(language_name, target_name):
    """
    Return `GeneratorDesc` instance for the given target and language name.
    """
    global generators
    language_name = language_name.lower()
    target_name = target_name.lower()
    if generators is None:
        generator_descriptions()
    try:
        generators_for_language = generators[language_name]
    except KeyError:
        raise TextXRegistrationError(
            'No generators registered for language "{}".'
            .format(language_name))
    try:
        return generators_for_language[target_name]
    except KeyError:
        raise TextXRegistrationError(
            'No generators registered for language "{}" and target "{}".'
            .format(language_name, target_name))

def generator_for_language_target(language_name, target_name):
    """
    Return generator callable for the given language name and target name.
    """
    generator_desc = generator_description(language_name, target_name)
    return generator_desc.generator

def register_language(language_desc_or_name, pattern=None, description='',
                      metamodel=None):
    """
    Programmatically register a language.

    Args:
        language_desc_or_name (LanguageDesc or str): If LanguageDesc is given
            other parameters are not used.
        For other parameters see `LanguageDesc`.
    """
    global languages
    if languages is None:
        language_descriptions()

    if type(language_desc_or_name) is not LanguageDesc:
        language_desc = LanguageDesc(
            name=language_desc_or_name,
            pattern=pattern,
            description=description,
            metamodel=metamodel
        )
    else:
        language_desc = language_desc_or_name

    if language_desc.name.lower() in languages:
        raise TextXRegistrationError(
            'Language "{}" already registered.'.format(language_desc.name))
    languages[language_desc.name.lower()] = language_desc

def clear_language_registrations():
    """
    Clear all registered languages.
    """
    global languages, metamodels
    languages = None
    metamodels = {}

def register_generator(generator_desc_or_language, target=None, description='',
                       generator=None):
    """
    Programmatically register a generator.

    Args:
        generator_desc_or_language (GeneratorDesc or str): If GeneratorDesc is
            given other parameters are not used.
        For other parameters see `GeneratorDesc`.
    """
    global generators
    if generators is None:
        generator_descriptions()

    if type(generator_desc_or_language) is not GeneratorDesc:
        generator_desc = GeneratorDesc(
            language=generator_desc_or_language,
            target=target,
            description=description,
            generator=generator
        )
    else:
        generator_desc = generator_desc_or_language

    lang_gens = generators.setdefault(generator_desc.language.lower(), {})
    if generator_desc.target.lower() in lang_gens:
        raise TextXRegistrationError(
            'Generator "{}->{}" already registered.'.format(
                generator_desc.language, generator_desc.target))
    lang_gens[generator_desc.target.lower()] = generator_desc

def clear_generator_registrations():
    """
    Clear all registered generators.
    """
    global generators
    generators = None

def metamodel_for_language(language_name):
    """
    Load and return the meta-model for the given language.
    Cache it for further use.
    """
    language_name = language_name.lower()
    if language_name not in metamodels:
        from textx.metamodel import TextXMetaModel, TextXMetaMetaModel
        language = language_description(language_name)
        if (isinstance(language.metamodel, TextXMetaModel)
                or isinstance(language.metamodel, TextXMetaMetaModel)):
            metamodels[language_name] = language.metamodel
        else:
            metamodel = language.metamodel()
            if not (isinstance(metamodel, TextXMetaModel) or
                    isinstance(metamodel, TextXMetaMetaModel)):
                raise TextXRegistrationError(
                    'Meta-model type for language "{}" is "{}".'
                    .format(language_name, type(metamodel).__name__))
            metamodels[language_name] = metamodel
    return metamodels[language_name]

def languages_for_file(file_name_or_pattern):
    """
    Return a list of `LanguageDesc` registered for the given file pattern.
    """
    file_languages = []
    for language in language_descriptions().values():
        if file_name_or_pattern == language.pattern \
                or fnmatch.fnmatch(file_name_or_pattern, language.pattern):
            file_languages.append(language)
    return file_languages

def language_for_file(file_or_pattern):
    """
    Return an instance of `LanguageDesc` that can parse the given file or raise
    `TextXRegistrationError` if more than one is registered.
    """
    languages = languages_for_file(file_or_pattern)
    if len(languages) > 1:
        raise TextXRegistrationError('Multiple languages can parse "{}".'
                                     .format(file_or_pattern))
    elif len(languages) == 0:
        raise TextXRegistrationError('No language registered that can parse'
                                     ' "{}".'.format(file_or_pattern))

    return languages[0]

def metamodels_for_file(file_name):
    """
    Return meta-models that can parse the given file.
    """
    return [metamodel_for_language(language.name)
            for language in languages_for_file(file_name)]

def metamodel_for_file(file_name):
    """
    Return a meta-model that can parse the given file or raise
    `TextXRegistrationError` if more than one is registered.
    """
    return metamodel_for_language(language_for_file(file_name).name)
<|endoftext|>