Skip to content

Commit

Permalink
Add mypy testing to python README
Browse files Browse the repository at this point in the history
  • Loading branch information
Sh1nku committed Nov 3, 2024
1 parent 1559cfa commit c5481c0
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 33 deletions.
64 changes: 38 additions & 26 deletions wrappers/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ context = SolrServerContext(SolrSingleServerHost('localhost:8983'), SolrBasicAut
client = AsyncSolrCloudClient(context)


async def main():
async def main() -> None:
# Create config and collection
await client.upload_config('example_config', 'path/to/config')
await client.create_collection('example_collection', 'example_config', shards=1, replication_factor=1)
Expand All @@ -48,7 +48,10 @@ async def main():

# Search for the document
response = await client.select(SelectQuery(fq=['title:Example document']), 'example_collection')
docs = response.get_docs_response().get_docs()
docs_response = response.get_docs_response()
assert docs_response is not None
assert docs_response.get_num_found() == 1
docs = docs_response.get_docs()

# Delete the document
await client.delete(DeleteQuery(ids=['example_document']), 'example_collection')
Expand Down Expand Up @@ -76,7 +79,10 @@ client.index(UpdateQuery(), 'example_collection', [{'id': 'example_document', 't

# Search for the document
response = client.select(SelectQuery(fq=['title:Example document']), 'example_collection')
docs = response.get_docs_response().get_docs()
docs_response = response.get_docs_response()
assert docs_response is not None
assert docs_response.get_num_found() == 1
docs = docs_response.get_docs()

# Delete the document
client.delete(DeleteQuery(ids=['example_document']), 'example_collection')
Expand All @@ -90,7 +96,7 @@ client.delete(DeleteQuery(ids=['example_document']), 'example_collection')
from solrstice import GroupingComponent, SelectQuery, SolrServerContext, AsyncSolrCloudClient
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main():
async def main() -> None:
group_builder = GroupingComponent(fields=["age"], limit=10)
select_builder = SelectQuery(fq=["age:[* TO *]"], grouping=group_builder)
groups = (await client.select(select_builder, "example_collection")).get_groups()
Expand All @@ -104,12 +110,13 @@ async def main():
from solrstice import GroupingComponent, SelectQuery, SolrServerContext, AsyncSolrCloudClient
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main():
async def main() -> None:
group_builder = GroupingComponent(queries=["age:[0 TO 59]", "age:[60 TO *]"], limit=10)
select_builder = SelectQuery(fq=["age:[* TO *]"], grouping=group_builder)
groups = (await client.select(select_builder, "example_collection")).get_groups()
age_group = groups["age:[0 TO 59]"]
group = age_group.get_query_result()
assert group is not None
docs = group.get_docs()
```

Expand All @@ -121,7 +128,7 @@ async def main():
from solrstice import LuceneQuery, SelectQuery, SolrServerContext, AsyncSolrCloudClient
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main():
async def main() -> None:
query_parser = LuceneQuery(df="population")
select_builder = SelectQuery(q="outdoors", def_type=query_parser)
response = (await client.select(select_builder, "example_collection")).get_docs_response()
Expand All @@ -135,7 +142,7 @@ async def main():
from solrstice import DismaxQuery, SelectQuery, SolrServerContext, AsyncSolrCloudClient
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main():
async def main() -> None:
query_parser = DismaxQuery(qf="interests^20", bq=["interests:cars^20"])
select_builder = SelectQuery(q="outdoors", def_type=query_parser)
response = (await client.select(select_builder, "example_collection")).get_docs_response()
Expand All @@ -149,7 +156,7 @@ async def main():
from solrstice import EdismaxQuery, SelectQuery, SolrServerContext, AsyncSolrCloudClient
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main():
async def main() -> None:
query_parser = EdismaxQuery(qf="interests^20", bq=["interests:cars^20"])
select_builder = SelectQuery(q="outdoors", def_type=query_parser)
response = (await client.select(select_builder, "example_collection")).get_docs_response()
Expand All @@ -165,7 +172,7 @@ async def main():
from solrstice import FacetSetComponent, PivotFacetComponent, SelectQuery, SolrServerContext, AsyncSolrCloudClient
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main():
async def main() -> None:
select_builder = SelectQuery(facet_set=FacetSetComponent(pivots=PivotFacetComponent(["interests,age"])))
response = await client.select(select_builder, "example_collection")
facets = response.get_facet_set()
Expand All @@ -179,7 +186,7 @@ async def main():
from solrstice import FacetSetComponent, FieldFacetComponent, FieldFacetEntry, SelectQuery, SolrServerContext, AsyncSolrCloudClient
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main():
async def main() -> None:
facet_set = FacetSetComponent(fields=FieldFacetComponent(fields=[FieldFacetEntry("age")]))
select_builder = SelectQuery(facet_set=facet_set)
response = await client.select(select_builder, "example_collection")
Expand All @@ -194,7 +201,7 @@ async def main():
from solrstice import AsyncSolrCloudClient, SolrServerContext, SelectQuery, FacetSetComponent, FacetSetComponent
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main():
async def main() -> None:
select_builder = SelectQuery(facet_set=FacetSetComponent(queries=["age:[0 TO 59]"]))
response = await client.select(select_builder, "example_collection")
facets = response.get_facet_set()
Expand All @@ -208,7 +215,7 @@ async def main():

```python
from solrstice import JsonFacetComponent, JsonQueryFacet, SelectQuery, SolrServerContext, AsyncSolrCloudClient
async def main():
async def main() -> None:
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))
select_builder = SelectQuery(
json_facet=JsonFacetComponent(
Expand All @@ -217,7 +224,9 @@ async def main():
)
response = await client.select(select_builder, "example_collection")
facets = response.get_json_facets()
assert facets is not None
below_60 = facets.get_nested_facets().get("below_60")
assert below_60 is not None
assert below_60.get_count() == 4
```

Expand All @@ -227,15 +236,16 @@ async def main():
from solrstice import JsonFacetComponent, JsonStatFacet, SelectQuery, SolrServerContext, AsyncSolrCloudClient
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main():
async def main() -> None:
select_builder = SelectQuery(
json_facet=JsonFacetComponent(
facets={"total_people": JsonStatFacet("sum(count)")}
)
)
response = await client.select(select_builder, "example_collection")
facets = response.get_json_facets()
total_people = facets.get_flat_facets().get("total_people")
assert facets is not None
total_people = facets.get_flat_facets()["total_people"]
assert total_people == 1000
```

Expand All @@ -245,13 +255,14 @@ async def main():
from solrstice import AsyncSolrCloudClient, SolrServerContext, SelectQuery, JsonFacetComponent, JsonTermsFacet
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main():
async def main() -> None:
select_builder = SelectQuery(
json_facet=JsonFacetComponent(facets={"age": JsonTermsFacet("age")})
)
response = await client.select(select_builder, "example_collection")
facets = response.get_json_facets()
age_buckets = facets.get_nested_facets().get("age").get_buckets()
assert facets is not None
age_buckets = facets.get_nested_facets()["age"].get_buckets()
assert len(age_buckets) == 3
```

Expand All @@ -261,7 +272,7 @@ async def main():
from solrstice import AsyncSolrCloudClient, SolrServerContext, SelectQuery, JsonFacetComponent, JsonQueryFacet, JsonStatFacet
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main():
async def main() -> None:
select_builder = SelectQuery(
json_facet=JsonFacetComponent(
facets={
Expand All @@ -274,9 +285,10 @@ async def main():
)
response = await client.select(select_builder, "example_collection")
facets = response.get_json_facets()
assert facets is not None
total_people = (
facets.get_nested_facets()
.get("below_60")
["below_60"]
.get_flat_facets()
.get("total_people")
)
Expand Down Expand Up @@ -312,7 +324,7 @@ client = AsyncSolrCloudClient(context)
```python
from solrstice import SolrServerContext, ZookeeperEnsembleHostConnector, SolrBasicAuth, AsyncSolrCloudClient

async def main():
async def main() -> None:
context = SolrServerContext(
await ZookeeperEnsembleHostConnector(["localhost:2181"], 30).connect(),
SolrBasicAuth('solr', 'SolrRocks'),
Expand All @@ -328,11 +340,11 @@ async def main():

For example, if you want to create a simpler way to create a client
```python
from typing import Optional
from solrstice import SolrServerContext, SolrSingleServerHost, SolrBasicAuth, AsyncSolrCloudClient, SolrAuth
class SolrClient(AsyncSolrCloudClient):
def __new__(cls, host: str, auth: Optional[SolrAuth] = None):
context = SolrServerContext(SolrSingleServerHost(host), auth)
return super().__new__(cls, context=context)
client = SolrClient("localhost:8983", SolrBasicAuth("username", "password"))
from typing import Optional
from solrstice import SolrServerContext, SolrSingleServerHost, SolrBasicAuth, AsyncSolrCloudClient, SolrAuth
class SolrClient(AsyncSolrCloudClient):
def __new__(cls, host: str, auth: Optional[SolrAuth] = None):
context = SolrServerContext(SolrSingleServerHost(host), auth)
return super().__new__(cls, context=context)
client = SolrClient("localhost:8983", SolrBasicAuth("username", "password"))
```
Empty file.
11 changes: 11 additions & 0 deletions wrappers/python/tests/meta/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from pathlib import Path

import solrstice


def find_mypy_config() -> Path:
solrstice_path = Path(solrstice.__path__[0]) # type: ignore
solrstice_parent = solrstice_path.parent
if (solrstice_parent / "mypy.ini").exists():
return solrstice_parent / "mypy.ini"
raise FileNotFoundError("Could not find mypy.ini")
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,7 @@

import solrstice


def find_mypy_config() -> Path:
solrstice_path = Path(solrstice.__path__[0]) # type: ignore
solrstice_parent = solrstice_path.parent
if (solrstice_parent / "mypy.ini").exists():
return solrstice_parent / "mypy.ini"
raise FileNotFoundError("Could not find mypy.ini")
from .helpers import find_mypy_config


def get_doctests_from_solrstice() -> Dict[str, List[doctest.Example]]:
Expand Down
55 changes: 55 additions & 0 deletions wrappers/python/tests/meta/test_readme.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import re
import tempfile
from pathlib import Path
from sys import stderr
from typing import List, Tuple

import mypy.api

import solrstice

from .helpers import find_mypy_config


def find_readme_path() -> Path:
solrstice_path = Path(solrstice.__path__[0]) # type: ignore
solrstice_parent = solrstice_path.parent
if (solrstice_parent / "README.md").exists():
return solrstice_parent / "README.md"
raise FileNotFoundError("Could not find README.md")


def extract_readme_examples() -> List[Tuple[int, str]]:
"""Extracts code examples from the README.md file with the first line of the example"""
readme_path = find_readme_path()
with open(readme_path) as f:
readme_content = f.read()
examples = []
extraction_regex = r"```python\n(.*?)\n```"
for match in re.finditer(extraction_regex, readme_content, re.DOTALL):
start_position = match.start()
line_number = readme_content.count("\n", 0, start_position) + 1
examples.append((line_number, match.group(1)))
return examples


def test_readme_with_mypy() -> None:
mypy_config = find_mypy_config()
readme_examples = extract_readme_examples()
file_contents: List[str] = []
with tempfile.NamedTemporaryFile(mode="w", suffix=".py") as f:
for example in readme_examples:
while len(file_contents) < example[0] - 1:
file_contents.append("\n")

file_contents.append(f"def test_readme_example_{example[0]}() -> None:\n")
for line in example[1].split("\n"):
file_contents.append(f" {line}\n")
f.write("".join(file_contents))
f.flush()
results = list(mypy.api.run(["--config-file", f"{mypy_config}", f.name]))
# Replace file path with the original file name
results[0] = results[0].replace(f.name, str(find_readme_path())) # type: ignore
if results[2] != 0:
print(f"\n{results[0]}", stderr)
raise AssertionError("Mypy failed. See above for details.")

0 comments on commit c5481c0

Please sign in to comment.