<commit_before>#! /usr/bin/python
import pyexiv2
import sys

def _main(argv):
  image = pyexiv2.ImageMetadata(argv[1])
  image.read()
  del image['Exif.Photo.ISOSpeedRatings']
  image.write()
  print reduce(lambda coll, next: "%s\n%s=%s" % (coll, next[0], next[1].value), image.items())

if __name__ == '__main__':
  _main(sys.argv)
<commit_msg>Script now walks a directory tree, creating sanitized copies of all galaxy nexus photos<commit_after>#! /usr/bin/python
""" Script that creates 'sanitized' copies of Galaxy Nexus jpeg's.

The Galaxy Nexus phone's default camera app puts an array of values
into the ISO EXIF Tag, and some applications can't handle that. This
script creates copies in the same directory with the name
    <basename>_isoremoved<extension>

Requires the gflags and pyexiv2 third-party python libraries
"""

import gflags
import logging
import os.path
import pyexiv2
import shutil
import sys

gflags.DEFINE_string('search_dir', None, 'Directory of media library')
gflags.MarkFlagAsRequired('search_dir')
FLAGS = gflags.FLAGS

def _create_parsable_gnexus_copies(search_dir):
  """ Walk a directory tree, finding photos that have arrays for ISO EXIF
  data, and make ISO-free copies.

  Useful for the PS3 Media Server, which currently cannot parse (and
  therefore serve) files with array ISO EXIF data. """
  paths = os.walk(search_dir)
  for (dirpath, _, filenames) in paths:
    for filename in filenames:
      filepath = os.path.join(dirpath, filename)
      prefix, suffix = os.path.splitext(filepath)
      is_array = _is_array_iso(filepath)
      if is_array:
        sanitized_filepath = os.path.join(dirpath, '%s_isoremoved%s'
                                          % (prefix, suffix))
        if not os.path.exists(sanitized_filepath):
          logging.info('Sanitizing %s to %s.', filepath, sanitized_filepath)
          shutil.copy2(filepath, sanitized_filepath)
          image = pyexiv2.ImageMetadata(sanitized_filepath)
          image.read()
          del image['Exif.Photo.ISOSpeedRatings']
          image.write()

def _is_array_iso(filepath):
  """Returns a True if the photo contains an array of multiple ISO values.
  """
  try:
    image = pyexiv2.ImageMetadata(filepath)
    image.read()
    logging.debug('Photo has an ISO SPeed Ratings Tag of %s',
                 image['Exif.Photo.ISOSpeedRatings'].value)
    return len(image['Exif.Photo.ISOSpeedRatings'].value) != 1
  except Exception:
    return False

def _configure_logging():
  """Configures logging to stderr, file."""
  root = logging.getLogger('')
  handler = logging.StreamHandler(sys.stderr)
  formatter = logging.Formatter('%(asctime)s %(filename)s' +
                                ':%(lineno)d %(levelname)s %(message)s')
  handler.setFormatter(formatter)
  root.addHandler(handler)
  file_handler = logging.FileHandler('/var/tmp/fix_gnexus_exif.log')
  file_handler.setFormatter(formatter)
  root.addHandler(file_handler)
  root.setLevel(logging.INFO)

def _main(argv):
  """Main script entry point """
  try:
    argv = FLAGS(argv)  # parse flags
  except gflags.FlagsError, error:
    print '%s\nUsage: %s ARGS\n%s' % (error, sys.argv[0], FLAGS)
    sys.exit(1)
  try:
    _configure_logging()
    _create_parsable_gnexus_copies(FLAGS.search_dir)
  except Exception:
    logging.exception('An unexpected error occurred while fixing'
                      + ' Galaxy Nexus photos')
    raise

if __name__ == '__main__':
  _main(sys.argv)
<|endoftext|>


<commit_before>"""
mbed SDK
Copyright (c) 2011-2015 ARM Limited

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.

Author: Przemyslaw Wirkus <Przemyslaw.wirkus@arm.com>
"""

import re
import sys
from time import time, sleep
from Queue import Queue, Empty
from threading import Thread
from subprocess import call, Popen, PIPE

from mbed_greentea.mbed_greentea_log import gt_logger

# Return codes for test script
TEST_RESULT_OK = "OK"
TEST_RESULT_FAIL = "FAIL"
TEST_RESULT_ERROR = "ERROR"
TEST_RESULT_UNDEF = "UNDEF"
TEST_RESULT_IOERR_COPY = "IOERR_COPY"
TEST_RESULT_IOERR_DISK = "IOERR_DISK"
TEST_RESULT_IOERR_SERIAL = "IOERR_SERIAL"
TEST_RESULT_TIMEOUT = "TIMEOUT"
TEST_RESULT_NO_IMAGE = "NO_IMAGE"
TEST_RESULT_MBED_ASSERT = "MBED_ASSERT"
TEST_RESULT_BUILD_FAILED = "BUILD_FAILED"

TEST_RESULTS = [TEST_RESULT_OK,
                TEST_RESULT_FAIL,
                TEST_RESULT_ERROR,
                TEST_RESULT_UNDEF,
                TEST_RESULT_IOERR_COPY,
                TEST_RESULT_IOERR_DISK,
                TEST_RESULT_IOERR_SERIAL,
                TEST_RESULT_TIMEOUT,
                TEST_RESULT_NO_IMAGE,
                TEST_RESULT_MBED_ASSERT,
                TEST_RESULT_BUILD_FAILED
                ]

TEST_RESULT_MAPPING = {"success" : TEST_RESULT_OK,
                       "failure" : TEST_RESULT_FAIL,
                       "error" : TEST_RESULT_ERROR,
                       "end" : TEST_RESULT_UNDEF,
                       "ioerr_copy" : TEST_RESULT_IOERR_COPY,
                       "ioerr_disk" : TEST_RESULT_IOERR_DISK,
                       "ioerr_serial" : TEST_RESULT_IOERR_SERIAL,
                       "timeout" : TEST_RESULT_TIMEOUT,
                       "no_image" : TEST_RESULT_NO_IMAGE,
                       "mbed_assert" : TEST_RESULT_MBED_ASSERT,
                       "build_failed" : TEST_RESULT_BUILD_FAILED
                       }

RE_DETECT_TESTCASE_RESULT = re.compile("\\{(" + "|".join(TEST_RESULT_MAPPING.keys()) + ")\\}")

def get_test_result(output):
    """! Parse test 'output' data
    @details If test result not found returns by default TEST_RESULT_TIMEOUT value
    @return Returns found test result
    """
    result = TEST_RESULT_TIMEOUT
    for line in "".join(output).splitlines():
        search_result = RE_DETECT_TESTCASE_RESULT.search(line)
        if search_result and search_result.groups():
            result = TEST_RESULT_MAPPING[search_result.groups(0)[0]]
            break
    return result

def run_host_test(image_path,
                  disk,
                  port,
                  duration=10,
                  micro=None,
                  reset=None,
                  reset_tout=None,
                  verbose=False,
                  copy_method=None,
                  program_cycle_s=None,
                  digest_source=None,
                  json_test_cfg=None,
                  max_failed_properties=5,
                  enum_host_tests_path=None,
                  run_app=None):
    """! This function runs host test supervisor (executes mbedhtrun) and checks output from host test process.
    @return Tuple with test results, test output and test duration times
    @param image_path Path to binary file for flashing
    @param disk Currently mounted mbed-enabled devices disk (mount point)
    @param port Currently mounted mbed-enabled devices serial port (console)
    @param duration Test case timeout
    @param micro Mbed-nebaled device name
    @param reset Reset type
    @param reset_tout Reset timeout (sec)
    @param verbose Verbose mode flag
    @param copy_method Copy method type (name)
    @param program_cycle_s Wait after flashing delay (sec)
    @param json_test_cfg Additional test configuration file path passed to host tests in JSON format
    @param max_failed_properties After how many unknown properties we will assume test is not ported
    @param enum_host_tests_path Directory where locally defined host tests may reside
    @param run_app Run application mode flag (we run application and grab serial port data)
    @param digest_source if None mbedhtrun will be executed. If 'stdin',
                           stdin will be used via StdInObserver or file (if
                           file name was given as switch option)
    """

    class StdInObserver(Thread):
        """ Process used to read stdin only as console input from MUT
        """
        def __init__(self):
            Thread.__init__(self)
            self.queue = Queue()
            self.daemon = True
            self.active = True
            self.start()

        def run(self):
            while self.active:
                c = sys.stdin.read(1)
                self.queue.put(c)

        def stop(self):
            self.active = False

    class FileObserver(Thread):
        """ process used to read file content as console input from MUT
        """
        def __init__(self, filename):
            Thread.__init__(self)
            self.filename = filename
            self.queue = Queue()
            self.daemon = True
            self.active = True
            self.start()

        def run(self):
            with open(self.filename) as f:
                while self.active:
                    c = f.read(1)
                    self.queue.put(c)

        def stop(self):
            self.active = False

    class ProcessObserver(Thread):
        """ Default process used to observe stdout of another process as console input from MUT
        """
        def __init__(self, proc):
            Thread.__init__(self)
            self.proc = proc
            self.queue = Queue()
            self.daemon = True
            self.active = True
            self.start()

        def run(self):
            while self.active:
                c = self.proc.stdout.read(1)
                self.queue.put(c)

        def stop(self):
            self.active = False

            # Try stopping mbed-host-test
            try:
                self.proc.stdin.close()
            finally:
                pass

            # Give 5 sec for mbedhtrun to exit
            ret_code = None
            for i in range(5):
                ret_code = self.proc.poll()
                # A None value indicates that the process hasn't terminated yet.
                if ret_code is not None:
                    break
                sleep(1)

            if ret_code is None:            # Kill it
                print 'Terminating mbed-host-test(mbedhtrun) process (PID %s)' % self.proc.pid
                try:
                    self.proc.terminate()
                except Exception as e:
                    print "ProcessObserver.stop(): %s" % str(e)

    def get_char_from_queue(obs):
        """ Get character from queue safe way
        """
        try:
            c = obs.queue.get(block=True, timeout=0.5)
            # signals to queue job is done
            obs.queue.task_done()
        except Empty:
            c = None
        except:
            raise
        return c

    def filter_queue_char(c):
        """ Filters out non ASCII characters from serial port
        """
        if ord(c) not in range(128):
            c = ' '
        return c

    def get_auto_property_value(property_name, line):
        """! Scans auto detection line from MUT and returns scanned parameter 'property_name'
        @details Host test case has to print additional properties for test to be set up
        @return Returns string or None if property search failed
        """
        result = None
        if re.search("HOST: Property '%s'"% property_name, line) is not None:
            property = re.search("HOST: Property '%s' = '([\w\d _]+)'"% property_name, line)
            if property is not None and len(property.groups()) == 1:
                result = property.groups()[0]
        return result

    # Detect from where input should be taken, if no --digest switch is specified
    # normal test execution can be performed

    if verbose:
        gt_logger.gt_log("selecting test case observer...")
        if digest_source:
            gt_logger.gt_log_tab("selected digest source: %s"% digest_source)

    # Select who will digest test case serial port data
    if digest_source == 'stdin':
        # When we want to scan stdin for test results
        obs = StdInObserver()
    elif digest_source is not None:
        # When we want to open file to scan for test results
        obs = FileObserver(digest_source)
    else:
        # Command executing CLI for host test supervisor (in detect-mode)
        cmd = ["mbedhtrun",
                '-d', disk,
                '-p', port,
                '-f', '"%s"'% image_path,
                ]

        # Add extra parameters to host_test
        if program_cycle_s is not None:
            cmd += ["-C", str(program_cycle_s)]
        if copy_method is not None:
            cmd += ["-c", copy_method]
        if micro is not None:
            cmd += ["-m", micro]
        if reset is not None:
            cmd += ["-r", reset]
        if reset_tout is not None:
            cmd += ["-R", str(reset_tout)]
        if json_test_cfg is not None:
            cmd += ["--test-cfg", '"%s"' % str(json_test_cfg)]
        if run_app is not None:
            cmd += ["--run"]    # -f stores binary name!
        if enum_host_tests_path:
            cmd += ["-e", '"%s"'% enum_host_tests_path]

        if verbose:
            gt_logger.gt_log_tab("calling mbedhtrun: %s"% " ".join(cmd))
            gt_logger.gt_log("mbed-host-test-runner: started")
        proc = Popen(cmd, stdin=PIPE, stdout=PIPE)
        obs = ProcessObserver(proc)

    result = None
    update_once_flag = {}   # Stores flags checking if some auto-parameter was already set
    unknown_property_count = 0
    total_duration = 20     # This for flashing, reset and other serial port operations
    line = ''
    output = []
    start_time = time()
    while (time() - start_time) < (total_duration):
        try:
            c = get_char_from_queue(obs)
        except Exception as e:
            output.append('get_char_from_queue(obs): %s'% str(e))
            break
        if c:
            if verbose:
                sys.stdout.write(c)
            c = filter_queue_char(c)
            output.append(c)
            # Give the mbed under test a way to communicate the end of the test
            if c in ['\n', '\r']:

                # Check for unknown property prints
                # If there are too many we will stop test execution and assume test is not ported
                if "HOST: Unknown property" in line:
                    unknown_property_count += 1
                    if unknown_property_count >= max_failed_properties:
                        output.append('{{error}}')
                        break

                # Checking for auto-detection information from the test about MUT reset moment
                if 'reset_target' not in update_once_flag and "HOST: Reset target..." in line:
                    # We will update this marker only once to prevent multiple time resets
                    update_once_flag['reset_target'] = True
                    start_time = time()
                    total_duration = duration   # After reset we gonna use real test case duration

                # Checking for auto-detection information from the test about timeout
                auto_timeout_val = get_auto_property_value('timeout', line)
                if 'timeout' not in update_once_flag and auto_timeout_val is not None:
                    # We will update this marker only once to prevent multiple time resets
                    update_once_flag['timeout'] = True
                    total_duration = int(auto_timeout_val)

                # Detect mbed assert:
                if 'mbed assertation failed: ' in line:
                    output.append('{{mbed_assert}}')
                    break

                # Check for test end. Only a '{{end}}' in the start of line indicates a test end.
                # A sub string '{{end}}' may also appear in an error message.
                if re.search('^\{\{end\}\}', line, re.I):
                    break
                line = ''
            else:
                line += c
    else:
        result = TEST_RESULT_TIMEOUT

    if not '{end}' in line:
        output.append('{{end}}')

    c = get_char_from_queue(obs)

    if c:
        if verbose:
            sys.stdout.write(c)
        c = filter_queue_char(c)
        output.append(c)

    # Stop test process
    obs.stop()

    end_time = time()
    testcase_duration = end_time - start_time   # Test case duration from reset to {end}

    if verbose:
        gt_logger.gt_log("mbed-host-test-runner: stopped")
    if not result:
        result = get_test_result(output)
    if verbose:
        gt_logger.gt_log("mbed-host-test-runner: returned '%s'"% result)
    return (result, "".join(output), testcase_duration, duration)

def run_cli_command(cmd, shell=True, verbose=False):
    """! Runs command from command line
    @param shell Shell command (e.g. ls, ps)
    @param verbose Verbose mode flag
    @return Returns (True, 0) if command was executed successfully else return (False, error code)
    """
    result = True
    ret = 0
    try:
        ret = call(cmd, shell=shell)
        if ret:
            result = False
            if verbose:
                print "mbedgt: [ret=%d] Command: %s"% (int(ret), cmd)
    except Exception as e:
        result = False
        if verbose:
            print "mbedgt: [ret=%d] Command: %s"% (int(ret), cmd)
            print str(e)
    return (result, ret)

def run_cli_process(cmd):
    """! Runs command as a process and return stdout, stderr and ret code
    @param cmd Command to execute
    @return Tuple of (stdout, stderr, returncode)
    """
    p = Popen(cmd, stdout=PIPE, stderr=PIPE)
    _stdout, _stderr = p.communicate()
    return _stdout, _stderr, p.returncode
<commit_msg>Add KiVi transport protocol support - draft<commit_after>"""
mbed SDK
Copyright (c) 2011-2015 ARM Limited

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.

Author: Przemyslaw Wirkus <Przemyslaw.wirkus@arm.com>
"""

import re
import sys
from time import time
from subprocess import call, Popen, PIPE, STDOUT

from mbed_greentea.mbed_greentea_log import gt_logger

# Return codes for test script
TEST_RESULT_OK = "OK"
TEST_RESULT_FAIL = "FAIL"
TEST_RESULT_ERROR = "ERROR"
TEST_RESULT_UNDEF = "UNDEF"
TEST_RESULT_IOERR_COPY = "IOERR_COPY"
TEST_RESULT_IOERR_DISK = "IOERR_DISK"
TEST_RESULT_IOERR_SERIAL = "IOERR_SERIAL"
TEST_RESULT_TIMEOUT = "TIMEOUT"
TEST_RESULT_NO_IMAGE = "NO_IMAGE"
TEST_RESULT_MBED_ASSERT = "MBED_ASSERT"
TEST_RESULT_BUILD_FAILED = "BUILD_FAILED"

TEST_RESULTS = [TEST_RESULT_OK,
                TEST_RESULT_FAIL,
                TEST_RESULT_ERROR,
                TEST_RESULT_UNDEF,
                TEST_RESULT_IOERR_COPY,
                TEST_RESULT_IOERR_DISK,
                TEST_RESULT_IOERR_SERIAL,
                TEST_RESULT_TIMEOUT,
                TEST_RESULT_NO_IMAGE,
                TEST_RESULT_MBED_ASSERT,
                TEST_RESULT_BUILD_FAILED
                ]

TEST_RESULT_MAPPING = {"success" : TEST_RESULT_OK,
                       "failure" : TEST_RESULT_FAIL,
                       "error" : TEST_RESULT_ERROR,
                       "end" : TEST_RESULT_UNDEF,
                       "ioerr_copy" : TEST_RESULT_IOERR_COPY,
                       "ioerr_disk" : TEST_RESULT_IOERR_DISK,
                       "ioerr_serial" : TEST_RESULT_IOERR_SERIAL,
                       "timeout" : TEST_RESULT_TIMEOUT,
                       "no_image" : TEST_RESULT_NO_IMAGE,
                       "mbed_assert" : TEST_RESULT_MBED_ASSERT,
                       "build_failed" : TEST_RESULT_BUILD_FAILED
                       }

def get_test_result(output):
    """! Parse test 'output' data
    @details If test result not found returns by default TEST_RESULT_TIMEOUT value
    @return Returns found test result
    """
    RE_DETECT_TESTCASE_RESULT = re.compile("\\{(" + "|".join(TEST_RESULT_MAPPING.keys()) + ")\\}")
    for line in "".join(output).splitlines():
        search_result = RE_DETECT_TESTCASE_RESULT.search(line)
        if search_result and search_result.groups():
            return TEST_RESULT_MAPPING[search_result.groups(0)[0]]
    return TEST_RESULT_TIMEOUT

def run_host_test(image_path,
                  disk,
                  port,
                  duration=10,
                  micro=None,
                  reset=None,
                  reset_tout=None,
                  verbose=False,
                  copy_method=None,
                  program_cycle_s=None,
                  digest_source=None,
                  json_test_cfg=None,
                  max_failed_properties=5,
                  enum_host_tests_path=None,
                  run_app=None):
    """! This function runs host test supervisor (executes mbedhtrun) and checks output from host test process.
    @return Tuple with test results, test output and test duration times
    @param image_path Path to binary file for flashing
    @param disk Currently mounted mbed-enabled devices disk (mount point)
    @param port Currently mounted mbed-enabled devices serial port (console)
    @param duration Test case timeout
    @param micro Mbed-nebaled device name
    @param reset Reset type
    @param reset_tout Reset timeout (sec)
    @param verbose Verbose mode flag
    @param copy_method Copy method type (name)
    @param program_cycle_s Wait after flashing delay (sec)
    @param json_test_cfg Additional test configuration file path passed to host tests in JSON format
    @param max_failed_properties After how many unknown properties we will assume test is not ported
    @param enum_host_tests_path Directory where locally defined host tests may reside
    @param run_app Run application mode flag (we run application and grab serial port data)
    @param digest_source if None mbedhtrun will be executed. If 'stdin',
                           stdin will be used via StdInObserver or file (if
                           file name was given as switch option)
    """

    def run_command(cmd):
        """! Runs command and prints proc stdout on screen """
        try:
            p = Popen(cmd,
                    stdout=PIPE,
                    stderr=STDOUT)
        except OSError as e:
            print "mbedgt: run_command(%s) ret= %d failed: "% (cmd, int(ret)), str(e), e.child_traceback
        return iter(p.stdout.readline, b'')

    if verbose:
        gt_logger.gt_log("selecting test case observer...")
        if digest_source:
            gt_logger.gt_log_tab("selected digest source: %s"% digest_source)

    # Select who will digest test case serial port data
    if digest_source == 'stdin':
        # When we want to scan stdin for test results
        raise NotImplementedError
    elif digest_source is not None:
        # When we want to open file to scan for test results
        raise NotImplementedError

    # Command executing CLI for host test supervisor (in detect-mode)
    cmd = ["mbedhtrun",
            '-d', disk,
            '-p', port,
            '-f', '"%s"'% image_path,
            ]

    # Add extra parameters to host_test
    if program_cycle_s is not None:
        cmd += ["-C", str(program_cycle_s)]
    if copy_method is not None:
        cmd += ["-c", copy_method]
    if micro is not None:
        cmd += ["-m", micro]
    if reset is not None:
        cmd += ["-r", reset]
    if reset_tout is not None:
        cmd += ["-R", str(reset_tout)]
    if json_test_cfg is not None:
        cmd += ["--test-cfg", '"%s"' % str(json_test_cfg)]
    if run_app is not None:
        cmd += ["--run"]    # -f stores binary name!
    if enum_host_tests_path:
        cmd += ["-e", '"%s"'% enum_host_tests_path]

    if verbose:
        gt_logger.gt_log_tab("calling mbedhtrun: %s"% " ".join(cmd))
        gt_logger.gt_log("mbed-host-test-runner: started")

    htrun_output = ''
    start_time = time()

    for line in run_command(cmd):
        htrun_output += line
        sys.stdout.write(line)
        sys.stdout.flush()

    end_time = time()
    testcase_duration = end_time - start_time   # Test case duration from reset to {end}

    result = get_test_result(htrun_output)

    if verbose:
        gt_logger.gt_log("mbed-host-test-runner: stopped")
        gt_logger.gt_log("mbed-host-test-runner: returned '%s'"% result)
    return (result, "".join(htrun_output), testcase_duration, duration)

def run_cli_command(cmd, shell=True, verbose=False):
    """! Runs command from command line
    @param shell Shell command (e.g. ls, ps)
    @param verbose Verbose mode flag
    @return Returns (True, 0) if command was executed successfully else return (False, error code)
    """
    result = True
    ret = 0
    try:
        ret = call(cmd, shell=shell)
        if ret:
            result = False
            if verbose:
                print "mbedgt: [ret=%d] Command: %s"% (int(ret), cmd)
    except OSError as e:
        result = False
        if verbose:
            print "mbedgt: [ret=%d] Command: %s"% (int(ret), cmd)
            print str(e)
            print "mbedgt: traceback..."
            print e.child_traceback
    return (result, ret)

def run_cli_process(cmd):
    """! Runs command as a process and return stdout, stderr and ret code
    @param cmd Command to execute
    @return Tuple of (stdout, stderr, returncode)
    """
    p = Popen(cmd, stdout=PIPE, stderr=PIPE)
    _stdout, _stderr = p.communicate()
    return _stdout, _stderr, p.returncode
<|endoftext|>


<commit_before># Copyright The OpenTelemetry Authors
#
# 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 json
import unittest
from unittest.mock import MagicMock, patch

from opentelemetry import trace as trace_api
from opentelemetry.exporter.zipkin import ZipkinSpanExporter
from opentelemetry.sdk import trace
from opentelemetry.sdk.trace import Resource
from opentelemetry.sdk.trace.export import SpanExportResult
from opentelemetry.trace import TraceFlags

class MockResponse:
    def __init__(self, status_code):
        self.status_code = status_code
        self.text = status_code

class TestZipkinSpanExporter(unittest.TestCase):
    def setUp(self):
        # create and save span to be used in tests
        context = trace_api.SpanContext(
            trace_id=0x000000000000000000000000DEADBEEF,
            span_id=0x00000000DEADBEF0,
            is_remote=False,
        )

        self._test_span = trace.Span("test_span", context=context)
        self._test_span.start()
        self._test_span.end()

    def test_constructor_default(self):
        """Test the default values assigned by constructor."""
        service_name = "my-service-name"
        host_name = "localhost"
        port = 9411
        endpoint = "/api/v2/spans"
        exporter = ZipkinSpanExporter(service_name)
        ipv4 = None
        ipv6 = None
        protocol = "http"
        url = "http://localhost:9411/api/v2/spans"

        self.assertEqual(exporter.service_name, service_name)
        self.assertEqual(exporter.host_name, host_name)
        self.assertEqual(exporter.port, port)
        self.assertEqual(exporter.endpoint, endpoint)
        self.assertEqual(exporter.ipv4, ipv4)
        self.assertEqual(exporter.ipv6, ipv6)
        self.assertEqual(exporter.protocol, protocol)
        self.assertEqual(exporter.url, url)

    def test_constructor_explicit(self):
        """Test the constructor passing all the options."""
        service_name = "my-opentelemetry-zipkin"
        host_name = "opentelemetry.io"
        port = 15875
        endpoint = "/myapi/traces?format=zipkin"
        ipv4 = "1.2.3.4"
        ipv6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
        protocol = "https"
        url = "https://opentelemetry.io:15875/myapi/traces?format=zipkin"
        exporter = ZipkinSpanExporter(
            service_name=service_name,
            host_name=host_name,
            port=port,
            endpoint=endpoint,
            ipv4=ipv4,
            ipv6=ipv6,
            protocol=protocol,
        )

        self.assertEqual(exporter.service_name, service_name)
        self.assertEqual(exporter.host_name, host_name)
        self.assertEqual(exporter.port, port)
        self.assertEqual(exporter.endpoint, endpoint)
        self.assertEqual(exporter.ipv4, ipv4)
        self.assertEqual(exporter.ipv6, ipv6)
        self.assertEqual(exporter.protocol, protocol)
        self.assertEqual(exporter.url, url)

    # pylint: disable=too-many-locals
    def test_export(self):

        span_names = ("test1", "test2", "test3", "test4")
        trace_id = 0x6E0C63257DE34C926F9EFCD03927272E
        span_id = 0x34BF92DEEFC58C92
        parent_id = 0x1111111111111111
        other_id = 0x2222222222222222

        base_time = 683647322 * 10 ** 9  # in ns
        start_times = (
            base_time,
            base_time + 150 * 10 ** 6,
            base_time + 300 * 10 ** 6,
            base_time + 400 * 10 ** 6,
        )
        durations = (50 * 10 ** 6, 100 * 10 ** 6, 200 * 10 ** 6, 300 * 10 ** 6)
        end_times = (
            start_times[0] + durations[0],
            start_times[1] + durations[1],
            start_times[2] + durations[2],
            start_times[3] + durations[3],
        )

        span_context = trace_api.SpanContext(
            trace_id,
            span_id,
            is_remote=False,
            trace_flags=TraceFlags(TraceFlags.SAMPLED),
        )
        parent_context = trace_api.SpanContext(
            trace_id, parent_id, is_remote=False
        )
        other_context = trace_api.SpanContext(
            trace_id, other_id, is_remote=False
        )

        event_attributes = {
            "annotation_bool": True,
            "annotation_string": "annotation_test",
            "key_float": 0.3,
        }

        event_timestamp = base_time + 50 * 10 ** 6
        event = trace.Event(
            name="event0",
            timestamp=event_timestamp,
            attributes=event_attributes,
        )

        link_attributes = {"key_bool": True}

        link = trace_api.Link(
            context=other_context, attributes=link_attributes
        )

        otel_spans = [
            trace.Span(
                name=span_names[0],
                context=span_context,
                parent=parent_context,
                events=(event,),
                links=(link,),
            ),
            trace.Span(
                name=span_names[1], context=parent_context, parent=None
            ),
            trace.Span(name=span_names[2], context=other_context, parent=None),
            trace.Span(name=span_names[3], context=other_context, parent=None),
        ]

        otel_spans[0].start(start_time=start_times[0])
        # added here to preserve order
        otel_spans[0].set_attribute("key_bool", False)
        otel_spans[0].set_attribute("key_string", "hello_world")
        otel_spans[0].set_attribute("key_float", 111.22)
        otel_spans[0].end(end_time=end_times[0])

        otel_spans[1].start(start_time=start_times[1])
        otel_spans[1].resource = Resource(
            labels={"key_resource": "some_resource"}
        )
        otel_spans[1].end(end_time=end_times[1])

        otel_spans[2].start(start_time=start_times[2])
        otel_spans[2].set_attribute("key_string", "hello_world")
        otel_spans[2].resource = Resource(
            labels={"key_resource": "some_resource"}
        )
        otel_spans[2].end(end_time=end_times[2])

        otel_spans[3].start(start_time=start_times[3])
        otel_spans[3].end(end_time=end_times[3])

        service_name = "test-service"
        local_endpoint = {"serviceName": service_name, "port": 9411}

        exporter = ZipkinSpanExporter(service_name)
        expected = [
            {
                "traceId": format(trace_id, "x"),
                "id": format(span_id, "x"),
                "name": span_names[0],
                "timestamp": start_times[0] // 10 ** 3,
                "duration": durations[0] // 10 ** 3,
                "localEndpoint": local_endpoint,
                "kind": None,
                "tags": {
                    "key_bool": "False",
                    "key_string": "hello_world",
                    "key_float": "111.22",
                },
                "annotations": [
                    {
                        "timestamp": event_timestamp // 10 ** 3,
                        "value": "event0",
                    }
                ],
                "debug": True,
                "parentId": format(parent_id, "x"),
            },
            {
                "traceId": format(trace_id, "x"),
                "id": format(parent_id, "x"),
                "name": span_names[1],
                "timestamp": start_times[1] // 10 ** 3,
                "duration": durations[1] // 10 ** 3,
                "localEndpoint": local_endpoint,
                "kind": None,
                "tags": {"key_resource": "some_resource"},
                "annotations": None,
            },
            {
                "traceId": format(trace_id, "x"),
                "id": format(other_id, "x"),
                "name": span_names[2],
                "timestamp": start_times[2] // 10 ** 3,
                "duration": durations[2] // 10 ** 3,
                "localEndpoint": local_endpoint,
                "kind": None,
                "tags": {
                    "key_string": "hello_world",
                    "key_resource": "some_resource",
                },
                "annotations": None,
            },
            {
                "traceId": format(trace_id, "x"),
                "id": format(other_id, "x"),
                "name": span_names[3],
                "timestamp": start_times[3] // 10 ** 3,
                "duration": durations[3] // 10 ** 3,
                "localEndpoint": local_endpoint,
                "kind": None,
                "tags": {},
                "annotations": None,
            },
        ]

        mock_post = MagicMock()
        with patch("requests.post", mock_post):
            mock_post.return_value = MockResponse(200)
            status = exporter.export(otel_spans)
            self.assertEqual(SpanExportResult.SUCCESS, status)

        mock_post.assert_called_with(
            url="http://localhost:9411/api/v2/spans",
            data=json.dumps(expected),
            headers={"Content-Type": "application/json"},
        )

    # pylint: disable=too-many-locals
    def test_zero_padding(self):
        """test that hex ids starting with 0
        are properly padded to 16 or 32 hex chars
        when exported
        """

        span_names = "testZeroes"
        trace_id = 0x0E0C63257DE34C926F9EFCD03927272E
        span_id = 0x04BF92DEEFC58C92
        parent_id = 0x0AAAAAAAAAAAAAAA

        start_time = 683647322 * 10 ** 9  # in ns
        duration = 50 * 10 ** 6
        end_time = start_time + duration

        span_context = trace_api.SpanContext(
            trace_id,
            span_id,
            is_remote=False,
            trace_flags=TraceFlags(TraceFlags.SAMPLED),
        )
        parent_context = trace_api.SpanContext(
            trace_id, parent_id, is_remote=False
        )

        otel_span = trace.Span(
            name=span_names[0], context=span_context, parent=parent_context,
        )

        otel_span.start(start_time=start_time)
        otel_span.end(end_time=end_time)

        service_name = "test-service"
        local_endpoint = {"serviceName": service_name, "port": 9411}

        exporter = ZipkinSpanExporter(service_name)
        # Check traceId are properly lowercase 16 or 32 hex
        expected = [
            {
                "traceId": "0e0c63257de34c926f9efcd03927272e",
                "id": "04bf92deefc58c92",
                "name": span_names[0],
                "timestamp": start_time // 10 ** 3,
                "duration": duration // 10 ** 3,
                "localEndpoint": local_endpoint,
                "kind": None,
                "tags": {},
                "annotations": None,
                "debug": True,
                "parentId": "0aaaaaaaaaaaaaaa",
            }
        ]

        mock_post = MagicMock()
        with patch("requests.post", mock_post):
            mock_post.return_value = MockResponse(200)
            status = exporter.export([otel_span])
            self.assertEqual(SpanExportResult.SUCCESS, status)

        mock_post.assert_called_with(
            url="http://localhost:9411/api/v2/spans",
            data=json.dumps(expected),
            headers={"Content-Type": "application/json"},
        )

    @patch("requests.post")
    def test_invalid_response(self, mock_post):
        mock_post.return_value = MockResponse(404)
        spans = []
        exporter = ZipkinSpanExporter("test-service")
        status = exporter.export(spans)
        self.assertEqual(SpanExportResult.FAILURE, status)
<commit_msg>Populate resource attributes as per semantic conventions (#1053)<commit_after># Copyright The OpenTelemetry Authors
#
# 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 json
import unittest
from unittest.mock import MagicMock, patch

from opentelemetry import trace as trace_api
from opentelemetry.exporter.zipkin import ZipkinSpanExporter
from opentelemetry.sdk import trace
from opentelemetry.sdk.trace import Resource
from opentelemetry.sdk.trace.export import SpanExportResult
from opentelemetry.trace import TraceFlags

class MockResponse:
    def __init__(self, status_code):
        self.status_code = status_code
        self.text = status_code

class TestZipkinSpanExporter(unittest.TestCase):
    def setUp(self):
        # create and save span to be used in tests
        context = trace_api.SpanContext(
            trace_id=0x000000000000000000000000DEADBEEF,
            span_id=0x00000000DEADBEF0,
            is_remote=False,
        )

        self._test_span = trace.Span("test_span", context=context)
        self._test_span.start()
        self._test_span.end()

    def test_constructor_default(self):
        """Test the default values assigned by constructor."""
        service_name = "my-service-name"
        host_name = "localhost"
        port = 9411
        endpoint = "/api/v2/spans"
        exporter = ZipkinSpanExporter(service_name)
        ipv4 = None
        ipv6 = None
        protocol = "http"
        url = "http://localhost:9411/api/v2/spans"

        self.assertEqual(exporter.service_name, service_name)
        self.assertEqual(exporter.host_name, host_name)
        self.assertEqual(exporter.port, port)
        self.assertEqual(exporter.endpoint, endpoint)
        self.assertEqual(exporter.ipv4, ipv4)
        self.assertEqual(exporter.ipv6, ipv6)
        self.assertEqual(exporter.protocol, protocol)
        self.assertEqual(exporter.url, url)

    def test_constructor_explicit(self):
        """Test the constructor passing all the options."""
        service_name = "my-opentelemetry-zipkin"
        host_name = "opentelemetry.io"
        port = 15875
        endpoint = "/myapi/traces?format=zipkin"
        ipv4 = "1.2.3.4"
        ipv6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
        protocol = "https"
        url = "https://opentelemetry.io:15875/myapi/traces?format=zipkin"
        exporter = ZipkinSpanExporter(
            service_name=service_name,
            host_name=host_name,
            port=port,
            endpoint=endpoint,
            ipv4=ipv4,
            ipv6=ipv6,
            protocol=protocol,
        )

        self.assertEqual(exporter.service_name, service_name)
        self.assertEqual(exporter.host_name, host_name)
        self.assertEqual(exporter.port, port)
        self.assertEqual(exporter.endpoint, endpoint)
        self.assertEqual(exporter.ipv4, ipv4)
        self.assertEqual(exporter.ipv6, ipv6)
        self.assertEqual(exporter.protocol, protocol)
        self.assertEqual(exporter.url, url)

    # pylint: disable=too-many-locals
    def test_export(self):

        span_names = ("test1", "test2", "test3", "test4")
        trace_id = 0x6E0C63257DE34C926F9EFCD03927272E
        span_id = 0x34BF92DEEFC58C92
        parent_id = 0x1111111111111111
        other_id = 0x2222222222222222

        base_time = 683647322 * 10 ** 9  # in ns
        start_times = (
            base_time,
            base_time + 150 * 10 ** 6,
            base_time + 300 * 10 ** 6,
            base_time + 400 * 10 ** 6,
        )
        durations = (50 * 10 ** 6, 100 * 10 ** 6, 200 * 10 ** 6, 300 * 10 ** 6)
        end_times = (
            start_times[0] + durations[0],
            start_times[1] + durations[1],
            start_times[2] + durations[2],
            start_times[3] + durations[3],
        )

        span_context = trace_api.SpanContext(
            trace_id,
            span_id,
            is_remote=False,
            trace_flags=TraceFlags(TraceFlags.SAMPLED),
        )
        parent_context = trace_api.SpanContext(
            trace_id, parent_id, is_remote=False
        )
        other_context = trace_api.SpanContext(
            trace_id, other_id, is_remote=False
        )

        event_attributes = {
            "annotation_bool": True,
            "annotation_string": "annotation_test",
            "key_float": 0.3,
        }

        event_timestamp = base_time + 50 * 10 ** 6
        event = trace.Event(
            name="event0",
            timestamp=event_timestamp,
            attributes=event_attributes,
        )

        link_attributes = {"key_bool": True}

        link = trace_api.Link(
            context=other_context, attributes=link_attributes
        )

        otel_spans = [
            trace.Span(
                name=span_names[0],
                context=span_context,
                parent=parent_context,
                events=(event,),
                links=(link,),
            ),
            trace.Span(
                name=span_names[1], context=parent_context, parent=None
            ),
            trace.Span(name=span_names[2], context=other_context, parent=None),
            trace.Span(name=span_names[3], context=other_context, parent=None),
        ]

        otel_spans[0].start(start_time=start_times[0])
        otel_spans[0].resource = Resource({})
        # added here to preserve order
        otel_spans[0].set_attribute("key_bool", False)
        otel_spans[0].set_attribute("key_string", "hello_world")
        otel_spans[0].set_attribute("key_float", 111.22)
        otel_spans[0].end(end_time=end_times[0])

        otel_spans[1].start(start_time=start_times[1])
        otel_spans[1].resource = Resource(
            labels={"key_resource": "some_resource"}
        )
        otel_spans[1].end(end_time=end_times[1])

        otel_spans[2].start(start_time=start_times[2])
        otel_spans[2].set_attribute("key_string", "hello_world")
        otel_spans[2].resource = Resource(
            labels={"key_resource": "some_resource"}
        )
        otel_spans[2].end(end_time=end_times[2])

        otel_spans[3].start(start_time=start_times[3])
        otel_spans[3].resource = Resource({})
        otel_spans[3].end(end_time=end_times[3])

        service_name = "test-service"
        local_endpoint = {"serviceName": service_name, "port": 9411}

        exporter = ZipkinSpanExporter(service_name)
        expected = [
            {
                "traceId": format(trace_id, "x"),
                "id": format(span_id, "x"),
                "name": span_names[0],
                "timestamp": start_times[0] // 10 ** 3,
                "duration": durations[0] // 10 ** 3,
                "localEndpoint": local_endpoint,
                "kind": None,
                "tags": {
                    "key_bool": "False",
                    "key_string": "hello_world",
                    "key_float": "111.22",
                },
                "annotations": [
                    {
                        "timestamp": event_timestamp // 10 ** 3,
                        "value": "event0",
                    }
                ],
                "debug": True,
                "parentId": format(parent_id, "x"),
            },
            {
                "traceId": format(trace_id, "x"),
                "id": format(parent_id, "x"),
                "name": span_names[1],
                "timestamp": start_times[1] // 10 ** 3,
                "duration": durations[1] // 10 ** 3,
                "localEndpoint": local_endpoint,
                "kind": None,
                "tags": {"key_resource": "some_resource"},
                "annotations": None,
            },
            {
                "traceId": format(trace_id, "x"),
                "id": format(other_id, "x"),
                "name": span_names[2],
                "timestamp": start_times[2] // 10 ** 3,
                "duration": durations[2] // 10 ** 3,
                "localEndpoint": local_endpoint,
                "kind": None,
                "tags": {
                    "key_string": "hello_world",
                    "key_resource": "some_resource",
                },
                "annotations": None,
            },
            {
                "traceId": format(trace_id, "x"),
                "id": format(other_id, "x"),
                "name": span_names[3],
                "timestamp": start_times[3] // 10 ** 3,
                "duration": durations[3] // 10 ** 3,
                "localEndpoint": local_endpoint,
                "kind": None,
                "tags": {},
                "annotations": None,
            },
        ]

        mock_post = MagicMock()
        with patch("requests.post", mock_post):
            mock_post.return_value = MockResponse(200)
            status = exporter.export(otel_spans)
            self.assertEqual(SpanExportResult.SUCCESS, status)

        mock_post.assert_called_with(
            url="http://localhost:9411/api/v2/spans",
            data=json.dumps(expected),
            headers={"Content-Type": "application/json"},
        )

    # pylint: disable=too-many-locals
    def test_zero_padding(self):
        """test that hex ids starting with 0
        are properly padded to 16 or 32 hex chars
        when exported
        """

        span_names = "testZeroes"
        trace_id = 0x0E0C63257DE34C926F9EFCD03927272E
        span_id = 0x04BF92DEEFC58C92
        parent_id = 0x0AAAAAAAAAAAAAAA

        start_time = 683647322 * 10 ** 9  # in ns
        duration = 50 * 10 ** 6
        end_time = start_time + duration

        span_context = trace_api.SpanContext(
            trace_id,
            span_id,
            is_remote=False,
            trace_flags=TraceFlags(TraceFlags.SAMPLED),
        )
        parent_context = trace_api.SpanContext(
            trace_id, parent_id, is_remote=False
        )

        otel_span = trace.Span(
            name=span_names[0], context=span_context, parent=parent_context,
        )

        otel_span.start(start_time=start_time)
        otel_span.resource = Resource({})
        otel_span.end(end_time=end_time)

        service_name = "test-service"
        local_endpoint = {"serviceName": service_name, "port": 9411}

        exporter = ZipkinSpanExporter(service_name)
        # Check traceId are properly lowercase 16 or 32 hex
        expected = [
            {
                "traceId": "0e0c63257de34c926f9efcd03927272e",
                "id": "04bf92deefc58c92",
                "name": span_names[0],
                "timestamp": start_time // 10 ** 3,
                "duration": duration // 10 ** 3,
                "localEndpoint": local_endpoint,
                "kind": None,
                "tags": {},
                "annotations": None,
                "debug": True,
                "parentId": "0aaaaaaaaaaaaaaa",
            }
        ]

        mock_post = MagicMock()
        with patch("requests.post", mock_post):
            mock_post.return_value = MockResponse(200)
            status = exporter.export([otel_span])
            self.assertEqual(SpanExportResult.SUCCESS, status)

        mock_post.assert_called_with(
            url="http://localhost:9411/api/v2/spans",
            data=json.dumps(expected),
            headers={"Content-Type": "application/json"},
        )

    @patch("requests.post")
    def test_invalid_response(self, mock_post):
        mock_post.return_value = MockResponse(404)
        spans = []
        exporter = ZipkinSpanExporter("test-service")
        status = exporter.export(spans)
        self.assertEqual(SpanExportResult.FAILURE, status)
<|endoftext|>


<commit_before>"""
Created on 11 May 2017

@author: Bruno Beloff (bruno.beloff@southcoastscience.com)

https://pymotw.com/2/subprocess/
"""

import os
import subprocess

from collections import OrderedDict

from scs_core.data.json import JSONable

# TODO: add listing of cmd directory as a native command.

# --------------------------------------------------------------------------------------------------------------------

class Command(JSONable):
    """
    classdocs
    """

    __PROHIBITED_TOKENS = ('<', '>', ';', '|')

    __TIMEOUT = 60.0

    # ----------------------------------------------------------------------------------------------------------------

    @classmethod
    def construct_from_jdict(cls, jdict):
        if not jdict:
            return None

        cmd = jdict.get('cmd')
        params = jdict.get('params')

        stdout = jdict.get('stdout')
        stderr = jdict.get('stderr')
        return_code = jdict.get('ret')

        datum = Command(cmd, params, stdout, stderr, return_code)

        return datum

    @classmethod
    def construct_from_tokens(cls, tokens):
        if not tokens:
            return Command(None, [])

        cmd = tokens[0]
        params = tokens[1:]

        return Command(cmd, params)

    # ----------------------------------------------------------------------------------------------------------------

    def __init__(self, cmd, params, stdout=None, stderr=None, return_code=None):
        """
        Constructor
        """
        self.__cmd = cmd                        # string
        self.__params = params                  # array

        self.__stdout = stdout                  # array of string
        self.__stderr = stderr                  # array of string
        self.__return_code = return_code        # int

    # ----------------------------------------------------------------------------------------------------------------

    def is_valid(self, host):
        try:
            host.COMMAND_DIR
        except AttributeError:
            return False

        if set(self.params).intersection(set(Command.__PROHIBITED_TOKENS)):
            return False

        if self.cmd not in os.listdir(host.COMMAND_DIR):
            return False

        return True

    def execute(self, host):
        if not self.cmd:
            return

        statement = ['./' + self.cmd]
        statement.extend(self.params)

        proc = subprocess.Popen(statement, cwd=host.COMMAND_DIR, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

        stdout_bytes, stderr_bytes = proc.communicate(None, Command.__TIMEOUT)

        self.__stdout = stdout_bytes.decode().strip().splitlines()
        self.__stderr = stderr_bytes.decode().strip().splitlines()
        self.__return_code = proc.returncode

        return self.__return_code == 0

    # ----------------------------------------------------------------------------------------------------------------

    def as_json(self):
        jdict = OrderedDict()

        jdict['cmd'] = self.cmd
        jdict['params'] = self.params

        jdict['stdout'] = self.stdout
        jdict['stderr'] = self.stderr
        jdict['ret'] = self.return_code

        return jdict

    # ----------------------------------------------------------------------------------------------------------------

    @property
    def cmd(self):
        return self.__cmd

    @property
    def params(self):
        return self.__params

    @property
    def stdout(self):
        return self.__stdout

    @property
    def stderr(self):
        return self.__stderr

    @property
    def return_code(self):
        return self.__return_code

    # ----------------------------------------------------------------------------------------------------------------

    def __str__(self, *args, **kwargs):
        return "Command:{cmd:%s, params:%s, stdout:%s, stderr:%s, return_code:%s}" % \
               (self.cmd, self.params, self.stdout, self.stderr, self.return_code)
<commit_msg>Upgrading Command.<commit_after>"""
Created on 11 May 2017

@author: Bruno Beloff (bruno.beloff@southcoastscience.com)

https://pymotw.com/2/subprocess/
"""

import os
import subprocess

from collections import OrderedDict

from scs_core.data.json import JSONable

# --------------------------------------------------------------------------------------------------------------------

class Command(JSONable):
    """
    classdocs
    """

    __LIST_CMD = '?'

    __PROHIBITED_TOKENS = ('<', '>', ';', '|')

    __TIMEOUT = 60.0

    # ----------------------------------------------------------------------------------------------------------------

    @classmethod
    def construct_from_jdict(cls, jdict):
        if not jdict:
            return None

        cmd = jdict.get('cmd')
        params = jdict.get('params')

        stdout = jdict.get('stdout')
        stderr = jdict.get('stderr')
        return_code = jdict.get('ret')

        datum = Command(cmd, params, stdout, stderr, return_code)

        return datum

    @classmethod
    def construct_from_tokens(cls, tokens):
        if not tokens:
            return Command(None, [])

        cmd = tokens[0]
        params = tokens[1:]

        return Command(cmd, params)

    # ----------------------------------------------------------------------------------------------------------------

    def __init__(self, cmd, params, stdout=None, stderr=None, return_code=None):
        """
        Constructor
        """
        self.__cmd = cmd                        # string
        self.__params = params                  # array

        self.__stdout = stdout                  # array of string
        self.__stderr = stderr                  # array of string
        self.__return_code = return_code        # int

    # ----------------------------------------------------------------------------------------------------------------

    def is_valid(self, host):
        try:
            host.COMMAND_DIR
        except AttributeError:
            return False

        if set(self.params).intersection(set(Command.__PROHIBITED_TOKENS)):
            return False

        if self.cmd == Command.__LIST_CMD:
            return True

        if self.cmd not in os.listdir(host.COMMAND_DIR):
            return False

        return True

    def execute(self, host):
        if not self.cmd:
            return None

        statement = ['./' + self.cmd]
        statement.extend(self.params)

        proc = subprocess.Popen(statement, cwd=host.COMMAND_DIR, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

        stdout_bytes, stderr_bytes = proc.communicate(None, Command.__TIMEOUT)

        self.__stdout = stdout_bytes.decode().strip().splitlines()
        self.__stderr = stderr_bytes.decode().strip().splitlines()
        self.__return_code = proc.returncode

        return self.__return_code == 0

    # ----------------------------------------------------------------------------------------------------------------

    def as_json(self):
        jdict = OrderedDict()

        jdict['cmd'] = self.cmd
        jdict['params'] = self.params

        jdict['stdout'] = self.stdout
        jdict['stderr'] = self.stderr
        jdict['ret'] = self.return_code

        return jdict

    # ----------------------------------------------------------------------------------------------------------------

    @property
    def cmd(self):
        return self.__cmd

    @property
    def params(self):
        return self.__params

    @property
    def stdout(self):
        return self.__stdout

    @property
    def stderr(self):
        return self.__stderr

    @property
    def return_code(self):
        return self.__return_code

    # ----------------------------------------------------------------------------------------------------------------

    def __str__(self, *args, **kwargs):
        return "Command:{cmd:%s, params:%s, stdout:%s, stderr:%s, return_code:%s}" % \
               (self.cmd, self.params, self.stdout, self.stderr, self.return_code)
<|endoftext|>


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

import mock
import os
import unittest

CURRENT_DIR = os.path.abspath(os.path.split(__file__)[0])
IMAGE_DIR = os.path.join(CURRENT_DIR, "..", "images")

class MockedGetResponse:
    status_code = 200

    def __init__(self, url):
        """Retrieve the file on the filesytem according to the name. """
        basename = os.path.basename(url)
        filename = os.path.join(IMAGE_DIR, basename)
        self.content = open(filename, "r").read()

def mocked_thumbor_get_response(url):
    response = MockedGetResponse(url)
    return response

class MockedPostResponse:
    headers = {}

def mocked_thumbor_post_response(url, data, headers):
    response = MockedPostResponse()
    response.headers["location"] = "/image/oooooo32chars_random_idooooooooo/%s" % headers["Slug"]
    return response

class ThumborStorageFileTest(unittest.TestCase):
    def setUp(self):
        super(ThumborStorageFileTest, self).setUp()
        os.environ['DJANGO_SETTINGS_MODULE'] = "settings"
        self.patcher_get = mock.patch('django_thumborstorage.storages.requests.get')
        self.MockGetClass = self.patcher_get.start()
        self.MockGetClass.side_effect = mocked_thumbor_get_response

        self.patcher_post = mock.patch('django_thumborstorage.storages.requests.post')
        self.MockPostClass = self.patcher_post.start()
        self.MockPostClass.side_effect = mocked_thumbor_post_response

    def tearDown(self):
        self.patcher_get.stop()

    def test_get_file(self):
        from django_thumborstorage import storages
        from django.conf import settings
        filename = '/image/5247a82854384f228c6fba432c67e6a8/people/new/TempletonPeck.jpg'
        thumbor_file = storages.ThumborStorageFile(filename, mode='r')
        thumbor_file.file
        self.MockGetClass.assert_called_with("%s%s" % (settings.THUMBOR_SERVER, filename))

    def test_size(self):
        from django_thumborstorage import storages
        from django.conf import settings
        filename = '/image/5247a82854384f228c6fba432c67e6a8/people/new/TempletonPeck.jpg'
        thumbor_file = storages.ThumborStorageFile(filename, mode='r')
        size = thumbor_file.size
        self.MockGetClass.assert_called_with("%s%s" % (settings.THUMBOR_SERVER, filename))
        self.assertEqual(size, 9730)

    def test_write_jpeg(self):
        from django_thumborstorage import storages
        from django.conf import settings
        from django.core.files.base import ContentFile
        filename = 'people/HannibalSmith.jpg'
        content = ContentFile(open('%s/HannibalSmith.jpg' % IMAGE_DIR))
        thumbor_file = storages.ThumborStorageFile(filename, mode="w")
        thumbor_file.write(content=content)
        self.MockPostClass.assert_called_with("%s/image" % settings.THUMBOR_WRITABLE_SERVER,
                                              data=content.file.read(),
                                              headers={"Content-Type": "image/jpeg", "Slug": filename})
        self.assertEqual(thumbor_file._location, '/image/oooooo32chars_random_idooooooooo/%s' % filename)

    def test_write_png(self):
        from django_thumborstorage import storages
        from django.conf import settings
        from django.core.files.base import ContentFile
        filename = 'foundations/gnu.png'
        content = ContentFile(open('%s/gnu.png' % IMAGE_DIR))
        thumbor_file = storages.ThumborStorageFile(filename, mode="w")
        thumbor_file.write(content=content)
        self.MockPostClass.assert_called_with("%s/image" % settings.THUMBOR_WRITABLE_SERVER,
                                              data=content.file.read(),
                                              headers={"Content-Type": "image/png", "Slug": filename})
        self.assertEqual(thumbor_file._location, '/image/oooooo32chars_random_idooooooooo/%s' % filename)

class ThumborStorageTest(unittest.TestCase):
    def setUp(self):
        super(ThumborStorageTest, self).setUp()
        os.environ['DJANGO_SETTINGS_MODULE'] = "settings"
        self.patcher_get = mock.patch('django_thumborstorage.storages.requests.get')
        self.MockGetClass = self.patcher_get.start()
        self.MockGetClass.side_effect = mocked_thumbor_get_response

        self.patcher_post = mock.patch('django_thumborstorage.storages.requests.post')
        self.MockPostClass = self.patcher_post.start()
        self.MockPostClass.side_effect = mocked_thumbor_post_response

    def tearDown(self):
        self.patcher_get.stop()

    def test_size(self):
        from django_thumborstorage import storages
        from django.conf import settings
        storage = storages.ThumborStorage()
        filename = '/image/5247a82854384f228c6fba432c67e6a8/people/new/TempletonPeck.jpg'
        size = storage.size(filename)
        self.MockGetClass.assert_called_with("%s%s" % (settings.THUMBOR_SERVER, filename))
        self.assertEqual(size, 9730)

def suite():
    suite = unittest.TestLoader().loadTestsFromTestCase(ThumborStorageTest)
    suite.addTests(unittest.TestLoader().loadTestsFromTestCase(ThumborStorageFileTest))
    return suite
<commit_msg>Add ThumborStorageTest.test_save().<commit_after># -*- coding: utf-8 -*-

import mock
import os
import unittest
from django.core.files.base import ContentFile

CURRENT_DIR = os.path.abspath(os.path.split(__file__)[0])
IMAGE_DIR = os.path.join(CURRENT_DIR, "..", "images")

class MockedGetResponse:
    status_code = 200

    def __init__(self, url):
        """Retrieve the file on the filesytem according to the name. """
        basename = os.path.basename(url)
        filename = os.path.join(IMAGE_DIR, basename)
        self.content = open(filename, "r").read()

def mocked_thumbor_get_response(url):
    response = MockedGetResponse(url)
    return response

class MockedPostResponse:
    headers = {}

def mocked_thumbor_post_response(url, data, headers):
    response = MockedPostResponse()
    response.headers["location"] = "/image/oooooo32chars_random_idooooooooo/%s" % headers["Slug"]
    return response

class ThumborStorageFileTest(unittest.TestCase):
    def setUp(self):
        super(ThumborStorageFileTest, self).setUp()
        os.environ['DJANGO_SETTINGS_MODULE'] = "settings"
        self.patcher_get = mock.patch('django_thumborstorage.storages.requests.get')
        self.MockGetClass = self.patcher_get.start()
        self.MockGetClass.side_effect = mocked_thumbor_get_response

        self.patcher_post = mock.patch('django_thumborstorage.storages.requests.post')
        self.MockPostClass = self.patcher_post.start()
        self.MockPostClass.side_effect = mocked_thumbor_post_response

    def tearDown(self):
        self.patcher_get.stop()

    def test_get_file(self):
        from django_thumborstorage import storages
        from django.conf import settings
        filename = '/image/5247a82854384f228c6fba432c67e6a8/people/new/TempletonPeck.jpg'
        thumbor_file = storages.ThumborStorageFile(filename, mode='r')
        thumbor_file.file
        self.MockGetClass.assert_called_with("%s%s" % (settings.THUMBOR_SERVER, filename))

    def test_size(self):
        from django_thumborstorage import storages
        from django.conf import settings
        filename = '/image/5247a82854384f228c6fba432c67e6a8/people/new/TempletonPeck.jpg'
        thumbor_file = storages.ThumborStorageFile(filename, mode='r')
        size = thumbor_file.size
        self.MockGetClass.assert_called_with("%s%s" % (settings.THUMBOR_SERVER, filename))
        self.assertEqual(size, 9730)

    def test_write_jpeg(self):
        from django_thumborstorage import storages
        from django.conf import settings
        filename = 'people/HannibalSmith.jpg'
        content = ContentFile(open('%s/HannibalSmith.jpg' % IMAGE_DIR))
        thumbor_file = storages.ThumborStorageFile(filename, mode="w")
        thumbor_file.write(content=content)
        self.MockPostClass.assert_called_with("%s/image" % settings.THUMBOR_WRITABLE_SERVER,
                                              data=content.file.read(),
                                              headers={"Content-Type": "image/jpeg", "Slug": filename})
        self.assertEqual(thumbor_file._location, '/image/oooooo32chars_random_idooooooooo/%s' % filename)

    def test_write_png(self):
        from django_thumborstorage import storages
        from django.conf import settings
        filename = 'foundations/gnu.png'
        content = ContentFile(open('%s/gnu.png' % IMAGE_DIR))
        thumbor_file = storages.ThumborStorageFile(filename, mode="w")
        thumbor_file.write(content=content)
        self.MockPostClass.assert_called_with("%s/image" % settings.THUMBOR_WRITABLE_SERVER,
                                              data=content.file.read(),
                                              headers={"Content-Type": "image/png", "Slug": filename})
        self.assertEqual(thumbor_file._location, '/image/oooooo32chars_random_idooooooooo/%s' % filename)

class ThumborStorageTest(unittest.TestCase):
    def setUp(self):
        super(ThumborStorageTest, self).setUp()
        os.environ['DJANGO_SETTINGS_MODULE'] = "settings"
        self.patcher_get = mock.patch('django_thumborstorage.storages.requests.get')
        self.MockGetClass = self.patcher_get.start()
        self.MockGetClass.side_effect = mocked_thumbor_get_response

        self.patcher_post = mock.patch('django_thumborstorage.storages.requests.post')
        self.MockPostClass = self.patcher_post.start()
        self.MockPostClass.side_effect = mocked_thumbor_post_response

    def tearDown(self):
        self.patcher_get.stop()

    def test_size(self):
        from django_thumborstorage import storages
        from django.conf import settings
        storage = storages.ThumborStorage()
        filename = '/image/5247a82854384f228c6fba432c67e6a8/people/new/TempletonPeck.jpg'
        size = storage.size(filename)
        self.MockGetClass.assert_called_with("%s%s" % (settings.THUMBOR_SERVER, filename))
        self.assertEqual(size, 9730)

    def test_save(self):
        from django_thumborstorage import storages
        from django.conf import settings
        storage = storages.ThumborStorage()
        filename = 'people/HannibalSmith.jpg'
        content = ContentFile(open('%s/HannibalSmith.jpg' % IMAGE_DIR))
        response = storage.save(filename, content)
        self.MockPostClass.assert_called_with("%s/image" % settings.THUMBOR_WRITABLE_SERVER,
                                              data=content.file.read(),
                                              headers={"Content-Type": "image/jpeg", "Slug": filename})
        self.assertEqual(response, '/image/oooooo32chars_random_idooooooooo/%s' % filename)

def suite():
    suite = unittest.TestLoader().loadTestsFromTestCase(ThumborStorageTest)
    suite.addTests(unittest.TestLoader().loadTestsFromTestCase(ThumborStorageFileTest))
    return suite
<|endoftext|>


<commit_before>from __future__ import absolute_import

from exam.decorators import before, after, around, patcher  # NOQA
from exam.objects import noop  # NOQA
from exam.asserts import AssertsMixin

import inspect

class MultipleGeneratorsContextManager(object):

    def __init__(self, *generators):
        self.generators = generators

    def __enter__(self, *args, **kwargs):
        [g.next() for g in self.generators]

    def __exit__(self, *args, **kwargs):
        for generator in reversed(self.generators):
            try:
                generator.next()
            except StopIteration:
                pass

class Exam(AssertsMixin):

    @before
    def __setup_patchers(self):
        for attr, patchr in self.__attrs_of_type(patcher):
            patch_object = patchr.build_patch(self)
            setattr(self, attr, patch_object.start())
            self.addCleanup(patch_object.stop)

    def __attrs_of_type(self, kind):
        for base in reversed(inspect.getmro(type(self))):
            for attr, class_value in vars(base).iteritems():
                resolved_value = getattr(type(self), attr, False)

                if type(resolved_value) is not kind:
                    continue
                # If the attribute inside of this base is not the exact same
                # value as the one in type(self), that means that it's been
                # overwritten somewhere down the line and we shall skip it
                elif class_value is not resolved_value:
                    continue
                else:
                    yield attr, resolved_value

    def __run_before_hooks(self):
        for _, value in self.__attrs_of_type(before):
            value(self)

    def __run_after_hooks(self):
        for _, value in self.__attrs_of_type(after):
            value(self)

    def run(self, *args, **kwargs):
        generators = (value(self) for _, value in self.__attrs_of_type(around))
        with MultipleGeneratorsContextManager(*generators):
            self.__run_before_hooks()
            getattr(super(Exam, self), 'run', noop)(*args, **kwargs)
            self.__run_after_hooks()
<commit_msg>Switch to abstract run_hooks method<commit_after>from __future__ import absolute_import

from exam.decorators import before, after, around, patcher  # NOQA
from exam.objects import noop  # NOQA
from exam.asserts import AssertsMixin

import inspect

class MultipleGeneratorsContextManager(object):

    def __init__(self, *generators):
        self.generators = generators

    def __enter__(self, *args, **kwargs):
        [g.next() for g in self.generators]

    def __exit__(self, *args, **kwargs):
        for generator in reversed(self.generators):
            try:
                generator.next()
            except StopIteration:
                pass

class Exam(AssertsMixin):

    @before
    def __setup_patchers(self):
        for attr, patchr in self.__attrs_of_type(patcher):
            patch_object = patchr.build_patch(self)
            setattr(self, attr, patch_object.start())
            self.addCleanup(patch_object.stop)

    def __attrs_of_type(self, kind):
        for base in reversed(inspect.getmro(type(self))):
            for attr, class_value in vars(base).iteritems():
                resolved_value = getattr(type(self), attr, False)

                if type(resolved_value) is not kind:
                    continue
                # If the attribute inside of this base is not the exact same
                # value as the one in type(self), that means that it's been
                # overwritten somewhere down the line and we shall skip it
                elif class_value is not resolved_value:
                    continue
                else:
                    yield attr, resolved_value

    def __run_hooks(self, hook):
        for _, value in self.__attrs_of_type(hook):
            value(self)

    def run(self, *args, **kwargs):
        generators = (value(self) for _, value in self.__attrs_of_type(around))
        with MultipleGeneratorsContextManager(*generators):
            self.__run_hooks(before)
            getattr(super(Exam, self), 'run', noop)(*args, **kwargs)
            self.__run_hooks(after)
<|endoftext|>


<commit_before>from ..settings import *

DEBUG = True
ALLOWED_HOSTS = ['*']

INSTALLED_APPS += [
    #    'django_extensions',
    'bootstrap3',
    'sites.dev.books',
]

ROOT_URLCONF = 'sites.dev.urls'
WSGI_APPLICATION = 'sites.dev.wsgi.application'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(SITE_DIR, 'db.sqlite3'),
    }
}

STATIC_URL = '/admin-static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
<commit_msg>fix for django tests at sites.dev.settings env<commit_after>from ..settings import *

DEBUG = True
ALLOWED_HOSTS = ['*']

INSTALLED_APPS += [
    #    'django_extensions',
    'bootstrap3',
    'sites.dev.books',
]

ROOT_URLCONF = 'sites.dev.urls'
WSGI_APPLICATION = 'sites.dev.wsgi.application'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(SITE_DIR, 'db.sqlite3'),
    }
}

STATIC_URL = '/admin-static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

if 'test' in sys.argv[1:] or 'jenkins' in sys.argv[1:]:
    from ..test.settings import *
<|endoftext|>