usfm-grammar


Nameusfm-grammar JSON
Version 3.0.0b5 PyPI version JSON
download
home_page
SummaryPython parser for USFM files, based on tree-sitter-usfm3
upload_time2024-03-14 04:30:01
maintainer
docs_urlNone
author
requires_python>=3.10
licenseMIT License
keywords usfm parser grammar tree-sitter
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # USFM-Grammar

The python library that facilitates
* Parsing and validation of USFM files using `tree-sitter-usfm3`
* Conversion of USFM files to other formats (USX, dict, list etc)
* Extraction of specific contents from USFM files like scripture alone(clean verses), notes (footnotes, cross-refs) etc

Built on python 3.10

## Installation

`pip install usfm-grammar`

This requires a C compiler. On Windows, Microsoft Visual C++ 14.0 or above is required. 
It is recommended that you update `pip`, `setuptools` and `wheel`.


## Usage

### By importing library in Python code

```
from usfm_grammar import USFMParser, Filter

# input_usfm_str = open("sample.usfm","r", encoding='utf8').read()
input_usfm_str = '''
\\id GEN
\\c 1
\\p
\\v 1 test verse
'''

my_parser = USFMParser(input_usfm_str)

errors = my_parser.errors
print(errors)
```

##### To convert to USX
```
from lxml import etree

usx_elem = my_parser.to_usx() # default filter=ALL
print(etree.tostring(usx_elem, encoding="unicode", pretty_print=True))
```

##### To convert to Dict/USJ

```
output = my_parser.to_usj() # default all markers

# filters out specified markers from output
# output = my_parser.to_usj(exclude_markers=['s1','h', 'toc1','toc2','mt'])

# retains only specified contents from output
# output = my_parser.to_usj(include_markers=['id', 'c', 'v']) 

# use predefined marker groups instead of listing them one by one
# output = my_parser.to_usj(include_markers=Filter.BCV+Filter.TEXT)

# for a flattened JSON removing nesting brought in by paragraphs, lists, quotes, tables and character level markups
# output = my_parser.to_usj(exclude_markers=Filter.PARAGRAPHS+Filter.CHARACTERS)

# To NOT concatinate text extracted from different markers
# output = my_parser.to_usj(exclude_markers=Filter.PARAGRAPHS+Filter.CHARACTERS, combine_texts=False) 

print(output)
```
To understand more about how `exclude_markers`, `include_markers`, `combine_texts`  and `Filter` works refer the section on [filtering on USJ](#filtering-on-usj)

##### To save as json
```
import json
dict_output = my_parser.to_usj()
with open("file_path.json", "w", encoding='utf-8') as fp:
	json.dump(dict_output, fp)
```

##### To convert to List or table like format
```
list_output = my_parser.to_list() 
#list_output = my_parser.to_list([Filter.SCRIPTURE_TEXT])

table_output = "\n".join(["\t".join(row) for row in list_output])
print(table_output)

```

##### To round trip with USJ
```
from usfm_grammar import USFMParser, Filter

my_parser = USFMParser(input_usfm_str)
usj_obj = my_parser.to_usj()

my_parser2 = USFMParser(from_usj=usj_obj)
print(my_parser2.usfm)
```
:warning: There will be differences between first USFM and the generated one in 1. Spaces and lines 2. Default attributes will be given their names 3. Closing markers may be newly added

##### To remove unwanted markers from USFM
```
from usfm_grammar import USFMParser, Filter, USFMGenerator

my_parser = USFMParser(input_usfm_str)
usj_obj = my_parser.to_usj(include_markers=Filter.BCV+Filter.TEXT)

my_parser2 = USFMParser(from_usj=usj_obj)
print(my_parser2.usfm)
```
##### USJ to USX or Table
```
from usfm_grammar import USFMParser, Filter

my_parser = USFMParser(input_usfm_str)
usj_obj = my_parser.to_usj()

my_parser2 = USFMParser(from_usj=usj_obj)
print(my_parser2.to_usx())
# print(my_parser2.to_list())
```

##### USX to USFM, USJ or Table
```
from usfm_grammar import USFMParser, Filter
from lxml import etree

test_xml_file = "sample_usx.xml"
with open(test_xml_file, 'r', encoding='utf-8') as usx_file:
    usx_str = usx_file.read()
    usx_obj = etree.fromstring(usx_str)

    my_parser = USFMParser(from_usx=usx_obj)
    print(my_parser.usfm)
    # print(my_parser.to_usj())
    # print(my_parser.to_list())
```

### From CLI

```
usage: usfm-grammar [-h] [--in_format {usfm,usj,usx}]
                    [--out_format {usj,table,syntax-tree,usx,markdown,usfm}]
                    [--include_markers {book_headers,titles,...}]
                    [--exclude_markers {book_headers,titles,...}]
                    [--csv_col_sep CSV_COL_SEP] [--csv_row_sep CSV_ROW_SEP]
                    [--ignore_errors] [--combine_text]
                    infile

Uses the tree-sitter-usfm grammar to parse and convert USFM to Syntax-tree,
JSON, CSV, USX etc.

positional arguments:
  infile                input usfm or usj file

options:
  -h, --help            show this help message and exit
  --in_format {usfm,usj}
                        input file format
  --out_format {usj,table,syntax-tree,usx,markdown,usfm}
                        output format
  --include_markers {book_headers,titles,comments,paragraphs,characters,notes,study_bible,bcv,text,ide,usfm,h,toc,toca,imt,is,ip,ipi,im,imi,ipq,imq,ipr,iq,ib,ili,iot,io,iex,imte,ie,mt,mte,cl,cd,ms,mr,s,sr,r,d,sp,sd,sts,rem,lit,restore,p,m,po,pr,cls,pmo,pm,pmc,pmr,pi,mi,nb,pc,ph,q,qr,qc,qa,qm,qd,lh,li,lf,lim,litl,tr,tc,th,tcr,thr,table,b,add,bk,dc,ior,iqt,k,litl,nd,ord,pn,png,qac,qs,qt,rq,sig,sls,tl,wj,em,bd,bdit,it,no,sc,sup,rb,pro,w,wh,wa,wg,lik,liv,jmp,f,fe,ef,efe,x,ex,fr,ft,fk,fq,fqa,fl,fw,fp,fv,fdc,xo,xop,xt,xta,xk,xq,xot,xnt,xdc,esb,cat,id,c,v,text-in-excluded-parent}
                        the list of of contents to be included
  --exclude_markers {book_headers,titles,comments,paragraphs,characters,notes,study_bible,bcv,text,ide,usfm,h,toc,toca,imt,is,ip,ipi,im,imi,ipq,imq,ipr,iq,ib,ili,iot,io,iex,imte,ie,mt,mte,cl,cd,ms,mr,s,sr,r,d,sp,sd,sts,rem,lit,restore,p,m,po,pr,cls,pmo,pm,pmc,pmr,pi,mi,nb,pc,ph,q,qr,qc,qa,qm,qd,lh,li,lf,lim,litl,tr,tc,th,tcr,thr,table,b,add,bk,dc,ior,iqt,k,litl,nd,ord,pn,png,qac,qs,qt,rq,sig,sls,tl,wj,em,bd,bdit,it,no,sc,sup,rb,pro,w,wh,wa,wg,lik,liv,jmp,f,fe,ef,efe,x,ex,fr,ft,fk,fq,fqa,fl,fw,fp,fv,fdc,xo,xop,xt,xta,xk,xq,xot,xnt,xdc,esb,cat,id,c,v,text-in-excluded-parent}
                        the list of of contents to be included
  --csv_col_sep CSV_COL_SEP
                        column separator or delimiter. Only useful with
                        format=table.
  --csv_row_sep CSV_ROW_SEP
                        row separator or delimiter. Only useful with
                        format=table.
  --ignore_errors       to get some output from successfully parsed portions
  --combine_text        to be used along with exclude_markers or
                        include_markers, to concatinate the consecutive text
                        snippets, from different components, or not
```
Example
```
>>> python3 -m usfm_grammar sample.usfm --out_format usx

>>> usfm-grammar sample.usfm

>>> usfm-grammar sample.usfm --out_format usx

>>> usfm-grammar sample.usfm --include_markers bcv --include_markers text --include_markers s

>>> usfm-grammar sample-usj.json --out_format usfm
```

### Filtering on USJ

The filtering on USJ, the JSON output, is a feature incorporated to allow data extraction, markup cleaning etc. The arguments `exclude_markers` and `include_markers` in the methods `USFMParser.to_usj()` makes this possible. Also the  `USFMParser.to_list()`, can accept these inputs and perform similar operations. There is CLI versions also for these arguments to replicate the filtering feature there.

- *include_markers*

  Optional input parameter to `to_usj()` and `to_list` in python library and also in CLI when `format=json` or `format=table`. Defaults to `None`.When proivded, only those markers listed will be included in the output. `include_markers` is applied before applying `exclude_markers`. 

- *exclude_markers*

  Optional input parameter to `to_usj()` and `to_list` in python library and also in CLI when `format=json` or `format=table`. Defaults to `None`. When proivded, all markers except those listed will be included in the output.

- *combine_texts*

   Optional input parameter to `to_usj()` and `to_list` in python library and also in CLI when `format=json` or `format=table`. Defaults to `True`. After filtering out makers like paragraphs and characters, we are left with texts from within them, if 'text-in-excluded-parent' is also not excluded. These text snippets may come as separate components in the contents list. When this option is `True`, the consequetive text snippets will be concatinated together. The text concatination is done in a puctuation and space aware manner. If users need more control over the space handling or for any other reason, would prefer the texts snippets as different components in the output, this can be set to `False`.

- *usfm_grammar.Filter*

  This Class provides a set of enums that would be useful in providing in the `exclude_markers` and `include_markers` inputs rather than users listing out individual markers. The class has following options
  ```
    BOOK_HEADERS : identification and introduction markers
    TITLES : section headings and associated markers
    COMMENTS : comment markers like \rem
    PARAGRAPHS : paragraph markers like \p, poetry markers, list table markers
    CHARACTERS : all character level markups like \em, \w, \wj etc and their nested versions with +
    NOTES : foot note, cross-reference and their content markers
    STUDY_BIBLE : \esb and `cat
    BCV : \id, \c and \v
    TEXT : 'text-in-excluded-parent'
    ```
    To inspect which are the markers in each of these options, it could be just printed out, `print(Filter.TITLES)`. These could be used individually or concatinated to get the desired filtering of markers and data:
    ```
    output = my_parser.to_usj(include_markers=Filter.BCV)
    output = my_parser.to_usj(include_markers=Filter.BCV+Filter.TEXT)
    output = my_parser.to_usj(exclude_markers=Filter.PARAGRAPHS+Filter.CHARACTERS)
    ``` 
- Inner contents of excluded markers

  For markers like `\p` `\q` etc, by excluding them, we only remove them from the heirachy and retain the inner contents like `\v`, text etc that would be coming inside it. But for certain other markers like `\f`, `\x`, `\esb`  etc, if they are excluded their inner contents are also excluded. Following is the set of all markers, who inner contents are discarded if they are mentioned in `exclude_markers` or not included in `include_markers`.
  ```
  BOOK_HEADERS, TITLES, COMMENTS, NOTES, STUDY_BIBLE
  ```
  :warning: Generally, it is recommended to NOT use both `exclude_markers` and `include_markers` together as it could lead to unexpected behavours and data loss. For instance if `include_makers` has `\fk` and `exclude_markers` has `\f`, the output will not contain `\fk` as all inner contents of `\f` will be discarded.

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "usfm-grammar",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": "Kavitha Raju <kavitha.raju@bridgeconn.com>, Joel Mathew <joel@bridgeconn.com>",
    "keywords": "usfm,parser,grammar,tree-sitter",
    "author": "",
    "author_email": "BCS Team <joel@bridgeconn.com>",
    "download_url": "",
    "platform": null,
    "description": "# USFM-Grammar\n\nThe python library that facilitates\n* Parsing and validation of USFM files using `tree-sitter-usfm3`\n* Conversion of USFM files to other formats (USX, dict, list etc)\n* Extraction of specific contents from USFM files like scripture alone(clean verses), notes (footnotes, cross-refs) etc\n\nBuilt on python 3.10\n\n## Installation\n\n`pip install usfm-grammar`\n\nThis requires a C compiler. On Windows, Microsoft Visual C++ 14.0 or above is required. \nIt is recommended that you update `pip`, `setuptools` and `wheel`.\n\n\n## Usage\n\n### By importing library in Python code\n\n```\nfrom usfm_grammar import USFMParser, Filter\n\n# input_usfm_str = open(\"sample.usfm\",\"r\", encoding='utf8').read()\ninput_usfm_str = '''\n\\\\id GEN\n\\\\c 1\n\\\\p\n\\\\v 1 test verse\n'''\n\nmy_parser = USFMParser(input_usfm_str)\n\nerrors = my_parser.errors\nprint(errors)\n```\n\n##### To convert to USX\n```\nfrom lxml import etree\n\nusx_elem = my_parser.to_usx() # default filter=ALL\nprint(etree.tostring(usx_elem, encoding=\"unicode\", pretty_print=True))\n```\n\n##### To convert to Dict/USJ\n\n```\noutput = my_parser.to_usj() # default all markers\n\n# filters out specified markers from output\n# output = my_parser.to_usj(exclude_markers=['s1','h', 'toc1','toc2','mt'])\n\n# retains only specified contents from output\n# output = my_parser.to_usj(include_markers=['id', 'c', 'v']) \n\n# use predefined marker groups instead of listing them one by one\n# output = my_parser.to_usj(include_markers=Filter.BCV+Filter.TEXT)\n\n# for a flattened JSON removing nesting brought in by paragraphs, lists, quotes, tables and character level markups\n# output = my_parser.to_usj(exclude_markers=Filter.PARAGRAPHS+Filter.CHARACTERS)\n\n# To NOT concatinate text extracted from different markers\n# output = my_parser.to_usj(exclude_markers=Filter.PARAGRAPHS+Filter.CHARACTERS, combine_texts=False) \n\nprint(output)\n```\nTo understand more about how `exclude_markers`, `include_markers`, `combine_texts`  and `Filter` works refer the section on [filtering on USJ](#filtering-on-usj)\n\n##### To save as json\n```\nimport json\ndict_output = my_parser.to_usj()\nwith open(\"file_path.json\", \"w\", encoding='utf-8') as fp:\n\tjson.dump(dict_output, fp)\n```\n\n##### To convert to List or table like format\n```\nlist_output = my_parser.to_list() \n#list_output = my_parser.to_list([Filter.SCRIPTURE_TEXT])\n\ntable_output = \"\\n\".join([\"\\t\".join(row) for row in list_output])\nprint(table_output)\n\n```\n\n##### To round trip with USJ\n```\nfrom usfm_grammar import USFMParser, Filter\n\nmy_parser = USFMParser(input_usfm_str)\nusj_obj = my_parser.to_usj()\n\nmy_parser2 = USFMParser(from_usj=usj_obj)\nprint(my_parser2.usfm)\n```\n:warning: There will be differences between first USFM and the generated one in 1. Spaces and lines 2. Default attributes will be given their names 3. Closing markers may be newly added\n\n##### To remove unwanted markers from USFM\n```\nfrom usfm_grammar import USFMParser, Filter, USFMGenerator\n\nmy_parser = USFMParser(input_usfm_str)\nusj_obj = my_parser.to_usj(include_markers=Filter.BCV+Filter.TEXT)\n\nmy_parser2 = USFMParser(from_usj=usj_obj)\nprint(my_parser2.usfm)\n```\n##### USJ to USX or Table\n```\nfrom usfm_grammar import USFMParser, Filter\n\nmy_parser = USFMParser(input_usfm_str)\nusj_obj = my_parser.to_usj()\n\nmy_parser2 = USFMParser(from_usj=usj_obj)\nprint(my_parser2.to_usx())\n# print(my_parser2.to_list())\n```\n\n##### USX to USFM, USJ or Table\n```\nfrom usfm_grammar import USFMParser, Filter\nfrom lxml import etree\n\ntest_xml_file = \"sample_usx.xml\"\nwith open(test_xml_file, 'r', encoding='utf-8') as usx_file:\n    usx_str = usx_file.read()\n    usx_obj = etree.fromstring(usx_str)\n\n    my_parser = USFMParser(from_usx=usx_obj)\n    print(my_parser.usfm)\n    # print(my_parser.to_usj())\n    # print(my_parser.to_list())\n```\n\n### From CLI\n\n```\nusage: usfm-grammar [-h] [--in_format {usfm,usj,usx}]\n                    [--out_format {usj,table,syntax-tree,usx,markdown,usfm}]\n                    [--include_markers {book_headers,titles,...}]\n                    [--exclude_markers {book_headers,titles,...}]\n                    [--csv_col_sep CSV_COL_SEP] [--csv_row_sep CSV_ROW_SEP]\n                    [--ignore_errors] [--combine_text]\n                    infile\n\nUses the tree-sitter-usfm grammar to parse and convert USFM to Syntax-tree,\nJSON, CSV, USX etc.\n\npositional arguments:\n  infile                input usfm or usj file\n\noptions:\n  -h, --help            show this help message and exit\n  --in_format {usfm,usj}\n                        input file format\n  --out_format {usj,table,syntax-tree,usx,markdown,usfm}\n                        output format\n  --include_markers {book_headers,titles,comments,paragraphs,characters,notes,study_bible,bcv,text,ide,usfm,h,toc,toca,imt,is,ip,ipi,im,imi,ipq,imq,ipr,iq,ib,ili,iot,io,iex,imte,ie,mt,mte,cl,cd,ms,mr,s,sr,r,d,sp,sd,sts,rem,lit,restore,p,m,po,pr,cls,pmo,pm,pmc,pmr,pi,mi,nb,pc,ph,q,qr,qc,qa,qm,qd,lh,li,lf,lim,litl,tr,tc,th,tcr,thr,table,b,add,bk,dc,ior,iqt,k,litl,nd,ord,pn,png,qac,qs,qt,rq,sig,sls,tl,wj,em,bd,bdit,it,no,sc,sup,rb,pro,w,wh,wa,wg,lik,liv,jmp,f,fe,ef,efe,x,ex,fr,ft,fk,fq,fqa,fl,fw,fp,fv,fdc,xo,xop,xt,xta,xk,xq,xot,xnt,xdc,esb,cat,id,c,v,text-in-excluded-parent}\n                        the list of of contents to be included\n  --exclude_markers {book_headers,titles,comments,paragraphs,characters,notes,study_bible,bcv,text,ide,usfm,h,toc,toca,imt,is,ip,ipi,im,imi,ipq,imq,ipr,iq,ib,ili,iot,io,iex,imte,ie,mt,mte,cl,cd,ms,mr,s,sr,r,d,sp,sd,sts,rem,lit,restore,p,m,po,pr,cls,pmo,pm,pmc,pmr,pi,mi,nb,pc,ph,q,qr,qc,qa,qm,qd,lh,li,lf,lim,litl,tr,tc,th,tcr,thr,table,b,add,bk,dc,ior,iqt,k,litl,nd,ord,pn,png,qac,qs,qt,rq,sig,sls,tl,wj,em,bd,bdit,it,no,sc,sup,rb,pro,w,wh,wa,wg,lik,liv,jmp,f,fe,ef,efe,x,ex,fr,ft,fk,fq,fqa,fl,fw,fp,fv,fdc,xo,xop,xt,xta,xk,xq,xot,xnt,xdc,esb,cat,id,c,v,text-in-excluded-parent}\n                        the list of of contents to be included\n  --csv_col_sep CSV_COL_SEP\n                        column separator or delimiter. Only useful with\n                        format=table.\n  --csv_row_sep CSV_ROW_SEP\n                        row separator or delimiter. Only useful with\n                        format=table.\n  --ignore_errors       to get some output from successfully parsed portions\n  --combine_text        to be used along with exclude_markers or\n                        include_markers, to concatinate the consecutive text\n                        snippets, from different components, or not\n```\nExample\n```\n>>> python3 -m usfm_grammar sample.usfm --out_format usx\n\n>>> usfm-grammar sample.usfm\n\n>>> usfm-grammar sample.usfm --out_format usx\n\n>>> usfm-grammar sample.usfm --include_markers bcv --include_markers text --include_markers s\n\n>>> usfm-grammar sample-usj.json --out_format usfm\n```\n\n### Filtering on USJ\n\nThe filtering on USJ, the JSON output, is a feature incorporated to allow data extraction, markup cleaning etc. The arguments `exclude_markers` and `include_markers` in the methods `USFMParser.to_usj()` makes this possible. Also the  `USFMParser.to_list()`, can accept these inputs and perform similar operations. There is CLI versions also for these arguments to replicate the filtering feature there.\n\n- *include_markers*\n\n  Optional input parameter to `to_usj()` and `to_list` in python library and also in CLI when `format=json` or `format=table`. Defaults to `None`.When proivded, only those markers listed will be included in the output. `include_markers` is applied before applying `exclude_markers`. \n\n- *exclude_markers*\n\n  Optional input parameter to `to_usj()` and `to_list` in python library and also in CLI when `format=json` or `format=table`. Defaults to `None`. When proivded, all markers except those listed will be included in the output.\n\n- *combine_texts*\n\n   Optional input parameter to `to_usj()` and `to_list` in python library and also in CLI when `format=json` or `format=table`. Defaults to `True`. After filtering out makers like paragraphs and characters, we are left with texts from within them, if 'text-in-excluded-parent' is also not excluded. These text snippets may come as separate components in the contents list. When this option is `True`, the consequetive text snippets will be concatinated together. The text concatination is done in a puctuation and space aware manner. If users need more control over the space handling or for any other reason, would prefer the texts snippets as different components in the output, this can be set to `False`.\n\n- *usfm_grammar.Filter*\n\n  This Class provides a set of enums that would be useful in providing in the `exclude_markers` and `include_markers` inputs rather than users listing out individual markers. The class has following options\n  ```\n    BOOK_HEADERS : identification and introduction markers\n    TITLES : section headings and associated markers\n    COMMENTS : comment markers like \\rem\n    PARAGRAPHS : paragraph markers like \\p, poetry markers, list table markers\n    CHARACTERS : all character level markups like \\em, \\w, \\wj etc and their nested versions with +\n    NOTES : foot note, cross-reference and their content markers\n    STUDY_BIBLE : \\esb and `cat\n    BCV : \\id, \\c and \\v\n    TEXT : 'text-in-excluded-parent'\n    ```\n    To inspect which are the markers in each of these options, it could be just printed out, `print(Filter.TITLES)`. These could be used individually or concatinated to get the desired filtering of markers and data:\n    ```\n    output = my_parser.to_usj(include_markers=Filter.BCV)\n    output = my_parser.to_usj(include_markers=Filter.BCV+Filter.TEXT)\n    output = my_parser.to_usj(exclude_markers=Filter.PARAGRAPHS+Filter.CHARACTERS)\n    ``` \n- Inner contents of excluded markers\n\n  For markers like `\\p` `\\q` etc, by excluding them, we only remove them from the heirachy and retain the inner contents like `\\v`, text etc that would be coming inside it. But for certain other markers like `\\f`, `\\x`, `\\esb`  etc, if they are excluded their inner contents are also excluded. Following is the set of all markers, who inner contents are discarded if they are mentioned in `exclude_markers` or not included in `include_markers`.\n  ```\n  BOOK_HEADERS, TITLES, COMMENTS, NOTES, STUDY_BIBLE\n  ```\n  :warning: Generally, it is recommended to NOT use both `exclude_markers` and `include_markers` together as it could lead to unexpected behavours and data loss. For instance if `include_makers` has `\\fk` and `exclude_markers` has `\\f`, the output will not contain `\\fk` as all inner contents of `\\f` will be discarded.\n",
    "bugtrack_url": null,
    "license": "MIT License",
    "summary": "Python parser for USFM files, based on tree-sitter-usfm3",
    "version": "3.0.0b5",
    "project_urls": {
        "Homepage": "https://github.com/Bridgeconn/usfm-grammar/py-usfm-grammar#readme"
    },
    "split_keywords": [
        "usfm",
        "parser",
        "grammar",
        "tree-sitter"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "137b24f4547c433ea18b1b6613e607bb85e0fdba7a5c36c8a0643db93f7f0538",
                "md5": "cb3aa5ec43fec1345a151987f49c0a10",
                "sha256": "cc88f3de048747872ce0e9d229640ed5ab9fcb374ab9e7e8abeec4fb2fd2403c"
            },
            "downloads": -1,
            "filename": "usfm_grammar-3.0.0b5-cp310-cp310-macosx_10_9_x86_64.whl",
            "has_sig": false,
            "md5_digest": "cb3aa5ec43fec1345a151987f49c0a10",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.10",
            "size": 253847,
            "upload_time": "2024-03-14T04:30:01",
            "upload_time_iso_8601": "2024-03-14T04:30:01.911345Z",
            "url": "https://files.pythonhosted.org/packages/13/7b/24f4547c433ea18b1b6613e607bb85e0fdba7a5c36c8a0643db93f7f0538/usfm_grammar-3.0.0b5-cp310-cp310-macosx_10_9_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "9153bc66dea0e985e12dab3cfdb4927b8b4870d521a20fd4e8c45553f7b3772f",
                "md5": "6e25917b5ab8db8064f96ea9b00c7a6d",
                "sha256": "b584dcc7810bd65cd763f9a649fab30917fe63c0c7481f43563d3f5a509c487f"
            },
            "downloads": -1,
            "filename": "usfm_grammar-3.0.0b5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",
            "has_sig": false,
            "md5_digest": "6e25917b5ab8db8064f96ea9b00c7a6d",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.10",
            "size": 269190,
            "upload_time": "2024-03-14T04:30:04",
            "upload_time_iso_8601": "2024-03-14T04:30:04.371127Z",
            "url": "https://files.pythonhosted.org/packages/91/53/bc66dea0e985e12dab3cfdb4927b8b4870d521a20fd4e8c45553f7b3772f/usfm_grammar-3.0.0b5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "8ef7dee51bf9aef86b9f0f0c9d2bc3e628a324e541666f0d1ba23733086e888c",
                "md5": "797d1f635d83ee393467f71cd7719190",
                "sha256": "6b2a0902d7cc48a6b375c5997a41a5894ee704c17ffcd921e93a3a5b74ee742f"
            },
            "downloads": -1,
            "filename": "usfm_grammar-3.0.0b5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "797d1f635d83ee393467f71cd7719190",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.10",
            "size": 260139,
            "upload_time": "2024-03-14T04:30:05",
            "upload_time_iso_8601": "2024-03-14T04:30:05.895726Z",
            "url": "https://files.pythonhosted.org/packages/8e/f7/dee51bf9aef86b9f0f0c9d2bc3e628a324e541666f0d1ba23733086e888c/usfm_grammar-3.0.0b5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "7f945f07a281b5bdec90089ab2d413fbabf77a0962ddf68018c957b454bcf6f9",
                "md5": "6502b64aea02372400dfda58dd09adae",
                "sha256": "99414d3f0922ab02502ed62b39443583970c932b284209ed8030e1f0809d7002"
            },
            "downloads": -1,
            "filename": "usfm_grammar-3.0.0b5-cp310-cp310-musllinux_1_1_i686.whl",
            "has_sig": false,
            "md5_digest": "6502b64aea02372400dfda58dd09adae",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.10",
            "size": 269456,
            "upload_time": "2024-03-14T04:30:07",
            "upload_time_iso_8601": "2024-03-14T04:30:07.957303Z",
            "url": "https://files.pythonhosted.org/packages/7f/94/5f07a281b5bdec90089ab2d413fbabf77a0962ddf68018c957b454bcf6f9/usfm_grammar-3.0.0b5-cp310-cp310-musllinux_1_1_i686.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "aec05917bca4c33bbeec60bfd11a82d913810c58c3bffbdb45123a80688fc933",
                "md5": "0770586e015cdb7cb907146d67dd9947",
                "sha256": "389ea63a2b4cc7280cf314d76db9571087e8c3900b51710e480be7dfea8fa976"
            },
            "downloads": -1,
            "filename": "usfm_grammar-3.0.0b5-cp310-cp310-musllinux_1_1_x86_64.whl",
            "has_sig": false,
            "md5_digest": "0770586e015cdb7cb907146d67dd9947",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.10",
            "size": 260416,
            "upload_time": "2024-03-14T04:30:10",
            "upload_time_iso_8601": "2024-03-14T04:30:10.082342Z",
            "url": "https://files.pythonhosted.org/packages/ae/c0/5917bca4c33bbeec60bfd11a82d913810c58c3bffbdb45123a80688fc933/usfm_grammar-3.0.0b5-cp310-cp310-musllinux_1_1_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "cfd48d0f5183f4fbdd22f412e0f103863fa76ed2b4f64be5168b0e3e4de921ae",
                "md5": "1066d54239fd68e2dbb3dd13e06c2176",
                "sha256": "9bacf828aa7adca6fcd8c0f8e5ac0782efbab013d3a57d2d5c15bd42d731253a"
            },
            "downloads": -1,
            "filename": "usfm_grammar-3.0.0b5-cp310-cp310-win32.whl",
            "has_sig": false,
            "md5_digest": "1066d54239fd68e2dbb3dd13e06c2176",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.10",
            "size": 263647,
            "upload_time": "2024-03-14T04:30:12",
            "upload_time_iso_8601": "2024-03-14T04:30:12.191922Z",
            "url": "https://files.pythonhosted.org/packages/cf/d4/8d0f5183f4fbdd22f412e0f103863fa76ed2b4f64be5168b0e3e4de921ae/usfm_grammar-3.0.0b5-cp310-cp310-win32.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "04bc297c95e59b98309e476962b06f1300f4028a0a8eb22079186460dceb7e0e",
                "md5": "8c73ef36e9608bebd289a50b2e3f5f18",
                "sha256": "8b28a7530a026d0fba28ca48c2caf6fc0d8eb45231fe4515c92d3d1e506baf2f"
            },
            "downloads": -1,
            "filename": "usfm_grammar-3.0.0b5-cp310-cp310-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "8c73ef36e9608bebd289a50b2e3f5f18",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.10",
            "size": 260763,
            "upload_time": "2024-03-14T04:30:13",
            "upload_time_iso_8601": "2024-03-14T04:30:13.879884Z",
            "url": "https://files.pythonhosted.org/packages/04/bc/297c95e59b98309e476962b06f1300f4028a0a8eb22079186460dceb7e0e/usfm_grammar-3.0.0b5-cp310-cp310-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3b38194ef855bac8e2c84333e52d45ea03c3ebb4f708f977df6cf9118bfbbe10",
                "md5": "eb6480377bd5c6e88cb59202df1f2dac",
                "sha256": "d34d0b76da000218c32c7992e4fa6c4034ff7f4fee0a350c635e693b31115d87"
            },
            "downloads": -1,
            "filename": "usfm_grammar-3.0.0b5-cp311-cp311-macosx_10_9_x86_64.whl",
            "has_sig": false,
            "md5_digest": "eb6480377bd5c6e88cb59202df1f2dac",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.10",
            "size": 253846,
            "upload_time": "2024-03-14T04:30:16",
            "upload_time_iso_8601": "2024-03-14T04:30:16.046627Z",
            "url": "https://files.pythonhosted.org/packages/3b/38/194ef855bac8e2c84333e52d45ea03c3ebb4f708f977df6cf9118bfbbe10/usfm_grammar-3.0.0b5-cp311-cp311-macosx_10_9_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "f6f20aa72837c13d5a08649f7fc5fb96bf668201f3fc87c8758f2e107efe9888",
                "md5": "0aea01391ecf67cf98035c84ef7673b5",
                "sha256": "a488c574667ab37ca6aec72daa033261600daf40e32f6e360277f75ea0aeffd7"
            },
            "downloads": -1,
            "filename": "usfm_grammar-3.0.0b5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",
            "has_sig": false,
            "md5_digest": "0aea01391ecf67cf98035c84ef7673b5",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.10",
            "size": 269190,
            "upload_time": "2024-03-14T04:30:18",
            "upload_time_iso_8601": "2024-03-14T04:30:18.195007Z",
            "url": "https://files.pythonhosted.org/packages/f6/f2/0aa72837c13d5a08649f7fc5fb96bf668201f3fc87c8758f2e107efe9888/usfm_grammar-3.0.0b5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "214c5495c8668d1e9bdbc17c7dccb4b0a3adcb9ce9f06f944b668e7a3c5f919a",
                "md5": "837ce851d437b2b26e17aa606348edf8",
                "sha256": "0a7b163ae9af5c26266e44bd1f743ba6d0eb42c920245ae6a9dd7f85efed953f"
            },
            "downloads": -1,
            "filename": "usfm_grammar-3.0.0b5-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "837ce851d437b2b26e17aa606348edf8",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.10",
            "size": 260139,
            "upload_time": "2024-03-14T04:30:20",
            "upload_time_iso_8601": "2024-03-14T04:30:20.231159Z",
            "url": "https://files.pythonhosted.org/packages/21/4c/5495c8668d1e9bdbc17c7dccb4b0a3adcb9ce9f06f944b668e7a3c5f919a/usfm_grammar-3.0.0b5-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a02825b6979e17b9ecb632bdb27cdd3484350cf73faf458f8f24222969503208",
                "md5": "0d8211d1a1229032fc14ac0c3ef1bd9e",
                "sha256": "0112ef59e066b16a8e5bd62073feb21a34425a387360196ad13a625827e327cc"
            },
            "downloads": -1,
            "filename": "usfm_grammar-3.0.0b5-cp311-cp311-musllinux_1_1_i686.whl",
            "has_sig": false,
            "md5_digest": "0d8211d1a1229032fc14ac0c3ef1bd9e",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.10",
            "size": 269455,
            "upload_time": "2024-03-14T04:30:21",
            "upload_time_iso_8601": "2024-03-14T04:30:21.552034Z",
            "url": "https://files.pythonhosted.org/packages/a0/28/25b6979e17b9ecb632bdb27cdd3484350cf73faf458f8f24222969503208/usfm_grammar-3.0.0b5-cp311-cp311-musllinux_1_1_i686.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "d39683ede5f7a92f1f1c97b02d30bdade2fab175ab572ffd275f24d05e501ef5",
                "md5": "ad238f5b4578372fa4ee124a713458d5",
                "sha256": "99b40511f1bc11ee379e29494adc0834d41e4d739f061598b3c594eb3a8eccf6"
            },
            "downloads": -1,
            "filename": "usfm_grammar-3.0.0b5-cp311-cp311-musllinux_1_1_x86_64.whl",
            "has_sig": false,
            "md5_digest": "ad238f5b4578372fa4ee124a713458d5",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.10",
            "size": 260415,
            "upload_time": "2024-03-14T04:30:23",
            "upload_time_iso_8601": "2024-03-14T04:30:23.662257Z",
            "url": "https://files.pythonhosted.org/packages/d3/96/83ede5f7a92f1f1c97b02d30bdade2fab175ab572ffd275f24d05e501ef5/usfm_grammar-3.0.0b5-cp311-cp311-musllinux_1_1_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "fa54a958a11675d22015cd1f1d4f8fbbc029cf7ae98503b5eea8985975b711c9",
                "md5": "69bd6c57fc89bc214b0f525622011417",
                "sha256": "228c4839c44ad6aab84f25f9d17bd4875dfc4f9604e24c1ee613b757858e610e"
            },
            "downloads": -1,
            "filename": "usfm_grammar-3.0.0b5-cp311-cp311-win32.whl",
            "has_sig": false,
            "md5_digest": "69bd6c57fc89bc214b0f525622011417",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.10",
            "size": 263648,
            "upload_time": "2024-03-14T04:30:25",
            "upload_time_iso_8601": "2024-03-14T04:30:25.812347Z",
            "url": "https://files.pythonhosted.org/packages/fa/54/a958a11675d22015cd1f1d4f8fbbc029cf7ae98503b5eea8985975b711c9/usfm_grammar-3.0.0b5-cp311-cp311-win32.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "5cbace62978cf3f0b72d2191d9118d5de59814dcfe202cddc83edee913f0fe92",
                "md5": "cd76042235ff8d27769de41c8bee288a",
                "sha256": "1c445a878291a5c31f5a504b19f7253639645750d2d2010be0fc075c0c0e4c10"
            },
            "downloads": -1,
            "filename": "usfm_grammar-3.0.0b5-cp311-cp311-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "cd76042235ff8d27769de41c8bee288a",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.10",
            "size": 260763,
            "upload_time": "2024-03-14T04:30:27",
            "upload_time_iso_8601": "2024-03-14T04:30:27.808954Z",
            "url": "https://files.pythonhosted.org/packages/5c/ba/ce62978cf3f0b72d2191d9118d5de59814dcfe202cddc83edee913f0fe92/usfm_grammar-3.0.0b5-cp311-cp311-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-03-14 04:30:01",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Bridgeconn",
    "github_project": "usfm-grammar",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "usfm-grammar"
}
        
Elapsed time: 0.21587s