<commit_before>"""
Meta messages for MIDI files.

Todo:
     - what if an unknown meta message is implemented and someone depends on
       the 'data' attribute?
     - is 'type_byte' a good name?
     - 'values' is not a good name for a dictionary.
     - type and value safety?
     - copy().
     - expose _key_signature_encode/decode?
"""
from __future__ import print_function, division
import sys
import math
from contextlib import contextmanager
from .messages import BaseMessage, check_time
from .types import signed, unsigned, encode_variable_int

PY2 = (sys.version_info.major == 2)

_charset = 'latin1'

def reverse_table(table):
    """Return value: key for dictionary."""
    return {value: key for (key, value) in table.items()}

_key_signature_decode = {
        (-7, 0): 'Cb',
        (-6, 0): 'Gb',
        (-5, 0): 'Db',
        (-4, 0): 'Ab',
        (-3, 0): 'Eb',
        (-2, 0): 'Bb',
        (-1, 0): 'F',
        (0, 0): 'C',
        (1, 0): 'G',
        (2, 0): 'D',
        (3, 0): 'A',
        (4, 0): 'E',
        (5, 0): 'B',
        (6, 0): 'F#',
        (7, 0): 'C#',
        (-7, 1): 'Abm',
        (-6, 1): 'Ebm',
        (-5, 1): 'Bbm',
        (-4, 1): 'Fm',
        (-3, 1): 'Cm',
        (-2, 1): 'Gm',
        (-1, 1): 'Dm',
        (0, 1): 'Am',
        (1, 1): 'Em',
        (2, 1): 'Bm',
        (3, 1): 'F#m',
        (4, 1): 'C#m',
        (5, 1): 'G#m',
        (6, 1): 'D#m',
        (7, 1): 'A#m',
    }
_key_signature_encode = reverse_table(_key_signature_decode)

_smpte_framerate_decode = {
        0: 24,
        1: 25,
        2: 29.97,
        3: 30,
    }
_smpte_framerate_encode = reverse_table(_smpte_framerate_decode)

def encode_string(string):
    return list(bytearray(string.encode(_charset)))

def decode_string(data):
    return bytearray(data).decode(_charset)

@contextmanager
def meta_charset(tmp_charset):
    global _charset
    old = _charset
    _charset = tmp_charset
    yield
    _charset = old

def check_int(value, low, high):
    if not isinstance(value, int):
        raise TypeError('attribute must be an integer')
    elif not low <= value <= high:
        raise ValueError('attribute must be in range {}..{}'.format(low, high))

def check_str(value):
    if PY2:
        if not isinstance(value, unicode) and not isinstance(value, str):
            raise TypeError('attribute must be unicode or string')
    else:
        if not isinstance(value, str):
            raise TypeError('attribute must a string')

class MetaSpec(object):
    def check(self, name, value):
        pass

class MetaSpec_sequence_number(MetaSpec):
    type_byte = 0x00
    attributes = ['number']
    defaults = [0]

    def decode(self, message, data):
        message.number = (data[0] << 8) | data[1]

    def encode(self, message):
        return [message.number >> 8, message.number & 0xff]<commit_msg>Improved check_str() a bit.<commit_after>"""
Meta messages for MIDI files.

Todo:
     - what if an unknown meta message is implemented and someone depends on
       the 'data' attribute?
     - is 'type_byte' a good name?
     - 'values' is not a good name for a dictionary.
     - type and value safety?
     - copy().
     - expose _key_signature_encode/decode?
"""
from __future__ import print_function, division
import sys
import math
from contextlib import contextmanager
from .messages import BaseMessage, check_time
from .types import signed, unsigned, encode_variable_int

PY2 = (sys.version_info.major == 2)

_charset = 'latin1'

def reverse_table(table):
    """Return value: key for dictionary."""
    return {value: key for (key, value) in table.items()}

_key_signature_decode = {
        (-7, 0): 'Cb',
        (-6, 0): 'Gb',
        (-5, 0): 'Db',
        (-4, 0): 'Ab',
        (-3, 0): 'Eb',
        (-2, 0): 'Bb',
        (-1, 0): 'F',
        (0, 0): 'C',
        (1, 0): 'G',
        (2, 0): 'D',
        (3, 0): 'A',
        (4, 0): 'E',
        (5, 0): 'B',
        (6, 0): 'F#',
        (7, 0): 'C#',
        (-7, 1): 'Abm',
        (-6, 1): 'Ebm',
        (-5, 1): 'Bbm',
        (-4, 1): 'Fm',
        (-3, 1): 'Cm',
        (-2, 1): 'Gm',
        (-1, 1): 'Dm',
        (0, 1): 'Am',
        (1, 1): 'Em',
        (2, 1): 'Bm',
        (3, 1): 'F#m',
        (4, 1): 'C#m',
        (5, 1): 'G#m',
        (6, 1): 'D#m',
        (7, 1): 'A#m',
    }
_key_signature_encode = reverse_table(_key_signature_decode)

_smpte_framerate_decode = {
        0: 24,
        1: 25,
        2: 29.97,
        3: 30,
    }
_smpte_framerate_encode = reverse_table(_smpte_framerate_decode)

def encode_string(string):
    return list(bytearray(string.encode(_charset)))

def decode_string(data):
    return bytearray(data).decode(_charset)

@contextmanager
def meta_charset(tmp_charset):
    global _charset
    old = _charset
    _charset = tmp_charset
    yield
    _charset = old

def check_int(value, low, high):
    if not isinstance(value, int):
        raise TypeError('attribute must be an integer')
    elif not low <= value <= high:
        raise ValueError('attribute must be in range {}..{}'.format(low, high))

if PY2:
    def check_str(value):
        if not isinstance(value, basestring):
            raise TypeError('attribute must be unicode or string')
else:
    def check_str(value):
        if not isinstance(value, str):
            raise TypeError('attribute must a string')

class MetaSpec(object):
    def check(self, name, value):
        pass

class MetaSpec_sequence_number(MetaSpec):
    type_byte = 0x00
    attributes = ['number']
    defaults = [0]

    def decode(self, message, data):
        message.number = (data[0] << 8) | data[1]

    def encode(self, message):
        return [message.number >> 8, message.number & 0xff]
{'fraction_non_alphanumeric': 0.15724258289703316, 'fraction_numerical': 0.030366492146596858, 'mean_word_length': 2.34559252772913, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5358469', 'n_tokens_mistral': 2079, 'n_tokens_neox': 1956, 'n_words': 596}