mergeron 2024.739079.11__tar.gz → 2024.739079.13__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 mergeron might be problematic. Click here for more details.
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/PKG-INFO +1 -1
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/pyproject.toml +1 -1
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/__init__.py +1 -1
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/core/excel_helper.py +145 -33
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/README.rst +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/License.txt +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/core/__init__.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/core/damodaran_margin_data.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/core/ftc_merger_investigations_data.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/core/guidelines_boundaries.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/core/guidelines_boundary_functions.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/core/guidelines_boundary_functions_extra.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/core/proportions_tests.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/core/pseudorandom_numbers.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/data/__init__.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/data/damodaran_margin_data.xls +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/data/damodaran_margin_data_dict.msgpack +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/data/ftc_invdata.msgpack +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/data/jinja2_LaTeX_templates/clrrate_cis_summary_table_template.tex.jinja2 +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/data/jinja2_LaTeX_templates/ftcinvdata_byhhianddelta_table_template.tex.jinja2 +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/data/jinja2_LaTeX_templates/ftcinvdata_summary_table_template.tex.jinja2 +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/data/jinja2_LaTeX_templates/ftcinvdata_summarypaired_table_template.tex.jinja2 +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/data/jinja2_LaTeX_templates/mergeron.cls +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/data/jinja2_LaTeX_templates/mergeron_table_collection_template.tex.jinja2 +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/data/jinja2_LaTeX_templates/setup_tikz_tables.tex +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/demo/__init__.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/demo/visualize_empirical_margin_distribution.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/ext/__init__.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/ext/tol_colors.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/gen/__init__.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/gen/_data_generation_functions.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/gen/data_generation.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/gen/enforcement_stats.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/gen/market_sample.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/gen/upp_tests.py +0 -0
- {mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mergeron
|
|
3
|
-
Version: 2024.739079.
|
|
3
|
+
Version: 2024.739079.13
|
|
4
4
|
Summary: Merger Policy Analysis using Python
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: merger policy analysis,merger guidelines,merger screening,policy presumptions,concentration standards,upward pricing pressure,GUPPI
|
|
@@ -4,6 +4,13 @@ the third-party package, `xlsxwriter`.
|
|
|
4
4
|
|
|
5
5
|
Includes a flexible system of defining cell formats.
|
|
6
6
|
|
|
7
|
+
NOTES
|
|
8
|
+
-----
|
|
9
|
+
|
|
10
|
+
This module is desinged for producing formatted summary output. For
|
|
11
|
+
writing bulk data to Excel, facilities provided in third-party packages
|
|
12
|
+
such as `polars` likely provide better performance.
|
|
13
|
+
|
|
7
14
|
"""
|
|
8
15
|
|
|
9
16
|
from __future__ import annotations
|
|
@@ -31,7 +38,11 @@ class CFmt(dict, Enum): # type: ignore
|
|
|
31
38
|
as xlsxWriter.Workbook.Format objects for writing
|
|
32
39
|
cell values to formatted cells in a spreadsheet.
|
|
33
40
|
|
|
34
|
-
|
|
41
|
+
NOTES
|
|
42
|
+
-----
|
|
43
|
+
|
|
44
|
+
For more information about xlsxwriter's cell formats,
|
|
45
|
+
see, https://xlsxwriter.readthedocs.io/format.html
|
|
35
46
|
"""
|
|
36
47
|
|
|
37
48
|
XL_DEFAULT: ClassVar = {"font_name": "Calibri", "font_size": 11}
|
|
@@ -71,16 +82,101 @@ class CFmt(dict, Enum): # type: ignore
|
|
|
71
82
|
HDR_BORDER: ClassVar = TOP_BORDER | BOT_BORDER
|
|
72
83
|
|
|
73
84
|
|
|
74
|
-
def
|
|
85
|
+
def write_header(
|
|
86
|
+
_xl_sheet: xlsxwriter.worksheet.Worksheet,
|
|
87
|
+
/,
|
|
88
|
+
*,
|
|
89
|
+
center_header: str | None = None,
|
|
90
|
+
left_header: str | None = None,
|
|
91
|
+
right_header: str | None = None,
|
|
92
|
+
) -> None:
|
|
93
|
+
"""Write header text to given worksheet.
|
|
94
|
+
|
|
95
|
+
Parameters
|
|
96
|
+
----------
|
|
97
|
+
_xl_sheet
|
|
98
|
+
Worksheet object
|
|
99
|
+
center_header
|
|
100
|
+
Text for center header
|
|
101
|
+
left_header
|
|
102
|
+
Text for left header
|
|
103
|
+
right_header
|
|
104
|
+
Text for right header
|
|
105
|
+
|
|
106
|
+
Raises
|
|
107
|
+
------
|
|
108
|
+
ValueError
|
|
109
|
+
Must specify at least one header
|
|
110
|
+
|
|
111
|
+
Returns
|
|
112
|
+
-------
|
|
113
|
+
None
|
|
114
|
+
"""
|
|
115
|
+
if not any((center_header, left_header, right_header)):
|
|
116
|
+
raise ValueError("must specify at least one header")
|
|
117
|
+
_xl_sheet.set_footer(
|
|
118
|
+
"".join([
|
|
119
|
+
f"&L{left_header}" if left_header else "",
|
|
120
|
+
f"&C{center_header}" if center_header else "",
|
|
121
|
+
f"&R{right_header}" if right_header else "",
|
|
122
|
+
])
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def write_footer(
|
|
127
|
+
_xl_sheet: xlsxwriter.worksheet.Worksheet,
|
|
128
|
+
/,
|
|
129
|
+
*,
|
|
130
|
+
center_footer: str | None = None,
|
|
131
|
+
left_footer: str | None = None,
|
|
132
|
+
right_footer: str | None = None,
|
|
133
|
+
) -> None:
|
|
134
|
+
"""Write footer text to given worksheet.
|
|
135
|
+
|
|
136
|
+
Parameters
|
|
137
|
+
----------
|
|
138
|
+
_xl_sheet
|
|
139
|
+
Worksheet object
|
|
140
|
+
center_footer
|
|
141
|
+
Text for center footer
|
|
142
|
+
left_footer
|
|
143
|
+
Text for left footer
|
|
144
|
+
right_footer
|
|
145
|
+
Text for right footer
|
|
146
|
+
|
|
147
|
+
Raises
|
|
148
|
+
------
|
|
149
|
+
ValueError
|
|
150
|
+
Must specify at least one footer
|
|
151
|
+
|
|
152
|
+
Returns
|
|
153
|
+
-------
|
|
154
|
+
None
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
if not any((center_footer, left_footer, right_footer)):
|
|
158
|
+
raise ValueError("must specify at least one footer")
|
|
159
|
+
|
|
160
|
+
_xl_sheet.set_footer(
|
|
161
|
+
"".join([
|
|
162
|
+
f"&L{left_footer}" if left_footer else "",
|
|
163
|
+
f"&C{center_footer}" if center_footer else "",
|
|
164
|
+
f"&R{right_footer}" if right_footer else "",
|
|
165
|
+
])
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def array_to_sheet(
|
|
75
170
|
_xl_book: xlsxwriter.workbook.Workbook,
|
|
76
171
|
_xl_sheet: xlsxwriter.worksheet.Worksheet,
|
|
77
|
-
_data_table: npt.
|
|
172
|
+
_data_table: Sequence[Any] | npt.NDArray[Any],
|
|
78
173
|
_row_id: int,
|
|
79
174
|
_col_id: int = 0,
|
|
80
175
|
/,
|
|
81
176
|
*,
|
|
82
177
|
cell_format: Sequence[CFmt] | CFmt | None = None,
|
|
83
178
|
green_bar_flag: bool = True,
|
|
179
|
+
ragged_flag: bool = True,
|
|
84
180
|
) -> tuple[int, int]:
|
|
85
181
|
"""
|
|
86
182
|
Write a 2-D array to a worksheet.
|
|
@@ -111,51 +207,44 @@ def matrix_to_sheet(
|
|
|
111
207
|
green_bar_flag
|
|
112
208
|
Whether to highlight alternating rows as in green bar paper
|
|
113
209
|
|
|
210
|
+
Raises
|
|
211
|
+
------
|
|
212
|
+
ValueError
|
|
213
|
+
If format tuple does not match data in length
|
|
214
|
+
|
|
114
215
|
Returns
|
|
115
216
|
-------
|
|
116
|
-
Tuple giving address of cell
|
|
217
|
+
Tuple giving address of cell at right below and after range written
|
|
117
218
|
|
|
118
219
|
"""
|
|
119
|
-
_data_array: npt.NDArray[Any] = np.array(_data_table)
|
|
120
|
-
del _data_table
|
|
121
|
-
|
|
122
|
-
if not len(_data_array.shape) == 2:
|
|
123
|
-
raise ValueError(
|
|
124
|
-
"Array to write must be a 2-D array, but"
|
|
125
|
-
f"the given array has shape, {_data_array.shape}."
|
|
126
|
-
)
|
|
127
220
|
|
|
128
221
|
# Get the array dimensions and row and column numbers for Excel
|
|
129
|
-
|
|
130
|
-
|
|
222
|
+
_num_rows = len(_data_table)
|
|
223
|
+
_bottom_row_id = _row_id + _num_rows
|
|
224
|
+
_num_cols = len(_data_table[0])
|
|
225
|
+
_right_column_id = _col_id + _num_cols
|
|
131
226
|
|
|
132
227
|
if isinstance(cell_format, tuple):
|
|
133
228
|
ensure_cell_format_spec_tuple(cell_format)
|
|
134
|
-
if not len(cell_format) == len(
|
|
229
|
+
if not len(cell_format) == len(_data_table[0]):
|
|
135
230
|
raise ValueError("Format tuple does not match data in length.")
|
|
136
231
|
_cell_format: Sequence[CFmt] = cell_format
|
|
137
232
|
elif isinstance(cell_format, CFmt):
|
|
138
|
-
_cell_format = (cell_format,) * len(
|
|
233
|
+
_cell_format = (cell_format,) * len(_data_table[0])
|
|
139
234
|
else:
|
|
140
|
-
_cell_format = (CFmt.XL_DEFAULT,) * len(
|
|
141
|
-
|
|
142
|
-
for _cell_row in range(_row_id, _bottom_row_id):
|
|
143
|
-
for _cell_col in range(_col_id, _right_column_id):
|
|
144
|
-
_cell_fmt = (
|
|
145
|
-
(_cell_format[_cell_col - _col_id], CFmt.BAR_FILL)
|
|
146
|
-
if green_bar_flag and (_cell_row - _row_id) % 2
|
|
147
|
-
else _cell_format[_cell_col - _col_id]
|
|
148
|
-
)
|
|
235
|
+
_cell_format = (CFmt.XL_DEFAULT,) * len(_data_table[0])
|
|
149
236
|
|
|
237
|
+
for _ri, _rv in enumerate(_data_table):
|
|
238
|
+
for _ci, _cv in enumerate(_rv):
|
|
239
|
+
_cell_fmt = _cell_format[_ci] | (
|
|
240
|
+
CFmt.BAR_FILL if green_bar_flag and _ri % 2 else {}
|
|
241
|
+
)
|
|
150
242
|
scalar_to_sheet(
|
|
151
|
-
_xl_book,
|
|
152
|
-
_xl_sheet,
|
|
153
|
-
_cell_row,
|
|
154
|
-
_cell_col,
|
|
155
|
-
_data_array[_cell_row - _row_id, _cell_col - _col_id],
|
|
156
|
-
_cell_fmt,
|
|
243
|
+
_xl_book, _xl_sheet, _row_id + _ri, _col_id + _ci, _cv, _cell_fmt
|
|
157
244
|
)
|
|
158
245
|
|
|
246
|
+
_right_column_id = _col_id + _ci + 1 if _ci > _num_cols else _right_column_id
|
|
247
|
+
|
|
159
248
|
return _bottom_row_id, _right_column_id
|
|
160
249
|
|
|
161
250
|
|
|
@@ -186,6 +275,17 @@ def scalar_to_sheet(
|
|
|
186
275
|
cell format, or the column-part of the 'R1,C1' address along with
|
|
187
276
|
cell value and cell format.
|
|
188
277
|
|
|
278
|
+
Raises
|
|
279
|
+
------
|
|
280
|
+
ValueError
|
|
281
|
+
If too many or too few arguments
|
|
282
|
+
ValueError
|
|
283
|
+
If incorrect/incomplete specification for Excel cell data
|
|
284
|
+
|
|
285
|
+
Returns
|
|
286
|
+
-------
|
|
287
|
+
None
|
|
288
|
+
|
|
189
289
|
"""
|
|
190
290
|
|
|
191
291
|
if isinstance(_cell_addr_0, str):
|
|
@@ -201,9 +301,16 @@ def scalar_to_sheet(
|
|
|
201
301
|
_cell_val = _s2s_args[1]
|
|
202
302
|
_cell_fmt = _s2s_args[2] if len(_s2s_args) == 3 else None # type: ignore
|
|
203
303
|
else:
|
|
204
|
-
raise ValueError("Incorrect specification for Excel cell data.")
|
|
304
|
+
raise ValueError("Incorrect/incomplete specification for Excel cell data.")
|
|
205
305
|
|
|
206
|
-
|
|
306
|
+
if isinstance(_cell_val, str):
|
|
307
|
+
_xl_sheet.write_string(*_cell_addr, _cell_val, xl_fmt(_xl_book, _cell_fmt))
|
|
308
|
+
else:
|
|
309
|
+
_xl_sheet.write(
|
|
310
|
+
*_cell_addr,
|
|
311
|
+
repr(_cell_val) if np.ndim(_cell_val) else _cell_val,
|
|
312
|
+
xl_fmt(_xl_book, _cell_fmt),
|
|
313
|
+
)
|
|
207
314
|
|
|
208
315
|
|
|
209
316
|
def xl_fmt(
|
|
@@ -247,6 +354,11 @@ def ensure_cell_format_spec_tuple(_cell_formats: Sequence[CFmt], /) -> None:
|
|
|
247
354
|
_cell_formats
|
|
248
355
|
Format specification
|
|
249
356
|
|
|
357
|
+
Raises
|
|
358
|
+
------
|
|
359
|
+
ValueError
|
|
360
|
+
If format specification is not tuple of CFmt aenums
|
|
361
|
+
|
|
250
362
|
Returns
|
|
251
363
|
-------
|
|
252
364
|
True if format specification passes, else False
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/core/damodaran_margin_data.py
RENAMED
|
File without changes
|
|
File without changes
|
{mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/core/guidelines_boundaries.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/core/pseudorandom_numbers.py
RENAMED
|
File without changes
|
|
File without changes
|
{mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/data/damodaran_margin_data.xls
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mergeron-2024.739079.11 → mergeron-2024.739079.13}/src/mergeron/gen/_data_generation_functions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|