예제 #1
0
def visan(name=None):
    """
    Creates the grammar for a V-ISAN code.

    This is a variation on the ISAN (International Standard Audiovisual Number)

    :param name: name for the field
    :return: grammar for an ISRC field
    """

    if name is None:
        name = 'V-ISAN Field'

    version = basic.numeric(8)
    version = version.setName('Version').setResultsName('version')

    isan = basic.numeric(12)
    isan = isan.setName('ISAN').setResultsName('isan')

    episode = basic.numeric(4)
    episode = episode.setName('Episode').setResultsName('episode')

    check_digit = basic.numeric(1)
    check_digit = check_digit.setName('Check Digit') \
        .setResultsName('check_digit')

    field = pp.Group(version + isan + episode + check_digit)

    field.setParseAction(lambda v: _to_visan(v[0]))

    field.setName(name)

    return field.setResultsName('visan')
예제 #2
0
    def test_name_set_no_changes(self):
        """
        Tests that the field name does not change for creating a new one
        """
        field1 = basic.numeric(5, name='field1')
        field2 = basic.numeric(5, name='field2')

        self.assertEqual('field1', field1.name)
        self.assertEqual('field2', field2.name)
예제 #3
0
def ipi_base_number(name=None):
    """
    IPI Base Number field.

    An IPI Base Number code written on a field follows the Pattern
    C-NNNNNNNNN-M. This being:
    - C: header, a character.
    - N: numeric value.
    - M: control digit.

    So, for example, an IPI Base Number code field can contain I-000000229-7.

    :param name: name for the field
    :return: a parser for the IPI Base Number field
    """

    if name is None:
        name = 'IPI Base Number Field'

    # Separators are '-'
    separator = pp.Literal('-').suppress()
    separator = separator.setName('IPI Base Number Separator') \
        .setResultsName('separator')

    # Header is a digit in uppercase
    header = pp.Literal('I')
    header = header.setName('IPI Base Number Header').setResultsName('header')

    # ID code is composed of 9 numbers
    id_code = basic.numeric(9)
    id_code = id_code.setName('ID Code').setResultsName('id_code')
    id_code = id_code.setParseAction(lambda c: int(c[0]))

    # Check digit is a single number
    check_digit = pp.Regex('[0-9]')
    check_digit = check_digit.setName('Check Digit') \
        .setResultsName('check_digit')
    check_digit = check_digit.setParseAction(lambda c: int(c[0]))

    # Digit followed separator, 9 numbers, separator and 1 number
    field = pp.Group(header + separator + id_code + separator + check_digit)

    # Parse action
    field.setParseAction(lambda c: _to_ipibasecode(c[0]))

    # Name
    field.setName(name)

    field_num = basic.numeric(13)
    field_num.setName(name)

    field = field | field_num

    # White spaces are not removed
    field.leaveWhitespace()

    return field.setResultsName('ipi_base_n')
예제 #4
0
def iswc(name=None, compulsory=False):
    """
    ISWC field.

    A ISWC code written on a field follows the Pattern TNNNNNNNNNC. This being:
    - T: header, it is always T.
    - N: numeric value.
    - C: control digit.

    So, for example, an ISWC code field can contain T0345246801.

    :param name: name for the field
    :param compulsory: indicates if the empty string is disallowed
    :return: a parser for the ISWC field
    """

    if name is None:
        name = 'ISWC Field'

    # Header is always T
    header = pp.Literal('T').suppress()
    header = header.setName('ISWC Header').setResultsName('header')

    # ID code is composed of 9 numbers
    id_code = basic.numeric(9, compulsory=True)
    id_code = id_code.setName('ID Code').setResultsName('id_code')

    # Check digit is a single number
    check_digit = basic.numeric(1, compulsory=True)
    check_digit = check_digit.setName('Check Digit').setResultsName('check_digit')

    # T followed by 10 numbers
    field = pp.Group(header + id_code + check_digit)

    # Parse action
    field.setParseAction(lambda c: _to_iswccode(c[0]))

    # Name
    field.setName(name)

    if not compulsory:
        # If it is not compulsory then it can be set as empty
        empty = pp.Regex('[ ]{11}')
        empty.setParseAction(pp.replaceWith(None))
        empty.setName(name)

        field = empty | field
        # Name
        field.setName(name)

    # White spaces are not removed
    field.leaveWhitespace()

    return field.setResultsName('iswc')
예제 #5
0
    def test_name_default_compulsory(self):
        """
        Tests that the default field name is correct for optional fields, for compulsory fields.
        """
        field = basic.numeric(5, compulsory=True)

        self.assertEqual('Numeric Field', field.name)
예제 #6
0
def audio_visual_key(name=None):
    """
    Creates the grammar for an Audio Visual Key code.

    This is a variation on the ISAN (International Standard Audiovisual Number)

    :param name: name for the field
    :return: grammar for an ISRC field
    """

    if name is None:
        name = 'AVI Field'

    society_code = basic.numeric(3)
    society_code = society_code.setName('Society Code') \
        .setResultsName('society_code')

    av_number = basic.alphanum(15)
    field_empty = pp.Regex('[ ]{15}')
    field_empty.setParseAction(pp.replaceWith(''))
    av_number = av_number | field_empty
    av_number = av_number.setName('Audio-Visual Number') \
        .setResultsName('av_number')

    field = pp.Group(society_code + av_number)

    field.setParseAction(lambda v: _to_avi(v[0]))

    field = field.setName(name)

    return field.setResultsName('audio_visual_key')
예제 #7
0
def ipi_name_number(name=None, compulsory=False):
    """
    IPI Name Number field.

    An IPI Name Number is composed of eleven digits.

    So, for example, an IPI Name Number code field can contain 00014107338.

    :param name: name for the field
    :param compulsory: indicates if the empty string is disallowed
    :return: a parser for the IPI Name Number field
    """

    if name is None:
        name = 'IPI Name Number Field'

    field = basic.numeric(11, compulsory=compulsory)

    if not compulsory:
        # If it is not compulsory then it can be set as empty
        empty = pp.Regex('[ ]{11}')
        empty.setParseAction(pp.replaceWith(None))
        empty.setName(name)

        field = empty | field
        # Name
        field.setName(name)

    field.setName(name)

    return field.setResultsName('ipi_name_n')
예제 #8
0
    def test_name_default(self):
        """
        Tests that the default field name is correct for optional fields.
        """
        field = basic.numeric(5)

        self.assertEqual('Numeric Field', field.name)
예제 #9
0
def ipi_base_number(name=None):
    """
    IPI Base Number field.

    An IPI Base Number code written on a field follows the Pattern
    C-NNNNNNNNN-M. This being:
    - C: header, a character.
    - N: numeric value.
    - M: control digit.

    So, for example, an IPI Base Number code field can contain I-000000229-7.

    :param name: name for the field
    :return: a parser for the IPI Base Number field
    """

    if name is None:
        name = 'IPI Base Number Field'

    field = pp.Regex('I-[0-9]{9}-[0-9]')

    # Name
    field.setName(name)

    field_num = basic.numeric(13)
    field_num.setName(name)

    field = field | field_num

    # White spaces are not removed
    field.leaveWhitespace()

    return field.setResultsName('ipi_base_n')
예제 #10
0
def audio_visual_key(name=None):
    """
    Creates the grammar for an Audio Visual Key code.

    This is a variation on the ISAN (International Standard Audiovisual Number)

    :param name: name for the field
    :return: grammar for an ISRC field
    """

    if name is None:
        name = 'AVI Field'

    society_code = basic.numeric(3)
    society_code = society_code.setName('Society Code') \
        .setResultsName('society_code')

    av_number = basic.alphanum(15)
    field_empty = pp.Regex('[ ]{15}')
    field_empty.setParseAction(pp.replaceWith(''))
    av_number = av_number | field_empty
    av_number = av_number.setName('Audio-Visual Number') \
        .setResultsName('av_number')

    field = pp.Group(society_code + av_number)

    field.setParseAction(lambda v: _to_avi(v[0]))

    field = field.setName(name)

    return field.setResultsName('audio_visual_key')
예제 #11
0
def ipi_base_number(name=None):
    """
    IPI Base Number field.

    An IPI Base Number code written on a field follows the Pattern
    C-NNNNNNNNN-M. This being:
    - C: header, a character.
    - N: numeric value.
    - M: control digit.

    So, for example, an IPI Base Number code field can contain I-000000229-7.

    :param name: name for the field
    :return: a parser for the IPI Base Number field
    """

    if name is None:
        name = 'IPI Base Number Field'

    field = pp.Regex('I-[0-9]{9}-[0-9]')

    # Name
    field.setName(name)

    field_num = basic.numeric(13)
    field_num.setName(name)

    field = field | field_num

    # White spaces are not removed
    field.leaveWhitespace()

    return field.setResultsName('ipi_base_n')
예제 #12
0
    def test_name_set(self):
        """
        Tests that the given field name is set correctly for optional fields.
        """
        name = "Field Name"
        field = basic.numeric(5, name=name)

        self.assertEqual(name, field.name)
예제 #13
0
def iswc(name=None):
    """
    ISWC field.

    A ISWC code written on a field follows the Pattern TNNNNNNNNNC.
    This being:
    - T: header, it is always T.
    - N: numeric value.
    - C: control digit.

    So, for example, an ISWC code field can contain T0345246801.

    :param name: name for the field
    :return: a parser for the ISWC field
    """

    if name is None:
        name = 'ISWC Field'

    # Header is always T
    header = pp.Literal('T').suppress()
    header = header.setName('ISWC Header').setResultsName('header')

    # ID code is composed of 9 numbers
    id_code = basic.numeric(9)
    id_code = id_code.setName('ID Code').setResultsName('id_code')

    # Check digit is a single number
    check_digit = basic.numeric(1)
    check_digit = check_digit.setName('Check Digit') \
        .setResultsName('check_digit')

    # T followed by 10 numbers
    field = pp.Group(header + id_code + check_digit)

    # Parse action
    field.setParseAction(lambda c: _to_iswccode(c[0]))

    # Name
    field.setName(name)

    # White spaces are not removed
    field.leaveWhitespace()

    return field.setResultsName('iswc')
예제 #14
0
def visan(name=None, compulsory=False):
    """
    Creates the grammar for a V-ISAN code.

    This is a variation on the ISAN (International Standard Audiovisual Number)

    :param name: name for the field
    :param compulsory: indicates if the empty string is disallowed
    :return: grammar for an ISRC field
    """

    if name is None:
        name = 'V-ISAN Field'

    version = basic.numeric(8)
    version = version.setName('Version').setResultsName('version')

    isan = basic.numeric(12)
    isan = isan.setName('ISAN').setResultsName('isan')

    episode = basic.numeric(4)
    episode = episode.setName('Episode').setResultsName('episode')

    check_digit = basic.numeric(1)
    check_digit = check_digit.setName('Check Digit').setResultsName('check_digit')

    field = pp.Group(version + isan + episode + check_digit)

    field.setParseAction(lambda v: _to_visan(v[0]))

    field.setName(name)

    if not compulsory:
        # If it is not compulsory then it can be set as empty
        empty = pp.Regex('[ ]{25}')
        empty.setParseAction(pp.replaceWith(None))
        empty.setName(name)

        field = empty | field

        # Name
        field.setName(name)

    return field.setResultsName('visan')
예제 #15
0
def record_seq_n(compulsory=False):
    """
    Creates a record sequence field.

    This represents the position of a record in a transaction.

    :param compulsory: indicates if the empty string is disallowed
    :return: grammar for the record sequence number field
    """
    field = basic.numeric(_config.field_size('record_prefix', 'record_sequence_n'), compulsory=compulsory)
    field = field.setName('Record Sequence Number')

    return field.setResultsName('record_sequence_n')
예제 #16
0
def transaction_count(compulsory=False):
    """
    Creates a transaction count field.

    This field is used on trailer records to indicate the total number of transactions previous to this record.

    :param compulsory: indicates if the empty string is disallowed
    :return: grammar for the transaction count field
    """
    field = basic.numeric(
        _config.field_size('trailer_record', 'transaction_count'), compulsory=compulsory)
    field = field.setName('Transaction Count')

    return field.setResultsName('transaction_count')
예제 #17
0
def ean_13(name=None):
    """
    Creates the grammar for an EAN 13 code.

    These are the codes on thirteen digits barcodes.

    :param name: name for the field
    :return: grammar for an EAN 13 field
    """

    if name is None:
        name = 'EAN 13 Field'

    field = basic.numeric(13)

    field = field.setName(name)

    return field.setResultsName('ean_13')
예제 #18
0
def ean_13(name=None):
    """
    Creates the grammar for an EAN 13 code.

    These are the codes on thirteen digits barcodes.

    :param name: name for the field
    :return: grammar for an EAN 13 field
    """

    if name is None:
        name = 'EAN 13 Field'

    field = basic.numeric(13)

    field = field.setName(name)

    return field.setResultsName('ean_13')
예제 #19
0
def ean_13(name=None, compulsory=False):
    """
    Creates the grammar for an EAN 13 code.

    These are the codes on thirteen digits barcodes.

    :param name: name for the field
    :param compulsory: indicates if the empty string is disallowed
    :return: grammar for an EAN 13 field
    """

    if name is None:
        name = 'Shares Field'

    field = basic.numeric(13, compulsory=compulsory)

    field = field.setName(name)

    return field.setResultsName('ean_13')
예제 #20
0
def year(columns, name=None):
    """
    Creates the grammar for a field containing a year.

    :param columns: the number of columns for the year
    :param name: the name of the field
    :return:
    """

    if columns < 0:
        # Can't have negative size
        raise BaseException()

    field = numeric(columns, name)

    # Parse action
    field.addParseAction(_to_year)

    return field
예제 #21
0
def year(columns, name=None):
    """
    Creates the grammar for a field containing a year.

    :param columns: the number of columns for the year
    :param name: the name of the field
    :return:
    """

    if columns < 0:
        # Can't have negative size
        raise BaseException()

    field = numeric(columns, name)

    # Parse action
    field.addParseAction(_to_year)

    return field
예제 #22
0
def ipi_name_number(name=None):
    """
    IPI Name Number field.

    An IPI Name Number is composed of eleven digits.

    So, for example, an IPI Name Number code field can contain 00014107338.

    :param name: name for the field
    :return: a parser for the IPI Name Number field
    """

    if name is None:
        name = 'IPI Name Number Field'

    field = basic.numeric(11)

    field.setName(name)

    return field.setResultsName('ipi_name_n')
예제 #23
0
def ipi_name_number(name=None):
    """
    IPI Name Number field.

    An IPI Name Number is composed of eleven digits.

    So, for example, an IPI Name Number code field can contain 00014107338.

    :param name: name for the field
    :return: a parser for the IPI Name Number field
    """

    if name is None:
        name = 'IPI Name Number Field'

    field = basic.numeric(11)

    field.setName(name)

    return field.setResultsName('ipi_name_n')
예제 #24
0
def audio_visual_key(name=None, compulsory=False):
    """
    Creates the grammar for an Audio Visual Key code.

    This is a variation on the ISAN (International Standard Audiovisual Number)

    :param name: name for the field
    :param compulsory: indicates if the empty string is disallowed
    :return: grammar for an ISRC field
    """

    if name is None:
        name = 'AVI Field'

    society_code = basic.numeric(3)
    society_code = society_code.setName('Society Code').setResultsName('society_code')

    av_number = basic.alphanum(15)
    av_number = av_number.setName('Audio-Visual Number').setResultsName('av_number')

    field = pp.Group(society_code + av_number)

    field.setParseAction(lambda v: _to_avi(v[0]))

    field = field.setName(name)

    if not compulsory:
        # If it is not compulsory then it can be set as empty
        empty = pp.Regex('[ ]{18}')
        empty.setParseAction(pp.replaceWith(None))
        empty.setName(name)

        field = empty | field
        # Name
        field.setName(name)

    return field.setResultsName('audio_visual_key')
예제 #25
0
 def get_field(self, name=None, columns=None, values=None):
     return basic.numeric(columns, name)
예제 #26
0

# Writer Last Name
writer_last_name = basic.alphanum(_config.field_size('writer', 'last_name'))
writer_last_name = writer_last_name.setName('Writer Last Name').setResultsName('writer_last_name')

# Writer First Name
writer_first_name = basic.alphanum(_config.field_size('writer', 'first_name'))
writer_first_name = writer_first_name.setName('Writer First Name').setResultsName('writer_first_name')

# Writer Unknown Indicator
unknown = basic.flag()
unknown = unknown.setName('Writer Unknown Indicator').setResultsName('writer_unknown')

# Reversionary Indicator
reversionary = basic.flag()
reversionary = reversionary.setName('Reversionary Indicator').setResultsName('reversionary')

# First Recording Refusal Indicator
first_recording_refusal = basic.flag()
first_recording_refusal = first_recording_refusal.setName('First Recording Refusal Indicator').setResultsName(
    'first_recording_refusal')

# Work For Hire Indicator
for_hire = basic.flag()
for_hire = for_hire.setName('Work For Hire Indicator').setResultsName('work_for_hire')

# Personal Number
personal_number = basic.numeric(_config.field_size('writer', 'personal_number'))
personal_number = personal_number.setName('Personal Number').setResultsName('personal_number')
예제 #27
0
# Acquires data sources
_config = CWRConfiguration()

"""
Group fields.

These fields are:
- Record Type. One for the header and another for the trailer, both a pre-defined string.
- Group ID. Numeric.
- Version Number. Must be a predefined string.
- Batch Request ID. Numeric.
"""

# Group ID
group_id = basic.numeric(_config.field_size('group_header', 'group_id'), compulsory=True)
group_id = group_id.setName('Group ID').setResultsName('group_id')

# Version Number
version_number = pp.Literal(_config.field_value('group_header', 'version_number'))
version_number = version_number.setName('Version Number').setResultsName('version_number')

# Batch Request ID
batch_request_id = basic.numeric(_config.field_size('group_header', 'batch_request_id'))
batch_request_id = batch_request_id.setName('Batch Request ID').setResultsName('batch_request_id')

"""
Unused fields.

These are fields which exist in the standard but are unused and ignored.
예제 #28
0
from cwr.grammar.field import basic


"""
CWR Message record fields grammar.
"""

__author__ = 'Bernardo Martínez Garrido'
__license__ = 'MIT'
__status__ = 'Development'

# Acquires data sources
_config = CWRConfiguration()

# Publisher Sequence #
publisher_sequence_n = basic.numeric(_config.field_size('publisher', 'sequence_n'), compulsory=True)
publisher_sequence_n = publisher_sequence_n.setName('Publisher Sequence #').setResultsName('publisher_sequence_n')

# Publisher name
name = basic.alphanum(_config.field_size('publisher', 'name'))
name = name.setName('Publisher name').setResultsName('name')

# Publisher Unknown Indicator
unknown = basic.flag()
unknown = unknown.setName('Publisher Unknown Indicator').setResultsName('publisher_unknown')

# Tax ID #
tax_id = basic.numeric(_config.field_size('publisher', 'tax_id'))
tax_id = tax_id.setName('Tax ID #').setResultsName('tax_id')

# Submitter Agreement Number
예제 #29
0
파일: adapter.py 프로젝트: weso/CWR-DataApi
 def get_field(self, name=None, columns=None, values=None):
     return basic.numeric(columns, name)
예제 #30
0
Transmission fields.

These fields are:
- Record Type. One for the header and another for the trailer, both a pre-defined string.
- Sender Type. Alphanumeric.
- Sender ID. Alphanumeric.
- Sender Name. Alphanumeric.
- EDI Version. Must be a predefined string.
- Creation Date. Date.
- Creation Time. Time.
- Transmission Date. Date.
- Character Set. Alphanumeric.
"""

# Sender ID
sender_id = basic.numeric(_config.field_size('transmission_header', 'sender_id'), compulsory=True)
sender_id = sender_id.setName('Sender ID').setResultsName('sender_id')

# Sender Name
sender_name = basic.alphanum(_config.field_size('transmission_header', 'sender_name'), compulsory=True)
sender_name = sender_name.setName('Sender Name').setResultsName('sender_name')

# EDI Version
edi_version = pp.Literal(_config.field_value('transmission_header', 'edi_version'))
edi_version = edi_version.setName('EDI Version').setResultsName('edi_version')

# Creation Date
creation_date = basic.date(compulsory=True)
creation_date = creation_date.setName('Creation Date').setResultsName('creation_date')

# Creation Time
예제 #31
0
- Sequence Number (old and new). 2 or 4 alphanumeric characters.
- Year. 2 numeric characters.
- Sender. 2 or 3 alphanumeric characters.
- Receiver. 2 or 3 alphanumeric characters.
- Version Number. 2 digits float (one value for integer, one for decimal).

Each of these fields is parsed into a value as follows:
- Sequence Number (old and new). Integer.
- Year. Four digits integer (year in the current century).
- Sender. String.
- Receiver. String.
- Version Number. Float.
"""

# Sequence Number old
sequence_old = basic.numeric(2)
sequence_old = sequence_old.setName('Sequence Number').setResultsName('sequence_n')

# Sequence Number new
sequence_new = basic.numeric(4)
sequence_new = sequence_new.setName('Sequence Number').setResultsName('sequence_n')

# Year
year = basic.numeric(2)
year.setParseAction(lambda y: _to_year(y))
year = year.setName('Year').setResultsName('year')


def _to_year(parsed):
    """
    Transforms the parsed two digits integer into a valid year value.
예제 #32
0
# -*- coding: utf-8 -*-

from data.accessor import CWRConfiguration
from cwr.grammar.field import special, basic


"""
CWR Publisher Territory of Control record fields grammar.
"""

__author__ = 'Bernardo Martínez Garrido'
__license__ = 'MIT'
__status__ = 'Development'

# Acquires data sources
_config = CWRConfiguration()

# Constant
constant = special.blank(_config.field_size('publisher_territory', 'constant'))

# Shares Change
shares_change = basic.boolean()
shares_change = shares_change.setName('Shares Change').setResultsName('shares_change')

# Sequence #
sequence_n = basic.numeric(_config.field_size('publisher_territory', 'sequence_n'))
sequence_n = sequence_n.setName('Sequence #').setResultsName('sequence_n')
예제 #33
0
 def setUp(self):
     self.num = basic.numeric(5)
예제 #34
0
from data.accessor import CWRConfiguration
from cwr.grammar.field import table, record, basic


"""
CWR Message record fields grammar.
"""

__author__ = 'Bernardo Martínez Garrido'
__license__ = 'MIT'
__status__ = 'Development'

# Acquires data sources
_config = CWRConfiguration()

# Validation Number
validation = basic.numeric(_config.field_size('message', 'validation'))
validation = validation.setName('Validation Number').setResultsName('validation')

# Message Record Type
record_message = table.record_types()
record_message = record_message.setName('Message Record Type').setResultsName('message_record_type')

# Message Text
message_text = basic.alphanum(_config.field_size('message', 'text'))
message_text = message_text.setName('Message Text').setResultsName('message_text')

# Original Record Sequence #
sequence_n = record.record_seq_n(compulsory=True)
sequence_n = sequence_n.setName('Original Record Sequence #').setResultsName('sequence_n')
예제 #35
0
_config = CWRConfiguration()

# Creation Date
creation_date = basic.date(compulsory=True)
creation_date = creation_date.setName('Creation Date').setResultsName('creation_date')

# Creation Time
creation_time = basic.time(compulsory=True)
creation_time = creation_time.setName('Creation Time').setResultsName('creation_time')

# Original Group ID
original_group_id = group.group_id
original_group_id = original_group_id.setName('Original Group ID')

# Original Transaction Sequence #
original_transaction_sequence_n = basic.numeric(_config.field_size('acknowledgement', 'transaction_n'), compulsory=True)
original_transaction_sequence_n = original_transaction_sequence_n.setName(
    'Original Transaction Sequence #').setResultsName(
    'original_transaction_sequence_n')

# Creation Title
creation_title = basic.alphanum(_config.field_size('acknowledgement', 'title'))
creation_title = creation_title.setName('Creation Title').setResultsName('creation_title')

# Submitter Creation #
submitter_creation_n = basic.alphanum(_config.field_size('acknowledgement', 'submitter_id'))
submitter_creation_n = submitter_creation_n.setName('Submitter Creation #').setResultsName('submitter_creation_n')

# Recipient Creation #
recipient_creation_n = basic.alphanum(_config.field_size('acknowledgement', 'recipient_id'))
recipient_creation_n = recipient_creation_n.setName('Recipient Creation #').setResultsName('recipient_creation_n')
예제 #36
0
recorded = recorded.setName('Recorded Indicator').setResultsName('recorded_indicator')

# Contact Name
contact_name = basic.alphanum(_config.field_size('work', 'contact_name'))
contact_name = contact_name.setName('Contact Name').setResultsName('contact_name')

# Contact ID
contact_id = basic.alphanum(_config.field_size('work', 'contact_id'))
contact_id = contact_id.setName('Contact ID').setResultsName('contact_id')

# Grand Rights Indicator
gr_indicator = basic.boolean()
gr_indicator = gr_indicator.setName('Grand Rights Indicator').setResultsName('grand_rights_indicator')

# Composite Component Count
composite_count = basic.numeric(_config.field_size('work', 'composite_count'))
composite_count = composite_count.setName('Composite Component Count').setResultsName('composite_component_count')

# Date of Publication of Printed Edition
date_publication_printed_edition = basic.date()
date_publication_printed_edition = date_publication_printed_edition.setName(
    'Date of Publication of Printed Edition').setResultsName('date_publication_printed_edition')

# Exceptional Clause
exceptional_clause = basic.flag()
exceptional_clause = exceptional_clause.setName('Exceptional Clause').setResultsName('exceptional_clause')

# Opus Number
opus_number = basic.alphanum(_config.field_size('work', 'opus_number'))
opus_number = opus_number.setName('Opus Number').setResultsName('opus_number')