getnikola / nikola

A static website and blog generator
https://getnikola.com/
MIT License
2.6k stars 445 forks source link

Nikola (markdown plugin) does not work with Python 3.11 due to problem with `GIST_RST_RE` and markdown regex compilation #3630

Closed AdamWill closed 2 years ago

AdamWill commented 2 years ago

Environment

Python Version: 3.11

Nikola Version: 8.2.2 (and git master, this code has not changed)

Operating System: Fedora Rawhide

Description:

Nikola will not work with Python 3.11. Here's a simplification of something nikola/plugins/compile/markdown/mdx_gist.py does:

#!/bin/python

import markdown
import re

GIST_RST_RE = r'(?m)^\.\.\s*gist::\s*(?P<gist_id>[^\]\s]+)(?:\s*(?P<filename>.+?))?\s*$'
re.compile(r"^(.*?)%s(.*)$" % GIST_RST_RE)

The original code does GistPattern(GIST_RST_RE), and GistPattern inherits from markdown.inlinepatterns.Pattern, and that class's __init__() does re.compile(r"^(.*?)%s(.*)$" % pattern) where pattern is the arg passed in.

If you run that test script on Python 3.10, you get a warning:

DeprecationWarning: Flags not at the start of the expression '^(.*?)(?m)^\\.\\.\\s*gi' (truncated) but at position 6

On Python 3.11, this warning has been turned into a fatal error:

E                               re.error: global flags not at the start of the expression at position 6
/usr/lib64/python3.11/re/_parser.py:841: error

The problematic bit of GIST_RST_RE is the (?m) at the start, which is trying to set multiline mode. If you drop that the error goes away, but of course I'm not sure if that is the appropriate fix or would cause other problems. I can't offhand see an easy way to fix this while preserving the multiline mode setting though.

AdamWill commented 2 years ago

One option might be to switch GistPattern to inherit from InlineProcessor (or a subclass of it) instead of Pattern, as InlineProcessor doesn't 'wrap' the pattern when compiling it. I am not sure what the overall implications of that would be, though.

AdamWill commented 2 years ago

OK, yeah, I think just inheriting from InlineProcessor instead should work. Testing that now.