<commit_before># -*- coding: utf-8 -*-
"""
    shipment.py

"""
import simplejson as json
from decimal import Decimal

from trytond.model import fields, ModelView
from trytond.pool import PoolMeta, Pool
from trytond.wizard import Wizard, StateView, Button, StateTransition
from trytond.pyson import Eval, Bool
from trytond.transaction import Transaction

from .mixin import ShipmentCarrierMixin

__metaclass__ = PoolMeta
__all__ = [
    'ShipmentOut', 'GenerateShippingLabelMessage',
    'GenerateShippingLabel', 'ShippingCarrierSelector',
    'SelectShippingRate'
]

class ShipmentOut(ShipmentCarrierMixin):
    __metaclass__ = PoolMeta
    __name__ = 'stock.shipment.out'

    @property
    def carrier_cost_moves(self):
        return self.outgoing_moves

    def on_change_inventory_moves(self):
        with Transaction().set_context(ignore_carrier_computation=True):
            super(ShipmentOut, self).on_change_inventory_moves()

    @classmethod
    def pack(cls, shipments):
        Package = Pool().get('stock.package')

        super(ShipmentOut, cls).pack(shipments)

        for shipment in shipments:
            if not shipment.packages:
                # No package, create a default package
                package = Package()
                package.shipment = shipment
                package.moves = shipment.outgoing_moves
                package.save()
            else:
                if (len(shipment.outgoing_moves) !=
                        sum(len(p.moves) for p in shipment.packages)):
                    cls.raise_user_error(
                        "Not all the items are packaged for shipment #%s", (
                            shipment.number, )
                    )

class ShippingCarrierSelector(ModelView):
    'View To Select Carrier'
    __name__ = 'shipping.label.start'

    carrier = fields.Many2One("carrier", "Carrier", required=True)
    override_weight = fields.Float("Override Weight", digits=(16, 2))
    no_of_packages = fields.Integer('Number of packages', readonly=True)
    box_type = fields.Many2One(
        "carrier.box_type", "Box Type", required=True, domain=[
            ('id', 'in', Eval("available_box_types"))
        ], depends=["available_box_types"]
    )

    shipping_instructions = fields.Text('Shipping Instructions', readonly=True)
    carrier_service = fields.Many2One(
        "carrier.service", "Carrier Service", domain=[
            ('id', 'in', Eval("available_carrier_services"))
        ], depends=["available_carrier_services"]
    )

    available_box_types = fields.Function(
        fields.One2Many("carrier.box_type", None, 'Available Box Types'),
        getter="on_change_with_available_box_types"
    )
    available_carrier_services = fields.Function(
        fields.One2Many("carrier.service", None, 'Available Carrier Services'),
        getter="on_change_with_available_carrier_services"
    )

    @fields.depends('carrier', 'carrier_service', 'box_type')
    def on_change_carrier(self):
        self.carrier_service = None
        self.box_type = None

    @fields.depends("carrier")
    def on_change_with_available_box_types(self, name=None):
        if self.carrier:
            return map(int, self.carrier.box_types)
        return []

    @fields.depends("carrier")
    def on_change_with_available_carrier_services(self, name=None):
        if self.carrier:
            return map(int, self.carrier.services)
        return []

    @classmethod
    def view_attributes(cls):
        return super(ShippingCarrierSelector, cls).view_attributes() + [
            ('//label[@name="no_of_packages"]', 'states', {
                    'invisible': Bool(Eval('no_of_packages')),
            })
        ]

class SelectShippingRate(ModelView):
    'Select Shipping Rate'
    __name__ = 'shipping.label.select_rate'

    rate = fields.Selection([], 'Rate')

class GenerateShippingLabelMessage(ModelView):
    'Generate Labels Message'
    __name__ = 'shipping.label.end'

    tracking_number = fields.Many2One(
        "shipment.tracking", "Tracking number", readonly=True
    )
    message = fields.Text("Message", readonly=True)
    attachments = fields.One2Many(
        'ir.attachment', None, 'Attachments', readonly=True
    )
    cost = fields.Numeric("Cost", digits=(16, 2), readonly=True)
    cost_currency = fields.Many2One(
        'currency.currency', 'Cost Currency', readonly=True
    )

class GenerateShippingLabel(Wizard):
    'Generate Labels'
    __name__ = 'shipping.label'

    #: This is the first state of wizard to generate shipping label.
    #: It asks for carrier, carrier_service, box_type and override weight,
    #: once entered, it move to `next` transition where it saves all the
    #: values on shipment.
    start = StateView(
        'shipping.label.start',
        'shipping.select_carrier_view_form',
        [
            Button('Cancel', 'end', 'tryton-cancel'),
            Button('Continue', 'next', 'tryton-go-next'),
        ]
    )

    #: Transition saves values from `start` state to the shipment.
    next = StateTransition()

    #: Select shipping rates
    select_rate = StateView(
        'shipping.label.select_rate',
        'shipping.select_rate_view_form',
        [
            Button('Cancel', 'end', 'tryton-cancel'),
            Button('Continue', 'generate_labels', 'tryton-go-next', default=True),  # noqa
        ]
    )

    #: Transition generates shipping labels.
    generate_labels = StateTransition()

    #: State shows the generated label, tracking number, cost and cost
    #: currency.
    generate = StateView(
        'shipping.label.end',
        'shipping.generate_shipping_label_message_view_form',
        [
            Button('Ok', 'end', 'tryton-ok'),
        ]
    )

    @property
    def shipment(self):
        "Gives the active shipment."
        Shipment = Pool().get(Transaction().context.get('active_model'))
        return Shipment(Transaction().context.get('active_id'))

    @classmethod
    def __setup__(cls):
        super(GenerateShippingLabel, cls).__setup__()
        cls._error_messages.update({
            'tracking_number_already_present':
                'Tracking Number is already present for this shipment.',
            'invalid_state': (
                'Labels can only be generated when the shipment is in Packed or'
                ' Done states only'
            ),
            'no_packages': 'Shipment %s has no packages',
        })

    def default_start(self, data):
        """Fill the default values for `start` state.
        """
        UOM = Pool().get('product.uom')
        if self.shipment.allow_label_generation():
            values = {
                'no_of_packages': len(self.shipment.packages),
                'shipping_instructions': self.shipment.shipping_instructions,
            }

        if self.shipment.carrier:
            values.update({
                'carrier': self.shipment.carrier.id,
            })
        if self.shipment.packages:
            package_weights = []
            for package in self.shipment.packages:
                if not package.override_weight:
                    continue
                package_weights.append(
                    UOM.compute_qty(
                        package.override_weight_uom,
                        package.override_weight,
                        self.shipment.weight_uom
                    )
                )
            values['override_weight'] = sum(package_weights)

        if self.shipment.carrier_service:
            values['carrier_service'] = self.shipment.carrier_service.id

        return values

    def transition_next(self):
        Company = Pool().get('company.company')

        shipment = self.shipment
        company = Company(Transaction().context['company'])
        shipment.carrier = self.start.carrier
        shipment.cost_currency = company.currency
        shipment.carrier_service = self.start.carrier_service
        shipment.save()

        if not shipment.packages:
            shipment._create_default_package(self.start.box_type)

        default_values = self.default_start({})
        per_package_weight = None
        if self.start.override_weight and \
                default_values['override_weight'] != self.start.override_weight:
            # Distribute weight equally
            per_package_weight = (
                self.start.override_weight / len(shipment.packages)
            )

        for package in shipment.packages:
            if per_package_weight:
                package.override_weight = per_package_weight
                package.override_weight_uom = shipment.weight_uom
            if self.start.box_type != package.box_type:
                package.box_type = self.start.box_type
            package.save()

        # Fetch rates, and fill selection field with result list
        rates = self.shipment.get_shipping_rate(
            self.start.carrier, self.start.carrier_service
        )
        result = []
        for rate in rates:
            json_safe_rate = rate.copy()
            json_safe_rate.update({
                'carrier': json_safe_rate['carrier'].id,
                'carrier_service': json_safe_rate['carrier_service'] and
                json_safe_rate['carrier_service'].id,
                'cost_currency': json_safe_rate['cost_currency'].id,
            })

            # Update when delivery date is not None
            if json_safe_rate.get('delivery_date'):
                json_safe_rate.update({
                    'delivery_date': json_safe_rate[
                        'delivery_date'].isoformat()
                })

            # Update when delivery time is not None
            if json_safe_rate.get('delivery_time'):
                json_safe_rate.update({
                    'delivery_time': json_safe_rate[
                        'delivery_time'].isoformat()
                })

            result.append((
                json.dumps(json_safe_rate), '%s %s %s' % (
                    rate['display_name'],
                    rate['cost'],
                    rate['cost_currency'].code,
                )
            ))

        self.select_rate.__class__.rate.selection = result

        return 'select_rate'

    def transition_generate_labels(self):
        "Generates shipping labels from data provided by earlier states"
        Carrier = Pool().get('carrier')
        CarrierService = Pool().get('carrier.service')
        Currency = Pool().get('currency.currency')

        if self.select_rate.rate:
            rate = json.loads(self.select_rate.rate)
            rate.update({
                'carrier': Carrier(rate['carrier']),
                'carrier_service': rate['carrier_service'] and
                CarrierService(rate['carrier_service']),
                'cost': Decimal(rate['cost']),
                'cost_currency': Currency(rate['cost_currency'])
            })
            self.shipment.apply_shipping_rate(rate)
        self.shipment.generate_shipping_labels()

        return "generate"

    def get_attachments(self):  # pragma: no cover
        """
        Returns list of attachments corresponding to shipment.
        """
        Attachment = Pool().get('ir.attachment')

        return map(
            int,
            Attachment.search([
                ('resource.origin.id', 'in', map(int, self.shipment.packages),
                    'shipment.tracking', 'stock.package')
            ])
        )

    def get_message(self):
        """
        Returns message to be displayed on wizard
        """
        message = 'Shipment labels have been generated via %s and saved as ' \
            'attachments for the tracking number' % (
                self.shipment.carrier.carrier_cost_method.upper()
            )
        return message

    def default_generate(self, data):
        return {
            'tracking_number': self.shipment.tracking_number and
            self.shipment.tracking_number.id,
            'message': self.get_message(),
            'attachments': self.get_attachments(),
            'cost': self.shipment.cost,
            'cost_currency': self.shipment.cost_currency.id,
        }
<commit_msg>Do not check if canceled moves are packaged<commit_after># -*- coding: utf-8 -*-
"""
    shipment.py

"""
import simplejson as json
from decimal import Decimal

from trytond.model import fields, ModelView
from trytond.pool import PoolMeta, Pool
from trytond.wizard import Wizard, StateView, Button, StateTransition
from trytond.pyson import Eval, Bool
from trytond.transaction import Transaction

from .mixin import ShipmentCarrierMixin

__metaclass__ = PoolMeta
__all__ = [
    'ShipmentOut', 'GenerateShippingLabelMessage',
    'GenerateShippingLabel', 'ShippingCarrierSelector',
    'SelectShippingRate'
]

class ShipmentOut(ShipmentCarrierMixin):
    __metaclass__ = PoolMeta
    __name__ = 'stock.shipment.out'

    @property
    def carrier_cost_moves(self):
        return self.outgoing_moves

    def on_change_inventory_moves(self):
        with Transaction().set_context(ignore_carrier_computation=True):
            super(ShipmentOut, self).on_change_inventory_moves()

    @classmethod
    def pack(cls, shipments):
        Package = Pool().get('stock.package')

        super(ShipmentOut, cls).pack(shipments)

        for shipment in shipments:
            if not shipment.packages:
                # No package, create a default package
                package = Package()
                package.shipment = shipment
                package.moves = shipment.outgoing_moves
                package.save()
            else:
                if (len(filter(lambda m: m.state != 'cancel', shipment.outgoing_moves)) !=  # noqa
                        sum(len(p.moves) for p in shipment.packages)):
                    cls.raise_user_error(
                        "Not all the items are packaged for shipment #%s", (
                            shipment.number, )
                    )

class ShippingCarrierSelector(ModelView):
    'View To Select Carrier'
    __name__ = 'shipping.label.start'

    carrier = fields.Many2One("carrier", "Carrier", required=True)
    override_weight = fields.Float("Override Weight", digits=(16, 2))
    no_of_packages = fields.Integer('Number of packages', readonly=True)
    box_type = fields.Many2One(
        "carrier.box_type", "Box Type", required=True, domain=[
            ('id', 'in', Eval("available_box_types"))
        ], depends=["available_box_types"]
    )

    shipping_instructions = fields.Text('Shipping Instructions', readonly=True)
    carrier_service = fields.Many2One(
        "carrier.service", "Carrier Service", domain=[
            ('id', 'in', Eval("available_carrier_services"))
        ], depends=["available_carrier_services"]
    )

    available_box_types = fields.Function(
        fields.One2Many("carrier.box_type", None, 'Available Box Types'),
        getter="on_change_with_available_box_types"
    )
    available_carrier_services = fields.Function(
        fields.One2Many("carrier.service", None, 'Available Carrier Services'),
        getter="on_change_with_available_carrier_services"
    )

    @fields.depends('carrier', 'carrier_service', 'box_type')
    def on_change_carrier(self):
        self.carrier_service = None
        self.box_type = None

    @fields.depends("carrier")
    def on_change_with_available_box_types(self, name=None):
        if self.carrier:
            return map(int, self.carrier.box_types)
        return []

    @fields.depends("carrier")
    def on_change_with_available_carrier_services(self, name=None):
        if self.carrier:
            return map(int, self.carrier.services)
        return []

    @classmethod
    def view_attributes(cls):
        return super(ShippingCarrierSelector, cls).view_attributes() + [
            ('//label[@name="no_of_packages"]', 'states', {
                    'invisible': Bool(Eval('no_of_packages')),
            })
        ]

class SelectShippingRate(ModelView):
    'Select Shipping Rate'
    __name__ = 'shipping.label.select_rate'

    rate = fields.Selection([], 'Rate')

class GenerateShippingLabelMessage(ModelView):
    'Generate Labels Message'
    __name__ = 'shipping.label.end'

    tracking_number = fields.Many2One(
        "shipment.tracking", "Tracking number", readonly=True
    )
    message = fields.Text("Message", readonly=True)
    attachments = fields.One2Many(
        'ir.attachment', None, 'Attachments', readonly=True
    )
    cost = fields.Numeric("Cost", digits=(16, 2), readonly=True)
    cost_currency = fields.Many2One(
        'currency.currency', 'Cost Currency', readonly=True
    )

class GenerateShippingLabel(Wizard):
    'Generate Labels'
    __name__ = 'shipping.label'

    #: This is the first state of wizard to generate shipping label.
    #: It asks for carrier, carrier_service, box_type and override weight,
    #: once entered, it move to `next` transition where it saves all the
    #: values on shipment.
    start = StateView(
        'shipping.label.start',
        'shipping.select_carrier_view_form',
        [
            Button('Cancel', 'end', 'tryton-cancel'),
            Button('Continue', 'next', 'tryton-go-next'),
        ]
    )

    #: Transition saves values from `start` state to the shipment.
    next = StateTransition()

    #: Select shipping rates
    select_rate = StateView(
        'shipping.label.select_rate',
        'shipping.select_rate_view_form',
        [
            Button('Cancel', 'end', 'tryton-cancel'),
            Button('Continue', 'generate_labels', 'tryton-go-next', default=True),  # noqa
        ]
    )

    #: Transition generates shipping labels.
    generate_labels = StateTransition()

    #: State shows the generated label, tracking number, cost and cost
    #: currency.
    generate = StateView(
        'shipping.label.end',
        'shipping.generate_shipping_label_message_view_form',
        [
            Button('Ok', 'end', 'tryton-ok'),
        ]
    )

    @property
    def shipment(self):
        "Gives the active shipment."
        Shipment = Pool().get(Transaction().context.get('active_model'))
        return Shipment(Transaction().context.get('active_id'))

    @classmethod
    def __setup__(cls):
        super(GenerateShippingLabel, cls).__setup__()
        cls._error_messages.update({
            'tracking_number_already_present':
                'Tracking Number is already present for this shipment.',
            'invalid_state': (
                'Labels can only be generated when the shipment is in Packed or'
                ' Done states only'
            ),
            'no_packages': 'Shipment %s has no packages',
        })

    def default_start(self, data):
        """Fill the default values for `start` state.
        """
        UOM = Pool().get('product.uom')
        if self.shipment.allow_label_generation():
            values = {
                'no_of_packages': len(self.shipment.packages),
                'shipping_instructions': self.shipment.shipping_instructions,
            }

        if self.shipment.carrier:
            values.update({
                'carrier': self.shipment.carrier.id,
            })
        if self.shipment.packages:
            package_weights = []
            for package in self.shipment.packages:
                if not package.override_weight:
                    continue
                package_weights.append(
                    UOM.compute_qty(
                        package.override_weight_uom,
                        package.override_weight,
                        self.shipment.weight_uom
                    )
                )
            values['override_weight'] = sum(package_weights)

        if self.shipment.carrier_service:
            values['carrier_service'] = self.shipment.carrier_service.id

        return values

    def transition_next(self):
        Company = Pool().get('company.company')

        shipment = self.shipment
        company = Company(Transaction().context['company'])
        shipment.carrier = self.start.carrier
        shipment.cost_currency = company.currency
        shipment.carrier_service = self.start.carrier_service
        shipment.save()

        if not shipment.packages:
            shipment._create_default_package(self.start.box_type)

        default_values = self.default_start({})
        per_package_weight = None
        if self.start.override_weight and \
                default_values['override_weight'] != self.start.override_weight:
            # Distribute weight equally
            per_package_weight = (
                self.start.override_weight / len(shipment.packages)
            )

        for package in shipment.packages:
            if per_package_weight:
                package.override_weight = per_package_weight
                package.override_weight_uom = shipment.weight_uom
            if self.start.box_type != package.box_type:
                package.box_type = self.start.box_type
            package.save()

        # Fetch rates, and fill selection field with result list
        rates = self.shipment.get_shipping_rate(
            self.start.carrier, self.start.carrier_service
        )
        result = []
        for rate in rates:
            json_safe_rate = rate.copy()
            json_safe_rate.update({
                'carrier': json_safe_rate['carrier'].id,
                'carrier_service': json_safe_rate['carrier_service'] and
                json_safe_rate['carrier_service'].id,
                'cost_currency': json_safe_rate['cost_currency'].id,
            })

            # Update when delivery date is not None
            if json_safe_rate.get('delivery_date'):
                json_safe_rate.update({
                    'delivery_date': json_safe_rate[
                        'delivery_date'].isoformat()
                })

            # Update when delivery time is not None
            if json_safe_rate.get('delivery_time'):
                json_safe_rate.update({
                    'delivery_time': json_safe_rate[
                        'delivery_time'].isoformat()
                })

            result.append((
                json.dumps(json_safe_rate), '%s %s %s' % (
                    rate['display_name'],
                    rate['cost'],
                    rate['cost_currency'].code,
                )
            ))

        self.select_rate.__class__.rate.selection = result

        return 'select_rate'

    def transition_generate_labels(self):
        "Generates shipping labels from data provided by earlier states"
        Carrier = Pool().get('carrier')
        CarrierService = Pool().get('carrier.service')
        Currency = Pool().get('currency.currency')

        if self.select_rate.rate:
            rate = json.loads(self.select_rate.rate)
            rate.update({
                'carrier': Carrier(rate['carrier']),
                'carrier_service': rate['carrier_service'] and
                CarrierService(rate['carrier_service']),
                'cost': Decimal(rate['cost']),
                'cost_currency': Currency(rate['cost_currency'])
            })
            self.shipment.apply_shipping_rate(rate)
        self.shipment.generate_shipping_labels()

        return "generate"

    def get_attachments(self):  # pragma: no cover
        """
        Returns list of attachments corresponding to shipment.
        """
        Attachment = Pool().get('ir.attachment')

        return map(
            int,
            Attachment.search([
                ('resource.origin.id', 'in', map(int, self.shipment.packages),
                    'shipment.tracking', 'stock.package')
            ])
        )

    def get_message(self):
        """
        Returns message to be displayed on wizard
        """
        message = 'Shipment labels have been generated via %s and saved as ' \
            'attachments for the tracking number' % (
                self.shipment.carrier.carrier_cost_method.upper()
            )
        return message

    def default_generate(self, data):
        return {
            'tracking_number': self.shipment.tracking_number and
            self.shipment.tracking_number.id,
            'message': self.get_message(),
            'attachments': self.get_attachments(),
            'cost': self.shipment.cost,
            'cost_currency': self.shipment.cost_currency.id,
        }
<|endoftext|>


<commit_before>"""
Position of the Sun.
"""
from __future__ import absolute_import
import numpy as np
#pylint: disable=E1101,E1121
__authors__ = ["Jack Ireland"]
__email__ = "jack.ireland@nasa.gov"

"""
Questions
---------
1. should the output always be an ndarray?
2. Should we be able to return position in other coordinate systems as well?
   If so, then this function should be to something like radec, and pos() should
   accept "radec" as input and call the current function.
3. Where do all of the "magic" numbers come from? If possible document them, and
   they may be useful elsewhere, consider putting them in sunpy.constants (could
   any of them already exist there or in scipy constants?)
"""

def pos(date, radian=False):
    """
    Routine to calculate the right ascension (RA) and declination (dec) of
    the Sun.

    Based in Solarsoft/IDL routine SUNPOS (Sept 1997)

    Parameters
    ----------
    date : scalar, numpy.ndarray ???
        Julian dates as input
    radian : boolean
        if True, return the results in radians

    Attributes
    ----------
    none

    Examples
    --------
    >>> from sunpy.sun import pos
    >>> pos.pos(0.0)
    >>> (array([ 241.65373812]), array([-21.68562104]), array([ 243.82420808]), array([ 24.31513199]))'
    >>> pos.pos(2455813.024259259, radian=True)
    >>> (array([ 2.90902792]), array([ 0.09958257]), array([ 2.88897706]), array([ 0.40905761]))

    See Also
    --------
    numpy.ndarray

    References
    ----------
    | http://docs.scipy.org/doc/numpy/reference/arrays.classes.html
    """

    # Make sure the input is a ndarray
    if np.isscalar(date):
        date = date + np.zeros([1])

    # Degrees to radians
    deg2rad = np.pi / 180.0

    # Time in Julian centuries from 1900.0
    time = (date - 2415020.0) / 36525.0

    # Sun's mean longitude
    longitude = (279.696678 + np.mod(36000.768925 * time, 360.0)) * 3600.0

    # Allow for ellipticity of the orbit (equation of centre)
    # using the Earth's mean anomaly ME
    me = 358.4758440 + np.mod(35999.0497500 * time, 360.0)
    ellcor  = ((6910.10 - 17.20 * time) * np.sin(me * deg2rad) +
               72.30 * np.sin(2.00 * me * deg2rad))
    longitude = longitude + ellcor

    # Allow for the Venus perturbations using the mean anomaly of Venus MV
    mv = 212.6032190 + np.mod(58517.8038750 * time, 360.0)
    vencorr = (4.80 * np.cos((299.10170 + mv - me) * deg2rad) +
               5.50 * np.cos((148.31330 + 2.00 * mv - 2.00 * me ) * deg2rad) +
               2.50 * np.cos((315.94330 + 2.00 * mv - 3.00 * me ) * deg2rad) +
               1.60 * np.cos((345.25330 + 3.00 * mv - 4.00 * me ) * deg2rad) +
               1.00 * np.cos((318.150   + 3.00 * mv - 5.00 * me ) * deg2rad))
    longitude = longitude + vencorr

    # Allow for the Mars perturbations using the mean anomaly of Mars MM
    mm = 319.5294250 + np.mod( 19139.8585000 * time,  360.00)
    marscorr = (2.00 * np.cos((343.88830 - 2.00 * mm + 2.00 * me) * deg2rad ) +
                1.80 * np.cos((200.40170 - 2.00 * mm + me) * deg2rad))
    longitude = longitude + marscorr

    # Allow for the Jupiter perturbations using the mean anomaly of
    # Jupiter MJ
    mj = 225.3283280 + np.mod( 3034.69202390 * time, 360.00 )
    jupcorr = (7.20 * np.cos(( 179.53170 - mj + me ) * deg2rad) +
               2.60 * np.cos((263.21670 - mj) * deg2rad) +
               2.70 * np.cos(( 87.14500 - 2.00 * mj + 2.00 * me) * deg2rad) +
               1.60 * np.cos((109.49330 - 2.00 * mj + me) * deg2rad))
    longitude = longitude + jupcorr

    # Allow for the Moons perturbations using the mean elongation of
    # the Moon from the Sun
    moon_me = 350.73768140 + np.mod(445267.114220 * time, 360.00)
    mooncorr = 6.50 * np.sin(moon_me * deg2rad)
    longitude = longitude + mooncorr

    # Allow for long period terms
    longterm = + 6.40 * np.sin((231.190 + 20.200 * time) * deg2rad)
    longitude = longitude + longterm
    longitude = np.mod(longitude + 2592000.00, 1296000.00)
    longmed = longitude / 3600.00

    # Allow for Aberration ??????
    longitude = longitude - 20.50

    # Allow for Nutation using the longitude of the Moons mean node OMEGA
    omega = 259.1832750 - np.mod(1934.1420080 * time, 360.00)
    longitude = longitude - 17.20 * np.sin(omega * deg2rad)

    # Form the True Obliquity
    obliquity = (23.4522940 - 0.01301250 *
                 time + (9.20 * np.cos(omega * deg2rad)) / 3600.00)

    # Form Right Ascension and Declination
    longitude = longitude / 3600.00
    ra = np.arctan2(np.sin(longitude * deg2rad) * np.cos(obliquity * deg2rad),
                    np.cos(longitude * deg2rad))

    # ?
    neg = np.where(ra < 0.0)
    if len(neg) > 0:
        ra[neg] = ra[neg] + 2.0 * np.pi

    dec = np.arcsin(np.sin(longitude * deg2rad) * np.sin(obliquity * deg2rad))

    if radian:
        obliquity = obliquity * deg2rad
        longmed = longmed * deg2rad
    else:
        ra = ra / deg2rad
        dec = dec / deg2rad

    return ra, dec, longmed, obliquity<commit_msg>cleaned up the exported namespace<commit_after>"""
Position of the Sun.
"""
from __future__ import absolute_import

import numpy as np
#pylint: disable=E1101,E1121

__all__ = ['pos']

__authors__ = ["Jack Ireland"]
__email__ = "jack.ireland@nasa.gov"

"""
Questions
---------
1. should the output always be an ndarray?
2. Should we be able to return position in other coordinate systems as well?
   If so, then this function should be to something like radec, and pos() should
   accept "radec" as input and call the current function.
3. Where do all of the "magic" numbers come from? If possible document them, and
   they may be useful elsewhere, consider putting them in sunpy.constants (could
   any of them already exist there or in scipy constants?)
"""

def pos(date, radian=False):
    """
    Routine to calculate the right ascension (RA) and declination (dec) of
    the Sun.

    Based in Solarsoft/IDL routine SUNPOS (Sept 1997)

    Parameters
    ----------
    date : scalar, numpy.ndarray ???
        Julian dates as input
    radian : boolean
        if True, return the results in radians

    Attributes
    ----------
    none

    Examples
    --------
    >>> from sunpy.sun import pos
    >>> pos.pos(0.0)
    >>> (array([ 241.65373812]), array([-21.68562104]), array([ 243.82420808]), array([ 24.31513199]))'
    >>> pos.pos(2455813.024259259, radian=True)
    >>> (array([ 2.90902792]), array([ 0.09958257]), array([ 2.88897706]), array([ 0.40905761]))

    See Also
    --------
    numpy.ndarray

    References
    ----------
    | http://docs.scipy.org/doc/numpy/reference/arrays.classes.html
    """

    # Make sure the input is a ndarray
    if np.isscalar(date):
        date = date + np.zeros([1])

    # Degrees to radians
    deg2rad = np.pi / 180.0

    # Time in Julian centuries from 1900.0
    time = (date - 2415020.0) / 36525.0

    # Sun's mean longitude
    longitude = (279.696678 + np.mod(36000.768925 * time, 360.0)) * 3600.0

    # Allow for ellipticity of the orbit (equation of centre)
    # using the Earth's mean anomaly ME
    me = 358.4758440 + np.mod(35999.0497500 * time, 360.0)
    ellcor  = ((6910.10 - 17.20 * time) * np.sin(me * deg2rad) +
               72.30 * np.sin(2.00 * me * deg2rad))
    longitude = longitude + ellcor

    # Allow for the Venus perturbations using the mean anomaly of Venus MV
    mv = 212.6032190 + np.mod(58517.8038750 * time, 360.0)
    vencorr = (4.80 * np.cos((299.10170 + mv - me) * deg2rad) +
               5.50 * np.cos((148.31330 + 2.00 * mv - 2.00 * me ) * deg2rad) +
               2.50 * np.cos((315.94330 + 2.00 * mv - 3.00 * me ) * deg2rad) +
               1.60 * np.cos((345.25330 + 3.00 * mv - 4.00 * me ) * deg2rad) +
               1.00 * np.cos((318.150   + 3.00 * mv - 5.00 * me ) * deg2rad))
    longitude = longitude + vencorr

    # Allow for the Mars perturbations using the mean anomaly of Mars MM
    mm = 319.5294250 + np.mod( 19139.8585000 * time,  360.00)
    marscorr = (2.00 * np.cos((343.88830 - 2.00 * mm + 2.00 * me) * deg2rad ) +
                1.80 * np.cos((200.40170 - 2.00 * mm + me) * deg2rad))
    longitude = longitude + marscorr

    # Allow for the Jupiter perturbations using the mean anomaly of
    # Jupiter MJ
    mj = 225.3283280 + np.mod( 3034.69202390 * time, 360.00 )
    jupcorr = (7.20 * np.cos(( 179.53170 - mj + me ) * deg2rad) +
               2.60 * np.cos((263.21670 - mj) * deg2rad) +
               2.70 * np.cos(( 87.14500 - 2.00 * mj + 2.00 * me) * deg2rad) +
               1.60 * np.cos((109.49330 - 2.00 * mj + me) * deg2rad))
    longitude = longitude + jupcorr

    # Allow for the Moons perturbations using the mean elongation of
    # the Moon from the Sun
    moon_me = 350.73768140 + np.mod(445267.114220 * time, 360.00)
    mooncorr = 6.50 * np.sin(moon_me * deg2rad)
    longitude = longitude + mooncorr

    # Allow for long period terms
    longterm = + 6.40 * np.sin((231.190 + 20.200 * time) * deg2rad)
    longitude = longitude + longterm
    longitude = np.mod(longitude + 2592000.00, 1296000.00)
    longmed = longitude / 3600.00

    # Allow for Aberration ??????
    longitude = longitude - 20.50

    # Allow for Nutation using the longitude of the Moons mean node OMEGA
    omega = 259.1832750 - np.mod(1934.1420080 * time, 360.00)
    longitude = longitude - 17.20 * np.sin(omega * deg2rad)

    # Form the True Obliquity
    obliquity = (23.4522940 - 0.01301250 *
                 time + (9.20 * np.cos(omega * deg2rad)) / 3600.00)

    # Form Right Ascension and Declination
    longitude = longitude / 3600.00
    ra = np.arctan2(np.sin(longitude * deg2rad) * np.cos(obliquity * deg2rad),
                    np.cos(longitude * deg2rad))

    # ?
    neg = np.where(ra < 0.0)
    if len(neg) > 0:
        ra[neg] = ra[neg] + 2.0 * np.pi

    dec = np.arcsin(np.sin(longitude * deg2rad) * np.sin(obliquity * deg2rad))

    if radian:
        obliquity = obliquity * deg2rad
        longmed = longmed * deg2rad
    else:
        ra = ra / deg2rad
        dec = dec / deg2rad

    return ra, dec, longmed, obliquity<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#  Copyright 2011 Takeshi KOMIYA
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

import re
import math
import unicodedata
from XY import XY

def is_zenkaku(char):
    u"""
    Detect given character is Japanese ZENKAKU character

    >>> is_zenkaku(u"A")
    False
    >>> is_zenkaku(u"あ")
    True
    """
    char_width = unicodedata.east_asian_width(char)
    return char_width in u"WFA"

def zenkaku_len(string):
    u"""
    Count Japanese ZENKAKU characters from string

    >>> zenkaku_len(u"abc")
    0
    >>> zenkaku_len(u"あいう")
    3
    >>> zenkaku_len(u"あいc")
    2
    """
    return len([x for x in string  if is_zenkaku(x)])

def hankaku_len(string):
    u"""
    Count non Japanese ZENKAKU characters from string

    >>> hankaku_len(u"abc")
    3
    >>> hankaku_len(u"あいう")
    0
    >>> hankaku_len(u"あいc")
    1
    """
    return len([x for x in string  if not is_zenkaku(x)])

def string_width(string):
    u"""
    Measure rendering width of string.
    Count ZENKAKU-character as 2-point and non ZENKAKU-character as 1-point

    >>> string_width(u"abc")
    3
    >>> string_width(u"あいう")
    6
    >>> string_width(u"あいc")
    5
    """
    width = 0
    for c in string:
        char_width = unicodedata.east_asian_width(c)
        if char_width in u"WFA":
            width += 2
        else:
            width += 1

    return width

class TextFolder:
    def __init__(self, box, string, **kwargs):
        self.box = box
        self.string = string
        self.scale = 1
        self.halign = kwargs.get('halign', 'center')
        self.valign = kwargs.get('valign', 'center')
        self.fontsize = kwargs.get('fontsize', 11)
        self.padding = kwargs.get('padding', 12)
        self.line_spacing = kwargs.get('line_spacing', 2)

        if kwargs.get('adjustBaseline'):
            self.adjustBaseline = True
        else:
            self.adjustBaseline = False

        self._result = self._lines()

    def textsize(self, string):
        u"""
        Measure rendering size (width and height) of line.
        Returned size will not be exactly as rendered text size,
        Because this method does not use fonts to measure size.

        >>> box = [0, 0, 100, 50]
        >>> TextFolder(box, "").textsize(u"abc")
        (19, 11)
        >>> TextFolder(box, "").textsize(u"あいう")
        (33, 11)
        >>> TextFolder(box, "").textsize(u"あいc")
        (29, 11)
        >>> TextFolder(box, "", fontsize=24).textsize(u"abc")
        (40, 24)
        >>> TextFolder(box, "", fontsize=18).textsize(u"あいう")
        (54, 18)
        """
        width = zenkaku_len(string) * self.fontsize + \
                hankaku_len(string) * self.fontsize * 0.55
        return (int(math.ceil(width)), self.fontsize)

    def height(self):
        u"""
        Measure rendering height of text.

        If texts is heighter than bounding box,
        jut out lines will be cut off.

        >>> box = [0, 0, 100, 50]
        >>> TextFolder(box, u"abc").height()
        11
        >>> TextFolder(box, u"abc\\ndef").height()
        24
        >>> TextFolder(box, u"abc\\n\\ndef").height()
        37
        >>> TextFolder(box, u"abc\\ndef\\nghi\\njkl").height()
        50
        >>> TextFolder(box, u"abc\\ndef\\nghi\\njkl\\nmno").height()
        50
        >>> TextFolder(box, u"abc", fontsize=24).height()
        24
        >>> TextFolder(box, u"abc\\ndef", line_spacing=8).height()
        30
        >>> TextFolder(box, u"abc\\ndef", fontsize=15, line_spacing=8).height()
        38
        """
        height = 0
        for string in self._result:
            height += self.textsize(string)[1]

        if len(self._result) > 1:
            height += (len(self._result) - 1) * self.line_spacing

        return height

    def each_line(self):
        size = XY(self.box[2] - self.box[0], self.box[3] - self.box[1])

        if self.valign == 'top':
            height = 0
        elif self.valign == 'bottom':
            height = size.y - self.height()
        else:
            height = int(math.ceil((size.y - self.height()) / 2.0))
        base_xy = XY(self.box[0], self.box[1])

        for string in self._result:
            textsize = self.textsize(string)

            halign = size.x - textsize[0] * self.scale
            if self.halign == 'left':
                x = self.padding
            elif self.halign == 'right':
                x = halign - self.padding
            else:
                x = int(math.ceil(halign / 2.0))

            if self.adjustBaseline:
                height += textsize[1]
            draw_xy = XY(base_xy.x + x, base_xy.y + height)

            yield string, draw_xy

            if self.adjustBaseline:
                height += self.line_spacing
            else:
                height += textsize[1] + self.line_spacing

    def outlineBox(self):
        corners = []
        for string, xy in self.each_line():
            textsize = self.textsize(string)
            width = textsize[0] * self.scale
            height = textsize[1] * self.scale

            if self.adjustBaseline:
                xy = XY(xy.x, xy.y - textsize[1])

            corners.append(xy)
            corners.append(XY(xy.x + width, xy.y + height))

        if corners:
            x_margin = 4  # MAGIC number
            y_margin = 2  # MAGIC number
            box = (min(p.x for p in corners) - x_margin,
                   min(p.y for p in corners) - y_margin,
                   max(p.x for p in corners) + x_margin,
                   max(p.y for p in corners) + y_margin)
        else:
            box = self.box

        return box

    def _splitlines(self):
        u"""
        Split text to lines as generator.
        Every line will be stripped.
        If text includes characters "\n", treat as line separator.

        >>> box = [0, 0, 100, 50]
        >>> [l for l in TextFolder(box, u"abc")._splitlines()]
        [u'abc']
        >>> [l for l in TextFolder(box, u"abc\\ndef")._splitlines()]
        [u'abc', u'def']
        >>> [l for l in TextFolder(box, u"abc\\\\ndef")._splitlines()]
        [u'abc', u'def']
        >>> [l for l in TextFolder(box, u" abc \\n def ")._splitlines()]
        [u'abc', u'def']
        >>> [l for l in TextFolder(box, u" \\nabc\\\\ndef")._splitlines()]
        [u'abc', u'def']
        >>> [l for l in TextFolder(box, u" \\\\nabc\\\\ndef")._splitlines()]
        [u'', u'abc', u'def']
        """
        string = re.sub('^\s*(.*?)\s*$', '\\1', self.string)
        for line in string.splitlines():
            for subline in line.split("\\n"):
                yield subline.strip()

    def _lines(self):
        lines = []
        size = (self.box[2] - self.box[0], self.box[3] - self.box[1])

        height = 0
        truncated = 0
        for line in self._splitlines():
            while True:
                string = line.strip()
                for i in range(0, len(string)):
                    length = len(string) - i
                    metrics = self.textsize(string[0:length])

                    if metrics[0] <= size[0]:
                        break
                else:
                    length = 0
                    metrics = self.textsize(u" ")

                if size[1] < height + metrics[1]:
                    truncated = 1
                    break

                lines.append(string[0:length])
                height += metrics[1] + self.line_spacing

                line = string[length:]
                if line == "":
                    break

        # truncate last line.
        if len(lines) == 0:
            pass
        elif truncated:
            string = lines.pop()
            for i in range(0, len(string)):
                if i == 0:
                    truncated = string + ' ...'
                else:
                    truncated = string[0:-i] + ' ...'

                metrics = self.textsize(truncated)
                if metrics[0] <= size[0]:
                    lines.append(truncated)
                    break

        return lines
<commit_msg> * Replace \xa5 + 'n' as return code  * Replace twin backslash (\x5c\x5c) as escaped backslash<commit_after># -*- coding: utf-8 -*-
#  Copyright 2011 Takeshi KOMIYA
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

import re
import math
import unicodedata
from XY import XY

def is_zenkaku(char):
    u"""
    Detect given character is Japanese ZENKAKU character

    >>> is_zenkaku(u"A")
    False
    >>> is_zenkaku(u"あ")
    True
    """
    char_width = unicodedata.east_asian_width(char)
    return char_width in u"WFA"

def zenkaku_len(string):
    u"""
    Count Japanese ZENKAKU characters from string

    >>> zenkaku_len(u"abc")
    0
    >>> zenkaku_len(u"あいう")
    3
    >>> zenkaku_len(u"あいc")
    2
    """
    return len([x for x in string  if is_zenkaku(x)])

def hankaku_len(string):
    u"""
    Count non Japanese ZENKAKU characters from string

    >>> hankaku_len(u"abc")
    3
    >>> hankaku_len(u"あいう")
    0
    >>> hankaku_len(u"あいc")
    1
    """
    return len([x for x in string  if not is_zenkaku(x)])

def string_width(string):
    u"""
    Measure rendering width of string.
    Count ZENKAKU-character as 2-point and non ZENKAKU-character as 1-point

    >>> string_width(u"abc")
    3
    >>> string_width(u"あいう")
    6
    >>> string_width(u"あいc")
    5
    """
    width = 0
    for c in string:
        char_width = unicodedata.east_asian_width(c)
        if char_width in u"WFA":
            width += 2
        else:
            width += 1

    return width

class TextFolder:
    def __init__(self, box, string, **kwargs):
        self.box = box
        self.string = string
        self.scale = 1
        self.halign = kwargs.get('halign', 'center')
        self.valign = kwargs.get('valign', 'center')
        self.fontsize = kwargs.get('fontsize', 11)
        self.padding = kwargs.get('padding', 12)
        self.line_spacing = kwargs.get('line_spacing', 2)

        if kwargs.get('adjustBaseline'):
            self.adjustBaseline = True
        else:
            self.adjustBaseline = False

        self._result = self._lines()

    def textsize(self, string):
        u"""
        Measure rendering size (width and height) of line.
        Returned size will not be exactly as rendered text size,
        Because this method does not use fonts to measure size.

        >>> box = [0, 0, 100, 50]
        >>> TextFolder(box, "").textsize(u"abc")
        (19, 11)
        >>> TextFolder(box, "").textsize(u"あいう")
        (33, 11)
        >>> TextFolder(box, "").textsize(u"あいc")
        (29, 11)
        >>> TextFolder(box, "", fontsize=24).textsize(u"abc")
        (40, 24)
        >>> TextFolder(box, "", fontsize=18).textsize(u"あいう")
        (54, 18)
        """
        width = zenkaku_len(string) * self.fontsize + \
                hankaku_len(string) * self.fontsize * 0.55
        return (int(math.ceil(width)), self.fontsize)

    def height(self):
        u"""
        Measure rendering height of text.

        If texts is heighter than bounding box,
        jut out lines will be cut off.

        >>> box = [0, 0, 100, 50]
        >>> TextFolder(box, u"abc").height()
        11
        >>> TextFolder(box, u"abc\\ndef").height()
        24
        >>> TextFolder(box, u"abc\\n\\ndef").height()
        37
        >>> TextFolder(box, u"abc\\ndef\\nghi\\njkl").height()
        50
        >>> TextFolder(box, u"abc\\ndef\\nghi\\njkl\\nmno").height()
        50
        >>> TextFolder(box, u"abc", fontsize=24).height()
        24
        >>> TextFolder(box, u"abc\\ndef", line_spacing=8).height()
        30
        >>> TextFolder(box, u"abc\\ndef", fontsize=15, line_spacing=8).height()
        38
        """
        height = 0
        for string in self._result:
            height += self.textsize(string)[1]

        if len(self._result) > 1:
            height += (len(self._result) - 1) * self.line_spacing

        return height

    def each_line(self):
        size = XY(self.box[2] - self.box[0], self.box[3] - self.box[1])

        if self.valign == 'top':
            height = 0
        elif self.valign == 'bottom':
            height = size.y - self.height()
        else:
            height = int(math.ceil((size.y - self.height()) / 2.0))
        base_xy = XY(self.box[0], self.box[1])

        for string in self._result:
            textsize = self.textsize(string)

            halign = size.x - textsize[0] * self.scale
            if self.halign == 'left':
                x = self.padding
            elif self.halign == 'right':
                x = halign - self.padding
            else:
                x = int(math.ceil(halign / 2.0))

            if self.adjustBaseline:
                height += textsize[1]
            draw_xy = XY(base_xy.x + x, base_xy.y + height)

            yield string, draw_xy

            if self.adjustBaseline:
                height += self.line_spacing
            else:
                height += textsize[1] + self.line_spacing

    def outlineBox(self):
        corners = []
        for string, xy in self.each_line():
            textsize = self.textsize(string)
            width = textsize[0] * self.scale
            height = textsize[1] * self.scale

            if self.adjustBaseline:
                xy = XY(xy.x, xy.y - textsize[1])

            corners.append(xy)
            corners.append(XY(xy.x + width, xy.y + height))

        if corners:
            x_margin = 4  # MAGIC number
            y_margin = 2  # MAGIC number
            box = (min(p.x for p in corners) - x_margin,
                   min(p.y for p in corners) - y_margin,
                   max(p.x for p in corners) + x_margin,
                   max(p.y for p in corners) + y_margin)
        else:
            box = self.box

        return box

    def _splitlines(self):
        u"""
        Split text to lines as generator.
        Every line will be stripped.
        If text includes characters "\n", treat as line separator.

        >>> box = [0, 0, 100, 50]
        >>> [l for l in TextFolder(box, u"abc")._splitlines()]
        [u'abc']
        >>> [l for l in TextFolder(box, u"abc\\ndef")._splitlines()]
        [u'abc', u'def']
        >>> [l for l in TextFolder(box, u"abc\\\\ndef")._splitlines()]
        [u'abc', u'def']
        >>> [l for l in TextFolder(box, u" abc \\n def ")._splitlines()]
        [u'abc', u'def']
        >>> [l for l in TextFolder(box, u" \\nabc\\\\ndef")._splitlines()]
        [u'abc', u'def']
        >>> [l for l in TextFolder(box, u" \\\\nabc \\\\ndef")._splitlines()]
        [u'', u'abc', u'def']
        >>> [l for l in TextFolder(box, u"abc\\\\\\\\ndef")._splitlines()]
        [u'abc\\\\ndef']
        >>> [l for l in TextFolder(box, u"abc\xa5\\\\ndef")._splitlines()]
        [u'abc\\\\ndef']
        """
        string = re.sub('^\s*(.*?)\s*$', '\\1', self.string)
        string = re.sub('(?:\xa5|\\\\){2}', '\x00', string)
        string = re.sub('(?:\xa5|\\\\)n', '\n', string)
        for line in string.splitlines():
            yield re.sub('\x00', '\\\\', line).strip()

    def _lines(self):
        lines = []
        size = (self.box[2] - self.box[0], self.box[3] - self.box[1])

        height = 0
        truncated = 0
        for line in self._splitlines():
            while True:
                string = line.strip()
                for i in range(0, len(string)):
                    length = len(string) - i
                    metrics = self.textsize(string[0:length])

                    if metrics[0] <= size[0]:
                        break
                else:
                    length = 0
                    metrics = self.textsize(u" ")

                if size[1] < height + metrics[1]:
                    truncated = 1
                    break

                lines.append(string[0:length])
                height += metrics[1] + self.line_spacing

                line = string[length:]
                if line == "":
                    break

        # truncate last line.
        if len(lines) == 0:
            pass
        elif truncated:
            string = lines.pop()
            for i in range(0, len(string)):
                if i == 0:
                    truncated = string + ' ...'
                else:
                    truncated = string[0:-i] + ' ...'

                metrics = self.textsize(truncated)
                if metrics[0] <= size[0]:
                    lines.append(truncated)
                    break

        return lines
<|endoftext|>


<commit_before>import zipfile
import bom_data_parser as bdp
from phildb.exceptions import DuplicateError

def load_cdo(db, files):

    for f in files:
        data, metadata = bdp.read_climate_data_online_zip(f)

        station_id = '{0:06d}'.format(metadata['Bureau of Meteorology station number'])
        data_column_name = data.columns[0]
        if data_column_name == 'airtemp_max':
            measurand = 'T_MAX'
        elif data_column_name == 'airtemp_min':
            measurand = 'T_MIN'
        else:
            raise ValueError("Unknown CDO data type: '{0}'".format(data_column_name ))

        try:
            db.add_timeseries(station_id)
        except DuplicateError:
            pass

        try:
            db.add_source('BOM_CDO', 'Bureau of Meterology Climate Data Online')
        except DuplicateError:
            pass

        try:
            db.add_measurand('T_MAX', 'MAXIMUM_TEMPERATURE', 'Maximum Temperature')
        except DuplicateError:
            pass

        try:
            db.add_measurand('T_MIN', 'MINIMUM_TEMPERATURE', 'Minimum Temperature')
        except DuplicateError:
            pass

        try:
            db.add_timeseries_instance(station_id, 'D', '', source='BOM_CDO', measurand='T_MAX')
        except DuplicateError:
            pass

        try:
            db.add_timeseries_instance(station_id, 'D', '', source='BOM_CDO', measurand='T_MIN')
        except DuplicateError:
            pass

        print("Loading CDO zip {0} as {1} with measurand {2}".format(f, station_id, measurand))

        db.write(station_id, 'D', data[data_column_name], source='BOM_CDO', measurand=measurand)

<commit_msg>Add reading and loading of streamflow from WDO<commit_after>import zipfile
import bom_data_parser as bdp
from kiwis_pie import KIWIS
from phildb.exceptions import DuplicateError

def load_cdo(db, files):

    for f in files:
        data, metadata = bdp.read_climate_data_online_zip(f)

        station_id = '{0:06d}'.format(metadata['Bureau of Meteorology station number'])
        data_column_name = data.columns[0]
        if data_column_name == 'airtemp_max':
            measurand = 'T_MAX'
        elif data_column_name == 'airtemp_min':
            measurand = 'T_MIN'
        else:
            raise ValueError("Unknown CDO data type: '{0}'".format(data_column_name ))

        try:
            db.add_timeseries(station_id)
        except DuplicateError:
            pass

        try:
            db.add_source('BOM_CDO', 'Bureau of Meterology Climate Data Online')
        except DuplicateError:
            pass

        try:
            db.add_measurand('T_MAX', 'MAXIMUM_TEMPERATURE', 'Maximum Temperature')
        except DuplicateError:
            pass

        try:
            db.add_measurand('T_MIN', 'MINIMUM_TEMPERATURE', 'Minimum Temperature')
        except DuplicateError:
            pass

        try:
            db.add_timeseries_instance(station_id, 'D', '', source='BOM_CDO', measurand='T_MAX')
        except DuplicateError:
            pass

        try:
            db.add_timeseries_instance(station_id, 'D', '', source='BOM_CDO', measurand='T_MIN')
        except DuplicateError:
            pass

        print("Loading CDO zip {0} as {1} with measurand {2}".format(f, station_id, measurand))

        db.write(station_id, 'D', data[data_column_name], source='BOM_CDO', measurand=measurand)

def read_streamflow(station_id, from_date = '1900-01-01', to_date = '2100-01-01'):
    k = KIWIS('http://www.bom.gov.au/waterdata/services')

    ts_id = k.get_timeseries_list(
        station_no = '410730',
        ts_name = 'PR01QaQc.Merged.DailyMean.09HR',
        return_fields = [
            'station_no',
            'ts_id',
            'ts_name',
            'parametertype_name'
        ]
    )['ts_id']

    if len(ts_id) != 1:
        raise ValueError("Unable to get unique series from WISKI for '{0}'".format(station_id))

    sf = k.get_timeseries_values(
        ts_id = ts_id,
        to = to_date,
        return_fields = ['Timestamp', 'Value'],
        **{'from': from_date}
    )

    if len(sf) == 0:
        raise ValueError("No streamflow could be read.")

    sf.index = sf.index.normalize()

    return sf

def load_streamflow(db, station_id):

    sf = read_streamflow(station_id)

    try:
        db.add_timeseries(station_id)
    except DuplicateError:
        pass

    try:
        db.add_source('BOM_WISKI', 'Bureau of Meterology Water Data Online')
    except DuplicateError:
        pass

    try:
        db.add_measurand('Q', 'STREAMFLOW', 'Streamflow')
    except DuplicateError:
        pass

    try:
        db.add_timeseries_instance(station_id, 'D', '', source='BOM_WISKI', measurand='Q')
    except DuplicateError:
        pass

    db.write(station_id, 'D', sf, source='BOM_WISKI', measurand='Q')
<|endoftext|>


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

shell = win32com.client.Dispatch('WScript.Shell')
#shell.Run('firefox')
#shell.AppActivate('firefox')

c = wmi.WMI()
firefox_id = False
for process in c.Win32_Process():
    if process.Name.lower() == 'firefox.exe':
        firefox_id = process.ProcessId
        shell.AppActivate(firefox_id)
        shell.SendKeys('^{F4}') # CTRL + F4
        print 'Close Firefox tab ID: %s' % process.ProcessId
    else:
        print 'Process open ID: %s Name: %s' % (
            process.ProcessId, process.Name)
if not firefox_id:
    print 'No Firefox open'
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<commit_msg>fast git<commit_after># -*- coding: utf-8 -*-
###############################################################################
#
#    Copyright (C) 2001-2014 Micronaet SRL (<http://www.micronaet.it>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published
#    by the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
#import os
#import sys
import wmi
import win32com.client

shell = win32com.client.Dispatch('WScript.Shell')
#shell.Run('firefox')
#shell.AppActivate('firefox')

c = wmi.WMI()
firefox_id = False
for process in c.Win32_Process():
    if process.Name.lower() == 'firefox.exe':
        firefox_id = process.ProcessId
        shell.AppActivate(firefox_id)
        shell.SendKeys('^{F4}') # CTRL + F4
        print 'Close Firefox tab ID: %s' % process.ProcessId
    #else:
    #    print 'Process open ID: %s Name: %s' % (
            process.ProcessId, process.Name)
if not firefox_id:
    print 'No Firefox open'
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<|endoftext|>


<commit_before>"""
A fake implementation of the Vuforia Web Query API.

See
https://library.vuforia.com/articles/Solution/How-To-Perform-an-Image-Recognition-Query
"""

import cgi
import io
import uuid
from typing import Any, Callable, Dict, List, Set, Tuple

import wrapt
from requests import codes
from requests_mock import POST
from requests_mock.request import _RequestObjectProxy
from requests_mock.response import _Context

from mock_vws._constants import ResultCodes
from mock_vws._mock_common import Route, json_dump, set_content_length_header
from mock_vws._mock_web_services_api import MockVuforiaWebServicesAPI

from ._validators import (
    validate_auth_header_exists,
    validate_authorization,
    validate_date,
)

ROUTES = set([])

@wrapt.decorator
def validate_content_type_header(
    wrapped: Callable[..., str],
    instance: Any,  # pylint: disable=unused-argument
    args: Tuple[_RequestObjectProxy, _Context],
    kwargs: Dict,
) -> str:
    """
    Validate the ``Content-Type`` header.

    Args:
        wrapped: An endpoint function for `requests_mock`.
        instance: The class that the endpoint function is in.
        args: The arguments given to the endpoint function.
        kwargs: The keyword arguments given to the endpoint function.

    Returns:
        The result of calling the endpoint.
        An ``UNSUPPORTED_MEDIA_TYPE`` response if the ``Content-Type`` header
        main part is not 'multipart/form-data'.
        A ``BAD_REQUEST`` response if the ``Content-Type`` header does not
        contain a boundary which is in the request body.
    """
    request, context = args

    main_value, pdict = cgi.parse_header(request.headers['Content-Type'])
    if main_value != 'multipart/form-data':
        context.status_code = codes.UNSUPPORTED_MEDIA_TYPE
        context.headers.pop('Content-Type')
        return ''

    if 'boundary' not in pdict:
        context.status_code = codes.BAD_REQUEST
        context.headers['Content-Type'] = 'text/html'
        return (
            'java.io.IOException: RESTEASY007550: '
            'Unable to get boundary for multipart'
        )

    if pdict['boundary'].encode() not in request.body:
        context.status_code = codes.BAD_REQUEST
        context.headers['Content-Type'] = 'text/html'
        return (
            'java.lang.RuntimeException: RESTEASY007500: '
            'Could find no Content-Disposition header within part'
        )

    return wrapped(*args, **kwargs)

@wrapt.decorator
def validate_accept_header(
    wrapped: Callable[..., str],
    instance: Any,  # pylint: disable=unused-argument
    args: Tuple[_RequestObjectProxy, _Context],
    kwargs: Dict,
) -> str:
    """
    Validate the accept header.

    Args:
        wrapped: An endpoint function for `requests_mock`.
        instance: The class that the endpoint function is in.
        args: The arguments given to the endpoint function.
        kwargs: The keyword arguments given to the endpoint function.

    Returns:
        The result of calling the endpoint.
        A `NOT_ACCEPTABLE` response if the Accept header is given and is not
        'application/json' or '*/*'.
    """
    request, context = args

    accept = request.headers.get('Accept')
    if accept in ('application/json', '*/*', None):
        return wrapped(*args, **kwargs)

    context.headers.pop('Content-Type')
    context.status_code = codes.NOT_ACCEPTABLE
    return ''

@wrapt.decorator
def validate_fields_given(
    wrapped: Callable[..., str],
    instance: Any,  # pylint: disable=unused-argument
    args: Tuple[_RequestObjectProxy, _Context],
    kwargs: Dict,
) -> str:
    """
    Validate the fields given.

    Args:
        wrapped: An endpoint function for `requests_mock`.
        instance: The class that the endpoint function is in.
        args: The arguments given to the endpoint function.
        kwargs: The keyword arguments given to the endpoint function.

    Returns:
        The result of calling the endpoint.
    """
    request, context = args
    body_file = io.BytesIO(request.body)

    _, pdict = cgi.parse_header(request.headers['Content-Type'])
    parsed = cgi.parse_multipart(
        fp=body_file,
        pdict={
            'boundary': pdict['boundary'].encode(),
        },
    )

    if 'image' in parsed.keys():
        return wrapped(*args, **kwargs)

    context.status_code = codes.BAD_REQUEST
    return 'No image.'

@wrapt.decorator
def validate_response_body_type(
    wrapped: Callable[..., str],
    instance: Any,  # pylint: disable=unused-argument
    args: Tuple[_RequestObjectProxy, _Context],
    kwargs: Dict,
) -> str:
    """
    Validate body type.

    Args:
        wrapped: An endpoint function for `requests_mock`.
        instance: The class that the endpoint function is in.
        args: The arguments given to the endpoint function.
        kwargs: The keyword arguments given to the endpoint function.

    Returns:
        The result of calling the endpoint.
        An `UNSUPPORTED_MEDIA_TYPE` response if the request body is valid UTF-8
        encoded text.
    """
    request, context = args

    try:
        request.body.decode('utf-8')
    except UnicodeDecodeError:
        return wrapped(*args, **kwargs)

    text = ''
    context.status_code = codes.UNSUPPORTED_MEDIA_TYPE
    context.headers.pop('Content-Type')
    return text

def route(
    path_pattern: str,
    http_methods: List[str],
) -> Callable[..., Callable]:
    """
    Register a decorated method so that it can be recognized as a route.

    Args:
        path_pattern: The end part of a URL pattern. E.g. `/targets` or
            `/targets/.+`.
        http_methods: HTTP methods that map to the route function.
    """

    def decorator(method: Callable[..., str]) -> Callable[..., str]:
        """
        Register a decorated method so that it can be recognized as a route.

        Args:
            method: Method to register.

        Returns:
            The given `method` with multiple changes, including added
            validators.
        """
        ROUTES.add(
            Route(
                route_name=method.__name__,
                path_pattern=path_pattern,
                http_methods=http_methods,
            ),
        )

        decorators = [
            validate_authorization,
            validate_date,
            validate_response_body_type,
            validate_fields_given,
            validate_content_type_header,
            validate_accept_header,
            validate_auth_header_exists,
            set_content_length_header,
        ]

        for decorator in decorators:
            method = decorator(method)

        return method

    return decorator

class MockVuforiaWebQueryAPI:
    """
    A fake implementation of the Vuforia Web Query API.

    This implementation is tied to the implementation of `requests_mock`.
    """

    def __init__(
        self,
        client_access_key: str,
        client_secret_key: str,
        mock_web_services_api: MockVuforiaWebServicesAPI,
    ) -> None:
        """
        Args:
            client_access_key: A VWS client access key.
            client_secret_key: A VWS client secret key.
            mock_web_services_api: An instance of a mock web services API.

        Attributes:
            routes: The `Route`s to be used in the mock.
            access_key (str): A VWS client access key.
            secret_key (str): A VWS client secret key.
            mock_web_services_api (MockVuforiaWebServicesAPI): An instance of a
                mock web services API.
        """
        self.routes: Set[Route] = ROUTES
        self.access_key: str = client_access_key
        self.secret_key: str = client_secret_key
        self.mock_web_services_api = mock_web_services_api

    @route(path_pattern='/v1/query', http_methods=[POST])
    def query(
        self,
        request: _RequestObjectProxy,
        context: _Context,
    ) -> str:
        """
        Perform an image recognition query.
        """
        body_file = io.BytesIO(request.body)

        _, pdict = cgi.parse_header(request.headers['Content-Type'])
        parsed = cgi.parse_multipart(
            fp=body_file,
            pdict={
                'boundary': pdict['boundary'].encode(),
            },
        )

        [max_num_results] = parsed.get('max_num_results', [b'1'])
        invalid_type_error = (
            f"Invalid value '{max_num_results.decode()}' in form data "
            "part 'max_result'. "
            'Expecting integer value in range from 1 to 50 (inclusive).'
        )

        try:
            max_num_results_int = int(max_num_results)
        except ValueError:
            context.status_code = codes.BAD_REQUEST
            return invalid_type_error

        java_max_int = 2147483647
        if max_num_results_int > java_max_int:
            context.status_code = codes.BAD_REQUEST
            return invalid_type_error

        if max_num_results_int < 1 or max_num_results_int > 50:
            context.status_code = codes.BAD_REQUEST
            out_of_range_error = (
                f'Integer out of range ({max_num_results_int}) in form data '
                "part 'max_result'. "
                'Accepted range is from 1 to 50 (inclusive).'
            )
            return out_of_range_error

        [include_target_data] = parsed.get('include_target_data', [b'top'])
        allowed_included_target_data = {b'top', b'all', b'none'}
        if include_target_data not in allowed_included_target_data:
            unexpected_target_data_message = (
                f"Invalid value '{include_target_data.decode()}' in form data "
                "part 'include_target_data'. "
                "Expecting one of the (unquoted) string values 'all', 'none' "
                "or 'top'."
            )
            context.status_code = codes.BAD_REQUEST
            return unexpected_target_data_message

        results: List[Dict[str, Any]] = []
        [image] = parsed['image']
        for target in self.mock_web_services_api.targets:
            if target.image.getvalue() == image:
                target_timestamp = int(target.last_modified_date.timestamp())
                target_data = {
                    'target_timestamp': target_timestamp,
                    'name': target.name,
                    'application_metadata': None,
                }
                result = {
                    'target_id': target.target_id,
                    'target_data': target_data,
                }
                results.append(result)

        body = {
            'result_code': ResultCodes.SUCCESS.value,
            'results': results,
            'query_id': uuid.uuid4().hex,
        }

        value = json_dump(body)
        return value
<commit_msg>Fix lint [skip ci]<commit_after>"""
A fake implementation of the Vuforia Web Query API.

See
https://library.vuforia.com/articles/Solution/How-To-Perform-an-Image-Recognition-Query
"""

import cgi
import io
import uuid
from typing import Any, Callable, Dict, List, Set, Tuple

import wrapt
from requests import codes
from requests_mock import POST
from requests_mock.request import _RequestObjectProxy
from requests_mock.response import _Context

from mock_vws._constants import ResultCodes
from mock_vws._mock_common import Route, json_dump, set_content_length_header
from mock_vws._mock_web_services_api import MockVuforiaWebServicesAPI

from ._validators import (
    validate_auth_header_exists,
    validate_authorization,
    validate_date,
)

ROUTES = set([])

@wrapt.decorator
def validate_content_type_header(
    wrapped: Callable[..., str],
    instance: Any,  # pylint: disable=unused-argument
    args: Tuple[_RequestObjectProxy, _Context],
    kwargs: Dict,
) -> str:
    """
    Validate the ``Content-Type`` header.

    Args:
        wrapped: An endpoint function for `requests_mock`.
        instance: The class that the endpoint function is in.
        args: The arguments given to the endpoint function.
        kwargs: The keyword arguments given to the endpoint function.

    Returns:
        The result of calling the endpoint.
        An ``UNSUPPORTED_MEDIA_TYPE`` response if the ``Content-Type`` header
        main part is not 'multipart/form-data'.
        A ``BAD_REQUEST`` response if the ``Content-Type`` header does not
        contain a boundary which is in the request body.
    """
    request, context = args

    main_value, pdict = cgi.parse_header(request.headers['Content-Type'])
    if main_value != 'multipart/form-data':
        context.status_code = codes.UNSUPPORTED_MEDIA_TYPE
        context.headers.pop('Content-Type')
        return ''

    if 'boundary' not in pdict:
        context.status_code = codes.BAD_REQUEST
        context.headers['Content-Type'] = 'text/html'
        return (
            'java.io.IOException: RESTEASY007550: '
            'Unable to get boundary for multipart'
        )

    if pdict['boundary'].encode() not in request.body:
        context.status_code = codes.BAD_REQUEST
        context.headers['Content-Type'] = 'text/html'
        return (
            'java.lang.RuntimeException: RESTEASY007500: '
            'Could find no Content-Disposition header within part'
        )

    return wrapped(*args, **kwargs)

@wrapt.decorator
def validate_accept_header(
    wrapped: Callable[..., str],
    instance: Any,  # pylint: disable=unused-argument
    args: Tuple[_RequestObjectProxy, _Context],
    kwargs: Dict,
) -> str:
    """
    Validate the accept header.

    Args:
        wrapped: An endpoint function for `requests_mock`.
        instance: The class that the endpoint function is in.
        args: The arguments given to the endpoint function.
        kwargs: The keyword arguments given to the endpoint function.

    Returns:
        The result of calling the endpoint.
        A `NOT_ACCEPTABLE` response if the Accept header is given and is not
        'application/json' or '*/*'.
    """
    request, context = args

    accept = request.headers.get('Accept')
    if accept in ('application/json', '*/*', None):
        return wrapped(*args, **kwargs)

    context.headers.pop('Content-Type')
    context.status_code = codes.NOT_ACCEPTABLE
    return ''

@wrapt.decorator
def validate_fields_given(
    wrapped: Callable[..., str],
    instance: Any,  # pylint: disable=unused-argument
    args: Tuple[_RequestObjectProxy, _Context],
    kwargs: Dict,
) -> str:
    """
    Validate the fields given.

    Args:
        wrapped: An endpoint function for `requests_mock`.
        instance: The class that the endpoint function is in.
        args: The arguments given to the endpoint function.
        kwargs: The keyword arguments given to the endpoint function.

    Returns:
        The result of calling the endpoint.
    """
    request, context = args
    body_file = io.BytesIO(request.body)

    _, pdict = cgi.parse_header(request.headers['Content-Type'])
    parsed = cgi.parse_multipart(
        fp=body_file,
        pdict={
            'boundary': pdict['boundary'].encode(),
        },
    )

    if 'image' in parsed.keys():
        return wrapped(*args, **kwargs)

    context.status_code = codes.BAD_REQUEST
    return 'No image.'

@wrapt.decorator
def validate_response_body_type(
    wrapped: Callable[..., str],
    instance: Any,  # pylint: disable=unused-argument
    args: Tuple[_RequestObjectProxy, _Context],
    kwargs: Dict,
) -> str:
    """
    Validate body type.

    Args:
        wrapped: An endpoint function for `requests_mock`.
        instance: The class that the endpoint function is in.
        args: The arguments given to the endpoint function.
        kwargs: The keyword arguments given to the endpoint function.

    Returns:
        The result of calling the endpoint.
        An `UNSUPPORTED_MEDIA_TYPE` response if the request body is valid UTF-8
        encoded text.
    """
    request, context = args

    try:
        request.body.decode('utf-8')
    except UnicodeDecodeError:
        return wrapped(*args, **kwargs)

    text = ''
    context.status_code = codes.UNSUPPORTED_MEDIA_TYPE
    context.headers.pop('Content-Type')
    return text

def route(
    path_pattern: str,
    http_methods: List[str],
) -> Callable[..., Callable]:
    """
    Register a decorated method so that it can be recognized as a route.

    Args:
        path_pattern: The end part of a URL pattern. E.g. `/targets` or
            `/targets/.+`.
        http_methods: HTTP methods that map to the route function.
    """

    def decorator(method: Callable[..., str]) -> Callable[..., str]:
        """
        Register a decorated method so that it can be recognized as a route.

        Args:
            method: Method to register.

        Returns:
            The given `method` with multiple changes, including added
            validators.
        """
        ROUTES.add(
            Route(
                route_name=method.__name__,
                path_pattern=path_pattern,
                http_methods=http_methods,
            ),
        )

        decorators = [
            validate_authorization,
            validate_date,
            validate_response_body_type,
            validate_fields_given,
            validate_content_type_header,
            validate_accept_header,
            validate_auth_header_exists,
            set_content_length_header,
        ]

        for decorator in decorators:
            method = decorator(method)

        return method

    return decorator

class MockVuforiaWebQueryAPI:
    """
    A fake implementation of the Vuforia Web Query API.

    This implementation is tied to the implementation of `requests_mock`.
    """

    def __init__(
        self,
        client_access_key: str,
        client_secret_key: str,
        mock_web_services_api: MockVuforiaWebServicesAPI,
    ) -> None:
        """
        Args:
            client_access_key: A VWS client access key.
            client_secret_key: A VWS client secret key.
            mock_web_services_api: An instance of a mock web services API.

        Attributes:
            routes: The `Route`s to be used in the mock.
            access_key (str): A VWS client access key.
            secret_key (str): A VWS client secret key.
            mock_web_services_api (MockVuforiaWebServicesAPI): An instance of a
                mock web services API.
        """
        self.routes: Set[Route] = ROUTES
        self.access_key: str = client_access_key
        self.secret_key: str = client_secret_key
        self.mock_web_services_api = mock_web_services_api

    @route(path_pattern='/v1/query', http_methods=[POST])
    def query(
        self,
        request: _RequestObjectProxy,
        context: _Context,
    ) -> str:
        """
        Perform an image recognition query.
        """
        body_file = io.BytesIO(request.body)

        _, pdict = cgi.parse_header(request.headers['Content-Type'])
        parsed = cgi.parse_multipart(
            fp=body_file,
            pdict={
                'boundary': pdict['boundary'].encode(),
            },
        )

        [max_num_results] = parsed.get('max_num_results', [b'1'])
        invalid_type_error = (
            f"Invalid value '{max_num_results.decode()}' in form data "
            "part 'max_result'. "
            'Expecting integer value in range from 1 to 50 (inclusive).'
        )

        try:
            max_num_results_int = int(max_num_results)
        except ValueError:
            context.status_code = codes.BAD_REQUEST
            return invalid_type_error

        java_max_int = 2147483647
        if max_num_results_int > java_max_int:
            context.status_code = codes.BAD_REQUEST
            return invalid_type_error

        if max_num_results_int < 1 or max_num_results_int > 50:
            context.status_code = codes.BAD_REQUEST
            out_of_range_error = (
                f'Integer out of range ({max_num_results_int}) in form data '
                "part 'max_result'. "
                'Accepted range is from 1 to 50 (inclusive).'
            )
            return out_of_range_error

        [include_target_data] = parsed.get('include_target_data', [b'top'])
        allowed_included_target_data = {b'top', b'all', b'none'}
        if include_target_data not in allowed_included_target_data:
            unexpected_target_data_message = (
                f"Invalid value '{include_target_data.decode()}' in form data "
                "part 'include_target_data'. "
                "Expecting one of the (unquoted) string values 'all', 'none' "
                "or 'top'."
            )
            context.status_code = codes.BAD_REQUEST
            return unexpected_target_data_message

        results: List[Dict[str, Any]] = []
        [image] = parsed['image']
        for target in self.mock_web_services_api.targets:
            if target.image.getvalue() == image:
                target_timestamp = int(target.last_modified_date.timestamp())
                target_data = {
                    'target_timestamp': target_timestamp,
                    'name': target.name,
                    'application_metadata': None,
                }
                result = {
                    'target_id': target.target_id,
                    'target_data': target_data,
                }
                results.append(result)

        body = {
            'result_code': ResultCodes.SUCCESS.value,
            'results': results,
            'query_id': uuid.uuid4().hex,
        }

        value = json_dump(body)
        return value
<|endoftext|>


<commit_before>import asyncio

from random import randint

import plugins

def _initialise(bot):
    plugins.register_handler(_handle_me_action)
    plugins.register_user_command(["diceroll", "coinflip"])

def _handle_me_action(bot, event, command):
    if event.text.startswith('/me'):
        if event.text.find("roll dice") > -1 or event.text.find("rolls dice") > -1 or event.text.find("rolls a dice") > -1 or event.text.find("rolled a dice") > -1:
            yield from asyncio.sleep(0.2)
            yield from command.run(bot, event, *["diceroll"])
        elif event.text.find("flips a coin") > -1 or event.text.find("flips coin") > -1 or event.text.find("flip coin") > -1 or event.text.find("flipped a coin") > -1:
            yield from asyncio.sleep(0.2)
            yield from command.run(bot, event, *["coinflip"])
        else:
            pass

def diceroll(bot, event, dice="1d6", *args):
    """rolls dice
    supply the number and sides of the dice as 'xdy' to roll x dice with y sides, e.g. 2d10 rolls 2 ten sided dice
    specifying simply dy will roll 1 y sided dice
    no parameter defaults to 1d6
    """
    errmsg = "dice rolls are specified as '$numberd$sides'"
    try:
        n,s = dice.split('d')
    except Exception:
        yield from bot.coro_send_message(event.conv, errmsg)
        return
    if not s:
        yield from bot.coro_send_message(event.conv, errmsg)
        return
    if not n:
        n = 1
    msg = "{} rolled ".format(event.user.full_name)
    tot = 0
    for i in range(0,int(n)):
        r = randint(1,int(s))
        tot = tot+r
        if i != 0:
            msg = msg+", "
        msg = msg+"{}".format(r)
    if int(n) != 1:
        msg = msg+" for a total of {}".format(tot)
    yield from bot.coro_send_message(event.conv, msg)

def coinflip(bot, event, *args):
    """flip a coin"""
    if randint(1,2) == 1:
        yield from bot.coro_send_message(event.conv, _("{}, coin turned up heads").format(event.user.full_name))
    else:
        yield from bot.coro_send_message(event.conv, _("{}, coin turned up tails").format(event.user.full_name))
<commit_msg>minor improvements to chance<commit_after>import asyncio

from random import randint

import plugins

def _initialise(bot):
    plugins.register_handler(_handle_me_action)
    plugins.register_user_command(["diceroll", "coinflip"])

def _handle_me_action(bot, event, command):
    if event.text.startswith('/me'):
        if event.text.find("roll dice") > -1 or event.text.find("rolls dice") > -1 or event.text.find("rolls a dice") > -1 or event.text.find("rolled a dice") > -1:
            yield from asyncio.sleep(0.2)
            yield from command.run(bot, event, *["diceroll"])
        elif event.text.find("flips a coin") > -1 or event.text.find("flips coin") > -1 or event.text.find("flip coin") > -1 or event.text.find("flipped a coin") > -1:
            yield from asyncio.sleep(0.2)
            yield from command.run(bot, event, *["coinflip"])
        else:
            pass

def diceroll(bot, event, dice="1d6", *args):
    """Rolls dice
    supply the number and sides of the dice as 'nds' to roll n dice with s sides
    'ds' will roll 1 s sided dice
    no parameters defaults to 1d6
    """
    usage = "usage: diceroll nds"
    try:
        n,s = dice.split('d')
    except Exception:
        yield from bot.coro_send_message(event.conv, usage)
        return
    if not s:
        yield from bot.coro_send_message(event.conv, usage)
        return
    if not n:
        n = 1
    n = int(n)
    s = int(s)
    if n < 1:
        yield from bot.coro_send_message(event.conv, "number of dice must be 1 or more")
        return
    if s < 2:
        yield from bot.coro_send_message(event.conv, "number of sides must be 2 or more")
        return
    msg = _("{} rolled ").format(event.user.full_name)
    total = 0
    for i in range(0,n):
        roll = randint(1,s)
        total = total + roll
        if i != 0:
            msg = msg + ", "
        msg = msg + _("{}").format(roll)
    if n != 1:
        msg = msg + _(" totalling {}").format(total)
    yield from bot.coro_send_message(event.conv, msg)

def coinflip(bot, event, *args):
    """flip a coin"""
    if randint(1,2) == 1:
        yield from bot.coro_send_message(event.conv, _("{}, coin turned up heads").format(event.user.full_name))
    else:
        yield from bot.coro_send_message(event.conv, _("{}, coin turned up tails").format(event.user.full_name))
<|endoftext|>