Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ The Python Shapefile Library (PyShp) reads and writes ESRI Shapefiles in pure Py

- **Author**: [Joel Lawhead](https://github.com/GeospatialPython)
- **Maintainers**: [James Parrott](https://github.com/JamesParrott) & [Karim Bahgat](https://github.com/karimbahgat)
- **Version**: 3.1.4.dev
- **Date**: 27th June 2026
- **Version**: 3.1.4
- **Date**: 29th June 2026
- **License**: [MIT](https://github.com/GeospatialPython/pyshp/blob/master/LICENSE.TXT)

## Contents
Expand Down Expand Up @@ -93,9 +93,14 @@ part of your geospatial project.

# Version Changes

## 3.1.4.dev
## 3.1.4
### Bug fix
- Fix bug causing dates supplied as length 8 strings of digits to be encoded by the custom encoding, not ascii.

### Testing
- Test other codecs (ascii and unicode so far).
- Test other codecs (ascii and UTF-8, UTF-16 & UTF-32 so far).
- Test all available codecs in CI (92 of them).

## 3.1.3
- Restore faster text writing paths for single-byte Ascii encodings, and Utf-8.

Expand Down
8 changes: 5 additions & 3 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@

VERSION 3.1.4.dev

VERSION 3.1.4
2026-06-29
* Fix bug causing dates supplied as length 8 strings to be encoded by the custom codec, not ascii
2026-06-27
* Test other codecs (ascii and unicode so far).
* Test other codecs (ascii and UTF-8, UTF-16 & UTF-32 so far).
* Test all other codecs in CI

VERSION 3.1.3

Expand Down
4 changes: 2 additions & 2 deletions src/shapefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from __future__ import annotations

__version__ = "3.1.4.dev"
__version__ = "3.1.4"

import abc
import array
Expand Down Expand Up @@ -4436,7 +4436,7 @@ def _record(self, record: list[RecordValue]) -> None:
elif value in MISSING:
str_val = "0" * 8 # QGIS NULL for date type
elif isinstance(value, str) and len(value) == 8:
pass # value is already a date string
str_val = value
else:
raise ShapefileException(
f"Could not read as date: {value}. "
Expand Down
52 changes: 21 additions & 31 deletions tests/hypothesis_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import datetime
import io
import itertools
import os
import string
import warnings

Expand All @@ -27,6 +28,8 @@

import shapefile as shp

IN_CI = bool(os.getenv("CI") or os.getenv("GITHUB_ACTIONS"))

@contextlib.contextmanager
def ignore_warnings(category=None):
with warnings.catch_warnings():
Expand Down Expand Up @@ -551,52 +554,39 @@ def test_shx_reader_writer_roundtrip(codes_and_shapes)-> None:
}


ENCODINGS = [
ENCODINGS = [
"ascii",
"latin1",
"utf-8",
"utf-16-be",
"utf-16-le",
"utf-16",
"utf-32-be",
"utf-32-le",
"cp1252",
"cp1254",
"cp932",
"euc_kr",
"euc_jp",
"mac_iceland",
"cp932",
"shift_jis",
"iso8859_5",
"koi8_r",
"gbk",
"gb18030",
"big5",
"cp1140",
]
encodings = sampled_from(ENCODINGS)

# from encodings.aliases import aliases
# encs = set()
# for enc in aliases.values():
# if enc in encs:
# continue
# try:
# "".encode(enc)
# except UnicodeEncodeError, LookupError:
# continue
# encs.add(enc)
# assert encs == ['utf_16_le', 'iso8859_7', 'cp437', 'iso2022_jp_3', 'shift_jis', 'cp775', 'cp1140',

def _encodings() -> set[str]:
from encodings.aliases import aliases
encs = set()
for enc in aliases.values():
if enc in encs:
continue
try:
"".encode(enc)
except (UnicodeEncodeError, LookupError):
continue
encs.add(enc)
return encs
# assert _encodings() == {'utf_16_le', 'iso8859_7', 'cp437', 'iso2022_jp_3', 'shift_jis', 'cp775', 'cp1140',
# 'cp861', 'iso8859_11', 'iso8859_9', 'euc_jp', 'utf_16', 'cp950', 'mac_cyrillic', 'mac_turkish', 'iso2022_jp_1', 'iso8859_10',
# 'iso2022_jp_2004', 'cp866', 'mac_greek', 'hz', 'cp1257', 'cp037', 'cp863', 'iso8859_4', 'utf_16_be', 'gb18030', 'cp1250',
# 'cp850', 'iso8859_5', 'shift_jisx0213', 'iso8859_8', 'cp273', 'euc_jisx0213', 'cp932', 'cp862', 'tis_620', 'cp1125', 'koi8_r',
# 'cp874', 'cp1026', 'cp1252', 'cp858', 'cp865', 'gb2312', 'iso8859_15', 'cp857', 'cp860', 'iso2022_jp', 'iso2022_jp_ext',
# 'ascii', 'cp1254', 'cp424', 'cp855', 'hp_roman8', 'mac_latin2', 'euc_jis_2004', 'euc_kr', 'cp1256', 'shift_jis_2004',
# 'utf_32_le', 'gbk', 'cp869', 'iso8859_13', 'iso8859_3', 'big5', 'cp1258', 'cp1253', 'latin_1', 'cp864', 'utf_8',
# 'iso2022_kr', 'cp1251', 'cp1255', 'mac_iceland', 'kz1048', 'iso8859_14', 'utf_32_be', 'ptcp154', 'iso8859_6', 'mac_roman',
# 'utf_32', 'iso2022_jp_2', 'iso8859_16', 'mbcs', 'cp500', 'iso8859_2', 'cp949', 'cp852', 'utf_7', 'big5hkscs', 'johab']
# 'utf_32', 'iso2022_jp_2', 'iso8859_16', 'mbcs', 'cp500', 'iso8859_2', 'cp949', 'cp852', 'utf_7', 'big5hkscs', 'johab'}

# encodings = sampled_from(list(encs))
encodings = sampled_from(list(_encodings())) # if IN_CI else ENCODINGS)


@composite
Expand Down
Loading