From 88eb9cc2d271d2f69ec23faca4f1d15b351b8cd5 Mon Sep 17 00:00:00 2001 From: prrao87 Date: Thu, 10 Oct 2024 14:48:47 -0400 Subject: [PATCH 1/9] Use uv for dependency mgmt and code execution --- pyproject.toml | 38 ----- src/simple_csv/README.md | 50 +++---- src/simple_csv/python/.python-version | 1 + src/simple_csv/python/README.md | 193 +++++++++++++++++++++++++ src/simple_csv/python/pyproject.toml | 7 + src/simple_csv/python/requirements.txt | 1 - src/simple_csv/python/uv.lock | 7 + 7 files changed, 229 insertions(+), 68 deletions(-) delete mode 100644 pyproject.toml create mode 100644 src/simple_csv/python/.python-version create mode 100644 src/simple_csv/python/README.md create mode 100644 src/simple_csv/python/pyproject.toml delete mode 100644 src/simple_csv/python/requirements.txt create mode 100644 src/simple_csv/python/uv.lock diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index c3b54be..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,38 +0,0 @@ -[tool.mypy] -check_untyped_defs = true -disallow_untyped_defs = true -plugins = ["pydantic.mypy"] - -[[tool.mypy.overrides]] -module = ["tests.*"] -disallow_untyped_defs = false - -[[tool.mypy.overrides]] -module = ["asyncpg.*", "srsly.*"] -ignore_missing_imports = true - -[tool.ruff] -line-length = 100 -target-version = "py38" -fix = true - -[tool.ruff.lint] -select=["E", "F", "UP", "I001"] -ignore=[ - # Recommened ignores by ruff when using formatter - "E501", - "W191", - "E111", - "E114", - "E117", - "D206", - "D300", - "Q000", - "Q001", - "Q002", - "Q003", - "COM812", - "COM819", - "ISC001", - "ISC002", -] diff --git a/src/simple_csv/README.md b/src/simple_csv/README.md index f2c0b07..4662b1b 100644 --- a/src/simple_csv/README.md +++ b/src/simple_csv/README.md @@ -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 diff --git a/src/simple_csv/python/.python-version b/src/simple_csv/python/.python-version new file mode 100644 index 0000000..e4fba21 --- /dev/null +++ b/src/simple_csv/python/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/src/simple_csv/python/README.md b/src/simple_csv/python/README.md new file mode 100644 index 0000000..d7de759 --- /dev/null +++ b/src/simple_csv/python/README.md @@ -0,0 +1,193 @@ +# # Modify a CSV file with simple types + +Read in data from a CSV file with simple types (strings, floats) and write it back to a new CSV file with modified values. + +## Goal + +In this project, we will add a new column to a CSV file that contains data on cities, the country they +belong to, and their average temperatures for the month of January in Fahrenheit. The goal is to write a new CSV file containing +the same data but an added column containing the average temperatures converted to Celsius. The raw +data is obtained from [this Wikipedia page](https://en.wikipedia.org/wiki/List_of_cities_by_average_temperature). + +The converted temperature in Celsius is calculated up to 1 decimal precision, because that's +the same precision as the input data. We will also test the results of the conversion +to be within 0.05 of the expected value. This is because numerical operations with floats +are always subject to [floating point errors](https://docs.python.org/3/tutorial/floatingpoint.html). + +## Inputs + +The input CSV file is `./data/city_temps.csv` with the following data. + +```csv +city,country,avg_temp_jan_f +Sydney,Australia,72.1 +Wellington,New Zealand,62.4 +Honolulu,United States,73.1 +Santiago,Chile,70.2 +Yellowknife,Canada,-14.1 +Toronto,Canada,25.3 +Salt Lake City,United States,29.6 +San Francisco,United States,52.1 +Nuuk,Greenland,18.7 +Yakutsk,Russia,-37.5 +``` + +We have a combination of positive and negative temperatures for these places in Fahrenheit. +In the northern hemisphere in January, certain cities go _brrr_ 🥶. + +## Output + +The output is also a CSV file `./data/city_temps-modified.csv` with an additional column `avg_temp_jan_c` +that has the converted temperature value in Celsius. + +```csv +city,country,avg_temp_jan_f,avg_temp_jan_c +Sydney,Australia,72.1,22.3 +Wellington,New Zealand,62.4,16.9 +Honolulu,United States,73.1,22.8 +Santiago,Chile,70.2,21.2 +Yellowknife,Canada,-14.1,-25.6 +Toronto,Canada,25.3,-3.7 +Salt Lake City,United States,29.6,-1.3 +San Francisco,United States,52.1,11.2 +Nuuk,Greenland,18.7,-7.4 +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 +``` + +### Run script + +```bash +python 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 +cachedir: .pytest_cache +rootdir: /Users/prrao/code/rustinpieces/pieces/simple_csv/python +plugins: Faker-21.0.1 +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 ================================================================================================= +``` + +## Rust Setup + +Install dependencies via Cargo. Note that because we perform CSV serialization/deserialization via +`serde`, we need to install it using the features flag. In addition, we need to install the `approx` +crate to perform approximate floating point comparisons during testing (all floating point comparisons +are subject to floating point errors, so approximate comparisons are required). + +```bash +cargo add csv +cargo add serde --features derive +# Only add the approx crate for testing with the --dev flag +cargo add --dev approx +``` + +### Run project + +The provided `Makefile` runs the formatter, linter, tests and the main file all in sequence. + +```bash +make all + +# Runs the following +cargo fmt --all --quiet +cargo check --all-targets --quiet +cargo clippy --all-targets --quiet +cargo test --quiet +cargo run --quiet +``` + +To run just the main file, use the following command. + +```bash +make run +# or, simply run via cargo +cargo run --quiet +``` + +### Run linter and formatter only + +Cargo provides out-of-the-box for formatting (`cargo fmt --all`), compile checks (`cargo check --all-targets`), +and linting (`cargo clippy --all-targets`). The following command runs both. It's highly recommended +to run both prior to pushing Rust code to a +repository. + +```bash +make format +make check +make lint +# Runs the following +cargo fmt --all --quiet +cargo check --all-targets --quiet +cargo clippy --all-targets --quiet +``` + +## Run tests only + +The Rust in-built test client allows tests to be defined within the same file as the code being tested. Because Rust is a compiled language, the compiler will know to ignore the tests when building the final binary for runtime. + +Tests are run using `make test` or `cargo test --quiet`. + +```bash +make test +cargo test --quiet + + +running 3 tests +test tests::test_conversion_to_celsius ... ok +test tests::test_read_csv ... ok +test tests::test_write_csv ... ok + +test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +## Takeaways + +Notice that in `read_csv` in the Rust file the return type is `Result, Box>`. +In Python, exceptions can be raised either explicitly or silently at any time. However, this is not +the case in Rust. If a function can error it, _must_ return the `Result` type, specifying the type +for success, the `Ok` value, and the type for errors, the `Err`. Any time a function is called +that returns a `Result` both the `Ok` and the `Err` possiblities have to be handled. The `?` operator +can be used when a function returns a `Result`, and specfifies that if the result of the function +call is an error that error should be returned, otherwise use the `Ok` value. + +You will also notice that `expect` and `unwrap` are used. These are similiar to using `?`, but can +be used in functions that don't return a `Result`. The difference between `expect` and `unwrap` is +`expect` allows you to provide a specific message when a panic, while `unwrap` uses a generaic message. +Because `expect` allows a custom message, it can make it easier to understand where an error is happening +since you will be to compare the error message to the messages you have provided. `expect` and `unwrap` +are good for prototyping and tests, but are almost never what you want to use in the final application +or library. If the result of the `expect`/`unwrap` is an error, the program will panic, meaning it +exits without the possiblity of recovering, so it's considered a best practice to clean up your code +with proper error handling using `Result` prior to running any code in production. diff --git a/src/simple_csv/python/pyproject.toml b/src/simple_csv/python/pyproject.toml new file mode 100644 index 0000000..1959963 --- /dev/null +++ b/src/simple_csv/python/pyproject.toml @@ -0,0 +1,7 @@ +[project] +name = "simple_csv" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [] diff --git a/src/simple_csv/python/requirements.txt b/src/simple_csv/python/requirements.txt deleted file mode 100644 index 8b667c7..0000000 --- a/src/simple_csv/python/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -pytest~=7.4.0 diff --git a/src/simple_csv/python/uv.lock b/src/simple_csv/python/uv.lock new file mode 100644 index 0000000..10972b3 --- /dev/null +++ b/src/simple_csv/python/uv.lock @@ -0,0 +1,7 @@ +version = 1 +requires-python = ">=3.12" + +[[package]] +name = "simple-csv" +version = "0.1.0" +source = { virtual = "." } From b30d6672fa0b493f6357c8477433484e99e0a06b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 10 Oct 2024 18:53:02 +0000 Subject: [PATCH 2/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/datetime_parsing_csv/python/main.py | 4 ++- src/intro/python/main.py | 8 +++-- src/meilisearch_with_cli/python/main.py | 34 ++++++++++++++++---- src/meilisearch_with_cli/python/test_main.py | 4 ++- src/mock_data/python/main.py | 4 ++- src/parallelism/python/analyze.py | 4 ++- src/parallelism/python/main.py | 20 +++++++++--- src/regex_json/python/main.py | 4 ++- 8 files changed, 64 insertions(+), 18 deletions(-) diff --git a/src/datetime_parsing_csv/python/main.py b/src/datetime_parsing_csv/python/main.py index 133a837..ae4426f 100644 --- a/src/datetime_parsing_csv/python/main.py +++ b/src/datetime_parsing_csv/python/main.py @@ -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"] diff --git a/src/intro/python/main.py b/src/intro/python/main.py index 2f56f89..1b284c7 100644 --- a/src/intro/python/main.py +++ b/src/intro/python/main.py @@ -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 """ @@ -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}") """ diff --git a/src/meilisearch_with_cli/python/main.py b/src/meilisearch_with_cli/python/main.py index 0c840f2..3e46105 100644 --- a/src/meilisearch_with_cli/python/main.py +++ b/src/meilisearch_with_cli/python/main.py @@ -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", @@ -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) @@ -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) diff --git a/src/meilisearch_with_cli/python/test_main.py b/src/meilisearch_with_cli/python/test_main.py index b52d862..5f7ec58 100644 --- a/src/meilisearch_with_cli/python/test_main.py +++ b/src/meilisearch_with_cli/python/test_main.py @@ -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 diff --git a/src/mock_data/python/main.py b/src/mock_data/python/main.py index 1ed0cb0..869072b 100644 --- a/src/mock_data/python/main.py +++ b/src/mock_data/python/main.py @@ -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): diff --git a/src/parallelism/python/analyze.py b/src/parallelism/python/analyze.py index f427012..1da417b 100644 --- a/src/parallelism/python/analyze.py +++ b/src/parallelism/python/analyze.py @@ -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 diff --git a/src/parallelism/python/main.py b/src/parallelism/python/main.py index 2308a93..6fa2ee1 100644 --- a/src/parallelism/python/main.py +++ b/src/parallelism/python/main.py @@ -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 @@ -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 @@ -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() @@ -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: diff --git a/src/regex_json/python/main.py b/src/regex_json/python/main.py index 5ec1224..3671867 100644 --- a/src/regex_json/python/main.py +++ b/src/regex_json/python/main.py @@ -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 From c5130a3d88495022db39b3546545490c56e204a2 Mon Sep 17 00:00:00 2001 From: prrao87 Date: Thu, 10 Oct 2024 14:55:03 -0400 Subject: [PATCH 3/9] Update hello_world --- src/hello_world/README.md | 4 +++- src/hello_world/python/.python-version | 1 + src/hello_world/python/README.md | 0 src/hello_world/python/pyproject.toml | 7 +++++++ src/hello_world/python/uv.lock | 7 +++++++ 5 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/hello_world/python/.python-version create mode 100644 src/hello_world/python/README.md create mode 100644 src/hello_world/python/pyproject.toml create mode 100644 src/hello_world/python/uv.lock diff --git a/src/hello_world/README.md b/src/hello_world/README.md index aee8ea0..88a1b32 100644 --- a/src/hello_world/README.md +++ b/src/hello_world/README.md @@ -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 diff --git a/src/hello_world/python/.python-version b/src/hello_world/python/.python-version new file mode 100644 index 0000000..e4fba21 --- /dev/null +++ b/src/hello_world/python/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/src/hello_world/python/README.md b/src/hello_world/python/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/hello_world/python/pyproject.toml b/src/hello_world/python/pyproject.toml new file mode 100644 index 0000000..0911de9 --- /dev/null +++ b/src/hello_world/python/pyproject.toml @@ -0,0 +1,7 @@ +[project] +name = "proj" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [] diff --git a/src/hello_world/python/uv.lock b/src/hello_world/python/uv.lock new file mode 100644 index 0000000..7a5d0b6 --- /dev/null +++ b/src/hello_world/python/uv.lock @@ -0,0 +1,7 @@ +version = 1 +requires-python = ">=3.12" + +[[package]] +name = "proj" +version = "0.1.0" +source = { virtual = "." } From f44d7a1c3cbf3ecdffa94beded69873accd88771 Mon Sep 17 00:00:00 2001 From: prrao87 Date: Tue, 15 Oct 2024 22:26:56 -0400 Subject: [PATCH 4/9] Re-add root level pyproject.toml --- pyproject.toml | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..c3b54be --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,38 @@ +[tool.mypy] +check_untyped_defs = true +disallow_untyped_defs = true +plugins = ["pydantic.mypy"] + +[[tool.mypy.overrides]] +module = ["tests.*"] +disallow_untyped_defs = false + +[[tool.mypy.overrides]] +module = ["asyncpg.*", "srsly.*"] +ignore_missing_imports = true + +[tool.ruff] +line-length = 100 +target-version = "py38" +fix = true + +[tool.ruff.lint] +select=["E", "F", "UP", "I001"] +ignore=[ + # Recommened ignores by ruff when using formatter + "E501", + "W191", + "E111", + "E114", + "E117", + "D206", + "D300", + "Q000", + "Q001", + "Q002", + "Q003", + "COM812", + "COM819", + "ISC001", + "ISC002", +] From 6ff37e99c46bd593716fa0eaebd3059052466c42 Mon Sep 17 00:00:00 2001 From: prrao87 Date: Tue, 15 Oct 2024 22:27:52 -0400 Subject: [PATCH 5/9] Update .gitignore to ignore .python-version --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 3b2ef29..449d0fa 100644 --- a/.gitignore +++ b/.gitignore @@ -166,3 +166,6 @@ cython_debug/ /target /ci/data/* + +# Ignore .python-version generated by uv +.python-version From 028084951620c9583997ef7a120792bee2825267 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 02:28:36 +0000 Subject: [PATCH 6/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/datetime_parsing_csv/python/main.py | 4 +--- src/intro/python/main.py | 8 ++----- src/meilisearch_with_cli/python/main.py | 25 +++++--------------- src/meilisearch_with_cli/python/test_main.py | 4 +--- src/mock_data/python/main.py | 4 +--- src/parallelism/python/analyze.py | 4 +--- src/parallelism/python/main.py | 11 +++------ src/regex_json/python/main.py | 4 +--- 8 files changed, 16 insertions(+), 48 deletions(-) diff --git a/src/datetime_parsing_csv/python/main.py b/src/datetime_parsing_csv/python/main.py index ae4426f..133a837 100644 --- a/src/datetime_parsing_csv/python/main.py +++ b/src/datetime_parsing_csv/python/main.py @@ -13,9 +13,7 @@ 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"] diff --git a/src/intro/python/main.py b/src/intro/python/main.py index 1b284c7..2f56f89 100644 --- a/src/intro/python/main.py +++ b/src/intro/python/main.py @@ -89,9 +89,7 @@ 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 """ @@ -119,9 +117,7 @@ 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}") """ diff --git a/src/meilisearch_with_cli/python/main.py b/src/meilisearch_with_cli/python/main.py index 3e46105..68bfa4d 100644 --- a/src/meilisearch_with_cli/python/main.py +++ b/src/meilisearch_with_cli/python/main.py @@ -18,25 +18,18 @@ 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( @@ -79,12 +72,8 @@ 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) @@ -101,9 +90,7 @@ 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) diff --git a/src/meilisearch_with_cli/python/test_main.py b/src/meilisearch_with_cli/python/test_main.py index 5f7ec58..b52d862 100644 --- a/src/meilisearch_with_cli/python/test_main.py +++ b/src/meilisearch_with_cli/python/test_main.py @@ -118,9 +118,7 @@ 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 diff --git a/src/mock_data/python/main.py b/src/mock_data/python/main.py index 869072b..1ed0cb0 100644 --- a/src/mock_data/python/main.py +++ b/src/mock_data/python/main.py @@ -48,9 +48,7 @@ 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): diff --git a/src/parallelism/python/analyze.py b/src/parallelism/python/analyze.py index 1da417b..f427012 100644 --- a/src/parallelism/python/analyze.py +++ b/src/parallelism/python/analyze.py @@ -6,9 +6,7 @@ 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 diff --git a/src/parallelism/python/main.py b/src/parallelism/python/main.py index 6fa2ee1..9dd1be0 100644 --- a/src/parallelism/python/main.py +++ b/src/parallelism/python/main.py @@ -52,9 +52,7 @@ 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 @@ -63,9 +61,7 @@ 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 @@ -105,8 +101,7 @@ 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: diff --git a/src/regex_json/python/main.py b/src/regex_json/python/main.py index 3671867..5ec1224 100644 --- a/src/regex_json/python/main.py +++ b/src/regex_json/python/main.py @@ -42,9 +42,7 @@ 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 From 3236d5176d70010fd9e91624e20e0274e15c9ca6 Mon Sep 17 00:00:00 2001 From: Paul Sanders Date: Wed, 16 Oct 2024 08:27:59 -0400 Subject: [PATCH 7/9] Fix pyo3_mock_data CI build failure --- Cargo.lock | 24 ++-- src/pyo3_mock_data/Cargo.toml | 2 +- src/pyo3_mock_data/Makefile | 6 +- src/pyo3_mock_data/README.md | 21 ++-- src/pyo3_mock_data/pyproject.toml | 13 ++- src/pyo3_mock_data/requirements.txt | 5 - src/pyo3_mock_data/uv.lock | 174 ++++++++++++++++++++++++++++ 7 files changed, 210 insertions(+), 35 deletions(-) delete mode 100644 src/pyo3_mock_data/requirements.txt create mode 100644 src/pyo3_mock_data/uv.lock diff --git a/Cargo.lock b/Cargo.lock index 4077250..79f7e6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2064,15 +2064,15 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.21.2" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e00b96a521718e08e03b1a622f01c8a8deb50719335de3f60b3b3950f069d8" +checksum = "3d922163ba1f79c04bc49073ba7b32fd5a8d3b76a87c955921234b8e77333c51" dependencies = [ "cfg-if", "indoc", "libc", "memoffset", - "parking_lot", + "once_cell", "portable-atomic", "pyo3-build-config", "pyo3-ffi", @@ -2082,9 +2082,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.21.2" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7883df5835fafdad87c0d888b266c8ec0f4c9ca48a5bed6bbb592e8dedee1b50" +checksum = "bc38c5feeb496c8321091edf3d63e9a6829eab4b863b4a6a65f26f3e9cc6b179" dependencies = [ "once_cell", "target-lexicon", @@ -2092,9 +2092,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.21.2" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01be5843dc60b916ab4dad1dca6d20b9b4e6ddc8e15f50c47fe6d85f1fb97403" +checksum = "94845622d88ae274d2729fcefc850e63d7a3ddff5e3ce11bd88486db9f1d357d" dependencies = [ "libc", "pyo3-build-config", @@ -2102,9 +2102,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.21.2" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77b34069fc0682e11b31dbd10321cbf94808394c56fd996796ce45217dfac53c" +checksum = "e655aad15e09b94ffdb3ce3d217acf652e26bbc37697ef012f5e5e348c716e5e" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -2114,11 +2114,11 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.21.2" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08260721f32db5e1a5beae69a55553f56b99bd0e1c3e6e0a5e8851a9d0f5a85c" +checksum = "ae1e3f09eecd94618f60a455a23def79f79eba4dc561a97324bf9ac8c6df30ce" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "pyo3-build-config", "quote", diff --git a/src/pyo3_mock_data/Cargo.toml b/src/pyo3_mock_data/Cargo.toml index 7478c18..473e070 100644 --- a/src/pyo3_mock_data/Cargo.toml +++ b/src/pyo3_mock_data/Cargo.toml @@ -11,7 +11,7 @@ crate-type = ["cdylib"] [dependencies] csv = "1.3.0" fake = { version = "2.9.2", features = ["derive"] } -pyo3 = { version = "0.21.0", features = ["abi3-py38"] } +pyo3 = { version = "0.22.5", features = ["extension-module"] } rand = "0.8.5" serde = { version = "1.0.193", features = ["derive"] } unicode-normalization = "0.1.22" diff --git a/src/pyo3_mock_data/Makefile b/src/pyo3_mock_data/Makefile index a4189b1..6dd7a6a 100644 --- a/src/pyo3_mock_data/Makefile +++ b/src/pyo3_mock_data/Makefile @@ -8,12 +8,12 @@ lint: cargo clippy --all-targets --quiet develop: - maturin develop + uv run maturin develop release: - maturin develop -r + uv run maturin develop -r test: develop - pytest + uv run pytest all: format check lint test diff --git a/src/pyo3_mock_data/README.md b/src/pyo3_mock_data/README.md index 43cb9a0..5ea1a8c 100644 --- a/src/pyo3_mock_data/README.md +++ b/src/pyo3_mock_data/README.md @@ -31,7 +31,6 @@ makes sense to write a Rust extension that can be called from Python, which is t The dataset should be in the following format: - ```json { "id": "int", @@ -82,12 +81,12 @@ 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 +uv venv +source .venv/bin/activate +uv sync --frozen # For subsequent runs, simply activate the environment -source venv/bin/activate +source .venv/bin/activate ``` ### Build the Rust module @@ -100,7 +99,7 @@ or directly. make develop # Directly with Maturin -maturin develop +uv run maturin develop ``` ### Run script @@ -115,9 +114,9 @@ that someone :joy:. ```bash # Generate 10 mock person profiles -python main.py -n 10 +uv run python main.py -n 10 # Generate 1000 mock person profiles -python main.py -n 1000 +uv run python main.py -n 1000 ``` ### Run tests @@ -130,8 +129,8 @@ running the tests. If you run manually don't forget the build step before testin make test # manually -maturin develop -pytest +uv run maturin develop +uv run pytest ==================================================================================== test session starts ===================================================================================== platform linux -- Python 3.12.2, pytest-8.0.0, pluggy-1.4.0 @@ -165,7 +164,7 @@ can be done with either the provide Makefile or manually. make release # Manually -maturin develop -r +uv run maturin develop -r ``` ## Performance diff --git a/src/pyo3_mock_data/pyproject.toml b/src/pyo3_mock_data/pyproject.toml index ede8df1..0243461 100644 --- a/src/pyo3_mock_data/pyproject.toml +++ b/src/pyo3_mock_data/pyproject.toml @@ -4,12 +4,19 @@ build-backend = "maturin" [project] name = "pyo3-mock-data" -requires-python = ">=3.8" +requires-python = ">=3.9" [tool.maturin] module-name = "pyo3_mock_data._pyo3_mock_data" binding = "pyo3" -# features = ["pyo3/extension-module"] +features = ["pyo3/extension-module"] + +[tool.uv] +dev-dependencies = [ + "maturin==1.7.3", + "mypy==1.12.0", + "pytest==8.3.3", +] [tool.mypy] check_untyped_defs = true @@ -17,7 +24,7 @@ disallow_untyped_defs = true [tool.ruff] line-length = 100 -target-version = "py38" +target-version = "py39" fix = true [tool.ruff.lint] diff --git a/src/pyo3_mock_data/requirements.txt b/src/pyo3_mock_data/requirements.txt deleted file mode 100644 index 62241df..0000000 --- a/src/pyo3_mock_data/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -maturin~=1.5.1 -mypy~=1.8.0 -pytest~=8.1.1 - --e . diff --git a/src/pyo3_mock_data/uv.lock b/src/pyo3_mock_data/uv.lock new file mode 100644 index 0000000..2c0dd2c --- /dev/null +++ b/src/pyo3_mock_data/uv.lock @@ -0,0 +1,174 @@ +version = 1 +requires-python = ">=3.9" + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 }, +] + +[[package]] +name = "iniconfig" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 }, +] + +[[package]] +name = "maturin" +version = "1.7.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b5/5d/bbfeaa60a5d62cd70b7c28e21e44d4391b33b32bb152e661398c10b0c00e/maturin-1.7.3.tar.gz", hash = "sha256:8a52aa529eefb919dcc4ab5920e37dd5af0af630b6879d8a39b1e4f6ef301927", size = 190854 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/6a/7d83817bce23d81357649a800b4265d3808ecfd13888e93988a5efdd5e8f/maturin-1.7.3-py3-none-linux_armv6l.whl", hash = "sha256:32b2772d2b9a1bf6d8b18a4dc9e391991831b13e8fb330e858578147908e888a", size = 8215908 }, + { url = "https://files.pythonhosted.org/packages/fd/ca/915a5efc99785625901fd10ff18dfb416d97aa17bf0bceed11628c9c5950/maturin-1.7.3-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:37e36b330b79fdad77409d81b7e71e6301aa78fb36db250e2b2825cabb1c5852", size = 15930145 }, + { url = "https://files.pythonhosted.org/packages/a1/ee/043affa39635eab82a522f2ce394d6d1f2d94b916ce1006b16ee6cc87870/maturin-1.7.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ef90b22882b984825d2283659af6edf64a2a8b2d5197adce66f9e7361b275190", size = 8165578 }, + { url = "https://files.pythonhosted.org/packages/6c/06/0d489aecedc58d4955aa5e426f890e8a61f036dec94c2ba5f0f018bc2800/maturin-1.7.3-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:da2175709f31f73981fa1bcad655729c48f342b8ff44d5d421693e2ea5371eeb", size = 8563897 }, + { url = "https://files.pythonhosted.org/packages/63/df/9c1afe120a0f9a6528f7789ee6c634328e9d19b2291b41ec6ccc0d849493/maturin-1.7.3-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:79254c1453bbdcd4127b59014c1130c79b17017a1aa195c566f6804b2d8e0ff4", size = 8939490 }, + { url = "https://files.pythonhosted.org/packages/de/07/bf17348dcd78448f23f22d4acf424a00136afc3fa97b034c85ea3e225fd2/maturin-1.7.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:3cc8b7fb64b36290328e9df2ff8329ec2cbefbf7d5bf0b45a40025d58a40fd85", size = 8430139 }, + { url = "https://files.pythonhosted.org/packages/ee/49/9179ecc0ac9ca9e6daa9a23db729e46e584c9ec40e952dfb121af802b900/maturin-1.7.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:b70acc73a91a8d79eba1e68ab346bc42174733eb6b5c494d0fe9712cdb83474c", size = 8107175 }, + { url = "https://files.pythonhosted.org/packages/75/cf/03aa2c61d46c0f52d0d942f0c08fbf0c036a137022dc4fe951f9a2f8eb3e/maturin-1.7.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:d9e431d5e4ff874161931131b1b9fb7989d87e3371d1cadc3a49929f63f8a925", size = 8728035 }, + { url = "https://files.pythonhosted.org/packages/de/79/4545a0eca3bf47ceb42770d763b7e6df4965d9d9b3e42058bca366a0aaec/maturin-1.7.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:74b200371d01ecce9d75ac71b14bec098cfba19fe43450bae944724be0e3f2da", size = 10134019 }, + { url = "https://files.pythonhosted.org/packages/79/f9/8324be04b6250f6dc9e3e522ad633dad939ed842ff57be8ae25d7f5f2733/maturin-1.7.3-py3-none-win32.whl", hash = "sha256:2d2d81d16ffbbe7cc5cdb50e54831b4de2384fbcd233ae3b826c2e5f920dc1b2", size = 6580133 }, + { url = "https://files.pythonhosted.org/packages/9b/c7/b82a973418e4c727d80089291cf7dab7daedd34979af7075962d6f916032/maturin-1.7.3-py3-none-win_amd64.whl", hash = "sha256:c10aafee38aa387cce161a48d9a94102d20b599c80ac2a116ab21410ad5ed45f", size = 7438484 }, + { url = "https://files.pythonhosted.org/packages/00/bf/2f616e70d9630b8f2db1abb044562df4eb17adf0b2d793123e60fedc3fdf/maturin-1.7.3-py3-none-win_arm64.whl", hash = "sha256:5afa48b5ccd5c66c31fd06449fee0a5daed9f0bce80a9bad393120db3fe30be1", size = 6386624 }, +] + +[[package]] +name = "mypy" +version = "1.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mypy-extensions" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f9/70/196a3339459fe22296ac9a883bbd998fcaf0db3e8d9a54cf4f53b722cad4/mypy-1.12.0.tar.gz", hash = "sha256:65a22d87e757ccd95cbbf6f7e181e6caa87128255eb2b6be901bb71b26d8a99d", size = 3149879 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/6d/9751ed6d77b42a5d704224fbadf6f1a18b5ab655c012d17bc8af819a7f06/mypy-1.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4397081e620dc4dc18e2f124d5e1d2c288194c2c08df6bdb1db31c38cd1fe1ed", size = 11017763 }, + { url = "https://files.pythonhosted.org/packages/74/03/5fa6824555460f74873a414c7f42332c219fdfcfbd63b55b2442794b634b/mypy-1.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:684a9c508a283f324804fea3f0effeb7858eb03f85c4402a967d187f64562469", size = 10181032 }, + { url = "https://files.pythonhosted.org/packages/89/56/20d3136d6904c369422423d267c5ceb312487586cdd81e90bf7e237b67e7/mypy-1.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cabe4cda2fa5eca7ac94854c6c37039324baaa428ecbf4de4567279e9810f9e", size = 12587243 }, + { url = "https://files.pythonhosted.org/packages/53/cb/64043dec34fbcecaced207b077b8e5041e263da43003cc6309c90bc5e26e/mypy-1.12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:060a07b10e999ac9e7fa249ce2bdcfa9183ca2b70756f3bce9df7a92f78a3c0a", size = 13105170 }, + { url = "https://files.pythonhosted.org/packages/5e/59/e89758d47412ec6bd7a2fd9cae8074b7ffb2acee40456a4efbedd42e2dfd/mypy-1.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:0eff042d7257f39ba4ca06641d110ca7d2ad98c9c1fb52200fe6b1c865d360ff", size = 9633620 }, + { url = "https://files.pythonhosted.org/packages/21/68/9098b11b5c4371793237c7a2c5e9415ece358bed97bc849e9191d38c66b5/mypy-1.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b86de37a0da945f6d48cf110d5206c5ed514b1ca2614d7ad652d4bf099c7de7", size = 10940151 }, + { url = "https://files.pythonhosted.org/packages/7c/11/14a4373e5da6636fc4c8475cabe65084ff640528bc6c4f426d9c992736a9/mypy-1.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:20c7c5ce0c1be0b0aea628374e6cf68b420bcc772d85c3c974f675b88e3e6e57", size = 10107645 }, + { url = "https://files.pythonhosted.org/packages/c7/07/b73faeeaadabb5aab23195bfd828392c9a5e21e7b8cdf8369a2546e00ce6/mypy-1.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a64ee25f05fc2d3d8474985c58042b6759100a475f8237da1f4faf7fcd7e6309", size = 12504561 }, + { url = "https://files.pythonhosted.org/packages/78/70/c35608364f9cdf97c048f0240be4d06d3baadede2767a5fbf60aad7c64f3/mypy-1.12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:faca7ab947c9f457a08dcb8d9a8664fd438080e002b0fa3e41b0535335edcf7f", size = 12983108 }, + { url = "https://files.pythonhosted.org/packages/74/fa/e5b0d4291ed9b94075fe13a0cdd1d9f1ba9d32ea1f8e88aec2ffcd057ac3/mypy-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:5bc81701d52cc8767005fdd2a08c19980de9ec61a25dbd2a937dfb1338a826f9", size = 9629293 }, + { url = "https://files.pythonhosted.org/packages/e7/c8/ef6e2a11f0de6cf4359552bf71f07a89f302d27e25bf4c9761649bf1b5a8/mypy-1.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8462655b6694feb1c99e433ea905d46c478041a8b8f0c33f1dab00ae881b2164", size = 11072079 }, + { url = "https://files.pythonhosted.org/packages/61/e7/1f9ba3965c3c445d863290d3f8521a7a726b878784f5ad642e82c038261f/mypy-1.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:923ea66d282d8af9e0f9c21ffc6653643abb95b658c3a8a32dca1eff09c06475", size = 10071930 }, + { url = "https://files.pythonhosted.org/packages/3a/11/c84fb4c3a42ffd460c2a9b27105fbd538ec501e5aa34671fd3d14a1b94ba/mypy-1.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1ebf9e796521f99d61864ed89d1fb2926d9ab6a5fab421e457cd9c7e4dd65aa9", size = 12588227 }, + { url = "https://files.pythonhosted.org/packages/f0/ad/b55d070d2001e47c4c6c7d00b13f8dafb16b74db5a99904a183e3c0a3bd6/mypy-1.12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e478601cc3e3fa9d6734d255a59c7a2e5c2934da4378f3dd1e3411ea8a248642", size = 13037186 }, + { url = "https://files.pythonhosted.org/packages/28/c8/5fc9ef8d3ea89490939ecdfea7a84cede31a69534d468c34807941f5a79f/mypy-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:c72861b7139a4f738344faa0e150834467521a3fba42dc98264e5aa9507dd601", size = 9727738 }, + { url = "https://files.pythonhosted.org/packages/a6/07/0df1b099a4a725e61782f7d9a34947fc93be688f9dfa011d86e411b2f036/mypy-1.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52b9e1492e47e1790360a43755fa04101a7ac72287b1a53ce817f35899ba0521", size = 11071648 }, + { url = "https://files.pythonhosted.org/packages/9a/60/2a8bdb4f822bcdb0fa4599b83c1ae9f9ab0e10c1bee262dd9c1ff4607b12/mypy-1.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:48d3e37dd7d9403e38fa86c46191de72705166d40b8c9f91a3de77350daa0893", size = 10065760 }, + { url = "https://files.pythonhosted.org/packages/cc/d9/065ec6bd21a0ae14b520574d531dc1aa23fdc30fd276dea25f71945172d2/mypy-1.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2f106db5ccb60681b622ac768455743ee0e6a857724d648c9629a9bd2ac3f721", size = 12584005 }, + { url = "https://files.pythonhosted.org/packages/e6/a8/31449fc5698d1a55062614790a885128e3b2a21de0f82a426942a5ae6a00/mypy-1.12.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:233e11b3f73ee1f10efada2e6da0f555b2f3a5316e9d8a4a1224acc10e7181d3", size = 13030941 }, + { url = "https://files.pythonhosted.org/packages/b5/8e/2347814cffccfb52fc02cbe457ae4a3fb5b660c5b361cdf72374266c231b/mypy-1.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:4ae8959c21abcf9d73aa6c74a313c45c0b5a188752bf37dace564e29f06e9c1b", size = 9734383 }, + { url = "https://files.pythonhosted.org/packages/81/91/67f83e940b4e195b8c87ed9a64c48c6eb1513822b41df6594ef8fb4e0f9a/mypy-1.12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b5df6c8a8224f6b86746bda716bbe4dbe0ce89fd67b1fa4661e11bfe38e8ec8", size = 11013910 }, + { url = "https://files.pythonhosted.org/packages/9d/df/437261d0f622878822e52682a4b41c4387c99a322bf352af52ab58cf7c5a/mypy-1.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5feee5c74eb9749e91b77f60b30771563327329e29218d95bedbe1257e2fe4b0", size = 10179201 }, + { url = "https://files.pythonhosted.org/packages/2a/4e/d2fed1aa4ee487ccd5818afc3f926c81508ad5618c124cfa22d586e60d53/mypy-1.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:77278e8c6ffe2abfba6db4125de55f1024de9a323be13d20e4f73b8ed3402bd1", size = 12585797 }, + { url = "https://files.pythonhosted.org/packages/6e/d1/a971f6abc11221019bb41b2d7d94e807bcf1d9a4f51cf50e4ee27e5d0921/mypy-1.12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:dcfb754dea911039ac12434d1950d69a2f05acd4d56f7935ed402be09fad145e", size = 13102159 }, + { url = "https://files.pythonhosted.org/packages/9b/d5/dde4feae6ff046899a4da883abe678beed7e8633e92c1d2cb2714bd4478c/mypy-1.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:06de0498798527451ffb60f68db0d368bd2bae2bbfb5237eae616d4330cc87aa", size = 9631514 }, + { url = "https://files.pythonhosted.org/packages/85/fd/2cc64da1ce9fada64b5d023dfbaf763548429145d08c958c78c02876c7f6/mypy-1.12.0-py3-none-any.whl", hash = "sha256:fd313226af375d52e1e36c383f39bf3836e1f192801116b31b090dfcd3ec5266", size = 2645791 }, +] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 }, +] + +[[package]] +name = "packaging" +version = "24.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/51/65/50db4dda066951078f0a96cf12f4b9ada6e4b811516bf0262c0f4f7064d4/packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", size = 148788 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/aa/cc0199a5f0ad350994d660967a8efb233fe0416e4639146c089643407ce6/packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124", size = 53985 }, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, +] + +[[package]] +name = "pyo3-mock-data" +version = "0.1.0" +source = { editable = "." } + +[package.dev-dependencies] +dev = [ + { name = "maturin" }, + { name = "mypy" }, + { name = "pytest" }, +] + +[package.metadata] + +[package.metadata.requires-dev] +dev = [ + { name = "maturin", specifier = "==1.7.3" }, + { name = "mypy", specifier = "==1.12.0" }, + { name = "pytest", specifier = "==8.3.3" }, +] + +[[package]] +name = "pytest" +version = "8.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8b/6c/62bbd536103af674e227c41a8f3dcd022d591f6eed5facb5a0f31ee33bbc/pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181", size = 1442487 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6b/77/7440a06a8ead44c7757a64362dd22df5760f9b12dc5f11b6188cd2fc27a0/pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2", size = 342341 }, +] + +[[package]] +name = "tomli" +version = "2.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/35/b9/de2a5c0144d7d75a57ff355c0c24054f965b2dc3036456ae03a51ea6264b/tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed", size = 16096 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/db/ce8eda256fa131af12e0a76d481711abe4681b6923c27efb9a255c9e4594/tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38", size = 13237 }, +] + +[[package]] +name = "typing-extensions" +version = "4.12.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, +] From 423cd004b0eb41545aed8fe7e15b7f00bb0d1125 Mon Sep 17 00:00:00 2001 From: prrao87 Date: Fri, 1 Nov 2024 10:18:22 -0400 Subject: [PATCH 8/9] Update intro --- src/intro/README.md | 6 +++--- src/intro/python/pyproject.toml | 7 +++++++ src/intro/python/uv.lock | 7 +++++++ src/simple_csv/README.md | 8 ++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 src/intro/python/pyproject.toml create mode 100644 src/intro/python/uv.lock diff --git a/src/intro/README.md b/src/intro/README.md index e890d92..0770e3d 100644 --- a/src/intro/README.md +++ b/src/intro/README.md @@ -50,11 +50,11 @@ Is "AMD Ryzen 3" in the hashset of processors?: true ### Setup and run -No dependencies are necessary -- simply install the latest version of Python and run the script -`main.py`. +No dependencies are necessary -- simply navigate to the `intro/python` directory and run the script +using the `uv` package manager. ```bash -python main.py +uv run main.py ``` ## Rust diff --git a/src/intro/python/pyproject.toml b/src/intro/python/pyproject.toml new file mode 100644 index 0000000..0911de9 --- /dev/null +++ b/src/intro/python/pyproject.toml @@ -0,0 +1,7 @@ +[project] +name = "proj" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [] diff --git a/src/intro/python/uv.lock b/src/intro/python/uv.lock new file mode 100644 index 0000000..7a5d0b6 --- /dev/null +++ b/src/intro/python/uv.lock @@ -0,0 +1,7 @@ +version = 1 +requires-python = ">=3.12" + +[[package]] +name = "proj" +version = "0.1.0" +source = { virtual = "." } diff --git a/src/simple_csv/README.md b/src/simple_csv/README.md index 4662b1b..3aa5b55 100644 --- a/src/simple_csv/README.md +++ b/src/simple_csv/README.md @@ -61,6 +61,14 @@ For this project, we only need the standard library of Python, so there are no d ### Run script +First, sync the dependencies from `pyproject.toml`. + +```bash +uv sync +``` + +The script can be then run using the following command. + ```bash uv run main.py ``` From c9468d08df395b91ca0cac298b1ca17a36bbabe2 Mon Sep 17 00:00:00 2001 From: prrao87 Date: Fri, 1 Nov 2024 10:19:05 -0400 Subject: [PATCH 9/9] Update deps --- src/intro/python/pyproject.toml | 5 ++ src/intro/python/uv.lock | 120 ++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) diff --git a/src/intro/python/pyproject.toml b/src/intro/python/pyproject.toml index 0911de9..8c11e94 100644 --- a/src/intro/python/pyproject.toml +++ b/src/intro/python/pyproject.toml @@ -5,3 +5,8 @@ description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = [] + +[tool.uv] +dev-dependencies = [ + "pre-commit>=4.0.1", +] diff --git a/src/intro/python/uv.lock b/src/intro/python/uv.lock index 7a5d0b6..3f93a93 100644 --- a/src/intro/python/uv.lock +++ b/src/intro/python/uv.lock @@ -1,7 +1,127 @@ version = 1 requires-python = ">=3.12" +[[package]] +name = "cfgv" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249 }, +] + +[[package]] +name = "distlib" +version = "0.3.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/dd/1bec4c5ddb504ca60fc29472f3d27e8d4da1257a854e1d96742f15c1d02d/distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403", size = 613923 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/a1/cf2472db20f7ce4a6be1253a81cfdf85ad9c7885ffbed7047fb72c24cf87/distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", size = 468973 }, +] + +[[package]] +name = "filelock" +version = "3.16.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9d/db/3ef5bb276dae18d6ec2124224403d1d67bccdbefc17af4cc8f553e341ab1/filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435", size = 18037 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/f8/feced7779d755758a52d1f6635d990b8d98dc0a29fa568bbe0625f18fdf3/filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0", size = 16163 }, +] + +[[package]] +name = "identify" +version = "2.6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/29/bb/25024dbcc93516c492b75919e76f389bac754a3e4248682fba32b250c880/identify-2.6.1.tar.gz", hash = "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98", size = 99097 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7d/0c/4ef72754c050979fdcc06c744715ae70ea37e734816bb6514f79df77a42f/identify-2.6.1-py2.py3-none-any.whl", hash = "sha256:53863bcac7caf8d2ed85bd20312ea5dcfc22226800f6d6881f232d861db5a8f0", size = 98972 }, +] + +[[package]] +name = "nodeenv" +version = "1.9.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314 }, +] + +[[package]] +name = "platformdirs" +version = "4.3.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 }, +] + +[[package]] +name = "pre-commit" +version = "4.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cfgv" }, + { name = "identify" }, + { name = "nodeenv" }, + { name = "pyyaml" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2e/c8/e22c292035f1bac8b9f5237a2622305bc0304e776080b246f3df57c4ff9f/pre_commit-4.0.1.tar.gz", hash = "sha256:80905ac375958c0444c65e9cebebd948b3cdb518f335a091a670a89d652139d2", size = 191678 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/16/8f/496e10d51edd6671ebe0432e33ff800aa86775d2d147ce7d43389324a525/pre_commit-4.0.1-py2.py3-none-any.whl", hash = "sha256:efde913840816312445dc98787724647c65473daefe420785f885e8ed9a06878", size = 218713 }, +] + [[package]] name = "proj" version = "0.1.0" source = { virtual = "." } + +[package.dev-dependencies] +dev = [ + { name = "pre-commit" }, +] + +[package.metadata] + +[package.metadata.requires-dev] +dev = [{ name = "pre-commit", specifier = ">=4.0.1" }] + +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223 }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542 }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164 }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611 }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, +] + +[[package]] +name = "virtualenv" +version = "20.27.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8c/b3/7b6a79c5c8cf6d90ea681310e169cf2db2884f4d583d16c6e1d5a75a4e04/virtualenv-20.27.1.tar.gz", hash = "sha256:142c6be10212543b32c6c45d3d3893dff89112cc588b7d0879ae5a1ec03a47ba", size = 6491145 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ae/92/78324ff89391e00c8f4cf6b8526c41c6ef36b4ea2d2c132250b1a6fc2b8d/virtualenv-20.27.1-py3-none-any.whl", hash = "sha256:f11f1b8a29525562925f745563bfd48b189450f61fb34c4f9cc79dd5aa32a1f4", size = 3117838 }, +]