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