def test_build_object__if_document_not_in_both_schemas__should_return_none(
            self, left_schema, document_type):
        right_schema = Schema({
            'Document_new':
            Schema.Document(
                {
                    'field1': {
                        'param11': 'schemavalue11',
                        'param12': 'schemavalue12'
                    },
                },
                parameters={'collection': 'document1'}),
            '~EmbeddedDocument2':
            Schema.Document({
                'field1': {
                    'param3': 'schemavalue3'
                },
                'field2': {
                    'param4': 'schemavalue4'
                },
            })
        })

        res = DropField.build_object(document_type, 'field2', left_schema,
                                     right_schema)

        assert res is None
Ejemplo n.º 2
0
 def load_db_schema(self) -> Schema:
     """Load schema from db"""
     fltr = {'type': 'schema'}
     res = self.migration_collection.find_one(fltr)
     schema = Schema()
     schema.load(res.get('value', {}) if res else {})
     return schema
    def test_build_object__if_field_creates__should_return_object(
            self, left_schema):
        right_schema = Schema({
            'Document1':
            Schema.Document(
                {
                    'field1': {
                        'param11': 'schemavalue11',
                        'param12': 'schemavalue12'
                    },
                },
                parameters={'collection': 'document1'}),
            '~EmbeddedDocument2':
            Schema.Document({
                'field1': {
                    'param3': 'schemavalue3'
                },
                'field2': {
                    'param4': 'schemavalue4'
                },
            })
        })

        res = DropField.build_object('Document1', 'field2', left_schema,
                                     right_schema)

        assert isinstance(res, DropField)
        assert res.document_type == 'Document1'
        assert res.field_name == 'field2'
        assert res.parameters == {}
Ejemplo n.º 4
0
def build_field_action_chain(action_cls: Type[BaseFieldAction],
                             left_schema: Schema,
                             right_schema: Schema,
                             document_types: Iterable[str]) -> Iterable[BaseAction]:
    """
    Walk through schema changes, and produce chain of Action objects
    of given type which could handle schema changes from left to right
    :param action_cls: Action type to consider
    :param left_schema:
    :param right_schema:
    :param document_types: list of document types to inspect
    :return: iterable of suitable Action objects
    """
    for document_type in document_types:
        # Take all fields to detect if they created, changed or dropped
        all_fields = left_schema.get(document_type, {}).keys() | \
                     right_schema.get(document_type, {}).keys()
        for field in all_fields:
            action_obj = action_cls.build_object(document_type,
                                                 field,
                                                 left_schema,
                                                 right_schema)
            if action_obj is not None:
                try:
                    left_schema = patch(action_obj.to_schema_patch(left_schema), left_schema)
                except (TypeError, ValueError, KeyError) as e:
                    raise ActionError(
                        f"Unable to apply schema patch of {action_obj!r}. More likely that the "
                        f"schema is corrupted. You can use schema repair tools to fix this issue"
                    ) from e

                yield action_obj
Ejemplo n.º 5
0
    def test_to_schema_patch__should_return_dictdiff_object(self):
        left_schema = Schema({
            'Document1':
            Schema.Document(
                {
                    'field1': {
                        'param11': 'schemavalue11',
                        'param12': 'schemavalue12'
                    },
                },
                parameters={'collection': 'document1'})
        })

        expect = [('remove', 'Document1', [('field1', {
            'param11': 'schemavalue11',
            'param12': 'schemavalue12'
        })]),
                  ('add', 'Document1', [('field2', {
                      'param11': 'schemavalue11',
                      'param12': 'schemavalue12'
                  })])]
        action = RenameField('Document1', 'field1', new_name='field2')

        res = action.to_schema_patch(left_schema)

        assert res == expect
Ejemplo n.º 6
0
    def test_build_object__if_document_is_not_dropping_in_schema__should_return_none(
            self, document_type):
        left_schema = Schema({
            '~EmbeddedDocument1':
            Schema.Document(
                {
                    'field1': {
                        'param1': 'schemavalue1',
                        'param2': 'schemavalue2'
                    },
                },
                parameters={'param1': 'value1'}),
            '~EmbeddedDocument2':
            Schema.Document({
                'field1': {
                    'param_new': 'schemavalue_new'
                },
            },
                            parameters={'test_parameter': 'test_value'})
        })
        right_schema = Schema({
            '~EmbeddedDocument2':
            Schema.Document({
                'field1': {
                    'param_new': 'schemavalue_new'
                },
            },
                            parameters={'test_parameter': 'test_value'})
        })

        res = DropEmbedded.build_object(document_type, left_schema,
                                        right_schema)

        assert res is None
def left_schema():
    return Schema({
        'Document1':
        Schema.Document(
            {
                'field1': {
                    'param11': 'schemavalue11',
                    'param12': 'schemavalue12'
                },
                'field2': {
                    'param21': 'schemavalue21',
                    'param22': 'schemavalue22'
                },
            },
            parameters={'collection': 'document1'}),
        '~EmbeddedDocument2':
        Schema.Document({
            'field1': {
                'param3': 'schemavalue3'
            },
            'field2': {
                'param4': 'schemavalue4'
            },
        })
    })
    def test_build_object__if_field_does_not_drop_in_schema__should_return_none(
            self, left_schema, field_name):
        right_schema = Schema({
            'Document1':
            Schema.Document(
                {
                    'field1': {
                        'param11': 'schemavalue11',
                        'param12': 'schemavalue12'
                    },
                    'field3': {
                        'param31': 'schemavalue31',
                        'param32': 'schemavalue32'
                    },
                },
                parameters={'collection': 'document1'}),
            '~EmbeddedDocument2':
            Schema.Document({
                'field1': {
                    'param3': 'schemavalue3'
                },
                'field2': {
                    'param4': 'schemavalue4'
                },
            })
        })

        res = DropField.build_object('Document1', field_name, left_schema,
                                     right_schema)

        assert res is None
Ejemplo n.º 9
0
def left_schema():
    return Schema({
        'Document1':
        Schema.Document({'field1': {
            'param1': 'val1'
        }},
                        parameters={'collection': 'document1'})
    })
Ejemplo n.º 10
0
    def test_to_schema_patch__should_return_dictdiffer_diff(self, left_schema):
        right_schema = Schema({
            'Document1':
            Schema.Document(
                {
                    'field1': {
                        'param11': 'schemavalue11',
                        'param12': 'schemavalue12'
                    },
                    'field2': {
                        'param21': 'schemavalue21',
                        'param22': 'schemavalue22'
                    },
                },
                parameters={'collection': 'document1'},
                indexes={
                    'index1': {
                        'fields': [('field1', pymongo.ASCENDING)]
                    },
                    'index2': {
                        'fields': [('field1', pymongo.ASCENDING),
                                   ('field2', pymongo.GEOHAYSTACK)],
                        'name':
                        'index2',
                        'sparse':
                        True
                    },
                    'index3': {
                        'fields': [('field2', pymongo.DESCENDING)],
                        'name': 'index3',
                        'sparse': False
                    }
                }),
            '~EmbeddedDocument2':
            Schema.Document({
                'field1': {
                    'param3': 'schemavalue3'
                },
                'field2': {
                    'param4': 'schemavalue4'
                },
            })
        })
        fields = [('field2', pymongo.DESCENDING)]
        action = CreateIndex('Document1',
                             'index3',
                             fields=fields,
                             name='index3',
                             sparse=False)
        expect = [('change', 'Document1', (left_schema['Document1'],
                                           right_schema['Document1']))]

        res = action.to_schema_patch(left_schema)

        assert res == expect
Ejemplo n.º 11
0
    def test_build_object__if_index_has_changed__should_return_object(
            self, left_schema):
        right_schema = Schema({
            'Document1':
            Schema.Document(
                {
                    'field1': {
                        'param11': 'schemavalue11',
                        'param12': 'schemavalue12'
                    },
                    'field2': {
                        'param21': 'schemavalue21',
                        'param22': 'schemavalue22'
                    },
                },
                parameters={'collection': 'document1'},
                indexes={
                    'index1': {
                        'fields': [('field1', pymongo.ASCENDING)]
                    },
                    'index2': {
                        'fields': [('field1', pymongo.ASCENDING),
                                   ('field2', pymongo.DESCENDING)],
                        'name':
                        'index2',
                        'sparse':
                        False
                    }
                }),
            '~EmbeddedDocument2':
            Schema.Document({
                'field1': {
                    'param3': 'schemavalue3'
                },
                'field2': {
                    'param4': 'schemavalue4'
                },
            })
        })

        res = AlterIndex.build_object('Document1', 'index2', left_schema,
                                      right_schema)

        assert isinstance(res, AlterIndex)
        assert res.document_type == 'Document1'
        assert res.index_name == 'index2'
        assert res.parameters == {
            'fields': [('field1', pymongo.ASCENDING),
                       ('field2', pymongo.DESCENDING)],
            'name':
            'index2',
            'sparse':
            False,
        }
Ejemplo n.º 12
0
    def test_build_object__if_document_not_in_both_schemas__should_return_none(
            self, left_schema, document_type):
        right_schema = Schema({
            'Document_new':
            Schema.Document(
                {
                    'field1': {
                        'param11': 'schemavalue11',
                        'param12': 'schemavalue12'
                    },
                    'field2': {
                        'param21': 'schemavalue21',
                        'param22': 'schemavalue22'
                    },
                    'field3': {
                        'param31': 'schemavalue31',
                        'param32': 'schemavalue32'
                    },
                },
                parameters={'collection': 'document1'},
                indexes={
                    'index1': {
                        'fields': [('field1', pymongo.ASCENDING)]
                    },
                    'index2': {
                        'fields': [('field1', pymongo.ASCENDING),
                                   ('field2', pymongo.DESCENDING)],
                        'name':
                        'index2',
                        'sparse':
                        False
                    }
                }),
            '~EmbeddedDocument2':
            Schema.Document({
                'field1': {
                    'param3': 'schemavalue3'
                },
                'field2': {
                    'param4': 'schemavalue4'
                },
            })
        })

        res = AlterIndex.build_object(document_type, 'index2', left_schema,
                                      right_schema)

        assert res is None
Ejemplo n.º 13
0
    def test_to_schema_patch__if_document_and_field_not_exist_in_left_schema__should_raise_error(
            self, document_type, field_name):
        left_schema = Schema({
            'Document1':
            Schema.Document(
                {
                    'field1': {
                        'param11': 'schemavalue11',
                        'param12': 'schemavalue12'
                    },
                },
                parameters={'collection': 'document1'})
        })
        action = RenameField(document_type, field_name, new_name='field2')

        with pytest.raises(SchemaError):
            action.to_schema_patch(left_schema)
Ejemplo n.º 14
0
    def test_build_object__on_usual_document_type__should_return_none(self):
        left_schema = Schema({
            'Document1': Schema.Document({
                'field1': {'param1': 'schemavalue1', 'param2': 'schemavalue2'},
            }, parameters={'collection': 'document1'})
        })
        right_schema = Schema({
            'Document1': Schema.Document({
                'field1': {'param1': 'schemavalue1', 'param2': 'schemavalue2'},
            }, parameters={'collection': 'document1'}),
            'Document_new': Schema.Document({
                'field1': {'param_new': 'schemavalue_new'},
            }, parameters={'collection': 'document_new', 'test_parameter': 'test_value'})
        })

        res = CreateEmbedded.build_object('Document_new', left_schema, right_schema)

        assert res is None
Ejemplo n.º 15
0
 def write_db_schema(self, schema: Schema) -> None:
     """
     Write schema to db
     :param schema:
     :return:
     """
     fltr = {'type': 'schema'}
     data = {'type': 'schema', 'value': schema.dump()}
     self.migration_collection.replace_one(fltr, data, upsert=True)
Ejemplo n.º 16
0
def left_schema():
    return Schema({
        'Document1':
        Schema.Document(
            {
                'field1': {
                    'param11': 'schemavalue11',
                    'param12': 'schemavalue12'
                },
                'field2': {
                    'param21': 'schemavalue21',
                    'param22': 'schemavalue22'
                },
            },
            parameters={'collection': 'document1'},
            indexes={
                'index1': {
                    'fields': [('field1', pymongo.ASCENDING)]
                },
                'index2': {
                    'fields': [('field1', pymongo.ASCENDING),
                               ('field2', pymongo.DESCENDING)],
                    'name':
                    'index2',
                    'sparse':
                    True
                }
            },
        ),
        '~EmbeddedDocument2':
        Schema.Document(
            {
                'field1': {
                    'param3': 'schemavalue3'
                },
                'field2': {
                    'param4': 'schemavalue4'
                },
            },
            indexes={'index3': {
                'fields': [('field1', pymongo.DESCENDING)]
            }})
    })
Ejemplo n.º 17
0
    def test_build_object__if_embedded_document_is_droppoing__should_return_object(
            self):
        left_schema = Schema({
            '~EmbeddedDocument1':
            Schema.Document(
                {
                    'field1': {
                        'param1': 'schemavalue1',
                        'param2': 'schemavalue2'
                    },
                },
                parameters={'param1': 'value1'}),
            'Document1':
            Schema.Document({
                'field1': {
                    'param_new': 'schemavalue_new'
                },
            },
                            parameters={
                                'collection': 'document_new',
                                'test_parameter': 'test_value'
                            })
        })
        right_schema = Schema({
            'Document1':
            Schema.Document({
                'field1': {
                    'param_new': 'schemavalue_new'
                },
            },
                            parameters={
                                'collection': 'document_new',
                                'test_parameter': 'test_value'
                            })
        })

        res = DropEmbedded.build_object('~EmbeddedDocument1', left_schema,
                                        right_schema)

        assert isinstance(res, DropEmbedded)
        assert res.document_type == '~EmbeddedDocument1'
        assert res.parameters == {}
Ejemplo n.º 18
0
    def test_build_object__if_document_is_not_creating_in_schema__should_return_none(
            self, document_type
    ):
        left_schema = Schema({
            '~EmbeddedDocument1': Schema.Document({
                'field1': {'param1': 'schemavalue1', 'param2': 'schemavalue2'},
            }, parameters={'collection': 'document1'})
        })
        right_schema = Schema({
            '~EmbeddedDocument1': Schema.Document({
                'field1': {'param1': 'schemavalue1', 'param2': 'schemavalue2'},
            }, parameters={'collection': 'document1'}),
            '~EmbeddedDocument2': Schema.Document({
                'field21': {'param21': 'schemavalue21', 'param22': 'schemavalue22'},
            }, parameters={}),
        })

        res = CreateEmbedded.build_object(document_type, left_schema, right_schema)

        assert res is None
Ejemplo n.º 19
0
    def test_build_object__if_embedded_document_is_creating__should_return_object(self):
        left_schema = Schema({
            'Document1': Schema.Document({
                'field1': {'param1': 'schemavalue1', 'param2': 'schemavalue2'},
            }, parameters={'collection': 'document1'})
        })
        right_schema = Schema({
            'Document1': Schema.Document({
                'field1': {'param1': 'schemavalue1', 'param2': 'schemavalue2'},
            }, parameters={'collection': 'document1'}),
            '~EmbeddedDocument1': Schema.Document({
                'field21': {'param21': 'schemavalue21', 'param22': 'schemavalue22'},
            }, parameters={'param1': 'value1'}),
        })

        res = CreateEmbedded.build_object('~EmbeddedDocument1', left_schema, right_schema)

        assert isinstance(res, CreateEmbedded)
        assert res.document_type == '~EmbeddedDocument1'
        assert res.parameters == {'param1': 'value1'}
Ejemplo n.º 20
0
    def test_build_object__if_document_is_droppoing__should_return_object(self):
        left_schema = Schema({
            'Document1': Schema.Document({
                'field1': {'param1': 'schemavalue1', 'param2': 'schemavalue2'},
            }, parameters={'collection': 'document1'}),
            'Document2': Schema.Document({
                'field21': {'param21': 'schemavalue21', 'param22': 'schemavalue22'},
            }, parameters={'collection': 'document21'}),
        })
        right_schema = Schema({
            'Document1': Schema.Document({
                'field1': {'param1': 'schemavalue1', 'param2': 'schemavalue2'},
            }, parameters={'collection': 'document1'}),
        })

        res = DropDocument.build_object('Document2', left_schema, right_schema)

        assert isinstance(res, DropDocument)
        assert res.document_type == 'Document2'
        assert res.parameters == {}
Ejemplo n.º 21
0
    def build_object(cls, document_type: str, left_schema: Schema,
                     right_schema: Schema):
        # Check if field exists under different name in schema.
        # Field also can have small schema changes in the same time
        # So we try to get similarity percentage and if it more than
        # threshold then we're consider such change as rename/alter.
        # Otherwise it is drop/create
        match = document_type in left_schema and document_type not in right_schema
        if not match:
            return

        is_left_embedded = document_type.startswith(
            flags.EMBEDDED_DOCUMENT_NAME_PREFIX)
        left_document_schema = left_schema[document_type]
        candidates = []
        for right_document_type, right_document_schema in right_schema.items():
            matches = 0
            compares = 0

            # Skip collections which apparently was not renamed
            if right_document_type in left_schema:
                continue

            # Prevent adding to 'candidates' a right document, which
            # could have same/similar schema but has another type
            # (embedded and usual and vice versa)
            is_right_embedded = right_document_type.startswith(
                flags.EMBEDDED_DOCUMENT_NAME_PREFIX)
            if is_left_embedded != is_right_embedded:
                continue

            # Exact match, collection was just renamed. We found it
            if left_document_schema == right_document_schema:
                candidates = [(right_document_type, right_document_schema)]
                break

            # Count of equal fields and parameters items and then
            # divide it on whole compared fields/parameters count
            items = ((left_document_schema, right_document_schema),
                     (left_document_schema.parameters,
                      right_document_schema.parameters))
            for left, right in items:
                all_keys = left.keys() | right.keys()
                compares += len(all_keys)
                # FIXME: keys can be functions (default for instance)
                #        they will not be equal then dispite they hasn't change
                matches += sum(left.get(k) == right.get(k) for k in all_keys)

            if compares > 0 and (matches / compares *
                                 100) >= cls.similarity_threshold:
                candidates.append((right_document_type, right_document_schema))

        if len(candidates) == 1:
            return cls(document_type=document_type, new_name=candidates[0][0])
Ejemplo n.º 22
0
def get_all_document_types(left_schema: Schema,
                           right_schema: Schema) -> Iterable[str]:
    """
    Return list of all document types collected from both schemas

    Document types should be processed in certain order depending
    if they are embedded or not, inherited or not. Embedded documents
    should be processed before common documents because their fields
    could refer to embedded documents which must be present in schema
    at the moment when migration of document is running. Also base
    document (common or embedded) should be processed before derived one

    So, common order is:

    1. Embedded documents
    2. Derived embedded documents ordered by their hierarchy depth
    3. Documents
    4. Derived documents ordered by their hierarchy depth

    :param left_schema:
    :param right_schema:
    :return:
    """
    def mark(document_type: str) -> int:
        # 0 -- embedded documents
        # 0 + derived depth -- embedded documents
        # 1000 -- documents
        # 1000 + derived_depth -- documents
        m = 0
        if not document_type.startswith(flags.EMBEDDED_DOCUMENT_NAME_PREFIX):
            m = 1000

        m += document_type.count(flags.DOCUMENT_NAME_SEPARATOR)

        return m

    all_document_types = ((k, mark(k))
                          for k in left_schema.keys() | right_schema.keys())
    all_document_types = sorted(all_document_types, key=lambda x: x[1])

    return [k[0] for k in all_document_types]
Ejemplo n.º 23
0
    def test_build_object__if_index_does_not_create_in_schema__should_return_none(
            self, left_schema, index_name):
        right_schema = Schema({
            'Document1':
            Schema.Document(
                {
                    'field1': {
                        'param11': 'schemavalue11',
                        'param12': 'schemavalue12'
                    },
                    'field3': {
                        'param31': 'schemavalue31',
                        'param32': 'schemavalue32'
                    },
                },
                parameters={'collection': 'document1'},
                indexes={
                    'index3': {
                        'fields': [('field2', pymongo.DESCENDING)],
                        'name': 'index3',
                        'sparse': True
                    },
                    'index1': {
                        'fields': [('field1', pymongo.DESCENDING)]
                    }
                }),
            '~EmbeddedDocument2':
            Schema.Document({
                'field1': {
                    'param3': 'schemavalue3'
                },
                'field2': {
                    'param4': 'schemavalue4'
                },
            })
        })

        res = CreateIndex.build_object('Document1', index_name, left_schema,
                                       right_schema)

        assert res is None
    def test_to_schema_patch__if_document_or_field_does_not_exist__should_raise_error(
            self, document_type, field_name):
        left_schema = Schema({
            'Document1':
            Schema.Document({
                'field1': {
                    'param11': 'schemavalue11',
                    'param12': 'schemavalue12'
                },
            })
        })

        action = DropField(document_type, field_name)
        test_schema_skel = {'param21': None, 'param22': None, 'param23': None}

        patcher = patch.object(action, 'get_field_handler_cls')
        with patcher as get_field_handler_cls_mock:
            get_field_handler_cls_mock.schema_skel.return_value = test_schema_skel

            with pytest.raises(SchemaError):
                action.to_schema_patch(left_schema)
    def test_build_object__if_document_is_similar_with_other_embedded_document__should_return_none(
            self
    ):
        left_schema = Schema({
            'Document1': Schema.Document({
                'field1': {'param1': 'schemavalue1', 'param2': 'schemavalue2'},
            }, parameters={'collection': 'document1'}),
            'Document2': Schema.Document({
                'field21': {'param21': 'schemavalue21', 'param22': 'schemavalue22'},
                'field22': {'param21': 'schemavalue21', 'param22': 'schemavalue22'},
            }, parameters={'collection': 'document21'}),
        })
        right_schema = Schema({
            'Document1': Schema.Document({
                'field1': {'param1': 'schemavalue1', 'param2': 'schemavalue2'},
            }, parameters={'collection': 'document1'}),
            '~EmbeddedDocument': Schema.Document({
                'field21': {'param21': 'schemavalue21', 'param22': 'schemavalue22'},
                'field22': {'param21': 'schemavalue21', 'param22': 'schemavalue22'},
            }, parameters={'collection': 'document21'}),
        })

        res = RenameDocument.build_object('Document2', left_schema, right_schema)

        assert res is None
    def test_build_object__if_there_are_several_rename_candidates__should_return_none(self):
        left_schema = Schema({
            'Document1': Schema.Document({
                'field11': {'param11': 'schemavalue11', 'param12': 'schemavalue21'},
                'field12': {'param21': 'schemavalue21', 'param22': 'schemavalue22'},
                'field13': {'param31': 'schemavalue31', 'param32': 'schemavalue32'},
                'field14': {'param41': 'schemavalue41', 'param42': 'schemavalue42'},
                'field15': {'param51': 'schemavalue51', 'param52': 'schemavalue52'},
            }, parameters={'collection': 'document1'}),
            'Document2': Schema.Document({
                'field1': {'param123': 'schemavalue123'},
            }, parameters={'collection': 'document123', 'test_parameter': 'test_value'}),
            'Document3': Schema.Document({
                'field11': {'param11': 'schemavalue11', 'param12': 'schemavalue21'},
                'field14': {'param41': 'schemavalue41', 'param42': 'schemavalue42'},
            })
        })
        
        right_schema = Schema({
            'Document11': Schema.Document({
                'field_changed': {'param11': 'schemavalue11', 'param12': 'schemavalue21'},
                'field12': {'param21': 'schemavalue21', 'param22': 'schemavalue22'},
                'field13': {'param31': 'schemavalue31', 'param32': 'schemavalue32'},
                'field14': {'param41': 'schemavalue41', 'param42': 'schemavalue42'},
                'field15': {'param51': 'schemavalue51', 'param52': 'schemavalue52'},
            }, parameters={'collection': 'document1'}),
            'Document111': Schema.Document({
                'field11': {'param11': 'schemavalue11', 'param12': 'schemavalue21'},
                'field12': {'param21': 'schemavalue_changed', 'param22': 'schemavalue22'},
                'field13': {'param31': 'schemavalue31', 'param32': 'schemavalue32'},
                'field14': {'param41': 'schemavalue41', 'param42': 'schemavalue42'},
                'field15': {'param51': 'schemavalue51', 'param52': 'schemavalue52'},
            }, parameters={'collection': 'document1'}),
            'Document2': Schema.Document({
                'field1': {'param123': 'schemavalue123'},
            }, parameters={'collection': 'document123', 'test_parameter': 'test_value'}),
            'Document31': Schema.Document({
                'field11': {'param11': 'schemavalue11', 'param12': 'schemavalue21'},
                'field14': {'param41': 'schemavalue41', 'param42': 'schemavalue42'},
            }),
        })
        
        res = RenameDocument.build_object('Document1', left_schema, right_schema)

        assert res is None
Ejemplo n.º 27
0
    def _fix_field_params(cls,
                          document_type: str,
                          field_name: str,
                          field_params: Mapping[str, Any],
                          old_schema: Schema,
                          new_schema: Schema) -> Mapping[str, Any]:
        """
        Search for potential problems which could be happened during
        migration and return fixed field schema. If such problem
        could not be resolved only by changing parameters then raise
        an SchemaError
        :param document_type:
        :param field_name:
        :param field_params:
        :param old_schema:
        :param new_schema:
        :raises SchemaError: when some problem found
        :return:
        """
        # TODO: Check all defaults in diffs against choices, required, etc.
        # TODO: check nones for type_key, etc.
        new_changes = {k: v.new for k, v in field_params.items()}

        # Field becomes required or left as required without changes
        become_required = new_changes.get('required',
                                          new_schema.get(field_name, {}).get('required'))

        # 'default' diff object has default parameter or field become
        # field with default or field has default value already
        default = (field_params.get('required') and field_params['required'].default) \
            or new_changes.get('default') \
            or new_schema.get(field_name, {}).get('default')
        if become_required and default is None:
            # TODO: replace following error on interactive mode
            raise SchemaError(f'Field {document_type}.{field_name} could not be '
                              f'created since it defined as required but has not a default value')

        return field_params
    def test_to_schema_patch__should_return_dictdiffer_diff(self, left_schema):
        right_schema = Schema({
            'Document1':
            Schema.Document(
                {
                    'field1': {
                        'param11': 'schemavalue11',
                        'param12': 'schemavalue12'
                    },
                    'field2': {
                        'param21': 'schemavalue21',
                        'param22': 'schemavalue22'
                    },
                },
                parameters={'collection': 'document1'},
                indexes={
                    'index1': {
                        'fields': [('field1', pymongo.ASCENDING)]
                    }
                }),
            '~EmbeddedDocument2':
            Schema.Document({
                'field1': {
                    'param3': 'schemavalue3'
                },
                'field2': {
                    'param4': 'schemavalue4'
                },
            })
        })
        action = DropIndex('Document1', 'index2')
        expect = [('change', 'Document1', (left_schema['Document1'],
                                           right_schema['Document1']))]

        res = action.to_schema_patch(left_schema)

        assert res == expect
Ejemplo n.º 29
0
    def test_build_object__if_index_in_embedded_document__should_return_none(
            self, left_schema):
        right_schema = Schema({
            'Document1':
            Schema.Document(
                {
                    'field1': {
                        'param11': 'schemavalue11',
                        'param12': 'schemavalue12'
                    },
                    'field3': {
                        'param31': 'schemavalue31',
                        'param32': 'schemavalue32'
                    },
                },
                parameters={'collection': 'document1'}),
            '~EmbeddedDocument2':
            Schema.Document(
                {
                    'field1': {
                        'param3': 'schemavalue3'
                    },
                    'field2': {
                        'param4': 'schemavalue4'
                    },
                },
                indexes={
                    'test_index': {
                        'fields': [('field1', pymongo.DESCENDING)]
                    }
                })
        })

        res = CreateIndex.build_object('~EmbeddedDocument2', 'test_index',
                                       left_schema, right_schema)

        assert res is None
Ejemplo n.º 30
0
    def test_build_object__if_embedded_document_schema_has_changed__should_return_object(
            self):
        left_schema = Schema({
            'Document1':
            Schema.Document(
                {
                    'field1': {
                        'param1': 'schemavalue1',
                        'param2': 'schemavalue2'
                    },
                },
                parameters={'collection': 'document1'}),
            '~EmbeddedDocument1':
            Schema.Document(
                {
                    'field21': {
                        'param21': 'schemavalue21',
                        'param22': 'schemavalue22'
                    },
                    'field22': {
                        'param21': 'schemavalue21',
                        'param22': 'schemavalue22'
                    },
                },
                parameters={'param': 'value'}),
        })
        right_schema = Schema({
            'Document1':
            Schema.Document(
                {
                    'field1': {
                        'param1': 'schemavalue1',
                        'param2': 'schemavalue2'
                    },
                },
                parameters={'collection': 'document1'}),
            '~EmbeddedDocument1':
            Schema.Document(
                {
                    'field21': {
                        'param_new': 'schemavalue_new'
                    },
                    'field22': {
                        'param21': 'schemavalue21',
                        'param22': 'schemavalue22'
                    },
                },
                parameters={'param123': 'value123'}),
        })

        res = AlterEmbedded.build_object('~EmbeddedDocument1', left_schema,
                                         right_schema)

        assert isinstance(res, AlterEmbedded)
        assert res.document_type == '~EmbeddedDocument1'
        assert res.parameters == {'param123': 'value123'}