Skip to content

Package update feed #2165

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

Closed
wants to merge 10 commits into from
20 changes: 20 additions & 0 deletions tests/unit/rss/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,23 @@ def test_rss_packages(db_request):
"newest_projects": [project3, project1],
}
assert db_request.response.content_type == "text/xml"


def test_rss_project_updates(db_request):
db_request.find_service = pretend.call_recorder(
lambda *args, **kwargs: pretend.stub(
enabled=False,
csp_policy=pretend.stub(),
merge=lambda _: None,
)
)

db_request.session = pretend.stub()

project = ProjectFactory.create()

db_request.matchdict["name"] = project.name
assert rss.rss_project_updates(project, db_request) == {
"project": project
}
assert db_request.response.content_type == "text/xml"
7 changes: 7 additions & 0 deletions tests/unit/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,13 @@ def add_policy(name, filename):
"https://files.example.com/packages/{path}",
),
pretend.call("rss.updates", "/rss/updates.xml", domain=warehouse),
pretend.call(
"rss.project_updates",
"/rss/{name}/updates.xml",
factory="warehouse.packaging.models:ProjectFactory",
traverse="/{name}",
domain=warehouse
),
pretend.call("rss.packages", "/rss/packages.xml", domain=warehouse),
pretend.call("legacy.api.simple.index", "/simple/", domain=warehouse),
pretend.call(
Expand Down
7 changes: 7 additions & 0 deletions warehouse/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,13 @@ def includeme(config):

# RSS
config.add_route("rss.updates", "/rss/updates.xml", domain=warehouse)
config.add_route(
"rss.project_updates",
"/rss/{name}/updates.xml",
factory="warehouse.packaging.models:ProjectFactory",
traverse="/{name}",
domain=warehouse
)
config.add_route("rss.packages", "/rss/packages.xml", domain=warehouse)

# Legacy URLs
Expand Down
19 changes: 19 additions & 0 deletions warehouse/rss/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,25 @@ def rss_updates(request):
return {"latest_releases": latest_releases}


@view_config(
route_name="rss.project_updates",
renderer="rss/project_updates.xml",
decorator=[
origin_cache(
1 * 24 * 60 * 60, # 1 day
stale_while_revalidate=1 * 24 * 60 * 60, # 1 day
stale_if_error=5 * 24 * 60 * 60, # 5 days
),
],
)
def rss_project_updates(project, request):
request.response.content_type = "text/xml"
request.find_service(name="csp").merge(XML_CSP)
return {
"project": project,
}


@view_config(
route_name="rss.packages",
renderer="rss/packages.xml",
Expand Down
1 change: 1 addition & 0 deletions warehouse/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

<link rel="alternate" type="application/rss+xml" title="RSS: 40 latest updates" href="{{ request.route_path('rss.updates') }}">
<link rel="alternate" type="application/rss+xml" title="RSS: 40 newest packages" href="{{ request.route_path('rss.packages') }}">
{% block extra_rss %}{% endblock %}
{% if self.canonical_url() %}
<link rel="canonical" href="{% block canonical_url %}{% endblock %}">
{% endif %}
Expand Down
4 changes: 4 additions & 0 deletions warehouse/templates/packaging/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ <h3 class="package-snippet__title">

{% block description %}{{ release.summary }}{% endblock %}

{% block extra_rss %}
<link rel="alternate" type="application/rss+xml" title="RSS: Latest releases of the {{ release.project.normalized_name }} package" href="{{ request.route_path('rss.project_updates', name=release.project.normalized_name) }}">
{% endblock %}

{% block canonical_url %}{{ request.route_url('packaging.project', name=release.project.name) }}{% endblock %}

{% block content %}
Expand Down
2 changes: 1 addition & 1 deletion warehouse/templates/rss/base.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<rss version="0.91">
<channel>
<title>{% block title %}{% endblock %}</title>
<link>{{ request.route_url('index') }}</link>
<link>{% block link %}{{ request.route_url('index') }}{% endblock %}</link>
<description>{% block description %}{% endblock %}</description>
<language>en</language>
{% block items %}{% endblock %}
Expand Down
14 changes: 14 additions & 0 deletions warehouse/templates/rss/project_updates.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{% extends "base.xml" %}
{% block title %}Latest releases of the "{{ project.name }}" project{% endblock %}
{% block description %}Latest releases of the "{{ project.name }}" project to the Python Package Index{% endblock %}
{% block link %}{{ request.route_url('packaging.project', name=project.name) }}{% endblock %}
{% block items %}
{% for release in project.releases %}
<item>
<title>{{ project_name }} {{ release.version }}</title>
<link>{{ request.route_url('packaging.release', name=release.project.normalized_name, version=release.version) }}</link>
<description>{{ release.summary }}</description>
<pubDate>{{ release.created|format_rfc822_datetime() }}</pubDate>
</item>
{% endfor %}
{% endblock %}