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
17 changes: 17 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: 2
updates:
- package-ecosystem: uv
directory: /
schedule:
interval: daily
time: '14:00'
open-pull-requests-limit: 10
cooldown:
default-days: 7
- package-ecosystem: github-actions
directory: /
schedule:
interval: daily
time: '14:00'
cooldown:
default-days: 7
38 changes: 38 additions & 0 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: "Code scanning - action"

on:
push:
branches-ignore:
- 'dependabot/**'
pull_request:
schedule:
- cron: '0 11 * * 2'

permissions: {}

jobs:
CodeQL-Build:

runs-on: ubuntu-latest

permissions:
security-events: write

steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 2
persist-credentials: false

- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}

- name: Initialize CodeQL
uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10

- name: Autobuild
uses: github/codeql-action/autobuild@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
49 changes: 49 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Build and upload to PyPI

on:
workflow_dispatch:
pull_request:
push:
branches:
- main
release:
types:
- published

permissions: {}

jobs:
build:
name: Build source distribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Install the latest version of uv
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # 7.2.1

- name: Build
run: uv build

- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
path: |
dist/*.tar.gz
dist/*.whl

upload_pypi:
needs: build
runs-on: ubuntu-latest
environment: release
permissions:
id-token: write
if: github.event_name == 'release' && github.event.action == 'published'
steps:
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: artifact
path: dist

- uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # 1.13.0
38 changes: 38 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Python tests

on:
push:
pull_request:
schedule:
- cron: '3 15 * * SUN'

permissions: {}

jobs:
test:
name: test with ${{ matrix.env }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
env: [3.11, 3.12, 3.13, 3.14]
os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest, windows-latest]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Install the latest version of uv
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # 7.2.1
- name: Install tox
run: uv tool install --python-preference only-managed --python 3.13 tox --with tox-uv --with tox-gh
- name: Install Python
if: matrix.env != '3.13'
run: uv python install --python-preference only-managed ${{ matrix.env }}
- name: Setup test suite
run: tox run -vv --notest --skip-missing-interpreters false
env:
TOX_GH_MAJOR_MINOR: ${{ matrix.env }}
- name: Run test suite
run: tox run --skip-pkg-install
env:
TOX_GH_MAJOR_MINOR: ${{ matrix.env }}
23 changes: 23 additions & 0 deletions .github/workflows/zizmor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: GitHub Actions Security Analysis with zizmor

on:
push:
branches: ["main"]
pull_request:
branches: ["**"]

permissions: {}

jobs:
zizmor:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Run zizmor
uses: zizmorcore/zizmor-action@0dce2577a4760a2749d8cfb7a84b7d5585ebcb7d # v0.5.0
2 changes: 1 addition & 1 deletion HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
History
-------

1.0.0 (2024-12-05)
0.1.0 (2026-02-10)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The date for version 0.1.0 appears to be a typo, as it is set to a future date (2026-02-10). Please correct this to the actual release date to avoid confusion for users.

++++++++++++++++++

* Initial release
Expand Down
File renamed without changes.
17 changes: 17 additions & 0 deletions LICENSE-MIT
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
30 changes: 28 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ asyncio.run(main())
### Loading Configuration from File

```python
from pathlib import Path

from pygeoipupdate import Config, Updater

config = Config.from_file(config_file=Path("/etc/GeoIP.conf"))
Expand Down Expand Up @@ -178,6 +180,18 @@ Options:
- Configuration file: `%SYSTEMDRIVE%\ProgramData\MaxMind\GeoIPUpdate\GeoIP.conf`
- Database directory: `%SYSTEMDRIVE%\ProgramData\MaxMind\GeoIPUpdate\GeoIP`

## Error Handling

When using the Python API, pygeoipupdate raises specific exceptions:

- `GeoIPUpdateError` — Base exception for all errors.
- `ConfigError` — Invalid configuration.
- `DownloadError` — Download failure.
- `AuthenticationError` — Invalid account ID or license key.
- `HTTPError` — HTTP error with `.status_code` and `.body` attributes.
- `LockError` — Could not acquire the lock file.
- `HashMismatchError` — Downloaded file hash mismatch (`.expected`, `.actual`).

## Running as a Cron Job

To keep your databases up to date, we recommend running pygeoipupdate at least
Expand All @@ -193,9 +207,21 @@ twice per week. Here's an example cron entry:
- Python 3.11+
- A MaxMind account with a license key

## License
## Bug Reports

Please report bugs by filing an issue with [our GitHub issue
tracker](https://github.com/maxmind/pygeoipupdate/issues).

## Versioning

This library uses [Semantic Versioning](https://semver.org/).

## Copyright and License

This software is Copyright (c) 2025 - 2026 by MaxMind, Inc.

Apache-2.0
This is free software, licensed under the [Apache License, Version
2.0](LICENSE-APACHE) or the [MIT License](LICENSE-MIT), at your option.

## Links

Expand Down
107 changes: 107 additions & 0 deletions dev-bin/release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/bin/bash

set -eu -o pipefail

# Pre-flight checks - verify all required tools are available and configured
# before making any changes to the repository

check_command() {
if ! command -v "$1" &>/dev/null; then
echo "Error: $1 is not installed or not in PATH"
exit 1
fi
}

# Verify gh CLI is authenticated
if ! gh auth status &>/dev/null; then
echo "Error: gh CLI is not authenticated. Run 'gh auth login' first."
exit 1
fi

# Verify we can access this repository via gh
if ! gh repo view --json name &>/dev/null; then
echo "Error: Cannot access repository via gh. Check your authentication and repository access."
exit 1
fi

# Verify git can connect to the remote (catches SSH key issues, etc.)
if ! git ls-remote origin &>/dev/null; then
echo "Error: Cannot connect to git remote. Check your git credentials/SSH keys."
exit 1
fi

check_command perl
check_command uv

# Check that we're not on the main branch
current_branch=$(git branch --show-current)
if [ "$current_branch" = "main" ]; then
echo "Error: Releases should not be done directly on the main branch."
echo "Please create a release branch and run this script from there."
exit 1
fi

# Fetch latest changes and check that we're not behind origin/main
echo "Fetching from origin..."
git fetch origin

if ! git merge-base --is-ancestor origin/main HEAD; then
echo "Error: Current branch is behind origin/main."
echo "Please merge or rebase with origin/main before releasing."
exit 1
fi

changelog=$(cat HISTORY.rst)

regex='
([0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?) \(([0-9]{4}-[0-9]{2}-[0-9]{2})\)
\+*

((.|
)*)
'

if [[ ! $changelog =~ $regex ]]; then
echo "Could not find date line in change log!"
exit 1
fi

version="${BASH_REMATCH[1]}"
date="${BASH_REMATCH[3]}"
notes="$(echo "${BASH_REMATCH[4]}" | sed -n -E '/^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?/,$!p')"

if [[ "$date" != "$(date +"%Y-%m-%d")" ]]; then
echo "$date is not today!"
exit 1
fi

tag="v$version"

if [ -n "$(git status --porcelain)" ]; then
echo ". is not clean." >&2
exit 1
fi

perl -pi -e "s/(?<=^version = \").+?(?=\")/$version/gsm" pyproject.toml

echo $"Test results:"
uv run tox

echo $'\nDiff:'
git diff

echo $'\nRelease notes:'
echo "$notes"

read -r -e -p "Commit changes and push to origin? " should_push

if [ "$should_push" != "y" ]; then
echo "Aborting"
exit 1
fi

git commit -m "Update for $tag" -a

git push

gh release create --target "$(git branch --show-current)" -t "$version" -n "$notes" "$tag"
8 changes: 8 additions & 0 deletions mise.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[[tools."aqua:astral-sh/uv"]]
version = "0.10.0"
backend = "aqua:astral-sh/uv"
"platforms.linux-arm64" = { checksum = "sha256:edf1adb1d183730302f87eef9b71bc4e47b4b8058832c3393b0fbcd86f270510", url = "https://github.com/astral-sh/uv/releases/download/0.10.0/uv-aarch64-unknown-linux-musl.tar.gz"}
"platforms.linux-x64" = { checksum = "sha256:312d37f31b6f2c3bfc65668ba0efea9f1f9eaf7bc3209fe1a109e5cf861b95fa", url = "https://github.com/astral-sh/uv/releases/download/0.10.0/uv-x86_64-unknown-linux-musl.tar.gz"}
"platforms.macos-arm64" = { checksum = "sha256:82d4b99dc6ea686695b5ee142ceba03dd3e3eda2b414e94215ab7bce94972fbb", url = "https://github.com/astral-sh/uv/releases/download/0.10.0/uv-aarch64-apple-darwin.tar.gz"}
"platforms.macos-x64" = { checksum = "sha256:664aed584c276f8d79cdc3b7685cd48f5d64657bd6840b06b4b2b0db731b9c99", url = "https://github.com/astral-sh/uv/releases/download/0.10.0/uv-x86_64-apple-darwin.tar.gz"}
"platforms.windows-x64" = { checksum = "sha256:4037b444541f695cd2eb93188a9346de3e334af562381411deade0a31c7bf898", url = "https://github.com/astral-sh/uv/releases/download/0.10.0/uv-x86_64-pc-windows-msvc.zip"}
21 changes: 21 additions & 0 deletions mise.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[settings]
# Require lockfile URLs to be present during installation
lockfile = true
locked = true

# Disable backends that use community-maintained bash scripts (supply chain risk)
# See: https://github.com/jdx/mise/discussions/4054
disable_backends = [
"asdf", # Community bash plugins - supply chain attack vector
"vfox", # Same bash plugin model as asdf - supply chain risk
]

[tools]
"aqua:astral-sh/uv" = "latest"

[hooks]
enter = "mise install --quiet"

[[watch_files]]
patterns = ["mise.toml", "mise.lock"]
run = "mise install --quiet"
Loading
Loading