rispy


Namerispy JSON
Version 0.9.0 PyPI version JSON
download
home_pageNone
SummaryA Python reader/writer of RIS reference files
upload_time2024-01-18 03:51:39
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseNone
keywords ris parser bibliograph
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # rispy - an RIS file parser/writer for Python

[![PyPI version](https://badge.fury.io/py/rispy.svg)](https://badge.fury.io/py/rispy)

A Python 3.8+ reader/writer of RIS reference files.

*Pronunciation* - `rispee` - like "crispy", but without the c.

## Usage

Parsing:

```python
>>> import rispy
>>> filepath = 'tests/data/example_full.ris'
>>> with open(filepath, 'r') as bibliography_file:
...     entries = rispy.load(bibliography_file)
...     for entry in entries:
...         print(entry['id'])
...         print(entry['first_authors'])
12345
['Marx, Karl', 'Lindgren, Astrid']
12345
['Marxus, Karlus', 'Lindgren, Astrid']

```

A file path can also be used to read RIS files. If an encoding is not specified in ``load``, the default system encoding will be used.

```python
>>> from pathlib import Path
>>> import rispy
>>> p = Path('tests', 'data', 'example_utf_chars.ris')
>>> entries = rispy.load(p, encoding='utf-8')
>>> for entry in entries:
...     print(entry['authors'][0])
Dobrokhotova, Yu E.

```

Writing:

```python
>>> import rispy
>>> entries = [
... {'type_of_reference': 'JOUR',
...  'id': '42',
...  'primary_title': 'The title of the reference',
...  'first_authors': ['Marxus, Karlus', 'Lindgren, Astrid']
...  },{
... 'type_of_reference': 'JOUR',
...  'id': '43',
...  'primary_title': 'Reference 43',
...  'abstract': 'Lorem ipsum'
...  }]
>>> filepath = 'export.ris'
>>> with open(filepath, 'w') as bibliography_file:
...     rispy.dump(entries, bibliography_file)

```

## Example RIS entry

```text
   1.
   TY  - JOUR
   ID  - 12345
   T1  - Title of reference
   A1  - Marx, Karl
   A1  - Lindgren, Astrid
   A2  - Glattauer, Daniel
   Y1  - 2014//
   N2  - BACKGROUND: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.  RESULTS: Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. CONCLUSIONS: Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium.
   KW  - Pippi
   KW  - Nordwind
   KW  - Piraten
   JF  - Lorem
   JA  - lorem
   VL  - 9
   IS  - 3
   SP  - e0815
   CY  - United States
   PB  - Fun Factory
   PB  - Fun Factory USA
   SN  - 1932-6208
   M1  - 1008150341
   L2  - http://example.com
   ER  -
```

## TAG_KEY_MAPPING

The most fields contain string values, but some like first_authors (A1) are parsed into lists. The default mapping were created from specifications scattered around the web, but to our knowledge there is not one single source of RIS truth, so these may need to be modified for specific export systems:

- [Wikipedia](https://en.wikipedia.org/wiki/RIS_(file_format))
- [ResearcherId](https://web.archive.org/web/20170707033254/http://www.researcherid.com/resources/html/help_upload.htm)
- [Refman](https://web.archive.org/web/20110930172154/http://www.refman.com/support/risformat_intro.asp)
- [Refman (RIS format)](https://web.archive.org/web/20110930172154/http://www.refman.com/support/risformat_intro.asp)
- [Zotero](https://github.com/zotero/translators/blob/master/RIS.js)

### Complete list of ListType tags

```python
>>> from rispy import LIST_TYPE_TAGS
>>> print(LIST_TYPE_TAGS)
['A1', 'A2', 'A3', 'A4', 'AU', 'KW', 'N1', 'UR']

```

### Complete default mapping

```python
>>> from rispy import TAG_KEY_MAPPING
>>> from pprint import pprint
>>> pprint(TAG_KEY_MAPPING)
{'A1': 'first_authors',
 'A2': 'secondary_authors',
 'A3': 'tertiary_authors',
 'A4': 'subsidiary_authors',
 'AB': 'abstract',
 'AD': 'author_address',
 'AN': 'accession_number',
 'AU': 'authors',
 'C1': 'custom1',
 'C2': 'custom2',
 'C3': 'custom3',
 'C4': 'custom4',
 'C5': 'custom5',
 'C6': 'custom6',
 'C7': 'custom7',
 'C8': 'custom8',
 'CA': 'caption',
 'CN': 'call_number',
 'CY': 'place_published',
 'DA': 'date',
 'DB': 'name_of_database',
 'DO': 'doi',
 'DP': 'database_provider',
 'EP': 'end_page',
 'ER': 'end_of_reference',
 'ET': 'edition',
 'ID': 'id',
 'IS': 'number',
 'J2': 'alternate_title1',
 'JA': 'alternate_title2',
 'JF': 'alternate_title3',
 'JO': 'journal_name',
 'KW': 'keywords',
 'L1': 'file_attachments1',
 'L2': 'file_attachments2',
 'L4': 'figure',
 'LA': 'language',
 'LB': 'label',
 'M1': 'note',
 'M3': 'type_of_work',
 'N1': 'notes',
 'N2': 'notes_abstract',
 'NV': 'number_of_volumes',
 'OP': 'original_publication',
 'PB': 'publisher',
 'PY': 'year',
 'RI': 'reviewed_item',
 'RN': 'research_notes',
 'RP': 'reprint_edition',
 'SE': 'section',
 'SN': 'issn',
 'SP': 'start_page',
 'ST': 'short_title',
 'T1': 'primary_title',
 'T2': 'secondary_title',
 'T3': 'tertiary_title',
 'TA': 'translated_author',
 'TI': 'title',
 'TT': 'translated_title',
 'TY': 'type_of_reference',
 'UK': 'unknown_tag',
 'UR': 'urls',
 'VL': 'volume',
 'Y1': 'publication_year',
 'Y2': 'access_date'}

```

### Override key mapping

The parser use a `TAG_KEY_MAPPING`, which one can override by calling `rispy.load()` with the `mapping` parameter.

```python
>>> from copy import deepcopy
>>> import rispy
>>> from pprint import pprint

>>> filepath = 'tests/data/example_full.ris'
>>> mapping = deepcopy(rispy.TAG_KEY_MAPPING)
>>> mapping["SP"] = "pages_this_is_my_fun"
>>> with open(filepath, 'r') as bibliography_file:
...     entries = rispy.load(bibliography_file, mapping=mapping)
...     pprint(sorted(entries[0].keys()))
['alternate_title2',
 'alternate_title3',
 'file_attachments2',
 'first_authors',
 'id',
 'issn',
 'keywords',
 'note',
 'notes_abstract',
 'number',
 'pages_this_is_my_fun',
 'place_published',
 'primary_title',
 'publication_year',
 'publisher',
 'secondary_authors',
 'type_of_reference',
 'urls',
 'volume']

```

List tags can be customized in the same way, by passing a list to the `list_tags` parameter.

### Changing rispy behavior

There are a few flags that can be passed to `rispy.load()` and `rispy.dump()` that change how `rispy` deals with tags. For example, setting `skip_unknown_tags` to `True` will cause `rispy` do not read or write tags not in the tag map. More can be found in the docstrings for each class. If more customization is necessary, a custom implementation can be created (see next section).

## Using custom implementations

Not all RIS files follow the same formatting guidelines. There is an interface for creating custom implementations for reading and writing such files. An implementation contains the methods and parameters used to work with RIS files, and should be passed to `rispy.load()` or `rispy.dump()`.

### Customizing implementations

Creating a custom implentation involves creating a class that inherits a base class, and overriding the necessary variables and methods. One of the existing parsers can also be inherited. Inheriting an existing class is advantageous if only minor changes need to be made. The sections below document what is available to be overriden, along with a few examples.

#### Parsing

Custom parsers can inherit `RisParser` (the default parser) or `BaseParser`. Various parameters and methods can be overridden when creating a new parser. These are documented in the `BaseParser` docstring.

Examples:

```python
class WokParser(BaseParser):
      """Subclass of Base for reading Wok RIS files."""

      START_TAG = "PT"
      IGNORE = ["FN", "VR", "EF"]
      PATTERN = r"^[A-Z][A-Z0-9] |^ER\s?|^EF\s?"
      DEFAULT_MAPPING = WOK_TAG_KEY_MAPPING
      DEFAULT_LIST_TAGS = WOK_LIST_TYPE_TAGS

      def get_content(self, line):
         return line[2:].strip()

      def is_header(self, line):
         return True

```

### Writing

Writing is very similar to parsing. A custom writer class can inherit `BaseWriter` or one if its subclasses, such as `RisWriter`.

Examples:

```python
class RisWriter(BaseWriter):
      """Subclass of BaseWriter for writing RIS files."""

      START_TAG = "TY"
      PATTERN = "{tag}  - {value}"
      DEFAULT_MAPPING = TAG_KEY_MAPPING
      DEFAULT_LIST_TAGS = LIST_TYPE_TAGS

      def set_header(self, count):
         return "{i}.".format(i=count)

```

## Other functionality

Other various utilities included in `rispy` are documented below.

### Reference type conversion

A method is available to convert common RIS reference types into more readable terms. It takes a list of references and returns a copy of that list with modified reference types. The map for this conversion is located in ``config.py``.

```python
>>> from rispy.utils import convert_reference_types
>>> refs = [{"type_of_reference": "JOUR"}]
>>> print(convert_reference_types(refs))
[{'type_of_reference': 'Journal'}]

```

## Software for other RIS-like formats

Some RIS-like formats contain rich citation data, for example lists and nested attributes, that `rispy` does not
support. Software specializing on these formats include:

* [nbib](https://pypi.org/project/nbib/) - parses the "PubMed" or "MEDLINE" format

## Developer instructions

Common developer commands are in the provided `Makefile`; if you don't have `make` installed, you can view the make commands and run the commands from the command-line manually:

```bash
# setup environment
python -m venv venv
source venv/bin/activate
python -m pip install -U pip
python -m pip install -e ".[dev]"

# check if code format changes are required
make lint

# reformat code
make format

# run tests
make test
```

Github Actions are currently enabled to run `lint` and `test` when submitting a pull-request.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "rispy",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "Andy Shapiro <shapiromatron@gmail.com>",
    "keywords": "RIS,parser,bibliograph",
    "author": null,
    "author_email": "Maik Derstappen <md@derico.de>",
    "download_url": "https://files.pythonhosted.org/packages/68/bf/c57b399f569c50266615f8cd56c046b6d28064d65d1b26714a951eb5f29f/rispy-0.9.0.tar.gz",
    "platform": null,
    "description": "# rispy - an RIS file parser/writer for Python\n\n[![PyPI version](https://badge.fury.io/py/rispy.svg)](https://badge.fury.io/py/rispy)\n\nA Python 3.8+ reader/writer of RIS reference files.\n\n*Pronunciation* - `rispee` - like \"crispy\", but without the c.\n\n## Usage\n\nParsing:\n\n```python\n>>> import rispy\n>>> filepath = 'tests/data/example_full.ris'\n>>> with open(filepath, 'r') as bibliography_file:\n...     entries = rispy.load(bibliography_file)\n...     for entry in entries:\n...         print(entry['id'])\n...         print(entry['first_authors'])\n12345\n['Marx, Karl', 'Lindgren, Astrid']\n12345\n['Marxus, Karlus', 'Lindgren, Astrid']\n\n```\n\nA file path can also be used to read RIS files. If an encoding is not specified in ``load``, the default system encoding will be used.\n\n```python\n>>> from pathlib import Path\n>>> import rispy\n>>> p = Path('tests', 'data', 'example_utf_chars.ris')\n>>> entries = rispy.load(p, encoding='utf-8')\n>>> for entry in entries:\n...     print(entry['authors'][0])\nDobrokhotova, Yu E.\n\n```\n\nWriting:\n\n```python\n>>> import rispy\n>>> entries = [\n... {'type_of_reference': 'JOUR',\n...  'id': '42',\n...  'primary_title': 'The title of the reference',\n...  'first_authors': ['Marxus, Karlus', 'Lindgren, Astrid']\n...  },{\n... 'type_of_reference': 'JOUR',\n...  'id': '43',\n...  'primary_title': 'Reference 43',\n...  'abstract': 'Lorem ipsum'\n...  }]\n>>> filepath = 'export.ris'\n>>> with open(filepath, 'w') as bibliography_file:\n...     rispy.dump(entries, bibliography_file)\n\n```\n\n## Example RIS entry\n\n```text\n   1.\n   TY  - JOUR\n   ID  - 12345\n   T1  - Title of reference\n   A1  - Marx, Karl\n   A1  - Lindgren, Astrid\n   A2  - Glattauer, Daniel\n   Y1  - 2014//\n   N2  - BACKGROUND: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.  RESULTS: Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. CONCLUSIONS: Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium.\n   KW  - Pippi\n   KW  - Nordwind\n   KW  - Piraten\n   JF  - Lorem\n   JA  - lorem\n   VL  - 9\n   IS  - 3\n   SP  - e0815\n   CY  - United States\n   PB  - Fun Factory\n   PB  - Fun Factory USA\n   SN  - 1932-6208\n   M1  - 1008150341\n   L2  - http://example.com\n   ER  -\n```\n\n## TAG_KEY_MAPPING\n\nThe most fields contain string values, but some like first_authors (A1) are parsed into lists. The default mapping were created from specifications scattered around the web, but to our knowledge there is not one single source of RIS truth, so these may need to be modified for specific export systems:\n\n- [Wikipedia](https://en.wikipedia.org/wiki/RIS_(file_format))\n- [ResearcherId](https://web.archive.org/web/20170707033254/http://www.researcherid.com/resources/html/help_upload.htm)\n- [Refman](https://web.archive.org/web/20110930172154/http://www.refman.com/support/risformat_intro.asp)\n- [Refman (RIS format)](https://web.archive.org/web/20110930172154/http://www.refman.com/support/risformat_intro.asp)\n- [Zotero](https://github.com/zotero/translators/blob/master/RIS.js)\n\n### Complete list of ListType tags\n\n```python\n>>> from rispy import LIST_TYPE_TAGS\n>>> print(LIST_TYPE_TAGS)\n['A1', 'A2', 'A3', 'A4', 'AU', 'KW', 'N1', 'UR']\n\n```\n\n### Complete default mapping\n\n```python\n>>> from rispy import TAG_KEY_MAPPING\n>>> from pprint import pprint\n>>> pprint(TAG_KEY_MAPPING)\n{'A1': 'first_authors',\n 'A2': 'secondary_authors',\n 'A3': 'tertiary_authors',\n 'A4': 'subsidiary_authors',\n 'AB': 'abstract',\n 'AD': 'author_address',\n 'AN': 'accession_number',\n 'AU': 'authors',\n 'C1': 'custom1',\n 'C2': 'custom2',\n 'C3': 'custom3',\n 'C4': 'custom4',\n 'C5': 'custom5',\n 'C6': 'custom6',\n 'C7': 'custom7',\n 'C8': 'custom8',\n 'CA': 'caption',\n 'CN': 'call_number',\n 'CY': 'place_published',\n 'DA': 'date',\n 'DB': 'name_of_database',\n 'DO': 'doi',\n 'DP': 'database_provider',\n 'EP': 'end_page',\n 'ER': 'end_of_reference',\n 'ET': 'edition',\n 'ID': 'id',\n 'IS': 'number',\n 'J2': 'alternate_title1',\n 'JA': 'alternate_title2',\n 'JF': 'alternate_title3',\n 'JO': 'journal_name',\n 'KW': 'keywords',\n 'L1': 'file_attachments1',\n 'L2': 'file_attachments2',\n 'L4': 'figure',\n 'LA': 'language',\n 'LB': 'label',\n 'M1': 'note',\n 'M3': 'type_of_work',\n 'N1': 'notes',\n 'N2': 'notes_abstract',\n 'NV': 'number_of_volumes',\n 'OP': 'original_publication',\n 'PB': 'publisher',\n 'PY': 'year',\n 'RI': 'reviewed_item',\n 'RN': 'research_notes',\n 'RP': 'reprint_edition',\n 'SE': 'section',\n 'SN': 'issn',\n 'SP': 'start_page',\n 'ST': 'short_title',\n 'T1': 'primary_title',\n 'T2': 'secondary_title',\n 'T3': 'tertiary_title',\n 'TA': 'translated_author',\n 'TI': 'title',\n 'TT': 'translated_title',\n 'TY': 'type_of_reference',\n 'UK': 'unknown_tag',\n 'UR': 'urls',\n 'VL': 'volume',\n 'Y1': 'publication_year',\n 'Y2': 'access_date'}\n\n```\n\n### Override key mapping\n\nThe parser use a `TAG_KEY_MAPPING`, which one can override by calling `rispy.load()` with the `mapping` parameter.\n\n```python\n>>> from copy import deepcopy\n>>> import rispy\n>>> from pprint import pprint\n\n>>> filepath = 'tests/data/example_full.ris'\n>>> mapping = deepcopy(rispy.TAG_KEY_MAPPING)\n>>> mapping[\"SP\"] = \"pages_this_is_my_fun\"\n>>> with open(filepath, 'r') as bibliography_file:\n...     entries = rispy.load(bibliography_file, mapping=mapping)\n...     pprint(sorted(entries[0].keys()))\n['alternate_title2',\n 'alternate_title3',\n 'file_attachments2',\n 'first_authors',\n 'id',\n 'issn',\n 'keywords',\n 'note',\n 'notes_abstract',\n 'number',\n 'pages_this_is_my_fun',\n 'place_published',\n 'primary_title',\n 'publication_year',\n 'publisher',\n 'secondary_authors',\n 'type_of_reference',\n 'urls',\n 'volume']\n\n```\n\nList tags can be customized in the same way, by passing a list to the `list_tags` parameter.\n\n### Changing rispy behavior\n\nThere are a few flags that can be passed to `rispy.load()` and `rispy.dump()` that change how `rispy` deals with tags. For example, setting `skip_unknown_tags` to `True` will cause `rispy` do not read or write tags not in the tag map. More can be found in the docstrings for each class. If more customization is necessary, a custom implementation can be created (see next section).\n\n## Using custom implementations\n\nNot all RIS files follow the same formatting guidelines. There is an interface for creating custom implementations for reading and writing such files. An implementation contains the methods and parameters used to work with RIS files, and should be passed to `rispy.load()` or `rispy.dump()`.\n\n### Customizing implementations\n\nCreating a custom implentation involves creating a class that inherits a base class, and overriding the necessary variables and methods. One of the existing parsers can also be inherited. Inheriting an existing class is advantageous if only minor changes need to be made. The sections below document what is available to be overriden, along with a few examples.\n\n#### Parsing\n\nCustom parsers can inherit `RisParser` (the default parser) or `BaseParser`. Various parameters and methods can be overridden when creating a new parser. These are documented in the `BaseParser` docstring.\n\nExamples:\n\n```python\nclass WokParser(BaseParser):\n      \"\"\"Subclass of Base for reading Wok RIS files.\"\"\"\n\n      START_TAG = \"PT\"\n      IGNORE = [\"FN\", \"VR\", \"EF\"]\n      PATTERN = r\"^[A-Z][A-Z0-9] |^ER\\s?|^EF\\s?\"\n      DEFAULT_MAPPING = WOK_TAG_KEY_MAPPING\n      DEFAULT_LIST_TAGS = WOK_LIST_TYPE_TAGS\n\n      def get_content(self, line):\n         return line[2:].strip()\n\n      def is_header(self, line):\n         return True\n\n```\n\n### Writing\n\nWriting is very similar to parsing. A custom writer class can inherit `BaseWriter` or one if its subclasses, such as `RisWriter`.\n\nExamples:\n\n```python\nclass RisWriter(BaseWriter):\n      \"\"\"Subclass of BaseWriter for writing RIS files.\"\"\"\n\n      START_TAG = \"TY\"\n      PATTERN = \"{tag}  - {value}\"\n      DEFAULT_MAPPING = TAG_KEY_MAPPING\n      DEFAULT_LIST_TAGS = LIST_TYPE_TAGS\n\n      def set_header(self, count):\n         return \"{i}.\".format(i=count)\n\n```\n\n## Other functionality\n\nOther various utilities included in `rispy` are documented below.\n\n### Reference type conversion\n\nA method is available to convert common RIS reference types into more readable terms. It takes a list of references and returns a copy of that list with modified reference types. The map for this conversion is located in ``config.py``.\n\n```python\n>>> from rispy.utils import convert_reference_types\n>>> refs = [{\"type_of_reference\": \"JOUR\"}]\n>>> print(convert_reference_types(refs))\n[{'type_of_reference': 'Journal'}]\n\n```\n\n## Software for other RIS-like formats\n\nSome RIS-like formats contain rich citation data, for example lists and nested attributes, that `rispy` does not\nsupport. Software specializing on these formats include:\n\n* [nbib](https://pypi.org/project/nbib/) - parses the \"PubMed\" or \"MEDLINE\" format\n\n## Developer instructions\n\nCommon developer commands are in the provided `Makefile`; if you don't have `make` installed, you can view the make commands and run the commands from the command-line manually:\n\n```bash\n# setup environment\npython -m venv venv\nsource venv/bin/activate\npython -m pip install -U pip\npython -m pip install -e \".[dev]\"\n\n# check if code format changes are required\nmake lint\n\n# reformat code\nmake format\n\n# run tests\nmake test\n```\n\nGithub Actions are currently enabled to run `lint` and `test` when submitting a pull-request.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "A Python reader/writer of RIS reference files",
    "version": "0.9.0",
    "project_urls": {
        "Changes": "https://github.com/MrTango/rispy/blob/main/HISTORY.md",
        "Download": "https://pypi.org/project/rispy/",
        "Issue Tracker": "https://github.com/MrTango/rispy/issues",
        "Source": "https://github.com/mrtango/rispy"
    },
    "split_keywords": [
        "ris",
        "parser",
        "bibliograph"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "2dbd704634fac841823dbdfce2ccc2fb73e86ce17b13678c32b13f13cb5da0a1",
                "md5": "2874bb7143cad0f29a897512ce2c071c",
                "sha256": "e73ce54541c6319563a3d2a4fbd6f05674313a323221c423c79f466de7dd8d66"
            },
            "downloads": -1,
            "filename": "rispy-0.9.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "2874bb7143cad0f29a897512ce2c071c",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 15811,
            "upload_time": "2024-01-18T03:51:38",
            "upload_time_iso_8601": "2024-01-18T03:51:38.324088Z",
            "url": "https://files.pythonhosted.org/packages/2d/bd/704634fac841823dbdfce2ccc2fb73e86ce17b13678c32b13f13cb5da0a1/rispy-0.9.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "68bfc57b399f569c50266615f8cd56c046b6d28064d65d1b26714a951eb5f29f",
                "md5": "0d4bf306794b60dd18b4aecc36916d89",
                "sha256": "1b4d1aa2243919796d0b4502a44d32e0b1361cf68a02d23146dc7904bdbc9190"
            },
            "downloads": -1,
            "filename": "rispy-0.9.0.tar.gz",
            "has_sig": false,
            "md5_digest": "0d4bf306794b60dd18b4aecc36916d89",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 18577,
            "upload_time": "2024-01-18T03:51:39",
            "upload_time_iso_8601": "2024-01-18T03:51:39.717248Z",
            "url": "https://files.pythonhosted.org/packages/68/bf/c57b399f569c50266615f8cd56c046b6d28064d65d1b26714a951eb5f29f/rispy-0.9.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-01-18 03:51:39",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "MrTango",
    "github_project": "rispy",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "rispy"
}
        
Elapsed time: 0.16466s