ariatosca-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "ASF GitHub Bot (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (ARIA-105) Integrate new models into parser
Date Sun, 19 Mar 2017 13:30:43 GMT

    [ https://issues.apache.org/jira/browse/ARIA-105?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15931670#comment-15931670
] 

ASF GitHub Bot commented on ARIA-105:
-------------------------------------

Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/72#discussion_r106802395
  
    --- Diff: aria/modeling/relationships.py ---
    @@ -0,0 +1,402 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +# pylint: disable=invalid-name, redefined-outer-name
    +
    +from sqlalchemy.orm import relationship, backref
    +from sqlalchemy.orm.collections import attribute_mapped_collection
    +from sqlalchemy import (
    +    Column,
    +    ForeignKey,
    +    Integer,
    +    Table
    +)
    +
    +from ..utils import formatting
    +
    +
    +def fk(other_table,
    +       nullable=False):
    +    """
    +    Declare a foreign key property, which will also create a foreign key column in the
table with
    +    the name of the property. By convention the property name should end in "_fk".
    +
    +    You are required to explicitly create foreign keys in order to allow for one-to-one,
    +    one-to-many, and many-to-one relationships (but not for many-to-many relationships).
If you do
    +    not do so, SQLAlchemy will fail to create the relationship property and raise an
exception with
    +    a clear error message.
    +
    +    You should normally not have to access this property directly, but instead use the
associated
    +    relationship properties.
    +
    +    *This utility method should only be used during class creation.*
    +
    +    :param other_table: Other table name
    +    :type other_table: basestring
    +    :param nullable: True to allow null values (meaning that there is no relationship)
    +    :type nullable: bool
    +    """
    +
    +    return Column(Integer,
    +                  ForeignKey('{table}.id'.format(table=other_table), ondelete='CASCADE'),
    +                  nullable=nullable)
    +
    +
    +def one_to_one_self(model_class,
    +                    fk,
    +                    relationship_kwargs=None):
    +    """
    +    Declare a one-to-one relationship property. The property value would be an instance
of the same
    +    model.
    +
    +    You will need an associated foreign key to our own table.
    +
    +    *This utility method should only be used during class creation.*
    +
    +    :param model_class: The class in which this relationship will be declared
    +    :type model_class: type
    +    :param fk: Foreign key name
    +    :type fk: basestring
    +    :param relationship_kwargs: Extra kwargs for SQLAlchemy `relationship`
    +    :type relationship_kwargs: {}
    +    """
    +
    +    relationship_kwargs = relationship_kwargs or {}
    +
    +    remote_side = '{model_class}.{remote_column}'.format(
    +        model_class=model_class.__name__,
    +        remote_column=model_class.id_column_name()
    +    )
    +
    +    primaryjoin = '{remote_side} == {model_class}.{column}'.format(
    +        remote_side=remote_side,
    +        model_class=model_class.__name__,
    +        column=fk
    +    )
    +
    +    return relationship(
    +        _get_class_for_table(model_class, model_class.__tablename__).__name__,
    +        primaryjoin=primaryjoin,
    +        remote_side=remote_side,
    +        post_update=True,
    +        **relationship_kwargs
    +    )
    +
    +
    +def one_to_many_self(model_class,
    +                     fk,
    +                     dict_key=None,
    +                     relationship_kwargs=None):
    +    """
    +    Declare a one-to-many relationship property. The property value would be a list or
dict of
    +    instances of the same model.
    +
    +    You will need an associated foreign key to our own table.
    +
    +    *This utility method should only be used during class creation.*
    +
    +    :param model_class: The class in which this relationship will be declared
    +    :type model_class: type
    +    :param fk: Foreign key name
    +    :type fk: basestring
    +    :param dict_key: If set the value will be a dict with this key as the dict key; otherwise
will
    +                     be a list
    +    :type dict_key: basestring
    +    :param relationship_kwargs: Extra kwargs for SQLAlchemy `relationship`
    +    :type relationship_kwargs: {}
    +    """
    +
    +    relationship_kwargs = relationship_kwargs or {}
    +
    +    relationship_kwargs.setdefault('remote_side', '{model_class}.{remote_column}'.format(
    +        model_class=model_class.__name__,
    +        remote_column=fk
    +    ))
    +
    +    return _relationship(model_class, model_class.__tablename__, None, relationship_kwargs,
    +                         other_property=False, dict_key=dict_key)
    +
    +
    +def one_to_one(model_class,
    +               other_table,
    +               fk=None,
    +               other_fk=None,
    +               other_property=None,
    +               relationship_kwargs=None,
    +               backref_kwargs=None):
    +    """
    +    Declare a one-to-one relationship property. The property value would be an instance
of the other
    +    table's model.
    +
    +    You have two options for the foreign key. Either this table can have an associated
key to the
    +    other table (use the `fk` argument) or the other table can have an associated foreign
key to
    +    this our table (use the `other_fk` argument).
    +
    +    *This utility method should only be used during class creation.*
    +
    +    :param model_class: The class in which this relationship will be declared
    +    :type model_class: type
    +    :param other_table: Other table name
    +    :type other_table: basestring
    +    :param fk: Foreign key name at our table (no need specify if there's no ambiguity)
    +    :type fk: basestring
    +    :param other_fk: Foreign key name at the other table (no need specify if there's
no ambiguity)
    +    :type other_fk: basestring
    +    :param relationship_kwargs: Extra kwargs for SQLAlchemy `relationship`
    +    :type relationship_kwargs: {}
    +    :param backref_kwargs: Extra kwargs for SQLAlchemy `backref`
    +    :type backref_kwargs: {}
    +    """
    +
    +    backref_kwargs = backref_kwargs or {}
    +    backref_kwargs.setdefault('uselist', False)
    +
    +    return _relationship(model_class, other_table, backref_kwargs, relationship_kwargs,
    +                         other_property, fk=fk, other_fk=other_fk)
    +
    +
    +def one_to_many(model_class,
    +                child_table,
    +                child_fk=None,
    +                dict_key=None,
    +                child_property=None,
    +                relationship_kwargs=None,
    +                backref_kwargs=None):
    +    """
    +    Declare a one-to-many relationship property. The property value would be a list or
dict of
    +    instances of the child table's model.
    +
    +    The child table will need an associated foreign key to our table.
    +
    +    The declaration will automatically create a matching many-to-one property at the
child model,
    +    named after our table name. Use the `child_property` argument to override this name.
    +
    +    *This utility method should only be used during class creation.*
    +
    +    :param model_class: The class in which this relationship will be declared
    +    :type model_class: type
    +    :param child_table: Child table name
    +    :type child_table: basestring
    +    :param child_fk: Foreign key name at the child table (no need specify if there's
no ambiguity)
    +    :type child_fk: basestring
    +    :param dict_key: If set the value will be a dict with this key as the dict key; otherwise
will
    +                     be a list
    +    :type dict_key: basestring
    +    :param child_property: Override name of matching many-to-one property at child table;
set to
    +                           false to disable
    +    :type child_property: basestring|bool
    +    :param relationship_kwargs: Extra kwargs for SQLAlchemy `relationship`
    +    :type relationship_kwargs: {}
    +    :param backref_kwargs: Extra kwargs for SQLAlchemy `backref`
    +    :type backref_kwargs: {}
    +    """
    +
    +    backref_kwargs = backref_kwargs or {}
    +    backref_kwargs.setdefault('uselist', False)
    +
    +    return _relationship(model_class, child_table, backref_kwargs, relationship_kwargs,
    +                         child_property, other_fk=child_fk, dict_key=dict_key)
    +
    +
    +def many_to_one(model_class,
    +                parent_table,
    +                fk=None,
    +                parent_fk=None,
    +                parent_property=None,
    +                relationship_kwargs=None,
    +                backref_kwargs=None):
    +    """
    +    Declare a many-to-one relationship property. The property value would be an instance
of the
    +    parent table's model.
    +
    +    You will need an associated foreign key to the parent table.
    +
    +    The declaration will automatically create a matching one-to-many property at the
child model,
    +    named after the plural form of our table name. Use the `parent_property` argument
to override
    +    this name. Note: the automatic property will always be a SQLAlchemy query object;
if you need a
    +    Python collection then use :meth:`one_to_many` at that model.
    +
    +    *This utility method should only be used during class creation.*
    +
    +    :param model_class: The class in which this relationship will be declared
    +    :type model_class: type
    +    :param parent_table: Parent table name
    +    :type parent_table: basestring
    +    :param fk: Foreign key name at our table (no need specify if there's no ambiguity)
    +    :type fk: basestring
    +    :param parent_property: Override name of matching one-to-many property at parent
table; set to
    +                            false to disable
    +    :type parent_property: basestring|bool
    +    :param relationship_kwargs: Extra kwargs for SQLAlchemy `relationship`
    +    :type relationship_kwargs: {}
    +    :param backref_kwargs: Extra kwargs for SQLAlchemy `backref`
    +    :type backref_kwargs: {}
    +    """
    +
    +    if parent_property is None:
    +        parent_property = formatting.pluralize(model_class.__tablename__)
    +
    +    backref_kwargs = backref_kwargs or {}
    +    backref_kwargs.setdefault('uselist', True)
    +    backref_kwargs.setdefault('lazy', 'dynamic')
    +    backref_kwargs.setdefault('cascade', 'all') # delete children when parent is deleted
    +
    +    return _relationship(model_class, parent_table, backref_kwargs, relationship_kwargs,
    +                         parent_property, fk=fk, other_fk=parent_fk)
    +
    +
    +def many_to_many(model_class,
    +                 other_table,
    +                 prefix=None,
    +                 dict_key=None,
    +                 other_property=None,
    +                 relationship_kwargs=None,
    +                 backref_kwargs=None):
    +    """
    +    Declare a many-to-many relationship property. The property value would be a list
or dict of
    +    instances of the other table's model.
    +
    +    You do not need associated foreign keys for this relationship. Instead, an extra
table will be
    +    created for you.
    +
    +    The declaration will automatically create a matching many-to-many property at the
other model,
    +    named after the plural form of our table name. Use the `other_property` argument
to override
    +    this name. Note: the automatic property will always be a SQLAlchemy query object;
if you need a
    +    Python collection then use :meth:`many_to_many` again at that model.
    +
    +    *This utility method should only be used during class creation.*
    +
    +    :param model_class: The class in which this relationship will be declared
    +    :type model_class: type
    +    :param parent_table: Parent table name
    +    :type parent_table: basestring
    +    :param prefix: Optional prefix for extra table name as well as for `other_property`
    +    :type prefix: basestring
    +    :param dict_key: If set the value will be a dict with this key as the dict key; otherwise
will
    +                     be a list
    +    :type dict_key: basestring
    +    :param other_property: Override name of matching many-to-many property at other table;
set to
    +                           false to disable
    +    :type other_property: basestring|bool
    +    :param relationship_kwargs: Extra kwargs for SQLAlchemy `relationship`
    +    :type relationship_kwargs: {}
    +    :param backref_kwargs: Extra kwargs for SQLAlchemy `backref`
    +    :type backref_kwargs: {}
    +    """
    +
    +    this_table = model_class.__tablename__
    +    this_column_name = '{0}_id'.format(this_table)
    +    this_foreign_key = '{0}.id'.format(this_table)
    +
    +    other_column_name = '{0}_id'.format(other_table)
    +    other_foreign_key = '{0}.id'.format(other_table)
    +
    +    secondary_table = '{0}_{1}'.format(this_table, other_table)
    +
    +    if other_property is None:
    +        other_property = formatting.pluralize(this_table)
    +        if prefix is not None:
    +            secondary_table = '{0}_{1}'.format(prefix, secondary_table)
    +            other_property = '{0}_{1}'.format(prefix, other_property)
    +
    +    backref_kwargs = backref_kwargs or {}
    +    backref_kwargs.setdefault('uselist', True)
    +
    +    relationship_kwargs = relationship_kwargs or {}
    +    relationship_kwargs.setdefault('secondary', _get_secondary_table(
    +        model_class.metadata,
    +        secondary_table,
    +        this_column_name,
    +        other_column_name,
    +        this_foreign_key,
    +        other_foreign_key
    +    ))
    +
    +    return _relationship(model_class, other_table, backref_kwargs, relationship_kwargs,
    +                         other_property, dict_key=dict_key)
    +
    +
    +def _relationship(model_class, other_table, backref_kwargs, relationship_kwargs, other_property,
    +                  fk=None, other_fk=None, dict_key=None):
    +    relationship_kwargs = relationship_kwargs or {}
    +
    +    if fk:
    +        relationship_kwargs.setdefault('foreign_keys',
    +                                       lambda: getattr(
    +                                           _get_class_for_table(
    +                                               model_class,
    +                                               model_class.__tablename__),
    +                                           fk))
    +
    +    elif other_fk:
    +        relationship_kwargs.setdefault('foreign_keys',
    +                                       lambda: getattr(
    +                                           _get_class_for_table(
    +                                               model_class,
    +                                               other_table),
    +                                           other_fk))
    +
    +    if dict_key:
    +        relationship_kwargs.setdefault('collection_class',
    +                                       attribute_mapped_collection(dict_key))
    +
    +    if other_property is False:
    +        # No backref
    +        return relationship(
    +            lambda: _get_class_for_table(model_class, other_table),
    +            **relationship_kwargs
    +        )
    +    else:
    +        if other_property is None:
    +            other_property = model_class.__tablename__
    +        backref_kwargs = backref_kwargs or {}
    +        return relationship(
    +            lambda: _get_class_for_table(model_class, other_table),
    +            backref=backref(other_property, **backref_kwargs),
    +            **relationship_kwargs
    +        )
    +
    +
    +def _get_class_for_table(model_class, tablename):
    --- End diff --
    
    it actually receive a tablename (and not a table), not sure about the name...


> Integrate new models into parser
> --------------------------------
>
>                 Key: ARIA-105
>                 URL: https://issues.apache.org/jira/browse/ARIA-105
>             Project: AriaTosca
>          Issue Type: Task
>            Reporter: Ran Ziv
>            Assignee: Tal Liron
>




--
This message was sent by Atlassian JIRA
(v6.3.15#6346)

Mime
View raw message