tpltable 0.3.3__tar.gz → 0.3.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.1
2
2
  Name: tpltable
3
- Version: 0.3.3
3
+ Version: 0.3.4
4
4
  Summary: define "Excel" "Table|StyleTable" "Row|Col|StyleRow|StyleCol". Can dynamic modify excel data & styles. Support multiple kinds of indexes. (70%)
5
5
  Author-email: 2229066748@qq.com
6
6
  Maintainer: Eagle'sBaby
@@ -5,7 +5,7 @@ from setuptools import find_packages, setup
5
5
 
6
6
  setup(
7
7
  name='tpltable',
8
- version='0.3.3',
8
+ version='0.3.4',
9
9
  description='define "Excel" "Table|StyleTable" "Row|Col|StyleRow|StyleCol". Can dynamic modify excel data & styles. Support multiple kinds of indexes. (70%)',
10
10
  author_email='2229066748@qq.com',
11
11
  maintainer="Eagle'sBaby",
@@ -73,6 +73,11 @@ COLORAMA_STYLES = {
73
73
 
74
74
  __PAT_COORD = re.compile("([A-Z]+)(\d+)")
75
75
 
76
+
77
+ # 模糊的行列索引混用警告
78
+ class AmbiguousIndexWarning(UserWarning):
79
+ ...
80
+
76
81
  class Coord:
77
82
  def __init__(self, iloc_c, iloc_r):
78
83
  self._r:int = iloc_r
@@ -143,7 +148,7 @@ def index_from_string(letters:str, *, only_int:bool=False, should:str=None) -> U
143
148
  if letters.isdigit():
144
149
  if should == 's':
145
150
  warnings.warn(
146
- f"Here should be a letter, but got '{letters}'. Regarded as '{get_column_letter(int(letters))}'."
151
+ AmbiguousIndexWarning(f"Here should be a letter (Col-Index), but got '{letters}' (Row-Index). Regarded as '{get_column_letter(int(letters))}'."),
147
152
  )
148
153
  return int(letters)
149
154
  _s = __PAT_COORD.match(letters)
@@ -154,7 +159,7 @@ def index_from_string(letters:str, *, only_int:bool=False, should:str=None) -> U
154
159
  return Coord(index_from_string(_c) - 1, int(_r) - 1)
155
160
  if should == 'i':
156
161
  warnings.warn(
157
- f"Here should be an digit, but got '{letters}'. Regarded as '{_column_index_from_string(letters)}'."
162
+ AmbiguousIndexWarning(f"Here should be an digit (Row-Index), but got '{letters}' (Col-Index). Regarded as '{_column_index_from_string(letters)}'.")
158
163
  )
159
164
  return _column_index_from_string(letters)
160
165
 
@@ -7,10 +7,96 @@ from tpltable.core import *
7
7
  from tpltable.style import Style, TYPE_BORDER
8
8
 
9
9
  _PAT_COORD = re.compile(r"([A-Z]+)(\d+)")
10
+
11
+
10
12
  class EMPTY_INDEX:
11
13
  pass
12
14
 
13
- class _ExcelIndexsLike_1DArray:
15
+
16
+ class _ExcelIndexsLike_1DArray_Def:
17
+
18
+ def _reindexself(self) -> None:
19
+ """
20
+ Reindex the Series
21
+ * Return None. Modify self._sr inplace.
22
+ :return:
23
+ """
24
+ raise NotImplementedError
25
+
26
+ def _reconstruct(self, other) -> None:
27
+ """
28
+ Reconstruct self
29
+ * Return None. Modify self._sr inplace.
30
+ :param other: inst of __class__. The other instance.
31
+ :return:
32
+ """
33
+ raise NotImplementedError
34
+
35
+ def _construct_new_from_index(self, new_index: Union[int, slice], *, inplace=False) -> '__class__() | None':
36
+ """
37
+ Construct a new __class__ from the new index
38
+ * Use this instead of directly create a new __class__ object. So you can override this method to add some other logic.
39
+ :param new_index: int|slice. The new index you want to index self
40
+ *
41
+ :param inplace: bool. If True, modify self inplace. If True, Return None.
42
+ :return: inst of __class__ | None
43
+ """
44
+ raise NotImplementedError
45
+
46
+ def _construct_new_from_insert(self, insert_index: int, *values, inplace=False) -> '__class__() | None':
47
+ """
48
+ Construct a new __class__ from the new index
49
+ * Use this instead of directly create a new __class__ object. So you can override this method to add some other logic.
50
+ :param insert_index: int. The index to insert before.
51
+ :param *values: Any. The values to insert.
52
+ :param inplace:
53
+ :return: inst of __class__ | None
54
+ """
55
+ raise NotImplementedError
56
+
57
+ def _construct_new_from_delete(self, delete_index: Union[int, slice], *, inplace=False) -> '__class__() | None':
58
+ """
59
+ Construct a new __class__ from the new index
60
+ * Use this instead of directly create a new __class__ object. So you can override this method to add some other logic.
61
+ :param delete_index: int|slice. The index to delete.
62
+ *
63
+ :param inplace: bool. If True, modify self inplace. If True, Return None.
64
+ :return: inst of __class__ | None
65
+ """
66
+ raise NotImplementedError
67
+
68
+ def on_subinstance(self, construction: object) -> '__class__()':
69
+ """
70
+ Hook function called when a subinstance is created.
71
+ * Return the new instance. So you can modify the new instance.
72
+ * When this method is called, self is not modified.
73
+ :param construction: inst of __class__. The subinstance created.
74
+ :return: inst of __class__ | None
75
+ """
76
+ return construction
77
+
78
+ def on_insert(self, construction: object) -> '__class__()':
79
+ """
80
+ Hook function called when a subinstance is created.
81
+ * Return the new instance. So you can modify the new instance.
82
+ * When this method is called, self is not modified.
83
+ :param construction: inst of __class__. The subinstance created.
84
+ :return: inst of __class__
85
+ """
86
+ return construction
87
+
88
+ def on_delete(self, construction: object) -> '__class__()':
89
+ """
90
+ Hook function called when a subinstance is created.
91
+ * Return the new instance. So you can modify the new instance.
92
+ * When this method is called, self is not modified.
93
+ :param construction: inst of __class__. The subinstance created.
94
+ :return: inst of __class__
95
+ """
96
+ return construction
97
+
98
+
99
+ class _ExcelIndexsLike_1DArray_Base(_ExcelIndexsLike_1DArray_Def):
14
100
  _CLS_DEFAULT_INDEX_TYPE = None # "i" or "s" or None
15
101
 
16
102
  # None: integer index, start with 0 and label'0'
@@ -18,65 +104,119 @@ class _ExcelIndexsLike_1DArray:
18
104
  # "s": letter index, start with 0 and label:'A'
19
105
  def __init__(self, _from=None, *, copy: bool = True):
20
106
  self._sr: pd.Series = None
21
- if isinstance(_from, pd.Series):
22
- self._sr = _from
23
- if copy:
24
- self._sr = self._sr.copy()
25
- elif isinstance(_from, np.ndarray):
26
- # check shape
27
- s = _from.shape
28
- if np.ndim(_from) != 1:
29
- raise ValueError(f"Only 1D array is supported. But got {np.ndim(_from)}D array.(shape={s})")
30
- self._sr = pd.Series(_from)
31
107
 
32
- elif isinstance(_from, list):
108
+ if isinstance(_from, list):
33
109
  try:
34
- arr = np.array(_from)
35
- s = arr.shape
36
- if np.ndim(arr) != 1:
37
- raise ValueError(f"Only 1D array is supported. But got {np.ndim(arr)}D array from list.(shape={s})")
38
- self._sr = pd.Series(arr)
110
+ _from = np.array(_from)
39
111
  except Exception as e:
40
112
  raise ValueError(f"Failed to convert list to 1D array. {e}")
41
- else:
42
- raise ValueError(f"Unsupported type: {type(_from)}")
43
-
44
- self._reindex()
45
113
 
46
- @staticmethod
47
- def _retype_to_unitcell(_from):
48
- if isinstance(_from, pd.Series):
49
- if len(_from) and not isinstance(_from.iloc[0]):
50
- ...
51
- self._sr = _from
52
- if copy:
53
- self._sr = self._sr.copy()
114
+ if _from is None:
115
+ self._sr = pd.Series()
54
116
  elif isinstance(_from, np.ndarray):
55
117
  # check shape
56
118
  s = _from.shape
57
119
  if np.ndim(_from) != 1:
58
120
  raise ValueError(f"Only 1D array is supported. But got {np.ndim(_from)}D array.(shape={s})")
59
- if _from.shape[0] != 0:
60
- ...
61
-
62
- elif isinstance(_from, list):
63
- try:
64
- arr = np.array(_from)
65
- s = arr.shape
66
- if np.ndim(arr) != 1:
67
- raise ValueError(f"Only 1D array is supported. But got {np.ndim(arr)}D array from list.(shape={s})")
68
- self._sr = pd.Series(arr)
69
- except Exception as e:
70
- raise ValueError(f"Failed to convert list to 1D array. {e}")
121
+ self._sr = pd.Series(_from)
122
+ elif isinstance(_from, pd.Series):
123
+ self._sr = _from
124
+ if copy:
125
+ self._sr = self._sr.copy()
126
+ elif isinstance(_from, _ExcelIndexsLike_1DArray_Base):
127
+ self._sr = _from._sr.copy()
71
128
  else:
72
129
  raise ValueError(f"Unsupported type: {type(_from)}")
73
130
 
74
- def _reindex(self):
131
+ self._reindexself()
132
+
133
+ def _reindexself(self):
134
+ """
135
+ Reindex the Series
136
+ * Return None. Modify self._sr inplace.
137
+ :return:
138
+ """
75
139
  if self._CLS_DEFAULT_INDEX_TYPE == "s":
76
140
  self._sr.index = [get_column_letter(i + 1) for i in range(self.size)]
77
141
  elif self._CLS_DEFAULT_INDEX_TYPE == "i":
78
142
  self._sr.index = [i + 1 for i in range(self.size)]
79
143
 
144
+ def _reconstruct(self, other):
145
+ """
146
+ Reconstruct self
147
+ * Return None. Modify self._sr inplace.
148
+ :param other: inst of __class__. The other instance.
149
+ :return:
150
+ """
151
+ self._sr = other._sr.copy()
152
+ self._reindexself()
153
+
154
+ def _construct_new_from_index(self, new_index: Union[int, slice], *, inplace=False) -> '__class__() | None':
155
+ """
156
+ Construct a new __class__ from the new index
157
+ * Use this instead of directly create a new __class__ object. So you can override this method to add some other logic.
158
+ :param new_index: int|slice. The new index you want to index self
159
+ *
160
+ :param inplace: bool. If True, modify self inplace. If True, Return None.
161
+ :return: inst of __class__ | None
162
+ """
163
+ _new = self.__class__(self._sr.iloc[new_index], copy=False)
164
+ _new = self.on_subinstance(_new)
165
+ if inplace:
166
+ self._reconstruct(_new)
167
+ else:
168
+ return _new
169
+
170
+ def _construct_new_from_insert(self, insert_index: int, *values, inplace=False) -> '__class__() | None':
171
+ """
172
+ Construct a new __class__ from the new index
173
+ * Use this instead of directly create a new __class__ object. So you can override this method to add some other logic.
174
+ :param insert_index: int. The index to insert before.
175
+ :param *values: Any. The values to insert.
176
+ :param inplace:
177
+ :return: inst of __class__ | None
178
+ """
179
+ _construct = self._sr.to_list()
180
+ values = list(values)
181
+ _construct = _construct[:insert_index] + values + _construct[insert_index:]
182
+ _new = self.__class__(_construct, copy=False)
183
+ _new = self.on_insert(_new)
184
+ if inplace:
185
+ self._reconstruct(_new)
186
+ else:
187
+ return _new
188
+
189
+ def _construct_new_from_delete(self, delete_index: Union[int, slice], *, inplace=False) -> '__class__() | None':
190
+ """
191
+ Construct a new __class__ from the new index
192
+ * Use this instead of directly create a new __class__ object. So you can override this method to add some other logic.
193
+ :param delete_index: int|slice. The index to delete. Special case: slice(None) means clear all.
194
+ *
195
+ :param inplace: bool. If True, modify self inplace. If True, Return None.
196
+ :return: inst of __class__ | None
197
+ """
198
+ if delete_index == slice(None):
199
+ _new = self.__class__()
200
+ else:
201
+ _new = self.__class__(self._sr.drop(self._sr.index[delete_index]), copy=False)
202
+ _new = self.on_delete(_new)
203
+
204
+ if inplace:
205
+ self._reconstruct(_new)
206
+ else:
207
+ return _new
208
+
209
+ def _parse_slice(self, key: slice) -> Tuple[int, int, int]:
210
+ """
211
+ Parse the slice to get the start, stop and step
212
+ :param key: slice. The slice to parse.
213
+ :return: start, stop, step
214
+ """
215
+ _start = key.start if key.start is not None else 0
216
+ _stop = key.stop if key.stop is not None else self.size
217
+ _step = key.step if key.step is not None else 1
218
+ return _start, _stop, _step
219
+
80
220
  def __str__(self):
81
221
  txt = str(self._sr)
82
222
 
@@ -111,10 +251,12 @@ class _ExcelIndexsLike_1DArray:
111
251
  :return: type, real_index
112
252
  * type:
113
253
  ' ': 简单索引类型
254
+ 'n': 全选类型
114
255
  "s": 文本ABC索引类型
115
256
  "i": 文本123索引类型
116
257
  "t??": slice类型, ? 可以是 ' nis'中的一个
117
258
  """
259
+ skey = skey.upper()
118
260
  # NOTE: index_from_string will thorw warning if the type is not matched
119
261
  # 先考虑是否是slice
120
262
  if ':' in skey:
@@ -125,20 +267,22 @@ class _ExcelIndexsLike_1DArray:
125
267
  _t1 = 'i' if l1.isdigit() else 's'
126
268
 
127
269
  start, end = index_from_string(l0, should=self._CLS_DEFAULT_INDEX_TYPE, only_int=True), index_from_string(l1, should=self._CLS_DEFAULT_INDEX_TYPE, only_int=True)
128
- return f"t{_t0}{_t1}", slice(start, end + 1)
270
+ return f"t{_t0}{_t1}", slice(start, end + 1) if start <= end else slice(end, start + 1) # NOTE: 'A:C' with 'C:A' is the same
129
271
 
130
272
  if _PAT_COORD.match(skey):
131
273
  raise ValueError(f"Unexpected index: {skey}.")
132
274
  _type = 'i' if skey.isdigit() else 's'
133
275
  return _type, index_from_string(skey, should=self._CLS_DEFAULT_INDEX_TYPE, only_int=True) - 1
134
276
 
135
- def __dim1_parse_index_key(self, key) -> Tuple[U[str, None], U[int, slice]]:
277
+ def _dim1_parse_index_key(self, key, *, err_when_slice=False) -> Tuple[U[str, None], U[int, slice]]:
136
278
  """
137
279
  Parse the key to get the type and index
138
280
  :param key:
281
+ :param err_when_slice: bool. If True, raise error when slice is found.
139
282
  :return: type, index
140
283
  * type:
141
284
  ' ': 简单索引类型
285
+ 'n': 全选类型
142
286
  "s": 文本ABC索引类型
143
287
  "i": 文本123索引类型
144
288
  "t??": slice类型, ? 可以是 ' nis'中的一个
@@ -152,53 +296,47 @@ class _ExcelIndexsLike_1DArray:
152
296
  # NOTE:交给专用于处理字符串索引的函数处理
153
297
  return self.__dim1_parse_str_index(key)
154
298
  elif isinstance(key, slice):
299
+ if err_when_slice:
300
+ raise ValueError(f"Unexpected slice index: {key}. (Because param err_when_slice=True).")
155
301
  _a, _b, _step = key.start, key.stop, key.step
302
+ _atype, _aindex, _btype, _bindex = 'n', None, 'n', None
156
303
  if _a is None and _b is None:
157
304
  return "tnn", key
158
- _atype, _aindex, _btype, _bindex, _any_flag = 'n', None, 'n', None, False
159
305
  if _a is not None:
160
- _atype, _aindex = self.__dim1_parse_index_key(_a)
161
- _any_flag = True
306
+ _atype, _aindex = self._dim1_parse_index_key(_a)
162
307
  if _b is not None:
163
- _btype, _bindex = self.__dim1_parse_index_key(_b)
164
- _any_flag = True
165
- assert _atype[0] != 't' and _btype[0] != 't', f"Unexpected slice index: {key}"
166
- assert not _any_flag or _atype == _btype, f"Unexpected index: '{key}'. Which is not in the same type."
308
+ _btype, _bindex = self._dim1_parse_index_key(_b)
309
+ if _atype != _btype:
310
+ raise ValueError(f"Unexpected index: '{key}'. Which is not in the same type.")
311
+
167
312
  return f"t{_atype}{_btype}", slice(_aindex, _bindex, _step)
168
313
  else:
169
314
  raise ValueError(f"Unsupported type: {type(key)}")
170
315
 
171
316
  def __getitem__(self, key):
172
- """
173
-
174
- :param key:
175
- only unit types:
176
- int -> value
177
- alpha -> value
178
- slice -> sub Series (new CLS)
179
- :return:
180
- """
181
- _stype, _index = self.__dim1_parse_index_key(key)
317
+ _stype, _index = self._dim1_parse_index_key(key)
182
318
  if _stype == 'n':
183
- return self
184
- elif _stype[0] != 't':
319
+ return self.copy() # None or ... Type
320
+ elif _stype[0] != 't': # return single value directly
185
321
  return self._sr.iloc[_index]
186
322
  else:
187
- return self.__class__(self._sr.iloc[_index], copy=False)
323
+ return self._construct_new_from_index(_index) # slice Type
188
324
 
189
325
  def __setitem__(self, key, value):
190
- _stype, _index = self.__dim1_parse_index_key(key)
326
+ _stype, _index = self._dim1_parse_index_key(key)
191
327
  if _stype == 'n':
192
- _index = slice()
193
- self._sr.iloc[_index] = value
328
+ _index = slice(None)
329
+ self._sr.iloc[_index] = value # NOTE: Set value won't change the shape. So no need to construct new one.
194
330
 
195
331
  def __delitem__(self, key):
196
- _stype, _index = self.__dim1_parse_index_key(key)
332
+ _stype, _index = self._dim1_parse_index_key(key)
197
333
  if _stype == 'n':
198
334
  self.clear()
199
335
  else:
200
- self._sr.drop(self._sr.index[_index], inplace=True)
201
- self._reindex()
336
+ self._construct_new_from_delete(_index, inplace=True)
337
+
338
+
339
+ class ExcelIndexsLike_1DArray(_ExcelIndexsLike_1DArray_Base):
202
340
 
203
341
  def append(self, *values):
204
342
  """
@@ -206,33 +344,30 @@ class _ExcelIndexsLike_1DArray:
206
344
  :param values: Any. The values to append.
207
345
  :return: None
208
346
  """
209
- self._sr = self._sr._append(pd.Series(values), ignore_index=True)
210
- self._reindex()
347
+ self._construct_new_from_insert(self.size, *values, inplace=True)
211
348
 
212
- def insert(self, index, *values):
349
+ def insert(self, index: Union[str, int], *values):
213
350
  """
214
351
  Insert values before the index
215
- :param index: int|str. The index to insert before. (Can be a column-letter string)
352
+ :param index: int|str. The index to insert before. (Can be a column-letter string) But not support slice.
216
353
  :param values: Any. The values to insert.
217
354
  :return: None
218
355
  """
219
- _stype, _index = self.__dim1_parse_index_key(index)
356
+ _stype, _index = self._dim1_parse_index_key(index)
220
357
  if _stype[0] == "t" or _stype == "n":
221
358
  raise ValueError(f"Here only accept non-slice index In {self.__class__.__name__}. But got {index}")
222
359
 
223
- _construct_list = self._sr.iloc[:_index].to_list() + list(values) + self._sr.iloc[_index:].to_list()
224
- self._sr = pd.Series(_construct_list)
225
- self._reindex()
360
+ self._construct_new_from_insert(_index, *values, inplace=True)
226
361
 
227
- def pop(self, index, n: int = 1):
362
+ def pop(self, index: Union[str, int], n: int = 1):
228
363
  """
229
364
  Remove and return the value at the index
230
- :param index: int|str. The index to remove. (Can be a column-letter string)
365
+ :param index: int|str. The index to remove. (Can be a column-letter string) But not support slice.
231
366
  :param n: int. The number of values to remove.
232
367
  - if index + n > size, remove until the end.
233
368
  :return: Any. The removed value. (If n > 1, return a list of values)
234
369
  """
235
- _stype, _index = self.__dim1_parse_index_key(index)
370
+ _stype, _index = self._dim1_parse_index_key(index)
236
371
  if _stype[0] == "t" or _stype == "n":
237
372
  raise ValueError(f"Here only accept non-slice index In {self.__class__.__name__}. But got {index}")
238
373
 
@@ -241,9 +376,7 @@ class _ExcelIndexsLike_1DArray:
241
376
  end = self.size
242
377
 
243
378
  _poped = self._sr.iloc[_index:end].to_list()
244
- _construct_list = self._sr.iloc[:_index].to_list() + self._sr.iloc[end:].to_list()
245
- self._sr = pd.Series(_construct_list)
246
- self._reindex()
379
+ self._construct_new_from_delete(slice(_index, end), inplace=True)
247
380
  if n == 1:
248
381
  return _poped[0]
249
382
  return _poped
@@ -254,10 +387,7 @@ class _ExcelIndexsLike_1DArray:
254
387
  :param other: Series/List/NumpyArray/ExcelIndexed-1D
255
388
  :return: None
256
389
  """
257
- if not isinstance(other, _ExcelIndexsLike_1DArray):
258
- other = self.__class__(other)
259
- self._sr = self._sr._append(other._sr, ignore_index=True)
260
- self._reindex()
390
+ self._construct_new_from_insert(self.size, *other, inplace=True)
261
391
 
262
392
  def index(self, value):
263
393
  """
@@ -292,22 +422,21 @@ class _ExcelIndexsLike_1DArray:
292
422
  Reverse the Series in place.
293
423
  :return: None
294
424
  """
295
- self._sr = self._sr.iloc[::-1]
296
- self._reindex()
425
+ self._construct_new_from_index(slice(None, None, -1), inplace=True)
297
426
 
298
427
  def clear(self):
299
428
  """
300
429
  Clear the Series.
301
430
  :return: None
302
431
  """
303
- self._sr = pd.Series()
432
+ self._construct_new_from_delete(slice(None), inplace=True)
304
433
 
305
434
  def copy(self):
306
435
  """
307
436
  Return a shallow copy of the Series.
308
437
  :return: Series. A shallow copy of the Series.
309
438
  """
310
- return self.__class__(self._sr.copy(), copy=False)
439
+ return self.__class__(self._sr.copy(), copy=False) # NOTE: copy won't change the shape. So no need to construct new one.
311
440
 
312
441
  def sort(self, key=None, reverse=False):
313
442
  """
@@ -318,8 +447,8 @@ class _ExcelIndexsLike_1DArray:
318
447
  """
319
448
  _construct_list = self._sr.to_list()
320
449
  _construct_list.sort(key=key, reverse=reverse)
321
- self._sr = pd.Series(_construct_list)
322
- self._reindex()
450
+ self._sr = pd.Series(_construct_list) # NOTE: sort won't change the shape. So no need to construct new one.
451
+ self._reindexself()
323
452
 
324
453
  def __iter__(self):
325
454
  return iter(self._sr)
@@ -328,7 +457,7 @@ class _ExcelIndexsLike_1DArray:
328
457
  return value in self._sr
329
458
 
330
459
  def __eq__(self, other):
331
- if not isinstance(other, _ExcelIndexsLike_1DArray):
460
+ if not isinstance(other, ExcelIndexsLike_1DArray):
332
461
  other = self.__class__(other)
333
462
  return self._sr.equals(other._sr)
334
463
 
@@ -347,14 +476,14 @@ class _ExcelIndexsLike_1DArray:
347
476
  return self.__class__(_construct_list)
348
477
 
349
478
 
350
- class Row(_ExcelIndexsLike_1DArray): # Like 1: (A B C D)
479
+ class Row(ExcelIndexsLike_1DArray): # Like 1: (A B C D)
351
480
  _CLS_DEFAULT_INDEX_TYPE = "s"
352
481
 
353
482
  def __str__(self):
354
483
  return "Row Series:\n" + super().__str__() + "\n"
355
484
 
356
485
 
357
- class Col(_ExcelIndexsLike_1DArray): # Like A: (1 2 3 4)
486
+ class Col(ExcelIndexsLike_1DArray): # Like A: (1 2 3 4)
358
487
  _CLS_DEFAULT_INDEX_TYPE = "i"
359
488
 
360
489
  def __str__(self):
@@ -393,7 +522,7 @@ class _ExcelIndexsLike_2DArray:
393
522
  warnings.warn(
394
523
  f"Table's input should be rows, but got a column. Regarded as a row.(at index:{i})"
395
524
  )
396
- elif isinstance(_l, _ExcelIndexsLike_1DArray):
525
+ elif isinstance(_l, ExcelIndexsLike_1DArray):
397
526
  _construct_list.append(_l._sr.to_list())
398
527
  elif isinstance(_l, list):
399
528
  _construct_list.append(_l.copy())
@@ -462,10 +591,8 @@ class _ExcelIndexsLike_2DArray:
462
591
  _cnd[lt.ir, lt.ic] = ':' + _cnd[lt.ir, lt.ic][1:]
463
592
  _unhandled_mask[lt.ir:rb.ir + 1, lt.ic:rb.ic + 1] = False
464
593
 
465
-
466
594
  return str(pd.DataFrame(_cnd, index=self._df.index, columns=self._df.columns, copy=False))
467
595
 
468
-
469
596
  def __repr__(self):
470
597
  c = Coord(self._df.shape[1] - 1, self._df.shape[0] - 1)
471
598
  return f"Table[:'{c.letter}']"
@@ -813,7 +940,6 @@ class _ExcelIndexsLike_2DArray:
813
940
  if isinstance(ic, slice):
814
941
  ic = ic.stop if ic.stop is not None else sc
815
942
 
816
-
817
943
  if ir is None:
818
944
  ir = sr
819
945
  if ic is None:
@@ -978,7 +1104,6 @@ class _ExcelIndexsLike_2DArray:
978
1104
  else:
979
1105
  self._df.iloc[_i0, _i1] = np.nan
980
1106
 
981
-
982
1107
  def append(self, *values, axis=0):
983
1108
  """
984
1109
  Append Rows to the end of the table
@@ -995,7 +1120,6 @@ class _ExcelIndexsLike_2DArray:
995
1120
  row.extend(values)
996
1121
  self._reconstruct(_construct, *self._other_raws, copy=False)
997
1122
 
998
-
999
1123
  def clear(self):
1000
1124
  """
1001
1125
  Clear the table
@@ -1051,7 +1175,6 @@ class _ExcelIndexsLike_2DArray:
1051
1175
  if _c > _new_c:
1052
1176
  self._reconstruct(self._df.iloc[:, :_new_c], *self._other_raws, copy=False)
1053
1177
 
1054
-
1055
1178
  def __iter__(self):
1056
1179
  for _r in self._df.values.tolist():
1057
1180
  yield _r
@@ -1076,7 +1199,6 @@ class _ExcelIndexsLike_2DArray:
1076
1199
  return self.shape[0]
1077
1200
 
1078
1201
 
1079
-
1080
1202
  class StyleRow(Row):
1081
1203
  def set(self, key, value):
1082
1204
  """
@@ -1088,6 +1210,7 @@ class StyleRow(Row):
1088
1210
  for ic in range(self.shape[0]):
1089
1211
  self._sr.iloc[ic][key] = value
1090
1212
 
1213
+
1091
1214
  class StyleCol(Col):
1092
1215
  def set(self, key, value):
1093
1216
  """
@@ -1099,9 +1222,11 @@ class StyleCol(Col):
1099
1222
  for ir in range(self.shape[0]):
1100
1223
  self._sr.iloc[ir][key] = value
1101
1224
 
1225
+
1102
1226
  class StyleTable(_ExcelIndexsLike_2DArray):
1103
1227
  _ROW_CLS = StyleRow
1104
1228
  _COL_CLS = StyleCol
1229
+
1105
1230
  def set(self, key, value):
1106
1231
  """
1107
1232
  Set the style of each cell
@@ -1113,9 +1238,10 @@ class StyleTable(_ExcelIndexsLike_2DArray):
1113
1238
  for ic in range(self.shape[1]):
1114
1239
  self._df.iloc[ir, ic][key] = value
1115
1240
 
1241
+
1116
1242
  class Table(_ExcelIndexsLike_2DArray):
1117
1243
  # def __init__(self, _from=None, *, copy: bool = True):
1118
- def __init__(self, data=None, styles=None, merges:list=None, *, copy: bool = True):
1244
+ def __init__(self, data=None, styles=None, merges: list = None, *, copy: bool = True):
1119
1245
  super().__init__(data, copy=copy)
1120
1246
  self._styles = StyleTable() if styles is None else (styles.copy() if isinstance(styles, StyleTable) else StyleTable(styles))
1121
1247
  self._merges = []
@@ -1143,7 +1269,7 @@ class Table(_ExcelIndexsLike_2DArray):
1143
1269
  def merges(self):
1144
1270
  return self._merges
1145
1271
 
1146
- def merge(self, key:U[int, str, slice, None], key1:U[int, str, slice, None]=EMPTY_INDEX, *, border:Border=None):
1272
+ def merge(self, key: U[int, str, slice, None], key1: U[int, str, slice, None] = EMPTY_INDEX, *, border: Border = None):
1147
1273
  if key1 is not EMPTY_INDEX:
1148
1274
  key = key, key1
1149
1275
 
@@ -1296,6 +1422,7 @@ class Table(_ExcelIndexsLike_2DArray):
1296
1422
 
1297
1423
 
1298
1424
  def __1d_test(_print=True):
1425
+
1299
1426
  d = [1, 2, 3, 4, 5]
1300
1427
 
1301
1428
  r = Row(d)
@@ -1326,6 +1453,16 @@ def __1d_test(_print=True):
1326
1453
  if _print: print(f"删除测试:\n{r}")
1327
1454
 
1328
1455
 
1456
+ def _1d_unit_test(_print=True):
1457
+ tc = TimeRecorder()
1458
+ __1d_test(_print)
1459
+ warnings.filterwarnings('ignore')
1460
+ for i in range(999):
1461
+ __1d_test(_print)
1462
+ warnings.filterwarnings('default')
1463
+ print(f"测试结束,耗时: {tc.dms(1000)} ms / 测试")
1464
+
1465
+
1329
1466
  def __2d_test(_print=True):
1330
1467
  import colorama
1331
1468
  r0 = Col([1, 2, 3, 4, 5])
@@ -1397,4 +1534,4 @@ if __name__ == '__main__':
1397
1534
  # print(f"Finish Test. Cost:{round((time.time() - _a) * 1000, 2)} ms")
1398
1535
  # exit(0)
1399
1536
 
1400
- __2d_test()
1537
+ _1d_unit_test(False)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tpltable
3
- Version: 0.3.3
3
+ Version: 0.3.4
4
4
  Summary: define "Excel" "Table|StyleTable" "Row|Col|StyleRow|StyleCol". Can dynamic modify excel data & styles. Support multiple kinds of indexes. (70%)
5
5
  Author-email: 2229066748@qq.com
6
6
  Maintainer: Eagle'sBaby
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes