<commit_before># -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
from logging import getLogger
import svgwrite
from psd_tools.user_api import BBox
from psd_tools.constants import TaggedBlock
from psd2svg.converter.constants import BLEND_MODE
from psd2svg.utils.xml import safe_utf8
from psd2svg.utils.color import cmyk2rgb
import numpy as np

logger = getLogger(__name__)

class LayerConverter(object):

    def convert_layer(self, layer):
        """
        Convert the given layer.

        The current implementation always converts a PSD layer to a single
        SVG element.

        :return: SVG element.
        """
        if layer.is_group():
            element = self.create_group(layer)

        elif layer.has_relevant_pixels():
            element = self.create_image(layer)
            if layer.kind == 'type':
                # TODO: Embed text metadata.
                # text = self._get_text(layer)
                pass

        elif layer.kind == 'shape' and layer.has_path():
            element = self.create_path(layer)
            # TODO: Deal with coflict in add_attributes() later.
            # Blending, mask, and class names conflict.
            element = self.add_stroke_style(layer, element)
            element = self.add_stroke_content_style(layer, element)

        else:
            # Boxless element is either shape fill or adjustment.
            # element = self._get_adjustments(layer)
            element = self.create_rect(layer)

        element = self.add_fill(layer, element)
        element = self.add_attributes(layer, element)
        mask_element = self.create_mask(layer)
        if mask_element and not layer.mask.disabled:
            element['mask'] = mask_element.get_funciri()

        element = self.add_effects(layer, element)
        return element

    def create_group(self, group, element=None):
        """Create and fill in a new group element."""
        if not element:
            element = self._dwg.g()
        for child_layer in reversed(group.layers):
            child_element = self.convert_layer(child_layer)
            element.add(child_element)

            # Clipping.
            if len(child_layer.clip_layers) > 0:
                clip_group = self.create_clipping(child_layer, child_element)
                element.add(clip_group)

                # TODO: Blending option.
                # layer.get_tag(TaggedBlock.BLEND_CLIPPING_ELEMENTS)
        return element

    def create_image(self, layer):
        """Create an image element."""
        element = self._dwg.image(
            self._get_image_href(layer.as_PIL()),
            insert=(layer.left, layer.top),
            size=(layer.width, layer.height),
            debug=False)  # To disable attribute validation.
        return element

    def create_path(self, layer):
        """Create a path element."""
        path = self._dwg.path(d=self.generate_path(layer.vector_mask))
        if layer.vector_mask.initial_fill_rule:
            element = self._dwg.defs.add(self._dwg.rect(
                insert=(self._psd.bbox.x1, self._psd.bbox.y1),
                size=(self._psd.bbox.width, self._psd.bbox.height)))
            mask = self._dwg.defs.add(self._dwg.mask())
            mask.add(self._dwg.rect(
                insert=(self._psd.bbox.x1, self._psd.bbox.y1),
                size=(self._psd.bbox.width, self._psd.bbox.height),
                fill='white'))
            path['fill'] = 'black'
            mask.add(path)
            element['mask'] = mask.get_funciri()
            use = self._dwg.use(element.get_iri())
            return use
        else:
            return path

    def create_rect(self, layer):
        """Create a shape or adjustment element."""
        if layer.has_box():
            element = self._dwg.rect(
                insert=(layer.left, layer.top),
                size=(layer.width, layer.height))
        else:
            element = self._dwg.rect(
                insert=(self._psd.bbox.x1, self._psd.bbox.y1),
                size=(self._psd.bbox.width, self._psd.bbox.height))
        # TODO: Create a backdrop-filter.
        element['fill'] = 'none'
        return element

    def create_mask(self, layer):
        """Create a mask."""
        if not layer.has_mask() or not layer.mask.has_box():
            return None

        # In SVG, mask needs a default rect.
        viewbox = layer.bbox
        if viewbox.is_empty():
            viewbox = BBox(0, 0, self.width, self.height)
        mask_element = self._dwg.defs.add(self._dwg.mask(
            size=(viewbox.width, viewbox.height)))
        mask_element.add(self._dwg.rect(
            insert=(viewbox.x1, viewbox.y1),
            size=(viewbox.width, viewbox.height),
            fill='rgb({0},{0},{0})'.format(layer.mask.background_color)))
        mask_element.add(self._dwg.image(
            self._get_image_href(layer.mask.as_PIL()),
            size=(layer.mask.width, layer.mask.height),
            insert=(layer.mask.left, layer.mask.top)))
        mask_element['color-interpolation'] = 'sRGB'
        return mask_element

    def create_clipping(self, layer, clip_element):
        """Create clipped elements."""
        # Create a mask for this clip element.
        if isinstance(clip_element, svgwrite.path.Path):
            clippath = self._dwg.defs.add(self._dwg.clipPath())
            use = self._dwg.use(clip_element.get_iri())
            clippath.add(use)
            element = self._dwg.g()
            element['clip-path'] = clippath.get_funciri()
        else:
            mask = self._dwg.defs.add(self._dwg.mask())
            use = self._dwg.use(clip_element.get_iri())
            use['filter'] = self._get_white_filter().get_funciri()
            mask.add(use)
            mask['color-interpolation'] = 'sRGB'
            element = self._dwg.g(mask=mask.get_funciri())

        element['class'] = 'psd-clipping'
        for child_layer in reversed(layer.clip_layers):
            clipped_element = self.convert_layer(child_layer)
            if clipped_element:
                element.add(clipped_element)
        return element

    def create_preview(self, hidden=True):
        """Create a preview image of the photoshop."""
        element = self._dwg.image(
            self._get_image_href(self._psd.as_PIL()),
            insert=(0, 0),
            size=(self.width, self.height))
        element['class'] = 'photoshop-image'
        if hidden:
            element['visibility'] = 'hidden'
        return element

    def add_fill(self, layer, element):
        """Add fill attribute to the given element."""
        if layer.has_tag(TaggedBlock.SOLID_COLOR_SHEET_SETTING):
            effect = layer.get_tag(TaggedBlock.SOLID_COLOR_SHEET_SETTING)
            element['fill'] = self.create_solid_color(effect)
        elif layer.has_tag(TaggedBlock.PATTERN_FILL_SETTING):
            effect = layer.get_tag(TaggedBlock.PATTERN_FILL_SETTING)
            pattern_element = self.create_pattern(effect)
            element['fill'] = pattern_element.get_funciri()
        elif layer.has_tag(TaggedBlock.GRADIENT_FILL_SETTING):
            effect = layer.get_tag(TaggedBlock.GRADIENT_FILL_SETTING)
            if layer.kind == 'shape' and not layer.has_box():
                bbox = layer.get_bbox(vector=True)
            else:
                bbox = layer.bbox
            if bbox.is_empty():
                bbox = layer._psd.viewbox
            gradient = self.create_gradient(effect, (bbox.width, bbox.height))
            element['fill'] = gradient.get_funciri()
        return element

    def add_attributes(self, layer, element):
        """Add layer attributes such as blending or visibility options."""
        element.set_desc(title=safe_utf8(layer.name))
        element['class'] = 'psd-layer psd-{}'.format(layer.kind)
        if not layer.visible:
            element['visibility'] = 'hidden'
        if layer.opacity < 255.0:
            element['opacity'] = layer.opacity / 255.0
        self.add_blend_mode(element, layer.blend_mode)
        return element

    def add_blend_mode(self, element, blend_mode):
        """Set blending option to the element."""
        blend_mode = BLEND_MODE.get(blend_mode, 'normal')
        if blend_mode != 'normal':
            element['style'] = 'mix-blend-mode: {}'.format(blend_mode)

    def create_solid_color(self, effect):
        """
        Create a fill attribute.

        This is supposed to be solidColor of SVG 1.2 Tiny spec, but for now,
        implement as fill attribute.

        :rtype: str
        """
        color = effect.color
        print(color)
        if color.name == 'rgb':
            return 'rgb({},{},{})'.format(*map(int, color.value))
        elif color.name == 'gray':
            return 'rgb({0},{0},{0})'.format(int(255 * color.value[0]))
        elif color.name == 'cmyk':
            rgb = cmyk2rgb(color.value)
            return 'rgb({},{},{})'.format(*map(int, rgb))
        else:
            logger.warning('Unsupported color: {}'.format(color))
            return 'rgba(0,0,0,0)'

    def create_pattern(self, effect, insert=(0, 0)):
        """Create a pattern element."""
        pattern = self._psd.patterns.get(effect.pattern.id)
        phase = effect.phase
        scale = effect.scale
        if not pattern:
            logger.error('Pattern data not found')
            return self._dwg.defs.add(svgwrite.pattern.Pattern())

        element = self._dwg.defs.add(svgwrite.pattern.Pattern(
            width=pattern.width,
            height=pattern.height,
            patternUnits='userSpaceOnUse',
            patternContentUnits='userSpaceOnUse',
            patternTransform='translate({},{}) scale({})'.format(
                insert[0] + phase[0], insert[1] + phase[1], scale / 100.0),
        ))
        element.add(self._dwg.image(
            self._get_image_href(pattern.as_PIL()),
            insert=(0, 0),
            size=(pattern.width, pattern.height),
        ))
        return element

    def create_gradient(self, effect, size):
        if effect.type == 'radial':
            element = self._dwg.defs.add(svgwrite.gradients.RadialGradient(
                center=None, r=.5))
        else:
            theta = np.radians(-effect.angle)
            start = np.array([size[0] * np.cos(theta - np.pi),
                              size[1] * np.sin(theta - np.pi)])
            end = np.array([size[0] * np.cos(theta), size[1] * np.sin(theta)])
            r = 1.0 * np.max(np.abs(start))

            start = start / (2 * r) + 0.5
            end = end / (2 * r) + 0.5

            start = [np.around(x, decimals=6) for x in start]
            end = [np.around(x, decimals=6) for x in end]

            element = self._dwg.defs.add(svgwrite.gradients.LinearGradient(
                start=start, end=end))

        gradient = effect.gradient
        if not gradient.colors:
            logger.warning("Unsupported gradient type: {}".format(gradient))
            return element

        # Interpolate color and opacity for both points.
        cp = np.array([x.location / 4096 for x in gradient.colors])
        op = np.array([x.location / 4096 for x in gradient.transform])
        c_items = np.array([
            x.color.value for x in gradient.colors]).transpose()
        o_items = np.array([x.opacity / 100.0 for x in gradient.transform])

        # Remove duplicate points.
        index = np.concatenate((np.diff(cp) > 0, [True]))
        if np.any(np.logical_not(index)):
            logger.warning('Duplicate gradient color stop: {}'.format(cp))
        cp = cp[index]
        c_items = c_items[:, index]
        index = np.concatenate((np.diff(op) > 0, [True]))
        if np.any(np.logical_not(index)):
            logger.warning('Duplicate gradient opacity stop: {}'.format(op))
        op = op[index]
        o_items = o_items[index]

        # Single point handling.
        if len(cp) < 2:
            cp = np.array([0.0, 1.0])
            c_items = np.concatenate((c_items, c_items), axis=1)
        if len(op) < 2:
            op = np.array([0.0, 1.0])
            o_items = np.array(list(o_items) + list(o_items))

        # Reverse if specified.
        if effect.reversed:
            cp = 1.0 - cp[::-1]
            op = 1.0 - op[::-1]
            c_items = c_items[:, ::-1]
            o_items = o_items[::-1]

        mp = np.unique(np.concatenate((cp, op)))
        fc = np.stack(
            [np.interp(mp, cp, c_items[index, :]) for index in range(3)])
        fo = np.interp(mp, op, o_items)

        for index in range(len(mp)):
            color = tuple(fc[:, index].astype(np.uint8).tolist())
            element.add_stop_color(offset=mp[index], opacity=fo[index],
                                   color='rgb{}'.format(color))
        return element
<commit_msg>Remove print<commit_after># -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
from logging import getLogger
import svgwrite
from psd_tools.user_api import BBox
from psd_tools.constants import TaggedBlock
from psd2svg.converter.constants import BLEND_MODE
from psd2svg.utils.xml import safe_utf8
from psd2svg.utils.color import cmyk2rgb
import numpy as np

logger = getLogger(__name__)

class LayerConverter(object):

    def convert_layer(self, layer):
        """
        Convert the given layer.

        The current implementation always converts a PSD layer to a single
        SVG element.

        :return: SVG element.
        """
        if layer.is_group():
            element = self.create_group(layer)

        elif layer.has_relevant_pixels():
            element = self.create_image(layer)
            if layer.kind == 'type':
                # TODO: Embed text metadata.
                # text = self._get_text(layer)
                pass

        elif layer.kind == 'shape' and layer.has_path():
            element = self.create_path(layer)
            # TODO: Deal with coflict in add_attributes() later.
            # Blending, mask, and class names conflict.
            element = self.add_stroke_style(layer, element)
            element = self.add_stroke_content_style(layer, element)

        else:
            # Boxless element is either shape fill or adjustment.
            # element = self._get_adjustments(layer)
            element = self.create_rect(layer)

        element = self.add_fill(layer, element)
        element = self.add_attributes(layer, element)
        mask_element = self.create_mask(layer)
        if mask_element and not layer.mask.disabled:
            element['mask'] = mask_element.get_funciri()

        element = self.add_effects(layer, element)
        return element

    def create_group(self, group, element=None):
        """Create and fill in a new group element."""
        if not element:
            element = self._dwg.g()
        for child_layer in reversed(group.layers):
            child_element = self.convert_layer(child_layer)
            element.add(child_element)

            # Clipping.
            if len(child_layer.clip_layers) > 0:
                clip_group = self.create_clipping(child_layer, child_element)
                element.add(clip_group)

                # TODO: Blending option.
                # layer.get_tag(TaggedBlock.BLEND_CLIPPING_ELEMENTS)
        return element

    def create_image(self, layer):
        """Create an image element."""
        element = self._dwg.image(
            self._get_image_href(layer.as_PIL()),
            insert=(layer.left, layer.top),
            size=(layer.width, layer.height),
            debug=False)  # To disable attribute validation.
        return element

    def create_path(self, layer):
        """Create a path element."""
        path = self._dwg.path(d=self.generate_path(layer.vector_mask))
        if layer.vector_mask.initial_fill_rule:
            element = self._dwg.defs.add(self._dwg.rect(
                insert=(self._psd.bbox.x1, self._psd.bbox.y1),
                size=(self._psd.bbox.width, self._psd.bbox.height)))
            mask = self._dwg.defs.add(self._dwg.mask())
            mask.add(self._dwg.rect(
                insert=(self._psd.bbox.x1, self._psd.bbox.y1),
                size=(self._psd.bbox.width, self._psd.bbox.height),
                fill='white'))
            path['fill'] = 'black'
            mask.add(path)
            element['mask'] = mask.get_funciri()
            use = self._dwg.use(element.get_iri())
            return use
        else:
            return path

    def create_rect(self, layer):
        """Create a shape or adjustment element."""
        if layer.has_box():
            element = self._dwg.rect(
                insert=(layer.left, layer.top),
                size=(layer.width, layer.height))
        else:
            element = self._dwg.rect(
                insert=(self._psd.bbox.x1, self._psd.bbox.y1),
                size=(self._psd.bbox.width, self._psd.bbox.height))
        # TODO: Create a backdrop-filter.
        element['fill'] = 'none'
        return element

    def create_mask(self, layer):
        """Create a mask."""
        if not layer.has_mask() or not layer.mask.has_box():
            return None

        # In SVG, mask needs a default rect.
        viewbox = layer.bbox
        if viewbox.is_empty():
            viewbox = BBox(0, 0, self.width, self.height)
        mask_element = self._dwg.defs.add(self._dwg.mask(
            size=(viewbox.width, viewbox.height)))
        mask_element.add(self._dwg.rect(
            insert=(viewbox.x1, viewbox.y1),
            size=(viewbox.width, viewbox.height),
            fill='rgb({0},{0},{0})'.format(layer.mask.background_color)))
        mask_element.add(self._dwg.image(
            self._get_image_href(layer.mask.as_PIL()),
            size=(layer.mask.width, layer.mask.height),
            insert=(layer.mask.left, layer.mask.top)))
        mask_element['color-interpolation'] = 'sRGB'
        return mask_element

    def create_clipping(self, layer, clip_element):
        """Create clipped elements."""
        # Create a mask for this clip element.
        if isinstance(clip_element, svgwrite.path.Path):
            clippath = self._dwg.defs.add(self._dwg.clipPath())
            use = self._dwg.use(clip_element.get_iri())
            clippath.add(use)
            element = self._dwg.g()
            element['clip-path'] = clippath.get_funciri()
        else:
            mask = self._dwg.defs.add(self._dwg.mask())
            use = self._dwg.use(clip_element.get_iri())
            use['filter'] = self._get_white_filter().get_funciri()
            mask.add(use)
            mask['color-interpolation'] = 'sRGB'
            element = self._dwg.g(mask=mask.get_funciri())

        element['class'] = 'psd-clipping'
        for child_layer in reversed(layer.clip_layers):
            clipped_element = self.convert_layer(child_layer)
            if clipped_element:
                element.add(clipped_element)
        return element

    def create_preview(self, hidden=True):
        """Create a preview image of the photoshop."""
        element = self._dwg.image(
            self._get_image_href(self._psd.as_PIL()),
            insert=(0, 0),
            size=(self.width, self.height))
        element['class'] = 'photoshop-image'
        if hidden:
            element['visibility'] = 'hidden'
        return element

    def add_fill(self, layer, element):
        """Add fill attribute to the given element."""
        if layer.has_tag(TaggedBlock.SOLID_COLOR_SHEET_SETTING):
            effect = layer.get_tag(TaggedBlock.SOLID_COLOR_SHEET_SETTING)
            element['fill'] = self.create_solid_color(effect)
        elif layer.has_tag(TaggedBlock.PATTERN_FILL_SETTING):
            effect = layer.get_tag(TaggedBlock.PATTERN_FILL_SETTING)
            pattern_element = self.create_pattern(effect)
            element['fill'] = pattern_element.get_funciri()
        elif layer.has_tag(TaggedBlock.GRADIENT_FILL_SETTING):
            effect = layer.get_tag(TaggedBlock.GRADIENT_FILL_SETTING)
            if layer.kind == 'shape' and not layer.has_box():
                bbox = layer.get_bbox(vector=True)
            else:
                bbox = layer.bbox
            if bbox.is_empty():
                bbox = layer._psd.viewbox
            gradient = self.create_gradient(effect, (bbox.width, bbox.height))
            element['fill'] = gradient.get_funciri()
        return element

    def add_attributes(self, layer, element):
        """Add layer attributes such as blending or visibility options."""
        element.set_desc(title=safe_utf8(layer.name))
        element['class'] = 'psd-layer psd-{}'.format(layer.kind)
        if not layer.visible:
            element['visibility'] = 'hidden'
        if layer.opacity < 255.0:
            element['opacity'] = layer.opacity / 255.0
        self.add_blend_mode(element, layer.blend_mode)
        return element

    def add_blend_mode(self, element, blend_mode):
        """Set blending option to the element."""
        blend_mode = BLEND_MODE.get(blend_mode, 'normal')
        if blend_mode != 'normal':
            element['style'] = 'mix-blend-mode: {}'.format(blend_mode)

    def create_solid_color(self, effect):
        """
        Create a fill attribute.

        This is supposed to be solidColor of SVG 1.2 Tiny spec, but for now,
        implement as fill attribute.

        :rtype: str
        """
        color = effect.color
        if color.name == 'rgb':
            return 'rgb({},{},{})'.format(*map(int, color.value))
        elif color.name == 'gray':
            return 'rgb({0},{0},{0})'.format(int(255 * color.value[0]))
        elif color.name == 'cmyk':
            rgb = cmyk2rgb(color.value)
            return 'rgb({},{},{})'.format(*map(int, rgb))
        else:
            logger.warning('Unsupported color: {}'.format(color))
            return 'rgba(0,0,0,0)'

    def create_pattern(self, effect, insert=(0, 0)):
        """Create a pattern element."""
        pattern = self._psd.patterns.get(effect.pattern.id)
        phase = effect.phase
        scale = effect.scale
        if not pattern:
            logger.error('Pattern data not found')
            return self._dwg.defs.add(svgwrite.pattern.Pattern())

        element = self._dwg.defs.add(svgwrite.pattern.Pattern(
            width=pattern.width,
            height=pattern.height,
            patternUnits='userSpaceOnUse',
            patternContentUnits='userSpaceOnUse',
            patternTransform='translate({},{}) scale({})'.format(
                insert[0] + phase[0], insert[1] + phase[1], scale / 100.0),
        ))
        element.add(self._dwg.image(
            self._get_image_href(pattern.as_PIL()),
            insert=(0, 0),
            size=(pattern.width, pattern.height),
        ))
        return element

    def create_gradient(self, effect, size):
        if effect.type == 'radial':
            element = self._dwg.defs.add(svgwrite.gradients.RadialGradient(
                center=None, r=.5))
        else:
            theta = np.radians(-effect.angle)
            start = np.array([size[0] * np.cos(theta - np.pi),
                              size[1] * np.sin(theta - np.pi)])
            end = np.array([size[0] * np.cos(theta), size[1] * np.sin(theta)])
            r = 1.0 * np.max(np.abs(start))

            start = start / (2 * r) + 0.5
            end = end / (2 * r) + 0.5

            start = [np.around(x, decimals=6) for x in start]
            end = [np.around(x, decimals=6) for x in end]

            element = self._dwg.defs.add(svgwrite.gradients.LinearGradient(
                start=start, end=end))

        gradient = effect.gradient
        if not gradient.colors:
            logger.warning("Unsupported gradient type: {}".format(gradient))
            return element

        # Interpolate color and opacity for both points.
        cp = np.array([x.location / 4096 for x in gradient.colors])
        op = np.array([x.location / 4096 for x in gradient.transform])
        c_items = np.array([
            x.color.value for x in gradient.colors]).transpose()
        o_items = np.array([x.opacity / 100.0 for x in gradient.transform])

        # Remove duplicate points.
        index = np.concatenate((np.diff(cp) > 0, [True]))
        if np.any(np.logical_not(index)):
            logger.warning('Duplicate gradient color stop: {}'.format(cp))
        cp = cp[index]
        c_items = c_items[:, index]
        index = np.concatenate((np.diff(op) > 0, [True]))
        if np.any(np.logical_not(index)):
            logger.warning('Duplicate gradient opacity stop: {}'.format(op))
        op = op[index]
        o_items = o_items[index]

        # Single point handling.
        if len(cp) < 2:
            cp = np.array([0.0, 1.0])
            c_items = np.concatenate((c_items, c_items), axis=1)
        if len(op) < 2:
            op = np.array([0.0, 1.0])
            o_items = np.array(list(o_items) + list(o_items))

        # Reverse if specified.
        if effect.reversed:
            cp = 1.0 - cp[::-1]
            op = 1.0 - op[::-1]
            c_items = c_items[:, ::-1]
            o_items = o_items[::-1]

        mp = np.unique(np.concatenate((cp, op)))
        fc = np.stack(
            [np.interp(mp, cp, c_items[index, :]) for index in range(3)])
        fo = np.interp(mp, op, o_items)

        for index in range(len(mp)):
            color = tuple(fc[:, index].astype(np.uint8).tolist())
            element.add_stop_color(offset=mp[index], opacity=fo[index],
                                   color='rgb{}'.format(color))
        return element
<|endoftext|>


<commit_before>import uuid
import time
import hashlib
import os
import getpass
import json
import logging
import socket

from parsl.dataflow.states import States

logger = logging.getLogger(__name__)

class UsageTracker (object) :
    """ Anonymized Usage Tracking for Parsl

    Client for this is here : https://github.com/Parsl/parsl_tracking
    This issue captures the discussion that went into functionality
    implemented here : https://github.com/Parsl/parsl/issues/34

    """

    def __init__ (self, dfk, ip='52.3.111.203', port=50077,
                  domain_name='tracking.parsl-project.org'):
        ''' Initialize usage tracking unless the user has opted-out.
        Tracks usage stats by inspecting the internal state of the dfk.

        Args:
             - dfk (DFK object) : Data Flow Kernel object

        KWargs:
             - ip (string) : IP address
             - port (int) : Port number, Default:50077
             - domain_name (string) : Domain name, will override IP
                  Default: tracking.parsl-project.org
        '''
        if domain_name :
            try:
                self.UDP_IP = socket.gethostbyname(domain_name)
            except Exception as e:
                logging.debug("Could not lookup domain_name, defaulting to 52.3.111.203")
                self.UDP_IP = ip
        else:
            self.UDP_IP = ip
        self.UDP_PORT= port
        self.dfk     = dfk
        self.config  = self.dfk.config
        self.uuid    = str(uuid.uuid4())
        print("Target : {}:{}".format(self.UDP_IP, self.UDP_PORT))
        self.test_mode, self.tracking_enabled = self.check_tracking_enabled()
        logger.debug("Tracking status: {}".format(self.tracking_enabled))
        logger.debug("Testing mode   : {}".format(self.test_mode))
        self.initialized = False # Once first message is sent this will be True

    def check_tracking_enabled (self):
        ''' By default tracking is enabled.

        If Test mode is set via env variable PARSL_TESTING, a test flag is set

        Tracking is disabled if :
            1. config["globals"]["usageTracking"] is set to False (Bool)
            2. Environment variable PARSL_TRACKING is set to false (case insensitive)

        '''

        track = True   # By default we track usage
        test  = False  # By default we are not in testing mode

        testvar = str(os.environ.get("PARSL_TESTING", 'None')).lower()
        if testvar == 'true' :
            test = True

        if self.config and self.config["globals"]["usageTracking"] == False:
            track = False

        envvar = str(os.environ.get("PARSL_TRACKING", True)).lower()
        if envvar == "false" :
            track = False

        return test, track

    def construct_start_message (self):
        """ Collect preliminary run info at the start of the DFK.

        Returns :
              - Message dict dumped as json string, ready for UDP
        """

        uname = getpass.getuser().encode('latin1')
        hashed_username = hashlib.sha256(uname).hexdigest()[0:10]
        hname = socket.gethostname().encode('latin1')
        hashed_hostname = hashlib.sha256(hname).hexdigest()[0:10]
        message = { 'uuid' : self.uuid,
                    'uname': hashed_username,
                    'hname': hashed_hostname,
                    'test' : self.test_mode,
                    'start': time.time() }

        return json.dumps(message)

    def construct_end_message (self):
        """ Collect the final run information at the time of DFK
        cleanup.

        Returns:
             - Message dict dumped as json string, ready for UDP
        """

        app_count = self.dfk.task_count

        site_count = 0
        if self.dfk._executors_managed :
            site_count = len(self.dfk.config['sites'])

        failed_states = (States.failed, States.dep_fail)
        app_fails = len([t for t in self.dfk.tasks if
                         self.dfk.tasks[t]['status'] in failed_states])

        message = { 'uuid'   : self.uuid,
                    'end'    : time.time(),
                    't_apps' : app_count,
                    'sites'  : site_count,
                    'c_time' : None,
                    'test'   : self.test_mode,
        }

        return json.dumps(message)

    def send_UDP_message(self, message):
        """ Send UDP message
        """
        if self.tracking_enabled :
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
                x = sock.sendto(bytes(message, "utf-8"), (self.UDP_IP, self.UDP_PORT))
                sock.close()
            except OSError as e:
                logger.debug("Unable to reach the network to send usage data")
                x = 0
        else:
            x = -1

        return x

    def send_message(self):
        """ Send message over UDP.
        If tracking is disables, the bytes_sent will always be set to -1

        Returns:
            (bytes_sent, time_taken)
        """
        start = time.time()
        message = None
        if not self.initialized :
            message = self.construct_start_message()
            self.initialized = True
        else:
            message = self.construct_end_message()

        x = self.send_UDP_message(message)
        end = time.time()

        return x, end-start

if __name__ == '__main__' :

    from parsl import *

    workers = ThreadPoolExecutor(max_workers=4)
    dfk = DataFlowKernel(executors=[workers])

    #ut = UsageTracker(dfk, ip='52.3.111.203')
    ut = UsageTracker(dfk, domain_name='tracking.parsl-project.org')

    for i in range(0,2):
        x = ut.send_message()
        print(x)
<commit_msg>Removing stray print line<commit_after>import uuid
import time
import hashlib
import os
import getpass
import json
import logging
import socket

from parsl.dataflow.states import States

logger = logging.getLogger(__name__)

class UsageTracker (object) :
    """ Anonymized Usage Tracking for Parsl

    Client for this is here : https://github.com/Parsl/parsl_tracking
    This issue captures the discussion that went into functionality
    implemented here : https://github.com/Parsl/parsl/issues/34

    """

    def __init__ (self, dfk, ip='52.3.111.203', port=50077,
                  domain_name='tracking.parsl-project.org'):
        ''' Initialize usage tracking unless the user has opted-out.
        Tracks usage stats by inspecting the internal state of the dfk.

        Args:
             - dfk (DFK object) : Data Flow Kernel object

        KWargs:
             - ip (string) : IP address
             - port (int) : Port number, Default:50077
             - domain_name (string) : Domain name, will override IP
                  Default: tracking.parsl-project.org
        '''
        if domain_name :
            try:
                self.UDP_IP = socket.gethostbyname(domain_name)
            except Exception as e:
                logging.debug("Could not lookup domain_name, defaulting to 52.3.111.203")
                self.UDP_IP = ip
        else:
            self.UDP_IP = ip
        self.UDP_PORT= port
        self.dfk     = dfk
        self.config  = self.dfk.config
        self.uuid    = str(uuid.uuid4())
        self.test_mode, self.tracking_enabled = self.check_tracking_enabled()
        logger.debug("Tracking status: {}".format(self.tracking_enabled))
        logger.debug("Testing mode   : {}".format(self.test_mode))
        self.initialized = False # Once first message is sent this will be True

    def check_tracking_enabled (self):
        ''' By default tracking is enabled.

        If Test mode is set via env variable PARSL_TESTING, a test flag is set

        Tracking is disabled if :
            1. config["globals"]["usageTracking"] is set to False (Bool)
            2. Environment variable PARSL_TRACKING is set to false (case insensitive)

        '''

        track = True   # By default we track usage
        test  = False  # By default we are not in testing mode

        testvar = str(os.environ.get("PARSL_TESTING", 'None')).lower()
        if testvar == 'true' :
            test = True

        if self.config and self.config["globals"]["usageTracking"] == False:
            track = False

        envvar = str(os.environ.get("PARSL_TRACKING", True)).lower()
        if envvar == "false" :
            track = False

        return test, track

    def construct_start_message (self):
        """ Collect preliminary run info at the start of the DFK.

        Returns :
              - Message dict dumped as json string, ready for UDP
        """

        uname = getpass.getuser().encode('latin1')
        hashed_username = hashlib.sha256(uname).hexdigest()[0:10]
        hname = socket.gethostname().encode('latin1')
        hashed_hostname = hashlib.sha256(hname).hexdigest()[0:10]
        message = { 'uuid' : self.uuid,
                    'uname': hashed_username,
                    'hname': hashed_hostname,
                    'test' : self.test_mode,
                    'start': time.time() }

        return json.dumps(message)

    def construct_end_message (self):
        """ Collect the final run information at the time of DFK
        cleanup.

        Returns:
             - Message dict dumped as json string, ready for UDP
        """

        app_count = self.dfk.task_count

        site_count = 0
        if self.dfk._executors_managed :
            site_count = len(self.dfk.config['sites'])

        failed_states = (States.failed, States.dep_fail)
        app_fails = len([t for t in self.dfk.tasks if
                         self.dfk.tasks[t]['status'] in failed_states])

        message = { 'uuid'   : self.uuid,
                    'end'    : time.time(),
                    't_apps' : app_count,
                    'sites'  : site_count,
                    'c_time' : None,
                    'test'   : self.test_mode,
        }

        return json.dumps(message)

    def send_UDP_message(self, message):
        """ Send UDP message
        """
        if self.tracking_enabled :
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
                x = sock.sendto(bytes(message, "utf-8"), (self.UDP_IP, self.UDP_PORT))
                sock.close()
            except OSError as e:
                logger.debug("Unable to reach the network to send usage data")
                x = 0
        else:
            x = -1

        return x

    def send_message(self):
        """ Send message over UDP.
        If tracking is disables, the bytes_sent will always be set to -1

        Returns:
            (bytes_sent, time_taken)
        """
        start = time.time()
        message = None
        if not self.initialized :
            message = self.construct_start_message()
            self.initialized = True
        else:
            message = self.construct_end_message()

        x = self.send_UDP_message(message)
        end = time.time()

        return x, end-start

if __name__ == '__main__' :

    from parsl import *

    workers = ThreadPoolExecutor(max_workers=4)
    dfk = DataFlowKernel(executors=[workers])

    #ut = UsageTracker(dfk, ip='52.3.111.203')
    ut = UsageTracker(dfk, domain_name='tracking.parsl-project.org')

    for i in range(0,2):
        x = ut.send_message()
        print(x)
<|endoftext|>


<commit_before># pylint: disable=missing-docstring
from conans import ConanFile, CMake

class LibDABCommonConan(ConanFile):
    name = 'libdabcommon'
    description = """The common subsystem for the ODR DAB data toolkit"""
    license = 'BSD 3-clause'
    version = '1.0.1'
    url = 'https://github.com/Opendigitalradio/libdabcommon.git'
    settings = None
    options = {"test": [True, False]}
    default_options = "test=False"
    exports_sources = (
        'include/*.h',
    )

    def build(self):
        if self.options.test:
            cmake = CMake(self)
            self.run('cmake libdabcommon %s' % cmake.command_line)
            self.run('cmake --build . %s' % cmake.build_config)

    def package(self):
        self.copy('*.h', dst='include', src='include')

    def package_info(self):
        self.cpp_info.libs = ['pthread']

    def requirements(self):
        if self.options.test:
            self.requires('CUTEX/[>=1.0]@fmorgner/stable')
<commit_msg>conan: use CMake for packaging<commit_after># pylint: disable=missing-docstring
from conans import ConanFile

class LibDABCommonConan(ConanFile):
    name = 'libdabcommon'
    description = """The common subsystem for the ODR DAB data toolkit"""
    license = 'BSD 3-clause'
    version = '1.0.1'
    url = 'https://github.com/Opendigitalradio/libdabcommon.git'
    settings = None
    options = {"test": [True, False]}
    default_options = "test=True"
    exports_sources = ('*', '!.git/*', '!build/*')

    def build(self):
        test = self.options.test

        args = ['-DDABCOMMON_ENABLE_TESTS=%s' % 'On' if test else 'Off']
        self.run('cmake %s %s %s' % (
            self.conanfile_directory,
            '-DCMAKE_INSTALL_PREFIX="%s"' % self.package_folder,
            ' '.join(args)
        ))
        self.run('cmake --build . --target install')

    def package_info(self):
        self.cpp_info.libs = ['pthread']

    def requirements(self):
        if self.options.test:
            self.requires('CUTEX/[>=1.0]@fmorgner/stable')
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Conan recipe package for Google FlatBuffers
"""
import os
from conans import ConanFile, CMake, tools

class FlatbuffersConan(ConanFile):
    name = "flatbuffers"
    version = "1.9.0"
    license = "https://github.com/google/flatbuffers/blob/master/LICENSE.txt"
    url = "https://github.com/google/flatbuffers"
    description = "Memory Efficient Serialization Library"
    settings = "os", "compiler", "build_type", "arch", "os_build", "arch_build"
    options = {"shared": [True, False]}
    default_options = "shared=False"
    generators = "cmake"
    exports = "LICENSE.txt"
    exports_sources = ["CMake/*", "include/*", "src/*", "grpc/*", "CMakeLists.txt"]

    def _inject_magic_lines(self):
        """Inject Conan setup in cmake file to solve exteral dependencies.
        """
        conan_magic_lines = '''project(FlatBuffers)
        include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
        conan_basic_setup()
        '''
        tools.replace_in_file("CMakeLists.txt", "project(FlatBuffers)", conan_magic_lines)

    def build(self):
        """Configure, build and install FlatBuffers using CMake.
        """
        self._inject_magic_lines()
        cmake = CMake(self)
        cmake.definitions["FLATBUFFERS_BUILD_TESTS"] = False
        cmake.definitions["FLATBUFFERS_BUILD_SHAREDLIB"] = self.options.shared
        cmake.configure()
        cmake.build()
        cmake.install()

    def package(self):
        """Copy Flatbuffers' artifacts to package folder
        """
        self.copy(pattern="LICENSE.txt", dst="licenses")
        self.copy(pattern="flathash*", dst="bin", src="bin")

    def package_info(self):
        """Collect built libraries names and solve flatc path.
        """
        self.cpp_info.libs = tools.collect_libs(self)
        self.env_info.PATH.append(os.path.join(self.package_folder, "bin"))
<commit_msg>Publishing flatc with conan (#4852)<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Conan recipe package for Google FlatBuffers
"""
import os
from conans import ConanFile, CMake, tools

class FlatbuffersConan(ConanFile):
    name = "flatbuffers"
    version = "1.9.0"
    license = "https://github.com/google/flatbuffers/blob/master/LICENSE.txt"
    url = "https://github.com/google/flatbuffers"
    description = "Memory Efficient Serialization Library"
    settings = "os", "compiler", "build_type", "arch", "os_build", "arch_build"
    options = {"shared": [True, False]}
    default_options = "shared=False"
    generators = "cmake"
    exports = "LICENSE.txt"
    exports_sources = ["CMake/*", "include/*", "src/*", "grpc/*", "CMakeLists.txt"]

    def _inject_magic_lines(self):
        """Inject Conan setup in cmake file to solve exteral dependencies.
        """
        conan_magic_lines = '''project(FlatBuffers)
        include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
        conan_basic_setup()
        '''
        tools.replace_in_file("CMakeLists.txt", "project(FlatBuffers)", conan_magic_lines)

    def build(self):
        """Configure, build and install FlatBuffers using CMake.
        """
        self._inject_magic_lines()
        cmake = CMake(self)
        cmake.definitions["FLATBUFFERS_BUILD_TESTS"] = False
        cmake.definitions["FLATBUFFERS_BUILD_SHAREDLIB"] = self.options.shared
        cmake.configure()
        cmake.build()
        cmake.install()

    def package(self):
        """Copy Flatbuffers' artifacts to package folder
        """
        self.copy(pattern="LICENSE.txt", dst="licenses")
        self.copy(pattern="flathash*", dst="bin", src="bin")
        self.copy(pattern="flatc*", dst="bin", src="bin")

    def package_info(self):
        """Collect built libraries names and solve flatc path.
        """
        self.cpp_info.libs = tools.collect_libs(self)
        self.env_info.PATH.append(os.path.join(self.package_folder, "bin"))
        self.user_info.flatc = os.path.join(self.package_folder, "bin", "flatc")
<|endoftext|>


<commit_before>import sys

print(sys.path)

from contextlib import contextmanager
from conans import ConanFile, CMake
from conans.tools import download, unzip
import shutil
import os

VERSION = "3.8.0"

@contextmanager
def in_dir(directory):
    last_dir = os.getcwd()
    try:
        os.makedirs(directory)
    except OSError:
        pass

    try:
        os.chdir(directory)
        yield directory
    finally:
        os.chdir(last_dir)

def extract_from_url(url):
    print("download {}".format(url))
    zip_name = os.path.basename(url)
    download(url, zip_name)
    unzip(zip_name)
    os.unlink(zip_name)

def download_extract_llvm_component(component, release, extract_to):
    extract_from_url("https://bintray.com/artifact/download/"
                     "polysquare/LLVM/{comp}-{ver}.src.zip"
                     "".format(ver=release, comp=component))
    shutil.move("{comp}-{ver}.src".format(comp=component,
                                          ver=release),
                extract_to)

class LLVMConan(ConanFile):
    name = "llvm"
    version = os.environ.get("CONAN_VERSION_OVERRIDE", VERSION)
    generators = "cmake"
    requires = tuple()
    url = "http://github.com/smspillaz/llvm-conan"
    license = "BSD"
    settings = "os", "compiler", "build_type", "arch"
    options = {"shared": [True, False]}
    default_options = "shared=False"

    def config(self):
        try:  # Try catch can be removed when conan 0.8 is released
            del self.settings.compiler.libcxx
        except:
            pass

    def source(self):
        download_extract_llvm_component("llvm", LLVMConan.version, "src")
        download_extract_llvm_component("cfe", LLVMConan.version,
                                        "src/tools/clang")
        download_extract_llvm_component("compiler-rt", LLVMConan.version,
                                        "src/projects/compiler-rt")
        download_extract_llvm_component("libcxx", LLVMConan.version,
                                        "src/projects/libcxx")
        download_extract_llvm_component("libcxxabi", LLVMConan.version,
                                        "src/projects/libcxxabi")
        download_extract_llvm_component("libunwind", "1.1",
                                        "src/projects/libunwind")
        download_extract_llvm_component("clang-tools-extra", LLVMConan.version,
                                        "src/tools/clang/tools/extra")

    def build(self):
        cmake = CMake(self.settings)
        try:
            os.makedirs("install")
        except OSError:
            pass

        with in_dir("build"):
            self.run("cmake {src} {cmd}"
                     " -DBUILD_SHARED_LIBS={shared}"
                     " -DCMAKE_INSTALL_PREFIX={installdir}"
                     " -DCMAKE_VERBOSE_MAKEFILE=1"
                     "".format(src=os.path.join(self.conanfile_directory,
                                                "src"),
                               cmd=cmake.command_line,
                               installdir=os.path.join(os.getcwd(), "install"),
                               shared=("ON" if self.options.shared
                                       else "OFF")))
            self.run("cmake --build . {cfg}".format(cfg=cmake.build_config))
            self.run("cmake --build . -- install")

    def package(self):
        self.copy(pattern="*",
                  dst="include",
                  src="build/install/include",
                  keep_path=True)
        self.copy(pattern="*.a",
                  dst="lib",
                  src="build/install/lib",
                  keep_path=True)
        self.copy(pattern="*.h",
                  dst="lib",
                  src="build/install/lib",
                  keep_path=True)
        self.copy(pattern="*.so",
                  dst="lib",
                  src="build/install/lib",
                  keep_path=True)
        self.copy(pattern="*.dylib",
                  dst="lib",
                  src="build/install/lib",
                  keep_path=True)
        self.copy(pattern="*.lib",
                  dst="lib",
                  src="build/install/lib",
                  keep_path=True)
        self.copy(pattern="*.cmake",
                  dst="lib",
                  src="build/install/lib",
                  keep_path=True)
        self.copy(pattern="*.dll",
                  dst="lib",
                  src="build/install/lib",
                  keep_path=True)
        self.copy(pattern="*",
                  dst="share",
                  src="build/install/share",
                  keep_path=True)
        self.copy(pattern="*",
                  dst="bin",
                  src="build/install/bin",
                  keep_path=True)
        self.copy(pattern="*",
                  dst="libexec",
                  src="build/install/libexec",
                  keep_path=True)
<commit_msg>conan: Remove debug message<commit_after>from contextlib import contextmanager
from conans import ConanFile, CMake
from conans.tools import download, unzip
import shutil
import os

VERSION = "3.8.0"

@contextmanager
def in_dir(directory):
    last_dir = os.getcwd()
    try:
        os.makedirs(directory)
    except OSError:
        pass

    try:
        os.chdir(directory)
        yield directory
    finally:
        os.chdir(last_dir)

def extract_from_url(url):
    print("download {}".format(url))
    zip_name = os.path.basename(url)
    download(url, zip_name)
    unzip(zip_name)
    os.unlink(zip_name)

def download_extract_llvm_component(component, release, extract_to):
    extract_from_url("https://bintray.com/artifact/download/"
                     "polysquare/LLVM/{comp}-{ver}.src.zip"
                     "".format(ver=release, comp=component))
    shutil.move("{comp}-{ver}.src".format(comp=component,
                                          ver=release),
                extract_to)

class LLVMConan(ConanFile):
    name = "llvm"
    version = os.environ.get("CONAN_VERSION_OVERRIDE", VERSION)
    generators = "cmake"
    requires = tuple()
    url = "http://github.com/smspillaz/llvm-conan"
    license = "BSD"
    settings = "os", "compiler", "build_type", "arch"
    options = {"shared": [True, False]}
    default_options = "shared=False"

    def config(self):
        try:  # Try catch can be removed when conan 0.8 is released
            del self.settings.compiler.libcxx
        except:
            pass

    def source(self):
        download_extract_llvm_component("llvm", LLVMConan.version, "src")
        download_extract_llvm_component("cfe", LLVMConan.version,
                                        "src/tools/clang")
        download_extract_llvm_component("compiler-rt", LLVMConan.version,
                                        "src/projects/compiler-rt")
        download_extract_llvm_component("libcxx", LLVMConan.version,
                                        "src/projects/libcxx")
        download_extract_llvm_component("libcxxabi", LLVMConan.version,
                                        "src/projects/libcxxabi")
        download_extract_llvm_component("libunwind", "1.1",
                                        "src/projects/libunwind")
        download_extract_llvm_component("clang-tools-extra", LLVMConan.version,
                                        "src/tools/clang/tools/extra")

    def build(self):
        cmake = CMake(self.settings)
        try:
            os.makedirs("install")
        except OSError:
            pass

        with in_dir("build"):
            self.run("cmake {src} {cmd}"
                     " -DBUILD_SHARED_LIBS={shared}"
                     " -DCMAKE_INSTALL_PREFIX={installdir}"
                     " -DCMAKE_VERBOSE_MAKEFILE=1"
                     "".format(src=os.path.join(self.conanfile_directory,
                                                "src"),
                               cmd=cmake.command_line,
                               installdir=os.path.join(os.getcwd(), "install"),
                               shared=("ON" if self.options.shared
                                       else "OFF")))
            self.run("cmake --build . {cfg}".format(cfg=cmake.build_config))
            self.run("cmake --build . -- install")

    def package(self):
        self.copy(pattern="*",
                  dst="include",
                  src="build/install/include",
                  keep_path=True)
        self.copy(pattern="*.a",
                  dst="lib",
                  src="build/install/lib",
                  keep_path=True)
        self.copy(pattern="*.h",
                  dst="lib",
                  src="build/install/lib",
                  keep_path=True)
        self.copy(pattern="*.so",
                  dst="lib",
                  src="build/install/lib",
                  keep_path=True)
        self.copy(pattern="*.dylib",
                  dst="lib",
                  src="build/install/lib",
                  keep_path=True)
        self.copy(pattern="*.lib",
                  dst="lib",
                  src="build/install/lib",
                  keep_path=True)
        self.copy(pattern="*.cmake",
                  dst="lib",
                  src="build/install/lib",
                  keep_path=True)
        self.copy(pattern="*.dll",
                  dst="lib",
                  src="build/install/lib",
                  keep_path=True)
        self.copy(pattern="*",
                  dst="share",
                  src="build/install/share",
                  keep_path=True)
        self.copy(pattern="*",
                  dst="bin",
                  src="build/install/bin",
                  keep_path=True)
        self.copy(pattern="*",
                  dst="libexec",
                  src="build/install/libexec",
                  keep_path=True)
<|endoftext|>


<commit_before>from bs4 import BeautifulSoup
import re
import json

from django.core.management.base import BaseCommand

from programs.models import Program, ProgramModules, LearningPlan
from disciplines.models import Discipline, Semester, TrainingTerms
from modules.models import Module

class Command(BaseCommand):
    help = "Create Django objects from raw&ugly UrFU data."
    requires_system_checks = True
    requires_migrations_checks = True

    def add_arguments(self, parser):
        parser.add_argument('html_path', nargs=1)
        parser.add_argument('uni_modules_path', nargs=1)
        parser.add_argument('programs_path', nargs=1)
        parser.add_argument('program_title', nargs=1)

    def handle(self, *args, **options):
        html_path = options["html_path"][0]
        uni_modules_path = options["uni_modules_path"][0]
        program_title = options["program_title"][0]
        programs_path = options["programs_path"][0]

        try:
            with open(html_path, encoding='utf-8') as html_file:
                raw_html = '\n'.join(html_file.readlines())
        except:
            raise FileNotFoundError

        try:
            with open(uni_modules_path, encoding='utf-8') as modules_file:
                modules_json = json.load(modules_file)
        except:
            raise FileNotFoundError

        try:
            with open(programs_path, encoding='utf-8') as programs_file:
                raw_programs = '\n'.join(programs_file.readlines())
        except:
            raise FileNotFoundError

        if raw_programs:
            programs_soup = BeautifulSoup(raw_programs, 'html.parser')
            rows = []
            for row in programs_soup.find_all('tr', {"class": "main-info"}):
                rows.append([val.text.strip() for val in row.find_all('td')])

            for row in rows:
                try:
                    program = Program.objects.get(title=row[1])
                except:
                    def level(x):
                        return {
                            'Магистр'.lower() in str(x).lower(): "m",
                            'Специалист'.lower() in str(x).lower(): "s",
                            'Бакалавр'.lower() in str(x).lower(): "b",
                        }[True]
                    program = Program(title=row[1],
                                      training_direction=row[2],
                                      level=level(row[4]),
                                      )
                    program.save()

        try:
            program = Program.objects.filter(title=program_title).first()
            program.status = "p"
            program.save()
        except:
            raise NotImplementedError

        if raw_html:
            soup = BeautifulSoup(raw_html, 'html.parser')
            [s.extract() for s in soup('script')]
            [s.extract() for s in soup('style')]
            self.decompose(soup, "table", "menu_table")
            self.decompose(soup, "td", "navpath")
            self.decompose(soup, "div", "buttons")
            soup.find('td', id="nav_td").decompose()

            try:
                stage = soup.find('td', id="EduVersionPlanTab.EduVersionPlan.stage").text.strip().lower() == "утверждено"
            except:
                stage = False
            try:
                displayableTitle = soup.find('td', id="EduVersionPlanTab.EduVersionPlan.displayableTitle").text.strip()
            except:
                displayableTitle = ""
            try:
                number = soup.find('td', id="EduVersionPlanTab.EduVersionPlan.number").text.strip()
            except:
                number = ""
            try:
                active = soup.find('td', id="EduVersionPlanTab.EduVersionPlan.active").text.strip()
            except:
                active = "нет"
            try:
                title = soup.find('td', id="EduVersionPlanTab.EduVersionPlan.title").text.strip()
            except:
                title = ""
            try:
                loadTimeType = soup.find("td", id="EduVersionPlanTab.EduVersionPlan.loadTimeType").text.strip()
            except:
                loadTimeType = "часов в неделю"

            html = soup.find("table", {"class": "basic"}).prettify()

            lps = LearningPlan.objects.filter(uni_number=number, status="p")
            if len(lps) > 0:
                for lp in lps:
                    lp.uni_displayableTitle = displayableTitle
                    lp.uni_number = number
                    lp.uni_active = active
                    lp.uni_title = title
                    lp.uni_stage = stage
                    lp.uni_loadTimeType = loadTimeType
                    lp.uni_html = html
                    lp.save()
                    if lp not in program.learning_plans.all():
                        program.learning_plans.add(lp)
                        program.save()
            else:
                lp = LearningPlan(uni_displayableTitle=displayableTitle,
                                  uni_number=number,
                                  uni_active=active,
                                  uni_title=title,
                                  uni_stage=stage,
                                  uni_loadTimeType=loadTimeType,
                                  uni_html=html,
                                  status="p"
                                  )
                lp.save()
                program.learning_plans.add(lp)
                program.save()

            table = soup.find('table', id="EduVersionPlanTab.EduDisciplineList")
            headers = [header.text.strip() for header in table.find_all('th')]

            def find_row_index(row_text):
                headers = table.find_all('th')
                return headers.index(table.find('th', text=row_text))

            def find_row_index_id(id):
                headers = table.find_all('th')
                return headers.index(table.find('th', id=id))

            rows = []
            for row in table.find_all('tr'):
                rows.append([val.text.strip() for val in row.find_all('td')])

            # Ищем модули
            modules = []
            for header in headers:
                if "Номер модуля, дисциплины".lower() == header.lower():
                    module_numbers_col = headers.index(header)

            for row in rows:
                if row:
                    m = re.search('\d\d+', row[module_numbers_col])
                    if m:
                        for module in modules_json:
                            if str(module["number"]) == str(m.group(0)):
                                module["row"] = row
                                modules.append(module)

            fulltime = False
            if 'зао' not in number:
                fulltime = True
            print("fulltime: ", fulltime)
            if fulltime:
                term = TrainingTerms.objects.filter(title="4 года").first()
                for module in [m for m in modules if m["disciplines"]]:
                    module_obj, semester = self.create_module(find_row_index_id, module, program)
                    semester = self.create_disciplines(find_row_index_id, module, module_obj, row, rows, semester, program, term)

            else:
                years = 0
                for module in [m for m in modules]:
                    try:
                        for i in range(1, 10):
                            try:
                                ze = module["row"][
                                    find_row_index_id(
                                        f"EduVersionPlanTab.EduDisciplineList.__term{i}.__term{i}headerCell")]
                                try:
                                    if int(ze) > 0:
                                        latest_semester = i
                                except:
                                    latest_semester = i - 1
                            except:
                                pass
                        if latest_semester / float(2) > years:
                            years = latest_semester / float(2)
                    except:
                        pass

                if years == 5:
                    term = TrainingTerms.objects.filter(title="5 лет").first()
                else:
                    term = TrainingTerms.objects.filter(title="3,5 года").first()
                for module in [m for m in modules if m["disciplines"]]:
                    module_obj, semester = self.create_module_not_save(find_row_index_id, module, program)
                    semester = self.create_disciplines(find_row_index_id, module, module_obj, row, rows, semester, program, term)

    def create_semester(self, program, discipline, module, find_row_index_id, term):
        """
        1. ИД дисциплины
        2. Дисциплина.Программа
        3. Год текущий?
        4. Семестр: 0?
        5. Срок обучения (парсим)
        6. Семестр изучения (парсим как семестр модуля)
        :param program:
        :param discipline:
        :return:
        """
        for i in range(10, 0, -1):
            try:
                ze = module["row"][find_row_index_id(f"EduVersionPlanTab.EduDisciplineList.__term{i}.__term{i}headerCell")]
                try:
                    if int(ze) > 0:
                        training_semester = i
                except:
                    pass
            except:
                pass

        try:
            semester_obj = Semester.filter(discipline=discipline, training_semester=training_semester).first()
        except:
            semester_obj = Semester(discipline=discipline,
                                    training_semester=training_semester,
                                    program=program,
                                    year='2017',
                                    admission_semester="0",
                                    term=term,
                                    )
            semester_obj.save()

    def create_disciplines(self, find_row_index_id, module, module_obj, row, rows, semester, program, term):
        for d in module["disciplines"]:
            if int(d["testUnits"]) > 0:
                for row in rows:
                    if d["title"] in row:
                        break
                try:
                    discipline = Discipline.objects.get(title=d["title"])
                except:
                    discipline = Discipline(title=d["title"])

                for i in range(10, 0, -1):
                    try:
                        ze = row[
                            find_row_index_id(f"EduVersionPlanTab.EduDisciplineList.__term{i}.__term{i}headerCell")]
                        try:
                            if int(ze) > 0:
                                semester = i
                        except:
                            pass
                    except:
                        pass

                discipline.module = module_obj
                discipline.labor = d["testUnits"]
                discipline.uni_uid = d["uid"]
                discipline.uni_discipline = d["discipline"]
                discipline.uni_number = d["number"]
                discipline.uni_section = d["section"]
                discipline.uni_file = d["file"]
                print(module_obj)
                discipline.period = semester - module_obj.semester + 1
                try:
                    try:
                        if int(max(row[5].split("-"))):
                            discipline.form = "z"
                    except:
                        pass
                    try:
                        if int(max(row[4].split("-"))):
                            discipline.form = "e"
                    except:
                        pass
                except:
                    pass

                discipline.status = "p"
                discipline.save()
                self.create_semester(program, discipline, module, find_row_index_id, term)
        return semester

    def create_module(self, find_row_index_id, module, program):
        for i in range(10, 0, -1):
            try:
                ze = module["row"][find_row_index_id(f"EduVersionPlanTab.EduDisciplineList.__term{i}.__term{i}headerCell")]
                try:
                    if int(ze) > 0:
                        semester = i
                except:
                    pass
            except:
                pass
        try:
            module_obj = Module.objects.filter(title=module["title"]).first()
            module_obj.uni_uuid = module["uuid"]
            module_obj.uni_number = module["number"]
            module_obj.uni_coordinator = module["coordinator"]
            module_obj.uni_type = module["type"]
            module_obj.uni_title = module["title"]
            module_obj.uni_competence = module["competence"]
            module_obj.uni_testUnits = module["testUnits"]
            module_obj.uni_priority = module["priority"]
            module_obj.uni_state = module["state"]
            module_obj.uni_approvedDate = module["approvedDate"]
            module_obj.uni_comment = module["comment"]
            module_obj.uni_file = module["file"]
            module_obj.uni_specialities = module["specialities"]
            module_obj.program = program
            module_obj.semester = semester
            module_obj.save()
        except:
            module_obj = Module(title=module["title"],
                                uni_uuid=module["uuid"],
                                uni_number=module["number"],
                                uni_coordinator=module["coordinator"],
                                uni_type=module["type"],
                                uni_title=module["title"],
                                uni_competence=module["competence"],
                                uni_testUnits=module["testUnits"],
                                uni_priority=module["priority"],
                                uni_state=module["state"],
                                uni_approvedDate=module["approvedDate"],
                                uni_comment=module["comment"],
                                uni_file=module["file"],
                                uni_specialities=module["specialities"],
                                program=program,
                                semester=semester,
                                )
            module_obj.save()  # Создали модуль

        return module_obj, semester

    def create_disciplines_not_save(self, find_row_index_id, module, module_obj, row, rows, semester, program, term):
        for d in module["disciplines"]:
            discipline = None
            if int(d["testUnits"]) > 0:
                for row in rows:
                    if d["title"] in row:
                        break
                try:
                    discipline = Discipline.objects.get(title=d["title"])
                except:
                    print("Unknown discipline: ", d["title"])

                for i in range(10, 0, -1):
                    try:
                        ze = row[
                            find_row_index_id(f"EduVersionPlanTab.EduDisciplineList.__term{i}.__term{i}headerCell")]
                        try:
                            if int(ze) > 0:
                                semester = i
                        except:
                            pass
                    except:
                        pass

                if discipline:
                    self.create_semester(program, discipline, module, find_row_index_id, term)
        return semester

    def create_module_not_save(self, find_row_index_id, module, program):
        for i in range(10, 0, -1):
            try:
                ze = module["row"][find_row_index_id(f"EduVersionPlanTab.EduDisciplineList.__term{i}.__term{i}headerCell")]
                try:
                    if int(ze) > 0:
                        semester = i
                except:
                    pass
            except:
                pass
        try:
            module_obj = Module.objects.filter(title=module["title"]).first()

        except:
            print("Unknown module: ", module["title"])

        return module_obj, semester

    def decompose(self, soup, tag, classname):
        [el.decompose() for el in soup.find_all(tag, {'class': classname})]

<commit_msg>create_disciplines#5<commit_after>from bs4 import BeautifulSoup
import re
import json

from django.core.management.base import BaseCommand

from programs.models import Program, ProgramModules, LearningPlan
from disciplines.models import Discipline, Semester, TrainingTerms
from modules.models import Module

class Command(BaseCommand):
    help = "Create Django objects from raw&ugly UrFU data."
    requires_system_checks = True
    requires_migrations_checks = True

    def add_arguments(self, parser):
        parser.add_argument('html_path', nargs=1)
        parser.add_argument('uni_modules_path', nargs=1)
        parser.add_argument('programs_path', nargs=1)
        parser.add_argument('program_title', nargs=1)

    def handle(self, *args, **options):
        html_path = options["html_path"][0]
        uni_modules_path = options["uni_modules_path"][0]
        program_title = options["program_title"][0]
        programs_path = options["programs_path"][0]

        try:
            with open(html_path, encoding='utf-8') as html_file:
                raw_html = '\n'.join(html_file.readlines())
        except:
            raise FileNotFoundError

        try:
            with open(uni_modules_path, encoding='utf-8') as modules_file:
                modules_json = json.load(modules_file)
        except:
            raise FileNotFoundError

        try:
            with open(programs_path, encoding='utf-8') as programs_file:
                raw_programs = '\n'.join(programs_file.readlines())
        except:
            raise FileNotFoundError

        if raw_programs:
            programs_soup = BeautifulSoup(raw_programs, 'html.parser')
            rows = []
            for row in programs_soup.find_all('tr', {"class": "main-info"}):
                rows.append([val.text.strip() for val in row.find_all('td')])

            for row in rows:
                try:
                    program = Program.objects.get(title=row[1])
                except:
                    def level(x):
                        return {
                            'Магистр'.lower() in str(x).lower(): "m",
                            'Специалист'.lower() in str(x).lower(): "s",
                            'Бакалавр'.lower() in str(x).lower(): "b",
                        }[True]
                    program = Program(title=row[1],
                                      training_direction=row[2],
                                      level=level(row[4]),
                                      )
                    program.save()

        try:
            program = Program.objects.filter(title=program_title).first()
            program.status = "p"
            program.save()
        except:
            raise NotImplementedError

        if raw_html:
            soup = BeautifulSoup(raw_html, 'html.parser')
            [s.extract() for s in soup('script')]
            [s.extract() for s in soup('style')]
            self.decompose(soup, "table", "menu_table")
            self.decompose(soup, "td", "navpath")
            self.decompose(soup, "div", "buttons")
            soup.find('td', id="nav_td").decompose()

            try:
                stage = soup.find('td', id="EduVersionPlanTab.EduVersionPlan.stage").text.strip().lower() == "утверждено"
            except:
                stage = False
            try:
                displayableTitle = soup.find('td', id="EduVersionPlanTab.EduVersionPlan.displayableTitle").text.strip()
            except:
                displayableTitle = ""
            try:
                number = soup.find('td', id="EduVersionPlanTab.EduVersionPlan.number").text.strip()
            except:
                number = ""
            try:
                active = soup.find('td', id="EduVersionPlanTab.EduVersionPlan.active").text.strip()
            except:
                active = "нет"
            try:
                title = soup.find('td', id="EduVersionPlanTab.EduVersionPlan.title").text.strip()
            except:
                title = ""
            try:
                loadTimeType = soup.find("td", id="EduVersionPlanTab.EduVersionPlan.loadTimeType").text.strip()
            except:
                loadTimeType = "часов в неделю"

            html = soup.find("table", {"class": "basic"}).prettify()

            lps = LearningPlan.objects.filter(uni_number=number, status="p")
            if len(lps) > 0:
                for lp in lps:
                    lp.uni_displayableTitle = displayableTitle
                    lp.uni_number = number
                    lp.uni_active = active
                    lp.uni_title = title
                    lp.uni_stage = stage
                    lp.uni_loadTimeType = loadTimeType
                    lp.uni_html = html
                    lp.save()
                    if lp not in program.learning_plans.all():
                        program.learning_plans.add(lp)
                        program.save()
            else:
                lp = LearningPlan(uni_displayableTitle=displayableTitle,
                                  uni_number=number,
                                  uni_active=active,
                                  uni_title=title,
                                  uni_stage=stage,
                                  uni_loadTimeType=loadTimeType,
                                  uni_html=html,
                                  status="p"
                                  )
                lp.save()
                program.learning_plans.add(lp)
                program.save()

            table = soup.find('table', id="EduVersionPlanTab.EduDisciplineList")
            headers = [header.text.strip() for header in table.find_all('th')]

            def find_row_index(row_text):
                headers = table.find_all('th')
                return headers.index(table.find('th', text=row_text))

            def find_row_index_id(id):
                headers = table.find_all('th')
                return headers.index(table.find('th', id=id))

            rows = []
            for row in table.find_all('tr'):
                rows.append([val.text.strip() for val in row.find_all('td')])

            # Ищем модули
            modules = []
            for header in headers:
                if "Номер модуля, дисциплины".lower() == header.lower():
                    module_numbers_col = headers.index(header)

            for row in rows:
                if row:
                    m = re.search('\d\d+', row[module_numbers_col])
                    if m:
                        for module in modules_json:
                            if str(module["number"]) == str(m.group(0)):
                                module["row"] = row
                                modules.append(module)

            fulltime = False
            if 'зао' not in number:
                fulltime = True
            print("fulltime: ", fulltime)
            if fulltime:
                term = TrainingTerms.objects.filter(title="4 года").first()
                for module in [m for m in modules if m["disciplines"]]:
                    module_obj, semester = self.create_module(find_row_index_id, module, program)
                    semester = self.create_disciplines(find_row_index_id, module, module_obj, row, rows, semester, program, term)

            else:
                years = 0
                for module in [m for m in modules]:
                    try:
                        for i in range(1, 10):
                            try:
                                ze = module["row"][
                                    find_row_index_id(
                                        f"EduVersionPlanTab.EduDisciplineList.__term{i}.__term{i}headerCell")]
                                try:
                                    if int(ze) > 0:
                                        latest_semester = i
                                except:
                                    latest_semester = i - 1
                            except:
                                pass
                        if latest_semester / float(2) > years:
                            years = latest_semester / float(2)
                    except:
                        pass

                if years == 5:
                    term = TrainingTerms.objects.filter(title="5 лет").first()
                else:
                    term = TrainingTerms.objects.filter(title="3,5 года").first()
                for module in [m for m in modules if m["disciplines"]]:
                    module_obj, semester = self.create_module_not_save(find_row_index_id, module, program)
                    semester = self.create_disciplines(find_row_index_id, module, module_obj, row, rows, semester, program, term)

    def create_semester(self, program, discipline, module, find_row_index_id, term):
        """
        1. ИД дисциплины
        2. Дисциплина.Программа
        3. Год текущий?
        4. Семестр: 0?
        5. Срок обучения (парсим)
        6. Семестр изучения (парсим как семестр модуля)
        :param program:
        :param discipline:
        :return:
        """
        for i in range(10, 0, -1):
            try:
                ze = module["row"][find_row_index_id(f"EduVersionPlanTab.EduDisciplineList.__term{i}.__term{i}headerCell")]
                try:
                    if int(ze) > 0:
                        training_semester = i
                except:
                    pass
            except:
                pass

        try:
            semester_obj = Semester.filter(discipline=discipline, training_semester=training_semester).first()
        except:
            semester_obj = Semester(discipline=discipline,
                                    training_semester=training_semester,
                                    program=program,
                                    year='2017',
                                    admission_semester="0",
                                    term=term,
                                    )
            semester_obj.save()

    def create_disciplines(self, find_row_index_id, module, module_obj, row, rows, semester, program, term):
        for d in module["disciplines"]:
            if int(d["testUnits"]) > 0:
                for row in rows:
                    if d["title"] in row:
                        break
                try:
                    discipline = Discipline.objects.get(title=d["title"])
                except:
                    discipline = Discipline(title=d["title"])

                for i in range(10, 0, -1):
                    try:
                        ze = row[
                            find_row_index_id(f"EduVersionPlanTab.EduDisciplineList.__term{i}.__term{i}headerCell")]
                        try:
                            if int(ze) > 0:
                                semester = i
                        except:
                            pass
                    except:
                        pass

                discipline.module = module_obj
                discipline.labor = d["testUnits"]
                discipline.uni_uid = d["uid"]
                discipline.uni_discipline = d["discipline"]
                discipline.uni_number = d["number"]
                discipline.uni_section = d["section"]
                discipline.uni_file = d["file"]
                if module_obj is not None:
                    discipline.period = semester - module_obj.semester + 1
                try:
                    try:
                        if int(max(row[5].split("-"))):
                            discipline.form = "z"
                    except:
                        pass
                    try:
                        if int(max(row[4].split("-"))):
                            discipline.form = "e"
                    except:
                        pass
                except:
                    pass

                discipline.status = "p"
                discipline.save()
                self.create_semester(program, discipline, module, find_row_index_id, term)
        return semester

    def create_module(self, find_row_index_id, module, program):
        for i in range(10, 0, -1):
            try:
                ze = module["row"][find_row_index_id(f"EduVersionPlanTab.EduDisciplineList.__term{i}.__term{i}headerCell")]
                try:
                    if int(ze) > 0:
                        semester = i
                except:
                    pass
            except:
                pass
        try:
            module_obj = Module.objects.filter(title=module["title"]).first()
            module_obj.uni_uuid = module["uuid"]
            module_obj.uni_number = module["number"]
            module_obj.uni_coordinator = module["coordinator"]
            module_obj.uni_type = module["type"]
            module_obj.uni_title = module["title"]
            module_obj.uni_competence = module["competence"]
            module_obj.uni_testUnits = module["testUnits"]
            module_obj.uni_priority = module["priority"]
            module_obj.uni_state = module["state"]
            module_obj.uni_approvedDate = module["approvedDate"]
            module_obj.uni_comment = module["comment"]
            module_obj.uni_file = module["file"]
            module_obj.uni_specialities = module["specialities"]
            module_obj.program = program
            module_obj.semester = semester
            module_obj.save()
        except:
            module_obj = Module(title=module["title"],
                                uni_uuid=module["uuid"],
                                uni_number=module["number"],
                                uni_coordinator=module["coordinator"],
                                uni_type=module["type"],
                                uni_title=module["title"],
                                uni_competence=module["competence"],
                                uni_testUnits=module["testUnits"],
                                uni_priority=module["priority"],
                                uni_state=module["state"],
                                uni_approvedDate=module["approvedDate"],
                                uni_comment=module["comment"],
                                uni_file=module["file"],
                                uni_specialities=module["specialities"],
                                program=program,
                                semester=semester,
                                )
            module_obj.save()  # Создали модуль

        return module_obj, semester

    def create_disciplines_not_save(self, find_row_index_id, module, module_obj, row, rows, semester, program, term):
        for d in module["disciplines"]:
            discipline = None
            if int(d["testUnits"]) > 0:
                for row in rows:
                    if d["title"] in row:
                        break
                try:
                    discipline = Discipline.objects.get(title=d["title"])
                except:
                    print("Unknown discipline: ", d["title"])

                for i in range(10, 0, -1):
                    try:
                        ze = row[
                            find_row_index_id(f"EduVersionPlanTab.EduDisciplineList.__term{i}.__term{i}headerCell")]
                        try:
                            if int(ze) > 0:
                                semester = i
                        except:
                            pass
                    except:
                        pass

                if discipline:
                    self.create_semester(program, discipline, module, find_row_index_id, term)
        return semester

    def create_module_not_save(self, find_row_index_id, module, program):
        for i in range(10, 0, -1):
            try:
                ze = module["row"][find_row_index_id(f"EduVersionPlanTab.EduDisciplineList.__term{i}.__term{i}headerCell")]
                try:
                    if int(ze) > 0:
                        semester = i
                except:
                    pass
            except:
                pass
        try:
            module_obj = Module.objects.filter(title=module["title"]).first()

        except:
            print("Unknown module: ", module["title"])

        return module_obj, semester

    def decompose(self, soup, tag, classname):
        [el.decompose() for el in soup.find_all(tag, {'class': classname})]

<|endoftext|>


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

from flexbe_core.proxy import ProxyPublisher
from flexbe_core.proxy import ProxySubscriberCached
from flexbe_core.proxy import ProxyServiceCaller
from flexbe_core.proxy import ProxyActionClient

import rospy
from wm_tts.msg import say
from wm_tts.srv import say_service
from std_msgs.msg import UInt8

class SaraSay(EventState):
    """
    Make sara say something

    -- Format      string   how to say it
    -- emotion     int       how to feel
    >= sentence              what key to say

    <= done                what's said is said
    """

    def __init__(self, sentence, emotion, block=True):
        """Constructor"""

        super(SaraSay, self).__init__(outcomes = ['done'])

        # Get parameters
        self.msg = say()
        self.msg.sentence = sentence
        self.msg.emotion = emotion
        self.block = block
        self.lastEmotion = None

        # Set topics
        self.emotion_topic = "sara_face/Emotion"
        self.say_topic = "/say"
        self.say_service = "/wm_say"
        self.emotion_pub = ProxyPublisher({self.emotion_topic: UInt8})

        # Prepare wm_tts
        if self.block:
            Logger.loginfo('Waiting for wm_tts')
            rospy.wait_for_service(self.say_service)
            self.serv = ProxyServiceCaller({self.say_service: say_service})
        else:
            self.pub = ProxyPublisher({self.say_topic: say})

    def execute(self, userdata):
        """Wait for action result and return outcome accordingly"""
        if(self.msg.emotion>0 and self.msg.emotion != self.lastEmotion):
            self.emotion_pub.publish(self.emotion_topic, self.msg.emotion)
            self.lastEmotion = self.msg.emotion

        Logger.loginfo('Say: '+str(self.msg))
        if self.block:
            # before:
            # self.serv(self.msg)

            # after:
            try:
                self._response = self.serv.call(self.say_service, self.msg)
                Logger.loginfo("Execute Known Trajectory Service requested: \n" + str(self.say_service))
            except rospy.ServiceException as exc:
                Logger.logwarn("Execute Known Trajectory Service did not process request: \n" + str(exc))

        else:
            self.pub.publish(self.say_topic, self.msg)

        return 'done'
<commit_msg>Passage sara_say vers proxy pub et service, test fait et fonctionnel<commit_after>#!/usr/bin/env python

from flexbe_core.proxy import ProxyPublisher
from flexbe_core.proxy import ProxySubscriberCached
from flexbe_core.proxy import ProxyServiceCaller
from flexbe_core.proxy import ProxyActionClient

import rospy

from flexbe_core import EventState, Logger

from wm_tts.msg import say
from wm_tts.srv import say_service, say_serviceRequest
from std_msgs.msg import UInt8

class SaraSay(EventState):
    """
    Make sara say something

    -- Format      string   how to say it
    -- emotion     int       how to feel
    >= sentence              what key to say

    <= done                what's said is said
    """

    def __init__(self, sentence, emotion, block=True):
        """Constructor"""

        super(SaraSay, self).__init__(outcomes = ['done'])

        # Get parameters
        self.msg = say()
        self.msg.sentence = sentence
        self.msg.emotion = emotion
        self.block = block
        self.lastEmotion = None

        # Set topics
        self.emotion_topic = "sara_face/Emotion"
        self.say_topic = "/say"
        self.say_service = "/wm_say"
        self.emotion_pub = ProxyPublisher({self.emotion_topic: UInt8})

        # Prepare wm_tts
        if self.block:
            Logger.loginfo('Waiting for wm_tts')
            rospy.wait_for_service(self.say_service)
            self.serv = ProxyServiceCaller({self.say_service: say_service})
        else:
            self.pub = ProxyPublisher({self.say_topic: say})

    def execute(self, userdata):
        """Wait for action result and return outcome accordingly"""
        if(self.msg.emotion>0 and self.msg.emotion != self.lastEmotion):
            self.emotion_pub.publish(self.emotion_topic, self.msg.emotion)
            self.lastEmotion = self.msg.emotion

        Logger.loginfo('Say: '+str(self.msg))
        if self.block: # call service
            try:
                message_say = say_serviceRequest()
                message_say.say.sentence = self.msg.sentence
                message_say.say.emotion = self.msg.emotion
                self._response = self.serv.call(self.say_service, message_say)
            except rospy.ServiceException as exc:
                Logger.logwarn("Execute did not process request: \n" + str(exc))

        else: #publisher
            self.pub.publish(self.say_topic, self.msg)

        return 'done'
<|endoftext|>