Документ взят из кэша поисковой машины. Адрес оригинального документа : http://kodomo.fbb.msu.ru/hg/allpy/rev/077e5e18a600
Дата изменения: Unknown
Дата индексирования: Tue Oct 2 01:21:43 2012
Кодировка:
allpy: 077e5e18a600

allpy

changeset 852:077e5e18a600

Added allpy.markups.MarkupIOMixin to simplify new saveable markups creation. Switched existing saveable makrups to using it. Tested. (closes #82)
author Daniil Alexeyevsky <dendik@kodomo.fbb.msu.ru>
date Wed, 20 Jul 2011 20:44:59 +0400
parents 2b74596f3c64
children 6cc007e68af6
files allpy/markups.py
diffstat 1 files changed, 61 insertions(+), 32 deletions(-) [+]
line diff
     1.1 --- a/allpy/markups.py	Wed Jul 20 19:17:03 2011 +0400
     1.2 +++ b/allpy/markups.py	Wed Jul 20 20:44:59 2011 +0400
     1.3 @@ -22,23 +22,61 @@
     1.4              assert fullname not in by_name, "Samenamed markup already exists!"
     1.5              by_name[fullname] = markup_class
     1.6  
     1.7 -class IntMarkupMixin(base.Markup):
     1.8 +class MarkupIOMixin(base.Markup):
     1.9 +    """Standard helper mixin for creating saveable markups."""
    1.10 +
    1.11 +    separator = ','
    1.12 +    """Separator to use when saving/loading markup."""
    1.13 +
    1.14 +    io_class = None
    1.15 +    """MUST be overloaded when subclassing. io_class in file."""
    1.16 +
    1.17 +    @staticmethod
    1.18 +    def parse_item(key, value):
    1.19 +        """Deserialize one item of markup. Overload when subclassing."""
    1.20 +        return value
    1.21 +
    1.22 +    @staticmethod
    1.23 +    def repr_item(key, value):
    1.24 +        """Serialize one item of markup. Overload when subclassing."""
    1.25 +        return str(value)
    1.26  
    1.27      @classmethod
    1.28      def from_record(cls, container, record, name=None):
    1.29 -        assert record['io_class'] == 'IntMarkup'
    1.30 +        """Read markup from semi-parsed record from 'markup' file."""
    1.31 +        assert record['io_class'] == cls.io_class
    1.32 +        separator = record.get('separator', cls.separator)
    1.33 +        values = record['markup'].split(separator)
    1.34          result = container.add_markup(name, markup_class=cls)
    1.35 -        separator = record.get('separator', ',')
    1.36 -        values = record['markup'].split(separator)
    1.37          assert len(values) == len(result.sorted_keys())
    1.38          for key, value in zip(result.sorted_keys(), values):
    1.39              if value:
    1.40 -                result[key] = int(value)
    1.41 +                result[key] = cls.parse_item(key, value)
    1.42          return result
    1.43  
    1.44      def to_record(self):
    1.45 -        values = self.sorted_values(default='', map=str)
    1.46 -        return {'markup': ','.join(values), 'io_class': 'IntMarkup'}
    1.47 +        """Write markup to semi-serialized record for 'markup' file."""
    1.48 +        values = []
    1.49 +        for key in self.sorted_keys():
    1.50 +            if key in self:
    1.51 +                values.append(self.repr_item(key, self[key]))
    1.52 +            else:
    1.53 +                values.append('')
    1.54 +        markup = self.separator.join(values)
    1.55 +        return {
    1.56 +            'markup': markup,
    1.57 +            'io_class': self.io_class,
    1.58 +            'separator': self.separator,
    1.59 +        }
    1.60 +
    1.61 +class IntMarkupMixin(MarkupIOMixin):
    1.62 +    """Markup that has integer values."""
    1.63 +
    1.64 +    io_class = 'IntMarkup'
    1.65 +
    1.66 +    @staticmethod
    1.67 +    def parse_item(key, value):
    1.68 +        return int(value)
    1.69  
    1.70  class SequenceNumberMarkup(base.SequenceMarkup):
    1.71  
    1.72 @@ -72,9 +110,10 @@
    1.73          for index, column in enumerate(self.alignment.columns):
    1.74              self[column] = index
    1.75  
    1.76 -class SequenceCaseMarkup(base.SequenceMarkup):
    1.77 +class SequenceCaseMarkup(base.SequenceMarkup, MarkupIOMixin):
    1.78  
    1.79      name = 'case'
    1.80 +    io_class = 'SequenceCaseMarkup'
    1.81  
    1.82      def refresh(self):
    1.83          for monomer in self.sequence:
    1.84 @@ -83,31 +122,21 @@
    1.85              elif monomer.input_code1.islower():
    1.86                  monomer.case = 'lower'
    1.87  
    1.88 -    @classmethod
    1.89 -    def from_record(cls, container, record, name=None):
    1.90 -        assert record['io_class'] == 'SequenceCaseMarkup'
    1.91 -        result = container.add_markup(name, markup_class=cls)
    1.92 -        markup = record['markup']
    1.93 -        assert markup[0] == markup[-1] == "'"
    1.94 -        markup = markup[1:-1]
    1.95 -        assert len(markup) == len(result.sequence)
    1.96 -        for monomer, mark in zip(result.sequence, markup):
    1.97 -            assert monomer.code1 == mark.upper()
    1.98 -            if mark.isupper():
    1.99 -                monomer.case = 'upper'
   1.100 -            if mark.islower():
   1.101 -                monomer.case = 'lower'
   1.102 -        return result
   1.103 +    @staticmethod
   1.104 +    def parse_value(monomer, value):
   1.105 +        assert mnomer.code1 == value.upper()
   1.106 +        if value.isupper():
   1.107 +            return 'upper'
   1.108 +        if value.islower():
   1.109 +            return 'lower'
   1.110  
   1.111 -    def to_record(self):
   1.112 -        markup = ''
   1.113 -        for monomer in self.sequence:
   1.114 -            case = self.get(monomer)
   1.115 -            if case == 'upper':
   1.116 -                markup += monomer.code1.upper()
   1.117 -            elif case == 'lower':
   1.118 -                markup += monomer.code1.lower()
   1.119 -        return {'markup': "'%s'" % markup, 'io_class': 'SequenceCaseMarkup'}
   1.120 +    @staticmethod
   1.121 +    def repr_value(monomer, value):
   1.122 +        if monomer.case == 'upper':
   1.123 +            return monomer.code1.upper()
   1.124 +        if monomer.case == 'lower':
   1.125 +            return monomer.code1.lower()
   1.126 +        raise AssertionError("Unknown monomer case")
   1.127  
   1.128  class SequencePdbResiMarkup(base.SequenceMarkup, IntMarkupMixin):
   1.129      name = 'pdb_resi'