tdrpa.tdworker 1.1.9.3__py39-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. tdrpa/_tdxlwings/__init__.py +193 -0
  2. tdrpa/_tdxlwings/__pycache__/__init__.cpython-311.pyc +0 -0
  3. tdrpa/_tdxlwings/__pycache__/__init__.cpython-38.pyc +0 -0
  4. tdrpa/_tdxlwings/__pycache__/_win32patch.cpython-311.pyc +0 -0
  5. tdrpa/_tdxlwings/__pycache__/_win32patch.cpython-38.pyc +0 -0
  6. tdrpa/_tdxlwings/__pycache__/_xlwindows.cpython-311.pyc +0 -0
  7. tdrpa/_tdxlwings/__pycache__/_xlwindows.cpython-38.pyc +0 -0
  8. tdrpa/_tdxlwings/__pycache__/apps.cpython-311.pyc +0 -0
  9. tdrpa/_tdxlwings/__pycache__/apps.cpython-38.pyc +0 -0
  10. tdrpa/_tdxlwings/__pycache__/base_classes.cpython-311.pyc +0 -0
  11. tdrpa/_tdxlwings/__pycache__/base_classes.cpython-38.pyc +0 -0
  12. tdrpa/_tdxlwings/__pycache__/com_server.cpython-311.pyc +0 -0
  13. tdrpa/_tdxlwings/__pycache__/com_server.cpython-38.pyc +0 -0
  14. tdrpa/_tdxlwings/__pycache__/constants.cpython-311.pyc +0 -0
  15. tdrpa/_tdxlwings/__pycache__/constants.cpython-38.pyc +0 -0
  16. tdrpa/_tdxlwings/__pycache__/expansion.cpython-311.pyc +0 -0
  17. tdrpa/_tdxlwings/__pycache__/expansion.cpython-38.pyc +0 -0
  18. tdrpa/_tdxlwings/__pycache__/main.cpython-311.pyc +0 -0
  19. tdrpa/_tdxlwings/__pycache__/main.cpython-38.pyc +0 -0
  20. tdrpa/_tdxlwings/__pycache__/udfs.cpython-311.pyc +0 -0
  21. tdrpa/_tdxlwings/__pycache__/udfs.cpython-38.pyc +0 -0
  22. tdrpa/_tdxlwings/__pycache__/utils.cpython-311.pyc +0 -0
  23. tdrpa/_tdxlwings/__pycache__/utils.cpython-38.pyc +0 -0
  24. tdrpa/_tdxlwings/_win32patch.py +90 -0
  25. tdrpa/_tdxlwings/_xlmac.py +2240 -0
  26. tdrpa/_tdxlwings/_xlwindows.py +2518 -0
  27. tdrpa/_tdxlwings/addin/Dictionary.cls +474 -0
  28. tdrpa/_tdxlwings/addin/IWebAuthenticator.cls +71 -0
  29. tdrpa/_tdxlwings/addin/WebClient.cls +772 -0
  30. tdrpa/_tdxlwings/addin/WebHelpers.bas +3203 -0
  31. tdrpa/_tdxlwings/addin/WebRequest.cls +875 -0
  32. tdrpa/_tdxlwings/addin/WebResponse.cls +453 -0
  33. tdrpa/_tdxlwings/addin/xlwings.xlam +0 -0
  34. tdrpa/_tdxlwings/apps.py +35 -0
  35. tdrpa/_tdxlwings/base_classes.py +1092 -0
  36. tdrpa/_tdxlwings/cli.py +1306 -0
  37. tdrpa/_tdxlwings/com_server.py +385 -0
  38. tdrpa/_tdxlwings/constants.py +3080 -0
  39. tdrpa/_tdxlwings/conversion/__init__.py +103 -0
  40. tdrpa/_tdxlwings/conversion/framework.py +147 -0
  41. tdrpa/_tdxlwings/conversion/numpy_conv.py +34 -0
  42. tdrpa/_tdxlwings/conversion/pandas_conv.py +184 -0
  43. tdrpa/_tdxlwings/conversion/standard.py +321 -0
  44. tdrpa/_tdxlwings/expansion.py +83 -0
  45. tdrpa/_tdxlwings/ext/__init__.py +3 -0
  46. tdrpa/_tdxlwings/ext/sql.py +73 -0
  47. tdrpa/_tdxlwings/html/xlwings-alert.html +71 -0
  48. tdrpa/_tdxlwings/js/xlwings.js +577 -0
  49. tdrpa/_tdxlwings/js/xlwings.ts +729 -0
  50. tdrpa/_tdxlwings/mac_dict.py +6399 -0
  51. tdrpa/_tdxlwings/main.py +5205 -0
  52. tdrpa/_tdxlwings/mistune/__init__.py +63 -0
  53. tdrpa/_tdxlwings/mistune/block_parser.py +366 -0
  54. tdrpa/_tdxlwings/mistune/inline_parser.py +216 -0
  55. tdrpa/_tdxlwings/mistune/markdown.py +84 -0
  56. tdrpa/_tdxlwings/mistune/renderers.py +220 -0
  57. tdrpa/_tdxlwings/mistune/scanner.py +121 -0
  58. tdrpa/_tdxlwings/mistune/util.py +41 -0
  59. tdrpa/_tdxlwings/pro/__init__.py +40 -0
  60. tdrpa/_tdxlwings/pro/_xlcalamine.py +536 -0
  61. tdrpa/_tdxlwings/pro/_xlofficejs.py +146 -0
  62. tdrpa/_tdxlwings/pro/_xlremote.py +1293 -0
  63. tdrpa/_tdxlwings/pro/custom_functions_code.js +150 -0
  64. tdrpa/_tdxlwings/pro/embedded_code.py +60 -0
  65. tdrpa/_tdxlwings/pro/udfs_officejs.py +549 -0
  66. tdrpa/_tdxlwings/pro/utils.py +199 -0
  67. tdrpa/_tdxlwings/quickstart.xlsm +0 -0
  68. tdrpa/_tdxlwings/quickstart_addin.xlam +0 -0
  69. tdrpa/_tdxlwings/quickstart_addin_ribbon.xlam +0 -0
  70. tdrpa/_tdxlwings/quickstart_fastapi/main.py +47 -0
  71. tdrpa/_tdxlwings/quickstart_fastapi/requirements.txt +3 -0
  72. tdrpa/_tdxlwings/quickstart_standalone.xlsm +0 -0
  73. tdrpa/_tdxlwings/reports.py +12 -0
  74. tdrpa/_tdxlwings/rest/__init__.py +1 -0
  75. tdrpa/_tdxlwings/rest/api.py +368 -0
  76. tdrpa/_tdxlwings/rest/serializers.py +103 -0
  77. tdrpa/_tdxlwings/server.py +14 -0
  78. tdrpa/_tdxlwings/udfs.py +775 -0
  79. tdrpa/_tdxlwings/utils.py +777 -0
  80. tdrpa/_tdxlwings/xlwings-0.31.6.applescript +30 -0
  81. tdrpa/_tdxlwings/xlwings.bas +2061 -0
  82. tdrpa/_tdxlwings/xlwings_custom_addin.bas +2042 -0
  83. tdrpa/_tdxlwings/xlwingslib.cp38-win_amd64.pyd +0 -0
  84. tdrpa/tdworker/__init__.pyi +8 -0
  85. tdrpa/tdworker/_excel.pyi +703 -0
  86. tdrpa/tdworker/_img.pyi +173 -0
  87. tdrpa/tdworker/_os.pyi +46 -0
  88. tdrpa/tdworker/_w.pyi +129 -0
  89. tdrpa/tdworker/_web.pyi +248 -0
  90. tdrpa/tdworker/_winE.pyi +246 -0
  91. tdrpa/tdworker/_winK.pyi +74 -0
  92. tdrpa/tdworker/_winM.pyi +117 -0
  93. tdrpa/tdworker.cp39-win_amd64.pyd +0 -0
  94. tdrpa.tdworker-1.1.9.3.dist-info/METADATA +25 -0
  95. tdrpa.tdworker-1.1.9.3.dist-info/RECORD +97 -0
  96. tdrpa.tdworker-1.1.9.3.dist-info/WHEEL +5 -0
  97. tdrpa.tdworker-1.1.9.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,103 @@
1
+ try:
2
+ import pandas as pd
3
+ except ImportError:
4
+ pd = None
5
+ try:
6
+ import numpy as np
7
+ except ImportError:
8
+ np = None
9
+
10
+ from .framework import (
11
+ Accessor,
12
+ ConversionContext,
13
+ Converter,
14
+ Options,
15
+ Pipeline,
16
+ accessors,
17
+ )
18
+ from .standard import (
19
+ AdjustDimensionsStage,
20
+ CleanDataForWriteStage,
21
+ CleanDataFromReadStage,
22
+ DictConverter,
23
+ Ensure2DStage,
24
+ ExpandRangeStage,
25
+ RangeAccessor,
26
+ RawValueAccessor,
27
+ ReadValueFromRangeStage,
28
+ TransposeStage,
29
+ ValueAccessor,
30
+ WriteValueToRangeStage,
31
+ )
32
+
33
+ if np:
34
+ from .numpy_conv import NumpyArrayConverter
35
+ if pd:
36
+ from .pandas_conv import PandasDataFrameConverter, PandasSeriesConverter
37
+
38
+ from .. import LicenseError
39
+
40
+ try:
41
+ from ..pro.reports.markdown import Markdown, MarkdownConverter
42
+
43
+ MarkdownConverter.register(Markdown)
44
+ except (ImportError, LicenseError, AttributeError):
45
+ pass
46
+
47
+
48
+ __all__ = (
49
+ "Accessor",
50
+ "ConversionContext",
51
+ "Converter",
52
+ "Options",
53
+ "Pipeline",
54
+ "accessors",
55
+ "AdjustDimensionsStage",
56
+ "CleanDataForWriteStage",
57
+ "CleanDataFromReadStage",
58
+ "DictConverter",
59
+ "Ensure2DStage",
60
+ "ExpandRangeStage",
61
+ "RangeAccessor",
62
+ "RawValueAccessor",
63
+ "ReadValueFromRangeStage",
64
+ "TransposeStage",
65
+ "ValueAccessor",
66
+ "WriteValueToRangeStage",
67
+ "NumpyArrayConverter",
68
+ "PandasDataFrameConverter",
69
+ "PandasSeriesConverter",
70
+ )
71
+
72
+
73
+ def read(rng, value, options, engine_name=None):
74
+ convert = options.get("convert", None)
75
+ pipeline = accessors.get(convert, convert).reader(options)
76
+ ctx = ConversionContext(rng=rng, value=value, engine_name=engine_name)
77
+ pipeline(ctx)
78
+ return ctx.value
79
+
80
+
81
+ def write(value, rng, options, engine_name=None):
82
+ # Don't allow to write lists and tuples as jagged arrays as appscript and pywin32
83
+ # don't handle that properly. This should really be handled in Ensure2DStage, but
84
+ # we'd have to set the original format in the conversion ctx meta as the check
85
+ # should only run for list and tuples.
86
+ if (
87
+ isinstance(value, (list, tuple))
88
+ and len(value) > 0
89
+ and isinstance(value[0], (list, tuple))
90
+ ):
91
+ first_row = value[0]
92
+ for row in value:
93
+ if len(first_row) != len(row):
94
+ raise Exception(
95
+ "All elements of a 2d list or tuple must be of the same length"
96
+ )
97
+ convert = options.get("convert", None)
98
+ pipeline = (
99
+ accessors.get(convert, convert).router(value, rng, options).writer(options)
100
+ )
101
+ ctx = ConversionContext(rng=rng, value=value, engine_name=engine_name)
102
+ pipeline(ctx)
103
+ return ctx.value
@@ -0,0 +1,147 @@
1
+ import tdrpa._tdxlwings as xlwings
2
+
3
+ class ConversionContext:
4
+ __slots__ = ["range", "value", "source_value", "meta", "engine"]
5
+
6
+ def __init__(self, rng=None, value=None, engine_name=None):
7
+ self.range = rng
8
+ if engine_name:
9
+ self.engine = xlwings.engines[engine_name]
10
+ else:
11
+ # rng can only be None if used via COM server UDFs
12
+ self.engine = rng.sheet.book.app.engine if rng else xlwings.engines["excel"]
13
+ self.value = value
14
+ # used for markdown (could be replaced by handing the parsed ast from
15
+ # the converter stage to the formatting stage
16
+ self.source_value = value
17
+ self.meta = {}
18
+
19
+
20
+ class Options(dict):
21
+ def __init__(self, original):
22
+ super(Options, self).__init__(original)
23
+
24
+ def override(self, **overrides):
25
+ self.update(overrides)
26
+ return self
27
+
28
+ def erase(self, keys):
29
+ for key in keys:
30
+ self.pop(key, None)
31
+ return self
32
+
33
+ def defaults(self, **defaults):
34
+ for k, v in defaults.items():
35
+ self.setdefault(k, v)
36
+ return self
37
+
38
+
39
+ class Pipeline(list):
40
+ def prepend_stage(self, stage, only_if=True):
41
+ if only_if:
42
+ self.insert(0, stage)
43
+ return self
44
+
45
+ def append_stage(self, stage, only_if=True):
46
+ if only_if:
47
+ self.append(stage)
48
+ return self
49
+
50
+ def insert_stage(
51
+ self, stage, index=None, after=None, before=None, replace=None, only_if=True
52
+ ):
53
+ if only_if:
54
+ if sum(x is not None for x in (index, after, before, replace)) != 1:
55
+ raise ValueError(
56
+ "Must specify exactly one of arguments: "
57
+ "index, after, before, replace"
58
+ )
59
+ if index is not None:
60
+ indices = (index,)
61
+ elif after is not None:
62
+ indices = tuple(
63
+ i + 1 for i, x in enumerate(self) if isinstance(x, after)
64
+ )
65
+ elif before is not None:
66
+ indices = tuple(i for i, x in enumerate(self) if isinstance(x, before))
67
+ elif replace is not None:
68
+ for i, x in enumerate(self):
69
+ if isinstance(x, replace):
70
+ self[i] = stage
71
+ return self
72
+ for i in reversed(indices):
73
+ self.insert(i, stage)
74
+ return self
75
+
76
+ def __call__(self, *args, **kwargs):
77
+ for stage in self:
78
+ stage(*args, **kwargs)
79
+
80
+
81
+ accessors = {}
82
+
83
+
84
+ class Accessor:
85
+ @classmethod
86
+ def reader(cls, options):
87
+ return Pipeline()
88
+
89
+ @classmethod
90
+ def writer(cls, options):
91
+ return Pipeline()
92
+
93
+ @classmethod
94
+ def register(cls, *types):
95
+ for type in types:
96
+ accessors[type] = cls
97
+
98
+ @classmethod
99
+ def router(cls, value, rng, options):
100
+ return cls
101
+
102
+
103
+ class Converter(Accessor):
104
+ class ToValueStage:
105
+ def __init__(self, write_value, options):
106
+ self.write_value = write_value
107
+ self.options = options
108
+
109
+ def __call__(self, c):
110
+ c.value = self.write_value(c.value, self.options)
111
+
112
+ class FromValueStage:
113
+ def __init__(self, read_value, options):
114
+ self.read_value = read_value
115
+ self.options = options
116
+
117
+ def __call__(self, c):
118
+ c.value = self.read_value(c.value, self.options)
119
+
120
+ base_type = None
121
+ base = None
122
+
123
+ @classmethod
124
+ def base_reader(cls, options, base_type=None):
125
+ if cls.base is not None:
126
+ return cls.base.reader(options)
127
+ else:
128
+ return accessors[base_type or cls.base_type].reader(options)
129
+
130
+ @classmethod
131
+ def base_writer(cls, options, base_type=None):
132
+ if cls.base is not None:
133
+ return cls.base.writer(options)
134
+ else:
135
+ return accessors[base_type or cls.base_type].writer(options)
136
+
137
+ @classmethod
138
+ def reader(cls, options):
139
+ return cls.base_reader(options).append_stage(
140
+ cls.FromValueStage(cls.read_value, options)
141
+ )
142
+
143
+ @classmethod
144
+ def writer(cls, options):
145
+ return cls.base_writer(options).prepend_stage(
146
+ cls.ToValueStage(cls.write_value, options)
147
+ )
@@ -0,0 +1,34 @@
1
+ try:
2
+ import numpy as np
3
+ except ImportError:
4
+ np = None
5
+
6
+
7
+ if np:
8
+ try:
9
+ import pandas as pd
10
+ except ImportError:
11
+ pd = None
12
+
13
+ from . import Converter, Options
14
+
15
+ class NumpyArrayConverter(Converter):
16
+ @classmethod
17
+ def base_reader(cls, options):
18
+ return super(NumpyArrayConverter, cls).base_reader(
19
+ Options(options).defaults(empty=np.nan)
20
+ )
21
+
22
+ @classmethod
23
+ def read_value(cls, value, options):
24
+ dtype = options.get("dtype", None)
25
+ copy = options.get("copy", True)
26
+ order = options.get("order", None)
27
+ ndim = options.get("ndim", None) or 0
28
+ return np.array(value, dtype=dtype, copy=copy, order=order, ndmin=ndim)
29
+
30
+ @classmethod
31
+ def write_value(cls, value, options):
32
+ return value.tolist()
33
+
34
+ NumpyArrayConverter.register(np.array, np.ndarray)
@@ -0,0 +1,184 @@
1
+ from ..utils import xlserial_to_datetime
2
+
3
+ try:
4
+ import pandas as pd
5
+ except ImportError:
6
+ pd = None
7
+
8
+
9
+ if pd:
10
+ from . import Converter, Options
11
+
12
+ def _parse_dates(df, parse_dates):
13
+ # Office.js UDFs don't have the info whether the cell is in date format
14
+ if parse_dates is True:
15
+ parse_dates = [0]
16
+ elif not isinstance(parse_dates, list):
17
+ parse_dates = [parse_dates]
18
+ for col in parse_dates:
19
+ if isinstance(col, str):
20
+ df.loc[:, col] = df.loc[:, col].apply(xlserial_to_datetime)
21
+ else:
22
+ df.iloc[:, col] = df.iloc[:, col].apply(xlserial_to_datetime)
23
+ return df
24
+
25
+ def write_value(cls, value, options):
26
+ index = options.get("index", True)
27
+ header = options.get("header", True)
28
+ assign_empty_index_names = options.get("assign_empty_index_names", False)
29
+
30
+ index_names = value.index.names
31
+ if assign_empty_index_names:
32
+ # Useful when you want to have your DataFrame formatted as an Excel table
33
+ # which requires column header names. Since Excel tables only allow an empty
34
+ # space once, we'll generate multiple empty spaces for each column.
35
+ index_names = [
36
+ " " * (i + 1) if name is None else name
37
+ for i, name in enumerate(index_names)
38
+ ]
39
+ else:
40
+ index_names = ["" if name is None else name for name in index_names]
41
+ index_levels = len(index_names)
42
+
43
+ if index:
44
+ if value.index.name in value.columns:
45
+ # Prevents column name collision when resetting the index
46
+ value.index = value.index.rename(None)
47
+ value = value.reset_index()
48
+
49
+ # Convert pandas-specific types without corresponding Excel type to strings
50
+ for ix, col in enumerate(value.columns):
51
+ if (
52
+ isinstance(value.iloc[:, ix].dtype, pd.PeriodDtype)
53
+ or value.iloc[:, ix].dtype == "timedelta64[ns]"
54
+ ):
55
+ value.iloc[:, ix] = value.iloc[:, ix].astype(str)
56
+
57
+ if header:
58
+ if isinstance(value.columns, pd.MultiIndex):
59
+ columns = list(zip(*value.columns.tolist()))
60
+ columns = [list(i) for i in columns]
61
+ # Move index names right above the index
62
+ if index:
63
+ for c in columns[:-1]:
64
+ c[:index_levels] = [""] * index_levels
65
+ columns[-1][:index_levels] = index_names
66
+ else:
67
+ columns = [value.columns.tolist()]
68
+ if index:
69
+ columns[0][:index_levels] = index_names
70
+ value = columns + value.values.tolist()
71
+ else:
72
+ value = value.values.tolist()
73
+
74
+ return value
75
+
76
+ class PandasDataFrameConverter(Converter):
77
+ @classmethod
78
+ def base_reader(cls, options):
79
+ return super(PandasDataFrameConverter, cls).base_reader(
80
+ Options(options).override(ndim=2)
81
+ )
82
+
83
+ @classmethod
84
+ def read_value(cls, value, options):
85
+ index = options.get("index", 1)
86
+ header = options.get("header", 1)
87
+ dtype = options.get("dtype", None)
88
+ copy = options.get("copy", False)
89
+ parse_dates = options.get("parse_dates", None)
90
+
91
+ # build dataframe with only columns (no index) but correct header
92
+ if header == 1:
93
+ columns = pd.Index(value[0])
94
+ elif header > 1:
95
+ columns = pd.MultiIndex.from_arrays(value[:header])
96
+ else:
97
+ columns = None
98
+
99
+ df = pd.DataFrame(value[header:], columns=columns, dtype=dtype, copy=copy)
100
+
101
+ if parse_dates:
102
+ df = _parse_dates(df, parse_dates)
103
+
104
+ # handle index by resetting the index to the index first columns
105
+ # and renaming the index according to the name in the last row
106
+ if index > 0:
107
+ # rename uniquely the index columns to some never used name for column
108
+ # we do not use the column name directly as it would cause issues if
109
+ # several columns have the same name
110
+ df.columns = pd.Index(range(len(df.columns)))
111
+ df = df.set_index(list(df.columns)[:index])
112
+
113
+ df.index.names = pd.Index(
114
+ value[header - 1][:index] if header else [None] * index
115
+ )
116
+
117
+ if header:
118
+ df.columns = columns[index:]
119
+ else:
120
+ df.columns = pd.Index(range(len(df.columns)))
121
+
122
+ return df
123
+
124
+ @classmethod
125
+ def write_value(cls, value, options):
126
+ return write_value(cls, value, options)
127
+
128
+ PandasDataFrameConverter.register(pd.DataFrame, "df")
129
+
130
+ class PandasSeriesConverter(Converter):
131
+ @classmethod
132
+ def read_value(cls, value, options):
133
+ index = options.get("index", 1)
134
+ header = options.get("header", True)
135
+ dtype = options.get("dtype", None)
136
+ copy = options.get("copy", False)
137
+ parse_dates = options.get("parse_dates", None)
138
+
139
+ if header:
140
+ columns = value[0]
141
+ if not isinstance(columns, list):
142
+ columns = [columns]
143
+ data = value[1:]
144
+ else:
145
+ columns = None
146
+ data = value
147
+
148
+ df = pd.DataFrame(data, columns=columns, dtype=dtype, copy=copy)
149
+
150
+ if parse_dates:
151
+ df = _parse_dates(df, parse_dates)
152
+
153
+ if index:
154
+ df.columns = pd.Index(range(len(df.columns)))
155
+ df = df.set_index(list(df.columns)[:index])
156
+ df.index.names = pd.Index(
157
+ value[header - 1][:index] if header else [None] * index
158
+ )
159
+
160
+ if header:
161
+ df.columns = columns[index:]
162
+ else:
163
+ df.columns = pd.Index(range(len(df.columns)))
164
+
165
+ series = df.squeeze()
166
+
167
+ if not header:
168
+ series.name = None
169
+ series.index.name = None
170
+
171
+ return series
172
+
173
+ @classmethod
174
+ def write_value(cls, value, options):
175
+ if all(v is None for v in value.index.names) and value.name is None:
176
+ default_header = False
177
+ else:
178
+ default_header = True
179
+
180
+ options["header"] = options.get("header", default_header)
181
+ values = write_value(cls, value.to_frame(), options)
182
+ return values
183
+
184
+ PandasSeriesConverter.register(pd.Series)