Skip to content
Closed
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
84 changes: 84 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: CI

on:
push:
pull_request:

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v4

- name: Get current date
id: date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: "latest"
enable-cache: true
cache-dependency-glob: "pyproject.toml"
cache-suffix: ${{ steps.date.outputs.date }}

- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}

- name: Install dependencies
run: |
uv venv --python ${{ matrix.python-version }}
uv pip install -e .

- name: Run tests
run: uv run python ipgroup_test.py -v

- name: Install coverage
run: uv pip install coverage coveralls

- name: Run tests with coverage
run: uv run coverage run ipgroup_test.py

- name: Upload coverage to Coveralls
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
run: |
uv run coveralls --service=github
continue-on-error: true

build:
runs-on: ubuntu-latest
needs: test

steps:
- uses: actions/checkout@v4

- name: Get current date
id: date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: "latest"
enable-cache: true
cache-dependency-glob: "pyproject.toml"
cache-suffix: ${{ steps.date.outputs.date }}

- name: Set up Python
run: uv python install 3.13

- name: Build package
run: uv build

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
78 changes: 78 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Publish to PyPI

on:
push:
tags:
- '*'

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: "latest"

- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}

- name: Install dependencies
run: |
uv venv --python ${{ matrix.python-version }}
uv pip install -e .

- name: Run tests
run: uv run python ipgroup_test.py -v

build:
runs-on: ubuntu-latest
needs: test

steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: "latest"

- name: Set up Python
run: uv python install 3.13

- name: Build package
run: uv build

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/

publish:
runs-on: ubuntu-latest
needs: build
permissions:
id-token: write # Required for trusted publishing to PyPI

steps:
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: dist
path: dist/

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,10 @@ nosetests.xml
*,cover

.idea/

# Virtual environments
.venv/
venv/

# uv lock file (not needed for libraries)
uv.lock
25 changes: 0 additions & 25 deletions .travis.yml

This file was deleted.

48 changes: 48 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
.PHONY: help test test-verbose build clean install dev lint format check-format

help:
@echo "Available targets:"
@echo " test - Run tests using uv"
@echo " test-verbose - Run tests with verbose output"
@echo " build - Build the package using uv"
@echo " clean - Remove build artifacts and cache files"
@echo " install - Install package in development mode"
@echo " dev - Install development dependencies"
@echo " lint - Run linting (if configured)"
@echo " format - Format code (if configured)"
@echo " check-format - Check code formatting"

test:
uv run python ipgroup_test.py

test-verbose:
uv run python ipgroup_test.py -v

build: clean
uv build

clean:
rm -rf build/
rm -rf dist/
rm -rf *.egg-info
rm -rf .pytest_cache
rm -rf __pycache__
find . -type d -name "__pycache__" -exec rm -rf {} +
find . -type f -name "*.pyc" -delete
find . -type f -name "*.pyo" -delete
find . -type f -name "*~" -delete

install:
uv pip install -e .

dev:
uv pip install -e ".[dev]"

lint:
@echo "No linting configured yet. Install ruff or flake8 to enable linting."

format:
@echo "No formatting configured yet. Install ruff or black to enable formatting."

check-format:
@echo "No format checking configured yet."
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
IP Grouping Python
==================
[![Build
Status](https://travis-ci.org/RyPeck/python-ipgroup.svg?branch=master)](https://travis-ci.org/RyPeck/python-ipgroup) [![Coverage
Status](https://coveralls.io/repos/RyPeck/python-ipgroup/badge.png)](https://coveralls.io/r/RyPeck/python-ipgroup) [![Downloads](https://pypip.in/download/ipgroup/badge.svg)](https://pypi.python.org/pypi/ipgroup/ ) [![License](https://pypip.in/license/ipgroup/badge.svg)](https://pypi.python.org/pypi/ipgroup/) [![Supported Python versions](https://pypip.in/py_versions/ipgroup/badge.svg)](https://pypi.python.org/pypi/ipgroup/) [![Development Status](https://pypip.in/status/ipgroup/badge.svg)](https://pypi.python.org/pypi/ipgroup/)
[![Coverage Status](https://coveralls.io/repos/RyPeck/python-ipgroup/badge.png)](https://coveralls.io/r/RyPeck/python-ipgroup) [![Downloads](https://pypip.in/download/ipgroup/badge.svg)](https://pypi.python.org/pypi/ipgroup/ ) [![License](https://pypip.in/license/ipgroup/badge.svg)](https://pypi.python.org/pypi/ipgroup/) [![Supported Python versions](https://pypip.in/py_versions/ipgroup/badge.svg)](https://pypi.python.org/pypi/ipgroup/) [![Development Status](https://pypip.in/status/ipgroup/badge.svg)](https://pypi.python.org/pypi/ipgroup/)

## Usage

Expand Down
12 changes: 8 additions & 4 deletions ipgroup.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,16 @@ def _validate_ips_param(self, ips):
"""

# Acceptable inputs
assert(isinstance(ips, (str, list, self.IPVersion)))
valid_types = (str, list)
if self.IPVersion is not None:
valid_types = valid_types + self.IPVersion
assert(isinstance(ips, valid_types))

# Unpack a list
if isinstance(ips, list):
for i in ips:
assert(isinstance(i, (str, ipaddress._IPAddressBase)))
assert(isinstance(i, (str, ipaddress.IPv4Address, ipaddress.IPv6Address,
ipaddress.IPv4Network, ipaddress.IPv6Network)))

if isinstance(i, str):
assert(self._validate_IPNetwork_str(i))
Expand Down Expand Up @@ -197,14 +201,14 @@ class IPv4Group(_BaseGroup):
"""Group of IPv4 Addresses"""

def __init__(self, ip_objs, net_bits=24):
_BaseGroup.__init__(self, ip_objs, net_bits, ipaddress._BaseV4)
_BaseGroup.__init__(self, ip_objs, net_bits, (ipaddress.IPv4Network, ipaddress.IPv4Address))


class IPv6Group(_BaseGroup):
"""Group of IPv6 Addresses"""

def __init__(self, ip_objs, net_bits=48):
_BaseGroup.__init__(self, ip_objs, net_bits, ipaddress._BaseV6)
_BaseGroup.__init__(self, ip_objs, net_bits, (ipaddress.IPv6Network, ipaddress.IPv6Address))


def totalAddresses(ips):
Expand Down
4 changes: 2 additions & 2 deletions ipgroup_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def test_group3(self):
# So out sample size is never bigger than the population of hosts
random_int = random.randint(1, 2**(32 - random_cidr - 1))

IPs = random.sample(set(network.hosts()), random_int)
IPs = random.sample(list(network.hosts()), random_int)

expected_results = {("129.21.0.0/%s" % random_cidr): random_int}

Expand All @@ -81,7 +81,7 @@ def test_IPv6(self):
# So out sample size is never bigger than the population of hosts
random_int = random.randint(1, 2**(128 - random_cidr - 1))

IPs = random.sample(set(network.hosts()), random_int)
IPs = random.sample(list(network.hosts()), random_int)

expected_results = {("2607:f8b0:4009:803::/%s" % random_cidr):
random_int}
Expand Down
46 changes: 46 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "ipgroup"
version = "0.0.5"
description = "Functions to gather info on a group of IPv4 or IPv6 Networks"
readme = "README.md"
requires-python = ">=3.9"
license = "Apache-2.0"
authors = [
{ name = "Ryan Peck", email = "ryan@rypeck.com" },
]
maintainers = [
{ name = "Ryan Peck", email = "ryan@rypeck.com" },
]
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Intended Audience :: Information Technology",
"Intended Audience :: System Administrators",
"Intended Audience :: Telecommunications Industry",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Internet",
"Topic :: Internet :: Log Analysis",
"Topic :: Software Development :: Libraries",
"Topic :: System :: Networking",
"Topic :: Utilities",
]

[project.urls]
Homepage = "https://github.com/RyPeck/python-ipgroup"
Repository = "https://github.com/RyPeck/python-ipgroup"
Issues = "https://github.com/RyPeck/python-ipgroup/issues"

[tool.hatch.build.targets.wheel]
packages = ["ipgroup.py"]
Loading
Loading