From 63d01b244807dfa58283792b69bf0db8d5f2d189 Mon Sep 17 00:00:00 2001 From: "Brian D. Caruso" Date: Tue, 16 Apr 2019 12:51:55 -0400 Subject: [PATCH 1/7] Sorting /abs secondaries by ID ARXIVNG-2066 --- arxiv/base/templates/base/macros.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arxiv/base/templates/base/macros.html b/arxiv/base/templates/base/macros.html index 0ddc480b..a0744e36 100644 --- a/arxiv/base/templates/base/macros.html +++ b/arxiv/base/templates/base/macros.html @@ -152,7 +152,7 @@

Title:{{ title|tex2utf Subjects: {{ primary_category|get_category_display }} - {%- for category in secondary_categories -%}; {{ category|get_category_display }}{%- endfor -%} + {%- for category in secondary_categories|sort(attribute='id') -%}; {{ category|get_category_display }}{%- endfor -%} {%- if msc_class %} @@ -229,7 +229,7 @@

Title:{{ title|tex2utf Title: {{ title }} Authors: {{ authors }} -Categories: {{ primary_category }}{%- for category in secondary_categories -%} {{ category }}{%- endfor %} +Categories: {{ primary_category }}{%- for category in secondary_categories|sort(attribute='id') -%} {{ category }}{%- endfor %} {% if comments -%}{{ ("Comments: " + comments)|wordwrap(77, wrapstring="\n ") }}{%- endif %} {% if msc_class -%}MSC classes: {{ msc_class }}{%- endif %} {% if acm_class -%}ACM classes: {{ acm_class }}{%- endif %} From a592dff926b70246a2f214171e56ab3d1cadccd3 Mon Sep 17 00:00:00 2001 From: erickpeirson Date: Wed, 17 Apr 2019 12:10:12 -0400 Subject: [PATCH 2/7] ARXIVNG-2073 add support for relative static paths --- Pipfile | 3 +- Pipfile.lock | 96 ++++++++++++++++++----------------- arxiv/base/__init__.py | 15 +++++- arxiv/base/config.py | 8 +++ arxiv/base/tests/test_urls.py | 50 +++++++++++++++++- 5 files changed, 123 insertions(+), 49 deletions(-) diff --git a/Pipfile b/Pipfile index 6bf1eda8..5b0370ab 100644 --- a/Pipfile +++ b/Pipfile @@ -10,10 +10,11 @@ pytz = "*" uwsgi = "*" "boto3" = "==1.9.108" wtforms = "*" -"e1839a8" = {path = "."} +e1839a8 = {path = "."} bleach = "*" "flask-s3" = "*" "backports-datetime-fromisoformat" = "==1.0.0" +arxiv-base = {path = "."} [dev-packages] pydocstyle = "*" diff --git a/Pipfile.lock b/Pipfile.lock index f94b93ea..ec53520a 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "75cc89a5e03bea10d6bbe0ae61f112b2270d6140fd5bef6ab02fa0bc08474c0c" + "sha256": "d110bbdfa41cd2a4a22e644be24c7c8f2c42590ee5dd7904ed7808e3ae3d7c6a" }, "pipfile-spec": 6, "requires": {}, @@ -14,6 +14,9 @@ ] }, "default": { + "arxiv-base": { + "path": "." + }, "attrs": { "hashes": [ "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", @@ -46,10 +49,10 @@ }, "botocore": { "hashes": [ - "sha256:7c8ec120bc5bcc4076aebd7dac3a679777ff3a3ce3263c64d7342ea7982b578c", - "sha256:f4607f8800f87fd8eacd450699666f92d7fbc48fbb757903ad56825ce08e072a" + "sha256:691a6fb8ef0edbe2aebe2c1b2707cac9b3f120a87f1c70af014e02542cf398a0", + "sha256:a0275f9b7cab4cab3a701ce53c8711c1a45b77bf1d719b9af9ed232f4abee99a" ], - "version": "==1.12.115" + "version": "==1.12.131" }, "click": { "hashes": [ @@ -94,10 +97,10 @@ }, "jinja2": { "hashes": [ - "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", - "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", + "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b" ], - "version": "==2.10" + "version": "==2.10.1" }, "jmespath": { "hashes": [ @@ -163,11 +166,11 @@ }, "pytz": { "hashes": [ - "sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9", - "sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c" + "sha256:303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda", + "sha256:d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141" ], "index": "pypi", - "version": "==2018.9" + "version": "==2019.1" }, "s3transfer": { "hashes": [ @@ -207,10 +210,10 @@ }, "werkzeug": { "hashes": [ - "sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c", - "sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b" + "sha256:0a73e8bb2ff2feecfc5d56e6f458f5b99290ef34f565ffb2665801ff7de6af7a", + "sha256:7fad9770a8778f9576693f0cc29c7dcc36964df916b83734f4431c0e612a7fbc" ], - "version": "==0.14.1" + "version": "==0.15.2" }, "wtforms": { "hashes": [ @@ -231,11 +234,11 @@ }, "astroid": { "hashes": [ - "sha256:0ef2bf9f07c3150929b25e8e61b5198c27b0dca195e156f0e4d5bdd89185ca1a", - "sha256:fc9b582dba0366e63540982c3944a9230cbc6f303641c51483fa547dcc22393a" + "sha256:87de48a92e29cedf7210ffa853d11441e7ad94cb47bacd91b023499b51cbc756", + "sha256:d25869fc7f44f1d9fb7d24fd7ea0639656f5355fc3089cd1f3d18c6ec6b124c7" ], "index": "pypi", - "version": "==1.6.5" + "version": "==1.6.6" }, "attrs": { "hashes": [ @@ -309,12 +312,12 @@ }, "hypothesis": { "hashes": [ - "sha256:6c715cd2ab3ed58f946484cc8967c15be968e6d6ef9eb2cd2079eb32eced4cbc", - "sha256:71f79108f21b5a27e76ac5b2dac3bf65af4e4c05d1b77394d680eb61e45352fd", - "sha256:f3954c8b2d1dff6b349fe191874ea51d37caa8c75e4951638b6d526592bc257c" + "sha256:4801b8175e2047abc8034fa1d4bce1a686225aefcfa3e0011d6c08f0324a807d", + "sha256:db7d64776d7c0fd04c874c5ab7d32d1b45c7d5d434fd130ce7746ec30c64bfc2", + "sha256:e86040269da16622fcc2771a211f93ce93e10fc8fb1f6f622dcd4507ae5670a4" ], "index": "pypi", - "version": "==4.11.5" + "version": "==4.17.1" }, "idna": { "hashes": [ @@ -332,17 +335,17 @@ }, "isort": { "hashes": [ - "sha256:18c796c2cd35eb1a1d3f012a214a542790a1aed95e29768bdcb9f2197eccbd0b", - "sha256:96151fca2c6e736503981896495d344781b60d18bfda78dc11b290c6125ebdb6" + "sha256:01cb7e1ca5e6c5b3f235f0385057f70558b70d2f00320208825fa62887292f43", + "sha256:268067462aed7eb2a1e237fcb287852f22077de3fb07964e87e00f829eea2d1a" ], - "version": "==4.3.15" + "version": "==4.3.17" }, "jinja2": { "hashes": [ - "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", - "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", + "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b" ], - "version": "==2.10" + "version": "==2.10.1" }, "lazy-object-proxy": { "hashes": [ @@ -435,10 +438,11 @@ }, "nose2": { "hashes": [ - "sha256:9052f2b46807b63d9bdf68e0768da1f8386368889b50043fd5d0889c470258f3" + "sha256:0ede156fd7974fa40893edeca0b709f402c0ccacd7b81b22e76f73c116d1b999", + "sha256:31d8beb00aed3ccc6efb1742bb90227d883e471715188249f594310676e0ef0e" ], "index": "pypi", - "version": "==0.8.0" + "version": "==0.9.1" }, "packaging": { "hashes": [ @@ -473,18 +477,18 @@ }, "pyparsing": { "hashes": [ - "sha256:66c9268862641abcac4a96ba74506e594c884e3f57690a696d21ad8210ed667a", - "sha256:f6c5ef0d7480ad048c054c37632c67fca55299990fff127850181659eea33fc3" + "sha256:1873c03321fc118f4e9746baf201ff990ceb915f433f23b395f5580d1840cb2a", + "sha256:9b6323ef4ab914af344ba97510e966d64ba91055d6b9afa6b30799340e89cc03" ], - "version": "==2.3.1" + "version": "==2.4.0" }, "pytz": { "hashes": [ - "sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9", - "sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c" + "sha256:303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda", + "sha256:d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141" ], "index": "pypi", - "version": "==2018.9" + "version": "==2019.1" }, "requests": { "hashes": [ @@ -509,11 +513,11 @@ }, "sphinx": { "hashes": [ - "sha256:230af939a2f678ab4f2a0a948c3b24a822a0d280821859caaefb750ef7413003", - "sha256:835c701420102a0a71ba2ed54a5bada2da6fd01263bf6dc8c5c80c798e27709c" + "sha256:423280646fb37944dd3c85c58fb92a20d745793a9f6c511f59da82fa97cd404b", + "sha256:de930f42600a4fef993587633984cc5027dedba2464bcf00ddace26b40f8d9ce" ], "index": "pypi", - "version": "==2.0.0b1" + "version": "==2.0.1" }, "sphinx-autodoc-typehints": { "hashes": [ @@ -539,10 +543,10 @@ }, "sphinxcontrib-htmlhelp": { "hashes": [ - "sha256:0d691ca8edf5995fbacfe69b191914256071a94cbad03c3688dca47385c9206c", - "sha256:e31c8271f5a8f04b620a500c0442a7d5cfc1a732fa5c10ec363f90fe72af0cb8" + "sha256:4670f99f8951bd78cd4ad2ab962f798f5618b17675c35c5ac3b2132a14ea8422", + "sha256:d4fd39a65a625c9df86d7fa8a2d9f3cd8299a3a4b15db63b50aac9e161d8eff7" ], - "version": "==1.0.1" + "version": "==1.0.2" }, "sphinxcontrib-jsmath": { "hashes": [ @@ -560,18 +564,18 @@ }, "sphinxcontrib-serializinghtml": { "hashes": [ - "sha256:01d9b2617d7e8ddf7a00cae091f08f9fa4db587cc160b493141ee56710810932", - "sha256:392187ac558863b8aff0d76dc78e0731fed58f3b06e2b00e22995dcdb630f213" + "sha256:c0efb33f8052c04fd7a26c0a07f1678e8512e0faec19f4aa8f2473a8b81d5227", + "sha256:db6615af393650bf1151a6cd39120c29abaf93cc60db8c48eb2dddbfdc3a9768" ], - "version": "==1.1.1" + "version": "==1.1.3" }, "sphinxcontrib-websupport": { "hashes": [ - "sha256:68ca7ff70785cbe1e7bccc71a48b5b6d965d79ca50629606c7861a21b206d9dd", - "sha256:9de47f375baf1ea07cdb3436ff39d7a9c76042c10a769c52353ec46e4e8fc3b9" + "sha256:4044751a075b6560f155c96f9fec6bc5198cd5307e5db9f77c7b1c5247ac9a09", + "sha256:c1b918b1b41cde045cdb9755941086b4ce4ebbfd7bff41d10ffb6d325779cbf9" ], "index": "pypi", - "version": "==1.1.0" + "version": "==1.1.1.dev20190321" }, "typed-ast": { "hashes": [ diff --git a/arxiv/base/__init__.py b/arxiv/base/__init__.py index 2bc54541..01bb51ba 100644 --- a/arxiv/base/__init__.py +++ b/arxiv/base/__init__.py @@ -51,6 +51,19 @@ def init_app(self, app: Flask) -> None: # Set the static url path. app_version = app.config.get("APP_VERSION", "null") app_static_path = f'/static/{app.name}/{app_version}' + + base_static_url_path = f'/static/base/{base_config.BASE_VERSION}' + + # In some cases, we want an app to handle all of its static files, e.g. + # when deploying in a development environment. Setting the + # configuration param RELATIVE_STATIC_PATHS to True will cause + # ``/{RELATIVE_STATIC_PATHS}`` to be prepended to the static paths for + # base assets. This should have no impact on static paths for + # blueprints. + if app.config.get('RELATIVE_STATIC_PATHS'): + prefix = app.config.get('RELATIVE_STATIC_PREFIX', '').strip('/') + base_static_url_path = f'/{prefix}{base_static_url_path}' + app.static_url_path = app_static_path # The base blueprint attaches static assets and templates. These are @@ -64,7 +77,7 @@ def init_app(self, app: Flask) -> None: __name__, template_folder='templates', static_folder='static', - static_url_path=f'/static/base/{base_config.BASE_VERSION}' + static_url_path=base_static_url_path ) app.register_blueprint(blueprint) diff --git a/arxiv/base/config.py b/arxiv/base/config.py index d5a4c495..e9b521a3 100644 --- a/arxiv/base/config.py +++ b/arxiv/base/config.py @@ -91,3 +91,11 @@ AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID', 'nope') AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY', 'nope') AWS_REGION = os.environ.get('AWS_REGION', 'us-east-1') + +# In some cases, we want an app to handle all of its static files, e.g. when +# deploying in a development environment. Setting the configuration param +# RELATIVE_STATIC_PATHS to True will cause ``/{RELATIVE_STATIC_PREFIX}`` to be +# prepended to the static paths for base assets. This should have no impact on +# static paths for blueprints. +RELATIVE_STATIC_PATHS = bool(int(os.environ.get('RELATIVE_STATIC_PATHS', '0'))) +RELATIVE_STATIC_PREFIX = os.environ.get('RELATIVE_STATIC_PREFIX', '') diff --git a/arxiv/base/tests/test_urls.py b/arxiv/base/tests/test_urls.py index f20f7330..724c11cc 100644 --- a/arxiv/base/tests/test_urls.py +++ b/arxiv/base/tests/test_urls.py @@ -1,12 +1,60 @@ """Tests for :mod:`arxiv.base.urls`.""" from unittest import TestCase, mock -from flask import Flask, url_for +from flask import Flask, url_for, Blueprint from arxiv.base import urls, Base from arxiv.base.exceptions import ConfigurationError from werkzeug.routing import BuildError +class TestStaticURLs(TestCase): + """Test building static URLs.""" + + def test_static_urls(self): + """We have vanilla Flask app with a blueprint.""" + self.app = Flask('test') + self.app.config['SERVER_NAME'] = 'nope.com' + Base(self.app) + + self.app.register_blueprint(Blueprint('fooprint', __name__, + url_prefix='/foo', + static_folder='static', + static_url_path='baz')) + + with self.app.app_context(): + url = url_for('base.static', filename='css/abs.css') + self.assertTrue(url.startswith('http://nope.com/static/base/')) + url = url_for('fooprint.static', filename='img/foo.jpg') + self.assertTrue(url.startswith('http://nope.com/foo/static/test/')) + + def test_relative_static_urls(self): + """Relative static paths are enabled.""" + self.app = Flask('test') + self.app.config['SERVER_NAME'] = 'nope.com' + self.app.config.update({ + 'SITE_HUMAN_NAME': 'The test site of testiness', + 'SITE_HUMAN_SHORT_NAME': 'Test site', + 'RELATIVE_STATIC_PATHS': True, + 'RELATIVE_STATIC_PREFIX': 'oof', + 'SITE_URL_PREFIX': '/test' + }) + Base(self.app) + + self.app.register_blueprint(Blueprint('fooprint', __name__, + url_prefix='/foo', + static_folder='static', + static_url_path='baz')) + + with self.app.app_context(): + url = url_for('base.static', filename='css/abs.css') + self.assertTrue(url.startswith('http://nope.com/oof/static/base/'), + 'The static URL for base starts with the' + ' configured prefix.') + url = url_for('fooprint.static', filename='img/foo.jpg') + self.assertFalse(url.startswith('http://nope.com/oof'), + 'The blueprint static path is not affected.') + + class TestGetURLMap(TestCase): """Tests for :func:`arxiv.base.urls.get_url_map`.""" From 19cdffc2239f7bd1f6f4bb1b5055a910de7da1fa Mon Sep 17 00:00:00 2001 From: "Brian D. Caruso" Date: Wed, 17 Apr 2019 12:52:14 -0400 Subject: [PATCH 3/7] Urlize no longer turns category names like math.CO into urls ARXIVNG-2068 --- arxiv/base/urls/links.py | 18 +++++++++++++++++- arxiv/base/urls/tests/test_urlize.py | 15 +++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/arxiv/base/urls/links.py b/arxiv/base/urls/links.py index 1cbfcc60..c58baeac 100644 --- a/arxiv/base/urls/links.py +++ b/arxiv/base/urls/links.py @@ -43,6 +43,7 @@ from jinja2 import Markup, escape import bleach +from arxiv.taxonomy import CATEGORIES from arxiv import identifier from . import clickthrough @@ -230,6 +231,21 @@ def _handle_doi_url(attrs: Attrs, new: bool = False) -> Attrs: attrs[(None, 'data-doi')] = target # Add arxiv="" return attrs +ENDS_WITH_TLD = r".*\.(" + TLDS + ")$" +CATEGORIES_THAT_COULD_BE_HOSTNAMES = '|'.join([cat_id for cat_id in CATEGORIES.keys() + if re.search(ENDS_WITH_TLD, cat_id, re.IGNORECASE)]) +DONT_URLIZE_CATS = re.compile(CATEGORIES_THAT_COULD_BE_HOSTNAMES, + re.IGNORECASE|re.UNICODE) +def _dont_urlize_arxiv_categories(attrs: Attrs, new: bool = False) -> Attrs: + """Prevents urlizing archive categories that look like hostnames. + + Ex. don't urlize math.CO but do urlize supermath.co + """ + url = urlparse(attrs[(None, 'href')]) + if DONT_URLIZE_CATS.match(url.netloc): + return None + else: + return attrs PATTERNS = { 'doi': DOI, @@ -248,7 +264,7 @@ def _handle_doi_url(attrs: Attrs, new: bool = False) -> Attrs: 'doi': [_handle_doi_url, _add_scheme_info, _add_rel_external], 'doi_field': [_handle_doi_url, _add_scheme_info, _add_rel_external], 'arxiv_id': [_handle_arxiv_url, _add_scheme_info], - 'url': [_this_url_text, _add_rel, _add_scheme_info ] + 'url': [_dont_urlize_arxiv_categories, _this_url_text, _add_rel, _add_scheme_info] } """Bleach attribute callbacks for each kind.""" diff --git a/arxiv/base/urls/tests/test_urlize.py b/arxiv/base/urls/tests/test_urlize.py index f1454c47..ec8cb955 100644 --- a/arxiv/base/urls/tests/test_urlize.py +++ b/arxiv/base/urls/tests/test_urlize.py @@ -1,5 +1,6 @@ import unittest from unittest import mock +import re from jinja2 import escape from .. import links @@ -51,6 +52,12 @@ def find_match(txt): class TestURLize(unittest.TestCase): + + def test_dont_urlize_cats( self ): + self.assertGreater(len(links.CATEGORIES_THAT_COULD_BE_HOSTNAMES), 0, + 'The links.CATEGORIES_THAT_COULD_BE_HOSTNAMES must not be empty or it will match everything') + + @mock.patch(f'{links.__name__}.clickthrough') def test_doi(self, mock_clickthrough): mock_clickthrough.clickthrough_url = lambda url: f'http://arxiv.org/clickthrough?url={url}' @@ -313,3 +320,11 @@ def test_broad_doi(self, mock_clickthrough): # Post clickthrough on legacy goes to : # https://dx.doi.org/10.1175%2F1520-0469%281996%29053%3C0946%3AASTFHH%3E2.0.CO%3B2 + + + def test_dont_urlize_category_name(self): + urlize = links.urlizer() + self.assertEqual(urlize('math.CO'), 'math.CO', + 'category name math.CO should not get urlized') + self.assertIn('href="http://supermath.co', urlize('supermath.co'), + 'hostname close to category name should get urlized') From 70c98fe511cc0de673dc08239d4ef9893dacb293 Mon Sep 17 00:00:00 2001 From: Martin Lessmeister Date: Wed, 17 Apr 2019 13:51:43 -0400 Subject: [PATCH 4/7] pydocstyle fixes --- arxiv/base/urls/links.py | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/arxiv/base/urls/links.py b/arxiv/base/urls/links.py index c58baeac..965e4ee7 100644 --- a/arxiv/base/urls/links.py +++ b/arxiv/base/urls/links.py @@ -33,14 +33,12 @@ Updated 20 March, 2019: refactored to provide independent bleach attribute callbacks for each kind of link. """ -from typing import Optional, List, Pattern, Match, Tuple, Callable, \ - NamedTuple, Dict, Union, Mapping +from typing import List, Pattern, Tuple, Callable, Dict, Union import re -from functools import partial, reduce +from functools import reduce from urllib.parse import quote, urlparse from flask import url_for -from jinja2 import Markup, escape import bleach from arxiv.taxonomy import CATEGORIES @@ -73,7 +71,7 @@ def _without_group_names(pattern: Pattern) -> str: """ -BROAD_DOI=re.compile(r'(?P10\.\d{4,5}\/\S+)', re.I) +BROAD_DOI = re.compile(r'(?P10\.\d{4,5}\/\S+)', re.I) """ Very broad pattern for matching DOIs in the abs DOI field. @@ -154,8 +152,9 @@ def _add_rel(attrs: Attrs, new: bool = False) -> Attrs: else: return _add_rel_internal(attrs, new) + def _add_rel_external(attrs: Attrs, new: bool = False) -> Attrs: - """Always adds external rel.""" + """Add an external rel.""" # noopener for security reasons # nofollow to disencentivie arXiv articles for SEO # external says that link is away from arxiv @@ -163,11 +162,13 @@ def _add_rel_external(attrs: Attrs, new: bool = False) -> Attrs: _extend_class_attr(attrs, 'link-external') return attrs + def _add_rel_internal(attrs: Attrs, new: bool = False) -> Attrs: - """Always adds interal rel.""" + """Add an interal rel.""" _extend_class_attr(attrs, 'link-internal') return attrs + def _this_url_text(attrs: Attrs, new: bool = False) -> Attrs: o = urlparse(attrs[(None, 'href')]) attrs['_text'] = f'this {o.scheme} URL' # Replaces the link text. @@ -231,13 +232,17 @@ def _handle_doi_url(attrs: Attrs, new: bool = False) -> Attrs: attrs[(None, 'data-doi')] = target # Add arxiv="" return attrs + ENDS_WITH_TLD = r".*\.(" + TLDS + ")$" CATEGORIES_THAT_COULD_BE_HOSTNAMES = '|'.join([cat_id for cat_id in CATEGORIES.keys() - if re.search(ENDS_WITH_TLD, cat_id, re.IGNORECASE)]) + if re.search(ENDS_WITH_TLD, cat_id, re.IGNORECASE)]) DONT_URLIZE_CATS = re.compile(CATEGORIES_THAT_COULD_BE_HOSTNAMES, - re.IGNORECASE|re.UNICODE) + re.IGNORECASE | re.UNICODE) + + def _dont_urlize_arxiv_categories(attrs: Attrs, new: bool = False) -> Attrs: - """Prevents urlizing archive categories that look like hostnames. + """ + Prevent urlizing archive categories that look like hostnames. Ex. don't urlize math.CO but do urlize supermath.co """ @@ -247,6 +252,7 @@ def _dont_urlize_arxiv_categories(attrs: Attrs, new: bool = False) -> Attrs: else: return attrs + PATTERNS = { 'doi': DOI, 'doi_field': BROAD_DOI, @@ -272,7 +278,7 @@ def _dont_urlize_arxiv_categories(attrs: Attrs, new: bool = False) -> Attrs: def _get_pattern(kinds: List[str]) -> Pattern: return re.compile( '|'.join([rf'(?:{PATTERNS[kind].pattern})' for kind - in sorted(kinds, key=lambda kind: ORDER.index(kind))]), + in sorted(kinds, key=lambda kind: ORDER.index(kind))]), re.IGNORECASE | re.VERBOSE | re.UNICODE ) @@ -290,7 +296,7 @@ def _get_linker_of_kind(kind: str) -> Callable_Linker: def _compose_list_of_funcs(fv: List[Callable_Linker]) -> Callable_Linker: - """Returns function that calls fv functions one after another.""" + """Return function that calls fv functions one after another.""" if not fv: return lambda x: x return reduce(lambda f, g: lambda x: f(g(x)), fv[1:], fv[0]) @@ -298,7 +304,8 @@ def _compose_list_of_funcs(fv: List[Callable_Linker]) -> Callable_Linker: def _get_linker(kinds: List[str]) -> Callable_Linker: if len(kinds) > 1 and 'doi_field' in kinds: - raise ValueError('doi_field should not be used in combination with other kinds') + raise ValueError( + 'doi_field should not be used in combination with other kinds') ordered_linkers = [_get_linker_of_kind(kind) for kind in sorted(kinds, key=lambda kind: ORDER.index(kind))] return _compose_list_of_funcs(ordered_linkers) From 3d34cc400bb71680573027741e302403977cd56a Mon Sep 17 00:00:00 2001 From: Martin Lessmeister Date: Wed, 17 Apr 2019 14:24:16 -0400 Subject: [PATCH 5/7] mypy fix --- arxiv/base/urls/links.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arxiv/base/urls/links.py b/arxiv/base/urls/links.py index 965e4ee7..d902c9ee 100644 --- a/arxiv/base/urls/links.py +++ b/arxiv/base/urls/links.py @@ -248,7 +248,7 @@ def _dont_urlize_arxiv_categories(attrs: Attrs, new: bool = False) -> Attrs: """ url = urlparse(attrs[(None, 'href')]) if DONT_URLIZE_CATS.match(url.netloc): - return None + return None # type: ignore else: return attrs From 88c6fcbbb96e5a9c33eb142b84624f7a2481bcb9 Mon Sep 17 00:00:00 2001 From: Martin Lessmeister Date: Wed, 17 Apr 2019 16:40:45 -0400 Subject: [PATCH 6/7] update release version to 0.15.5 --- arxiv/base/config.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arxiv/base/config.py b/arxiv/base/config.py index d5a4c495..eb91842b 100644 --- a/arxiv/base/config.py +++ b/arxiv/base/config.py @@ -70,7 +70,7 @@ ARXIV_BUSINESS_TZ = os.environ.get("ARXIV_BUSINESS_TZ", "US/Eastern") -BASE_VERSION = "0.15.4" +BASE_VERSION = "0.15.5" """The version of the arxiv-base package.""" APP_VERSION = "0.15.4" diff --git a/setup.py b/setup.py index 5dea6df8..0dbd1b51 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name='arxiv-base', - version='0.15.4', + version='0.15.5', packages=[f'arxiv.{package}' for package in find_packages('arxiv', exclude=['*test*'])], zip_safe=False, From 222017285d3f522c568b191329400ae6f2ab2471 Mon Sep 17 00:00:00 2001 From: Erick Date: Thu, 18 Apr 2019 07:25:19 -0400 Subject: [PATCH 7/7] Update Pipfile --- Pipfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Pipfile b/Pipfile index 5b0370ab..2a91e4e7 100644 --- a/Pipfile +++ b/Pipfile @@ -10,11 +10,9 @@ pytz = "*" uwsgi = "*" "boto3" = "==1.9.108" wtforms = "*" -e1839a8 = {path = "."} bleach = "*" "flask-s3" = "*" "backports-datetime-fromisoformat" = "==1.0.0" -arxiv-base = {path = "."} [dev-packages] pydocstyle = "*"