packaging-problems icon indicating copy to clipboard operation
packaging-problems copied to clipboard

Broken links on PyPI

Open s2t2 opened this issue 1 year ago • 6 comments

Problem description

I am publishing my package to PyPI, and my repository's README file is displayed on PyPI as desired.

However all the markdown links in the README file that point to other documentation files in my repo are broken.

Because the README file markdown link is like this [other file](/docs/other.md), PyPI sends the user to https://pypi.org/docs/other.md instead of to the relative file in my repo.

What is the intended way to fix this issue? Absolute links is not what I'm looking for.

See:

  • https://github.com/s2t2/gspread-models-py
  • https://pypi.org/project/gspread-models/

s2t2 avatar Apr 29 '24 18:04 s2t2

You must use the full URLs for the README. PyPI does not support hosting your full documentation, only one page - the package "readme" (which is part of your metadata). If you want to have relative links in your on-disk/git README.md file, you can post-process them when filling the package metadata. It's easy with hatchling, you can use hatch-fancy-pypi-readme and statically defined regular expressions. With setuptools, you can open the file in setup.py and process it yourself.

henryiii avatar Apr 29 '24 18:04 henryiii

OK I am taking a look at the hatch-fancy-pypi-readme repo, however since I am using setup.py, if you are able to point me at some specific source code within the repo I can use / repurpose, that would be helpful Thanks!

s2t2 avatar Apr 29 '24 20:04 s2t2

Not tested and I used ChatGPT to write the expression, but something like this:

import re

with open("README.md", "r", encoding="utf-8") as fh:
    long_description = fh.read()

Then I asked ChatGPT and this is what it gave me:

import re

# Sample markdown text
long_description = """
Here is a [sample relative link](../path/to/page) in markdown format.
And here is another [relative link](../another/path) for demonstration.
And here is an [absolute link](https://example.com) to be ignored.
"""

# Base URL
base_url = "https://github.com/a/b"

def convert_to_absolute(match):
    text = match.group(1)
    relative_url = match.group(2)
    absolute_url = f"{base_url.rstrip('/')}/{relative_url.lstrip('/')}"
    return f"[{text}]({absolute_url})"

# Replace relative links with absolute links
long_description = re.sub(r'\[([^\[\]]+)\]\((?!https?://)([^/\(\)]+)\)', convert_to_absolute, long_description)

That's not exactly how I'd write it, but hopefully that's close enough to help?

henryiii avatar Apr 29 '24 20:04 henryiii

OK thanks. Just as a brainstorm, it would be cool to be able to hook into the functionality of hatch_fancy_pypi_readme as an installable Python package.

So desired usage would be something like:

# this is the setup.py file

from setuptools import setup 
from hatch_fancy_pypi_readme import fix_relative_links

long_description = fix_relative_links("README.md", base_url="https://github.com/user-name/repo-name")

setup(
    # ...
    long_description=long_description,
    long_description_content_type="text/markdown"
    # ...
)

s2t2 avatar Apr 29 '24 21:04 s2t2

Do you have a specific reason for needing setuptools and setup.py instead of hatchling as your build backend?

jeanas avatar Apr 29 '24 21:04 jeanas

Example usage: https://github.com/pydantic/pydantic/blob/4d7bef62aeff10985fe67d13477fe666b13ba070/pyproject.toml#L83-L97

ofek avatar May 05 '24 04:05 ofek