reliq


Namereliq JSON
Version 0.0.44 PyPI version JSON
download
home_pageNone
SummaryPython ctypes bindings for reliq
upload_time2025-08-16 11:23:43
maintainerNone
docs_urlNone
authorNone
requires_python>=3.7
licenseGPLv3
keywords ctypes html parser text-processing
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # reliq-python

A python bindings for [reliq](https://github.com/TUVIMEN/reliq) library.

## Installation

    pip install reliq

## Benchmark

Benchmarks were inspired by [selectolax](https://github.com/rushter/selectolax/blob/master/examples/benchmark.py) and performed on 355MB, 896 files sample of most popular websites. You can find the benchmark script [here](benchmark/benchmark.py).

### Parsing

| Package             | Time     |
| --------------      | ----     |
| bs4                 | 121.615s |
| html5-parser        | 22.424s  |
| lxml                | 4.955s   |
| selectolax (modest) | 2.901s   |
| selectolax (lexbor) | 1.200s   |
| reliq               | 0.310s   |

### Collective memory usage of parsed trees

| Package             | Memory |
| --------------      | ----   |
| bs4                 | 2234MB |
| selectolax (lexbor) | 1666MB |
| selectolax (modest) | 1602MB |
| lxml                | 1274MB |
| html5-parser        | 1262MB |
| reliq               | 58MB   |

### Parsing and processing

| Package             | Time     |
| --------------      | ----     |
| bs4                 | 230.661s |
| html5-parser        | 31.138s  |
| lxml                | 14.010s  |
| selectolax (modest) | 4.291s   |
| reliq               | 2.974s   |
| selectolax (lexbor) | 2.628s   |

## Usage

### Code

```python
from reliq import reliq

html = ""
with open('index.html','r') as f:
    html = f.read()

rq = reliq(html) #parse html
expr = reliq.expr(r"""
    div .user; {
        a href; {
            .name @ | "%i",
            .link @ | "%(href)v"
        },
        .score.u span .score,
        .info dl; {
            .key dt | "%i",
            .value dd | "%i"
        } |,
        .achievements.a li class=b>"achievement-" | "%i\n"
    }
""") #expressions can be compiled

users = []
links = []

for i in rq.filter(r'table; { tr, text@ iw>lisp }')[:-2]:
    # ignore comments and text nodes
    if i.type is not reliq.Type.tag:
        continue

    first_child = i[0]

    if first_child.desc_count < 3 and first_child.name == "div" and first_child.starttag == '<div>':
        continue

    link = first_child[2].attrib['href']
    if re.match('^https://$',link):
        links.append(link)
        continue

    #make sure that object is an ancestor of <main> tag
    for j in i.ancestors():
        if j.name == "main":
          break
    else:
      continue

    #search() returns str, in this case expression is already compiled
    #  but can be also passed as a str() or bytes(). If Path() is passed
    #  file will be read
    user = json.loads(i.search(expr))
    users.append(user)

try: #handle errors
    rq.search('p / /','<p></p>')
except reliq.ScriptError: # all errors inherit from reliq.Error
    print("error")

#get text from all text nodes that are descendants of object
print(rq[2].text_recursive)
#get text from all text nodes that are children of object
print(rq[2].text)

#decode html entities
reliq.decode('loop &amp; &lt &tdot; &#212')

#execute and convert to dictionary
rq.json(r"""
    .files * #files; ( li )( span .head ); {
        .type i class child@ | "%(class)v" / sed "s/^flaticon-//",
        .name @ | "%Dt" / trim sed "s/ ([^)]* [a-zA-Z][Bb])$//",
        .size @ | "%t" / sed 's/.* \(([^)]* [a-zA-Z][Bb])\)$/\1/; s/,//g; /^[0-9].* [a-zA-Z][bB]$/!d' "E"
    } |
""") #dict format is enforced and any incompatible expressions will raise reliq.ScriptError
```

### Import

Most is contained inside `reliq` class

```python
from reliq import reliq, RQ
```

### Initialization

`reliq` object takes an argument representing html, this can be `str()`, `bytes()`, `Path()` (file is read as `bytes`), `reliq()` or `None`.

```python
rq = reliq('<p>Example</p>') #passed directly

rq2 = reliq(Path('index.html')) #passed from file

rq3 = reliq(None) # empty object
rq4 = reliq() # empty object
```

If optional argument `ref` is a string it'll set url to the first base tag in html structure, and in case there isn't any it'll be set to `ref`.

```python
rq = reliq('<p>Example</p>')
rq.ref # None

rq2 = reliq(b'<p>Second example</p>',ref="http://en.wikipedia.org")
rq2.ref # http://en.wikipedia.org

rq3 = reliq(b'<base href="https://wikipedia.org"><p>Second example</p>',ref="http://en.wikipedia.org")
rq3.ref # https://wikipedia.org

rq4 = reliq(b'<base href="https://wikipedia.org"><p>Second example</p>',ref="")
rq4.ref # https://wikipedia.org
```

### Types

`reliq` can have 5 types that change the behaviour of methods.

Calling `type` property on object e.g. `rq.type` returns instance of `reliq.Type(Flag)`.

#### empty

Gets returned from either `reliq(None)` or `reliq.filter()` that matches nothing, makes all methods return default values.

#### unknown

Similar to `empty` but should never happen

#### struct

Returned by successful initialization e.g.

```python
reliq('<p>Example</p>')
```

#### list

Returned by `reliq.filter()` that succeeds

#### single

Returned by axis methods or by accessing the object like a list.

The type itself is a grouping of more specific types:

 - tag
 - comment
 - textempty (text made only of whitespaces)
 - texterr (text where an html error occurred)
 - text
 - textall (grouping of text types)

### get_data(raw=False) -> str|bytes

Returns the same html from which the object was compiled.

If first argument is `True` or `raw=True` returns `bytes`.

```python
data = Path('index.html').read_bytes

rq = reliq(data)
x = rq[0][2][1][8]

# if both objects are bytes() then their ids should be the same
x.get_data(True) is data
```

### special methods

#### \_\_bytes\_\_ and \_\_str\_\_

Full string representation of current object

```python
rq = reliq("""
  <h1><b>H</b>1</h1>
  <h2>N2</h2>
  <h2>N3</h2>
""")

str(rq) # struct
# '\n  <h1><b>H</b>1</h1>\n  <h2>N2</h2>\n  <h2>N3</h2>\n'

str(rq.filter('h2')) # list
# '<h2>N2</h2><h2>N3</h2>'

str(rq[0]) # single
# '<h1><b>H</b>1</h1>'

str(reliq()) # empty
# ''
```

#### \_\_getitem\_\_

For `single` indexes results from `children()` axis, otherwise from `self()` axis

```python
rq = reliq('<div><p>1</p> Text <b>H</b></div>')

first = rq[0] # struct
# <div>

first[1] # single
# <b>

r = first.filter('( text@ * )( * ) child@')
r[1] # list
# " Text " obj

r[2] == first[1]
```

#### \_\_len\_\_

Amount of objects returned from `__getitem__`

### ref and ref_raw

`ref -> str`

`ref_raw -> bytes`

They return saved reference url at initialization.

```python
rq = reliq('',ref="http://en.wikipedia.org")
rq.ref # "http://en.wikipedia.org"
rq.ref_raw # b"http://en.wikipedia.org"
```

### properties of single

Calling these properties for types other than `single` returns their default values.

`lvl -> int` level in html structure

`rlvl -> int` level in html structure, relative to parent

`position -> int` position in html structure

`rposition -> int` position in html structure, relative to parent

Calling some properties makes sense only for certain types.

#### tag

`tag_count -> int` count of tags

`text_count -> int` count of text

`comment_count -> int` count of comments

`desc_count -> int` count of descendants

`attribl -> int` number of attributes

----

`attrib -> dict` dictionary of attributes

----

These return `None` only if called from `empty` type. They also have `_raw` counterparts that return `bytes` e.g. `text_recursive_raw -> Optional[bytes]`, `name_raw -> Optional[bytes]`

`insides -> Optional[str]` string containing contents inside tag or comment

`name -> Optional[str]` tag name e.g. `'div'`

`starttag -> Optional[str]` head of the tag e.g. `'<div class="user">'`

`endtag -> Optional[str]` tail of the tag e.g. `'</div>'`

`endtag_strip -> Optional[str]` tail of the tag, stripped of `<` and `>` e.g. `'/div'`

`text -> Optional[str]` text of children

`text_recursive -> Optional[str]` text of descendants

```python
rq = reliq("""
  <main>
    <ul>
      <a>
        <li>L1</li>
      </a>
      <li>L2</li>
    </ul>
  </main>
""")

ul = rq[0][0]
a = ul[0]
li1 = a[0]
li2 = ul[1]

ul.name
# 'ul'

ul.name_raw
# b'ul'

ul.lvl
# 1

li1.lvl
# 3

ul.text
# '\n      \n      \n    '

ul.text_recursive
# '\n      \n        L1\n      \n      L2\n    '

a.insides
# '\n        <li>L1</li>\n      '
```

#### comment

Comments can either return their string representation or insides by `insides` property.

```python
c = reliq('<!-- Comment -->').self(type=None)[0]

c.insides
# ' Comment '

bytes(c)
# b'<!-- Comment -->'

str(c)
# '<!-- Comment -->'
```

#### text

Text can only be converted to string

```python
t = reliq('Example').self(type=None)[0]

str(t)
# 'Example'
```
### axes

Convert `reliq` objects into a list or a generator of `single` type objects.

If their first argument is set to `True` or `gen=True` is passed, a generator is returned, otherwise a list.

By default they filter node types to only `reliq.Type.tag`, this can be changed by setting the `type` argument e.g. `type=reliq.Type.comment|reliq.Type.texterr`. If type is set to `None` all types are matched.

If `rel=True` is passed returned objects will be relative to object from which they were matched.

```python
rq = reliq("""
  <!DOCTYPE html>
  <head>
    <title>Title</title>
  </head>
  <body>
    <section>
      <h1>Title</h1>
      <p>A</p>
    </section>
    <h2>List</h2>
    <ul>
      <li>A</li>
      <li>B</li>
      <li>C</li>
    </ul>
    <section>
      TEXT
    </section>
  </body>
""")
```

#### everything

`everything()` gets all elements in structure, no matter the previous context.

```python
#traverse everything through generator
for i in rq.everything(True):
  print(str(i))
```

#### self

`self()` gets the context itself, single element for `single` type, list of the `list` type and elements with `.lvl == 0` for `struct` type.

By default filtered type depends on object type it was called for, for `single` and `list` types are unfiltered, only `struct` type enforces `type=reliq.Type.tag`.

```python
# rq is a reliq.Type.struct object

rq.self()
# [<tag head>, <tag body>]

rq.self(type=None)
# [<textempty>, <comment>, <textempty>, <tag head>, <textempty>, <tag body>]

rq.self(type=reliq.Type.tag|reliq.Type.comment)
# [<comment>,<tag head>, <tag body>]

# ls is a reliq.Type.list object that has comments and text types
ls = rq.filter('[:3] ( comment@ * )( text@ * )')

ls.self()
# [<comment>, <text>, <text>, <text>]

ls.self(type=reliq.Type.tag|reliq.Type.comment)
# [<comment>]

# body is a reliq.Type.single object
body = rq[1].self()

len(body.self())
# 1

body.self()[0].name
# "body"
```
#### children

`children()` gets all nodes of the context that have level relative to them equal to 1.

```python
# struct
rq.children()
# [<tag title>, <tag section>, <tag h2>, <tag ul>, <tag section>]

# list
rq.filter('head, ul').children()
# [<tag title>, <tag li>, <tag li>, <tag li>]

# single
first_section = rq[1][0]
first_section.children()
# [<tag h1>, <tag p>]
```

#### descendants

`descendants()` gets all nodes of the context that have level relative to them greater or equal to 1.

```python
# struct
rq.descendants()
# [<tag title>, <tag section>, <tag h1>, <tag p>, <tag h2>, <tag ul>, <tag li>, <tag li>, <tag li>, <tag section>]

# list
rq.filter('[0] section').descendants()
# [<tag h1>, <tag p>]

# single
rq[1][0].descendants()
# [<tag h1>, <tag p>]
```

#### full

`full()` gets all nodes of the context and all nodes below them (like calling `self()` and `descendants()` at once).

```python
# struct
rq.full()
# [<tag head>, <tag title>, <tag body>, <tag section>, <tag h1>, <tag p>, <tag h2>, <tag ul>, <tag li>, <tag li>, <tag li>, <tag section>]

# list
rq.filter('[0] section').descendants()
# [<tag section>, <tag h1>, <tag p>]

# single
rq[1][0].descendants()
# [<tag section>, <tag h1>, <tag p>]
```

#### parent

`parent()` gets parent of context nodes. Doesn't work for `struct` type.

```python
# list
rq.filter('li').parent()
# [<tag ul>, <tag ul>, <tag ul>]

# single
rq[1][2][0].parent()
# [<tag li>]

# single
rq[0].parent() # top level nodes don't have parents
# []
```

#### rparent

`rparent()` behaves like `parent()` but returns the parent to which the current object is relative to. Doesn't work for `struct` type.

It doesn't take `rel` argument, returned objects are always relative.

#### ancestors

`ancestors()` gets ancestors of context nodes. Doesn't work for `struct` type.

```python
# list
rq.filter('li').ancestors()
# [<tag ul>, <tag body>, <tag ul>, <tag body>, <tag ul>, <tag body>]

# single
rq[1][2][0].ancestors()
# [<tag ul>, <tag body>]

# first element of ancestors() should be the same as for parent()
rq[1][2][0].ancestors()[0].name == rq[1][2][0].parent()[0].name

# single
rq[0].ancestors() # top level nodes don't have ancestors
# []
```

#### before

`before()` gets all nodes that have lower `.position` property than context nodes. Doesn't work for `struct` type.

```python
# list
rq.filter('[0] title, [1] section').before()
# [<tag head>, <tag li>, <tag li>, <tag li>, <tag ul>, <tag h2>, <tag p>, <tag h1>, <tag section>, <tag body>, <tag title>, <tag head>]

# single
title = rq[0][0]
title.before()
# [<tag head>]

# single
second_section = rq[1][3]
second_section.before()
# [<tag li>, <tag li>, <tag li>, <tag ul>, <tag h2>, <tag p>, <tag h1>, <tag section>, <tag body>, <tag title>, <tag head>]

# single
head = rq[0]
head.before() #first element doesn't have any nodes before it
# []
```

#### preceding

`preceding()` is similar to `before()` but ignores ancestors. Doesn't work for `struct` type.

```python
# list
rq.filter('[0] title, [1] section').preceding()
# [<tag li>, <tag li>, <tag li>, <tag ul>, <tag h2>, <tag p>, <tag h1>, <tag section>, <tag title>, <tag head>]

# single
title = rq[0][0]
title.preceding() # all tags before it are it's ancestors
# []

# single
second_section = rq[1][3]
second_section.preceding()
# [<tag li>, <tag li>, <tag li>, <tag ul>, <tag h2>, <tag p>, <tag h1>, <tag section>, <tag title>, <tag head>]
```

#### after

`after()` gets all nodes that have higher `.position` property than context nodes. Doesn't work for `struct` type.

```python
# list
rq.filter('h2, ul').after()
# [<tag ul>, <tag li>, <tag li>, <tag li>, <tag section>, <tag li>, <tag li>, <tag li>, <tag section>]

# single
h2 = rq[1][1]
h2.after()
# [<tag ul>, <tag li>, <tag li>, <tag li>, <tag section>]

# single
ul = rq[1][2]
ul.after()
# [<tag li>, <tag li>, <tag li>, <tag section>]

# single
third_section = rq[1][3] # last element
third_section.after()
# []
```

#### subsequent

`subsequent()` is similar to `after()` but ignores descendants. Doesn't work for `struct` type.

```python
# list
rq.filter('h2, ul').subsequent()
# [<tag ul>, <tag li>, <tag li>, <tag li>, <tag section>, <tag section>]

# single
h2 = rq[1][1]
h2.subsequent()
# [<tag ul>, <tag li>, <tag li>, <tag li>, <tag section>]

# single
ul = rq[1][2]
ul.subsequent()
# [<tag section>]
```

#### siblings_preceding

`siblings_preceding()` gets nodes on the same level as context nodes but before them and limited to their parent. Doesn't work for `struct` type.

If `full=True` is passed descendants of siblings will also be matched.

```python
# list
rq.filter('ul, h2').siblings_preceding()
# [<tag h2>, <tag section>, <tag section>]

# single
h2 = rq[1][1]

h2.siblings_preceding()
# [<tag section>]
h2.siblings_preceding(full=True)
# [<tag p>, <tag h1>, <tag section>]

# single
ul = rq[1][2]

ul.siblings_preceding()
# [<tag h2>, <tag section>]
ul.siblings_preceding(full=True)
# [<tag h2>, <tag p>, <tag h1>, <tag section>]
```

#### siblings_subsequent

`siblings_preceding()` gets nodes on the same level as context nodes but after them and limited to their parent. Doesn't work for `struct` type.

If `full=True` is passed descendants of siblings will also be matched.

```python
# list
rq.filter('ul, h2').siblings_subsequent()
# [<tag h2>, <tag section>, <tag section>]

# single
h2 = rq[1][1]

h2.siblings_subsequent()
# [<tag ul>, <tag section>]
h2.siblings_subsequent(full=True)
# [<tag ul>, <tag li>, <tag li>, <tag li>, <tag section>]

# single
ul = rq[1][2]

ul.siblings_subsequent()
# [<tag section>]
ul.siblings_subsequent(full=True)
# [<tag section>]
```

#### siblings

`siblings()` returns merged output of `siblings_preceding()` and `siblings_subsequent()`.

### expr

`reliq.expr` is a class that compiles expressions, it accepts only one argument that can be a `str()`, `bytes()` or `Path()`.

If `Path()` argument is specified, file under it will be read with `Path.read_bytes()`.

```python
# str
reliq.expr(r'table; { tr .name; li | "%(title)v\n", th }')

# bytes
reliq.expr(rb'li')

# file from Path
reliq.expr(Path('expression.reliq'))
```

### search

`search()` executes expression in the first argument and returns `str()` or `bytes` if second argument is `True` or `raw=True`.

Expression can be passed both as compiled object of `reliq.expr` or its representation in `str()`, `bytes()` or `Path()` that will be compiled in function.

```python
rq = reliq('<span class=name data-user-id=1282>User</span><p>Title: N1ase</p>')

rq.search(r'p')
# '<p>Title: N1ase</p>\n'

rq.search(r'p', True)
# b'<p>Title: N1ase</p>\n'

rq.search(r'p', raw=True)
# b'<p>Title: N1ase</p>\n'

rq.search(r"""
  span .name; {
    .id.u @ | "%(data-user-id)v",
    .name @ | "%t"
  },
  .title p | "%i" sed "s/^Title: //"
""",True)
# b'{"id":1282,"name":"User","title":"N1ase"}'

rq.search(Path('expression.reliq'))
```

### json

Similar to `search()` but returns `dict()` while validating expression.

### filter

`filter()` executes expression in the first argument and returns `reliq` object of `list` type or `empty` type if nothing has been found.

If second argument is `True` or `independent=True` then returned object will be completely independent from the one the function was called on. A new HTML string representation will be created, and structure will be copied and shifted to new string, levels will also change.

Expression can be passed both as compiled object of `reliq.expr` or its representation in `str()`, `bytes()` or `Path()` that will be compiled in function.

Any field, formatting or string conversion in expression will be ignored, only objects used in them will be returned.

```python
rq = reliq('<span class=name data-user-id=1282>User</span><p>Title: N1ase</p>')

rq.filter(r'p').self()
# [<tag p>]

rq.filter(r'p').type
# reliq.Type.list

rq.filter(r'p').get_data()
# '<span class=name data-user-id=1282>User</span><p>Title: N1ase</p>'

rq.filter(r'p',True).get_data()
# '<p>Title: N1ase</p>'

rq.filter(r'nothing').type
# reliq.Type.empty

rq.filter(r"""
  span .name; {
    .id.u @ | "%(data-user-id)v",
    .name @ | "%t"
  },
  .title p | "%i" sed "s/^Title: //"
""")
# [<tag span>, <tag span>, <tag p>]

rq.filter(Path('expression.reliq'))
```

### Encoding and decoding html entities

`decode()` decodes html entities in first argument of `str()` or `bytes()`, and returns `str()` or `bytes()` if second argument is `True` or `raw=True`.

By default `&nbsp;` is translated to space, this can be changed by setting `no_nbsp=False`.

`encode()` does the opposite of `decode()` in the same fashion.

By default only special characters are encoded i.e. `<`, `>`, `"`, `'`, `&`. If `full=True` is set everything possible will be converted to html entities (quite slow approach).

```python
reliq.decode(r"text &amp; &lt &tdot; &#212")
# "loop & <  ⃛⃛ Ô"

reliq.decode(r"text &amp; &lt &tdot; &#212",True)
# b'text & <  \xe2\x83\x9b\xe2\x83\x9b \xc3\x94'

reliq.decode(r"text &amp; &lt &tdot; &#212",raw=True)
# b'text & <  \xe2\x83\x9b\xe2\x83\x9b \xc3\x94'

reliq.decode('ex&nbsp;t')
# "ex t"

reliq.decode('ex&nbsp;t',no_nbsp=False)
# 'ex\xa0t'

reliq.decode('ex&nbsp;t',True,no_nbsp=False)
# b'ex\xc2\xa0t'

reliq.encode("<p>li &amp; \t 'seq' \n </p>")
# '&lt;p&gt;li &amp;amp; \t &#x27;seq&#x27; \n &lt;/p&gt;'

reliq.encode("<p>li &amp; \t 'seq' \n </p>",True)
# b'&lt;p&gt;li &amp;amp; \t &#x27;seq&#x27; \n &lt;/p&gt;'

reliq.encode("<p>li &amp; \t 'seq' \n </p>",raw=True)
# b'&lt;p&gt;li &amp;amp; \t &#x27;seq&#x27; \n &lt;/p&gt;'

reliq.encode("<p>li &amp; \t 'seq' \n </p>",full=True)
# '&lt;p&gt;li &amp;amp&semi; &Tab; &#x27;seq&#x27; &NewLine; &lt;&sol;p&gt;'

reliq.encode("<p>li &amp; \t 'seq' \n </p>",True,full=True)
# b'&lt;p&gt;li &amp;amp&semi; &Tab; &#x27;seq&#x27; &NewLine; &lt;&sol;p&gt;'
```

### URLS

`urljoin` work like `urllib.parse.urljoin` but it can take argument's in `bytes` and returns `str` or `bytes` depending on `raw` argument.

`ujoin` works the same way as `urljoin` but `ref` argument is set to default reference url in structure.

### Errors

All errors are instances of `reliq.Error`.

`reliq.SystemError` is raised when kernel fails (you should assume it doesn't happen).

`reliq.HtmlError` is raised when html structure exceeds limits.

`reliq.ScriptError` is raised when incorrect script is compiled.

```python
try:
  reliq('<div>'*8193) # 8192 passes :D
except reliq.HtmlError:
  print('html depth limit exceeded')

try:
  reliq.expr('| |')
except reliq.ScriptError:
  print('incorrect expression')
```

### Relativity

`list` and `single` type object also stores a pointer to node that object is relative to in context i.e. `rq.filter(r'body; nav')` will return `nav` objects that were found in `body` tags, `nav` objects might not be direct siblings of `body` tags but because of relativity their relation is not lost.

`reliq.filter()` always keeps the relativity.

By default axis functions don't change relativity unless `rel=True` is passed.

```python
rq = reliq("""
  <body>
    <nav>
      <ul>
        <li> A </li>
        <li> B </li>
        <li> C </li>
      </ul>
    </nav>
  </body>
""")

li = rq[0][0][0][1] # not relative

li_self = rq.filter('li i@w>"B"')[0] # relative to itself

li_rel = rq.filter('nav; li i@w>"B"')[0] # relative to nav

# .rlvl and .rposition for non relative objects return same values as .lvl and .position

li.lvl
# 3
li_rel.lvl
# 3

li.rlvl
# 3
li_rel.rlvl
# 2

li.position
# 10
li_rel.position
# 10

li.rposition
# 10
li_rel.rposition
# 9

nav = rq[0][0]
for i in nav.descendants(rel=True):
    if i.rlvl == 2 and i.name == 'li':
        print(i.lvl,i.rlvl)
        # 3 2
        break

nav_rel = li_rel.rparent()[0] # nav element relative to li

nav_rel.rlvl
# -2
nav_rel.rposition
# -7
```

### Project wrapper

Expressions can grow into considerable sizes so it's beneficial to save them in separate directories and cache them. `RQ` function returns a new `reliq` type that keeps track of cache and directory of the script that has called this function.

```python
from reliq import RQ

reliq = RQ(cached=True)

rq = reliq('<p>Alive!</p>')
print(rq)
```

It takes two optional arguments `def RQ(path="", cached=False)`. If `cached` is set, compiled expressions will be saved and reused.

If `path` is not an absolute path it will be merged with directory of the calling function. When in any function that takes expression argument a `Path()` is passed it will be relative to first declared `path` argument. Exceptions to that are paths that are absolute or begin with `./` or `../`.

This function should be used by packages to save reliq expressions under their directories without polluting the general `reliq` object space. After the first declaration of this type it should be reused everywhere in project.

## Projects using reliq in python

- [forumscraper](https://github.com/TUVIMEN/forumscraper)
- [lightnovelworld](https://github.com/TUVIMEN/lightnovelworld/)
- [1337x-scraper](https://github.com/TUVIMEN/1337x-scraper)
- [blu-ray-scraper](https://github.com/TUVIMEN/blu-ray-scraper)
- [9gag-scraper](https://github.com/TUVIMEN/9gag-scraper)

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "reliq",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": null,
    "keywords": "ctypes, html, parser, text-processing",
    "author": null,
    "author_email": "Dominik Stanis\u0142aw Suchora <hexderm@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/9f/d5/261cae39778cea2a106383b13898b765e4050cf3d2467714d7ea33292462/reliq-0.0.44.tar.gz",
    "platform": null,
    "description": "# reliq-python\n\nA python bindings for [reliq](https://github.com/TUVIMEN/reliq) library.\n\n## Installation\n\n    pip install reliq\n\n## Benchmark\n\nBenchmarks were inspired by [selectolax](https://github.com/rushter/selectolax/blob/master/examples/benchmark.py) and performed on 355MB, 896 files sample of most popular websites. You can find the benchmark script [here](benchmark/benchmark.py).\n\n### Parsing\n\n| Package             | Time     |\n| --------------      | ----     |\n| bs4                 | 121.615s |\n| html5-parser        | 22.424s  |\n| lxml                | 4.955s   |\n| selectolax (modest) | 2.901s   |\n| selectolax (lexbor) | 1.200s   |\n| reliq               | 0.310s   |\n\n### Collective memory usage of parsed trees\n\n| Package             | Memory |\n| --------------      | ----   |\n| bs4                 | 2234MB |\n| selectolax (lexbor) | 1666MB |\n| selectolax (modest) | 1602MB |\n| lxml                | 1274MB |\n| html5-parser        | 1262MB |\n| reliq               | 58MB   |\n\n### Parsing and processing\n\n| Package             | Time     |\n| --------------      | ----     |\n| bs4                 | 230.661s |\n| html5-parser        | 31.138s  |\n| lxml                | 14.010s  |\n| selectolax (modest) | 4.291s   |\n| reliq               | 2.974s   |\n| selectolax (lexbor) | 2.628s   |\n\n## Usage\n\n### Code\n\n```python\nfrom reliq import reliq\n\nhtml = \"\"\nwith open('index.html','r') as f:\n    html = f.read()\n\nrq = reliq(html) #parse html\nexpr = reliq.expr(r\"\"\"\n    div .user; {\n        a href; {\n            .name @ | \"%i\",\n            .link @ | \"%(href)v\"\n        },\n        .score.u span .score,\n        .info dl; {\n            .key dt | \"%i\",\n            .value dd | \"%i\"\n        } |,\n        .achievements.a li class=b>\"achievement-\" | \"%i\\n\"\n    }\n\"\"\") #expressions can be compiled\n\nusers = []\nlinks = []\n\nfor i in rq.filter(r'table; { tr, text@ iw>lisp }')[:-2]:\n    # ignore comments and text nodes\n    if i.type is not reliq.Type.tag:\n        continue\n\n    first_child = i[0]\n\n    if first_child.desc_count < 3 and first_child.name == \"div\" and first_child.starttag == '<div>':\n        continue\n\n    link = first_child[2].attrib['href']\n    if re.match('^https://$',link):\n        links.append(link)\n        continue\n\n    #make sure that object is an ancestor of <main> tag\n    for j in i.ancestors():\n        if j.name == \"main\":\n          break\n    else:\n      continue\n\n    #search() returns str, in this case expression is already compiled\n    #  but can be also passed as a str() or bytes(). If Path() is passed\n    #  file will be read\n    user = json.loads(i.search(expr))\n    users.append(user)\n\ntry: #handle errors\n    rq.search('p / /','<p></p>')\nexcept reliq.ScriptError: # all errors inherit from reliq.Error\n    print(\"error\")\n\n#get text from all text nodes that are descendants of object\nprint(rq[2].text_recursive)\n#get text from all text nodes that are children of object\nprint(rq[2].text)\n\n#decode html entities\nreliq.decode('loop &amp; &lt &tdot; &#212')\n\n#execute and convert to dictionary\nrq.json(r\"\"\"\n    .files * #files; ( li )( span .head ); {\n        .type i class child@ | \"%(class)v\" / sed \"s/^flaticon-//\",\n        .name @ | \"%Dt\" / trim sed \"s/ ([^)]* [a-zA-Z][Bb])$//\",\n        .size @ | \"%t\" / sed 's/.* \\(([^)]* [a-zA-Z][Bb])\\)$/\\1/; s/,//g; /^[0-9].* [a-zA-Z][bB]$/!d' \"E\"\n    } |\n\"\"\") #dict format is enforced and any incompatible expressions will raise reliq.ScriptError\n```\n\n### Import\n\nMost is contained inside `reliq` class\n\n```python\nfrom reliq import reliq, RQ\n```\n\n### Initialization\n\n`reliq` object takes an argument representing html, this can be `str()`, `bytes()`, `Path()` (file is read as `bytes`), `reliq()` or `None`.\n\n```python\nrq = reliq('<p>Example</p>') #passed directly\n\nrq2 = reliq(Path('index.html')) #passed from file\n\nrq3 = reliq(None) # empty object\nrq4 = reliq() # empty object\n```\n\nIf optional argument `ref` is a string it'll set url to the first base tag in html structure, and in case there isn't any it'll be set to `ref`.\n\n```python\nrq = reliq('<p>Example</p>')\nrq.ref # None\n\nrq2 = reliq(b'<p>Second example</p>',ref=\"http://en.wikipedia.org\")\nrq2.ref # http://en.wikipedia.org\n\nrq3 = reliq(b'<base href=\"https://wikipedia.org\"><p>Second example</p>',ref=\"http://en.wikipedia.org\")\nrq3.ref # https://wikipedia.org\n\nrq4 = reliq(b'<base href=\"https://wikipedia.org\"><p>Second example</p>',ref=\"\")\nrq4.ref # https://wikipedia.org\n```\n\n### Types\n\n`reliq` can have 5 types that change the behaviour of methods.\n\nCalling `type` property on object e.g. `rq.type` returns instance of `reliq.Type(Flag)`.\n\n#### empty\n\nGets returned from either `reliq(None)` or `reliq.filter()` that matches nothing, makes all methods return default values.\n\n#### unknown\n\nSimilar to `empty` but should never happen\n\n#### struct\n\nReturned by successful initialization e.g.\n\n```python\nreliq('<p>Example</p>')\n```\n\n#### list\n\nReturned by `reliq.filter()` that succeeds\n\n#### single\n\nReturned by axis methods or by accessing the object like a list.\n\nThe type itself is a grouping of more specific types:\n\n - tag\n - comment\n - textempty (text made only of whitespaces)\n - texterr (text where an html error occurred)\n - text\n - textall (grouping of text types)\n\n### get_data(raw=False) -> str|bytes\n\nReturns the same html from which the object was compiled.\n\nIf first argument is `True` or `raw=True` returns `bytes`.\n\n```python\ndata = Path('index.html').read_bytes\n\nrq = reliq(data)\nx = rq[0][2][1][8]\n\n# if both objects are bytes() then their ids should be the same\nx.get_data(True) is data\n```\n\n### special methods\n\n#### \\_\\_bytes\\_\\_ and \\_\\_str\\_\\_\n\nFull string representation of current object\n\n```python\nrq = reliq(\"\"\"\n  <h1><b>H</b>1</h1>\n  <h2>N2</h2>\n  <h2>N3</h2>\n\"\"\")\n\nstr(rq) # struct\n# '\\n  <h1><b>H</b>1</h1>\\n  <h2>N2</h2>\\n  <h2>N3</h2>\\n'\n\nstr(rq.filter('h2')) # list\n# '<h2>N2</h2><h2>N3</h2>'\n\nstr(rq[0]) # single\n# '<h1><b>H</b>1</h1>'\n\nstr(reliq()) # empty\n# ''\n```\n\n#### \\_\\_getitem\\_\\_\n\nFor `single` indexes results from `children()` axis, otherwise from `self()` axis\n\n```python\nrq = reliq('<div><p>1</p> Text <b>H</b></div>')\n\nfirst = rq[0] # struct\n# <div>\n\nfirst[1] # single\n# <b>\n\nr = first.filter('( text@ * )( * ) child@')\nr[1] # list\n# \" Text \" obj\n\nr[2] == first[1]\n```\n\n#### \\_\\_len\\_\\_\n\nAmount of objects returned from `__getitem__`\n\n### ref and ref_raw\n\n`ref -> str`\n\n`ref_raw -> bytes`\n\nThey return saved reference url at initialization.\n\n```python\nrq = reliq('',ref=\"http://en.wikipedia.org\")\nrq.ref # \"http://en.wikipedia.org\"\nrq.ref_raw # b\"http://en.wikipedia.org\"\n```\n\n### properties of single\n\nCalling these properties for types other than `single` returns their default values.\n\n`lvl -> int` level in html structure\n\n`rlvl -> int` level in html structure, relative to parent\n\n`position -> int` position in html structure\n\n`rposition -> int` position in html structure, relative to parent\n\nCalling some properties makes sense only for certain types.\n\n#### tag\n\n`tag_count -> int` count of tags\n\n`text_count -> int` count of text\n\n`comment_count -> int` count of comments\n\n`desc_count -> int` count of descendants\n\n`attribl -> int` number of attributes\n\n----\n\n`attrib -> dict` dictionary of attributes\n\n----\n\nThese return `None` only if called from `empty` type. They also have `_raw` counterparts that return `bytes` e.g. `text_recursive_raw -> Optional[bytes]`, `name_raw -> Optional[bytes]`\n\n`insides -> Optional[str]` string containing contents inside tag or comment\n\n`name -> Optional[str]` tag name e.g. `'div'`\n\n`starttag -> Optional[str]` head of the tag e.g. `'<div class=\"user\">'`\n\n`endtag -> Optional[str]` tail of the tag e.g. `'</div>'`\n\n`endtag_strip -> Optional[str]` tail of the tag, stripped of `<` and `>` e.g. `'/div'`\n\n`text -> Optional[str]` text of children\n\n`text_recursive -> Optional[str]` text of descendants\n\n```python\nrq = reliq(\"\"\"\n  <main>\n    <ul>\n      <a>\n        <li>L1</li>\n      </a>\n      <li>L2</li>\n    </ul>\n  </main>\n\"\"\")\n\nul = rq[0][0]\na = ul[0]\nli1 = a[0]\nli2 = ul[1]\n\nul.name\n# 'ul'\n\nul.name_raw\n# b'ul'\n\nul.lvl\n# 1\n\nli1.lvl\n# 3\n\nul.text\n# '\\n      \\n      \\n    '\n\nul.text_recursive\n# '\\n      \\n        L1\\n      \\n      L2\\n    '\n\na.insides\n# '\\n        <li>L1</li>\\n      '\n```\n\n#### comment\n\nComments can either return their string representation or insides by `insides` property.\n\n```python\nc = reliq('<!-- Comment -->').self(type=None)[0]\n\nc.insides\n# ' Comment '\n\nbytes(c)\n# b'<!-- Comment -->'\n\nstr(c)\n# '<!-- Comment -->'\n```\n\n#### text\n\nText can only be converted to string\n\n```python\nt = reliq('Example').self(type=None)[0]\n\nstr(t)\n# 'Example'\n```\n### axes\n\nConvert `reliq` objects into a list or a generator of `single` type objects.\n\nIf their first argument is set to `True` or `gen=True` is passed, a generator is returned, otherwise a list.\n\nBy default they filter node types to only `reliq.Type.tag`, this can be changed by setting the `type` argument e.g. `type=reliq.Type.comment|reliq.Type.texterr`. If type is set to `None` all types are matched.\n\nIf `rel=True` is passed returned objects will be relative to object from which they were matched.\n\n```python\nrq = reliq(\"\"\"\n  <!DOCTYPE html>\n  <head>\n    <title>Title</title>\n  </head>\n  <body>\n    <section>\n      <h1>Title</h1>\n      <p>A</p>\n    </section>\n    <h2>List</h2>\n    <ul>\n      <li>A</li>\n      <li>B</li>\n      <li>C</li>\n    </ul>\n    <section>\n      TEXT\n    </section>\n  </body>\n\"\"\")\n```\n\n#### everything\n\n`everything()` gets all elements in structure, no matter the previous context.\n\n```python\n#traverse everything through generator\nfor i in rq.everything(True):\n  print(str(i))\n```\n\n#### self\n\n`self()` gets the context itself, single element for `single` type, list of the `list` type and elements with `.lvl == 0` for `struct` type.\n\nBy default filtered type depends on object type it was called for, for `single` and `list` types are unfiltered, only `struct` type enforces `type=reliq.Type.tag`.\n\n```python\n# rq is a reliq.Type.struct object\n\nrq.self()\n# [<tag head>, <tag body>]\n\nrq.self(type=None)\n# [<textempty>, <comment>, <textempty>, <tag head>, <textempty>, <tag body>]\n\nrq.self(type=reliq.Type.tag|reliq.Type.comment)\n# [<comment>,<tag head>, <tag body>]\n\n# ls is a reliq.Type.list object that has comments and text types\nls = rq.filter('[:3] ( comment@ * )( text@ * )')\n\nls.self()\n# [<comment>, <text>, <text>, <text>]\n\nls.self(type=reliq.Type.tag|reliq.Type.comment)\n# [<comment>]\n\n# body is a reliq.Type.single object\nbody = rq[1].self()\n\nlen(body.self())\n# 1\n\nbody.self()[0].name\n# \"body\"\n```\n#### children\n\n`children()` gets all nodes of the context that have level relative to them equal to 1.\n\n```python\n# struct\nrq.children()\n# [<tag title>, <tag section>, <tag h2>, <tag ul>, <tag section>]\n\n# list\nrq.filter('head, ul').children()\n# [<tag title>, <tag li>, <tag li>, <tag li>]\n\n# single\nfirst_section = rq[1][0]\nfirst_section.children()\n# [<tag h1>, <tag p>]\n```\n\n#### descendants\n\n`descendants()` gets all nodes of the context that have level relative to them greater or equal to 1.\n\n```python\n# struct\nrq.descendants()\n# [<tag title>, <tag section>, <tag h1>, <tag p>, <tag h2>, <tag ul>, <tag li>, <tag li>, <tag li>, <tag section>]\n\n# list\nrq.filter('[0] section').descendants()\n# [<tag h1>, <tag p>]\n\n# single\nrq[1][0].descendants()\n# [<tag h1>, <tag p>]\n```\n\n#### full\n\n`full()` gets all nodes of the context and all nodes below them (like calling `self()` and `descendants()` at once).\n\n```python\n# struct\nrq.full()\n# [<tag head>, <tag title>, <tag body>, <tag section>, <tag h1>, <tag p>, <tag h2>, <tag ul>, <tag li>, <tag li>, <tag li>, <tag section>]\n\n# list\nrq.filter('[0] section').descendants()\n# [<tag section>, <tag h1>, <tag p>]\n\n# single\nrq[1][0].descendants()\n# [<tag section>, <tag h1>, <tag p>]\n```\n\n#### parent\n\n`parent()` gets parent of context nodes. Doesn't work for `struct` type.\n\n```python\n# list\nrq.filter('li').parent()\n# [<tag ul>, <tag ul>, <tag ul>]\n\n# single\nrq[1][2][0].parent()\n# [<tag li>]\n\n# single\nrq[0].parent() # top level nodes don't have parents\n# []\n```\n\n#### rparent\n\n`rparent()` behaves like `parent()` but returns the parent to which the current object is relative to. Doesn't work for `struct` type.\n\nIt doesn't take `rel` argument, returned objects are always relative.\n\n#### ancestors\n\n`ancestors()` gets ancestors of context nodes. Doesn't work for `struct` type.\n\n```python\n# list\nrq.filter('li').ancestors()\n# [<tag ul>, <tag body>, <tag ul>, <tag body>, <tag ul>, <tag body>]\n\n# single\nrq[1][2][0].ancestors()\n# [<tag ul>, <tag body>]\n\n# first element of ancestors() should be the same as for parent()\nrq[1][2][0].ancestors()[0].name == rq[1][2][0].parent()[0].name\n\n# single\nrq[0].ancestors() # top level nodes don't have ancestors\n# []\n```\n\n#### before\n\n`before()` gets all nodes that have lower `.position` property than context nodes. Doesn't work for `struct` type.\n\n```python\n# list\nrq.filter('[0] title, [1] section').before()\n# [<tag head>, <tag li>, <tag li>, <tag li>, <tag ul>, <tag h2>, <tag p>, <tag h1>, <tag section>, <tag body>, <tag title>, <tag head>]\n\n# single\ntitle = rq[0][0]\ntitle.before()\n# [<tag head>]\n\n# single\nsecond_section = rq[1][3]\nsecond_section.before()\n# [<tag li>, <tag li>, <tag li>, <tag ul>, <tag h2>, <tag p>, <tag h1>, <tag section>, <tag body>, <tag title>, <tag head>]\n\n# single\nhead = rq[0]\nhead.before() #first element doesn't have any nodes before it\n# []\n```\n\n#### preceding\n\n`preceding()` is similar to `before()` but ignores ancestors. Doesn't work for `struct` type.\n\n```python\n# list\nrq.filter('[0] title, [1] section').preceding()\n# [<tag li>, <tag li>, <tag li>, <tag ul>, <tag h2>, <tag p>, <tag h1>, <tag section>, <tag title>, <tag head>]\n\n# single\ntitle = rq[0][0]\ntitle.preceding() # all tags before it are it's ancestors\n# []\n\n# single\nsecond_section = rq[1][3]\nsecond_section.preceding()\n# [<tag li>, <tag li>, <tag li>, <tag ul>, <tag h2>, <tag p>, <tag h1>, <tag section>, <tag title>, <tag head>]\n```\n\n#### after\n\n`after()` gets all nodes that have higher `.position` property than context nodes. Doesn't work for `struct` type.\n\n```python\n# list\nrq.filter('h2, ul').after()\n# [<tag ul>, <tag li>, <tag li>, <tag li>, <tag section>, <tag li>, <tag li>, <tag li>, <tag section>]\n\n# single\nh2 = rq[1][1]\nh2.after()\n# [<tag ul>, <tag li>, <tag li>, <tag li>, <tag section>]\n\n# single\nul = rq[1][2]\nul.after()\n# [<tag li>, <tag li>, <tag li>, <tag section>]\n\n# single\nthird_section = rq[1][3] # last element\nthird_section.after()\n# []\n```\n\n#### subsequent\n\n`subsequent()` is similar to `after()` but ignores descendants. Doesn't work for `struct` type.\n\n```python\n# list\nrq.filter('h2, ul').subsequent()\n# [<tag ul>, <tag li>, <tag li>, <tag li>, <tag section>, <tag section>]\n\n# single\nh2 = rq[1][1]\nh2.subsequent()\n# [<tag ul>, <tag li>, <tag li>, <tag li>, <tag section>]\n\n# single\nul = rq[1][2]\nul.subsequent()\n# [<tag section>]\n```\n\n#### siblings_preceding\n\n`siblings_preceding()` gets nodes on the same level as context nodes but before them and limited to their parent. Doesn't work for `struct` type.\n\nIf `full=True` is passed descendants of siblings will also be matched.\n\n```python\n# list\nrq.filter('ul, h2').siblings_preceding()\n# [<tag h2>, <tag section>, <tag section>]\n\n# single\nh2 = rq[1][1]\n\nh2.siblings_preceding()\n# [<tag section>]\nh2.siblings_preceding(full=True)\n# [<tag p>, <tag h1>, <tag section>]\n\n# single\nul = rq[1][2]\n\nul.siblings_preceding()\n# [<tag h2>, <tag section>]\nul.siblings_preceding(full=True)\n# [<tag h2>, <tag p>, <tag h1>, <tag section>]\n```\n\n#### siblings_subsequent\n\n`siblings_preceding()` gets nodes on the same level as context nodes but after them and limited to their parent. Doesn't work for `struct` type.\n\nIf `full=True` is passed descendants of siblings will also be matched.\n\n```python\n# list\nrq.filter('ul, h2').siblings_subsequent()\n# [<tag h2>, <tag section>, <tag section>]\n\n# single\nh2 = rq[1][1]\n\nh2.siblings_subsequent()\n# [<tag ul>, <tag section>]\nh2.siblings_subsequent(full=True)\n# [<tag ul>, <tag li>, <tag li>, <tag li>, <tag section>]\n\n# single\nul = rq[1][2]\n\nul.siblings_subsequent()\n# [<tag section>]\nul.siblings_subsequent(full=True)\n# [<tag section>]\n```\n\n#### siblings\n\n`siblings()` returns merged output of `siblings_preceding()` and `siblings_subsequent()`.\n\n### expr\n\n`reliq.expr` is a class that compiles expressions, it accepts only one argument that can be a `str()`, `bytes()` or `Path()`.\n\nIf `Path()` argument is specified, file under it will be read with `Path.read_bytes()`.\n\n```python\n# str\nreliq.expr(r'table; { tr .name; li | \"%(title)v\\n\", th }')\n\n# bytes\nreliq.expr(rb'li')\n\n# file from Path\nreliq.expr(Path('expression.reliq'))\n```\n\n### search\n\n`search()` executes expression in the first argument and returns `str()` or `bytes` if second argument is `True` or `raw=True`.\n\nExpression can be passed both as compiled object of `reliq.expr` or its representation in `str()`, `bytes()` or `Path()` that will be compiled in function.\n\n```python\nrq = reliq('<span class=name data-user-id=1282>User</span><p>Title: N1ase</p>')\n\nrq.search(r'p')\n# '<p>Title: N1ase</p>\\n'\n\nrq.search(r'p', True)\n# b'<p>Title: N1ase</p>\\n'\n\nrq.search(r'p', raw=True)\n# b'<p>Title: N1ase</p>\\n'\n\nrq.search(r\"\"\"\n  span .name; {\n    .id.u @ | \"%(data-user-id)v\",\n    .name @ | \"%t\"\n  },\n  .title p | \"%i\" sed \"s/^Title: //\"\n\"\"\",True)\n# b'{\"id\":1282,\"name\":\"User\",\"title\":\"N1ase\"}'\n\nrq.search(Path('expression.reliq'))\n```\n\n### json\n\nSimilar to `search()` but returns `dict()` while validating expression.\n\n### filter\n\n`filter()` executes expression in the first argument and returns `reliq` object of `list` type or `empty` type if nothing has been found.\n\nIf second argument is `True` or `independent=True` then returned object will be completely independent from the one the function was called on. A new HTML string representation will be created, and structure will be copied and shifted to new string, levels will also change.\n\nExpression can be passed both as compiled object of `reliq.expr` or its representation in `str()`, `bytes()` or `Path()` that will be compiled in function.\n\nAny field, formatting or string conversion in expression will be ignored, only objects used in them will be returned.\n\n```python\nrq = reliq('<span class=name data-user-id=1282>User</span><p>Title: N1ase</p>')\n\nrq.filter(r'p').self()\n# [<tag p>]\n\nrq.filter(r'p').type\n# reliq.Type.list\n\nrq.filter(r'p').get_data()\n# '<span class=name data-user-id=1282>User</span><p>Title: N1ase</p>'\n\nrq.filter(r'p',True).get_data()\n# '<p>Title: N1ase</p>'\n\nrq.filter(r'nothing').type\n# reliq.Type.empty\n\nrq.filter(r\"\"\"\n  span .name; {\n    .id.u @ | \"%(data-user-id)v\",\n    .name @ | \"%t\"\n  },\n  .title p | \"%i\" sed \"s/^Title: //\"\n\"\"\")\n# [<tag span>, <tag span>, <tag p>]\n\nrq.filter(Path('expression.reliq'))\n```\n\n### Encoding and decoding html entities\n\n`decode()` decodes html entities in first argument of `str()` or `bytes()`, and returns `str()` or `bytes()` if second argument is `True` or `raw=True`.\n\nBy default `&nbsp;` is translated to space, this can be changed by setting `no_nbsp=False`.\n\n`encode()` does the opposite of `decode()` in the same fashion.\n\nBy default only special characters are encoded i.e. `<`, `>`, `\"`, `'`, `&`. If `full=True` is set everything possible will be converted to html entities (quite slow approach).\n\n```python\nreliq.decode(r\"text &amp; &lt &tdot; &#212\")\n# \"loop & <  \u20db\u20db \u00d4\"\n\nreliq.decode(r\"text &amp; &lt &tdot; &#212\",True)\n# b'text & <  \\xe2\\x83\\x9b\\xe2\\x83\\x9b \\xc3\\x94'\n\nreliq.decode(r\"text &amp; &lt &tdot; &#212\",raw=True)\n# b'text & <  \\xe2\\x83\\x9b\\xe2\\x83\\x9b \\xc3\\x94'\n\nreliq.decode('ex&nbsp;t')\n# \"ex t\"\n\nreliq.decode('ex&nbsp;t',no_nbsp=False)\n# 'ex\\xa0t'\n\nreliq.decode('ex&nbsp;t',True,no_nbsp=False)\n# b'ex\\xc2\\xa0t'\n\nreliq.encode(\"<p>li &amp; \\t 'seq' \\n </p>\")\n# '&lt;p&gt;li &amp;amp; \\t &#x27;seq&#x27; \\n &lt;/p&gt;'\n\nreliq.encode(\"<p>li &amp; \\t 'seq' \\n </p>\",True)\n# b'&lt;p&gt;li &amp;amp; \\t &#x27;seq&#x27; \\n &lt;/p&gt;'\n\nreliq.encode(\"<p>li &amp; \\t 'seq' \\n </p>\",raw=True)\n# b'&lt;p&gt;li &amp;amp; \\t &#x27;seq&#x27; \\n &lt;/p&gt;'\n\nreliq.encode(\"<p>li &amp; \\t 'seq' \\n </p>\",full=True)\n# '&lt;p&gt;li &amp;amp&semi; &Tab; &#x27;seq&#x27; &NewLine; &lt;&sol;p&gt;'\n\nreliq.encode(\"<p>li &amp; \\t 'seq' \\n </p>\",True,full=True)\n# b'&lt;p&gt;li &amp;amp&semi; &Tab; &#x27;seq&#x27; &NewLine; &lt;&sol;p&gt;'\n```\n\n### URLS\n\n`urljoin` work like `urllib.parse.urljoin` but it can take argument's in `bytes` and returns `str` or `bytes` depending on `raw` argument.\n\n`ujoin` works the same way as `urljoin` but `ref` argument is set to default reference url in structure.\n\n### Errors\n\nAll errors are instances of `reliq.Error`.\n\n`reliq.SystemError` is raised when kernel fails (you should assume it doesn't happen).\n\n`reliq.HtmlError` is raised when html structure exceeds limits.\n\n`reliq.ScriptError` is raised when incorrect script is compiled.\n\n```python\ntry:\n  reliq('<div>'*8193) # 8192 passes :D\nexcept reliq.HtmlError:\n  print('html depth limit exceeded')\n\ntry:\n  reliq.expr('| |')\nexcept reliq.ScriptError:\n  print('incorrect expression')\n```\n\n### Relativity\n\n`list` and `single` type object also stores a pointer to node that object is relative to in context i.e. `rq.filter(r'body; nav')` will return `nav` objects that were found in `body` tags, `nav` objects might not be direct siblings of `body` tags but because of relativity their relation is not lost.\n\n`reliq.filter()` always keeps the relativity.\n\nBy default axis functions don't change relativity unless `rel=True` is passed.\n\n```python\nrq = reliq(\"\"\"\n  <body>\n    <nav>\n      <ul>\n        <li> A </li>\n        <li> B </li>\n        <li> C </li>\n      </ul>\n    </nav>\n  </body>\n\"\"\")\n\nli = rq[0][0][0][1] # not relative\n\nli_self = rq.filter('li i@w>\"B\"')[0] # relative to itself\n\nli_rel = rq.filter('nav; li i@w>\"B\"')[0] # relative to nav\n\n# .rlvl and .rposition for non relative objects return same values as .lvl and .position\n\nli.lvl\n# 3\nli_rel.lvl\n# 3\n\nli.rlvl\n# 3\nli_rel.rlvl\n# 2\n\nli.position\n# 10\nli_rel.position\n# 10\n\nli.rposition\n# 10\nli_rel.rposition\n# 9\n\nnav = rq[0][0]\nfor i in nav.descendants(rel=True):\n    if i.rlvl == 2 and i.name == 'li':\n        print(i.lvl,i.rlvl)\n        # 3 2\n        break\n\nnav_rel = li_rel.rparent()[0] # nav element relative to li\n\nnav_rel.rlvl\n# -2\nnav_rel.rposition\n# -7\n```\n\n### Project wrapper\n\nExpressions can grow into considerable sizes so it's beneficial to save them in separate directories and cache them. `RQ` function returns a new `reliq` type that keeps track of cache and directory of the script that has called this function.\n\n```python\nfrom reliq import RQ\n\nreliq = RQ(cached=True)\n\nrq = reliq('<p>Alive!</p>')\nprint(rq)\n```\n\nIt takes two optional arguments `def RQ(path=\"\", cached=False)`. If `cached` is set, compiled expressions will be saved and reused.\n\nIf `path` is not an absolute path it will be merged with directory of the calling function. When in any function that takes expression argument a `Path()` is passed it will be relative to first declared `path` argument. Exceptions to that are paths that are absolute or begin with `./` or `../`.\n\nThis function should be used by packages to save reliq expressions under their directories without polluting the general `reliq` object space. After the first declaration of this type it should be reused everywhere in project.\n\n## Projects using reliq in python\n\n- [forumscraper](https://github.com/TUVIMEN/forumscraper)\n- [lightnovelworld](https://github.com/TUVIMEN/lightnovelworld/)\n- [1337x-scraper](https://github.com/TUVIMEN/1337x-scraper)\n- [blu-ray-scraper](https://github.com/TUVIMEN/blu-ray-scraper)\n- [9gag-scraper](https://github.com/TUVIMEN/9gag-scraper)\n",
    "bugtrack_url": null,
    "license": "GPLv3",
    "summary": "Python ctypes bindings for reliq",
    "version": "0.0.44",
    "project_urls": {
        "Homepage": "https://github.com/TUVIMEN/reliq-python"
    },
    "split_keywords": [
        "ctypes",
        " html",
        " parser",
        " text-processing"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "333da615ae4dc1e22fa81d3aef8a6936150cb6704a029ba019f7f24b01252842",
                "md5": "988dc926d85f9c8066fd5b09c55ad043",
                "sha256": "bdb3e3988ed01bd38cb35f62414eefa9e37f5a69eebc948bab91e94fa50a62d8"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp310-cp310-macosx_13_0_x86_64.whl",
            "has_sig": false,
            "md5_digest": "988dc926d85f9c8066fd5b09c55ad043",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.7",
            "size": 120847,
            "upload_time": "2025-08-16T11:22:29",
            "upload_time_iso_8601": "2025-08-16T11:22:29.456269Z",
            "url": "https://files.pythonhosted.org/packages/33/3d/a615ae4dc1e22fa81d3aef8a6936150cb6704a029ba019f7f24b01252842/reliq-0.0.44-cp310-cp310-macosx_13_0_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "6470ec0aa5062a6418eeb4c0ff9376a774fea93b3c485b91bd84ba3382950e02",
                "md5": "741aa91b0f82b91cf2076a8748f4b500",
                "sha256": "1d29fedaea55738697f526f1f7535bb671c16bb6381dd187cb4519487700af1c"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp310-cp310-macosx_14_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "741aa91b0f82b91cf2076a8748f4b500",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.7",
            "size": 115310,
            "upload_time": "2025-08-16T11:22:31",
            "upload_time_iso_8601": "2025-08-16T11:22:31.505038Z",
            "url": "https://files.pythonhosted.org/packages/64/70/ec0aa5062a6418eeb4c0ff9376a774fea93b3c485b91bd84ba3382950e02/reliq-0.0.44-cp310-cp310-macosx_14_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d4095be29f7179cef9297991fdf69d1bcca933a2d95bd6439927ad9b8d50a3eb",
                "md5": "7f789094e26c1c1fa4e4b147d4145fd4",
                "sha256": "34007a0f8650d9f83f074be1fdaafe71babb9de4535ba654784de0589a058df6"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp310-cp310-macosx_15_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "7f789094e26c1c1fa4e4b147d4145fd4",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.7",
            "size": 115909,
            "upload_time": "2025-08-16T11:22:33",
            "upload_time_iso_8601": "2025-08-16T11:22:33.137846Z",
            "url": "https://files.pythonhosted.org/packages/d4/09/5be29f7179cef9297991fdf69d1bcca933a2d95bd6439927ad9b8d50a3eb/reliq-0.0.44-cp310-cp310-macosx_15_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d364190ff684ca5672a9b31bbe6dbd9ae0638186032f5ea1be2d1cd8e8e7b328",
                "md5": "f721b06ec81bae6cc7dd09a27b14d4a5",
                "sha256": "1422d83e7157ac037156026cd22afe4834ef283689b2c3764cb4b44b920d0980"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp310-cp310-manylinux2014_aarch64.whl",
            "has_sig": false,
            "md5_digest": "f721b06ec81bae6cc7dd09a27b14d4a5",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.7",
            "size": 147215,
            "upload_time": "2025-08-16T11:22:34",
            "upload_time_iso_8601": "2025-08-16T11:22:34.752784Z",
            "url": "https://files.pythonhosted.org/packages/d3/64/190ff684ca5672a9b31bbe6dbd9ae0638186032f5ea1be2d1cd8e8e7b328/reliq-0.0.44-cp310-cp310-manylinux2014_aarch64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "f0958901ce70f33217a83389dd1bdb28a7a212d3d52c82ea4a8429232d766bea",
                "md5": "7fbc82d29602f0d6afada73862402d0e",
                "sha256": "161ff4d02259775e0804067613dc1fd2b38b2ab12563e6b20cbfbb4e845af4e4"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp310-cp310-manylinux2014_armv7l.whl",
            "has_sig": false,
            "md5_digest": "7fbc82d29602f0d6afada73862402d0e",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.7",
            "size": 120601,
            "upload_time": "2025-08-16T11:22:36",
            "upload_time_iso_8601": "2025-08-16T11:22:36.033036Z",
            "url": "https://files.pythonhosted.org/packages/f0/95/8901ce70f33217a83389dd1bdb28a7a212d3d52c82ea4a8429232d766bea/reliq-0.0.44-cp310-cp310-manylinux2014_armv7l.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "461ab69c49df071b4edf614b964891d3096252780f064900b38bfe7abb7b4906",
                "md5": "bdd4c5b5e18aebae35bc82ad711726b1",
                "sha256": "2497148087cfcfcecfee41c7e937c671e6ed2014ea0d498426d8637c2d9d4c30"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp310-cp310-manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "bdd4c5b5e18aebae35bc82ad711726b1",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.7",
            "size": 151267,
            "upload_time": "2025-08-16T11:22:37",
            "upload_time_iso_8601": "2025-08-16T11:22:37.794938Z",
            "url": "https://files.pythonhosted.org/packages/46/1a/b69c49df071b4edf614b964891d3096252780f064900b38bfe7abb7b4906/reliq-0.0.44-cp310-cp310-manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "8f94d8122f58faf046e77089bf651d27610abd16c2d8361b0dbd88df279b445e",
                "md5": "a6d9e45e3952d8245fa71b04cc30c2e4",
                "sha256": "30ee6594f330e45530e4d82f20de883b77f5d0e2fc67745e1da4f1a1bdb79a61"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp310-cp310-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "a6d9e45e3952d8245fa71b04cc30c2e4",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.7",
            "size": 181379,
            "upload_time": "2025-08-16T11:22:39",
            "upload_time_iso_8601": "2025-08-16T11:22:39.551570Z",
            "url": "https://files.pythonhosted.org/packages/8f/94/d8122f58faf046e77089bf651d27610abd16c2d8361b0dbd88df279b445e/reliq-0.0.44-cp310-cp310-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "3c174348d8f2e52b0ad4601e6058d29091af05c0c79faa44a0b10fe6f2e27238",
                "md5": "106a809d0e4baca95c5ec5300355dbe0",
                "sha256": "e68d70227ae9417637ccf47d654fa5377bb2f65b631621c827a77c022cbe1ec8"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp311-cp311-macosx_13_0_x86_64.whl",
            "has_sig": false,
            "md5_digest": "106a809d0e4baca95c5ec5300355dbe0",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.7",
            "size": 120847,
            "upload_time": "2025-08-16T11:22:41",
            "upload_time_iso_8601": "2025-08-16T11:22:41.624882Z",
            "url": "https://files.pythonhosted.org/packages/3c/17/4348d8f2e52b0ad4601e6058d29091af05c0c79faa44a0b10fe6f2e27238/reliq-0.0.44-cp311-cp311-macosx_13_0_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "8db93938008a20f8cc9a2df3b0d5aec4e660f09d1e9156ac7abb934ff23598e8",
                "md5": "855618fae70b0d52fe2eebaade6f3fc4",
                "sha256": "7b3a95bce1434a243ce90b5ccab0d482efd26f2a600ea26bdd5ed4b5c10b44f2"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp311-cp311-macosx_14_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "855618fae70b0d52fe2eebaade6f3fc4",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.7",
            "size": 115313,
            "upload_time": "2025-08-16T11:22:42",
            "upload_time_iso_8601": "2025-08-16T11:22:42.936231Z",
            "url": "https://files.pythonhosted.org/packages/8d/b9/3938008a20f8cc9a2df3b0d5aec4e660f09d1e9156ac7abb934ff23598e8/reliq-0.0.44-cp311-cp311-macosx_14_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "996a2e943f63854b34d4a796742be511a7486bdfe8ccb6853966254f33fb670b",
                "md5": "d0a6c761d50c07384bafd31973df9220",
                "sha256": "383e7cbe45fdbee93d583b50645174985388141bba3fae70cd4679d9500dfc3a"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp311-cp311-macosx_15_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "d0a6c761d50c07384bafd31973df9220",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.7",
            "size": 115911,
            "upload_time": "2025-08-16T11:22:44",
            "upload_time_iso_8601": "2025-08-16T11:22:44.951058Z",
            "url": "https://files.pythonhosted.org/packages/99/6a/2e943f63854b34d4a796742be511a7486bdfe8ccb6853966254f33fb670b/reliq-0.0.44-cp311-cp311-macosx_15_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "dd9fe65a76489a303bdd87b050fceecebd3849dcff5fef72ab72061220bdb069",
                "md5": "1ee1890aac46de6cc5e92a9bbf7a5030",
                "sha256": "c112c77c1328715c3310209434a6f18789e1c1d09b45324f8a26fd3aa569b6ac"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp311-cp311-manylinux2014_armv7l.whl",
            "has_sig": false,
            "md5_digest": "1ee1890aac46de6cc5e92a9bbf7a5030",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.7",
            "size": 120600,
            "upload_time": "2025-08-16T11:22:46",
            "upload_time_iso_8601": "2025-08-16T11:22:46.197152Z",
            "url": "https://files.pythonhosted.org/packages/dd/9f/e65a76489a303bdd87b050fceecebd3849dcff5fef72ab72061220bdb069/reliq-0.0.44-cp311-cp311-manylinux2014_armv7l.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "4857e00948053134ef3633d79ffe9ce08d89edcd070835aaa8f53d6f4040e26a",
                "md5": "64b42d4de9a6102b298184cb963c52cd",
                "sha256": "f8d80a5aff52e2329e4a4230b62864a6a55dd9551e98b517fda34c8876296e79"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp311-cp311-manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "64b42d4de9a6102b298184cb963c52cd",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.7",
            "size": 151268,
            "upload_time": "2025-08-16T11:22:48",
            "upload_time_iso_8601": "2025-08-16T11:22:48.002887Z",
            "url": "https://files.pythonhosted.org/packages/48/57/e00948053134ef3633d79ffe9ce08d89edcd070835aaa8f53d6f4040e26a/reliq-0.0.44-cp311-cp311-manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "fc6bb7895247372eb38e7f7803fbd08f760cb33745a610d620d94992c9f5acaa",
                "md5": "8389c0040d9e76fe3fcb31869e05a68d",
                "sha256": "cd255df3242fa8f5d9ff319b5cd83fab40b190b412b839fba670553031c15686"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp311-cp311-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "8389c0040d9e76fe3fcb31869e05a68d",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.7",
            "size": 181380,
            "upload_time": "2025-08-16T11:22:49",
            "upload_time_iso_8601": "2025-08-16T11:22:49.568907Z",
            "url": "https://files.pythonhosted.org/packages/fc/6b/b7895247372eb38e7f7803fbd08f760cb33745a610d620d94992c9f5acaa/reliq-0.0.44-cp311-cp311-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "5cf4364f811291ae2b08b36285b92d91dc23c750d58cde0738c6c308b3938599",
                "md5": "40e49283f5851a5172c4941efe89c8ac",
                "sha256": "d79d0222b34b6378f029d0525e0af7161e4cade2a98daf39096b1a33fbb4c058"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp312-cp312-macosx_13_0_x86_64.whl",
            "has_sig": false,
            "md5_digest": "40e49283f5851a5172c4941efe89c8ac",
            "packagetype": "bdist_wheel",
            "python_version": "cp312",
            "requires_python": ">=3.7",
            "size": 120848,
            "upload_time": "2025-08-16T11:22:50",
            "upload_time_iso_8601": "2025-08-16T11:22:50.976928Z",
            "url": "https://files.pythonhosted.org/packages/5c/f4/364f811291ae2b08b36285b92d91dc23c750d58cde0738c6c308b3938599/reliq-0.0.44-cp312-cp312-macosx_13_0_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e7541f1ebed9615554ccdde83d274096c0acc20a7fa496af015aebdd9ded0ea9",
                "md5": "46b65176b8ffd86fb6c8966bb11eb792",
                "sha256": "9ad7a2463107c079d2fee14f9b27a489a5f5f5861322a962aa7cd0977f5b4418"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp312-cp312-macosx_14_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "46b65176b8ffd86fb6c8966bb11eb792",
            "packagetype": "bdist_wheel",
            "python_version": "cp312",
            "requires_python": ">=3.7",
            "size": 115313,
            "upload_time": "2025-08-16T11:22:52",
            "upload_time_iso_8601": "2025-08-16T11:22:52.616726Z",
            "url": "https://files.pythonhosted.org/packages/e7/54/1f1ebed9615554ccdde83d274096c0acc20a7fa496af015aebdd9ded0ea9/reliq-0.0.44-cp312-cp312-macosx_14_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "7abd9b0b588f357ef15ba3b6923f61e789d709b96eb318a4bf10bb0b308a143d",
                "md5": "9fefb0ff2dca80590f28ce52e3641466",
                "sha256": "9c71885ce2a18b1bfa795a18474b2279ef974c7e45c3d101a81d1f97b21de39a"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp312-cp312-macosx_15_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "9fefb0ff2dca80590f28ce52e3641466",
            "packagetype": "bdist_wheel",
            "python_version": "cp312",
            "requires_python": ">=3.7",
            "size": 115911,
            "upload_time": "2025-08-16T11:22:54",
            "upload_time_iso_8601": "2025-08-16T11:22:54.184188Z",
            "url": "https://files.pythonhosted.org/packages/7a/bd/9b0b588f357ef15ba3b6923f61e789d709b96eb318a4bf10bb0b308a143d/reliq-0.0.44-cp312-cp312-macosx_15_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "856e87bb65c5d2a35c1162e269bdffae4380113d1fe8610a8ffc53e612a9e576",
                "md5": "0f7854e65056fbd5785b716a6cb57eca",
                "sha256": "cf230b7a4c21307892e947e4a92399082321fa1f539240602bfce211b807d9b6"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp312-cp312-manylinux2014_aarch64.whl",
            "has_sig": false,
            "md5_digest": "0f7854e65056fbd5785b716a6cb57eca",
            "packagetype": "bdist_wheel",
            "python_version": "cp312",
            "requires_python": ">=3.7",
            "size": 147214,
            "upload_time": "2025-08-16T11:22:55",
            "upload_time_iso_8601": "2025-08-16T11:22:55.810454Z",
            "url": "https://files.pythonhosted.org/packages/85/6e/87bb65c5d2a35c1162e269bdffae4380113d1fe8610a8ffc53e612a9e576/reliq-0.0.44-cp312-cp312-manylinux2014_aarch64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "6e43c7c2e91b53857e74110424078008d421d3c0b057cca12c22ebea6e58d835",
                "md5": "108e1ac2b4346d4f16001b5e09e0bfb5",
                "sha256": "5792dc378d65cbf36abab21783288c5a7548b594fd819b56277c1ec0dccb18aa"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp312-cp312-manylinux2014_armv7l.whl",
            "has_sig": false,
            "md5_digest": "108e1ac2b4346d4f16001b5e09e0bfb5",
            "packagetype": "bdist_wheel",
            "python_version": "cp312",
            "requires_python": ">=3.7",
            "size": 120601,
            "upload_time": "2025-08-16T11:22:57",
            "upload_time_iso_8601": "2025-08-16T11:22:57.438718Z",
            "url": "https://files.pythonhosted.org/packages/6e/43/c7c2e91b53857e74110424078008d421d3c0b057cca12c22ebea6e58d835/reliq-0.0.44-cp312-cp312-manylinux2014_armv7l.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "cfc430d525f7eee6e9f01ff99f157a356feff6d58294e5dc45a07985fcae4a8a",
                "md5": "4ea4e692978e5eabdc770ab459b7de32",
                "sha256": "0a52e4498b36629d1df15343e549e5fd8cb7f68c63fddd36ab9f71422267e1a7"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp312-cp312-manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "4ea4e692978e5eabdc770ab459b7de32",
            "packagetype": "bdist_wheel",
            "python_version": "cp312",
            "requires_python": ">=3.7",
            "size": 151267,
            "upload_time": "2025-08-16T11:22:58",
            "upload_time_iso_8601": "2025-08-16T11:22:58.967834Z",
            "url": "https://files.pythonhosted.org/packages/cf/c4/30d525f7eee6e9f01ff99f157a356feff6d58294e5dc45a07985fcae4a8a/reliq-0.0.44-cp312-cp312-manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "f1a20275e5eab27dfbbedb04ef15a80c841522df803909048f05d7b1f9ed4938",
                "md5": "edae6944c410580ac6ac769546031ce8",
                "sha256": "2aee5002a6f85e58265ac5f4c84244e12b1693cd0acbb8299e7f11ed0f4e2a7a"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp312-cp312-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "edae6944c410580ac6ac769546031ce8",
            "packagetype": "bdist_wheel",
            "python_version": "cp312",
            "requires_python": ">=3.7",
            "size": 181378,
            "upload_time": "2025-08-16T11:23:00",
            "upload_time_iso_8601": "2025-08-16T11:23:00.200296Z",
            "url": "https://files.pythonhosted.org/packages/f1/a2/0275e5eab27dfbbedb04ef15a80c841522df803909048f05d7b1f9ed4938/reliq-0.0.44-cp312-cp312-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "0c88cb98e6bae52863adcf66223b87dd15d14fa09a4e070513e01134f4151557",
                "md5": "f29bf987ebe8691d1474d2f74c9d63f8",
                "sha256": "7bcab09d06ab393f0d2c9af44159a5291939d5f70260a6b23a9e351bf14b26d3"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp313-cp313-macosx_13_0_x86_64.whl",
            "has_sig": false,
            "md5_digest": "f29bf987ebe8691d1474d2f74c9d63f8",
            "packagetype": "bdist_wheel",
            "python_version": "cp313",
            "requires_python": ">=3.7",
            "size": 120846,
            "upload_time": "2025-08-16T11:23:02",
            "upload_time_iso_8601": "2025-08-16T11:23:02.365038Z",
            "url": "https://files.pythonhosted.org/packages/0c/88/cb98e6bae52863adcf66223b87dd15d14fa09a4e070513e01134f4151557/reliq-0.0.44-cp313-cp313-macosx_13_0_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e52a9f9048c21591edbcc6af65aadf34e50a7b0790d7762bcc291679586c0b39",
                "md5": "07f64d0a9d49493213f28cdb5aeb1b15",
                "sha256": "248e198c714c5808b7a8b4c788d33c2b4d87137596d870411579167254a77d2c"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp313-cp313-macosx_14_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "07f64d0a9d49493213f28cdb5aeb1b15",
            "packagetype": "bdist_wheel",
            "python_version": "cp313",
            "requires_python": ">=3.7",
            "size": 115312,
            "upload_time": "2025-08-16T11:23:03",
            "upload_time_iso_8601": "2025-08-16T11:23:03.975147Z",
            "url": "https://files.pythonhosted.org/packages/e5/2a/9f9048c21591edbcc6af65aadf34e50a7b0790d7762bcc291679586c0b39/reliq-0.0.44-cp313-cp313-macosx_14_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "b513d93c505040e77746b13ad5879423b93228ac519ce729ed66d1c0a2315ef6",
                "md5": "2a8d220c02ba2c59f5792e2946c153fe",
                "sha256": "5d2ff003aa6d65c60b6320f834c4929a6da6ca5855395b81a09d263a916bf45d"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp313-cp313-macosx_15_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "2a8d220c02ba2c59f5792e2946c153fe",
            "packagetype": "bdist_wheel",
            "python_version": "cp313",
            "requires_python": ">=3.7",
            "size": 115911,
            "upload_time": "2025-08-16T11:23:05",
            "upload_time_iso_8601": "2025-08-16T11:23:05.583453Z",
            "url": "https://files.pythonhosted.org/packages/b5/13/d93c505040e77746b13ad5879423b93228ac519ce729ed66d1c0a2315ef6/reliq-0.0.44-cp313-cp313-macosx_15_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "9115791a2320013238d84f29fdb3fbce922a5f41cd57409c222db609ea091de1",
                "md5": "52d9919f73f11f69d72772ce59600125",
                "sha256": "c561cd87f4cdc017a6746a1e671e1f0f8a3e748b04397148dcc70b10826ed2ba"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp313-cp313-manylinux2014_aarch64.whl",
            "has_sig": false,
            "md5_digest": "52d9919f73f11f69d72772ce59600125",
            "packagetype": "bdist_wheel",
            "python_version": "cp313",
            "requires_python": ">=3.7",
            "size": 147214,
            "upload_time": "2025-08-16T11:23:07",
            "upload_time_iso_8601": "2025-08-16T11:23:07.848719Z",
            "url": "https://files.pythonhosted.org/packages/91/15/791a2320013238d84f29fdb3fbce922a5f41cd57409c222db609ea091de1/reliq-0.0.44-cp313-cp313-manylinux2014_aarch64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e93800a060c190e18e9a489590ffb2e04922e98ee4f59416dea63a9376de0640",
                "md5": "9098a11f8ddb9bba680d28835949f105",
                "sha256": "78d54af68777ae668b94c52790bd6332f340133482d25753d2e781a2166f7036"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp313-cp313-manylinux2014_armv7l.whl",
            "has_sig": false,
            "md5_digest": "9098a11f8ddb9bba680d28835949f105",
            "packagetype": "bdist_wheel",
            "python_version": "cp313",
            "requires_python": ">=3.7",
            "size": 120601,
            "upload_time": "2025-08-16T11:23:09",
            "upload_time_iso_8601": "2025-08-16T11:23:09.056512Z",
            "url": "https://files.pythonhosted.org/packages/e9/38/00a060c190e18e9a489590ffb2e04922e98ee4f59416dea63a9376de0640/reliq-0.0.44-cp313-cp313-manylinux2014_armv7l.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "db34c6b69a28418ed1aa065406312feca81b7cc6ee41e9677e4bcb1cfd05f59d",
                "md5": "ace42d931000992bef60a7003d95dc01",
                "sha256": "620e514b956f1a60a147436dc5099cb60317ae23f563d1a4f87295934c6cbf21"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp313-cp313-manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "ace42d931000992bef60a7003d95dc01",
            "packagetype": "bdist_wheel",
            "python_version": "cp313",
            "requires_python": ">=3.7",
            "size": 151267,
            "upload_time": "2025-08-16T11:23:10",
            "upload_time_iso_8601": "2025-08-16T11:23:10.428668Z",
            "url": "https://files.pythonhosted.org/packages/db/34/c6b69a28418ed1aa065406312feca81b7cc6ee41e9677e4bcb1cfd05f59d/reliq-0.0.44-cp313-cp313-manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "47cf386804848f8be51648a836fed7ae217744ae4e418c77bf2d89f7d4280e80",
                "md5": "939604b5aebe48cea65cb3beb5f91611",
                "sha256": "218a4dd00f3caa1dd76d831bfc2ffe6fc1b7433e72e981b70a7c56a5954d56d8"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp313-cp313-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "939604b5aebe48cea65cb3beb5f91611",
            "packagetype": "bdist_wheel",
            "python_version": "cp313",
            "requires_python": ">=3.7",
            "size": 181379,
            "upload_time": "2025-08-16T11:23:12",
            "upload_time_iso_8601": "2025-08-16T11:23:12.065487Z",
            "url": "https://files.pythonhosted.org/packages/47/cf/386804848f8be51648a836fed7ae217744ae4e418c77bf2d89f7d4280e80/reliq-0.0.44-cp313-cp313-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "f3113e731109c5ac3dafb5f9520c58f0a5f87a040a3ceaaaa2a102508eb71e5b",
                "md5": "988a2a2b666617fd47b2d7c1a12fe080",
                "sha256": "abfc82721a1da91c6810ff30175ca82a455f2c6aada431fc21b2041ff78f253c"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp37-cp37-macosx_13_0_x86_64.whl",
            "has_sig": false,
            "md5_digest": "988a2a2b666617fd47b2d7c1a12fe080",
            "packagetype": "bdist_wheel",
            "python_version": "cp37",
            "requires_python": ">=3.7",
            "size": 120848,
            "upload_time": "2025-08-16T11:23:13",
            "upload_time_iso_8601": "2025-08-16T11:23:13.624058Z",
            "url": "https://files.pythonhosted.org/packages/f3/11/3e731109c5ac3dafb5f9520c58f0a5f87a040a3ceaaaa2a102508eb71e5b/reliq-0.0.44-cp37-cp37-macosx_13_0_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "b3afc370d547cf48cb5e40be47ffc4035fcece02908f49133711f98fb344f829",
                "md5": "9cd5d86ff0e47956e0f5c7efe928c243",
                "sha256": "df5dcb98dee60448fc73c8ee222537c9a4212f8ce12cd6de01223bcdd1bbb6a4"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp37-cp37-macosx_14_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "9cd5d86ff0e47956e0f5c7efe928c243",
            "packagetype": "bdist_wheel",
            "python_version": "cp37",
            "requires_python": ">=3.7",
            "size": 115311,
            "upload_time": "2025-08-16T11:23:14",
            "upload_time_iso_8601": "2025-08-16T11:23:14.822936Z",
            "url": "https://files.pythonhosted.org/packages/b3/af/c370d547cf48cb5e40be47ffc4035fcece02908f49133711f98fb344f829/reliq-0.0.44-cp37-cp37-macosx_14_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "77dd3ad233c83d14f69b6f0074ac226d513dc94002e881cbb6e65a799924e5a9",
                "md5": "a7df58d0c3ae78a2911af85d9b4a1f6f",
                "sha256": "a47e9cd539231a6ea0085406f334490cdd640e665e7a714aa4d5dbfbb566c33f"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp37-cp37-macosx_15_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "a7df58d0c3ae78a2911af85d9b4a1f6f",
            "packagetype": "bdist_wheel",
            "python_version": "cp37",
            "requires_python": ">=3.7",
            "size": 115909,
            "upload_time": "2025-08-16T11:23:15",
            "upload_time_iso_8601": "2025-08-16T11:23:15.999662Z",
            "url": "https://files.pythonhosted.org/packages/77/dd/3ad233c83d14f69b6f0074ac226d513dc94002e881cbb6e65a799924e5a9/reliq-0.0.44-cp37-cp37-macosx_15_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "b1e09d7509f2eaa808842ddbba6fd3e422168039bc90d08dc099be4d00e71ee6",
                "md5": "3a4eea719894ad2f0dd8535da1bec1f9",
                "sha256": "84964de2909b3964f6a368f22e439f96b5082ae48fc0d4b7f684c5630296ea00"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp37-cp37-manylinux2014_aarch64.whl",
            "has_sig": false,
            "md5_digest": "3a4eea719894ad2f0dd8535da1bec1f9",
            "packagetype": "bdist_wheel",
            "python_version": "cp37",
            "requires_python": ">=3.7",
            "size": 147216,
            "upload_time": "2025-08-16T11:23:17",
            "upload_time_iso_8601": "2025-08-16T11:23:17.375016Z",
            "url": "https://files.pythonhosted.org/packages/b1/e0/9d7509f2eaa808842ddbba6fd3e422168039bc90d08dc099be4d00e71ee6/reliq-0.0.44-cp37-cp37-manylinux2014_aarch64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d8f93fd89c88fa9948cf227cd8921dc4a64bf0cf4db8045458fddc34891fe9a3",
                "md5": "9e5f7dcc06ac3da57cfb95baf3ec19a2",
                "sha256": "83241c6bb4653d5aeaddf3e347c0ce1f718e4321e2ef78ec06181f4780f55e1a"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp37-cp37-manylinux2014_armv7l.whl",
            "has_sig": false,
            "md5_digest": "9e5f7dcc06ac3da57cfb95baf3ec19a2",
            "packagetype": "bdist_wheel",
            "python_version": "cp37",
            "requires_python": ">=3.7",
            "size": 120600,
            "upload_time": "2025-08-16T11:23:19",
            "upload_time_iso_8601": "2025-08-16T11:23:19.057948Z",
            "url": "https://files.pythonhosted.org/packages/d8/f9/3fd89c88fa9948cf227cd8921dc4a64bf0cf4db8045458fddc34891fe9a3/reliq-0.0.44-cp37-cp37-manylinux2014_armv7l.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "17a0e5f120801a834fdeee4149d39133d35a0ff0b1acee82589bdf44e201a885",
                "md5": "d6fcae684eb8ab596e9c15bc8312f445",
                "sha256": "2a553162b8b6a7cf4c2258479a0cd52f499bbb09e06a4c287e08f5ad9d6d7d9a"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp37-cp37-manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "d6fcae684eb8ab596e9c15bc8312f445",
            "packagetype": "bdist_wheel",
            "python_version": "cp37",
            "requires_python": ">=3.7",
            "size": 151267,
            "upload_time": "2025-08-16T11:23:20",
            "upload_time_iso_8601": "2025-08-16T11:23:20.548302Z",
            "url": "https://files.pythonhosted.org/packages/17/a0/e5f120801a834fdeee4149d39133d35a0ff0b1acee82589bdf44e201a885/reliq-0.0.44-cp37-cp37-manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "97c4404e92518d14bc7fdcbcb6363055142b0a8a465b1898be0501accc06b30d",
                "md5": "e880f018455551a5b9bd3026952ed3c7",
                "sha256": "ffd810bcb356133ca3b662cc35721d619737e825b0df350a347bea0e9e159bf6"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp37-cp37-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "e880f018455551a5b9bd3026952ed3c7",
            "packagetype": "bdist_wheel",
            "python_version": "cp37",
            "requires_python": ">=3.7",
            "size": 181377,
            "upload_time": "2025-08-16T11:23:21",
            "upload_time_iso_8601": "2025-08-16T11:23:21.912779Z",
            "url": "https://files.pythonhosted.org/packages/97/c4/404e92518d14bc7fdcbcb6363055142b0a8a465b1898be0501accc06b30d/reliq-0.0.44-cp37-cp37-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "4b1afbe4efd4cc4412060c9dcc306cdf9f630d9853ecf982e3e5f5ae41352e36",
                "md5": "13e9f71110c80d75eca6a2388557bdd1",
                "sha256": "b01ed3c398fb27b5d343242005d83bf07db3432505fedca924c4065a5c6c2d4f"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp38-cp38-macosx_13_0_x86_64.whl",
            "has_sig": false,
            "md5_digest": "13e9f71110c80d75eca6a2388557bdd1",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.7",
            "size": 120848,
            "upload_time": "2025-08-16T11:23:23",
            "upload_time_iso_8601": "2025-08-16T11:23:23.655244Z",
            "url": "https://files.pythonhosted.org/packages/4b/1a/fbe4efd4cc4412060c9dcc306cdf9f630d9853ecf982e3e5f5ae41352e36/reliq-0.0.44-cp38-cp38-macosx_13_0_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "b0b07e14566bea4bbe8cc853b951820d784931b4d6a77073435ac9257d8e8976",
                "md5": "2f1e2eb471f139299d4a9bd2c8990563",
                "sha256": "9dd8b60b531e3f8b73f9be92dce4551183c9f5cbb6239c9b89ae969bc7db3182"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp38-cp38-macosx_14_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "2f1e2eb471f139299d4a9bd2c8990563",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.7",
            "size": 115310,
            "upload_time": "2025-08-16T11:23:24",
            "upload_time_iso_8601": "2025-08-16T11:23:24.832245Z",
            "url": "https://files.pythonhosted.org/packages/b0/b0/7e14566bea4bbe8cc853b951820d784931b4d6a77073435ac9257d8e8976/reliq-0.0.44-cp38-cp38-macosx_14_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "440d605acb3a18fce3fa1de3cd4dd229e29b8b3fb5e631c24fe2244d445eff43",
                "md5": "77d7f9d4ff9bc9f315708f7fd6baa89f",
                "sha256": "770a1a880146e49120824c5fe28ecd53eb35d5e4e3f023e7e873ad3eb32c451d"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp38-cp38-macosx_15_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "77d7f9d4ff9bc9f315708f7fd6baa89f",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.7",
            "size": 115909,
            "upload_time": "2025-08-16T11:23:26",
            "upload_time_iso_8601": "2025-08-16T11:23:26.183647Z",
            "url": "https://files.pythonhosted.org/packages/44/0d/605acb3a18fce3fa1de3cd4dd229e29b8b3fb5e631c24fe2244d445eff43/reliq-0.0.44-cp38-cp38-macosx_15_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d0375a625be4d050b0159c706761406dbebe6d95ca37c2e113e915bf66a3ff1e",
                "md5": "dc3b10eb6f9d2d792c2613164d0ce9fe",
                "sha256": "71bcfa18523e918943b202fd813205978a2aa20c14cc7bc0dd3fc3f42f399e0c"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp38-cp38-manylinux2014_aarch64.whl",
            "has_sig": false,
            "md5_digest": "dc3b10eb6f9d2d792c2613164d0ce9fe",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.7",
            "size": 147216,
            "upload_time": "2025-08-16T11:23:27",
            "upload_time_iso_8601": "2025-08-16T11:23:27.344040Z",
            "url": "https://files.pythonhosted.org/packages/d0/37/5a625be4d050b0159c706761406dbebe6d95ca37c2e113e915bf66a3ff1e/reliq-0.0.44-cp38-cp38-manylinux2014_aarch64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "6acdbb5b3896021cb220f498a659651aa77aa487f85e5d55825cfdadb720e21a",
                "md5": "6216559962a0add8e19af62ba4431480",
                "sha256": "464dbd6a83c834740dfe90cd6dd06e0d6263ac46c9124a88dab82bb09d32388a"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp38-cp38-manylinux2014_armv7l.whl",
            "has_sig": false,
            "md5_digest": "6216559962a0add8e19af62ba4431480",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.7",
            "size": 120601,
            "upload_time": "2025-08-16T11:23:28",
            "upload_time_iso_8601": "2025-08-16T11:23:28.524618Z",
            "url": "https://files.pythonhosted.org/packages/6a/cd/bb5b3896021cb220f498a659651aa77aa487f85e5d55825cfdadb720e21a/reliq-0.0.44-cp38-cp38-manylinux2014_armv7l.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "57f47cd108f7bbee0d64f85d42b71a3cb6c259759d0859626e16fc2ccdfb285a",
                "md5": "28748b764a52b6a33489b819e6cae0de",
                "sha256": "a20b9b3ef9b51cb51a8ddb3241627a0dfe4758205ca4282cd739fc7ff2bbbcf5"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp38-cp38-manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "28748b764a52b6a33489b819e6cae0de",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.7",
            "size": 151266,
            "upload_time": "2025-08-16T11:23:29",
            "upload_time_iso_8601": "2025-08-16T11:23:29.731945Z",
            "url": "https://files.pythonhosted.org/packages/57/f4/7cd108f7bbee0d64f85d42b71a3cb6c259759d0859626e16fc2ccdfb285a/reliq-0.0.44-cp38-cp38-manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "92d66fe58b1041db927c7395a7f5c348a7fb53966470812a037b13e0d5373b75",
                "md5": "d7a22fbdd4ca6d78acc121890f168572",
                "sha256": "8cd3cf1589fb10f67a3ddc855d2e463024d8e2ce812e2231a708f685f36f40d3"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp38-cp38-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "d7a22fbdd4ca6d78acc121890f168572",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.7",
            "size": 181376,
            "upload_time": "2025-08-16T11:23:31",
            "upload_time_iso_8601": "2025-08-16T11:23:31.967726Z",
            "url": "https://files.pythonhosted.org/packages/92/d6/6fe58b1041db927c7395a7f5c348a7fb53966470812a037b13e0d5373b75/reliq-0.0.44-cp38-cp38-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "7531bd34dcb258d6877b5f6cc10d1c1f50134479dfad394677d295702aed78da",
                "md5": "845ad05511901b51718228b45c0eb528",
                "sha256": "08117fe946b30ffd8f30c5482ae6333c8453cf0e59a0ec0e6b920f6581218916"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp39-cp39-macosx_13_0_x86_64.whl",
            "has_sig": false,
            "md5_digest": "845ad05511901b51718228b45c0eb528",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.7",
            "size": 120845,
            "upload_time": "2025-08-16T11:23:33",
            "upload_time_iso_8601": "2025-08-16T11:23:33.658060Z",
            "url": "https://files.pythonhosted.org/packages/75/31/bd34dcb258d6877b5f6cc10d1c1f50134479dfad394677d295702aed78da/reliq-0.0.44-cp39-cp39-macosx_13_0_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "8d420c65928aff3931641d04257691813a393a48e0f253ffcf57377af9315b2d",
                "md5": "c7c332933b6480ede4fbda88f051840f",
                "sha256": "7f2d05b21633512a28133aa6b34efa7e5c1a155d27f0de8c50bf18042b33a108"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp39-cp39-macosx_14_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "c7c332933b6480ede4fbda88f051840f",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.7",
            "size": 115311,
            "upload_time": "2025-08-16T11:23:34",
            "upload_time_iso_8601": "2025-08-16T11:23:34.825949Z",
            "url": "https://files.pythonhosted.org/packages/8d/42/0c65928aff3931641d04257691813a393a48e0f253ffcf57377af9315b2d/reliq-0.0.44-cp39-cp39-macosx_14_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "29456236bbd068b8bea1c988e85734986fbac6e4a1141d46e197f8698a54f7ea",
                "md5": "a448014dce2d9112ad2b234c20e3ca4a",
                "sha256": "a79ef8930eb367e45ec0f2ccf498e8e7f8205351b72bfe541a10fc536bef00a1"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp39-cp39-macosx_15_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "a448014dce2d9112ad2b234c20e3ca4a",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.7",
            "size": 115909,
            "upload_time": "2025-08-16T11:23:36",
            "upload_time_iso_8601": "2025-08-16T11:23:36.445646Z",
            "url": "https://files.pythonhosted.org/packages/29/45/6236bbd068b8bea1c988e85734986fbac6e4a1141d46e197f8698a54f7ea/reliq-0.0.44-cp39-cp39-macosx_15_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "20cb0227ba7439dd515bf55b076695fd0d686f92189b0a37fa2f354d22013e1f",
                "md5": "7d75f9f827db54fc55e57b4e8613821e",
                "sha256": "c85c9a052d97e50f09e3f1c70722792126671d162fccc8781906b9e73ac7b479"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp39-cp39-manylinux2014_aarch64.whl",
            "has_sig": false,
            "md5_digest": "7d75f9f827db54fc55e57b4e8613821e",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.7",
            "size": 147216,
            "upload_time": "2025-08-16T11:23:37",
            "upload_time_iso_8601": "2025-08-16T11:23:37.618317Z",
            "url": "https://files.pythonhosted.org/packages/20/cb/0227ba7439dd515bf55b076695fd0d686f92189b0a37fa2f354d22013e1f/reliq-0.0.44-cp39-cp39-manylinux2014_aarch64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "6aeec700ea0704c87f0ec6dc07552ec06cb80414068cd101c4dc48bdaeadcff1",
                "md5": "5d87f2b253f906b13399f351ebde331a",
                "sha256": "ae5da04908142e1b77e004a9c97802196d6f81e6f4985ce31b4e99a61baa8894"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp39-cp39-manylinux2014_armv7l.whl",
            "has_sig": false,
            "md5_digest": "5d87f2b253f906b13399f351ebde331a",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.7",
            "size": 120600,
            "upload_time": "2025-08-16T11:23:38",
            "upload_time_iso_8601": "2025-08-16T11:23:38.880397Z",
            "url": "https://files.pythonhosted.org/packages/6a/ee/c700ea0704c87f0ec6dc07552ec06cb80414068cd101c4dc48bdaeadcff1/reliq-0.0.44-cp39-cp39-manylinux2014_armv7l.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "83f5e8baac6ec17272fd6a16c991f03f104ed009022ba7b272ff8678f315da20",
                "md5": "b56b1526ef0ba0587fe6aed4b5d6bbbe",
                "sha256": "8ec61e041cba56eca626361a667f8f88e5df73509fb19822c5da778cfb701705"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp39-cp39-manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "b56b1526ef0ba0587fe6aed4b5d6bbbe",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.7",
            "size": 151267,
            "upload_time": "2025-08-16T11:23:40",
            "upload_time_iso_8601": "2025-08-16T11:23:40.499011Z",
            "url": "https://files.pythonhosted.org/packages/83/f5/e8baac6ec17272fd6a16c991f03f104ed009022ba7b272ff8678f315da20/reliq-0.0.44-cp39-cp39-manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "cd1d2f3909c7ee7c4c4a10e7358abc2a5329e75b55be40204fd1a55cfcc53fc4",
                "md5": "8423d1c85be10a4068af0517e9f5a111",
                "sha256": "96712e21f80a636e6f6a6b0160a16d9cc5dd8d61d8dbeed6c4f58a2dc1cb187b"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44-cp39-cp39-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "8423d1c85be10a4068af0517e9f5a111",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.7",
            "size": 181377,
            "upload_time": "2025-08-16T11:23:41",
            "upload_time_iso_8601": "2025-08-16T11:23:41.711876Z",
            "url": "https://files.pythonhosted.org/packages/cd/1d/2f3909c7ee7c4c4a10e7358abc2a5329e75b55be40204fd1a55cfcc53fc4/reliq-0.0.44-cp39-cp39-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "9fd5261cae39778cea2a106383b13898b765e4050cf3d2467714d7ea33292462",
                "md5": "a1f535f91c5647211b4c75d9ef51d782",
                "sha256": "d5fc5ba231c83aae61f00ea4d315592d9783b9fbab1973ba71cd4668b2e66bb8"
            },
            "downloads": -1,
            "filename": "reliq-0.0.44.tar.gz",
            "has_sig": false,
            "md5_digest": "a1f535f91c5647211b4c75d9ef51d782",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 2668523,
            "upload_time": "2025-08-16T11:23:43",
            "upload_time_iso_8601": "2025-08-16T11:23:43.915634Z",
            "url": "https://files.pythonhosted.org/packages/9f/d5/261cae39778cea2a106383b13898b765e4050cf3d2467714d7ea33292462/reliq-0.0.44.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-16 11:23:43",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "TUVIMEN",
    "github_project": "reliq-python",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "reliq"
}
        
Elapsed time: 2.18832s