From 4dc7c15b8fa593abac4906e6e20c1550ed238617 Mon Sep 17 00:00:00 2001 From: Joanne Bogart Date: Tue, 25 Feb 2025 20:49:46 -0800 Subject: [PATCH 01/16] modify schema to make dataset.relative_path nullable. Update db version (bump minor) --- scripts/create_registry_schema.py | 2 +- src/dataregistry/schema/schema.yaml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/create_registry_schema.py b/scripts/create_registry_schema.py index eac2d598..657d5bd2 100644 --- a/scripts/create_registry_schema.py +++ b/scripts/create_registry_schema.py @@ -272,7 +272,7 @@ def _BuildTable(schema, table_name, has_production, production): # The following should be adjusted whenever there is a change to the structure # of the database tables. _DB_VERSION_MAJOR = 3 -_DB_VERSION_MINOR = 3 +_DB_VERSION_MINOR = 4 _DB_VERSION_PATCH = 0 _DB_VERSION_COMMENT = "Remove `is_overwritten`, `replace_date` and `replace_uid` columns, the information is in `status`" diff --git a/src/dataregistry/schema/schema.yaml b/src/dataregistry/schema/schema.yaml index c0f44f30..a797407f 100644 --- a/src/dataregistry/schema/schema.yaml +++ b/src/dataregistry/schema/schema.yaml @@ -341,7 +341,6 @@ tables: relative_path: type: "String" description: "Relative path storing the data, relative to ``. If None, generated from the `name` and `version_string`" - nullable: False cli_optional: True version_major: type: "Integer" From 339e64cc634b978bf2b92f4a6ca17313254452e4 Mon Sep 17 00:00:00 2001 From: Joanne Bogart Date: Tue, 25 Feb 2025 20:50:39 -0800 Subject: [PATCH 02/16] document procedure for modifying db in place --- docs/source/for_maintainers.rst | 59 +++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 docs/source/for_maintainers.rst diff --git a/docs/source/for_maintainers.rst b/docs/source/for_maintainers.rst new file mode 100644 index 00000000..1113e68e --- /dev/null +++ b/docs/source/for_maintainers.rst @@ -0,0 +1,59 @@ +.. _maintenance + +Maintenance +=========== + +Procedure for Database Upgrades +------------------------------- + +Creating an alternate database +****************************** + +If it doesn't already exist, create an alternate database from ``psql`` using +the admin account: + +.. code-block:: bash + + $ psql dest_data_registry reg_admin + desc_data_registry=# create database alt_db; + +and add an entry to your .pgpass for the reg_admin account and alt_db database. +If you expect to use standard ``dataregistry`` utilities for your updates +(recommended) you'll also need an alternate config file for connecting to +the alternate database as reg_admin. + +Dump the active database +************************ + +Dump both schemas and data from the ``desc_data_registry`` database +.. code-block:: bash + + $ pg_dump -U reg_admin desc_data_registry --schema=lsst_desc_production --file=production_dump.sql + $ pg_dump -U reg_admin desc_data_registry --schema=lsst_desc_working --file=working_dump.sql + +See ``pg_dump`` documentation for a description of all options. For example you +might want to use a different format than the default simple one used here. + +Restore to alt_db database +************************** + +.. code-block:: bash + + $ psql -U reg_admin -X --set ON_ERROR_STOP=on alt_db < production_dump.sql + $ psql -U reg_admin -X --set ON_ERROR_STOP=on alt_db < working_dump.sql + +Depending on the format of your dumped data, you might instead need to use the +``pg_restore`` program rather than ``psql`` to do the restore. + +Test and apply for real +*********************** + +If the update involves changes to the schema you'll need a script to implement +them and also add an entry to the ``provenance`` table. +If the update involves changes to entries stored in the database, you'll need +a script for that as well (or if more convenient use a single script for both). +See an example (somewhere). + +Run your script(s) in alt_db, fix any issues, then run in the +``desc_data_registry``. Once you're satisfied everything is ok, +delete the copy of the schemas in ``alt_db`` From 714196338d447b0180bd6ec0471a7ad0e0d0143b Mon Sep 17 00:00:00 2001 From: Joanne Bogart Date: Tue, 25 Feb 2025 21:25:53 -0800 Subject: [PATCH 03/16] Store db version info in a separate module so it can be referenced both when creating a new schema or modifying one in place --- scripts/create_registry_schema.py | 18 ++++++------------ src/dataregistry/schema/schema_version.py | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 12 deletions(-) create mode 100644 src/dataregistry/schema/schema_version.py diff --git a/scripts/create_registry_schema.py b/scripts/create_registry_schema.py index 657d5bd2..d007e95f 100644 --- a/scripts/create_registry_schema.py +++ b/scripts/create_registry_schema.py @@ -18,6 +18,12 @@ load_preset_keywords, DEFAULT_NAMESPACE, ) +from dataregistry.schema_version import ( + _DB_VERSION_MAJOR, + _DB_VERSION_MINOR, + _DB_VERSION_PATCH, + _DB_VERSION_COMMENT +) """ A script to create a schema. @@ -264,18 +270,6 @@ def _BuildTable(schema, table_name, has_production, production): Model = type(class_name, (Base,), {**columns, **meta}) return Model - -# ---------------- -# Database version -# ---------------- - -# The following should be adjusted whenever there is a change to the structure -# of the database tables. -_DB_VERSION_MAJOR = 3 -_DB_VERSION_MINOR = 4 -_DB_VERSION_PATCH = 0 -_DB_VERSION_COMMENT = "Remove `is_overwritten`, `replace_date` and `replace_uid` columns, the information is in `status`" - # ---------------------------- # Parse command line arguments # ---------------------------- diff --git a/src/dataregistry/schema/schema_version.py b/src/dataregistry/schema/schema_version.py new file mode 100644 index 00000000..1fb025e5 --- /dev/null +++ b/src/dataregistry/schema/schema_version.py @@ -0,0 +1,15 @@ +''' +Store major, minor, patch for db version expected by this code version as +well as associated comment for provenance table. +These quantities should be updated whenever there is a change to the schema +structure +The information is only needed when creating a new schema or when +modifying the schema in place +''' +_DB_VERSION_MAJOR = 3 +_DB_VERSION_MINOR = 4 +_DB_VERSION_PATCH = 0 +_DB_VERSION_COMMENT = "Allow dataset.relative_path to be NULL" + +__all__ = ["_DB_VERSION_MAJOR", "_DB_VERSION_MINOR", "_DB_VERSION_PATCH", + "_DB_VERSION_COMMENT"] From ea7837037cbde1129c15ef88642943427131642b Mon Sep 17 00:00:00 2001 From: Joanne Bogart Date: Tue, 25 Feb 2025 21:35:40 -0800 Subject: [PATCH 04/16] placate flake8 --- scripts/create_registry_schema.py | 5 +++-- src/dataregistry/registrar/dataset.py | 10 ++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/scripts/create_registry_schema.py b/scripts/create_registry_schema.py index d007e95f..8c782f15 100644 --- a/scripts/create_registry_schema.py +++ b/scripts/create_registry_schema.py @@ -270,6 +270,7 @@ def _BuildTable(schema, table_name, has_production, production): Model = type(class_name, (Base,), {**columns, **meta}) return Model + # ---------------------------- # Parse command line arguments # ---------------------------- @@ -323,7 +324,7 @@ def _BuildTable(schema, table_name, has_production, production): print(f"Database dialect is '{db_connection.dialect}'") if db_connection.dialect == "sqlite": - print(f"Creating sqlite database...") + print("Creating sqlite database...") schema = None elif schema == prod_schema: print(f"Creating production schema {prod_schema}...") @@ -388,7 +389,7 @@ def _BuildTable(schema, table_name, has_production, production): ): privs = "SELECT" else: - privs = f"SELECT, INSERT, UPDATE" + privs = "SELECT, INSERT, UPDATE" select_prv = ( f"GRANT {privs} ON ALL TABLES IN SCHEMA {schema} to {acct}" ) diff --git a/src/dataregistry/registrar/dataset.py b/src/dataregistry/registrar/dataset.py index 58eeab04..67dbc31a 100644 --- a/src/dataregistry/registrar/dataset.py +++ b/src/dataregistry/registrar/dataset.py @@ -95,6 +95,11 @@ def _validate_register_inputs( "External datasets require either a url or contact_email" ) + # For location_type external or metadata_only, relative_path + # must be none + if kwargs_dict["location_type"] in ["external", "meta_only"]: + kwargs_dict["relative_path"] = None + # Make sure the user passed `relative_path` is legal # Only needed for `register` function, `replace` has no `relative_path` # argument as this cannot be changed from the original `register` @@ -399,7 +404,7 @@ def register( Absolute location of dataset to copy into the data registry. If None, dataset should already be at correct relative_path within - the data registry. + the data registry (for datasets of location_type "dataregistry") verbose : bool, optional Provide some additional output information owner** : str, optional @@ -426,7 +431,8 @@ def register( contact_email**: str, optional test_production: boolean, default False. Set to True for testing code for production owner_type - relative_path** : str, optional + relative_path** : str, optional. Always None for datasets with + location_type "external" or "meta_only" kwargs_dict : dict Stores all the keyword arguments passed to this function (and defaults). Automatically generated by the decorator, do not pass From b05d2e60a6c5d0f376b678f28bef4648a6534c7f Mon Sep 17 00:00:00 2001 From: Joanne Bogart Date: Wed, 26 Feb 2025 14:13:47 -0800 Subject: [PATCH 05/16] Script removing null constraint from dataset.relative_path --- .../update_relative_path_null_constraint.py | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 scripts/schema_migration/update_relative_path_null_constraint.py diff --git a/scripts/schema_migration/update_relative_path_null_constraint.py b/scripts/schema_migration/update_relative_path_null_constraint.py new file mode 100644 index 00000000..f6c94f73 --- /dev/null +++ b/scripts/schema_migration/update_relative_path_null_constraint.py @@ -0,0 +1,69 @@ +import os +import argparse +from sqlalchemy import text +from dataregistry.db_basic import DbConnection +from dataregistry.db_basic import _insert_provenance +from dataregistry.schema.schema_version import ( + _DB_VERSION_MAJOR, + _DB_VERSION_MINOR, + _DB_VERSION_PATCH, + _DB_VERSION_COMMENT +) + +parser = argparse.ArgumentParser( + description="Update specified schema, using specified config, to make dataset.relative_path nullable", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, +) +parser.add_argument("schema", + help="name of schema whose tables are to be modified.") + +home = os.getenv('HOME') +alt_config = os.path.join(home, '.config_100_alt_admin') +parser.add_argument("--config", help="Path to the data registry config file. Determines database (regular or alt) to be modified", default=alt_config) +parser.add_argument("--steps", choices=['mod_schema', 'mod_data', 'both'], + default='mod_schema') +args = parser.parse_args() + +if args.schema.endswith('production'): + assoc_production = args.schema + entry_mode = 'production' +elif args.schema.endswith('working'): + assoc_production = args.schema.replace('working', 'production') + entry_mode = 'working' +else: + raise ValueError('Schema name must end with "production" or "working"') + +query_mode = entry_mode + +db_connection = DbConnection(schema=args.schema, config_file=args.config, + entry_mode=entry_mode, query_mode=query_mode) + +if args.steps in ['mod_schema', 'both']: + # Update the schema: + alter_col = f"alter table {args.schema}.dataset alter column relative_path drop not null" + + print("To be executed: ", alter_col) + with db_connection.engine.connect() as conn: + conn.execute(text(alter_col)) + conn.commit() + + # If we got this far add a row to the provenance table + _insert_provenance( + db_connection, + _DB_VERSION_MAJOR, + _DB_VERSION_MINOR, + _DB_VERSION_PATCH, + "MIGRATE", + comment=_DB_VERSION_COMMENT, + associated_production=assoc_production + ) + +if args.steps in ['mod_data', 'both']: + # Update entries which should have relative_path set to NULL, now that + # it's possible + upd_col = f" update {args.schema}.dataset set relative_path = NULL where location_type in ('external', 'meta_only')" + + print("to be executed: ", upd_col) + with db_connection.engine.connect() as conn: + conn.execute(text(upd_col)) + conn.commit() From 7392f6cbc2575a2f46412e3c39520a600d102330 Mon Sep 17 00:00:00 2001 From: Joanne Bogart Date: Wed, 26 Feb 2025 14:25:15 -0800 Subject: [PATCH 06/16] add a little more to maintainers doc --- docs/source/for_maintainers.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/source/for_maintainers.rst b/docs/source/for_maintainers.rst index 1113e68e..b7d00cbb 100644 --- a/docs/source/for_maintainers.rst +++ b/docs/source/for_maintainers.rst @@ -49,10 +49,13 @@ Test and apply for real *********************** If the update involves changes to the schema you'll need a script to implement -them and also add an entry to the ``provenance`` table. +them and also add an entry to the ``provenance`` table. You'll also need +to update the database version as stored in +`dataregistry/src/dataregistry/schema/schema_version.py`. If the update involves changes to entries stored in the database, you'll need a script for that as well (or if more convenient use a single script for both). -See an example (somewhere). +See examples in the dataregistry GitHub repo under +`dataregistry/scripts/schema_migration/`. Run your script(s) in alt_db, fix any issues, then run in the ``desc_data_registry``. Once you're satisfied everything is ok, From 7f28bee2dedabacd16785a760607546f1063b48b Mon Sep 17 00:00:00 2001 From: Joanne Bogart Date: Wed, 26 Feb 2025 14:42:24 -0800 Subject: [PATCH 07/16] fix path in import --- scripts/create_registry_schema.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/create_registry_schema.py b/scripts/create_registry_schema.py index 8c782f15..9b6cd1ee 100644 --- a/scripts/create_registry_schema.py +++ b/scripts/create_registry_schema.py @@ -18,7 +18,7 @@ load_preset_keywords, DEFAULT_NAMESPACE, ) -from dataregistry.schema_version import ( +from dataregistry.schema.schema_version import ( _DB_VERSION_MAJOR, _DB_VERSION_MINOR, _DB_VERSION_PATCH, From 17ad425f86378e396de14cc03d3805fed57d6c2b Mon Sep 17 00:00:00 2001 From: Joanne Bogart Date: Wed, 26 Feb 2025 17:50:40 -0800 Subject: [PATCH 08/16] Bug fix changing '|' to 'or' --- scripts/create_registry_schema.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/create_registry_schema.py b/scripts/create_registry_schema.py index 9b6cd1ee..f428a335 100644 --- a/scripts/create_registry_schema.py +++ b/scripts/create_registry_schema.py @@ -351,9 +351,9 @@ def _BuildTable(schema, table_name, has_production, production): except Exception: raise RuntimeError("production schema does not exist or is ill-formed") if ( - result["db_version_major"][0] - != _DB_VERSION_MAJOR | int(result["db_version_minor"][0]) - > _DB_VERSION_MINOR + (result["db_version_major"][0] + != _DB_VERSION_MAJOR) or (int(result["db_version_minor"][0]) + > _DB_VERSION_MINOR) ): raise RuntimeError("production schema version incompatible") From 0fb5f4105acb47414734b89e26cc7550f753713e Mon Sep 17 00:00:00 2001 From: Joanne Bogart Date: Wed, 26 Feb 2025 17:57:25 -0800 Subject: [PATCH 09/16] Use new --sqlite option when creating schema for sqlite --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6479b9cc..203c8a9c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -219,7 +219,7 @@ jobs: # Create schema - name: Create data registry default schema run: | - python scripts/create_registry_schema.py --config $DATAREG_CONFIG + python scripts/create_registry_schema.py --config $DATAREG_CONFIG --sqlite # Run CI tests - name: Run CI tests From f93061e1bc6b96b019d299d99df34efda46ab283 Mon Sep 17 00:00:00 2001 From: Joanne Bogart Date: Fri, 7 Mar 2025 15:24:29 -0800 Subject: [PATCH 10/16] fix for rebase. Do not need sqlite argument or associated changes --- scripts/create_registry_schema.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/create_registry_schema.py b/scripts/create_registry_schema.py index f428a335..b5b550e2 100644 --- a/scripts/create_registry_schema.py +++ b/scripts/create_registry_schema.py @@ -308,10 +308,20 @@ def _BuildTable(schema, table_name, has_production, production): # ------------------ # What schemas are we creating? +<<<<<<< HEAD if args.create_both: schema_list = [args.production_schema, args.schema] else: schema_list = [args.schema] +======= +if args.sqlite: + schema_list = [None] +elif args.create_both: + schema_list = [args.production_schema, args.schema] +else: + schema_list = [args.schema] + +>>>>>>> 3af7aa1 (one last fix for sqlite) prod_schema = args.production_schema # Load the preset keywords From 2cafd74ee46cac976183679ffeb313fe1c252fcd Mon Sep 17 00:00:00 2001 From: Joanne Bogart Date: Thu, 27 Feb 2025 11:32:34 -0800 Subject: [PATCH 11/16] address some reviewer comments --- .../{for_maintainers.rst => database_upgrades.rst} | 9 ++++----- docs/source/index.rst | 3 ++- src/dataregistry/registrar/dataset.py | 6 +++++- 3 files changed, 11 insertions(+), 7 deletions(-) rename docs/source/{for_maintainers.rst => database_upgrades.rst} (95%) diff --git a/docs/source/for_maintainers.rst b/docs/source/database_upgrades.rst similarity index 95% rename from docs/source/for_maintainers.rst rename to docs/source/database_upgrades.rst index b7d00cbb..d82a2db9 100644 --- a/docs/source/for_maintainers.rst +++ b/docs/source/database_upgrades.rst @@ -1,10 +1,9 @@ -.. _maintenance -Maintenance -=========== +Database Upgrades +================= + +.. _database_upgrades -Procedure for Database Upgrades -------------------------------- Creating an alternate database ****************************** diff --git a/docs/source/index.rst b/docs/source/index.rst index 94e16787..9e3761a7 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -25,7 +25,7 @@ Getting started This documentation is to help you get set up using the ``dataregistry`` Python package; covering installation, how to register datasets, and how to query for -them. +them. .. toctree:: :maxdepth: 2 @@ -61,6 +61,7 @@ them. dev_notes_spin dev_notes_database installation_locally + database_upgrades .. toctree:: :maxdepth: 2 diff --git a/src/dataregistry/registrar/dataset.py b/src/dataregistry/registrar/dataset.py index 67dbc31a..9ba20910 100644 --- a/src/dataregistry/registrar/dataset.py +++ b/src/dataregistry/registrar/dataset.py @@ -453,7 +453,11 @@ def register( self._compute_version_string(name, version, kwargs_dict) # If `relative_path` not passed, automatically generate it - if kwargs_dict["relative_path"] is None: + # But for location types "external" and "meta_only" it should + # be None + if kwargs_dict["location_type"] in ["external", "meta_only"]: + kwargs_dict["relative_path"] = None + elif kwargs_dict["relative_path"] is None: kwargs_dict["relative_path"] = _relpath_from_name( name, kwargs_dict["version_string"], kwargs_dict["old_location"] ) From 35cd1e618d590bbc274bfb34ea6eb39618ab6f5d Mon Sep 17 00:00:00 2001 From: Joanne Bogart Date: Fri, 7 Mar 2025 15:32:36 -0800 Subject: [PATCH 12/16] remove --sqlite option, which no longer exists --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 203c8a9c..6479b9cc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -219,7 +219,7 @@ jobs: # Create schema - name: Create data registry default schema run: | - python scripts/create_registry_schema.py --config $DATAREG_CONFIG --sqlite + python scripts/create_registry_schema.py --config $DATAREG_CONFIG # Run CI tests - name: Run CI tests From d695650283795ba243b90dc4a1c81864e81940ce Mon Sep 17 00:00:00 2001 From: Joanne Bogart Date: Fri, 7 Mar 2025 15:53:12 -0800 Subject: [PATCH 13/16] clean up after rebase --- scripts/create_registry_schema.py | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/create_registry_schema.py b/scripts/create_registry_schema.py index b5b550e2..c3e20b11 100644 --- a/scripts/create_registry_schema.py +++ b/scripts/create_registry_schema.py @@ -321,7 +321,6 @@ def _BuildTable(schema, table_name, has_production, production): else: schema_list = [args.schema] ->>>>>>> 3af7aa1 (one last fix for sqlite) prod_schema = args.production_schema # Load the preset keywords From d709caefacd4270f2e6133152c57d80d69294dbd Mon Sep 17 00:00:00 2001 From: Joanne Bogart Date: Fri, 7 Mar 2025 16:03:28 -0800 Subject: [PATCH 14/16] more clean up after rebase --- scripts/create_registry_schema.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/scripts/create_registry_schema.py b/scripts/create_registry_schema.py index c3e20b11..f428a335 100644 --- a/scripts/create_registry_schema.py +++ b/scripts/create_registry_schema.py @@ -308,19 +308,10 @@ def _BuildTable(schema, table_name, has_production, production): # ------------------ # What schemas are we creating? -<<<<<<< HEAD if args.create_both: schema_list = [args.production_schema, args.schema] else: schema_list = [args.schema] -======= -if args.sqlite: - schema_list = [None] -elif args.create_both: - schema_list = [args.production_schema, args.schema] -else: - schema_list = [args.schema] - prod_schema = args.production_schema # Load the preset keywords From 6cfda6d9db0b3011ea015e8ace7dc318a0278320 Mon Sep 17 00:00:00 2001 From: Joanne Bogart Date: Mon, 10 Mar 2025 11:09:34 -0700 Subject: [PATCH 15/16] Bump code version to 1.2.0 --- CHANGELOG.md | 10 +++++++++- src/dataregistry/_version.py | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a49e3cf7..53eaf513 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## Version 1.2.0 + +- Make `dataset.relative_path` nullable +- Adjust code to set `dataset.relative_path` to null for datasets of + location type `exteranl` and `meta_only` +- Add documentation for in-place database upgrades +- Add script for making db upgrade + ## Version 1.1.1 - Move `get_keyword_list()` function to the `Query()` class. @@ -111,7 +119,7 @@ list the proper join would not be made. This has been corrected. ## Version 0.5.3 - Update the `schema.yaml` file to include unique constraints and table - indexes. + indexes. - Update the unique constraints for the dataset table to be `owner`, `owner_type`, `name`, `version`, `version_suffix`. diff --git a/src/dataregistry/_version.py b/src/dataregistry/_version.py index a82b376d..a955fdae 100644 --- a/src/dataregistry/_version.py +++ b/src/dataregistry/_version.py @@ -1 +1 @@ -__version__ = "1.1.1" +__version__ = "1.2.1" From 211fbf982efd053693b8363c763e3740422d42dc Mon Sep 17 00:00:00 2001 From: Joanne Bogart Date: Mon, 10 Mar 2025 11:13:30 -0700 Subject: [PATCH 16/16] fix typo in version --- src/dataregistry/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dataregistry/_version.py b/src/dataregistry/_version.py index a955fdae..c68196d1 100644 --- a/src/dataregistry/_version.py +++ b/src/dataregistry/_version.py @@ -1 +1 @@ -__version__ = "1.2.1" +__version__ = "1.2.0"