{ "info": { "author": "Johan van der Knijff", "author_email": "johan.vanderknijff@kb.nl", "bugtrack_url": null, "classifiers": [ "Environment :: Console", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3" ], "description": "# Jprofile\n\nJohan van der Knijff, KB/National Library of the Netherlands.\n\n## What is *jprofile*?\n\n*Jprofile* is a simple tool for automated profiling of large batches of *JP2* (JPEG 2000 part 1) images. Internally it wraps around [*jpylyzer*](http://jpylyzer.openpreservation.org/), which is used for validating each image and for extracting its properties. The *jpylyzer* output is then validated against a set of [*Schematron*](http://en.wikipedia.org/wiki/Schematron) schemas that contain the required characteristics for master, access and target images, respectively.\n\n## Batch structure\n\n*Jprofile* was designed for processing digitisation batches that are delivered to the KB by external suppliers. These batches typically contain (losslessly compressed) *master* JP2s, (lossily compressed) *access* JP2s and (sometimes) also *technical target* JP2s. These are located in a folder structure that contains (sub) directories named *master*, *access* and *targets-jp2*, respectively. Below is an example:\n\n\t./testbatch\n\t\u251c\u2500\u2500 access\n\t\u2502 \u251c\u2500\u2500 IMAGE000060.jp2\n\t\u2502 \u251c\u2500\u2500 IMAGE000061.jp2\n\t\u2502 \u251c\u2500\u2500 IMAGE000062.jp2\n\t\u2502 \u251c\u2500\u2500 ::\n\t\u2502 \u251c\u2500\u2500 IMAGE000080.jp2\n\t\u2502 \u2514\u2500\u2500 IMAGE000081.jp2\n\t\u251c\u2500\u2500 master\n\t\u2502 \u251c\u2500\u2500 IMAGE000060.jp2\n\t\u2502 \u251c\u2500\u2500 IMAGE000061.jp2\n\t\u2502 \u251c\u2500\u2500 IMAGE000062.jp2\n\t\u2502 \u251c\u2500\u2500 ::\n\t\u2502 \u251c\u2500\u2500 IMAGE000080.jp2\n\t\u2502 \u2514\u2500\u2500 IMAGE000081.jp2\n\t\u2514\u2500\u2500 targets-jp2\n\n\nAs long as a batch follows this basic structure, *Jprofile* can handle it. Note that:\n\n* *master*, *access* and *targets-jp2* directories may occur at different nesting levels. This is no problem, since *profile* recursively traverses all subdirctories in a batch.\n\n* if either a *master*, *access* or *targets-jp2* directory is missing, *jprofile* will simply ignore it (i.e. it's perfectly OK if your batch only contains *master* images).\n\n* Batches may contain other folders. These are ignored by *jprofile*. \n\n## Licensing\n\n*Jprofile* is released under the [GNU Lesser General Public License](https://www.gnu.org/licenses/lgpl.html).\n\n## Installation\n\nThe easiest method to install *Jprofile* is to use the [*pip* package manager](https://en.wikipedia.org/wiki/Pip_(package_manager)). Alternatively, Windows users can also use stand-alone binaries that don't require Python at all (see below).\n\n## Installation with pip (single user)\n\nThis will work on any platform for which Python is available. You need a recent version of *pip* (version 9.0 or more recent). To install *Jprofile* for a single user, use the following command:\n\n pip install jprofile --user\n\n## Installation with pip (all users)\n\nTo install *Jprofile* for *all* users, use the following command:\n\n pip install jprofile\n\nYou need local admin (Windows) / superuser (Linux) privilige to do this. On Windows, you can do this by running the above command in a Command Prompt window that was opened as Administrator. On Linux, use this:\n\n sudo pip install jprofile\n\n## Installation of Windows binaries\n\nFor Windows users who don't have Python available on their system, stand-alone binaries of *Jprofile* are available. In this case the installation steps are:\n\n1. Download the latest binaries (64 or 32 bit) from the [latest release page ](https://github.com/KBNLresearch/jprofile/releases/latest).\n\n2. Unzip the downloaded file to an empty directory. \n\n## Command-line syntax\n\n\n usage: jprofile batchDir prefixOut -p PROFILE\n\n\n## Positional arguments\n\n**batchDir**: root directory of batch \n\n**prefixOut**: prefix that is used for writing output files\n\n**PROFILE**: name of profile that defines schemas for master, access and target images \n\nTo list all available profiles, use a value of *l* or *list* for *PROFILE*.\n\n\n## Profiles\n\nA *profile* is an *XML*-formatted file that simply defines which schemas are used to validate *jpylyzer*'s output for master, access and target images, respectively. Here's an example:\n\n \n\n \n\n master300Gray_2014.sch\n access300Colour_2014.sch\n master300Colour_2014.sch\n\n \n\nNote that each entry only contains the *name* of a profile, not its full path! All profiles are located in the *profiles* directory in the installation folder.\n\n## Available profiles\n\nThe following profiles are included by default:\n\n| Name|Description|\n| :------| :-----|\n|kb_generic_2014.xml|Generic profile for KB digitisation streams (doesn't include any checks on resolution or colour spaces!)|\n|kb_300Colour_2014.xml|As generic profile, but with additional requirements than resolution equals 300 ppi and colour space is Adobe RGB 1998|\n|kb_300Gray_2014.xml|As generic profile, but with additional requirements than resolution equals 300 ppi and colour space is Gray Gamma 2.2|\n|kb_600Colour_2014.xml|As generic profile, but with additional requirements than resolution equals 600 ppi and colour space is Adobe RGB 1998|\n|kb_600Gray_2014.xml|As generic profile, but with additional requirements than resolution equals 360 ppi and colour space is Gray Gamma 2.2|\n\nIt is possible to create custom-made profiles. Just add them to the *profiles* directory in the installation folder. \n\n## Schemas\n\nThe quality assessment is based on a number of rules/tests that are defined a set of *Schematron* schemas. These are located in the *schemas* folder in the installation directory. In principe *any* property that is reported by *jpylyzer* can be used here, and new tests can be added by editing the schemas. More details on this can be found in [this blog post](http://openpreservation.org/knowledge/blogs/2012/09/04/automated-assessment-jp2-against-technical-profile/). \n\n## Available schemas\n\n| Name|Description|\n|:------| :-----|\n|kbMaster_2014.sch|Generic schema for losslessly-compressed master images according to 2014 specifications|\n|master600Colour_2014.sch|Schema for losslessly-compressed master images, 600 ppi, Adobe RGB (1998) colour space|\n|master600Gray_2014.sch|Schema for losslessly-compressed master images, 600 ppi, Gray Gamma 2.2 colour space|\n|master300Colour_2014.sch|Schema for losslessly-compressed master images, 300 ppi, Adobe RGB (1998) colour space|\n|master300Gray_2014.sch|Schema for losslessly-compressed master images, 300 ppi, Gray Gamma 2.2 colour space|\n|kbAccess_2014.sch|Generic schema for lossily-compressed access images according to 2014 specifications|\n|access600Colour_2014.sch|Schema for lossily-compressed access images, 600 ppi, Adobe RGB (1998) colour space|\n|access600Gray_2014.sch|Schema for lossily-compressed access images, 600 ppi, Gray Gamma 2.2 colour space|\n|access300Colour_2014.sch|Schema for lossily-compressed access images, 300 ppi, Adobe RGB (1998) colour space|\n|access300Gray_2014.sch|Schema for lossily-compressed access images, 300 ppi, Gray Gamma 2.2 colour space|\n\nIt is possible to create custom-made schemas. Just add them to the *schemas* directory in the installation folder.\n\n## Overview of 2014 schemas\n\nThe following tables give a general overview of the technical profiles that the generic master- and access schemas are representing:\n\n### Master\n\n|Parameter|Value|\n|:---|:---|\n|File format|JP2 (JPEG 2000 Part 1)|\n|Compression type|Reversible 5-3 wavelet filter|\n|Colour transform|Yes (only for colour images)|\n|Number of decomposition levels|5|\n|Progression order |RPCL|\n|Tile size |1024 x 1024|\n|Code block size| 64 x 64 (26 x 26)|\n|Precinct size\t|256 x 256 (28) for 2 highest resolution levels; 128 x 128 (27) for remaining resolution levels|\n|Number of quality layers|11|\n|Target compression ratio layers|2560:1 [1] ; 1280:1 [2] ; 640:1 [3] ; 320:1 [4] ; 160:1 [5] ; 80:1 [6] ; 40:1 [7] ; 20:1 [8] ; 10:1 [9] ; 5:1 [10] ; 2.5:1 [11]|\n|Error resilience|Start-of-packet headers; end-of-packet headers; segmentation symbols|\n|Sampling rate|Stored in \"Capture Resolution\" fields|\n|Capture metadata|Embedded as XMP metadata in XML box|\n\n\n### Access\n\n|Parameter|Value|\n|:---|:---|\n|File format|JP2 (JPEG 2000 Part 1)|\n|Compression type|Irreversible 7-9 wavelet filter|\n|Colour transform|Yes (only for colour images)|\n|Number of decomposition levels|5|\n|Progression order |RPCL|\n|Tile size |1024 x 1024|\n|Code block size| 64 x 64 (26 x 26)|\n|Precinct size\t|256 x 256 (28) for 2 highest resolution levels; 128 x 128 (27) for remaining resolution levels|\n|Number of quality layers|8|\n|Target compression ratio layers|2560:1 [1] ; 1280:1 [2] ; 640:1 [3] ; 320:1 [4] ; 160:1 [5] ; 80:1 [6] ; 40:1 [7] ; 20:1 [8]|\n|Error resilience|\tStart-of-packet headers; end-of-packet headers; segmentation symbols|\n|Sampling rate|Stored in \"Capture Resolution\" fields|\n|Capture metadata|Embedded as XMP metadata in XML box|\n\nNote that jpylyzer is unable to establish the compression ratio of individual layers, so the access schema only checks for the overall compression ratio (i.e. 20:1). The more specific schemas (300Colour, 600Gray, etc.) contain additional checks for resolution values, the number of colour components and embedded ICC profiles. \n\n## Usage examples\n\n### List available profiles\n\n jprofile d:\\myBatch mybatch -p list\n\nThis results in a list of all available profiles (these are stored in the installation folder's *profiles* directory):\n\n Available profiles:\n\n kb_600Gray_2014.xml\n kb_300Gray_2014.xml\n kb_300Colour_2014.xml\n kb_600Colour_2014.xml\n kb_generic_2014.xml\n\n\n### Analyse batch\n\n jprofile d:\\myBatch mybatch -p kb_300Colour_2014.xml\n\nThis will result in the creation of 2 output files:\n\n- `mybatch_status.csv` (status output file)\n- `mybatch_failed.txt` (detailed output on images that failed quality asessment)\n\n## Status output file\n\nThis is a comma-separated file with the assessment status of each analysed image. The assessment status is either *pass* (passed all tests) or *fail* (failed one or more tests). Here's an example:\n\n F:\\test\\access\\MMKB03_000004896_00015_access.jp2,pass\n F:\\test\\access\\MMKB03_000004896_00115_access.jp2,pass\n F:\\test\\access\\MMKB03_000004896_00215_access.jp2,pass\n F:\\test\\targets-jp2\\MMKB03_MTF_RGB_20120626_02_01.jp2,fail\n F:\\test\\master\\MMKB03_000004896_00015_master.jp2,pass\n\n\n## Failure output file\n\nAny image that failed one or more tests are reported in the failure output file. For each failed image, it contains a full reference to the file path, followed by the specific errors. An example:\n\n\n F:\\test\\targets-jp2\\MMKB03_MTF_RGB_20120626_02_01.jp2\n *** Schema validation errors:\n Test \"layers = '11'\" failed (wrong number of layers)\n Test \"transformation = '5-3 reversible'\" failed (wrong transformation)\n Test \"comment = 'KB_MASTER_LOSSLESS_01/01/2015'\" failed (wrong codestream comment string)\n ####\n\nEntries in this file are separated by a sequence of 4 '#' characters. Note that each line here corresponds to a failed test in the schema (this information is taken from *Probatron*'s output). For images that are identified as not-valid JP2 some additional information from *jpylyzer*'s output is included as well. For example:\n\n\n F:\\test\\master\\MMUBL07_MTF_GRAY_20121213_01_05.jp2\n *** Schema validation errors:\n Test \"isValidJP2 = 'True'\" failed (no valid JP2)\n *** Jpylyzer JP2 validation errors:\n Test methIsValid failed\n Test precIsValid failed\n Test approxIsValid failed\n Test foundNextTilePartOrEOC failed\n Test foundEOCMarker failed\n ####\n\n\nHere, the outcome of test *isValidJP2* means that the image does not conform to the *JP2* specification. The lines following 'Jpylyzer JP2 validation errors' lists the specific errors that were reported by *jpylyzer*. The meaning of these errors can be found in the *jpylyzer* User Manual.\n\n## Preconditions\n\n- All images that are to be analysed have a .jp2 extension (all others are ignored!)\n- *Master* images are located in a (subdirectory of a) directory called '*master*'\n- *Access* images are located in a (subdirectory of a) directory called '*access*'\n- *Target* images are located in a (subdirectory of a) directory called '*targets-jp2*'.\n- Either of the above directories may be missing.\n\nOther than that, the organisation of images may follow any arbitrary directory structure (*jprofile* does a recursive scan of whole directory tree of a batch)\n\n## Known limitations\n\n- Images that have names containing square brackets (\"[\" and \"]\" are ignored (limitation of *Python*'s *glob* module, will be solved in the future).\n\n## Useful links\n\n- [*jpylyzer*](http://jpylyzer.openpreservation.org/)\n- [*Schematron*](http://en.wikipedia.org/wiki/Schematron)\n- [Automated assesment of JP2 against a technical profile using jpylyzer and Schematron](http://openpreservation.org/blog/2012/09/04/automated-assessment-jp2-against-technical-profile/)\n\n\n\n\n", "description_content_type": null, "docs_url": null, "download_url": "https://github.com/KBNLresearch/jprofile/archive/0.8.0.tar.gz", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/KBNLresearch/jprofile", "keywords": "", "license": "LGPL", "maintainer": "", "maintainer_email": "", "name": "jprofile", "package_url": "https://pypi.org/project/jprofile/", "platform": "POSIX", "project_url": "https://pypi.org/project/jprofile/", "project_urls": { "Download": "https://github.com/KBNLresearch/jprofile/archive/0.8.0.tar.gz", "Homepage": "https://github.com/KBNLresearch/jprofile" }, "release_url": "https://pypi.org/project/jprofile/0.8.0/", "requires_dist": [ "setuptools", "jpylyzer", "lxml" ], "requires_python": ">=2.7, !=3.0.*, !=3.1.*, <4", "summary": "Automated JP2 profiling for digitisation batches", "version": "0.8.0" }, "last_serial": 3262912, "releases": { "0.7.1": [ { "comment_text": "", "digests": { "md5": "1fda8cbe9f0cbeece39bd48ab6b00125", "sha256": "81e8d9425ebce3949cb2108b3af2c0aa743a58fb762eb4e9f0ab448442a72568" }, "downloads": -1, "filename": "jprofile-0.7.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "1fda8cbe9f0cbeece39bd48ab6b00125", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, <4", "size": 41507, "upload_time": "2017-10-17T16:32:21", "url": "https://files.pythonhosted.org/packages/e0/56/0264372711535ea1a62a5b9db5d896608247a5a2966b6f30a18d3f5fcb68/jprofile-0.7.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "6c6eb983a6303936eb9900bb9301595d", "sha256": "ad31fc7182a74da9f077a668329a881cbbaf245d6848c3b26e603b2fa02cb665" }, "downloads": -1, "filename": "jprofile-0.7.1.tar.gz", "has_sig": false, "md5_digest": "6c6eb983a6303936eb9900bb9301595d", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, <4", "size": 18082, "upload_time": "2017-10-17T16:32:23", "url": "https://files.pythonhosted.org/packages/1e/43/23f7b93ba1a6728de425899eb0d86baa38051f01fee92e247dd9226647b1/jprofile-0.7.1.tar.gz" } ], "0.7.2": [ { "comment_text": "", "digests": { "md5": "aa8eb2224fd0b59108e72e87c50109bf", "sha256": "faf19e38ec354210faa4887411bdbf2717b8b8737d97fe7740c3b0cce30ccc99" }, "downloads": -1, "filename": "jprofile-0.7.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "aa8eb2224fd0b59108e72e87c50109bf", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, <4", "size": 41657, "upload_time": "2017-10-18T11:16:16", "url": "https://files.pythonhosted.org/packages/2f/61/b3ff229e12efd49f8b70e5b09f7879f1279d9f645a03d8f8581487297bbb/jprofile-0.7.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "eac5b50d7c9b51b1fc06c9d5a3f6bda7", "sha256": "0618ca2342475634dc0621a8456a23a001ff2fe63e35ff2e81e13e1a3b3d163e" }, "downloads": -1, "filename": "jprofile-0.7.2.tar.gz", "has_sig": false, "md5_digest": "eac5b50d7c9b51b1fc06c9d5a3f6bda7", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, <4", "size": 18231, "upload_time": "2017-10-18T11:16:18", "url": "https://files.pythonhosted.org/packages/63/6c/151ecc05b8447b4f5eb2a7d74815c7b93b0f0d7d774292c87985571b5deb/jprofile-0.7.2.tar.gz" } ], "0.7.3": [ { "comment_text": "", "digests": { "md5": "7392bdc50dc8aabb7723b80a7d7a4ebd", "sha256": "34d7a83cad53b3d4b046388ac87d5d6bf2cddba26757d594c011f3f65257554b" }, "downloads": -1, "filename": "jprofile-0.7.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "7392bdc50dc8aabb7723b80a7d7a4ebd", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, <4", "size": 41650, "upload_time": "2017-10-18T12:03:02", "url": "https://files.pythonhosted.org/packages/1b/03/776e97050fdf78d549cedce8dbe9abcc4cbab90ff03edd8f45397d60fb8d/jprofile-0.7.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "6c4a2ae5ab337f2ebd391e044cb0af70", "sha256": "55200b6e78ba3cb82d0f3df62d54ad2c4215fba7087da1198135a15fc3c78650" }, "downloads": -1, "filename": "jprofile-0.7.3.tar.gz", "has_sig": false, "md5_digest": "6c4a2ae5ab337f2ebd391e044cb0af70", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, <4", "size": 18225, "upload_time": "2017-10-18T12:03:04", "url": "https://files.pythonhosted.org/packages/19/8d/bea7c73474cb971837da2e32251517c3ac93455a9fa3283b8df2b7204c02/jprofile-0.7.3.tar.gz" } ], "0.7.5": [ { "comment_text": "", "digests": { "md5": "ddf84a345e7a5abc462b1d3d4e379b6c", "sha256": "ed4d4ebe7009acde84340209a7b6768fa314980c95c463308263463372316d05" }, "downloads": -1, "filename": "jprofile-0.7.5-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "ddf84a345e7a5abc462b1d3d4e379b6c", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, <4", "size": 37977, "upload_time": "2017-10-18T15:54:21", "url": "https://files.pythonhosted.org/packages/61/7a/2bfdfe5cc8fdb7572469df56153e954342db4c6419ce3d6ec600e0847eb3/jprofile-0.7.5-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "679e5c42f16bde06ff01f3907dd15af1", "sha256": "e475b27c31529af528c00f0256974c2764270ae10d8a7dca340dc622fb546894" }, "downloads": -1, "filename": "jprofile-0.7.5.tar.gz", "has_sig": false, "md5_digest": "679e5c42f16bde06ff01f3907dd15af1", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, <4", "size": 15121, "upload_time": "2017-10-18T15:54:23", "url": "https://files.pythonhosted.org/packages/b7/15/e2b9b0b49cdb50172d27a628dede31a1c23047dc9f6cafd0c4827da9258d/jprofile-0.7.5.tar.gz" } ], "0.8.0": [ { "comment_text": "", "digests": { "md5": "ea3f9d928b4ced9ca78f506d90265b72", "sha256": "c26f6a84ca1c84f1e344bce48a3e714531237f4f60f6f482e0a50c4fb787eac0" }, "downloads": -1, "filename": "jprofile-0.8.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "ea3f9d928b4ced9ca78f506d90265b72", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, <4", "size": 44596, "upload_time": "2017-10-19T12:46:33", "url": "https://files.pythonhosted.org/packages/0d/0d/eaac6c06588736a550dceb52c67ec8dae7f26f8b4eadb5697220befe169c/jprofile-0.8.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a33538b4f39f84ca2a4fff3cc25e8e0f", "sha256": "3ad3edc4330d2c50f3bb201e59f648115cbce7a7a8a0fa6bef68853ba605929f" }, "downloads": -1, "filename": "jprofile-0.8.0.tar.gz", "has_sig": false, "md5_digest": "a33538b4f39f84ca2a4fff3cc25e8e0f", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, <4", "size": 20132, "upload_time": "2017-10-19T12:46:34", "url": "https://files.pythonhosted.org/packages/bb/ba/a0aa47d89493d98081210aa840a12670fb0f98977ce194944e6f0764e681/jprofile-0.8.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "ea3f9d928b4ced9ca78f506d90265b72", "sha256": "c26f6a84ca1c84f1e344bce48a3e714531237f4f60f6f482e0a50c4fb787eac0" }, "downloads": -1, "filename": "jprofile-0.8.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "ea3f9d928b4ced9ca78f506d90265b72", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, <4", "size": 44596, "upload_time": "2017-10-19T12:46:33", "url": "https://files.pythonhosted.org/packages/0d/0d/eaac6c06588736a550dceb52c67ec8dae7f26f8b4eadb5697220befe169c/jprofile-0.8.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a33538b4f39f84ca2a4fff3cc25e8e0f", "sha256": "3ad3edc4330d2c50f3bb201e59f648115cbce7a7a8a0fa6bef68853ba605929f" }, "downloads": -1, "filename": "jprofile-0.8.0.tar.gz", "has_sig": false, "md5_digest": "a33538b4f39f84ca2a4fff3cc25e8e0f", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, <4", "size": 20132, "upload_time": "2017-10-19T12:46:34", "url": "https://files.pythonhosted.org/packages/bb/ba/a0aa47d89493d98081210aa840a12670fb0f98977ce194944e6f0764e681/jprofile-0.8.0.tar.gz" } ] }