-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpyproject.toml
More file actions
1239 lines (1164 loc) · 71.5 KB
/
Copy pathpyproject.toml
File metadata and controls
1239 lines (1164 loc) · 71.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
[build-system]
requires = ["setuptools>=58.0.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "benchbox"
version = "0.2.1"
description = "Embedded benchmark datasets and queries for database evaluation. Implements TPC-H, TPC-DS, TPC-DI and other industry-standard benchmarks."
readme = "README.md"
authors = [{ name = "Joe Harris", email = "joe@benchbox.dev" }]
license = {text = "MIT"}
keywords = ["benchmark", "database", "tpc-h", "tpc-ds", "tpc-di", "analytics", "olap", "performance-testing"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Topic :: Database",
"Topic :: Software Development :: Testing :: Acceptance",
"Topic :: System :: Benchmark",
]
requires-python = ">=3.10,<3.15"
dependencies = [
"textcharts>=0.1.0",
# sqlglot ships majors ~quarterly with dialect-translation breakage; cap to next major to catch
# regressions in CI rather than silently in `uv sync`. Bump after validating on the new major.
# Floor is v25.6.0 — first release containing PR #3756, which preserves DuckDB
# GROUP/ORDER BY ALL as bare keywords under identify=True (was a BenchBox post-fixup).
"sqlglot>=25.6.0,<31.0.0",
# CLI essentials
# click: capped <9 - historically click majors rename decorators/context APIs.
"click>=8.3.3,<9.0.0", # >=8.3.3: PYSEC-2026-2132 fix
"rich>=13.0.0",
"keyring>=25.0.0",
"psutil>=5.9.0",
# pydantic: v1→v2 migration broke the entire validation surface; capped <3 until pydantic v3 lands
# and is audited.
"pydantic>=2.0.0,<3.0.0",
"pyyaml>=6.0.0",
"packaging>=24.0",
# Python 3.10 compatibility (tomllib is stdlib in 3.11+)
"tomli>=2.0.0; python_version < '3.11'",
# pyarrow: ABI-sensitive (bundled C++); wide cap to <25 to give runway while catching jumps.
"pyarrow>=21.0.0,<25.0.0",
"numpy>=1.24.0",
# pandas is intentionally NOT a core dependency. It is an optional
# engine/DataFrame dep (DataFrame mode, TPC-DI, ClickHouse-local) declared
# in the relevant extras (pandas, dataframe-pandas, tpcdi, modin, dask) and
# pulled transitively by chdb. All pandas uses on the import path are lazy;
# the minimal-import-surface CI gate enforces this. See
# docs/development/dependency-inventory.md (pandas = DataFrame/Benchmark).
"zstandard>=0.20.0",
# requests: imported unconditionally by benchbox.core.data_fetch.downloader, which is
# reached on the canonical JoinOrder benchmark import path. Must be core so a bare
# `pip install benchbox` (no extras) doesn't raise ModuleNotFoundError. Floor matches
# the version already pinned in the questdb / cloud-spark extras.
"requests>=2.31.0",
# grpcio / grpcio-status are NOT declared at the core level. They are
# pulled in transitively by optional cloud / connectivity extras
# (e.g. influxdb3-python, snowflake, databricks-sdk, pyspark[connect]).
# Users without those extras don't pay the grpc weight.
]
[tool.setuptools]
# Include non-Python files specified in MANIFEST.in
include-package-data = true
[tool.setuptools.packages.find]
include = ["benchbox*"]
exclude = [
"benchmark_runs",
"benchmark_runs.*",
# benchbox.experimental is intentionally INCLUDED in the default wheel (Option A, Beta contract).
# It is an explicitly unsupported namespace with no CLI/registry integration.
# See README.md "Beta Software" section for the documented support boundary.
# To exclude it from the wheel, add "benchbox.experimental" and "benchbox.experimental.*" here.
]
[project.optional-dependencies]
# Development and documentation
dev = [
"pytest>=8.0.0",
"pytest-cov>=4.1.0",
"pytest-benchmark>=4.0.0",
"pytest-xdist>=3.0.0",
# duckdb: tight integration with BenchBox SQL runner and browser snapshot writer.
# Cap <2 to catch the next-major API break in CI; browser results.duckdb files
# use the default v1.0.0 on-disk format (version 64), which @duckdb/duckdb-wasm
# attaches regardless of writer version.
"duckdb>=1.0.0,<2.0.0",
"tox>=4.13.0",
"pyspark>=3.5.0", # Aligned with pyspark extra
]
docs = [
"sphinx>=7.2.0",
"roman-numerals<4.0", # Sphinx 9 needs roman_numerals module; v4.x broke the import
"furo>=2025.9.25",
"myst-parser>=2.0.0",
"sphinxcontrib-mermaid>=0.8.1",
"pygments>=2.18.0",
"sphinx-tags>=0.4.0",
"sphinx-design>=0.6.0",
"ablog>=0.11.13 ; python_version >= '3.11'", # uv source override pins to git main for unreleased Sphinx 9 fix
]
viz = []
explorer = ["duckdb>=1.0.0,<2.0.0"]
# Meta-groups for common scenarios
all = [
# Browser-generated results.duckdb files use the default v1.0.0 on-disk format,
# readable by @duckdb/duckdb-wasm regardless of writer version; cap <2 to catch
# the next-major API break in CI.
"duckdb>=1.0.0,<2.0.0",
"clickhouse-connect>=0.10.0",
"clickhouse-driver>=0.2.0",
"databricks-sql-connector>=2.0.0",
"databricks-sdk>=0.20.0",
"databricks-connect>=14.0.0", # For DataFrame mode
"datafusion>=50.1.0", # Updated to match datafusion extra
"pyarrow>=10.0.0", # For DataFusion (also in core with higher version)
"firebolt-sdk>=1.18.0",
"google-cloud-bigquery>=3.0.0",
"google-cloud-storage>=2.0.0",
"redshift-connector>=2.0.0",
"snowflake-connector-python>=3.0.0",
"trino>=0.328.0",
"presto-python-client>=0.8.4",
"psycopg[binary]>=3.1",
"pyodbc>=4.0.0",
"azure-identity>=1.15.0", # For Azure Synapse and Fabric
"azure-storage-file-datalake>=12.14.0", # For Microsoft Fabric OneLake
"pyathena>=3.0.0", # For AWS Athena
"boto3>=1.20.0",
"cloudpathlib>=0.15.0",
"pandas>=2.0.0", # For TPC-DI benchmark
"chdb>=0.10.0; sys_platform != 'win32'", # For ClickHouse local mode (not available on Windows)
"deltalake>=1.2.1", # For Delta Lake table format
"pyiceberg>=0.10.0", # For Iceberg table format
"influxdb3-python>=0.10.0", # For InfluxDB 3.0 time-series
"pymysql>=1.1.0", # For StarRocks and Doris via MySQL protocol
"singlestoredb>=1.0.0", # For SingleStore (Helios / self-managed)
# DataFrame platforms
"polars>=1.35.2",
"dask[distributed]>=2024.1.0",
"modin[ray]>=0.32.0",
"pyspark[connect]>=3.5.0",
]
cloud = [
"databricks-sql-connector>=2.0.0",
"databricks-sdk>=0.20.0",
"firebolt-sdk>=1.18.0",
"google-cloud-bigquery>=3.0.0",
"google-cloud-storage>=2.0.0",
"redshift-connector>=2.0.0",
"snowflake-connector-python>=3.0.0",
"trino>=0.328.0",
"pyathena>=3.0.0", # For AWS Athena
"boto3>=1.20.0",
"cloudpathlib>=0.15.0",
]
cloudstorage = ["cloudpathlib>=0.15.0"]
# Individual platforms (for minimal installations)
duckdb = ["duckdb>=1.0.0,<2.0.0"]
clickhouse = ["clickhouse-driver>=0.2.0"] # TCP binary protocol (clickhouse-server)
clickhouse-server = ["clickhouse-driver>=0.2.0"] # Canonical extra for clickhouse-server platform
clickhouse-cloud = ["clickhouse-connect>=0.10.0"] # HTTP protocol (ClickHouse Cloud)
databricks = [
"databricks-sql-connector>=2.0.0",
"databricks-sdk>=0.20.0",
"cloudpathlib>=0.15.0",
]
bigquery = [
"google-cloud-bigquery>=3.0.0",
"google-cloud-storage>=2.0.0",
"cloudpathlib>=0.15.0",
]
redshift = [
"redshift-connector>=2.0.0",
"boto3>=1.20.0",
"cloudpathlib>=0.15.0",
]
snowflake = ["snowflake-connector-python>=3.0.0", "cloudpathlib>=0.15.0"]
trino = ["trino>=0.328.0", "cloudpathlib>=0.15.0"]
presto = ["presto-python-client>=0.8.4", "cloudpathlib>=0.15.0"]
postgresql = ["psycopg[binary]>=3.1"]
questdb = ["psycopg[binary]>=3.1", "requests>=2.28.0"]
synapse = ["pyodbc>=4.0.0"]
fabric = [
"pyodbc>=4.0.0",
"azure-identity>=1.15.0",
"azure-storage-file-datalake>=12.14.0",
]
athena = [
"pyathena>=3.0.0",
"boto3>=1.20.0",
]
datafusion = ["datafusion>=50.1.0", "pyarrow>=10.0.0"]
firebolt = [
"firebolt-sdk>=1.18.0",
"cloudpathlib>=0.15.0",
]
databend = [
"databend-driver>=0.28.0",
]
doris = ["pymysql>=1.0.0"]
influxdb = [
"influxdb3-python>=0.10.0",
"pyarrow>=10.0.0",
]
starrocks = ["pymysql>=1.1.0"]
singlestore = ["singlestoredb>=1.0.0"]
# Individual benchmark extras
tpcdi = ["pandas>=2.0.0"]
clickhouse-local = ["chdb>=0.10.0; sys_platform != 'win32'"]
table-formats = [
"deltalake>=1.2.1",
"pyiceberg>=0.10.0",
"vortex-data>=0.29.0",
]
ai-primitives = [
# ML/NLP stack used by benchbox/core/ai_primitives/ (all imports guarded with try/except)
"sentence-transformers>=2.0.0",
"torch>=2.0.0",
"textblob>=0.17.0",
"spacy>=3.0.0",
]
# DataFrame platform extras (for benchbox.platforms.dataframe)
# Plain-name extras are the preferred install names.
# dataframe-* variants are kept as backward-compatible aliases.
# Pandas family - string-based column access, eager evaluation
pandas = ["pandas>=2.0.0"]
dataframe-pandas = ["pandas>=2.0.0"]
modin = ["modin[ray]>=0.32.0", "pandas>=2.0.0"]
dataframe-modin = [
"modin[ray]>=0.32.0",
"pandas>=2.0.0",
]
dask = ["dask[distributed]>=2024.1.0", "pandas>=2.0.0"]
dataframe-dask = [
"dask[distributed]>=2024.1.0",
"pandas>=2.0.0",
]
# Note: cudf requires NVIDIA GPU with CUDA 12.x
# cuDF is not on PyPI directly - install via RAPIDS:
# pip install --extra-index-url=https://pypi.nvidia.com cudf-cu12
# This extra is a placeholder to document the dependency; actual installation
# requires the RAPIDS pip index or conda.
cudf = []
dataframe-cudf = [
# Placeholder - actual cudf installation requires NVIDIA pip index
]
# Expression family - expression-based API, lazy evaluation
polars = ["polars>=1.35.2"]
dataframe-polars = [
"polars>=1.35.2",
]
pyspark = ["pyspark>=3.5.0"]
lakesail = ["pyspark[connect]>=3.5.0"]
velox = ["pyspark[connect]>=3.5.0"]
dataframe-pyspark = [
"pyspark>=3.5.0",
]
dataframe-datafusion = [
"datafusion>=50.1.0",
"pyarrow>=10.0.0",
]
# DataFrame family convenience groups
dataframe-pandas-family = [
"pandas>=2.0.0",
"modin[ray]>=0.32.0",
"dask[distributed]>=2024.1.0",
# cudf not included - requires NVIDIA GPU/CUDA, install separately
]
dataframe-expression-family = [
"polars>=1.35.2",
"pyspark>=3.5.0",
"datafusion>=50.1.0",
]
dataframe-all = [
"pandas>=2.0.0",
"modin[ray]>=0.32.0",
"dask[distributed]>=2024.1.0",
"polars>=1.35.2",
"pyspark>=3.5.0",
"datafusion>=50.1.0",
]
# Quick start - DuckDB + Polars for easy experimentation
quick-start = [
"polars>=1.35.2",
]
# Cloud Spark Platforms - Managed Spark with DataFrame API
# These extras enable DataFrame mode execution on managed cloud Spark platforms
# Provider-specific cloud Spark groups
cloud-spark-aws = [
"boto3>=1.34.0",
]
cloud-spark-gcp = [
"google-cloud-dataproc>=5.0.0",
"google-cloud-storage>=2.0.0",
]
cloud-spark-azure = [
"azure-identity>=1.15.0",
"azure-storage-file-datalake>=12.14.0",
"requests>=2.31.0",
]
cloud-spark-snowflake = [
"snowflake-snowpark-python>=1.11.0",
"pyspark>=3.5.0",
]
cloud-spark-databricks = [
"databricks-sql-connector>=2.0.0",
"databricks-sdk>=0.20.0",
"databricks-connect>=14.0.0",
"cloudpathlib>=0.15.0",
]
# All cloud Spark platforms combined
cloud-spark = [
# AWS (Glue, EMR Serverless, Athena Spark)
"boto3>=1.34.0",
# GCP (Dataproc, Dataproc Serverless)
"google-cloud-dataproc>=5.0.0",
"google-cloud-storage>=2.0.0",
# Azure (Synapse Spark, Fabric Spark)
"azure-identity>=1.15.0",
"azure-storage-file-datalake>=12.14.0",
"requests>=2.31.0",
# Snowflake (Snowpark)
"snowflake-snowpark-python>=1.11.0",
"pyspark>=3.5.0",
# Databricks
"databricks-sql-connector>=2.0.0",
"databricks-sdk>=0.20.0",
"databricks-connect>=14.0.0",
"cloudpathlib>=0.15.0",
]
# MCP (Model Context Protocol) server for AI agent integration
# Note: mcp requires Python 3.10+, so this extra only works on 3.10+
# Includes visualization deps since MCP server exposes chart generation tools
mcp = [
"mcp>=1.28.1", # >=1.28.1: CVE-2026-52870/52869/59950 fixes
]
spark = [
"pyspark>=4.0.1",
]
[project.scripts]
benchbox = "benchbox.cli.app:main"
benchbox-mcp = "benchbox.mcp.cli:main"
[project.urls]
"Homepage" = "https://github.com/joeharris76/benchbox"
"Bug Tracker" = "https://github.com/joeharris76/benchbox/issues"
"Documentation" = "https://benchbox.readthedocs.io/"
"Repository" = "https://github.com/joeharris76/benchbox.git"
"Changelog" = "https://github.com/joeharris76/benchbox/blob/release/CHANGELOG.md"
[tool.ty]
# ty configuration
[tool.ty.src]
# Source code to type check
include = ["benchbox", "tests"]
exclude = ["tests/fixtures", "**/__pycache__"]
[tool.ty.rules]
# Configure rule severities - start lenient, gradually tighten
# Note: This codebase was developed without strict type checking.
# Rules are configured permissively; tighten as code is updated.
# Error: These rules are now enforced (previously ignored, now fixed)
too-many-positional-arguments = "error" # Fixed: method signature alignment
conflicting-declarations = "error" # Fixed: optional import patterns
invalid-parameter-default = "error" # Fixed: Optional[] wrappers added
unresolved-reference = "error" # Fixed: missing imports/variables
not-iterable = "error" # Fixed: type narrowing and assertions
# Ignore: These rules have too many false positives or require major refactoring
unresolved-attribute = "ignore" # 954 hits - Missing type stubs, dynamic attributes, class method discovery
invalid-argument-type = "ignore" # 763 hits - Function param type mismatches (str vs Literal, Optional narrowing)
invalid-assignment = "ignore" # 463 hits - Literal type mismatches, Optional subscript access
unsupported-operator = "ignore" # 184 hits - Dict value type inference (counter += 1 patterns)
invalid-method-override = "ignore" # 143 hits - Intentional LSP violations (run_benchmark, execute_query, generate_data, etc.)
not-subscriptable = "ignore" # ~700 hits - Dynamic DataFrame APIs, Optional dict access patterns
call-non-callable = "ignore" # ~700 hits - Optional imports, dynamic DataFrame APIs, hasattr patterns
# Warn: Track these but don't fail CI
unresolved-import = "warn" # Often optional dependencies
invalid-return-type = "warn" # Should be fixed but not blocking
invalid-type-form = "warn" # Syntax issues
no-matching-overload = "warn" # Complex overload patterns
unknown-argument = "warn" # Keyword argument issues
missing-argument = "warn" # Tuple unpacking not tracked
# Control flow tracking limitations
possibly-unresolved-reference = "warn"
possibly-missing-attribute = "warn"
[tool.ty.terminal]
# Output configuration
error-on-warning = false
[dependency-groups]
dev = [
"ruff==0.11.13", # pinned: preview = true is active globally; ruff upgrades may activate new rules
"ty>=0.0.1a14",
"ansi2html>=1.8.0", # scripts/capture_chart_images.py - ANSI→HTML conversion for chart captures
"pillow>=12.3.0", # scripts/capture_chart_images.py - PIL.Image for chart PNG output; >=12.3.0: PYSEC-2026-2253..3453 fixes
# Explorer fixture and deployment snapshots use the default v1.0.0 on-disk format,
# readable by @duckdb/duckdb-wasm regardless of writer version; cap <2 to catch
# the next-major API break in CI.
"duckdb>=1.0.0,<2.0.0",
"polars>=1.35.2",
"clickhouse-connect>=0.10.0",
"psycopg[binary]>=3.1",
"pytest>=8.0.0", # Test framework
"pytest-cov>=6.2.1",
"pytest-benchmark>=5.1.0",
"pytest-xdist>=3.8.0",
"pytest-timeout>=2.4.0",
"pandas>=2.0.0", # DataFrame dependencies (needed for many tests)
"pyiceberg[sql-sqlite,pyarrow]>=0.10.0", # Table format converters (needed for tests/unit/utils/format_converters/)
"deltalake>=1.2.1",
"datafusion>=40.0.0", # DataFusion (needed for tests/integration/test_datafusion_integration.py)
"cloudpathlib[s3,gs,azure]>=0.15.0", # Cloud storage with S3 support (needed for tests/unit/utils/test_cloud_storage.py)
"chdb>=0.10.0; sys_platform != 'win32'", # ClickHouse local (chdb is not available on Windows)
"clickhouse-driver>=0.2.0", # ClickHouse server (needed for tests/unit/platforms/test_clickhouse_local.py server tests)
"trino>=0.336.0", # Firebolt (needed for tests/unit/platforms/test_firebolt_adapter.py)
"firebolt-sdk>=1.18.0", # InfluxDB (needed for tests/unit/platforms/test_influxdb_adapter.py)
"influxdb3-python>=0.10.0", # Databricks SDK (needed for tests/unit/platforms/test_databricks_copy_into.py UC volumes)
"databricks-sdk>=0.20.0", # PySpark (needed for tests/unit/platforms/dataframe/test_pyspark_df.py and related)
"pyspark>=3.5.0", # XML parsing (needed for tests/unit/core/tpcdi/test_etl_sources.py)
"mcp>=1.28.1", # >=1.28.1: CVE-2026-52870/52869/59950 fixes
"sphinx>=7.4.7", # Documentation
"roman-numerals<4.0", # Sphinx 9 needs roman_numerals module; v4.x broke the import
"myst-parser>=3.0.1",
"sphinxcontrib-mermaid>=1.2.3",
"sphinx-tags>=0.4",
"sphinx-design>=0.6.1",
"furo>=2025.9.25",
"ablog>=0.11.13 ; python_version >= '3.11'", # version that includes a required Sphinx 9 fix
"mutmut>=3.5.0",
"dask[distributed]>=2026.1.1",
"pymysql>=1.1.2",
"delta-spark>=4.1.0",
"presto-python-client>=0.8.4",
"codespell>=2.4.2",
"pre-commit>=4.6.0",
"import-linter>=2.13",
]
[tool.mutmut]
paths_to_mutate = [
"benchbox/platforms/duckdb.py",
"benchbox/platforms/base/adapter.py",
"benchbox/core/runner/runner.py",
"benchbox/core/visualization/chart_generator.py",
"benchbox/cli/commands/run.py",
]
tests_dir = ["tests/unit/"]
[tool.setuptools.package-data]
"benchbox.core" = ["benchmark_registry.yaml"]
"benchbox.core.equivalence" = ["cross_surface_baseline.yaml"]
"benchbox.core.flightdata" = ["query_catalog.yaml"]
"benchbox.core.nyctaxi" = ["query_catalog.yaml"]
"benchbox.core.results" = ["benchmark_specs.yaml"]
"benchbox.core.primitives.catalog" = ["queries.yaml"]
"benchbox.core.tsbs_devops" = ["query_catalog.yaml"]
"benchbox.data.coffeeshop" = ["*.csv"]
[tool.ruff]
line-length = 120
exclude = [
"migrations",
"venv",
".git",
"__pycache__",
".tox",
# Non-production directories
"_project", # Internal project tooling and scripts
"examples/notebooks", # Example notebooks (different code style)
"examples/visualization", # Visualization notebooks
"tests/validation", # One-off validation scripts
]
[tool.ruff.lint]
# preview = true is required to activate PLW1514 (unspecified-encoding).
# Side-effect: surfaces pre-existing F822 violations in __init__.py lazy-import
# modules and one C419/F401 elsewhere. Those are suppressed below.
preview = true
# Enable comprehensive linting rules that replace flake8/pycodestyle
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"UP", # pyupgrade
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"C90", # mccabe complexity
"PIE", # flake8-pie
"SIM", # flake8-simplify
"PLW1514", # unspecified-encoding: open() without explicit encoding= (Windows compat)
]
ignore = [
"E501", # line too long (handled by formatter)
# The following are temporarily ignored to allow CI to pass.
# These pre-existed and should be addressed in a future cleanup.
# TODO: Create TODO item to address these lint issues systematically
"E402", # module-import-not-at-top-of-file (often intentional for conditional imports)
"E721", # type-comparison (use isinstance - valid but requires careful review)
"E731", # lambda-assignment (sometimes clearer than def)
"E741", # ambiguous-variable-name (context-dependent)
# Bugbear rules - good practices but not critical
"B905", # zip-without-explicit-strict (19 occurrences; TODO: add strict= and remove)
"B007", # unused-loop-control-variable (often intentional, e.g., for _ in range())
"B017", # assert-raises-exception (test pattern)
"B023", # function-uses-loop-variable (often intentional in closures)
"B024", # abstract-base-class-without-abstract-method
"B027", # empty-method-without-abstract-decorator
# Simplify rules - style preferences
"SIM102", # collapsible-if
"SIM103", # needless-bool
"SIM105", # suppressible-exception
"SIM108", # if-else-block-instead-of-if-exp (ternaries can reduce readability)
"SIM110", # reimplemented-builtin
"SIM113", # enumerate-for-loop
"SIM115", # open-file-with-context-handler (sometimes intentional)
"SIM116", # if-else-block-instead-of-dict-lookup
"SIM117", # multiple-with-statements
"SIM118", # in-dict-keys
"SIM201", # negate-equal-op
"SIM401", # if-else-block-instead-of-dict-get
# Comprehensions
"C401", # unnecessary-generator-set
# PIE rules
"PIE810", # multiple-starts-ends-with
# Upgrade rules - require newer Python versions
"UP006", # non-pep585-annotation (use dict instead of Dict - requires Python 3.9+)
"UP007", # non-pep604-annotation-union (use X | Y - requires Python 3.10+)
"UP035", # deprecated-import (typing.Dict etc - requires Python 3.9+)
"UP045", # non-pep604-annotation-optional
# Naming conventions - often intentional in specific contexts
"N802", # invalid-function-name (test methods, compatibility)
"N803", # invalid-argument-name (mathematical notation, API compatibility)
"N806", # non-lowercase-variable-in-function (constants, compatibility)
"N811", # constant-imported-as-non-constant
"N818", # error-suffix-on-exception-name
# C901 (mccabe complexity) is now a permanent gate - all violations resolved.
]
[tool.ruff.lint.isort]
force-single-line = false
combine-as-imports = true
[tool.ruff.lint.mccabe]
# Cyclomatic complexity gate: no function may exceed McCabe 18.
# All pre-existing violations resolved as of 2026-04-14.
max-complexity = 18
[tool.ruff.lint.per-file-ignores]
# Files that use `from x import *` pattern legitimately
"benchbox/core/tpcds/schema/registry.py" = ["F405"]
# Test files often have unused imports for fixtures or type checking
"tests/**/conftest.py" = ["F401", "F811"]
"tests/**/test_*.py" = ["F401", "F811"]
# __init__.py files often re-export symbols via lazy imports; F822 fires in
# preview mode for names defined in TYPE_CHECKING blocks or deferred imports.
"**/__init__.py" = ["F401", "F811", "F822"]
# Pre-existing violations surfaced by preview mode; out of scope for windows-ci-hardening.
"benchbox/utils/runtime_env.py" = ["F401"] # unused importlib.machinery import
# PLW1514 (unspecified-encoding): all benchbox/ sites now have explicit encoding=
# (fixed under quality-bulk-fix-encoding-lint-and-ratchet). Per-file-ignores removed.
[tool.ruff.format]
# Use black-compatible formatting
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"
[tool.interrogate]
# Docstring coverage enforcement
ignore-init-method = false
ignore-init-module = false
ignore-magic = false
ignore-module = false
ignore-nested-functions = true
ignore-nested-classes = true
ignore-private = true
ignore-property-decorators = false
# Keep the blocking gate focused on public API documentation; single-underscore
# helpers churn heavily and are covered by code review/tests instead.
ignore-semiprivate = true
ignore-setters = false
fail-under = 90 # Ratcheted from baseline after local audit reported 93.1% coverage.
exclude = [
"tests",
"_build",
"venv",
".venv",
"benchmark_runs",
"_project",
"docs/_build",
"benchbox/platforms/credentials",
# Bulk mechanical DataFrame query catalogs are generated-style
# implementations; keep the gate focused on hand-authored public APIs.
"benchbox/core/clickbench/dataframe_queries/queries.py",
"benchbox/core/datavault/dataframe_queries/queries.py",
"benchbox/core/flightdata/dataframe_queries.py",
"benchbox/core/nyctaxi/dataframe_queries/queries.py",
"benchbox/core/tpcds/dataframe_queries/queries.py",
"benchbox/core/tpcds_obt/dataframe_queries.py",
"benchbox/core/tpchavoc/dataframe_queries",
]
verbose = 2
quiet = false
whitelist-regex = []
color = true
[tool.coverage.run]
# Test coverage configuration
source = ["benchbox"]
branch = true
omit = [
"benchbox/__main__.py",
"**/test_*.py",
"**/conftest.py",
# Low-ROI bulk DF query sets: mechanical translations untestable without
# full-scale benchmark infrastructure (TPC-DS requires SF>=1, others need
# large external datasets). Excluding ~5,742 statements.
"benchbox/core/tpcds/dataframe_queries/queries.py",
"benchbox/core/tpcds/dataframe_queries/rollup_helper.py",
"benchbox/core/tpcds/dataframe_queries/channel_helper.py",
"benchbox/core/datavault/dataframe_queries/queries.py",
"benchbox/core/nyctaxi/dataframe_queries/queries.py",
# TPC-DI ETL: requires full CDC/SCD pipeline infrastructure with staged
# incremental loads. Cannot be meaningfully unit-tested at unit granularity.
"benchbox/core/tpcdi/etl/scd_processor.py",
# Experimental load testing: changes frequently, pool tester requires real
# concurrent database connections (~284 miss stmts).
"benchbox/experimental/load_testing/executor.py",
"benchbox/experimental/load_testing/pool_tester.py",
# ClickBench DF queries: single wide table with 105 columns and specific
# data patterns, same rationale as TPC-DS/datavault/nyctaxi DF omissions
# (~310 miss stmts).
"benchbox/core/clickbench/dataframe_queries/queries.py",
]
[tool.coverage.report]
# Coverage reporting thresholds
fail_under = 80
show_missing = true
skip_covered = false
exclude_lines = [
"pragma: no cover",
"if TYPE_CHECKING:",
"if __name__ == .__main__.:",
"raise NotImplementedError",
"@abstractmethod",
]
[tool.benchbox.complexity]
# Cyclomatic complexity check configuration (used by scripts/check_complexity.py).
# max_complexity: hard ceiling - functions above this are CI failures.
# warn_complexity: advisory - functions above this are printed as warnings.
max_complexity = 20
warn_complexity = 12
# Modules temporarily excluded from per-module complexity checks.
exclude_modules = []
# Individual functions excluded from the check (format: "file:function").
# Use sparingly - only for genuinely irreducible complexity (e.g., CLI dispatch).
exclude_functions = [
# CLI run() is a Click command with many flags; refactoring underway.
"benchbox/cli/commands/run.py:run",
# ── Approved ignore_with_rationale entries (2026-02-20) ──
# Each maps to a row in quality/complexity/classification-matrix.yaml
# Re-review triggers are documented per-function in the matrix.
# --- ASCII visualization renderers (inherent grid/layout complexity) ---
"benchbox/core/visualization/ascii/line_chart.py:render", # 43 - Bresenham line drawing + grid state
"benchbox/core/visualization/ascii/box_plot.py:render", # 30 - three-line-per-series box plot geometry
"benchbox/core/visualization/ascii/scatter_plot.py:render", # 26 - Pareto frontier + grid point placement
"benchbox/core/visualization/ascii/bar_chart.py:render", # 22 - outlier truncation + sub-character blocks
"benchbox/core/visualization/ascii/rank_table.py:render", # 22 - ranking with tie handling
"benchbox/core/visualization/ascii/cdf_chart.py:render", # 21 - grid-based CDF plotting
# --- TPC specification implementations (spec-driven branching) ---
"benchbox/core/tpcds/power_test.py:run", # 33 - TPC-DS power test per spec
"benchbox/core/tpcds_obt/query_conversion.py:_post_process", # 32 - per-query OBT conversion edge cases
"benchbox/core/tpcds/c_tools.py:_generate_with_binary", # 25 - dsqgen binary wrapper
"benchbox/core/tpcds/throughput_test.py:_execute_stream", # 24 - TPC-DS throughput stream execution
"benchbox/core/tpcds/benchmark/runner.py:run_throughput_test", # 22 - TPC-DS throughput test per spec
"benchbox/core/tpcds/benchmark/runner.py:run_power_test", # 22 - TPC-DS power test per spec
"benchbox/core/results/display.py:print_dry_run_summary", # 21 - conditional section display
"benchbox/core/tpcds/throughput_test.py:run", # 18 - TPC-DS spec; outer loop coordinates concurrent streams
"benchbox/core/tpcds_obt/query_conversion.py:_rewrite_select", # 18 - AST rewrite with dependency ordering (role_map → column → join)
"benchbox/core/tpch/maintenance_test.py:_execute_rf1", # 18 - TPC-H RF1 spec; each SQL step depends on prior result
"benchbox/core/tpch/power_test.py:run", # 18 - TPC-H power test; spec mandates permutation order
"benchbox/core/tpch/throughput_test.py:run", # 18 - TPC-H throughput; spec mandates TTT timing from first to last stream
"benchbox/core/runner/dataframe_runner.py:_execute_dataframe_queries", # 18 - TPC power test methodology; warmup + permuted query loop
"benchbox/core/tpch/throughput_test.py:_execute_stream", # 17 - TPC-H single stream; 22 queries in spec permutation order
# --- Platform adapters (genuinely distinct platform semantics) ---
"benchbox/platforms/base/adapter.py:_summarize_performance_characteristics", # 34 - well-structured statistical aggregation
"benchbox/platforms/dataframe/unified_frame.py:join", # 33 - multi-platform join dispatch (Polars/PySpark/DataFusion)
"benchbox/platforms/base/adapter.py:_collect_resource_utilization", # 24 - cross-platform metric collection with independent try/except
"benchbox/platforms/credentials/redshift.py:setup_redshift_credentials", # 24 - interactive credential wizard
"benchbox/platforms/redshift.py:get_platform_info", # 24 - serverless vs provisioned deployment branching
"benchbox/platforms/bigquery.py:get_platform_info", # 23 - independent INFORMATION_SCHEMA queries
"benchbox/platforms/dataframe/unified_frame.py:_datafusion_join_with_exprs", # 23 - DataFusion join workaround
"benchbox/platforms/credentials/redshift.py:validate_redshift_credentials", # 22 - sequential validation pipeline
"benchbox/platforms/clickhouse/metadata.py:get_platform_info", # 21 - local vs server mode branching
"benchbox/platforms/credentials/bigquery.py:validate_bigquery_credentials", # 21 - multi-service validation
"benchbox/platforms/databricks/adapter.py:apply_table_tunings", # 21 - Liquid Clustering vs Z-ORDER
"benchbox/platforms/dataframe/unified_frame.py:_extract_multi_agg_arithmetic", # 21 - DataFusion AST workaround
"benchbox/platforms/dataframe/unified_frame.py:sort", # 20 - Polars/PySpark/DataFusion each require distinct sort APIs
"benchbox/platforms/credentials/athena.py:setup_athena_credentials", # 20 - interactive credential wizard; auto-detect vs manual with dependent branching
"benchbox/platforms/credentials/bigquery.py:setup_bigquery_credentials", # 20 - interactive credential wizard; file validation + optional Cloud Storage path
"benchbox/platforms/dataframe/unified_frame.py:_apply_datafusion_post_ops", # 19 - literal vs multi-agg arithmetic post-ops have fundamentally different expression semantics
"benchbox/platforms/base/adapter.py:capture_query_plan", # 17 - multi-level filter chain (query ID, iteration count, sampling, EXPLAIN)
"benchbox/platforms/credentials/snowflake.py:setup_snowflake_credentials", # 16 - interactive credential wizard; account normalization + multi-step auth validation
# --- MCP tool registration (structural nesting from framework) ---
"benchbox/mcp/tools/discovery.py:register_discovery_tools", # 29 - MCP registration pattern
"benchbox/mcp/tools/analytics.py:register_analytics_tools", # 22 - MCP registration pattern
# --- Thread-safety (single-flight cache; locking protocol cannot be simplified) ---
"benchbox/core/expected_results/registry.py:_get_benchmark_results", # 17 - single-flight cache with cross-thread coordination
# --- Query plan parsers (AST node dispatch; each operator has distinct properties) ---
"benchbox/core/query_plans/parsers/datafusion.py:_convert_to_logical_operator", # 17 - AST node → LogicalOperator with operator-specific property extraction
"benchbox/core/query_plans/parsers/datafusion.py:_extract_operator_info", # 23 - operator-type dispatch (scan/join/filter/sort/projection/aggregate/limit)
# --- Platform registration (41 independent try/except blocks, one per platform) ---
"benchbox/core/platform_registry.py:auto_register_platforms", # 41 - each platform import is isolated; CC reflects platform count, not algorithmic complexity
# --- Catalog loaders (per-field YAML validation with distinct rules per field) ---
"benchbox/core/ai_primitives/catalog/loader.py:load_ai_catalog", # 29 - field-by-field validation: id, sql, category, variants, skip_on, model, tokens, batch_size, cost
"benchbox/core/write_primitives/catalog/loader.py:load_write_primitives_catalog", # 25 - field-by-field validation: id, category, write_sql, validation_queries, cleanup_sql, flags
# --- Manifest validation (multi-layer validation recently expanded for contamination detection) ---
"benchbox/core/runner/runner.py:_validate_manifest_if_present", # 23 - entry validation + directory collision detection + cloud/local path dispatch
# --- Benchmark test setup (spec-required sequential dependency chain) ---
"benchbox/core/transaction_primitives/benchmark.py:setup", # 17 - spec-required: validation → lock → cleanup → staging population in strict order
# --- Deferred complexity reduction (architectural redesign needed) ---
"benchbox/core/runner/runner.py:run_benchmark_lifecycle", # 39 - main orchestration with genuinely distinct code paths (data_only, load_only, SQL, DataFrame)
"benchbox/cli/orchestrator.py:execute_benchmark", # 24 - interleaved output/phase/adapter/credential logic; tightly coupled to CLI UX
# --- CLI/release (linear workflows with safety-critical branching) ---
"benchbox/cli/commands/compare_plans.py:compare_plans", # 27 - deprecated, slated for removal
"benchbox/cli/commands/export.py:export", # 22 - clean CLI with distinct source resolution paths
"benchbox/release/sync.py:cmd_pull", # 25 — auditable safety-check workflow
"benchbox/release/sync.py:cmd_push", # 22 — mirror of cmd_pull
# --- Interactive shell REPL (user-input dispatch loop is state-machine-inherent) ---
"benchbox/cli/commands/shell.py:_launch_sqlite_shell", # 16 - SQLite REPL; command dispatch + SQL execution loop cannot be flattened
"benchbox/cli/commands/shell.py:_launch_duckdb_shell", # 15 - DuckDB REPL; same pattern as SQLite shell
# --- Converters (linear pipelines with resource cleanup) ---
"benchbox/utils/format_converters/iceberg_converter.py:convert", # 24 - Iceberg conversion pipeline
# --- Required complexity at CC=14 (2026-02-21 evaluation, batch w15) ---
# These sit at CC=14 (below warn=15) but are documented for completeness.
"benchbox/cli/commands/show_plan.py:show_plan", # 14 - 4 except branches + 3-way format dispatch; irreducible for CLI command
"benchbox/cli/commands/tuning_group.py:_display_config_settings_table", # 14 - one guard per config field; proportional to field count
"benchbox/core/query_plans/parsers/base.py:_harmonize_operator_type", # 14 - 12-way keyword→enum mapping; 1:1 with enum members
"benchbox/core/concurrency/analyzer.py:analyze_contention", # 14 - mutually-exclusive classification decision tree
"benchbox/core/metadata_primitives/complexity.py:__post_init__", # 14 - N independent field validation guards; inherent to dataclass
# --- Required complexity at CC=14 (2026-03-12 evaluation) ---
# Inherent complexity: domain-driven branching that cannot be meaningfully reduced.
"benchbox/core/results/builder.py:to_dict", # 14 - conditional serialization of 12 optional fields; each `if` guards one field
"benchbox/platforms/clickhouse_cloud.py:_create_external_tables_via_s3", # 14 - 4-way format dispatch (iceberg/parquet × local/cloud) with distinct S3 semantics
"benchbox/platforms/databricks/adapter.py:get_platform_info", # 14 - independent try/except probes for SDK, runtime, and warehouse metadata
"benchbox/platforms/dataframe/benchmark_mixin.py:run_benchmark", # 14 - orchestration flow: memory check → validation → context → load → execute → result
"benchbox/platforms/redshift.py:apply_table_tunings", # 14 - Redshift DDL constraints require individual DISTSTYLE/DISTKEY/SORTKEY inspection
"benchbox/utils/format_converters/base.py:map_sql_type_to_arrow", # 14 - type dispatch; DECIMAL requires parameter parsing that breaks dict-based approach
"benchbox/utils/input_validation.py:validate_query_id", # 14 - benchmark-specific allowlists with distinct ID format rules per benchmark
"benchbox/utils/stale_artifact_pruning.py:prune_stale_table_artifacts", # 14 - compressed/uncompressed × single/sharded × expected-format; branching reflects real combinations
# --- Required complexity at CC=13 (2026-03-12 evaluation, wave 3) ---
# Inherent complexity: validator/serializer logic, spec orchestration, and platform-specific semantics.
"benchbox/cli/benchmarks.py:prompt_table_format", # 13 - interactive format/compression wizard with dependent prompts
"benchbox/cli/composite_params.py:parse", # 13 - per-key plan-capture parsing with distinct validation rules
"benchbox/cli/config.py:create_sample_unified_tuning_config", # 13 - sample tuning config mirrors real platform capability differences
"benchbox/cli/platform.py:setup_platforms", # 13 - stateful interactive setup wizard with action dispatch
"benchbox/core/dataframe/capabilities.py:check_sufficient_memory", # 13 - GPU/system memory checks and platform recommendations are capability-driven
"benchbox/core/dryrun.py:_extract_queries", # 13 - query extraction dispatch is benchmark/spec driven across SQL and DataFrame modes
"benchbox/core/metadata_primitives/dataframe_operations.py:execute_get_schema", # 13 - per-platform schema APIs are genuinely distinct
"benchbox/core/query_plans/parsers/duckdb.py:_convert_to_logical_operator", # 13 - AST-driven operator dispatch with type-specific property extraction
"benchbox/core/query_plans/parsers/duckdb.py:_harmonize_duckdb_operator", # 13 - 1:1 DuckDB operator mapping to logical enums
"benchbox/core/results/query_plan_models.py:get_structural_signature", # 13 - semantic fingerprint builder conditionally serializes plan fields
"benchbox/core/results/schema.py:validate", # 13 - schema validator applies separate rules per required block
"benchbox/core/results/schema.py:_build_execution_from_context", # 13 - execution serialization merges optional flags with special-case compression/force handling
"benchbox/core/results/schema.py:_build_config_block", # 13 - config serialization needs per-field precedence and compression merge rules
"benchbox/core/results/schema.py:_build_phases_block", # 13 - phase serialization mirrors heterogeneous setup/power/throughput structures
"benchbox/core/schemas.py:to_cli_args", # 13 - CLI reconstruction is proportional to optional flag formatting rules
"benchbox/core/tpc_validation.py:validate", # 13 - validator subclasses apply one rule per completeness/result/schema concern
"benchbox/core/tpcdi/queries.py:resolve_query_order", # 13 - Kahn topological sort with query-only dependency filtering is algorithmic
"benchbox/core/tpcds/generator/streaming.py:_generate_parent_table_chunk_with_children", # 13 - TPC-DS parent/child chunk generation couples subprocess, compression, and manifest updates
"benchbox/core/tpch/generator.py:_run_dbgen_native", # 13 - dbgen orchestration spans streaming/file modes, env setup, and cleanup
"benchbox/core/tpch/maintenance_test.py:_execute_rf2", # 13 - TPC-H RF2 requires ordered deletes, transaction handling, and rollback
"benchbox/core/transaction_primitives/benchmark.py:execute_operation", # 13 - transaction operation lifecycle coordinates setup, validation, cleanup, and warnings
"benchbox/core/tuning/generators/doris.py:generate_tuning_clauses", # 13 - Doris tuning maps distinct tuning types to engine-specific DDL semantics
"benchbox/core/tuning/generators/redshift.py:generate_tuning_clauses", # 13 - Redshift tuning maps sort/dist semantics to engine-specific clauses
"benchbox/core/write_primitives/benchmark.py:setup", # 13 - staging-table setup is a guarded sequence with lock/release guarantees
"benchbox/platforms/azure_synapse.py:load_data", # 13 - load path must juggle benchmark tables, manifest fallback, and blob vs bulk-insert semantics
"benchbox/platforms/base/adapter.py:handle_existing_database", # 13 - safety-critical reuse/recreate decision tree depends on file vs server DB semantics
"benchbox/platforms/base/adapter.py:_execute_combined_test", # 13 - combined TPC flow dispatches benchmark-specific phase orchestration
"benchbox/platforms/base/adapter.py:_execute_tpcds_power_test", # 13 - wraps official TPC-DS power test with warmups, stream handling, and normalization
"benchbox/platforms/base/adapter.py:_execute_tpcds_throughput_test", # 13 - wraps official TPC-DS throughput test with stream/concurrency normalization
"benchbox/platforms/base/spark_execution_mixin.py:_load_data_spark", # 13 - Spark load path branches on format, staging, and Spark-specific writer semantics
"benchbox/platforms/bigquery.py:apply_table_tunings", # 13 - tuning application depends on BigQuery partition/clustering metadata constraints
"benchbox/platforms/clickhouse_cloud.py:_create_external_tables_via_gcs", # 13 - GCS external view creation spans local/cloud Iceberg and Parquet inputs
"benchbox/platforms/databricks/adapter.py:_upload_to_uc_volume", # 13 - UC volume uploads handle local vs manifest sources and Databricks path semantics
"benchbox/platforms/dataframe/polars_maintenance.py:_do_merge", # 13 - Polars MERGE emulation dispatches inserts/updates/deletes by clause semantics
"benchbox/platforms/datafusion.py:_convert_and_register_parquet", # 13 - DataFusion loading coordinates conversion, registration, and schema preservation
"benchbox/platforms/duckdb.py:execute_query", # 13 - DuckDB execution path combines execution, plan capture, and result-shape compatibility
"benchbox/platforms/firebolt.py:_resolve_data_files", # 13 - Firebolt file resolution spans local/cloud/manifest staging variants
"benchbox/platforms/firebolt.py:_load_data_via_insert", # 13 - Firebolt insert loading coordinates staged files, SQL generation, and fallback handling
"benchbox/platforms/influxdb/client.py:to_line_protocol", # 13 - Influx line-protocol encoding branches by tags, fields, types, and escaping rules
"benchbox/platforms/presto.py:get_platform_info", # 13 - platform info comes from independent engine/catalog/session probes
"benchbox/platforms/redshift.py:configure_for_benchmark", # 13 - Redshift session tuning and cache validation are safety-oriented engine semantics
"benchbox/platforms/snowflake.py:get_platform_info", # 13 - platform info is assembled from independent account/runtime probes
"benchbox/platforms/snowflake.py:apply_table_tunings", # 13 - Snowflake tuning compares live clustering state before engine-specific DDL changes
"benchbox/release/content_validation.py:_is_example_line", # 13 — heuristic classifier must combine marker, table, bullet, and blockquote context
"benchbox/utils/execution_manager.py:execute_power_runs", # 13 - power-run orchestration manages warmups, monitoring, fail-fast, and stream permutations
# --- Required complexity at CC=12 (2026-03-12 evaluation, wave 4) ---
# Inherent complexity: sequential workflows, platform/operator dispatch, measurement protocols.
"benchbox/cli/commands/run_official.py:run_official", # 12 - deprecated CLI wrapper with TPC spec validation + argument assembly
"benchbox/cli/commands/convert.py:convert", # 12 - sequential conversion workflow with distinct error handling per step
"benchbox/cli/tuning.py:_run_simple_wizard", # 12 - platform-specific tuning dispatch (Databricks/Snowflake/BigQuery/Redshift)
"benchbox/core/dataframe/benchmark_suite.py:_benchmark_query", # 12 - interleaved measurement protocol (warmup/timing/memory/lazy evaluation)
"benchbox/core/dataframe/benchmark_suite.py:_run_df_query", # 12 - sequential benchmark phases (resolve/load/lookup/warmup/measure)
"benchbox/core/metadata_primitives/benchmark.py:run_dataframe_benchmark", # 12 - schema vs catalog operation dispatch with fundamentally different execution models
"benchbox/core/metadata_primitives/dataframe_operations.py:execute_complex_type_introspection", # 12 - platform-specific type APIs (Polars/Spark/Pandas)
"benchbox/core/query_plans/insights.py:detect_antipatterns", # 12 - semantically distinct antipattern checks (cross-join/conditions/depth/scans)
"benchbox/core/query_plans/parsers/duckdb.py:_parse_json_node", # 12 - operator-specific attribute extraction (scan/filter/join/aggregate/sort)
"benchbox/core/read_primitives/benchmark.py:_load_data", # 12 - sequential data loading with reuse check, schema creation, and per-table file resolution
"benchbox/core/runner/runner.py:_execute_load_only_mode", # 12 - external vs native table mode dispatch with mode-dependent execution paths
"benchbox/core/tpcdi/etl/customer_mgmt_processor.py:parse_file", # 12 - XML action type dispatch (NEW/UPDCUST/ADDACCT/INACT) with namespace resilience
# --- Required complexity at CC=12 (2026-03-12 follow-up, wave 4b) ---
# Inherent complexity: spec workflows, platform-specific loading, runtime resolution, and SQL normalization.
"benchbox/core/tpcds/c_tools.py:_clean_sql", # 12 - TPC-DS SQL normalization handles vendor-specific syntax families with distinct rewrites
"benchbox/core/tpcds/dataframe_queries/rollup_helper.py:expand_rollup_pandas", # 12 - rollup expansion must switch between grouped levels, grand totals, and Dask scalar handling
"benchbox/core/tpcds/generator/streaming.py:_generate_parent_table_with_children", # 12 - streaming generation coordinates subprocess output, compression, manifest updates, and cleanup
"benchbox/core/tpcds_obt/query_conversion.py:_rewrite_columns", # 12 - AST column rewrite must distinguish fact vs dimension mapping and OBT alias semantics
"benchbox/core/tpch/generator.py:_generate_local", # 12 - TPC-H data generation orchestrates validation, sample reuse, regeneration, and streaming/file output modes
"benchbox/core/tpch/maintenance_test.py:run_maintenance_test", # 12 - maintenance test follows the spec-required RF1/RF2 workflow with timed intervals and result accounting
"benchbox/core/tpch/power_test.py:__init__", # 12 - seed/validation initialization reflects TPC-H answer-set rules and stream-specific validation constraints
"benchbox/platforms/adapter_factory.py:get_adapter", # 12 - unified platform factory must validate mode/deployment combinations before dispatch
"benchbox/platforms/base/adapter.py:_create_enhanced_data_generation_phase", # 12 - defensive per-table stats extraction handles arbitrary benchmark table containers
"benchbox/platforms/clickhouse/tuning.py:generate_tuning_clause", # 12 - ClickHouse tuning composes partition/order semantics with engine-specific precedence rules
"benchbox/platforms/databend/adapter.py:_insert_files_batched", # 12 - batch loader interleaves delimiter validation, row escaping, and flush boundaries
"benchbox/platforms/databricks/credentials.py:setup_databricks_credentials", # 12 - interactive credential setup mixes autodetect, secure prompting, validation, and optional defaults
"benchbox/platforms/dataframe/benchmark_mixin.py:_get_tpcds_queries", # 12 - TPC-DS stream permutation and variant fallback are spec-driven and registry-dependent
"benchbox/platforms/datafusion.py:create_connection", # 12 - DataFusion connection setup must branch across runtime APIs, spill config, and session options
"benchbox/platforms/duckdb.py:validate_platform_capabilities", # 12 - capability validator applies independent library/version/memory checks with structured warnings
"benchbox/platforms/fabric_warehouse.py:load_data", # 12 - Fabric loading coordinates table discovery, OneLake COPY, direct fallback, and platform-specific errors
"benchbox/platforms/firebolt.py:_load_data_via_s3", # 12 - Firebolt S3 staging combines upload, credential resolution, ingest SQL, and per-file accounting
"benchbox/platforms/postgresql.py:validate_platform_capabilities", # 12 - capability validator applies independent driver/version/memory checks with structured warnings
"benchbox/platforms/redshift.py:__init__", # 12 - Redshift initialization validates dependencies, staging config, and connection defaults in one workflow
"benchbox/platforms/starburst.py:_configure_starburst_defaults", # 12 - Galaxy config must merge env defaults, role-qualified usernames, and required-auth validation
"benchbox/utils/format_converters/delta_converter.py:convert", # 12 - Delta conversion pipeline validates schema, reads shards, writes table metadata, and reports progress
"benchbox/utils/format_converters/vortex_converter.py:convert", # 12 - Vortex conversion pipeline validates schema, writes output, validates row counts, and cleans partial files
"benchbox/utils/runtime_env.py:discover_isolated_runtime", # 12 - isolated runtime discovery scans filesystem candidates, site-packages, and ABI compatibility
"benchbox/utils/runtime_env.py:ensure_driver_version", # 12 - driver resolution workflow must check current env, isolated runtimes, and optional auto-install fallbacks
]
[tool.benchbox.duplicates]
# Duplicate code detection configuration (scripts/check_duplicate_code.py).
# Uses AST structural hashing to find Type-2 clones (same structure, different
# identifiers). The threshold is a ceiling on total duplicated lines; raise it
# only when intentional duplication is added and lower it as clones are removed.
#
# Re-baseline protocol: when `make duplicate-check-verbose` reports actual
# duplicated lines consistently above the threshold, re-run the classification
# triage (see _project/DONE/core-functionality/active/
# duplicate-code-followup-triage-centralization.yaml for methodology) and set
# threshold = ceil(actual * 1.10). Last re-baseline: 2026-03-12, 7,339 actual.
source_root = "benchbox"
min_lines = 10 # minimum function body size to analyse
threshold = 8073 # max duplicated lines before the check fails
exclude_patterns = [
"tests/", # test files often have intentional boilerplate
"__pycache__",
]
ignore_function_names = [
# Structural clone patterns that differ by benchmark domain content
"_load_queries",
"_generate_default_params",
# Facade chains / thin delegations
"get_all_variants",
# G5: dataclass-to-dict conversion methods on distinct config/artifact classes
"to_dict",
"get_etl_config",
"get_performance_config",
]
ignore_rules = [
# Platform adapter interface boilerplate - intentionally repeated per-adapter.
# Lists explicit adapter files (excludes benchbox/platforms/base/ utilities).
{ function_names = ["from_config", "apply_constraint_configuration", "apply_unified_tuning", "supports_tuning_type", "apply_tuning_configuration"], path_contains = [
"benchbox/platforms/athena.py", "benchbox/platforms/azure_synapse.py",
"benchbox/platforms/bigquery.py", "benchbox/platforms/clickhouse_cloud.py",
"benchbox/platforms/cudf.py", "benchbox/platforms/datafusion.py",
"benchbox/platforms/doris.py", "benchbox/platforms/duckdb.py",
"benchbox/platforms/fabric_lakehouse.py", "benchbox/platforms/fabric_warehouse.py",
"benchbox/platforms/firebolt.py", "benchbox/platforms/lakesail.py",
"benchbox/platforms/motherduck.py", "benchbox/platforms/pg_duckdb.py",
"benchbox/platforms/pg_mooncake.py", "benchbox/platforms/polars_platform.py",
"benchbox/platforms/postgresql.py", "benchbox/platforms/presto.py",
"benchbox/platforms/questdb.py", "benchbox/platforms/redshift.py",
"benchbox/platforms/snowflake.py", "benchbox/platforms/spark.py",
"benchbox/platforms/sqlite.py", "benchbox/platforms/starburst.py",
"benchbox/platforms/timescaledb.py", "benchbox/platforms/trino.py",
"benchbox/platforms/snowpark_connect.py",
"benchbox/platforms/aws/athena_spark_adapter.py",
"benchbox/platforms/aws/emr_serverless_adapter.py",
"benchbox/platforms/aws/glue_adapter.py",
"benchbox/platforms/azure/fabric_spark_adapter.py",
"benchbox/platforms/azure/synapse_spark_adapter.py",
"benchbox/platforms/gcp/dataproc_adapter.py",
"benchbox/platforms/gcp/dataproc_serverless_adapter.py",
"benchbox/platforms/databricks/adapter.py",
"benchbox/platforms/databricks/dataframe_adapter.py",
"benchbox/platforms/databend/adapter.py",
"benchbox/platforms/influxdb/adapter.py",
"benchbox/platforms/onehouse/quanton_adapter.py",
"benchbox/platforms/clickhouse/tuning.py",
"benchbox/platforms/clickhouse/metadata.py",
"benchbox/platforms/starrocks/tuning.py",
"benchbox/platforms/starrocks/metadata.py",
"benchbox/platforms/influxdb/metadata.py",
"benchbox/platforms/dataframe/pandas_df.py",
"benchbox/platforms/dataframe/polars_df.py",
"benchbox/platforms/dataframe/datafusion_df.py",
"benchbox/platforms/dataframe/cudf_df.py",
"benchbox/platforms/dataframe/modin_df.py",
"benchbox/platforms/dataframe/dask_df.py",
"benchbox/platforms/dataframe/pyspark_df.py",
] },
# DataFrame adapter/protocol casting boilerplate
# G26: extend to cover context.py (where cast_date/cast_string actually live as protocol stubs)
{ function_names = ["cast_date", "cast_string"], path_contains = ["benchbox/platforms/dataframe/", "benchbox/core/dataframe/protocols.py", "benchbox/core/dataframe/context.py"] },
# UnifiedFrame per-operation wrappers are intentional API surface methods
{ function_names = ["__call__", "count", "cum_sum", "cum_max", "cum_min", "cum_prod"], path_contains = ["benchbox/platforms/dataframe/unified_frame.py"] },
# Protocol method signatures are intentionally repeated contracts
{ function_names = ["agg", "group_by", "first", "max", "min", "mean", "sum"], path_contains = ["benchbox/core/dataframe/protocols.py"] },
# Top-level benchmark facade wrappers are intentional public API surface
# w3-G8: extend with generate_data, get_all_aliases, get_benchmark_info and platform_registry
{ function_names = ["get_query", "get_queries", "get_create_tables_sql", "generate_data", "get_all_aliases", "get_benchmark_info"], path_contains = [
"benchbox/amplab.py", "benchbox/clickbench.py", "benchbox/coffeeshop.py",
"benchbox/datavault.py", "benchbox/h2odb.py", "benchbox/joinorder.py",
"benchbox/metadata_primitives.py", "benchbox/nyctaxi.py", "benchbox/read_primitives.py",
"benchbox/ssb.py", "benchbox/tpcdi.py", "benchbox/tpcds.py", "benchbox/tpcds_obt.py",
"benchbox/tpch.py", "benchbox/tpch_skew.py", "benchbox/tpchavoc.py",
"benchbox/transaction_primitives.py", "benchbox/tsbs_devops.py",
"benchbox/write_primitives.py",
"benchbox/core/platform_registry.py",
] },
# Cloud/Spark adapter platform-info accessors are intentionally provider-specific
{ function_names = ["get_platform_info"], path_contains = [
"benchbox/platforms/aws/athena_spark_adapter.py",
"benchbox/platforms/aws/emr_serverless_adapter.py",
"benchbox/platforms/aws/glue_adapter.py",
"benchbox/platforms/azure/fabric_spark_adapter.py",
"benchbox/platforms/azure/synapse_spark_adapter.py",
"benchbox/platforms/gcp/dataproc_adapter.py",
"benchbox/platforms/gcp/dataproc_serverless_adapter.py",
"benchbox/platforms/databricks/adapter.py",
"benchbox/platforms/databricks/dataframe_adapter.py",
"benchbox/platforms/onehouse/quanton_adapter.py",
"benchbox/platforms/snowpark_connect.py",
] },
# CLI tuning defaults display commands are intentionally duplicated UX pathways
{ function_names = ["show_defaults"], path_contains = ["benchbox/cli/commands/df_tuning.py", "benchbox/cli/commands/tuning_group.py"] },
# --- Boilerplate ignore rules added 2026-02-21 (groups G1-G28 from duplicate-check triage) ---
# G8,G9,G11,G22: Protocol/ABC abstract method stubs across dataframe type hierarchy
# G17: window function protocol stubs in context.py
{ function_names = ["col", "filter", "limit", "scalar_to_df", "can_provide", "create_schema", "date_add", "date_sub", "get_table", "table_exists", "lit", "list_tables", "concat", "cast_timestamp", "when", "window_dense_rank", "window_rank", "window_row_number"], path_contains = [
"benchbox/core/dataframe/context.py",
"benchbox/core/dataframe/protocols.py",
"benchbox/core/operations/base.py",
"benchbox/core/tpcdi/etl/sources.py",
"benchbox/platforms/base/adapter.py",
"benchbox/platforms/base/data_loading.py",
"benchbox/utils/format_converters/base.py",
] },
{ function_names = ["_do_delete", "delete_rows", "generate_tuning_clauses"], path_contains = [
"benchbox/core/dataframe/maintenance_interface.py",
"benchbox/core/tuning/ddl_generator.py",
"benchbox/platforms/dataframe/expression_family.py",
] },
# G3,G10: DataFrame platform adapter thin wrappers (col/lit/from_pandas/detect_format/read_*)