diff --git a/ms_sample_list_creator/csv_batch.py b/ms_sample_list_creator/csv_batch.py index 0303120..bde4597 100644 --- a/ms_sample_list_creator/csv_batch.py +++ b/ms_sample_list_creator/csv_batch.py @@ -1,8 +1,12 @@ +import csv import os import tkinter as tk from datetime import datetime from tkinter import filedialog +import pandas as pd +import requests + class csvBatch(tk.Frame): def __init__(self, csv_batch_window: tk.Toplevel, root: tk.Tk): @@ -32,7 +36,7 @@ def __init__(self, csv_batch_window: tk.Toplevel, root: tk.Tk): self.pre_blk = int(str(os.environ.get("PRE_BLK"))) self.post_blk = int(str(os.environ.get("POST_BLK"))) self.blk_name = str(os.environ.get("BLK_NAME")) - self.blk_pos = str(os.environ.get("LK_POS")) + self.blk_pos = str(os.environ.get("BLK_POS")) self.inj_volume = int(str(os.environ.get("INJ_VOLUME"))) self.access_token = str(os.environ.get("ACCESS_TOKEN")) self.method_file = str(os.environ.get("METHOD_FILE")) @@ -41,14 +45,14 @@ def __init__(self, csv_batch_window: tk.Toplevel, root: tk.Tk): self.file = str(os.environ.get("FILE")) self.current_position = 1 self.current_row = 1 - self.timestamp = datetime.now().strftime("%Y%m%d%H%M") + self.timestamp = "202404101527"#datetime.now().strftime("%Y%m%d%H%M") self.csv_path = f"{self.output_folder}/{datetime.now().strftime('%Y%m%d')}_{self.operator}_dbgi_{self.file}.csv" - warning_label = tk.Label( + self.warning_label = tk.Label( self.csv_batch_window, text="Warning, this mode is exclusively made to submit sample lists that have already been made using this tool.", ) - warning_label.pack() + self.warning_label.pack() label = tk.Label(self.csv_batch_window, text="Search for your CSV:", pady=10) label.pack() @@ -99,4 +103,117 @@ def submit_result(self) -> None: Returns: None """ - print("correctly written") + # Retrieves file path and method name given by the user + file_path = os.environ.get("FILE_PATH") + self.file = str(os.environ.get("FILE")) + + # Converts the CSV to a dataframe + df = pd.read_csv(str(file_path), skiprows=1) + + # Delete standby row + df = df.drop(df.index[-1]) + + # Remove blanks + patterns = ["pre", "post"] + combined_patterns = "|".join(patterns) + filtered_df = df[~df["File Name"].str.contains(combined_patterns, regex=True)] + + # Update data path, instrument method and injection volume + path = self.data_path.replace("/", "\\") + instrument_method = self.method_file.replace("/", "\\") + filtered_df["Path"] = path + filtered_df["Instrument Method"] = instrument_method + filtered_df["Inj Vol"] = self.inj_volume + + # Change timestamp and operator initials + filtered_df["File Name"] = df["File Name"].apply( + lambda x: "_".join([self.timestamp, self.operator] + x.split("_")[2:]) + ) + + # Prepare data for directus + directus_df = filtered_df + directus_df = directus_df.drop(columns=["Path", "Position"]) + directus_df["aliquot_id"] = "" + directus_df["ms_id"] = self.ms_id + directus_df = directus_df.rename(columns={"File Name": "mass_spec_id"}) + directus_df = directus_df.rename(columns={"Inj Vol": "injection_volume"}) + directus_df = directus_df.rename(columns={"Instrument Method": "injection_method"}) + directus_df["injection_method"] = self.file + for index, row in directus_df.iterrows(): # Iterate over rows using iterrows() + parts = row["mass_spec_id"].split("_") # Split the "File Name" column by underscores + aliquot_id = "_".join(parts[2:]) # Extract the desired parts of the split string + directus_df.at[index, "aliquot_id"] = aliquot_id + + # Send data to directus + records = directus_df.to_json(orient="records") + base_url = "http://directus.dbgi.org" + collection_url = base_url + "/items/Mass_Spectrometry_Analysis" + session = requests.Session() + headers = {"Content-Type": "application/json"} + session.headers.update({"Authorization": f"Bearer {self.access_token}"}) + response = session.post(url=collection_url, headers=headers, data=records) + + # Check if correctly added to directus + if response.status_code == 200: + self.warning_label.config(text="Success!! Writing CSV...", foreground="green") + # Write data to the CSV file + with open(self.csv_path, "w", newline="") as csv_file: + csv_writer = csv.writer(csv_file) + # Write headers + csv_writer.writerow(["Bracket Type=4", "", "", "", ""]) + csv_writer.writerow(["File Name", "Path", "Instrument Method", "Position", "Inj Vol"]) + + # Write pre blanks + if self.pre_blk > 0: + for i in range(1, self.pre_blk + 1): + padded_number = str(i).zfill(2) + filename = ( + self.timestamp + "_" + self.operator + "_dbgi_" + self.blk_name + "_blk_pre" + padded_number + ) + path = self.data_path.replace("/", "\\") + instrument_method = self.method_file.replace("/", "\\") + position = self.blk_pos + inj_volume = self.inj_volume + csv_writer.writerow([filename, path, instrument_method, position, inj_volume]) + else: + print("no pre blanks") + + # Write data + csv_writer.writerows(filtered_df.values) + + # Write post blanks + if self.post_blk > 0: + for i in range(1, self.post_blk + 1): + padded_number = str(i).zfill(2) + filename = ( + self.timestamp + + "_" + + self.operator + + "_dbgi_" + + self.blk_name + + "_blk_post" + + padded_number + ) + path = self.data_path.replace("/", "\\") + instrument_method = self.method_file.replace("/", "\\") + position = self.blk_pos + inj_volume = self.inj_volume + csv_writer.writerow([filename, path, instrument_method, position, inj_volume]) + else: + print("no post blanks") + + # Write standby line + parts = self.standby_file.split("/") + file = parts[-1] + filename = self.timestamp + "_" + self.operator + "_" + file + path = self.data_path.replace("/", "\\") + standby = self.standby_file.replace("/", "\\") + position = self.blk_pos + inj_volume = self.inj_volume + csv_writer.writerow([filename, path, standby, position, inj_volume]) + + # Close the Tkinter window + self.csv_batch_window.destroy() + self.root.destroy() + else: + self.warning_label.config(text="Directus error, please check your CSV.", foreground="red") diff --git a/ms_sample_list_creator/home_page.py b/ms_sample_list_creator/home_page.py index cff7893..ed64ff6 100644 --- a/ms_sample_list_creator/home_page.py +++ b/ms_sample_list_creator/home_page.py @@ -50,8 +50,10 @@ def __init__(self, parent: tk.Tk, *args: Any, **kwargs: Any): frame_entries_up.pack(fill="x", pady=5) entry_username = tk.Entry(frame_entries_up, textvariable=self.username) + self.username.set("edouard.bruelhart@unifr.ch") entry_username.pack(side="left", anchor="center") entry_password = tk.Entry(frame_entries_up, textvariable=self.password, show="*") + self.password.set("861510Eb.98") entry_password.pack(side="right", anchor="center") frame_labels_om = tk.Frame(self) @@ -67,9 +69,11 @@ def __init__(self, parent: tk.Tk, *args: Any, **kwargs: Any): frame_entries_om.pack(fill="x", pady=(5, 0)) entry_operator = tk.Entry(frame_entries_om, textvariable=self.operator) + self.operator.set("EB") entry_operator.pack(side="left", anchor="center") entry_ms = tk.Entry(frame_entries_om, textvariable=self.ms_id) + self.ms_id.set("ms_000001") entry_ms.pack(side="right", anchor="center") frame_label_rack = tk.Frame(self) diff --git a/ms_sample_list_creator/ms_sample_list_creator.py b/ms_sample_list_creator/ms_sample_list_creator.py index 24c4b76..2aa6a8b 100644 --- a/ms_sample_list_creator/ms_sample_list_creator.py +++ b/ms_sample_list_creator/ms_sample_list_creator.py @@ -1,8 +1,8 @@ -# To generate binaries for this script, install pyinstaller (pip install pyinstaller) and run "pyinstaller --onefile main.py" +# To generate binaries for this script, install pyinstaller (pip install pyinstaller) and run "pyinstaller --onefile ms_sample_list_creator.py" # Generated binaries are made for the native system where the pyinstaller command is run. # You can generate windows executable from linux using wine, by previously installing wine, python 3.8.19, pyinstaller and -# other non-built-in packages (here requests) inside wine. Then run: wine pyinstaller --onefile main.py +# other non-built-in packages (here requests and pandas) inside wine. Then run: wine pyinstaller --onefile ms_sample_list_creator.py import tkinter as tk @@ -29,6 +29,7 @@ def submit_results(clicked_button: str) -> None: def handle_user_choice() -> None: """ Collect user choice and transmits it to de function that shows the correct window. + ;C:\users\edouard\Local Settings\Application Data\Programs\Python\Python38\Scripts Args: None @@ -43,15 +44,6 @@ def handle_user_choice() -> None: def show_selected_window(choice: str) -> None: - """ - Accepts user choice and launches the correct window. - - Args: - choice (str): Retrieves the user choice. - - Returns: - None - """ if choice == "new": # Create a new Toplevel window for the new batch new_batch_window = tk.Toplevel(root) diff --git a/ms_sample_list_creator/ms_test.exe b/ms_sample_list_creator/ms_test.exe new file mode 100755 index 0000000..add6c17 Binary files /dev/null and b/ms_sample_list_creator/ms_test.exe differ diff --git a/ms_sample_list_creator/new_batch.py b/ms_sample_list_creator/new_batch.py index 595cf9d..004a85a 100644 --- a/ms_sample_list_creator/new_batch.py +++ b/ms_sample_list_creator/new_batch.py @@ -36,7 +36,7 @@ def __init__(self, new_batch_window: tk.Toplevel, root: tk.Tk): self.pre_blk = int(str(os.environ.get("PRE_BLK"))) self.post_blk = int(str(os.environ.get("POST_BLK"))) self.blk_name = str(os.environ.get("BLK_NAME")) - self.blk_pos = str(os.environ.get("LK_POS")) + self.blk_pos = str(os.environ.get("BLK_POS")) self.inj_volume = int(str(os.environ.get("INJ_VOLUME"))) self.access_token = str(os.environ.get("ACCESS_TOKEN")) self.method_file = str(os.environ.get("METHOD_FILE")) @@ -165,7 +165,7 @@ def add_row(self, event: Optional[tk.Event] = None) -> None: self.label.config(text="") - if response.status_code == 200: + if response.status_code != 200: # Check if it is the first run or not the first position in the rack if (self.current_position > self.col_rack_size and self.current_position > self.col_rack_size) or ( self.current_position == 1 and self.current_row == 1 diff --git a/poetry.lock b/poetry.lock index 9f5b127..396292c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -414,6 +414,43 @@ files = [ [package.dependencies] setuptools = "*" +[[package]] +name = "numpy" +version = "1.24.4" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64"}, + {file = "numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1"}, + {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4"}, + {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6"}, + {file = "numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc"}, + {file = "numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e"}, + {file = "numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810"}, + {file = "numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254"}, + {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7"}, + {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5"}, + {file = "numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d"}, + {file = "numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694"}, + {file = "numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61"}, + {file = "numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f"}, + {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e"}, + {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc"}, + {file = "numpy-1.24.4-cp38-cp38-win32.whl", hash = "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2"}, + {file = "numpy-1.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706"}, + {file = "numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400"}, + {file = "numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f"}, + {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9"}, + {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d"}, + {file = "numpy-1.24.4-cp39-cp39-win32.whl", hash = "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835"}, + {file = "numpy-1.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2"}, + {file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"}, +] + [[package]] name = "packaging" version = "24.0" @@ -425,6 +462,83 @@ files = [ {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, ] +[[package]] +name = "pandas" +version = "2.0.3" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pandas-2.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4c7c9f27a4185304c7caf96dc7d91bc60bc162221152de697c98eb0b2648dd8"}, + {file = "pandas-2.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f167beed68918d62bffb6ec64f2e1d8a7d297a038f86d4aed056b9493fca407f"}, + {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce0c6f76a0f1ba361551f3e6dceaff06bde7514a374aa43e33b588ec10420183"}, + {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba619e410a21d8c387a1ea6e8a0e49bb42216474436245718d7f2e88a2f8d7c0"}, + {file = "pandas-2.0.3-cp310-cp310-win32.whl", hash = "sha256:3ef285093b4fe5058eefd756100a367f27029913760773c8bf1d2d8bebe5d210"}, + {file = "pandas-2.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:9ee1a69328d5c36c98d8e74db06f4ad518a1840e8ccb94a4ba86920986bb617e"}, + {file = "pandas-2.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b084b91d8d66ab19f5bb3256cbd5ea661848338301940e17f4492b2ce0801fe8"}, + {file = "pandas-2.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37673e3bdf1551b95bf5d4ce372b37770f9529743d2498032439371fc7b7eb26"}, + {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9cb1e14fdb546396b7e1b923ffaeeac24e4cedd14266c3497216dd4448e4f2d"}, + {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9cd88488cceb7635aebb84809d087468eb33551097d600c6dad13602029c2df"}, + {file = "pandas-2.0.3-cp311-cp311-win32.whl", hash = "sha256:694888a81198786f0e164ee3a581df7d505024fbb1f15202fc7db88a71d84ebd"}, + {file = "pandas-2.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:6a21ab5c89dcbd57f78d0ae16630b090eec626360085a4148693def5452d8a6b"}, + {file = "pandas-2.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4da0d45e7f34c069fe4d522359df7d23badf83abc1d1cef398895822d11061"}, + {file = "pandas-2.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:32fca2ee1b0d93dd71d979726b12b61faa06aeb93cf77468776287f41ff8fdc5"}, + {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:258d3624b3ae734490e4d63c430256e716f488c4fcb7c8e9bde2d3aa46c29089"}, + {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eae3dc34fa1aa7772dd3fc60270d13ced7346fcbcfee017d3132ec625e23bb0"}, + {file = "pandas-2.0.3-cp38-cp38-win32.whl", hash = "sha256:f3421a7afb1a43f7e38e82e844e2bca9a6d793d66c1a7f9f0ff39a795bbc5e02"}, + {file = "pandas-2.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:69d7f3884c95da3a31ef82b7618af5710dba95bb885ffab339aad925c3e8ce78"}, + {file = "pandas-2.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5247fb1ba347c1261cbbf0fcfba4a3121fbb4029d95d9ef4dc45406620b25c8b"}, + {file = "pandas-2.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:81af086f4543c9d8bb128328b5d32e9986e0c84d3ee673a2ac6fb57fd14f755e"}, + {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1994c789bf12a7c5098277fb43836ce090f1073858c10f9220998ac74f37c69b"}, + {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ec591c48e29226bcbb316e0c1e9423622bc7a4eaf1ef7c3c9fa1a3981f89641"}, + {file = "pandas-2.0.3-cp39-cp39-win32.whl", hash = "sha256:04dbdbaf2e4d46ca8da896e1805bc04eb85caa9a82e259e8eed00254d5e0c682"}, + {file = "pandas-2.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:1168574b036cd8b93abc746171c9b4f1b83467438a5e45909fed645cf8692dbc"}, + {file = "pandas-2.0.3.tar.gz", hash = "sha256:c02f372a88e0d17f36d3093a644c73cfc1788e876a7c4bcb4020a77512e2043c"}, +] + +[package.dependencies] +numpy = {version = ">=1.20.3", markers = "python_version < \"3.10\""} +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.1" + +[package.extras] +all = ["PyQt5 (>=5.15.1)", "SQLAlchemy (>=1.4.16)", "beautifulsoup4 (>=4.9.3)", "bottleneck (>=1.3.2)", "brotlipy (>=0.7.0)", "fastparquet (>=0.6.3)", "fsspec (>=2021.07.0)", "gcsfs (>=2021.07.0)", "html5lib (>=1.1)", "hypothesis (>=6.34.2)", "jinja2 (>=3.0.0)", "lxml (>=4.6.3)", "matplotlib (>=3.6.1)", "numba (>=0.53.1)", "numexpr (>=2.7.3)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pandas-gbq (>=0.15.0)", "psycopg2 (>=2.8.6)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "python-snappy (>=0.6.0)", "pyxlsb (>=1.0.8)", "qtpy (>=2.2.0)", "s3fs (>=2021.08.0)", "scipy (>=1.7.1)", "tables (>=3.6.1)", "tabulate (>=0.8.9)", "xarray (>=0.21.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)", "zstandard (>=0.15.2)"] +aws = ["s3fs (>=2021.08.0)"] +clipboard = ["PyQt5 (>=5.15.1)", "qtpy (>=2.2.0)"] +compression = ["brotlipy (>=0.7.0)", "python-snappy (>=0.6.0)", "zstandard (>=0.15.2)"] +computation = ["scipy (>=1.7.1)", "xarray (>=0.21.0)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pyxlsb (>=1.0.8)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)"] +feather = ["pyarrow (>=7.0.0)"] +fss = ["fsspec (>=2021.07.0)"] +gcp = ["gcsfs (>=2021.07.0)", "pandas-gbq (>=0.15.0)"] +hdf5 = ["tables (>=3.6.1)"] +html = ["beautifulsoup4 (>=4.9.3)", "html5lib (>=1.1)", "lxml (>=4.6.3)"] +mysql = ["SQLAlchemy (>=1.4.16)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.0.0)", "tabulate (>=0.8.9)"] +parquet = ["pyarrow (>=7.0.0)"] +performance = ["bottleneck (>=1.3.2)", "numba (>=0.53.1)", "numexpr (>=2.7.1)"] +plot = ["matplotlib (>=3.6.1)"] +postgresql = ["SQLAlchemy (>=1.4.16)", "psycopg2 (>=2.8.6)"] +spss = ["pyreadstat (>=1.1.2)"] +sql-other = ["SQLAlchemy (>=1.4.16)"] +test = ["hypothesis (>=6.34.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.6.3)"] + +[[package]] +name = "pandas-stubs" +version = "2.0.3.230814" +description = "Type annotations for pandas" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pandas_stubs-2.0.3.230814-py3-none-any.whl", hash = "sha256:4b3dfc027d49779176b7daa031a3405f7b839bcb6e312f4b9f29fea5feec5b4f"}, + {file = "pandas_stubs-2.0.3.230814.tar.gz", hash = "sha256:1d5cc09e36e3d9f9a1ed9dceae4e03eeb26d1b898dd769996925f784365c8769"}, +] + +[package.dependencies] +types-pytz = ">=2022.1.1" + [[package]] name = "pefile" version = "2023.2.7" @@ -594,6 +708,31 @@ pytest = ">=4.6" [package.extras] testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytz" +version = "2024.1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, +] + [[package]] name = "pywin32-ctypes" version = "0.2.2" @@ -702,6 +841,17 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + [[package]] name = "tomli" version = "2.0.1" @@ -740,6 +890,17 @@ virtualenv = ">=20.25" docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-argparse-cli (>=1.11.1)", "sphinx-autodoc-typehints (>=1.25.2)", "sphinx-copybutton (>=0.5.2)", "sphinx-inline-tabs (>=2023.4.21)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.11)"] testing = ["build[virtualenv] (>=1.0.3)", "covdefaults (>=2.3)", "detect-test-pollution (>=1.2)", "devpi-process (>=1)", "diff-cover (>=8.0.2)", "distlib (>=0.3.8)", "flaky (>=3.7)", "hatch-vcs (>=0.4)", "hatchling (>=1.21)", "psutil (>=5.9.7)", "pytest (>=7.4.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-xdist (>=3.5)", "re-assert (>=1.1)", "time-machine (>=2.13)", "wheel (>=0.42)"] +[[package]] +name = "types-pytz" +version = "2024.1.0.20240203" +description = "Typing stubs for pytz" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-pytz-2024.1.0.20240203.tar.gz", hash = "sha256:c93751ee20dfc6e054a0148f8f5227b9a00b79c90a4d3c9f464711a73179c89e"}, + {file = "types_pytz-2024.1.0.20240203-py3-none-any.whl", hash = "sha256:9679eef0365db3af91ef7722c199dbb75ee5c1b67e3c4dd7bfbeb1b8a71c21a3"}, +] + [[package]] name = "types-requests" version = "2.31.0.20240406" @@ -765,6 +926,17 @@ files = [ {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, ] +[[package]] +name = "tzdata" +version = "2024.1" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, + {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, +] + [[package]] name = "urllib3" version = "2.2.1" @@ -820,4 +992,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.8.18,<=3.8.19" -content-hash = "c0196ea9497fa39d8ec15385c345cb0c1ec91cd8ebcd99887bd3f1809ab384c8" +content-hash = "d8326a131a4b36ce2a3de0254fc174fea9932bd54b2f1611f06f6c0ecf376472" diff --git a/pyproject.toml b/pyproject.toml index 6e932d9..cf55359 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,8 @@ types-requests = "^2.31.0.20240406" pyinstaller = "^6.5.0" pytest = "^7.2.0" pytest-cov = "^5.0.0" +pandas = "^2.0.3" +pandas-stubs = "^2.0.3" [tool.poetry.group.dev.dependencies] mypy = "^1.5.1"