Name | reliq JSON |
Version |
0.0.44
JSON |
| download |
home_page | None |
Summary | Python ctypes bindings for reliq |
upload_time | 2025-08-16 11:23:43 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.7 |
license | GPLv3 |
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 & < ⃛ Ô')
#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 ` ` 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 & < ⃛ Ô")
# "loop & < ⃛⃛ Ô"
reliq.decode(r"text & < ⃛ Ô",True)
# b'text & < \xe2\x83\x9b\xe2\x83\x9b \xc3\x94'
reliq.decode(r"text & < ⃛ Ô",raw=True)
# b'text & < \xe2\x83\x9b\xe2\x83\x9b \xc3\x94'
reliq.decode('ex t')
# "ex t"
reliq.decode('ex t',no_nbsp=False)
# 'ex\xa0t'
reliq.decode('ex t',True,no_nbsp=False)
# b'ex\xc2\xa0t'
reliq.encode("<p>li & \t 'seq' \n </p>")
# '<p>li &amp; \t 'seq' \n </p>'
reliq.encode("<p>li & \t 'seq' \n </p>",True)
# b'<p>li &amp; \t 'seq' \n </p>'
reliq.encode("<p>li & \t 'seq' \n </p>",raw=True)
# b'<p>li &amp; \t 'seq' \n </p>'
reliq.encode("<p>li & \t 'seq' \n </p>",full=True)
# '<p>li &amp; 	 'seq' 
 </p>'
reliq.encode("<p>li & \t 'seq' \n </p>",True,full=True)
# b'<p>li &amp; 	 'seq' 
 </p>'
```
### 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 & < ⃛ Ô')\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 ` ` 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 & < ⃛ Ô\")\n# \"loop & < \u20db\u20db \u00d4\"\n\nreliq.decode(r\"text & < ⃛ Ô\",True)\n# b'text & < \\xe2\\x83\\x9b\\xe2\\x83\\x9b \\xc3\\x94'\n\nreliq.decode(r\"text & < ⃛ Ô\",raw=True)\n# b'text & < \\xe2\\x83\\x9b\\xe2\\x83\\x9b \\xc3\\x94'\n\nreliq.decode('ex t')\n# \"ex t\"\n\nreliq.decode('ex t',no_nbsp=False)\n# 'ex\\xa0t'\n\nreliq.decode('ex t',True,no_nbsp=False)\n# b'ex\\xc2\\xa0t'\n\nreliq.encode(\"<p>li & \\t 'seq' \\n </p>\")\n# '<p>li &amp; \\t 'seq' \\n </p>'\n\nreliq.encode(\"<p>li & \\t 'seq' \\n </p>\",True)\n# b'<p>li &amp; \\t 'seq' \\n </p>'\n\nreliq.encode(\"<p>li & \\t 'seq' \\n </p>\",raw=True)\n# b'<p>li &amp; \\t 'seq' \\n </p>'\n\nreliq.encode(\"<p>li & \\t 'seq' \\n </p>\",full=True)\n# '<p>li &amp; 	 'seq' 
 </p>'\n\nreliq.encode(\"<p>li & \\t 'seq' \\n </p>\",True,full=True)\n# b'<p>li &amp; 	 'seq' 
 </p>'\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"
}