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 @@ -141,6 +141,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 @@ -114,6 +114,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,
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we made the necessary changes to get a project via the ProjectFactory, we could just pass the project variable to the template here, and use project.name and project.releases (which is ordered by creation date) directly in the template.



@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 }} package{% endblock %}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: this should probably say "project", not package. It would be good to put the project name in quotes too.

{% block description %}Latest releases of the {{ project.name }} to the Python Package Index{% endblock %}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, let's add quotes and "project".

{% 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 %}