From 62930529b7da17c411646f5ee7a4cbf4bff4a566 Mon Sep 17 00:00:00 2001 From: Sanjay Santhanam <51058514+Sanjays2402@users.noreply.github.com> Date: Fri, 3 Jul 2026 04:25:15 -0700 Subject: [PATCH] Fix Table.from_fixed reading data as schema for file-like schema_path When schema_path is passed as a file-like object (has a read attribute) rather than a path string, from_fixed took the else branch and assigned schema_f = path -- the data file object -- instead of schema_f = schema_path. As a result the data stream was parsed as the schema, which almost always raised "Schema must contain exactly three columns" (or, if the data happened to look like a valid schema, silently produced the wrong columns). Only the string-path branch, which reopens schema_path by name, worked; the file-object branch was never exercised by the tests. Assign schema_f = schema_path in the else branch, mirroring how the data file's else branch assigns f = path. Add a regression test that passes both the fixed-width file and its schema as open file objects and asserts the parsed columns, types and rows match the string-path result. It fails without the fix (ValueError from the schema check) and passes with it. --- AUTHORS.rst | 1 + CHANGELOG.rst | 1 + agate/table/from_fixed.py | 2 +- tests/test_table/test_from_fixed.py | 12 ++++++++++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 7fc88e31..d6014b4d 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -53,3 +53,4 @@ agate is made by a community. The following individuals have contributed code, d * `Karthik Ramadugu `__ * `Josh Renaud `__ * `Vincent Gao `__ +* `Sanjay Santhanam `__ diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f5824fa0..e0acb44f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,6 +3,7 @@ - fix: :meth:`.Table.distinct` now deduplicates rows when ``key`` is a sequence of column names. - fix: :class:`.Rank` ranks null values last when ``reverse=True``. +- fix: :meth:`.Table.from_fixed` reads the schema instead of the data file when ``schema_path`` is a file-like object. 1.14.2 - February 27, 2026 -------------------------- diff --git a/agate/table/from_fixed.py b/agate/table/from_fixed.py index 08ad9a0e..7f0d929f 100644 --- a/agate/table/from_fixed.py +++ b/agate/table/from_fixed.py @@ -47,7 +47,7 @@ def from_fixed(cls, path, schema_path, column_names=utils.default, column_types= schema_f = open(schema_path, encoding=schema_encoding) close_schema_f = True else: - schema_f = path + schema_f = schema_path reader = fixed.reader(f, schema_f) rows = list(reader) diff --git a/tests/test_table/test_from_fixed.py b/tests/test_table/test_from_fixed.py index a546125a..ed001c6e 100644 --- a/tests/test_table/test_from_fixed.py +++ b/tests/test_table/test_from_fixed.py @@ -11,3 +11,15 @@ def test_from_fixed(self): self.assertColumnTypes(table2, [type(c) for c in table1.column_types]) self.assertRows(table2, table1.rows) + + def test_from_fixed_file_like_objects(self): + table1 = Table.from_csv('examples/testfixed_converted.csv') + + with open('examples/testfixed', encoding='utf-8') as f, \ + open('examples/testfixed_schema.csv', encoding='utf-8') as schema_f: + table2 = Table.from_fixed(f, schema_f) + + self.assertColumnNames(table2, table1.column_names) + self.assertColumnTypes(table2, [type(c) for c in table1.column_types]) + + self.assertRows(table2, table1.rows)