From 49a3ec90c7236f770c134c3c45af8b5faf58e166 Mon Sep 17 00:00:00 2001 From: Sebastiaan Huber Date: Thu, 21 Nov 2019 10:18:07 +0100 Subject: [PATCH 1/3] Add data migration to rename legacy default return link label The original default link label that was used when no explicit one was specified by the user was set to `_return`. In a later change, link labels starting or ending with an underscore were banned because it would interfere with use of double underscores to indicate namespaces. As a result the default link was renamed to `result` however a data migration was never put in place. --- .../db/migrations/0043_default_link_label.py | 45 +++++++++++++++ .../backends/djsite/db/migrations/__init__.py | 2 +- ...test_migrations_0043_default_link_label.py | 47 ++++++++++++++++ .../migrations/test_migrations_common.py | 1 + .../118349c10896_default_link_label.py | 49 +++++++++++++++++ .../sqlalchemy/tests/test_migrations.py | 55 +++++++++++++++++++ aiida/backends/tests/__init__.py | 1 + 7 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 aiida/backends/djsite/db/migrations/0043_default_link_label.py create mode 100644 aiida/backends/djsite/db/subtests/migrations/test_migrations_0043_default_link_label.py create mode 100644 aiida/backends/sqlalchemy/migrations/versions/118349c10896_default_link_label.py diff --git a/aiida/backends/djsite/db/migrations/0043_default_link_label.py b/aiida/backends/djsite/db/migrations/0043_default_link_label.py new file mode 100644 index 0000000000..b3af227040 --- /dev/null +++ b/aiida/backends/djsite/db/migrations/0043_default_link_label.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +########################################################################### +# Copyright (c), The AiiDA team. All rights reserved. # +# This file is part of the AiiDA code. # +# # +# The code is hosted on GitHub at https://github.com/aiidateam/aiida-core # +# For further information on the license, see the LICENSE.txt file # +# For further information please visit http://www.aiida.net # +########################################################################### +# pylint: disable=invalid-name,too-few-public-methods +"""Update all link labels with the value `_return` which is the legacy default single link label. + +The old process functions used to use `_return` as the default link label, however, since labels that start or end with +and underscore are illegal because they are used for namespacing. +""" +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals +from __future__ import absolute_import + +# Remove when https://github.com/PyCQA/pylint/issues/1931 is fixed +# pylint: disable=no-name-in-module,import-error +from django.db import migrations +from aiida.backends.djsite.db.migrations import upgrade_schema_version + +REVISION = '1.0.43' +DOWN_REVISION = '1.0.42' + + +class Migration(migrations.Migration): + """Migrate.""" + + dependencies = [ + ('db', '0042_prepare_schema_reset'), + ] + + operations = [ + migrations.RunSQL( + sql=r""" + UPDATE db_dblink SET label='result' WHERE label = '_return'; + """, + reverse_sql='' + ), + upgrade_schema_version(REVISION, DOWN_REVISION) + ] diff --git a/aiida/backends/djsite/db/migrations/__init__.py b/aiida/backends/djsite/db/migrations/__init__.py index 3e9bf2cabd..fe8cf402d5 100644 --- a/aiida/backends/djsite/db/migrations/__init__.py +++ b/aiida/backends/djsite/db/migrations/__init__.py @@ -23,7 +23,7 @@ class DeserializationException(AiidaException): pass -LATEST_MIGRATION = '0042_prepare_schema_reset' +LATEST_MIGRATION = '0043_default_link_label' def _update_schema_version(version, apps, schema_editor): diff --git a/aiida/backends/djsite/db/subtests/migrations/test_migrations_0043_default_link_label.py b/aiida/backends/djsite/db/subtests/migrations/test_migrations_0043_default_link_label.py new file mode 100644 index 0000000000..0e388ffbf9 --- /dev/null +++ b/aiida/backends/djsite/db/subtests/migrations/test_migrations_0043_default_link_label.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +########################################################################### +# Copyright (c), The AiiDA team. All rights reserved. # +# This file is part of the AiiDA code. # +# # +# The code is hosted on GitHub at https://github.com/aiidateam/aiida-core # +# For further information on the license, see the LICENSE.txt file # +# For further information please visit http://www.aiida.net # +########################################################################### +# pylint: disable=import-error,no-name-in-module,invalid-name +"""Tests for the migrations of legacy process attributes.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from aiida.backends.djsite.db.subtests.migrations.test_migrations_common import TestMigrations + + +class TestSealUnsealedProcessesMigration(TestMigrations): + """Test the migration that performs a data migration of legacy `JobCalcState`.""" + + migrate_from = '0042_prepare_schema_reset' + migrate_to = '0043_default_link_label' + + def setUpBeforeMigration(self): + node_process = self.DbNode( + node_type='process.calculation.calcjob.CalcJobNode.', + user_id=self.default_user.id, + ) + node_process.save() + self.node_process_id = node_process.id + + node_data = self.DbNode( + node_type='data.dict.Dict.', + user_id=self.default_user.id, + ) + node_data.save() + self.node_data_id = node_data.id + + link = self.DbLink(input=node_data, output=node_process, type='input', label='_return') + link.save() + + def test_data_migrated(self): + """Verify that the link label has been renamed.""" + node = self.load_node(self.node_data_id) + link = self.DbLink.objects.get(input=node) + self.assertEqual(link.label, 'result') diff --git a/aiida/backends/djsite/db/subtests/migrations/test_migrations_common.py b/aiida/backends/djsite/db/subtests/migrations/test_migrations_common.py index 4fb749e538..dfe72abdb3 100644 --- a/aiida/backends/djsite/db/subtests/migrations/test_migrations_common.py +++ b/aiida/backends/djsite/db/subtests/migrations/test_migrations_common.py @@ -60,6 +60,7 @@ def setUp(self): # Reset session after the migration sa.get_scoped_session().close() + self.DbLink = self.apps.get_model('db', 'DbLink') self.DbNode = self.apps.get_model('db', 'DbNode') self.DbUser = self.apps.get_model('db', 'DbUser') self.DbUser.objects.all().delete() diff --git a/aiida/backends/sqlalchemy/migrations/versions/118349c10896_default_link_label.py b/aiida/backends/sqlalchemy/migrations/versions/118349c10896_default_link_label.py new file mode 100644 index 0000000000..42b9538e56 --- /dev/null +++ b/aiida/backends/sqlalchemy/migrations/versions/118349c10896_default_link_label.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +########################################################################### +# Copyright (c), The AiiDA team. All rights reserved. # +# This file is part of the AiiDA code. # +# # +# The code is hosted on GitHub at https://github.com/aiidateam/aiida-core # +# For further information on the license, see the LICENSE.txt file # +# For further information please visit http://www.aiida.net # +########################################################################### +# pylint: disable=invalid-name +"""Update all link labels with the value `_return` which is the legacy default single link label. + +The old process functions used to use `_return` as the default link label, however, since labels that start or end with +and underscore are illegal because they are used for namespacing. + +Revision ID: 118349c10896 +Revises: 91b573400be5 +Create Date: 2019-11-21 09:43:45.006053 + +""" +from __future__ import division +from __future__ import print_function +from __future__ import absolute_import + +# pylint: disable=no-member,no-name-in-module,import-error +from alembic import op +from sqlalchemy.sql import text + +# revision identifiers, used by Alembic. +revision = '118349c10896' +down_revision = '91b573400be5' +branch_labels = None +depends_on = None + + +def upgrade(): + """Migrations for the upgrade.""" + conn = op.get_bind() + + # The old process functions used to use `_return` as the default link label, however, since labels that start or end + # with and underscore are illegal. + statement = text(""" + UPDATE db_dblink SET label='result' WHERE label = '_return'; + """) + conn.execute(statement) + + +def downgrade(): + """Migrations for the downgrade.""" diff --git a/aiida/backends/sqlalchemy/tests/test_migrations.py b/aiida/backends/sqlalchemy/tests/test_migrations.py index 8c22809cc4..a26cc78029 100644 --- a/aiida/backends/sqlalchemy/tests/test_migrations.py +++ b/aiida/backends/sqlalchemy/tests/test_migrations.py @@ -1610,3 +1610,58 @@ def test_data_migrated(self): finally: session.close() + + +class TestDefaultLinkLabelMigration(TestMigrationsSQLA): + """Test the migration that performs a data migration of legacy default link labels.""" + + migrate_from = '91b573400be5' + migrate_to = '118349c10896' + + def setUpBeforeMigration(self): + from sqlalchemy.orm import Session # pylint: disable=import-error,no-name-in-module + + DbLink = self.get_auto_base().classes.db_dblink # pylint: disable=invalid-name + DbNode = self.get_auto_base().classes.db_dbnode # pylint: disable=invalid-name + DbUser = self.get_auto_base().classes.db_dbuser # pylint: disable=invalid-name + + with sa.ENGINE.begin() as connection: + try: + session = Session(connection.engine) + + user = DbUser(email='{}@aiida.net'.format(self.id())) + session.add(user) + session.commit() + + node_process = DbNode(node_type='process.calculation.calcjob.CalcJobNode.', user_id=user.id) + node_data = DbNode(node_type='data.dict.Dict.', user_id=user.id) + link = DbLink(input_id=node_data.id, output_id=node_process.id, type='input', label='_return') + + session.add(node_process) + session.add(node_data) + session.add(link) + session.commit() + + self.node_process_id = node_process.id + self.node_data_id = node_data.id + self.link_id = link.id + except Exception: + session.rollback() + raise + finally: + session.close() + + def test_data_migrated(self): + """Verify that the attributes for process node have been deleted and `_sealed` has been changed to `sealed`.""" + from sqlalchemy.orm import Session # pylint: disable=import-error,no-name-in-module + + DbLink = self.get_auto_base().classes.db_dblink # pylint: disable=invalid-name + + with sa.ENGINE.begin() as connection: + try: + session = Session(connection.engine) + link = session.query(DbLink).filter(DbLink.id == self.link_id).one() + self.assertEqual(link.label, 'result') + + finally: + session.close() diff --git a/aiida/backends/tests/__init__.py b/aiida/backends/tests/__init__.py index bbe7ced09b..4823647777 100644 --- a/aiida/backends/tests/__init__.py +++ b/aiida/backends/tests/__init__.py @@ -27,6 +27,7 @@ 'aiida.backends.djsite.db.subtests.migrations.test_migrations_0038_data_migration_legacy_job_calculations', 'aiida.backends.djsite.db.subtests.migrations.test_migrations_0040_data_migration_legacy_process_attributes', 'aiida.backends.djsite.db.subtests.migrations.test_migrations_0041_seal_unsealed_processes', + 'aiida.backends.djsite.db.subtests.migrations.test_migrations_0043_default_link_label', ], }, BACKEND_SQLA: { From 3d7ea608b460f4320374464901e396b733d93595 Mon Sep 17 00:00:00 2001 From: Sebastiaan Huber Date: Thu, 21 Nov 2019 10:37:01 +0100 Subject: [PATCH 2/3] Add archive migration to version `v0.8` Only the tests are missing. --- aiida/tools/importexport/common/config.py | 2 +- .../tools/importexport/migration/__init__.py | 6 ++- aiida/tools/importexport/migration/utils.py | 14 ++--- .../importexport/migration/v07_to_v08.py | 53 +++++++++++++++++++ 4 files changed, 63 insertions(+), 12 deletions(-) create mode 100644 aiida/tools/importexport/migration/v07_to_v08.py diff --git a/aiida/tools/importexport/common/config.py b/aiida/tools/importexport/common/config.py index 05052375be..d89c5ffca3 100644 --- a/aiida/tools/importexport/common/config.py +++ b/aiida/tools/importexport/common/config.py @@ -18,7 +18,7 @@ __all__ = ('EXPORT_VERSION',) # Current export version -EXPORT_VERSION = '0.7' +EXPORT_VERSION = '0.8' IMPORTGROUP_TYPE = GroupTypeString.IMPORTGROUP_TYPE.value DUPL_SUFFIX = ' (Imported #{})' diff --git a/aiida/tools/importexport/migration/__init__.py b/aiida/tools/importexport/migration/__init__.py index c3da12209c..cd5bfbd260 100644 --- a/aiida/tools/importexport/migration/__init__.py +++ b/aiida/tools/importexport/migration/__init__.py @@ -15,13 +15,14 @@ from aiida.cmdline.utils import echo from aiida.tools.importexport.common.exceptions import DanglingLinkError -from .utils import verify_metadata_version, update_metadata +from .utils import verify_metadata_version from .v01_to_v02 import migrate_v1_to_v2 from .v02_to_v03 import migrate_v2_to_v3 from .v03_to_v04 import migrate_v3_to_v4 from .v04_to_v05 import migrate_v4_to_v5 from .v05_to_v06 import migrate_v5_to_v6 from .v06_to_v07 import migrate_v6_to_v7 +from .v07_to_v08 import migrate_v7_to_v8 __all__ = ('migrate_recursively', 'verify_metadata_version') @@ -31,7 +32,8 @@ '0.3': migrate_v3_to_v4, '0.4': migrate_v4_to_v5, '0.5': migrate_v5_to_v6, - '0.6': migrate_v6_to_v7 + '0.6': migrate_v6_to_v7, + '0.7': migrate_v7_to_v8, } diff --git a/aiida/tools/importexport/migration/utils.py b/aiida/tools/importexport/migration/utils.py index c57299aa7a..96db4cce86 100644 --- a/aiida/tools/importexport/migration/utils.py +++ b/aiida/tools/importexport/migration/utils.py @@ -16,10 +16,9 @@ def verify_metadata_version(metadata, version=None): - """ - Utility function to verify that the metadata has the correct version number. - If no version number is passed, it will just extract the version number - and return it. + """Utility function to verify that the metadata has the correct version number. + + If no version number is passed, it will just extract the version number and return it. :param metadata: the content of an export archive metadata.json file :param version: string version number that the metadata is expected to have @@ -41,9 +40,7 @@ def verify_metadata_version(metadata, version=None): def update_metadata(metadata, version): - """ - Update the metadata with a new version number and a notification of the - conversion that was executed + """Update the metadata with a new version number and a notification of the conversion that was executed. :param metadata: the content of an export archive metadata.json file :param version: string version number that the updated metadata should get @@ -62,8 +59,7 @@ def update_metadata(metadata, version): def remove_fields(metadata, data, entities, fields): - """ - Remove fields under entities from data.json and metadata.json + """Remove fields under entities from data.json and metadata.json. :param metadata: the content of an export archive metadata.json file :param data: the content of an export archive data.json file diff --git a/aiida/tools/importexport/migration/v07_to_v08.py b/aiida/tools/importexport/migration/v07_to_v08.py new file mode 100644 index 0000000000..2d66ace0bf --- /dev/null +++ b/aiida/tools/importexport/migration/v07_to_v08.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +########################################################################### +# Copyright (c), The AiiDA team. All rights reserved. # +# This file is part of the AiiDA code. # +# # +# The code is hosted on GitHub at https://github.com/aiidateam/aiida-core # +# For further information on the license, see the LICENSE.txt file # +# For further information please visit http://www.aiida.net # +########################################################################### +"""Migration from v0.7 to v0.8, used by `verdi export migrate` command. + +The migration steps are named similarly to the database migrations for Django and SQLAlchemy. +In the description of each migration, a revision number is given, which refers to the Django migrations. +The individual Django database migrations may be found at: + + `aiida.backends.djsite.db.migrations.00XX_.py` + +Where XX are the numbers in the migrations' documentation: REV. 1.0.XX +And migration-name is the name of the particular migration. +The individual SQLAlchemy database migrations may be found at: + + `aiida.backends.sqlalchemy.migrations.versions._.py` + +Where id is a SQLA id and migration-name is the name of the particular migration. +""" +# pylint: disable=invalid-name +from __future__ import division +from __future__ import print_function +from __future__ import absolute_import + +from aiida.tools.importexport.migration.utils import verify_metadata_version, update_metadata + + +def migration_default_link_label(_, data): + """Apply migration 0043 - REV. 1.0.43 + + Rename all link labels `_return` to `result`. + """ + for link in data.get('links_uuid', []): + if link['label'] == '_return': + link['label'] = 'result' + + +def migrate_v7_to_v8(metadata, data, *args): # pylint: disable=unused-argument + """Migration of export files from v0.7 to v0.8.""" + old_version = '0.7' + new_version = '0.8' + + verify_metadata_version(metadata, old_version) + update_metadata(metadata, new_version) + + # Apply migrations + migration_default_link_label(metadata, data) From ca96e839d6e8728ab2b23188454e7fd37ae22905 Mon Sep 17 00:00:00 2001 From: Casper Welzel Andersen Date: Thu, 21 Nov 2019 16:26:13 +0100 Subject: [PATCH 3/3] Tests for export migration v0.7 to v0.8 --- aiida/backends/tests/__init__.py | 1 + .../fixtures/calcjob/arithmetic.add.aiida | Bin 8768 -> 8777 bytes .../fixtures/calcjob/arithmetic.add_old.aiida | Bin 8603 -> 8611 bytes .../fixtures/export/compare/django.aiida | Bin 1888 -> 1895 bytes .../fixtures/export/compare/sqlalchemy.aiida | Bin 1876 -> 1883 bytes .../export/migrate/export_v0.8_simple.aiida | Bin 0 -> 52453 bytes .../importexport/migration/test_migration.py | 55 ++++++++ .../importexport/migration/test_v07_to_v08.py | 127 ++++++++++++++++++ .../importexport/migration/v07_to_v08.py | 4 +- docs/requirements_for_rtd.txt | 2 +- setup.json | 2 +- 11 files changed, 187 insertions(+), 4 deletions(-) create mode 100644 aiida/backends/tests/fixtures/export/migrate/export_v0.8_simple.aiida create mode 100644 aiida/backends/tests/tools/importexport/migration/test_v07_to_v08.py diff --git a/aiida/backends/tests/__init__.py b/aiida/backends/tests/__init__.py index 4823647777..edafb350bd 100644 --- a/aiida/backends/tests/__init__.py +++ b/aiida/backends/tests/__init__.py @@ -163,6 +163,7 @@ 'tools.importexport.migration.v04_to_v05': ['aiida.backends.tests.tools.importexport.migration.test_v04_to_v05'], 'tools.importexport.migration.v05_to_v06': ['aiida.backends.tests.tools.importexport.migration.test_v05_to_v06'], 'tools.importexport.migration.v06_to_v07': ['aiida.backends.tests.tools.importexport.migration.test_v06_to_v07'], + 'tools.importexport.migration.v07_to_v08': ['aiida.backends.tests.tools.importexport.migration.test_v07_to_v08'], 'tools.importexport.orm.attributes': ['aiida.backends.tests.tools.importexport.orm.test_attributes'], 'tools.importexport.orm.calculations': ['aiida.backends.tests.tools.importexport.orm.test_calculations'], 'tools.importexport.orm.codes': ['aiida.backends.tests.tools.importexport.orm.test_codes'], diff --git a/aiida/backends/tests/fixtures/calcjob/arithmetic.add.aiida b/aiida/backends/tests/fixtures/calcjob/arithmetic.add.aiida index 573c7da52351e6de4a2f536bfa5cf19b242ceb4e..4c0de43491913f2831935d27051ca4d13c2bdb8b 100644 GIT binary patch delta 1978 zcmX@$a?*t_z?+#xgaHJ+D@y$*@+q)@=#56P?DZgq-E)nW-HZ$j?^zibc!7#?Q%e$4 z5=#>GvWoNbriOUu-!|a+r`>eUc|v0C!tF_{Rhm_=S4!|4O_E`%+EKMcn&z#_0jrjsTDq61%IYQeeY5oKKA0_-ckfiM$;0^hwVw5Y3XfHPTuYSqig)H)d#m}& z0a*>LX}yBG9Kzdv)NXqGz;sdbl}`ur7QL98d+_(%m}Q|!tXbtABAau*JU{t#wueLQ zuH!Y;p6PRZlV-`UbN*RmgIUjOmnLP>S~ z)UP*V_8Ht$J@k0n`S{$eh5J9Nt1Zm=zE?9Kkv)%z?|$*pOn=w%8$makR!N$$I38UT zx8U&cz}5L{_)UwR9p-%e`TWwjUy|l?Yj-nBitdQKn*ROUp4peB=JNaME z$S-02|NTB@eg7FzV}5c0r!qL|fef+9YdLx096_TbeGIi?lYb*CF-ydz#FGnQ%H#qV zr;$qyYBsmn)Y_c~$k`HF{BUDW;S5Tk)h9BziU;Kd(!~6vzAdJ-lHzAA;!FVuZ z^J~HVj1bm3;Q$D0GRQ{~qDZDLR@CG{&dK0l>=m_um~~Rr0K)hyYRrq0uP57z=|QCO z#iV4jIT;x8@>5ca^(_p5fxyTl!i*>!CIeM4PMUmBOah@{CtL$Km0;2EV6whAk_L7z zm<`}GgGGbhV=w&rH$0lk<2D`OrcW|$kL-~}qmO)W`G zNi0d!%PP*#n;PPs{n$X@pSII;p`c$)d#CDs+4N@Z@=X#)XIU^;?YN|IH|fv)aDMfP zyFD+@$?1Joede%SMfO>-Iqum~CfTR!H-!J2lFTw`?cA$5yV6e|)m4_3FMlJOd00-c z-fq*|`maelBi7~p5VhvrqkZ7F@`2m>jo(>+6o~v#S9+MAFKa5SbnCgHbs(3E=Bo-- zah`pw839d-G0A5-Ihp_GsxCPr5Fi#Fb-c&w%bT1RuMgY+U#BVzcVUR-lps`Z=G?YadyMu?=dfTEMH`uqnYD)l}F0sNJ^mog@=zCokX>o7~UI3yyUlM;XQtpL~y#2gVT-G)dIQqEVX*u2D?TG6kEGN|+LVZn4P= zxC9_Z>hXz9KE-7S;WUVXIO>yaxcMOh{@iK^W&PYp%5HI+L1aXDA|Z@Io@5v!V6wb4 z`(%AysI%>PkxZ%QMKa|SFVqx}o22;QZgPj11aeP5ACi*$2qj{ZIr))Hx+$y2gPeaR zgG^k)4>wV4@;QD(K~P2lXE7*YKKY=4)nqRLE{J^*0ud0#7J-`(#zet*K9DAxYge+P zfVpob)8vD~E|YgC@NV`ON?`;m+Pqyj0Kx)UDw33{pPYss0ia;^7KOXl4`TWyQ3D8r zP0W}VC6iBf6Vro8trwG$P2yx=$jeVjE!MX%0GiCmB*Kg+DJFwdbi!2_f$YXq!MI^E zqqqdZ$m?(o-~@%Kf$1OTD->j<6pG;*fUY(*!gN-F zv=rmq$$kfQa)S(#F-btK z!DMb(gfWbpCR@uQ>}9&cH<^*&kPj^uK!Kn>`GTw?!oB5_4djsYE##jpD4;)imK-#1 zu9A~tdIJ)(MmLLJUW&<4VDd)=hsoLUP}S8yvAF_3)s~Yl$U{wi4-~5s1dF*Sh(Iik zQIKM~D+t!RLqSp=6eDM++lRdd#zZ|Z7kQ(^$b!iq6rvCg{xUgJ5#eA)xyk<&4UnP- TQaw%v`7{$K<;u2G6l59z8*z<3 diff --git a/aiida/backends/tests/fixtures/calcjob/arithmetic.add_old.aiida b/aiida/backends/tests/fixtures/calcjob/arithmetic.add_old.aiida index 649e43e7c810f9f6b1422db2ef4f99963ae6adce..17357815a08a60d12660027f2cacaae10cae7256 100644 GIT binary patch delta 1930 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 X*9G{&TPGDA@{~|LL*Q}R`h@-uIu*6) diff --git a/aiida/backends/tests/fixtures/export/compare/django.aiida b/aiida/backends/tests/fixtures/export/compare/django.aiida index ba9c7483da81376290ad04ce106aed4e2a89df44..633c58159e4131478eeb39bd897b2637660e9219 100644 GIT binary patch delta 707 zcmaFB_neO}z?+#xgaHH=Rh0TqDq9b6%Ky^zO`uZw|ky$UQ4J$30ui zB>MFJ4e@_o3veskycT(uuX0;VP13<-^F@C*Cmw&G+F$m&nAgsIML-khj-xFeFZ=#)5i-(qoASitb&H1c{kgrll0On>8+%D# z7CCie@^a&h#;)%-X9k7t3iGVL)A#XHU&c#i=28dWz^D}gt^40T2<&2L4zuOYoV)hm z@8qQVfUqRyR}}^?-+7u%dfI0l;OQFXmT~D$%9``3mKA+36t?$yopIT@(qFd1xc1F0 z1;#D=Ot!3huRi$&pH%phY^Jz71|{Vy*1X8eim+I5PNdeiY|U?bo>ltSRzJ23|M}p8 z$>RNoex=ly_n1e1*!8yZ`g-5yvbr>(Q)cgj!ISHqn8%Tb*OrLR*rY5bvoJ8^<)@?;>nEq`2Y53wi7+FQ892Q`2_85{fZ?s>N enY@e52EzTtCdH)BI(avn{$y8nQMP(kkUjv>o+&5* delta 723 zcmaFP_kfQtz?+#xgaHJePI=`wkxzjIL~k_8V&Vlcgg)(5IM2wypf`CXlWe`y^FsyM z>a11VQVXUlZJ*QRwBYF0Jq+?(J4=K)etn;?NGG^2SJlB!Y`XF0&HS5nwHAL*kd=yE zbZ^!p@oKHQ?}khVw_VdPyR-S}BX(usy0AC)m--HJH(re~3XjZL@#C1Dad_v>e>TN) zXP9?ZwpY|2|8`&e^wFZtyS(;z9=UCNr2cE@qg4 z1s10kb>CZ};~b@VC-Fk^C$o!(+*!1orY_1fU$Nx+vhNxej_X6uI!k416}&6BsO`Ov zvC`s2{eGCaobD;fY^7SfCkJ&Sh zT`RkrBJ_4aq2oTU1Lcyx-hG>zdY6}Xv19477v7ta@5URf(2HKbt)qOYa`!H|zp2;M zAMZ}u)7LaT_xx@<^WH6=jVDi7_V0!W(}q6%2~ykh?@i?je|_flW23`zDeD$AR4{z5 zY3z%xj0)ayU($W2Lta7B*`l|<#MS@r-jT(A$a}-&7uLf4?UuP0t+a|`Px>>x+$h1f zLRRtTV}V`ocu`}0@k2PGD8 zGJ+DEaE<`OTgRTs0c;Ww?Kx~x)|*)v81nK{Qj7JIQ}vBg^aH#ZnM9Zo$q=p=$k2sz gKnC5Ne2~osVh|&{6q5$)Bv$>&KJ21w6|5k20Glc@hyVZp diff --git a/aiida/backends/tests/fixtures/export/compare/sqlalchemy.aiida b/aiida/backends/tests/fixtures/export/compare/sqlalchemy.aiida index 420e8171d8094b9de7cf43f6375db02b51698065..bd3ae08f442d34d1a38b3a022b636a5f12b1a131 100644 GIT binary patch delta 746 zcmcb@cbktdz?+#xgaHIrRh0Tq#W3D;+8C#}1GK1TR+-;Dl_ z`*Jt`Jx@xD3Go_PlzH*4hL6$p7PD@IT*GF+miYt2+Eh%-Hvhe-6W7~NCY&a{qv^SG0_07r4 z<{6D$-*3(g3bhLJw9h+UQsKVk%cMrD1Y?ELNNosr4;e_1m6jmHxHWk1fN0KDc1Ac>m{P zbNoNH{a1S(S8ktQmlbXQ_RkrWDY^H|T3K>FZC$$j?drRK`YipKHw0`ZZ86ah|@mb5q!?nTx^!D9r?BTlO`Q^}&%N7fCt>jk)g?Dadkdikz za!L8Fd~?M8|IDb-KDm!Y865AEx3Z`~824G+Aq*{6KM13S)d0fSz-o+^Ha@WG$%9f0 zI2}O=PB=$^;jLr)WLq|gNOUzkC~DTRFfiohr=%9^CmQJ+8t4ajGct)VBN8WEF_57P j=YUMVF?k)E4a9Np*rb@0StqY&)1Pd~F3MKS3Q`CFeXc7c delta 723 zcmcc3cZH8Hz?+#xgaHIzPkH4xkxzjIL~k^TW8wud8aOI+&NDJF=uMu>q+HKh#T~U^ zy3+PJO->7rZr#Hm&$Y88nB&*?NsCl3_vNZO_)nToZrMiK(Bn^W2%;XKEb& zd_3@NzWC{*MVohd?m2zrH}{dRzK?3v>gxA;{E?mc;Z~IU)kZ<($AWWJSQm+;?!BQW zQNtOqki~h&(T>iBKKm$6PD!RyZ@gZ2Xn5Pt<;{)!kviMhOFC&m>f4jg^Di)ozMpKq zbk&Zvlj?H5Y^j`{`B9b8bm6(HHqs#%@0WehU_H1X^t^LadiIC97>OxUZ!}2R``r1R zVw!TgUbcL}qOLVP7b1%%Z?Ka+ebC#1U2|8>5tk{mf6X|s`(8(6Emd% diff --git a/aiida/backends/tests/fixtures/export/migrate/export_v0.8_simple.aiida b/aiida/backends/tests/fixtures/export/migrate/export_v0.8_simple.aiida new file mode 100644 index 0000000000000000000000000000000000000000..250876da285055362a897f9c59a49a7bc18343a5 GIT binary patch literal 52453 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. + # data also has one "invalid" link, in form of . + # After the migration, the "invalid" link should have been updated to the "valid" link + data = { + 'links_uuid': [{ + 'input': 'some-random-uuid', + 'output': 'some-other-random-uuid', + 'label': '_return', + 'type': 'return' + }, { + 'input': 'some-random-uuid', + 'output': 'some-other-random-uuid', + 'label': 'a_good_label', + 'type': 'return' + }] + } + + migration_default_link_label(data) + + self.assertEqual( + data, { + 'links_uuid': [{ + 'input': 'some-random-uuid', + 'output': 'some-other-random-uuid', + 'label': 'result', + 'type': 'return' + }, { + 'input': 'some-random-uuid', + 'output': 'some-other-random-uuid', + 'label': 'a_good_label', + 'type': 'return' + }] + } + ) diff --git a/aiida/tools/importexport/migration/v07_to_v08.py b/aiida/tools/importexport/migration/v07_to_v08.py index 2d66ace0bf..3e588b811c 100644 --- a/aiida/tools/importexport/migration/v07_to_v08.py +++ b/aiida/tools/importexport/migration/v07_to_v08.py @@ -31,7 +31,7 @@ from aiida.tools.importexport.migration.utils import verify_metadata_version, update_metadata -def migration_default_link_label(_, data): +def migration_default_link_label(data): """Apply migration 0043 - REV. 1.0.43 Rename all link labels `_return` to `result`. @@ -50,4 +50,4 @@ def migrate_v7_to_v8(metadata, data, *args): # pylint: disable=unused-argument update_metadata(metadata, new_version) # Apply migrations - migration_default_link_label(metadata, data) + migration_default_link_label(data) diff --git a/docs/requirements_for_rtd.txt b/docs/requirements_for_rtd.txt index f044af5df6..1e36e7b3d6 100644 --- a/docs/requirements_for_rtd.txt +++ b/docs/requirements_for_rtd.txt @@ -1,6 +1,6 @@ PyCifRW==4.2.1; python_version < '3' PyCifRW==4.4.1; python_version >= '3' -aiida-export-migration-tests==0.7.0 +aiida-export-migration-tests==0.8.0 aldjemy==0.9.1 alembic==1.2.1 ase==3.17.0 diff --git a/setup.json b/setup.json index f0d3b9bad6..986dd99a68 100644 --- a/setup.json +++ b/setup.json @@ -105,7 +105,7 @@ "notebook<6" ], "testing": [ - "aiida-export-migration-tests==0.7.0", + "aiida-export-migration-tests==0.8.0", "codecov==2.0.15", "coverage==4.5.4", "futures==3.3.0; python_version=='2.7'",