From 73dcecae078d60c46e430cff0d0954d67cecebe0 Mon Sep 17 00:00:00 2001 From: mahiki Date: Tue, 2 Aug 2022 08:41:30 -0700 Subject: [PATCH 01/11] small cleanup merge workflow; notes on RESUME --- .github/workflows/merge-after-tests.yml | 11 ++--- todo/RESUME.manual-build-bump-formula.md | 41 +++++++++++++++ todo/poetry-build-github-actions.md | 63 ++++++++++++++++++++---- 3 files changed, 99 insertions(+), 16 deletions(-) create mode 100644 todo/RESUME.manual-build-bump-formula.md diff --git a/.github/workflows/merge-after-tests.yml b/.github/workflows/merge-after-tests.yml index 5c9f6d8..089ee2f 100644 --- a/.github/workflows/merge-after-tests.yml +++ b/.github/workflows/merge-after-tests.yml @@ -36,7 +36,7 @@ jobs: with: fetch-depth: 0 - - name: Generate tag name from release branch name + - name: Generate tag name >> GITHUB_ENV run: | echo "release_tag_name=$(echo "$RELEASE_BRANCH" \ | sed --regexp-extended \ @@ -44,13 +44,11 @@ jobs: - name: Configure repo for autobot merge commit run: | - echo "set git user.name and email" git config user.name gha-bot git config user.email 41898282+github-actions[bot]@users.noreply.github.com git config --list git checkout "$RELEASE_BRANCH" git branch --list - echo "git log this stuff" git log --graph -n10 --pretty=format:'%h %as %cn %x09%s %d' - name: Merge the latest release commit @@ -63,10 +61,8 @@ jobs: git checkout main git branch --list git merge --no-ff "$RELEASE_BRANCH" - git status git tag --annotate "$release_tag_name" -m "release $release_tag_name" - git log --graph -n20 --pretty=format:'%h %as %cn %x09%s %d' - echo 'running: git push origin $release_tag_name' + git log --graph -n10 --pretty=format:'%h %as %cn %x09%s %d' git push origin "$release_tag_name" git push origin main @@ -76,7 +72,8 @@ jobs: git merge --no-ff main git push origin "$release_tag_name" git push origin dev - echo "you can delete your release branch now" + echo "RELEASE AND DEV MERGED" + ehco "YOU CAN DELETE RELEASE BRANCH: $RELEASE_BRANCH" on-failure: runs-on: ubuntu-latest diff --git a/todo/RESUME.manual-build-bump-formula.md b/todo/RESUME.manual-build-bump-formula.md new file mode 100644 index 0000000..6d299c2 --- /dev/null +++ b/todo/RESUME.manual-build-bump-formula.md @@ -0,0 +1,41 @@ +# RESUME Automation Work From this Point +>I need to get back to my day job for now + +Completed: +* merge releases +* tag +* merge back to dev + +TODO: + +* poetry build and create release +* upload built tar.gz to github release tag +* edit mahiki/homebrew-tap with new URL and SHA +* prompt for delete release branch + +## MANUAL BUILD +```sh +# cd ../desertislandtils +git checkout tag v0.2.1 +poetry build --format sdist + +# MANUALLY UPLOAD TO GITHUB RELEASE TAG v0.2.1 +curl -Ls \ + https://github.com/mahiki/desertislandutils/releases/download/v0.2.1/desertislandutils-0.2.1.tar.gz \ + | shasum -a 256 + +# 573c103661d99ff73a3f9749f5c3343f2e8255e36a66928a7192aaabecd056ef + +cd /repo/homebrew-tap +code Formula/desertislandutils.rb + +# edit URL +# edit SHA + +################ NOTE: YOU MAY HAVE TO REBUILD WITH brew ################################# +# If your project dependencies change then the brew pr-pull workflow may be needed, +# or brew create workflow. +########################################################################################## + +# now the new version should be available +brew upgrade desertislandutils \ No newline at end of file diff --git a/todo/poetry-build-github-actions.md b/todo/poetry-build-github-actions.md index b223984..7c4bdc2 100644 --- a/todo/poetry-build-github-actions.md +++ b/todo/poetry-build-github-actions.md @@ -1,19 +1,64 @@ # Build on Github +Auto-merge done, now to build the packaged release. +Next up: bump homebrew formula. ## TODO: UNICORN-DREAM: BUILD & RELEASE -DONE: GHA `poetry run pytest` - -TODO: Merge release/vX.X.X to main -TODO: Tag TODO: Build release artifact `poetry build --format sdist` -TODO: Create release from tagged version and built thing +TODO: Create release from tagged version and built thing, upload to github artifact URL TODO: Get SHA from github archive URL TODO: Call the homebrew-tap to bump formula, or just a cron to gather the update. - TODO: how to bump version numbers automatically +DONE: GHA `poetry run pytest` +DONE: Merge release/vX.X.X to main +DONE: Tag + +### How to create release from `main tag vX.X.X` +```sh +poetry run pytest +poetry build --format sdist + +TODO: upload artifact +``` + +[Github API: Create a release](https://docs.github.com/en/rest/releases/releases#create-a-release) + +[Github API: Upload a release asset](https://docs.github.com/en/rest/releases/assets#upload-a-release-asset) + +**Probably the `actions/github-script@` utility will have good API interaction** + +[marketplace action-upload-release]9https://github.com/softprops/action-gh-release) + +#### **BINGO** github-relase GO application +https://github.com/github-release/github-release + +CLI application that wraps the github API. Here is the part where a built binary is uploaded: + +```sh +# upload a file, for example the OSX/AMD64 binary of my gofinance app +$ github-release upload \ + --user aktau \ + --repo gofinance \ + --tag v0.1.0 \ + --name "gofinance-osx-amd64" \ + --file bin/darwin/amd64/**gofinance** +``` + +#### additional searching +[action/create-release seems ... oh nevermind](https://github.com/actions/create-release). Its an 8000 line index.js application. + +But, it does say this for the interface, create release for every tag pushed. +```yaml +name: Create Release +on: + push: + # Sequence of patterns matched against refs/tags + tags: + - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 + +``` -### Auto merge after tests +### DONE: Auto merge after tests Q: how to get the name of release branch github.event.workflow_run... @@ -59,7 +104,7 @@ https://github.com/OSS-Docs-Tools/code-owner-self-merge ---------- -TODO: automate CI build task on push to dev, merge to main. +DONE: automate CI build task on push to dev, merge to main. Github actions has pypi publisher and build templates, but dont use poetry. The CI template should install poetry, build, and publish to pypi as usual. @@ -77,7 +122,7 @@ The CI template should install poetry, build, and publish to pypi as usual. That covers the build. What about triggering homebrew repo action with new release? -## TODO: semantic versioning +## NODO: semantic versioning [see link of semver][semantic release] for automated gh releases, using poetry. ---------- From d62c5d0c38c1162b930a6e0cdbeea369daf34115 Mon Sep 17 00:00:00 2001 From: mahiki Date: Mon, 12 Sep 2022 21:05:04 -0700 Subject: [PATCH 02/11] TODO notes --- todo/RESUME.manual-build-bump-formula.md | 55 +++++++++++++++++++++--- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/todo/RESUME.manual-build-bump-formula.md b/todo/RESUME.manual-build-bump-formula.md index 6d299c2..c55d8eb 100644 --- a/todo/RESUME.manual-build-bump-formula.md +++ b/todo/RESUME.manual-build-bump-formula.md @@ -13,24 +13,31 @@ TODO: * edit mahiki/homebrew-tap with new URL and SHA * prompt for delete release branch -## MANUAL BUILD +## TODO: MANUAL BUILD STEPS TO AUTOMATE ```sh # cd ../desertislandtils git checkout tag v0.2.1 +poetry run pytest # DEFINITELY INCLUDE THIS IN WORKFLOW poetry build --format sdist + # Building desertislandutils (0.2.1) + # - Building sdist + # - Built desertislandutils-0.2.1.tar.gz +############## MANUAL UPLOAD ########################################################### # MANUALLY UPLOAD TO GITHUB RELEASE TAG v0.2.1 +######################################################################################## curl -Ls \ https://github.com/mahiki/desertislandutils/releases/download/v0.2.1/desertislandutils-0.2.1.tar.gz \ | shasum -a 256 +# e7e31e37a4073382a0be4ac8410b41117671700cc4aa9e17cf43a2d06bfd5625 -# 573c103661d99ff73a3f9749f5c3343f2e8255e36a66928a7192aaabecd056ef +brew edit mahiki/tap/desertislandutils +# edit URL +# edit SHA cd /repo/homebrew-tap -code Formula/desertislandutils.rb -# edit URL -# edit SHA +git tag --annotate v0.2.1 -m ################ NOTE: YOU MAY HAVE TO REBUILD WITH brew ################################# # If your project dependencies change then the brew pr-pull workflow may be needed, @@ -38,4 +45,40 @@ code Formula/desertislandutils.rb ########################################################################################## # now the new version should be available -brew upgrade desertislandutils \ No newline at end of file +brew upgrade desertislandutils + # ==> Upgrading 1 outdated package: + # mahiki/tap/desertislandutils 0.1.0 -> 0.2.1 + # .. + # ==> Downloading https://github.com/mahiki/desertislandutils/releases/download/v0.2.1/desertislandutils-0.2.1.tar.gz + # ==> Downloading from https://objects.githubusercontent.com/github-production-release-asset-2e65be/467741670/6203a243-4d19-4109-9abe-9 + # ######################################################################## 100.0% + # ==> Upgrading mahiki/tap/desertislandutils + # 0.1.0 -> 0.2.1 + # .. + # ==> Installing mahiki/tap/desertislandutils dependency: python@3.9 + # ==> Pouring python@3.9--3.9.13_1.arm64_monterey.bottle.tar.gz + # ==> /opt/homebrew/Cellar/python@3.9/3.9.13_1/bin/python3 -m ensurepip + # ==> /opt/homebrew/Cellar/python@3.9/3.9.13_1/bin/python3 -m pip install -v --no-deps --no-index --upgrade --isolated --target=/opt/ho + # 🍺 /opt/homebrew/Cellar/python@3.9/3.9.13_1: 3,088 files, 57.6MB + # ==> Installing mahiki/tap/desertislandutils + # ==> python3.9 -m venv --system-site-packages /opt/homebrew/Cellar/desertislandutils/0.2.1/libexec + # ==> /opt/homebrew/Cellar/desertislandutils/0.2.1/libexec/bin/pip install -v --no-deps --no-binary :all: --ignore-installed /private/t + # ==> /opt/homebrew/Cellar/desertislandutils/0.2.1/libexec/bin/pip install -v --no-deps --no-binary :all: --ignore-installed /private/t + # ==> /opt/homebrew/Cellar/desertislandutils/0.2.1/libexec/bin/pip install -v --no-deps --no-binary :all: --ignore-installed /private/t + # ==> /opt/homebrew/Cellar/desertislandutils/0.2.1/libexec/bin/pip install -v --no-deps --no-binary :all: --ignore-installed /private/t + # 🍺 /opt/homebrew/Cellar/desertislandutils/0.2.1: 1,719 files, 19.1MB, built in 19 seconds + +brew info mahiki/tap/desertislandutils + # mahiki/tap/desertislandutils: stable 0.2.1 + # Be here, thy collection of personal convenience utilities + # https://github.com/mahiki/homebrew-tap + # /opt/homebrew/Cellar/desertislandutils/0.2.1 (1,719 files, 19.1MB) * + # Built from source on 2022-08-02 at 08:58:17 + +mcd desertislandutils +too big +ls -la +lrwxr-xr-x 1 55 Aug 2 09:25 big -> /Users/segovia/toobig/trashwork/tests/desertislandutils +``` + +### DONE \ No newline at end of file From 6429c30b67256869dd370d7946772fde7e76bf90 Mon Sep 17 00:00:00 2001 From: mahiki Date: Fri, 2 Dec 2022 13:48:50 -0800 Subject: [PATCH 03/11] minor update --- notes/workflow.unit-testing.md | 4 ++-- tests/test_unit.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/notes/workflow.unit-testing.md b/notes/workflow.unit-testing.md index 8abc186..faaa065 100644 --- a/notes/workflow.unit-testing.md +++ b/notes/workflow.unit-testing.md @@ -19,7 +19,7 @@ poetry run pytest -q poetry run pytest -v -poetry run pytest --captures=no +poetry run pytest --capture=no ``` # test_pytest @@ -56,7 +56,7 @@ def test_needsfiles(tmp_path): assert 0 # at shell ~/.../desertislandutils -$> poetry run pytest -v --captures=no +$> poetry run pytest -v --capture=no # ----------------------------------------------- Captured stdout call ----------------------------------------------- # /private/var/folders/sq/4qxp1j7x2jv5c18qty294kfm0000gn/T/pytest-of-segovia/pytest-3/test_needsfiles0 ``` diff --git a/tests/test_unit.py b/tests/test_unit.py index 9b11984..63c8872 100644 --- a/tests/test_unit.py +++ b/tests/test_unit.py @@ -1,4 +1,4 @@ -# Pytest example: using temporary test directory +w# Pytest example: using temporary test directory # # poetry run pytest --capture=no ./tests/test_unit.py # pytest --capture=no ./tests/test_unit.py From 4f38fa3ecf564cdf8c581d37483581c01be14c95 Mon Sep 17 00:00:00 2001 From: mahiki Date: Tue, 25 Apr 2023 15:53:54 -0700 Subject: [PATCH 04/11] todo list added --- todo/desertislandutils.markdowner.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 todo/desertislandutils.markdowner.md diff --git a/todo/desertislandutils.markdowner.md b/todo/desertislandutils.markdowner.md new file mode 100644 index 0000000..863f89a --- /dev/null +++ b/todo/desertislandutils.markdowner.md @@ -0,0 +1,13 @@ +# DesertIslandUtils Markdown Formatter + +## markdowner +* cron job +* uppercase all `## \w+` +* equivalent `sed 's:## \(\w+\):\U\1:' file.md` +* write in python + +## TEST: file open in vscode, changed by cron job underneath + +## RSRC +https://stackoverflow.com/questions/38633787/how-to-edit-lines-of-all-text-files-in-a-directory-with-python +https://stackoverflow.com/questions/12714415/python-equivalent-to-sed From 1ee83ac0416a2b9b5d51311471a73e972e54a62d Mon Sep 17 00:00:00 2001 From: mahiki Date: Wed, 28 Jun 2023 14:21:50 +0200 Subject: [PATCH 05/11] upgrade pytest, add ptpython --- poetry.lock | 253 ++++++++++++++++++++++++++++++++++++++----------- pyproject.toml | 8 +- 2 files changed, 202 insertions(+), 59 deletions(-) diff --git a/poetry.lock b/poetry.lock index 07525af..d09efa9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,3 +1,17 @@ +# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand. + +[[package]] +name = "appdirs" +version = "1.4.4" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, + {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, +] + [[package]] name = "argparse" version = "1.4.0" @@ -5,77 +19,158 @@ description = "Python command-line parsing library" category = "main" optional = false python-versions = "*" - -[[package]] -name = "atomicwrites" -version = "1.4.1" -description = "Atomic file writes." -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "argparse-1.4.0-py2.py3-none-any.whl", hash = "sha256:c31647edb69fd3d465a847ea3157d37bed1f95f19760b11a47aa91c04b666314"}, + {file = "argparse-1.4.0.tar.gz", hash = "sha256:62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4"}, +] [[package]] name = "attrs" -version = "21.4.0" +version = "22.2.0" description = "Classes Without Boilerplate" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.6" +files = [ + {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, + {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, +] [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] -docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] +cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] +tests = ["attrs[tests-no-zope]", "zope.interface"] +tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] [[package]] name = "colorama" -version = "0.4.5" +version = "0.4.6" description = "Cross-platform colored terminal text." category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.1.0" +description = "Backport of PEP 654 (exception groups)" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"}, + {file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"}, +] + +[package.extras] +test = ["pytest (>=6)"] [[package]] name = "gitdb" -version = "4.0.9" +version = "4.0.10" description = "Git Object Database" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" +files = [ + {file = "gitdb-4.0.10-py3-none-any.whl", hash = "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7"}, + {file = "gitdb-4.0.10.tar.gz", hash = "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a"}, +] [package.dependencies] smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.27" -description = "GitPython is a python library used to interact with Git repositories" +version = "3.1.31" +description = "GitPython is a Python library used to interact with Git repositories" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "GitPython-3.1.31-py3-none-any.whl", hash = "sha256:f04893614f6aa713a60cbbe1e6a97403ef633103cdd0ef5eb6efe0deb98dbe8d"}, + {file = "GitPython-3.1.31.tar.gz", hash = "sha256:8ce3bcf69adfdf7c7d503e78fd3b1c492af782d58893b650adb2ac8912ddd573"}, +] [package.dependencies] gitdb = ">=4.0.1,<5" [[package]] name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "jedi" +version = "0.18.2" +description = "An autocompletion tool for Python that can be used for text editors." +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "jedi-0.18.2-py2.py3-none-any.whl", hash = "sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e"}, + {file = "jedi-0.18.2.tar.gz", hash = "sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612"}, +] + +[package.dependencies] +parso = ">=0.8.0,<0.9.0" + +[package.extras] +docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] +qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] +testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] [[package]] name = "packaging" -version = "21.3" +version = "23.0" description = "Core utilities for Python packages" category = "dev" optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, + {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, +] + +[[package]] +name = "parso" +version = "0.8.3" +description = "A Python Parser" +category = "dev" +optional = false python-versions = ">=3.6" +files = [ + {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, + {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, +] -[package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" +[package.extras] +qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] +testing = ["docopt", "pytest (<6.0.0)"] + +[[package]] +name = "pathlib" +version = "1.0.1" +description = "Object-oriented filesystem paths" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "pathlib-1.0.1-py3-none-any.whl", hash = "sha256:f35f95ab8b0f59e6d354090350b44a80a80635d22efdedfa84c7ad1cf0a74147"}, + {file = "pathlib-1.0.1.tar.gz", hash = "sha256:6940718dfc3eff4258203ad5021090933e5c04707d5ca8cc9e73c94a7894ea9f"}, +] [[package]] name = "pluggy" @@ -84,47 +179,87 @@ description = "plugin and hook calling mechanisms for python" category = "dev" optional = false python-versions = ">=3.6" +files = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] [[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" +name = "prompt-toolkit" +version = "3.0.38" +description = "Library for building powerful interactive command lines in Python" +category = "dev" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "prompt_toolkit-3.0.38-py3-none-any.whl", hash = "sha256:45ea77a2f7c60418850331366c81cf6b5b9cf4c7fd34616f733c5427e6abbb1f"}, + {file = "prompt_toolkit-3.0.38.tar.gz", hash = "sha256:23ac5d50538a9a38c8bde05fecb47d0b403ecd0662857a86f886f798563d5b9b"}, +] + +[package.dependencies] +wcwidth = "*" + +[[package]] +name = "ptpython" +version = "3.0.23" +description = "Python REPL build on top of prompt_toolkit" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" +files = [ + {file = "ptpython-3.0.23-py2.py3-none-any.whl", hash = "sha256:51069503684169b21e1980734a9ba2e104643b7e6a50d3ca0e5669ea70d9e21c"}, + {file = "ptpython-3.0.23.tar.gz", hash = "sha256:9fc9bec2cc51bc4000c1224d8c56241ce8a406b3d49ec8dc266f78cd3cd04ba4"}, +] + +[package.dependencies] +appdirs = "*" +jedi = ">=0.16.0" +prompt-toolkit = ">=3.0.28,<3.1.0" +pygments = "*" + +[package.extras] +all = ["black"] +ptipython = ["ipython"] [[package]] -name = "pyparsing" -version = "3.0.9" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" +name = "pygments" +version = "2.14.0" +description = "Pygments is a syntax highlighting package written in Python." category = "dev" optional = false -python-versions = ">=3.6.8" +python-versions = ">=3.6" +files = [ + {file = "Pygments-2.14.0-py3-none-any.whl", hash = "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"}, + {file = "Pygments-2.14.0.tar.gz", hash = "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297"}, +] [package.extras] -diagrams = ["railroad-diagrams", "jinja2"] +plugins = ["importlib-metadata"] [[package]] name = "pytest" -version = "7.1.2" +version = "7.2.2" description = "pytest: simple powerful testing with Python" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "pytest-7.2.2-py3-none-any.whl", hash = "sha256:130328f552dcfac0b1cec75c12e3f005619dc5f874f0a06e8ff7263f0ee6225e"}, + {file = "pytest-7.2.2.tar.gz", hash = "sha256:c99ab0c73aceb050f68929bc93af19ab6db0558791c6a0715723abe9d0ade9d4"}, +] [package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -tomli = ">=1.0.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] @@ -136,6 +271,10 @@ description = "A pure Python implementation of a sliding window memory map manag category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, + {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, +] [[package]] name = "tomli" @@ -144,24 +283,24 @@ description = "A lil' TOML parser" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "wcwidth" +version = "0.2.6" +description = "Measures the displayed width of unicode strings in a terminal" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"}, + {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, +] [metadata] -lock-version = "1.1" +lock-version = "2.0" python-versions = "^3.9" -content-hash = "4e8b2d419090e33cf1fd64479dd3ead74f37dc982c851d9c7a37e656e0044382" - -[metadata.files] -argparse = [] -atomicwrites = [] -attrs = [] -colorama = [] -gitdb = [] -gitpython = [] -iniconfig = [] -packaging = [] -pluggy = [] -py = [] -pyparsing = [] -pytest = [] -smmap = [] -tomli = [] +content-hash = "6b3c1b2f70722381c91b402af43f6f04dc37c0a7ce7d8787688faebc301680e7" diff --git a/pyproject.toml b/pyproject.toml index 4ff8cd7..f93e01d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,8 +13,12 @@ python = "^3.9" argparse = "^1.4.0" GitPython = "^3.1.27" -[tool.poetry.dev-dependencies] -pytest = "^7.1" +[tool.poetry.group.dev.dependencies] +ptpython = "^3.0.23" +pathlib = "^1.0.1" + +[tool.poetry.group.test.dependencies] +pytest = "^7.2.2" [build-system] requires = ["poetry-core>=1.0.0"] From a9f2a998c987f46759c70571d62e6c5d5b06957b Mon Sep 17 00:00:00 2001 From: mahiki Date: Mon, 4 Dec 2023 22:27:34 -0800 Subject: [PATCH 06/11] WN: new feature, week number program with Typer cli --- justfile | 42 +++++++ notes/weeknumber/weeknumber.md | 83 +++++++++++++ poetry.lock | 211 ++++++++++++++++++++++++++------- pyproject.toml | 8 +- src/weeknumber/__init__.py | 0 src/weeknumber/wn.py | 73 ++++++++++++ 6 files changed, 370 insertions(+), 47 deletions(-) create mode 100644 justfile create mode 100644 notes/weeknumber/weeknumber.md create mode 100644 src/weeknumber/__init__.py create mode 100644 src/weeknumber/wn.py diff --git a/justfile b/justfile new file mode 100644 index 0000000..9fb0750 --- /dev/null +++ b/justfile @@ -0,0 +1,42 @@ +YW := '\033[0;33m' +RD := '\033[0;31m' +LC := '\033[0;36m' +LB := '\033[0;34m' +LG := '\033[0;32m' +NC := '\033[0m' + +# just --list +default: + @just --list --unsorted + +# INFO: develop, build, deploy +info: + @echo + @echo " {{LC}}Workflow to develop python scripts and deploy to homebrew.{{LG}}" + @echo + @echo " Develop and commit on dev, pull feature branch." + @echo " Commit incrementally." + @echo " Make tests, test." + @echo " Push branch." + @echo " version, tag, push, ...?." + @echo " 4. finalize dev commits, pull release branch release/0.2.0" + @echo " * final TESTS and debug" + @echo " * bump version" + @echo " * PR 'release/0.2.0' for CI/CD tests" + @echo " * merge to main" + @echo " * tag" + @echo " 5. release to homebrew repo on merge to main" + + +# ptpython REPL in poetry shell +repl: + @poetry run ptpython + +# instructions to bump version number +bump: + @echo + @echo " {{LC}}REMINDER:{{NC}} You need to manually bump the version numbers in these locations." + @echo " ./desertislandutils/" + @echo " {{YW}}__init__.py" + @echo " pyproject.toml" + @echo " tests/test_desertislandutils.py" diff --git a/notes/weeknumber/weeknumber.md b/notes/weeknumber/weeknumber.md new file mode 100644 index 0000000..2ab31af --- /dev/null +++ b/notes/weeknumber/weeknumber.md @@ -0,0 +1,83 @@ +# WN: Week Number +I need to know the ISO reporting week for the current date all the time. And I like to be able to get the week number for any arbitrary date, usually this is in SQL but a CLI script also good. + +This has been working fine in bash for years, but time to thaw out my python package development. +Also, its time to incorporate `justfile` into my package development workflow, so much easier to document commands that way. + +Typer is pretty sweet, waaay beyond Argparse. + +## REQUIREMENTS +Options: + input date, default current date + Week ending day, default saturday (ISO minus 1) + +Dependencies: +[Typer CLI package instead of ArgParse](https://typer.tiangolo.com/tutorial/first-steps/) +Pendulum date package +Just -- yes tis time + +## CHEWS PLACE +```sh +poetry env use 3.11 +poetry add "typer[all]" +poetry add pendulum="~2.0" +# note pendulum 2.1.2 kept failing build, I went through this before +poetry install + +# add script name to pyproject: +[tool.poetry.scripts] +wn = "src.weeknumber.wn:app" +``` + +At this point I can try the app: +```sh +poetry shell +(desertislandutils-py3.11) $> wn --help +``` +actually its expecting a command, gotta figure single command app. + +## TEARS IN RAIN +**It works great!** + +```sh +wn --help + + Usage: wn [OPTIONS] [DATE] + + ISO year week number of a date as YYYY-WDD. Default weekend day is Sat. + Example: + $> wn 'Jul 22' + 2023-W29 + +╭─ Arguments ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ date [DATE] A text expression of date, ex: 'November 27', or 2112-07-29 [default: (dynamic)] │ +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ --sunday Weekend is Saturday by default, this flag sets Sunday weekend day. │ +│ --last Give week number of most recently completed week (overrides DATE argument). │ +│ --verbose --no-verbose [default: no-verbose] │ +│ --install-completion Install completion for the current shell. │ +│ --show-completion Show completion for the current shell, to copy it or customize the installation. │ +│ --help Show this message and exit. │ +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + +wn 2112-07-24 --sunday --verbose +# Input date string: 2112-07-24 +# Timezone: US/Pacific +# Parsed date: 2112-07-24 +# ISO week number: +# 2112-W29 + +wn 2112-07-24 --verbose +# Input date string: 2112-07-24 +# Timezone: US/Pacific +# Parsed date: 2112-07-24 +# ISO week number: +# 2112-W30 + +wn 2112-07-24 +# 2112-W30 + +wn --last +# 2023-W48 +``` \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index d09efa9..db0fb77 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. [[package]] name = "appdirs" version = "1.4.4" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" optional = false python-versions = "*" files = [ @@ -16,7 +15,6 @@ files = [ name = "argparse" version = "1.4.0" description = "Python command-line parsing library" -category = "main" optional = false python-versions = "*" files = [ @@ -28,7 +26,6 @@ files = [ name = "attrs" version = "22.2.0" description = "Classes Without Boilerplate" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -43,11 +40,24 @@ docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib- tests = ["attrs[tests-no-zope]", "zope.interface"] tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + [[package]] name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -55,26 +65,10 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -[[package]] -name = "exceptiongroup" -version = "1.1.0" -description = "Backport of PEP 654 (exception groups)" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"}, - {file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"}, -] - -[package.extras] -test = ["pytest (>=6)"] - [[package]] name = "gitdb" version = "4.0.10" description = "Git Object Database" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -89,7 +83,6 @@ smmap = ">=3.0.1,<6" name = "gitpython" version = "3.1.31" description = "GitPython is a Python library used to interact with Git repositories" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -104,7 +97,6 @@ gitdb = ">=4.0.1,<5" name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -116,7 +108,6 @@ files = [ name = "jedi" version = "0.18.2" description = "An autocompletion tool for Python that can be used for text editors." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -132,11 +123,45 @@ docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alab qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.8" +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + [[package]] name = "packaging" version = "23.0" description = "Core utilities for Python packages" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -148,7 +173,6 @@ files = [ name = "parso" version = "0.8.3" description = "A Python Parser" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -164,7 +188,6 @@ testing = ["docopt", "pytest (<6.0.0)"] name = "pathlib" version = "1.0.1" description = "Object-oriented filesystem paths" -category = "dev" optional = false python-versions = "*" files = [ @@ -172,11 +195,29 @@ files = [ {file = "pathlib-1.0.1.tar.gz", hash = "sha256:6940718dfc3eff4258203ad5021090933e5c04707d5ca8cc9e73c94a7894ea9f"}, ] +[[package]] +name = "pendulum" +version = "2.0.5" +description = "Python datetimes made easy" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pendulum-2.0.5-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:c460f4d8dc41ec3c4377ac1807678cd72fe5e973cc2943c104ffdeaac32dacb7"}, + {file = "pendulum-2.0.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:57801754e05f30e8a7e4d24734c9fad82c6c3ec489151555f0fc66bb32ba6d6d"}, + {file = "pendulum-2.0.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:485aef2089defee88607d37d5bc238934d0b90993d7bf9ceb36e481af41e9c66"}, + {file = "pendulum-2.0.5-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:1cde6e3c6310fb882c98f373795f807cb2bd6af01f34d2857e6e283b5ee91e09"}, + {file = "pendulum-2.0.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:7ee344bc87cb425b04717b90d14ffde14c1dd64eaa73060b3772edcf57f3e866"}, + {file = "pendulum-2.0.5.tar.gz", hash = "sha256:d3078e007315a959989c41cee5cfd63cfeeca21dd3d8295f4bc24199489e9b6c"}, +] + +[package.dependencies] +python-dateutil = ">=2.6,<3.0" +pytzdata = ">=2018.3" + [[package]] name = "pluggy" version = "1.0.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -192,7 +233,6 @@ testing = ["pytest", "pytest-benchmark"] name = "prompt-toolkit" version = "3.0.38" description = "Library for building powerful interactive command lines in Python" -category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -207,7 +247,6 @@ wcwidth = "*" name = "ptpython" version = "3.0.23" description = "Python REPL build on top of prompt_toolkit" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -229,7 +268,6 @@ ptipython = ["ipython"] name = "pygments" version = "2.14.0" description = "Pygments is a syntax highlighting package written in Python." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -244,7 +282,6 @@ plugins = ["importlib-metadata"] name = "pytest" version = "7.2.2" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -255,20 +292,82 @@ files = [ [package.dependencies] attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytzdata" +version = "2020.1" +description = "The Olson timezone database for Python." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pytzdata-2020.1-py2.py3-none-any.whl", hash = "sha256:e1e14750bcf95016381e4d472bad004eef710f2d6417240904070b3d6654485f"}, + {file = "pytzdata-2020.1.tar.gz", hash = "sha256:3efa13b335a00a8de1d345ae41ec78dd11c9f8807f522d39850f2dd828681540"}, +] + +[[package]] +name = "rich" +version = "13.7.0" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "rich-13.7.0-py3-none-any.whl", hash = "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235"}, + {file = "rich-13.7.0.tar.gz", hash = "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + +[[package]] +name = "shellingham" +version = "1.5.4" +description = "Tool to Detect Surrounding Shell" +optional = false +python-versions = ">=3.7" +files = [ + {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, + {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, +] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + [[package]] name = "smmap" version = "5.0.0" description = "A pure Python implementation of a sliding window memory map manager" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -277,22 +376,44 @@ files = [ ] [[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -category = "dev" +name = "typer" +version = "0.9.0" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." optional = false -python-versions = ">=3.7" +python-versions = ">=3.6" +files = [ + {file = "typer-0.9.0-py3-none-any.whl", hash = "sha256:5d96d986a21493606a358cae4461bd8cdf83cbf33a5aa950ae629ca3b51467ee"}, + {file = "typer-0.9.0.tar.gz", hash = "sha256:50922fd79aea2f4751a8e0408ff10d2662bd0c8bbfa84755a699f3bada2978b2"}, +] + +[package.dependencies] +click = ">=7.1.1,<9.0.0" +colorama = {version = ">=0.4.3,<0.5.0", optional = true, markers = "extra == \"all\""} +rich = {version = ">=10.11.0,<14.0.0", optional = true, markers = "extra == \"all\""} +shellingham = {version = ">=1.3.0,<2.0.0", optional = true, markers = "extra == \"all\""} +typing-extensions = ">=3.7.4.3" + +[package.extras] +all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"] +dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"] +doc = ["cairosvg (>=2.5.2,<3.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pillow (>=9.3.0,<10.0.0)"] +test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<8.0.0)", "pytest-cov (>=2.10.0,<5.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<4.0.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"] + +[[package]] +name = "typing-extensions" +version = "4.8.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, + {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, + {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, ] [[package]] name = "wcwidth" version = "0.2.6" description = "Measures the displayed width of unicode strings in a terminal" -category = "dev" optional = false python-versions = "*" files = [ @@ -302,5 +423,5 @@ files = [ [metadata] lock-version = "2.0" -python-versions = "^3.9" -content-hash = "6b3c1b2f70722381c91b402af43f6f04dc37c0a7ce7d8787688faebc301680e7" +python-versions = "^3.11" +content-hash = "10e1acaba33291333a79e1cd9fc5ba3c1a7e5d05912379dbf1eebf133acfe106" diff --git a/pyproject.toml b/pyproject.toml index f93e01d..7788648 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,11 +7,14 @@ license = "MIT" packages = [ { include = "src/toobigdatadoc" } ] +readme = "README.md" [tool.poetry.dependencies] -python = "^3.9" +python = "^3.11" argparse = "^1.4.0" GitPython = "^3.1.27" +typer = {extras = ["all"], version = "^0.9.0"} +pendulum = "~2.0" [tool.poetry.group.dev.dependencies] ptpython = "^3.0.23" @@ -25,4 +28,5 @@ requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" [tool.poetry.scripts] -too = 'src.toobigdatadoc.too:main' +too = "src.toobigdatadoc.too:main" +wn = "src.weeknumber.wn:app" diff --git a/src/weeknumber/__init__.py b/src/weeknumber/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/weeknumber/wn.py b/src/weeknumber/wn.py new file mode 100644 index 0000000..7b3fb9d --- /dev/null +++ b/src/weeknumber/wn.py @@ -0,0 +1,73 @@ +""" +CLI utility that gives the ISO reporting week for a given date. +Option allows week ending day of Saturday or Sunday. +Option for week number of most recently completed week. +Example: wn --last + 2023-W48 +""" +# TODO: wont need to quote DATE if arguments are List type, and " ".join() + +import os +import pendulum +import typer +from typing_extensions import Annotated, Optional, List + +app = typer.Typer() + +def input_date_validate(value: str): + try: + pendulum.parse(value, strict=False) + except Exception as ex: + raise typer.BadParameter(f"Unparseable date string: {value}, try YYYY-MM-DD format.") + # os._exit(0) + return value + +def today_datestring(): + return pendulum.now().strftime("%Y-%m-%d") + +def week_number_string(date, sunday_weekend = False): + if sunday_weekend: + return date.strftime("%Y-W%V") + else: + return date.add(days=1).strftime("%Y-W%V") + +@app.command() +def main( + date: Annotated[str + , typer.Argument( + callback=input_date_validate + , help="A text expression of date, ex: 'November 27', or 2112-07-29" + , default_factory=today_datestring)] + , sunday_weekend: Annotated[bool + , typer.Option( + "--sunday" + , help="Weekend is Saturday by default, this flag sets Sunday weekend day.")] = False + , last_week: Annotated[bool + , typer.Option( + "--last" + , help="Give week number of most recently completed week (overrides DATE argument).")] = False + , verbose: bool = False + ): + """ + ISO year week number of a date as YYYY-WDD. Default weekend day is Sat. + + Example: + + $> wn 'Jul 22' + + 2023-W29 + """ + parsed_date = pendulum.parse(date, strict=False) + + if verbose: + typer.echo(f"Input date string: {date}") + typer.echo(f"Timezone: {pendulum.now().timezone.name}") + typer.echo(f"Parsed date: {parsed_date.strftime('%Y-%m-%d')}") + typer.echo("ISO week number:") + + if last_week: + result = week_number_string(parsed_date.subtract(weeks=1), sunday_weekend=sunday_weekend) + else: + result = week_number_string(parsed_date, sunday_weekend=sunday_weekend) + + typer.echo(result) \ No newline at end of file From 68d7839dc316c7144b4cf369fd3cc480dec11129 Mon Sep 17 00:00:00 2001 From: mahiki Date: Tue, 5 Dec 2023 00:24:42 -0800 Subject: [PATCH 07/11] wn tests added; passing --- bump_version.sh | 7 ------ justfile | 6 +++++ notes/weeknumber/weeknumber.md | 15 ++++++++++++ src/weeknumber/wn.py | 1 - tests/test_unit.py | 2 +- tests/wn/test_wn.py | 42 ++++++++++++++++++++++++++++++++++ 6 files changed, 64 insertions(+), 9 deletions(-) delete mode 100755 bump_version.sh create mode 100644 tests/wn/test_wn.py diff --git a/bump_version.sh b/bump_version.sh deleted file mode 100755 index 4dd3313..0000000 --- a/bump_version.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -cat << EOF -REMINDER: You need to manually bump the version numbers in these locations. -__init__.py -pyproject.toml -tests/test_desertislandutils.py -EOF diff --git a/justfile b/justfile index 9fb0750..e051f89 100644 --- a/justfile +++ b/justfile @@ -40,3 +40,9 @@ bump: @echo " {{YW}}__init__.py" @echo " pyproject.toml" @echo " tests/test_desertislandutils.py" + +# pytest +test *args: + @echo + @echo " ✙✙✙✙✙✙✙✙ TESTING ✙✙✙✙✙✙✙✙" + poetry run pytest --disable-warnings --verbose {{args}} diff --git a/notes/weeknumber/weeknumber.md b/notes/weeknumber/weeknumber.md index 2ab31af..b53bd4e 100644 --- a/notes/weeknumber/weeknumber.md +++ b/notes/weeknumber/weeknumber.md @@ -80,4 +80,19 @@ wn 2112-07-24 wn --last # 2023-W48 +``` + +## TEST +* its a cli service that echoes to stdout +* use `capsys` fixture as in `test_wn` to compare outputs to expected + +```sh +just test tests/wn + + ✙✙✙✙✙✙✙✙ TESTING ✙✙✙✙✙✙✙✙ +poetry run pytest --disable-warnings --verbose tests/wn +========================================================= test session starts ========================================================== +rootdir: /Users/merlinr/repo/the-others/desertislandutils +collected 1 item +tests/wn/test_wn.py::test_wn_options PASSED [100%] ``` \ No newline at end of file diff --git a/src/weeknumber/wn.py b/src/weeknumber/wn.py index 7b3fb9d..c23c2fe 100644 --- a/src/weeknumber/wn.py +++ b/src/weeknumber/wn.py @@ -5,7 +5,6 @@ Example: wn --last 2023-W48 """ -# TODO: wont need to quote DATE if arguments are List type, and " ".join() import os import pendulum diff --git a/tests/test_unit.py b/tests/test_unit.py index 63c8872..9b11984 100644 --- a/tests/test_unit.py +++ b/tests/test_unit.py @@ -1,4 +1,4 @@ -w# Pytest example: using temporary test directory +# Pytest example: using temporary test directory # # poetry run pytest --capture=no ./tests/test_unit.py # pytest --capture=no ./tests/test_unit.py diff --git a/tests/wn/test_wn.py b/tests/wn/test_wn.py new file mode 100644 index 0000000..6027dce --- /dev/null +++ b/tests/wn/test_wn.py @@ -0,0 +1,42 @@ +import pendulum +from src.weeknumber.wn import main + +def test_wn_options(capsys): + out1 = "2023-W48\n" + main("2023-11-29") + out, _ = capsys.readouterr() + assert out == "2023-W48\n" + + out2 = """Input date string: 2112-07-24 +Timezone: US/Pacific +Parsed date: 2112-07-24 +ISO week number: +2112-W29\n""" + main("2112-07-24", sunday_weekend=True, verbose=True) + out, _ = capsys.readouterr() + assert out == out2 + + out3 = """Input date string: 2112-07-24 +Timezone: US/Pacific +Parsed date: 2112-07-24 +ISO week number: +2112-W30\n""" + main("2112-07-24", sunday_weekend=False, verbose=True) + out, _ = capsys.readouterr() + assert out == out3 + + out4 = "2112-W30\n" + main("2112-07-24") + out, _ = capsys.readouterr() + assert out == out4 + + out5 = "2112-W29\n" + main("2112-07-24", last_week=True) + out, _ = capsys.readouterr() + assert out == out5 + + out6 = pendulum.now().subtract(weeks=1).strftime("%Y-W%V") + today = pendulum.now().strftime("%Y-%m-%d") + main(today, last_week=True) + out, _ = capsys.readouterr() + assert out == out6 + "\n" From 7e17a1bb2bdd68a3bddda7d49bb23dfa3d9e767d Mon Sep 17 00:00:00 2001 From: mahiki Date: Tue, 5 Dec 2023 00:28:54 -0800 Subject: [PATCH 08/11] bump version to 0.3.0; justfile --- __init__.py | 2 +- justfile | 6 +++--- pyproject.toml | 2 +- tests/test_desertislandutils.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/__init__.py b/__init__.py index fc79d63..0404d81 100644 --- a/__init__.py +++ b/__init__.py @@ -1 +1 @@ -__version__ = '0.2.1' +__version__ = '0.3.0' diff --git a/justfile b/justfile index e051f89..e806915 100644 --- a/justfile +++ b/justfile @@ -16,9 +16,8 @@ info: @echo @echo " Develop and commit on dev, pull feature branch." @echo " Commit incrementally." - @echo " Make tests, test." - @echo " Push branch." - @echo " version, tag, push, ...?." + @echo " 2. just test" + @echo " 3. just bump" @echo " 4. finalize dev commits, pull release branch release/0.2.0" @echo " * final TESTS and debug" @echo " * bump version" @@ -40,6 +39,7 @@ bump: @echo " {{YW}}__init__.py" @echo " pyproject.toml" @echo " tests/test_desertislandutils.py" + code __init__.py pyproject.toml tests/test_desertislandutils.py # pytest test *args: diff --git a/pyproject.toml b/pyproject.toml index 7788648..ac05c3b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "desertislandutils" -version = "0.2.1" +version = "0.3.0" description = "A collection of personal convenience utilities" authors = ["mahiki "] license = "MIT" diff --git a/tests/test_desertislandutils.py b/tests/test_desertislandutils.py index ceff2c6..715e599 100644 --- a/tests/test_desertislandutils.py +++ b/tests/test_desertislandutils.py @@ -3,4 +3,4 @@ def test_version(): # I don't know why I'm testing this but at least the import worked in pytest - assert __version__ == '0.2.1' + assert __version__ == '0.3.0' From 34ac656c335ae7e9550554cc73a2cc6126bd1228 Mon Sep 17 00:00:00 2001 From: mahiki Date: Tue, 5 Dec 2023 00:31:40 -0800 Subject: [PATCH 09/11] justfile --- justfile | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/justfile b/justfile index e806915..e8e8a38 100644 --- a/justfile +++ b/justfile @@ -14,17 +14,15 @@ info: @echo @echo " {{LC}}Workflow to develop python scripts and deploy to homebrew.{{LG}}" @echo - @echo " Develop and commit on dev, pull feature branch." - @echo " Commit incrementally." - @echo " 2. just test" - @echo " 3. just bump" - @echo " 4. finalize dev commits, pull release branch release/0.2.0" + @echo " {{LG}}1.{{NC}} Develop/commit on dev" + @echo " {{LG}}2.{{NC}} just test" + @echo " {{LG}}3.{{NC}} just bump" + @echo " {{LG}}4.{{NC}} pull release branch release/X.Y.Z" @echo " * final TESTS and debug" - @echo " * bump version" @echo " * PR 'release/0.2.0' for CI/CD tests" @echo " * merge to main" @echo " * tag" - @echo " 5. release to homebrew repo on merge to main" + @echo " {{LG}}5.{{NC}} release to homebrew repo on merge to main" # ptpython REPL in poetry shell From 54025cbe4b4174c097525182cee45bc24cdef70d Mon Sep 17 00:00:00 2001 From: mahiki Date: Tue, 5 Dec 2023 11:13:51 -0800 Subject: [PATCH 10/11] update cicd python version 3.11 --- .github/workflows/poetry.test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/poetry.test.yml b/.github/workflows/poetry.test.yml index dd85cc1..e962cae 100644 --- a/.github/workflows/poetry.test.yml +++ b/.github/workflows/poetry.test.yml @@ -31,7 +31,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: - python-version: '3.9' + python-version: '3.11' - run: python --version From 9a120c202a7a93bfe36cb687c7fb6ddc76ccb720 Mon Sep 17 00:00:00 2001 From: mahiki Date: Tue, 5 Dec 2023 11:50:17 -0800 Subject: [PATCH 11/11] timezone support in tests --- justfile | 13 +++++++++++-- tests/wn/test_wn.py | 11 +++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/justfile b/justfile index e8e8a38..cb52350 100644 --- a/justfile +++ b/justfile @@ -9,6 +9,14 @@ NC := '\033[0m' default: @just --list --unsorted +# poetry pass thru command +po *args: + poetry run {{args}} + +# pass thru +blank *args: + {{args}} + # INFO: develop, build, deploy info: @echo @@ -17,9 +25,10 @@ info: @echo " {{LG}}1.{{NC}} Develop/commit on dev" @echo " {{LG}}2.{{NC}} just test" @echo " {{LG}}3.{{NC}} just bump" - @echo " {{LG}}4.{{NC}} pull release branch release/X.Y.Z" + @echo " {{LG}}4.{{NC}} git checkout -b release/0.3.1" @echo " * final TESTS and debug" - @echo " * PR 'release/0.2.0' for CI/CD tests" + @echo " * git push --set-upstream origin release/0.3.1" + @echo " * PR 'release/0.3.1' for CI/CD tests (click link to open PR)" @echo " * merge to main" @echo " * tag" @echo " {{LG}}5.{{NC}} release to homebrew repo on merge to main" diff --git a/tests/wn/test_wn.py b/tests/wn/test_wn.py index 6027dce..072d9af 100644 --- a/tests/wn/test_wn.py +++ b/tests/wn/test_wn.py @@ -1,14 +1,17 @@ +import os, time import pendulum from src.weeknumber.wn import main +TZ = pendulum.local_timezone().name + def test_wn_options(capsys): out1 = "2023-W48\n" main("2023-11-29") out, _ = capsys.readouterr() assert out == "2023-W48\n" - out2 = """Input date string: 2112-07-24 -Timezone: US/Pacific + out2 = f"""Input date string: 2112-07-24 +Timezone: {TZ} Parsed date: 2112-07-24 ISO week number: 2112-W29\n""" @@ -16,8 +19,8 @@ def test_wn_options(capsys): out, _ = capsys.readouterr() assert out == out2 - out3 = """Input date string: 2112-07-24 -Timezone: US/Pacific + out3 = f"""Input date string: 2112-07-24 +Timezone: {TZ} Parsed date: 2112-07-24 ISO week number: 2112-W30\n"""