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
31 changes: 31 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Tests

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

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

steps:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install package
run: |
python -m pip install --upgrade pip
pip install -e .

- name: Run tests
run: python -m unittest discover -s tests -v
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ repos:
rev: v3.21.2
hooks:
- id: pyupgrade
args: ['--py36-plus']
args: ['--py310-plus']
- repo: https://github.com/pycqa/flake8
rev: 7.3.0
hooks:
Expand Down
41 changes: 41 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Contributing

Thanks for considering a contribution!

## Setup

```sh
python3 -m venv .venv
.venv/bin/pip install -e .
.venv/bin/pip install pre-commit
.venv/bin/pre-commit install
```

## Running tests

```sh
.venv/bin/python -m unittest discover -vs tests
```

Tests also run in CI on Python 3.10–3.14. New hooks should ship with tests
in `tests/`.

## Linting and formatting

`pre-commit` runs `black`, `isort`, `flake8`, and `pyupgrade`. Either let
the installed hook handle it on commit, or run it manually:

```sh
.venv/bin/pre-commit run --all-files
```

pre-commit.ci also runs these hooks on every PR.

## Adding a new hook

A new hook needs:

- An entry in `.pre-commit-hooks.yaml`
- An entry point in `setup.py`
- A usage example in `README.md`
- Tests in `tests/`
3 changes: 1 addition & 2 deletions pre_commit_macadmin_hooks/check_autopkg_recipe_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import argparse
import json
import plistlib
from typing import List, Optional
from xml.parsers.expat import ExpatError

import ruamel.yaml
Expand All @@ -26,7 +25,7 @@ def build_argument_parser() -> argparse.ArgumentParser:
return parser


def main(argv: Optional[List[str]] = None) -> int:
def main(argv: list[str] | None = None) -> int:
"""Main process."""

# Parse command line arguments.
Expand Down
4 changes: 2 additions & 2 deletions pre_commit_macadmin_hooks/check_autopkg_recipes.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import os
import sys
from contextlib import contextmanager
from typing import Any, Dict, List
from typing import Any

from packaging.version import Version

Expand Down Expand Up @@ -88,7 +88,7 @@ def build_argument_parser() -> argparse.ArgumentParser:


def validate_recipe_prefix(
recipe: Dict[str, Any], filename: str, prefix: List[str]
recipe: dict[str, Any], filename: str, prefix: list[str]
) -> bool:
"""Verify that the recipe identifier starts with the expected prefix."""

Expand Down
3 changes: 1 addition & 2 deletions pre_commit_macadmin_hooks/check_git_config_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import argparse
import subprocess
from typing import List, Optional


def build_argument_parser() -> argparse.ArgumentParser:
Expand All @@ -20,7 +19,7 @@ def build_argument_parser() -> argparse.ArgumentParser:
return parser


def main(argv: Optional[List[str]] = None) -> int:
def main(argv: list[str] | None = None) -> int:
"""Main process."""

# Parse command line arguments.
Expand Down
3 changes: 1 addition & 2 deletions pre_commit_macadmin_hooks/check_jamf_extension_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import argparse
import re
from typing import List, Optional

from pre_commit_macadmin_hooks.util import validate_shebangs

Expand All @@ -24,7 +23,7 @@ def build_argument_parser() -> argparse.ArgumentParser:
return parser


def main(argv: Optional[List[str]] = None) -> int:
def main(argv: list[str] | None = None) -> int:
"""Main process."""

# Parse command line arguments.
Expand Down
18 changes: 9 additions & 9 deletions pre_commit_macadmin_hooks/check_jamf_json_manifests.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import argparse
import json
from datetime import datetime
from typing import Any, Dict, List, Optional, Tuple
from typing import Any

from pre_commit_macadmin_hooks.util import validate_required_keys

Expand Down Expand Up @@ -45,7 +45,7 @@ def build_argument_parser() -> argparse.ArgumentParser:
return parser


def validate_key_types(name: str, manifest: Dict[str, Any], filename: str) -> bool:
def validate_key_types(name: str, manifest: dict[str, Any], filename: str) -> bool:
"""Validation of manifest key types."""

# Manifest keys and their known types. Omitted keys are left unvalidated.
Expand Down Expand Up @@ -80,8 +80,8 @@ def validate_key_types(name: str, manifest: Dict[str, Any], filename: str) -> bo


def validate_type(
name: str, property: Dict[str, Any], filename: str
) -> Tuple[bool, Optional[str]]: # noqa: A002
name: str, property: dict[str, Any], filename: str
) -> tuple[bool, str | None]: # noqa: A002
"""Ensure property type keu is present and among expected values."""
passed = True
type_found = None
Expand All @@ -102,7 +102,7 @@ def validate_type(


def validate_list_item_types(
name: str, manifest: Dict[str, Any], filename: str
name: str, manifest: dict[str, Any], filename: str
) -> bool:
"""Validation of list member items."""

Expand Down Expand Up @@ -131,7 +131,7 @@ def validate_list_item_types(


def validate_default(
name: str, prop: Dict[str, Any], type_found: Optional[str], filename: str
name: str, prop: dict[str, Any], type_found: str | None, filename: str
) -> bool:
"""Ensure that default values have the expected type."""
passed = True
Expand All @@ -151,7 +151,7 @@ def validate_default(
return passed


def validate_urls(name: str, prop: Dict[str, Any], filename: str) -> bool:
def validate_urls(name: str, prop: dict[str, Any], filename: str) -> bool:
"""Ensure that URL values are actual URLs."""
passed = True

Expand All @@ -167,7 +167,7 @@ def validate_urls(name: str, prop: Dict[str, Any], filename: str) -> bool:
return passed


def validate_properties(properties: Dict[str, Any], filename: str) -> bool:
def validate_properties(properties: dict[str, Any], filename: str) -> bool:
"""Given a list of properties, run validation on their contents."""
passed = True

Expand Down Expand Up @@ -206,7 +206,7 @@ def validate_properties(properties: Dict[str, Any], filename: str) -> bool:
return passed


def main(argv: Optional[List[str]] = None) -> int:
def main(argv: list[str] | None = None) -> int:
"""Main process."""

# Parse command line arguments.
Expand Down
3 changes: 1 addition & 2 deletions pre_commit_macadmin_hooks/check_jamf_profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import argparse
import plistlib
from typing import List, Optional
from xml.parsers.expat import ExpatError


Expand All @@ -17,7 +16,7 @@ def build_argument_parser() -> argparse.ArgumentParser:
return parser


def main(argv: Optional[List[str]] = None) -> int:
def main(argv: list[str] | None = None) -> int:
"""Main process."""

# Parse command line arguments.
Expand Down
3 changes: 1 addition & 2 deletions pre_commit_macadmin_hooks/check_jamf_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"""Check Jamf scripts for common issues."""

import argparse
from typing import List, Optional

from pre_commit_macadmin_hooks.util import validate_shebangs

Expand All @@ -23,7 +22,7 @@ def build_argument_parser() -> argparse.ArgumentParser:
return parser


def main(argv: Optional[List[str]] = None) -> int:
def main(argv: list[str] | None = None) -> int:
"""Main process."""

# Parse command line arguments.
Expand Down
3 changes: 1 addition & 2 deletions pre_commit_macadmin_hooks/check_munki_pkgsinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import os
import plistlib
from pathlib import Path
from typing import List, Optional
from xml.parsers.expat import ExpatError

from pre_commit_macadmin_hooks.util import (
Expand Down Expand Up @@ -89,7 +88,7 @@ def _check_case_sensitive_path(path: str) -> bool:
p = p.parent


def main(argv: Optional[List[str]] = None) -> int:
def main(argv: list[str] | None = None) -> int:
"""Main process."""

# Typical extensions for installer packages.
Expand Down
3 changes: 1 addition & 2 deletions pre_commit_macadmin_hooks/check_munkiadmin_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import argparse
import os
from typing import List, Optional

from pre_commit_macadmin_hooks.util import validate_shebangs

Expand All @@ -24,7 +23,7 @@ def build_argument_parser() -> argparse.ArgumentParser:
return parser


def main(argv: Optional[List[str]] = None) -> int:
def main(argv: list[str] | None = None) -> int:
"""Main process."""

# Parse command line arguments.
Expand Down
6 changes: 3 additions & 3 deletions pre_commit_macadmin_hooks/check_munkipkg_buildinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import argparse
import json
import plistlib
from typing import Any, Dict, List, Optional
from typing import Any
from xml.parsers.expat import ExpatError

import ruamel.yaml
Expand All @@ -29,7 +29,7 @@ def build_argument_parser() -> argparse.ArgumentParser:
return parser


def validate_buildinfo_key_types(buildinfo: Dict[str, Any], filename: str) -> bool:
def validate_buildinfo_key_types(buildinfo: dict[str, Any], filename: str) -> bool:
"""Ensure build-info files contain the proper types."""

# Pkginfo keys and their known types. Omitted keys are left unvalidated.
Expand Down Expand Up @@ -62,7 +62,7 @@ def validate_buildinfo_key_types(buildinfo: Dict[str, Any], filename: str) -> bo
return passed


def main(argv: Optional[List[str]] = None) -> int:
def main(argv: list[str] | None = None) -> int:
"""Main process."""

# Parse command line arguments.
Expand Down
3 changes: 1 addition & 2 deletions pre_commit_macadmin_hooks/check_outset_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import argparse
import os
from typing import List, Optional

from pre_commit_macadmin_hooks.util import validate_shebangs

Expand All @@ -24,7 +23,7 @@ def build_argument_parser() -> argparse.ArgumentParser:
return parser


def main(argv: Optional[List[str]] = None) -> int:
def main(argv: list[str] | None = None) -> int:
"""Main process."""

# Parse command line arguments.
Expand Down
3 changes: 1 addition & 2 deletions pre_commit_macadmin_hooks/check_plists.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import argparse
import plistlib
from typing import List, Optional
from xml.parsers.expat import ExpatError


Expand All @@ -17,7 +16,7 @@ def build_argument_parser() -> argparse.ArgumentParser:
return parser


def main(argv: Optional[List[str]] = None) -> int:
def main(argv: list[str] | None = None) -> int:
"""Main process."""

# Parse command line arguments.
Expand Down
10 changes: 5 additions & 5 deletions pre_commit_macadmin_hooks/check_preference_manifests.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import argparse
import plistlib
from datetime import datetime
from typing import Any, Dict, List, Optional, Tuple
from typing import Any
from xml.parsers.expat import ExpatError

from pre_commit_macadmin_hooks.util import PLIST_TYPES
Expand Down Expand Up @@ -40,8 +40,8 @@ def build_argument_parser() -> argparse.ArgumentParser:


def validate_required_keys(
input_dict: Dict[str, Any],
required_keys: Tuple[str, ...],
input_dict: dict[str, Any],
required_keys: tuple[str, ...],
dict_name: str,
filename: str,
) -> bool:
Expand All @@ -54,7 +54,7 @@ def validate_required_keys(
return passed


def validate_manifest_key_types(manifest: Dict[str, Any], filename: str) -> bool:
def validate_manifest_key_types(manifest: dict[str, Any], filename: str) -> bool:
"""Validation of manifest key types."""

# manifest keys and their known types. Omitted keys are left un-validated.
Expand Down Expand Up @@ -410,7 +410,7 @@ def validate_subkeys(subkeys, filename):
return passed


def main(argv: Optional[List[str]] = None) -> int:
def main(argv: list[str] | None = None) -> int:
"""Main process."""

# Parse command line arguments.
Expand Down
Loading
Loading