Skip to content

Commit

Permalink
Merge pull request #230 from arXiv/add-gh-test
Browse files Browse the repository at this point in the history
Adds GH tests, Deletes arxiv.release
  • Loading branch information
bdc34 authored Oct 13, 2023
2 parents 1badbdc + 17b637d commit b934a9c
Show file tree
Hide file tree
Showing 17 changed files with 320 additions and 641 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/pullreqeust_tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Run Python Tests
on:
pull_request

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Python 3
uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install poetry
poetry install --with=dev
- name: Run Tests
run: poetry run pytest --cov=arxiv fourohfour --cov-fail-under=36 arxiv fourohfour
# - name: Check Types
# TODO The types are in bad shape and need to be fixed
# run: poetry run mypy --exclude "test*" -p arxiv
- name: Check Doc Style
run: poetry run pydocstyle --convention=numpy --add-ignore=D401 arxiv
- name: Run App Tests
run: poetry run python tests/run_app_tests.py
42 changes: 22 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
This project provides a base Flask application and base Docker image for
arXiv-NG services.

Each component of this project **must** meet all of the following criteria:
Each component of this project **must** meet all the following criteria:

1. It is likely that the component will be utilized in many or all arXiv
services.
2. Once stable, it is unlikely to change often.
3. It is unlikely that implementing new features in specific services
would require changes to the component.
4. When a component does change, it **must** change in the same way for all of
the services that use it.
4. When a component does change, it **must** change in the same way for all the services that use it.

## Base CSS and Templates for arXiv.org-NG

Expand Down Expand Up @@ -74,16 +73,18 @@ templates and static files available to you. For example, in your
```python
from flask import Flask
from arxiv.base import Base
from someapp import routes


def create_web_app() -> Flask:
app = Flask('someapp')
app = Flask('mega_tool')
app.config.from_pyfile('config.py')

Base(app) # Registers the base/UI blueprint.
app.register_blueprint(routes.blueprint) # Your blueprint.
return app
@app.route("/mega_tool")
def mega_tool():
# TODO use something from arxiv-base
return "<p>Mega_tool!</p>"

return app
```

You can now extend base templates, e.g.:
Expand All @@ -104,7 +105,7 @@ And use static files in your templates, e.g.:

## Static files and paths

In order to serve static assets for multiple versions of the an app at
In order to serve static assets for multiple versions of the app at
the same time, arxiv-base prefixes the app name and app version to
asset urls. This is to allow gracefully upgrades with no broken links
to css, js or images.
Expand All @@ -131,15 +132,16 @@ Be sure to initialize the integration after instantiating ``Base`` and
registering your blueprints. For example:

```python
def create_web_app() -> Flask:
"""Initialize and configure the application."""

app = Flask('coolapp')
app.config.from_object(config)
Base(app) # Gives us access to the base UI templates and resources.
app.register_blueprint(routes.blueprint)
s3.init_app(app) # <- Down here!
return app
# TODO just have a s3 script
# def create_web_app() -> Flask:
# """Initialize and configure the application."""
#
# app = Flask('cool_app')
# app.config.from_object(config)
# Base(app) # Gives us access to the base UI templates and resources.
# app.register_blueprint(routes.blueprint)
# s3.init_app(app) # <- Down here!
# return app
```

## App tests
Expand All @@ -149,8 +151,8 @@ Some tests to check app configuration and pattern compliance are provided in

## Editing and compiling sass

The file arxivstyle.css should never be edited directly. It is compiled from
arxivstyle.sass with this command from project directory root:
The file `arxivstyle.css` should never be edited directly. It is compiled from
`arxivstyle.sass` with this command from project directory root:
``sass arxiv/base/static/sass/arxivstyle.sass:arxiv/base/static/css/arxivstyle.css``

or you can use the ``--watch`` option to autocompile on any changed file:
Expand Down
7 changes: 3 additions & 4 deletions arxiv/base/config.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
"""Flask configuration."""

import importlib.metadata
from typing import Optional
import os
import secrets
from urllib.parse import urlparse
from arxiv.release.dist_version import get_version

SERVER_NAME = None

Expand Down Expand Up @@ -118,10 +117,10 @@

ARXIV_BUSINESS_TZ = os.environ.get("ARXIV_BUSINESS_TZ", "US/Eastern")

BASE_VERSION = get_version('arxiv-base')
BASE_VERSION = os.environ.get("BASE_VERSION", importlib.metadata.version('arxiv-base'))
"""The version of the arxiv-base package."""

APP_VERSION = get_version('arxiv-base')
APP_VERSION = os.environ.get("APP_VERSION", BASE_VERSION)
"""The version of the base test app. This is used to build the paths
to static assets, see :mod:`arxiv.base`."""

Expand Down
4 changes: 2 additions & 2 deletions arxiv/base/middleware/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def wrap(app: Flask, middlewares: List[IWSGIMiddlewareFactory]) -> Callable:
raise TypeError('Not a valid Flask app or middleware')

if not hasattr(app, 'middlewares'):
app.middlewares = {}
app.middlewares = {} #type: ignore

# Apply the last middleware first, so that the first middleware is called
# first upon the request.
Expand All @@ -127,7 +127,7 @@ def wrap(app: Flask, middlewares: List[IWSGIMiddlewareFactory]) -> Callable:
wrapped_app = middleware(wrapped_app)

key = getattr(middleware, '__name__', str(middleware))
app.middlewares[key] = wrapped_app
app.middlewares[key] = wrapped_app #type: ignore

app.wsgi_app = wrapped_app # type: ignore
return app
7 changes: 4 additions & 3 deletions arxiv/legacy/papers/deleted.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,17 @@

_deleted_data = None

def ensure_deleted_data(location=None) -> None:
def ensure_deleted_data(location: Optional[str] = None) -> None:
"""Checks that deleted data loads from Google storage and is not empty.
Raises an Exception if there are problems."""
Raises an Exception if there are problems.
"""
rd = get_deleted_data(location)
if not rd:
raise Exception("Deleted data was empty")


def get_deleted_data(location=None)->dict:
def get_deleted_data(location: Optional[str] = None)->dict:
"""Get the deleted data.
`get_deleted_data()` will attempt to get the data from GS only
Expand Down
13 changes: 8 additions & 5 deletions arxiv/legacy/papers/dissemination/reasons.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,17 @@

_reasons_data = None

def ensure_reasons_data(location=None) -> None:
"""Checks that reasons data loads from Google storage and is not
empty.
def ensure_reasons_data(location:Optional[str]=None) -> None:
"""Checks that reasons data loads from Google storage and is not empty.
Raises an Exception if there are problems.
"""
rd = get_reasons_data(location)
if not rd:
raise Exception("Reasons data was empty")


def get_reasons_data(location=None)->dict:
def get_reasons_data(location:Optional[str]=None)->dict:
"""Get the reasons data.
`get_reasons_data()` will attempt to get the data from GS only
Expand Down Expand Up @@ -61,6 +59,9 @@ def get_reasons_data(location=None)->dict:
if location is None:
location = os.environ.get("REASONS_GS_URL", DEFAULT_REASONS_GS_URL)

if location is None:
raise ValueError("Must pass location or set env var REASONS_GS_URL")

blob = None
try:
bucket_name = location.strip('gs://').split('/')[0]
Expand All @@ -86,6 +87,8 @@ def get_reasons_data(location=None)->dict:

def reasons(id: str, format: FORMATS)-> Optional[str] :
"""
Find any reasons for inability to process this paper.
Find all the recorded reasons for inability to process this paper (if any),
that are either general ($id recorded in reasons file with no extension) or
specific to $format ($id.format recorded in reasons file). If $id includes a
Expand Down
2 changes: 1 addition & 1 deletion arxiv/license/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,5 @@
}

CURRENT_LICENSE_URIS = \
sorted(CURRENT_LICENSES, key=lambda x: CURRENT_LICENSES[x]['order'])
sorted(CURRENT_LICENSES, key=lambda x: CURRENT_LICENSES[x]['order']) # type: ignore
"""Current license URIs by display order."""
154 changes: 0 additions & 154 deletions arxiv/release/README.md

This file was deleted.

1 change: 0 additions & 1 deletion arxiv/release/__init__.py

This file was deleted.

Loading

0 comments on commit b934a9c

Please sign in to comment.