xlwings-utils 25.0.7.post0__py3-none-any.whl → 25.0.8__py3-none-any.whl
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.
Potentially problematic release.
This version of xlwings-utils might be problematic. Click here for more details.
- xlwings_utils/xlwings_utils.py +86 -75
- {xlwings_utils-25.0.7.post0.dist-info → xlwings_utils-25.0.8.dist-info}/METADATA +5 -3
- xlwings_utils-25.0.8.dist-info/RECORD +6 -0
- xlwings_utils-25.0.7.post0.dist-info/RECORD +0 -6
- {xlwings_utils-25.0.7.post0.dist-info → xlwings_utils-25.0.8.dist-info}/WHEEL +0 -0
- {xlwings_utils-25.0.7.post0.dist-info → xlwings_utils-25.0.8.dist-info}/top_level.txt +0 -0
xlwings_utils/xlwings_utils.py
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# /_/\_\|_| \_/\_/ |_||_| |_| \__, ||___/ _____ \__,_| \__||_||_||___/
|
|
6
6
|
# |___/ |_____|
|
|
7
7
|
|
|
8
|
-
__version__ = "25.0.
|
|
8
|
+
__version__ = "25.0.8"
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
import dropbox
|
|
@@ -20,20 +20,48 @@ Pythonista = sys.platform == "ios"
|
|
|
20
20
|
try:
|
|
21
21
|
import xlwings
|
|
22
22
|
|
|
23
|
+
xlwings = True
|
|
24
|
+
|
|
23
25
|
except ImportError:
|
|
24
26
|
xlwings = False
|
|
25
27
|
|
|
26
28
|
missing = object()
|
|
27
29
|
|
|
28
30
|
|
|
31
|
+
def pythonista_environ():
|
|
32
|
+
"""
|
|
33
|
+
tries to update environment variables from the file environ.toml at top level.
|
|
34
|
+
should only be used under Pythonista
|
|
35
|
+
"""
|
|
36
|
+
try:
|
|
37
|
+
import tomlib
|
|
38
|
+
except ModuleNotFoundError:
|
|
39
|
+
import tomli as tomlib
|
|
40
|
+
from pathlib import Path
|
|
41
|
+
import os
|
|
42
|
+
|
|
43
|
+
environ_file = Path("~/Documents").expanduser() / "environ.toml"
|
|
44
|
+
with open(environ_file, "rb") as f:
|
|
45
|
+
d0 = tomlib.load(f)
|
|
46
|
+
d1 = {}
|
|
47
|
+
for k0, v0 in d0.items():
|
|
48
|
+
if isinstance(v0, dict):
|
|
49
|
+
for k1, v1 in v0.items():
|
|
50
|
+
d1[f"{k0}.{k1}".upper()] = v1
|
|
51
|
+
else:
|
|
52
|
+
d1[k0.upper()] = v0
|
|
53
|
+
|
|
54
|
+
os.environ.update(d1)
|
|
55
|
+
|
|
56
|
+
|
|
29
57
|
def dropbox_init(refresh_token=missing, app_key=missing, app_secret=missing, **kwargs):
|
|
30
58
|
"""
|
|
31
59
|
dropbox initialize
|
|
32
60
|
|
|
33
61
|
This function may to be called prior to using any dropbox function
|
|
34
62
|
to specify the request token, app key and app secret.
|
|
35
|
-
If these are specified as REFRESH_TOKEN, APP_KEY and APP_SECRET
|
|
36
|
-
environment variables, it is
|
|
63
|
+
If these are specified as DROPBOX.REFRESH_TOKEN, DROPBOX.APP_KEY and DROPBOX.APP_SECRET
|
|
64
|
+
environment variables, it is not necessary to call dropbox_init().
|
|
37
65
|
|
|
38
66
|
Parameters
|
|
39
67
|
----------
|
|
@@ -55,47 +83,41 @@ def dropbox_init(refresh_token=missing, app_key=missing, app_secret=missing, **k
|
|
|
55
83
|
|
|
56
84
|
Returns
|
|
57
85
|
-------
|
|
58
|
-
|
|
86
|
+
dropbox object
|
|
59
87
|
"""
|
|
60
88
|
global dbx
|
|
61
89
|
|
|
62
90
|
if Pythonista:
|
|
63
|
-
|
|
64
|
-
environ_file = Path(os.environ["HOME"]) / "Documents" / ".environ.toml"
|
|
65
|
-
|
|
66
|
-
if environ_file.is_file():
|
|
67
|
-
with open(environ_file, "r") as f:
|
|
68
|
-
import toml
|
|
69
|
-
|
|
70
|
-
d = toml.load(f)
|
|
71
|
-
os.environ.update(d)
|
|
91
|
+
pythonista_environ()
|
|
72
92
|
|
|
73
93
|
if refresh_token is missing:
|
|
74
|
-
if "REFRESH_TOKEN" in os.environ:
|
|
75
|
-
refresh_token = os.environ["REFRESH_TOKEN"]
|
|
94
|
+
if "DROPBOX.REFRESH_TOKEN" in os.environ:
|
|
95
|
+
refresh_token = os.environ["DROPBOX.REFRESH_TOKEN"]
|
|
76
96
|
else:
|
|
77
|
-
raise ValueError("no REFRESH_TOKEN found in environment.")
|
|
97
|
+
raise ValueError("no DROPBOX.REFRESH_TOKEN found in environment.")
|
|
78
98
|
if app_key is missing:
|
|
79
|
-
if "APP_KEY" in os.environ:
|
|
80
|
-
app_key = os.environ["APP_KEY"]
|
|
99
|
+
if "DROPBOX.APP_KEY" in os.environ:
|
|
100
|
+
app_key = os.environ["DROPBOX.APP_KEY"]
|
|
81
101
|
else:
|
|
82
|
-
raise ValueError("no APP_KEY found in environment.")
|
|
102
|
+
raise ValueError("no DROPBOX.APP_KEY found in environment.")
|
|
83
103
|
if app_secret is missing:
|
|
84
|
-
if "APP_SECRET" in os.environ:
|
|
85
|
-
app_secret = os.environ["APP_SECRET"]
|
|
104
|
+
if "DROPBOX.APP_SECRET" in os.environ:
|
|
105
|
+
app_secret = os.environ["DROPBOX.APP_SECRET"]
|
|
86
106
|
else:
|
|
87
|
-
raise ValueError("no APP_SECRET found in environment.")
|
|
107
|
+
raise ValueError("no DROPBOX.APP_SECRET found in environment.")
|
|
88
108
|
|
|
89
|
-
|
|
109
|
+
_dbx = dropbox.Dropbox(oauth2_refresh_token=refresh_token, app_key=app_key, app_secret=app_secret, **kwargs)
|
|
90
110
|
try:
|
|
91
|
-
|
|
111
|
+
_dbx.files_list_folder(path="") # just to test proper credentials
|
|
92
112
|
except dropbox.exceptions.AuthError:
|
|
93
113
|
raise ValueError("invalid dropbox credentials")
|
|
114
|
+
return _dbx
|
|
94
115
|
|
|
95
116
|
|
|
96
117
|
def _login_dbx():
|
|
118
|
+
global dbx
|
|
97
119
|
if dbx is None:
|
|
98
|
-
dropbox_init() # use environment
|
|
120
|
+
dbx = dropbox_init() # use environment
|
|
99
121
|
|
|
100
122
|
|
|
101
123
|
def list_dropbox(path="", recursive=False, show_files=True, show_folders=False):
|
|
@@ -110,7 +132,7 @@ def list_dropbox(path="", recursive=False, show_files=True, show_folders=False):
|
|
|
110
132
|
path from which to list all files (default: '')
|
|
111
133
|
|
|
112
134
|
recursive : bool
|
|
113
|
-
if True, recursively list files. if False (default) no recursion
|
|
135
|
+
if True, recursively list files and folders. if False (default) no recursion
|
|
114
136
|
|
|
115
137
|
show_files : bool
|
|
116
138
|
if True (default), show file entries
|
|
@@ -124,10 +146,6 @@ def list_dropbox(path="", recursive=False, show_files=True, show_folders=False):
|
|
|
124
146
|
-------
|
|
125
147
|
files : list
|
|
126
148
|
|
|
127
|
-
Note
|
|
128
|
-
----
|
|
129
|
-
Directory entries are never returned
|
|
130
|
-
|
|
131
149
|
Note
|
|
132
150
|
----
|
|
133
151
|
If REFRESH_TOKEN, APP_KEY and APP_SECRET environment variables are specified,
|
|
@@ -290,6 +308,11 @@ class block:
|
|
|
290
308
|
self.number_of_rows = number_of_rows
|
|
291
309
|
self.number_of_columns = number_of_columns
|
|
292
310
|
|
|
311
|
+
def __eq__(self, other):
|
|
312
|
+
if isinstance(other, block):
|
|
313
|
+
return self.value == other.value
|
|
314
|
+
return False
|
|
315
|
+
|
|
293
316
|
@classmethod
|
|
294
317
|
def from_value(cls, value, column_like=False):
|
|
295
318
|
"""
|
|
@@ -297,18 +320,12 @@ class block:
|
|
|
297
320
|
|
|
298
321
|
Parameters
|
|
299
322
|
----------
|
|
300
|
-
value :
|
|
323
|
+
value : scalar, list of scalars, list of lists of scalars or block
|
|
301
324
|
value to be used in block, possibly expanded to a list of lists of scalars
|
|
302
325
|
|
|
303
326
|
column_like : boolean
|
|
304
327
|
if value is a list of scalars, values is interpreted as a column if True, as a row otherwise
|
|
305
328
|
|
|
306
|
-
number_of_rows : int
|
|
307
|
-
if given, expand or shrink to the given number of rows
|
|
308
|
-
|
|
309
|
-
number_of_columns : int
|
|
310
|
-
if given, expand or shrink to the given number of columns
|
|
311
|
-
|
|
312
329
|
Returns
|
|
313
330
|
-------
|
|
314
331
|
block : block
|
|
@@ -328,7 +345,7 @@ class block:
|
|
|
328
345
|
for column, item in enumerate(row_contents, 1):
|
|
329
346
|
if item and not (isinstance(item, float) and math.isnan(item)):
|
|
330
347
|
bl.dict[row, column] = item
|
|
331
|
-
|
|
348
|
+
bl._number_of_columns = max(bl.number_of_columns, column)
|
|
332
349
|
return bl
|
|
333
350
|
|
|
334
351
|
@classmethod
|
|
@@ -341,19 +358,12 @@ class block:
|
|
|
341
358
|
rng : xlwings.Range
|
|
342
359
|
range to be used be used in block
|
|
343
360
|
|
|
344
|
-
number_of_rows : int
|
|
345
|
-
if given, expand or shrink to the given number of rows
|
|
346
|
-
|
|
347
|
-
number_of_columns : int
|
|
348
|
-
if given, expand or shrink to the given number of columns
|
|
349
|
-
|
|
350
361
|
Returns
|
|
351
362
|
-------
|
|
352
363
|
block : block
|
|
353
364
|
"""
|
|
354
365
|
number_of_rows, number_of_columns = rng.shape
|
|
355
|
-
|
|
356
|
-
return bl
|
|
366
|
+
return cls.from_value(rng.value, column_like=(number_of_columns == 1))
|
|
357
367
|
|
|
358
368
|
@classmethod
|
|
359
369
|
def from_xlrd_sheet(cls, sheet):
|
|
@@ -365,12 +375,6 @@ class block:
|
|
|
365
375
|
sheet : xlrd sheet
|
|
366
376
|
sheet to be used be used in block
|
|
367
377
|
|
|
368
|
-
number_of_rows : int
|
|
369
|
-
if given, expand or shrink to the given number of rows
|
|
370
|
-
|
|
371
|
-
number_of_columns : int
|
|
372
|
-
if given, expand or shrink to the given number of columns
|
|
373
|
-
|
|
374
378
|
Returns
|
|
375
379
|
-------
|
|
376
380
|
block : block
|
|
@@ -380,6 +384,18 @@ class block:
|
|
|
380
384
|
|
|
381
385
|
@classmethod
|
|
382
386
|
def from_openpyxl_sheet(cls, sheet):
|
|
387
|
+
"""
|
|
388
|
+
makes a block from an openpyxl sheet
|
|
389
|
+
|
|
390
|
+
Parameters
|
|
391
|
+
----------
|
|
392
|
+
sheet : xlrd sheet
|
|
393
|
+
sheet to be used be used in block
|
|
394
|
+
|
|
395
|
+
Returns
|
|
396
|
+
-------
|
|
397
|
+
block : block
|
|
398
|
+
"""
|
|
383
399
|
v = [[cell.value for cell in row] for row in sheet.iter_rows()]
|
|
384
400
|
return cls.from_value(v)
|
|
385
401
|
|
|
@@ -393,12 +409,6 @@ class block:
|
|
|
393
409
|
filename : str
|
|
394
410
|
file to be used be used in block
|
|
395
411
|
|
|
396
|
-
number_of_rows : int
|
|
397
|
-
if given, expand or shrink to the given number of rows
|
|
398
|
-
|
|
399
|
-
number_of_columns : int
|
|
400
|
-
if given, expand or shrink to the given number of columns
|
|
401
|
-
|
|
402
412
|
Returns
|
|
403
413
|
-------
|
|
404
414
|
block : block
|
|
@@ -417,12 +427,6 @@ class block:
|
|
|
417
427
|
df : pandas dataframe
|
|
418
428
|
dataframe to be used be used in block
|
|
419
429
|
|
|
420
|
-
number_of_rows : int
|
|
421
|
-
if given, expand or shrink to the given number of rows
|
|
422
|
-
|
|
423
|
-
number_of_columns : int
|
|
424
|
-
if given, expand or shrink to the given number of columns
|
|
425
|
-
|
|
426
430
|
Returns
|
|
427
431
|
-------
|
|
428
432
|
block : block
|
|
@@ -432,18 +436,12 @@ class block:
|
|
|
432
436
|
|
|
433
437
|
def to_openpyxl_sheet(self, sheet):
|
|
434
438
|
"""
|
|
435
|
-
|
|
439
|
+
appends a block to a given openpyxl sheet
|
|
436
440
|
|
|
437
441
|
Parameters
|
|
438
442
|
----------
|
|
439
443
|
sheet: openpyxl sheet
|
|
440
|
-
sheet to be used be used
|
|
441
|
-
|
|
442
|
-
number_of_rows : int
|
|
443
|
-
if given, expand or shrink to the given number of rows
|
|
444
|
-
|
|
445
|
-
number_of_columns : int
|
|
446
|
-
if given, expand or shrink to the given number of columns
|
|
444
|
+
sheet to be used be used
|
|
447
445
|
|
|
448
446
|
Returns
|
|
449
447
|
-------
|
|
@@ -488,7 +486,11 @@ class block:
|
|
|
488
486
|
raise IndexError(f"row must be between 1 and {self.number_of_rows} not {row}")
|
|
489
487
|
if column < 1 or column > self.number_of_columns:
|
|
490
488
|
raise IndexError(f"column must be between 1 and {self.number_of_columns} not {column}")
|
|
491
|
-
|
|
489
|
+
if value is None:
|
|
490
|
+
if (row, column) in self.dict:
|
|
491
|
+
del self.dict[row, column]
|
|
492
|
+
else:
|
|
493
|
+
self.dict[row, column] = value
|
|
492
494
|
|
|
493
495
|
def __getitem__(self, row_column):
|
|
494
496
|
row, column = row_column
|
|
@@ -562,7 +564,7 @@ class block:
|
|
|
562
564
|
if column > self.number_of_columns:
|
|
563
565
|
raise ValueError(f"{name}={column} > number_of_columns={self.number_of_columns}")
|
|
564
566
|
|
|
565
|
-
def
|
|
567
|
+
def transposed(self):
|
|
566
568
|
"""
|
|
567
569
|
transpose block
|
|
568
570
|
|
|
@@ -827,7 +829,16 @@ class block:
|
|
|
827
829
|
|
|
828
830
|
def decode_to_files(self):
|
|
829
831
|
"""
|
|
830
|
-
decode the block with encoded file(s) to individual pyoidide
|
|
832
|
+
decode the block with encoded file(s) to individual pyoidide file(s)
|
|
833
|
+
|
|
834
|
+
Returns
|
|
835
|
+
-------
|
|
836
|
+
count : int
|
|
837
|
+
number of files decoded
|
|
838
|
+
|
|
839
|
+
Note
|
|
840
|
+
----
|
|
841
|
+
if the block does not contain an encode file, the method just returns 0
|
|
831
842
|
"""
|
|
832
843
|
count = 0
|
|
833
844
|
for column in range(1, self.number_of_columns + 1):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xlwings_utils
|
|
3
|
-
Version: 25.0.
|
|
3
|
+
Version: 25.0.8
|
|
4
4
|
Summary: xlwings_utils
|
|
5
5
|
Author-email: Ruud van der Ham <rt.van.der.ham@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/salabim/xlwings_utils
|
|
@@ -51,7 +51,9 @@ The xlwings lite system does not provide access to the local file system. With t
|
|
|
51
51
|
|
|
52
52
|
Currently, it is only possible to use full-access Dropbox apps.
|
|
53
53
|
|
|
54
|
-
The easiest way to use the Dropbox functionality is to add the credentials to the environment variables. Add REFRESH_TOKEN,
|
|
54
|
+
The easiest way to use the Dropbox functionality is to add the credentials to the environment variables. Add DROPBOX.REFRESH_TOKEN,
|
|
55
|
+
DROPBOX.APP_KEY and DROPBOX.APP_SECRET with their corresponding values to the environment variables.
|
|
56
|
+
Instructions on how to get these variables can be found here.
|
|
55
57
|
|
|
56
58
|
In order to make a Dropbox app, and get the required environment variables, just execute this line from the command line (shell).
|
|
57
59
|
|
|
@@ -60,7 +62,7 @@ python -c "exec(__import__('requests').get('https://salabim.org/dropbox setup.py
|
|
|
60
62
|
```
|
|
61
63
|
|
|
62
64
|
Then, it is possible to list all files in a specified folder using the list_dropbox function.
|
|
63
|
-
It is also possible to get
|
|
65
|
+
It is also possible to get at all folders and to access all underlying folders.
|
|
64
66
|
|
|
65
67
|
The `read_dropbox` function can be used to read the contents (bytes) of a Dropbox file. As reading from Dropbox under pyodide is rather unreliable, xlwings_utils automatically retries several times (by default 100 times). The actual number of retries can be found with `read_dropbox.retries`.
|
|
66
68
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
xlwings_utils/__init__.py,sha256=FdaRztevSu5akGL7KBUBRzqwLMRTdvVUuS2Kfp2f1Uc,68
|
|
2
|
+
xlwings_utils/xlwings_utils.py,sha256=HNip6tVo2sxhlysNm2zWVRY2bciWUujpzN-NmISUOiM,28690
|
|
3
|
+
xlwings_utils-25.0.8.dist-info/METADATA,sha256=KwS8dQNtM4n95zj2EXYaQfZFXMGga8MkQKVchmCQO9w,12447
|
|
4
|
+
xlwings_utils-25.0.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
5
|
+
xlwings_utils-25.0.8.dist-info/top_level.txt,sha256=kf5SEv0gZiRObPhUoYcc1O_iX_wwTOPeUIYvzyYeAM4,14
|
|
6
|
+
xlwings_utils-25.0.8.dist-info/RECORD,,
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
xlwings_utils/__init__.py,sha256=FdaRztevSu5akGL7KBUBRzqwLMRTdvVUuS2Kfp2f1Uc,68
|
|
2
|
-
xlwings_utils/xlwings_utils.py,sha256=f13mQGcZ6syg7vkU97iYEHXj4Mlai6gPZd0XhOkxiwY,28717
|
|
3
|
-
xlwings_utils-25.0.7.post0.dist-info/METADATA,sha256=vsTv_WzSM6miRYN5OltUUr2i5YkybpepE9crGXMZrZk,12424
|
|
4
|
-
xlwings_utils-25.0.7.post0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
5
|
-
xlwings_utils-25.0.7.post0.dist-info/top_level.txt,sha256=kf5SEv0gZiRObPhUoYcc1O_iX_wwTOPeUIYvzyYeAM4,14
|
|
6
|
-
xlwings_utils-25.0.7.post0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|