sumry 0.2.0__tar.gz → 0.3.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sumry
3
- Version: 0.2.0
3
+ Version: 0.3.1
4
4
  Summary: A data summarization tool for analyzing various file formats
5
5
  Author: Sparkgeo
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sumry"
7
- version = "0.2.0"
7
+ version = "0.3.1"
8
8
  description = "A data summarization tool for analyzing various file formats"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -93,7 +93,7 @@ def main(
93
93
 
94
94
  # Display sample records if requested
95
95
  if sample is not None or show_sample:
96
- sample_count = sample if sample and sample > 0 else 5
96
+ sample_count = sample if sample is not None and sample != 0 else 5
97
97
  display_sample_records(file_path, file_type, sample_count)
98
98
 
99
99
  except Exception as e:
@@ -102,28 +102,51 @@ def main(
102
102
 
103
103
 
104
104
  def display_sample_records(file_path: Path, file_type: str, sample_count: int):
105
- """Display sample records from the file."""
105
+ """Display sample records from the file.
106
+
107
+ Args:
108
+ sample_count: Number of records to show. Positive for first N, negative for last N.
109
+ """
106
110
  import pandas as pd
107
111
  import geopandas as gpd
108
-
109
- console.print(f"\n[bold cyan]Sample Records (first {sample_count}):[/bold cyan]")
110
-
112
+
113
+ # Determine if we're showing first or last records
114
+ show_last = sample_count < 0
115
+ abs_count = abs(sample_count)
116
+ position = "last" if show_last else "first"
117
+
118
+ console.print(f"\n[bold cyan]Sample Records ({position} {abs_count}):[/bold cyan]")
119
+
111
120
  try:
112
121
  # Read the data based on file type
113
122
  if file_type == "CSV":
114
- df = pd.read_csv(file_path, nrows=sample_count)
123
+ if show_last:
124
+ df = pd.read_csv(file_path).tail(abs_count)
125
+ else:
126
+ df = pd.read_csv(file_path, nrows=abs_count)
115
127
  elif file_type == "Excel":
116
- df = pd.read_excel(file_path, nrows=sample_count)
128
+ if show_last:
129
+ df = pd.read_excel(file_path).tail(abs_count)
130
+ else:
131
+ df = pd.read_excel(file_path, nrows=abs_count)
117
132
  elif file_type == "Parquet":
118
- df = pd.read_parquet(file_path).head(sample_count)
133
+ full_df = pd.read_parquet(file_path)
134
+ df = full_df.tail(abs_count) if show_last else full_df.head(abs_count)
119
135
  elif file_type in ["GeoJSON", "Shapefile", "GeoParquet"]:
120
136
  # For spatial files, use geopandas
121
137
  if file_type == "GeoJSON":
122
- gdf = gpd.read_file(file_path, rows=sample_count)
138
+ if show_last:
139
+ gdf = gpd.read_file(file_path).tail(abs_count)
140
+ else:
141
+ gdf = gpd.read_file(file_path, rows=abs_count)
123
142
  elif file_type == "Shapefile":
124
- gdf = gpd.read_file(file_path, rows=sample_count)
143
+ if show_last:
144
+ gdf = gpd.read_file(file_path).tail(abs_count)
145
+ else:
146
+ gdf = gpd.read_file(file_path, rows=abs_count)
125
147
  else: # GeoParquet
126
- gdf = gpd.read_parquet(file_path).head(sample_count)
148
+ full_gdf = gpd.read_parquet(file_path)
149
+ gdf = full_gdf.tail(abs_count) if show_last else full_gdf.head(abs_count)
127
150
 
128
151
  # Replace geometry column with placeholder
129
152
  df = gdf.copy()
@@ -82,18 +82,33 @@ class XLSX(BaseFormat):
82
82
 
83
83
  # Read sample data from the specified layer
84
84
  try:
85
- sample_query = f"""
86
- SELECT * FROM st_read('{self.file}', layer='{self.layer}')
87
- LIMIT {count}
88
- """
89
- df = duckdb.sql(sample_query).df()
90
-
85
+ abs_count = abs(count)
86
+
87
+ if count < 0:
88
+ # Get last N records by using row number and ordering
89
+ sample_query = f"""
90
+ SELECT * EXCLUDE (_rn) FROM (
91
+ SELECT *, ROW_NUMBER() OVER () as _rn
92
+ FROM st_read('{self.file}', layer='{self.layer}')
93
+ ) ORDER BY _rn DESC LIMIT {abs_count}
94
+ """
95
+ df = duckdb.sql(sample_query).df()
96
+ # Reverse to show in original order
97
+ df = df.iloc[::-1].reset_index(drop=True)
98
+ else:
99
+ sample_query = f"""
100
+ SELECT * FROM st_read('{self.file}', layer='{self.layer}')
101
+ LIMIT {abs_count}
102
+ """
103
+ df = duckdb.sql(sample_query).df()
104
+
91
105
  if df.empty:
92
106
  console.print(f"[yellow]No data found in layer '{self.layer}'[/yellow]")
93
107
  return
94
-
108
+
109
+ position = "last" if count < 0 else "first"
95
110
  # Create a Rich table
96
- table = Table(title=f"Sample data from '{self.layer}' (showing {min(count, len(df))} of {count} requested records)")
111
+ table = Table(title=f"Sample data from '{self.layer}' (showing {position} {len(df)} records)")
97
112
 
98
113
  # Add columns to the table
99
114
  for col in df.columns:
@@ -18,7 +18,7 @@ def info(
18
18
  def sample(
19
19
  file: str = typer.Argument(..., help="Source file."),
20
20
  layer: str = typer.Argument(None, help="Layer name."),
21
- count: int = typer.Option(5, "--count", "-n", help="Number of sample records to display."),
21
+ count: int = typer.Option(5, "--count", "-n", help="Number of sample records to display. Use negative values to show records from the end (e.g., -5 for last 5 records)."),
22
22
  ):
23
23
  xlsx = XLSX(file, layer=layer)
24
24
  xlsx.sample(count=count)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sumry
3
- Version: 0.2.0
3
+ Version: 0.3.1
4
4
  Summary: A data summarization tool for analyzing various file formats
5
5
  Author: Sparkgeo
6
6
  License: MIT
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes