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
65 changes: 65 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: CI

on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
push:
branches: [main]

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
checks:
name: Lint / Format Check / Tests
runs-on: ubuntu-latest
if: ${{ github.event_name != 'push' || github.ref == 'refs/heads/main' }}

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python
id: py
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install Poetry
uses: abatilo/actions-poetry@v3
with:
poetry-version: "2.2.0"

- name: Enable in-project venv
run: poetry config virtualenvs.in-project true

- name: Cache Poetry venv
uses: actions/cache@v4
with:
path: .venv
key: venv-${{ runner.os }}-${{ steps.py.outputs.python-version }}-${{ hashFiles('poetry.lock') }}
restore-keys: |
venv-${{ runner.os }}-

- name: Install dependencies
run: poetry install --no-interaction

# ---- Static checks (no file modifications in CI) ----
- name: Ruff lint
run: poetry run ruff check .

- name: Ruff format (check only)
run: poetry run ruff format --check .

# ---- Run tests with coverage threshold ----
- name: Run tests with coverage
run: |
poetry run pytest \
-q --maxfail=1 --disable-warnings \
--cov=src --cov-report=term-missing \
--cov-report=xml:coverage.xml \
--cov-fail-under=100
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@

**Workflow**:
1. Fork this repository to your own GitHub account.
2. Create a new branch from `develop` and name it `feature/student1name_student2name`.
3. Clone the repo to AWS VM.
4. Implement the functions until all `pytest` tests pass.
5. Push your code to your Github repo.
2. Clone the repo to AWS VM.
3. Run poetry install to install dependencies
4. Run poetry run pre-commit install to install the pre-commit hook.
5. Create a new branch from `develop` and name it `feature/student1name_student2name`.
7. Implement the functions until all `pytest` tests pass.
8. Make the pre-commit checks all pass and commit the code.
9. Push your code to your Github repo.
5. Submit a Pull Request back to the `develop` branch of the main repo. CI must pass.
6. Wait for code review and grading.
4 changes: 2 additions & 2 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@ dependencies = [
"pre-commit (>=4.3.0,<5.0.0)"
]

[tool.poetry]
name = "arithmetic"
version = "0.1.0"
description = "Toy arithmetic package"
authors = ["Your Name <you@example.com>"]
readme = "README.md"
packages = [{ include = "src/arithmetic" }]

[tool.poetry.dependencies]
python = "^3.12"


[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
Expand Down
48 changes: 16 additions & 32 deletions src/arithmetic/arithmetic.py
Original file line number Diff line number Diff line change
@@ -1,46 +1,30 @@
"""arithmetic functions."""
"""Arithmetic functions used in the assignment."""

from __future__ import annotations


def add_numbers(a: int, b: int) -> int:
"""Return the sum of two integers.

Args:
a: first integer
b: second integer

Returns:
Sum of a and b.
"""
raise NotImplementedError
"""Return the sum of two integers."""
return a + b


def factorial(n: int) -> int:
"""Compute the factorial of n.

Args:
n: non-negative integer

Returns:
n! as int
"""Compute n! for a non-negative integer n.

Raises:
ValueError: if n is negative
ValueError: if n is negative.
"""
raise NotImplementedError
if n < 0:
raise ValueError("factorial is undefined for negative integers")
result = 1
for i in range(2, int(n) + 1):
result *= i
return result


def is_prime(n: int) -> bool:
"""Check whether n is a prime number.

A prime number is an integer greater than 1 that has no positive
divisors other than 1 and itself.

Args:
n: integer to test

Returns:
True if n is prime; otherwise False.
"""
raise NotImplementedError
"""Return True if n is prime, else False."""
if n <= 1:
return False
# one-liner makes coverage hit this branch for all cases
return not any(n % d == 0 for d in range(2, int(n**0.5) + 1))