From 6044eb709692ab123b5d9d692099e28bdf4f1ab0 Mon Sep 17 00:00:00 2001 From: Mike Foster Date: Fri, 1 Mar 2024 08:56:07 +0100 Subject: [PATCH 1/6] mdBook workflow as starter --- .github/workflows/docs.yml | 60 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 .github/workflows/docs.yml diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..8a10250 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,60 @@ +# Sample workflow for building and deploying a mdBook site to GitHub Pages +# +# To get started with mdBook see: https://rust-lang.github.io/mdBook/index.html +# +name: Deploy mdBook site to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: [$default-branch] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Build job + build: + runs-on: ubuntu-latest + env: + MDBOOK_VERSION: 0.4.36 + steps: + - uses: actions/checkout@v4 + - name: Install mdBook + run: | + curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf -y | sh + rustup update + cargo install --version ${MDBOOK_VERSION} mdbook + - name: Setup Pages + id: pages + uses: actions/configure-pages@v4 + - name: Build with mdBook + run: mdbook build + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: ./book + + # Deployment job + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 \ No newline at end of file From 0393cf39ffeb1dab3690545c8fc74a4ae2148d52 Mon Sep 17 00:00:00 2001 From: Mike Foster Date: Fri, 1 Mar 2024 09:00:26 +0100 Subject: [PATCH 2/6] update workflow to run mkdocs build --- .github/workflows/docs.yml | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 8a10250..5f8291c 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,14 +1,9 @@ -# Sample workflow for building and deploying a mdBook site to GitHub Pages -# -# To get started with mdBook see: https://rust-lang.github.io/mdBook/index.html -# -name: Deploy mdBook site to Pages +name: Deploy mkdocs site to Pages on: # Runs on pushes targeting the default branch push: branches: [$default-branch] - # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -28,24 +23,25 @@ jobs: # Build job build: runs-on: ubuntu-latest - env: - MDBOOK_VERSION: 0.4.36 steps: - uses: actions/checkout@v4 - - name: Install mdBook + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.x" + - name: Install dependencies run: | - curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf -y | sh - rustup update - cargo install --version ${MDBOOK_VERSION} mdbook + python -m pip install --upgrade pip + python -m pip install -e .[dev] - name: Setup Pages id: pages uses: actions/configure-pages@v4 - - name: Build with mdBook - run: mdbook build + - name: Build with mkdocs + run: mkdocs build - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: - path: ./book + path: ./site # Deployment job deploy: From 14ba2f5ac9aa4cb1cff5a4e1135ec1d4c36a060a Mon Sep 17 00:00:00 2001 From: Mike Foster Date: Fri, 1 Mar 2024 09:03:35 +0100 Subject: [PATCH 3/6] also run on any branch named docs/** --- .github/workflows/docs.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 5f8291c..87c712d 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,24 +1,30 @@ name: Deploy mkdocs site to Pages on: - # Runs on pushes targeting the default branch + # Runs on pushes targeting the default branch or any branch named docs/* push: - branches: [$default-branch] + branches: + - $default-branch + - "docs/**" + # Allows you to run this workflow manually from the Actions tab workflow_dispatch: + # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: contents: read pages: write id-token: write + # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. concurrency: group: "pages" cancel-in-progress: false + jobs: # Build job build: From 30d068414128181592dc39717fefa96fcacc9c3f Mon Sep 17 00:00:00 2001 From: Mike Foster Date: Fri, 1 Mar 2024 09:19:45 +0100 Subject: [PATCH 4/6] Provide link to docs on pypi --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index bb435d9..618692e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ classifiers = [ [project.urls] Homepage = "https://github.com/MusicalNinjaDad/recurtools" -# Documentation = "https://github.com/MusicalNinjaDad/recurtools" +Documentation = "https://musicalninjadad.github.io/recurtools/" Repository = "https://github.com/MusicalNinjaDad/recurtools" Issues = "https://github.com/MusicalNinjaDad/recurtools/issues" Changelog = "https://github.com/MusicalNinjaDad/recurtools/blob/main/CHANGELOG.md" From 531d3ba502f5713261fc5a9602eed9ae26ab441d Mon Sep 17 00:00:00 2001 From: Mike Foster Date: Fri, 1 Mar 2024 09:20:18 +0100 Subject: [PATCH 5/6] v1.0.0 version bump --- CHANGELOG.md | 4 +++- __version__ | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87b01da..ec52048 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,14 @@ # Changelog: recurtools +## v1.0.0 - simplified interface around nested & flatten +- documentation published to https://musicalninjadad.github.io/recurtools/ - removed `sumrecursive()`see [Issue 11](https://github.com/MusicalNinjaDad/recurtools/issues/11) - removed `chainanything()` - some of the functionality may later be incorporated into `in nested.something()` - removed `indexrecursive()` function in preference for `nested.index()`. - removed `countrecursive()` function in preference for `nested.count()`. - removed `inrecursive()` function in preference for `in nested()`. - removed `lenrecursive()` function in preference for `len(nested())`. `countcontainers` not implemented in new version. -- standardised on keywork argument `preserve` +- standardised on keywork argument `preserve` for flatten. Will later be integrated into nested ## v0.4.0 - update to flatten (BREAKING) - **new keyword-only argument** `dontflatten` (optional): type which will not be flattened. Default: `(str, bytes)`. diff --git a/__version__ b/__version__ index 60a2d3e..afaf360 100644 --- a/__version__ +++ b/__version__ @@ -1 +1 @@ -0.4.0 \ No newline at end of file +1.0.0 \ No newline at end of file From ac08492d8df95a040ebb5759bcbedb9bc4dfb9bb Mon Sep 17 00:00:00 2001 From: Mike Foster Date: Fri, 1 Mar 2024 09:26:45 +0100 Subject: [PATCH 6/6] update README to match docs --- README.md | 113 +++++--------------------------------------------- docs/index.md | 2 +- 2 files changed, 11 insertions(+), 104 deletions(-) diff --git a/README.md b/README.md index d6868ce..4832736 100644 --- a/README.md +++ b/README.md @@ -1,118 +1,25 @@ # recurtools -So many questions on StackExchange take the form "How do I ... with a nested list?". -Here are some tools and helpers I developed to solve those kinds of problems +A simple library to support working with recursively nested objects. -**WARNING** This is a 0.x.x version because I am not yet happy with the function naming. Expect the API to change. -v0.4.0 made breaking changes to string handling in `flatten` - see Changelog for more details. +Primarily built around the **`nested`** class which offers `in`, `len`, `index()` and `count()` functionality. +Additionally, the **`flatten()`** function provides the ability to configure behaviour for strings etc. -Currently standard functionality is to traverse left-to-right as the collection would be output by `print()` +## Installation -## Getting Started - -Installation `pip install recurtools` - -### flatten - -A generator which will flatten any iterable collection recursively. - -```python -from recurtools import flatten -input = [1,2,[3,4,[5],6],7,[8,9]] -assert [x for x in flatten(input)] == [1,2,3,4,5,6,7,8,9] ``` - -New in 0.3.0: Optional argument `preservestrings` (default: `False`) will not flatten strings: - -```python -from recurtools import flatten -input = ['ab',3,('cd','e')] -assert [x for x in flatten(input, preservestrings=True)] == ['ab',3,'cd','e'] +pip install recurtools ``` -### nested +## Usage -A `Container` which implements `lenrecursive`, `countrecursive`, `inrecursive` and `flatten` for `len()`, `.count()`, `in` and `for x in` - -```python -from recurtools import nested -input = [1,2,[3,4,[5],6],7,[8,9]] -nest = nested(input) - -assert len(nest) == 9 -assert 4 in nest -assert 0 not in nest - -out = [x for x in nest] -assert out == [1,2,3,4,5,6,7,8,9] - -nest2 = nested([1,2,[3,2,[5],6],7,[2,9]]) -assert nest2.count(2) == 3 ``` - -### lenrecursive, sumrecursive, countrecursive, inrecursive - -Recursive versions of `sum`, `count`, `in` and `index`. - -Generally these will return a 0 or `None` value rather than raising an `TypeError` or `ValueError` as their nonrecursive brethren do. -`indexrecursive` is an exception and will raise a specific `NotFoundError`. - -They can also cope with situations where some elements in the nested collection are summable / have a length etc. and others do not. - -```python -from recurtools import sumrecursive -assert sumrecursive([1, 2, [3, 4]]) == 10 -assert sumrecursive([1,2.5,[4,"foo"],(5,(0.5,5))]) == 18 -``` - -```python -from recurtools import countrecursive -assert countrecursive([1, 2, [3, 2]],2) == 2 -assert countrecursive(["ab", "b", ["c", "db", ["e","bob"]]],'b') == 5 -``` - -```python -from recurtools import inrecursive -assert inrecursive([1, 2, [3, 2]],3) == True +from recurtools import nested ``` -```python -from recurtools import indexrecursive -assert indexrecursive([1, 2, [3, 2]],2) == (1,) -assert indexrecursive([1, 2, [3, 2]],3) == (2,0) -assert indexrecursive(["Foo",[1,"Bar"]],"a") == (1,1,1) - -with raises(NotFoundError): - indexrecursive([1, 2, [3, 2]],4) ``` - -### chainanything - -A generator that chains (m)anything(s). - -```python -from recurtools import chainanything -a = [1, 2, 3] -b = "de" -c = 5 -d = [4, 5, 23, 11, 5] -e = ["dg", "kuku"] -assert [x for x in chainanything(a,b,c,d,e)] == [1, 2, 3, "de", 5, 4, 5, 23, 11, 5, "dg", "kuku"] -assert ''.join(map(str,chainanything(a,b,c,d,e))) == "123de54523115dgkuku" +from recurtools import flatten ``` -preservestrings = False will lead to strings being yielded as individual characters. Default = `True` -recursive = True will recursively flatten container. Default = `False` (Warning: This may change in v1.0.0) - -Note: preservestrings = False, recursive = False will only flatten strings which are not part of another container. -e.g.: 'abc' -> 'a','b','c' but ['ab','cd'] -> 'ab','cd' - -```python -a = [1, 2, 3] -b = "de" -c = 5 -d = [4, 5, 23, 11, 5] -e = ["dg", "kuku"] -assert [x for x in chainanything(a,b,c,d,e, recursive=False, preservestrings=False)] == [1, 2, 3, "d","e", 5, 4, 5, 23, 11, 5, "dg", "kuku"] -assert [x for x in chainanything(a,b,c,d,e, recursive=True, preservestrings=False)] == [1, 2, 3, "d","e", 5, 4, 5, 23, 11, 5, "d","g", "k","u","k","u"] -``` +## Documentation +For full details see [the docs on github.io](https://musicalninjadad.github.io/recurtools/) \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index e069433..d77e4cf 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,7 +3,7 @@ A simple library to support working with recursively nested objects. Primarily built around the [nested class](#nested) which offers `in`, `len`, `index()` and `count()` functionality. -Additionally, a [flatten() function](#flatten) is provided via `recurtools.utils`. +Additionally, the [flatten() function](#flatten) provides the ability to configure behaviour for strings etc. !!! Tip "A note on strings in nested objects"