Metadata-Version: 2.1
Name: web-valueist
Version: 3.0.0
Summary: 
Author: Andreas Galazis
Requires-Python: >=3.12
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Requires-Dist: beautifulsoup4 (>=4.12.3,<5.0.0)
Requires-Dist: requests (>=2.32.3,<3.0.0)
Project-URL: CI, https://github.com/agalazis/web-valueist/actions
Project-URL: Documentation, https://web-valueist.csmonk.com/
Project-URL: Issues, https://github.com/agalazis/web-valueist/issues
Project-URL: Releases, https://github.com/agalazis/web-valueist/releases
Project-URL: Source Code, https://github.com/agalazis/web-valueist
Description-Content-Type: text/markdown

<p align="center">
  <img src="logo.svg" alt="Web Valueist Logo">
</p>

# Web Valueist

[![PyPI version](https://badge.fury.io/py/web-valueist.svg)](https://badge.fury.io/py/web-valueist)
[![Python versions](https://img.shields.io/pypi/pyversions/web-valueist.svg)](https://pypi.org/project/web-valueist/)
[![License](https://img.shields.io/github/license/agalazis/web-valueist.svg)](https://github.com/agalazis/web-valueist/blob/main/LICENSE)
[![GitHub Issues](https://img.shields.io/github/issues/agalazis/web-valueist.svg)](https://github.com/agalazis/web-valueist/issues)
[![CI](https://github.com/agalazis/web-valueist/actions/workflows/pypi-publish.yml/badge.svg)](https://github.com/agalazis/web-valueist/actions/workflows/pypi-publish.yml)
[![Docs](https://github.com/agalazis/web-valueist/actions/workflows/docs-publish.yml/badge.svg)](https://web-valueist.csmonk.com/)

[Documentation Website](https://web-valueist.csmonk.com/)

Fetches a value from the web, compares it with a given value and exits with zero
exit code if the condition is satisfied

## Table of Contents
- [Installation](#installation)
- [Usage](#usage)
  - [Library](#library)
  - [CLI](#cli)
    - [Sample Usage](#sample-usage)
    - [Debugging](#debugging)
    - [JSON Output](#json-output)
    - [Using Quantifiers](#using-quantifiers)
    - [Sample cron job](#sample-cron-job)
- [Development setup from repository](#development-setup-from-repository)

## Installation

You can install `web-valueist` from PyPI using your preferred package manager:

**pip:**
```bash
pip install web-valueist
```

**Poetry:**
```bash
poetry add web-valueist
```

**uv:**
```bash
uv pip install web-valueist
```

**pipenv:**
```bash
pipenv install web-valueist
```

## Usage

### Library

You can import and use `web_valueist` directly in your Python code without relying on the CLI. The `evaluate` function returns a generic `EvaluateResult` dictionary indicating whether the condition was met, along with the extracted and typed parsed values (`list[int | float | str | bool]`). By default, if a value fails to parse it is silently filtered out, but you can enable `strict_parsing=True` to instead raise a `ParserError`.

```python
import web_valueist

result = web_valueist.evaluate(
    url="http://example.com",
    selector="h1",
    parser_name="str",
    operator_name="eq",
    value="Example Domain",
    quantifier="ANY", # Optional, defaults to "ANY"
    strict_parsing=False # Optional, defaults to False. If True, unparsable values raise ParserError.
)

if result["success"]:
    print(f"Match found! Fetched values (typed): {result['values']}")
else:
    print("Condition not met.")
```

### CLI

`web_valueist [-h] [--debug] [--json] [--strict-parsing] url parser_name [quantifier] selector operator_name value`

```text
positional arguments:
  url
  parser_name
  quantifier      Optional: ANY or EVERY (default: ANY)
  selector
  operator_name
  value

options:
  -h, --help         show this help message and exit
  --debug            Show debug logs including found values
  --json             Output input and result as JSON
  --strict-parsing   Raise error if a fetched value cannot be parsed instead of filtering it
```

#### Sample Usage

By default, `web_valueist` is silent and communicates success or failure via the exit code.

Sample success

```bash
python -m web_valueist https://www.ikea.com.cy/en/products/fjallhavre-duvet-warm-240x220-cm/70458057/ int span.price__integer ">" 240
```

( you can also use `gt` instead of `">"`)

Exit Code: `0`

Sample failure

```bash
python -m web_valueist https://www.ikea.com.cy/en/products/fjallhavre-duvet-warm-240x220-cm/70458057/ int span.price__integer "<" 240
```

( you can also use `lt` instead of `"<"`)

Exit Code: `1`

#### Debugging

Use the `--debug` flag to see the values fetched from the web.

```bash
python -m web_valueist https://www.ikea.com.cy/en/products/fjallhavre-duvet-warm-240x220-cm/70458057/ int span.price__integer ">" 240 --debug
```

Output:

```text
DEBUG:web_valueist.lib:Found value ['245']
```

#### JSON Output

Use the `--json` flag to get a structured output.

```bash
python -m web_valueist http://example.com str h1 "eq" "Example Domain" --json
```

Output:
```json
{"args": {"url": "http://example.com", "parser_name": "str", "quantifier": "ANY", "selector": "h1", "operator_name": "eq", "value": "Example Domain"}, "result": {"success": true, "values": ["Example Domain"]}}
```

#### Using Quantifiers

When a selector matches multiple elements, you can use `ANY` or `EVERY`.

- **ANY** (default): At least one selector match needs to satisfy the condition.
- **EVERY**: All selector matches need to satisfy the condition.

Example using `EVERY`:
```bash
python -m web_valueist https://example.com int EVERY .price ">" 100
```

If no quantifier is specified, `ANY` is used by default.

#### Sample cron job

```bash
*/30 * * * * web_valueist "https://www.bazaraki.com/car-motorbikes-boats-and-parts/cars-trucks-and-vans/mazda/mazda-mx5/year_min---71/?ordering=cheapest&lat=35.01804869361969&lng=34.04709596563199&radius=5000&price_max=30000" int .advert__content-price._not-title   "<" 22500 &&message="Some fancy car matching your criteria was found" &&if command -v notify-send >/dev/null 2>&1 ; then notify-send "$message"; else say "$message"; fi
```

## Development setup from repository

While in project directory:
```bash
./install.sh
```

---
<p align="center">Maintainer: <a href="https://www.csmonk.com">csmonk</a></p>

