rushti 2.3.1__tar.gz → 2.3.2__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.
Files changed (62) hide show
  1. {rushti-2.3.1/src/rushti.egg-info → rushti-2.3.2}/PKG-INFO +1 -1
  2. {rushti-2.3.1 → rushti-2.3.2}/pyproject.toml +1 -1
  3. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/__init__.py +1 -1
  4. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/tm1_objects.py +87 -11
  5. {rushti-2.3.1 → rushti-2.3.2/src/rushti.egg-info}/PKG-INFO +1 -1
  6. {rushti-2.3.1 → rushti-2.3.2}/LICENSE +0 -0
  7. {rushti-2.3.1 → rushti-2.3.2}/README.md +0 -0
  8. {rushti-2.3.1 → rushti-2.3.2}/setup.cfg +0 -0
  9. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/_shlex_utils.py +0 -0
  10. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/app_paths.py +0 -0
  11. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/checkpoint.py +0 -0
  12. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/cli.py +0 -0
  13. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/commands/__init__.py +0 -0
  14. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/commands/build.py +0 -0
  15. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/commands/db.py +0 -0
  16. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/commands/resume.py +0 -0
  17. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/commands/stats/__init__.py +0 -0
  18. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/commands/stats/analyze.py +0 -0
  19. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/commands/stats/export.py +0 -0
  20. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/commands/stats/list.py +0 -0
  21. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/commands/stats/optimize.py +0 -0
  22. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/commands/stats/visualize.py +0 -0
  23. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/commands/tasks/__init__.py +0 -0
  24. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/commands/tasks/expand.py +0 -0
  25. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/commands/tasks/export.py +0 -0
  26. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/commands/tasks/push.py +0 -0
  27. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/commands/tasks/validate.py +0 -0
  28. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/commands/tasks/visualize.py +0 -0
  29. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/contention_analyzer.py +0 -0
  30. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/dag.py +0 -0
  31. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/dashboard.py +0 -0
  32. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/db_admin.py +0 -0
  33. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/exclusive.py +0 -0
  34. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/execution.py +0 -0
  35. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/logging.py +0 -0
  36. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/logging_setup.py +0 -0
  37. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/messages.py +0 -0
  38. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/optimization_report.py +0 -0
  39. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/optimizer.py +0 -0
  40. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/parsing.py +0 -0
  41. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/results_writer.py +0 -0
  42. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/settings.py +0 -0
  43. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/stats/__init__.py +0 -0
  44. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/stats/dynamodb.py +0 -0
  45. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/stats/paths.py +0 -0
  46. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/stats/repository.py +0 -0
  47. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/stats/signature.py +0 -0
  48. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/stats/sqlite.py +0 -0
  49. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/task.py +0 -0
  50. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/taskfile.py +0 -0
  51. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/taskfile_ops.py +0 -0
  52. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/templates/__init__.py +0 -0
  53. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/templates/visualization.html +0 -0
  54. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/tm1_build.py +0 -0
  55. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/tm1_integration.py +0 -0
  56. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/utils.py +0 -0
  57. {rushti-2.3.1 → rushti-2.3.2}/src/rushti/visualization_template.py +0 -0
  58. {rushti-2.3.1 → rushti-2.3.2}/src/rushti.egg-info/SOURCES.txt +0 -0
  59. {rushti-2.3.1 → rushti-2.3.2}/src/rushti.egg-info/dependency_links.txt +0 -0
  60. {rushti-2.3.1 → rushti-2.3.2}/src/rushti.egg-info/entry_points.txt +0 -0
  61. {rushti-2.3.1 → rushti-2.3.2}/src/rushti.egg-info/requires.txt +0 -0
  62. {rushti-2.3.1 → rushti-2.3.2}/src/rushti.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rushti
3
- Version: 2.3.1
3
+ Version: 2.3.2
4
4
  Summary: RushTI - Parallel TM1 TurboIntegrator Process Execution
5
5
  Author-email: nicolasbisurgi <nbisurgi@cubewise.com>, Marius Wirtz <mwirtz@cubewise.com>
6
6
  Maintainer: Cubewise CODE
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "rushti"
7
- version = "2.3.1"
7
+ version = "2.3.2"
8
8
  description = "RushTI - Parallel TM1 TurboIntegrator Process Execution"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -5,7 +5,7 @@ This package provides tools for executing TM1 TI processes in parallel
5
5
  with dependency management, checkpoint/resume support, and execution logging.
6
6
  """
7
7
 
8
- __version__ = "2.3.1"
8
+ __version__ = "2.3.2"
9
9
  __app_name__ = "RushTI"
10
10
 
11
11
  # Core exports for programmatic use
@@ -150,6 +150,8 @@ nProcessReturnCode = 0;
150
150
  nErrors = 0;
151
151
  nMetadataRecordCount= 0;
152
152
  nDataRecordCount = 0;
153
+ nHeaderChecked = 0;
154
+ nDataHeaderChecked = 0;
153
155
 
154
156
  ### Process Specific Constants
155
157
  cFileSrc = pSourceFile;
@@ -220,7 +222,9 @@ CubeSetLogChanges( cCubeTgt, 0 );
220
222
  If( nErrors = 0 );
221
223
  DatasourceType = 'CHARACTERDELIMITED';
222
224
  DatasourceNameForServer = cFileSrc;
223
- DatasourceASCIIHeaderRecords = 1;
225
+ # 0 (not 1): the header row is consumed as the first record so the
226
+ # metadata tab can validate it against the expected columns (issue #169).
227
+ DatasourceASCIIHeaderRecords = 0;
224
228
  DatasourceASCIIDelimiter=',';
225
229
  DatasourceASCIIDecimalSeparator='.';
226
230
  DatasourceASCIIThousandSeparator='';
@@ -290,6 +294,8 @@ nProcessReturnCode = 0;
290
294
  nErrors = 0;
291
295
  nMetadataRecordCount= 0;
292
296
  nDataRecordCount = 0;
297
+ nHeaderChecked = 0;
298
+ nDataHeaderChecked = 0;
293
299
 
294
300
  ### Process Specific Constants
295
301
  cFileSrc = pSourceFile;
@@ -356,7 +362,9 @@ EndIf;
356
362
  If( nErrors = 0 );
357
363
  DatasourceType = 'CHARACTERDELIMITED';
358
364
  DatasourceNameForServer = cFileSrc;
359
- DatasourceASCIIHeaderRecords = 1;
365
+ # 0 (not 1): the header row is consumed as the first record so the
366
+ # metadata tab can validate it against the expected columns (issue #169).
367
+ DatasourceASCIIHeaderRecords = 0;
360
368
  DatasourceASCIIDelimiter=',';
361
369
  DatasourceASCIIDecimalSeparator='.';
362
370
  DatasourceASCIIThousandSeparator='';
@@ -366,10 +374,17 @@ EndIf;
366
374
  #################################################################################################
367
375
  """
368
376
 
369
- PROCESS_METADATA = r"""#****Begin: Generated Statements***
377
+ # Marker pair TM1 Architect uses to inject auto-generated variable/parameter
378
+ # code at the top of a tab. Kept as the first lines of every generated
379
+ # procedure so the process round-trips cleanly if later opened in Architect.
380
+ _GENERATED_STATEMENTS_MARKER = """#****Begin: Generated Statements***
370
381
  #****End: Generated Statements****
382
+ """
371
383
 
372
- If( pLogOutput >= 1 );
384
+ # Body of the metadata tab. The header-validation preamble is generated from
385
+ # PROCESS_VARIABLES and prepended in ``build_metadata_procedure`` so it stays
386
+ # in lockstep with the CSV column contract (see issue #169).
387
+ _PROCESS_METADATA_BODY = r"""If( pLogOutput >= 1 );
373
388
  nMetadataRecordCount = nMetadataRecordCount + 1;
374
389
  EndIf;
375
390
 
@@ -388,10 +403,9 @@ if (DimensionElementExists(pRunId_Dim, vrun_id) = 0);
388
403
  DimensionElementInsertDirect(pRunId_Dim, '', vrun_id, 'N');
389
404
  endif;"""
390
405
 
391
- PROCESS_DATA = r"""#****Begin: Generated Statements***
392
- #****End: Generated Statements****
393
-
394
- If( pLogOutput >= 1 );
406
+ # Body of the data tab. The header-skip preamble is prepended in
407
+ # ``build_data_procedure`` so the CSV header row is not written to the cube.
408
+ _PROCESS_DATA_BODY = r"""If( pLogOutput >= 1 );
395
409
  nDataRecordCount = nDataRecordCount + 1;
396
410
  EndIf;
397
411
 
@@ -544,8 +558,9 @@ PROCESS_PARAMETERS = [
544
558
  # declaration list. Must match the column order produced by
545
559
  # ``rushti.tm1_integration.upload_results_to_tm1`` (which inserts
546
560
  # ``workflow`` and ``run_id`` ahead of the columns built by
547
- # ``build_results_dataframe``). Mismatched ordering silently scrambles
548
- # the loaded payload.
561
+ # ``build_results_dataframe``). Mismatched ordering scrambles the loaded
562
+ # payload; the metadata-tab header check generated from this list turns a
563
+ # stale-process mismatch into a hard error instead (see issue #169).
549
564
  PROCESS_VARIABLES = [
550
565
  "vworkflow",
551
566
  "vrun_id",
@@ -571,12 +586,73 @@ PROCESS_VARIABLES = [
571
586
  "vsucceed_on_minor_errors",
572
587
  ]
573
588
 
589
+
590
+ def build_metadata_procedure() -> str:
591
+ """Assemble the ``}rushti.load.results`` metadata tab.
592
+
593
+ Prepends a header-validation preamble generated from ``PROCESS_VARIABLES``
594
+ so it stays in lockstep with the CSV column contract. The loader maps CSV
595
+ columns to variables positionally; with ``asciiHeaderRecords=0`` the CSV
596
+ header row is the first source record, so validating each column name
597
+ against the variable it feeds makes a process left stale by an in-place
598
+ rushti upgrade fail loudly instead of silently writing values to the wrong
599
+ measures (issue #169). Re-run ``rushti build`` to refresh a stale process.
600
+ """
601
+ checks = "\n".join(
602
+ f" If( {var} @<> '{var[1:]}' );\n"
603
+ f" sHeaderError = sHeaderError | ' {var[1:]}';\n"
604
+ f" EndIf;"
605
+ for var in PROCESS_VARIABLES
606
+ )
607
+ preamble = f"""### Validate the CSV header against the columns this process expects.
608
+ ### The loader maps columns to variables positionally, so a process built by
609
+ ### an older rushti scrambles measures (issue #169). Fail loudly on mismatch
610
+ ### and skip the header so it is not loaded as data.
611
+ If( nHeaderChecked = 0 );
612
+ nHeaderChecked = 1;
613
+ sHeaderError = '';
614
+ {checks}
615
+ If( Trim( sHeaderError ) @<> '' );
616
+ nErrors = nErrors + 1;
617
+ sMessage = Expand( 'Results CSV header does not match the columns }}rushti.load.results expects (mismatched:%sHeaderError% ). This process is out of date with the rushti version that produced the file - re-run: rushti build --tm1-instance <instance>.' );
618
+ LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );
619
+ ProcessQuit;
620
+ EndIf;
621
+ ItemSkip;
622
+ EndIf;
623
+
624
+ """
625
+ return _GENERATED_STATEMENTS_MARKER + "\n" + preamble + _PROCESS_METADATA_BODY
626
+
627
+
628
+ def build_data_procedure() -> str:
629
+ """Assemble the ``}rushti.load.results`` data tab.
630
+
631
+ Skips the CSV header row (validated in the metadata tab) so it is not
632
+ written to the cube, then delegates to the static body. See issue #169.
633
+ """
634
+ preamble = """### Skip the CSV header row (asciiHeaderRecords=0; validated in the
635
+ ### metadata tab). See issue #169.
636
+ If( nDataHeaderChecked = 0 );
637
+ nDataHeaderChecked = 1;
638
+ ItemSkip;
639
+ EndIf;
640
+
641
+ """
642
+ return _GENERATED_STATEMENTS_MARKER + "\n" + preamble + _PROCESS_DATA_BODY
643
+
644
+
645
+ PROCESS_METADATA = build_metadata_procedure()
646
+ PROCESS_DATA = build_data_procedure()
647
+
574
648
  PROCESS_DATASOURCE = {
575
649
  "Type": "ASCII",
576
650
  "asciiDecimalSeparator": ".",
577
651
  "asciiDelimiterChar": ",",
578
652
  "asciiDelimiterType": "Character",
579
- "asciiHeaderRecords": 1,
653
+ # 0: the header row is validated (not skipped) by the metadata tab; see
654
+ # the DatasourceASCIIHeaderRecords note in the prolog and issue #169.
655
+ "asciiHeaderRecords": 0,
580
656
  "asciiQuoteCharacter": '"',
581
657
  "asciiThousandSeparator": ",",
582
658
  "dataSourceNameForClient": "",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rushti
3
- Version: 2.3.1
3
+ Version: 2.3.2
4
4
  Summary: RushTI - Parallel TM1 TurboIntegrator Process Execution
5
5
  Author-email: nicolasbisurgi <nbisurgi@cubewise.com>, Marius Wirtz <mwirtz@cubewise.com>
6
6
  Maintainer: Cubewise CODE
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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes