{ "info": { "author": "", "author_email": "", "bugtrack_url": null, "classifiers": [], "description": "# Setupy\n\n[gitignore.io](https://gitignore.io/) for `setup.py`\n\n[![CircleCI](https://circleci.com/gh/aweidner/setupy.svg?style=svg)](https://circleci.com/gh/aweidner/setupy)\n\n\n\nSetupy is a tool for generating `setup.py` files made of composable\nlayers of features and settings.\n\n# Use\n\n`setup.py` files can be generated from [setupy.dev](https://setupy.dev) in one of two ways\n\n* The web UI (with or without Javascript enabled)\n* The API\n\nSome examples of API usage on the web\n\n # Get a base setup.py file that can be extended\n curl https://setupy.dev/get\n\n # Include the help text to make it easier to manually edit the output\n curl https://setupy.dev/get?include_help=true\n\n # Include a feature and setting \n curl https://setupy.dev/get?features=merge&settings=add_upload_command\n\n # Get a list of all the available features\n curl https://setupy.dev/features/list\n\n # Get a list of all available settings\n curl https://setupy.dev/settings/list\n\nAnd on the command line (if [setupy](https://pypi.org/project/setupy/) is installed)\n\n python -m setupy \\\n -s base add_upload_command add_long_description \\\n --include-setting \"$(cat setupy.yaml)\"\n\n python -m setupy help\n\n**Note**: Order is important when passing in settings\n\n# What Setupy generates\n\nThe `setup.py` file for Setupy is generated by Setupy so it serves as a good example to see\nwhat can be generated. Here's an earlier (smaller) version:\n\n # 1\n import os\n import sys\n from os import path\n from shutil import rmtree\n\n from setuptools import Command, find_packages, setup\n\n\n # 2\n here = path.abspath(path.dirname(__file__))\n\n with open(path.join(here, 'README.md'), encoding='utf-8') as f:\n long_description = f.read()\n\n\n VERSION = open(\"VERSION.txt\").read()\n\n\n def merge(*dicts):\n r = {}\n for d in dicts:\n r.update(d)\n return r\n\n\n # 3\n base = {\n \"name\": \"mypackage\",\n \"version\": \"0.1.0\",\n \"packages\": find_packages(exclude=['contrib', 'docs', 'test'])\n }\n\n add_long_description = {\n \"long_description\": long_description,\n \"long_description_content_type\": \"text/markdown\"\n }\n\n setupy = {\n \"name\": \"setupy\",\n \"version\": VERSION,\n \"install_requires\": [\"isort>=4.3\", \"pyyaml>=3.13\", \"flask>=1.0.2\"],\n \"extras_require\": {\n \"dev\": [\"pytest\", \"pytest-cov\"],\n \"neovim\": [\"neovim\"]\n }\n }\n\n\n # 4\n setup(**merge(base, add_upload_command, add_long_description, setupy))\n\n\nThere are 4 primary sections in files generated by Setupy\n\n1. Imports\n2. Features\n3. Settings\n4. Merging all setting layers together and calling `setup`\n\n## Settings\n\nLets start at the beginning to see the motivation for each section. Our end goal is to call\n`setup` from `setuptools` (which is the end goal of every `setup.py` file. The `setup` command\ntakes a number of key word arguments. In order to make things more modular, we can create a number\nof dictionaries and merge them together, then unpack them with `**` and execute `setup` on the result.\n\nThis is Setupy's core model. Settings are used to generate these dictionaries which are ultimately merged\nand passed to `setup`. Settings like base:\n\n base = {\n \"name\": \"mypackage\",\n \"version\": \"0.1.0\",\n \"packages\": find_packages(exclude=['contrib', 'docs', 'test'])\n }\n\nAre provided by Setupy to be used across setup files while settings like `setupy` in the above example\n\n setupy = {\n \"name\": \"setupy\",\n \"version\": VERSION,\n \"install_requires\": [\"isort>=4.3\", \"pyyaml>=3.13\", \"flask>=1.0.2\"],\n \"extras_require\": {\n \"dev\": [\"pytest\", \"pytest-cov\"],\n \"neovim\": [\"neovim\"]\n }\n }\n\nOverride previous settings during the merge. In the final call to merge\n\n merge(base, add_upload_command, add_long_description, setupy)\n\nEarlier dictionaries in the argument list have their values overriden by later dictionaries. So in this case,\nthe default name passed in by `base` gets overriden by the `setup` dictionary. You can download a file from\n`Setupy` and define a new dictionary with any of the provided features or settings and then augment them\nby editing the resulting `setup` file. You can also use the command line to provide custom settings or features\nas Setupy does in order to generate its own `setup.py` file: \n\n python -m setupy \\\n -s base add_upload_command add_long_description \\\n --include-setting \"$(cat setupy.yaml)\"\n\nSettings will override each other (be passed to merge) in the order they are passed in to the API, whether that's\non the web or through the command line. If you want to know how merge works, there's no secret. It's an included feature!\n\n def merge(*dicts):\n r = {}\n for d in dicts:\n r.update(d)\n return r\n\n## Features\n\nIn order to support special functionality for a `setup.py` file (for example getting the version from a `VERSION.txt` file\nor uploading through `twine`) we need to be able to add python code to our `setup.py` files. Features add this functionality.\nFor example a standard feature in Setupy allows extracting the version from `VERSION.txt`\n\n VERSION = open(\"VERSION.txt\").read()\n\nLater settings can then use the `VERSION` variable. In order to keep from having to manually track which features are required\nto activate which settings, settings can declare their feature dependencies:\n\n # setupy/settings/long_description.yaml, one of the standard settings \n ---\n name: add_long_description\n dependencies:\n features:\n - long_description # Depends on the long_description feature\n properties:\n long_description: long_description\n long_description_content_type: \"\\\"text/markdown\\\"\"\n\n\nAny features that a setting depends on will automatically be pulled in when the setting is added. Features may also depend on other\nfeatures.\n\n**Note**: There isn't a lot of validation logic built around this dependency graph behavior just yet. Tread carefully when building long\nchains of dependencies.\n\n## Imports\n\nFeatures and settings might need to import a python module in order to work. Those dependencies are also declared in the yaml files.\nTake this example from the `upload` feature:\n\n # setupy/features/upload.yaml\n ---\n name: upload\n dependencies:\n features:\n - version_txt\n imports:\n - import os\n - from shutil import rmtree \n - import sys\n - from setuptools import Command\n\nFour imports are needed to make this feature work. They will all be pulled in when the file is built. Lots of features and settings\nmay end up depending on the same imports. In order to prevent a messy collection of imports sitting at the top of the file, all\nimports are run through [isort](https://github.com/timothycrosley/isort) before the final `setup.py` is written. \n\n# Why Setupy\n\nWhenever I start a new python project there's a couple of things I do, I update pipenv and start a new shell, I `git init`, add a\n`.gitignore` file from [gitignore.io](https://gitignore.io) and create a few directories for my project files (the main module,\na `__main__`, some `__init__.py` files and `tests/` mostly.\n\nEventually I get to the point that I want to create a `setup.py` file and maybe publish my module to PyPi. In order to do that I\ninevitably have to look up a `setup.py` file to copy, figure out which options I want and spend a couple minutes filling everything out.\n\nI wanted a solution like gitignore.io, something with an easy to use API that would interact well with `curl` and would be modular enough\nto work with lots of different projects. My hope is that the number of features and settings in this repository continues to grow\nand Setupy can become a really useful tool for generating standardized and customizable `setup.py` files. \n\n# Self hosting\n\nThe standard repository likely won't work for everybody. You or your organization might also want to use Setupy on projects where\nyou want to retain the rights to any features or settings you build without making them open source. Setupy can be self hosted\nand pointed to a custom set of settings and features by pulling and running the docker container:\n\n docker pull setupy:latest \n docker run setupy:latest \\\n -e SETUPY_SETTINGS /path/to/setupy/settings\n -e SETUPY_FEATURES /path/to/setupy/features\n\n## Defining your own features\n\nFeatures reside in the directory pointed to by the environment variable `SETUPY_FEATURES`. There are two types of files in this\ndirectory\n\n* .yaml files which define the metadata for a feature\n* .py files which define the code for a feature\n\nLets define a new feature called `long_description`. First we create the metadata file `long_description.yaml`\n\n ---\n name: long_description\n dependencies:\n imports:\n - from os import path\n\nThis feature has only one dependant import. The name is important here, it must be the same as the file name. Next we create the\npython file that contains the code that will be pulled into our `setup.py` file: \n\n here = path.abspath(path.dirname(__file__))\n\n with open(path.join(here, 'README.md'), encoding='utf-8') as f:\n long_description = f.read() \n\nAnd that's it. We can now generate `setup.py` files using this custom feature \n\nThe full schema for a feature `.yaml` file looks like:\n\n ---\n name (required): string \n dependencies (optional):\n imports (optional):\n - list (optional)\n - of \n - strings\n features (optional):\n - list (optional)\n - of\n - strings\n\nEach entry in the list `dependencies.features` should be the name of an existing feature. All features must have a unique name.\n\n## Defining your own settings\n\nSettings reside in the directory pointed to by the environment variable `SETUPY_SETTINGS`. This file contains `.yaml` files that\nlook like:\n\n ---\n name: add_long_description\n dependencies:\n features:\n - long_description\n properties:\n long_description: long_description\n long_description_content_type: \"\\\"text/markdown\\\"\"\n\nThe dependencies object has the same schema as the dependencies object from `features`. Note that `settings` may not depend on settings.\nThis is an intentional design choice to:\n\n1. Keep chains of dependencies as short and clear as possible\n2. Prevent complex and possibly unpredictable ordering behavior when constructing the final ordered list of dictionaries to merge\n\nYou may notice the `\\\"` (escaped quotes) characters in the `properties` object. Because properties may reference variables AND\nliteral strings, there must be a way to differentiate them when the properties object is translated to a python dictionary to be\nincluded in the `setup.py` file. Literal strings must be enclosed in quotes and escaped quotes (as in `\"\\\"text/markdown\\\"\"`).\nVariables should be enclosed in neither (as in `long_description`).\n\nThe name property in this file should match the filename (minus the `.yaml` extension) and will be used as the variable to assign\nthe resulting dictionary to when `seutp.py` is created. Thus all settings must have a unique name.\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": "", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "setupy", "package_url": "https://pypi.org/project/setupy/", "platform": "", "project_url": "https://pypi.org/project/setupy/", "project_urls": null, "release_url": "https://pypi.org/project/setupy/0.6.0/", "requires_dist": [ "isort (>=4.3)", "pyyaml (>=3.13)", "flask (>=1.0.2)", "pytest ; extra == 'dev'", "pytest-cov ; extra == 'dev'", "neovim ; extra == 'neovim'" ], "requires_python": "", "summary": "", "version": "0.6.0" }, "last_serial": 5126637, "releases": { "0.4.2": [ { "comment_text": "", "digests": { "md5": "5a983b685cdcecc9ed9a533c707e38d0", "sha256": "3dfbae819cd14f9b0867272dd9428d6740f3ad5463554e16c0bc99b43ebc836b" }, "downloads": -1, "filename": "setupy-0.4.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "5a983b685cdcecc9ed9a533c707e38d0", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 10069, "upload_time": "2019-04-06T21:27:14", "url": "https://files.pythonhosted.org/packages/08/b2/ce5ed2b072084c846781e9bb56c45f7efd43fa238d464d2808c93f3c33e4/setupy-0.4.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "3757c0f6a7f661a437b6cce9a119f60a", "sha256": "d6dd6beb031041dbbd7c2f5d799e4bc70bdefaebbc6a566ec31028ec0a702f5c" }, "downloads": -1, "filename": "setupy-0.4.2.tar.gz", "has_sig": false, "md5_digest": "3757c0f6a7f661a437b6cce9a119f60a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9021, "upload_time": "2019-04-06T21:27:16", "url": "https://files.pythonhosted.org/packages/50/33/23ac93fcbeb9115c8eb5129aa0c90d8dcfd478abe3504a8c3d07db750e3a/setupy-0.4.2.tar.gz" } ], "0.4.3": [ { "comment_text": "", "digests": { "md5": "512383a5acc5871450e0c941808f1d73", "sha256": "5b7b0ab52d076ec8225d9d12cc6417b3e706196575751ba86f5a96596c7d247c" }, "downloads": -1, "filename": "setupy-0.4.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "512383a5acc5871450e0c941808f1d73", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 10094, "upload_time": "2019-04-06T21:33:48", "url": "https://files.pythonhosted.org/packages/09/ec/43785f45f19dadef20b18b80a4e0bcfda96749f600800b147f0fc0534adb/setupy-0.4.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "593d6b1c29f30e6c4d4b7ac058436103", "sha256": "589fc520d6cac5b39eb5bad7cb341a256371277abeda0afaf4a27019f0101e9c" }, "downloads": -1, "filename": "setupy-0.4.3.tar.gz", "has_sig": false, "md5_digest": "593d6b1c29f30e6c4d4b7ac058436103", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9047, "upload_time": "2019-04-06T21:33:49", "url": "https://files.pythonhosted.org/packages/31/74/8eb6586d14a4dbbeebad3a148f0b87a6eff163547bcea7ddb3c2c52a49ea/setupy-0.4.3.tar.gz" } ], "0.5.0": [ { "comment_text": "", "digests": { "md5": "dbcb976530e64b86254a575775f4db91", "sha256": "b4f870314dc12d93c749ca8ea7da89c29ee971485eee408a7bb89b4051d2ea31" }, "downloads": -1, "filename": "setupy-0.5.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "dbcb976530e64b86254a575775f4db91", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 10821, "upload_time": "2019-04-06T22:02:43", "url": "https://files.pythonhosted.org/packages/20/b5/3ec509b873241660af4d4b35124f791df15fb55fab0b2eb65627a597e0b3/setupy-0.5.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "de18aacca85ed1c8f4085ee991159b10", "sha256": "ed6e31dc031ddd21793df8ad49b24cd04575fcb580911f6aa2e1821fe0068dc7" }, "downloads": -1, "filename": "setupy-0.5.0.tar.gz", "has_sig": false, "md5_digest": "de18aacca85ed1c8f4085ee991159b10", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9508, "upload_time": "2019-04-06T22:02:44", "url": "https://files.pythonhosted.org/packages/d4/f7/e0ad4e53b3be3bd0ac955721f043dc9ec594e6a536381c1b75b43fa17b27/setupy-0.5.0.tar.gz" } ], "0.5.1": [ { "comment_text": "", "digests": { "md5": "6d3336c58987fe2774d3750b6a57bd0e", "sha256": "6cee4d9f865b0e05c94afef128d94366bdc2870f91253e092c2ea5ee665f3eec" }, "downloads": -1, "filename": "setupy-0.5.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "6d3336c58987fe2774d3750b6a57bd0e", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 14640, "upload_time": "2019-04-08T23:58:41", "url": "https://files.pythonhosted.org/packages/6a/69/3b686c1b1ee1590b424d26fbf1068b051cb96a81b12bebcbe7d6421656c2/setupy-0.5.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "41b941347f16beeaa20fd44a2c225200", "sha256": "98278128d4da86b87bb5e9178cc741a8c46c5eb85c1131dfc69f197bf3edaa5f" }, "downloads": -1, "filename": "setupy-0.5.1.tar.gz", "has_sig": false, "md5_digest": "41b941347f16beeaa20fd44a2c225200", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13812, "upload_time": "2019-04-08T23:58:42", "url": "https://files.pythonhosted.org/packages/58/68/def8462accefbcfe9764a6964057107f7e5cd60fc19d7b02ee01766d66b5/setupy-0.5.1.tar.gz" } ], "0.6.0": [ { "comment_text": "", "digests": { "md5": "cc6bb3cdb557ae963bfba70e6643cb48", "sha256": "190ae9a6b55518a2418bca72810adb8753562e863bc0fed832a7b5d52b47e6be" }, "downloads": -1, "filename": "setupy-0.6.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "cc6bb3cdb557ae963bfba70e6643cb48", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 14720, "upload_time": "2019-04-11T00:42:28", "url": "https://files.pythonhosted.org/packages/19/e7/db32b5add3e84d4cc8038cc6f147d53bc41e3d67dd1b0bc4d899e33d8221/setupy-0.6.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "565c8afcb14c5b1e15c351a4499b2d98", "sha256": "9cdda6d574a0f66d3109378e24da75d4ee060f7ec601039750a344b9b1966230" }, "downloads": -1, "filename": "setupy-0.6.0.tar.gz", "has_sig": false, "md5_digest": "565c8afcb14c5b1e15c351a4499b2d98", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13896, "upload_time": "2019-04-11T00:42:29", "url": "https://files.pythonhosted.org/packages/e9/c3/e6cde354b17286bc930eb8d28fd1c25ec9b705e4f065e8b13471b76121d5/setupy-0.6.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "cc6bb3cdb557ae963bfba70e6643cb48", "sha256": "190ae9a6b55518a2418bca72810adb8753562e863bc0fed832a7b5d52b47e6be" }, "downloads": -1, "filename": "setupy-0.6.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "cc6bb3cdb557ae963bfba70e6643cb48", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 14720, "upload_time": "2019-04-11T00:42:28", "url": "https://files.pythonhosted.org/packages/19/e7/db32b5add3e84d4cc8038cc6f147d53bc41e3d67dd1b0bc4d899e33d8221/setupy-0.6.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "565c8afcb14c5b1e15c351a4499b2d98", "sha256": "9cdda6d574a0f66d3109378e24da75d4ee060f7ec601039750a344b9b1966230" }, "downloads": -1, "filename": "setupy-0.6.0.tar.gz", "has_sig": false, "md5_digest": "565c8afcb14c5b1e15c351a4499b2d98", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13896, "upload_time": "2019-04-11T00:42:29", "url": "https://files.pythonhosted.org/packages/e9/c3/e6cde354b17286bc930eb8d28fd1c25ec9b705e4f065e8b13471b76121d5/setupy-0.6.0.tar.gz" } ] }