{ "info": { "author": "Felix Meyer-Wolters", "author_email": "felix@meyerwolters.de", "bugtrack_url": null, "classifiers": [], "description": "# cmdi - Command Interface\n\n## Description\n\nA decorator `@command` that applies a special interface called the _Command Interface_ to its decorated function. Initially written for the _buildlib_.\n\nThe _Command Interface_ allows you to control the exectuion of a function via the _Command Interface_:\n\n- It allows you to save/redirect/mute output streams (stdout/stderr) for its decorated function. This works on file descriptor level, thus it's possible to redirect output of subproesses and C code.\n- It allows you to catch exceptions for its decorated function and return them with the `CmdResult()`, including _return codes_, _error messages_ and colored _status messages_.\n- It allows you to print status messages and summaries for a command at runtime.\n- And more...\n\nA function that is decorated with `@command` can receive a set of sepcial keyword arguments (`_verbose=...`, `_stdout=...`, `_stderr=...`, `catch_err=...`, etc.) and it returns a `CmdResult()` object.\n\n## Requirements\n\nPython `>= 3.7`\n\n## Install\n\n```\npip install cmdi\n```\n\n## Usage\n\n### The `@command` decorator\n\nUse the `@command` decorator to apply the _command interface_ to a function.\n\n```python\nfrom cmdi import command\n\n@command\ndef foo_cmd(x, **cmdargs) -> CmdResult:\n print(x)\n return x * 2\n```\n\nNow you can use `foo_cmd` as a `command`:\n\n```python\nresult = foo_cmd(10)\n```\n\nWhich will print the following output (in color):\n\n```\nCmd: foo_cmd\n------------\n10\nfoo_cmd: Ok\n```\n\nand return a `CmdResult` object:\n\n```python\nCmdResult(\n val=20,\n code=0,\n name='foo_cmd',\n status='Ok',\n color=0,\n stdout=None,\n stderr=None\n)\n```\n\n### Command Function Arguments\n\nYou can define the behaviour of a command function using a set of special keyword argumnets that are applied to the decorated function.\n\nIn this example we redirect the output of `foo_cmd` to a custom writer and catch exceptions, the output and information of the exception are then returned with the `CmdResult()` object:\n\n```python\nfrom cmdi import CmdResult, Pipe\n\n\nresult = foo_cmd(10, _stdout=Pipe(), _catch_err=True)\n\nisinstance(result, CmdResult) # True\n\nprint(result.stdout) # prints caught output.\n```\n\nMore about special keyword arguments can be found in the API documentation below.\n\n### Customizing the Result of a command function\n\nA command always returns a `CmdResult` object, for which the `@command` wrapper function automatically guesses the values, which is good enough in many situations. But sometimes you need fine grained control over the output, e.g. to create function specific return codes:\n\n```python\n@command\ndef foo_cmd(x: str, **cmdargs) -> CmdResult:\n\n print(x)\n somestr = \"foo\" + x\n\n if x == \"bar\":\n code = 0\n else:\n code = 42\n\n # Return a customized Command Result:\n\n return CmdResult(\n val=somestr,\n code=code,\n )\n```\n\n**Note:** In the example above, we return a customized `CmdResult` for which we only customize the fields `val` and `code`. You can customize every field of the `CmdResult` object (optionally). The fields you leave out are set automatically.\n\n### Command Interface Wrappers\n\nSometimes you want to use the _Command Interface_ for an existing function, without touching the function definition. You can do so by creating a _Command Interface Wrapper_:\n\n```python\nfrom cmdi import command, strip_cmdargs, CmdResult\n\n# This function wraps the Command Interface around an existing function:\n\n@command\ndef foo_cmd(x, **cmdargs) -> CmdResult:\n return foo(**strip_cmdargs(loclas()))\n\n\n# The original function that is being wrapped:\n\ndef foo(x) -> int:\n print(x)\n return x * 2\n```\n\n### Command Interface Wrappers and `subprocess` return codes.\n\nIf you need to create a _Command Interface Wrapper_ for an existing function that runs a `subprocess` and your command depends on the `returncode` of that, you can use the `subprocess.CalledProcessError` exception to compose something. E.g.:\n\n```python\nimport subprocess as sp\nfrom cmdi import command, CmdResult, Status\n\n@command\ndef foo_cmd(x, **cmdargs) -> CmdResult:\n\n try:\n return foo(**strip_cmdargs(locals()))\n\n except sp.CalledProcessError as e:\n\n if e.returncode == 13:\n return CmdResult(\n code=e.returncode,\n status=Status.ok,\n )\n elif e.returncode == 42:\n return CmdResult(\n code=e.returncode,\n status=Status.skip,\n )\n else:\n raise sp.CalledProcessError(e.returncode, e.args)\n\n\ndef foo(x) -> int:\n return sp.run([\"my_arg\"], check=True, ...)\n\n```\n\n## API\n\n### decorator `@command`\n\nThis decorator allows you to apply the _command interface_ to a function.\n\nA function decorated with `@command` can take the following keyword arguments:\n\n#### `_verbose: bool = True`\n\nEnable/Disable printing of header/status message during runtime.\n\n**Example:**\n\n```python\nresult = my_command_func(\"some_arg\", _verbose=False)\n```\n\n#### `_color: bool = True`\n\nEnable/Disable color for header/status message.\n\n**Example:**\n\n```python\nresult = my_command_func(\"some_arg\", _color=False)\n```\n\n#### `_stdout: Optional[Pipe] = None`\n\nRedirect stdout of the child function.\n\n**Example:**\n\n```python\nfrom cmdi import Pipe\n\npipe = Pipe(text=False, tty=True, ...) # See Pipe doc for arguments...\n\nresult = my_command_func('foo', _stdout=pipe)\n\nprint(result.stdout) # Prints the caught ouput.\n```\n\n#### `_stderr: Union[Optional[Pipe], STDOUT] = None`\n\nRedirect stderr of the child function.\n\n**Example:**\n\n```python\nfrom cmdi import Pipe\n\npipe = Pipe(text=False, tty=True, ...) # See Pipe doc for arguments...\n\nresult = my_command_func('foo', _stderr=pipe))\n\nprint(result.stderr) # Prints the caught ouput.\n```\n\nIf you want to redirect `stderr` to `stdout`, you can use this:\n\n```python\nfrom cmdi import STDOUT\n\nresult = my_command_func('foo', _stderr=STDOUT))\n```\n\n#### `_catch_err: bool = True`\n\nCatch errors from child function.\n\nThis will let the runtime continue, even if a child function throws an exception. If an exception occurs the `CmdResult` object will provide information about the error at `result.stderr`, `result.code` and `result.status`. The status message will appear in red.\n\n**Example:**\nfrom cmdi import Pipe\n\n```python\nr = my_command_func(\"some_arg\", _catch_err=True, _stderr=Pipe())\n\nr.status # Error\nr.code # 1\nr.stdout # The stderr output from the function call.\n\n```\n\n### dataclass `CmdResult()`\n\nThe command result object.\n\nA function decorated with `@command` returns a `CmdResult` object:\n\n```python\n@dataclass\nclass CmdResult:\n val: Optional[Any]\n code: Optional[int]\n name: Optional[str]\n status: Optional[str]\n color: Optional[int]\n out: Optional[TextIO]\n err: Optional[TextIO]\n```\n\n### dataclass `Pipe()`\n\nUse this type to configure `stdout`/`stderr` for a command call.\n\n**Parameters**\n\n- `save: bool = True` - Save the function ouput if `True`.\n- `text: bool = True` - Save function output as text if `True` else save as bytes.\n- `dup: bool = False` - Redirect ouput at file discriptor level if `True`. This allows you to redirect output of subprocesses and C code.\n- `tty: bool = False` - Keep ANSI sequences for saved output if `True`, else strip ANSI sequences.\n- `mute: bool = False` - Mute output of function call in terminal if `True`. NOTE: You can still save and return the ouput if this is enabled.\n\n**Example:**\n\n```python\nfrom cmdi import CmdResult, Pipe\n\nout_pipe = Pipe(text=False, dup=True, mute=True)\nerr_pipe = Pipe(text=False, dup=True, mute=False)\n\nresult = foo_cmd(10, _stdout=out_pipe, _stderr=err_pipe, _catch_err=True)\n\nprint(result.stdout) # prints caught output.\nprint(result.stderr) # prints caught output.\n```\n\n### Redirect ouput of functions that run subprocesses or C code.\n\nIf you want to redirect the ouput of a function that runs a subprocess or calls C code, you have to use a `Pipe` with the argument `dup=True`. This will catch the output of stdout/stderr at a lower level (by duping file descriptors):\n\n```python\nimport subprocess\nfrom cmdi import command, Pipe\n\n@command\ndef foo(x, **cmdargs) -> CmdResult:\n subprocess.run(\"my_script\")\n\n# Catch stdout of the function via low level redirect:\nfoo(_stdout=Pipe(dup=True))\n```\n\n### function `strip_cmdargs(locals_)`\n\n**Parameters**\n\n- `locals_: Dict[str, Any]`\n\n**Returns**\n\n- `Dict[str, Any]`\n\nRemove cmdargs from dictionary.\nThis function is useful for _Command Interface Wrappers_.\n\nExample usage:\n\n```python\ndef foo(x):\n # Do a lot of stuff\n return x * 2\n\n@command\ndef foo_cmd(x, **cmdargs):\n return foo(strip_cmdargs(locals()))\n```\n\n### function `print_title(result, color, file)`\n\n**Parameter**\n\n- `result: CmdResult`\n- `color: bool = True`\n- `file: Optional[IO[str]] = None`\n\n**Returns**\n\n- `None`\n\nPrint the title for a command result\n\n**Example usage:**\n\n```python\nresult = my_cmd('foo')\n\nprint_title(result)\n```\n\nOutput:\n\n```\nCmd: my_cmd\n-----------\n```\n\n### function `print_status(result, color, file)`\n\n**Parameter**\n\n- `result: CmdResult`\n- `color: bool = True`\n- `file: Optional[IO[str]] = None`\n\n**Returns**\n\n- `None`\n\nPrint the status of a command result.\n\n**Example usage:**\n\n```python\nresult = my_cmd('foo')\n\nprint_status(result)\n```\n\nOutput:\n\n```\nmy_cmd: Ok\n```\n\n### function `print_result(result, color, file)`\n\n**Parameter**\n\n- `result: CmdResult`\n- `color: bool = True`\n- `file: Optional[IO[str]] = None`\n\n**Returns**\n\n- `None`\n\nPrint out the CmdResult object.\n\n**Example usage:**\n\n```python\nresult = my_cmd('foo')\n\nprint_result(result)\n```\n\nOutput:\n\n```\nCmd: my_cmd\n-----------\nStdout:\nRuntime output of my_cmd...\nStderr:\nSome err\nfoo_cmd3: Ok\n```\n\n### function `print_summary(results, color, headline, file)`\n\n**Parameter**\n\n- `results: CmdResult`\n- `color: bool = True`\n- `headline: bool = True`\n- `file: Optional[IO[str]] = None`\n\n**Returns**\n\n- `None`\n\n```python\nfrom cmdi import print_summary\n\nresults = []\n\nresults.append(my_foo_cmd())\nresults.append(my_bar_cmd())\nresults.append(my_baz_cmd())\n\nprint_summary(results)\n```\n\nOutput:\n\n```\nCmd: my_foo_cmd\n---------------\nstdout of foo function...\nmy_foo_cmd: Ok\n\nCmd: my_bar_cmd\n---------------\nstdout of bar function...\nmy_bar_cmd: Ok\n\nCmd: my_baz_cmd\n---------------\nstdout of baz function...\nmy_baz_cmd: Ok\n```\n\n### function `read_popen_pipes(p, interval)`\n\n**Parameter**\n\n- `p: subprocess.Popen`\n- `interval: int = 10` - The interval which the output streams are read and written with.\n\n**Returns**\n\n- `Iterator[Tuple[str, str]]`\n\nThis returns an iterator which returns Popen pipes line by line for both `stdout` and `stderr` in realtime.\n\n**Example usage:**\n\n```python\nfrom cmdi import POPEN_DEFAULTS, read_popen_pipes\n\np = subprocess.Popen(mycmd, **POPEN_DEFAULTS)\n\nfor out_line, err_line in read_popen_pipes:\n print(out_line, end='')\n print(err_line, end='')\n\ncode = p.poll()\n```\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "https://github.com/feluxe/cmdi/tarball/1.1.4", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/feluxe/cmdi", "keywords": "", "license": "unlicensed", "maintainer": "Felix Meyer-Wolters", "maintainer_email": "felix@meyerwolters.de", "name": "cmdi", "package_url": "https://pypi.org/project/cmdi/", "platform": "", "project_url": "https://pypi.org/project/cmdi/", "project_urls": { "Download": "https://github.com/feluxe/cmdi/tarball/1.1.4", "Homepage": "https://github.com/feluxe/cmdi" }, "release_url": "https://pypi.org/project/cmdi/1.1.4/", "requires_dist": null, "requires_python": "", "summary": "", "version": "1.1.4" }, "last_serial": 5792357, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "72ece04e0543250902e5d813b3f22e7d", "sha256": "c4100a3f0f7eb732f0c6d31ec351720eee5ce5a7d188df7e57f66baeb62d87a3" }, "downloads": -1, "filename": "cmdi-0.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "72ece04e0543250902e5d813b3f22e7d", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 2261, "upload_time": "2018-02-13T12:08:13", "url": "https://files.pythonhosted.org/packages/bc/e1/258ce2ee7e6b846114550ce59ce08263cbddcdbb85610360c8a7d363c92f/cmdi-0.0.1-py3-none-any.whl" } ], "0.0.11": [ { "comment_text": "", "digests": { "md5": "6244304da1a70ac5b4ab5a6f19f3bb48", "sha256": "d0afb4319eef0d7d4153475792d9fd7b69482676d05d5db0d082fb360d771898" }, "downloads": -1, "filename": "cmdi-0.0.11-py3-none-any.whl", "has_sig": false, "md5_digest": "6244304da1a70ac5b4ab5a6f19f3bb48", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 5387, "upload_time": "2018-02-16T23:53:21", "url": "https://files.pythonhosted.org/packages/45/5c/16f5682dc7098a786de73ced7e4c84bd5741374d020fc47c820a004ea7f2/cmdi-0.0.11-py3-none-any.whl" } ], "0.0.12": [ { "comment_text": "", "digests": { "md5": "2ef6924fac6adcbed50d164106a10efa", "sha256": "40818821ad852298ba94b315f7d4d7d7f8fe0fd0fa3fa0a18877b20b31952966" }, "downloads": -1, "filename": "cmdi-0.0.12-py3-none-any.whl", "has_sig": false, "md5_digest": "2ef6924fac6adcbed50d164106a10efa", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 5390, "upload_time": "2018-02-17T01:07:30", "url": "https://files.pythonhosted.org/packages/55/06/f7c7e2faca48a5c9289850bdebf155be7cf18d9f65042a8db8073f092b1a/cmdi-0.0.12-py3-none-any.whl" } ], "0.0.13": [ { "comment_text": "", "digests": { "md5": "04a24dd188cc6a3622da98e24bd65054", "sha256": "34472db940439eeb85f0fcb56f3dbd6f36a09ff9c89868e8f341971b77f4b21b" }, "downloads": -1, "filename": "cmdi-0.0.13-py3-none-any.whl", "has_sig": false, "md5_digest": "04a24dd188cc6a3622da98e24bd65054", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 5409, "upload_time": "2018-02-17T02:14:45", "url": "https://files.pythonhosted.org/packages/99/96/9d5efe3ecee3c0ff7f6a43c50597168efd7e039f90b8b458d11678e31e35/cmdi-0.0.13-py3-none-any.whl" } ], "0.0.14": [ { "comment_text": "", "digests": { "md5": "ae961a781e1eeb79eb0da7bea3fa61c3", "sha256": "f7194420a399af1869cf5ae872fa290fae83f685969779594f7daf24fa2b133e" }, "downloads": -1, "filename": "cmdi-0.0.14-py3-none-any.whl", "has_sig": false, "md5_digest": "ae961a781e1eeb79eb0da7bea3fa61c3", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 5417, "upload_time": "2018-02-17T04:12:55", "url": "https://files.pythonhosted.org/packages/a1/7f/8399054cc4828d0ecf0bb22486fae03e7646828bbe3d914cb7811297a4c4/cmdi-0.0.14-py3-none-any.whl" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "5f6d78ee249d14166694f5dab1e00210", "sha256": "6a2f7202dffe03cd9c99645ee263ee9d0e11d2b1e32a9361bea3177010b01fe4" }, "downloads": -1, "filename": "cmdi-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "5f6d78ee249d14166694f5dab1e00210", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 3302, "upload_time": "2018-02-15T15:42:09", "url": "https://files.pythonhosted.org/packages/c2/7f/2667c433023c4a73ce5c95d85f249ffc5b45a4066e8c2d51c6fe7de2092d/cmdi-0.0.2-py3-none-any.whl" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "7e3ed63e02baec2e3cf422811c1682fd", "sha256": "76116a541f7d91ccb16f4f60243113a001e3d4fdf6d620796c4313eb7abf1676" }, "downloads": -1, "filename": "cmdi-0.0.3-py3-none-any.whl", "has_sig": false, "md5_digest": "7e3ed63e02baec2e3cf422811c1682fd", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 3427, "upload_time": "2018-02-15T16:45:57", "url": "https://files.pythonhosted.org/packages/09/02/92738f7f0a905cddd55560be5cb7b754165d3daa04562b7e864df4bfdf0f/cmdi-0.0.3-py3-none-any.whl" } ], "0.0.4": [ { "comment_text": "", "digests": { "md5": "afebc41d15d3f1114ea1d7b6d30ba196", "sha256": "ba552dbeaf676d1eb22d89e24408550b522b762c7fd1d802fffa635154f0788a" }, "downloads": -1, "filename": "cmdi-0.0.4-py3-none-any.whl", "has_sig": false, "md5_digest": "afebc41d15d3f1114ea1d7b6d30ba196", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 3441, "upload_time": "2018-02-15T16:56:19", "url": "https://files.pythonhosted.org/packages/99/9c/f090526149ed54c49f797a84973c6bd3806258eb548d47895963e7aa50ab/cmdi-0.0.4-py3-none-any.whl" } ], "0.0.5": [ { "comment_text": "", "digests": { "md5": "aa604c5e3ab72de231f68a35dd7d2124", "sha256": "21a09f3ae04f1aba0b05d82b8788a6e96f562e5068a70f39b15376dcbc7c6c1b" }, "downloads": -1, "filename": "cmdi-0.0.5-py3-none-any.whl", "has_sig": false, "md5_digest": "aa604c5e3ab72de231f68a35dd7d2124", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 3463, "upload_time": "2018-02-16T13:47:32", "url": "https://files.pythonhosted.org/packages/cb/5a/9d5a0855df724cc9f9988b2bfe90829a3562ffdf6a5f488efeedc18a7e4b/cmdi-0.0.5-py3-none-any.whl" } ], "0.0.6": [ { "comment_text": "", "digests": { "md5": "f785142d109a4be1ac6106b6498541bd", "sha256": "b3433e1e71859173c33540d7987c2554ff143debe0f96582b827d15bfed4bb16" }, "downloads": -1, "filename": "cmdi-0.0.6-py3-none-any.whl", "has_sig": false, "md5_digest": "f785142d109a4be1ac6106b6498541bd", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 3468, "upload_time": "2018-02-16T13:53:33", "url": "https://files.pythonhosted.org/packages/fd/3d/9f1a3491ca03019e480e0430c855f47b2390a29d3fceaf62e500852c497e/cmdi-0.0.6-py3-none-any.whl" } ], "0.0.7": [ { "comment_text": "", "digests": { "md5": "24797f22d05b4b9e2e66159938bb170e", "sha256": "5a5a25ae154315628abbbfc850962d3570e9805948d006586a9c3112336b6894" }, "downloads": -1, "filename": "cmdi-0.0.7-py3-none-any.whl", "has_sig": false, "md5_digest": "24797f22d05b4b9e2e66159938bb170e", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 3569, "upload_time": "2018-02-16T16:32:26", "url": "https://files.pythonhosted.org/packages/09/53/1be4b3feaa6eb67426df90c41b2253dba521b3eec8c299f9a5f4cd477687/cmdi-0.0.7-py3-none-any.whl" } ], "0.0.8": [ { "comment_text": "", "digests": { "md5": "5e0432ab819a62cd43c92cfba5a74504", "sha256": "f8e05af0d2236193d6ed3e8da8295d9b6a69f4caddab3c495aef2f7304f7249b" }, "downloads": -1, "filename": "cmdi-0.0.8-py3-none-any.whl", "has_sig": false, "md5_digest": "5e0432ab819a62cd43c92cfba5a74504", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 3573, "upload_time": "2018-02-16T16:35:29", "url": "https://files.pythonhosted.org/packages/32/15/0239e1eae8567d8ae3be63de440abaa70ad7c0cba953f66dbd0b3616898c/cmdi-0.0.8-py3-none-any.whl" } ], "0.0.9": [ { "comment_text": "", "digests": { "md5": "6d948bf0f0443087c2002669bb675d93", "sha256": "ae7303f71fc840f576634bac561468a6fdc8ce337d7c121967a6a72f01f75bce" }, "downloads": -1, "filename": "cmdi-0.0.9-py3-none-any.whl", "has_sig": false, "md5_digest": "6d948bf0f0443087c2002669bb675d93", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 5131, "upload_time": "2018-02-16T21:36:12", "url": "https://files.pythonhosted.org/packages/64/4b/d0f917b3f33ebdaf163e0c862cb8f76e50c7969b98447b1f200a9b9e7c1f/cmdi-0.0.9-py3-none-any.whl" } ], "0.1.0": [ { "comment_text": "", "digests": { "md5": "db8c3b4dba6c493a7c595d0f0cb9e645", "sha256": "33d0e2c58880ae3266e4e04ad3127ef6ea34facb4a81b29a0b737db1f2295810" }, "downloads": -1, "filename": "cmdi-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "db8c3b4dba6c493a7c595d0f0cb9e645", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 6012, "upload_time": "2018-02-27T00:42:40", "url": "https://files.pythonhosted.org/packages/7e/a3/3a07ba6d11d29f1a16b24283a427f8dfd492ff14486cd8900a43080ff11d/cmdi-0.1.0-py3-none-any.whl" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "e76773588eca3494404556fd5e58f8ad", "sha256": "48da74000b925f9412c438d0042347c2be5b307aaf343e7a2e81ed4e2fb81906" }, "downloads": -1, "filename": "cmdi-0.2.0-py3-none-any.whl", "has_sig": false, "md5_digest": "e76773588eca3494404556fd5e58f8ad", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 4629, "upload_time": "2018-03-22T18:15:37", "url": "https://files.pythonhosted.org/packages/8a/a4/306ff5718d45f744e85cf488f50162938b60ff500b20f81b6b45d84b9a59/cmdi-0.2.0-py3-none-any.whl" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "9c51b876d6bbc8c18cc62c691a9022d5", "sha256": "c8a76f80f67e897e4d7a85bc95bf9f8a406e4785313758801dcfcfb2493432c1" }, "downloads": -1, "filename": "cmdi-0.2.1-py3-none-any.whl", "has_sig": false, "md5_digest": "9c51b876d6bbc8c18cc62c691a9022d5", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 4616, "upload_time": "2018-03-24T15:01:28", "url": "https://files.pythonhosted.org/packages/bd/27/401b0799be0e9a957d242c6f2d421962639bc14666f0f4af0f9101ee2a53/cmdi-0.2.1-py3-none-any.whl" } ], "0.2.2": [ { "comment_text": "", "digests": { "md5": "32d7b3d9595eef5324127e9923604309", "sha256": "0704dab1058ccfa714c54069e136d10928746da4ccef66c43a94a44112eb0617" }, "downloads": -1, "filename": "cmdi-0.2.2-py3-none-any.whl", "has_sig": false, "md5_digest": "32d7b3d9595eef5324127e9923604309", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 4617, "upload_time": "2018-03-24T15:07:30", "url": "https://files.pythonhosted.org/packages/b3/37/41c08e72f12e21ec5a2ec126a0d3b6827e910b86072e153d43db5c1df3f5/cmdi-0.2.2-py3-none-any.whl" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "786cebda04afb5e71bce06851cc0a9bb", "sha256": "fdf9bc66d53a6003573e22004b78880d485f9b5f323b478b99666ee32e7481c7" }, "downloads": -1, "filename": "cmdi-0.3.0-py3-none-any.whl", "has_sig": false, "md5_digest": "786cebda04afb5e71bce06851cc0a9bb", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 4394, "upload_time": "2018-03-24T19:08:26", "url": "https://files.pythonhosted.org/packages/e4/80/1e0e7b80064e47c0b82cc65048a643b3a7291d71baa0d288ba7d0adcb80b/cmdi-0.3.0-py3-none-any.whl" } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "5d76c902473c02914698f4acd98383dd", "sha256": "085bbfc27db21908e1949413fe53c93c728e9500f4c5ed6d6d9b488faf960b63" }, "downloads": -1, "filename": "cmdi-0.3.1-py3-none-any.whl", "has_sig": false, "md5_digest": "5d76c902473c02914698f4acd98383dd", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 4402, "upload_time": "2018-03-26T14:12:46", "url": "https://files.pythonhosted.org/packages/e4/30/e2933570ed5a9580d686c49abee006d2e57d126b697b155acbe9036b968c/cmdi-0.3.1-py3-none-any.whl" } ], "0.3.2": [ { "comment_text": "", "digests": { "md5": "fc167d128479558f0e6b2cb519500ddb", "sha256": "91b10c496f2f423ba895c8c5f14ccb8695e344588ff18a9f9ec7c298790f09cc" }, "downloads": -1, "filename": "cmdi-0.3.2-py3-none-any.whl", "has_sig": false, "md5_digest": "fc167d128479558f0e6b2cb519500ddb", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 4400, "upload_time": "2018-03-26T16:13:03", "url": "https://files.pythonhosted.org/packages/fd/d6/9ae15a0ce431414d1eded1e043eb3c889360186328ab25bbd02a2003b95a/cmdi-0.3.2-py3-none-any.whl" } ], "0.3.3": [ { "comment_text": "", "digests": { "md5": "58230e9613a2abb52086b04893b59f43", "sha256": "4ade649f3e98ab352e36bf2a6d0ebe4d6e3b2bea02083cbd4af198031a15bc86" }, "downloads": -1, "filename": "cmdi-0.3.3-py3-none-any.whl", "has_sig": false, "md5_digest": "58230e9613a2abb52086b04893b59f43", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 3568, "upload_time": "2018-09-05T17:28:31", "url": "https://files.pythonhosted.org/packages/74/4a/1890e766978c342804b77c1cea5eb3d1a7cdd35f8155bf329dad5123f032/cmdi-0.3.3-py3-none-any.whl" } ], "0.3.4": [ { "comment_text": "", "digests": { "md5": "a7795c05f887005f93814f4fb468fe4b", "sha256": "c009239c451c39c551034c297429d04967571c680329eb7f621b12ae78ef02c9" }, "downloads": -1, "filename": "cmdi-0.3.4-py3-none-any.whl", "has_sig": false, "md5_digest": "a7795c05f887005f93814f4fb468fe4b", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 3568, "upload_time": "2018-12-11T05:00:22", "url": "https://files.pythonhosted.org/packages/4d/df/384e685eeaae4dffc30da1bc548852257b4d4aa5432a331894973497cc6f/cmdi-0.3.4-py3-none-any.whl" } ], "0.3.5": [ { "comment_text": "", "digests": { "md5": "19bba0fe121a18d9ab689f58a2053573", "sha256": "932436bb6b02079fbf98b90cd54fa2b76cb3d8640f62af32e09774daf5e96e51" }, "downloads": -1, "filename": "cmdi-0.3.5-py3-none-any.whl", "has_sig": false, "md5_digest": "19bba0fe121a18d9ab689f58a2053573", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 3581, "upload_time": "2019-05-23T00:26:04", "url": "https://files.pythonhosted.org/packages/c4/d0/e3fd14889c601b266467c58659753990ed6b9182c0b22f1a241a6ba078b8/cmdi-0.3.5-py3-none-any.whl" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "f4a9db2f88e366baf90f4fbab2cc522e", "sha256": "f79aead3494cbf270c56975bb429431b70c251c650933843fd5d79b3f5d0db28" }, "downloads": -1, "filename": "cmdi-0.4.0-py3-none-any.whl", "has_sig": false, "md5_digest": "f4a9db2f88e366baf90f4fbab2cc522e", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 3582, "upload_time": "2019-05-28T12:08:37", "url": "https://files.pythonhosted.org/packages/e6/5d/6eb7ca570230a593416fda6bfb28f76dac5401e8a9ad93d2840f56482c9b/cmdi-0.4.0-py3-none-any.whl" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "14ac978652f457ed5752e970686547aa", "sha256": "8f91e127d39d27bb75a5bf57e3f4eecd025fa681b9ec25395038d0c0469dc686" }, "downloads": -1, "filename": "cmdi-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "14ac978652f457ed5752e970686547aa", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8488, "upload_time": "2019-07-19T18:23:17", "url": "https://files.pythonhosted.org/packages/35/d2/c0b0ac6be1e57493a0001a26aa6b0168048a014abc1bab855ed1d756e92e/cmdi-1.0.0-py3-none-any.whl" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "6e6c32a559eb78f22ee6a9ec97826c46", "sha256": "4a7906e602d16fd04db6347175f7c9859f216f99282e638c1c1abd95c84166b7" }, "downloads": -1, "filename": "cmdi-1.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "6e6c32a559eb78f22ee6a9ec97826c46", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8487, "upload_time": "2019-07-20T09:53:37", "url": "https://files.pythonhosted.org/packages/3f/d1/921e6dcd61914d42522d327c03bfbe05ea770d298c486d8925a1cc58f103/cmdi-1.0.1-py3-none-any.whl" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "90334d46dfcf4d15b26279bea520c18c", "sha256": "02a448ebf11ae677f7e1038e743971f4fa20ae2db365ab87f00162645adadb88" }, "downloads": -1, "filename": "cmdi-1.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "90334d46dfcf4d15b26279bea520c18c", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8487, "upload_time": "2019-07-20T09:59:24", "url": "https://files.pythonhosted.org/packages/65/bc/a261227e2f582f0bb77dbba2a0236880c7ec7b44c83a517b1c2ece9e31d3/cmdi-1.0.2-py3-none-any.whl" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "7dfc9de6c4f00d317859eb13425ac0b9", "sha256": "9a825abf50a63ad278685df26e47e1dc5fe298a5a64d099d45d6d31ae28420a3" }, "downloads": -1, "filename": "cmdi-1.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "7dfc9de6c4f00d317859eb13425ac0b9", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11920, "upload_time": "2019-08-02T16:05:30", "url": "https://files.pythonhosted.org/packages/93/d9/b1de89be529d5b96ffe7ea3edf747390a175bb25b2a95a70114970caf8d5/cmdi-1.1.0-py3-none-any.whl" } ], "1.1.1": [ { "comment_text": "", "digests": { "md5": "a49fd8f7389545897b774e0720d64412", "sha256": "5d7c8c4141f8f43bf84f289e713ef0dd94cbcd9c6827f274317b93342c465548" }, "downloads": -1, "filename": "cmdi-1.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "a49fd8f7389545897b774e0720d64412", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11980, "upload_time": "2019-08-02T17:00:56", "url": "https://files.pythonhosted.org/packages/73/89/85ef6037a51a654c274251458c637fb1bb03680e0c6bbc871ef977a5cbcd/cmdi-1.1.1-py3-none-any.whl" } ], "1.1.2": [ { "comment_text": "", "digests": { "md5": "dda8e6808a81a2a076c1bdc2b40518d8", "sha256": "6ac3b584cc0fce80fa56b06f4f07b6295f9e2a67f0d1d96c6e652bb9ad592fd7" }, "downloads": -1, "filename": "cmdi-1.1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "dda8e6808a81a2a076c1bdc2b40518d8", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11904, "upload_time": "2019-08-06T15:58:42", "url": "https://files.pythonhosted.org/packages/6a/11/f8de03b3e819d4360be4cff02c2201bab44c12221b5ab3012aacf24878bb/cmdi-1.1.2-py3-none-any.whl" } ], "1.1.3": [ { "comment_text": "", "digests": { "md5": "7e92e0ca1fc72660eb40d129f3d7abd2", "sha256": "11587e033712a6af05066e19b11c39fc879de9280cb231043bc4f7e88f03d379" }, "downloads": -1, "filename": "cmdi-1.1.3-py3-none-any.whl", "has_sig": false, "md5_digest": "7e92e0ca1fc72660eb40d129f3d7abd2", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11211, "upload_time": "2019-08-07T08:47:07", "url": "https://files.pythonhosted.org/packages/12/1a/f2fd2a6ea058c09a208e84550105e71d63b7baa69b3052489b679a1f23e1/cmdi-1.1.3-py3-none-any.whl" } ], "1.1.4": [ { "comment_text": "", "digests": { "md5": "badd8dcd02f992f83932291f23df3b7b", "sha256": "0b1caed8d5dfd107d63690da069034120034c73da1c97d15725bc4f47859bb75" }, "downloads": -1, "filename": "cmdi-1.1.4-py3-none-any.whl", "has_sig": false, "md5_digest": "badd8dcd02f992f83932291f23df3b7b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11217, "upload_time": "2019-09-06T13:46:04", "url": "https://files.pythonhosted.org/packages/e4/aa/14a3708eb92bcf2dc6538091d61535432647e525991f88ddd04f8344809e/cmdi-1.1.4-py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "badd8dcd02f992f83932291f23df3b7b", "sha256": "0b1caed8d5dfd107d63690da069034120034c73da1c97d15725bc4f47859bb75" }, "downloads": -1, "filename": "cmdi-1.1.4-py3-none-any.whl", "has_sig": false, "md5_digest": "badd8dcd02f992f83932291f23df3b7b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11217, "upload_time": "2019-09-06T13:46:04", "url": "https://files.pythonhosted.org/packages/e4/aa/14a3708eb92bcf2dc6538091d61535432647e525991f88ddd04f8344809e/cmdi-1.1.4-py3-none-any.whl" } ] }