{ "info": { "author": "Cameron Simpson", "author_email": "cs@cskk.id.au", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "*Latest release 20191006*:\nAdjust import of cs.deco.cachedmethod.\n\nAssorted convenience functions for files and filenames/pathnames.\n\n## Function `abspath_from_file(path, from_file)`\n\nReturn the absolute path of `path` with respect to `from_file`,\nas one might do for an include file.\n\n## Class `BackedFile`\n\nMRO: `ReadMixin` \nA RawIOBase duck type\nwhich uses a backing file for initial data\nand writes new data to a front scratch file.\n\n### Method `BackedFile.__init__(self, back_file, dirpath=None)`\n\nInitialise the BackedFile using `back_file` for the backing data.\n\n## Class `BackedFile_TestMethods`\n\nMixin for testing subclasses of BackedFile.\nTests self.backed_fp.\n\n## Function `compare(f1, f2, mode='rb')`\n\nCompare the contents of two file-like objects `f1` and `f2` for equality.\n\nIf `f1` or `f2` is a string, open the named file using `mode`\n(default: \"rb\").\n\n## Function `copy_data(fpin, fpout, nbytes, rsize=None)`\n\nCopy `nbytes` of data from `fpin` to `fpout`,\nreturn the number of bytes copied.\n\nParameters:\n* `nbytes`: number of bytes to copy.\n If `None`, copy until EOF.\n* `rsize`: read size, default `DEFAULT_READSIZE`.\n\n## Function `datafrom(arg, *a, **kw)`\n\nGeneral purpose reader for files yielding data from `offset`.\n\n*WARNING*: this function might move the file pointer.\n\nParameters:\n* `f`: the file from which to read data; if a string, the file\n is opened with mode=\"rb\"; if an int, treated as an OS file\n descriptor; otherwise presumed to be a file-like object.\n If that object has a `.fileno()` method, treat that as an\n OS file descriptor and use it.\n* `offset`: starting offset for the data\n* `maxlength`: optional maximum amount of data to yield\n* `readsize`: read size, default DEFAULT_READSIZE.\n\nFor file-like objects, the read1 method is used in preference\nto read if available. The file pointer is briefly moved during\nfetches.\n\n## Function `datafrom_fd(fd, offset=None, readsize=None, aligned=True, maxlength=None)`\n\nGeneral purpose reader for file descriptors yielding data from `offset`.\nThis does not move the file descriptor position.\n\nParameters:\n* `fd`: the file descriptor from which to read.\n* `offset`: the offset from which to read.\n If omitted, use the current file descriptor position.\n* `readsize`: the read size, default: `DEFAULT_READSIZE`\n* `aligned`: if true (the default), the first read is sized\n to align the new offset with a multiple of `readsize`.\n* `maxlength`: if specified yield no more than this many bytes of data.\n\n## Function `file_based(*da, **dkw)`\n\nA decorator which caches a value obtained from a file.\n\nIn addition to all the keyword arguments for `@cs.deco.cachedmethod`,\nthis decorator also accepts the following arguments:\n* `attr_name`: the name for the associated attribute, used as\n the basis for the internal cache value attribute\n* `filename`: the filename to monitor.\n Default from the `._{attr_name}__filename attribute.\n This value will be passed to the method as the `filename` keyword\n parameter.\n* `poll_delay`: delay between file polls, default `DEFAULT_POLL_INTERVAL`.\n* `sig_func`: signature function used to encapsulate the relevant\n information about the file; default\n cs.filestate.FileState({filename}).\n\nIf the decorated function raises OSError with errno == ENOENT,\nthis returns None. Other exceptions are reraised.\n\n## Function `file_data(fp, nbytes=None, rsize=None)`\n\nRead `nbytes` of data from `fp` and yield the chunks as read.\n\nParameters:\n* `nbytes`: number of bytes to read; if None read until EOF.\n* `rsize`: read size, default DEFAULT_READSIZE.\n\n## Function `file_property(*da, **dkw)`\n\nA property whose value reloads if a file changes.\n\n## Function `files_property(func)`\n\nA property whose value reloads if any of a list of files changes.\n\nThis is just the default mode for make_files_property().\n`func` accepts the file path and returns the new value.\nThe underlying attribute name is '_' + func.__name__,\nthe default from make_files_property().\nThe attribute {attr_name}_lock controls access to the property.\nThe attributes {attr_name}_filestates and {attr_name}_paths track the\nassociated file states.\nThe attribute {attr_name}_lastpoll tracks the last poll time.\n\nThe decorated function is passed the current list of files\nand returns the new list of files and the associated value.\nOne example use would be a configuration file with recurive\ninclude operations; the inner function would parse the first\nfile in the list, and the parse would accumulate this filename\nand those of any included files so that they can be monitored,\ntriggering a fresh parse if one changes. Example:\n\n class C(object):\n def __init__(self):\n self._foo_path = '.foorc'\n @files_property\n def foo(self,paths):\n new_paths, result = parse(paths[0])\n return new_paths, result\n\nThe load function is called on the first access and on every\naccess thereafter where an associated file's FileState() has\nchanged and the time since the last successful load exceeds\nthe poll_rate (1s). An attempt at avoiding races is made by\nignoring reloads that raise exceptions and ignoring reloads\nwhere files that were stat()ed during the change check have\nchanged state after the load.\n\n## Function `lines_of(fp, partials=None)`\n\nGenerator yielding lines from a file until EOF.\nIntended for file-like objects that lack a line iteration API.\n\n## Function `lockfile(path, ext=None, poll_interval=None, timeout=None, runstate=None)`\n\nA context manager which takes and holds a lock file.\n\nParameters:\n* `path`: the base associated with the lock file.\n* `ext`: the extension to the base used to construct the lock file name.\n Default: \".lock\"\n* `timeout`: maximum time to wait before failing.\n Default: `None` (wait forever).\n* `poll_interval`: polling frequency when timeout is not 0.\n* `runstate`: optional RunState duck instance supporting cancellation.\n\n## Function `longpath(path, environ=None, prefixes=None)`\n\nReturn `path` with prefixes and environment variables substituted.\nThe converse of shortpath().\n\n## Function `make_files_property(attr_name=None, unset_object=None, poll_rate=1.0)`\n\nConstruct a decorator that watches multiple associated files.\n\nParameters:\n* `attr_name`: the underlying attribute, default: '_' + func.__name__\n* `unset_object`: the sentinel value for \"uninitialised\", default: None\n* `poll_rate`: how often in seconds to poll the file for changes, default: 1\n\nThe attribute {attr_name}_lock controls access to the property.\nThe attributes {attr_name}_filestates and {attr_name}_paths track the\nassociated files' state.\nThe attribute {attr_name}_lastpoll tracks the last poll time.\n\nThe decorated function is passed the current list of files\nand returns the new list of files and the associated value.\nOne example use would be a configuration file with recurive\ninclude operations; the inner function would parse the first\nfile in the list, and the parse would accumulate this filename\nand those of any included files so that they can be monitored,\ntriggering a fresh parse if one changes. Example:\n\n class C(object):\n def __init__(self):\n self._foo_path = '.foorc'\n @files_property\n def foo(self,paths):\n new_paths, result = parse(paths[0])\n return new_paths, result\n\nThe load function is called on the first access and on every\naccess thereafter where an associated file's FileState() has\nchanged and the time since the last successful load exceeds\nthe poll_rate (default 1s). An attempt at avoiding races is made by\nignoring reloads that raise exceptions and ignoring reloads\nwhere files that were stat()ed during the change check have\nchanged state after the load.\n\n## Function `makelockfile(path, ext=None, poll_interval=None, timeout=None, runstate=None)`\n\nCreate a lockfile and return its path.\n\nThe lockfile can be removed with os.remove.\nThis is the core functionality supporting the lockfile()\ncontext manager.\n\nParamaters:\n* `path`: the base associated with the lock file,\n often the filesystem object whose access is being managed.\n* `ext`: the extension to the base used to construct the lockfile name.\n Default: \".lock\"\n* `timeout`: maximum time to wait before failing.\n Default: `None` (wait forever).\n Note that zero is an accepted value\n and requires the lock to succeed on the first attempt.\n* `poll_interval`: polling frequency when timeout is not 0.\n* `runstate`: optional RunState duck instance supporting cancellation.\n Note that if a cancelled RunState is provided\n no attempt will be made to make the lockfile.\n\n## Function `max_suffix(dirpath, pfx)`\n\nCompute the highest existing numeric suffix\nfor names starting with the prefix `pfx`.\n\nThis is generally used as a starting point for picking a new numeric suffix.\n\n## Function `mkdirn(path, sep='')`\n\nCreate a new directory named `path+sep+n`,\nwhere `n` exceeds any name already present.\n\nParameters:\n* `path`: the basic directory path.\n* `sep`: a separator between `path` and n.\n Default: \"\"\n\n## Class `NullFile`\n\nWritable file that discards its input.\n\nNote that this is _not_ an open of `os.devnull`;\nit just discards writes and is not the underlying file descriptor.\n\n### Method `NullFile.__init__(self)`\n\nInitialise the file offset to 0.\n\n## Class `Pathname`\n\nMRO: `builtins.str` \nSubclass of str presenting convenience properties useful for\nformat strings related to file paths.\n\n## Function `poll_file(path, old_state, reload_file, missing_ok=False)`\n\nWatch a file for modification by polling its state as obtained by FileState().\nCall reload_file(path) if the state changes.\nReturn (new_state, reload_file(path)) if the file was modified and was\nunchanged (stable state) beofre and after the reload_file().\nOtherwise return (None, None).\n\nThis may raise an OSError if the `path` cannot be os.stat()ed\nand of course for any exceptions that occur calling `reload_file`.\n\nIf `missing_ok` is true then a failure to os.stat() which\nraises OSError with ENOENT will just return (None, None).\n\n## Function `read_data(fp, nbytes, rsize=None)`\n\nRead `nbytes` of data from `fp`, return the data.\n\nParameters:\n* `nbytes`: number of bytes to copy.\n If `None`, copy until EOF.\n* `rsize`: read size, default `DEFAULT_READSIZE`.\n\n## Function `read_from(fp, rsize=None, tail_mode=False, tail_delay=None)`\n\nGenerator to present text or data from an open file until EOF.\n\nParameters:\n* `rsize`: read size, default: DEFAULT_READSIZE\n* `tail_mode`: if true, yield an empty chunk at EOF, allowing resumption\n if the file grows.\n\n## Class `ReadMixin`\n\nUseful read methods to accomodate modes not necessarily available in a class.\n\nNote that this mixin presumes that the attribute `self._lock`\nis a threading.RLock like context manager.\n\nClasses using this mixin should consider overriding the default\n.datafrom method with something more efficient or direct.\n\n## Function `rewrite(filepath, data, mode='w', backup_ext=None, do_rename=False, do_diff=None, empty_ok=False, overwrite_anyway=False)`\n\nRewrite the file `filepath` with data from the file object `data`.\n\nParameters:\n* `empty_ok`: if not true, raise ValueError if the new data are\n empty.\n Default: `False`.\n* `overwrite_anyway`: if true (default `False`),\n skip the content check and overwrite unconditionally.\n* `backup_ext`: if a nonempty string,\n take a backup of the original at `filepath + backup_ext`.\n* `do_diff`: if not None, call `do_diff(filepath, tempfile)`.\n* `do_rename`: if true (default False),\n rename the temp file to `filepath`\n after copying the permission bits.\n Otherwise (default), copy the tempfile to `filepath`.\n\n## Function `rewrite_cmgr(pathname, mode='w', backup_ext=None, keep_backup=False, do_rename=False, do_diff=None, empty_ok=False, overwrite_anyway=False)`\n\nRewrite a file, presented as a context manager.\n\nParameters:\n* `mode`: file write mode, defaulting to \"w\" for text.\n* `backup_ext`: backup extension. `None` means no backup.\n An empty string generates an extension based on the current time.\n* `keep_backup`: keep the backup file even if everything works.\n* `do_rename`: rename the temporary file to the original to update.\n* `do_diff`: call `do_diff(pathname, tempfile)` before commiting.\n* `empty_ok`: do not consider empty output an error.\n* `overwrite_anyway`: do not update the original if the new\n data are identical.\n\n## Class `RWFileBlockCache`\n\nA scratch file for storing data.\n\n### Method `RWFileBlockCache.__init__(self, pathname=None, dirpath=None, suffix=None, lock=None)`\n\nInitialise the file.\n\nParameters:\n* `pathname`: path of file. If None, create a new file with\n tempfile.mkstemp using dir=`dirpath` and unlink that file once\n opened.\n* `dirpath`: location for the file if made by mkstemp as above.\n* `lock`: an object to use as a mutex, allowing sharing with\n some outer system. A Lock will be allocated if omitted.\n\n## Function `saferename(oldpath, newpath)`\n\nRename a path using os.rename(),\nbut raise an exception if the target path already exists.\nNote: slightly racey.\n\n## Function `seekable(fp)`\n\nTry to test if a filelike object is seekable.\n\nFirst try the .seekable method from IOBase, otherwise try\ngetting a file descriptor from fp.fileno and stat()ing that,\notherwise return False.\n\n## Function `shortpath(path, environ=None, prefixes=None)`\n\nReturn `path` with the first matching leading prefix replaced.\n\nParameters:\n* `environ`: environment mapping if not os.environ\n* `prefixes`: iterable of (prefix, subst) to consider for replacement;\n each `prefix` is subject to environment variable\n substitution before consideration\n The default considers \"$HOME/\" for replacement by \"~/\".\n\n## Class `Tee`\n\nAn object with .write, .flush and .close methods\nwhich copies data to multiple output files.\n\n### Method `Tee.__init__(self, *fps)`\n\nInitialise the Tee; any arguments are taken to be output file objects.\n\n## Function `tee(fp, fp2)`\n\nContext manager duplicating .write and .flush from fp to fp2.\n\n## Function `tmpdir()`\n\nReturn the pathname of the default temporary directory for scratch data,\n$TMPDIR or '/tmp'.\n\n## Function `tmpdirn(tmp=None)`\n\nMake a new temporary directory with a numeric suffix.\n\n## Function `trysaferename(oldpath, newpath)`\n\nA saferename() that returns True on success, False on failure.\n\n\n\n# Release Log\n\n*Release 20191006*:\nAdjust import of cs.deco.cachedmethod.\n\n*Release 20190729*:\ndatafrom_fd: make `offset` optional, defaulting to fd position at call.\n\n*Release 20190617*:\n@file_based: adjust use of @cached from cached(wrap0, **dkw) to cached(**dkw)(wrap0).\n\n*Release 20190101*:\ndatafrom: add maxlength keyword arg, bugfix fd and f.fileno cases.\n\n*Release 20181109*:\nVarious bugfixes for BackedFile.\nUse a file's .read1 method if available in some scenarios.\nmakelockfile: accept am optional RunState control parameter, improve some behaviour.\ndatafrom_fd: new optional maxlength parameter limiting the amount of data returned.\ndatafrom_fd: by default, perform an initial read to align all subsequent reads with the readsize.\ndrop fdreader, add datafrom(f, offset, readsize) accepting a file or a file descriptor, expose datafrom_fd.\nReadMixin.datafrom now mandatory. Add ReadMixin.bufferfrom.\nAssorted other improvements, minor bugfixes, documentation improvements.\n\n*Release 20171231.1*:\nTrite DISTINFO fix, no semantic changes.\n\n*Release 20171231*:\nUpdate imports, bump DEFAULT_READSIZE from 8KiB to 128KiB.\n\n*Release 20170608*:\nMove lockfile and the SharedAppend* classes to cs.sharedfile.\nBackedFile internal changes.\n\n*Release 20160918*:\nBackedFile: redo implementation of .front_file to fix resource leak; add .__len__; add methods .spans, .front_spans and .back_spans to return information about front vs back data.\nseek: bugfix: seek should return the new file offset.\nBackedFile does not subclass RawIOBase, it just works like one.\n\n*Release 20160828*:\nUse \"install_requires\" instead of \"requires\" in DISTINFO.\nRename maxFilenameSuffix to max_suffix.\nPull in OpenSocket file-like socket wrapper from cs.venti.tcp.\nUpdate for cs.asynchron changes.\n... then move cs.fileutils.OpenSocket into new module cs.socketutils.\nNew Tee class, for copying output to multiple files.\nNullFile class which discards writes (==> no-op for Tee).\nNew class SavingFile to accrue output and move to specified pathname when complete.\nMemory usage improvements.\nPolyfill non-threadsafe implementation of pread if os.pread does not exist.\nNew function seekable() to probe a file for seekability.\nSharedAppendFile: provide new .open(filemode) context manager for allowing direct file output for external users.\nNew function makelockfile() presenting the logic to create a lock file separately from the lockfile context manager.\nAssorted bugfixes and improvements.\n\n*Release 20150116*:\nInitial PyPI release.", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://bitbucket.org/cameron_simpson/css/commits/all", "keywords": "python2,python3", "license": "GNU General Public License v3 or later (GPLv3+)", "maintainer": "", "maintainer_email": "", "name": "cs.fileutils", "package_url": "https://pypi.org/project/cs.fileutils/", "platform": "", "project_url": "https://pypi.org/project/cs.fileutils/", "project_urls": { "Homepage": "https://bitbucket.org/cameron_simpson/css/commits/all" }, "release_url": "https://pypi.org/project/cs.fileutils/20191006/", "requires_dist": null, "requires_python": "", "summary": "convenience functions and classes for files and filenames/pathnames", "version": "20191006" }, "last_serial": 5933657, "releases": { "20150116": [ { "comment_text": "", "digests": { "md5": "99322a9058f1a0b401e1e475d5b740fe", "sha256": "5a0092c0bf75d3168ef970bd21d297f8d300395b90e0c05d2412f8b81ba3c717" }, "downloads": -1, "filename": "cs.fileutils-20150116.tar.gz", "has_sig": false, "md5_digest": "99322a9058f1a0b401e1e475d5b740fe", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13204, "upload_time": "2015-01-18T06:14:09", "url": "https://files.pythonhosted.org/packages/79/ba/8d01cf350ede6a120780de08b96acaf32630b11f23724d1823040fe7152f/cs.fileutils-20150116.tar.gz" } ], "20160828": [ { "comment_text": "", "digests": { "md5": "f8509570fbb01404d266b541aa49ddc1", "sha256": "b1c899ff3cb1a05a8ddb327b126da5bb139460083905dab7e74d7199f049de7d" }, "downloads": -1, "filename": "cs.fileutils-20160828.tar.gz", "has_sig": false, "md5_digest": "f8509570fbb01404d266b541aa49ddc1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15312, "upload_time": "2016-08-28T06:05:24", "url": "https://files.pythonhosted.org/packages/93/b0/4b5277e9254fcaf1dd72db6025df101b1e912a230e38cc9cfea9e407e02d/cs.fileutils-20160828.tar.gz" } ], "20160918": [ { "comment_text": "", "digests": { "md5": "7a88d03490bc316e90726986df03dc42", "sha256": "3c4dae756c39c9c13b42dae1220079378c772f970931c857e28497a2435ff649" }, "downloads": -1, "filename": "cs.fileutils-20160918.tar.gz", "has_sig": false, "md5_digest": "7a88d03490bc316e90726986df03dc42", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15321, "upload_time": "2016-09-18T04:59:18", "url": "https://files.pythonhosted.org/packages/85/03/34018f48e4ae8197ca74d2bbad75b5a4df4111f9d8b674297e2b0b0049be/cs.fileutils-20160918.tar.gz" } ], "20171231.1": [ { "comment_text": "", "digests": { "md5": "348ce9261e79e844377b55c920dedbac", "sha256": "a7fbd8d719fbf79f3b434567df80a5563ef9059db0ec5da1739858e690c59002" }, "downloads": -1, "filename": "cs.fileutils-20171231.1.tar.gz", "has_sig": false, "md5_digest": "348ce9261e79e844377b55c920dedbac", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12265, "upload_time": "2017-12-30T23:12:27", "url": "https://files.pythonhosted.org/packages/99/67/1a1afb9860c55b0c3bce3ecbe441325a7619164a467eb496f1f61d65ad46/cs.fileutils-20171231.1.tar.gz" } ], "20181109": [ { "comment_text": "", "digests": { "md5": "b9028f81861774543ad069b07ad986a3", "sha256": "3bc37749989af08308965d41e504122da0b5e857c6b8eb4cc3b747300f20f438" }, "downloads": -1, "filename": "cs.fileutils-20181109.tar.gz", "has_sig": false, "md5_digest": "b9028f81861774543ad069b07ad986a3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18162, "upload_time": "2018-11-08T22:44:45", "url": "https://files.pythonhosted.org/packages/6a/3e/051c23c41130984c2d251f3456fdab8399b03ab066d90623ac0675f12693/cs.fileutils-20181109.tar.gz" } ], "20190101": [ { "comment_text": "", "digests": { "md5": "6fc1d8c37c406af29208d682f31fc896", "sha256": "3c1af48d749abe1f25ab2fa7b8e23ae96b59ade2479d1faaae92bf892b97c3a3" }, "downloads": -1, "filename": "cs.fileutils-20190101.tar.gz", "has_sig": false, "md5_digest": "6fc1d8c37c406af29208d682f31fc896", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18258, "upload_time": "2018-12-31T22:28:48", "url": "https://files.pythonhosted.org/packages/ad/d3/c368c4dbfab430a0697358f0107b16f5fd9b558c76aac3e6e9facb7490e7/cs.fileutils-20190101.tar.gz" } ], "20190617": [ { "comment_text": "", "digests": { "md5": "f1609030161333467733dd9fe2cbec6e", "sha256": "41a82afe9fbf62758c521721ea85dc50208a68d33c5f45307ad3cc478bfdb55c" }, "downloads": -1, "filename": "cs.fileutils-20190617.tar.gz", "has_sig": false, "md5_digest": "f1609030161333467733dd9fe2cbec6e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21379, "upload_time": "2019-06-17T02:54:13", "url": "https://files.pythonhosted.org/packages/c1/87/ecaa34e796db27ceb3de23bde02c4f066f025ea2f5666d847bedc49c30e0/cs.fileutils-20190617.tar.gz" } ], "20190729": [ { "comment_text": "", "digests": { "md5": "2492f2f6c65ccc974cc238c06ddf16dd", "sha256": "258f3c9d138957e3dc47a57716067194b3d9a3141be25f25f125e6016aa52633" }, "downloads": -1, "filename": "cs.fileutils-20190729.tar.gz", "has_sig": false, "md5_digest": "2492f2f6c65ccc974cc238c06ddf16dd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21379, "upload_time": "2019-07-28T23:59:13", "url": "https://files.pythonhosted.org/packages/fc/68/83f04a9a4a8970b77b9fc8d89ccf2538bf3a9a71680b493b45df0219fbc8/cs.fileutils-20190729.tar.gz" } ], "20191006": [ { "comment_text": "", "digests": { "md5": "e8992e76d9ae18dc5ceb11104a66fb67", "sha256": "4232521d92e1fc510fb05a5276a6a24971f55562d3e9e896487810455c65e245" }, "downloads": -1, "filename": "cs.fileutils-20191006.tar.gz", "has_sig": false, "md5_digest": "e8992e76d9ae18dc5ceb11104a66fb67", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25425, "upload_time": "2019-10-06T03:07:28", "url": "https://files.pythonhosted.org/packages/c2/9a/30e4356af403d12a4a977ecf109c6cd17815b3fb58e7da3e7941291af941/cs.fileutils-20191006.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "e8992e76d9ae18dc5ceb11104a66fb67", "sha256": "4232521d92e1fc510fb05a5276a6a24971f55562d3e9e896487810455c65e245" }, "downloads": -1, "filename": "cs.fileutils-20191006.tar.gz", "has_sig": false, "md5_digest": "e8992e76d9ae18dc5ceb11104a66fb67", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25425, "upload_time": "2019-10-06T03:07:28", "url": "https://files.pythonhosted.org/packages/c2/9a/30e4356af403d12a4a977ecf109c6cd17815b3fb58e7da3e7941291af941/cs.fileutils-20191006.tar.gz" } ] }