Added latest version check to info plugin

This commit is contained in:
squidfunk 2022-12-18 17:23:12 +01:00
parent 5ec4a45110
commit 78f3d151a2
7 changed files with 145 additions and 53 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -246,7 +246,7 @@
{% endfor %} {% endfor %}
{% endblock %} {% endblock %}
{% if page.meta and page.meta.ᴴₒᴴₒᴴₒ %} {% if page.meta and page.meta.ᴴₒᴴₒᴴₒ %}
<link rel="stylesheet" href="{{ 'assets/stylesheets/extra.195e5743.min.css' | url }}"> <link rel="stylesheet" href="{{ 'assets/stylesheets/extra.744965a2.min.css' | url }}">
<script src="{{ 'assets/javascripts/extra/bundle.cfb3feee.min.js' | url }}" defer></script> <script src="{{ 'assets/javascripts/extra/bundle.cfb3feee.min.js' | url }}" defer></script>
{% endif %} {% endif %}
</body> </body>

View File

@ -21,6 +21,7 @@
import logging import logging
import os import os
import platform import platform
import requests
import sys import sys
import warnings import warnings
@ -35,6 +36,7 @@ from mkdocs.config import config_options as opt
from mkdocs.config.base import Config from mkdocs.config.base import Config
from mkdocs.plugins import BasePlugin, event_priority from mkdocs.plugins import BasePlugin, event_priority
from mkdocs.structure.files import get_files from mkdocs.structure.files import get_files
from pkg_resources import get_distribution
from zipfile import ZipFile, ZIP_DEFLATED from zipfile import ZipFile, ZIP_DEFLATED
try: try:
@ -53,11 +55,12 @@ except ImportError:
# Info plugin configuration scheme # Info plugin configuration scheme
class InfoPluginConfig(Config): class InfoPluginConfig(Config):
enabled = opt.Type(bool, default = True), enabled = opt.Type(bool, default = True)
# Options for archive # Options for archive
archive = opt.Type(bool, default = True), archive = opt.Type(bool, default = True)
archive_name = opt.Type(str, default = "example"), archive_name = opt.Type(str, default = "example")
archive_stop_on_violation = opt.Type(bool, default = True)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
@ -73,13 +76,24 @@ class InfoPlugin(BasePlugin[InfoPluginConfig]):
# Check if required dependencies are installed # Check if required dependencies are installed
if not dependencies: if not dependencies:
log.error("Required dependencies of \"info\" plugin not found.") log.error("Required dependencies of \"info\" plugin not found.")
print(Fore.RED) print(Style.NORMAL)
print(" pip install \"mkdocs-material[info]\"") print(" pip install \"mkdocs-material[info]\"")
print(Style.RESET_ALL) print(Style.NORMAL)
sys.exit(1) sys.exit(1)
# Print info that we're creating a bug report # Resolve latest version
log.info("Started creating archive for bug report") url = "https://github.com/squidfunk/mkdocs-material/releases/latest"
res = requests.get(url, allow_redirects = False)
# Check if we're running the latest version
_, version = res.headers.get("location").rsplit("/", 1)
package = get_distribution("mkdocs-material")
if package.version != version:
log.error("Please update to the latest version.")
self._help_on_versions_and_exit(package.version, version)
# Print message that we're creating a bug report
log.info("Started archive creation for bug report")
# Check that there are no overrides in place - we need to use a little # Check that there are no overrides in place - we need to use a little
# hack to detect whether the custom_dir setting was used without parsing # hack to detect whether the custom_dir setting was used without parsing
@ -88,12 +102,15 @@ class InfoPlugin(BasePlugin[InfoPluginConfig]):
base = utils.get_theme_dir(config.theme.name) base = utils.get_theme_dir(config.theme.name)
if config.theme.dirs.index(base): if config.theme.dirs.index(base):
log.error("Please remove 'custom_dir' setting.") log.error("Please remove 'custom_dir' setting.")
self._help_and_exit() self._help_on_customizations_and_exit()
# Check that there are no hooks in place # Check that there are no hooks in place - hooks can alter the behavior
# of MkDocs in unpredictable ways, which is why they must be considered
# being customizations. Thus, we can't offer support for debugging and
# must abort here.
if config.hooks: if config.hooks:
log.error("Please remove 'hooks' setting.") log.error("Please remove 'hooks' setting.")
self._help_and_exit() self._help_on_customizations_and_exit()
# Create in-memory archive # Create in-memory archive
archive = BytesIO() archive = BytesIO()
@ -123,7 +140,7 @@ class InfoPlugin(BasePlugin[InfoPluginConfig]):
for a in f.filelist: for a in f.filelist:
files.append("".join([ files.append("".join([
Fore.LIGHTBLACK_EX, a.filename, " ", Fore.LIGHTBLACK_EX, a.filename, " ",
Fore.GREEN, _size(a.compress_size) _size(a.compress_size)
])) ]))
# Finally, write archive to disk # Finally, write archive to disk
@ -131,33 +148,56 @@ class InfoPlugin(BasePlugin[InfoPluginConfig]):
with open(f"{archive_name}.zip", "wb") as f: with open(f"{archive_name}.zip", "wb") as f:
f.write(archive.getvalue()) f.write(archive.getvalue())
# Print summary and archive name # Print summary
log.info("Archive successfully created:") log.info("Archive successfully created:")
print(Style.NORMAL) print(Style.NORMAL)
print("".join([
" ", f.name, " ",
Fore.GREEN, _size(buffer.nbytes)
]))
print(Style.RESET_ALL)
# Print sorted list of archived files # Print archive file names
files.sort() files.sort()
for file in files: for file in files:
print(f" {file}") print(f" {file}")
# Aaaaaand done. # Print archive name
print(Style.RESET_ALL) print(Style.RESET_ALL)
print("".join([
" ", f.name, " ",
_size(buffer.nbytes, 10)
]))
# Print warning when file size is excessively large
print(Style.RESET_ALL)
if buffer.nbytes > 250000:
log.warning("Archive exceeds recommended maximum size of 1 MB")
# Aaaaaand done.
sys.exit(1) sys.exit(1)
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# Print explanation and exit # Print help on versions and exit
def _help_and_exit(self): def _help_on_versions_and_exit(self, have, need):
print(Fore.RED)
print(" When reporting issues, please first update to the latest")
print(" version of Material for MkDocs, as the problem might already")
print(" be fixed in the latest version. This helps reduce duplicate")
print(" efforts and saves the maintainers time.")
print(Style.NORMAL)
print(f" Please update from {have} to {need}.")
print(Style.RESET_ALL)
print(f" pip install \"mkdocs-material=={need}\"")
print(Style.NORMAL)
# Exit, unless explicitly told not to
if self.config.archive_stop_on_violation:
sys.exit(1)
# Print help on customizations and exit
def _help_on_customizations_and_exit(self):
print(Fore.RED) print(Fore.RED)
print(" When reporting issues, you must remove all customizations") print(" When reporting issues, you must remove all customizations")
print(" and check if the problem persists. If not, the problem is") print(" and check if the problem persists. If not, the problem is")
print(" caused by your overrides. Please understand that we can't") print(" caused by your overrides. Please understand that we can't")
print(" provide support for customizations. Please remove:") print(" help you debug your customizations. Please remove:")
print(Style.NORMAL) print(Style.NORMAL)
print(" - theme.custom_dir") print(" - theme.custom_dir")
print(" - hooks") print(" - hooks")
@ -168,17 +208,23 @@ class InfoPlugin(BasePlugin[InfoPluginConfig]):
print(" - extra_css") print(" - extra_css")
print(" - extra_javascript") print(" - extra_javascript")
print(Style.RESET_ALL) print(Style.RESET_ALL)
sys.exit(1)
# Exit, unless explicitly told not to
if self.config.archive_stop_on_violation:
sys.exit(1)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Helper functions # Helper functions
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Print human-readable size # Print human-readable size
def _size(value): def _size(value, factor = 1):
color = Fore.GREEN
if value > 100000 * factor: color = Fore.RED
elif value > 25000 * factor: color = Fore.YELLOW
for unit in ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB"]: for unit in ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB"]:
if abs(value) < 1000.0: if abs(value) < 1000.0:
return f"{value:3.1f} {unit}" return f"{color}{value:3.1f} {unit}"
value /= 1000.0 value /= 1000.0
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------

View File

@ -21,6 +21,7 @@
import logging import logging
import os import os
import platform import platform
import requests
import sys import sys
import warnings import warnings
@ -35,6 +36,7 @@ from mkdocs.config import config_options as opt
from mkdocs.config.base import Config from mkdocs.config.base import Config
from mkdocs.plugins import BasePlugin, event_priority from mkdocs.plugins import BasePlugin, event_priority
from mkdocs.structure.files import get_files from mkdocs.structure.files import get_files
from pkg_resources import get_distribution
from zipfile import ZipFile, ZIP_DEFLATED from zipfile import ZipFile, ZIP_DEFLATED
try: try:
@ -53,11 +55,12 @@ except ImportError:
# Info plugin configuration scheme # Info plugin configuration scheme
class InfoPluginConfig(Config): class InfoPluginConfig(Config):
enabled = opt.Type(bool, default = True), enabled = opt.Type(bool, default = True)
# Options for archive # Options for archive
archive = opt.Type(bool, default = True), archive = opt.Type(bool, default = True)
archive_name = opt.Type(str, default = "example"), archive_name = opt.Type(str, default = "example")
archive_stop_on_violation = opt.Type(bool, default = True)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
@ -73,13 +76,24 @@ class InfoPlugin(BasePlugin[InfoPluginConfig]):
# Check if required dependencies are installed # Check if required dependencies are installed
if not dependencies: if not dependencies:
log.error("Required dependencies of \"info\" plugin not found.") log.error("Required dependencies of \"info\" plugin not found.")
print(Fore.RED) print(Style.NORMAL)
print(" pip install \"mkdocs-material[info]\"") print(" pip install \"mkdocs-material[info]\"")
print(Style.RESET_ALL) print(Style.NORMAL)
sys.exit(1) sys.exit(1)
# Print info that we're creating a bug report # Resolve latest version
log.info("Started creating archive for bug report") url = "https://github.com/squidfunk/mkdocs-material/releases/latest"
res = requests.get(url, allow_redirects = False)
# Check if we're running the latest version
_, version = res.headers.get("location").rsplit("/", 1)
package = get_distribution("mkdocs-material")
if package.version != version:
log.error("Please update to the latest version.")
self._help_on_versions_and_exit(package.version, version)
# Print message that we're creating a bug report
log.info("Started archive creation for bug report")
# Check that there are no overrides in place - we need to use a little # Check that there are no overrides in place - we need to use a little
# hack to detect whether the custom_dir setting was used without parsing # hack to detect whether the custom_dir setting was used without parsing
@ -88,12 +102,15 @@ class InfoPlugin(BasePlugin[InfoPluginConfig]):
base = utils.get_theme_dir(config.theme.name) base = utils.get_theme_dir(config.theme.name)
if config.theme.dirs.index(base): if config.theme.dirs.index(base):
log.error("Please remove 'custom_dir' setting.") log.error("Please remove 'custom_dir' setting.")
self._help_and_exit() self._help_on_customizations_and_exit()
# Check that there are no hooks in place # Check that there are no hooks in place - hooks can alter the behavior
# of MkDocs in unpredictable ways, which is why they must be considered
# being customizations. Thus, we can't offer support for debugging and
# must abort here.
if config.hooks: if config.hooks:
log.error("Please remove 'hooks' setting.") log.error("Please remove 'hooks' setting.")
self._help_and_exit() self._help_on_customizations_and_exit()
# Create in-memory archive # Create in-memory archive
archive = BytesIO() archive = BytesIO()
@ -123,7 +140,7 @@ class InfoPlugin(BasePlugin[InfoPluginConfig]):
for a in f.filelist: for a in f.filelist:
files.append("".join([ files.append("".join([
Fore.LIGHTBLACK_EX, a.filename, " ", Fore.LIGHTBLACK_EX, a.filename, " ",
Fore.GREEN, _size(a.compress_size) _size(a.compress_size)
])) ]))
# Finally, write archive to disk # Finally, write archive to disk
@ -131,33 +148,56 @@ class InfoPlugin(BasePlugin[InfoPluginConfig]):
with open(f"{archive_name}.zip", "wb") as f: with open(f"{archive_name}.zip", "wb") as f:
f.write(archive.getvalue()) f.write(archive.getvalue())
# Print summary and archive name # Print summary
log.info("Archive successfully created:") log.info("Archive successfully created:")
print(Style.NORMAL) print(Style.NORMAL)
print("".join([
" ", f.name, " ",
Fore.GREEN, _size(buffer.nbytes)
]))
print(Style.RESET_ALL)
# Print sorted list of archived files # Print archive file names
files.sort() files.sort()
for file in files: for file in files:
print(f" {file}") print(f" {file}")
# Aaaaaand done. # Print archive name
print(Style.RESET_ALL) print(Style.RESET_ALL)
print("".join([
" ", f.name, " ",
_size(buffer.nbytes, 10)
]))
# Print warning when file size is excessively large
print(Style.RESET_ALL)
if buffer.nbytes > 250000:
log.warning("Archive exceeds recommended maximum size of 1 MB")
# Aaaaaand done.
sys.exit(1) sys.exit(1)
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# Print explanation and exit # Print help on versions and exit
def _help_and_exit(self): def _help_on_versions_and_exit(self, have, need):
print(Fore.RED)
print(" When reporting issues, please first update to the latest")
print(" version of Material for MkDocs, as the problem might already")
print(" be fixed in the latest version. This helps reduce duplicate")
print(" efforts and saves the maintainers time.")
print(Style.NORMAL)
print(f" Please update from {have} to {need}.")
print(Style.RESET_ALL)
print(f" pip install \"mkdocs-material=={need}\"")
print(Style.NORMAL)
# Exit, unless explicitly told not to
if self.config.archive_stop_on_violation:
sys.exit(1)
# Print help on customizations and exit
def _help_on_customizations_and_exit(self):
print(Fore.RED) print(Fore.RED)
print(" When reporting issues, you must remove all customizations") print(" When reporting issues, you must remove all customizations")
print(" and check if the problem persists. If not, the problem is") print(" and check if the problem persists. If not, the problem is")
print(" caused by your overrides. Please understand that we can't") print(" caused by your overrides. Please understand that we can't")
print(" provide support for customizations. Please remove:") print(" help you debug your customizations. Please remove:")
print(Style.NORMAL) print(Style.NORMAL)
print(" - theme.custom_dir") print(" - theme.custom_dir")
print(" - hooks") print(" - hooks")
@ -168,17 +208,23 @@ class InfoPlugin(BasePlugin[InfoPluginConfig]):
print(" - extra_css") print(" - extra_css")
print(" - extra_javascript") print(" - extra_javascript")
print(Style.RESET_ALL) print(Style.RESET_ALL)
sys.exit(1)
# Exit, unless explicitly told not to
if self.config.archive_stop_on_violation:
sys.exit(1)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Helper functions # Helper functions
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Print human-readable size # Print human-readable size
def _size(value): def _size(value, factor = 1):
color = Fore.GREEN
if value > 100000 * factor: color = Fore.RED
elif value > 25000 * factor: color = Fore.YELLOW
for unit in ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB"]: for unit in ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB"]:
if abs(value) < 1000.0: if abs(value) < 1000.0:
return f"{value:3.1f} {unit}" return f"{color}{value:3.1f} {unit}"
value /= 1000.0 value /= 1000.0
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------