pypa / packaging-problems

An issue tracker for the problems in packaging
139 stars 33 forks source link

Broken links on PyPI #752

Open s2t2 opened 2 months ago

s2t2 commented 2 months ago

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:

henryiii commented 2 months ago

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.

s2t2 commented 2 months ago

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!

henryiii commented 2 months ago

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?

s2t2 commented 2 months ago

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"
    # ...
)
jeanas commented 2 months ago

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

ofek commented 1 month ago

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