@@ -27,6 +27,16 @@ export type CatalogueExpectation =
2727 kind : 'table-rows' ;
2828 value : readonly object [ ] ;
2929 pandasMetadataIncludes ?: readonly string [ ] ;
30+ pandasMetadataAbsent ?: boolean ;
31+ pandasIndexColumns ?: readonly unknown [ ] ;
32+ fields ?: readonly {
33+ name : string ;
34+ type : string ;
35+ nullCount ?: number ;
36+ validity ?: readonly boolean [ ] ;
37+ dictionaryValues ?: readonly unknown [ ] ;
38+ dictionaryOrdered ?: boolean ;
39+ } [ ] ;
3040 } ;
3141
3242export interface CatalogueRow {
@@ -422,17 +432,59 @@ export const RUNTIME_CATALOGUE: readonly CatalogueRow[] = [
422432 kind : 'table-rows' ,
423433 value : [ { value : 1n } , { value : null } ] ,
424434 pandasMetadataIncludes : [ '"numpy_type": "Int64"' ] ,
435+ pandasIndexColumns : [ { kind : 'range' , name : null , start : 0 , stop : 2 , step : 1 } ] ,
436+ fields : [ { name : 'value' , type : 'Int64' , nullCount : 1 , validity : [ true , false ] } ] ,
425437 } ,
426438 } ) ,
427439 libraryRow ( {
428440 id : 'pandas-nullable-int64-json' ,
429441 call : 'pandas_nullable_int64()' ,
430442 codec : 'json' ,
431443 requires : [ 'pandas' ] ,
432- status : 'KNOWN_LIE' ,
433- currentBehavior : 'JSON preserves values but drops the nullable integer dtype.' ,
444+ status : 'EXPECTED_OK' ,
445+ currentBehavior :
446+ 'Values-only JSON preserves nullable integer values and normalizes pd.NA to null.' ,
434447 expected : equal ( [ { value : 1 } , { value : null } ] ) ,
435448 } ) ,
449+ libraryRow ( {
450+ id : 'pandas-series-arrow-current-truth' ,
451+ call : 'pandas_named_series()' ,
452+ codec : 'arrow' ,
453+ requires : [ 'pandas' , 'pyarrow' ] ,
454+ status : 'KNOWN_LIE' ,
455+ currentBehavior :
456+ 'Series Arrow output is table-like: values survive, while its name and RangeIndex metadata do not.' ,
457+ expected : {
458+ kind : 'table-rows' ,
459+ value : [ { value : 1n } , { value : null } ] ,
460+ pandasMetadataAbsent : true ,
461+ fields : [ { name : 'value' , type : 'Int64' , nullCount : 1 , validity : [ true , false ] } ] ,
462+ } ,
463+ expectedFix : 'Preserve the Series name and RangeIndex metadata through Arrow decoding.' ,
464+ } ) ,
465+ libraryRow ( {
466+ id : 'pandas-nullable-boolean-arrow' ,
467+ call : 'pandas_nullable_boolean()' ,
468+ codec : 'arrow' ,
469+ requires : [ 'pandas' , 'pyarrow' ] ,
470+ status : 'EXPECTED_OK' ,
471+ currentBehavior : 'Arrow preserves nullable boolean values and their null bitmap.' ,
472+ expected : {
473+ kind : 'table-rows' ,
474+ value : [ { value : true } , { value : null } , { value : false } ] ,
475+ pandasMetadataIncludes : [ '"numpy_type": "boolean"' ] ,
476+ fields : [ { name : 'value' , type : 'Bool' , nullCount : 1 , validity : [ true , false , true ] } ] ,
477+ } ,
478+ } ) ,
479+ libraryRow ( {
480+ id : 'pandas-nullable-boolean-json' ,
481+ call : 'pandas_nullable_boolean()' ,
482+ codec : 'json' ,
483+ requires : [ 'pandas' ] ,
484+ status : 'EXPECTED_OK' ,
485+ currentBehavior : 'Values-only JSON preserves booleans and normalizes pd.NA to null.' ,
486+ expected : equal ( [ { value : true } , { value : null } , { value : false } ] ) ,
487+ } ) ,
436488 libraryRow ( {
437489 id : 'pandas-categorical-arrow' ,
438490 call : 'pandas_categorical()' ,
@@ -443,17 +495,28 @@ export const RUNTIME_CATALOGUE: readonly CatalogueRow[] = [
443495 expected : {
444496 kind : 'table-rows' ,
445497 value : [ { value : 'a' } , { value : 'b' } , { value : 'a' } ] ,
446- pandasMetadataIncludes : [ '"pandas_type": "categorical"' ] ,
498+ pandasMetadataIncludes : [
499+ '"pandas_type": "categorical"' ,
500+ '"num_categories": 3, "ordered": true' ,
501+ ] ,
502+ fields : [
503+ {
504+ name : 'value' ,
505+ type : 'Dictionary<Int8, LargeUtf8>' ,
506+ dictionaryValues : [ 'unused' , 'b' , 'a' ] ,
507+ dictionaryOrdered : true ,
508+ } ,
509+ ] ,
447510 } ,
448511 } ) ,
449512 libraryRow ( {
450513 id : 'pandas-categorical-json' ,
451514 call : 'pandas_categorical()' ,
452515 codec : 'json' ,
453516 requires : [ 'pandas' ] ,
454- status : 'KNOWN_LIE ' ,
455- currentBehavior : 'JSON preserves values but drops categorical dtype information .' ,
456- expected : equal ( [ { value : 'a' } , { value : 'b' } , { value : 'a' } ] ) ,
517+ status : 'LOUD_FAIL ' ,
518+ currentBehavior : 'JSON rejects categorical dtype instead of dropping its vocabulary and order .' ,
519+ expected : error ( / c a t e g o r i c a l d t y p e . * A r r o w . * a s t y p e \( s t r \) / i ) ,
457520 } ) ,
458521 libraryRow ( {
459522 id : 'pandas-pyarrow-string-arrow' ,
@@ -467,6 +530,7 @@ export const RUNTIME_CATALOGUE: readonly CatalogueRow[] = [
467530 kind : 'table-rows' ,
468531 value : [ { value : 'a' } , { value : null } ] ,
469532 pandasMetadataIncludes : [ '"numpy_type": "string"' ] ,
533+ fields : [ { name : 'value' , type : 'LargeUtf8' , nullCount : 1 , validity : [ true , false ] } ] ,
470534 } ,
471535 } ) ,
472536 libraryRow ( {
@@ -475,8 +539,8 @@ export const RUNTIME_CATALOGUE: readonly CatalogueRow[] = [
475539 codec : 'json' ,
476540 requires : [ 'pandas' , 'pyarrow' ] ,
477541 featureProbe : 'import pandas as pd; pd.Series(["a"], dtype="string[pyarrow]"); print("1")' ,
478- status : 'KNOWN_LIE ' ,
479- currentBehavior : 'JSON preserves values but drops the Arrow-backed string dtype .' ,
542+ status : 'EXPECTED_OK ' ,
543+ currentBehavior : 'Values-only JSON preserves strings and normalizes pd.NA to null .' ,
480544 expected : equal ( [ { value : 'a' } , { value : null } ] ) ,
481545 } ) ,
482546 libraryRow ( {
@@ -490,16 +554,18 @@ export const RUNTIME_CATALOGUE: readonly CatalogueRow[] = [
490554 kind : 'table-rows' ,
491555 value : [ { when : 1704164645000 } ] ,
492556 pandasMetadataIncludes : [ '"timezone": "UTC"' ] ,
557+ fields : [ { name : 'when' , type : 'Timestamp<MICROSECOND, UTC>' } ] ,
493558 } ,
494559 } ) ,
495560 libraryRow ( {
496561 id : 'pandas-timezone-json' ,
497562 call : 'pandas_timezone_aware()' ,
498563 codec : 'json' ,
499564 requires : [ 'pandas' ] ,
500- status : 'KNOWN_LIE' ,
501- currentBehavior : 'JSON delivers an ISO string but loses timestamp dtype and timezone schema.' ,
502- expected : equal ( [ { when : '2024-01-02T03:04:05+00:00' } ] ) ,
565+ status : 'LOUD_FAIL' ,
566+ currentBehavior :
567+ 'JSON rejects timezone-aware Timestamp cells instead of dropping their dtype schema.' ,
568+ expected : error ( / v a l u e o f t y p e T i m e s t a m p .* A r r o w .* a s t y p e \( s t r \) / i) ,
503569 } ) ,
504570 libraryRow ( {
505571 id : 'pandas-multiindex-arrow' ,
@@ -519,9 +585,9 @@ export const RUNTIME_CATALOGUE: readonly CatalogueRow[] = [
519585 call : 'pandas_multiindex()' ,
520586 codec : 'json' ,
521587 requires : [ 'pandas' ] ,
522- status : 'KNOWN_LIE ' ,
523- currentBehavior : 'Records-oriented JSON drops the MultiIndex.' ,
524- expected : equal ( [ { value : 3 } ] ) ,
588+ status : 'LOUD_FAIL ' ,
589+ currentBehavior : 'JSON rejects MultiIndex instead of silently dropping its levels .' ,
590+ expected : error ( / M u l t i I n d e x . * A r r o w . * r e s e t _ i n d e x \( \) / i ) ,
525591 } ) ,
526592 libraryRow ( {
527593 id : 'pandas-duplicate-labels-arrow' ,
@@ -537,9 +603,10 @@ export const RUNTIME_CATALOGUE: readonly CatalogueRow[] = [
537603 call : 'pandas_duplicate_labels()' ,
538604 codec : 'json' ,
539605 requires : [ 'pandas' ] ,
540- status : 'KNOWN_LIE' ,
541- currentBehavior : 'Records-oriented JSON silently retains only the last duplicate label.' ,
542- expected : equal ( [ { value : 2 } ] ) ,
606+ status : 'LOUD_FAIL' ,
607+ currentBehavior :
608+ 'JSON rejects duplicate column labels instead of silently retaining the last value.' ,
609+ expected : error ( / c o l u m n l a b e l s .* u n i q u e a f t e r J S O N o b j e c t - k e y c o e r c i o n .* a s t y p e \( s t r \) / i) ,
543610 } ) ,
544611 libraryRow ( {
545612 id : 'pandas-empty-frame' ,
@@ -559,8 +626,8 @@ export const RUNTIME_CATALOGUE: readonly CatalogueRow[] = [
559626 call : 'pandas_empty_frame()' ,
560627 codec : 'json' ,
561628 requires : [ 'pandas' ] ,
562- status : 'KNOWN_LIE ' ,
563- currentBehavior : 'Records-oriented JSON loses the empty DataFrame schema .' ,
629+ status : 'EXPECTED_OK ' ,
630+ currentBehavior : 'The documented values-only JSON case permits an empty DataFrame.' ,
564631 expected : equal ( [ ] ) ,
565632 } ) ,
566633 libraryRow ( {
0 commit comments