"""Bump version numbers in pyproject.toml and geemap/__init__.py.
This script updates the version in two places in pyproject.toml:
1. [project] section: version = "..."
2. [tool.bumpversion] section: current_version = "..."
And updates __version__ in geemap/__init__.py:
__version__ = "..."
Usage:
python scripts/bump_geemap_version.py NEW_VERSION
Example:
python scripts/bump_geemap_version.py 0.36.5
"""
import pathlib
import re
import sys
def update_pyproject_toml(file_path: pathlib.Path, new_version: str) -> bool:
"""Update version in pyproject.toml (two occurrences)."""
content = file_path.read_text()
original_content = content
project_pattern = r'(^\[project\](?:.*?\n)*?version\s*=\s*)"([^"]+)"'
bumpversion_pattern = (
r'(^\[tool\.bumpversion\](?:.*?\n)*?current_version\s*=\s*)"([^"]+)"'
)
project_match = re.search(project_pattern, content, re.MULTILINE | re.DOTALL)
bumpversion_match = re.search(
bumpversion_pattern, content, re.MULTILINE | re.DOTALL
)
if not project_match:
print(
"ERROR: Could not find 'version = \"...\"' in [project] section of "
"pyproject.toml"
)
return False
if not bumpversion_match:
print(
"ERROR: Could not find 'current_version = \"...\"' in "
"[tool.bumpversion] section of pyproject.toml"
)
return False
old_project_version = project_match.group(2)
old_bumpversion = bumpversion_match.group(2)
print(f"Found project version: {old_project_version}")
print(f"Found bumpversion: {old_bumpversion}")
lines = content.split("\n")
new_lines = []
in_project = False
in_bumpversion = False
project_replaced = False
bumpversion_replaced = False
for line in lines:
stripped_line = line.strip()
if stripped_line == "[project]":
in_project = True
in_bumpversion = False
elif stripped_line == "[tool.bumpversion]":
in_bumpversion = True
in_project = False
elif stripped_line.startswith("["):
in_project = False
in_bumpversion = False
if (
in_project
and not project_replaced
and re.match(r'^version\s*=\s*"', stripped_line)
):
new_lines.append(f'version = "{new_version}"')
project_replaced = True
elif (
in_bumpversion
and not bumpversion_replaced
and re.match(r'^current_version\s*=\s*"', stripped_line)
):
new_lines.append(f'current_version = "{new_version}"')
bumpversion_replaced = True
else:
new_lines.append(line)
if not project_replaced or not bumpversion_replaced:
print("ERROR: Failed to replace version strings in pyproject.toml")
return False
new_content = "\n".join(new_lines)
if new_content != original_content:
file_path.write_text(new_content)
print(f"✓ Updated pyproject.toml to {new_version}")
return True
else:
print("ERROR: No changes made to pyproject.toml")
return False
def update_init_py(file_path: pathlib.Path, new_version: str) -> bool:
"""Update __version__ in geemap/__init__.py."""
content = file_path.read_text()
original_content = content
pattern = r'^__version__\s*=\s*"([^"]+)"'
if not re.search(pattern, content, re.MULTILINE):
print("ERROR: Could not find '__version__ = \"...\"' in geemap/__init__.py")
return False
new_content = re.sub(
pattern, f'__version__ = "{new_version}"', content, flags=re.MULTILINE
)
if new_content != original_content:
file_path.write_text(new_content)
print(f"✓ Updated geemap/__init__.py to {new_version}")
return True
else:
print("ERROR: No changes made to geemap/__init__.py")
return False
def update_version(new_version: str) -> bool:
"""Updates the version number in pyproject.toml and geemap/__init__.py.
Args:
new_version: The new version string to set.
Returns:
True if the version was successfully updated in both files, False otherwise.
"""
if not re.match(r"^\d+\.\d+\.\d+(rc\d+|\.post\d+)*$", new_version):
print(f"ERROR: Invalid version format: {new_version}")
print("Expected format: X.Y.Z, X.Y.ZrcN, or X.Y.Z.postN (e.g., 0.36.5.post0)")
return False
print(f"\nBumping version to: {new_version}\n")
repo_root = pathlib.Path(__file__).parent.parent
pyproject_path = repo_root / "pyproject.toml"
init_path = repo_root / "geemap" / "__init__.py"
if not pyproject_path.exists():
print(f"ERROR: pyproject.toml not found at {pyproject_path}")
return False
if not init_path.exists():
print(f"ERROR: geemap/__init__.py not found at {init_path}")
return False
if not update_pyproject_toml(pyproject_path, new_version):
print("\n✗ Version bump failed in pyproject.toml! Halting.")
return False
if not update_init_py(init_path, new_version):
print("\n✗ Version bump failed in geemap/__init__.py! Halting.")
return False
print("\n✓ Version bump completed successfully!")
return True
def main() -> None:
if len(sys.argv) != 2:
print("Usage: python scripts/bump_geemap_version.py NEW_VERSION")
print("Example: python scripts/bump_geemap_version.py 0.36.5")
sys.exit(1)
new_version = sys.argv[1]
if not update_version(new_version):
sys.exit(1)
if __name__ == "__main__":
main()