Reason
_populate_attrs_from_geo_info is the single source of truth for every read backend's DataArray.attrs (called 4× in __init__.py). Alongside it sit _resolve_nodata_attr, _merge_friendly_extra_tags, _extract_rich_tags, _extent_to_window, and the GeoTIFF tag-ID constants. Together they form a self-contained "attrs lifecycle" bundle that all four read backends and three writers depend on. Extracting it removes a coupling point every later backend PR would otherwise have to navigate.
Proposal
Move them to xrspatial/geotiff/_attrs.py. Re-import from __init__.py for the still-inline entry points. test_attrs_parity_1548.py, test_extra_tags_safe_filter_1657.py, test_geotags.py exercise behaviour through the public surface; the #1813 parity matrix is the regression backstop.
Drawbacks
Many call sites (8+ in __init__.py); a missed re-import would fail loudly. Mitigated by the parity matrix in #1813 step 1.
Refs: #1813.
Reason
_populate_attrs_from_geo_infois the single source of truth for every read backend'sDataArray.attrs(called 4× in__init__.py). Alongside it sit_resolve_nodata_attr,_merge_friendly_extra_tags,_extract_rich_tags,_extent_to_window, and the GeoTIFF tag-ID constants. Together they form a self-contained "attrs lifecycle" bundle that all four read backends and three writers depend on. Extracting it removes a coupling point every later backend PR would otherwise have to navigate.Proposal
Move them to
xrspatial/geotiff/_attrs.py. Re-import from__init__.pyfor the still-inline entry points.test_attrs_parity_1548.py,test_extra_tags_safe_filter_1657.py,test_geotags.pyexercise behaviour through the public surface; the #1813 parity matrix is the regression backstop.Drawbacks
Many call sites (8+ in
__init__.py); a missed re-import would fail loudly. Mitigated by the parity matrix in #1813 step 1.Refs: #1813.