Compare commits
12 commits
main
...
dependenci
| Author | SHA1 | Date | |
|---|---|---|---|
| d7b9006c64 | |||
| c268768187 | |||
| d02aa74413 | |||
| 2bb5e4f66f | |||
| 491e566566 | |||
| 6cef4c9fe5 | |||
| e93a323959 | |||
| 2879bc8305 | |||
| 89efdb30fd | |||
| 28df757ea8 | |||
| 841ca7d674 | |||
| 2f22e635b3 |
50 changed files with 11613 additions and 16845 deletions
11
.babelrc
11
.babelrc
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"presets": ["@babel/preset-env"],
|
|
||||||
"plugins": [
|
|
||||||
"@babel/plugin-transform-runtime",
|
|
||||||
"@babel/plugin-syntax-dynamic-import",
|
|
||||||
"@babel/plugin-transform-react-jsx",
|
|
||||||
"@babel/plugin-syntax-function-bind",
|
|
||||||
"@babel/plugin-proposal-function-bind",
|
|
||||||
["@babel/plugin-proposal-class-properties", {loose: true}],
|
|
||||||
]
|
|
||||||
}
|
|
||||||
12
CHANGELOG.md
12
CHANGELOG.md
|
|
@ -1,5 +1,17 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.5.0
|
||||||
|
|
||||||
|
- Require python 3.11
|
||||||
|
- Require node 18 (current LTS)
|
||||||
|
- Upgrade webpack 4 -> 5
|
||||||
|
- Updated python dependencies
|
||||||
|
- `django` `3.2` -> `4.2`
|
||||||
|
- `psycopg` `2.9.x` -> `3.1.x`
|
||||||
|
- `python-dotenv` `2.9.x` -> `3.1.x`
|
||||||
|
- migrated from `python-memcached` to `pymemcache`
|
||||||
|
- removed `drf-yasg`
|
||||||
|
|
||||||
## 0.4.2
|
## 0.4.2
|
||||||
|
|
||||||
- Set `SECURE_PROXY_SSL_HEADER` setting for production
|
- Set `SECURE_PROXY_SSL_HEADER` setting for production
|
||||||
|
|
|
||||||
12
babel.config.js
Normal file
12
babel.config.js
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
module.exports = {
|
||||||
|
presets: [
|
||||||
|
['@babel/preset-env', { targets: { node: 'current' } }],
|
||||||
|
'@babel/preset-react',
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
'@babel/plugin-transform-runtime',
|
||||||
|
'@babel/plugin-syntax-function-bind',
|
||||||
|
'@babel/plugin-proposal-function-bind',
|
||||||
|
['@babel/plugin-proposal-class-properties', { loose: true }],
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# stage 1
|
# stage 1
|
||||||
FROM python:3.9-bullseye as backend
|
FROM python:3.11-bookworm as backend
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
vim \
|
vim \
|
||||||
|
|
@ -18,7 +18,7 @@ RUN pip install -r requirements/base.txt
|
||||||
|
|
||||||
|
|
||||||
# stage 2
|
# stage 2
|
||||||
FROM node:16-bullseye AS frontend-build
|
FROM node:lts-bookworm AS frontend-build
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
git \
|
git \
|
||||||
|
|
@ -28,15 +28,15 @@ WORKDIR /app
|
||||||
|
|
||||||
COPY ./*.json ./*.js ./.babelrc /app/
|
COPY ./*.json ./*.js ./.babelrc /app/
|
||||||
|
|
||||||
RUN npm ci
|
RUN npm ci --include=dev
|
||||||
|
|
||||||
COPY ./src /app/src
|
COPY ./src /app/src
|
||||||
|
|
||||||
RUN npm run build
|
RUN npm run build:prod
|
||||||
|
|
||||||
|
|
||||||
# stage 3
|
# stage 3
|
||||||
FROM python:3.9-bullseye as production
|
FROM python:3.11-bookworm as production
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
postgresql-client \
|
postgresql-client \
|
||||||
|
|
@ -51,7 +51,7 @@ RUN mkdir /app/logs
|
||||||
RUN mkdir /app/media
|
RUN mkdir /app/media
|
||||||
RUN mkdir /app/bin
|
RUN mkdir /app/bin
|
||||||
|
|
||||||
COPY --from=backend /usr/local/lib/python3.9 /usr/local/lib/python3.9
|
COPY --from=backend /usr/local/lib/python3.11 /usr/local/lib/python3.11
|
||||||
COPY --from=backend /usr/local/bin/celery /usr/local/bin/celery
|
COPY --from=backend /usr/local/bin/celery /usr/local/bin/celery
|
||||||
|
|
||||||
COPY ./bin/docker-entrypoint.sh /app/bin/docker-entrypoint.sh
|
COPY ./bin/docker-entrypoint.sh /app/bin/docker-entrypoint.sh
|
||||||
|
|
@ -81,7 +81,7 @@ RUN python src/manage.py collectstatic --noinput
|
||||||
|
|
||||||
|
|
||||||
# (optional) stage 4
|
# (optional) stage 4
|
||||||
FROM python:3.9-bullseye as development
|
FROM python:3.11-bookworm as development
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
vim \
|
vim \
|
||||||
|
|
@ -96,7 +96,7 @@ RUN mkdir /app/bin
|
||||||
|
|
||||||
COPY ./requirements /app/requirements
|
COPY ./requirements /app/requirements
|
||||||
COPY ./bin/docker-entrypoint.sh /app/bin/docker-entrypoint.sh
|
COPY ./bin/docker-entrypoint.sh /app/bin/docker-entrypoint.sh
|
||||||
COPY --from=backend /usr/local/lib/python3.9 /usr/local/lib/python3.9
|
COPY --from=backend /usr/local/lib/python3.11 /usr/local/lib/python3.11
|
||||||
COPY --from=backend /usr/local/bin/celery /usr/local/bin/celery
|
COPY --from=backend /usr/local/bin/celery /usr/local/bin/celery
|
||||||
COPY --from=backend /app/src/ /app/src/
|
COPY --from=backend /app/src/ /app/src/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
FROM node:16-bullseye
|
FROM node:lts-bookworm
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN mkdir /app/src
|
RUN mkdir /app/src
|
||||||
|
|
||||||
COPY package*.json webpack.*.js .babelrc /app/
|
COPY package*.json webpack.*.js .babelrc /app/
|
||||||
|
|
||||||
RUN npm install
|
RUN npm ci --include=dev
|
||||||
|
|
||||||
COPY ./src /app/src
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
static:
|
static:
|
||||||
stage: build
|
stage: build
|
||||||
image: node:16-bullseye
|
image: node:lts-bookworm
|
||||||
before_script:
|
before_script:
|
||||||
- npm install
|
- npm install
|
||||||
script:
|
script:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
python-linting:
|
python-linting:
|
||||||
stage: lint
|
stage: lint
|
||||||
image: python:3.9-bullseye
|
image: python:3.11-bookworm
|
||||||
before_script:
|
before_script:
|
||||||
- pip install -r requirements/ci.txt
|
- pip install -r requirements/ci.txt
|
||||||
script:
|
script:
|
||||||
|
|
@ -14,7 +14,7 @@ python-linting:
|
||||||
|
|
||||||
javascript-linting:
|
javascript-linting:
|
||||||
stage: lint
|
stage: lint
|
||||||
image: node:16-bullseye
|
image: node:lts-bookworm
|
||||||
before_script:
|
before_script:
|
||||||
- npm install
|
- npm install
|
||||||
script:
|
script:
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ python-tests:
|
||||||
services:
|
services:
|
||||||
- postgres:15
|
- postgres:15
|
||||||
- memcached:1.5.22
|
- memcached:1.5.22
|
||||||
image: python:3.9-bullseye
|
image: python:3.11-bookworm
|
||||||
before_script:
|
before_script:
|
||||||
- pip install -r requirements/ci.txt
|
- pip install -r requirements/ci.txt
|
||||||
script:
|
script:
|
||||||
|
|
@ -12,7 +12,7 @@ python-tests:
|
||||||
|
|
||||||
javascript-tests:
|
javascript-tests:
|
||||||
stage: test
|
stage: test
|
||||||
image: node:16-bullseye
|
image: node:lts-bookworm
|
||||||
before_script:
|
before_script:
|
||||||
- npm install
|
- npm install
|
||||||
script:
|
script:
|
||||||
|
|
|
||||||
28042
package-lock.json
generated
28042
package-lock.json
generated
File diff suppressed because it is too large
Load diff
60
package.json
60
package.json
|
|
@ -1,20 +1,20 @@
|
||||||
{
|
{
|
||||||
"name": "newsreader",
|
"name": "newsreader",
|
||||||
"version": "0.4.2",
|
"version": "0.5.0",
|
||||||
"description": "Application for viewing RSS feeds",
|
"description": "Application for viewing RSS feeds",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "npx prettier \"src/newsreader/js/**/*.js\" --check",
|
"lint": "prettier \"src/newsreader/js/**/*.js\" --check",
|
||||||
"format": "npx prettier \"src/newsreader/js/**/*.js\" --write",
|
"format": "prettier \"src/newsreader/js/**/*.js\" --write",
|
||||||
"build": "npx webpack --config webpack.dev.babel.js",
|
"build": "webpack --config webpack.dev.babel.js",
|
||||||
"build:watch": "npx webpack --config webpack.dev.babel.js --watch",
|
"build:watch": "webpack --config webpack.dev.babel.js --watch",
|
||||||
"build:prod": "npx webpack --config webpack.prod.babel.js",
|
"build:prod": "webpack --config webpack.prod.babel.js",
|
||||||
"test": "npx jest",
|
"test": "jest",
|
||||||
"test:watch": "npm test -- --watch"
|
"test:watch": "npm test -- --watch"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "[git@git.fudiggity.nl:5000]:sonny/newsreader.git"
|
"url": "git@git.fudiggity.nl:sonny/newsreader.git"
|
||||||
},
|
},
|
||||||
"author": "Sonny",
|
"author": "Sonny",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
|
|
@ -29,35 +29,33 @@
|
||||||
"redux-thunk": "^2.3.0"
|
"redux-thunk": "^2.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.12.13",
|
"@babel/core": "^7.22.9",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.12.13",
|
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||||
"@babel/plugin-proposal-function-bind": "^7.12.13",
|
"@babel/plugin-proposal-function-bind": "^7.22.5",
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
"@babel/plugin-syntax-function-bind": "^7.22.5",
|
||||||
"@babel/plugin-syntax-function-bind": "^7.12.13",
|
"@babel/plugin-transform-runtime": "^7.22.9",
|
||||||
"@babel/plugin-transform-react-jsx": "^7.12.13",
|
"@babel/preset-env": "^7.22.9",
|
||||||
"@babel/plugin-transform-runtime": "^7.12.15",
|
"@babel/preset-react": "^7.22.5",
|
||||||
"@babel/preset-env": "^7.12.13",
|
"@babel/register": "^7.22.5",
|
||||||
"@babel/register": "^7.12.13",
|
"@babel/runtime": "^7.22.6",
|
||||||
"@babel/runtime": "^7.12.13",
|
"babel-jest": "^29.6.2",
|
||||||
"babel-jest": "^24.9.0",
|
"babel-loader": "^9.1.3",
|
||||||
"babel-loader": "^8.2.2",
|
"copy-webpack-plugin": "^11.0.0",
|
||||||
"clean-webpack-plugin": "^3.0.0",
|
"css-loader": "^6.8.1",
|
||||||
"css-loader": "^3.6.0",
|
|
||||||
"fetch-mock": "^8.3.2",
|
"fetch-mock": "^8.3.2",
|
||||||
"file-loader": "^6.2.0",
|
"jest": "^29.6.2",
|
||||||
"jest": "^24.9.0",
|
"mini-css-extract-plugin": "^2.7.6",
|
||||||
"mini-css-extract-plugin": "^0.9.0",
|
|
||||||
"node-fetch": "^2.6.1",
|
"node-fetch": "^2.6.1",
|
||||||
"prettier": "^1.19.1",
|
"prettier": "^1.19.1",
|
||||||
"react": "^16.14.0",
|
"react": "^16.14.0",
|
||||||
"react-dom": "^16.14.0",
|
"react-dom": "^16.14.0",
|
||||||
"redux-mock-store": "^1.5.4",
|
"redux-mock-store": "^1.5.4",
|
||||||
"sass": "^1.52.1",
|
"sass": "^1.64.2",
|
||||||
"sass-loader": "^8.0.2",
|
"sass-loader": "^13.3.2",
|
||||||
"style-loader": "^1.3.0",
|
"style-loader": "^3.3.3",
|
||||||
"url-loader": "^4.1.1",
|
"url-loader": "^4.1.1",
|
||||||
"webpack": "^4.46.0",
|
"webpack": "5.88.x",
|
||||||
"webpack-cli": "^3.3.12",
|
"webpack-cli": "^5.1.4",
|
||||||
"webpack-merge": "^4.2.2"
|
"webpack-merge": "^5.9.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,31 @@
|
||||||
[project]
|
[project]
|
||||||
name = 'newsreader'
|
name = 'newsreader'
|
||||||
version = '0.4.2'
|
version = '0.5.0'
|
||||||
authors = [{name = 'Sonny', email= 'sonnyba871@gmail.com'}]
|
authors = [{name = 'Sonny', email= 'sonnyba871@gmail.com'}]
|
||||||
license = {text = 'GPL-3.0'}
|
license = {text = 'GPL-3.0'}
|
||||||
requires-python = '>=3.11'
|
requires-python = '>=3.11'
|
||||||
dependencies = [
|
dependencies = [
|
||||||
'django~=3.2',
|
'django~=4.2.0',
|
||||||
'celery~=5.0',
|
'celery~=5.0',
|
||||||
'psycopg2',
|
'psycopg~=3.1.10',
|
||||||
|
|
||||||
'django-axes',
|
'django-axes~=6.0.4',
|
||||||
'django-celery-beat~=2.5.0',
|
'django-celery-beat~=2.5.0',
|
||||||
'django-registration-redux~=2.7',
|
'django-registration-redux~=2.12.0',
|
||||||
'django-rest-framework',
|
'djangorestframework~=3.14.0',
|
||||||
'drf-yasg',
|
|
||||||
|
|
||||||
'python-memcached',
|
'pymemcache~=4.0.0',
|
||||||
'python-dotenv~=0.12',
|
'python-dotenv~=1.0.0',
|
||||||
|
|
||||||
'ftfy~=5.8',
|
'ftfy~=6.1.1',
|
||||||
|
|
||||||
'requests',
|
'requests~=2.31.0',
|
||||||
'requests_oauthlib',
|
'requests_oauthlib~=1.3.1',
|
||||||
|
|
||||||
'feedparser',
|
'feedparser~=6.0.10',
|
||||||
'bleach',
|
'bleach~=6.0.0',
|
||||||
'beautifulsoup4',
|
'beautifulsoup4~=4.12.2',
|
||||||
'lxml'
|
'lxml~=4.9.2'
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
|
|
@ -47,4 +46,4 @@ development = [
|
||||||
|
|
||||||
ci = ['coverage>=5.3.1']
|
ci = ['coverage>=5.3.1']
|
||||||
|
|
||||||
production = ['gunicorn~=20.0', 'sentry-sdk~=1.0']
|
production = ['gunicorn~=21.2.0', 'sentry-sdk~=1.26.0']
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,12 @@ click-repl==0.3.0
|
||||||
# via celery
|
# via celery
|
||||||
cron-descriptor==1.4.0
|
cron-descriptor==1.4.0
|
||||||
# via django-celery-beat
|
# via django-celery-beat
|
||||||
django==3.2.19
|
django==4.2.4
|
||||||
# via
|
# via
|
||||||
# django-axes
|
# django-axes
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
# django-timezone-field
|
# django-timezone-field
|
||||||
# djangorestframework
|
# djangorestframework
|
||||||
# drf-yasg
|
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
django-axes==6.0.4
|
django-axes==6.0.4
|
||||||
# via newsreader (pyproject.toml)
|
# via newsreader (pyproject.toml)
|
||||||
|
|
@ -50,35 +49,27 @@ django-celery-beat==2.5.0
|
||||||
# via newsreader (pyproject.toml)
|
# via newsreader (pyproject.toml)
|
||||||
django-registration-redux==2.12
|
django-registration-redux==2.12
|
||||||
# via newsreader (pyproject.toml)
|
# via newsreader (pyproject.toml)
|
||||||
django-rest-framework==0.1.0
|
|
||||||
# via newsreader (pyproject.toml)
|
|
||||||
django-timezone-field==5.1
|
django-timezone-field==5.1
|
||||||
# via django-celery-beat
|
# via django-celery-beat
|
||||||
djangorestframework==3.14.0
|
djangorestframework==3.14.0
|
||||||
# via
|
|
||||||
# django-rest-framework
|
|
||||||
# drf-yasg
|
|
||||||
drf-yasg==1.21.6
|
|
||||||
# via newsreader (pyproject.toml)
|
# via newsreader (pyproject.toml)
|
||||||
feedparser==6.0.10
|
feedparser==6.0.10
|
||||||
# via newsreader (pyproject.toml)
|
# via newsreader (pyproject.toml)
|
||||||
ftfy==5.9
|
ftfy==6.1.1
|
||||||
# via newsreader (pyproject.toml)
|
# via newsreader (pyproject.toml)
|
||||||
idna==3.4
|
idna==3.4
|
||||||
# via requests
|
# via requests
|
||||||
inflection==0.5.1
|
|
||||||
# via drf-yasg
|
|
||||||
kombu==5.3.1
|
kombu==5.3.1
|
||||||
# via celery
|
# via celery
|
||||||
lxml==4.9.2
|
lxml==4.9.2
|
||||||
# via newsreader (pyproject.toml)
|
# via newsreader (pyproject.toml)
|
||||||
oauthlib==3.2.2
|
oauthlib==3.2.2
|
||||||
# via requests-oauthlib
|
# via requests-oauthlib
|
||||||
packaging==23.1
|
|
||||||
# via drf-yasg
|
|
||||||
prompt-toolkit==3.0.38
|
prompt-toolkit==3.0.38
|
||||||
# via click-repl
|
# via click-repl
|
||||||
psycopg2==2.9.6
|
psycopg==3.1.10
|
||||||
|
# via newsreader (pyproject.toml)
|
||||||
|
pymemcache==4.0.0
|
||||||
# via newsreader (pyproject.toml)
|
# via newsreader (pyproject.toml)
|
||||||
python-crontab==2.7.1
|
python-crontab==2.7.1
|
||||||
# via django-celery-beat
|
# via django-celery-beat
|
||||||
|
|
@ -86,18 +77,12 @@ python-dateutil==2.8.2
|
||||||
# via
|
# via
|
||||||
# celery
|
# celery
|
||||||
# python-crontab
|
# python-crontab
|
||||||
python-dotenv==0.21.1
|
python-dotenv==1.0.0
|
||||||
# via newsreader (pyproject.toml)
|
|
||||||
python-memcached==1.59
|
|
||||||
# via newsreader (pyproject.toml)
|
# via newsreader (pyproject.toml)
|
||||||
pytz==2023.3
|
pytz==2023.3
|
||||||
# via
|
# via
|
||||||
# django
|
|
||||||
# django-timezone-field
|
# django-timezone-field
|
||||||
# djangorestframework
|
# djangorestframework
|
||||||
# drf-yasg
|
|
||||||
pyyaml==6.0
|
|
||||||
# via drf-yasg
|
|
||||||
requests==2.31.0
|
requests==2.31.0
|
||||||
# via
|
# via
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
|
|
@ -110,7 +95,6 @@ six==1.16.0
|
||||||
# via
|
# via
|
||||||
# bleach
|
# bleach
|
||||||
# python-dateutil
|
# python-dateutil
|
||||||
# python-memcached
|
|
||||||
soupsieve==2.4.1
|
soupsieve==2.4.1
|
||||||
# via beautifulsoup4
|
# via beautifulsoup4
|
||||||
sqlparse==0.4.4
|
sqlparse==0.4.4
|
||||||
|
|
@ -119,12 +103,11 @@ typing-extensions==4.6.3
|
||||||
# via
|
# via
|
||||||
# asgiref
|
# asgiref
|
||||||
# kombu
|
# kombu
|
||||||
|
# psycopg
|
||||||
tzdata==2023.3
|
tzdata==2023.3
|
||||||
# via
|
# via
|
||||||
# celery
|
# celery
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
uritemplate==4.1.1
|
|
||||||
# via drf-yasg
|
|
||||||
urllib3==2.0.3
|
urllib3==2.0.3
|
||||||
# via requests
|
# via requests
|
||||||
vine==5.0.0
|
vine==5.0.0
|
||||||
|
|
|
||||||
|
|
@ -81,14 +81,13 @@ cron-descriptor==1.4.0
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
django==3.2.19
|
django==4.2.4
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# django-axes
|
# django-axes
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
# django-timezone-field
|
# django-timezone-field
|
||||||
# djangorestframework
|
# djangorestframework
|
||||||
# drf-yasg
|
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
django-axes==6.0.4
|
django-axes==6.0.4
|
||||||
# via
|
# via
|
||||||
|
|
@ -102,22 +101,12 @@ django-registration-redux==2.12
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
django-rest-framework==0.1.0
|
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# newsreader (pyproject.toml)
|
|
||||||
django-timezone-field==5.1
|
django-timezone-field==5.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
djangorestframework==3.14.0
|
djangorestframework==3.14.0
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# -r requirements/testing.txt
|
|
||||||
# django-rest-framework
|
|
||||||
# drf-yasg
|
|
||||||
drf-yasg==1.21.6
|
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
|
|
@ -137,7 +126,7 @@ freezegun==1.2.2
|
||||||
# via
|
# via
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
ftfy==5.9
|
ftfy==6.1.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
|
|
@ -146,11 +135,6 @@ idna==3.4
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# requests
|
# requests
|
||||||
inflection==0.5.1
|
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# -r requirements/testing.txt
|
|
||||||
# drf-yasg
|
|
||||||
isort==5.12.0
|
isort==5.12.0
|
||||||
# via
|
# via
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
|
|
@ -175,10 +159,8 @@ oauthlib==3.2.2
|
||||||
# requests-oauthlib
|
# requests-oauthlib
|
||||||
packaging==23.1
|
packaging==23.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# black
|
# black
|
||||||
# drf-yasg
|
|
||||||
pathspec==0.11.1
|
pathspec==0.11.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
|
|
@ -192,7 +174,7 @@ prompt-toolkit==3.0.38
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# click-repl
|
# click-repl
|
||||||
psycopg2==2.9.6
|
psycopg==3.1.10
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
|
|
@ -200,6 +182,10 @@ pyflakes==3.0.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# autoflake
|
# autoflake
|
||||||
|
pymemcache==4.0.0
|
||||||
|
# via
|
||||||
|
# -r requirements/base.txt
|
||||||
|
# newsreader (pyproject.toml)
|
||||||
python-crontab==2.7.1
|
python-crontab==2.7.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
|
@ -213,11 +199,7 @@ python-dateutil==2.8.2
|
||||||
# faker
|
# faker
|
||||||
# freezegun
|
# freezegun
|
||||||
# python-crontab
|
# python-crontab
|
||||||
python-dotenv==0.21.1
|
python-dotenv==1.0.0
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# newsreader (pyproject.toml)
|
|
||||||
python-memcached==1.59
|
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
|
|
@ -225,15 +207,8 @@ pytz==2023.3
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# django
|
|
||||||
# django-timezone-field
|
# django-timezone-field
|
||||||
# djangorestframework
|
# djangorestframework
|
||||||
# drf-yasg
|
|
||||||
pyyaml==6.0
|
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# -r requirements/testing.txt
|
|
||||||
# drf-yasg
|
|
||||||
requests==2.31.0
|
requests==2.31.0
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
|
@ -254,7 +229,6 @@ six==1.16.0
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# bleach
|
# bleach
|
||||||
# python-dateutil
|
# python-dateutil
|
||||||
# python-memcached
|
|
||||||
soupsieve==2.4.1
|
soupsieve==2.4.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
|
@ -281,17 +255,13 @@ typing-extensions==4.6.3
|
||||||
# asgiref
|
# asgiref
|
||||||
# black
|
# black
|
||||||
# kombu
|
# kombu
|
||||||
|
# psycopg
|
||||||
tzdata==2023.3
|
tzdata==2023.3
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# celery
|
# celery
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
uritemplate==4.1.1
|
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# -r requirements/testing.txt
|
|
||||||
# drf-yasg
|
|
||||||
urllib3==2.0.3
|
urllib3==2.0.3
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ cron-descriptor==1.4.0
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
django==3.2.19
|
django==4.2.4
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# django-axes
|
# django-axes
|
||||||
|
|
@ -91,7 +91,6 @@ django==3.2.19
|
||||||
# django-extensions
|
# django-extensions
|
||||||
# django-timezone-field
|
# django-timezone-field
|
||||||
# djangorestframework
|
# djangorestframework
|
||||||
# drf-yasg
|
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
django-axes==6.0.4
|
django-axes==6.0.4
|
||||||
# via
|
# via
|
||||||
|
|
@ -109,22 +108,12 @@ django-registration-redux==2.12
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
django-rest-framework==0.1.0
|
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# newsreader (pyproject.toml)
|
|
||||||
django-timezone-field==5.1
|
django-timezone-field==5.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
djangorestframework==3.14.0
|
djangorestframework==3.14.0
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# -r requirements/testing.txt
|
|
||||||
# django-rest-framework
|
|
||||||
# drf-yasg
|
|
||||||
drf-yasg==1.21.6
|
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
|
|
@ -144,7 +133,7 @@ freezegun==1.2.2
|
||||||
# via
|
# via
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
ftfy==5.9
|
ftfy==6.1.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
|
|
@ -153,11 +142,6 @@ idna==3.4
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# requests
|
# requests
|
||||||
inflection==0.5.1
|
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# -r requirements/testing.txt
|
|
||||||
# drf-yasg
|
|
||||||
isort==5.12.0
|
isort==5.12.0
|
||||||
# via
|
# via
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
|
|
@ -182,11 +166,9 @@ oauthlib==3.2.2
|
||||||
# requests-oauthlib
|
# requests-oauthlib
|
||||||
packaging==23.1
|
packaging==23.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# black
|
# black
|
||||||
# build
|
# build
|
||||||
# drf-yasg
|
|
||||||
pathspec==0.11.1
|
pathspec==0.11.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
|
|
@ -202,7 +184,7 @@ prompt-toolkit==3.0.38
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# click-repl
|
# click-repl
|
||||||
psycopg2==2.9.6
|
psycopg==3.1.10
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
|
|
@ -210,6 +192,10 @@ pyflakes==3.0.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# autoflake
|
# autoflake
|
||||||
|
pymemcache==4.0.0
|
||||||
|
# via
|
||||||
|
# -r requirements/base.txt
|
||||||
|
# newsreader (pyproject.toml)
|
||||||
pyproject-hooks==1.0.0
|
pyproject-hooks==1.0.0
|
||||||
# via build
|
# via build
|
||||||
python-crontab==2.7.1
|
python-crontab==2.7.1
|
||||||
|
|
@ -225,11 +211,7 @@ python-dateutil==2.8.2
|
||||||
# faker
|
# faker
|
||||||
# freezegun
|
# freezegun
|
||||||
# python-crontab
|
# python-crontab
|
||||||
python-dotenv==0.21.1
|
python-dotenv==1.0.0
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# newsreader (pyproject.toml)
|
|
||||||
python-memcached==1.59
|
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
|
|
@ -237,15 +219,8 @@ pytz==2023.3
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# django
|
|
||||||
# django-timezone-field
|
# django-timezone-field
|
||||||
# djangorestframework
|
# djangorestframework
|
||||||
# drf-yasg
|
|
||||||
pyyaml==6.0
|
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# -r requirements/testing.txt
|
|
||||||
# drf-yasg
|
|
||||||
requests==2.31.0
|
requests==2.31.0
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
|
@ -266,7 +241,6 @@ six==1.16.0
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# bleach
|
# bleach
|
||||||
# python-dateutil
|
# python-dateutil
|
||||||
# python-memcached
|
|
||||||
soupsieve==2.4.1
|
soupsieve==2.4.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
|
@ -296,17 +270,13 @@ typing-extensions==4.6.3
|
||||||
# asgiref
|
# asgiref
|
||||||
# black
|
# black
|
||||||
# kombu
|
# kombu
|
||||||
|
# psycopg
|
||||||
tzdata==2023.3
|
tzdata==2023.3
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# -r requirements/testing.txt
|
# -r requirements/testing.txt
|
||||||
# celery
|
# celery
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
uritemplate==4.1.1
|
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# -r requirements/testing.txt
|
|
||||||
# drf-yasg
|
|
||||||
urllib3==2.0.3
|
urllib3==2.0.3
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
|
|
||||||
|
|
@ -61,14 +61,13 @@ cron-descriptor==1.4.0
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
django==3.2.19
|
django==4.2.4
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# django-axes
|
# django-axes
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
# django-timezone-field
|
# django-timezone-field
|
||||||
# djangorestframework
|
# djangorestframework
|
||||||
# drf-yasg
|
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
django-axes==6.0.4
|
django-axes==6.0.4
|
||||||
# via
|
# via
|
||||||
|
|
@ -82,20 +81,11 @@ django-registration-redux==2.12
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
django-rest-framework==0.1.0
|
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# newsreader (pyproject.toml)
|
|
||||||
django-timezone-field==5.1
|
django-timezone-field==5.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
djangorestframework==3.14.0
|
djangorestframework==3.14.0
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# django-rest-framework
|
|
||||||
# drf-yasg
|
|
||||||
drf-yasg==1.21.6
|
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
|
|
@ -103,20 +93,16 @@ feedparser==6.0.10
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
ftfy==5.9
|
ftfy==6.1.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
gunicorn==20.1.0
|
gunicorn==21.2.0
|
||||||
# via newsreader (pyproject.toml)
|
# via newsreader (pyproject.toml)
|
||||||
idna==3.4
|
idna==3.4
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# requests
|
# requests
|
||||||
inflection==0.5.1
|
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# drf-yasg
|
|
||||||
kombu==5.3.1
|
kombu==5.3.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
|
@ -130,14 +116,16 @@ oauthlib==3.2.2
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# requests-oauthlib
|
# requests-oauthlib
|
||||||
packaging==23.1
|
packaging==23.1
|
||||||
# via
|
# via gunicorn
|
||||||
# -r requirements/base.txt
|
|
||||||
# drf-yasg
|
|
||||||
prompt-toolkit==3.0.38
|
prompt-toolkit==3.0.38
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# click-repl
|
# click-repl
|
||||||
psycopg2==2.9.6
|
psycopg==3.1.10
|
||||||
|
# via
|
||||||
|
# -r requirements/base.txt
|
||||||
|
# newsreader (pyproject.toml)
|
||||||
|
pymemcache==4.0.0
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
|
|
@ -150,25 +138,15 @@ python-dateutil==2.8.2
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# celery
|
# celery
|
||||||
# python-crontab
|
# python-crontab
|
||||||
python-dotenv==0.21.1
|
python-dotenv==1.0.0
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# newsreader (pyproject.toml)
|
|
||||||
python-memcached==1.59
|
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
pytz==2023.3
|
pytz==2023.3
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# django
|
|
||||||
# django-timezone-field
|
# django-timezone-field
|
||||||
# djangorestframework
|
# djangorestframework
|
||||||
# drf-yasg
|
|
||||||
pyyaml==6.0
|
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# drf-yasg
|
|
||||||
requests==2.31.0
|
requests==2.31.0
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
|
@ -189,7 +167,6 @@ six==1.16.0
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# bleach
|
# bleach
|
||||||
# python-dateutil
|
# python-dateutil
|
||||||
# python-memcached
|
|
||||||
soupsieve==2.4.1
|
soupsieve==2.4.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
|
@ -203,15 +180,12 @@ typing-extensions==4.6.3
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# asgiref
|
# asgiref
|
||||||
# kombu
|
# kombu
|
||||||
|
# psycopg
|
||||||
tzdata==2023.3
|
tzdata==2023.3
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# celery
|
# celery
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
uritemplate==4.1.1
|
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# drf-yasg
|
|
||||||
urllib3==2.0.3
|
urllib3==2.0.3
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
|
|
||||||
|
|
@ -65,14 +65,13 @@ cron-descriptor==1.4.0
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
django==3.2.19
|
django==4.2.4
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# django-axes
|
# django-axes
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
# django-timezone-field
|
# django-timezone-field
|
||||||
# djangorestframework
|
# djangorestframework
|
||||||
# drf-yasg
|
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
django-axes==6.0.4
|
django-axes==6.0.4
|
||||||
# via
|
# via
|
||||||
|
|
@ -86,20 +85,11 @@ django-registration-redux==2.12
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
django-rest-framework==0.1.0
|
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# newsreader (pyproject.toml)
|
|
||||||
django-timezone-field==5.1
|
django-timezone-field==5.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
djangorestframework==3.14.0
|
djangorestframework==3.14.0
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# django-rest-framework
|
|
||||||
# drf-yasg
|
|
||||||
drf-yasg==1.21.6
|
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
|
|
@ -113,7 +103,7 @@ feedparser==6.0.10
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
freezegun==1.2.2
|
freezegun==1.2.2
|
||||||
# via newsreader (pyproject.toml)
|
# via newsreader (pyproject.toml)
|
||||||
ftfy==5.9
|
ftfy==6.1.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
|
|
@ -121,10 +111,6 @@ idna==3.4
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# requests
|
# requests
|
||||||
inflection==0.5.1
|
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# drf-yasg
|
|
||||||
isort==5.12.0
|
isort==5.12.0
|
||||||
# via newsreader (pyproject.toml)
|
# via newsreader (pyproject.toml)
|
||||||
kombu==5.3.1
|
kombu==5.3.1
|
||||||
|
|
@ -142,10 +128,7 @@ oauthlib==3.2.2
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# requests-oauthlib
|
# requests-oauthlib
|
||||||
packaging==23.1
|
packaging==23.1
|
||||||
# via
|
# via black
|
||||||
# -r requirements/base.txt
|
|
||||||
# black
|
|
||||||
# drf-yasg
|
|
||||||
pathspec==0.11.1
|
pathspec==0.11.1
|
||||||
# via black
|
# via black
|
||||||
platformdirs==3.8.0
|
platformdirs==3.8.0
|
||||||
|
|
@ -154,12 +137,16 @@ prompt-toolkit==3.0.38
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# click-repl
|
# click-repl
|
||||||
psycopg2==2.9.6
|
psycopg==3.1.10
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
pyflakes==3.0.1
|
pyflakes==3.0.1
|
||||||
# via autoflake
|
# via autoflake
|
||||||
|
pymemcache==4.0.0
|
||||||
|
# via
|
||||||
|
# -r requirements/base.txt
|
||||||
|
# newsreader (pyproject.toml)
|
||||||
python-crontab==2.7.1
|
python-crontab==2.7.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
|
@ -171,25 +158,15 @@ python-dateutil==2.8.2
|
||||||
# faker
|
# faker
|
||||||
# freezegun
|
# freezegun
|
||||||
# python-crontab
|
# python-crontab
|
||||||
python-dotenv==0.21.1
|
python-dotenv==1.0.0
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# newsreader (pyproject.toml)
|
|
||||||
python-memcached==1.59
|
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# newsreader (pyproject.toml)
|
# newsreader (pyproject.toml)
|
||||||
pytz==2023.3
|
pytz==2023.3
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# django
|
|
||||||
# django-timezone-field
|
# django-timezone-field
|
||||||
# djangorestframework
|
# djangorestframework
|
||||||
# drf-yasg
|
|
||||||
pyyaml==6.0
|
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# drf-yasg
|
|
||||||
requests==2.31.0
|
requests==2.31.0
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
|
@ -208,7 +185,6 @@ six==1.16.0
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# bleach
|
# bleach
|
||||||
# python-dateutil
|
# python-dateutil
|
||||||
# python-memcached
|
|
||||||
soupsieve==2.4.1
|
soupsieve==2.4.1
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
|
@ -229,15 +205,12 @@ typing-extensions==4.6.3
|
||||||
# asgiref
|
# asgiref
|
||||||
# black
|
# black
|
||||||
# kombu
|
# kombu
|
||||||
|
# psycopg
|
||||||
tzdata==2023.3
|
tzdata==2023.3
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
# celery
|
# celery
|
||||||
# django-celery-beat
|
# django-celery-beat
|
||||||
uritemplate==4.1.1
|
|
||||||
# via
|
|
||||||
# -r requirements/base.txt
|
|
||||||
# drf-yasg
|
|
||||||
urllib3==2.0.3
|
urllib3==2.0.3
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ from django import forms
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin
|
from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin
|
||||||
from django.contrib.auth.forms import UserChangeForm
|
from django.contrib.auth.forms import UserChangeForm
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from newsreader.accounts.models import User
|
from newsreader.accounts.models import User
|
||||||
|
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
|
@ -19,7 +19,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent.parent.parent
|
||||||
DJANGO_PROJECT_DIR = os.path.join(BASE_DIR, "src", "newsreader")
|
DJANGO_PROJECT_DIR = os.path.join(BASE_DIR, "src", "newsreader")
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
|
||||||
# SECURITY WARNING: don"t run with debug turned on in production!
|
# SECURITY WARNING: don"t run with debug turned on in production!
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
|
|
||||||
|
|
@ -37,7 +37,6 @@ INSTALLED_APPS = [
|
||||||
"django.forms",
|
"django.forms",
|
||||||
# third party apps
|
# third party apps
|
||||||
"rest_framework",
|
"rest_framework",
|
||||||
"drf_yasg",
|
|
||||||
"celery",
|
"celery",
|
||||||
"django_celery_beat",
|
"django_celery_beat",
|
||||||
"registration",
|
"registration",
|
||||||
|
|
@ -91,7 +90,7 @@ TEMPLATES = [
|
||||||
WSGI_APPLICATION = "newsreader.wsgi.application"
|
WSGI_APPLICATION = "newsreader.wsgi.application"
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
"default": {
|
"default": {
|
||||||
"ENGINE": "django.db.backends.postgresql",
|
"ENGINE": "django.db.backends.postgresql",
|
||||||
|
|
@ -107,17 +106,17 @@ DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
|
||||||
|
|
||||||
CACHES = {
|
CACHES = {
|
||||||
"default": {
|
"default": {
|
||||||
"BACKEND": "django.core.cache.backends.memcached.MemcachedCache",
|
"BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache",
|
||||||
"LOCATION": "memcached:11211",
|
"LOCATION": "memcached:11211",
|
||||||
},
|
},
|
||||||
"axes": {
|
"axes": {
|
||||||
"BACKEND": "django.core.cache.backends.memcached.MemcachedCache",
|
"BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache",
|
||||||
"LOCATION": "memcached:11211",
|
"LOCATION": "memcached:11211",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
# https://docs.djangoproject.com/en/2.2/topics/logging/#configuring-logging
|
# https://docs.djangoproject.com/en/4.2/topics/logging/#configuring-logging
|
||||||
LOGGING = {
|
LOGGING = {
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"disable_existing_loggers": False,
|
"disable_existing_loggers": False,
|
||||||
|
|
@ -172,7 +171,7 @@ LOGGING = {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Password validation
|
# Password validation
|
||||||
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
{
|
{
|
||||||
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"
|
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"
|
||||||
|
|
@ -188,7 +187,7 @@ AUTH_USER_MODEL = "accounts.User"
|
||||||
LOGIN_REDIRECT_URL = "/"
|
LOGIN_REDIRECT_URL = "/"
|
||||||
|
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/2.2/topics/i18n/
|
# https://docs.djangoproject.com/en/4.2/topics/i18n/
|
||||||
LANGUAGE_CODE = "en-us"
|
LANGUAGE_CODE = "en-us"
|
||||||
|
|
||||||
TIME_ZONE = "Europe/Amsterdam"
|
TIME_ZONE = "Europe/Amsterdam"
|
||||||
|
|
@ -197,12 +196,12 @@ USE_L10N = True
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/2.2/howto/static-files/
|
# https://docs.djangoproject.com/en/4.2/howto/static-files/
|
||||||
STATIC_URL = "/static/"
|
STATIC_URL = "/static/"
|
||||||
STATIC_ROOT = os.path.join(BASE_DIR, "static")
|
STATIC_ROOT = os.path.join(BASE_DIR, "static")
|
||||||
STATICFILES_DIRS = [os.path.join(DJANGO_PROJECT_DIR, "static")]
|
STATICFILES_DIRS = [os.path.join(DJANGO_PROJECT_DIR, "static")]
|
||||||
|
|
||||||
# https://docs.djangoproject.com/en/2.2/ref/settings/#std:setting-STATICFILES_FINDERS
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#std:setting-STATICFILES_FINDERS
|
||||||
STATICFILES_FINDERS = [
|
STATICFILES_FINDERS = [
|
||||||
"django.contrib.staticfiles.finders.FileSystemFinder",
|
"django.contrib.staticfiles.finders.FileSystemFinder",
|
||||||
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
|
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
|
||||||
|
|
|
||||||
|
|
@ -17,17 +17,6 @@ EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
|
||||||
|
|
||||||
AXES_ENABLED = False
|
AXES_ENABLED = False
|
||||||
|
|
||||||
CACHES = {
|
|
||||||
"default": {
|
|
||||||
"BACKEND": "django.core.cache.backends.memcached.MemcachedCache",
|
|
||||||
"LOCATION": "memcached:11211",
|
|
||||||
},
|
|
||||||
"axes": {
|
|
||||||
"BACKEND": "django.core.cache.backends.memcached.MemcachedCache",
|
|
||||||
"LOCATION": "memcached:11211",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
# Project settings
|
# Project settings
|
||||||
VERSION = get_current_version()
|
VERSION = get_current_version()
|
||||||
ENVIRONMENT = "gitlab"
|
ENVIRONMENT = "gitlab"
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
||||||
|
|
||||||
ALLOWED_HOSTS = ["127.0.0.1", "localhost", "rss.fudiggity.nl", "django"]
|
ALLOWED_HOSTS = ["127.0.0.1", "localhost", "rss.fudiggity.nl", "django"]
|
||||||
|
|
||||||
|
CSRF_TRUSTED_ORIGINS = ["https://rss.fudiggity.nl"]
|
||||||
|
|
||||||
ADMINS = [
|
ADMINS = [
|
||||||
("", email)
|
("", email)
|
||||||
for email in os.getenv("ADMINS", "").split(",")
|
for email in os.getenv("ADMINS", "").split(",")
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,11 @@ import logging
|
||||||
|
|
||||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
|
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from feedparser import parse
|
from feedparser import parse
|
||||||
|
|
||||||
from newsreader.news.collection.base import (
|
from newsreader.news.collection.base import (
|
||||||
|
|
@ -58,7 +57,7 @@ class FeedBuilder(PostBuilder):
|
||||||
"published_parsed": "publication_date",
|
"published_parsed": "publication_date",
|
||||||
"author": "author",
|
"author": "author",
|
||||||
}
|
}
|
||||||
tz = pytz.timezone(self.stream.rule.timezone)
|
tz = ZoneInfo(self.stream.rule.timezone)
|
||||||
data = {"rule_id": self.stream.rule.pk}
|
data = {"rule_id": self.stream.rule.pk}
|
||||||
|
|
||||||
for field, model_field in field_mapping.items():
|
for field, model_field in field_mapping.items():
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,30 @@
|
||||||
|
from datetime import timezone as python_timezone
|
||||||
|
from zoneinfo import available_timezones
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from newsreader.core.forms import CheckboxInput
|
from newsreader.core.forms import CheckboxInput
|
||||||
from newsreader.news.collection.forms.base import CollectionRuleForm
|
from newsreader.news.collection.forms.base import CollectionRuleForm
|
||||||
from newsreader.news.collection.models import CollectionRule
|
from newsreader.news.collection.models import CollectionRule
|
||||||
|
|
||||||
|
|
||||||
|
def get_timezones():
|
||||||
|
return [
|
||||||
|
(
|
||||||
|
_timezone,
|
||||||
|
_timezone,
|
||||||
|
)
|
||||||
|
for _timezone in available_timezones()
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class FeedForm(CollectionRuleForm):
|
class FeedForm(CollectionRuleForm):
|
||||||
timezone = forms.ChoiceField(
|
timezone = forms.ChoiceField(
|
||||||
widget=forms.Select(attrs={"size": len(pytz.all_timezones)}),
|
widget=forms.Select(attrs={"size": len(get_timezones())}),
|
||||||
choices=((timezone, timezone) for timezone in pytz.all_timezones),
|
choices=get_timezones(),
|
||||||
help_text=_("The timezone which the feed uses"),
|
help_text=_("The timezone which the feed uses"),
|
||||||
initial=pytz.utc,
|
initial=python_timezone.utc,
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
|
from datetime import timezone
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from newsreader.news.collection.choices import RuleTypeChoices
|
from newsreader.news.collection.choices import RuleTypeChoices
|
||||||
from newsreader.news.collection.forms.base import CollectionRuleForm
|
from newsreader.news.collection.forms.base import CollectionRuleForm
|
||||||
from newsreader.news.collection.models import CollectionRule
|
from newsreader.news.collection.models import CollectionRule
|
||||||
|
|
@ -36,7 +36,7 @@ class SubRedditForm(CollectionRuleForm):
|
||||||
instance = super().save(commit=False)
|
instance = super().save(commit=False)
|
||||||
|
|
||||||
instance.type = RuleTypeChoices.subreddit
|
instance.type = RuleTypeChoices.subreddit
|
||||||
instance.timezone = str(pytz.utc)
|
instance.timezone = str(timezone.utc)
|
||||||
|
|
||||||
if commit:
|
if commit:
|
||||||
instance.save()
|
instance.save()
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
|
from datetime import timezone
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from newsreader.news.collection.choices import RuleTypeChoices
|
from newsreader.news.collection.choices import RuleTypeChoices
|
||||||
from newsreader.news.collection.forms.base import CollectionRuleForm
|
from newsreader.news.collection.forms.base import CollectionRuleForm
|
||||||
from newsreader.news.collection.models import CollectionRule
|
from newsreader.news.collection.models import CollectionRule
|
||||||
|
|
@ -21,7 +21,7 @@ class TwitterTimelineForm(CollectionRuleForm):
|
||||||
instance = super().save(commit=False)
|
instance = super().save(commit=False)
|
||||||
|
|
||||||
instance.type = RuleTypeChoices.twitter_timeline
|
instance.type = RuleTypeChoices.twitter_timeline
|
||||||
instance.timezone = str(pytz.utc)
|
instance.timezone = str(timezone.utc)
|
||||||
instance.url = f"{TWITTER_API_URL}/statuses/user_timeline.json?screen_name={instance.screen_name}&tweet_mode=extended"
|
instance.url = f"{TWITTER_API_URL}/statuses/user_timeline.json?screen_name={instance.screen_name}&tweet_mode=extended"
|
||||||
|
|
||||||
if commit:
|
if commit:
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,24 @@
|
||||||
|
from datetime import timezone
|
||||||
|
from zoneinfo import available_timezones
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from newsreader.core.models import TimeStampedModel
|
from newsreader.core.models import TimeStampedModel
|
||||||
from newsreader.news.collection.choices import RuleTypeChoices
|
from newsreader.news.collection.choices import RuleTypeChoices
|
||||||
|
|
||||||
|
|
||||||
|
def get_timezones():
|
||||||
|
return [
|
||||||
|
(
|
||||||
|
_timezone,
|
||||||
|
_timezone,
|
||||||
|
)
|
||||||
|
for _timezone in available_timezones()
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class CollectionRuleQuerySet(models.QuerySet):
|
class CollectionRuleQuerySet(models.QuerySet):
|
||||||
def enabled(self):
|
def enabled(self):
|
||||||
return self.filter(enabled=True)
|
return self.filter(enabled=True)
|
||||||
|
|
@ -26,9 +37,9 @@ class CollectionRule(TimeStampedModel):
|
||||||
favicon = models.URLField(blank=True, null=True)
|
favicon = models.URLField(blank=True, null=True)
|
||||||
|
|
||||||
timezone = models.CharField(
|
timezone = models.CharField(
|
||||||
choices=((timezone, timezone) for timezone in pytz.all_timezones),
|
choices=get_timezones(),
|
||||||
max_length=100,
|
max_length=100,
|
||||||
default=str(pytz.utc),
|
default=str(timezone.utc),
|
||||||
)
|
)
|
||||||
|
|
||||||
category = models.ForeignKey(
|
category = models.ForeignKey(
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import logging
|
||||||
|
|
||||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
from datetime import timezone as _timezone
|
||||||
from html import unescape
|
from html import unescape
|
||||||
from json.decoder import JSONDecodeError
|
from json.decoder import JSONDecodeError
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
|
|
@ -12,7 +13,6 @@ from django.core.cache import cache
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.html import format_html
|
from django.utils.html import format_html
|
||||||
|
|
||||||
import pytz
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from newsreader.news.collection.base import (
|
from newsreader.news.collection.base import (
|
||||||
|
|
@ -215,7 +215,8 @@ class RedditBuilder(PostBuilder):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
parsed_date = datetime.fromtimestamp(entry_data["created_utc"])
|
parsed_date = datetime.fromtimestamp(entry_data["created_utc"])
|
||||||
created_date = pytz.utc.localize(parsed_date)
|
|
||||||
|
created_date = parsed_date.replace(tzinfo=_timezone.utc)
|
||||||
except (OverflowError, OSError) as e:
|
except (OverflowError, OSError) as e:
|
||||||
raise BuilderParseException(payload=entry) from e
|
raise BuilderParseException(payload=entry) from e
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.core.mail import send_mail
|
from django.core.mail import send_mail
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from datetime import date, datetime, time
|
from datetime import date, datetime, time, timezone
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from newsreader.accounts.tests.factories import UserFactory
|
from newsreader.accounts.tests.factories import UserFactory
|
||||||
from newsreader.news.collection.tests.factories import FeedFactory
|
from newsreader.news.collection.tests.factories import FeedFactory
|
||||||
from newsreader.news.core.tests.factories import CategoryFactory, FeedPostFactory
|
from newsreader.news.core.tests.factories import CategoryFactory, FeedPostFactory
|
||||||
|
|
@ -154,21 +152,21 @@ class NestedRuleListViewTestCase(TestCase):
|
||||||
title="I'm the first post",
|
title="I'm the first post",
|
||||||
rule=rule,
|
rule=rule,
|
||||||
publication_date=datetime.combine(
|
publication_date=datetime.combine(
|
||||||
date(2019, 5, 20), time(hour=16, minute=7, second=37), pytz.utc
|
date(2019, 5, 20), time(hour=16, minute=7, second=37), timezone.utc
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
FeedPostFactory(
|
FeedPostFactory(
|
||||||
title="I'm the second post",
|
title="I'm the second post",
|
||||||
rule=rule,
|
rule=rule,
|
||||||
publication_date=datetime.combine(
|
publication_date=datetime.combine(
|
||||||
date(2019, 7, 20), time(hour=18, minute=7, second=37), pytz.utc
|
date(2019, 7, 20), time(hour=18, minute=7, second=37), timezone.utc
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
FeedPostFactory(
|
FeedPostFactory(
|
||||||
title="I'm the third post",
|
title="I'm the third post",
|
||||||
rule=rule,
|
rule=rule,
|
||||||
publication_date=datetime.combine(
|
publication_date=datetime.combine(
|
||||||
date(2019, 7, 20), time(hour=16, minute=7, second=37), pytz.utc
|
date(2019, 7, 20), time(hour=16, minute=7, second=37), timezone.utc
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from datetime import timezone as _timezone
|
||||||
from unittest.mock import Mock
|
from unittest.mock import Mock
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from freezegun import freeze_time
|
from freezegun import freeze_time
|
||||||
|
|
||||||
from newsreader.news.collection.feed import FeedBuilder
|
from newsreader.news.collection.feed import FeedBuilder
|
||||||
|
|
@ -35,7 +34,7 @@ class FeedBuilderTestCase(TestCase):
|
||||||
post = posts[0]
|
post = posts[0]
|
||||||
|
|
||||||
publication_date = datetime(
|
publication_date = datetime(
|
||||||
2019, 5, 20, hour=16, minute=32, second=38, tzinfo=pytz.utc
|
2019, 5, 20, hour=16, minute=32, second=38, tzinfo=_timezone.utc
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
|
@ -59,7 +58,7 @@ class FeedBuilderTestCase(TestCase):
|
||||||
post = posts[1]
|
post = posts[1]
|
||||||
|
|
||||||
publication_date = datetime(
|
publication_date = datetime(
|
||||||
2019, 5, 20, hour=16, minute=7, second=37, tzinfo=pytz.utc
|
2019, 5, 20, hour=16, minute=7, second=37, tzinfo=_timezone.utc
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
|
@ -94,7 +93,7 @@ class FeedBuilderTestCase(TestCase):
|
||||||
post = posts[0]
|
post = posts[0]
|
||||||
|
|
||||||
publication_date = datetime(
|
publication_date = datetime(
|
||||||
2019, 5, 20, hour=16, minute=7, second=37, tzinfo=pytz.utc
|
2019, 5, 20, hour=16, minute=7, second=37, tzinfo=_timezone.utc
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(post.publication_date, publication_date)
|
self.assertEqual(post.publication_date, publication_date)
|
||||||
|
|
@ -109,7 +108,7 @@ class FeedBuilderTestCase(TestCase):
|
||||||
post = posts[1]
|
post = posts[1]
|
||||||
|
|
||||||
publication_date = datetime(
|
publication_date = datetime(
|
||||||
2019, 5, 20, hour=12, minute=19, second=19, tzinfo=pytz.utc
|
2019, 5, 20, hour=12, minute=19, second=19, tzinfo=_timezone.utc
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(post.publication_date, publication_date)
|
self.assertEqual(post.publication_date, publication_date)
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
from datetime import date, datetime, time
|
from datetime import date, datetime, time
|
||||||
|
from datetime import timezone as _timezone
|
||||||
from time import struct_time
|
from time import struct_time
|
||||||
from unittest.mock import Mock, patch
|
from unittest.mock import Mock, patch
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from freezegun import freeze_time
|
from freezegun import freeze_time
|
||||||
|
|
||||||
from newsreader.news.collection.exceptions import (
|
from newsreader.news.collection.exceptions import (
|
||||||
|
|
@ -100,7 +99,7 @@ class FeedCollectorTestCase(TestCase):
|
||||||
def test_forbidden(self):
|
def test_forbidden(self):
|
||||||
self.mocked_fetch.side_effect = StreamForbiddenException
|
self.mocked_fetch.side_effect = StreamForbiddenException
|
||||||
|
|
||||||
old_run = pytz.utc.localize(datetime(2019, 10, 30, 12, 30))
|
old_run = datetime(2019, 10, 30, 12, 30, tzinfo=_timezone.utc)
|
||||||
rule = FeedFactory(last_run=old_run)
|
rule = FeedFactory(last_run=old_run)
|
||||||
|
|
||||||
collector = FeedCollector()
|
collector = FeedCollector()
|
||||||
|
|
@ -130,7 +129,7 @@ class FeedCollectorTestCase(TestCase):
|
||||||
self.assertEquals(rule.succeeded, False)
|
self.assertEquals(rule.succeeded, False)
|
||||||
self.assertEquals(rule.error, "Stream timed out")
|
self.assertEquals(rule.error, "Stream timed out")
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
rule.last_run, pytz.utc.localize(datetime(2019, 10, 30, 12, 30))
|
rule.last_run, datetime(2019, 10, 30, 12, 30, tzinfo=_timezone.utc)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_duplicates(self):
|
def test_duplicates(self):
|
||||||
|
|
@ -139,7 +138,7 @@ class FeedCollectorTestCase(TestCase):
|
||||||
rule = FeedFactory()
|
rule = FeedFactory()
|
||||||
|
|
||||||
aware_datetime = build_publication_date(
|
aware_datetime = build_publication_date(
|
||||||
struct_time((2019, 5, 20, 16, 7, 37, 0, 140, 0)), pytz.utc
|
struct_time((2019, 5, 20, 16, 7, 37, 0, 140, 0)), _timezone.utc
|
||||||
)
|
)
|
||||||
|
|
||||||
first_post = FeedPostFactory(
|
first_post = FeedPostFactory(
|
||||||
|
|
@ -152,7 +151,7 @@ class FeedCollectorTestCase(TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
aware_datetime = build_publication_date(
|
aware_datetime = build_publication_date(
|
||||||
struct_time((2019, 5, 20, 12, 19, 19, 0, 140, 0)), pytz.utc
|
struct_time((2019, 5, 20, 12, 19, 19, 0, 140, 0)), _timezone.utc
|
||||||
)
|
)
|
||||||
|
|
||||||
second_post = FeedPostFactory(
|
second_post = FeedPostFactory(
|
||||||
|
|
@ -165,7 +164,7 @@ class FeedCollectorTestCase(TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
aware_datetime = build_publication_date(
|
aware_datetime = build_publication_date(
|
||||||
struct_time((2019, 5, 20, 16, 32, 38, 0, 140, 0)), pytz.utc
|
struct_time((2019, 5, 20, 16, 32, 38, 0, 140, 0)), _timezone.utc
|
||||||
)
|
)
|
||||||
|
|
||||||
third_post = FeedPostFactory(
|
third_post = FeedPostFactory(
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
from datetime import datetime
|
from datetime import datetime, timezone
|
||||||
from unittest.mock import Mock
|
from unittest.mock import Mock
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from newsreader.news.collection.reddit import RedditBuilder
|
from newsreader.news.collection.reddit import RedditBuilder
|
||||||
from newsreader.news.collection.tests.factories import SubredditFactory
|
from newsreader.news.collection.tests.factories import SubredditFactory
|
||||||
from newsreader.news.collection.tests.reddit.builder.mocks import *
|
from newsreader.news.collection.tests.reddit.builder.mocks import *
|
||||||
|
|
@ -59,7 +57,7 @@ class RedditBuilderTestCase(TestCase):
|
||||||
"https://www.reddit.com/r/linux/comments/hm0qct/linux_experiencesrants_or_educationcertifications/",
|
"https://www.reddit.com/r/linux/comments/hm0qct/linux_experiencesrants_or_educationcertifications/",
|
||||||
)
|
)
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
post.publication_date, pytz.utc.localize(datetime(2020, 7, 6, 6, 11, 22))
|
post.publication_date, datetime(2020, 7, 6, 6, 11, 22, tzinfo=timezone.utc)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_empty_data(self):
|
def test_empty_data(self):
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from datetime import timezone as _timezone
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from newsreader.news.collection.choices import RuleTypeChoices
|
from newsreader.news.collection.choices import RuleTypeChoices
|
||||||
from newsreader.news.collection.exceptions import (
|
from newsreader.news.collection.exceptions import (
|
||||||
StreamDeniedException,
|
StreamDeniedException,
|
||||||
|
|
@ -82,7 +81,8 @@ class RedditCollectorTestCase(TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
post.publication_date, pytz.utc.localize(datetime(2020, 7, 11, 22, 23, 24))
|
post.publication_date,
|
||||||
|
datetime(2020, 7, 11, 22, 23, 24, tzinfo=_timezone.utc),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEquals(post.author, "HannahB888")
|
self.assertEquals(post.author, "HannahB888")
|
||||||
|
|
@ -99,7 +99,8 @@ class RedditCollectorTestCase(TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
post.publication_date, pytz.utc.localize(datetime(2020, 7, 12, 10, 29, 10))
|
post.publication_date,
|
||||||
|
datetime(2020, 7, 12, 10, 29, 10, tzinfo=_timezone.utc),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEquals(post.author, "Sebaron")
|
self.assertEquals(post.author, "Sebaron")
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
from datetime import datetime
|
from datetime import datetime, timezone
|
||||||
from unittest.mock import Mock
|
from unittest.mock import Mock
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from ftfy import fix_text
|
from ftfy import fix_text
|
||||||
|
|
||||||
from newsreader.news.collection.tests.factories import TwitterTimelineFactory
|
from newsreader.news.collection.tests.factories import TwitterTimelineFactory
|
||||||
|
|
@ -69,7 +67,7 @@ class TwitterBuilderTestCase(TestCase):
|
||||||
post.url, f"{TWITTER_URL}/RobertsSpaceInd/status/1291528756373286914"
|
post.url, f"{TWITTER_URL}/RobertsSpaceInd/status/1291528756373286914"
|
||||||
)
|
)
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
post.publication_date, pytz.utc.localize(datetime(2020, 8, 7, 0, 17, 5))
|
post.publication_date, datetime(2020, 8, 7, 0, 17, 5, tzinfo=timezone.utc)
|
||||||
)
|
)
|
||||||
|
|
||||||
post = posts["1288550304095416320"]
|
post = posts["1288550304095416320"]
|
||||||
|
|
@ -85,7 +83,7 @@ class TwitterBuilderTestCase(TestCase):
|
||||||
post.url, f"{TWITTER_URL}/RobertsSpaceInd/status/1288550304095416320"
|
post.url, f"{TWITTER_URL}/RobertsSpaceInd/status/1288550304095416320"
|
||||||
)
|
)
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
post.publication_date, pytz.utc.localize(datetime(2020, 7, 29, 19, 1, 47))
|
post.publication_date, datetime(2020, 7, 29, 19, 1, 47, tzinfo=timezone.utc)
|
||||||
)
|
)
|
||||||
|
|
||||||
# note that only one media type can be uploaded to an Tweet
|
# note that only one media type can be uploaded to an Tweet
|
||||||
|
|
@ -114,7 +112,7 @@ class TwitterBuilderTestCase(TestCase):
|
||||||
post.url, f"{TWITTER_URL}/RobertsSpaceInd/status/1269039237166321664"
|
post.url, f"{TWITTER_URL}/RobertsSpaceInd/status/1269039237166321664"
|
||||||
)
|
)
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
post.publication_date, pytz.utc.localize(datetime(2020, 6, 5, 22, 51, 46))
|
post.publication_date, datetime(2020, 6, 5, 22, 51, 46, tzinfo=timezone.utc)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
|
|
@ -179,7 +177,7 @@ class TwitterBuilderTestCase(TestCase):
|
||||||
post.url, f"{TWITTER_URL}/RobertsSpaceInd/status/1291080532361527296"
|
post.url, f"{TWITTER_URL}/RobertsSpaceInd/status/1291080532361527296"
|
||||||
)
|
)
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
post.publication_date, pytz.utc.localize(datetime(2020, 8, 5, 18, 36, 0))
|
post.publication_date, datetime(2020, 8, 5, 18, 36, 0, tzinfo=timezone.utc)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertIn(full_text, post.body)
|
self.assertIn(full_text, post.body)
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from datetime import timezone as _timezone
|
||||||
from unittest.mock import Mock, patch
|
from unittest.mock import Mock, patch
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from freezegun import freeze_time
|
from freezegun import freeze_time
|
||||||
from ftfy import fix_text
|
from ftfy import fix_text
|
||||||
|
|
||||||
|
|
@ -67,7 +66,8 @@ class TwitterCollectorTestCase(TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
post.publication_date, pytz.utc.localize(datetime(2020, 9, 18, 20, 32, 22))
|
post.publication_date,
|
||||||
|
datetime(2020, 9, 18, 20, 32, 22, tzinfo=_timezone.utc),
|
||||||
)
|
)
|
||||||
|
|
||||||
title = truncate_text(
|
title = truncate_text(
|
||||||
|
|
@ -89,7 +89,8 @@ class TwitterCollectorTestCase(TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
post.publication_date, pytz.utc.localize(datetime(2020, 9, 18, 18, 50, 11))
|
post.publication_date,
|
||||||
|
datetime(2020, 9, 18, 18, 50, 11, tzinfo=_timezone.utc),
|
||||||
)
|
)
|
||||||
|
|
||||||
body = fix_text(
|
body = fix_text(
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
|
from datetime import timezone
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from django_celery_beat.models import PeriodicTask
|
from django_celery_beat.models import PeriodicTask
|
||||||
|
|
||||||
from newsreader.news.collection.choices import RuleTypeChoices
|
from newsreader.news.collection.choices import RuleTypeChoices
|
||||||
|
|
@ -21,7 +21,7 @@ class FeedCreateViewTestCase(CollectionRuleViewTestCase, TestCase):
|
||||||
self.form_data.update(
|
self.form_data.update(
|
||||||
name="new rule",
|
name="new rule",
|
||||||
url="https://www.rss.com/rss",
|
url="https://www.rss.com/rss",
|
||||||
timezone=pytz.utc,
|
timezone=str(timezone.utc),
|
||||||
category=str(self.category.pk),
|
category=str(self.category.pk),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ class FeedCreateViewTestCase(CollectionRuleViewTestCase, TestCase):
|
||||||
|
|
||||||
self.assertEquals(rule.type, RuleTypeChoices.feed)
|
self.assertEquals(rule.type, RuleTypeChoices.feed)
|
||||||
self.assertEquals(rule.url, "https://www.rss.com/rss")
|
self.assertEquals(rule.url, "https://www.rss.com/rss")
|
||||||
self.assertEquals(rule.timezone, str(pytz.utc))
|
self.assertEquals(rule.timezone, str(timezone.utc))
|
||||||
self.assertEquals(rule.favicon, None)
|
self.assertEquals(rule.favicon, None)
|
||||||
self.assertEquals(rule.category.pk, self.category.pk)
|
self.assertEquals(rule.category.pk, self.category.pk)
|
||||||
self.assertEquals(rule.user.pk, self.user.pk)
|
self.assertEquals(rule.user.pk, self.user.pk)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
|
from datetime import timezone
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from newsreader.news.collection.choices import RuleTypeChoices
|
from newsreader.news.collection.choices import RuleTypeChoices
|
||||||
from newsreader.news.collection.models import CollectionRule
|
from newsreader.news.collection.models import CollectionRule
|
||||||
from newsreader.news.collection.reddit import REDDIT_API_URL, REDDIT_URL
|
from newsreader.news.collection.reddit import REDDIT_API_URL, REDDIT_URL
|
||||||
|
|
@ -38,7 +38,7 @@ class SubRedditCreateViewTestCase(CollectionRuleViewTestCase, TestCase):
|
||||||
|
|
||||||
self.assertEquals(rule.type, RuleTypeChoices.subreddit)
|
self.assertEquals(rule.type, RuleTypeChoices.subreddit)
|
||||||
self.assertEquals(rule.url, f"{REDDIT_API_URL}/r/aww")
|
self.assertEquals(rule.url, f"{REDDIT_API_URL}/r/aww")
|
||||||
self.assertEquals(rule.timezone, str(pytz.utc))
|
self.assertEquals(rule.timezone, str(timezone.utc))
|
||||||
self.assertEquals(rule.favicon, None)
|
self.assertEquals(rule.favicon, None)
|
||||||
self.assertEquals(rule.category.pk, self.category.pk)
|
self.assertEquals(rule.category.pk, self.category.pk)
|
||||||
self.assertEquals(rule.user.pk, self.user.pk)
|
self.assertEquals(rule.user.pk, self.user.pk)
|
||||||
|
|
@ -70,7 +70,7 @@ class SubRedditUpdateViewTestCase(CollectionRuleViewTestCase, TestCase):
|
||||||
"name": self.rule.name,
|
"name": self.rule.name,
|
||||||
"url": self.rule.url,
|
"url": self.rule.url,
|
||||||
"category": str(self.category.pk),
|
"category": str(self.category.pk),
|
||||||
"timezone": pytz.utc,
|
"timezone": str(timezone.utc),
|
||||||
"reddit_allow_nfsw": False,
|
"reddit_allow_nfsw": False,
|
||||||
"reddit_allow_spoiler": False,
|
"reddit_allow_spoiler": False,
|
||||||
"reddit_allow_viewed": True,
|
"reddit_allow_viewed": True,
|
||||||
|
|
@ -125,7 +125,7 @@ class SubRedditUpdateViewTestCase(CollectionRuleViewTestCase, TestCase):
|
||||||
|
|
||||||
self.assertEquals(rule.type, RuleTypeChoices.subreddit)
|
self.assertEquals(rule.type, RuleTypeChoices.subreddit)
|
||||||
self.assertEquals(rule.url, f"{REDDIT_API_URL}/r/aww")
|
self.assertEquals(rule.url, f"{REDDIT_API_URL}/r/aww")
|
||||||
self.assertEquals(rule.timezone, str(pytz.utc))
|
self.assertEquals(rule.timezone, str(timezone.utc))
|
||||||
self.assertEquals(rule.favicon, None)
|
self.assertEquals(rule.favicon, None)
|
||||||
self.assertEquals(rule.category.pk, self.category.pk)
|
self.assertEquals(rule.category.pk, self.category.pk)
|
||||||
self.assertEquals(rule.user.pk, self.user.pk)
|
self.assertEquals(rule.user.pk, self.user.pk)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
|
from datetime import timezone
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from django_celery_beat.models import PeriodicTask
|
from django_celery_beat.models import PeriodicTask
|
||||||
|
|
||||||
from newsreader.news.collection.choices import RuleTypeChoices
|
from newsreader.news.collection.choices import RuleTypeChoices
|
||||||
|
|
@ -37,7 +37,7 @@ class TwitterTimelineCreateViewTestCase(CollectionRuleViewTestCase, TestCase):
|
||||||
rule.url,
|
rule.url,
|
||||||
f"{TWITTER_API_URL}/statuses/user_timeline.json?screen_name=RobertsSpaceInd&tweet_mode=extended",
|
f"{TWITTER_API_URL}/statuses/user_timeline.json?screen_name=RobertsSpaceInd&tweet_mode=extended",
|
||||||
)
|
)
|
||||||
self.assertEquals(rule.timezone, str(pytz.utc))
|
self.assertEquals(rule.timezone, str(timezone.utc))
|
||||||
self.assertEquals(rule.favicon, None)
|
self.assertEquals(rule.favicon, None)
|
||||||
self.assertEquals(rule.category.pk, self.category.pk)
|
self.assertEquals(rule.category.pk, self.category.pk)
|
||||||
self.assertEquals(rule.user.pk, self.user.pk)
|
self.assertEquals(rule.user.pk, self.user.pk)
|
||||||
|
|
@ -70,7 +70,7 @@ class TwitterTimelineUpdateViewTestCase(CollectionRuleViewTestCase, TestCase):
|
||||||
"name": self.rule.name,
|
"name": self.rule.name,
|
||||||
"screen_name": self.rule.screen_name,
|
"screen_name": self.rule.screen_name,
|
||||||
"category": str(self.category.pk),
|
"category": str(self.category.pk),
|
||||||
"timezone": pytz.utc,
|
"timezone": str(timezone.utc),
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_name_change(self):
|
def test_name_change(self):
|
||||||
|
|
@ -123,7 +123,7 @@ class TwitterTimelineUpdateViewTestCase(CollectionRuleViewTestCase, TestCase):
|
||||||
self.rule.url,
|
self.rule.url,
|
||||||
f"{TWITTER_API_URL}/statuses/user_timeline.json?screen_name=CyberpunkGame&tweet_mode=extended",
|
f"{TWITTER_API_URL}/statuses/user_timeline.json?screen_name=CyberpunkGame&tweet_mode=extended",
|
||||||
)
|
)
|
||||||
self.assertEquals(self.rule.timezone, str(pytz.utc))
|
self.assertEquals(self.rule.timezone, str(timezone.utc))
|
||||||
self.assertEquals(self.rule.favicon, None)
|
self.assertEquals(self.rule.favicon, None)
|
||||||
self.assertEquals(self.rule.category.pk, self.category.pk)
|
self.assertEquals(self.rule.category.pk, self.category.pk)
|
||||||
self.assertEquals(self.rule.user.pk, self.user.pk)
|
self.assertEquals(self.rule.user.pk, self.user.pk)
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,14 @@ import logging
|
||||||
|
|
||||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from datetime import timezone as _timezone
|
||||||
from json import JSONDecodeError
|
from json import JSONDecodeError
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.mail import send_mail
|
from django.core.mail import send_mail
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.html import format_html, urlize
|
from django.utils.html import format_html, urlize
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from ftfy import fix_text
|
from ftfy import fix_text
|
||||||
from requests_oauthlib import OAuth1 as OAuth
|
from requests_oauthlib import OAuth1 as OAuth
|
||||||
|
|
@ -82,9 +81,11 @@ class TwitterBuilder(PostBuilder):
|
||||||
Post, "title", self.sanitize_fragment(data["full_text"])
|
Post, "title", self.sanitize_fragment(data["full_text"])
|
||||||
)
|
)
|
||||||
|
|
||||||
publication_date = pytz.utc.localize(
|
parsed_date = datetime.strptime(
|
||||||
datetime.strptime(data["created_at"], "%a %b %d %H:%M:%S +0000 %Y")
|
data["created_at"], "%a %b %d %H:%M:%S +0000 %Y"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
publication_date = parsed_date.replace(tzinfo=_timezone.utc)
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
raise BuilderMissingDataException(payload=data) from e
|
raise BuilderMissingDataException(payload=data) from e
|
||||||
except (OverflowError, OSError) as e:
|
except (OverflowError, OSError) as e:
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from datetime import timezone as _timezone
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db.models.fields import CharField, TextField
|
from django.db.models.fields import CharField, TextField
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
import pytz
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from requests.exceptions import RequestException
|
from requests.exceptions import RequestException
|
||||||
|
|
@ -22,7 +22,7 @@ def build_publication_date(dt, tz):
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
return timezone.now()
|
return timezone.now()
|
||||||
|
|
||||||
return published_parsed.astimezone(pytz.utc)
|
return published_parsed.astimezone(_timezone.utc)
|
||||||
|
|
||||||
|
|
||||||
def fetch(url, auth=None, headers={}):
|
def fetch(url, auth=None, headers={}):
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from django.urls import reverse_lazy
|
from zoneinfo import available_timezones
|
||||||
|
|
||||||
import pytz
|
from django.urls import reverse_lazy
|
||||||
|
|
||||||
from django_celery_beat.models import IntervalSchedule, PeriodicTask
|
from django_celery_beat.models import IntervalSchedule, PeriodicTask
|
||||||
|
|
||||||
|
|
@ -25,7 +25,9 @@ class CollectionRuleDetailMixin:
|
||||||
context_data = super().get_context_data(**kwargs)
|
context_data = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
categories = Category.objects.filter(user=self.request.user).order_by("name")
|
categories = Category.objects.filter(user=self.request.user).order_by("name")
|
||||||
timezones = [timezone for timezone in pytz.all_timezones]
|
|
||||||
|
_available_timezones = available_timezones()
|
||||||
|
timezones = [timezone for timezone in _available_timezones]
|
||||||
|
|
||||||
context_data["categories"] = categories
|
context_data["categories"] = categories
|
||||||
context_data["timezones"] = timezones
|
context_data["timezones"] = timezones
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_str
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from rest_framework import filters
|
from rest_framework import filters
|
||||||
from rest_framework.compat import coreapi, coreschema
|
from rest_framework.compat import coreapi, coreschema
|
||||||
|
|
@ -25,8 +25,8 @@ class ReadFilter(filters.BaseFilterBackend):
|
||||||
required=False,
|
required=False,
|
||||||
location="query",
|
location="query",
|
||||||
schema=coreschema.String(
|
schema=coreschema.String(
|
||||||
title=force_text(self.query_param),
|
title=force_str(self.query_param),
|
||||||
description=force_text(_("Wether posts should be read or not")),
|
description=force_str(_("Wether posts should be read or not")),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
@ -52,8 +52,8 @@ class SavedFilter(filters.BaseFilterBackend):
|
||||||
required=False,
|
required=False,
|
||||||
location="query",
|
location="query",
|
||||||
schema=coreschema.String(
|
schema=coreschema.String(
|
||||||
title=force_text(self.query_param),
|
title=force_str(self.query_param),
|
||||||
description=force_text(_("Wether posts should be saved or not")),
|
description=force_str(_("Wether posts should be saved or not")),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from newsreader.accounts.tests.factories import UserFactory
|
from newsreader.accounts.tests.factories import UserFactory
|
||||||
from newsreader.news.collection.tests.factories import FeedFactory
|
from newsreader.news.collection.tests.factories import FeedFactory
|
||||||
from newsreader.news.core.tests.factories import CategoryFactory, FeedPostFactory
|
from newsreader.news.core.tests.factories import CategoryFactory, FeedPostFactory
|
||||||
|
|
@ -29,15 +27,15 @@ class CategoryListViewTestCase(TestCase):
|
||||||
def test_ordering(self):
|
def test_ordering(self):
|
||||||
categories = [
|
categories = [
|
||||||
CategoryFactory(
|
CategoryFactory(
|
||||||
created=datetime(2019, 5, 20, 16, 7, 37, tzinfo=pytz.utc),
|
created=datetime(2019, 5, 20, 16, 7, 37, tzinfo=timezone.utc),
|
||||||
user=self.user,
|
user=self.user,
|
||||||
),
|
),
|
||||||
CategoryFactory(
|
CategoryFactory(
|
||||||
created=datetime(2019, 7, 20, 18, 7, 37, tzinfo=pytz.utc),
|
created=datetime(2019, 7, 20, 18, 7, 37, tzinfo=timezone.utc),
|
||||||
user=self.user,
|
user=self.user,
|
||||||
),
|
),
|
||||||
CategoryFactory(
|
CategoryFactory(
|
||||||
created=datetime(2019, 7, 20, 16, 7, 37, tzinfo=pytz.utc),
|
created=datetime(2019, 7, 20, 16, 7, 37, tzinfo=timezone.utc),
|
||||||
user=self.user,
|
user=self.user,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
@ -430,12 +428,12 @@ class NestedCategoryPostView(TestCase):
|
||||||
FeedPostFactory.create(
|
FeedPostFactory.create(
|
||||||
title="Second Reuters post",
|
title="Second Reuters post",
|
||||||
rule=reuters_rule,
|
rule=reuters_rule,
|
||||||
publication_date=datetime(2019, 5, 21, 15, tzinfo=pytz.utc),
|
publication_date=datetime(2019, 5, 21, 15, tzinfo=timezone.utc),
|
||||||
),
|
),
|
||||||
FeedPostFactory.create(
|
FeedPostFactory.create(
|
||||||
title="First Reuters post",
|
title="First Reuters post",
|
||||||
rule=reuters_rule,
|
rule=reuters_rule,
|
||||||
publication_date=datetime(2019, 5, 20, 12, tzinfo=pytz.utc),
|
publication_date=datetime(2019, 5, 20, 12, tzinfo=timezone.utc),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -443,12 +441,12 @@ class NestedCategoryPostView(TestCase):
|
||||||
FeedPostFactory.create(
|
FeedPostFactory.create(
|
||||||
title="Second Guardian post",
|
title="Second Guardian post",
|
||||||
rule=guardian_rule,
|
rule=guardian_rule,
|
||||||
publication_date=datetime(2019, 5, 21, 14, tzinfo=pytz.utc),
|
publication_date=datetime(2019, 5, 21, 14, tzinfo=timezone.utc),
|
||||||
),
|
),
|
||||||
FeedPostFactory.create(
|
FeedPostFactory.create(
|
||||||
title="First Guardian post",
|
title="First Guardian post",
|
||||||
rule=guardian_rule,
|
rule=guardian_rule,
|
||||||
publication_date=datetime(2019, 5, 20, 11, tzinfo=pytz.utc),
|
publication_date=datetime(2019, 5, 20, 11, tzinfo=timezone.utc),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -456,12 +454,12 @@ class NestedCategoryPostView(TestCase):
|
||||||
FeedPostFactory.create(
|
FeedPostFactory.create(
|
||||||
title="Second BBC post",
|
title="Second BBC post",
|
||||||
rule=bbc_rule,
|
rule=bbc_rule,
|
||||||
publication_date=datetime(2019, 5, 21, 16, tzinfo=pytz.utc),
|
publication_date=datetime(2019, 5, 21, 16, tzinfo=timezone.utc),
|
||||||
),
|
),
|
||||||
FeedPostFactory.create(
|
FeedPostFactory.create(
|
||||||
title="First BBC post",
|
title="First BBC post",
|
||||||
rule=bbc_rule,
|
rule=bbc_rule,
|
||||||
publication_date=datetime(2019, 5, 20, 13, tzinfo=pytz.utc),
|
publication_date=datetime(2019, 5, 20, 13, tzinfo=timezone.utc),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
from datetime import datetime
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from newsreader.accounts.tests.factories import UserFactory
|
from newsreader.accounts.tests.factories import UserFactory
|
||||||
from newsreader.news.collection.tests.factories import FeedFactory
|
from newsreader.news.collection.tests.factories import FeedFactory
|
||||||
from newsreader.news.core.tests.factories import CategoryFactory, FeedPostFactory
|
from newsreader.news.core.tests.factories import CategoryFactory, FeedPostFactory
|
||||||
|
|
@ -32,17 +30,17 @@ class PostListViewTestCase(TestCase):
|
||||||
FeedPostFactory(
|
FeedPostFactory(
|
||||||
title="I'm the first post",
|
title="I'm the first post",
|
||||||
rule=rule,
|
rule=rule,
|
||||||
publication_date=datetime(2019, 5, 20, 16, 7, 38, tzinfo=pytz.utc),
|
publication_date=datetime(2019, 5, 20, 16, 7, 38, tzinfo=timezone.utc),
|
||||||
),
|
),
|
||||||
FeedPostFactory(
|
FeedPostFactory(
|
||||||
title="I'm the second post",
|
title="I'm the second post",
|
||||||
rule=rule,
|
rule=rule,
|
||||||
publication_date=datetime(2019, 5, 20, 16, 7, 37, tzinfo=pytz.utc),
|
publication_date=datetime(2019, 5, 20, 16, 7, 37, tzinfo=timezone.utc),
|
||||||
),
|
),
|
||||||
FeedPostFactory(
|
FeedPostFactory(
|
||||||
title="I'm the third post",
|
title="I'm the third post",
|
||||||
rule=rule,
|
rule=rule,
|
||||||
publication_date=datetime(2019, 5, 20, 16, 7, 36, tzinfo=pytz.utc),
|
publication_date=datetime(2019, 5, 20, 16, 7, 36, tzinfo=timezone.utc),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
from datetime import timezone
|
||||||
|
|
||||||
import factory
|
import factory
|
||||||
import factory.fuzzy
|
import factory.fuzzy
|
||||||
import pytz
|
|
||||||
|
|
||||||
from newsreader.accounts.tests.factories import UserFactory
|
from newsreader.accounts.tests.factories import UserFactory
|
||||||
from newsreader.news.collection.reddit import REDDIT_API_URL
|
from newsreader.news.collection.reddit import REDDIT_API_URL
|
||||||
|
|
@ -19,7 +20,7 @@ class PostFactory(factory.django.DjangoModelFactory):
|
||||||
title = factory.Faker("sentence")
|
title = factory.Faker("sentence")
|
||||||
body = factory.Faker("paragraph")
|
body = factory.Faker("paragraph")
|
||||||
author = factory.Faker("name")
|
author = factory.Faker("name")
|
||||||
publication_date = factory.Faker("date_time_this_year", tzinfo=pytz.utc)
|
publication_date = factory.Faker("date_time_this_year", tzinfo=timezone.utc)
|
||||||
url = factory.Faker("url")
|
url = factory.Faker("url")
|
||||||
remote_identifier = factory.Faker("uuid4")
|
remote_identifier = factory.Faker("uuid4")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
$fa-font-path: '/static/fonts';
|
$fa-font-path: '~@fortawesome/fontawesome-free/webfonts';
|
||||||
|
|
||||||
@import '@fortawesome/fontawesome-free/scss/fontawesome';
|
@import '~@fortawesome/fontawesome-free/scss/fontawesome';
|
||||||
@import '@fortawesome/fontawesome-free/scss/solid';
|
@import '~@fortawesome/fontawesome-free/scss/regular';
|
||||||
@import '@fortawesome/fontawesome-free/scss/regular';
|
@import '~@fortawesome/fontawesome-free/scss/brands';
|
||||||
|
@import '~@fortawesome/fontawesome-free/scss/solid';
|
||||||
|
|
|
||||||
|
|
@ -6,5 +6,5 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block extrahead %}
|
{% block extrahead %}
|
||||||
<link type="image/png" href="{% static 'favicon.png' %}" rel="shortcut icon" />
|
<link type="image/png" href="{% static 'images/favicon.png' %}" rel="shortcut icon" />
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Newreader</title>
|
<title>Newreader</title>
|
||||||
<link type="image/png" href="{% static 'favicon.png' %}" rel="shortcut icon" />
|
<link type="image/png" href="{% static 'images/favicon.png' %}" rel="shortcut icon" />
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<link href="{% static 'css/main.css' %}" rel="stylesheet" />
|
<link href="{% static 'css/main.css' %}" rel="stylesheet" />
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,6 @@ from django.contrib import admin
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.urls import include, path
|
from django.urls import include, path
|
||||||
|
|
||||||
from drf_yasg import openapi
|
|
||||||
from drf_yasg.views import get_schema_view
|
|
||||||
|
|
||||||
from newsreader.accounts.urls import urlpatterns as login_urls
|
from newsreader.accounts.urls import urlpatterns as login_urls
|
||||||
from newsreader.news.core.views import NewsView
|
from newsreader.news.core.views import NewsView
|
||||||
from newsreader.news.urls import endpoints as news_endpoints
|
from newsreader.news.urls import endpoints as news_endpoints
|
||||||
|
|
@ -14,16 +11,12 @@ from newsreader.news.urls import urlpatterns as news_patterns
|
||||||
|
|
||||||
api_patterns = [path("api/", include((news_endpoints, "news")))]
|
api_patterns = [path("api/", include((news_endpoints, "news")))]
|
||||||
|
|
||||||
schema_info = openapi.Info(title="Newsreader API", default_version="v1")
|
|
||||||
schema_view = get_schema_view(schema_info, patterns=api_patterns)
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", login_required(NewsView.as_view()), name="index"),
|
path("", login_required(NewsView.as_view()), name="index"),
|
||||||
path("", include((news_patterns, "news"))),
|
path("", include((news_patterns, "news"))),
|
||||||
path("", include((api_patterns, "api"))),
|
path("", include((api_patterns, "api"))),
|
||||||
path("accounts/", include((login_urls, "accounts")), name="accounts"),
|
path("accounts/", include((login_urls, "accounts")), name="accounts"),
|
||||||
path("admin/", admin.site.urls, name="admin"),
|
path("admin/", admin.site.urls, name="admin"),
|
||||||
path("api/", schema_view.with_ui("swagger"), name="api"),
|
|
||||||
path("api/auth/", include("rest_framework.urls"), name="rest_framework"),
|
path("api/auth/", include("rest_framework.urls"), name="rest_framework"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { resolve } from 'path';
|
import { resolve } from 'path';
|
||||||
import { CleanWebpackPlugin } from 'clean-webpack-plugin';
|
|
||||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||||
|
import CopyPlugin from 'copy-webpack-plugin';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
resolve: { extensions: ['.js', '.scss'] },
|
resolve: { extensions: ['.js', '.scss'] },
|
||||||
|
|
@ -10,6 +11,7 @@ export default {
|
||||||
output: {
|
output: {
|
||||||
path: resolve(__dirname, 'src', 'newsreader', 'static'),
|
path: resolve(__dirname, 'src', 'newsreader', 'static'),
|
||||||
filename: 'js/[name].bundle.js',
|
filename: 'js/[name].bundle.js',
|
||||||
|
clean: true,
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
|
|
@ -23,26 +25,30 @@ export default {
|
||||||
use: [{ loader: MiniCssExtractPlugin.loader }, 'css-loader', 'sass-loader'],
|
use: [{ loader: MiniCssExtractPlugin.loader }, 'css-loader', 'sass-loader'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.(ttf|woff|woff2)$/,
|
test: /\.(ttf|woff|woff2|eot|otf)$/,
|
||||||
use: {
|
type: 'asset/resource',
|
||||||
loader: 'file-loader',
|
generator: {
|
||||||
options: {
|
filename: 'fonts/[name][ext]',
|
||||||
name: '[name].[ext]',
|
|
||||||
outputPath: 'fonts',
|
|
||||||
publicPath: '/static/fonts/',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
test: /\.(png|svg|jpg|jpeg)$/,
|
||||||
|
type: 'asset/resource',
|
||||||
|
generator: {
|
||||||
|
filename: 'images/[name][ext]',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new MiniCssExtractPlugin({
|
new MiniCssExtractPlugin({ filename: 'css/main.css' }),
|
||||||
filename: 'css/main.css',
|
new CopyPlugin({
|
||||||
allChunks: true,
|
patterns: [
|
||||||
}),
|
{
|
||||||
new CleanWebpackPlugin({
|
from: './src/newsreader/assets/images/favicon.png',
|
||||||
cleanOnceBeforeBuildPatterns: ['js', 'css', 'fonts'],
|
to: 'images/',
|
||||||
cleanAfterEveryBuildPatterns: ['!fonts/**'],
|
},
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue