Skip to content

Commit

Permalink
Remove click, requests. Add jsonargparse, httpx, loguru
Browse files Browse the repository at this point in the history
  • Loading branch information
duksosleepy committed Jul 27, 2024
1 parent 2660852 commit 0ec8f6b
Show file tree
Hide file tree
Showing 8 changed files with 1,171 additions and 489 deletions.
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.11.1
3.12.2
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# hypermodern-python
Modern python environment

poetry, pyenv, pytest, pytest-cov, pytest-mock, nox, flake8 (and plugins), black, safety, pre-commit, mypy, pytype (or pyre, pyright), desert, marshmallow, yypeguard,
poetry, pyenv, pytest, pytest-cov, pytest-mock, nox, flake8 (and plugins), black, safety, pre-commit, mypy, pytype (or pyre, pyright), desert, marshmallow, typeguard,
sphinx, sphinx-autodoc-typehints, git actions, codecov.

And important, run in python v3.11
And important, run in python v3.12
1,470 changes: 1,016 additions & 454 deletions poetry.lock

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "hypermodern-python"
version = "0.1.0"
version = "0.2.0"
description = "My python modern config"
authors = ["Duk <[email protected]>"]
license = "MIT"
Expand All @@ -11,12 +11,14 @@ documentation = "https://hypermodern-python.readthedocs.io"


[tool.poetry.dependencies]
python = "^3.11"
click = "^8.1.3"
requests = "^2.28.2"
python = "^3.12"
safety-db = "^2021.7.17"
desert = "^2022.9.22"
marshmallow = "^3.19.0"
codecov = "^2.1.13"
httpx = "^0.27.0"
jsonargparse = {extras = ["all"], version = "^4.32.0"}
loguru = "^0.7.2"


[tool.poetry.group.dev.dependencies]
Expand Down
3 changes: 2 additions & 1 deletion src/hypermodern_python/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
"""The hypermodern Python project."""
__version__ = "0.1.0"

__version__ = "0.2.0"
25 changes: 11 additions & 14 deletions src/hypermodern_python/console.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
"""Command-line interface."""

import textwrap

import click
from prettier import cprint

from . import wikipedia


def cmd():
from jsonargparse import CLI

from . import __version__, wikipedia
CLI(wikipedia.Fetcher)


@click.command()
@click.option(
"--language",
"-l",
default="en",
help="Language edition of Wikipedia",
metavar="LANG",
show_default=True,
)
@click.version_option(version=__version__)
def main(language: str) -> None:
"""The hypermodern Python project."""
page = wikipedia.random_page(language=language)
click.secho(page.title, fg="green")
click.echo(textwrap.fill(page.extract))
cprint(page.title, fg="g")
cprint(textwrap.fill(page.extract))
71 changes: 71 additions & 0 deletions src/hypermodern_python/prettier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import os

# System call
os.system("")


def cprint(fmt, fg=None, bg=None, style=None):
"""
Colour-printer.
cprint( 'Hello!' ) # normal
cprint( 'Hello!', fg='g' ) # green
cprint( 'Hello!', fg='r', bg='w', style='bx' ) # bold red blinking on white
List of colours (for fg and bg):
k black
r red
g green
y yellow
b blue
m magenta
c cyan
w white
List of styles:
b bold
i italic
u underline
s strikethrough
x blinking
r reverse
y fast blinking
f faint
h hide
"""

COLCODE = {
"k": 0, # black
"r": 1, # red
"g": 2, # green
"y": 3, # yellow
"b": 4, # blue
"m": 5, # magenta
"c": 6, # cyan
"w": 7, # white
}

FMTCODE = {
"b": 1, # bold
"f": 2, # faint
"i": 3, # italic
"u": 4, # underline
"x": 5, # blinking
"y": 6, # fast blinking
"r": 7, # reverse
"h": 8, # hide
"s": 9, # strikethrough
}

# properties
props = []
if isinstance(style, str):
props = [FMTCODE[s] for s in style]
if isinstance(fg, str):
props.append(30 + COLCODE[fg])
if isinstance(bg, str):
props.append(40 + COLCODE[bg])

# display
props = ";".join([str(x) for x in props])
if props:
print("\x1b[%sm%s\x1b[0m" % (props, fmt))
else:
print(fmt)
75 changes: 62 additions & 13 deletions src/hypermodern_python/wikipedia.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
"""Client for the Wikipedia REST API, version 1."""
import click

import requests

from dataclasses import dataclass
import asyncio
from dataclasses import dataclass, field

import desert

import httpx
import marshmallow
from loguru import logger

API_URL: str = "https://{language}.wikipedia.org/api/rest_v1/page/random/summary"
API_URL: str = (
"https://{language}.wikipedia.org/api/rest_v1/page/random/summary"
)


@dataclass
Expand All @@ -28,7 +29,40 @@ class Page:
schema = desert.schema(Page, meta={"unknown": marshmallow.EXCLUDE})


def random_page(language: str = "en") -> Page:
@dataclass(slots=True)
class Fetcher:
url: str
timeout: float | None = None

# These two are marked 'init=False' so they do not show up in the constructor # noqa: E501
# logic because the user doesn't need the ability to initialize these values since # noqa: E501
# they a.) have defaults and b.) are internal implementation details.
client: httpx.Client = field(default_factory=httpx.Client, init=False)
results: list[str] = field(default_factory=list, init=False)

def __post_init__(self) -> None:
# Attach our timeout to our instance httpx client
# (note how we need to do this in __post_init__ since we can't access
# peer instance variables in the `field()` defaults above because there's # noqa: E501
# no `self` existing there yet)
self.client.timeout = self.timeout

def fetch(self) -> None:
logger.info("[{}] Fetching with timeout {}", self.url, self.timeout)

self.results.append(self.client.get(self.url))

logger.info(
"[{} :: {}] Found results: {}",
self.url,
len(self.results),
self.results,
)


async def random_page(
client: httpx.AsyncClient(), language: str = "en"
) -> Page:
"""Return a random page.
Performs a GET request to the /page/random/summary endpoint.
Expand All @@ -52,10 +86,25 @@ def random_page(language: str = "en") -> Page:
url = API_URL.format(language=language)

try:
with requests.get(url) as response:
response.raise_for_status()
data = response.json()
return schema.load(data)
except (requests.RequestException, marshmallow.ValidationError) as error:
response = await client.get(url)
data = response.json()
return schema.load(data)
except marshmallow.ValidationError as error:
message = str(error)
raise click.ClickException(message)
raise message


async def main() -> None:
async with httpx.AsyncClient() as client:
tasks = []
for number in range(1, 10):
tasks.append(
asyncio.ensure_future(random_page(client, language="en"))
)

original_page = await asyncio.gather(*tasks)
for page in original_page:
print(page)


asyncio.run(main())

0 comments on commit 0ec8f6b

Please sign in to comment.