{ "info": { "author": "Ryan Tuck", "author_email": "ryan.tuck@warbyparker.com", "bugtrack_url": null, "classifiers": [], "description": "# lookmlint\n\nLint your LookML.\n\nProvides additional linting checks beyond what is built into the LookML Validator.\n\n\n## usage\n\nFrom the CLI:\n\n```\n$ lookmlint lint ~/my-lookml-repo\n```\n\nAlternatively, specify which `checks` to run:\n\n```\n$ lookmlint lint ~/my-lookml-repo --checks label-issues,views-missing-primary-keys\n```\n\nFor structured output, set the `--json` flag:\n\n```\n$ lookmlint lint ~/my-lookml-repo --json\n```\n\n### configuration\n\n`lookmlint` looks for a file named `.lintconfig.yml` in your lookML project repo.\n\nIts contents can contain lists of abbreviations and/or acronyms you'd like to flag. More detail below.\n\n#### sample .lintconfig.yml\n\n```yml\nabbreviations:\n - num\n - qty\nacronyms:\n - aov\n - sms\n - sku\n - sla\n```\n\n## installation\n\nRequires `python3`.\n\n```\n$ pip install lookmlint\n```\n\n### lookml-parser dependency\n\nThis project invokes and relies on outputs generated by the awesome [lookml-parser](https://www.npmjs.com/package/lookml-parser) tool, which parses a lookML repo and outputs the results as `json`.\n\nEnsure this is installed to get `lookmlint` to work properly:\n\n```\n$ npm install -g lookml-parser\n```\n\n## checks\n\n### `label-issues`\n\n#### acronyms\n\nLookML automatically converts snake case strings (e.g. `unit_cost_usd`) to title case (e.g. `Unit Cost Usd`), which looks funny when using acronyms. Leverages the list of acronyms defined in `.lintconfig.yml`.\n\n**Bad**\n\n```\ndimension: unit_cost_usd {\n ...\n}\n```\n\n**Good**\n\n```\ndimension: unit_cost_usd {\n label: \"Unit Cost (USD)\"\n ...\n}\n```\n\n#### abbreviations\n\nIf you'd prefer some words fully spelled out (e.g. 'Quantity' instead of 'Qty'), define a list of abbreviations for `lookmlint` to catch.\n\n\n### `raw-sql-in-joins`\n\nJoins should refer to LookML dimensions as opposed to the underlying fields where possible.\n\nFor example:\n\n**Bad**\n\n```\njoin: order_items {\n sql_on: orders.id = order_items.order_id ;;\n}\n```\n\n**Good**\n\n```\njoin: order_items {\n sql_on: ${orders.id} = ${order_items.order_id} ;;\n}\n```\n\n### `unused-includes`\n\nIf your LookML model explicitly specifies views to include, `lookmlint` can catch views that are `include`d in your model but not referenced in any of the explorations in that model.\n\n### `unused-view-files`\n\nFind all view files that aren't referenced in any explorations in your project.\n\n### `views-missing-primary-keys`\n\nFind all view files that don't contain a `primary_key` dimension.\n\n### `duplicate-view-labels`\n\nFind any cases when two `join`s in an exploration end up with the same label.\n\nOne way this can unwittingly creep into code is if a `label` is defined in a view file, that view is joined twice to the same exploration, but `view_label`s are not assigned to those joins.\n\n### `missing-view-sql-definitions`\n\nFind any views that do not have a `sql_table_name` or `derived_table` value set.\n\n### `semicolons-in-derived-table-sql`\n\nFind any derived table SQL expressions that contain a rogue semicolon, which will throw errors at query time.\n\n### `mismatched-view-names`\n\nFind any views where the view name does not match the view filename.\n\n## examples\n\nThe sample repo at `examples/sample_repo/` contains instances of all linting violations:\n\n\n```\n~/src/lookmlint $$$ lookmlint lint examples/sample_repo/\nError:\n\n\nduplicate-view-labels\n---------------------\nModel: test\n Explore: inventory_transfers\n Inventory Locations: 2\n\n\nlabel-issues\n------------\nFields:\n View: order_items\n - Qty: ['Qty']\n - Unit Cost Usd: ['USD']\n\n\nmismatched-view-names\n---------------------\n- items.view.lkml: order_items\n\n\nmissing-view-sql-definitions\n----------------------------\n- order_items\n\n\nraw-sql-in-joins\n----------------\nModel: test\n Explore: orders\n order_items: orders.id = order_items.order_id\n\n\nsemicolons-in-derived-table-sql\n-------------------------------\n- products\n\n\nunused-includes\n---------------\nModel: test\n - web_sessions\n\n\nunused-view-files\n-----------------\n- legacy_products\n- web_sessions\n\n\nviews-missing-primary-keys\n--------------------------\n- order_items\n```\n\n## adding to CircleCI\n\nWe use CircleCI at Warby Parker to run our checks.\n\nAdding the following contents to `.circleci/config.yml` in your LookML project should work for running linting as part of your CI/CD workflow. This all runs in a few seconds, but leveraging caching could also help to speed things up.\n\nCustomize the list of checks you run to suit your team's needs, or leave out the `--checks` flag to run all possible lint checks.\n\n```\nversion: 2\njobs:\n build:\n docker:\n - image: circleci/python:3.6.1\n working_directory: ~/repo\n steps:\n - checkout\n - run:\n name: Install lookml-parser\n command: |\n curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -\n sudo apt install nodejs\n sudo npm install -g lookml-parser\n - run:\n name: Install lookmlint\n command: |\n sudo pip install lookmlint\n - run:\n name: Lint lookml\n command: |\n lookmlint lint . --checks label-issues,unused-includes,unused-view-files,mismatched-view-names,semicolons-in-derived-table-sql,missing-view-sql-definitions\n```\n\n\n## issues?\n\nThis repo is still in alpha, so use at your own risk!\n\nPlease open an issue for any feature suggestions or bugs, or feel free to open a PR with a fix / feature!\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/WarbyParker/lookmlint", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "lookmlint", "package_url": "https://pypi.org/project/lookmlint/", "platform": "", "project_url": "https://pypi.org/project/lookmlint/", "project_urls": { "Homepage": "https://github.com/WarbyParker/lookmlint" }, "release_url": "https://pypi.org/project/lookmlint/0.2.1/", "requires_dist": [ "attrs", "click", "lkml (==0.1.2)", "pyyaml" ], "requires_python": "", "summary": "Linter for LookML", "version": "0.2.1" }, "last_serial": 5652010, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "6960478a23a6fb67442926c8c5b3a853", "sha256": "174c8344868efaad82b38b661077c16e7e222fd21150eebaf54abe12c59aeba6" }, "downloads": -1, "filename": "lookmlint-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "6960478a23a6fb67442926c8c5b3a853", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 12156, "upload_time": "2018-11-28T17:41:12", "url": "https://files.pythonhosted.org/packages/54/fb/1638f06c46bdb3a32631c42833f1f67e69a5554539263c544066fb556b84/lookmlint-0.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "1db2949040a0cb29ae6ef2ce8297e89a", "sha256": "8ea7c787f4262214153ff6513870a0ce9e54623cbe41fd46dbe9112d84c09e90" }, "downloads": -1, "filename": "lookmlint-0.1.0.tar.gz", "has_sig": false, "md5_digest": "1db2949040a0cb29ae6ef2ce8297e89a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7021, "upload_time": "2018-11-28T17:41:14", "url": "https://files.pythonhosted.org/packages/ce/c6/ba1c9e5726112ee9ac179762eedf8abdaf91efc82d56c1b02f60cca312db/lookmlint-0.1.0.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "f0f53fd10ae92f942f2ce4180cbc16a5", "sha256": "dfc38fd2b93547a52107af6f4f964d9404d38e0a8d98c9996ecdd4e2e1cf11bd" }, "downloads": -1, "filename": "lookmlint-0.2.0-py3-none-any.whl", "has_sig": false, "md5_digest": "f0f53fd10ae92f942f2ce4180cbc16a5", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 12947, "upload_time": "2019-08-08T20:02:46", "url": "https://files.pythonhosted.org/packages/6e/f5/0c7280d2ee2b040b880ea366c043abb32fb188fddc0d9de6071804d24f35/lookmlint-0.2.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8a7584e4c8a3bf6291b9a003a7972e09", "sha256": "103e76f797b46367a052e97910dc863265623ebe1ba661fd7c3455d90a44ac12" }, "downloads": -1, "filename": "lookmlint-0.2.0.tar.gz", "has_sig": false, "md5_digest": "8a7584e4c8a3bf6291b9a003a7972e09", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9556, "upload_time": "2019-08-08T20:02:48", "url": "https://files.pythonhosted.org/packages/2d/9b/f9d269baeb2cb34e42a60b15a73e6fe697477a6ccd432d0b1dff7586cfd2/lookmlint-0.2.0.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "97e26a7484dcb822abd493a7c9658f39", "sha256": "ad7355223deff1a9227072cd3b3087249f76c5ecff76f515c653ca4c62c0a5f9" }, "downloads": -1, "filename": "lookmlint-0.2.1-py3-none-any.whl", "has_sig": false, "md5_digest": "97e26a7484dcb822abd493a7c9658f39", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 12959, "upload_time": "2019-08-08T20:05:34", "url": "https://files.pythonhosted.org/packages/03/04/b155db484aa5e8f0c6f1c7f5772529aa68c39e3a618bdfb3c347b6043d83/lookmlint-0.2.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f3816a2a2d0a4239b809f7c202a16342", "sha256": "dc720d6adb409feec12f54eb63bd8e6d566640ead851151c5f182204811f099c" }, "downloads": -1, "filename": "lookmlint-0.2.1.tar.gz", "has_sig": false, "md5_digest": "f3816a2a2d0a4239b809f7c202a16342", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9574, "upload_time": "2019-08-08T20:05:36", "url": "https://files.pythonhosted.org/packages/48/43/410d23f4886f591ee556554bf12444d8f13292de4f4611e685eab3054b31/lookmlint-0.2.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "97e26a7484dcb822abd493a7c9658f39", "sha256": "ad7355223deff1a9227072cd3b3087249f76c5ecff76f515c653ca4c62c0a5f9" }, "downloads": -1, "filename": "lookmlint-0.2.1-py3-none-any.whl", "has_sig": false, "md5_digest": "97e26a7484dcb822abd493a7c9658f39", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 12959, "upload_time": "2019-08-08T20:05:34", "url": "https://files.pythonhosted.org/packages/03/04/b155db484aa5e8f0c6f1c7f5772529aa68c39e3a618bdfb3c347b6043d83/lookmlint-0.2.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f3816a2a2d0a4239b809f7c202a16342", "sha256": "dc720d6adb409feec12f54eb63bd8e6d566640ead851151c5f182204811f099c" }, "downloads": -1, "filename": "lookmlint-0.2.1.tar.gz", "has_sig": false, "md5_digest": "f3816a2a2d0a4239b809f7c202a16342", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9574, "upload_time": "2019-08-08T20:05:36", "url": "https://files.pythonhosted.org/packages/48/43/410d23f4886f591ee556554bf12444d8f13292de4f4611e685eab3054b31/lookmlint-0.2.1.tar.gz" } ] }