コード例 #1
0
class BaseSyllable(db.Model, InitBase, DBBase):
    """Base Syllable's DB Model

    Describes a table structure for storing information about loglan syllables.

    <details><summary>Show Examples</summary><p>
    ```python
    {'id': 37, 'name': 'zv', 'type': 'InitialCC', 'allowed': True}

    {'id': 38, 'name': 'cdz', 'type': 'UnintelligibleCCC', 'allowed': False}
    ```
    </p></details>
    """

    __tablename__ = t_name_syllables

    id = db.Column(db.Integer, primary_key=True)
    """*Syllable's internal ID number*  
        **int** : primary_key=True"""
    name = db.Column(db.String(8), nullable=False, unique=False)
    """*Syllable itself*  
            **str** : max_length=8, nullable=False, unique=False"""
    type = db.Column(db.String(32), nullable=False, unique=False)
    """*Syllable's type*  
            **str** : max_length=8, nullable=False, unique=False"""
    allowed = db.Column(db.Boolean, nullable=True, unique=False)
    """*Is this syllable acceptable in grammar*  
コード例 #2
0
class BaseAuthor(db.Model, InitBase, DBBase):
    """Base Author's DB Model

    Describes a table structure for storing information about words authors.

    Connects with words with "many-to-many" relationship. See `t_connect_authors`.

    <details><summary>Show Examples</summary><p>
    ```python
    {'id': 13, 'full_name': 'James Cooke Brown',
    'abbreviation': 'JCB', 'notes': ''}

    {'id': 29, 'full_name': 'Loglan 4&5',
    'abbreviation': 'L4',
    'notes': 'The printed-on-paper book,
              1975 version of the dictionary.'}
    ```
    </p></details>
    """

    __tablename__ = t_name_authors

    id = db.Column(db.Integer, primary_key=True)
    """*Author's internal ID number*  
        **int** : primary_key=True"""

    abbreviation = db.Column(db.String(64), nullable=False, unique=True)
    """*Author's abbreviation (used in the LOD dictionary)*  
        **str** : max_length=64, nullable=False, unique=True
    Example:
        > JCB, L4
    """

    full_name = db.Column(db.String(64), nullable=True, unique=False)
    """
    *Author's full name (if exists)*  
        **str** : max_length=64, nullable=True, unique=False
    Example:
        > James Cooke Brown, Loglan 4&5
    """

    notes = db.Column(db.String(128), nullable=True, unique=False)
    """*Any additional information about author*  
        **str** : max_length=128, nullable=True, unique=False
    """

    _contribution = db.relationship("BaseWord",
                                    back_populates="_authors",
                                    secondary=t_connect_authors)

    @property
    def contribution(self):
        """
        *Relationship query for getting a list of words coined by this author*
         **query** : Optional[List[BaseWord]]
        """
        return self._contribution
コード例 #3
0
ファイル: base_setting.py プロジェクト: torrua/loglan_db
class BaseSetting(db.Model, InitBase, DBBase):
    """Base Setting's DB Model

    Describes a table structure for storing dictionary settings.

    <details><summary>Show Examples</summary><p>
    ```python
    {'id': 1, 'last_word_id': 10141,
    'date': datetime.datetime(2020, 10, 25, 5, 10, 20),
    'db_release': '4.5.9', 'db_version': 2}
    ```
    </p></details>
    """
    __tablename__ = t_name_settings

    id = db.Column(db.Integer, primary_key=True)
    """*Setting's internal ID number*  
        **int** : primary_key=True"""
    date = db.Column(db.DateTime, nullable=True, unique=False)
    """*Last modified date*  
        **dateime.datetime** : nullable=True, unique=False"""
    db_version = db.Column(db.Integer, nullable=False, unique=False)
    """*Database version (for old application)*  
        **int** : nullable=False, unique=False"""
    last_word_id = db.Column(db.Integer, nullable=False, unique=False)
    """*ID number of the last word in DB*  
            **int** : nullable=False, unique=False"""
    db_release = db.Column(db.String(16), nullable=False)
    """*Database release (for new application)*  
コード例 #4
0
ファイル: base_key.py プロジェクト: torrua/loglan_db
class BaseKey(db.Model, InitBase, DBBase):
    """Base Key's DB Model

    Describes a table structure for storing information
    about key words of the word's definitions.
    Some key words could belong to many definitions
    and some definitions could have many key words.
    That's why the relationship between Key
    and Definition should be many-to-many. See `t_connect_keys`.

    There is additional `word_language` UniqueConstraint here.

    <details><summary>Show Examples</summary><p>
    ```python
    {'language': 'en', 'word': 'aura', 'id': 1234}

    {'language': 'en', 'word': 'emotionality', 'id': 4321}
    ```
    </p></details>
    """
    __tablename__ = t_name_keys
    __table_args__ = (db.UniqueConstraint('word',
                                          'language',
                                          name='_word_language_uc'), )

    id = db.Column(db.Integer, primary_key=True)
    """*Key's internal ID number*  
        **int** : primary_key=True"""
    word = db.Column(db.String(64), nullable=False, unique=False)
    """*Key's vernacular word*  
        **str** : max_length=64, nullable=False, unique=False  
    It is non-unique, as words can be the same in spelling in different languages"""
    language = db.Column(db.String(16), nullable=False, unique=False)
    """*Key's language*  
        **str** : max_length=16, nullable=False, unique=False"""

    _definitions = db.relationship("BaseDefinition",
                                   secondary=t_connect_keys,
                                   lazy='dynamic',
                                   back_populates="_keys")

    @property
    def definitions(self):
        return self._definitions
コード例 #5
0
ファイル: base_type.py プロジェクト: torrua/loglan_db
class BaseType(db.Model, InitBase, DBBase):
    """BaseType model"""
    __tablename__ = t_name_types

    id = db.Column(db.Integer, primary_key=True)
    """Type's internal ID number: Integer - E.g. 4, 8"""

    type = db.Column(db.String(16), nullable=False)  # E.g. 2-Cpx, C-Prim
    type_x = db.Column(db.String(16),
                       nullable=False)  # E.g. Predicate, Predicate
    group = db.Column(db.String(16))  # E.g. Cpx, Prim
    parentable = db.Column(db.Boolean, nullable=False)  # E.g. True, False
    description = db.Column(db.String(255))  # E.g. Two-term Complex, ...

    _words = db.relationship("BaseWord",
                             back_populates="_type",
                             foreign_keys="BaseWord.type_id")

    @property
    def words(self):
        return self._words

    @classmethod
    def by(cls, type_filter: Union[str, List[str]]) -> BaseQuery:
        """

        Args:
          type_filter: Union[str, List[str]]:

        Returns:

        """
        type_filter = [
            type_filter,
        ] if isinstance(type_filter, str) else type_filter

        return cls.query.filter(
            or_(
                cls.type.in_(type_filter),
                cls.type_x.in_(type_filter),
                cls.group.in_(type_filter),
            ))
コード例 #6
0
ファイル: base_word.py プロジェクト: torrua/loglan_db
class BaseWord(db.Model, InitBase, DBBase):
    """BaseWord model"""
    __tablename__ = t_name_words

    id = db.Column(db.Integer, primary_key=True)
    """Word's internal ID number: Integer"""
    name = db.Column(db.String(64), nullable=False)
    origin = db.Column(db.String(128))
    origin_x = db.Column(db.String(64))
    match = db.Column(db.String(8))
    rank = db.Column(db.String(8))
    year = db.Column(db.Date)
    notes = db.Column(db.JSON)

    # Fields for legacy database compatibility
    id_old = db.Column(db.Integer, nullable=False)
    TID_old = db.Column(db.Integer)  # references

    # Relationships
    type_id = db.Column("type",
                        db.ForeignKey(f'{t_name_types}.id'),
                        nullable=False)
    _type: BaseType = db.relationship(BaseType.__name__,
                                      back_populates="_words")

    event_start_id = db.Column("event_start",
                               db.ForeignKey(f'{t_name_events}.id'),
                               nullable=False)
    _event_start: BaseEvent = db.relationship(BaseEvent.__name__,
                                              foreign_keys=[event_start_id],
                                              back_populates="_appeared_words")

    event_end_id = db.Column("event_end", db.ForeignKey(f'{t_name_events}.id'))
    _event_end: BaseEvent = db.relationship(BaseEvent.__name__,
                                            foreign_keys=[event_end_id],
                                            back_populates="_deprecated_words")

    _authors: BaseQuery = db.relationship(BaseAuthor.__name__,
                                          secondary=t_connect_authors,
                                          back_populates="_contribution",
                                          lazy='dynamic',
                                          enable_typechecks=False)

    _definitions: BaseQuery = db.relationship(BaseDefinition.__name__,
                                              back_populates="_source_word",
                                              lazy='dynamic')

    # word's derivatives
    _derivatives = db.relationship(
        'BaseWord',
        secondary=t_connect_words,
        primaryjoin=(t_connect_words.c.parent_id == id),
        secondaryjoin=(t_connect_words.c.child_id == id),
        backref=db.backref('_parents', lazy='dynamic',
                           enable_typechecks=False),
        lazy='dynamic',
        enable_typechecks=False)

    @property
    def type(self) -> BaseQuery:
        return self._type

    @property
    def event_start(self) -> BaseQuery:
        return self._event_start

    @property
    def event_end(self) -> BaseQuery:
        return self._event_end

    @property
    def authors(self) -> BaseQuery:
        return self._authors

    @property
    def definitions(self) -> BaseQuery:
        return self._definitions

    @property
    def derivatives(self) -> BaseQuery:
        return self._derivatives

    def query_derivatives(self,
                          word_type: str = None,
                          word_type_x: str = None,
                          word_group: str = None) -> BaseQuery:
        """Query to get all derivatives of the word, depending on its parameters

        Args:
          word_type: str:  (Default value = None)
          E.g. "2-Cpx", "C-Prim", "LW"<hr>

          word_type_x: str:  (Default value = None)
          E.g. "Predicate", "Name", "Affix"<hr>

          word_group: str:  (Default value = None)
          E.g. "Cpx", "Prim", "Little"<hr>

        Returns:
            BaseQuery
        """

        type_values = [
            (BaseType.type, word_type),
            (BaseType.type_x, word_type_x),
            (BaseType.group, word_group),
        ]

        type_filters = [i[0] == i[1] for i in type_values if i[1]]

        return self._derivatives.join(BaseType)\
            .filter(self.id == t_connect_words.c.parent_id, *type_filters)\
            .order_by(type(self).name.asc())

    @property
    def parents(self) -> BaseQuery:
        """Query to get all parents for Complexes, Little words or Affixes

        Returns:
            BaseQuery
        """
        return self._parents

    @property
    def complexes(self) -> BaseQuery:
        """
        Get all word's complexes if exist
        Only primitives and Little Words have complexes.

        Returns:
            BaseQuery
        """
        return self.query_derivatives(word_group="Cpx")

    @property
    def affixes(self) -> BaseQuery:
        """
        Get all word's affixes if exist
        Only primitives have affixes.

        Returns:
            BaseQuery
        """
        return self.query_derivatives(word_type="Afx")

    @property
    def keys(self) -> BaseQuery:
        """Get all BaseKey object related to this BaseWord.

        Keep in mind that duplicated keys from related definitions
        will be counted with ```.count()``` but excluded from ```.all()``` request

        Returns:
            BaseQuery
        """
        return BaseKey.query.join(t_connect_keys, BaseDefinition,
                                  BaseWord).filter(BaseWord.id == self.id)
コード例 #7
0
class BaseEvent(db.Model, InitBase, DBBase):
    """Base Event's DB Model

    Describes a table structure for storing information about lexical events.

    <details><summary>Show Examples</summary><p>
    ```python
    {'suffix': 'INIT', 'definition': 'The initial vocabulary before updates.',
     'date': datetime.date(1975, 1, 1), 'annotation': 'Initial', 'name': 'Start', 'id': 1}

    {'suffix': 'RDC', 'definition': 'parsed all the words in the dictionary,
    identified ones that the parser did not recognize as words',
    'date': datetime.date(2016, 1, 15), 'annotation': 'Randall Cleanup',
    'name': 'Randall Dictionary Cleanup', 'id': 5}
    ```
    </p></details>
    """
    __tablename__ = t_name_events

    id = db.Column(db.Integer, primary_key=True)
    """*Event's internal ID number*  
        **int** : primary_key=True"""
    date = db.Column(db.Date, nullable=False, unique=False)
    """*Event's starting day*  
        **dateime.date** : nullable=False, unique=False"""
    name = db.Column(db.String(64), nullable=False, unique=False)
    """*Event's short name*  
        **str** : max_length=64, nullable=False, unique=False"""
    definition = db.Column(db.Text, nullable=False, unique=False)
    """*Event's definition*  
        **str** : nullable=False, unique=False"""
    annotation = db.Column(db.String(16), nullable=False, unique=False)
    """*Event's annotation (displayed in old format dictionary HTML file)*  
        **str** : max_length=16, nullable=False, unique=False"""
    suffix = db.Column(db.String(16), nullable=False, unique=False)
    """*Event's suffix (used to create filename when exporting HTML file)*  
        **str** : max_length=16, nullable=False, unique=False"""

    _deprecated_words = db.relationship("BaseWord",
                                        back_populates="_event_end",
                                        foreign_keys="BaseWord.event_end_id")

    _appeared_words = db.relationship("BaseWord",
                                      back_populates="_event_start",
                                      foreign_keys="BaseWord.event_start_id")

    @property
    def deprecated_words(self):
        """
        *Relationship query for getting a list of words deprecated during this event*

        **query** : Optional[List[BaseWord]]"""

        return self._deprecated_words

    @property
    def appeared_words(self):
        """
        *Relationship query for getting a list of words appeared during this event*

        **query** : Optional[List[BaseWord]]"""

        return self._appeared_words

    @classmethod
    def latest(cls) -> BaseEvent:
        """
        Gets the latest (current) `BaseEvent` from DB
        """
        return cls.query.order_by(-cls.id).first()
コード例 #8
0
class BaseDefinition(db.Model, InitBase, DBBase):
    """BaseDefinition model"""
    __tablename__ = t_name_definitions

    id = db.Column(db.Integer, primary_key=True)
    """Definition's internal ID number: Integer"""

    word_id = db.Column(db.Integer,
                        db.ForeignKey(f'{t_name_words}.id'),
                        nullable=False)
    position = db.Column(db.Integer, nullable=False)
    usage = db.Column(db.String(64))
    grammar_code = db.Column(db.String(8))
    slots = db.Column(db.Integer)
    case_tags = db.Column(db.String(16))
    body = db.Column(db.Text, nullable=False)
    language = db.Column(db.String(16))
    notes = db.Column(db.String(255))

    APPROVED_CASE_TAGS = [
        "B",
        "C",
        "D",
        "F",
        "G",
        "J",
        "K",
        "N",
        "P",
        "S",
        "V",
    ]
    KEY_PATTERN = r"(?<=\«)(.+?)(?=\»)"

    _keys = db.relationship(BaseKey.__name__,
                            secondary=t_connect_keys,
                            back_populates="_definitions",
                            lazy='dynamic')

    _source_word = db.relationship("BaseWord", back_populates="_definitions")

    @property
    def keys(self) -> BaseQuery:
        """

        Returns:

        """
        return self._keys

    @property
    def source_word(self) -> BaseQuery:
        """

        Returns:

        """
        return self._source_word

    @property
    def grammar(self) -> str:
        """
        Combine definition's 'slots' and 'grammar_code' attributes

        Returns:
            String with grammar data like (3v) or (2n)
        """
        return f"({self.slots if self.slots else ''}" \
               f"{self.grammar_code if self.grammar_code else ''})"

    def link_keys_from_list_of_str(self,
                                   source: List[str],
                                   language: str = None) -> List[BaseKey]:
        """Linking a list of vernacular words with BaseDefinition
        Only new words will be linked, skipping those that were previously linked

        Args:
          source: List[str]: List of words on vernacular language
          language: str: Language of source words (Default value = None)

        Returns:
          List of linked BaseKey objects

        """

        language = language if language else self.language

        new_keys = BaseKey.query.filter(
            BaseKey.word.in_(source),
            BaseKey.language == language,
            ~exists().where(BaseKey.id == self.keys.subquery().c.id),
        ).all()

        self.keys.extend(new_keys)
        return new_keys

    def link_key_from_str(self,
                          word: str,
                          language: str = None) -> Optional[BaseKey]:
        """Linking vernacular word with BaseDefinition object
        Only new word will be linked, skipping this that was previously linked

        Args:
          word: str: name of BaseWord on vernacular language
          language: str: BaseWord's language (Default value = None)

        Returns:
          Linked BaseKey object or None if it were already linked

        """
        language = language if language else self.language
        result = self.link_keys_from_list_of_str(source=[
            word,
        ],
                                                 language=language)
        return result[0] if result else None

    def link_keys_from_definition_body(
            self,
            language: str = None,
            pattern: str = KEY_PATTERN) -> List[BaseKey]:
        """Extract and link keys from BaseDefinition's body

        Args:
          language: str: Language of BaseDefinition's keys (Default value = None)
          pattern: str: Regex pattern for extracting keys from the BaseDefinition's body
            (Default value = KEY_PATTERN)

        Returns:
          List of linked BaseKey objects

        """
        language = language if language else self.language
        keys = re.findall(pattern, self.body)
        return self.link_keys_from_list_of_str(source=keys, language=language)

    def link_keys(
            self,
            source: Union[List[str], str, None] = None,
            language: str = None,
            pattern: str = KEY_PATTERN) -> Union[BaseKey, List[BaseKey], None]:
        """Universal method for linking all available types of key sources with BaseDefinition

        Args:
          source: Union[List[str], str, None]:
            If no source is provided, keys will be extracted from the BaseDefinition's body
            If source is a string or a list of strings, the language of the keys must be specified
            TypeError will be raised if the source contains inappropriate data
            (Default value = None)
          language: str: Language of BaseDefinition's keys (Default value = None)
          pattern: str: Regex pattern for extracting keys from the BaseDefinition's body
            (Default value = KEY_PATTERN)

        Returns:
          None, BaseKey, or List of BaseKeys

        """
        def is_list_of_str(src: list) -> bool:
            checked_items = all(isinstance(item, str) for item in src)
            return bool(isinstance(src, list) and checked_items)

        language = language if language else self.language

        if not source:
            return self.link_keys_from_definition_body(language=language,
                                                       pattern=pattern)

        if isinstance(source, str):
            return self.link_key_from_str(word=source, language=language)

        if is_list_of_str(source):
            return self.link_keys_from_list_of_str(source=source,
                                                   language=language)

        raise TypeError(
            "Source for keys should have a string, or list of strings."
            "You input %s" % type(source))

    @classmethod
    def by_key(cls,
               key: Union[BaseKey, str],
               language: str = None,
               case_sensitive: bool = False) -> BaseQuery:
        """Definition.Query filtered by specified key

        Args:
          key: Union[BaseKey, str]:
          language: str: Language of key (Default value = None)
          case_sensitive: bool:  (Default value = False)

        Returns:
          BaseQuery

        """

        key = (BaseKey.word if isinstance(key, BaseKey) else str(key)).replace(
            "*", "%")
        request = cls.query.join(t_connect_keys,
                                 BaseKey).order_by(BaseKey.word)

        if language:
            request = request.filter(BaseKey.language == language)

        return request.filter(
            BaseKey.word.like(key) if case_sensitive else BaseKey.word.
            ilike(key))