somepytools 1.2.2__tar.gz → 1.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,27 +1,28 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: somepytools
3
- Version: 1.2.2
3
+ Version: 1.4.0
4
4
  Summary: Just some useful Python tools
5
- Home-page: https://github.com/v-goncharenko/somepytools
6
5
  License: Apache-2.0
7
6
  Keywords: tools,utilities,python,torch,opencv
8
7
  Author: Vladilav Goncharenko
9
8
  Author-email: vladislav.goncharenko@phystech.edu
10
9
  Maintainer: Vladislav Goncharenko
11
10
  Maintainer-email: vladislav.goncharenko@phystech.edu
12
- Requires-Python: >=3.8
11
+ Requires-Python: >=3.9
13
12
  Classifier: License :: OSI Approved :: Apache Software License
14
13
  Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.10
16
- Classifier: Programming Language :: Python :: 3.8
17
14
  Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
18
19
  Provides-Extra: all
19
- Requires-Dist: PyYAML (>=6.0,<7.0); extra == "all"
20
- Requires-Dist: matplotlib (>=3.5.1,<4.0.0); extra == "all"
21
- Requires-Dist: numpy (>=1.22.3,<2.0.0); extra == "all"
22
- Requires-Dist: opencv-python-headless (>=4.5.5,<5.0.0); extra == "all"
23
- Requires-Dist: toml (>=0.10.2,<0.11.0); extra == "all"
24
- Requires-Dist: torch (>=1.11.0,<2.0.0); extra == "all"
20
+ Requires-Dist: PyYAML (>=6.0,<7.0) ; extra == "all"
21
+ Requires-Dist: matplotlib (>=3.5.1,<4.0.0) ; extra == "all"
22
+ Requires-Dist: numpy (>=1.22.3,<2.0.0) ; extra == "all"
23
+ Requires-Dist: opencv-python-headless (>=4.5.5,<5.0.0) ; extra == "all"
24
+ Requires-Dist: toml (>=0.10.2,<0.11.0) ; extra == "all"
25
+ Requires-Dist: torch (>=1.11.0,<2.0.0) ; extra == "all"
25
26
  Project-URL: Repository, https://github.com/v-goncharenko/somepytools
26
27
  Description-Content-Type: text/markdown
27
28
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "somepytools"
3
- version = "1.2.2"
3
+ version = "1.4.0"
4
4
  description = "Just some useful Python tools"
5
5
  authors = ["Vladilav Goncharenko <vladislav.goncharenko@phystech.edu>"]
6
6
  maintainers = ["Vladislav Goncharenko <vladislav.goncharenko@phystech.edu>"]
@@ -10,7 +10,7 @@ keywords = ["tools", "utilities", "python", "torch", "opencv"]
10
10
  license = "Apache-2.0"
11
11
 
12
12
  [tool.poetry.dependencies]
13
- python = ">=3.8"
13
+ python = ">=3.9"
14
14
 
15
15
  PyYAML = {version = "^6.0", optional = true}
16
16
  toml = {version = "^0.10.2", optional = true}
@@ -23,8 +23,8 @@ matplotlib = {version = "^3.5.1", optional = true}
23
23
  [tool.poetry.extras]
24
24
  all = ["PyYAML", "toml", "numpy", "opencv-python-headless", "torch", "matplotlib"]
25
25
 
26
- [tool.poetry.dev-dependencies]
27
- pre-commit = "^2.16.0"
26
+ [tool.poetry.group.dev.dependencies]
27
+ pre-commit = "^4.3.0"
28
28
  pytest = "^6.2.5"
29
29
 
30
30
  [tool.black]
@@ -0,0 +1 @@
1
+ __version__ = "1.4.0"
@@ -0,0 +1,136 @@
1
+ # duplicates in sheets formula: =COUNTIF(A:A, A1) > 1
2
+
3
+ from typing import Any, Union
4
+
5
+ import gspread
6
+ import polars as pl
7
+ from google.auth import default
8
+ from google.colab import auth
9
+ from oauth2client.client import GoogleCredentials
10
+ from pydrive2.auth import GoogleAuth
11
+ from pydrive2.drive import GoogleDrive
12
+
13
+
14
+ def auth_gspread() -> gspread.client.Client:
15
+ auth.authenticate_user()
16
+ creds, _ = default()
17
+ gc = gspread.authorize(creds)
18
+ return gc
19
+
20
+
21
+ def auth_pydrive(dummy_call: bool = False) -> GoogleDrive:
22
+ """
23
+ Args:
24
+ dummy_call: needed if you want to perform non PyDrive2 native operations with service object
25
+ """
26
+ auth.authenticate_user()
27
+ gauth = GoogleAuth()
28
+ gauth.credentials = GoogleCredentials.get_application_default()
29
+ drive = GoogleDrive(gauth)
30
+
31
+ if dummy_call:
32
+ file_list = drive.ListFile( # noqa: F841
33
+ {"q": "'root' in parents and trashed=false"}
34
+ ).GetList()
35
+
36
+ return drive
37
+
38
+
39
+ def sheets(gc, spreadsheet_id: str) -> dict[str, Any]:
40
+ """"""
41
+ spreadsheet = gc.open_by_key(spreadsheet_id)
42
+ return {ws.title: ws for ws in spreadsheet}
43
+
44
+
45
+ def worksheet2pl(worksheet):
46
+ all_vals = worksheet.get(
47
+ major_dimension=gspread.utils.Dimension.cols,
48
+ value_render_option=gspread.utils.ValueRenderOption.unformatted,
49
+ date_time_render_option=gspread.utils.DateTimeOption.formatted_string,
50
+ pad_values=True,
51
+ )
52
+
53
+ df = pl.DataFrame(all_vals, strict=False)
54
+ df = df.rename(df.head(1).to_dicts().pop())
55
+ df = df.with_row_index()
56
+ df = df.filter(pl.col("index") != 0)
57
+ return df
58
+
59
+
60
+ def number2letters(q: int) -> str:
61
+ """Helper function to convert number of column to its index, like 10 -> 'A'"""
62
+ q = q - 1
63
+ result = ""
64
+
65
+ while q >= 0:
66
+ remain = q % 26
67
+ result = chr(remain + 65) + result
68
+ q = q // 26 - 1
69
+
70
+ return result
71
+
72
+
73
+ def colrow2range(col: int, row: int) -> str:
74
+ """Helper function converting coordinates into sheets range string representation"""
75
+ return number2letters(col) + str(row)
76
+
77
+
78
+ def write_table(
79
+ ws,
80
+ table: Union[list, pl.DataFrame],
81
+ left: int = 1,
82
+ top: int = 1,
83
+ *,
84
+ with_headers: bool = True,
85
+ ):
86
+ """Updates the google spreadsheet with given table
87
+
88
+ Args:
89
+ ws: gspread.models.Worksheet object
90
+ rows: a table (list of lists) or polars data frame (will be converted internally)
91
+ left: the number of the first column in the target document (beginning with 1)
92
+ top: the number of first row in the target document (beginning with 1)
93
+ with_headers: in case of rows as pl.DataFrame to take headers or not
94
+ """
95
+ if isinstance(table, pl.DataFrame):
96
+ columns = table.columns
97
+ table = table.rows()
98
+ if with_headers:
99
+ table.insert(0, columns)
100
+
101
+ # number of rows and columns
102
+ num_lines, num_columns = len(table), len(table[0])
103
+
104
+ # selection of the range that will be updated
105
+ top_left = colrow2range(left, top)
106
+ bot_right = colrow2range(left + num_columns - 1, top + num_lines - 1)
107
+ cell_list = ws.range(f"{top_left}:{bot_right}")
108
+
109
+ # modifying the values in the range
110
+
111
+ for cell in cell_list:
112
+ cell.value = table[cell.row - top][cell.col - left]
113
+
114
+ # update in batch
115
+ ws.update_cells(cell_list)
116
+
117
+
118
+ def copy_drive_file(drive, source: str, dest_dir: str, dest_fname: str):
119
+ """Copy Google Drive file
120
+
121
+ Args:
122
+ source: id of the file to be copyed
123
+ dest_dir: id of directory to put copy to
124
+ dest_fname: name of restulting document
125
+ """
126
+ return (
127
+ drive.auth.service.files()
128
+ .copy(
129
+ fileId=source,
130
+ body={
131
+ "parents": [{"kind": "drive#fileLink", "id": dest_dir}],
132
+ "title": dest_fname,
133
+ },
134
+ )
135
+ .execute()
136
+ )
@@ -1,13 +1,15 @@
1
1
  import shutil
2
+ from datetime import date, datetime, timedelta
2
3
  from functools import wraps
3
4
  from inspect import getfullargspec
4
5
  from pathlib import Path
6
+ from typing import Any, Iterator, Union, get_args
5
7
  from urllib.parse import urlparse
6
8
  from urllib.request import urlopen
7
9
  from zipfile import ZipFile
8
10
 
9
11
  from .constants import SIZE_CONSTANTS
10
- from .typing import Any, Directory, File, Union, get_args
12
+ from .typing import Directory, File
11
13
 
12
14
 
13
15
  def str2pathlib(func):
@@ -160,3 +162,26 @@ def dir_size(
160
162
  src = f.resolve()
161
163
  total_size += dir_size(src, units)
162
164
  return total_size
165
+
166
+
167
+ def daterange(
168
+ start_date: Union[str, datetime],
169
+ end_date: Union[str, datetime],
170
+ *,
171
+ include_last: bool = False,
172
+ ) -> Iterator[date]:
173
+ """Generates dates in requested range
174
+
175
+ Note:
176
+ Date format is ISO: 'yyyy-mm-dd'
177
+ """
178
+ if isinstance(start_date, str):
179
+ start_date = datetime.strptime(start_date, "%Y-%m-%d").date()
180
+ if isinstance(end_date, str):
181
+ end_date = datetime.strptime(end_date, "%Y-%m-%d").date()
182
+ days = (end_date - start_date).days
183
+ if include_last:
184
+ days += 1
185
+
186
+ for i in range(days):
187
+ yield start_date + timedelta(i)
@@ -1,4 +1,6 @@
1
- from .typing import Array, Bbox, Number, OpencvFlag, Optional, Sequence
1
+ from typing import Optional, Sequence
2
+
3
+ from .typing import Array, Bbox, Number, OpencvFlag
2
4
 
3
5
 
4
6
  try:
@@ -2,7 +2,6 @@
2
2
 
3
3
  from numbers import Number
4
4
  from pathlib import Path
5
- from typing import * # noqa: F403
6
5
  from typing import Any, Dict, Generic, List, Sequence, TypeVar, Union
7
6
 
8
7
 
@@ -1,8 +1,9 @@
1
1
  from contextlib import contextmanager
2
2
  from pathlib import Path
3
+ from typing import Iterable, Sequence, Union
3
4
 
4
5
  from .general import str2pathlib
5
- from .typing import Array, File, Iterable, Sequence, Union
6
+ from .typing import Array, File
6
7
 
7
8
 
8
9
  try:
@@ -41,7 +42,7 @@ def open_video(video_path: File, mode: str = "r", *args):
41
42
  elif mode == "w":
42
43
  video = cv2.VideoWriter(video_path.as_posix(), *args)
43
44
  else:
44
- raise ValueError(f'Incorrect open mode "{mode}"; "r" or "w" expected!')
45
+ raise ValueError(f'Incorrect open mode {mode!r}; "r" or "w" expected!')
45
46
 
46
47
  if not video.isOpened():
47
48
  raise ValueError(f"Video {video_path} is not opened!")
@@ -1,35 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- from setuptools import setup
3
-
4
- packages = \
5
- ['somepytools']
6
-
7
- package_data = \
8
- {'': ['*']}
9
-
10
- extras_require = \
11
- {'all': ['PyYAML>=6.0,<7.0',
12
- 'toml>=0.10.2,<0.11.0',
13
- 'numpy>=1.22.3,<2.0.0',
14
- 'opencv-python-headless>=4.5.5,<5.0.0',
15
- 'torch>=1.11.0,<2.0.0',
16
- 'matplotlib>=3.5.1,<4.0.0']}
17
-
18
- setup_kwargs = {
19
- 'name': 'somepytools',
20
- 'version': '1.2.2',
21
- 'description': 'Just some useful Python tools',
22
- 'long_description': "# Some useful tools for Python [in context of Data Science]\n\n[![PyPI](https://img.shields.io/pypi/v/somepytools)](https://pypi.org/project/somepytools/)\n[![Downloads](https://pepy.tech/badge/somepytools)](https://pepy.tech/project/somepytools)\n[![License: Apache](https://img.shields.io/badge/license-Apache%202-blue)](https://github.com/v-goncharenko/somepytools/blob/master/LICENSE)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n\nHere I gather functions that are handful in Data Science & Machine Learning\nprojects.\n\nAll functions are described by their docstrings, rendering documentation is next\nstep.\n\n## Installation\n\nIt's [published on PyPI](https://pypi.org/project/somepytools/), so simply\n\n`pip install somepytools`\n\n## Reference\n\nModules inclues:\n\n- extended typing module\n- common read-write operations for configs\n- utils to work with filesystem\n- functions to handle videos in opencv\n- torch utilities (infer and count parameters)\n- even more (e.g. wrapper to convert strings inputs to `pathlib`)\n\nFor now it's better to go through the files and look at contents\n",
23
- 'author': 'Vladilav Goncharenko',
24
- 'author_email': 'vladislav.goncharenko@phystech.edu',
25
- 'maintainer': 'Vladislav Goncharenko',
26
- 'maintainer_email': 'vladislav.goncharenko@phystech.edu',
27
- 'url': 'https://github.com/v-goncharenko/somepytools',
28
- 'packages': packages,
29
- 'package_data': package_data,
30
- 'extras_require': extras_require,
31
- 'python_requires': '>=3.8',
32
- }
33
-
34
-
35
- setup(**setup_kwargs)
@@ -1 +0,0 @@
1
- __version__ = "1.2.2"
File without changes
File without changes