Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,29 @@ on:
jobs:
Pipeline:
if: github.ref == 'refs/heads/main'

runs-on: ubuntu-22.04
container: python:3.12

steps:
- uses: actions/checkout@v2
- name: Check out Git repository
uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: "0.5.8"
enable-cache: true
cache-suffix: "optional-suffix"
cache-dependency-glob: "base/pyproject.toml"

- name: Set up Python
run: uv python install 3.12

- name: Install dependencies
run: make requirements

- name: Build package
run: make package
run: make build

- name: Get version
run: echo "version=$(make version)" >> $GITHUB_ENV
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ jobs:
- uses: actions/checkout@v2

- name: Build Image
run: docker build -t biar --target dependencies .
run: docker build -t biar .

- name: Checks
run: docker run biar make checks

- name: Tests
run: docker run biar make tests
run: docker run biar make test
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,6 @@ cython_debug/

# PyCharm
.idea/

# Coverage
tests-cov/
28 changes: 16 additions & 12 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
FROM python:3.12 as dependencies
FROM python:3.12-slim-bookworm

## requirements
RUN pip install --upgrade pip
COPY requirements.dev.txt .
RUN pip install -r requirements.dev.txt
COPY requirements.txt .
RUN pip install -r requirements.txt
# Install make and other build dependencies
RUN apt-get update && \
apt-get install -y --no-install-recommends make && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

# Set the working directory in the container
WORKDIR /biar
COPY . /biar

## setup package
FROM dependencies as biar
# Copy project file into the container
COPY . .

# Tell the container about our project layout
ENV PROJECT_ROOT=/biar

RUN pip install /biar/.
RUN python -c "import biar"
# Install the project dependencies using UV
RUN uv sync --all-extras --dev
185 changes: 46 additions & 139 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,153 +1,60 @@
# globals
VERSION := $(shell grep __version__ biar/__metadata__.py | head -1 | cut -d \" -f2 | cut -d \' -f2)
VERSION := $(shell uvx --from=toml-cli toml get --toml-path=pyproject.toml project.version)
GH := $(shell command -v gh 2> /dev/null)

define PRINT_HELP_PYSCRIPT
import re, sys

print("Please use 'make <target>' where <target> is one of\n")
for line in sys.stdin:
match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line)
if match:
target, help = match.groups()
print("%-20s %s" % (target, help))
print("\nCheck the Makefile for more information")
endef
export PRINT_HELP_PYSCRIPT

define check_gh
@if [ -z $(GH) ]; then echo "gh could not be found. See https://cli.github.com/"; exit 2; fi
endef

.PHONY: requirements-dev
## install development requirements
requirements-dev:
@python -m pip install -U -r requirements.dev.txt

.PHONY: requirements-minimum
## install prod requirements
requirements-minimum:
@python -m pip install -U -r requirements.txt

.PHONY: requirements
## install requirements
requirements: requirements-dev requirements-minimum
.PHONY: help
.DEFAULT_GOAL := help
help:
@python3 -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST)

.PHONY: tests-coverage
## run unit and integration tests with coverage report
tests-coverage:
@echo ""
@echo "Tests"
@echo "=========="
@echo ""
@python -m pytest --cov-report term --cov-report html:tests-cov --cov=biar --cov-fail-under=100 tests/
install-uv:
@echo "Installing uv package manager..."
curl -LsSf https://astral.sh/uv/install.sh | sh

.PHONY: unit-tests
## run unit tests
unit-tests:
@echo ""
@echo "Unit Tests"
@echo "=========="
@echo ""
@python -m pytest tests/unit
requirements: ## install dependencies
@echo "Installing project dependencies..."
uv sync --all-extras --dev

.PHONY: integration-tests
## run integration tests
integration-tests:
@echo ""
@echo "Integration Tests"
@echo "================="
@echo ""
@python -m pytest tests/integration
apply-style:
@echo "Applying style..."
uv run ruff check --select I --fix --unsafe-fixes
uv run ruff format

.PHONY: style-check
## run code style checks with black
style-check:
@echo ""
@echo "Code Style"
@echo "=========="
@echo ""
@python -m black --check --exclude="build/|buck-out/|dist/|_build/|pip/|\.pip/|\.git/|\.hg/|\.mypy_cache/|\.tox/|\.venv/" . && echo "\n\nSuccess" || (echo "\n\nFailure\n\nRun \"make black\" to apply style formatting to your code"; exit 1)

.PHONY: quality-check
## run code quality checks with flake8
quality-check:
@echo ""
@echo "Flake 8"
@echo "======="
@echo ""
@python -m flake8 && echo "Success"
@echo ""
@echo "Running checks..."
uv run ruff check --fix

.PHONY: type-check
## run code type checks with mypy
type-check:
@echo ""
@echo "Mypy"
@echo "======="
@echo ""
@python -m mypy --install-types --non-interactive biar && echo "Success"
@echo ""
@echo "Running type checks..."
uv run mypy biar

.PHONY: checks
## run all code checks
checks: style-check quality-check type-check
checks: style-check type-check ## run all code checks

.PHONY: apply-style
## fix stylistic errors with black and isort
apply-style:
@python -m black --exclude="build/|buck-out/|dist/|_build/|pip/|\\.pip/|\.git/|\.hg/|\.mypy_cache/|\.tox/|\.venv/" .
@python -m isort biar/ tests/

.PHONY: package
## build biar package wheel
package:
@python -m setup sdist bdist_wheel
test:
@echo "Running tests..."
uv run pytest tests/

.PHONY: version
## show version
version:
@echo "$(VERSION)"

.PHONY: clean
## clean unused artifacts
clean:
@find ./ -type d -name 'dist' -exec rm -rf {} +;
@find ./ -type d -name 'build' -exec rm -rf {} +;
@find ./ -type d -name 'biar.egg-info' -exec rm -rf {} +;
@find ./ -type d -name 'htmlcov' -exec rm -rf {} +;
@find ./ -type d -name '.pytest_cache' -exec rm -rf {} +;
@find ./ -type d -name 'spark-warehouse' -exec rm -rf {} +;
@find ./ -type d -name 'metastore_db' -exec rm -rf {} +;
@find ./ -type d -name '.ipynb_checkpoints' -exec rm -rf {} +;
@find ./ -type f -name '*.egg-info' -exec rm -rf {} +;
@find ./ -name 'tests-cov' -exec rm -rf {} +;
@find ./ -type f -name 'coverage-badge.svg' -exec rm -f {} \;
@find ./ -type f -name 'coverage.xml' -exec rm -f {} \;
@find ./ -type f -name '*derby.log' -exec rm -f {} \;
@find ./ -name '*.pyc' -exec rm -f {} \;
@find ./ -name '*.pyo' -exec rm -f {} \;
@find ./ -name '*~' -exec rm -f {} \;
version: ## package version
@echo '${VERSION}'

.DEFAULT_GOAL := help
.PHONY: help
help:
@echo "$$(tput bold)Available rules:$$(tput sgr0)"
@echo
@sed -n -e "/^## / { \
h; \
s/.*//; \
:doc" \
-e "H; \
n; \
s/^## //; \
t doc" \
-e "s/:.*//; \
G; \
s/\\n## /---/; \
s/\\n/ /g; \
p; \
}" ${MAKEFILE_LIST} \
| LC_ALL='C' sort --ignore-case \
| awk -F '---' \
-v ncol=$$(tput cols) \
-v indent=19 \
-v col_on="$$(tput setaf 6)" \
-v col_off="$$(tput sgr0)" \
'{ \
printf "%s%*s%s ", col_on, -indent, $$1, col_off; \
n = split($$2, words, " "); \
line_length = ncol - indent; \
for (i = 1; i <= n; i++) { \
line_length -= length(words[i]) + 1; \
if (line_length <= 0) { \
line_length = ncol - indent - length(words[i]) - 1; \
printf "\n%*s ", -indent, " "; \
} \
printf "%s ", words[i]; \
} \
printf "\n"; \
}' \
| more $(shell test $(shell uname) = Darwin && echo '--no-init --raw-control-chars')
build:
@echo "Building package..."
uv build
2 changes: 2 additions & 0 deletions biar/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""biar - batteries-included async requests tool for python."""

from biar.__metadata__ import (
__author__,
__description__,
Expand Down
3 changes: 3 additions & 0 deletions biar/errors.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
"""Errors module."""


class ResponseEvaluationError(Exception):
"""Base Exception for non-OK responses."""

Expand Down
13 changes: 11 additions & 2 deletions biar/model.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
"""Model module."""

import asyncio
import logging
from functools import cached_property
from typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Type

Expand All @@ -7,7 +10,12 @@
from aiohttp import ClientResponseError
from loguru import logger
from pydantic import BaseModel, ConfigDict, Field, JsonValue, computed_field
from pyrate_limiter import Duration, InMemoryBucket, Limiter, Rate
from pyrate_limiter import ( # type: ignore[attr-defined]
Duration,
InMemoryBucket,
Limiter,
Rate,
)
from yarl import URL

from biar.errors import ContentCallbackError, ResponseEvaluationError
Expand Down Expand Up @@ -110,7 +118,8 @@ def retrying_config(self) -> Dict[str, Any]:
wait=tenacity.wait_exponential(min=self.min_delay, max=self.max_delay),
reraise=True,
before_sleep=tenacity.before_sleep_log(
logger=logger, log_level="DEBUG" # type: ignore[arg-type]
logger=logger, # type: ignore[arg-type]
log_level=logging.DEBUG,
),
)

Expand Down
Empty file added biar/py.typed
Empty file.
7 changes: 5 additions & 2 deletions biar/services.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Services module."""

import asyncio
import datetime
import ssl
Expand Down Expand Up @@ -58,8 +60,9 @@ def get_ssl_context(extra_certificate: Optional[str] = None) -> ssl.SSLContext:
"""
with open(certifi.where()) as f:
certificate = f.read()
if extra_certificate:
certificate = certificate + "\n" + extra_certificate
certificate = (
certificate + "\n" + extra_certificate if extra_certificate else certificate
)
return ssl.create_default_context(cadata=certificate)


Expand Down
22 changes: 12 additions & 10 deletions biar/user_agents.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
"""User-Agent module."""

import random
from typing import List, Optional

USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 12_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36",
"Mozilla/5.0 (iPhone; CPU iPhone OS 15_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/98.0.4758.85 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:96.0) Gecko/20100101 Firefox/96.0",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36", # noqa: E501
"Mozilla/5.0 (Macintosh; Intel Mac OS X 12_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36", # noqa: E501
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36", # noqa: E501
"Mozilla/5.0 (iPhone; CPU iPhone OS 15_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/98.0.4758.85 Mobile/15E148 Safari/604.1", # noqa: E501
"Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Mobile Safari/537.36", # noqa: E501
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:96.0) Gecko/20100101 Firefox/96.0", # noqa: E501
"Mozilla/5.0 (Macintosh; Intel Mac OS X 12.2; rv:96.0) Gecko/20100101 Firefox/96.0",
"Mozilla/5.0 (X11; Linux i686; rv:96.0) Gecko/20100101 Firefox/96.0",
"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/96.0 Mobile/15E148 Safari/605.1.15",
"Mozilla/5.0 (Android 12; Mobile; rv:68.0) Gecko/68.0 Firefox/96.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 12_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15",
"Mozilla/5.0 (iPhone; CPU iPhone OS 15_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/96.0 Mobile/15E148 Safari/605.1.15", # noqa: E501
"Mozilla/5.0 (Android 12; Mobile; rv:68.0) Gecko/68.0 Firefox/96.0", # noqa: E501
"Mozilla/5.0 (Macintosh; Intel Mac OS X 12_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15", # noqa: E501
"Mozilla/5.0 (iPhone; CPU iPhone OS 15_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Mobile/15E148 Safari/604.1", # noqa: E501
]


Expand Down
Loading