xlwings-utils 0.0.6__tar.gz → 0.0.7__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.

Potentially problematic release.


This version of xlwings-utils might be problematic. Click here for more details.

@@ -0,0 +1,132 @@
1
+ Metadata-Version: 2.4
2
+ Name: xlwings_utils
3
+ Version: 0.0.7
4
+ Summary: xlwings_utils
5
+ Author-email: Ruud van der Ham <rt.van.der.ham@gmail.com>
6
+ Project-URL: Homepage, https://github.com/salabim/xlwings_utils
7
+ Project-URL: Repository, https://github.com/salabim/xlwings_utils
8
+ Classifier: Development Status :: 5 - Production/Stable
9
+ Classifier: Programming Language :: Python :: 3 :: Only
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: dropbox
13
+ Requires-Dist: ssl
14
+
15
+ <img src="https://www.salabim.org/xlwings_utils_logo2.png">
16
+
17
+ ## Introduction
18
+
19
+ This module provides some useful functions to be used in xlwings lite.
20
+
21
+ ## Installation
22
+
23
+ Just add xlwings-utils to the *requirement.txt* tab. It might be required to add ssl.
24
+
25
+ In the script, add
26
+
27
+ ```ìmport xlwings_utils as xwu```
28
+
29
+ ## Dropbox support
30
+
31
+ The xlwings lite system does not provide access to the local file system. With this module, files can be copied between Dropbox and the local pyodide file system, making it possible to indirectly use the local file system.
32
+
33
+ It is only possible, as of now, to use full-access Dropbox apps.
34
+
35
+ The easiest way to use the Dropbox functionality is to add the credentials to the environment variables. Add REFRESH_TOKEN, APP_KEY and APP_SECRET with their corresponding values to the environment variables.
36
+
37
+ Then, it is possible to list all files in a specified folder with the function `list_dropbox`.
38
+ It is also possible to get the folders and to access all underlying folders.
39
+
40
+ The function `read_dropbox` can be used to read a Dropbox file's contents (bytes).
41
+
42
+ The function `write_dropbox` can be used to write contents (bytes) to a Dropbox file.
43
+
44
+ The functions `list_local`, `read_local` and `write_local` offer similar functionality for the local file system (on pyodide).
45
+
46
+ So, a way to access a file on the system's drive (mapped to Dropbox) as a local file is:
47
+
48
+ ```
49
+ contents = xlwings_utils.read_dropbox('/downloads/file1.xls')
50
+ xlwings_utils.write_local('file1.xlsx')
51
+ df = pandas.read_excel"file1.xlsx")
52
+ ...
53
+ ```
54
+ And the other direction:
55
+ ```
56
+ contents = xlwings_utils.read_local('file1.gif')
57
+ xlwings_utils.write_dropbox('/downloads/file1.gif')
58
+ ```
59
+
60
+ ## Block support
61
+
62
+ The module contains a useful 2-dimensional data structure: *block*.
63
+ This can be useful to manipulate a range without accessing the range directly, which is expensive in terms of memory and execution time.
64
+ The advantage over an ordinary list of lists is that a block is index one-based, in line with range and addressing is done with a row, column tuple.
65
+ So, `my_block(lol)[row, col]` is roughly equivalent to `lol[row-1][col-1]`
66
+
67
+ A block stores the values internally as a dictionary and will only convert these to a list of lists when using `block.value`.
68
+
69
+ Converting the value of a range (usually a list of lists, but can also be a list or scalar) to a block can be done with
70
+
71
+ ```
72
+ my_block = xwu.block.from_value(range.value)
73
+ ```
74
+ The dimensions (number of rows and number of columns) are automatically set.
75
+
76
+ Setting of an individual item (one-based, like range) can be done like
77
+ ```
78
+ my_block[row, column] = x
79
+ ```
80
+ And, likewise, reading an individual item can be done like
81
+ ```
82
+ x = my_block[row, column]
83
+ ```
84
+ It is not allowed t,o read or write outside the block dimensions.
85
+
86
+ It is also possible to define an empty block, like
87
+ ```
88
+ block = xlwings_utils.block(number_of_rows, number_columns)
89
+ ```
90
+ The dimensions can be queried or redefined with `block.number_of_rows` and
91
+ `block.number_of_columns`.
92
+
93
+ To assign a block to range, use
94
+ ```
95
+ range.value = block.value
96
+ ```
97
+
98
+ The property `block.highest`_used_row_number returns the
99
+
100
+ The method `block.minimized()` returns a block that has the dimensions of (highest_used_row_number, highest_used_column_number).
101
+
102
+ ## Capture stdout support
103
+
104
+ The module has support for capturing stdout and -later- using showing the captured output on a sheet.
105
+
106
+ To do that:
107
+
108
+ ```makes it possible to capture stdout writes, which
109
+ with xwu.capture_stdout():
110
+ ...
111
+ ```
112
+ and then the captured output can be copied to the screen, like
113
+
114
+ ```can then be copied to a worksheet in a later stage.
115
+ sheet.range(4,5).value = xwu.captured_stdout_as_value()
116
+ ```
117
+
118
+ Clearing the captured stdout buffer can be done with `xwu.clear_captured_std_out`.
119
+
120
+ Normally, stdout will be also sent to the xlwings lite UI panel. This can be suppressed with
121
+
122
+ ```
123
+ with xwu.capture_stdout(include_print=False):
124
+ ...
125
+ ```
126
+
127
+ ## Badges
128
+
129
+ ![PyPI](https://img.shields.io/pypi/v/xlwings-utils) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/xlwings-utils) ![PyPI - Implementation](https://img.shields.io/pypi/implementation/xlwings-utils)
130
+ ![PyPI - License](https://img.shields.io/pypi/l/xlwings-utils) ![ruff](https://img.shields.io/badge/style-ruff-41B5BE?style=flat)
131
+ ![GitHub last commit](https://img.shields.io/github/last-commit/salabim/peek)
132
+
@@ -0,0 +1,118 @@
1
+ <img src="https://www.salabim.org/xlwings_utils_logo2.png">
2
+
3
+ ## Introduction
4
+
5
+ This module provides some useful functions to be used in xlwings lite.
6
+
7
+ ## Installation
8
+
9
+ Just add xlwings-utils to the *requirement.txt* tab. It might be required to add ssl.
10
+
11
+ In the script, add
12
+
13
+ ```ìmport xlwings_utils as xwu```
14
+
15
+ ## Dropbox support
16
+
17
+ The xlwings lite system does not provide access to the local file system. With this module, files can be copied between Dropbox and the local pyodide file system, making it possible to indirectly use the local file system.
18
+
19
+ It is only possible, as of now, to use full-access Dropbox apps.
20
+
21
+ The easiest way to use the Dropbox functionality is to add the credentials to the environment variables. Add REFRESH_TOKEN, APP_KEY and APP_SECRET with their corresponding values to the environment variables.
22
+
23
+ Then, it is possible to list all files in a specified folder with the function `list_dropbox`.
24
+ It is also possible to get the folders and to access all underlying folders.
25
+
26
+ The function `read_dropbox` can be used to read a Dropbox file's contents (bytes).
27
+
28
+ The function `write_dropbox` can be used to write contents (bytes) to a Dropbox file.
29
+
30
+ The functions `list_local`, `read_local` and `write_local` offer similar functionality for the local file system (on pyodide).
31
+
32
+ So, a way to access a file on the system's drive (mapped to Dropbox) as a local file is:
33
+
34
+ ```
35
+ contents = xlwings_utils.read_dropbox('/downloads/file1.xls')
36
+ xlwings_utils.write_local('file1.xlsx')
37
+ df = pandas.read_excel"file1.xlsx")
38
+ ...
39
+ ```
40
+ And the other direction:
41
+ ```
42
+ contents = xlwings_utils.read_local('file1.gif')
43
+ xlwings_utils.write_dropbox('/downloads/file1.gif')
44
+ ```
45
+
46
+ ## Block support
47
+
48
+ The module contains a useful 2-dimensional data structure: *block*.
49
+ This can be useful to manipulate a range without accessing the range directly, which is expensive in terms of memory and execution time.
50
+ The advantage over an ordinary list of lists is that a block is index one-based, in line with range and addressing is done with a row, column tuple.
51
+ So, `my_block(lol)[row, col]` is roughly equivalent to `lol[row-1][col-1]`
52
+
53
+ A block stores the values internally as a dictionary and will only convert these to a list of lists when using `block.value`.
54
+
55
+ Converting the value of a range (usually a list of lists, but can also be a list or scalar) to a block can be done with
56
+
57
+ ```
58
+ my_block = xwu.block.from_value(range.value)
59
+ ```
60
+ The dimensions (number of rows and number of columns) are automatically set.
61
+
62
+ Setting of an individual item (one-based, like range) can be done like
63
+ ```
64
+ my_block[row, column] = x
65
+ ```
66
+ And, likewise, reading an individual item can be done like
67
+ ```
68
+ x = my_block[row, column]
69
+ ```
70
+ It is not allowed t,o read or write outside the block dimensions.
71
+
72
+ It is also possible to define an empty block, like
73
+ ```
74
+ block = xlwings_utils.block(number_of_rows, number_columns)
75
+ ```
76
+ The dimensions can be queried or redefined with `block.number_of_rows` and
77
+ `block.number_of_columns`.
78
+
79
+ To assign a block to range, use
80
+ ```
81
+ range.value = block.value
82
+ ```
83
+
84
+ The property `block.highest`_used_row_number returns the
85
+
86
+ The method `block.minimized()` returns a block that has the dimensions of (highest_used_row_number, highest_used_column_number).
87
+
88
+ ## Capture stdout support
89
+
90
+ The module has support for capturing stdout and -later- using showing the captured output on a sheet.
91
+
92
+ To do that:
93
+
94
+ ```makes it possible to capture stdout writes, which
95
+ with xwu.capture_stdout():
96
+ ...
97
+ ```
98
+ and then the captured output can be copied to the screen, like
99
+
100
+ ```can then be copied to a worksheet in a later stage.
101
+ sheet.range(4,5).value = xwu.captured_stdout_as_value()
102
+ ```
103
+
104
+ Clearing the captured stdout buffer can be done with `xwu.clear_captured_std_out`.
105
+
106
+ Normally, stdout will be also sent to the xlwings lite UI panel. This can be suppressed with
107
+
108
+ ```
109
+ with xwu.capture_stdout(include_print=False):
110
+ ...
111
+ ```
112
+
113
+ ## Badges
114
+
115
+ ![PyPI](https://img.shields.io/pypi/v/xlwings-utils) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/xlwings-utils) ![PyPI - Implementation](https://img.shields.io/pypi/implementation/xlwings-utils)
116
+ ![PyPI - License](https://img.shields.io/pypi/l/xlwings-utils) ![ruff](https://img.shields.io/badge/style-ruff-41B5BE?style=flat)
117
+ ![GitHub last commit](https://img.shields.io/github/last-commit/salabim/peek)
118
+
@@ -10,7 +10,7 @@ authors = [
10
10
  { name = "Ruud van der Ham", email = "rt.van.der.ham@gmail.com" },
11
11
  ]
12
12
  description = "xlwings_utils"
13
- version = "0.0.6"
13
+ version = "0.0.7"
14
14
  readme = "README.md"
15
15
  requires-python = ">=3.9"
16
16
  dependencies = [
@@ -0,0 +1,128 @@
1
+ import os
2
+ import sys
3
+ from pathlib import Path
4
+
5
+ if __name__ == "__main__": # to make the tests run without the pytest cli
6
+ file_folder = os.path.dirname(__file__)
7
+ os.chdir(file_folder)
8
+ sys.path.insert(0, file_folder + "/../xlwings_utils")
9
+
10
+ import pytest
11
+
12
+ import xlwings_utils as xwu
13
+
14
+
15
+ def test_block0():
16
+ this_block = xwu.block(number_of_rows=4, number_of_columns=6)
17
+ this_block[1, 2] = 2
18
+ this_block[2, 5] = 25
19
+ assert this_block.dict == {(1, 2): 2, (2, 5): 25}
20
+ assert this_block.value == [
21
+ [None, 2, None, None, None, None],
22
+ [None, None, None, None, 25, None],
23
+ [None, None, None, None, None, None],
24
+ [None, None, None, None, None, None],
25
+ ]
26
+ assert this_block.minimized().value == [[None, 2, None, None, None], [None, None, None, None, 25]]
27
+ assert this_block.number_of_rows == 4
28
+ assert this_block.number_of_columns == 6
29
+ assert this_block.highest_used_row_number == 2
30
+ assert this_block.highest_used_column_number == 5
31
+
32
+ this_block.number_of_rows = 99
33
+ this_block.number_of_columns = 99
34
+ assert this_block.highest_used_row_number == 2
35
+ assert this_block.highest_used_column_number == 5
36
+
37
+ this_block.number_of_rows = 1
38
+ this_block.number_of_columns = 3
39
+ assert this_block.value == [[None, 2, None]]
40
+ assert this_block.minimized().value == [[None, 2]]
41
+
42
+
43
+ def test_block1():
44
+ this_block = xwu.block([[1, 2, 3], [4, 5, 6]])
45
+ assert this_block.dict == {(1, 1): 1, (1, 2): 2, (1, 3): 3, (2, 1): 4, (2, 2): 5, (2, 3): 6}
46
+ assert this_block.value == [[1, 2, 3], [4, 5, 6]]
47
+ assert this_block.minimized().value == [[1, 2, 3], [4, 5, 6]]
48
+ with pytest.raises(ValueError):
49
+ this_block.number_of_rows = 0
50
+ with pytest.raises(ValueError):
51
+ this_block.number_of_columns = 0
52
+ with pytest.raises(ValueError):
53
+ this_block = xwu.block(number_of_rows=0, number_of_columns=1)
54
+ with pytest.raises(ValueError):
55
+ this_block = xwu.block(number_of_rows=1, number_of_columns=0)
56
+
57
+
58
+ def test_block2():
59
+ this_block = xwu.block([[1, 2, 3], [4, 5, 6]], number_of_rows=1)
60
+ assert this_block.value == [[1, 2, 3]]
61
+
62
+ this_block = xwu.block([[1, 2, 3], [4, 5, 6]], number_of_rows=1, number_of_columns=2)
63
+ assert this_block.value == [[1, 2]]
64
+
65
+ this_block = xwu.block([[1, 2, 3], [4, 5, 6]], number_of_rows=3, number_of_columns=4)
66
+ assert this_block.value == [[1, 2, 3, None], [4, 5, 6, None], [None, None, None, None]]
67
+
68
+
69
+ def test_block_one_dimension():
70
+ this_block = xwu.block([1, 2, 3])
71
+ assert this_block.value == [[1, 2, 3]]
72
+
73
+ this_block = xwu.block([1, 2, 3], column_like=True)
74
+ assert this_block.value == [[1], [2], [3]]
75
+
76
+
77
+ def test_block_scalar():
78
+ this_block = xwu.block(1)
79
+ assert this_block.value == [[1]]
80
+
81
+
82
+ def test_raise():
83
+ this_block = xwu.block(number_of_rows=4, number_of_columns=6)
84
+ with pytest.raises(IndexError):
85
+ a = this_block[0, 1]
86
+ with pytest.raises(IndexError):
87
+ a = this_block[5, 1]
88
+
89
+ with pytest.raises(IndexError):
90
+ a = this_block[1, 0]
91
+ with pytest.raises(IndexError):
92
+ a = this_block[1, 7]
93
+
94
+ with pytest.raises(IndexError):
95
+ this_block[0, 1] = 1
96
+ with pytest.raises(IndexError):
97
+ this_block[5, 1] = 1
98
+
99
+ with pytest.raises(IndexError):
100
+ this_block[1, 0] = 1
101
+ with pytest.raises(IndexError):
102
+ this_block[1, 7] = 1
103
+
104
+
105
+ def test_capture_stdout(capsys):
106
+ with xwu.capture_stdout():
107
+ print("abc")
108
+ print("def")
109
+ assert xwu.captured_stdout_as_str() == "abc\ndef\n"
110
+ assert xwu.captured_stdout_as_value() == [["abc"], ["def"]]
111
+
112
+ out, err = capsys.readouterr()
113
+ assert out == "abc\ndef\n"
114
+
115
+ xwu.clear_captured_stdout()
116
+ assert xwu.captured_stdout_as_str() == ""
117
+ with xwu.capture_stdout(include_print=False):
118
+ print("ghi")
119
+ print("jkl")
120
+ assert xwu.captured_stdout_as_str() == "ghi\njkl\n"
121
+ assert xwu.captured_stdout_as_value() == [["ghi"], ["jkl"]]
122
+ out, err = capsys.readouterr()
123
+ assert out == ""
124
+
125
+
126
+ if __name__ == "__main__":
127
+ pytest.main(["-vv", "-s", "-x", __file__])
128
+
@@ -5,7 +5,7 @@
5
5
  # /_/\_\|_| \_/\_/ |_||_| |_| \__, ||___/ _____ \__,_| \__||_||_||___/
6
6
  # |___/ |_____|
7
7
 
8
- __version__ = "0.0.6"
8
+ __version__ = "0.0.7"
9
9
 
10
10
 
11
11
  import dropbox
@@ -268,55 +268,51 @@ class block:
268
268
  block
269
269
  """
270
270
 
271
- def __init__(self, number_of_rows, number_of_columns):
271
+ def __init__(self, value=None, *, number_of_rows=None, number_of_columns=None,column_like=False):
272
272
  self.dict = {}
273
- self.number_of_columns = number_of_columns
274
- self.number_of_rows = number_of_rows
275
-
276
- @classmethod
277
- def from_list_of_lists(cls, list_of_lists, column_like=False):
278
- """
279
- from_list_of_lists
280
-
281
- Parameters
282
- ----------
283
- list_of_lists : list of lists
284
- to be used to fill the block
285
-
286
- columns_like : bool
287
- if False (default), one dimenional lists will be treated as a 1 high range (row-like)
288
-
289
- if True, one dimenional lists will be treated as a 1 wide range (column-like)
290
-
291
- This parameter is not used for proper 2 dimensional list of lists or scalars
292
-
293
- Returns
294
- -------
295
- block
296
-
297
- Note
298
- ----
299
- number_of_rows and number_of_columns will be retrieved from list_of_lists dimension
300
- """
301
- if not isinstance(list_of_lists, list):
302
- list_of_lists = [[list_of_lists]]
303
- if not isinstance(list_of_lists[0], list):
304
- if column_like:
305
- list_of_lists = [[value] for value in list_of_lists]
273
+ self.column_like=column_like
274
+ if value is None:
275
+ if number_of_rows is None:
276
+ number_of_rows=1
277
+ if number_of_columns is None:
278
+ number_of_columns=1
279
+ self.number_of_rows=number_of_rows
280
+ self.number_of_columns=number_of_columns
281
+
282
+ else:
283
+ if isinstance(value,block):
284
+ value=value.value
285
+ self.value=value
286
+ if number_of_rows is not None:
287
+ self.number_of_rows=number_of_rows
288
+ if number_of_columns is not None:
289
+ self.number_of_columns=number_of_columns
290
+
291
+
292
+ @property
293
+ def value(self):
294
+ return [[self.dict.get((row, column)) for column in range(1, self.number_of_columns + 1)] for row in range(1, self.number_of_rows + 1)]
295
+
296
+ @value.setter
297
+ def value(self,value):
298
+ if not isinstance(value, list):
299
+ value = [[value]]
300
+ if not isinstance(value[0], list):
301
+ if self.column_like:
302
+ value = [[item] for item in value]
306
303
  else:
307
- list_of_lists = [list_of_lists]
304
+ value = [value]
308
305
 
309
- self = cls(1, 1)
310
306
 
311
- self.number_of_rows = len(list_of_lists)
307
+ self.number_of_rows = len(value)
312
308
  self._number_of_columns = 0
313
309
 
314
- for row, row_contents in enumerate(list_of_lists, 1):
315
- for column, value in enumerate(row_contents, 1):
316
- if value is not None:
317
- self.dict[row, column] = value
318
- self._number_of_columns = max(self.number_of_columns, column)
319
- return self
310
+ for row, row_contents in enumerate(value, 1):
311
+ for column, item in enumerate(row_contents, 1):
312
+ if item is not None:
313
+ self.dict[row, column] = item
314
+ self._number_of_columns = max(self.number_of_columns, column)
315
+
320
316
 
321
317
  def __setitem__(self, row_column, value):
322
318
  row, column = row_column
@@ -333,14 +329,9 @@ class block:
333
329
  if column < 1 or column > self.number_of_columns:
334
330
  raise IndexError(f"column must be between 1 and {self.number_of_columns} not {column}")
335
331
  return self.dict.get((row, column))
336
-
337
- @property
338
- def as_list_of_lists(self):
339
- return [[self.dict.get((row, column)) for column in range(1, self.number_of_columns + 1)] for row in range(1, self.number_of_rows + 1)]
340
-
341
- @property
342
- def as_minimal_list_of_lists(self):
343
- return [[self.dict.get((row, column)) for column in range(1, self.maximum_column + 1)] for row in range(1, self.maximum_row + 1)]
332
+
333
+ def minimized(self):
334
+ return block(self, number_of_rows=self.highest_used_row_number, number_of_columns=self.highest_used_column_number)
344
335
 
345
336
  @property
346
337
  def number_of_rows(self):
@@ -367,23 +358,24 @@ class block:
367
358
  for row, column in list(self.dict):
368
359
  if column > self._number_of_columns:
369
360
  del self.dict[row, column]
361
+
370
362
 
371
363
  @property
372
- def maximum_row(self):
364
+ def highest_used_row_number(self):
373
365
  if self.dict:
374
366
  return max(row for (row, column) in self.dict)
375
367
  else:
376
368
  return 1
377
369
 
378
370
  @property
379
- def maximum_column(self):
371
+ def highest_used_column_number(self):
380
372
  if self.dict:
381
373
  return max(column for (row, column) in self.dict)
382
374
  else:
383
375
  return 1
384
376
 
385
377
  def __repr__(self):
386
- return f"block.from_list_of_lists({self.as_list_of_lists})"
378
+ return f"block({self.value})"
387
379
 
388
380
 
389
381
  def clear_captured_stdout():
@@ -406,7 +398,7 @@ def captured_stdout_as_str():
406
398
  return "".join(_captured_stdout)
407
399
 
408
400
 
409
- def captured_stdout_as_list_of_lists():
401
+ def captured_stdout_as_value():
410
402
  """
411
403
  returns the captured stdout as a list of lists
412
404
 
@@ -0,0 +1,132 @@
1
+ Metadata-Version: 2.4
2
+ Name: xlwings_utils
3
+ Version: 0.0.7
4
+ Summary: xlwings_utils
5
+ Author-email: Ruud van der Ham <rt.van.der.ham@gmail.com>
6
+ Project-URL: Homepage, https://github.com/salabim/xlwings_utils
7
+ Project-URL: Repository, https://github.com/salabim/xlwings_utils
8
+ Classifier: Development Status :: 5 - Production/Stable
9
+ Classifier: Programming Language :: Python :: 3 :: Only
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: dropbox
13
+ Requires-Dist: ssl
14
+
15
+ <img src="https://www.salabim.org/xlwings_utils_logo2.png">
16
+
17
+ ## Introduction
18
+
19
+ This module provides some useful functions to be used in xlwings lite.
20
+
21
+ ## Installation
22
+
23
+ Just add xlwings-utils to the *requirement.txt* tab. It might be required to add ssl.
24
+
25
+ In the script, add
26
+
27
+ ```ìmport xlwings_utils as xwu```
28
+
29
+ ## Dropbox support
30
+
31
+ The xlwings lite system does not provide access to the local file system. With this module, files can be copied between Dropbox and the local pyodide file system, making it possible to indirectly use the local file system.
32
+
33
+ It is only possible, as of now, to use full-access Dropbox apps.
34
+
35
+ The easiest way to use the Dropbox functionality is to add the credentials to the environment variables. Add REFRESH_TOKEN, APP_KEY and APP_SECRET with their corresponding values to the environment variables.
36
+
37
+ Then, it is possible to list all files in a specified folder with the function `list_dropbox`.
38
+ It is also possible to get the folders and to access all underlying folders.
39
+
40
+ The function `read_dropbox` can be used to read a Dropbox file's contents (bytes).
41
+
42
+ The function `write_dropbox` can be used to write contents (bytes) to a Dropbox file.
43
+
44
+ The functions `list_local`, `read_local` and `write_local` offer similar functionality for the local file system (on pyodide).
45
+
46
+ So, a way to access a file on the system's drive (mapped to Dropbox) as a local file is:
47
+
48
+ ```
49
+ contents = xlwings_utils.read_dropbox('/downloads/file1.xls')
50
+ xlwings_utils.write_local('file1.xlsx')
51
+ df = pandas.read_excel"file1.xlsx")
52
+ ...
53
+ ```
54
+ And the other direction:
55
+ ```
56
+ contents = xlwings_utils.read_local('file1.gif')
57
+ xlwings_utils.write_dropbox('/downloads/file1.gif')
58
+ ```
59
+
60
+ ## Block support
61
+
62
+ The module contains a useful 2-dimensional data structure: *block*.
63
+ This can be useful to manipulate a range without accessing the range directly, which is expensive in terms of memory and execution time.
64
+ The advantage over an ordinary list of lists is that a block is index one-based, in line with range and addressing is done with a row, column tuple.
65
+ So, `my_block(lol)[row, col]` is roughly equivalent to `lol[row-1][col-1]`
66
+
67
+ A block stores the values internally as a dictionary and will only convert these to a list of lists when using `block.value`.
68
+
69
+ Converting the value of a range (usually a list of lists, but can also be a list or scalar) to a block can be done with
70
+
71
+ ```
72
+ my_block = xwu.block.from_value(range.value)
73
+ ```
74
+ The dimensions (number of rows and number of columns) are automatically set.
75
+
76
+ Setting of an individual item (one-based, like range) can be done like
77
+ ```
78
+ my_block[row, column] = x
79
+ ```
80
+ And, likewise, reading an individual item can be done like
81
+ ```
82
+ x = my_block[row, column]
83
+ ```
84
+ It is not allowed t,o read or write outside the block dimensions.
85
+
86
+ It is also possible to define an empty block, like
87
+ ```
88
+ block = xlwings_utils.block(number_of_rows, number_columns)
89
+ ```
90
+ The dimensions can be queried or redefined with `block.number_of_rows` and
91
+ `block.number_of_columns`.
92
+
93
+ To assign a block to range, use
94
+ ```
95
+ range.value = block.value
96
+ ```
97
+
98
+ The property `block.highest`_used_row_number returns the
99
+
100
+ The method `block.minimized()` returns a block that has the dimensions of (highest_used_row_number, highest_used_column_number).
101
+
102
+ ## Capture stdout support
103
+
104
+ The module has support for capturing stdout and -later- using showing the captured output on a sheet.
105
+
106
+ To do that:
107
+
108
+ ```makes it possible to capture stdout writes, which
109
+ with xwu.capture_stdout():
110
+ ...
111
+ ```
112
+ and then the captured output can be copied to the screen, like
113
+
114
+ ```can then be copied to a worksheet in a later stage.
115
+ sheet.range(4,5).value = xwu.captured_stdout_as_value()
116
+ ```
117
+
118
+ Clearing the captured stdout buffer can be done with `xwu.clear_captured_std_out`.
119
+
120
+ Normally, stdout will be also sent to the xlwings lite UI panel. This can be suppressed with
121
+
122
+ ```
123
+ with xwu.capture_stdout(include_print=False):
124
+ ...
125
+ ```
126
+
127
+ ## Badges
128
+
129
+ ![PyPI](https://img.shields.io/pypi/v/xlwings-utils) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/xlwings-utils) ![PyPI - Implementation](https://img.shields.io/pypi/implementation/xlwings-utils)
130
+ ![PyPI - License](https://img.shields.io/pypi/l/xlwings-utils) ![ruff](https://img.shields.io/badge/style-ruff-41B5BE?style=flat)
131
+ ![GitHub last commit](https://img.shields.io/github/last-commit/salabim/peek)
132
+
@@ -1,52 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: xlwings_utils
3
- Version: 0.0.6
4
- Summary: xlwings_utils
5
- Author-email: Ruud van der Ham <rt.van.der.ham@gmail.com>
6
- Project-URL: Homepage, https://github.com/salabim/xlwings_utils
7
- Project-URL: Repository, https://github.com/salabim/xlwings_utils
8
- Classifier: Development Status :: 5 - Production/Stable
9
- Classifier: Programming Language :: Python :: 3 :: Only
10
- Requires-Python: >=3.9
11
- Description-Content-Type: text/markdown
12
- Requires-Dist: dropbox
13
- Requires-Dist: ssl
14
-
15
- <img src="https://www.salabim.org/xlwings_utils_logo1.png">
16
-
17
- ## Introduction
18
-
19
- This module provides some useful functions to be used in xlwings lite.
20
-
21
- The xlwings lite system does not provide access to the local file system. With this
22
- module, files can be copied between dropbox and the local pyodide file systen. And
23
- therefore, it is possible to indirectly use the local file system.
24
-
25
- The module contains support for a useful 2 dimensional data structure: block.
26
- Thjs can be useful to manipulate a range without accessing the range directly,
27
- which is expensive in terms of memory and execution time.
28
-
29
- On top of that, this module makes it possible to capture stdout writes, which
30
- can then be copied to a worksheet in a later stage.
31
-
32
- ## Installation
33
-
34
- Just add xlwings-utils to the requirement tab. It might be required to add ssl.
35
-
36
- ## Dropbox support
37
-
38
- xlwings_lite only works with full access dropbox apps.
39
-
40
- In order to use dropbox functionality, is is necessary to initialize the module with credentials.
41
-
42
- ```xwu.dropbox_init()```
43
- If called without parameters, the refresh_token is
44
-
45
- ## Capture stdout support
46
-
47
- Badges
48
-
49
- ![PyPI](https://img.shields.io/pypi/v/xlwings-utils) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/xlwings-utils) ![PyPI - Implementation](https://img.shields.io/pypi/implementation/xlwings-utils)
50
- ![PyPI - License](https://img.shields.io/pypi/l/xlwings-utils) ![ruff](https://img.shields.io/badge/style-ruff-41B5BE?style=flat)
51
- ![GitHub last commit](https://img.shields.io/github/last-commit/salabim/peek)
52
-
@@ -1,38 +0,0 @@
1
- <img src="https://www.salabim.org/xlwings_utils_logo1.png">
2
-
3
- ## Introduction
4
-
5
- This module provides some useful functions to be used in xlwings lite.
6
-
7
- The xlwings lite system does not provide access to the local file system. With this
8
- module, files can be copied between dropbox and the local pyodide file systen. And
9
- therefore, it is possible to indirectly use the local file system.
10
-
11
- The module contains support for a useful 2 dimensional data structure: block.
12
- Thjs can be useful to manipulate a range without accessing the range directly,
13
- which is expensive in terms of memory and execution time.
14
-
15
- On top of that, this module makes it possible to capture stdout writes, which
16
- can then be copied to a worksheet in a later stage.
17
-
18
- ## Installation
19
-
20
- Just add xlwings-utils to the requirement tab. It might be required to add ssl.
21
-
22
- ## Dropbox support
23
-
24
- xlwings_lite only works with full access dropbox apps.
25
-
26
- In order to use dropbox functionality, is is necessary to initialize the module with credentials.
27
-
28
- ```xwu.dropbox_init()```
29
- If called without parameters, the refresh_token is
30
-
31
- ## Capture stdout support
32
-
33
- Badges
34
-
35
- ![PyPI](https://img.shields.io/pypi/v/xlwings-utils) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/xlwings-utils) ![PyPI - Implementation](https://img.shields.io/pypi/implementation/xlwings-utils)
36
- ![PyPI - License](https://img.shields.io/pypi/l/xlwings-utils) ![ruff](https://img.shields.io/badge/style-ruff-41B5BE?style=flat)
37
- ![GitHub last commit](https://img.shields.io/github/last-commit/salabim/peek)
38
-
@@ -1,113 +0,0 @@
1
- import os
2
- import sys
3
- from pathlib import Path
4
-
5
- if __name__ == "__main__": # to make the tests run without the pytest cli
6
- file_folder = os.path.dirname(__file__)
7
- os.chdir(file_folder)
8
- sys.path.insert(0, file_folder + "/../xlwings_utils")
9
-
10
- import pytest
11
-
12
- import xlwings_utils as xwu
13
-
14
- def test_block():
15
- this_block = xwu.block(number_of_rows=4, number_of_columns=6)
16
- this_block[1, 2] = 2
17
- this_block[2, 5] = 25
18
- assert this_block.dict == {(1, 2): 2, (2, 5): 25}
19
- assert this_block.as_list_of_lists == [
20
- [None, 2, None, None, None, None],
21
- [None, None, None, None, 25, None],
22
- [None, None, None, None, None, None],
23
- [None, None, None, None, None, None],
24
- ]
25
- assert this_block.as_minimal_list_of_lists == [[None, 2, None, None, None], [None, None, None, None, 25]]
26
- assert this_block.number_of_rows == 4
27
- assert this_block.number_of_columns == 6
28
- assert this_block.maximum_row == 2
29
- assert this_block.maximum_column == 5
30
-
31
- this_block.number_of_rows = 99
32
- this_block.number_of_columns = 99
33
- assert this_block.maximum_row == 2
34
- assert this_block.maximum_column == 5
35
-
36
- this_block.number_of_rows = 1
37
- this_block.number_of_columns = 3
38
- assert this_block.as_list_of_lists == [[None, 2, None]]
39
- assert this_block.as_minimal_list_of_lists == [[None, 2]]
40
-
41
-
42
- def test_block_from_list_of_lists():
43
- this_block = xwu.block.from_list_of_lists([[1, 2, 3], [4, 5, 6]])
44
- assert this_block.dict == {(1, 1): 1, (1, 2): 2, (1, 3): 3, (2, 1): 4, (2, 2): 5, (2, 3): 6}
45
- assert this_block.as_list_of_lists == [[1, 2, 3], [4, 5, 6]]
46
- assert this_block.as_minimal_list_of_lists == [[1, 2, 3], [4, 5, 6]]
47
- with pytest.raises(ValueError):
48
- this_block.number_of_rows = 0
49
- with pytest.raises(ValueError):
50
- this_block.number_of_columns = 0
51
- with pytest.raises(ValueError):
52
- this_block = xwu.block(0, 1)
53
- with pytest.raises(ValueError):
54
- this_block = xwu.block(1, 0)
55
-
56
-
57
- def test_block_one_dimension():
58
- this_block = xwu.block.from_list_of_lists([1, 2, 3])
59
- assert this_block.as_list_of_lists == [[1, 2, 3]]
60
-
61
- this_block = xwu.block.from_list_of_lists([1, 2, 3], column_like=True)
62
- assert this_block.as_list_of_lists == [[1], [2], [3]]
63
-
64
-
65
- def test_block_scalar():
66
- this_block = xwu.block.from_list_of_lists(1, column_like=True)
67
- assert this_block.as_list_of_lists == [[1]]
68
-
69
- def test_raise():
70
- this_block=xwu.block(4,6)
71
- with pytest.raises(IndexError):
72
- a=this_block[0,1]
73
- with pytest.raises(IndexError):
74
- a=this_block[5,1]
75
-
76
- with pytest.raises(IndexError):
77
- a=this_block[1,0]
78
- with pytest.raises(IndexError):
79
- a=this_block[1,7]
80
-
81
- with pytest.raises(IndexError):
82
- this_block[0,1]=1
83
- with pytest.raises(IndexError):
84
- this_block[5,1]=1
85
-
86
- with pytest.raises(IndexError):
87
- this_block[1,0]=1
88
- with pytest.raises(IndexError):
89
- this_block[1,7]=1
90
-
91
- def test_capture_stdout(capsys):
92
- with xwu.capture_stdout():
93
- print("abc")
94
- print("def")
95
- assert xwu.captured_stdout_as_str()=="abc\ndef\n"
96
- assert xwu.captured_stdout_as_list_of_lists()==[["abc"],["def"]]
97
-
98
- out, err = capsys.readouterr()
99
- assert out=="abc\ndef\n"
100
-
101
- xwu.clear_captured_stdout()
102
- assert xwu.captured_stdout_as_str()==""
103
- with xwu.capture_stdout(include_print=False):
104
- print("ghi")
105
- print("jkl")
106
- assert xwu.captured_stdout_as_str()=="ghi\njkl\n"
107
- assert xwu.captured_stdout_as_list_of_lists()==[["ghi"],["jkl"]]
108
- out, err = capsys.readouterr()
109
- assert out==""
110
-
111
-
112
- if __name__ == "__main__":
113
- pytest.main(["-vv", "-s", "-x", __file__])
@@ -1,52 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: xlwings_utils
3
- Version: 0.0.6
4
- Summary: xlwings_utils
5
- Author-email: Ruud van der Ham <rt.van.der.ham@gmail.com>
6
- Project-URL: Homepage, https://github.com/salabim/xlwings_utils
7
- Project-URL: Repository, https://github.com/salabim/xlwings_utils
8
- Classifier: Development Status :: 5 - Production/Stable
9
- Classifier: Programming Language :: Python :: 3 :: Only
10
- Requires-Python: >=3.9
11
- Description-Content-Type: text/markdown
12
- Requires-Dist: dropbox
13
- Requires-Dist: ssl
14
-
15
- <img src="https://www.salabim.org/xlwings_utils_logo1.png">
16
-
17
- ## Introduction
18
-
19
- This module provides some useful functions to be used in xlwings lite.
20
-
21
- The xlwings lite system does not provide access to the local file system. With this
22
- module, files can be copied between dropbox and the local pyodide file systen. And
23
- therefore, it is possible to indirectly use the local file system.
24
-
25
- The module contains support for a useful 2 dimensional data structure: block.
26
- Thjs can be useful to manipulate a range without accessing the range directly,
27
- which is expensive in terms of memory and execution time.
28
-
29
- On top of that, this module makes it possible to capture stdout writes, which
30
- can then be copied to a worksheet in a later stage.
31
-
32
- ## Installation
33
-
34
- Just add xlwings-utils to the requirement tab. It might be required to add ssl.
35
-
36
- ## Dropbox support
37
-
38
- xlwings_lite only works with full access dropbox apps.
39
-
40
- In order to use dropbox functionality, is is necessary to initialize the module with credentials.
41
-
42
- ```xwu.dropbox_init()```
43
- If called without parameters, the refresh_token is
44
-
45
- ## Capture stdout support
46
-
47
- Badges
48
-
49
- ![PyPI](https://img.shields.io/pypi/v/xlwings-utils) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/xlwings-utils) ![PyPI - Implementation](https://img.shields.io/pypi/implementation/xlwings-utils)
50
- ![PyPI - License](https://img.shields.io/pypi/l/xlwings-utils) ![ruff](https://img.shields.io/badge/style-ruff-41B5BE?style=flat)
51
- ![GitHub last commit](https://img.shields.io/github/last-commit/salabim/peek)
52
-
File without changes