Skip to content

Commit

Permalink
Create Real Build (#12)
Browse files Browse the repository at this point in the history
* Working on reusable workflows. Associate with Make real build #10.

* Still trying to get reusable workflows working. Make real build #10

* More attempts at this reusable job stuff. Make real build #10

* So much for reusability. :( Make real build #10.

* Gave up on trying to Don't Repeat Yourself as GitHub actions don't support common sense reuse. Oh well. Associated with Make real build #10.

* Added uploading of coverage data and counting the unit tests. Now to test. Associate with Make real build #10.

* Working on getting coverage data uploaded. Associate Make real build #10.

* Still working on trying to upload coverage data. Associate Make real build #10.

* Now with unique names for each OS coverage file.

* Removed #pragma no cover lines to test coverage. Associated with Make real build #10.

* Added the cov-report-job. Now the testing starts. Associated with Make real build #10.

* Had to add emojis! The coverage numbers even surprized me on the first run! 🤯🤯

* Updated text and links in the readme. Associated with Make real build #10.

* Added first badge to test. Make real build #10.

* Had indenting wrong. Not impressed with YAML so far. Also forgot to use the right GitHub environment variable.

* Forgot gist id. Make real build #10.

* Added unit test badge. Make real build #10.

* Updated README with the new badges. Make real build #10.

* Updated more README text.

* Renamed the documentation build and deploy file to have consistent naming between code and docs.

* Badges only updated on the main branch.

Updated comments to reflect the correct badge.
  • Loading branch information
John-Robbins authored Sep 2, 2024
1 parent b14ea79 commit 39c8008
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 47 deletions.
162 changes: 137 additions & 25 deletions .github/workflows/Code-CI.yml
Original file line number Diff line number Diff line change
@@ -1,53 +1,165 @@
# My attempt at creating the tbp CI action.
# Use this tool to lint files: https://rhysd.github.io/actionlint/
# A huge shout out of appreciation to Ned Batchelder! I learned and leaned
# heavily on GitHub Action code from his excellent scriv project.
# https://github.com/nedbat/scriv
# I'm an idiot standing on the shoulder of a giant. Thanks, Ned!
name: Code CI

# Only trigger on the main branch
on:
push:
branches: ["main"]

# Allows you to run this workflow manually from the Actions tab, which is
# kind of important for developing this action!
pull_request:
branches: ["main"]
# Allows you to run this workflow manually from the Actions tab, which is
# kind of important for developing this action as well as testing on any
# branch.
workflow_dispatch:

jobs:
# I really want to break this up into multiple jobs, but I have no idea how.
setup-python_job:
name: lint-test-cov

# The first job is to type check and is to type check and lint the project.
# I'll do that on Ubuntu and won't proceed if this fails.
lint-types-job:
name: "Type and Lint Checks"
runs-on: ubuntu-latest
steps:
# You have to love copying and pasting the same 11 lines into each job.
# I tried to make these a reusable job, but GitHub Actions wants to
# force you to ARY: Always Repeat Yourself. 😹😹
- name: "Checkout Code"
uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: 'pip'
- name: "Install Dependencies"
run: |
python -m pip install --upgrade pip
python -m pip install .[dev]
# The unique part starts here.
- name: "Check Types"
run: mypy --config-file pyproject.toml src/ tests/
- name: Ruff Lint
run: ruff check --config ./pyproject.toml src/ tests/
- name: Pylint Lint
run: pylint --rcfile pyproject.toml src/ tests/


test-cov-job:
name: "Tests and Coverage"
runs-on: ${{ matrix.os }}
needs: lint-types-job
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.12"]
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
# Repeat ourselves again.
- name: "Checkout Code"
uses: actions/checkout@v4
- name: "Set up Python ${{ matrix.python-version }}"
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Display OS version
run: |
python3 -c 'import platform; print(f"{platform.system()} - {platform.release()}")'
- name: Install Dependencies
# I'm not sure if I need the 'python -m pip install --editable .'
# there, but I'll play it safe.
- name: "Install Dependencies"
run: |
python -m pip install --upgrade pip
python -m pip install .[dev]
python -m pip install --editable .
- name: Check Types
run: mypy --config-file pyproject.toml src/ tests/
- name: Ruff Lint
run: ruff check --config ./pyproject.toml src/ tests/
- name: Pylint Lint
run: pylint --rcfile pyproject.toml src/ tests/
- name: Test and Coverage
# The unique part of this job.
- name: "Test and Coverage"
# Generate the coverage data for this operating system.
# The default name for the file is ".coverage", which is the same for
# all operating systems and makes combining them later a little hard.
# This uses the COVERAGE_FILE environment variable to give each their
# own name.
env:
COVERAGE_FILE: ".coverage.${{ matrix.os }}"
run: |
coverage run -m pytest --maxfail=1 -console_output_style=classic --junit-xml=.test-results.xml
- name: "Count Unit Tests"
# Count the number of unit tests for the badge.
# Note, I had no idea bash could not handle spaces arounf the '=' in
# the export command.
if: runner.os == 'Linux'
run: |
export TOTAL_UNIT_TESTS=$(python ./tools/num_pytest_tests.py .test-results.xml)
echo "total_unit_tests=$TOTAL_UNIT_TESTS" >> $GITHUB_ENV
echo "## Total Unit Tests: :trophy: ${TOTAL_UNIT_TESTS} :1st_place_medal:" >> $GITHUB_STEP_SUMMARY
- name: "Make Unit Tests Badge"
# The unit test badge is only updated on tbp and for the main branch.
if: runner.os == 'Linux' && (github.repository == 'John-Robbins/tbp') && (github.ref == 'refs/heads/main')
# https://gist.github.com/John-Robbins/bd5e145f62ac1cf199a458977b8e1f16
uses: schneegans/dynamic-badges-action@v1.7.0
with:
# GIST_BADGES_SECRET is a GitHub personal access token with scope "gist".
auth: ${{ secrets.GIST_BADGES_SECRET }}
gistID: bd5e145f62ac1cf199a458977b8e1f16
filename: unittestsbadge.json
label: Unit Tests
message: ${{ env.total_unit_tests }}
minColorRange: 200
maxColorRange: 290
valColorRange: ${{ env.total_unit_tests }}
style: "flat-square"
- name: "Upload Coverage Data"
# Upload the coverage data for the coverage-job
uses: actions/upload-artifact@v4
with:
name: covdata-${{ matrix.os }}
path: .coverage*


cov-report-job:
name: "Coverage Reports"
runs-on: ubuntu-latest
needs: test-cov-job
steps:
# Repeat ourselves again.
- name: "Checkout Code"
uses: actions/checkout@v4
- name: "Set up Python 3.12"
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: 'pip'
- name: "Install Dependencies"
run: |
python -m pip install --upgrade pip
python -m pip install .[dev]
# The unique part of this job.
- name: "Download Coverage Data"
# Gather all those operating system coverage files.
uses: actions/download-artifact@v4
with:
pattern: covdata-*
merge-multiple: true
- name: "Combine and Report"
# Get the code coverage data.
run: |
coverage combine
coverage report --precision=2 --show-missing --sort=Cover --skip-covered
coverage json
export TOTAL_COVERAGE=$(python -c "import json;print(round(float(json.load(open('coverage.json'))['totals']['percent_covered']),2))")
echo "total_coverage=$TOTAL_COVERAGE" >> $GITHUB_ENV
echo "## Total coverage: :fire: ${TOTAL_COVERAGE}% :fireworks:" >> $GITHUB_STEP_SUMMARY
- name: "Make Coverage Badge"
# Code coverage is only updated on tbp and the main branch.
if: (github.repository == 'John-Robbins/tbp') && (github.ref == 'refs/heads/main')
# https://gist.github.com/John-Robbins/bd5e145f62ac1cf199a458977b8e1f16
uses: schneegans/dynamic-badges-action@v1.7.0
with:
# GIST_BADGES_SECRET is a GitHub personal access token with scope "gist".
auth: ${{ secrets.GIST_BADGES_SECRET }}
gistID: bd5e145f62ac1cf199a458977b8e1f16
filename: covbadge.json
label: Coverage
message: ${{ env.total_coverage }}%
minColorRange: 50
maxColorRange: 90
valColorRange: ${{ env.total_coverage }}
style: "flat-square"

File renamed without changes.
2 changes: 2 additions & 0 deletions .vscode/ltex.dictionary.en-US.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,5 @@ asciinema
prime-decomp
Otten
IntelliSense
Batchelder
scriv
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,11 @@
"Libertadores",
"Lookin",
"López",
"maxfail",
"megamouth",
"Mitbestimmungsgesetz",
"Muppets",
"mypy",
"Nagin",
"Nevill",
"nologo",
Expand All @@ -80,8 +82,12 @@
"PRETURN",
"PRIN",
"Pylance",
"Pylint",
"pyproject",
"pyreadline",
"pytest",
"Ramones",
"rcfile",
"RETROBITS",
"RETUR",
"Rodovia",
Expand Down
40 changes: 22 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@
<!-- markdownlint-disable MD026 -->
## Party like it's 1976!

Badges I need:

![https://en.wikipedia.org/wiki/Tiny_BASIC](https://img.shields.io/badge/Ancient_Technology-blue)

[![Docs CI](https://github.com/John-Robbins/tbp/actions/workflows/Build%20and%20Deploy%20Site%20to%20Pages.yml/badge.svg)](https://github.com/John-Robbins/tbp/actions/workflows/Build%20and%20Deploy%20Site%20to%20Pages.yml)

- Continuous Integration: Pass/Fail
- Unit Tests: count
- Code Coverage: 99%
[![Ancient Technology](https://img.shields.io/badge/Ancient%20Technology-blue?style=flat-square)](https://en.wikipedia.org/wiki/Tiny_BASIC)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue)](https://github.com/John-Robbins/tbp/blob/main/LICENSE)
[![mypy -strict](https://img.shields.io/badge/mypy-strict-green?style=flat-square&color=hsl(120%2C%20100%25%2C%2040%25))](https://mypy.readthedocs.io/en/stable/command_line.html#cmdoption-mypy-strict)
[![Unit Test Count](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/John-Robbins/bd5e145f62ac1cf199a458977b8e1f16/raw/unittestsbadge.json)](https://github.com/John-Robbins/tbp/tree/main/tests)
[![Code Coverage Percentage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/John-Robbins/bd5e145f62ac1cf199a458977b8e1f16/raw/covbadge.json)](https://github.com/John-Robbins/tbp/actions/workflows/Code-CI.yml)
[![Code CI](https://img.shields.io/github/actions/workflow/status/John-Robbins/tbp/Code-CI.yml?branch=main&style=flat-square&label=Code%20CI)](https://github.com/John-Robbins/tbp/actions/workflows/Code-CI.yml)
[![Docs CI](https://img.shields.io/github/actions/workflow/status/John-Robbins/tbp/Docs-CI.yml?branch=main&style=flat-square&label=Docs%20CI)](https://John-Robbins.github.io/tbp)

Tiny BASIC in Python (tbp) is an implementation of the [Tiny BASIC language](https://en.wikipedia.org/wiki/Tiny_BASIC) first proposed by [Dennis Allison](https://en.wikipedia.org/wiki/Dennis_Allison) in response to Bill Gate's "[An Open Letter to Hobbyists](https://en.wikipedia.org/wiki/An_Open_Letter_to_Hobbyists)." In 1976, [Dr. Tom Pittman](http://www.ittybittycomputers.com) developed his version of Tiny BASIC, which was one of many developed at that time. He has graciously posted on his [Tiny BASIC website](www.ittybittycomputers.com/IttyBitty/TinyBasic/index.htm) OCR'd copies of documentation, programs, and much more about that exciting time in computer history, which provided the inspiration for tbp.

Expand All @@ -32,22 +30,22 @@ As powerful as [The Bionic Woman](https://en.wikipedia.org/wiki/The_Bionic_Woman

## :sparkles: Features Galore

- Supports all 12 statements and the two functions of the original, including `USR`.
- Supports all [12 statements and the two functions](https://john-robbins.github.io/tbp/tb-language) of the original, including `USR`.
- Supports all 26 variables, `A` - `Z`. Why would anyone need more than that?
- Loading and saving programs to/from disk. Feel free to make a pull request for cassette tape support.
- A linter to help with program correctness.
- [Loading](https://john-robbins.github.io/tbp/tbp-command-language#loading-files-loadfile--lf) and [saving](https://john-robbins.github.io/tbp/tbp-command-language#saving-files-savefile--sf) programs to/from disk. Feel free to make a pull request for cassette tape support.
- A [linter](https://john-robbins.github.io/tbp/tbp-command-language#linting-lint) to help with program correctness.
- Potential uninitialized variable usage.
- Invalid `GOTO` and `GOSUB` address (i.e., line numbers).
- Missing `END` in the program.
- Using `CLEAR` in a program.
- A **full** debugger built in!
- A **complete** [debugger](https://john-robbins.github.io/tbp/tbp-command-language#the-tiny-basic-in-python-debugger) built in!
- Breakpoints.
- Single stepping.
- Call stack.
- Variable display (all 26!)
- Line timings.
- [Line timings](https://john-robbins.github.io/tbp/tbp-command-language#options-opt).
- Runs all Tiny BASIC programs from the 1970s! [^1]
- More documentation than you ever wanted!
- More [documentation](https://john-robbins.github.io/tbp/) than you ever wanted!

![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)

Expand Down Expand Up @@ -79,19 +77,25 @@ Everything about tbp is lovingly documented to death in the GitHub Pages for thi

### [Bob Nystrom](https://github.com/munificent)

His glorious [Crafting Interpreters](http://www.craftinginterpreters.com) book sparked my huge interest in programming languages. He wrote a book that perfectly threaded the needle between practical and theory and gives you the learning hooks to successfully move on to books like the [Dragon Book](https://www.malaprops.com/book/9780321486813) and [Engineering a Compiler](https://www.malaprops.com/book/9780128154120). My rating: 5,000 :star:! You will see Bob's influence all over this project. All the ugly and mistakes are all on me, not Bob.
His glorious [Crafting Interpreters](http://www.craftinginterpreters.com) book sparked my huge interest in programming languages. Bob wrote a book that perfectly threaded the needle between practical and theory and gives you the learning hooks to successfully move on to books like the [Dragon Book](https://www.malaprops.com/book/9780321486813) and [Engineering a Compiler](https://www.malaprops.com/book/9780128154120). My rating: 5,000 :star:! You will see Bob's influence all over this project. All the ugly and mistakes are all on me, not Bob.

### [Tom Pittman](http://www.ittybittycomputers.com)

He wrote a popular version of [Tiny BASIC](http://www.ittybittycomputers.com/IttyBitty/TinyBasic/index.htm), but more importantly, uploaded old documentation and original programs that gave me the idea to focus on Tiny BASIC as a learning project.

### [Marco's Retrobits](https://retrobits.altervista.org/blog/)

Marco's [TinyBasicBlazor](https://retrobits.altervista.org/tinybasicblazor/), a WebAssembly port of Tiny BASIC, was a huge help in helping me understand lots of edge cases in Tiny BASIC behavior. His [Day of the Week](https://retrobits.altervista.org/tinybasicblazor/programs/DayOfTheWeek.txt) program helped me uncover a major bug in my code, too.
Marco's [TinyBasicBlazor](https://retrobits.altervista.org/tinybasicblazor/), a WebAssembly port of Tiny BASIC, was a huge help in helping me understand lots of edge cases in Tiny BASIC behavior. I hope I didn't eat too much bandwidth at your site Marco, because I felt I was there a lot! His [Day of the Week](https://retrobits.altervista.org/tinybasicblazor/programs/DayOfTheWeek.txt) program helped me uncover a major bug in my code, too.

### [Ned Batchelder](https://nedbatchelder.com)

[Coverage.py](https://coverage.readthedocs.io/en/latest/index.html) is one of those perfect software tools. As an absolute Python beginner, it took me less than five minutes to get it running and made me a better Python developer. Also, when I was trying to learn [GitHub Actions](https://docs.github.com/en/actions), his [scriv](https://github.com/nedbat/scriv) project is a great example. Not too complicated, but more complete than the documentation.

### :heart: YOU! :heart:

Thank you so much for looking at tbp. It's my first Python project so any feedback on what I can do better, or what I did wrong, is appreciated.
Thank you so much for looking at tbp. It's my first Python project and first time using GitHub Actions so any feedback on what I can do better, or what I did wrong, greatly is appreciated. Hit me up in the [Issues](https://github.com/John-Robbins/tbp/issues).

*To all of you, thanks! I'm a Python beginner standing on the shoulders of giants!*

![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)

Expand Down
8 changes: 4 additions & 4 deletions src/tbp/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@
from typing import TYPE_CHECKING

# I dislike having to do this pure ick here.
if sys.platform.startswith("win32"): # pragma no cover
if sys.platform.startswith("win32"):
# Windows doesn't have readline so as far as I can tell this is the
# only way I can get something close.
# https://stackoverflow.com/questions/51157443/pythons-readline-module-not-available-for-windows
# https://github.com/pyreadline3/pyreadline3
from pyreadline3 import Readline # type: ignore # pragma no cover # noqa: PGH003
from pyreadline3 import Readline # type: ignore # noqa: PGH003

readline = Readline() # pragma no cover
readline = Readline()
else:
# Including readline gives a *much* better editing experience.
# https://docs.astral.sh/ruff/rules/unused-import/
import readline # pylint: disable=unused-import # noqa: F401 #pragma no cover
import readline # pylint: disable=unused-import # noqa: F401


if TYPE_CHECKING:
Expand Down

0 comments on commit 39c8008

Please sign in to comment.