{ "info": { "author": "Erik Price", "author_email": "", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Programming Language :: Python :: 3 :: Only", "Programming Language :: SQL", "Topic :: Utilities" ], "description": "squabble\n========\n\n|build-status| |docs| |pypi|\n\nCatch unsafe SQL migrations.\n\n.. code:: console\n\n $ squabble sql/migration.sql\n sql/migration.sql:4:46 ERROR: column \"uh_oh\" has a disallowed constraint [1004]\n ALTER TABLE big_table ADD COLUMN uh_oh integer DEFAULT 0;\n ^\n # Use --explain to get more information on a lint violation\n $ squabble --explain 1004\n ConstraintNotAllowed\n When adding a column to an existing table, certain constraints can have\n unintentional side effects, like locking the table or introducing\n performance issues.\n ...\n\nSquabble can also be `integrated with your editor\n`__ to catch errors in\nSQL files.\n\n.. code:: console\n\n $ echo 'SELECT * FROM WHERE x = y;' | squabble --reporter=plain\n stdin:1:15 CRITICAL: syntax error at or near \"WHERE\"\n\nCurrently, most of the rules have been focused on Postgres and its\nquirks. However, squabble can parse any ANSI SQL and new rules that are\nspecific to other databases are appreciated!\n\nInstallation\n------------\n\n.. code-block:: console\n\n $ pip3 install squabble\n $ squabble --help\n\n.. note::\n\n Squabble is only supported on Python 3.5+\n\nIf you\u2019d like to install from source:\n\n.. code-block:: console\n\n $ git clone https://github.com/erik/squabble.git && cd squabble\n $ python3 -m venv ve && source ve/bin/activate\n $ python setup.py install\n $ squabble --help\n\nConfiguration\n-------------\n\nTo see a list of rules, try\n\n.. code-block:: console\n\n $ squabble --list-rules\n\nThen, to show more verbose information about a rule (such as rationale\nand configuration options)\n\n.. code-block:: console\n\n $ squabble --show-rule AddColumnsDisallowConstraints\n\nOnce a configuration file is in place, it can be passed explicitly on\nthe command line, or automatically looked up.\n\n.. code-block:: console\n\n $ squabble -c path/to/config ...\n\nIf not explicitly given on the command line, squabble will look for a\nfile named ``.squabblerc`` in the following places (in order):\n\n- ``./.squabblerc``\n- ``(git_repo_root)/.squabblerc``\n- ``~/.squabblerc``\n\nPer-File Configuration\n~~~~~~~~~~~~~~~~~~~~~~\n\nConfiguration can also be applied at the file level by using SQL line comments\nin the form ``-- enable:RuleName`` or ``-- disable:RuleName``.\n\nFor example, to disable ``RuleA`` and enable ``RuleB`` just for one file,\nthis could be done:\n\n.. code-block:: sql\n\n -- disable:RuleA\n -- enable:RuleB config=value array=1,2,3\n SELECT email FROM users WHERE ...;\n\n\nExample Configuration\n~~~~~~~~~~~~~~~~~~~~~\n\n.. code-block:: json\n\n {\n \"reporter\": \"color\",\n\n \"plugins\": [\n \"/some/directory/with/custom/rules\"\n ],\n\n \"rules\": {\n \"AddColumnsDisallowConstraints\": {\n \"disallowed\": [\"DEFAULT\", \"FOREIGN\", \"NOT NULL\"]\n }\n }\n }\n\nPrior Art\n---------\n\n``squabble`` is of course not the first tool in this space. If it\ndoesn't fit your needs, consider one of these tools:\n\n- `sqlcheck `__ - regular\n expression based (rather than parsing), focuses more on ``SELECT``\n statements than migrations.\n- `sqlint `__ - checks that the\n syntax of a file is valid. Uses the same parsing library as\n squabble.\n- `sqlfluff `__ -\n focused more on style and formatting, seems to still be a work in\n progress.\n\n\nAcknowledgments\n---------------\n\nThis project would not be possible without:\n\n- `libpg_query `__ - Postgres\n query parser\n- `pglast `__ - Python bindings to\n libpg_query\n- Postgres - \u2026obviously\n\nThe `logo image `__ used\nin the documentation is created by Gianni - Dolce Merda from the Noun\nProject.\n\n.. |build-status| image:: https://img.shields.io/travis/erik/squabble.svg?style=flat\n :alt: build status\n :target: https://travis-ci.org/erik/squabble\n\n.. |docs| image:: https://readthedocs.org/projects/squabble/badge/?version=stable\n :alt: Documentation Status\n :target: https://squabble.readthedocs.io/en/stable/?badge=stable\n\n.. |pypi| image:: https://img.shields.io/pypi/v/squabble.svg\n :alt: PyPI version\n :target: https://pypi.org/project/squabble\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/erik/squabble", "keywords": "", "license": "GPLv3+", "maintainer": "", "maintainer_email": "", "name": "squabble", "package_url": "https://pypi.org/project/squabble/", "platform": "", "project_url": "https://pypi.org/project/squabble/", "project_urls": { "Homepage": "https://github.com/erik/squabble" }, "release_url": "https://pypi.org/project/squabble/1.3.3/", "requires_dist": null, "requires_python": "", "summary": "An extensible linter for SQL", "version": "1.3.3" }, "last_serial": 5735226, "releases": { "0.0.0": [ { "comment_text": "", "digests": { "md5": "b9778bca42776da6f2c6574793ace753", "sha256": "a264213369a55f254ec4ed101c68b4a4606bddde7a11032abeda6bcbccd22875" }, "downloads": -1, "filename": "squabble-0.0.0.tar.gz", "has_sig": false, "md5_digest": "b9778bca42776da6f2c6574793ace753", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8814, "upload_time": "2018-12-23T23:32:05", "url": "https://files.pythonhosted.org/packages/3d/2e/f6c3e0ebcc138f1372a3e58cf6d70e64d7f3cddd9114708757404111a18a/squabble-0.0.0.tar.gz" } ], "0.1.0": [ { "comment_text": "", "digests": { "md5": "cfe0d746fefc1a4e89ddf67227ef4907", "sha256": "3fbe325ad250a62848ab68e31e2a89f6683aa82d360bdfa4dbc94b82f8a535ef" }, "downloads": -1, "filename": "squabble-0.1.0.tar.gz", "has_sig": false, "md5_digest": "cfe0d746fefc1a4e89ddf67227ef4907", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11414, "upload_time": "2018-12-28T05:47:07", "url": "https://files.pythonhosted.org/packages/77/42/e8f637d0e1533f915da2d53a3f65579d31bf7975bc6448c65a2d02ecdb1b/squabble-0.1.0.tar.gz" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "85005015830b5314026c89ccb2c046cd", "sha256": "0232454eefbd65cc31a55e2c1e4ae5f56da97885e91a8b3da8d3fe78d1f587cc" }, "downloads": -1, "filename": "squabble-1.0.0.tar.gz", "has_sig": false, "md5_digest": "85005015830b5314026c89ccb2c046cd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21703, "upload_time": "2019-01-06T06:33:23", "url": "https://files.pythonhosted.org/packages/a7/1e/de5f2fd3611ff40ae0d225d2612db174bcaec865565093311ac1c74cc8ad/squabble-1.0.0.tar.gz" } ], "1.0.0rc0": [ { "comment_text": "", "digests": { "md5": "19d33f0289dd1b03bb1e75f057654d8d", "sha256": "0bf307de1102006cce7c4fd9ccecc11575615e2fcc8d6ca175c6b8dc1351b723" }, "downloads": -1, "filename": "squabble-1.0.0rc0.tar.gz", "has_sig": false, "md5_digest": "19d33f0289dd1b03bb1e75f057654d8d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12566, "upload_time": "2019-01-03T07:29:14", "url": "https://files.pythonhosted.org/packages/0d/8c/ff6ebebf9f84553bcfb25d88c093f2b8799c0808ea412eacdfbc5c996d50/squabble-1.0.0rc0.tar.gz" } ], "1.0.0rc1": [ { "comment_text": "", "digests": { "md5": "c7e587a5edd4e678a3c9ef931027c127", "sha256": "824df3ab0e9c5e03e92eab60bd388255b0e67b3cfb64d8ca81529829cf3a445c" }, "downloads": -1, "filename": "squabble-1.0.0rc1.tar.gz", "has_sig": false, "md5_digest": "c7e587a5edd4e678a3c9ef931027c127", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12933, "upload_time": "2019-01-04T06:30:40", "url": "https://files.pythonhosted.org/packages/33/2d/e6709952bfaa06fbb87f92f6a2eec62067b0020c62839a6e0fd7fb04873d/squabble-1.0.0rc1.tar.gz" } ], "1.0.0rc2": [ { "comment_text": "", "digests": { "md5": "e2cd5b1d1f21b070626fcfebf7caa6e8", "sha256": "f9788a9d7c84eabceb87e94aa3da7de2cfd3e9b1b2347edadd5bec230e4f7f12" }, "downloads": -1, "filename": "squabble-1.0.0rc2.tar.gz", "has_sig": false, "md5_digest": "e2cd5b1d1f21b070626fcfebf7caa6e8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13410, "upload_time": "2019-01-04T06:34:54", "url": "https://files.pythonhosted.org/packages/05/f1/54077ec2071ba973927fed4878bc7723c397d17d2a60fb07536f3253e11c/squabble-1.0.0rc2.tar.gz" } ], "1.0.0rc3": [ { "comment_text": "", "digests": { "md5": "ec5fb446ff40e510425093148c47875b", "sha256": "a13ace0976590737af734c66bffcfcde8d6abca4019be02e4237da950e365a3f" }, "downloads": -1, "filename": "squabble-1.0.0rc3.tar.gz", "has_sig": false, "md5_digest": "ec5fb446ff40e510425093148c47875b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13408, "upload_time": "2019-01-04T06:40:55", "url": "https://files.pythonhosted.org/packages/06/c3/8e26780898a230ba3075bbe673394bbd2a93e8d16c5d48569e55eaabbf1f/squabble-1.0.0rc3.tar.gz" } ], "1.0.0rc4": [ { "comment_text": "", "digests": { "md5": "6b8cf8a1c72963de49f6a790c167c105", "sha256": "da9e7133b81cf537bf431a49eca7c8a23d48e088a4a566d33c749d7935768f0e" }, "downloads": -1, "filename": "squabble-1.0.0rc4.tar.gz", "has_sig": false, "md5_digest": "6b8cf8a1c72963de49f6a790c167c105", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20395, "upload_time": "2019-01-04T06:52:52", "url": "https://files.pythonhosted.org/packages/4a/21/ecd4712ce5010b928fff0809269f2d28ec3a4936dcf726f33a5300e2604b/squabble-1.0.0rc4.tar.gz" } ], "1.0.0rc5": [ { "comment_text": "", "digests": { "md5": "490c3a0d6643c19358b06701b30a00ab", "sha256": "f35a28ef7d6830604a850f6fe6d28fb81c3915ed1ef0932dcc466576ea3f0a97" }, "downloads": -1, "filename": "squabble-1.0.0rc5.tar.gz", "has_sig": false, "md5_digest": "490c3a0d6643c19358b06701b30a00ab", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21010, "upload_time": "2019-01-05T23:17:18", "url": "https://files.pythonhosted.org/packages/41/9f/aed5dc12fbc765b0089951d4fa56d343d14c32708df21cc19006400bfc9e/squabble-1.0.0rc5.tar.gz" } ], "1.0.0rc6": [ { "comment_text": "", "digests": { "md5": "b5390b8d83398dd9123e068875dafef1", "sha256": "c8013166d0422b687c2d3b9cec5603284fa0124ee7d8adcbb525587fb537a7b7" }, "downloads": -1, "filename": "squabble-1.0.0rc6.tar.gz", "has_sig": false, "md5_digest": "b5390b8d83398dd9123e068875dafef1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21182, "upload_time": "2019-01-06T05:51:13", "url": "https://files.pythonhosted.org/packages/54/3d/e86cdb514a1cacde4bb38ebb7c81a8926f54762ad3fd5d065d127769d37e/squabble-1.0.0rc6.tar.gz" } ], "1.0.0rc7": [ { "comment_text": "", "digests": { "md5": "2dfbf34188316ccf7fda7cb64e861c9c", "sha256": "b154fd4b430a2ae9d93be85d38594a406a222c22f56ffaca5752d7d8219aef0c" }, "downloads": -1, "filename": "squabble-1.0.0rc7.tar.gz", "has_sig": false, "md5_digest": "2dfbf34188316ccf7fda7cb64e861c9c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21716, "upload_time": "2019-01-06T06:23:11", "url": "https://files.pythonhosted.org/packages/73/c6/c055dec3b64ab6df6edd631da624682db83f10c33614b607cc7082171738/squabble-1.0.0rc7.tar.gz" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "80724c5ce0e35733c903b215d8b27e18", "sha256": "29ee5f14bace7b0a4c58cee0dc2c2360eb63322bdf7941622c8dc6d7ee2f0e07" }, "downloads": -1, "filename": "squabble-1.1.0.tar.gz", "has_sig": false, "md5_digest": "80724c5ce0e35733c903b215d8b27e18", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 24321, "upload_time": "2019-01-11T17:16:52", "url": "https://files.pythonhosted.org/packages/37/69/a009f6d7f84f4be8676297c5818b7acf654ccc945e4721c152657d2f171c/squabble-1.1.0.tar.gz" } ], "1.1.0rc0": [ { "comment_text": "", "digests": { "md5": "b8b4b75ad5f36b9d5bf44b68615c3c8e", "sha256": "64b6731dad67871a5d69bb895ef2259643cf2588a3bc0ff4a23299bd14fe2889" }, "downloads": -1, "filename": "squabble-1.1.0rc0.tar.gz", "has_sig": false, "md5_digest": "b8b4b75ad5f36b9d5bf44b68615c3c8e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 24246, "upload_time": "2019-01-11T05:34:53", "url": "https://files.pythonhosted.org/packages/66/e0/77a488693d44f84a460ff1b7113f38251a9e1463a8db419881c75b4ac604/squabble-1.1.0rc0.tar.gz" } ], "1.1.0rc1": [ { "comment_text": "", "digests": { "md5": "7eda91f58169a08f1c2b9c070ca8595d", "sha256": "491ceaf47c138f163a99faa01a302ad57ab126ebd94b7c21ea9abdc995b5e7a9" }, "downloads": -1, "filename": "squabble-1.1.0rc1.tar.gz", "has_sig": false, "md5_digest": "7eda91f58169a08f1c2b9c070ca8595d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 24294, "upload_time": "2019-01-11T17:06:13", "url": "https://files.pythonhosted.org/packages/2a/f2/fc5874f7eae170ca566bca0f02b82db26f849954eb58735837dc152e6b25/squabble-1.1.0rc1.tar.gz" } ], "1.2.0": [ { "comment_text": "", "digests": { "md5": "abcc37a9e4158d860cddf2ac180d7576", "sha256": "e6f3dbfd527efdc1f1d71db2d2c5cd9fefd14c771a5ed813f52d4144e7647c39" }, "downloads": -1, "filename": "squabble-1.2.0.tar.gz", "has_sig": false, "md5_digest": "abcc37a9e4158d860cddf2ac180d7576", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25084, "upload_time": "2019-01-15T05:12:59", "url": "https://files.pythonhosted.org/packages/e2/9e/45e5da14758c9414b6fcb9dd897f00e8d84e9f2f5950b88c75140c93398c/squabble-1.2.0.tar.gz" } ], "1.2.0rc0": [ { "comment_text": "", "digests": { "md5": "fd756cd40e71d401f5b01a6d7026658b", "sha256": "3448d511eebabd5b16ec9889e4f479a376c3e7aaa722133c59c8e6ab51d886c2" }, "downloads": -1, "filename": "squabble-1.2.0rc0.tar.gz", "has_sig": false, "md5_digest": "fd756cd40e71d401f5b01a6d7026658b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25017, "upload_time": "2019-01-13T19:58:22", "url": "https://files.pythonhosted.org/packages/f7/8b/47d3a1a4968a721f6700cce19ba1da4f57a75b81914b9080c3276386c22a/squabble-1.2.0rc0.tar.gz" } ], "1.3.0": [ { "comment_text": "", "digests": { "md5": "fb5ff6fad92015da2f715247306c2b3e", "sha256": "8d99357678c95c33f4b31996b9d641cb4f9ef1c317ba1218a13fe333b09ee4e6" }, "downloads": -1, "filename": "squabble-1.3.0.tar.gz", "has_sig": false, "md5_digest": "fb5ff6fad92015da2f715247306c2b3e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30384, "upload_time": "2019-05-10T22:36:14", "url": "https://files.pythonhosted.org/packages/78/6a/f6aa23f91d55181f2da27107415198bdfe4eca2f4b210be305647dad3cee/squabble-1.3.0.tar.gz" } ], "1.3.1": [ { "comment_text": "", "digests": { "md5": "d267a1f39efeeda421d659bffaf780c9", "sha256": "c34fe09caaa642408475a413a6ec2bbf6a49f9e9b4727debba404e2b511180f7" }, "downloads": -1, "filename": "squabble-1.3.1.tar.gz", "has_sig": false, "md5_digest": "d267a1f39efeeda421d659bffaf780c9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30472, "upload_time": "2019-05-15T07:15:40", "url": "https://files.pythonhosted.org/packages/2f/a7/e91c075c499a62e3332b581031f3f3cd457af7f9e301dbf4325da748a9a4/squabble-1.3.1.tar.gz" } ], "1.3.2": [ { "comment_text": "", "digests": { "md5": "869bcafcc6baa5a5849ba5a54478368f", "sha256": "1dfe74da816e2807d58dd6292b629b489e23064acf9b0e9cf902fa6afbc0373b" }, "downloads": -1, "filename": "squabble-1.3.2.tar.gz", "has_sig": false, "md5_digest": "869bcafcc6baa5a5849ba5a54478368f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30352, "upload_time": "2019-07-31T06:14:15", "url": "https://files.pythonhosted.org/packages/41/21/a98b0edbf3a58103c8f925f156a6dbcf3cf38460bff41344f0deb1e95c0a/squabble-1.3.2.tar.gz" } ], "1.3.3": [ { "comment_text": "", "digests": { "md5": "794563982e5fc2365db576b504daed90", "sha256": "f2ad08eec9f3db002f088fcf0fb786f9f462de1ad4404ef1e47d0a249d759a58" }, "downloads": -1, "filename": "squabble-1.3.3.tar.gz", "has_sig": false, "md5_digest": "794563982e5fc2365db576b504daed90", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30492, "upload_time": "2019-08-27T07:49:26", "url": "https://files.pythonhosted.org/packages/8d/d3/bbf9948c122146beb912c0f01e7efee57a8fcd71e5666c93725b44a76307/squabble-1.3.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "794563982e5fc2365db576b504daed90", "sha256": "f2ad08eec9f3db002f088fcf0fb786f9f462de1ad4404ef1e47d0a249d759a58" }, "downloads": -1, "filename": "squabble-1.3.3.tar.gz", "has_sig": false, "md5_digest": "794563982e5fc2365db576b504daed90", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30492, "upload_time": "2019-08-27T07:49:26", "url": "https://files.pythonhosted.org/packages/8d/d3/bbf9948c122146beb912c0f01e7efee57a8fcd71e5666c93725b44a76307/squabble-1.3.3.tar.gz" } ] }