-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Move builtin themes to external packages other than MkDocs and ReadTheDocs #530
Conversation
|
||
for theme in iter_entry_points(group='mkdocs.themes', name=None): | ||
theme = theme.load() | ||
location = os.path.dirname(theme.__file__) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this. The theme author does not need to write any Python code. In sphinx, the theme author needs to write some code in the __init__.py
file which returns the location. This is much better. Just include the empty file at the root of the theme, and it becomes available.
I'm not sure what happens if two packages provide the same theme name, I can't find any documentation on this and you can't specify a duplicate in one package, so I guess I'll need to manually test and see. |
Yeah, I'm not sure either. Although my understanding is that there is no restriction on duplicates. The duplicates are separated by the namespace/package that they ship in (the idea being that an entry_point named "foo" for package A would not be confused with an entry_point named "foo" for package B. Of course, when package B is a third party addon to package A, then package A can't make that distinction. As the only way to get entry_points across multiple packages is to iterate, the last entry_point named "foo" in your for loop will be the one that gets used. I am not sure what determined the order. If it is 'last installed' that is probably fine, but it my not be and I haven't worked that part out. |
Last installed would still be vague. Maybe we should change the theme config option to So in the case of the builtin themes, it would be I'm tempted to say that the risk is really small enough that it is worth the convenience. |
I think the last paragraph in this section is relevant. Specifically, it is up to you to decide how to handle duplicates. That said, the docs for iter_entry_points states that duplicates are ordered by the package/distribution they are associated with on the PYTHONPATH. So, if two themes exist with the same name, the second one to be found on the PYTHONPATH will always overwrite the first one in your loop. Which comes first or second depends on how each machine is configured and where each package in installed on the path. You will even find different configurations on different machines using the same version of the same OS. In other words, it is completely unpredictable. You could check for duplicates and either raise a warning or an error. At least that way a user would have a clue as to why the wrong theme is being used. Just make sure each warning/error message lists which package the duplicates are associated with so they can uninstall the one they don't want. For the themes included with mkdocs, you can special case them to not allow duplicates. That way, others will not even bother making duplicates of the builtin themes as it will never work. Doing |
Sorry, actually |
Perhaps something like this would work (untested): themes = {}
builtins = get_entry_map(dist='mkdocs', group='mkdocs.themes')
for theme in iter_entry_points(group='mkdocs.themes'):
if theme.name in builtins and theme.dist.key != 'mkdocs':
# raise an error...
if theme.name in themes:
# raise a warning...
themes[theme.name] = os.path.dirname(theme.load().__file__) |
Another possibility (again untested): themes = {}
for theme in iter_entry_points(group='mkdocs.themes'):
name = '.'.join(theme.dist.key, theme.name)
themes[name] = os.path.dirname(theme.load().__file__) According to the docs, There would be no duplicates. However, the entry point would not be the full name, only the last part and that could be slightly confusing to some. Clear documentation would be required. |
And I just realized my last suggestion was the same as yours @d0ugal.
That is a valid point. But what if you renamed the "mkdocs" theme to "default" or "basic" (or something better). That way, in the config the user would set |
Thanks for throwing those ideas in, I am inclined to go for erroring if a builtin theme is used and logging a warning if a name is used twice. Simply because this provides us the easiest transition path, all the current names are will work and I expect the most common case will be theme packages that contain one theme. We can then encourage users use the package name for the theme name, ensuring some uniqueness (assuming they register and upload to PyPI). |
@d0ugal that sounds like a reasonable conclusion and my preference as well. |
It also means I can probably remove the bootswatch themes for 0.13, and just add them as a requirement. It might delay the release a bit, but I've been itching to do this for a long time. I'm even slightly tempted to move the mkdocs and readthedocs themes into their own packages. However, that might be going a bit far. I'll need to think about that more. |
Nice! I think this is a good idea. |
7f6ec8d
to
17a2e6f
Compare
I think I'm happy with this, but I want to play with it a bit more. So targeting the next release and I'll get 0.13 out of the door by the end of the month. |
I like it. |
❤️ @appveyor's new speed. |
Move builtin themes to external packages other than MkDocs and ReadTheDocs
+697 −12,897. So happy. |
✨ 😌 ✨ |
This needs a few remaining things done: