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

on:
pull_request:
push:

jobs:
lint:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.11"

- run: pip install -e .[dev]

- run: ruff check .

- run: ruff format --check .
3 changes: 2 additions & 1 deletion README.hi.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
![License](https://img.shields.io/badge/license-MIT-green)
![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen)
![good first issues](https://img.shields.io/badge/good%20first%20issues-30%2B-orange)
[![Ruff](https://github.com/codepiyusss/open_source_issue_contribution/actions/workflows/ruff.yml/badge.svg)](https://github.com/codepiyusss/open_source_issue_contribution/actions/workflows/ruff.yml)

## 🎯 यह क्या है?

Expand Down Expand Up @@ -70,4 +71,4 @@
## 📄 लाइसेंस (License)
MIT। LICENSE देखें।

⭐ अगर इससे आपको मदद मिली हो, तो इस रिपॉजिटरी को स्टार (star) दें और अपने उन दोस्तों के साथ शेयर करें जो ओपन सोर्स शुरू करना चाहते हैं!
⭐ अगर इससे आपको मदद मिली हो, तो इस रिपॉजिटरी को स्टार (star) दें और अपने उन दोस्तों के साथ शेयर करें जो ओपन सोर्स शुरू करना चाहते हैं!
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
![License](https://img.shields.io/badge/license-MIT-green)
![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen)
![good first issues](https://img.shields.io/badge/good%20first%20issues-30%2B-orange)
[![Ruff](https://github.com/codepiyusss/open_source_issue_contribution/actions/workflows/ruff.yml/badge.svg)](https://github.com/codepiyusss/open_source_issue_contribution/actions/workflows/ruff.yml)

## 🎯 What is this?

Expand Down
1 change: 1 addition & 0 deletions fixit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
"""fixit - a tiny Python CLI toolbox made for practicing open source contributions."""

__version__ = "0.1.0"
1 change: 1 addition & 0 deletions fixit/__main__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import sys

from fixit.cli import main

sys.exit(main())
22 changes: 18 additions & 4 deletions fixit/cli.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Command line entry point: `fixit <command>`."""

import argparse
import sys
import uuid
Expand Down Expand Up @@ -94,9 +95,11 @@ def build_parser() -> argparse.ArgumentParser:
args = parser.parse_args(["wc", "hello world"])
assert args.command == "wc"
"""
parser = argparse.ArgumentParser(prog="fixit", description="A tiny toolbox to practice open source.")
parser = argparse.ArgumentParser(
prog="fixit", description="A tiny toolbox to practice open source."
)
parser.add_argument("--version", action="version", version=f"fixit {__version__}")
sub = parser.add_subparsers(dest="command", required=True)
sub = parser.add_subparsers(dest="command")

wc = sub.add_parser("wc", help="count words, lines and characters")
wc.add_argument("text", nargs="?")
Expand Down Expand Up @@ -127,7 +130,9 @@ def build_parser() -> argparse.ArgumentParser:

top = sub.add_parser("top-words", help="show the most frequent words")
top.add_argument("text")
top.add_argument("--n", type=int, default=3, help="number of words to show (default: 3)")
top.add_argument(
"--n", type=int, default=3, help="number of words to show (default: 3)"
)

return parser

Expand All @@ -138,8 +143,17 @@ def main(argv=None) -> int:
Example:
main(["convert", "100", "c2f"]) prints 212.0 and returns 0.
"""
parser = build_parser()

if argv is None:
argv = sys.argv[1:]

if not argv:
parser.print_help()
return 0

try:
args = build_parser().parse_args(argv)
args = parser.parse_args(argv)
COMMAND_TABLE[args.command](args)
return 0
except ValueError as e:
Expand Down
1 change: 1 addition & 0 deletions fixit/jsonfmt.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""JSON pretty-printer."""

import json


Expand Down
5 changes: 4 additions & 1 deletion fixit/password.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
"""Random password generator."""

import random
import string


def generate(length: int = 12, use_digits: bool = True, use_symbols: bool = False) -> str:
def generate(
length: int = 12, use_digits: bool = True, use_symbols: bool = False
) -> str:
"""Generate a random password of the given length.

Example:
Expand Down
10 changes: 3 additions & 7 deletions fixit/textutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@ def is_palindrome(text: str) -> bool:
is_palindrome("hello") returns False.
"""

cleaned = "".join(
ch.lower()
for ch in text
if ch.isalnum()
)
cleaned = "".join(ch.lower() for ch in text if ch.isalnum())
return cleaned == cleaned[::-1]


Expand All @@ -25,7 +21,7 @@ def reverse_words(text: str) -> str:
"""
return " ".join(reversed(text.split()))


def slugify(text: str) -> str:
"""Convert text into a URL-friendly slug.

Expand All @@ -37,4 +33,4 @@ def slugify(text: str) -> str:
text = text.lower()
text = re.sub(r"[^\w\s-]", "", text)
text = re.sub(r"[\s_-]+", "-", text)
return text.strip("-")
return text.strip("-")
5 changes: 3 additions & 2 deletions fixit/wordcount.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""Word, line and character counting."""

from __future__ import annotations

import re
from collections import Counter
from typing import List, Tuple


def count_words(text: str) -> int:
Expand Down Expand Up @@ -35,7 +36,7 @@ def count_chars(text: str) -> int:
return len(text)


def top_words(text: str, n: int = 3) -> List[Tuple[str, int]]:
def top_words(text: str, n: int = 3) -> list[tuple[str, int]]:
"""Return up to n most frequent words and their counts.

Words are matched case-insensitively; punctuation is treated as a
Expand Down
15 changes: 12 additions & 3 deletions tests/test_convert.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import pytest
from fixit.convert import (celsius_to_fahrenheit, fahrenheit_to_celsius,
km_to_miles, miles_to_km)

from fixit.convert import (
celsius_to_fahrenheit,
fahrenheit_to_celsius,
km_to_miles,
miles_to_km,
)


def test_c_to_f():
Expand All @@ -14,18 +19,22 @@ def test_f_to_c():
def test_km_to_miles():
assert km_to_miles(10) == pytest.approx(6.21371, rel=1e-4)


def test_miles_to_km():
assert miles_to_km(1) == pytest.approx(1.609344)


def test_negative_celsius():
assert celsius_to_fahrenheit(-20)==-4
assert celsius_to_fahrenheit(-20) == -4


def test_zero_celsius():
assert celsius_to_fahrenheit(0) == 32


def test_absolute_zero():
assert celsius_to_fahrenheit(-273.15) == pytest.approx(-459.67)


def test_float_km_to_miles():
assert km_to_miles(1.5) == pytest.approx(0.932056788)
2 changes: 2 additions & 0 deletions tests/test_errors.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from fixit import cli


def test_invalid_json_returns_1():
assert cli.main(["json", "{bad"]) == 1


def test_invalid_password_returns_1():
assert cli.main(["password", "--length", "0"]) == 1
1 change: 1 addition & 0 deletions tests/test_jsonfmt.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pytest

from fixit.jsonfmt import format_json


Expand Down
1 change: 1 addition & 0 deletions tests/test_password.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pytest

from fixit.password import generate


Expand Down
3 changes: 2 additions & 1 deletion tests/test_textutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ def test_palindrome_ignores_punctuation():
def test_reverse_words_extra_spaces():
assert reverse_words("hello world") == "world hello"


def test_slugify_basic():
assert slugify("Hello World!") == "hello-world"


def test_slugify_punctuation_and_spaces():
assert slugify("Open Source, Project!") == "open-source-project"
assert slugify("Open Source, Project!") == "open-source-project"
2 changes: 0 additions & 2 deletions tests/test_uuid.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from uuid import UUID

import pytest

from fixit.cli import main


Expand Down
1 change: 1 addition & 0 deletions tests/test_wordcount.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pytest

from fixit.wordcount import count_chars, count_lines, count_words, top_words


Expand Down
Loading