iparq 0.2.0__tar.gz → 0.2.6__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.
@@ -27,7 +27,7 @@ jobs:
27
27
  strategy:
28
28
  fail-fast: false
29
29
  matrix:
30
- os: ["ubuntu-20.04", "windows-latest"]
30
+ os: ["ubuntu-latest", "windows-latest"]
31
31
  python_version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
32
32
  env:
33
33
  UV_SYSTEM_PYTHON: 1
@@ -56,5 +56,5 @@ jobs:
56
56
  run: uvx black . --check --verbose
57
57
  - name: Run Python tests
58
58
  if: runner.os != 'Windows'
59
- run: uv run pytest -s -vv
59
+ run: uv run pytest -vv
60
60
 
@@ -0,0 +1,50 @@
1
+ # This workflow will install Python dependencies, run tests and lint with a variety of Python versions
2
+ # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
3
+
4
+ name: Python package
5
+ on:
6
+ push:
7
+ branches: [ "main" ]
8
+ pull_request:
9
+ branches: [ "main" ]
10
+
11
+ jobs:
12
+ build:
13
+ permissions:
14
+ contents: read
15
+ pull-requests: write
16
+ name: Test ${{ matrix.os }} Python ${{ matrix.python_version }}
17
+ runs-on: ${{ matrix.os }}
18
+ strategy:
19
+ fail-fast: false
20
+ matrix:
21
+ os: ["ubuntu-latest", "windows-latest"]
22
+ python_version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
23
+ env:
24
+ UV_SYSTEM_PYTHON: 1
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+ - name: Setup python
28
+ uses: actions/setup-python@v5
29
+ with:
30
+ python-version: ${{ matrix.python_version }}
31
+ architecture: x64
32
+ - name: Install uv
33
+ uses: astral-sh/setup-uv@v5
34
+
35
+ # dependencies are in uv.lock
36
+ - name: Install dependencies
37
+ run: |
38
+ uv sync --all-extras
39
+
40
+ - name: Lint with ruff
41
+ run: uv run ruff check .
42
+ - name: Check types with mypy
43
+ run: |
44
+ cd src/iparq
45
+ uv run mypy . --config-file=../../pyproject.toml
46
+ - name: Check formatting with black
47
+ run: uvx black . --check --verbose
48
+ - name: Run Python tests
49
+ if: runner.os != 'Windows'
50
+ run: uv run pytest -vv
@@ -15,11 +15,71 @@ permissions:
15
15
  contents: read
16
16
 
17
17
  jobs:
18
+ test-and-validate:
19
+ permissions:
20
+ contents: read
21
+ pull-requests: write
22
+ runs-on: ubuntu-latest
23
+
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+
27
+ - name: Install uv
28
+ uses: astral-sh/setup-uv@v5
29
+
30
+ - name: "Set up Python"
31
+ uses: actions/setup-python@v5
32
+ with:
33
+ python-version-file: "pyproject.toml"
34
+
35
+ - name: Update dependencies and sync
36
+ run: |
37
+ uv lock --upgrade
38
+ uv sync --all-extras
39
+
40
+ - name: Run linting
41
+ run: |
42
+ uv run ruff check .
43
+
44
+ - name: Run type checking
45
+ run: |
46
+ cd src/iparq
47
+ uv run mypy . --config-file=../../pyproject.toml
48
+
49
+ - name: Run tests
50
+ run: |
51
+ uv run pytest -v
52
+
53
+ - name: Test package build
54
+ run: |
55
+ uv build
56
+
57
+ - name: Test package installation in clean environment
58
+ run: |
59
+ # Test that the built package can be installed and imported
60
+ python -m venv test_install_env
61
+ source test_install_env/bin/activate
62
+ # Install the latest wheel file
63
+ pip install $(ls -t dist/*.whl | head -1)
64
+ python -c "import iparq; print(f'Successfully imported iparq version {iparq.__version__}')"
65
+ iparq --help
66
+ deactivate
67
+
68
+ - name: Upload test results
69
+ uses: actions/upload-artifact@v4
70
+ if: always()
71
+ with:
72
+ name: test-results
73
+ path: |
74
+ .coverage
75
+ htmlcov/
76
+
18
77
  release-build:
19
78
  permissions:
20
79
  contents: read
21
80
  pull-requests: write
22
81
  runs-on: ubuntu-latest
82
+ needs: test-and-validate
23
83
 
24
84
  steps:
25
85
  - uses: actions/checkout@v4
@@ -32,9 +92,14 @@ jobs:
32
92
  with:
33
93
  python-version-file: "pyproject.toml"
34
94
 
95
+ - name: Update dependencies and sync
96
+ run: |
97
+ uv lock --upgrade
98
+ uv sync --all-extras
99
+
35
100
  - name: Build release distributions
36
101
  run: |
37
- uv build
102
+ uv build
38
103
 
39
104
  - name: Upload distributions
40
105
  uses: actions/upload-artifact@v4
@@ -45,6 +110,7 @@ jobs:
45
110
  pypi-publish:
46
111
  runs-on: ubuntu-latest
47
112
  needs:
113
+ - test-and-validate
48
114
  - release-build
49
115
  permissions:
50
116
  # IMPORTANT: this permission is mandatory for trusted publishing
@@ -11,9 +11,7 @@
11
11
  "request": "launch",
12
12
  "program": "${file}",
13
13
  "console": "integratedTerminal",
14
- "args": [
15
- "${command:pickArgs}"
16
- ]
14
+ "args": "${command:pickArgs}"
17
15
  }
18
16
  ]
19
17
  }
iparq-0.2.6/PKG-INFO ADDED
@@ -0,0 +1,145 @@
1
+ Metadata-Version: 2.4
2
+ Name: iparq
3
+ Version: 0.2.6
4
+ Summary: Display version compression and bloom filter information about a parquet file
5
+ Author-email: MiguelElGallo <miguel.zurcher@gmail.com>
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.9
8
+ Requires-Dist: pyarrow
9
+ Requires-Dist: pydantic
10
+ Requires-Dist: rich
11
+ Requires-Dist: typer
12
+ Provides-Extra: checks
13
+ Requires-Dist: mypy>=1.14.1; extra == 'checks'
14
+ Requires-Dist: ruff>=0.9.3; extra == 'checks'
15
+ Provides-Extra: test
16
+ Requires-Dist: pytest>=7.0; extra == 'test'
17
+ Description-Content-Type: text/markdown
18
+
19
+ # iparq
20
+
21
+ [![Python package](https://github.com/MiguelElGallo/iparq/actions/workflows/python-package.yml/badge.svg)](https://github.com/MiguelElGallo/iparq/actions/workflows/python-package.yml)
22
+
23
+ [![Dependabot Updates](https://github.com/MiguelElGallo/iparq/actions/workflows/dependabot/dependabot-updates/badge.svg)](https://github.com/MiguelElGallo/iparq/actions/workflows/dependabot/dependabot-updates)
24
+
25
+ [![Upload Python Package](https://github.com/MiguelElGallo/iparq/actions/workflows/python-publish.yml/badge.svg)](https://github.com/MiguelElGallo/iparq/actions/workflows/python-publish.yml)
26
+
27
+ ![alt text](media/iparq.png)
28
+ After reading [this blog](https://duckdb.org/2025/01/22/parquet-encodings.html), I began to wonder which Parquet version and compression methods the everyday tools we rely on actually use, only to find that there's no straightforward way to determine this. That curiosity and the difficulty of quickly discovering such details motivated me to create iparq (Information Parquet). My goal with iparq is to help users easily identify the specifics of the Parquet files generated by different engines, making it clear which features—like newer encodings or certain compression algorithms—the creator of the parquet is using.
29
+
30
+ ***New*** Bloom filters information: Displays if there are bloom filters.
31
+ Read more about bloom filters in this [great article](https://duckdb.org/2025/03/07/parquet-bloom-filters-in-duckdb.html).
32
+
33
+ ## Installation
34
+
35
+ ### Zero installation - Recommended
36
+
37
+ 1) Make sure to have Astral's UV installed by following the steps here:
38
+
39
+ <https://docs.astral.sh/uv/getting-started/installation/>
40
+
41
+ 2) Execute the following command:
42
+
43
+ ```sh
44
+ uvx --refresh iparq inspect yourparquet.parquet
45
+ ```
46
+
47
+ ### Using pip
48
+
49
+ 1) Install the package using pip:
50
+
51
+ ```sh
52
+ pip install iparq
53
+ ```
54
+
55
+ 2) Verify the installation by running:
56
+
57
+ ```sh
58
+ iparq --help
59
+ ```
60
+
61
+ ### Using uv
62
+
63
+ 1) Make sure to have Astral's UV installed by following the steps here:
64
+
65
+ <https://docs.astral.sh/uv/getting-started/installation/>
66
+
67
+ 2) Execute the following command:
68
+
69
+ ```sh
70
+ uv pip install iparq
71
+ ```
72
+
73
+ 3) Verify the installation by running:
74
+
75
+ ```sh
76
+ iparq --help
77
+ ```
78
+
79
+ ### Using Homebrew in a MAC
80
+
81
+ 1) Run the following:
82
+
83
+ ```sh
84
+ brew tap MiguelElGallo/tap https://github.com/MiguelElGallo//homebrew-iparq.git
85
+ brew install MiguelElGallo/tap/iparq
86
+ iparq --help
87
+ ```
88
+
89
+ ## Usage
90
+
91
+ iparq now supports additional options:
92
+
93
+ ```sh
94
+ iparq inspect <filename> [OPTIONS]
95
+ ```
96
+
97
+ Options include:
98
+
99
+ - `--format`, `-f`: Output format, either `rich` (default) or `json`
100
+ - `--metadata-only`, `-m`: Show only file metadata without column details
101
+ - `--column`, `-c`: Filter results to show only a specific column
102
+
103
+ Examples:
104
+
105
+ ```sh
106
+ # Output in JSON format
107
+ iparq inspect yourfile.parquet --format json
108
+
109
+ # Show only metadata
110
+ iparq inspect yourfile.parquet --metadata-only
111
+
112
+ # Filter to show only a specific column
113
+ iparq inspect yourfile.parquet --column column_name
114
+ ```
115
+
116
+ Replace `<filename>` with the path to your .parquet file. The utility will read the metadata of the file and print the compression codecs used in the parquet file.
117
+
118
+ ## Example ouput - Bloom Filters
119
+
120
+ ```log
121
+ ParquetMetaModel(
122
+ created_by='DuckDB version v1.2.1 (build 8e52ec4395)',
123
+ num_columns=1,
124
+ num_rows=100000000,
125
+ num_row_groups=10,
126
+ format_version='1.0',
127
+ serialized_size=1196
128
+ )
129
+ Parquet Column Information
130
+ ┏━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
131
+ ┃ Row Group ┃ Column Name ┃ Index ┃ Compression ┃ Bloom Filter ┃
132
+ ┡━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━┩
133
+ │ 0 │ r │ 0 │ SNAPPY │ ✅ │
134
+ │ 1 │ r │ 0 │ SNAPPY │ ✅ │
135
+ │ 2 │ r │ 0 │ SNAPPY │ ✅ │
136
+ │ 3 │ r │ 0 │ SNAPPY │ ✅ │
137
+ │ 4 │ r │ 0 │ SNAPPY │ ✅ │
138
+ │ 5 │ r │ 0 │ SNAPPY │ ✅ │
139
+ │ 6 │ r │ 0 │ SNAPPY │ ✅ │
140
+ │ 7 │ r │ 0 │ SNAPPY │ ✅ │
141
+ │ 8 │ r │ 0 │ SNAPPY │ ✅ │
142
+ │ 9 │ r │ 0 │ SNAPPY │ ✅ │
143
+ └───────────┴─────────────┴───────┴─────────────┴──────────────┘
144
+ Compression codecs: {'SNAPPY'}
145
+ ```
iparq-0.2.6/README.md ADDED
@@ -0,0 +1,127 @@
1
+ # iparq
2
+
3
+ [![Python package](https://github.com/MiguelElGallo/iparq/actions/workflows/python-package.yml/badge.svg)](https://github.com/MiguelElGallo/iparq/actions/workflows/python-package.yml)
4
+
5
+ [![Dependabot Updates](https://github.com/MiguelElGallo/iparq/actions/workflows/dependabot/dependabot-updates/badge.svg)](https://github.com/MiguelElGallo/iparq/actions/workflows/dependabot/dependabot-updates)
6
+
7
+ [![Upload Python Package](https://github.com/MiguelElGallo/iparq/actions/workflows/python-publish.yml/badge.svg)](https://github.com/MiguelElGallo/iparq/actions/workflows/python-publish.yml)
8
+
9
+ ![alt text](media/iparq.png)
10
+ After reading [this blog](https://duckdb.org/2025/01/22/parquet-encodings.html), I began to wonder which Parquet version and compression methods the everyday tools we rely on actually use, only to find that there's no straightforward way to determine this. That curiosity and the difficulty of quickly discovering such details motivated me to create iparq (Information Parquet). My goal with iparq is to help users easily identify the specifics of the Parquet files generated by different engines, making it clear which features—like newer encodings or certain compression algorithms—the creator of the parquet is using.
11
+
12
+ ***New*** Bloom filters information: Displays if there are bloom filters.
13
+ Read more about bloom filters in this [great article](https://duckdb.org/2025/03/07/parquet-bloom-filters-in-duckdb.html).
14
+
15
+ ## Installation
16
+
17
+ ### Zero installation - Recommended
18
+
19
+ 1) Make sure to have Astral's UV installed by following the steps here:
20
+
21
+ <https://docs.astral.sh/uv/getting-started/installation/>
22
+
23
+ 2) Execute the following command:
24
+
25
+ ```sh
26
+ uvx --refresh iparq inspect yourparquet.parquet
27
+ ```
28
+
29
+ ### Using pip
30
+
31
+ 1) Install the package using pip:
32
+
33
+ ```sh
34
+ pip install iparq
35
+ ```
36
+
37
+ 2) Verify the installation by running:
38
+
39
+ ```sh
40
+ iparq --help
41
+ ```
42
+
43
+ ### Using uv
44
+
45
+ 1) Make sure to have Astral's UV installed by following the steps here:
46
+
47
+ <https://docs.astral.sh/uv/getting-started/installation/>
48
+
49
+ 2) Execute the following command:
50
+
51
+ ```sh
52
+ uv pip install iparq
53
+ ```
54
+
55
+ 3) Verify the installation by running:
56
+
57
+ ```sh
58
+ iparq --help
59
+ ```
60
+
61
+ ### Using Homebrew in a MAC
62
+
63
+ 1) Run the following:
64
+
65
+ ```sh
66
+ brew tap MiguelElGallo/tap https://github.com/MiguelElGallo//homebrew-iparq.git
67
+ brew install MiguelElGallo/tap/iparq
68
+ iparq --help
69
+ ```
70
+
71
+ ## Usage
72
+
73
+ iparq now supports additional options:
74
+
75
+ ```sh
76
+ iparq inspect <filename> [OPTIONS]
77
+ ```
78
+
79
+ Options include:
80
+
81
+ - `--format`, `-f`: Output format, either `rich` (default) or `json`
82
+ - `--metadata-only`, `-m`: Show only file metadata without column details
83
+ - `--column`, `-c`: Filter results to show only a specific column
84
+
85
+ Examples:
86
+
87
+ ```sh
88
+ # Output in JSON format
89
+ iparq inspect yourfile.parquet --format json
90
+
91
+ # Show only metadata
92
+ iparq inspect yourfile.parquet --metadata-only
93
+
94
+ # Filter to show only a specific column
95
+ iparq inspect yourfile.parquet --column column_name
96
+ ```
97
+
98
+ Replace `<filename>` with the path to your .parquet file. The utility will read the metadata of the file and print the compression codecs used in the parquet file.
99
+
100
+ ## Example ouput - Bloom Filters
101
+
102
+ ```log
103
+ ParquetMetaModel(
104
+ created_by='DuckDB version v1.2.1 (build 8e52ec4395)',
105
+ num_columns=1,
106
+ num_rows=100000000,
107
+ num_row_groups=10,
108
+ format_version='1.0',
109
+ serialized_size=1196
110
+ )
111
+ Parquet Column Information
112
+ ┏━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
113
+ ┃ Row Group ┃ Column Name ┃ Index ┃ Compression ┃ Bloom Filter ┃
114
+ ┡━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━┩
115
+ │ 0 │ r │ 0 │ SNAPPY │ ✅ │
116
+ │ 1 │ r │ 0 │ SNAPPY │ ✅ │
117
+ │ 2 │ r │ 0 │ SNAPPY │ ✅ │
118
+ │ 3 │ r │ 0 │ SNAPPY │ ✅ │
119
+ │ 4 │ r │ 0 │ SNAPPY │ ✅ │
120
+ │ 5 │ r │ 0 │ SNAPPY │ ✅ │
121
+ │ 6 │ r │ 0 │ SNAPPY │ ✅ │
122
+ │ 7 │ r │ 0 │ SNAPPY │ ✅ │
123
+ │ 8 │ r │ 0 │ SNAPPY │ ✅ │
124
+ │ 9 │ r │ 0 │ SNAPPY │ ✅ │
125
+ └───────────┴─────────────┴───────┴─────────────┴──────────────┘
126
+ Compression codecs: {'SNAPPY'}
127
+ ```
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "iparq"
3
- version = "0.2.0"
3
+ version = "0.2.6"
4
4
  description = "Display version compression and bloom filter information about a parquet file"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -9,7 +9,7 @@ authors = [
9
9
  requires-python = ">=3.9"
10
10
  dependencies = [
11
11
  "pyarrow",
12
- "typer[all]",
12
+ "typer",
13
13
  "pydantic",
14
14
  "rich",
15
15
  ]
@@ -31,7 +31,7 @@ requires = ["hatchling"]
31
31
  build-backend = "hatchling.build"
32
32
 
33
33
  [tool.pytest.ini_options]
34
- addopts = "-ra -q"
34
+ addopts = ["-ra", "-q"]
35
35
  testpaths = [
36
36
  "tests",
37
37
  ]
@@ -0,0 +1 @@
1
+ __version__ = "0.2.6"
File without changes
@@ -1,3 +1,5 @@
1
+ import json
2
+ from enum import Enum
1
3
  from typing import List, Optional
2
4
 
3
5
  import pyarrow.parquet as pq
@@ -7,10 +9,19 @@ from rich import print
7
9
  from rich.console import Console
8
10
  from rich.table import Table
9
11
 
10
- app = typer.Typer()
12
+ app = typer.Typer(
13
+ help="Inspect Parquet files for metadata, compression, and bloom filters"
14
+ )
11
15
  console = Console()
12
16
 
13
17
 
18
+ class OutputFormat(str, Enum):
19
+ """Enum for output format options."""
20
+
21
+ RICH = "rich"
22
+ JSON = "json"
23
+
24
+
14
25
  class ParquetMetaModel(BaseModel):
15
26
  """
16
27
  ParquetMetaModel is a data model representing metadata for a Parquet file.
@@ -227,20 +238,59 @@ def print_column_info_table(column_info: ParquetColumnInfo) -> None:
227
238
  console.print(table)
228
239
 
229
240
 
230
- @app.command()
231
- def main(filename: str):
241
+ def output_json(
242
+ meta_model: ParquetMetaModel,
243
+ column_info: ParquetColumnInfo,
244
+ compression_codecs: set,
245
+ ) -> None:
232
246
  """
233
- Main function to read and print Parquet file metadata.
247
+ Outputs the parquet information in JSON format.
234
248
 
235
249
  Args:
236
- filename (str): The path to the Parquet file.
237
-
238
- Returns:
239
- Metadata of the Parquet file and the compression codecs used.
250
+ meta_model: The Parquet metadata model
251
+ column_info: The column information model
252
+ compression_codecs: Set of compression codecs used
253
+ """
254
+ result = {
255
+ "metadata": meta_model.model_dump(),
256
+ "columns": [column.model_dump() for column in column_info.columns],
257
+ "compression_codecs": list(compression_codecs),
258
+ }
259
+
260
+ print(json.dumps(result, indent=2))
261
+
262
+
263
+ @app.command(name="")
264
+ @app.command(name="inspect")
265
+ def inspect(
266
+ filename: str = typer.Argument(..., help="Path to the Parquet file to inspect"),
267
+ format: OutputFormat = typer.Option(
268
+ OutputFormat.RICH, "--format", "-f", help="Output format (rich or json)"
269
+ ),
270
+ metadata_only: bool = typer.Option(
271
+ False,
272
+ "--metadata-only",
273
+ "-m",
274
+ help="Show only file metadata without column details",
275
+ ),
276
+ column_filter: Optional[str] = typer.Option(
277
+ None, "--column", "-c", help="Filter results to show only specific column"
278
+ ),
279
+ ):
280
+ """
281
+ Inspect a Parquet file and display its metadata, compression settings, and bloom filter information.
240
282
  """
241
283
  (parquet_metadata, compression) = read_parquet_metadata(filename)
242
284
 
243
- print_parquet_metadata(parquet_metadata)
285
+ # Create metadata model
286
+ meta_model = ParquetMetaModel(
287
+ created_by=parquet_metadata.created_by,
288
+ num_columns=parquet_metadata.num_columns,
289
+ num_rows=parquet_metadata.num_rows,
290
+ num_row_groups=parquet_metadata.num_row_groups,
291
+ format_version=str(parquet_metadata.format_version),
292
+ serialized_size=parquet_metadata.serialized_size,
293
+ )
244
294
 
245
295
  # Create a model to store column information
246
296
  column_info = ParquetColumnInfo()
@@ -249,10 +299,27 @@ def main(filename: str):
249
299
  print_compression_types(parquet_metadata, column_info)
250
300
  print_bloom_filter_info(parquet_metadata, column_info)
251
301
 
252
- # Print the information as a table
253
- print_column_info_table(column_info)
254
-
255
- print(f"Compression codecs: {compression}")
302
+ # Filter columns if requested
303
+ if column_filter:
304
+ column_info.columns = [
305
+ col for col in column_info.columns if col.column_name == column_filter
306
+ ]
307
+ if not column_info.columns:
308
+ console.print(
309
+ f"No columns match the filter: {column_filter}", style="yellow"
310
+ )
311
+
312
+ # Output based on format selection
313
+ if format == OutputFormat.JSON:
314
+ output_json(meta_model, column_info, compression)
315
+ else: # Rich format
316
+ # Print the metadata
317
+ console.print(meta_model)
318
+
319
+ # Print column details if not metadata only
320
+ if not metadata_only:
321
+ print_column_info_table(column_info)
322
+ console.print(f"Compression codecs: {compression}")
256
323
 
257
324
 
258
325
  if __name__ == "__main__":
File without changes
Binary file
@@ -0,0 +1,78 @@
1
+ import json
2
+ from pathlib import Path
3
+
4
+ from typer.testing import CliRunner
5
+
6
+ from iparq.source import app
7
+
8
+ # Define path to test fixtures
9
+ FIXTURES_DIR = Path(__file__).parent
10
+ fixture_path = FIXTURES_DIR / "dummy.parquet"
11
+
12
+
13
+ def test_parquet_info():
14
+ """Test that the CLI correctly displays parquet file information."""
15
+ runner = CliRunner()
16
+ result = runner.invoke(app, ["inspect", str(fixture_path)])
17
+
18
+ assert result.exit_code == 0
19
+
20
+ expected_output = """ParquetMetaModel(
21
+ created_by='parquet-cpp-arrow version 14.0.2',
22
+ num_columns=3,
23
+ num_rows=3,
24
+ num_row_groups=1,
25
+ format_version='2.6',
26
+ serialized_size=2223
27
+ )
28
+ Parquet Column Information
29
+ ┏━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
30
+ ┃ Row Group ┃ Column Name ┃ Index ┃ Compression ┃ Bloom Filter ┃
31
+ ┡━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━┩
32
+ │ 0 │ one │ 0 │ SNAPPY │ ✅ │
33
+ │ 0 │ two │ 1 │ SNAPPY │ ✅ │
34
+ │ 0 │ three │ 2 │ SNAPPY │ ✅ │
35
+ └───────────┴─────────────┴───────┴─────────────┴──────────────┘
36
+ Compression codecs: {'SNAPPY'}"""
37
+
38
+ assert expected_output in result.stdout
39
+
40
+
41
+ def test_metadata_only_flag():
42
+ """Test that the metadata-only flag works correctly."""
43
+ runner = CliRunner()
44
+ fixture_path = FIXTURES_DIR / "dummy.parquet"
45
+ result = runner.invoke(app, ["inspect", "--metadata-only", str(fixture_path)])
46
+
47
+ assert result.exit_code == 0
48
+ assert "ParquetMetaModel" in result.stdout
49
+ assert "Parquet Column Information" not in result.stdout
50
+
51
+
52
+ def test_column_filter():
53
+ """Test that filtering by column name works correctly."""
54
+ runner = CliRunner()
55
+ fixture_path = FIXTURES_DIR / "dummy.parquet"
56
+ result = runner.invoke(app, ["inspect", "--column", "one", str(fixture_path)])
57
+
58
+ assert result.exit_code == 0
59
+ assert "one" in result.stdout
60
+ assert "two" not in result.stdout
61
+
62
+
63
+ def test_json_output():
64
+ """Test JSON output format."""
65
+ runner = CliRunner()
66
+ fixture_path = FIXTURES_DIR / "dummy.parquet"
67
+ result = runner.invoke(app, ["inspect", "--format", "json", str(fixture_path)])
68
+
69
+ assert result.exit_code == 0
70
+
71
+ # Test that output is valid JSON
72
+ data = json.loads(result.stdout)
73
+
74
+ # Check JSON structure
75
+ assert "metadata" in data
76
+ assert "columns" in data
77
+ assert "compression_codecs" in data
78
+ assert data["metadata"]["num_columns"] == 3