{ "info": { "author": "Adam Griffiths", "author_email": "UNKNOWN", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Natural Language :: English", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Programming Language :: Python", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "\n\n======\nEXODUS\n======\n\n.. image:: https://travis-ci.org/someones/exodus.svg?branch=master\n :target: https://travis-ci.org/someones/exodus\n\nMass Migrations for all!\n\nExodus is a simple framework that allows you to define data migrations and apply\nthem to an entire data store, or individual objects.\n\nExodus does not know anything about your data store, instead each migration\nprovides the logic for accessing the data store.\n\nThe ability to migrate an entire data store, or a single object at a time, enable\nExodus to update data at read time, or through a batch process.\n\nExodus reads python files from a specified directory, migration objects are\nautomatically registered and sorted by version.\n\nBy not providing extensive abstractions, Exodus allows *you* to migrate your data\nthe way *you* want to. You won't have to fight Exodus.\n\n\nHow to Use\n==========\n\nCreate a database migration module - './migrations' by default - and add a migration\nfile.\nA specific filename format is not required, but it is recommended to use either\nthe current date, an incrementing number, or both, as the prefix followed by a short\ndescription.\n\nEg:\n\n* 2015_10_12_add_address_to_user.py\n* 01_add_address_to_user.py, 02_add_rating_to_movie.py\n\n\nA migration should inherit from BaseMigration and must define a number of variables\nand methods::\n\n from exodus import BaseMigration\n\n class Migration(BaseMigration):\n # used to sort the migrations, recommended to use a string that matches\n # the filename's unique prefix.\n version = '2015_10_20'\n\n # an optional list of class name variables that are used to check if\n # an object should be migrated. These values should match the\n # class.__name__ value of the class / object to be migrated.\n # the logic that uses this can be modified by over-riding the\n # `can_migrate_object` method\n classes = ['TestObject']\n\n def can_migrate_database(self, adapter):\n '''Returns True if the database can be migrated, False otherwise.\n This function should use your own logic to check the database version\n or other 'signal' that the migration is appropriate for your database.\n '''\n return self.version > adapter['version']\n \n def migrate_database(self, adapter):\n '''Performs a full migration on the database.\n This can include moving or updating objects.\n For each object requiring a migration, the method `migrate_object` should\n be called.\n By default, migrate_object will look for a function matching `migrate_`.\n If the `classes` variable defines a class name, but there is no corresponding `migrate_`,\n an exception will be thrown on construction.\n Before calling `migrate_`, a check if made for a function matching\n the name `can_migrate_`, if found (it is entirely optional to define)\n it is called with the object as a parameter. If False, the migration is\n not performed.\n Ensure any migration version signals are set at the end of the function.\n '''\n adapter['objects'] = adapter['old_objects']\n del adapter['old_objects']\n \n for obj in adapter['objects']:\n self.migrate_object(obj)\n adapter['version'] = self.version\n \n def can_migrate_TestObject(self, obj):\n '''Called when an object of type TestObject is sent to `migrate_object`.\n Returns True if the migration should be applied to the object.\n This function is entirely optional. If not defined, the migration will be\n performed regardless.\n '''\n return obj.version < self.version\n \n def migrate_TestObject(self, obj):\n '''Performs a migration on the object.\n If the `classes` variable defines a class name, but there is no corresponding `migrate_`,\n an exception will be thrown on construction.\n Ensure any migration version signals are set at the end of the function.\n '''\n obj.my_value = obj.my_value + 1\n obj.version = self.version\n return obj\n\n\nOverriding Migration Logic\n==========================\n\nAt times the default migration logic is not appropriate.\nThe majority of the intelligence is located in the BaseMigration class to\nallow you to over-ride logic whenever required.\n\nFor example, you could modify a Migration to work on serialised JSON data\nrather than Python classes like so::\n\n class JsonMigration(BaseMigration):\n def can_migrate_object(self, obj):\n if not self.classes:\n return False\n # the class name is stored in the __class__ value of the dict\n obj = json.loads(obj)\n clsname = obj['__class__']\n return clsname in self.classes\n\n def migrate_object(self, obj):\n # load the string\n parsed = json.loads(obj)\n\n # get the object class name and dispatch to the appropriate function\n clsname = parsed['__class__']\n\n # check if we can migrate the object\n # this is an optional function\n func = self._can_migrate_object_func(clsname)\n if func:\n if not func(parsed):\n return obj\n\n # perform the migration\n func = self._migrate_object_func(clsname)\n if func:\n parsed = func(parsed)\n # convert back to a string\n return json.dumps(parsed)\n\n def can_migrate_TestObject(self, obj):\n return obj['version'] < self.version\n\n def migrate_TestObject(self, obj):\n obj['my_value'] = obj['my_value'] + 1\n obj['version'] = self.version\n return obj\n\nAuthors\n=======\n\n* `Adam Griffiths `_\n", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/adamlwgriffiths/exodus", "keywords": null, "license": "BSD", "maintainer": null, "maintainer_email": null, "name": "exodus", "package_url": "https://pypi.org/project/exodus/", "platform": "any", "project_url": "https://pypi.org/project/exodus/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/adamlwgriffiths/exodus" }, "release_url": "https://pypi.org/project/exodus/1.0.8/", "requires_dist": null, "requires_python": null, "summary": "A light-weight, storage agnostic, data migration framework", "version": "1.0.8" }, "last_serial": 2722334, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "c4a205deac0d2e6877a73c97772a1404", "sha256": "0f1c654e533bdce3347f7f671ac56df05fbc9ca8fd3ba8f128e2ee7a1d75323a" }, "downloads": -1, "filename": "exodus-1.0.0.tar.gz", "has_sig": false, "md5_digest": "c4a205deac0d2e6877a73c97772a1404", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4289, "upload_time": "2015-10-21T06:12:45", "url": "https://files.pythonhosted.org/packages/7d/a1/1a2a1ccf39537b0845e859d04ab1d98dcaa43ad537240f5814bd31805cbb/exodus-1.0.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "18cf26219b39e2f95d44ba5cfb23a1a4", "sha256": "1e43c58d22c79e12e707658c9338fff0358e9e3f28549fdaaee92ddadfa658c0" }, "downloads": -1, "filename": "exodus-1.0.1.tar.gz", "has_sig": false, "md5_digest": "18cf26219b39e2f95d44ba5cfb23a1a4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4378, "upload_time": "2015-10-21T23:35:04", "url": "https://files.pythonhosted.org/packages/2e/99/c832a6f540973eaabd811c5af637474462f453fa8a1754c05365f5a7f7c3/exodus-1.0.1.tar.gz" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "6c3961a611970ebd021af691a1cd92c2", "sha256": "0e5f5377f9b5095de689c10d045e4baa65c93700175fdc10de4eb28c61a06da5" }, "downloads": -1, "filename": "exodus-1.0.2.tar.gz", "has_sig": false, "md5_digest": "6c3961a611970ebd021af691a1cd92c2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4397, "upload_time": "2015-10-22T03:43:45", "url": "https://files.pythonhosted.org/packages/54/e5/07f7b9f1f46951014da4ef36404c02978879520ac9c92d98c784213bfb4a/exodus-1.0.2.tar.gz" } ], "1.0.3": [ { "comment_text": "", "digests": { "md5": "cbc7e7835e6d24164633be004bd63913", "sha256": "1b053ea0283ff796884254f881c408ab1fd9751420ef81e5bc04ecd2f7729d7d" }, "downloads": -1, "filename": "exodus-1.0.3.tar.gz", "has_sig": false, "md5_digest": "cbc7e7835e6d24164633be004bd63913", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4440, "upload_time": "2015-10-22T04:28:01", "url": "https://files.pythonhosted.org/packages/75/3b/9817a8b4b128725e8af650435b4ff9223f238bd16358fd3d3fce610cea71/exodus-1.0.3.tar.gz" } ], "1.0.4": [ { "comment_text": "", "digests": { "md5": "dea6a27445676de21dd4b684c2d5d52b", "sha256": "e260cd48997211750819c906d734f4c62591da90a4df72b2b0944b22af055c54" }, "downloads": -1, "filename": "exodus-1.0.4.tar.gz", "has_sig": false, "md5_digest": "dea6a27445676de21dd4b684c2d5d52b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4447, "upload_time": "2015-10-22T05:22:31", "url": "https://files.pythonhosted.org/packages/fb/88/2fc1042024e44a2b605d9d8575a299e029e7edf0527b2a064af8d833802d/exodus-1.0.4.tar.gz" } ], "1.0.5": [ { "comment_text": "", "digests": { "md5": "aa70c2e4f6e273c515b684763eb7320a", "sha256": "df2f324950cd4c97f1b52da3450f4b49253defab343423d8345f6f3c2eafc58b" }, "downloads": -1, "filename": "exodus-1.0.5.tar.gz", "has_sig": false, "md5_digest": "aa70c2e4f6e273c515b684763eb7320a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4278, "upload_time": "2015-10-25T23:41:55", "url": "https://files.pythonhosted.org/packages/77/62/a1e917c3c78ab8ef7ce3d23609d4377b3438ee4951b6c1d314b58b9dde29/exodus-1.0.5.tar.gz" } ], "1.0.6": [ { "comment_text": "", "digests": { "md5": "a49624564a18ffba11ce7f2f5034c3c0", "sha256": "aa0d6d9b79c391f7213526e73fba3d0b027224efcd232749f77e2cd9a81b9baa" }, "downloads": -1, "filename": "exodus-1.0.6.tar.gz", "has_sig": false, "md5_digest": "a49624564a18ffba11ce7f2f5034c3c0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4278, "upload_time": "2015-10-26T00:36:56", "url": "https://files.pythonhosted.org/packages/85/c9/a45181a81fffa0d99d7a60595140d33f900314679f33f991b0f5a2024a5c/exodus-1.0.6.tar.gz" } ], "1.0.7": [ { "comment_text": "", "digests": { "md5": "8aff6a5b36cf81c395ab8bd61f5ee197", "sha256": "68b520adc747beeb97a146333f4df9128c1e802f8a180694c327d3924327c0e4" }, "downloads": -1, "filename": "exodus-1.0.7.tar.gz", "has_sig": false, "md5_digest": "8aff6a5b36cf81c395ab8bd61f5ee197", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4311, "upload_time": "2015-10-26T04:13:54", "url": "https://files.pythonhosted.org/packages/88/a8/cebc734e91e576e88b12d3527327716233fe9925f172b187d2537d854f9f/exodus-1.0.7.tar.gz" } ], "1.0.8": [ { "comment_text": "", "digests": { "md5": "da4f78e114ced2a9752348092a9d7cea", "sha256": "311664b847f5d70346356b8f7331aaf452e05e6c755662b83c0747b2dea33199" }, "downloads": -1, "filename": "exodus-1.0.8.tar.gz", "has_sig": false, "md5_digest": "da4f78e114ced2a9752348092a9d7cea", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4362, "upload_time": "2017-03-22T05:39:40", "url": "https://files.pythonhosted.org/packages/9b/42/9b9d593628dbbba36930530a13bcf39fbfb83e86841ce111990863a3700e/exodus-1.0.8.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "da4f78e114ced2a9752348092a9d7cea", "sha256": "311664b847f5d70346356b8f7331aaf452e05e6c755662b83c0747b2dea33199" }, "downloads": -1, "filename": "exodus-1.0.8.tar.gz", "has_sig": false, "md5_digest": "da4f78e114ced2a9752348092a9d7cea", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4362, "upload_time": "2017-03-22T05:39:40", "url": "https://files.pythonhosted.org/packages/9b/42/9b9d593628dbbba36930530a13bcf39fbfb83e86841ce111990863a3700e/exodus-1.0.8.tar.gz" } ] }