{ "info": { "author": "Joni Turunen", "author_email": "rojun.itu@gmail.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License" ], "description": "# fissle - Quick command line interfaces\n\nCreate a semi-self-documenting command line interface that handles loading configuration\nfiles and enabling env variable overloading in addition to command line arguments\nby defining a simple schema of the configuration and a class with your \"business logic\".\n\nExample: this is a minimal required setup for having configurations and a command line interface ready for use:\n\n from fissle import c, NamedTuple\n \n @c\n class C(NamedTuple):\n a: int = 1\n \n @c\n class Cli:\n def foo(self):\n # using configuration\n print(c.a)\n \nIn other words, use this to wrap your scripts as command line commands without\nfussing about and maintaining argument parsing and duplicating comments for help or remembering\nwhat the arguments were and did\nwhile still having the typical use experience of a cli program (e.g. --help, subcommands, ...).\nThis implementation is focused on a premise that for a simple script you have a global configuration which\nwould be used through out the user code i.e. a context for the program. That configuration\nis populated with given arguments falling back on\ndefaults in the code and some further complimentary options.\n \nShould work for linux, macos and windows.\n\n## Installing\n\n pip install --user fissle\n \nSee alternative options at the end of the README\n\n## Usage\n\nSee the example file in `tester/__main__.py`. Here's a run down of the individual\nparts in it.\n\nFirst import the required components:\n\n from fissle import c, NamedTuple\n \nIn your code define the schema as a NamedTuple decorating it with `c`:\n\n @c\n class Configuration(NamedTuple):\n a: str = 'A' # a description\n x: int = 1 # x description\n\n\"Configuration\" is an arbitrary name, no magic there. The inherited NamedTuple\nsimplifies the schema's templating to defining just the attributes (i.e. `a` and `x` in this\nexample). Those have a set way:\n\n # attribute: type = default value # Description for the --help\n a: str = 'A' # a description\n \n`a` is the attribute which can be called in the code later with `c.a`. It has a type of 'str', default\nvalue of 'A'. The comment after it is parsed for the command line so it's not redundant. All of these\nparts will be parsed for the '--help' for the subcommands of the cli, which should be defined as follows:\n\n @c\n class Cli:\n def subcommand_foo(self):\n \"\"\"This will be shown in --help for subcommand-foo\"\"\"\n print('foo')\n print(c.a)\n print(c.x)\n\n def subcommand_bar(self):\n \"\"\"This will be shown in --help for subcommand-bar\"\"\"\n print('bar')\n\nThe methods are parsed as subcommands for the cli and their respective doc strings will show in the \nsubcommands' help print out. Note the usage of the parsed configuration `c`:\n\n print(c.a)\n print(c.x)\n \nAlso, to enable autocompletion in IDEs, this hack is needed for the time being:\n\n c: Configuration = c\n\nPut it in the \"global space\" e.g. just after defining the template. See the `tester/__main__.py` for a specific example.\n\nWhen all is complete, the imported `c` variable should have all the bits and pieces for the configuration. It can be\nused inside the Cli class as well as imported around the codebase thus encapsulating all the configurations into one\ncontainer with quick access with attributes `c.a`, `c.x`, etc...\n\n### Running the cli\n\n # Test the damage (presuming you did the flit step below)\n tester -- -h\n tester subcommand-foo -- -h\n tester subcommand-bar\n\nOutput should resemble this (fire v0.1.3 prints out Args, fire v0.2.1 doesn't (though looks much nicer))\n\n \n```\n$ tester subcommand-foo -- -h\n\nType: method\nString form: >\nFile: C:\\Users\\foobar\\code\\py\\fissle\\tester\\__main__.py\nLine: 18\nDocstring: This will be shown in --help for subcommand-foo\nArgs:\n --a (str): a description (Default is 'A')\n --x (int): x description (Default is 1)\n\nUsage: __main__.py subcommand-foo [--X ...]\n```\n\n## Configuration file and environment variables\n\nThe `c` decorator/configuration chains multiple configuration options together in order of priority (lower number overrides higher number):\n\n1. command line arguments\n1. Environment variables\n1. configuration file definitions\n1. defaults in the schema/template/namedtuple class\n\nThe configuration file should be named with postfix `.cfg` e.g. `foo.cfg` and have an ini type formatting with\na 'Default' section:\n\n # foo.cfg\n [Default]\n x = 2\n\nThe keys are the same as what you define in the schema. You can define all, some or none of the attributes.\nSame applies for the env variables.\n \n # linux example\n X=2 tester subcommand-foo\n \n## Installing as command line program i.e. a command\n\n # Install dev version (omit --symlink for more permanent solution):\n flit install --symlink\n \n## Out-of-the-box features via Fire\n\nSee the [Python Fire's Flags](https://github.com/google/python-fire/blob/master/docs/using-cli.md#python-fires-flags)\ndocumentation for nice additional features such as:\n\n # e.g. tester.py is our cli program\n tester.py subcommand-foo -- --trace\n tester.py -- --interactive\n tester.py -- --completion\n \n## Why another cli framework?\n\nThis is just a tool to slap together a cli program in python, so you don't have to resort to bash. The intention is to\nget something reasonably configurable and generic up and running as fast as possible. I can't bother to memorize\nargparses syntax, even though it's a very good package. Also click works nice for more elaborate things though fire is\nmy personal favourite for the time being.\n\n## Installing from source\n\n**Note**:\nIf you prefer some other tooling, maybe try out [DepHell](https://github.com/dephell/dephell)\nto transform this from pipenv to requirements.txt etc.. (or what ever floats you boat)\n\n### pipenv\n\n # From the beginning...\n pip install -U pip pipenv\n \n # on some mac configurations, when pipenv isn't included in the path..\n sudo -H pip install -U pip pipenv\n \n### pipenv environment\n\n pipenv install --ignore-pipfile\n \n # activate the environment alternative 1\n pipenv shell\n \n # activate the environment alternative 2\n pipenv run \n \n**Note**: consecutive steps presume the pipenv environment is being\nused/activated\n\n### Dependencies\n\n* fire - [python-fire](https://github.com/google/python-fire) from google does the cli wrapping\n\n\n## DONE:\n\n* Show params in help / How to pass namedtuple's signature programmatically to the Cli functions? \n * Need to do code generation i.e. write the signature into a separate python file and eval that?\n * Any fire-specific tricks to use for this? Cli(C) definition doesn't work..\n * Maybe overwriting the 'usage' portion or generating a docstring\n * Create a companion class which describes the namedtuple fields' functions\n * hardcoded defaults mechanism\n* config parser\n* decorator or some other wrapper for the cli-class to configure with given parameters without boilerplate\n* c++ template like behaviour in which you can define the named tuple with the cli class\n * code completion should work in the IDE (DONE: a hack around this..)\n * configure should know to chain config file with params \n* Configuration file requires copying fissle in the same directory with the user code\n * location independent now\n* parsing configuration and help/description require separate steps\n * would be nice to have a single point of access and import requirement\n* base level help (