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
61 changes: 61 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: CI / CD - Morse Code

on:
pull_request:
branches: [pipfile-experiment]
push:
tags: ["v*"]
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 5
strategy:
matrix:
python-version: ["3.10", "3.11"]

steps:
- uses: actions/checkout@v4

- name: Install Python and Pipenv
uses: kojoru/prepare-pipenv@v1
with:
python-version: ${{ matrix.python-version }}


- name: Turn on 'editable' mode
run: |
pipenv install -e .

- name: Run pytest
run: |
pipenv install pytest
pipenv --venv
pipenv run python -m pytest

deliver:
if: github.event_name != 'pull_request'
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
with:
python-version: "3.10"

- name: Build package
run: |
pipenv install build
pipenv run python -m build .

# publish to PyPI Test server
# - name: Publish to TestPyPI
# uses: pypa/gh-action-pypi-publish@release/v1
# with:
# password: ${{ secrets.TEST_PYPI_API_TOKEN }}
# repository-url: https://test.pypi.org/legacy/
13 changes: 13 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
pytest = "*"
morse-code = {file = ".", editable = true}

[dev-packages]

[requires]
python_version = "3.10"
66 changes: 66 additions & 0 deletions Pipfile.lock

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

Empty file added examples/demo.py
Empty file.
31 changes: 31 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "morse_code"
version = "0.1.0"
description = "A Python package for encoding and decoding Morse code."
readme = "README.md"
requires-python = ">=3.10"
license = { file = "LICENSE" }
authors = [{ name = "Team Lumen" }]
keywords = ["python", "morse code", "encoder", "decoder"]
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent"
]

[project.urls]
Homepage = "https://github.com/swe-students-fall2025/3-python-package-team_lumen"
Issues = "https://github.com/swe-students-fall2025/3-python-package-team_lumen/issues"

[tool.setuptools]
package-dir = {"" = "src"}

[tool.setuptools.packages.find]
where = ["src"]

[project.scripts]
morse_code = "morse_code.core:cli"
27 changes: 27 additions & 0 deletions src/morseify/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""
Morse Code Package
A Python package for encoding and decoding Morse code with additional utilities.
"""

from morseify.core import (
encode,
decode,
is_valid
)
from morseify.normalize import (
normalize_text,
normalize_code
)
from morseify.explain import explain
from morseify.quiz import quiz

__all__ = [
'encode',
'decode',
'is_valid',
'normalize_text',
'normalize_code',
'explain',
'quiz'
]

40 changes: 40 additions & 0 deletions src/morseify/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from .core import encode, decode, is_valid
from .explain import explain


def main():
print("Morse Code Encode/Decode Test")
# Test cases
test_cases = [
"HELLO",
"HELLO WORLD",
"SOS",
"PYTHON",
"123",
"A1B2C3"
]

for text in test_cases:
encoded = encode(text)
decoded = decode(encoded)

print(f"\nOriginal: '{text}'")
print(f"Encoded : '{encoded}'")
print(f"Decoded : '{decoded}'")

# Check if round-trip works
if decoded == text:
print("✓ Round-trip successful!")
else:
print(f"✗ Round-trip failed! Expected: '{text}'")

# Uncomment for interactive mode
# print("\nInteractive mode:")
# text = input("Enter text to encode: ")
# encoded = encode(text)
# print(f"Encoded: {encoded}")
# decoded = decode(encoded)
# print(f"Decoded: {decoded}")

if __name__ == "__main__":
main()
98 changes: 98 additions & 0 deletions src/morseify/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
from morseify.mapping import LETTER_TO_MORSE
from morseify.mapping import MORSE_TO_LETTER

def encode(text):
"""
Convert English text to morse code.

Args:
text: English text string to encode

Returns:
Morse code string
"""

# Normalize the text first(delete after normalize function is implemented)
if text is None:
return None
normalized = text.upper().strip()

# change to this:
# normalized = normalize_text(text)

# Convert each character to morse code
result = []
for char in normalized:
if char == ' ':
# Space between words becomes ' / '
result.append('/')
else:
# Get morse code for character
morse_char = LETTER_TO_MORSE.get(char, '')
if morse_char:
result.append(morse_char)

# Join with spaces between letters
return ' '.join(result)


def decode(morse_code):
"""
Convert morse code to English text.

Args:
morse_code: Morse code string to decode

Returns:
English text string
"""
# check if the morse code is valid
# valid_morse = is_valid(morse_code)

valid_morse = morse_code

# Split morse code by spaces to get individual morse sequences
morse_words = valid_morse.split(' ')
# print(morse_words)

result = []
for i in morse_words:
if i == '':
# Skip empty sequences (multiple spaces)
continue
elif i == '/':
# Word separator
result.append(' ')
else:
# Look up the morse sequence in the dictionary
letter = MORSE_TO_LETTER.get(i, '')
result.append(letter)

return ''.join(result)




def is_valid(morse_code):
# check if morse_code is str or empty
try:
morse_code = morse_code.strip()
except AttributeError:
return False

if not morse_code:
return False

#check if valid chars or sequence
validchars = {'.', '-', '/', ' '}
if any(ch not in validchars for ch in morse_code):
return False

for seq in morse_code.split(' '):
if not seq or seq == '/':
continue
if seq not in MORSE_TO_LETTER:
return False
return True


3 changes: 3 additions & 0 deletions src/morseify/explain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
def explain(morse_message):
# TODO: Implement explanation logic
pass
13 changes: 13 additions & 0 deletions src/morseify/mapping.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
LETTER_TO_MORSE = {
"A": ".-", "B": "-...", "C": "-.-.", "D": "-..", "E": ".",
"F": "..-.", "G": "--.", "H": "....", "I": "..", "J": ".---",
"K": "-.-", "L": ".-..", "M": "--", "N": "-.", "O": "---",
"P": ".--.", "Q": "--.-", "R": ".-.", "S": "...", "T": "-",
"U": "..-", "V": "...-", "W": ".--", "X": "-..-", "Y": "-.--",
"Z": "--..",
"0": "-----", "1": ".----", "2": "..---", "3": "...--", "4": "....-",
"5": ".....", "6": "-....", "7": "--...", "8": "---..", "9": "----.",
".": ".-.-.-", ",": "--..--", "?": "..--..", "/": "-..-.", "-": "-....-",
"(": "-.--.", ")": "-.--.-"
}
MORSE_TO_LETTER = {v: k for k, v in LETTER_TO_MORSE.items()}
8 changes: 8 additions & 0 deletions src/morseify/normalize.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
def normalize_text(text):
# TODO: Implement text normalization logic
pass


def normalize_code(morse_code):
# TODO: Implement code normalization logic
pass
3 changes: 3 additions & 0 deletions src/morseify/quiz.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
def quiz(morse_code):
# TODO: Implement quiz logic
pass
2 changes: 2 additions & 0 deletions tests/test_decode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def test_encode():
assert True
2 changes: 2 additions & 0 deletions tests/test_encode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def test_decode():
assert True
2 changes: 2 additions & 0 deletions tests/test_is_valid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def test_is_valid():
assert True
Loading