Skip to content
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/bandit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.x"
python-version: "3.14"
cache: "pip"
cache-dependency-path: pyproject.toml

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/mypy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.9"
python-version: "3.10"
cache: "pip"
cache-dependency-path: pyproject.toml

Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/pypi-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,7 @@ jobs:
- name: Check distributions
run: twine check dist/*

# Embeds after the build, not with Pitloom's Hatchling build hook:
# Pitloom needs Python 3.10+, but PyThaiNLP still builds from source on
# Python 3.9, where an unknown build hook fails the build.
# Embeds after the build, not with Pitloom's Hatchling build hook.
# Pitloom 0.20.0+ lists only the wheel's payload, so the files the
# embedding rewrites (RECORD and the SBOM itself) are not in the SBOM
# with stale hashes, as they were with 0.19.0.
Expand Down
8 changes: 3 additions & 5 deletions .github/workflows/unittest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
# See details of test matrix in:
# https://github.com/PyThaiNLP/pythainlp/blob/dev/tests/README.md
os: ["ubuntu-latest", "windows-latest", "macos-latest"]
python-version: ["3.14", "3.9"] # Latest and earliest
python-version: ["3.14", "3.10"] # Latest and earliest
include:
# Test the rest of Python versions only on Ubuntu
- os: "ubuntu-latest"
Expand All @@ -77,17 +77,15 @@ jobs:
python-version: "3.12"
- os: "ubuntu-latest"
python-version: "3.11"
- os: "ubuntu-latest"
python-version: "3.10"

runs-on: ${{ matrix.os }}
timeout-minutes: 60
env:
PYICU_WIN_VER: 2.15 # 2.15 is the last version that supports Python 3.9
PYICU_WIN_VER: 2.15 # 2.15 is the last version that supports Python 3.10
INSTALL_FULL_DEPS: false
PYTHON_VERSION_LATEST: "3.14"
PYTHON_VERSION_LATEST_2: "3.13" # Second-latest supported version
PYTHON_VERSION_EARLIEST: "3.9"
PYTHON_VERSION_EARLIEST: "3.10"

steps:
- name: Checkout
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ and this project adheres to

## [Unreleased]

The minimum Python version is now 3.10.

### Added

- `thai_name_to_char` and `thai_char_to_name` in `pythainlp.util`
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
![Project Logo](./docs/images/logo.png)

[![pypi](https://img.shields.io/pypi/v/pythainlp.svg)](https://pypi.python.org/pypi/pythainlp)
[![Python 3.9](https://img.shields.io/badge/python-3.9-blue.svg)](https://www.python.org/downloads/)
[![Python 3.10](https://img.shields.io/badge/python-3.10-blue.svg)](https://www.python.org/downloads/)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3519354.svg)](https://doi.org/10.5281/zenodo.3519354)
[![Project Status: Active](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
Expand Down Expand Up @@ -32,7 +32,7 @@ pip install pythainlp
| Version | Python version | Changes | Documentation |
|:-------:|:--------------:|:-------:|:-------------:|
| [5.4.0](https://github.com/PyThaiNLP/pythainlp/releases) | 3.9+ | [Log](https://github.com/PyThaiNLP/pythainlp/blob/dev/CHANGELOG.md) | [pythainlp.org/docs](https://pythainlp.org/docs) |
| [`dev`](https://github.com/PyThaiNLP/pythainlp/tree/dev) | 3.9+ | [Log](https://github.com/PyThaiNLP/pythainlp/compare/v5.4.0...HEAD) | [pythainlp.org/dev-docs](https://pythainlp.org/dev-docs/) |
| [`dev`](https://github.com/PyThaiNLP/pythainlp/tree/dev) | 3.10+ | [Log](https://github.com/PyThaiNLP/pythainlp/compare/v5.4.0...HEAD) | [pythainlp.org/dev-docs](https://pythainlp.org/dev-docs/) |

## Features

Expand Down
4 changes: 2 additions & 2 deletions README_TH.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
![Project Logo](https://avatars0.githubusercontent.com/u/32934255?s=200&v=4)

[![pypi](https://img.shields.io/pypi/v/pythainlp.svg)](https://pypi.python.org/pypi/pythainlp)
[![Python 3.9](https://img.shields.io/badge/python-3.9-blue.svg)](https://www.python.org/downloads/)
[![Python 3.10](https://img.shields.io/badge/python-3.10-blue.svg)](https://www.python.org/downloads/)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3519354.svg)](https://doi.org/10.5281/zenodo.3519354)
[![Project Status: Active](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
Expand All @@ -30,7 +30,7 @@ pip install pythainlp
| รุ่น | รุ่นของ Python | มีอะไรเปลี่ยน | เอกสาร |
| :-: | :-: | :-: | :-: |
| [5.4.0](https://github.com/PyThaiNLP/pythainlp/releases) | 3.9+ | [Log](https://github.com/PyThaiNLP/pythainlp/blob/dev/CHANGELOG.md) | [pythainlp.org/docs](https://pythainlp.org/docs) |
| [`dev`](https://github.com/PyThaiNLP/pythainlp/tree/dev) | 3.9+ | [Log](https://github.com/PyThaiNLP/pythainlp/compare/v5.4.0...HEAD) | [pythainlp.org/dev-docs](https://pythainlp.org/dev-docs/) |
| [`dev`](https://github.com/PyThaiNLP/pythainlp/tree/dev) | 3.10+ | [Log](https://github.com/PyThaiNLP/pythainlp/compare/v5.4.0...HEAD) | [pythainlp.org/dev-docs](https://pythainlp.org/dev-docs/) |

## ความสามารถ

Expand Down
39 changes: 14 additions & 25 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ name = "pythainlp"
version = "6.0.0-dev0"
description = "Thai Natural Language Processing library"
readme = "README.md"
requires-python = ">=3.9"
requires-python = ">=3.10"
license = "Apache-2.0"
authors = [
{ name = "Wannaphong Phatthiyaphaibun", email = "wannaphong@pythainlp.org" },
Expand Down Expand Up @@ -45,7 +45,6 @@ classifiers = [
"Development Status :: 5 - Production/Stable",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
Expand All @@ -71,28 +70,19 @@ dependencies = [
## 1) Development ########################################

dev = [
# Some tools drop Python 3.9 in newer releases. Use the latest version
# for each Python range. bandit 1.8.x reports false positives for B615
# (revision is a variable).
"bandit>=1.8.6;python_version<'3.10'",
"bandit>=1.9.4;python_version>='3.10'",
"build>=1.4.4;python_version<'3.10'",
"build>=1.6.1;python_version>='3.10'",
# bandit 1.8.x reports false positives for B615 (revision is a variable).
"bandit>=1.9.4",
"build>=1.6.1",
"bump-my-version>=1.5.1",
"coverage>=7.10.7;python_version<'3.10'",
"coverage>=7.16.2;python_version>='3.10'",
"coverage>=7.16.2",
"diff-cover>=10.6.0",
"flake8>=7.3.0;python_version<'3.10'",
"flake8>=7.4.1;python_version>='3.10'",
"flake8>=7.4.1",
"flake8-cognitive-complexity>=0.1.0",
# Same as CI. mypy 2.x requires Python 3.10 or later and rejects
# python_version = "3.9" in [tool.mypy].
# Same as CI.
"mypy==1.19.1",
"pylint>=3.3.9;python_version<'3.10'",
"pylint>=4.1.2;python_version>='3.10'",
"pylint>=4.1.2",
"ruff>=0.16.10",
"tox>=4.30.3;python_version<'3.10'",
"tox>=4.64.9;python_version>='3.10'",
"tox>=4.64.9",
]

docs = [
Expand Down Expand Up @@ -452,7 +442,7 @@ ignore = ["D203", "D212"]
[tool.ruff]
indent-width = 4
line-length = 79
target-version = "py39"
target-version = "py310"

[tool.ruff.format]
docstring-code-format = true
Expand Down Expand Up @@ -554,7 +544,7 @@ extend-ignore = ["B905", "E501", "RET504", "SIM108", "SIM117"]
"docs/**" = ["D1"]

[tool.tox]
env_list = ["py39", "py310", "py311", "py312", "py313", "py314", "pypy310", "pypy311", "ruff", "flake8", "mypy"]
env_list = ["py310", "py311", "py312", "py313", "py314", "pypy310", "pypy311", "ruff", "flake8", "mypy"]
skip_missing_interpreters = true

[tool.tox.env_run_base]
Expand Down Expand Up @@ -585,8 +575,7 @@ skip_install = true

[tool.tox.env.mypy]
commands = [["mypy", "pythainlp", "tests"]]
# Same version as mypy.yml. mypy 1.19 is the last release that targets
# Python 3.9; python_version in [tool.mypy] sets the target.
# Same version as mypy.yml. python_version in [tool.mypy] sets the target.
deps = ["mypy==1.19.1"]
extras = []

Expand All @@ -597,7 +586,7 @@ disallow_subclassing_any = true
disallow_untyped_decorators = true
disallow_untyped_defs = true
pretty = true
python_version = "3.9"
python_version = "3.10"
show_column_numbers = true
show_error_code_links = true
show_error_context = true
Expand All @@ -619,7 +608,7 @@ disallow_untyped_defs = false

# Treat optional dependencies as untyped, whether installed or not.
# Without "follow_imports = skip", mypy analyzes installed packages
# (for example, torch) with python_version = "3.9" and fails on
# (for example, torch) with python_version = "3.10" and fails on
# newer syntax.
[[tool.mypy.overrides]]
module = [
Expand Down
4 changes: 3 additions & 1 deletion pythainlp/augment/word2vec/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@

import itertools
import logging
from typing import TYPE_CHECKING, Callable, Union
from typing import TYPE_CHECKING, Union

if TYPE_CHECKING:
from collections.abc import Callable

from gensim.models.keyedvectors import KeyedVectors


Expand Down
3 changes: 2 additions & 1 deletion pythainlp/augment/wordnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@

import itertools
from collections import OrderedDict
from typing import TYPE_CHECKING, Callable, Optional
from collections.abc import Callable # noqa: TC003 # for get_type_hints()
from typing import TYPE_CHECKING, Optional

from nltk.corpus import wordnet as wn

Expand Down
3 changes: 2 additions & 1 deletion pythainlp/tokenize/_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
from __future__ import annotations

import re
from typing import TYPE_CHECKING, Callable, NoReturn, Optional, TypeVar
from collections.abc import Callable
from typing import TYPE_CHECKING, NoReturn, Optional, TypeVar

if TYPE_CHECKING:
from pythainlp.util.trie import Trie
Expand Down
2 changes: 1 addition & 1 deletion pythainlp/tools/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

if sys.version_info >= (3, 11):
from importlib.resources import files # Available in Python 3.11+
else: # pragma: no cover - only runs on Python 3.9 and 3.10
else: # pragma: no cover - only runs on Python 3.10
from importlib_resources import files

PYTHAINLP_DEFAULT_DATA_DIR: str = "pythainlp-data"
Expand Down
5 changes: 4 additions & 1 deletion pythainlp/transliterate/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@

from __future__ import annotations

from typing import Callable
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from collections.abc import Callable

DEFAULT_ROMANIZE_ENGINE: str = "royin"
DEFAULT_TRANSLITERATE_ENGINE: str = "thaig2p"
Expand Down
3 changes: 2 additions & 1 deletion pythainlp/util/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@

from __future__ import annotations

from collections.abc import Callable # noqa: TC003 # for get_type_hints()
from contextlib import suppress
from datetime import datetime, time
from functools import lru_cache
from typing import Callable, Optional, Union
from typing import Optional, Union

from pythainlp.tokenize import Tokenizer
from pythainlp.util.numtoword import num_to_thaiword
Expand Down
15 changes: 7 additions & 8 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,13 @@ inside that test suite's directory.
The following table outlines the automated test coverage across
supported Python versions and operating systems:

| Python | Ubuntu | Windows | macOS |
| -------------- | ------- | ------- | ----- |
| 3.14 (Latest) | O+C | O | O |
| 3.13 | O+C+X | O+C | O+C |
| 3.12 | O | | |
| 3.11 | O | | |
| 3.10 | O | | |
| 3.9 (Earliest) | O+C | O+C | O+C |
| Python | Ubuntu | Windows | macOS |
| --------------- | ------- | ------- | ----- |
| 3.14 (Latest) | O+C | O | O |
| 3.13 | O+C+X | O+C | O+C |
| 3.12 | O | | |
| 3.11 | O | | |
| 3.10 (Earliest) | O+C | O+C | O+C |

The CI/CD test workflow is at
<https://github.com/PyThaiNLP/pythainlp/blob/dev/.github/workflows/unittest.yml>.
Expand Down
4 changes: 2 additions & 2 deletions tests/core/test_util_syllable.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import itertools
import random
import unittest
from typing import TYPE_CHECKING, Callable
from typing import TYPE_CHECKING

from pythainlp import thai_consonants, thai_tonemarks, thai_vowels
from pythainlp.util.syllable import (
Expand All @@ -26,7 +26,7 @@
)

if TYPE_CHECKING:
from collections.abc import Iterator
from collections.abc import Callable, Iterator

# (syllable, sound_syllable result, tone_detector result);
# "!Name" means that the exception type Name is raised.
Expand Down
2 changes: 1 addition & 1 deletion tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"""

import unittest
from typing import Callable
from collections.abc import Callable


def assert_segment_handles_none_and_empty(
Expand Down
Loading