<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: ai ts=4 sts=4 et sw=4 nu
"""
(c) 2014 <NAME>
Doremi API Commands definition
:author: <NAME>
"""
from __future__ import (unicode_literals, absolute_import,
                        division, print_function)
from . import handlers
import toolbox
import logging

TIMEOUT = 3600

REQUEST_ID = 0


def pretty_print_command(header, key, ber, id, data):
    short_data = data.encode('hex')
    if len(data) > 40:
        short_data = short_data[0:40] + str('...')
    return """
             0.......4.......8.......12......16......20......24......28......32
    Header : {}
    Key    : {}
    Ber    : {}
    ID     : {}
    Data   : {}
    Command: {}
    """.format(header.encode('hex'), key.encode('hex'), ber.encode('hex'), id.encode('hex'), short_data,
               (header + key + ber + id).encode('hex') + short_data)


class ParameterException(Exception):
    pass


class CommandCall():
    """
    Command Call class.

    Represents a pair of request sent and response received.
    """
    def __init__(self, socket, key, debug, host, port):
        """
        Init function.
        """
        self.socket = socket
        self.key = key
        self.debug = debug
        self.host = host
        self.port = port

    def send(self, *args, **kwargs):
        """
        Send a command request with formatted parameters.
        """
        try:
            request_bin = NAMES[self.key].construct(*args, **kwargs)
        except KeyError as ke:
            raise Exception("Command named %s does not exists. Implementation error. Error : %s" % (self.key, ke))
        except Exception as e:
            if self.debug: import traceback; traceback.print_exc()
            raise ParameterException(*e.args)

        self.socket.send(request_bin)

        if self.debug:
            logging.debug(
                "REQUEST SENT TO %s:%d : \n%s" % (
                    self.host,
                    self.port,
                    NAMES[self.key].explain(*args, **kwargs)
                )
            )
        return 0

    def receive(self):
        """
        Receive and parse a command response.
        """
        response_header = self.socket.receive(13)
        response_key = self.socket.receive(3)
        response_ber = self.socket.receive(4)
        response_data_size = toolbox.bytes.ber_2_int(response_ber) - 4
        response_id = self.socket.receive(4)
        response_data = self.socket.receive(response_data_size)

        response_command = KEYS[response_key]
        response_handler = response_command.handler

        if self.debug:
            logging.debug(
                "RESPONSE RECEIVE FROM %s:%d :\n RESPONSE %s %sResult : %s\n" % (
                    self.host,
                    self.port,
                    response_command.name,
                    pretty_print_command(
                        response_header,
                        response_key,
                        response_ber,
                        response_id,
                        response_data
                    ),
                    response_data[-1].encode('hex') if len(response_data)>0 else '---'
                )
            )
        parsed_response = response_handler(response_data)
        return parsed_response

    def send_and_receive(self, *args, **kwargs):
        """
        Send a command request, receive and parse response.
        """
        self.send(*args, **kwargs)
        return self.receive()

    def __call__(self, *args, **kwargs):
        """
         Callable object. Send a command request, receive and parse response.
        """
        return self.send_and_receive(*args, **kwargs)


class DoremiAPICommand:
    """Generic Doremi API Command Class

    Packs data about a requestor a response command.
    """
    command_type = 'COMMAND'

    def __init__(self, name, key, handler, timeout=TIMEOUT):
        self.name = name
        self.key = key.decode('hex')
        self.handler = handler
        self.timeout = timeout

    def header(self):
        """
        0x06 # Object Identifier
        0x0E # Label side
        0x2B # ISO, ORG designator
        0x34 # SMPTE designator
        0x02 # KLV Groups (Sets and Packs)
        0x05 # Fixed Length Pack
        0x01 # Set/Pack Dictionary
        0x0A # Registry Version at the point of registration of this key
        0x0E # Organizationally Registered for Private Use
        0x10 # Doremi Labs, Inc
        0x01 # DCP-2000 Messages
        0x01 # Version 1
        0x01 # DCP-2000 Intra-Theater Messages Packs
        """
        return '060E2B340205010A0E10010101'.decode('hex')

    def construct(self, *args, **kwargs):
        return self.header() + self.key + self.ber(*args, **kwargs) + self.request_id() + self.data(*args, **kwargs)

    def to_hex(self, *args, **kwargs):
        return self.construct(*args, **kwargs).encode('hex')

    def ber(self, *args, **kwargs):
        siz = len(self.data(*args, **kwargs))
        return toolbox.bytes.int_2_ber(siz).tostring()

    def request_id(self, inc=True):
        global REQUEST_ID
        if inc:
            REQUEST_ID = (REQUEST_ID + 1) % 60000
        return toolbox.bytes.pack_word(REQUEST_ID)

    def data(self, *args, **kwargs):
        if self.handler:
            return self.handler(*args, **kwargs).tostring()
        else:
            return str('')

    def explain(self, *args, **kwargs):
        ppc = pretty_print_command(self.header(), self.key, self.ber(*args, **kwargs), self.request_id(inc=False),
                                   self.data(*args, **kwargs))
        return """ {} {} {} """.format(self.command_type, self.name, ppc)


class DoremiAPIRequest(DoremiAPICommand):
    """Generic Doremi API Request Class

    Packs data about a request command.
    """
    command_type = 'REQUEST'


class DoremiAPIResponse(DoremiAPICommand):
    """Generic Doremi API Response Class

    Packs data about a response command.
    """
    command_type = 'RESPONSE'


COMMANDS = [
    DoremiAPIRequest('IngestAddJob', '070F00', handlers.ingest_add_job_request_handler),
    DoremiAPIResponse('IngestAddJob', '071000', handlers.ingest_add_job_response_handler),

    DoremiAPIRequest('GetCPLInfo', '010300', handlers.uuid_request_handler),
    DoremiAPIResponse('GetCPLInfo', '010400', handlers.get_cpl_info_response_handler),

    DoremiAPIRequest('IngestCancelJob', '071700', handlers.ingest_cancel_job_request_handler),<commit_msg>Python 3 bugfixes<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: ai ts=4 sts=4 et sw=4 nu
"""
(c) 2014 <NAME>
Doremi API Commands definition
:author: <NAME>
"""
from __future__ import (unicode_literals, absolute_import,
                        division, print_function)
from . import handlers
import toolbox
import logging
import binascii

TIMEOUT = 3600

REQUEST_ID = 0


def pretty_print_command(header, key, ber, id, data):
    short_data = data.encode('hex')
    if len(data) > 40:
        short_data = short_data[0:40] + str('...')
    return """
             0.......4.......8.......12......16......20......24......28......32
    Header : {}
    Key    : {}
    Ber    : {}
    ID     : {}
    Data   : {}
    Command: {}
    """.format(header.encode('hex'), key.encode('hex'), ber.encode('hex'), id.encode('hex'), short_data,
               (header + key + ber + id).encode('hex') + short_data)


class ParameterException(Exception):
    pass


class CommandCall():
    """
    Command Call class.

    Represents a pair of request sent and response received.
    """
    def __init__(self, socket, key, debug, host, port):
        """
        Init function.
        """
        self.socket = socket
        self.key = key
        self.debug = debug
        self.host = host
        self.port = port

    def send(self, *args, **kwargs):
        """
        Send a command request with formatted parameters.
        """
        try:
            request_bin = NAMES[self.key].construct(*args, **kwargs)
        except KeyError as ke:
            raise Exception("Command named %s does not exists. Implementation error. Error : %s" % (self.key, ke))
        except Exception as e:
            if self.debug: import traceback; traceback.print_exc()
            raise ParameterException(*e.args)

        self.socket.send(request_bin)

        if self.debug:
            logging.debug(
                "REQUEST SENT TO %s:%d : \n%s" % (
                    self.host,
                    self.port,
                    NAMES[self.key].explain(*args, **kwargs)
                )
            )
        return 0

    def receive(self):
        """
        Receive and parse a command response.
        """
        response_header = self.socket.receive(13)
        response_key = self.socket.receive(3)
        response_ber = self.socket.receive(4)
        response_data_size = toolbox.bytes.ber_2_int(response_ber) - 4
        response_id = self.socket.receive(4)
        response_data = self.socket.receive(response_data_size)

        response_command = KEYS[response_key]
        response_handler = response_command.handler

        if self.debug:
            logging.debug(
                "RESPONSE RECEIVE FROM %s:%d :\n RESPONSE %s %sResult : %s\n" % (
                    self.host,
                    self.port,
                    response_command.name,
                    pretty_print_command(
                        response_header,
                        response_key,
                        response_ber,
                        response_id,
                        response_data
                    ),
                    response_data[-1].encode('hex') if len(response_data)>0 else '---'
                )
            )
        parsed_response = response_handler(response_data)
        return parsed_response

    def send_and_receive(self, *args, **kwargs):
        """
        Send a command request, receive and parse response.
        """
        self.send(*args, **kwargs)
        return self.receive()

    def __call__(self, *args, **kwargs):
        """
         Callable object. Send a command request, receive and parse response.
        """
        return self.send_and_receive(*args, **kwargs)


class DoremiAPICommand:
    """Generic Doremi API Command Class

    Packs data about a requestor a response command.
    """
    command_type = 'COMMAND'

    def __init__(self, name, key, handler, timeout=TIMEOUT):
        self.name = name
        self.key = bytes.fromhex(key)
        self.handler = handler
        self.timeout = timeout

    def header(self):
        """
        0x06 # Object Identifier
        0x0E # Label side
        0x2B # ISO, ORG designator
        0x34 # SMPTE designator
        0x02 # KLV Groups (Sets and Packs)
        0x05 # Fixed Length Pack
        0x01 # Set/Pack Dictionary
        0x0A # Registry Version at the point of registration of this key
        0x0E # Organizationally Registered for Private Use
        0x10 # Doremi Labs, Inc
        0x01 # DCP-2000 Messages
        0x01 # Version 1
        0x01 # DCP-2000 Intra-Theater Messages Packs
        """
        return bytes.fromhex('060E2B340205010A0E10010101')

    def construct(self, *args, **kwargs):
        return self.header() + self.key + self.ber(*args, **kwargs) + self.request_id() + self.data(*args, **kwargs)

    def to_hex(self, *args, **kwargs):
        return binascii.hexlify(self.construct(*args, **kwargs))

    def ber(self, *args, **kwargs):
        siz = len(self.data(*args, **kwargs))
        return toolbox.bytes.int_2_ber(siz).tostring()

    def request_id(self, inc=True):
        global REQUEST_ID
        if inc:
            REQUEST_ID = (REQUEST_ID + 1) % 60000
        return toolbox.bytes.pack_word(REQUEST_ID)

    def data(self, *args, **kwargs):
        if self.handler:
            return self.handler(*args, **kwargs).tostring()
        else:
            return bytearray()

    def explain(self, *args, **kwargs):
        ppc = pretty_print_command(self.header(), self.key, self.ber(*args, **kwargs), self.request_id(inc=False),
                                   self.data(*args, **kwargs))
        return """ {} {} {} """.format(self.command_type, self.name, ppc)


class DoremiAPIRequest(DoremiAPICommand):
    """Generic Doremi API Request Class

    Packs data about a request command.
    """
    command_type = 'REQUEST'


class DoremiAPIResponse(DoremiAPICommand):
    """Generic Doremi API Response Class

    Packs data about a response command.
    """
    command_type = 'RESPONSE'


COMMANDS = [
    DoremiAPIRequest('IngestAddJob', '070F00', handlers.ingest_add_job_request_handler),
    DoremiAPIResponse('IngestAddJob', '071000', handlers.ingest_add_job_response_handler),

    DoremiAPIRequest('GetCPLInfo', '010300', handlers.uuid_request_handler),
    DoremiAPIResponse('GetCPLInfo', '010400', handlers.get_cpl_info_response_handler),

    DoremiAPIRequest('IngestCancelJob', '071700', handlers.ingest_cancel_job_request_handler),
{'fraction_non_alphanumeric': 0.11932515337423313, 'fraction_numerical': 0.0223159509202454, 'mean_word_length': 2.0576787807737396, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4494282', 'n_tokens_mistral': 4077, 'n_tokens_neox': 3786, 'n_words': 921}