Metadata-Version: 1.1
Name: Rels
Version: 0.2.2
Summary: Library for describing data relations in python (Enums, "relational" tables)
Home-page: https://github.com/Tiendil/rels
Author: Aleksey Yeletsky <Tiendil>
Author-email: a.eletsky@gmail.com
License: BSD
Description: ##############################
        Rels — перечисления для Python
        ##############################
        
        *********
        Установка
        *********
        
        ::
        
           pip install rels
        
        ********
        Введение
        ********
        
        Rels позволяет создавать сложные перечисляемые типы, со следующими свойствами:
        
        * каждый элемент перечисления — отдельный объект со всеми необходимыми методами;
        * наследование перечислений;
        * любое количество дополнительных данных, привязанных к элементу перечисления;
        * автоматическое создание индексов по данным;
        * дополнительные проверки данных;
        * формирование обратных ссылок в связанных друг с другом перечислениях (и других объектах);
        
        Общая идея заключается в использовании реляционной модели данных. При описании нового типа описываются поля отношения (столбцы таблицы) и непосредственно сами данные (в виде таблицы).
        
        За счёт наследования можно заранее объявить необходимые общие (абстрактные) типы, а конкретные перечисления уже наследовать от них.
        
        Благодаря динамической природе Python, при создании новых перечислений данные можно загружать из внешних источников, например, электронных таблиц.
        
        Пример использования:
        
        .. code:: python
        
           from rels import Column, Relation
        
           class Enum(Relation):             # объявляем абстраткное перечисление
               name = Column(primary=True)   # имя
               value = Column(external=True) # значение
        
        
           class EnumWithText(Enum):  # добавляем дополнительный столбец для описания значений
                text = Column()       # например, для использования в пользовательском интерфейсе
        
        
           nclass SOME_CONSTANTS(Enum):       # объявляем конкретное перечисление
                records = ( ('NAME_1', 1),   # и указываем данные для него
                            ('NAME_2', 2))
        
        
           # Варианты работы с элементами перечислений
           SOME_CONSTANTS.NAME_1.name == 'NAME_1'          # True
           SOME_CONSTANTS.NAME_1.value == 1                # True
        
           SOME_CONSTANTS(1) == SOME_CONSTANTS.NAME_1      # True
        
           SOME_CONSTANTS.NAME_2 == SOME_CONSTANTS.NAME_2  # True
           SOME_CONSTANTS.NAME_2 != SOME_CONSTANTS.NAME_1  # True
           SOME_CONSTANTS.NAME_2.is_NAME_2                 # True
        
        
           class SOME_CONSTANTS_WITH_TEXT(EnumWithText):
               records = ( ('NAME_1', 1, 'constant 1'),
                           ('NAME_2', 2, 'constant 2'))
        
        
           SOME_CONSTANTS.NAME_2 != SOME_CONSTANTS_WITH_TEXT.NAME_2  # True
           SOME_CONSTANTS.NAME_1 != SOME_CONSTANTS_WITH_TEXT.NAME_1  # True
        
        
           # добавление новых элементов перечисления
           class EXTENDED_CONSTANTS(SOME_CONSTANTS_WITH_TEXT):
               records = ( ('NAME_3', 3, 'constant 3'), )  # добавляем ещё одно значение
        
        
        *********************
        Описание перечисления
        *********************
        
        При описании столбцов таблицы, можно указать их свойства:
        
        * name — ``string`` — имя столбца (по умолчанию равно имени, которому присваивается объект столбца);
        * unique — ``boolean`` — значения в столбце должны быть уникальными, иначе будет брошено исключение (по умолчанию ``True``);
        * primary — ``boolean`` — элементы перечисления будут доступны как атрибуты перечисления с именами, указанными в этом столбце (например, ``ENUM.COLUMN_VALUE``) (по умолчанию ``False``);
        * external — ``boolean`` — элемент перечисления можно будет получить по значению этого столбца, передав его в конструктор перечисления (например, ``ENUM(some_value)``) (по умолчанию ``False``);
        * single_type — ``boolean`` — все значения в столбце должны быть одного типа (по умолчанию ``True``);
        * index_name — ``string`` — имя, по которому будет доступен индекс с ключам из этого столбца (по умолчанию равен ``index_<имя столбца>``), см. подробнее в описании индексов;
        * related_name — ``string`` | ``None`` — имя, по которому элемент перечисления будет доступен в объектах, на которые ссылается этот столбец (по умолчанию ``None``), см. подробнее в описании связывания.
        
        При создании перечисления:
        
        * Каждая строка данных в таблице превратится в элемент перечисления.
        * В классе перечисления будут установлен атрибут, ссылающиеся на соответствующий элемент перечисления. Имя атрибута будет установлено в значение в столбце, отмеченном как ``primary``.
        * Если ``primary`` столбцов больше 1, то будут установлены атрибуты для каждого.
        
        
        *****************
        Атрибуты и методы
        *****************
        
        Атрибуты перечисления:
        
        * ``.<имя из primary столбца>`` — ссылка на элемент перечисления (создаётся для всех значений из primary столбцов);
        * ``.records`` — список всех элементов перечисления в порядке их объявления в «сырых» данных;
        * ``.<имя индекса>``— индексы всех столбцов (по умолчанию ``index_<имя столбца>``);
        * ``.__call__`` — принимает значение из столбца с external установленным в ``True``, возвращает элемент перечисления, которому оно соответствует;
        * ``.select(*<список имён столбцов>)`` — возвращает таблицу с выборкой данных по указанным столбцам;
        * ``.get_from_name(<полное имя элемента перечисления>)`` — принимает строку с именем конкретного элемента перечисления (например, ``"ENUM.NAME"``) и возвращает соответствующий элемент перечисления или бросает исключение.
        
        Атрибуты элемента перечисления:
        
        * ``.<имя столбца>`` — получение данных для соответствующего столбца;
        * ``.is_<имя из primary столбца>`` — возвращает ``True``, если
        
        *******
        Индексы
        *******
        
        Для каждого столбца таблицы формируются индексы с ключами, равными данным в этом столбце, и значениями, равными элементам перечисления (если значения в столбце помечены как уникальные) или спискам элементов перечисления (если значения в столбце не уникальны).
        
        По умолчанию индекс доступен как атрибут перечисления с именем ``index_<имя столбца>``, но оно может быть изменено при описании столбца.
        
        Пример:
        
        .. code:: python
           from rels import Column, Relation
        
           class ENUM(Relation):
               name = Column(primary=True)
               value = Column(external=True)
               text = Column(unique=False, index_name='by_key')
        
               records = ( ('NAME_1', 0, 'key_1'),
                           ('NAME_2', 1, 'key_2'),
                           ('NAME_3', 2, 'key_2'), )
        
           ENUM.index_name # {'NAME_1': ENUM.NAME_1, 'NAME_2': ENUM.NAME_2,  'NAME_3': ENUM.NAME_3}
           ENUM.by_key     # {'key_1': [ENUM.NAME_1], 'key_2': [ENUM.NAME_2, ENUM.NAME_3]}
        
        ************
        Наследование
        ************
        
        Наследование позволяет расширять как количество столбцов, так и добавлять новые элементы перечисления (дополняя таблицу данных).
        
        **Добавлять столбцы можно только если в родительском классе не была указана таблица данных.**
        
        Пример наследования можно видеть в самом первом листинге.
        
        
        **********
        Связывание
        **********
        
        Если для одного из столбцов указано ``related_name``, то во время создания перечисления, для каждого объекта из этого столбца будет вызван метод ``set_related_name(<имя атрибута>, <ссылка на соответствующий элемент перечисления>)``, который должен установить объекту атрибут с соответствующим значением.
        
        В первую очередь, этот механизм предназначен для связи отношений друг с другом, но может использоваться и в других объектах.
        
        Пример:
        
        .. code:: python
           from rels import Column, Relation
        
           class DESTINATION_ENUM(Relation):
               name = Column(primary=True)
               val_1 = Column()
        
               records = ( ('STATE_1', 'value_1'),
                           ('STATE_2', 'value_2') )
        
           class SOURCE_ENUM(Relation):
               name = Column(primary=True)
               val_1 = Column()
               rel = Column(related_name='rel_source')
        
               records = ( ('STATE_1', 'value_1', DESTINATION_ENUM.STATE_1),
                           ('STATE_2', 'value_2', DESTINATION_ENUM.STATE_2) )
        
        
           DESTINATION_ENUM.STATE_1.rel_source == SOURCE_ENUM.STATE_1 # True
           DESTINATION_ENUM.STATE_2 == SOURCE_ENUM.STATE_2.rel        # True
        
        *********************************
        Взаимодействие со сторонним кодом
        *********************************
        
        Для взаимодействия с кодом, использующим другую реализацию перечислений, можно использовать значения из столбца с установленным в True параметром ``external``. Для восстановления объекта элемента перечисления, достаточно передать это значение в конструктор перечисления.
        
        Пример использования можно найти в самом первом листинге (``SOME_CONSTANTS(1) == SOME_CONSTANTS.NAME_1``)
        
        ## Использование библиотеки
        
        Все необходимые объекты вынесены в корень модуля:
        
        .. code:: python
           import rels
        
           # Базовые классы
           rels.Column # класс столбца
           rels.Record # класс элемента перечисления (обычно использовать нет необходимости)
           rels.Relation  # базовый клас перечисления
        
           # Простые перечисления
           rels.Enum         # простое перечисление со столбцами name и value
           rels.EnumWithText # простое перечисление с дополнительным столбцом text
        
           # Прочее
           rels.NullObject   # объект заглушка для отсутствующих значений в external столбцах
           rels.exceptions   # модуль с исключениями
        
        Название классов перечислений и имена элементов перечисления в primary столбцах желательно писать заглавными буквами так как у них семантика констант (также, это решает проблему пересечения имён стандартных методов с именами элементов перечисления ).
        
        ******
        Django
        ******
        
        В модуле ``rels.django`` реализован небольшой функционал для взаимодействия с Django.
        
        ==========
        DjangoEnum
        ==========
        
        Перечисление, унаследованное от EnumWithText, дополнительные методы:
        
        * choices — возвращает список ``[<элемент перечисления, текс>, …]``
        
        ====================
        RelationIntegerField
        ====================
        
        Наследник ``models.IntegerField``, автоматически конвертирует друг в друга целочисленные значения из базы и элементы перечисления.
        
        Конструктор принимает следующие параметры (кроме стандартных для ``IntegerField``):
        
        * relation — объект отношения
        * relation_column — имя столбца, который сохраняется в базу (по умолчанию, равен ``"value"``)
        
        =================
        Django Migrations
        =================
        
        Django нормально воспринимает ``RelationIntegerField``, но в случае указания параметра ``default``, понадобится править код миграции, так как django ничего о rels не знает.
        
        =====
        Тесты
        =====
        
        Все «фичи», за исключением связанных с Django, покрыты тестами.
        
Keywords: enums,data relations,relational tables
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: License :: OSI Approved :: BSD License
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Natural Language :: English
Classifier: Natural Language :: Russian
