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
40 changes: 40 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: CI / CD
on: []
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 5
strategy:
matrix:
python-version: ["3.9", "3.11"]
steps:
- uses: actions/checkout@v4
- name: Install Python, pipenv and Pipfile packages
uses: kojoru/prepare-pipenv@v1
with:
python-version: ${{ matrix.python-version }}
- name: Turn on 'editable' mode
run: |
pipenv install -e .
- name: Test with pytest
run: |
pipenv install pytest
pipenv --venv
pipenv run python -m pytest
deliver:
needs: [build]
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- name: Install Python, pipenv and Pipfile packages
uses: kojoru/prepare-pipenv@v1
- name: Build package
run: |
pipenv install build
pipenv run python -m build .
- name: Publish to PyPI test server
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
repository-url: https://test.pypi.org/legacy/
14 changes: 14 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
twine = "*"
build = "*"

[dev-packages]

[requires]
python_version = "3.11"
python_full_version = "3.11.0"
375 changes: 375 additions & 0 deletions Pipfile.lock

Large diffs are not rendered by default.

177 changes: 177 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,180 @@
# Python Package Exercise

An exercise to create a Python package, build it, test it, distribute it, and use it. See [instructions](./instructions.md) for details.

# Halloween Theme Package

Read a scary story or generate a fun drawing!

Teammates:
Evelynn Mak (evemak)
Leo Li(https://github.com/LiShangcheng)
Harrison Gao
Christine Jin (https://github.com/Christine-Jin)
<<<<<<< Updated upstream
=======

---

## Introduction

Pylloween is designed as a lightweight package for practicing:

- Python package structure and modularity
- Unit testing with `pytest`
- Continuous Integration and Delivery via GitHub Actions
- PyPI publishing using `build` and `twine`

---

## Features

```
________________________________________________________________________
< I'm haunting your terminal! Zelle me 50 or I'll overflow your stack. >
------------------------------------------------------------------------

⣴⣿⣿⣿⣦
⣰⣿⡟⢻⣿⡟⢻⣧
⣰⣿⣿⣇⣸⣿⣇⣸⣿
⣴⣿⣿⣿⣿⠟⢻⣿⣿⣿
⣠⣾⣿⣿⣿⣿⣿⣤⣼⣿⣿⠇
⢿⡿⢿⣿⣿⣿⣿⣿⣿⣿⡿⠀
⠈⠿⠿⠋⠙⢿⣿⡿⠁

```

```
;::;;::;,
;::;;::;;,
;;:::;;::;;,
.vnmmnv%vnmnv%,.;;;:::;;::;;, .,vnmnv%vnmnv,
vnmmmnv%vnmmmnv%vnmmnv%;;;;;;;%nmmmnv%vnmmnv%vnmmnv
vnmmnv%vnmmmmmnv%vnmmmmmnv%;:;%nmmmmmmnv%vnmmmnv%vnmmmnv
vnmmnv%vnmmmmmnv%vnmmmmmmmmnv%vnmmmmmmmmnv%vnmmmnv%vnmmmnv
vnmmnv%vnmmmmmnv%vnmmmmmmmmnv%vnmmmmmmmmmmnv%vnmmmnv%vnmmmnv
vnmmnv%vnmmmmmnv%vnmm;mmmmmmnv%vnmmmmmmmm;mmnv%vnmmmnv%vnmmmnv,
vnmmnv%vnmmmmmnv%vnmm;' mmmmmnv%vnmmmmmmm;' mmnv%vnmmmnv%vnmmmnv
vnmmnv%vnmmmmmnv%vn;; mmmmnv%vnmmmmmm;; nv%vnmmmmnv%vnmmmnv
vnmmnv%vnmmmmmmnv%v;; mmmnv%vnmmmmm;; v%vnmmmmmnv%vnmmmnv
vnmmnv%vnmmmmmmnv%vnmmmmmmmmm;; mmmmmmmmmnv%vnmmmmmmnv%vnmmmnv
vnmmnv%vnmmmmmmnv%vnmmmmmmmmmm;; mmmmmmmmmmnv%vnmmmmmmnv%vnmmmnv
vnmmnv%vnmmmmm nv%vnmmmmmmmmmmnv;, mmmmmmmmmmmmnv%vn;mmmmmnv%vnmmmnv
vnmmnv%vnmmmmm nv%vnmmmmmmmmmnv%;nmmmmmmmmmmmnv%vn; mmmmmnv%vnmmmnv
`vnmmnv%vnmmmm, v%vnmmmmmmmmmmnv%vnmmmmmmmmmmnv%v; mmmmnv%vnnmmnv'
vnmmnv%vnmmmm;, %vnmmmmmmmmmnv%vnmmmmmmmmmnv%;' mmmnv%vnmmmmnv
vnmmnv%vnmmmm;;, nmmm;' mmmm;;' mmmnv%vnmmmmnv'
`vnmmnv%vnmmmmm;;,. mmnv%v;, mmmmnv%vnmmmmnv'
`vnmmnv%vnmmmmmmnv%vnmmmmmmmmnv%vnmmmmmmnv%vnmmmmmnv%vnmmmmnv'
`vnmvn%vnmmmmmmnv%vnmmmmmmmnv%vnmmmmmnv%vnmmmmmnv%vnmmmnv'
`vn%vnmmmmmmn%:%vnmnmmmmnv%vnmmmnv%:%vnmmnv%vnmnv'

```

| Function | Description | Example |
| -------------------------------- | --------------------------------------------------------------- | --------------------------------- |
| `draw_ghost()` | Prints a random ASCII ghost | `plw.draw_ghost()` |
| `draw_pumpkin()` | Prints a random ASCII pumpkin | `plw.draw_pumpkin()` |
| `draw_bat()` | Prints a random ASCII bat | `plw.draw_bat()` |
| `draw_random()` | Prints a random Halloween symbol | `plw.draw_random()` |
| `ghost_say(message)` | Prints a ghost with a message bubble | `plw.ghost_say("HTK-G!")` |
| `ghost_story(length)` | Displays a ghost telling a story (`short`, `medium`, `long`) | `plw.ghost_story("short")` |
| `ghost_idea(genre)` | Ghost recommends a movie (`horror`, `comedy`, `cartoon`, `all`) | `plw.ghost_idea("horror")` |
| `get_horror(length)` | Returns a story string based on length | `plw.get_horror("medium")` |
| `get_movie_idea(genre)` | Returns a random movie title | `plw.get_movie_idea("comedy")` |
| `trick_or_treat(n, bag, seed)` | Returns sampled candies and counts`(picks, counts)` | `plw.trick_or_treat(10, seed=42)` |
---

## Installation

From TestPyPI:

```bash
pip install -i https://test.pypi.org/simple/ pylloween
```

<!--
From PyPI (after release):

```bash
pip install pylloween
``` -->

---

## Usage

### Import in Python

```python
import pylloween as plw

plw.ghost_say("Hello world!")
plw.ghost_story("medium")
print(plw.get_movie_idea("cartoon"))

plw.draw_pumpkin()

picks, counts = plw.trick_or_treat(n=12, seed=2025)
print(picks)
print(counts)
```

### Run via Command Line

```bash
python -m pylloween
```

### Run via Demo Script

```bash
python src/pylloween/main.py
```

---

## Running Tests

```bash
pip install pytest
pytest -v
```

---

## CI/CD Overview

This project has a continuous integration workflow that builds and runs unit tests automatically with every push of the code to GitHub.

---

## Project Structure

```
pylloween/
├── src/
│ └── pylloween/
│ ├── __init__.py
│ ├── __main__.py
│ ├── ghosts.py
│ ├── horrors.py
| ├── pumpkin.py
| └── treats.py
├── tests/
│ ├── test_ghosts.py
│ ├── test_horrors.py
| ├── test_pumpkin.py
| └── test_treats.py
├── pyproject.toml
└── .github/
└── workflows/
├── build.yaml
```

---

## License

GNU v3 License. See `LICENSE` for details.
>>>>>>> Stashed changes
40 changes: 40 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "pylloween"
<<<<<<< Updated upstream
description = "A silly Halloween-themed Python package 🎃"
version = "0.1.0"
=======
description = "A silly Halloween-themed Python package 🎃. Get some Horror Stories & Movie ideas."
version = "0.1.13"
>>>>>>> Stashed changes
authors = [
{ name="Harrison Gao", email="hg2655@nyu.edu" },
{ name="Evelynn", email="" },
{ name="Leo", email="" },
{ name="Christine", email="" },
]
license = { file = "LICENSE" }
readme = "README.md"
keywords = ["python", "package", "build", "tutorial"]
requires-python = ">=3.7"
classifiers = [
"Programming Language :: Python :: 3",

"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Operating System :: OS Independent",
]

[project.optional-dependencies]
dev = ["pytest"]

[project.urls]
"Homepage" = "https://github.com/swe-students-fall2025/3-python-package-team_zenith"
"Repository" = "https://github.com/swe-students-fall2025/3-python-package-team_zenith.git"
"Bug Tracker" = "https://github.com/swe-students-fall2025/3-python-package-team_zenith/issues"

[project.scripts]
examplepackagefb1258 = "examplepackagefb1258.__main__:main"
104 changes: 104 additions & 0 deletions src/data/horror_stories.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
story
I woke up to find a photo of myself sleeping—on my own phone.
The last sound I heard before waking up was my own voice calling my name.
"As I held the baby monitor, I realized I was the one whispering someone else’s lullaby."
"The mirror cracked, but the reflection only smiled."
He came home carrying flowers—though he’d died two weeks ago.
Every night the same shadow stood at the foot of my bed; one night it moved closer.
When I turned off the lights I saw the TV still playing—but no one was watching.
My cat curled up beside me and purred; then its eyes stared into the dark corner.
"I whispered 'I’m sorry' into the void—and the void whispered back, 'Thank you.'"
She told me she wasn’t afraid of the dark—until the darkness answered her.
My phone buzzed with a text from my wife; she was buried yesterday.
Someone knocked on my window from the tenth floor.
I watched the baby sleep peacefully until it opened my eyes.
"The reflection blinked, but I didn’t."
I keep hearing my mother calling me downstairs—but she’s sitting next to me.
I took a photo of the empty hallway; a hand waved back.
The voicemail was only breathing—but it came from my number.
The GPS kept saying 'You’ve arrived' long before I reached the house.
Something brushed my leg under the bed. I live alone.
"I kissed my husband goodnight, and he whispered, 'Who are you?'"
I locked the door and checked twice; someone locked it from the inside again.
The recording played my laughter—then another voice laughed with me.
My shadow stopped moving when I did.
The doll’s eyes were glass until they blinked.
I received an email from myself dated one year after my death.
"The lights flickered in Morse code, spelling my name."
"Every time I wash my hands, the water runs red for a moment."
"I told Alexa to turn off the lights. She said, 'But I’m not Alexa.'"
The portrait in the hallway aged overnight—just like me.
"I deleted the photo, but it keeps appearing on my lock screen."
"I sneezed, and someone whispered 'Bless you' from behind the mirror."
"I can still hear the heartbeat through the walls, though the house is empty."
My smartwatch says someone is holding my hand.
The music box only plays when no one is in the room.
The babysitter texted: 'Everything’s fine.' We don’t have a babysitter.
I found my diary rewritten in someone else’s handwriting.
"The elevator stopped between floors; a voice whispered, 'Finally, alone.'"
The footprints in the snow led to my door—but none led away.
"My voice assistant keeps asking, 'Shall I open the door now?'"
I keep deleting the same message: 'I see you.'
The grave I visited today had my name freshly carved on it.
The whispers stopped when I covered my ears—then started inside my head.
I thought I was humming alone until something harmonized.
I woke up from a nightmare to find the dream still watching me.
The house lights turn off one by one—except in the room I’m in.
"The photograph showed everyone smiling—except me, I wasn’t there."
The echo said my name twice.
I found a tooth in my soup. I live alone.
The ceiling fan spelled something with its creaks: 'RUN.'
I keep finding notes in my handwriting that I don’t remember writing.
"At 3:00 AM, the baby monitor whispered, 'He’s awake now.'"
"The voicemail from my dead sister said, 'Don’t come home.'"
My dog growled at the corner—then his tail wagged.
I can’t find the door I entered this room through.
"The voice said 'Turn around,' and I did—but there was still someone behind me."
I watched myself walk past the window.
My reflection mouthed a word I didn’t say: 'Soon.'
All the family portraits have a new person in them tonight.
I dreamt I was drowning and woke up coughing up water.
I opened the closet. Something closed it from the inside.
"The candle went out, but the shadow remained."
"I asked my son who he was talking to. He said, 'The man in your chair.'"
"The voicemail said, 'We’re here now.' It was my own voice."
"I turned off the baby monitor; the whisper said, 'You shouldn’t have done that.'"
"I tried to scream, but the recording stayed silent."
"My husband texted, 'I’m home.' The doorbell rang a minute later."
I found a mirror in the attic—my reflection was already smiling.
"I tucked my daughter into bed; she asked, 'Who’s sleeping next to me?'"
"The nightlight went out, but something was glowing under the bed."
I woke up to my cat purring on my chest—then I remembered she died last week.
"The man in my dream said, 'See you soon.' He was my doctor this morning."
The footprints on my ceiling are getting closer to my bed.
The basement door keeps unlocking itself every night at 2:17 AM.
I recorded white noise to fall asleep; I heard my name in the playback.
I took a selfie and saw someone standing behind me.
I looked out the window and saw myself walking up the driveway.
The doorbell camera shows someone knocking—from the inside.
The whispers stopped when I turned off the light—but not the breathing.
"I can’t find my phone, but something is typing on my laptop."
My favorite song started playing from an unplugged speaker.
I found handprints on the inside of my mirror.
"The voice on the radio said, 'Look behind you.'"
The lullaby stopped halfway through—then someone finished it in my voice.
"I turned off my alarm clock; it said, 'Don’t oversleep again.'"
The neighbor’s lights flicker in sync with my heartbeat.
"I looked at the stars, and one of them blinked back."
I was home alone when my phone got an AirDrop request labeled 'me.jpg'.
My reflection waved first.
I deleted the security footage; it uploaded itself again.
"The doll’s head turned toward me and whispered, 'Mommy?'"
I heard a knock on the coffin—before it was buried.
"The nursery mobile started spinning backwards, singing a name we never chose."
"The last text I got said, 'I’m outside.' Then the lights went out."
I set my phone to airplane mode; it still received a message from 'Unknown Passenger.'
I woke up cold because the blanket was tucked in around someone else.
My child’s imaginary friend just told me my secrets.
The lights flickered in Morse code: S-O-S.
I pressed the elevator button for floor 1—it went to floor 13.
"My wallpaper app keeps showing pictures of my bedroom, but messier."
The door creaks every time I breathe in.
I said goodnight to my roommate. She moved out last month.
I keep hearing typing in the next room. My laptop is in there.
I found a fingerprint inside my eye.
Empty file added src/pylloween/__init__.py
Empty file.
1 change: 1 addition & 0 deletions src/pylloween/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from pylloween import horrors
9 changes: 9 additions & 0 deletions src/pylloween/drawGhost.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"""
Returns a drawing of a ghost once the function is called
"""

def draw_ghost():

print( " ⣴⣿⣿⣿⣦"," ⣰⣿⡟⢻⣿⡟⢻⣧"," ⣰⣿⣿⣇⣸⣿⣇⣸⣿"," ⣴⣿⣿⣿⣿⠟⢻⣿⣿⣿","⣠⣾⣿⣿⣿⣿⣿⣤⣼⣿⣿⠇","⢿⡿⢿⣿⣿⣿⣿⣿⣿⣿⡿⠀"," ⠈⠿⠿⠋⠙⢿⣿⡿⠁",sep="\n")

draw_ghost()
1 change: 1 addition & 0 deletions src/pylloween/horrors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import random
Empty file added tests/__init__.py
Empty file.
Loading
Loading