Skip to content

Commit

Permalink
Merge pull request #97 from weso/develop
Browse files Browse the repository at this point in the history
All the rules are now created through factories.
  • Loading branch information
Bernardo-MG committed Apr 16, 2015
2 parents 71c58ae + ca1f613 commit c7f9baf
Show file tree
Hide file tree
Showing 99 changed files with 4,691 additions and 1,993 deletions.
7 changes: 0 additions & 7 deletions MANIFEST.in

This file was deleted.

20 changes: 18 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ endif

help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " sdist to make the standard distribution"
@echo " bdist to make the binary distribution"
@echo " sdist to make the standard distribution"
@echo " bdist to make the binary distribution"
@echo " pypi_reg to register on pypi"
@echo " pypitest_reg to register on testpypi"
@echo " pypi to upload to pypi"
@echo " pypitest to upload to testpypi"

clean:
rm -r $(DISTDIR)
Expand All @@ -27,3 +31,15 @@ sdist:

bdist:
$(PYTHON) setup.py bdist

pypi_reg:
$(PYTHON) setup.py register -r pypi

pypitest_reg:
$(PYTHON) setup.py register -r testpypi

pypi:
$(PYTHON) setup.py sdist upload -r pypi

pypitest:
$(PYTHON) setup.py sdist upload -r testpypi
53 changes: 20 additions & 33 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CWR Data Model API
===================
==================

This projects offers a domain model for the CISAC CWR standard v2.1 to be
used on Python applications.
Expand All @@ -16,6 +16,11 @@ The library includes a data model for representing the contents of a CWR
file, and parsers to create that model from a file, and to decode and
encode JSON messages with the data model.

Documentation
-------------

The current version is under development. No public documentation is still offered.

Status
------

Expand All @@ -26,59 +31,41 @@ Issues management

Issues are managed at the GitHub `project issues page`_.

Documentation
-------------

Documentation for the project can be found at the GitHub `project
wiki`_.

Building the code
-----------------

The application has been coded in Python, and tested for various
versions of the Python 2 and 3 interpreter.

Dependencies are indicated on requirements.txt.
The application has been coded in Python, without using any particular framework.

Prerequisites
~~~~~~~~~~~~~

Requires Python, and has been tested on the following interpreters:
The project has been tested in the following versions of the interpreter:

- Python 2 (2.6, 2.7)
- Python 3 (3.2, 3.3, 3.4)
- Pypy (for Python 2 and 3)
- Python 2.6
- Python 2.7
- Python 3.2
- Python 3.3
- Python 3.4
- Pypy
- Pypy 3

The dependencies can be acquired using the list on requirements.txt,
with the command:
Al other dependencies are indicated on requirements.txt, which can be installed with the command:

``pip install -r requirements.txt``

Getting the code
~~~~~~~~~~~~~~~~

The code can be found at the GitHub `project page`_.

To acquire it through Git use the following clone URI:

``git clone https://github.com/weso/CWR-DataApi.git``

Continuous integration
----------------------

The continuous integration information can be found at the `project CI
page`_ based on Travis CI.
The code can be found at the `GitHub project page`_.

License
-------

The project is released under the `MIT License`_.
The project has been released under the `MIT License`_.

.. _CISAC: http://www.cisac.org/
.. _BMAT: http://www.bmat.com/
.. _WESO: http://www.weso.es/
.. _project issues page: https://travis-ci.org/weso/CWR-DataApi/issues
.. _project wiki: https://github.com/weso/CWR-DataApi/wiki
.. _project page: https://github.com/weso/CWR-DataApi
.. _project CI page: https://travis-ci.org/weso/CWR-DataApi
.. _project issues page: https://github.com/weso/CWR-DataApi/issues
.. _GitHub project page: https://github.com/weso/CWR-DataApi
.. _MIT License: http://www.opensource.org/licenses/mit-license.php
2 changes: 1 addition & 1 deletion cwr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
:license: MIT, see LICENSE for more details.
"""

__version__ = '0.0.6'
__version__ = '0.0.7'
__license__ = 'MIT'
30 changes: 28 additions & 2 deletions cwr/grammar/factory/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import pyparsing as pp

from cwr.grammar.field import basic, special, table
from cwr.grammar.field import basic, special, table, filename

"""
CWR fields grammar adapters.
Expand Down Expand Up @@ -285,4 +285,30 @@ def __init__(self):
super(CharSetAdapter, self).__init__()

def get_field(self, name=None, columns=None, values=None):
return table.char_code(columns=columns, name=name)
return table.char_code(columns=columns, name=name)


class VariableAlphanumAdapter(FieldAdapter):
def __init__(self):
super(VariableAlphanumAdapter, self).__init__()

def get_field(self, name=None, columns=None, values=None):
if values is not None and len(values) > 0:
min = int(values[0])
else:
min = columns

return filename.alphanum_variable(min=min, max=columns, name=name)


class NumericFloatAdapter(FieldAdapter):
def __init__(self):
super(NumericFloatAdapter, self).__init__()

def get_field(self, name=None, columns=None, values=None):
if values is not None and len(values) > 0:
nums_int = int(values[0])
else:
nums_int = columns

return basic.numeric_float(columns=columns, nums_int=nums_int, name=name)
140 changes: 70 additions & 70 deletions cwr/grammar/factory/record.py → cwr/grammar/factory/decorator.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# -*- coding: utf-8 -*-

from abc import ABCMeta
import logging
from abc import ABCMeta, abstractmethod

import pyparsing as pp

from cwr.grammar.field import record as field_record
from cwr.parser.dictionary import *
from cwr.grammar.factory.rule import RuleDecorator


"""
Expand All @@ -22,43 +22,29 @@
"""


class PrefixBuilder(object):
def __init__(self, config):
self._config = config
class RecordFactory(object):
__metaclass__ = ABCMeta

def get_prefix(self, id):
return field_record.record_type(self._config[id])
def __init__(self):
pass

def get_transaction_prefix(self, id):
return field_record.record_prefix(self._config[id])
@abstractmethod
def get_record(self, id):
raise NotImplementedError("The get_record method is not implemented")


class RecordFactory(object):
"""
Factory for acquiring record rules.
"""
__metaclass__ = ABCMeta

class RecordRuleDecorator(RuleDecorator):
_lineStart = pp.lineStart.suppress()
_lineStart.setName("Start of line")

_lineEnd = pp.lineEnd.suppress()
_lineEnd.setName("End of line")

def __init__(self, record_configs, prefixer, field_factory):
# records already created
self._records = {}
# Logger
self._logger = logging.getLogger(__name__)
# Configuration for creating the record
self._record_configs = record_configs
# Fields factory
self._field_factory = field_factory
# Prefix builder
self._prefixer = prefixer
# Dictionary decoders
self._decoders = {}
def __init__(self, factory):
super(RecordRuleDecorator, self).__init__()
self._factory = factory

self._decoders = {}
# TODO: Do this somewhere else
self._decoders['acknowledgement'] = AcknowledgementDictionaryDecoder()
self._decoders['message'] = MessageDictionaryDecoder()
Expand All @@ -67,7 +53,7 @@ def __init__(self, record_configs, prefixer, field_factory):
self._decoders['additional_related_information'] = AdditionalRelatedInformationDictionaryDecoder()
self._decoders['group_header'] = GroupHeaderDictionaryDecoder()
self._decoders['group_trailer'] = GroupTrailerDictionaryDecoder()
self._decoders['interested_party_agreement'] = InterestedPartyForAgreementDecoder()
self._decoders['interested_party_agreement'] = InterestedPartyForAgreementDictionaryDecoder()
self._decoders['nra_agreement_party'] = NonRomanAlphabetAgreementPartyDictionaryDecoder()
self._decoders['nra_publisher_name'] = NonRomanAlphabetPublisherNameDictionaryDecoder()
self._decoders['nra_writer_name'] = NonRomanAlphabetWriterNameDictionaryDecoder()
Expand All @@ -76,7 +62,7 @@ def __init__(self, record_configs, prefixer, field_factory):
self._decoders['nra_work'] = NonRomanAlphabetWorkDictionaryDecoder()
self._decoders['nra_other_writer'] = NonRomanAlphabetOtherWriterDictionaryDecoder()
self._decoders['publisher'] = PublisherRecordDictionaryDecoder()
self._decoders['publisher_territory'] = IPTerritoryOfControlDecoder()
self._decoders['publisher_territory'] = IPTerritoryOfControlDictionaryDecoder()
self._decoders['transmission_header'] = TransmissionHeaderDictionaryDecoder()
self._decoders['transmission_trailer'] = TransmissionTrailerDictionaryDecoder()
self._decoders['work'] = WorkDictionaryDecoder()
Expand All @@ -87,59 +73,73 @@ def __init__(self, record_configs, prefixer, field_factory):
self._decoders['performing_artist'] = PerformingArtistDictionaryDecoder()
self._decoders['recording_detail'] = RecordingDetailDictionaryDecoder()
self._decoders['work_origin'] = WorkOriginDictionaryDecoder()
self._decoders['instrumentation_summary'] = InstrumentationSummaryDecoder()
self._decoders['instrumentation_detail'] = InstrumentationDetailDecoder()
self._decoders['instrumentation_summary'] = InstrumentationSummaryDictionaryDecoder()
self._decoders['instrumentation_detail'] = InstrumentationDetailDictionaryDecoder()
self._decoders['component'] = ComponentDictionaryDecoder()
self._decoders['writer'] = WriterRecordDictionaryDecoder()
self._decoders['writer_publisher'] = PublisherForWriterDecoder()
self._decoders['writer_territory'] = IPTerritoryOfControlDecoder()
self._decoders['writer_publisher'] = PublisherForWriterDictionaryDecoder()
self._decoders['writer_territory'] = IPTerritoryOfControlDictionaryDecoder()
self._decoders['filename_new'] = FileTagDictionaryDecoder()
self._decoders['filename_old'] = FileTagDictionaryDecoder()

def decorate(self, rule, data):
sequence = []

def get_transaction_record(self, id):
record = self._lineStart + \
self._prefixer.get_transaction_prefix(id) + \
self._build_record(id) + \
self._lineEnd
id = data['id']

sequence.append(self._lineStart)

prefix = self._get_prefix(data)

if prefix is not None:
sequence.append(prefix)

sequence.append(rule)

sequence.append(self._lineEnd)

record = pp.And(sequence)

if id in self._decoders:
decoder = self._decoders[id]
record.setParseAction(lambda p: decoder.decode(p))

return record.setResultsName(id)

def get_record(self, id):
record = self._lineStart + \
self._prefixer.get_prefix(id) + \
self._build_record(id) + \
self._lineEnd
def _get_prefix(self, config):
rule_type = config['rule_type']

if rule_type == 'transaction':
header = field_record.record_prefix(config['record_type'], self._factory)
elif rule_type == 'record':
header = field_record.record_type(config['record_type'])
else:
header = None

return header


class GroupRuleDecorator(RuleDecorator):
_lineStart = pp.lineStart.suppress()
_lineStart.setName("Start of line")

_lineEnd = pp.lineEnd.suppress()
_lineEnd.setName("End of line")

def __init__(self):
super(GroupRuleDecorator, self).__init__()

self._decoders = {}
# TODO: Do this somewhere else
self._decoders['transmission'] = TransmissionDictionaryDecoder()

def decorate(self, rule, data):
id = data['id']

record = rule

if id in self._decoders:
decoder = self._decoders[id]
record.setParseAction(lambda p: decoder.decode(p))

return record.setResultsName(id)

def _build_record(self, id):
field_config = self._record_configs[id]

fields = []
for config in field_config:
if 'compulsory' in config:
compulsory = config['compulsory']
else:
compulsory = False

fields.append(self._field_factory.get_field(config['name'], compulsory=compulsory))

if len(fields) > 0:
first = True
record = None
for field in fields:
if first:
record = field
first = False
else:
record += field
else:
record = None

return record

0 comments on commit c7f9baf

Please sign in to comment.