Skip to content

Commit

Permalink
Merge branch 'release/1.2.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
s3rius committed Sep 25, 2023
2 parents 0fd0a99 + 822df9f commit 848e3f8
Show file tree
Hide file tree
Showing 35 changed files with 904 additions and 145 deletions.
1 change: 1 addition & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ jobs:
cmd:
- black
- isort
- ruff
- mypy
runs-on: ubuntu-latest
steps:
Expand Down
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ repos:
always_run: true
pass_filenames: false
args: ["python"]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.0.291
hooks:
- id: ruff
name: ruff
pass_filenames: false
always_run: true
args: ["python", "--fix"]
- repo: local
hooks:
- id: fmt
Expand Down
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "scyllapy"
version = "1.1.3"
version = "1.2.0"
edition = "2021"

[lib]
Expand All @@ -9,8 +9,9 @@ crate-type = ["cdylib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
chrono = "0.4.26"
chrono = "0.4.31"
eq-float = "0.1.0"
futures = "0.3.28"
log = "0.4.20"
openssl = { version = "0.10.57", features = ["vendored"] }
pyo3 = { version = "0.19.2", features = [
Expand Down
111 changes: 111 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,104 @@ async def run_batch(scylla: Scylla, num_queries: int) -> None:
await scylla.batch(batch, [{"id": 1}]) # Will rase an error!
```

## Pagination

Sometimes you want to query lots of data. For such cases it's better not to
fetch all results at once, but fetch them using pagination. It reduces load
not only on your application, but also on a cluster.

To execute query with pagination, simply add `paged=True` in execute method.
After doing so, `execute` method will return `IterableQueryResult`, instead of `QueryResult`.
Instances of `IterableQueryResult` can be iterated with `async for` statements.
You, as a client, won't see any information about pages, it's all handeled internally within a driver.

Please note, that paginated queries are slower to fetch all rows, but much more memory efficent for large datasets.

```python
result = await scylla.execute("SELECT * FROM table", paged=True)
async for row in result:
print(row)

```

Of course, you can change how results returned to you, by either using `scalars` or
`as_cls`. For example:

```python
async def func(scylla: Scylla) -> None:
rows = await scylla.execute("SELECT id FROM table", paged=True)
# Will print ids of each returned row.
async for test_id in rows.scalars():
print(test_id)

```

```python
from dataclasses import dataclass

@dataclass
class MyDTO:
id: int
val: int

async def func(scylla: Scylla) -> None:
rows = await scylla.execute("SELECT * FROM table", paged=True)
# Will print ids of each returned row.
async for my_dto in rows.as_cls(MyDTO):
print(my_dto.id, my_dto.val)

```

## Execution profiles

You can define profiles using `ExecutionProfile` class. After that the
profile can be used while creating a cluster or when defining queries.

```python
from scyllapy import Consistency, ExecutionProfile, Query, Scylla, SerialConsistency
from scyllapy.load_balancing import LoadBalancingPolicy, LatencyAwareness

default_profile = ExecutionProfile(
consistency=Consistency.LOCAL_QUORUM,
serial_consistency=SerialConsistency.LOCAL_SERIAL,
request_timeout=2,
)

async def main():
query_profile = ExecutionProfile(
consistency=Consistency.ALL,
serial_consistency=SerialConsistency.SERIAL,
# Load balancing cannot be constructed without running event loop.
# If you won't do it inside async funcion, it will result in error.
load_balancing_policy=await LoadBalancingPolicy.build(
token_aware=True,
prefer_rack="rack1",
prefer_datacenter="dc1",
permit_dc_failover=True,
shuffling_replicas=True,
latency_awareness=LatencyAwareness(
minimum_measurements=10,
retry_period=1000,
exclusion_threshold=1.4,
update_rate=1000,
scale=2,
),
),
)

scylla = Scylla(
["192.168.32.4"],
default_execution_profile=default_profile,
)
await scylla.startup()
await scylla.execute(
Query(
"SELECT * FROM system_schema.keyspaces;",
profile=query_profile,
)
)
```

### Results

Every query returns a class that represents returned rows. It allows you to not fetch
Expand Down Expand Up @@ -291,4 +389,17 @@ async def execute_batch(scylla: Scylla) -> None:
Insert("users").set("id", i).set("name", "test").add_to_batch(batch)
await scylla.batch(batch)

```

## Paging

Queries that were built with QueryBuilder also support paged returns.
But it supported only for select, because update, delete and insert should
not return anything and it makes no sense implementing it.
To make built `Select` query return paginated iterator, add paged parameter in execute method.

```python
rows = await Select("test").execute(scylla, paged=True)
async for row in rows:
print(row['id'])
```
63 changes: 63 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,66 @@ warn_unused_ignores = false
[build-system]
requires = ["maturin>=1.0,<2.0"]
build-backend = "maturin"

[tool.ruff]
# List of enabled rulsets.
# See https://docs.astral.sh/ruff/rules/ for more information.
select = [
"E", # Error
"F", # Pyflakes
"W", # Pycodestyle
"C90", # McCabe complexity
"N", # pep8-naming
"D", # Pydocstyle
"ANN", # Pytype annotations
"S", # Bandit
"B", # Bugbear
"COM", # Commas
"C4", # Comprehensions
"ISC", # Implicit string concat
"PIE", # Unnecessary code
"T20", # Catch prints
"PYI", # validate pyi files
"Q", # Checks for quotes
"RSE", # Checks raise statements
"RET", # Checks return statements
"SLF", # Self checks
"SIM", # Simplificator
"PTH", # Pathlib checks
"ERA", # Checks for commented out code
"PL", # PyLint checks
"RUF", # Specific to Ruff checks
]
ignore = [
"D105", # Missing docstring in magic method
"D107", # Missing docstring in __init__
"D211", # No blank lines allowed before class docstring
"D212", # Multi-line docstring summary should start at the first line
"D401", # First line should be in imperative mood
"D104", # Missing docstring in public package
"D100", # Missing docstring in public module
"ANN102", # Missing type annotation for self in method
"ANN101", # Missing type annotation for argument
"ANN401", # typing.Any are disallowed in `**kwargs
"PLR0913", # Too many arguments for function call
"D106", # Missing docstring in public nested class
]
exclude = [".venv/"]
mccabe = { max-complexity = 10 }
line-length = 88

[tool.ruff.per-file-ignores]
"python/scyllapy/*" = ["PYI021"]
"python/tests/*" = [
"S101", # Use of assert detected
"S608", # Possible SQL injection vector through string-based query construction
"D103", # Missing docstring in public function
"S311", # Standard pseudo-random generators are not suitable for security/cryptographic purposes
]

[tool.ruff.pydocstyle]
convention = "pep257"
ignore-decorators = ["typing.overload"]

[tool.ruff.pylint]
allow-magic-value-types = ["int", "str", "float", "tuple"]
3 changes: 2 additions & 1 deletion python/scyllapy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
Batch,
BatchType,
Consistency,
ExecutionProfile,
InlineBatch,
PreparedQuery,
Query,
Expand All @@ -26,5 +27,5 @@
"QueryResult",
"extra_types",
"InlineBatch",
"query_builder",
"ExecutionProfile",
]
Loading

0 comments on commit 848e3f8

Please sign in to comment.