xlwings-utils 0.0.3__tar.gz → 0.0.5__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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xlwings_utils
3
- Version: 0.0.3
3
+ Version: 0.0.5
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
@@ -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.3"
13
+ version = "0.0.5"
14
14
  readme = "README.md"
15
15
  requires-python = ">=3.9"
16
16
  dependencies = [
@@ -0,0 +1,98 @@
1
+ import math
2
+ import itertools
3
+ import os
4
+ import sys
5
+ import re
6
+ from pathlib import Path
7
+
8
+ if __name__ == "__main__": # to make the tests run without the pytest cli
9
+ file_folder = os.path.dirname(__file__)
10
+ os.chdir(file_folder)
11
+ sys.path.insert(0, file_folder + "/../xlwings_utils")
12
+
13
+ import pytest
14
+
15
+ import xlwings_utils as xwu
16
+
17
+
18
+ def test_block():
19
+ this_block = xwu.block(number_of_rows=4, number_of_columns=6)
20
+ this_block[1, 2] = 2
21
+ this_block[2, 5] = 25
22
+ assert this_block.dict == {(1, 2): 2, (2, 5): 25}
23
+ assert this_block.as_list_of_lists == [
24
+ [None, 2, None, None, None, None],
25
+ [None, None, None, None, 25, None],
26
+ [None, None, None, None, None, None],
27
+ [None, None, None, None, None, None],
28
+ ]
29
+ assert this_block.as_minimal_list_of_lists == [[None, 2, None, None, None], [None, None, None, None, 25]]
30
+ assert this_block.number_of_rows == 4
31
+ assert this_block.number_of_columns == 6
32
+ assert this_block.maximum_row == 2
33
+ assert this_block.maximum_column == 5
34
+
35
+ this_block.number_of_rows = 99
36
+ this_block.number_of_columns = 99
37
+ assert this_block.maximum_row == 2
38
+ assert this_block.maximum_column == 5
39
+
40
+ this_block.number_of_rows = 1
41
+ this_block.number_of_columns = 3
42
+ assert this_block.as_list_of_lists == [[None, 2, None]]
43
+ assert this_block.as_minimal_list_of_lists == [[None, 2]]
44
+
45
+
46
+ def test_block_from_list_of_lists():
47
+ this_block = xwu.block.from_list_of_lists([[1, 2, 3], [4, 5, 6]])
48
+ assert this_block.dict == {(1, 1): 1, (1, 2): 2, (1, 3): 3, (2, 1): 4, (2, 2): 5, (2, 3): 6}
49
+ assert this_block.as_list_of_lists == [[1, 2, 3], [4, 5, 6]]
50
+ assert this_block.as_minimal_list_of_lists == [[1, 2, 3], [4, 5, 6]]
51
+ with pytest.raises(ValueError):
52
+ this_block.number_of_rows = 0
53
+ with pytest.raises(ValueError):
54
+ this_block.number_of_columns = 0
55
+ with pytest.raises(ValueError):
56
+ this_block = xwu.block(0, 1)
57
+ with pytest.raises(ValueError):
58
+ this_block = xwu.block(1, 0)
59
+
60
+
61
+ def test_block_one_dimension():
62
+ this_block = xwu.block.from_list_of_lists([1, 2, 3])
63
+ assert this_block.as_list_of_lists == [[1, 2, 3]]
64
+
65
+ this_block = xwu.block.from_list_of_lists([1, 2, 3], column_like=True)
66
+ assert this_block.as_list_of_lists == [[1], [2], [3]]
67
+
68
+
69
+ def test_block_scalar():
70
+ this_block = xwu.block.from_list_of_lists(1, column_like=True)
71
+ assert this_block.as_list_of_lists == [[1]]
72
+
73
+ def test_raise():
74
+ this_block=xwu.block(4,6)
75
+ with pytest.raises(IndexError):
76
+ a=this_block[0,1]
77
+ with pytest.raises(IndexError):
78
+ a=this_block[5,1]
79
+
80
+ with pytest.raises(IndexError):
81
+ a=this_block[1,0]
82
+ with pytest.raises(IndexError):
83
+ a=this_block[1,7]
84
+
85
+ with pytest.raises(IndexError):
86
+ this_block[0,1]=1
87
+ with pytest.raises(IndexError):
88
+ this_block[5,1]=1
89
+
90
+ with pytest.raises(IndexError):
91
+ this_block[1,0]=1
92
+ with pytest.raises(IndexError):
93
+ this_block[1,7]=1
94
+
95
+
96
+
97
+ if __name__ == "__main__":
98
+ pytest.main(["-vv", "-s", "-x", __file__])
@@ -5,12 +5,11 @@
5
5
  # /_/\_\|_| \_/\_/ |_||_| |_| \__, ||___/ _____ \__,_| \__||_||_||___/
6
6
  # |___/ |_____|
7
7
 
8
- __version__ = "0.0.3"
8
+ __version__ = "0.0.5"
9
9
 
10
10
 
11
11
  import dropbox
12
12
  from pathlib import Path
13
- import sys
14
13
  import os
15
14
 
16
15
  _captured_stdout = []
@@ -18,7 +17,7 @@ dbx = None
18
17
 
19
18
 
20
19
  def dropbox_init(refresh_token=None, app_key=None, app_secret=None):
21
- '''
20
+ """
22
21
  dropbox initialize
23
22
 
24
23
  This function has to be called prior to using any dropbox function
@@ -29,13 +28,13 @@ def dropbox_init(refresh_token=None, app_key=None, app_secret=None):
29
28
  oauth2 refreshntoken
30
29
 
31
30
  if omitted: use the environment variable REFRESH_TOKEN
32
-
31
+
33
32
  app_key : str
34
33
  app key
35
34
 
36
35
  if omitted: use the environment variable APP_KEY
37
36
 
38
-
37
+
39
38
  app_secret : str
40
39
  app secret
41
40
 
@@ -44,41 +43,42 @@ def dropbox_init(refresh_token=None, app_key=None, app_secret=None):
44
43
  Returns
45
44
  -------
46
45
  -
47
- '''
46
+ """
48
47
  if refresh_token is None:
49
- refresh_token =os.environ["REFRESH_TOKEN"]
48
+ refresh_token = os.environ["REFRESH_TOKEN"]
50
49
  if app_key is None:
51
- app_key=os.environ["APP_KEY"]
50
+ app_key = os.environ["APP_KEY"]
52
51
  if app_secret is None:
53
- app_secret =os.environ["APP_SECRET"]
52
+ app_secret = os.environ["APP_SECRET"]
54
53
 
55
54
  global dbx
56
55
  dbx = dropbox.Dropbox(oauth2_refresh_token=refresh_token, app_key=app_key, app_secret=app_secret)
57
-
56
+
57
+
58
58
  def _check_dbx():
59
59
  if dbx is None:
60
- raise ValueError('not initialized. Please call dropbox_init()')
60
+ raise ValueError("not initialized. Please call dropbox_init()")
61
61
 
62
62
 
63
63
  def list_dropbox(path="", recursive=False):
64
- '''
64
+ """
65
65
  list_dropbox
66
-
66
+
67
67
  returns all dropbox files in path
68
-
68
+
69
69
  Parameters
70
70
  ----------
71
71
  path : str or Pathlib.Path
72
72
  path from which to list all files (default: '')
73
-
74
-
73
+
74
+
75
75
  recursive : bool
76
76
  if True, recursively list files. if False (default) no recursion
77
-
77
+
78
78
  Returns
79
79
  -------
80
80
  files, relative to path : list
81
- '''
81
+ """
82
82
  _check_dbx()
83
83
  out = []
84
84
  result = dbx.files_list_folder(path, recursive=recursive)
@@ -97,20 +97,20 @@ def list_dropbox(path="", recursive=False):
97
97
 
98
98
 
99
99
  def read_dropbox(dropbox_path):
100
- '''
100
+ """
101
101
  read_dropbox
102
-
102
+
103
103
  read from dopbox at given path
104
-
104
+
105
105
  Parameters
106
106
  ----------
107
- path : str or Pathlib.Path
107
+ dropbox_path : str or Pathlib.Path
108
108
  path to read from
109
-
109
+
110
110
  Returns
111
111
  -------
112
112
  contents of the dropbox file : bytes
113
- '''
113
+ """
114
114
 
115
115
  _check_dbx()
116
116
  metadata, response = dbx.files_download(dropbox_path)
@@ -120,85 +120,177 @@ def read_dropbox(dropbox_path):
120
120
 
121
121
  def write_dropbox(dropbox_path, contents):
122
122
  _check_dbx()
123
+ """
124
+ write_dropbox
125
+
126
+ write from dopbox at given path
127
+
128
+ Parameters
129
+ ----------
130
+ dropbox_path : str or Pathlib.Path
131
+ path to write to
132
+
133
+ contents : bytes
134
+ contents to be written
135
+
136
+ """
123
137
  dbx.files_upload(contents, dropbox_path, mode=dropbox.files.WriteMode.overwrite)
124
138
 
125
139
 
126
- def list_pyodide(path):
140
+ def list_local(path):
127
141
  path = Path(path)
128
142
  return list(path.iterdir())
129
143
 
130
144
 
131
- def write_pyodide(path, contents):
145
+ def write_local(path, contents):
132
146
  path = Path(path)
133
147
  path.parent.mkdir(parents=True, exist_ok=True)
134
148
  with open(path, "wb") as f:
135
149
  f.write(contents)
136
150
 
137
151
 
138
- def read_pyodide(path):
152
+ def read_local(path):
139
153
  path = Path(path)
140
154
  with open(path, "rb") as f:
141
155
  contents = f.read()
142
156
  return contents
143
157
 
158
+
144
159
  class block:
145
- def __init__(self, number_of_rows,number_of_columns):
146
- self.dict={}
147
- self.number_of_columns=number_of_columns
148
- self.number_of_rows=number_of_rows
160
+ """
161
+ block is 2 dimensional data structure with 1 as lowest index (like xlwings range)
162
+
163
+ Parameters
164
+ ----------
165
+ number_of_rows : int
166
+ number of rows
167
+
168
+ number_of_columns : int
169
+ number of columns
170
+
171
+ Returns
172
+ -------
173
+ block
174
+ """
175
+
176
+ def __init__(self, number_of_rows, number_of_columns):
177
+ self.dict = {}
178
+ self.number_of_columns = number_of_columns
179
+ self.number_of_rows = number_of_rows
149
180
 
150
181
  @classmethod
151
182
  def from_list_of_lists(cls, list_of_lists, column_like=False):
152
- if not isinstance(list_of_lists[0],list):
183
+ """
184
+ from_list_of_lists
185
+
186
+ Parameters
187
+ ----------
188
+ list_of_lists : list of lists
189
+ to be used to fill the block
190
+
191
+ columns_like : bool
192
+ if False (default), one dimenional lists will be treated as a 1 high range (row-like)
193
+
194
+ if True, one dimenional lists will be treated as a 1 wide range (column-like)
195
+
196
+ This parameter is not used for proper 2 dimensional list of lists or scalars
197
+
198
+ Returns
199
+ -------
200
+ block
201
+
202
+ Note
203
+ ----
204
+ number_of_rows and number_of_columns will be retrieved from list_of_lists dimension
205
+ """
206
+ if not isinstance(list_of_lists, list):
207
+ list_of_lists = [[list_of_lists]]
208
+ if not isinstance(list_of_lists[0], list):
153
209
  if column_like:
154
- list_of_lists=[[value] for value in list_of_lists]
210
+ list_of_lists = [[value] for value in list_of_lists]
155
211
  else:
156
- list_of_lists=[list_of_lists]
212
+ list_of_lists = [list_of_lists]
157
213
 
158
- self=cls(0,0)
214
+ self = cls(1, 1)
159
215
 
160
- self.number_of_rows=len(list_of_lists)
161
- self.number_of_columns=0
162
-
216
+ self.number_of_rows = len(list_of_lists)
217
+ self._number_of_columns = 0
163
218
 
164
- for row,row_contents in enumerate(list_of_lists,1):
165
- for column,value in enumerate(row_contents,1):
219
+ for row, row_contents in enumerate(list_of_lists, 1):
220
+ for column, value in enumerate(row_contents, 1):
166
221
  if value is not None:
167
- self.dict[row,column]=value
168
- self.number_of_columns=max(self.number_of_columns, column)
222
+ self.dict[row, column] = value
223
+ self._number_of_columns = max(self.number_of_columns, column)
169
224
  return self
170
-
225
+
171
226
  def __setitem__(self, row_column, value):
172
- row,column=row_column
173
- if row<1 or row>self.number_of_rows:
174
- raise IndexError
175
- if column<1 or column>self.number_of_columns:
176
- raise IndexError
177
- self.dict[row,column]=value
227
+ row, column = row_column
228
+ if row < 1 or row > self.number_of_rows:
229
+ raise IndexError(f"row must be between 1 and {self.number_of_rows} not {row}")
230
+ if column < 1 or column > self.number_of_columns:
231
+ raise IndexError(f"column must be between 1 and {self.number_of_columns} not {column}")
232
+ self.dict[row, column] = value
178
233
 
179
234
  def __getitem__(self, row_column):
180
- row,column=row_column
181
- if row<1 or row>self.number_of_rows:
182
- raise IndexError
183
- if column<1 or column>self.number_of_columns:
184
- raise IndexError
185
- return self.dict.get((row,column))
235
+ row, column = row_column
236
+ if row < 1 or row > self.number_of_rows:
237
+ raise IndexError(f"row must be between 1 and {self.number_of_rows} not {row}")
238
+ if column < 1 or column > self.number_of_columns:
239
+ raise IndexError(f"column must be between 1 and {self.number_of_columns} not {column}")
240
+ return self.dict.get((row, column))
186
241
 
187
242
  @property
188
243
  def as_list_of_lists(self):
189
- 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)]
190
-
244
+ 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)]
191
245
 
192
246
  @property
193
247
  def as_minimal_list_of_lists(self):
194
- number_of_rows=max(row for row,column in self.dict)
195
- number_of_columns=max(column for row,column in self.dict)
196
- return [[self.dict.get((row,column)) for column in range(1,number_of_columns+1)] for row in range(1,number_of_rows+1)]
248
+ return [[self.dict.get((row, column)) for column in range(1, self.maximum_column + 1)] for row in range(1, self.maximum_row + 1)]
249
+
250
+ @property
251
+ def number_of_rows(self):
252
+ return self._number_of_rows
253
+
254
+ @number_of_rows.setter
255
+ def number_of_rows(self, value):
256
+ if value<1:
257
+ raise ValueError(f"number_of_rows should be >=1, not {value}")
258
+ self._number_of_rows = value
259
+ for row, column in list(self.dict):
260
+ if row > self._number_of_rows:
261
+ del self.dict[row, column]
197
262
 
263
+ @property
264
+ def number_of_columns(self):
265
+ return self._number_of_columns
266
+
267
+ @number_of_columns.setter
268
+ def number_of_columns(self, value):
269
+ if value<1:
270
+ raise ValueError(f"number_of_columns should be >=1, not {value}")
271
+ self._number_of_columns = value
272
+ for row, column in list(self.dict):
273
+ if column > self._number_of_columns:
274
+ del self.dict[row, column]
275
+
276
+ @property
277
+ def maximum_row(self):
278
+ if self.dict:
279
+ return max(row for (row, column) in self.dict)
280
+ else:
281
+ return 1
282
+
283
+ @property
284
+ def maximum_column(self):
285
+ if self.dict:
286
+ return max(column for (row, column) in self.dict)
287
+ else:
288
+ return 1
198
289
 
199
290
  def __repr__(self):
200
291
  return f"block.from_list_of_lists({self.as_list_of_lists})"
201
292
 
293
+
202
294
  def clear_captured_stdout():
203
295
  """
204
296
  empties the captured stdout
@@ -219,9 +311,9 @@ def captured_stdout_as_str():
219
311
  return "".join(_captured_stdout)
220
312
 
221
313
 
222
- def captured_stdout_as_range():
314
+ def captured_stdout_as_list_of_lists():
223
315
  """
224
- returns the captured stdout as a list of strings
316
+ returns the captured stdout as a list of lists
225
317
 
226
318
  Returns
227
319
  -------
@@ -274,31 +366,3 @@ class capture_stdout:
274
366
 
275
367
  if __name__ == "__main__":
276
368
  ...
277
-
278
-
279
- # @xw.script
280
- # def test_stdout(book: xw.Book):
281
- # with capture_stdout():
282
- # for i in range(10):
283
- # print(10 * f'{i}')
284
- # book.sheets.active.range("A1").value=captured_stdout_as_range()
285
-
286
-
287
- # @xw.script
288
- # def test(book: xw.Book):
289
- # dropbox_init(
290
- # refresh_token=REFRESH_TOKEN,
291
- # app_key=APP_KEY,
292
- # app_secret=APP_SECRET,
293
- # )
294
-
295
- # files =list_dropbox("/Downloads",recursive=True)
296
- # peek(files)
297
- # write_pyodide("Test/x.x", b"abc")
298
- # files = list_pyodide("Test")
299
-
300
- # # files=list_dropbox_files("/Downloads")
301
- # # peek(files)
302
- # contents = read_dropbox("/Downloads/dropbox setup.py")
303
- # write_dropbox("/Downloads/dropbox setup1.py", contents)
304
- # peek("done")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xlwings_utils
3
- Version: 0.0.3
3
+ Version: 0.0.5
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
@@ -1,5 +1,6 @@
1
1
  README.md
2
2
  pyproject.toml
3
+ tests/test_xlwings_utils.py
3
4
  xlwings_utils/__init__.py
4
5
  xlwings_utils/xlwings_utils.py
5
6
  xlwings_utils.egg-info/PKG-INFO
File without changes
File without changes