mirror of
https://github.com/langchain-ai/markdown-exec.git
synced 2026-07-01 18:25:52 -04:00
chore: Template upgrade
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
# Changes here will be overwritten by Copier
|
||||
_commit: 1.2.10
|
||||
_commit: 1.5.4
|
||||
_src_path: gh:pawamoy/copier-uv
|
||||
author_email: dev@pawamoy.fr
|
||||
author_fullname: Timothée Mazzucotelli
|
||||
|
||||
@@ -53,7 +53,7 @@ PASTE TRACEBACK HERE
|
||||
python -m markdown_exec.debug # | xclip -selection clipboard
|
||||
```
|
||||
|
||||
PASTE OUTPUT HERE
|
||||
PASTE MARKDOWN OUTPUT HERE
|
||||
|
||||
### Additional context
|
||||
<!-- Add any other relevant context about the problem here,
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
name: Documentation update
|
||||
about: Point at unclear, missing or outdated documentation.
|
||||
title: "docs: "
|
||||
labels: docs
|
||||
assignees: pawamoy
|
||||
---
|
||||
|
||||
### Is something unclear, missing or outdated in our documentation?
|
||||
<!-- A clear and concise description of what the documentation issue is. Ex. I can't find an explanation on feature [...]. -->
|
||||
|
||||
### Relevant code snippets
|
||||
<!-- If the documentation issue is related to code, please provide relevant code snippets. -->
|
||||
|
||||
### Link to the relevant documentation section
|
||||
<!-- Add a link to the relevant section of our documentation, or any addition context. -->
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
name: Change request
|
||||
about: Suggest any other kind of change for this project.
|
||||
title: "change: "
|
||||
assignees: pawamoy
|
||||
---
|
||||
|
||||
### Is your change request related to a problem? Please describe.
|
||||
<!-- A clear and concise description of what the problem is. -->
|
||||
|
||||
### Describe the solution you'd like
|
||||
<!-- A clear and concise description of what you want to happen. -->
|
||||
|
||||
### Describe alternatives you've considered
|
||||
<!-- A clear and concise description of any alternative solutions you've considered. -->
|
||||
|
||||
### Additional context
|
||||
<!-- Add any other context or screenshots about the change request here. -->
|
||||
+24
-14
@@ -25,20 +25,23 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Fetch all tags
|
||||
run: git fetch --depth=1 --tags
|
||||
with:
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: Set up Graphviz
|
||||
uses: ts-graphviz/setup-graphviz@v1
|
||||
|
||||
- name: Set up Python
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install uv
|
||||
run: pip install uv
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: pyproject.toml
|
||||
|
||||
- name: Install dependencies
|
||||
run: make setup
|
||||
@@ -66,11 +69,11 @@ jobs:
|
||||
echo 'jobs=[
|
||||
{"os": "macos-latest"},
|
||||
{"os": "windows-latest"},
|
||||
{"python-version": "3.9"},
|
||||
{"python-version": "3.10"},
|
||||
{"python-version": "3.11"},
|
||||
{"python-version": "3.12"},
|
||||
{"python-version": "3.13"}
|
||||
{"python-version": "3.13"},
|
||||
{"python-version": "3.14"}
|
||||
]' | tr -d '[:space:]' >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo 'jobs=[
|
||||
@@ -89,31 +92,38 @@ jobs:
|
||||
- macos-latest
|
||||
- windows-latest
|
||||
python-version:
|
||||
- "3.8"
|
||||
- "3.9"
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
- "3.13"
|
||||
- "3.14"
|
||||
resolution:
|
||||
- highest
|
||||
- lowest-direct
|
||||
exclude: ${{ fromJSON(needs.exclude-test-jobs.outputs.jobs) }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
continue-on-error: ${{ matrix.python-version == '3.13' }}
|
||||
continue-on-error: ${{ matrix.python-version == '3.14' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: Set up Python
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
allow-prereleases: true
|
||||
|
||||
- name: Install uv
|
||||
run: pip install uv
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: pyproject.toml
|
||||
cache-suffix: py${{ matrix.python-version }}
|
||||
|
||||
- name: Install dependencies
|
||||
env:
|
||||
|
||||
@@ -11,35 +11,34 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Fetch all tags
|
||||
run: git fetch --depth=1 --tags
|
||||
with:
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
- name: Install build
|
||||
if: github.repository_owner == 'pawamoy-insiders'
|
||||
run: python -m pip install build
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
- name: Build dists
|
||||
if: github.repository_owner == 'pawamoy-insiders'
|
||||
run: python -m build
|
||||
run: uv tool run --from build pyproject-build
|
||||
- name: Upload dists artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
if: github.repository_owner == 'pawamoy-insiders'
|
||||
with:
|
||||
name: markdown-exec-insiders
|
||||
path: ./dist/*
|
||||
- name: Install git-changelog
|
||||
if: github.repository_owner != 'pawamoy-insiders'
|
||||
run: pip install git-changelog
|
||||
- name: Prepare release notes
|
||||
if: github.repository_owner != 'pawamoy-insiders'
|
||||
run: git-changelog --release-notes > release-notes.md
|
||||
run: uv tool run git-changelog --release-notes > release-notes.md
|
||||
- name: Create release with assets
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@v2
|
||||
if: github.repository_owner == 'pawamoy-insiders'
|
||||
with:
|
||||
files: ./dist/*
|
||||
- name: Create release
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@v2
|
||||
if: github.repository_owner != 'pawamoy-insiders'
|
||||
with:
|
||||
body_path: release-notes.md
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
/.pdm-build/
|
||||
/htmlcov/
|
||||
/site/
|
||||
uv.lock
|
||||
|
||||
# cache
|
||||
.cache/
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
FROM gitpod/workspace-full
|
||||
USER gitpod
|
||||
ENV PIP_USER=no
|
||||
RUN pip3 install pipx; \
|
||||
pipx install uv; \
|
||||
pipx ensurepath
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
vscode:
|
||||
extensions:
|
||||
- ms-python.python
|
||||
|
||||
image:
|
||||
file: .gitpod.dockerfile
|
||||
|
||||
ports:
|
||||
- port: 8000
|
||||
onOpen: notify
|
||||
|
||||
tasks:
|
||||
- init: make setup
|
||||
+7
-10
@@ -23,12 +23,11 @@ make setup
|
||||
> You can install it with:
|
||||
>
|
||||
> ```bash
|
||||
> python3 -m pip install --user pipx
|
||||
> pipx install uv
|
||||
> curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
> ```
|
||||
>
|
||||
> Now you can try running `make setup` again,
|
||||
> or simply `uv install`.
|
||||
> or simply `uv sync`.
|
||||
|
||||
You now have the dependencies installed.
|
||||
|
||||
@@ -36,13 +35,11 @@ Run `make help` to see all the available actions!
|
||||
|
||||
## Tasks
|
||||
|
||||
This project uses [duty](https://github.com/pawamoy/duty) to run tasks.
|
||||
A Makefile is also provided. The Makefile will try to run certain tasks
|
||||
on multiple Python versions. If for some reason you don't want to run the task
|
||||
on multiple Python versions, you run the task directly with `make run duty TASK`.
|
||||
|
||||
The Makefile detects if a virtual environment is activated,
|
||||
so `make` will work the same with the virtualenv activated or not.
|
||||
The entry-point to run commands and tasks is the `make` Python script,
|
||||
located in the `scripts` directory. Try running `make` to show the available commands and tasks.
|
||||
The *commands* do not need the Python dependencies to be installed,
|
||||
while the *tasks* do.
|
||||
The cross-platform tasks are written in Python, thanks to [duty](https://github.com/pawamoy/duty).
|
||||
|
||||
If you work in VSCode, we provide
|
||||
[an action to configure VSCode](https://pawamoy.github.io/copier-uv/work/#vscode-setup)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
[](https://github.com/pawamoy/markdown-exec/actions?query=workflow%3Aci)
|
||||
[](https://pawamoy.github.io/markdown-exec/)
|
||||
[](https://pypi.org/project/markdown-exec/)
|
||||
[](https://gitpod.io/#https://github.com/pawamoy/markdown-exec)
|
||||
[](https://app.gitter.im/#/room/#markdown-exec:gitter.im)
|
||||
|
||||
Utilities to execute code blocks in Markdown files.
|
||||
@@ -13,8 +12,6 @@ and this HTML is injected in place of the code block.
|
||||
|
||||
## Installation
|
||||
|
||||
With `pip`:
|
||||
|
||||
```bash
|
||||
pip install markdown-exec[ansi]
|
||||
```
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
target-version = "py38"
|
||||
target-version = "py39"
|
||||
line-length = 120
|
||||
|
||||
[lint]
|
||||
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
# dev
|
||||
editables>=0.5
|
||||
|
||||
# maintenance
|
||||
build>=1.2
|
||||
git-changelog>=2.5
|
||||
twine>=5.1; python_version < '3.13'
|
||||
|
||||
# ci
|
||||
duty>=1.4
|
||||
ruff>=0.4
|
||||
pytest>=8.2
|
||||
pytest-cov>=5.0
|
||||
pytest-randomly>=3.15
|
||||
pytest-xdist>=3.6
|
||||
mypy>=1.10
|
||||
types-markdown>=3.6
|
||||
types-pyyaml>=6.0
|
||||
|
||||
# docs
|
||||
black>=24.4
|
||||
markdown-callouts>=0.4
|
||||
mkdocs>=1.6
|
||||
mkdocs-coverage>=1.0
|
||||
mkdocs-gen-files>=0.5
|
||||
mkdocs-git-committers-plugin-2>=2.3
|
||||
mkdocs-literate-nav>=0.6
|
||||
mkdocs-material>=9.5
|
||||
mkdocs-minify-plugin>=0.8
|
||||
mkdocstrings[python]>=0.25
|
||||
tomli>=2.0; python_version < '3.11'
|
||||
|
||||
# docs gallery
|
||||
pydeps>=1.12; python_version > '3.8' and python_version < '3.13'
|
||||
diagrams>=0.21; python_version > '3.8' and python_version < '3.13'
|
||||
rich>=12.3; python_version > '3.8' and python_version < '3.13'
|
||||
matplotlib>=3.5; python_version > '3.8' and python_version < '3.13'
|
||||
numpy>=1.24.4; python_version > '3.8' and python_version < '3.13'
|
||||
textual>=0.67; python_version > '3.8' and python_version < '3.13'
|
||||
pytermgui>=6.3; python_version > '3.8' and python_version < '3.13'
|
||||
pipdeptree>=2.6; python_version > '3.8' and python_version < '3.13'
|
||||
pip>=24; python_version > '3.8' and python_version < '3.13'
|
||||
pygments>=2.15; python_version > '3.8' and python_version < '3.13'
|
||||
drawsvg>=2.3; python_version > '3.8' and python_version < '3.13'
|
||||
hyperbolic>=2.0; python_version > '3.8' and python_version < '3.13'
|
||||
qrcode>=7.4; python_version > '3.8' and python_version < '3.13'
|
||||
plotly>=5.22; python_version > '3.8' and python_version < '3.13'
|
||||
pandas>=2.2; python_version > '3.8' and python_version < '3.13'
|
||||
chalk-diagrams>=0.2; python_version > '3.8' and python_version < '3.13'
|
||||
@@ -2,17 +2,19 @@
|
||||
|
||||
{% block announce %}
|
||||
|
||||
<a href="{{ 'insiders/#how-to-become-a-sponsor' | url }}"><strong>Sponsorship</strong></a>
|
||||
is now available!
|
||||
<strong>Fund this project</strong> through
|
||||
<a href="{{ 'insiders/#how-to-become-a-sponsor' | url }}"><strong>sponsorship</strong></a>
|
||||
<span class="twemoji heart pulse">
|
||||
{% include ".icons/octicons/heart-fill-16.svg" %}
|
||||
</span> —
|
||||
|
||||
For updates follow <strong>@pawamoy</strong> on
|
||||
Follow
|
||||
<strong>@pawamoy</strong> on
|
||||
<a rel="me" href="https://fosstodon.org/@pawamoy">
|
||||
<span class="twemoji mastodon">
|
||||
{% include ".icons/fontawesome/brands/mastodon.svg" %}
|
||||
</span>
|
||||
<strong>Fosstodon</strong>
|
||||
</a>
|
||||
for updates
|
||||
{% endblock %}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
<!-- Giscus -->
|
||||
<!-- https://squidfunk.github.io/mkdocs-material/setup/adding-a-comment-system/#giscus-integration -->
|
||||
<div id="feedback" style="display: none;">
|
||||
<h2 id="__comments">Feedback</h2>
|
||||
<script src="https://giscus.app/client.js"
|
||||
data-repo="pawamoy/markdown-exec"
|
||||
data-repo-id="R_kgDOG1IOMQ"
|
||||
data-category="Documentation"
|
||||
data-category-id="DIC_kwDOG1IOMc4Ck2cD"
|
||||
data-mapping="pathname"
|
||||
data-strict="1"
|
||||
data-reactions-enabled="0"
|
||||
data-emit-metadata="0"
|
||||
data-input-position="top"
|
||||
data-theme="preferred_color_scheme"
|
||||
data-lang="en"
|
||||
data-loading="lazy"
|
||||
crossorigin="anonymous"
|
||||
async>
|
||||
</script>
|
||||
|
||||
<!-- Synchronize Giscus theme with palette -->
|
||||
<script>
|
||||
var giscus = document.querySelector("script[src*=giscus]")
|
||||
|
||||
// Set palette on initial load
|
||||
var palette = __md_get("__palette")
|
||||
if (palette && typeof palette.color === "object") {
|
||||
var theme = palette.color.scheme === "slate"
|
||||
? "transparent_dark"
|
||||
: "light"
|
||||
|
||||
// Instruct Giscus to set theme
|
||||
giscus.setAttribute("data-theme", theme)
|
||||
}
|
||||
|
||||
// Register event handlers after documented loaded
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var ref = document.querySelector("[data-md-component=palette]")
|
||||
ref.addEventListener("change", function() {
|
||||
var palette = __md_get("__palette")
|
||||
if (palette && typeof palette.color === "object") {
|
||||
var theme = palette.color.scheme === "slate"
|
||||
? "transparent_dark"
|
||||
: "light"
|
||||
|
||||
// Instruct Giscus to change theme
|
||||
var frame = document.querySelector(".giscus-frame")
|
||||
frame.contentWindow.postMessage(
|
||||
{ giscus: { setConfig: { theme } } },
|
||||
"https://giscus.app"
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</div>
|
||||
@@ -1 +1,6 @@
|
||||
---
|
||||
hide:
|
||||
- feedback
|
||||
---
|
||||
|
||||
--8<-- "README.md"
|
||||
|
||||
@@ -95,6 +95,10 @@ with your GitHub account, visit [pawamoy's sponsor profile][github sponsor profi
|
||||
and complete a sponsorship of **$10 a month or more**.
|
||||
You can use your individual or organization GitHub account for sponsoring.
|
||||
|
||||
Sponsorships lower than $10 a month are also very much appreciated, and useful.
|
||||
They won't grant you access to Insiders, but they will be counted towards reaching sponsorship goals.
|
||||
*Every* sponsorship helps us implementing new features and releasing them to the public.
|
||||
|
||||
**Important**: If you're sponsoring **[@pawamoy][github sponsor profile]**
|
||||
through a GitHub organization, please send a short email
|
||||
to insiders@pawamoy.fr with the name of your
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
const feedback = document.forms.feedback;
|
||||
feedback.hidden = false;
|
||||
|
||||
feedback.addEventListener("submit", function(ev) {
|
||||
ev.preventDefault();
|
||||
const commentElement = document.getElementById("feedback");
|
||||
commentElement.style.display = "block";
|
||||
feedback.firstElementChild.disabled = true;
|
||||
const data = ev.submitter.getAttribute("data-md-value");
|
||||
const note = feedback.querySelector(".md-feedback__note [data-md-value='" + data + "']");
|
||||
if (note) {
|
||||
note.hidden = false;
|
||||
}
|
||||
})
|
||||
@@ -1,3 +1,8 @@
|
||||
---
|
||||
hide:
|
||||
- feedback
|
||||
---
|
||||
|
||||
# License
|
||||
|
||||
```
|
||||
|
||||
@@ -7,11 +7,13 @@ import sys
|
||||
from contextlib import contextmanager
|
||||
from importlib.metadata import version as pkgversion
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Iterator
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from duty import duty, tools
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterator
|
||||
|
||||
from duty.context import Context
|
||||
|
||||
|
||||
@@ -57,8 +59,8 @@ def changelog(ctx: Context, bump: str = "") -> None:
|
||||
ctx.run(tools.git_changelog(bump=bump or None), title="Updating changelog")
|
||||
|
||||
|
||||
@duty(pre=["check_quality", "check_types", "check_docs", "check_dependencies", "check-api"])
|
||||
def check(ctx: Context) -> None: # noqa: ARG001
|
||||
@duty(pre=["check-quality", "check-types", "check-docs", "check-api"])
|
||||
def check(ctx: Context) -> None:
|
||||
"""Check it all!"""
|
||||
|
||||
|
||||
@@ -119,19 +121,33 @@ def docs(ctx: Context, *cli_args: str, host: str = "127.0.0.1", port: int = 8000
|
||||
|
||||
|
||||
@duty(skip_if=not below_312, skip_reason=skip_docs_reason)
|
||||
def docs_deploy(ctx: Context) -> None:
|
||||
"""Deploy the documentation to GitHub pages."""
|
||||
def docs_deploy(ctx: Context, *, force: bool = False) -> None:
|
||||
"""Deploy the documentation to GitHub pages.
|
||||
|
||||
Parameters:
|
||||
force: Whether to force deployment, even from non-Insiders version.
|
||||
"""
|
||||
os.environ["DEPLOY"] = "true"
|
||||
with material_insiders() as insiders:
|
||||
if not insiders:
|
||||
ctx.run(lambda: False, title="Not deploying docs without Material for MkDocs Insiders!")
|
||||
origin = ctx.run("git config --get remote.origin.url", silent=True, allow_overrides=False)
|
||||
if "pawamoy-insiders/markdown-exec" in origin:
|
||||
ctx.run("git remote add upstream git@github.com:pawamoy/markdown-exec", silent=True, nofail=True)
|
||||
ctx.run(
|
||||
"git remote add upstream git@github.com:pawamoy/markdown-exec",
|
||||
silent=True,
|
||||
nofail=True,
|
||||
allow_overrides=False,
|
||||
)
|
||||
ctx.run(
|
||||
tools.mkdocs.gh_deploy(remote_name="upstream", force=True),
|
||||
title="Deploying documentation",
|
||||
)
|
||||
elif force:
|
||||
ctx.run(
|
||||
tools.mkdocs.gh_deploy(force=True),
|
||||
title="Deploying documentation",
|
||||
)
|
||||
else:
|
||||
ctx.run(
|
||||
lambda: False,
|
||||
|
||||
+18
-2
@@ -86,6 +86,9 @@ extra_css:
|
||||
- css/mkdocstrings.css
|
||||
- css/insiders.css
|
||||
|
||||
extra_javascript:
|
||||
- js/feedback.js
|
||||
|
||||
markdown_extensions:
|
||||
- admonition
|
||||
- attr_list
|
||||
@@ -154,9 +157,10 @@ plugins:
|
||||
show_symbol_type_toc: true
|
||||
signature_crossrefs: true
|
||||
summary: true
|
||||
- git-committers:
|
||||
- git-revision-date-localized:
|
||||
enabled: !ENV [DEPLOY, false]
|
||||
repository: pawamoy/markdown-exec
|
||||
enable_creation_date: true
|
||||
type: timeago
|
||||
- minify:
|
||||
minify_html: !ENV [DEPLOY, false]
|
||||
- group:
|
||||
@@ -176,3 +180,15 @@ extra:
|
||||
link: https://gitter.im/markdown-exec/community
|
||||
- icon: fontawesome/brands/python
|
||||
link: https://pypi.org/project/markdown-exec/
|
||||
analytics:
|
||||
feedback:
|
||||
title: Was this page helpful?
|
||||
ratings:
|
||||
- icon: material/emoticon-happy-outline
|
||||
name: This page was helpful
|
||||
data: 1
|
||||
note: Thanks for your feedback!
|
||||
- icon: material/emoticon-sad-outline
|
||||
name: This page could be improved
|
||||
data: 0
|
||||
note: Let us know how we can improve this page.
|
||||
|
||||
+62
-3
@@ -8,7 +8,7 @@ description = "Utilities to execute code blocks in Markdown files."
|
||||
authors = [{name = "Timothée Mazzucotelli", email = "dev@pawamoy.fr"}]
|
||||
license = {text = "ISC"}
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.8"
|
||||
requires-python = ">=3.9"
|
||||
keywords = ["markdown", "python", "exec", "shell", "bash", "mkdocs"]
|
||||
dynamic = ["version"]
|
||||
classifiers = [
|
||||
@@ -17,12 +17,12 @@ classifiers = [
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3.14",
|
||||
"Topic :: Documentation",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Utilities",
|
||||
@@ -54,6 +54,8 @@ version = {source = "scm"}
|
||||
[tool.pdm.build]
|
||||
package-dir = "src"
|
||||
editable-backend = "editables"
|
||||
|
||||
# Include as much as possible in the source distribution, to help redistributors.
|
||||
excludes = ["**/.pytest_cache"]
|
||||
source-includes = [
|
||||
"config",
|
||||
@@ -61,7 +63,6 @@ source-includes = [
|
||||
"scripts",
|
||||
"share",
|
||||
"tests",
|
||||
"devdeps.txt",
|
||||
"duties.py",
|
||||
"mkdocs.yml",
|
||||
"*.md",
|
||||
@@ -69,6 +70,64 @@ source-includes = [
|
||||
]
|
||||
|
||||
[tool.pdm.build.wheel-data]
|
||||
# Manual pages can be included in the wheel.
|
||||
# Depending on the installation tool, they will be accessible to users.
|
||||
# pipx supports it, uv does not yet, see https://github.com/astral-sh/uv/issues/4731.
|
||||
data = [
|
||||
{path = "share/**/*", relative-to = "."},
|
||||
]
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
# dev
|
||||
"editables>=0.5",
|
||||
|
||||
# maintenance
|
||||
"build>=1.2",
|
||||
"git-changelog>=2.5",
|
||||
"twine>=5.1",
|
||||
|
||||
# ci
|
||||
"duty>=1.4",
|
||||
"ruff>=0.4",
|
||||
"pytest>=8.2",
|
||||
"pytest-cov>=5.0",
|
||||
"pytest-randomly>=3.15",
|
||||
"pytest-xdist>=3.6",
|
||||
"mypy>=1.10",
|
||||
"types-markdown>=3.6",
|
||||
"types-pyyaml>=6.0",
|
||||
|
||||
# docs
|
||||
"black>=24.4",
|
||||
"markdown-callouts>=0.4",
|
||||
"markdown-exec>=1.8",
|
||||
"mkdocs>=1.6",
|
||||
"mkdocs-coverage>=1.0",
|
||||
"mkdocs-gen-files>=0.5",
|
||||
"mkdocs-git-revision-date-localized-plugin>=1.2",
|
||||
"mkdocs-literate-nav>=0.6",
|
||||
"mkdocs-material>=9.5",
|
||||
"mkdocs-minify-plugin>=0.8",
|
||||
"mkdocstrings[python]>=0.25",
|
||||
# YORE: EOL 3.10: Remove line.
|
||||
"tomli>=2.0; python_version < '3.11'",
|
||||
|
||||
# docs gallery
|
||||
"pydeps>=1.12; python_version < '3.13'",
|
||||
"diagrams>=0.21; python_version < '3.13'",
|
||||
"rich>=12.3; python_version < '3.13'",
|
||||
"matplotlib>=3.5; python_version < '3.13'",
|
||||
"numpy>=1.24.4; python_version < '3.13'",
|
||||
"textual>=0.67; python_version < '3.13'",
|
||||
"pytermgui>=6.3; python_version < '3.13'",
|
||||
"pipdeptree>=2.6; python_version < '3.13'",
|
||||
"pip>=24; python_version < '3.13'",
|
||||
"pygments>=2.15; python_version < '3.13'",
|
||||
"drawsvg>=2.3; python_version < '3.13'",
|
||||
"hyperbolic>=2.0; python_version < '3.13'",
|
||||
"qrcode>=7.4; python_version < '3.13'",
|
||||
"plotly>=5.22; python_version < '3.13'",
|
||||
"pandas>=2.2; python_version < '3.13'",
|
||||
"chalk-diagrams>=0.2; python_version < '3.13'",
|
||||
]
|
||||
@@ -5,17 +5,18 @@ from __future__ import annotations
|
||||
import os
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from collections.abc import Iterable
|
||||
from importlib.metadata import distributions
|
||||
from itertools import chain
|
||||
from pathlib import Path
|
||||
from textwrap import dedent
|
||||
from typing import Dict, Iterable, Union
|
||||
from typing import Union
|
||||
|
||||
from jinja2 import StrictUndefined
|
||||
from jinja2.sandbox import SandboxedEnvironment
|
||||
from packaging.requirements import Requirement
|
||||
|
||||
# TODO: Remove once support for Python 3.10 is dropped.
|
||||
# YORE: EOL 3.10: Replace block with line 2.
|
||||
if sys.version_info >= (3, 11):
|
||||
import tomllib
|
||||
else:
|
||||
@@ -26,11 +27,10 @@ with project_dir.joinpath("pyproject.toml").open("rb") as pyproject_file:
|
||||
pyproject = tomllib.load(pyproject_file)
|
||||
project = pyproject["project"]
|
||||
project_name = project["name"]
|
||||
with project_dir.joinpath("devdeps.txt").open() as devdeps_file:
|
||||
devdeps = [line.strip() for line in devdeps_file if line.strip() and not line.strip().startswith(("-e", "#"))]
|
||||
devdeps = [dep for dep in pyproject["dependency-groups"]["dev"] if not dep.startswith("-e")]
|
||||
|
||||
PackageMetadata = Dict[str, Union[str, Iterable[str]]]
|
||||
Metadata = Dict[str, PackageMetadata]
|
||||
PackageMetadata = dict[str, Union[str, Iterable[str]]]
|
||||
Metadata = dict[str, PackageMetadata]
|
||||
|
||||
|
||||
def _merge_fields(metadata: dict) -> PackageMetadata:
|
||||
|
||||
+4
-1
@@ -10,13 +10,16 @@ from dataclasses import dataclass
|
||||
from datetime import date, datetime, timedelta
|
||||
from itertools import chain
|
||||
from pathlib import Path
|
||||
from typing import Iterable, cast
|
||||
from typing import TYPE_CHECKING, cast
|
||||
from urllib.error import HTTPError
|
||||
from urllib.parse import urljoin
|
||||
from urllib.request import urlopen
|
||||
|
||||
import yaml
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterable
|
||||
|
||||
logger = logging.getLogger(f"mkdocs.logs.{__name__}")
|
||||
|
||||
|
||||
|
||||
-203
@@ -1,203 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Management commands."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
from typing import Any, Iterator
|
||||
|
||||
PYTHON_VERSIONS = os.getenv("PYTHON_VERSIONS", "3.8 3.9 3.10 3.11 3.12 3.13").split()
|
||||
|
||||
exe = ""
|
||||
prefix = ""
|
||||
|
||||
|
||||
def shell(cmd: str) -> None:
|
||||
"""Run a shell command."""
|
||||
subprocess.run(cmd, shell=True, check=True) # noqa: S602
|
||||
|
||||
|
||||
@contextmanager
|
||||
def environ(**kwargs: str) -> Iterator[None]:
|
||||
"""Temporarily set environment variables."""
|
||||
original = dict(os.environ)
|
||||
os.environ.update(kwargs)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
os.environ.clear()
|
||||
os.environ.update(original)
|
||||
|
||||
|
||||
def uv_install() -> None:
|
||||
"""Install dependencies using uv."""
|
||||
uv_opts = ""
|
||||
if "UV_RESOLUTION" in os.environ:
|
||||
uv_opts = f"--resolution={os.getenv('UV_RESOLUTION')}"
|
||||
cmd = f"uv pip compile {uv_opts} --all-extras pyproject.toml devdeps.txt | uv pip install -r -"
|
||||
shell(cmd)
|
||||
if "CI" not in os.environ:
|
||||
shell("uv pip install --no-deps -e .")
|
||||
else:
|
||||
shell("uv pip install --no-deps .")
|
||||
|
||||
|
||||
def setup() -> None:
|
||||
"""Setup the project."""
|
||||
if not shutil.which("uv"):
|
||||
raise ValueError("make: setup: uv must be installed, see https://github.com/astral-sh/uv")
|
||||
|
||||
print("Installing dependencies (default environment)") # noqa: T201
|
||||
default_venv = Path(".venv")
|
||||
if not default_venv.exists():
|
||||
shell("uv venv --python python")
|
||||
uv_install()
|
||||
|
||||
if PYTHON_VERSIONS:
|
||||
for version in PYTHON_VERSIONS:
|
||||
print(f"\nInstalling dependencies (python{version})") # noqa: T201
|
||||
venv_path = Path(f".venvs/{version}")
|
||||
if not venv_path.exists():
|
||||
shell(f"uv venv --python {version} {venv_path}")
|
||||
with environ(VIRTUAL_ENV=str(venv_path.resolve())):
|
||||
uv_install()
|
||||
|
||||
|
||||
def activate(path: str) -> None:
|
||||
"""Activate a virtual environment."""
|
||||
global exe, prefix # noqa: PLW0603
|
||||
|
||||
if (bin := Path(path, "bin")).exists():
|
||||
activate_script = bin / "activate_this.py"
|
||||
elif (scripts := Path(path, "Scripts")).exists():
|
||||
activate_script = scripts / "activate_this.py"
|
||||
exe = ".exe"
|
||||
prefix = f"{path}/Scripts/"
|
||||
else:
|
||||
raise ValueError(f"make: activate: Cannot find activation script in {path}")
|
||||
|
||||
if not activate_script.exists():
|
||||
raise ValueError(f"make: activate: Cannot find activation script in {path}")
|
||||
|
||||
exec(activate_script.read_text(), {"__file__": str(activate_script)}) # noqa: S102
|
||||
|
||||
|
||||
def run(version: str, cmd: str, *args: str, **kwargs: Any) -> None:
|
||||
"""Run a command in a virtual environment."""
|
||||
kwargs = {"check": True, **kwargs}
|
||||
if version == "default":
|
||||
activate(".venv")
|
||||
subprocess.run([f"{prefix}{cmd}{exe}", *args], **kwargs) # noqa: S603, PLW1510
|
||||
else:
|
||||
activate(f".venvs/{version}")
|
||||
os.environ["MULTIRUN"] = "1"
|
||||
subprocess.run([f"{prefix}{cmd}{exe}", *args], **kwargs) # noqa: S603, PLW1510
|
||||
|
||||
|
||||
def multirun(cmd: str, *args: str, **kwargs: Any) -> None:
|
||||
"""Run a command for all configured Python versions."""
|
||||
if PYTHON_VERSIONS:
|
||||
for version in PYTHON_VERSIONS:
|
||||
run(version, cmd, *args, **kwargs)
|
||||
else:
|
||||
run("default", cmd, *args, **kwargs)
|
||||
|
||||
|
||||
def allrun(cmd: str, *args: str, **kwargs: Any) -> None:
|
||||
"""Run a command in all virtual environments."""
|
||||
run("default", cmd, *args, **kwargs)
|
||||
if PYTHON_VERSIONS:
|
||||
multirun(cmd, *args, **kwargs)
|
||||
|
||||
|
||||
def clean() -> None:
|
||||
"""Delete build artifacts and cache files."""
|
||||
paths_to_clean = ["build", "dist", "htmlcov", "site", ".coverage*", ".pdm-build"]
|
||||
for path in paths_to_clean:
|
||||
shell(f"rm -rf {path}")
|
||||
|
||||
cache_dirs = [".cache", ".pytest_cache", ".mypy_cache", ".ruff_cache", "__pycache__"]
|
||||
for dirpath in Path(".").rglob("*"):
|
||||
if any(dirpath.match(pattern) for pattern in cache_dirs) and not (dirpath.match(".venv") or dirpath.match(".venvs")):
|
||||
shutil.rmtree(path, ignore_errors=True)
|
||||
|
||||
|
||||
def vscode() -> None:
|
||||
"""Configure VSCode to work on this project."""
|
||||
Path(".vscode").mkdir(parents=True, exist_ok=True)
|
||||
shell("cp -v config/vscode/* .vscode")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
"""Main entry point."""
|
||||
args = list(sys.argv[1:])
|
||||
if not args or args[0] == "help":
|
||||
if len(args) > 1:
|
||||
run("default", "duty", "--help", args[1])
|
||||
else:
|
||||
print("Available commands") # noqa: T201
|
||||
print(" help Print this help. Add task name to print help.") # noqa: T201
|
||||
print(" setup Setup all virtual environments (install dependencies).") # noqa: T201
|
||||
print(" run Run a command in the default virtual environment.") # noqa: T201
|
||||
print(" multirun Run a command for all configured Python versions.") # noqa: T201
|
||||
print(" allrun Run a command in all virtual environments.") # noqa: T201
|
||||
print(" 3.x Run a command in the virtual environment for Python 3.x.") # noqa: T201
|
||||
print(" clean Delete build artifacts and cache files.") # noqa: T201
|
||||
print(" vscode Configure VSCode to work on this project.") # noqa: T201
|
||||
try:
|
||||
run("default", "python", "-V", capture_output=True)
|
||||
except (subprocess.CalledProcessError, ValueError):
|
||||
pass
|
||||
else:
|
||||
print("\nAvailable tasks") # noqa: T201
|
||||
run("default", "duty", "--list")
|
||||
return 0
|
||||
|
||||
while args:
|
||||
cmd = args.pop(0)
|
||||
|
||||
if cmd == "run":
|
||||
run("default", *args)
|
||||
return 0
|
||||
|
||||
if cmd == "multirun":
|
||||
multirun(*args)
|
||||
return 0
|
||||
|
||||
if cmd == "allrun":
|
||||
allrun(*args)
|
||||
return 0
|
||||
|
||||
if cmd.startswith("3."):
|
||||
run(cmd, *args)
|
||||
return 0
|
||||
|
||||
opts = []
|
||||
while args and (args[0].startswith("-") or "=" in args[0]):
|
||||
opts.append(args.pop(0))
|
||||
|
||||
if cmd == "clean":
|
||||
clean()
|
||||
elif cmd == "setup":
|
||||
setup()
|
||||
elif cmd == "vscode":
|
||||
vscode()
|
||||
elif cmd == "check":
|
||||
multirun("duty", "check-quality", "check-types", "check-docs")
|
||||
run("default", "duty", "check-api")
|
||||
elif cmd in {"check-quality", "check-docs", "check-types", "test"}:
|
||||
multirun("duty", cmd, *opts)
|
||||
else:
|
||||
run("default", "duty", cmd, *opts)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
sys.exit(main())
|
||||
except Exception: # noqa: BLE001
|
||||
sys.exit(1)
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
make.py
|
||||
Executable
+193
@@ -0,0 +1,193 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Management commands."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
from textwrap import dedent
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterator
|
||||
|
||||
|
||||
PYTHON_VERSIONS = os.getenv("PYTHON_VERSIONS", "3.9 3.10 3.11 3.12 3.13 3.14").split()
|
||||
|
||||
|
||||
def shell(cmd: str, *, capture_output: bool = False, **kwargs: Any) -> str | None:
|
||||
"""Run a shell command."""
|
||||
if capture_output:
|
||||
return subprocess.check_output(cmd, shell=True, text=True, **kwargs) # noqa: S602
|
||||
subprocess.run(cmd, shell=True, check=True, stderr=subprocess.STDOUT, **kwargs) # noqa: S602
|
||||
return None
|
||||
|
||||
|
||||
@contextmanager
|
||||
def environ(**kwargs: str) -> Iterator[None]:
|
||||
"""Temporarily set environment variables."""
|
||||
original = dict(os.environ)
|
||||
os.environ.update(kwargs)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
os.environ.clear()
|
||||
os.environ.update(original)
|
||||
|
||||
|
||||
def uv_install(venv: Path) -> None:
|
||||
"""Install dependencies using uv."""
|
||||
with environ(UV_PROJECT_ENVIRONMENT=str(venv), PYO3_USE_ABI3_FORWARD_COMPATIBILITY="1"):
|
||||
if "CI" in os.environ:
|
||||
shell("uv sync --all-extras --no-editable")
|
||||
else:
|
||||
shell("uv sync --all-extras")
|
||||
|
||||
|
||||
def setup() -> None:
|
||||
"""Setup the project."""
|
||||
if not shutil.which("uv"):
|
||||
raise ValueError("make: setup: uv must be installed, see https://github.com/astral-sh/uv")
|
||||
|
||||
print("Installing dependencies (default environment)")
|
||||
default_venv = Path(".venv")
|
||||
if not default_venv.exists():
|
||||
shell("uv venv")
|
||||
uv_install(default_venv)
|
||||
|
||||
if PYTHON_VERSIONS:
|
||||
for version in PYTHON_VERSIONS:
|
||||
print(f"\nInstalling dependencies (python{version})")
|
||||
venv_path = Path(f".venvs/{version}")
|
||||
if not venv_path.exists():
|
||||
shell(f"uv venv --python {version} {venv_path}")
|
||||
with environ(UV_PROJECT_ENVIRONMENT=str(venv_path.resolve())):
|
||||
uv_install(venv_path)
|
||||
|
||||
|
||||
def run(version: str, cmd: str, *args: str, no_sync: bool = False, **kwargs: Any) -> None:
|
||||
"""Run a command in a virtual environment."""
|
||||
kwargs = {"check": True, **kwargs}
|
||||
uv_run = ["uv", "run"]
|
||||
if no_sync:
|
||||
uv_run.append("--no-sync")
|
||||
if version == "default":
|
||||
with environ(UV_PROJECT_ENVIRONMENT=".venv"):
|
||||
subprocess.run([*uv_run, cmd, *args], **kwargs) # noqa: S603, PLW1510
|
||||
else:
|
||||
with environ(UV_PROJECT_ENVIRONMENT=f".venvs/{version}", MULTIRUN="1"):
|
||||
subprocess.run([*uv_run, cmd, *args], **kwargs) # noqa: S603, PLW1510
|
||||
|
||||
|
||||
def multirun(cmd: str, *args: str, **kwargs: Any) -> None:
|
||||
"""Run a command for all configured Python versions."""
|
||||
if PYTHON_VERSIONS:
|
||||
for version in PYTHON_VERSIONS:
|
||||
run(version, cmd, *args, **kwargs)
|
||||
else:
|
||||
run("default", cmd, *args, **kwargs)
|
||||
|
||||
|
||||
def allrun(cmd: str, *args: str, **kwargs: Any) -> None:
|
||||
"""Run a command in all virtual environments."""
|
||||
run("default", cmd, *args, **kwargs)
|
||||
if PYTHON_VERSIONS:
|
||||
multirun(cmd, *args, **kwargs)
|
||||
|
||||
|
||||
def clean() -> None:
|
||||
"""Delete build artifacts and cache files."""
|
||||
paths_to_clean = ["build", "dist", "htmlcov", "site", ".coverage*", ".pdm-build"]
|
||||
for path in paths_to_clean:
|
||||
shutil.rmtree(path, ignore_errors=True)
|
||||
|
||||
cache_dirs = {".cache", ".pytest_cache", ".mypy_cache", ".ruff_cache", "__pycache__"}
|
||||
for dirpath in Path(".").rglob("*/"):
|
||||
if dirpath.parts[0] not in (".venv", ".venvs") and dirpath.name in cache_dirs:
|
||||
shutil.rmtree(dirpath, ignore_errors=True)
|
||||
|
||||
|
||||
def vscode() -> None:
|
||||
"""Configure VSCode to work on this project."""
|
||||
shutil.copytree("config/vscode", ".vscode", dirs_exist_ok=True)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
"""Main entry point."""
|
||||
args = list(sys.argv[1:])
|
||||
if not args or args[0] == "help":
|
||||
if len(args) > 1:
|
||||
run("default", "duty", "--help", args[1])
|
||||
else:
|
||||
print(
|
||||
dedent(
|
||||
"""
|
||||
Available commands
|
||||
help Print this help. Add task name to print help.
|
||||
setup Setup all virtual environments (install dependencies).
|
||||
run Run a command in the default virtual environment.
|
||||
multirun Run a command for all configured Python versions.
|
||||
allrun Run a command in all virtual environments.
|
||||
3.x Run a command in the virtual environment for Python 3.x.
|
||||
clean Delete build artifacts and cache files.
|
||||
vscode Configure VSCode to work on this project.
|
||||
""",
|
||||
),
|
||||
flush=True,
|
||||
)
|
||||
if os.path.exists(".venv"):
|
||||
print("\nAvailable tasks", flush=True)
|
||||
run("default", "duty", "--list", no_sync=True)
|
||||
return 0
|
||||
|
||||
while args:
|
||||
cmd = args.pop(0)
|
||||
|
||||
if cmd == "run":
|
||||
run("default", *args)
|
||||
return 0
|
||||
|
||||
if cmd == "multirun":
|
||||
multirun(*args)
|
||||
return 0
|
||||
|
||||
if cmd == "allrun":
|
||||
allrun(*args)
|
||||
return 0
|
||||
|
||||
if cmd.startswith("3."):
|
||||
run(cmd, *args)
|
||||
return 0
|
||||
|
||||
opts = []
|
||||
while args and (args[0].startswith("-") or "=" in args[0]):
|
||||
opts.append(args.pop(0))
|
||||
|
||||
if cmd == "clean":
|
||||
clean()
|
||||
elif cmd == "setup":
|
||||
setup()
|
||||
elif cmd == "vscode":
|
||||
vscode()
|
||||
elif cmd == "check":
|
||||
multirun("duty", "check-quality", "check-types", "check-docs")
|
||||
run("default", "duty", "check-api")
|
||||
elif cmd in {"check-quality", "check-docs", "check-types", "test"}:
|
||||
multirun("duty", cmd, *opts)
|
||||
else:
|
||||
run("default", "duty", cmd, *opts)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
sys.exit(main())
|
||||
except subprocess.CalledProcessError as process:
|
||||
if process.output:
|
||||
print(process.output, file=sys.stderr)
|
||||
sys.exit(process.returncode)
|
||||
Reference in New Issue
Block a user