Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use uv for Python dependency management and code execution #107

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 3 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
38 changes: 0 additions & 38 deletions pyproject.toml

This file was deleted.

4 changes: 3 additions & 1 deletion src/datetime_parsing_csv/python/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ def modify_fields(item: dict, i: int) -> dict:
new_item: dict[str, Any] = dict()
new_item["id"] = i
new_item["name"] = item["name"]
new_item["dob"] = datetime.strptime(item["dob"], "%m-%d-%Y").date() if item.get("dob") else None
new_item["dob"] = (
datetime.strptime(item["dob"], "%m-%d-%Y").date() if item.get("dob") else None
)
new_item["age"] = item["age"]
new_item["isMarried"] = item["isMarried"]
new_item["city"] = item["city"]
Expand Down
4 changes: 3 additions & 1 deletion src/hello_world/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ Simple hello world program to show how this repo is organized 😀.

## How to run the Python program

The `uv` package manager is used to run the Python program.

```bash
python hello_world.py
uv run main.py
```

### Output
Expand Down
1 change: 1 addition & 0 deletions src/hello_world/python/.python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.12
prrao87 marked this conversation as resolved.
Show resolved Hide resolved
Empty file.
7 changes: 7 additions & 0 deletions src/hello_world/python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[project]
name = "proj"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []
7 changes: 7 additions & 0 deletions src/hello_world/python/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions src/intro/python/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ def run5() -> None:
persons = [Person("Aiko", 41), Person("Rohan", 18)]
sorted_by_age = sorted(persons, key=lambda person: person.age)
youngest_person = sorted_by_age[0]
print(f"{youngest_person.name} is the youngest person at {youngest_person.age} years old")
print(
f"{youngest_person.name} is the youngest person at {youngest_person.age} years old"
)
"""
Rohan is the youngest person at 18 years old
"""
Expand Down Expand Up @@ -117,7 +119,9 @@ def run7() -> None:
"""
persons = [Person("Issa", 39), Person("Ibrahim", 26)]
persons_born_after_1995 = [
(person.name, person.age) for person in persons if approx_year_of_birth(person) > 1995
(person.name, person.age)
for person in persons
if approx_year_of_birth(person) > 1995
]
print(f"Persons born after 1995: {persons_born_after_1995}")
"""
Expand Down
34 changes: 27 additions & 7 deletions src/meilisearch_with_cli/python/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,39 @@
console = Console()


async def preform_indexing(data: List[dict[str, Any]], index_name: str, wait: bool) -> None:
async def preform_indexing(
data: List[dict[str, Any]], index_name: str, wait: bool
) -> None:
async with AsyncClient(MEILISEARCH_URL, MEILISEARCH_API_KEY) as client:
index = client.index(index_name)
tasks = await index.add_documents_in_batches(data)
if wait:
waits = [client.wait_for_task(task.task_uid, timeout_in_ms=None) for task in tasks]
waits = [
client.wait_for_task(task.task_uid, timeout_in_ms=None)
for task in tasks
]
await asyncio.gather(*waits)


@app.command()
def create_index(
index_name: str = Option("wine", "-i", "--index-name", help="The name to use for the index"),
index_name: str = Option(
"wine", "-i", "--index-name", help="The name to use for the index"
),
) -> None:
client = Client(MEILISEARCH_URL, MEILISEARCH_API_KEY)
client.create_index(
index_name,
primary_key="id",
settings=MeilisearchSettings(
ranking_rules=["sort", "words", "typo", "proximity", "attribute", "exactness"],
ranking_rules=[
"sort",
"words",
"typo",
"proximity",
"attribute",
"exactness",
],
sortable_attributes=["title", "country"],
searchable_attributes=[
"title",
Expand Down Expand Up @@ -65,8 +79,12 @@ def index_data(
dir_okay=False,
help="Path to the data file",
),
index_name: str = Option("wine", "-i", "--index-name", help="The name to use for the index"),
wait: bool = Option(False, "-w", "--wait", help="Wait for the data to finish indexing"),
index_name: str = Option(
"wine", "-i", "--index-name", help="The name to use for the index"
),
wait: bool = Option(
False, "-w", "--wait", help="Wait for the data to finish indexing"
),
) -> None:
if data_path:
data = srsly.read_gzip_jsonl(data_path)
Expand All @@ -83,7 +101,9 @@ def search(
query: str = Argument(..., help="The search to preform"),
limit: int = Option(20, "-l", "--limit", help="Limit the number of search results"),
sort: List[str] = Option(None, "-s", "--sort", help="Sort order for the results"),
index_name: str = Option("wine", "-i", "--index-name", help="The name to use for the index"),
index_name: str = Option(
"wine", "-i", "--index-name", help="The name to use for the index"
),
) -> None:
client = Client(MEILISEARCH_URL, MEILISEARCH_API_KEY)
index = client.index(index_name)
Expand Down
4 changes: 3 additions & 1 deletion src/meilisearch_with_cli/python/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ def test_index_data(client, tmp_path, wine_data, index_name):
index = client.create_index(index_name)
file_path = tmp_path / "data.jsonl.gz"
srsly.write_gzip_jsonl(file_path, wine_data)
CliRunner().invoke(app, ["index-data", "-d", str(file_path), "-w", "-i", index_name])
CliRunner().invoke(
app, ["index-data", "-d", str(file_path), "-w", "-i", index_name]
)
documents = index.get_documents()
assert documents.total == 5

Expand Down
4 changes: 3 additions & 1 deletion src/mock_data/python/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ def get_locations(filename: Path) -> list[Location]:
return locations


def generate_fake_persons(faker: Faker, locations: list[Location], num: int) -> list[Person]:
def generate_fake_persons(
faker: Faker, locations: list[Location], num: int
) -> list[Person]:
# Generate fake persons with the desired structure and return a list of mappings
profiles = []
for i in range(1, num + 1):
Expand Down
4 changes: 3 additions & 1 deletion src/parallelism/python/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ def get_result() -> pl.DataFrame:
articles2 = pl.read_csv("../data/articles2_processed.csv")
articles3 = pl.read_csv("../data/articles3_processed.csv")
# Combine the data into a single DataFrame
result = pl.concat([articles1, articles2, articles3]).unique(subset=["id"]).sort("id")
result = (
pl.concat([articles1, articles2, articles3]).unique(subset=["id"]).sort("id")
)
print(f"Number of articles: {result.height}")
return result

Expand Down
20 changes: 16 additions & 4 deletions src/parallelism/python/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ def _clean_text(self, text: str) -> str:
"ll": " will",
}
# Replace contractions with full words
formatted_text = re.sub(r"([’'])(s|d|ll)", lambda x: suffix_mapping[x.group(2)], text_lower)
formatted_text = re.sub(
r"([’'])(s|d|ll)", lambda x: suffix_mapping[x.group(2)], text_lower
)
# Remove non-alphabetic characters
result = re.sub(r"[^a-zA-Z\s]", "", formatted_text)
return result
Expand All @@ -61,7 +63,9 @@ def calculate_counts(self, data: JsonBlob) -> JsonBlob:
text = data["content"]
result = self._clean_text(text)
tokens = result.split()
data["num_male_pronouns"], data["num_female_pronouns"] = count_gendered_pronouns(tokens)
data["num_male_pronouns"], data["num_female_pronouns"] = (
count_gendered_pronouns(tokens)
)
data.pop("content")
return data

Expand All @@ -84,7 +88,14 @@ def count_gendered_pronouns(tokens: list[str]) -> tuple[int, int]:

def write_results(data: list[JsonBlob], file_path: Path, file_name: str) -> None:
output_path = file_path / file_name
fieldnames = ["id", "publication", "author", "date", "num_male_pronouns", "num_female_pronouns"]
fieldnames = [
"id",
"publication",
"author",
"date",
"num_male_pronouns",
"num_female_pronouns",
]
with open(output_path, "w") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
Expand All @@ -94,7 +105,8 @@ def write_results(data: list[JsonBlob], file_path: Path, file_name: str) -> None
def main(file_path: Path, batch_size: int) -> None:
# Get all .csv files in the directory
files = [
Path(f"../data/{file}") for file in ("articles1.csv", "articles2.csv", "articles3.csv")
Path(f"../data/{file}")
for file in ("articles1.csv", "articles2.csv", "articles3.csv")
]
processor = BatchProcessor(batch_size)
for input_file in files:
Expand Down
4 changes: 3 additions & 1 deletion src/regex_json/python/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ def run() -> list[dict[str, Any]]:
raise ValueError("No data found")

for company in data:
annual_revenue_lower, annual_revenue_upper = calculate_range(company["annual_revenue"])
annual_revenue_lower, annual_revenue_upper = calculate_range(
company["annual_revenue"]
)
# Append to existing dict
company["annual_revenue_lower"] = annual_revenue_lower
company["annual_revenue_upper"] = annual_revenue_upper
Expand Down
50 changes: 21 additions & 29 deletions src/simple_csv/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,47 +56,39 @@ Yakutsk,Russia,-37.5,-38.6

## Python Setup

Install the dependencies in a virtual environment via `requirements.txt`.

```bash
# First time setup
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt

# For subsequent runs, simply activate the environment
source venv/bin/activate
```
Install dependencies via the `uv` package manager. All dependencies are listed in `pyproject.toml`.
For this project, we only need the standard library of Python, so there are no dependencies to install.

### Run script

```bash
python main.py
uv run main.py
```

### Run tests

```bash
$ pytest -v
================================================================================================ test session starts ================================================================================================
platform darwin -- Python 3.11.7, pytest-7.4.4, pluggy-1.3.0 -- /Users/prrao/code/rustinpieces/.venv/bin/python3.11
$ uv run pytest -v
===================================================================================================== test session starts =====================================================================================================
platform darwin -- Python 3.12.5, pytest-8.3.2, pluggy-1.5.0 -- /Users/prrao/.pyenv/versions/3.12.5/bin/python3.12
cachedir: .pytest_cache
rootdir: /Users/prrao/code/rustinpieces/pieces/simple_csv/python
plugins: Faker-21.0.1
rootdir: /Users/prrao/code/rustinpieces/src/simple_csv/python
configfile: pyproject.toml
plugins: anyio-4.4.0
collected 10 items

test_main.py::test_read_and_modify PASSED [ 10%]
test_main.py::test_modify_fields PASSED [ 20%]
test_main.py::test_convert_f_to_c[70.2-21.2] PASSED [ 30%]
test_main.py::test_convert_f_to_c[-14.1--25.6] PASSED [ 40%]
test_main.py::test_convert_f_to_c[25.3--3.7] PASSED [ 50%]
test_main.py::test_convert_f_to_c[29.6--1.3] PASSED [ 60%]
test_main.py::test_convert_f_to_c[52.1-11.2] PASSED [ 70%]
test_main.py::test_convert_f_to_c[18.7--7.4] PASSED [ 80%]
test_main.py::test_convert_f_to_c[-37.5--38.6] PASSED [ 90%]
test_main.py::test_write_csv PASSED [100%]

================================================================================================ 10 passed in 0.02s =================================================================================================
test_main.py::test_read_and_modify PASSED [ 10%]
test_main.py::test_modify_fields PASSED [ 20%]
test_main.py::test_convert_f_to_c[70.2-21.2] PASSED [ 30%]
test_main.py::test_convert_f_to_c[-14.1--25.6] PASSED [ 40%]
test_main.py::test_convert_f_to_c[25.3--3.7] PASSED [ 50%]
test_main.py::test_convert_f_to_c[29.6--1.3] PASSED [ 60%]
test_main.py::test_convert_f_to_c[52.1-11.2] PASSED [ 70%]
test_main.py::test_convert_f_to_c[18.7--7.4] PASSED [ 80%]
test_main.py::test_convert_f_to_c[-37.5--38.6] PASSED [ 90%]
test_main.py::test_write_csv PASSED [100%]

===================================================================================================== 10 passed in 0.01s ======================================================================================================
```

## Rust Setup
Expand Down
1 change: 1 addition & 0 deletions src/simple_csv/python/.python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.12
Loading
Loading