Skip to content
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

Introduce SemanticVersioningProcessor #6

Merged
merged 1 commit into from
Jun 9, 2023
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
6 changes: 1 addition & 5 deletions docs/_quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ project:
website:
sidebar:
search: true
contents:
- index.qmd
- getting_started.qmd
- section: "Package Reference"
contents: package_reference/*
contents: auto
margin-header: |
![](/logo.png)
favicon: /logo.png
Expand Down
5 changes: 2 additions & 3 deletions docs/package_reference/processor.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ Processes notebook cells and comments in a notebook

</div><div style="background:#f7f7f7; border:2px solid #5a5a5a; border-top-width:2px; border-left-width: 2px; border-top-left-radius: 0.75rem; margin-top: 2rem; margin-bottom: 1.5rem; padding-left: 1rem; padding-right: .5rem;">
#### `process_cell` {#nbquarto.processor.NotebookProcessor.process_cell}
[\<source\>](https://github.com/muellerzr/nbquarto/blob/main/src/nbquarto/processor.py#L154){style="float:right;font-size:.875rem;"}
[\<source\>](https://github.com/muellerzr/nbquarto/blob/main/src/nbquarto/processor.py#L155){style="float:right;font-size:.875rem;"}
<p style="font-size:.875rem;line-height:1.25rem;">
(**`processor`**`: callable`, **`cell`**`: AttributeDictionary`)
</p>
Expand All @@ -151,7 +151,7 @@ explicitly and instead a user should use `process_notebook`
</div></div>
<div style="background:#f7f7f7; border:2px solid #5a5a5a; border-top-width:2px; border-left-width: 2px; border-top-left-radius: 0.75rem; margin-top: 2rem; margin-bottom: 1.5rem; padding-left: 1rem; padding-right: .5rem;">
#### `process_notebook` {#nbquarto.processor.NotebookProcessor.process_notebook}
[\<source\>](https://github.com/muellerzr/nbquarto/blob/main/src/nbquarto/processor.py#L172){style="float:right;font-size:.875rem;"}
[\<source\>](https://github.com/muellerzr/nbquarto/blob/main/src/nbquarto/processor.py#L173){style="float:right;font-size:.875rem;"}
<p style="font-size:.875rem;line-height:1.25rem;">
()
</p>
Expand All @@ -164,4 +164,3 @@ Processes the content of the notebook

</div>


49 changes: 41 additions & 8 deletions docs/package_reference/processors.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Example usage:

```python
#| process
def my_function():
def my_function():
return "Hello world!"
```

Expand All @@ -36,10 +36,9 @@ Example outcome:
def my_function():
return "Hello world!"
```

<div style="background:#f7f7f7; border:2px solid #5a5a5a; border-top-width:2px; border-left-width: 2px; border-top-left-radius: 0.75rem; margin-top: 2rem; margin-bottom: 1.5rem; padding-left: 1rem; padding-right: .5rem;">

### `class AutoDocProcessor` {#nbquarto.processors.autodoc.AutoDocProcessor}
### `class AutoDocProcessor` {#nbquarto.processors.AutoDocProcessor}
[\<source\>](https://github.com/muellerzr/nbquarto/blob/main/src/nbquarto/processors/autodoc.py#L250){style="float:right;font-size:.875rem;"}
<p style="font-size:.875rem;line-height:1.25rem;">
(**`notebook`**, **`processor_args`**`: dict = {}`)
Expand All @@ -48,7 +47,7 @@ def my_function():
<div style="font-size:.875rem;line-height:1.25rem;margin-bottom:1.25em; margin-top:1.25em; padding_bottom:0;">

A processor which will automatically generate API documentation for a given class or method.
Largely relies on the implementation in [hf-doc-builder](https://github.comn/huggingface/doc-builder),
Largely relies on the implementation in [hf-doc-builder](https://github.com/huggingface/doc-builder),
while adding some customizations for Quarto.

This processor expects the following directives:
Expand Down Expand Up @@ -86,10 +85,9 @@ To expose all public methods and include special or hidden methods:
Example outcome:

(See the auto-generated docs that made this!)

<div style="background:#f7f7f7; border:2px solid #5a5a5a; border-top-width:2px; border-left-width: 2px; border-top-left-radius: 0.75rem; margin-top: 2rem; margin-bottom: 1.5rem; padding-left: 1rem; padding-right: .5rem;">

### `class CodeNoteProcessor` {#nbquarto.processors.codenotes.CodeNoteProcessor}
### `class CodeNoteProcessor` {#nbquarto.processors.CodeNoteProcessor}
[\<source\>](https://github.com/muellerzr/nbquarto/blob/main/src/nbquarto/processors/codenotes.py#L124){style="float:right;font-size:.875rem;"}
<p style="font-size:.875rem;line-height:1.25rem;">
(**`notebook`**`: AttributeDictionary`)
Expand Down Expand Up @@ -139,8 +137,43 @@ def addition(a,b):
```{.python}
addition(a,b)
```
:::{style='padding-top: 0px;'}
::::{style='padding-top: 0px;'}
This function adds two numbers together
::::
:::
:::

<div style="background:#f7f7f7; border:2px solid #5a5a5a; border-top-width:2px; border-left-width: 2px; border-top-left-radius: 0.75rem; margin-top: 2rem; margin-bottom: 1.5rem; padding-left: 1rem; padding-right: .5rem;">

### `class SemanticVersioningProcessor` {#nbquarto.processors.SemanticVersioningProcessor}
[\<source\>](https://github.com/muellerzr/nbquarto/blob/main/src/nbquarto/processors/semantic_versioning.py#L65){style="float:right;font-size:.875rem;"}
<p style="font-size:.875rem;line-height:1.25rem;">
(**`notebook`**`: AttributeDictionary`)
</p>

<div style="font-size:.875rem;line-height:1.25rem;margin-bottom:1.25em; margin-top:1.25em; padding_bottom:0;">

A processor which will inject javascript into the top of the `qmd` or
notebook to enable semantic versioning of the documentation.

Assumes your documentation structure is as follows:

```
- docs/
- version_1
- page_1.qmd
- page_2.qmd
- version_2
- page_1.qmd
- page_2.qmd
```

From here, the sidebar will be populated based on the
current opened page and its semantic version. So if
you are on `/docs/version_1/page_1`, the sidebar will
hide all of `version_2`'s pages (and any others there may be),
and only show `version_1`.

</div>
</div>

This processor also requires that your project is configured in a particular way. To read more be sure to check out the usage guide. **TO BE COMPLETED**
34 changes: 22 additions & 12 deletions nbs/package_reference/processors.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"#| autodoc nbquarto.processors.autodoc.AutoDocProcessor"
"#| autodoc nbquarto.processors.AutoDocProcessor"
]
},
{
Expand All @@ -54,22 +54,16 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"#| autodoc nbquarto.processors.codenotes.CodeNoteProcessor"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Example outcome:"
"#| autodoc nbquarto.processors.CodeNoteProcessor"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Example outcome:\n",
"\n",
"::: {.panel-tabset}\n",
"## Code\n",
"```python\n",
Expand All @@ -85,11 +79,27 @@
"```{.python}\n",
"addition(a,b)\n",
"```\n",
":::{style='padding-top: 0px;'}\n",
"::::{style='padding-top: 0px;'}\n",
"This function adds two numbers together\n",
":::\n",
"::::\n",
":::\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"#| autodoc nbquarto.processors.SemanticVersioningProcessor"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"This processor also requires that your project is configured in a particular way. To read more be sure to check out the usage guide. **TO BE COMPLETED**"
]
}
],
"metadata": {
Expand Down
1 change: 1 addition & 0 deletions src/nbquarto/processors/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .autodoc import AutoDocProcessor
from .codenotes import CodeNoteProcessor
from .semantic_versioning import SemanticVersioningProcessor
109 changes: 109 additions & 0 deletions src/nbquarto/processors/semantic_versioning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Copyright 2023 Zachary Mueller. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging

from ..notebook import make_cell
from ..processor import Processor


logger = logging.getLogger(__name__)

# This is the javascript that will be injected into the top of the notebook
# to enable semantic versioning of the documentation

REFERENCE_JAVASCRIPT = """/**
* Enables semantic versioning through careful sidebar menu item selection.
* Hide sidebar menu items that are not related to the current page that is open.
* Assumes a directory structure of:
* - version_1
* - page_1
* - page_2
* - version_2
* - page_2
* - page_3
*
* If version_1 is open, then version_2 and it's pages will not be visible to the sidebar.
* These will also link to {url}/{version_num}/page_{num}.
*
* In the `_quarto.yml` sidebar *must* be set to `auto` for this to work.
*/
var all_versioned_menus = $(".sidebar-menu-container > .list-unstyled").children()
// Get the current url, which should be something like: /branch_name/{version_number}/{something}
// the latter parts after the version number are not important nor will be in there.
// eventually need to handle a special case when we use the latest stable version
var url = window.location.pathname.split("/")[1]
for (var versioned_menu of all_versioned_menus){
// Check if the current url extension is in the sidebar menu
var active_sidebar = $(versioned_menu).find(`a[href*="${url}"]`)[0]
// If it is, wrap it in a div so it's easily recognizeable
if (active_sidebar !== undefined){
$(active_sidebar).parent().parent().wrap("<div id='active-sidebar'></div>")
}
// Else hide the additional menus
else {
versioned_menu.style.display = "none"
}
}"""

# We inject it directly to the markdown so there doesn't have to be other random files we need to worry about
REFERENCE_JQUERY = '<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>'
REFERENCE_JAVASCRIPT = f"<script>{REFERENCE_JAVASCRIPT}</script>"


class SemanticVersioningProcessor(Processor):
"""
A processor which will inject javascript into the top of the `qmd` or
notebook to enable semantic versioning of the documentation.

Assumes your documentation structure is as follows:

```
- docs/
- version_1
- page_1.qmd
- page_2.qmd
- version_2
- page_1.qmd
- page_2.qmd
```

From here, the sidebar will be populated based on the
current opened page and its semantic version. So if
you are on `/docs/version_1/page_1`, the sidebar will
hide all of `version_2`'s pages (and any others there may be),
and only show `version_1`.
"""

cell_types = "markdown"
found_markdown_cell = False
markdown_cell_index = None

def process(self, cell):
if self.is_first_markdown(cell):
# Create the new markdown cell
new_cell = make_cell("\n".join([REFERENCE_JQUERY, REFERENCE_JAVASCRIPT]), "markdown")
# Insert the new cell just after the first markdown cell
self.notebook.cells.insert(self.markdown_cell_index + 1, new_cell)
# Update the notebook order
for i, cell in enumerate(self.notebook.cells):
cell.index_ = i

def is_first_markdown(self, cell):
if not self.found_markdown_cell:
self.found_markdown_cell = True
self.markdown_cell_index = cell["index_"]
return True
else:
return False
45 changes: 44 additions & 1 deletion tests/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

from nbquarto.notebook import make_cell, new_notebook
from nbquarto.processor import NotebookProcessor, Processor
from nbquarto.processors import AutoDocProcessor, CodeNoteProcessor
from nbquarto.processors import AutoDocProcessor, CodeNoteProcessor, SemanticVersioningProcessor
from nbquarto.processors.semantic_versioning import REFERENCE_JAVASCRIPT, REFERENCE_JQUERY


class BasicProcessor(Processor):
Expand Down Expand Up @@ -117,3 +118,45 @@ def test_codenotes(self):
self.assertTrue(
"Applies the processor to a cell if the cell is of the" in self.notebook_processor.notebook.cells[2].source
)


class TestSemanticVersioning(unittest.TestCase):
processor = SemanticVersioningProcessor

def reset_cells(self):
test_cells = [
make_cell("# Test Notebook", "markdown"),
make_cell("Here's some text!", "markdown"),
]
self.test_notebooks = [
new_notebook(cells=test_cells),
new_notebook(cells=[make_cell("print('Some code!')")] + test_cells),
]

def setUp(self):
self.reset_cells()

def test_base_case(self):
"Checks if we can insert directly to the first cell"
self.notebook_processor = NotebookProcessor(
processors=[self.processor],
notebook=self.test_notebooks[0],
)
self.notebook_processor.process_notebook()
self.assertEqual(self.notebook_processor.notebook.cells[0].source, "# Test Notebook")
self.assertEqual(
self.notebook_processor.notebook.cells[1].source, f"{REFERENCE_JQUERY}\n{REFERENCE_JAVASCRIPT}"
)

def test_around_code_cell(self):
"Checks that it can be inserted under a markdown cell after a code cell in the very start"
self.notebook_processor = NotebookProcessor(
processors=[self.processor],
notebook=self.test_notebooks[1],
)
self.notebook_processor.process_notebook()
self.assertEqual(self.notebook_processor.notebook.cells[0].source, "print('Some code!')")
self.assertEqual(self.notebook_processor.notebook.cells[1].source, "# Test Notebook")
self.assertEqual(
self.notebook_processor.notebook.cells[2].source, f"{REFERENCE_JQUERY}\n{REFERENCE_JAVASCRIPT}"
)