diff --git a/.gitignore b/.gitignore index b7faf40..da44c85 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,171 @@ +# Created by https://www.toptal.com/developers/gitignore/api/windows,linux,macos,visualstudiocode,pycharm,python +# Edit at https://www.toptal.com/developers/gitignore?templates=windows,linux,macos,visualstudiocode,pycharm,python + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### PyCharm ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### PyCharm Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint +.idea/**/sonarlint/ + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator-enh.xml +.idea/**/markdown-navigator/ + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 +.idea/$CACHE_FILE$ + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream +.idea/codestream.xml + +# Azure Toolkit for IntelliJ plugin +# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij +.idea/**/azureSettings.xml + +### Python ### # Byte-compiled / optimized / DLL files __pycache__/ -*.py[codz] +*.py[cod] *$py.class # C extensions @@ -46,7 +211,7 @@ htmlcov/ nosetests.xml coverage.xml *.cover -*.py.cover +*.py,cover .hypothesis/ .pytest_cache/ cover/ @@ -94,35 +259,20 @@ ipython_config.py # install all needed dependencies. #Pipfile.lock -# UV -# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -#uv.lock - # poetry # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. # This is especially recommended for binary packages to ensure reproducibility, and is more # commonly ignored for libraries. # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control #poetry.lock -#poetry.toml # pdm # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python. -# https://pdm-project.org/en/latest/usage/project/#working-with-version-control #pdm.lock -#pdm.toml -.pdm-python -.pdm-build/ - -# pixi -# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control. -#pixi.lock -# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one -# in the .venv directory. It is recommended not to include this directory in version control. -.pixi +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm __pypackages__/ @@ -136,7 +286,6 @@ celerybeat.pid # Environments .env -.envrc .venv env/ venv/ @@ -175,33 +324,61 @@ cython_debug/ # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ -# Abstra -# Abstra is an AI-powered process automation framework. -# Ignore directories containing user credentials, local state, and settings. -# Learn more at https://abstra.io/docs -.abstra/ +### Python Patch ### +# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration +poetry.toml -# Visual Studio Code -# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore -# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore -# and can be added to the global gitignore or merged into this file. However, if you prefer, -# you could uncomment the following to ignore the entire vscode folder -# .vscode/ - -# Ruff stuff: +# ruff .ruff_cache/ -# PyPI configuration file -.pypirc +# LSP config files +pyrightconfig.json -# Cursor -# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to -# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data -# refer to https://docs.cursor.com/context/ignore-files -.cursorignore -.cursorindexingignore +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets -# Marimo -marimo/_static/ -marimo/_lsp/ -__marimo__/ +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.toptal.com/developers/gitignore/api/windows,linux,macos,visualstudiocode,pycharm,python + +playgournd/ \ No newline at end of file diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..2c07333 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.11 diff --git a/README.md b/README.md index 2a24828..d733e6c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # python_utils + Useful Python utils and scripts diff --git a/common_utils.py b/common_utils.py new file mode 100644 index 0000000..20cca1d --- /dev/null +++ b/common_utils.py @@ -0,0 +1,18 @@ +import sys +from pathlib import Path + +BASE_DIR = Path(__file__).resolve().parent + + +def boolean_to_emooji(bool_val, primary_emooji: bool): + if primary_emooji: + return "✅" if bool_val else "❌" + return "☑️" if bool_val else "✖️" + + +def confirm_exit_terminal(): + user_input = input('\n\nType "q" to exit.\n') + if user_input != "q": + return confirm_exit_terminal() + else: + sys.exit() diff --git a/excel_utls.py b/excel_utls.py new file mode 100644 index 0000000..df54515 --- /dev/null +++ b/excel_utls.py @@ -0,0 +1,56 @@ +from pathlib import Path + +from openpyxl import Workbook, load_workbook +from openpyxl.utils import get_column_letter + +BASE_DIR = Path(__file__).resolve().parent + +EXCEL_FILE_PATH = BASE_DIR / "spreadsheet.xlsx" + +EXCEL_HEADERS = [ + "Row", + "Column Header 1", + "Column Header 2", + "Column Header 3", +] + + +def create_excel_with_headers(file_path=EXCEL_FILE_PATH, headers_list=EXCEL_HEADERS): + wb = Workbook() + ws = wb.active + ws.title = "TD_0_to_LS_export_result" + ws.append(headers_list) + wb.save(filename=file_path) + return True + + +def add_row_to_excel(row_list, file_path=EXCEL_FILE_PATH, headers=EXCEL_HEADERS): + wb = load_workbook(filename=file_path) + ws = wb.active + ws.append(row_list) + + # Optional: Adjust column widths for better readability + # This is a simple auto-width, might not be perfect for all data + for col_idx, header in enumerate(headers, 1): + max_length = 0 + does_column_has_long_texts = ( + "link" in header.lower() + or header.lower() == "data with annot" + or header.lower() == "users creation result" + or header.lower() == "data with predict" + ) + for cell in ws[get_column_letter(col_idx)]: + if does_column_has_long_texts: + continue + try: + if len(str(cell.value)) > max_length: + max_length = len(str(cell.value)) + except TypeError: + pass # Handle cases where cell.value might be None + adjusted_width = (max_length + 2) * 1.1 # Add some padding + if does_column_has_long_texts: + adjusted_width = (len(header) + 2) * 1.1 + ws.column_dimensions[get_column_letter(col_idx)].width = adjusted_width + + wb.save(filename=file_path) + return True diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..c676b25 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,9 @@ +[project] +name = "python-utils" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.11" +dependencies = [ + "openpyxl>=3.1.5", +] diff --git a/python_bash_utils.py b/python_bash_utils.py new file mode 100644 index 0000000..2bc549f --- /dev/null +++ b/python_bash_utils.py @@ -0,0 +1,20 @@ + +import subprocess + + +def open_file_in_vscode(file_path): + subprocess.run(f"code {file_path}", check=True, text=True, shell=True) + + +def run_bash_commmand(command): + subprocess.run( + args=command, + check=True, + text=True, + shell=True, + ) + + +def open_url(url): + subprocess.run(f"brave-browser {url}", check=True, text=True, shell=True) + diff --git a/read_wirte_file_utils.py b/read_wirte_file_utils.py new file mode 100644 index 0000000..5205659 --- /dev/null +++ b/read_wirte_file_utils.py @@ -0,0 +1,23 @@ +import json +from pathlib import Path + + +def serialize_sets(obj): + if isinstance(obj, set): + return list(obj) + raise TypeError + + +def write_to_file(content, file_path: Path, json_dumps=False, indent=None): + file_path.parent.mkdir(parents=True, exist_ok=True) + with open(file_path, mode="w") as f: + if json_dumps: + return f.write(json.dumps(content, indent=indent, default=serialize_sets)) + return f.write(content) + + +def read_file(file_path, json_loads): + with open(file_path, "r") as file: + if json_loads: + return json.loads(file.read()) + return file.read() diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..ec63c89 --- /dev/null +++ b/uv.lock @@ -0,0 +1,35 @@ +version = 1 +revision = 2 +requires-python = ">=3.11" + +[[package]] +name = "et-xmlfile" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/38/af70d7ab1ae9d4da450eeec1fa3918940a5fafb9055e934af8d6eb0c2313/et_xmlfile-2.0.0.tar.gz", hash = "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54", size = 17234, upload-time = "2024-10-25T17:25:40.039Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa", size = 18059, upload-time = "2024-10-25T17:25:39.051Z" }, +] + +[[package]] +name = "openpyxl" +version = "3.1.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "et-xmlfile" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/f9/88d94a75de065ea32619465d2f77b29a0469500e99012523b91cc4141cd1/openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050", size = 186464, upload-time = "2024-06-28T14:03:44.161Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/da/977ded879c29cbd04de313843e76868e6e13408a94ed6b987245dc7c8506/openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2", size = 250910, upload-time = "2024-06-28T14:03:41.161Z" }, +] + +[[package]] +name = "python-utils" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "openpyxl" }, +] + +[package.metadata] +requires-dist = [{ name = "openpyxl", specifier = ">=3.1.5" }]