{ "info": { "author": "Anybox", "author_email": "contact@anybox.fr", "bugtrack_url": null, "classifiers": [], "description": "================================\nFast OpenERP migration framework\n================================\n\n.. warning:: Reminder\n This tool is complex and highly experimental and is distributed in the hope\n that it **might** be useful, but WITHOUT ANY WARRANTY of FITNESS FOR A\n PARTICULAR PURPOSE. In particular, if you're using OpenERP for your company,\n you should consider purchasing an OpenERP Enterprise contract that will provide\n you with the best and riskless migration path for your database and custom\n developments.\n\n.. contents::\n\nThis tool has been developped with these initial goals in mind, in this\npriority order:\n\n - **Merging** 2 different OpenERP databases into a single multicompany db\n - **Migrating** from OpenERP 6.1 to 7.0\n - Migrating data from a legacy business application (Access, Delphi, etc.)\n - Migrating from Dolibarr to OpenERP\n\nThe principle of this tool is to export CSV data from an old application (only\nOpenERP for now), then to process CSV files in order to import them into a\nfreshly installed OpenERP database. This is a completely different strategy\nthan the in-place migration of OpenERP or OpenUpgrade and allows to start over\nfrom a clean database, while keeping history. Import and export are done with\nthe PostgreSQL-specific COPY command, and results in extremely fast exports and\nimports. Combined with a pure in-memory Python csv processing, this tool can\noften achieve overall migration rates over 2000 lines/sec.\n\n\nInstallation\n============\n\nThis tool only works with **Python 2.7**!\n\nWith virtualenv\n---------------\n::\n\n $ virtualenv sandbox\n $ sandbox/bin/pip install anybox.migration.openerp\n $ sandbox/bin/migrate -h\n\nWith Buildout\n-------------\n\nIf you're using Buildout, you may add this tool in a new part like this::\n\n [migration]\n recipe = zc.recipe.egg\n eggs = anybox.migration.openerp\n\nThen, don't forget to add the ``migration`` section in the ``parts`` of the\n``[buildout]`` section. After relaunching ``bin/buildout``, the ``migrate``\nscript will appear in the ``bin`` directory of the buildout.\n\nStarting from the version 1.7 of the `OpenERP buildout recipe\n`_ You may also install\nthis tool directly in your ``[openerp]`` part, just by adding::\n\n eggs = anybox.migration.openerp\n scripts = migrate\n\nUsage\n=====\n\nThis tool offers a single ``migrate`` script::\n\n $ migrate -h\n\nYou can list the available default mapping files::\n\n\n $ migrate -l\n openerp6.1-openerp7.0.yml\n\nYou should specify the source and target DBs, a selection of the source tables\nto migrate, and the mapping files to use. The tool then takes care of\nselecting the dependant tables::\n\n $ migrate -s source_dbname -t target_dbname -r res_partner account_move -p openerp6.1-openerp7.0.yml custom.yml\n\nIf you want to inspect the temporary CSV files created, use the ``--keepcsv``\noption. They will be stored in a temporary directory under the current\ndirectory.\n\nThis script won't actually write anything in the target database unless you\nspecify the ``-w`` option to commit the transaction at the end.\n\nThe most important part of the migration process is the YML mapping file, which\ndescribes how to handle data, table by table and column by column. A default\nmapping file is provided and is being used as a real mapping for a migration\nconsisting in migrating two 6.1 databases into a single 7.0 multicompany\ndatabase. You can mix the default 6.1 to 7.0 file provided, and augment it\nwith other custom yml files, they will be merged.\n\n\nInternals\n=========\n\nThis tool was very loosely inspired from:\n\n - the external_referential OpenERP module\n - the OpenUpgrade project\n - Talend Open Studio\n\nThe different internal steps are:\n\n - Exporting CSV from the old database\n - Transforming CSV to match the target database\n - Detect data existing in the target DB with discriminators\n - Postprocessing CSV files to fix foreign keys\n - Reinjecting into OpenERP\n - Updating possible pre-existing data with incoming data\n\nThe processing of CSV files is done using a mapping file written in Yaml.\nInitial versions of the mapping file have been written with the help of the\nOpenUpgrade analysis files.\n\n\nMapping file\n============\n\nYou should keep in mind that this migration tool is only dealing with database\ntables and columns: the OpenERP fields are unknown to it. Each table,\neach line, each cell of the source database is handled independently and the\nmapping file tells what to do with the current cell. This leads to limitations\nand this tool won't be able to handle extremely complex migration. But it\nis powerful enough to allow to simultaneously merge and migrate two 6.1\ndatabases into a 7.0 multicompany database.\n\nFor a real-life example, you can have a look at the OpenERP 6.1 to 7.0 mapping\nfile provided in the ``mappings`` directory of this tool.\n\nCopying data\n------------\n\nThe most simple and basic YML statement for a column mapping is the following::\n\n module:\n table1.column1:\n table2.column2: __copy__\n\nIt tells that, if the OpenERP ``module`` is installed in the **target**\ndatabase, the ``column1`` of the ``table1`` from the source DB should be copied\nto the ``column2`` of the ``table2`` in the target DB.\n\nThe ``__copy__`` instruction can even be omitted and the previous statement is\nequivalent to this one::\n\n module:\n table1.column1:\n table2.column2:\n\nInternally, this statement is actually converted to a Python dict::\n\n {'module':\n {'table1.column1':\n {'table2.column2': '__copy__'}}\n\nAnd the whole yml file is converted to a large mapping dict whose leafs are\nstatements or functions which are able to process data.\n\nCopying all columns of a table\n------------------------------\n\nIf your target table has the same structure as the source table, you can avoid\nspecifying one mapping statement for each column and use a wildcard::\n\n module:\n table1.*:\n\nIt means: copy all the columns of table1 from the source db to table1 in the\ntarget db. This kind of mapping is often used as a starting point when source\nand table structures are similar. You can then add mapping statements for\nspecific columns to override this wildcard.\n\nCopying all columns to a different table\n----------------------------------------\n\nIf the source table has only been renamed, you can copy all the columns of the\nsource table1 to the target table2::\n\n module:\n table1.*:\n table2.*:\n\nCopying everything\n------------------\n\nIf the source and target db have exactly the same structure and you just want\nto transfer data, you may use a global wildcard (but we have not had the\nopportunity to try this one for real yet)::\n\n module:\n .*:\n\nIt means: copy all tables to the target database without processing. It may\nseem unuseful compared to a bare dump and restore, but remind that this way you\ncan append data to the target DB, not only replace it. In that case you should\ntake care of existing data, if the table has constraints (see discriminators\nbelow)\n\nSplitting one source line to several tables (table splitting)\n-------------------------------------------------------------\n\nFor a single source line coming from a source table, you can feed data in\nseveral target tables. This can be done just by putting several target lines\nlike this::\n\n module:\n table1.column1:\n table2.column2:\n table3.column3:\n\nIt means: for each ``column1`` in the ``table1`` of the source DB, create two\ntarget lines: one for ``table2`` and one for ``table3``.\n\nDuring the processing of the current line, other mapping statements\ncan feed the same target lines. Take this example::\n\n module:\n table1.column1:\n table2.column2:\n table3.column3:\n table1.column2:\n table2.column2:\n table3.column4:\n\nIn this case, data in the ``table1`` will be directed to ``table2`` and\n``table3``. You can then add more lines to handle all the columns of ``table1``\n\nHowever in the example above, there is a conflict since two source cells are directed\nto the same target cell (``table2.column2``). In this scenario, there is no way to\npredict which one will be used (because the mapping is a Python *dict* and a dict is not\nordered). You should avoid this kind of conflicts.\n\nIn case of an OpenERP 6.1 to 7.0 migration, this kind of mapping is actually\nused to migrate one source ``res_users`` line to three different lines: one in\n``res_users`` + one in ``res_partner`` + one in ``mail_alias``. See the default\nmapping for a real example.\n\nData moved to another table (table merging)\n-------------------------------------------\n\nWhen input lines must move to a different table, you want the foreign keys\npointing to them to be kept so that they point to the new table after\nmigration, you should use the ``__moved__`` statement.\n\nThe only current situation in OpenERP is for the ``res_partner_address`` data\nmoving to the ``res_partner`` table::\n\n base:\n res_partner_address.id:\n res_partner.id: __moved__\n\nThis statement must be accompanied with a ``__fk__`` statement for all the\nforeign keys pointing to the moved table (See the ``__fk__`` chapter).\n\nNot migrating a column\n----------------------\n\nIf you want to get rid of a specific column in a table, use the ``__forget__``\nstatement::\n\n module:\n table1.column1: __forget__\n\nThis statement is useful if you defined a wildcard, to prevent from migrating a\nspecific column.\n\n\nTransforming data with Python code\n----------------------------------\n\nInstead of just copying data with the ``__copy__`` statement, you can use any\nPython code. The Python code should be written in a literal Yaml block and is\nexecuted as is, as a function body, so that you have to insert a ``return``\nstatement somewhere.\n\nExample from the ``mail`` module::\n\n mail:\n mail_message.type:\n mail_message.type: return 'email'\n\nIt means the ``type`` column of the ``mail_message`` table will be filled with\n``'email'`` strings, whatever data the source column had.\n\nThe eventual signature of the function constructed using the Python code block is ::\n\n def mapping_function(self, source_row, target_rows):\n\nIt means that in the function body you can access the full ``source_row``,\nwhich is a dict containing all the keys (column names) and values of the\ncurrent line being processed. But keep in mind that at this time, you are\ndealing with one specific cell of this line, and you should return the value\nthat will be inserted in the corresponding cell of the target table. This can\nbe used to aggregate data from two source cells into a target cell::\n\n base:\n table1.firstname: __forget__\n table1.name:\n table1.name: return source_row['firstname'] + ' ' + source_row['name']\n\nYou can also access the ``target_rows`` beeing filled during the processing of\nthe line, so that data coming from a source cell can influence several cells in\nthe target lines, or even different target tables. Here is an example::\n\n base:\n table1.id:\n table1.id:\n table2.id:\n table1.name:\n table1.name: |\n name = source_row['firstname'] + ' ' + source_row['name']\n target_rows['table1']['display_name'] = name\n target_rows['table2']['display_name'] = name\n return name\n table2.name\n\nNote that in the example above, the Python code spans on several lines, and you\nshould define a Yaml literal block using ``|``. The example above eventually\nmeans: append ``firstname`` to ``name`` coming from the ``table1``, and put it\nin the ``display_name`` cell of the target ``table1`` and ``table2``. The\ntarget ``name`` cell will contain a copy of the source ``name`` cell.\n\nIf the target line is not supposed to have the same *id* as the source line,\nyou can create a new *id* with the newid() function. This function returns a\ndifferent value at each call and is responsible of incrementing the *id*. Here\nis an example::\n\n base:\n res_users.id:\n res_users.id:\n res_users.partner_id:\n res_partner.notification_email_send: return 'comment'\n res_partner.id: |\n i = newid()\n target_rows['res_users']['partner_id'] = i\n target_rows['res_partner']['id'] = i\n target_rows['res_partner']['name'] = source_row['name']\n target_rows['res_partner']['email'] = source_row['user_email']\n return i\n\nEach ``res_users`` line will generate a new ``res_partner`` line with a new\n*id*, while the ``res_users`` *id* will be the same as the source. (Actually it\nwill not be the same, because an offset is applied to all ids).\n\nFeeding a new column\n--------------------\n\nIf a target column should contain data but has no equivalent in the source\ntable, you can use '_' as a substitute to the not existing source column name::\n\n base:\n res_partner._:\n res_partner.is_company: return False\n\n\nMerging with existing data\n--------------------------\n\nWhen data is inserted in the target table, you may want to merge it with\nexisting data.\n\nImagine the target ``res_users`` table already contains an\n``admin`` account, and you don't want to duplicate this account by migrating\ndata from the source ``res_users`` table. In this case you should tell the\nmapping how to recognize existing data. This is done by replacing the\nsource column name with the ``__discriminator__`` statement, and by providing a\nlist of column names that will be used to recognize existing data::\n\n base:\n res_users.__discriminator__:\n - login\n\nUsing this statement, you can install a new OpenERP database with its admin\naccount, and merge all existing accounts with data coming from the source\ntable. The ``login`` column will be used to match data. The preexisting *admin*\naccount won't be duplicated but will be updated with the *admin* account from\nthe source table.\n\nAnother use case in a multicompany scenario is to merge partners existing in\nthe target database, but keep them separate for the two companies::\n\n base:\n res_partner.__discriminator__:\n - name\n - company_id\n\nForeign keys without constraints\n--------------------------------\n\nThe first step of the migration is to automatically detect all the foreign keys\nof the source and target tables. Sometimes, OpenERP defines foreign keys\nwithout constraints. This mainly happens with *related* fields with\n``store=True``, which create a column of integers without constraints. If you\ndon't want to ``__forget__`` such columns, you have to tell the mapping what\nthe target of the foreign key is, like in the real example below::\n\n account:\n account_move.company_id:\n account_move.company_id: __fk__ res_company\n\n\nHere is another example for the ``crm_lead`` table, which may contain a field\ncoming from a ``__moved__`` table. Imagine you want the ``partner_id`` field of\nthe CRM leads in OpenERP 7.0 to come from the ``partner_address_id`` field of\nthe same table in OpenERP 6.1. The new field is a foreign key to\n``res_partner``, while the old one was pointing to ``res_partner_address``. You\ncan tell this with the following statement::\n\n crm_lead.partner_address_id:\n crm_lead.partner_id: __fk__ res_partner_address\n\nHowever you should also not forget to forget the partner_id field, or you will\nhave a conflict an mix data badly if you used a wildcard for the table::\n\n crm_lead.*:\n crm_lead.partner_id: __forget__\n\nReference fields\n----------------\n\nSometimes columns define a dynamic reference id to another table, just like a\nforeign key, except that the name of the table is actually stored in another\ncolumn.\n\n=== ================= =======\nid model res_id\n=== ================= =======\n1 cr.claim 23\n2 cr.claim 35\n3 base.action.rule 27\n=== ================= =======\n\nIn the example above, since the ``res_id`` is not a real foreign key, its value\nwon't be fixed to correspond to the target database. In that case you should\nuse the ``__ref__`` statement, followed by the name of the column holding the\ntable or model name. This statement assumes the model-to-table transformation\nof OpenERP is used (replacing '.' with '_')::\n\n\n mail_message.res_id:\n mail_message.res_id: __ref__ model\n\n\nHandle cyclic dependant tables\n------------------------------\n\nDuring the last step, the migrated CSV files are imported one by one. Some\ntables depend on other tables through foreign key constraints, and such\ndependencies sometimes happen to be cyclic. In that case, there is no way to\nimport tables because they all depend on another one. One solution is to\n``__forget__`` the column, which is rarely desirable because you lose data. To\nbe able to keep such data, you should use the ``__defer__`` statement, so that\nthe column will be updated after all the data is imported::\n\n base:\n res_users.create_uid:\n res_users.create_uid: __defer__\n res_users.write_uid:\n res_users.write_uid: __defer__\n\nrunning SQL requests during migration\n-------------------------------------\n\nIn case the wanted migration is too complex to be handled by regular\nstatements, you can run SQL queries on both the source and target database.\nThis should be used in limited cases because the queries will be executed for\neach source cell for which the mapping defines it, and the migration may be\nslowed down, unless you limit the queries with manual caching. (See the\nworkflow migration in the mapping).\n\nA simple sql() function is available in the mapping file, and has the following signature::\n\n sql(db, query, args)\n\n where:\n - db is the string 'source' or 'target'\n - query is the SQL query\n - args is the arguments to insert in the query\n The query is actually executed with: cursor.execute(query, args)\n\nHere is an example::\n\n base:\n res_users._:\n (...)\n mail_alias.alias_model_id: return sql('target', \"select id from ir_model where model='res.users'\")[0][0]\n\nField size limit\n----------------\n\nWhen running migration, you may encounter a ``csv.Error: field larger than\nfield limit``. This is due to the csv module limiting the csv field size to\n128k by default. The default value has been increased to 20MB. If this is not\nenough for your migration, you can increase the limit by inserting a direct\ncall to ``csv.field_size_limit()``.\n\nFor example::\n\n module:\n table1.column1:\n table2.column2: |\n import csv\n csv.field_size_limit(262144)\n return source_row['column1']\n\n\nOverall migration process\n=========================\n\nMigrating need several steps described below. If you need, you can easily write\na small script to automate this full process.\n\nBefore migration\n----------------\n\nThe different steps before migration are the following. All of them are\nimportant for the migration to be successful and should be done on the target db:\n\n- Create a clean target database without demo data, using the latest migrated code\n- Install the expected modules\n- Rename the target company so that its name exactly match the company in the source database\n- Remove the company of all internal sequences by running the following SQL:\n ``update ir_sequence set company_id=NULL;``. This will allow to remove duplicate after migration.\n\nMigration\n---------\n\nThe migration consists in running the ``migrate`` script by selecting the\ncorrect options. If the data in the target database are not the one you expect,\nyou must adapt the options and the mapping file to obtain what you want.\n\nHere is a real example ::\n\n ../bin/migrate -s sourcedb -t targetdb -p openerp6.1-openerp7.0.yml custom.yml\n -r res_partner account_move res_users pos_order pos_order_line account_move_line\n account_journal sale_order_line stock_inventory_line account_tax\n product_supplierinfo wkf_instance wkf_workitem wkf_triggers -w\n\nAfter migration\n---------------\n\nThe ``migrate`` script alone may not be sufficient for your database to be\nclean and usable. You may have to handle additional corrections. Please test\nyour instance thoroughly! Since version 0.6 you shouldn't have to manually fix\nthe internal sequences, as they are now handled by the mapping file. You may\njust clean them up to remove duplicates (from the menu\nSettings/Technical/Sequences&Identifiers/Sequences). However one of the\nrequired remaining fixes consists in dropping some ``parent_left`` and\n``parent_right`` columns. Here is the example with the accounting module::\n\n psql targetdb -c 'alter table account_account drop parent_left;'\n psql targetdb -c 'alter table account_account drop parent_right;'\n\nYou might also need to force a recalculation of new or changed related fields\nthat are persisted in the database (store=True). Here is an example with \nthe account_report_company module::\n\n psql targetdb -c 'alter table account_invoice drop commercial_partner_id;'\n\nAt the end, you should run a final global update of the database.\nIf you're using the `buildout recipe `_ it should look like this::\n\n ../bin/start_openerp -u all -d targetdb --stop-after-init\n\n\nUnderstanding errors\n====================\n\nThe most difficult part of using this tool is to understand the errors during\nthe processing, as it requires a deep knowledge of how it internally works.\nMost errors generally come from an erroneous mapping file. Errors can happen\nduring the processing of the CSV files, but the most difficult ones come from\nthe last import step, because some tables may fail to be imported. In this\ncase, you should carefully look at the logging messages at the end, and try to\nunderstand the constraint errors or why tables cannot be imported. You also\nshould use the ``--keepcsv`` option, and inspect the intermediate CSV files to\nunderstand the problem. By using this option, you will end up with a directory\ncontaining five CSV files for each table.\n\nFor instance, for the ``res_partner`` table you will find these files:\n\n - **res_partner.csv** is the original data exported from the source\n database\n - **res_partner.target.csv** contains data after the first processing with\n the mapping file, but wrong foreign keys\n - **res_partner.target2.csv** contains final data with fixed foreign keys,\n that will eventually be imported at the end\n - **res_partner.update.csv** contains data which have been detected as\n existing in the target database, with wrong foreign keys.\n - **res_partner.update2.csv** contains the final existing data with fixed\n foreign keys, that will be used to update the target table after import.\n\nIf you're going into trouble during the import step with foreign key errors,\nplease have a look at this log, as it contains most of the common\nencountered issues to solve:\nhttps://bitbucket.org/anybox/anybox.migration.openerp/issue/3/foreign-key-constraints\n\nContribute\n==========\n\nAuthors and contributors\n------------------------\n\n - Christophe Combelles\n - Florent Jouatte\n - Guy-Clovis Nzouendjou\n - St\u00e9phane Bidoul\n\nCode repository and bug tracker\n-------------------------------\n\nSee here: https://bitbucket.org/anybox/anybox.migration.openerp\n\nPlease don't hesitate to give us feedback, report bugs or contribute the mapping files\non Bitbucket.\n\nChanges\n=======\n\n0.9 (2013-12-31)\n----------------\n\n- cleaned up and added missing tables\n- Many mapping improvements, fixes and cleanup\n- Added mapping for HR migration\n\n0.8 (2013-09-30)\n----------------\n\n- restored mapping for users/company assignment\n- improved message migration\n\n0.7 (2013-09-24)\n----------------\n\n- Fixed CRM migration\n- Migrate email_template\n- Migrate email_message\n- Support references with ``__ref__`` statements\n- Fixed and improved the mapping\n- Increased the default csv field size limit to 20MB\n\n0.6 (2013-08-24)\n----------------\n\n- Migrate ir_sequence without needing post-migration script\n- Fixed workflow instance and workitem migration\n- Major performance improvement (x3) in case of db merging\n- Fixed unwanted merging due to bad offset of foreign key discriminators\n- Break some dependency loops and other mapping improvements\n\n0.5 (2013-08-02)\n----------------\n\n- Fixed foreign keys pointing to a ``__moved__`` table with existing data\n- Updated doc\n\n0.4 (2013-07-28)\n----------------\n\n- Fixed migration of leads and purchase orders\n- simplified ``__moved__`` statement handling\n- improved workflow migration\n- migrate employees and expenses\n- set suppliers as companies by default\n- how to install in a buildout\n- updated doc\n\n0.3 (2013-07-11)\n----------------\n\n- Lots of improvements for the 6.1 to 7.0 migration\n- Fixed a bug during import due to bad quoting\n- Allow m2o to m2m migration without custom code\n- Added mapping for project, crm and auth_ldap modules\n- Fixed move lines\n- Allow to request the source db as well\n- Improved documentation\n- Migration of running workflows\n\n\n0.2 (2013-07-01)\n----------------\n\n - initial release", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://bitbucket.org/anybox/anybox.migration.openerp/overview", "keywords": null, "license": "GPLv3+", "maintainer": null, "maintainer_email": null, "name": "anybox.migration.openerp", "package_url": "https://pypi.org/project/anybox.migration.openerp/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/anybox.migration.openerp/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://bitbucket.org/anybox/anybox.migration.openerp/overview" }, "release_url": "https://pypi.org/project/anybox.migration.openerp/0.9/", "requires_dist": null, "requires_python": null, "summary": "Fast OpenERP migration framework", "version": "0.9" }, "last_serial": 957693, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "2034b11c9affbc8293710bf57aff8609", "sha256": "f6cfe2dfe2546992701a994a387455cfad8fe539a3b88986f374a1877ea142eb" }, "downloads": -1, "filename": "anybox.migration.openerp-0.1.tar.gz", "has_sig": false, "md5_digest": "2034b11c9affbc8293710bf57aff8609", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32500, "upload_time": "2013-06-30T22:23:42", "url": "https://files.pythonhosted.org/packages/a0/59/b02ed173abbc03ac6540287556665d774cded9e679d898b3ccd8df923d8a/anybox.migration.openerp-0.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "6c9beb63ef3d9ddfabbe83602142a411", "sha256": "ed6da3c6ab783eed6ae762db7a261be01d9c7ad2edc3f7b703bb803f7cb13970" }, "downloads": -1, "filename": "anybox.migration.openerp-0.2.tar.gz", "has_sig": false, "md5_digest": "6c9beb63ef3d9ddfabbe83602142a411", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32549, "upload_time": "2013-06-30T22:40:56", "url": "https://files.pythonhosted.org/packages/97/18/ee5ed65c5fae71989ac08fc4cd80fd50f8bc419bb37c2ecfd46eeb37b77b/anybox.migration.openerp-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "6b848582dcc10bf96c93c34a644b9b7e", "sha256": "0df33ee22438bc01cfceeece386aa9e05c7bf7fe54d0bfabab2e1017909ed16f" }, "downloads": -1, "filename": "anybox.migration.openerp-0.3.tar.gz", "has_sig": false, "md5_digest": "6b848582dcc10bf96c93c34a644b9b7e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 37096, "upload_time": "2013-07-11T19:42:55", "url": "https://files.pythonhosted.org/packages/6e/4b/8fe2cec5c8bb336c4d51c7aeb668f6944e31ffefa3c44470ae137d9e748a/anybox.migration.openerp-0.3.tar.gz" } ], "0.4": [ { "comment_text": "", "digests": { "md5": "2b5453a4655ec975f86a18c2d4abef02", "sha256": "f6ce6325a157dd398f094f72019de2c2c21bb0a521e8ab4ea800f4ab53ff1a1c" }, "downloads": -1, "filename": "anybox.migration.openerp-0.4.tar.gz", "has_sig": false, "md5_digest": "2b5453a4655ec975f86a18c2d4abef02", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 38357, "upload_time": "2013-07-28T20:12:37", "url": "https://files.pythonhosted.org/packages/02/33/21513d5e88479bd019e3e0039db829f4d243488cb8048d97f5ef3e2b1bb8/anybox.migration.openerp-0.4.tar.gz" } ], "0.5": [ { "comment_text": "", "digests": { "md5": "9446cbea521e15fbccfe6bdd091e57cc", "sha256": "d43d6c7dd8232589033fc252e1f308052ba80fb6e597279eee1ef8706ff330df" }, "downloads": -1, "filename": "anybox.migration.openerp-0.5.tar.gz", "has_sig": false, "md5_digest": "9446cbea521e15fbccfe6bdd091e57cc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 38713, "upload_time": "2013-08-02T18:07:28", "url": "https://files.pythonhosted.org/packages/1b/35/2ebb9ee3e09916d33da9b33786c03d473f39591297db7af7447c2d2049f5/anybox.migration.openerp-0.5.tar.gz" } ], "0.6": [ { "comment_text": "", "digests": { "md5": "06db16425313e9ebb468c9941b4ec33c", "sha256": "6f9f15f06e9a61c9002a0968bc54a67ed70e62fc280c9f2f69820320f94eb702" }, "downloads": -1, "filename": "anybox.migration.openerp-0.6.tar.gz", "has_sig": false, "md5_digest": "06db16425313e9ebb468c9941b4ec33c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 40982, "upload_time": "2013-08-24T12:07:46", "url": "https://files.pythonhosted.org/packages/6d/12/e8620d9c724a0f75346c36b87bda520914cd76736524345b1e626a1aa46c/anybox.migration.openerp-0.6.tar.gz" } ], "0.7": [ { "comment_text": "", "digests": { "md5": "10c2e2c7ac6999693916f4bd96dd163e", "sha256": "3126bb2527878e52a9b9780c7a27adc0b6723e4e4e66477322132ff7e6315550" }, "downloads": -1, "filename": "anybox.migration.openerp-0.7.tar.gz", "has_sig": false, "md5_digest": "10c2e2c7ac6999693916f4bd96dd163e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 44360, "upload_time": "2013-09-24T21:38:57", "url": "https://files.pythonhosted.org/packages/cf/08/43d01417943450fba680f7bc32a9d995549327fe41a289e1fa26f5fb7138/anybox.migration.openerp-0.7.tar.gz" } ], "0.8": [ { "comment_text": "", "digests": { "md5": "6b7ad72df7d6268a271d36a3cc985a8d", "sha256": "2e0b9067b4b131dca592389453e7eaa4c24cde64268519ff560832a4de7ee9f8" }, "downloads": -1, "filename": "anybox.migration.openerp-0.8.tar.gz", "has_sig": false, "md5_digest": "6b7ad72df7d6268a271d36a3cc985a8d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 44474, "upload_time": "2013-09-29T23:48:20", "url": "https://files.pythonhosted.org/packages/9a/d7/a68e823d597ea64579c4045c0f41e1ad07cd6f87dda18cea597a760affb8/anybox.migration.openerp-0.8.tar.gz" } ], "0.9": [ { "comment_text": "", "digests": { "md5": "8faabd52ebd197c444a6450b526f5aee", "sha256": "ec356d2b81d0e32254fc718303b506f2eb9c840bc9e974ad99cd4514eaec83af" }, "downloads": -1, "filename": "anybox.migration.openerp-0.9.tar.gz", "has_sig": false, "md5_digest": "8faabd52ebd197c444a6450b526f5aee", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 43485, "upload_time": "2013-12-31T21:37:15", "url": "https://files.pythonhosted.org/packages/4b/f8/2f72c3f8cbbb496447c81d80b2b4dc2f4d9630e4077f8cebae78016706cd/anybox.migration.openerp-0.9.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "8faabd52ebd197c444a6450b526f5aee", "sha256": "ec356d2b81d0e32254fc718303b506f2eb9c840bc9e974ad99cd4514eaec83af" }, "downloads": -1, "filename": "anybox.migration.openerp-0.9.tar.gz", "has_sig": false, "md5_digest": "8faabd52ebd197c444a6450b526f5aee", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 43485, "upload_time": "2013-12-31T21:37:15", "url": "https://files.pythonhosted.org/packages/4b/f8/2f72c3f8cbbb496447c81d80b2b4dc2f4d9630e4077f8cebae78016706cd/anybox.migration.openerp-0.9.tar.gz" } ] }