Skip to content

Meg interest calculator #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Nov 19, 2022
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
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ repos:
entry: pyupgrade
language: system
types: [python]
args: [--py37-plus]
args: [--py310-plus]
- id: trailing-whitespace
name: Trim Trailing Whitespace
entry: trailing-whitespace-fixer
Expand Down
6 changes: 3 additions & 3 deletions CONTRIBUTING.MD
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ We try not to have strong boundaries in what kinds of contributions are accepted
- Adding meta-data

- adding tags to your example will help us organize this repository in a much more meaningful way. Example tags come at the beginning of your main `HTML` file in the form of a comment.
- you're also welcome to add your email or name or other forms of contact information in the header at the beginning of the file.
- you're also welcome to add your email or name or other forms of contact information in the header at the beginning of the file. For reference see the [example](examples/hello_world.html).

TODO Add back in `See the example examples/hello_world.html`
TODO Add back in `See the example examples/hello_world.html`

- Adding docs

Expand All @@ -54,7 +54,7 @@ The PyScript Collective also welcomes contributions like blog posts, videos, vid

The contributions in this topic are more similar to what an `awesome-page` would look like.

*If you want to add a new kind of contribution that wasn't laid out on the [README](index) yet, feel free to do so.*
_If you want to add a new kind of contribution that wasn't laid out on the [README](index) yet, feel free to do so._

#### Recommended guidelines for a resource

Expand Down
2 changes: 1 addition & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ channels:
- conda-forge
- microsoft
dependencies:
- python=3.9
- python=3.10
- pip=20.2.2
- pytest=7
- nodejs=16
Expand Down
178 changes: 58 additions & 120 deletions poetry.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ typeguard = ">=2.13.3"
xdoctest = { extras = ["colors"], version = ">=0.15.10" }
myst-parser = { version = ">=0.16.1" }
requests = "^2.28.1"
playwright = "^1.27"
pytest-playwright = "^0.3.0"
pytest-asyncio-cooperative = "^0.28.0"
nox-poetry = "^1.0.1"
Expand Down
2 changes: 1 addition & 1 deletion src/psc/app.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""Provide a web server to browse the examples."""
import contextlib
from collections.abc import Iterator
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a really good catch. I always get this wrong. I probably should write some flake8 extension that complains. 😀

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is specifically to latest python versions right?
I was used to do from typings import blah haha

from pathlib import PurePath
from typing import AsyncContextManager
from typing import Iterator

from starlette.applications import Starlette
from starlette.requests import Request
Expand Down
59 changes: 57 additions & 2 deletions src/psc/fixtures.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
"""Automate some testing."""
from __future__ import annotations

import builtins
from collections.abc import Callable
from collections.abc import Generator
from collections.abc import Iterable
from dataclasses import dataclass
from dataclasses import field
from mimetypes import guess_type
from typing import Callable
from typing import Generator
from urllib.parse import urlparse

import pytest
Expand Down Expand Up @@ -180,3 +182,56 @@ def _route_handler(route: Route) -> None:
# Don't spend 30 seconds on timeout
page.set_default_timeout(12000)
return page


@dataclass
class FakeDocument:
"""Pretend to be a DOM that holds values at id's."""

values: dict[str, str] = field(default_factory=dict)
log: list[str] = field(default_factory=list)


@pytest.fixture
def fake_document() -> Iterable[FakeDocument]:
"""Yield a document that cleans up."""
yield FakeDocument()


@dataclass
class ElementNode:
"""An element node."""

value: str
document: FakeDocument

def write(self, value: str) -> None:
"""Collect anything that is written to the node."""
self.document.log.append(value)

def removeAttribute(self, name: str) -> None: # noqa
"""Pretend to remove an attribute from this node."""
pass


@dataclass
class ElementCallable:
"""A callable that returns an ElementNode."""

document: FakeDocument

def __call__(self, key: str) -> ElementNode:
"""Return an ElementNode."""
value = self.document.values[key]
node = ElementNode(value, self.document)
return node


@pytest.fixture
def fake_element(fake_document: FakeDocument) -> None: # type: ignore [misc]
"""Install the stateful Element into builtins."""
try:
builtins.Element = ElementCallable(fake_document) #type: ignore [attr-defined]
yield
finally:
delattr(builtins, "Element")
2 changes: 1 addition & 1 deletion src/psc/gallery/examples/hello_world_py/hello_world.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Say Hello."""
output = Element("output")
output = Element("output") #type: ignore
output.write("From Python...")
4 changes: 1 addition & 3 deletions src/psc/gallery/examples/hello_world_py/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
<link rel="stylesheet" href="hello_world.css">
</head>
<body>
<py-config src="../py_config.toml">
paths = ["hello_world.py"]
</py-config>
<py-config src="../py_config.toml"></py-config>
<main>
<h1>Hello Python ...</h1>
<div id="output"></div>
Expand Down
26 changes: 26 additions & 0 deletions src/psc/gallery/examples/interest_calculator/calculator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
def interest(*args, **kwargs):
"""Main interest calculation function."""
# Signal that PyScript is alive by setting the ``Calculate``
# button away from disabled.
calculate_button = Element("calc") # noqa
# calculate_button.element.setAttribute("disabled")

# Now get the various inputs
element_principal = Element("principal") # noqa
element_rate = Element("interest_rate") # noqa
element_time = Element("time") # noqa
principal = float(element_principal.value)
rate = float(element_rate.value)
time = float(element_time.value)
output1 = Element("simple_interest") # noqa
output2 = Element("compound_interest") # noqa
res1 = round(principal + (principal * rate * time))
res2 = round(principal * ((1 + rate) ** time))
output1.write(f"simple interest: {res1}")
output2.write(f"compound interest: {res2}")


def setup():
"""When Pyodide starts up, enable the Calculate button."""
calculate_button = Element("calc") # noqa
calculate_button.element.removeAttribute("disabled")
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
92 changes: 92 additions & 0 deletions src/psc/gallery/examples/interest_calculator/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Interest Calculator</title>
<link rel="icon" type="image/png" href="../../../favicon.png">
<link rel="stylesheet" href="styles.css"/>
<script defer src="../../../pyscript/pyscript.js"></script>
</head>
<body>

<section class="calculator-demo">
<section class="calculator-inner">
<div class="flexelement" id="first_div">
<p id="first_p">
Welcome to the "Simple and Compound Interest Calculator!"
<br/>
<strong>"how does it work?"</strong>
to use the "Simple and Compound Interest Calculator", please enter the input data into the form.
after clicking "Calculate", your result will be shown at the bottom of the form.
</p>

<div style="margin-left: 15%;">
<div style="width: 100%;">
<input type="radio" name='expander' id="expander-1">
<label class="expander_label" for="expander-1">Compound Interest Formula &#187;</label>
<img src="compound-interest.png" alt="Compound Interest"
style="height: 200px;"/>
</div>

<div style="margin-top: 25px;">
<input type="radio" name='expander' id="expander-2">
<label class="expander_label" for="expander-2">Simple Interest Formula &#187;</label>
<img src="simple-interest.png" alt="Simple Interest"
style="height: 150px;"/>
</div>
</div>
</div>


<div class="flexelement">

<div id="form">

<div>
<label>Principal
<input id="principal" type="number" step="1" , style="color: black; min-height: 60px;"/></label>
<br/><br>
<label>Interest rate
<input id="interest_rate" type="number" step="0.1" style="color: black; min-height: 60px;"
placeholder="Decimal, f.e. 0.8"/>
</label>
<br>
<br/>

<label>Time
<input id="time" type="number" step="1" min="0" style="color: black; min-height: 60px;"
placeholder="in years"/></label>
<br> <br/>

<button py-click="interest()" id="calc" style="min-height: 60px;" disabled>Calculate</button>

<div style="margin-top: 2%;">
<span id="simple_interest"></span>
<br/>
<span id="compound_interest"></span>
</div>

</div>

</div>

</div>

<py-config src="../py_config.toml"></py-config>
<py-script src="calculator.py"></py-script>
<py-script>
setup()
</py-script>
</section>
</section>

<footer>
<p id="footer_p">
Thank you for using the "Simple and Compound
Interest Calculator!", powered by PyScript!
</p>
</footer>

</body>

</html>

5 changes: 5 additions & 0 deletions src/psc/gallery/examples/interest_calculator/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
title: Compound Interest Calculator
subtitle: The classic hello world, but in Python -- in a browser!
---
The *body* description.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading