From 27708152d2b6a4cb478d481342c68ffe74cd6bb8 Mon Sep 17 00:00:00 2001 From: Nick Sweeting <git@nicksweeting.com> Date: Tue, 2 Apr 2019 16:36:41 -0400 Subject: [PATCH] wip initial django setup --- archivebox/__init__.py | 4 +- archivebox/archivebox/VERSION | 1 + archivebox/archivebox/__init__.py | 0 archivebox/archivebox/settings.py | 123 ++++++++++++++++++ archivebox/archivebox/urls.py | 21 +++ archivebox/archivebox/wsgi.py | 16 +++ archivebox/core/__init__.py | 0 archivebox/core/admin.py | 3 + archivebox/core/apps.py | 5 + archivebox/{ => core}/archive.py | 16 +-- archivebox/{ => core}/archive_methods.py | 10 +- archivebox/{ => core}/config.py | 0 archivebox/{ => core}/index.py | 14 +- archivebox/{ => core}/links.py | 6 +- archivebox/{ => core}/logs.py | 4 +- .../core/management/commands/archivebox.py | 10 ++ archivebox/core/migrations/__init__.py | 0 archivebox/core/models.py | 3 + archivebox/{ => core}/parse.py | 4 +- archivebox/{ => core}/purge.py | 4 +- archivebox/{ => core}/schema.py | 28 ++-- archivebox/core/tests.py | 3 + archivebox/{ => core}/util.py | 22 ++-- archivebox/core/views.py | 3 + archivebox/manage.py | 15 +++ archivebox/{templates => }/static/archive.png | Bin .../{templates => }/static/bootstrap.min.css | 0 .../{templates => }/static/external.png | Bin .../static/jquery.dataTables.min.css | 0 .../static/jquery.dataTables.min.js | 0 .../{templates => }/static/jquery.min.js | 0 .../{templates => }/static/sort_asc.png | Bin .../{templates => }/static/sort_both.png | Bin .../{templates => }/static/sort_desc.png | Bin archivebox/{templates => }/static/spinner.gif | Bin requirements.txt | 1 + 36 files changed, 257 insertions(+), 59 deletions(-) create mode 120000 archivebox/archivebox/VERSION create mode 100644 archivebox/archivebox/__init__.py create mode 100644 archivebox/archivebox/settings.py create mode 100644 archivebox/archivebox/urls.py create mode 100644 archivebox/archivebox/wsgi.py create mode 100644 archivebox/core/__init__.py create mode 100644 archivebox/core/admin.py create mode 100644 archivebox/core/apps.py rename archivebox/{ => core}/archive.py (95%) rename archivebox/{ => core}/archive_methods.py (99%) rename archivebox/{ => core}/config.py (100%) rename archivebox/{ => core}/index.py (97%) rename archivebox/{ => core}/links.py (96%) rename archivebox/{ => core}/logs.py (98%) create mode 100644 archivebox/core/management/commands/archivebox.py create mode 100644 archivebox/core/migrations/__init__.py create mode 100644 archivebox/core/models.py rename archivebox/{ => core}/parse.py (99%) rename archivebox/{ => core}/purge.py (93%) rename archivebox/{ => core}/schema.py (94%) create mode 100644 archivebox/core/tests.py rename archivebox/{ => core}/util.py (99%) create mode 100644 archivebox/core/views.py create mode 100755 archivebox/manage.py rename archivebox/{templates => }/static/archive.png (100%) rename archivebox/{templates => }/static/bootstrap.min.css (100%) rename archivebox/{templates => }/static/external.png (100%) rename archivebox/{templates => }/static/jquery.dataTables.min.css (100%) rename archivebox/{templates => }/static/jquery.dataTables.min.js (100%) rename archivebox/{templates => }/static/jquery.min.js (100%) rename archivebox/{templates => }/static/sort_asc.png (100%) rename archivebox/{templates => }/static/sort_both.png (100%) rename archivebox/{templates => }/static/sort_desc.png (100%) rename archivebox/{templates => }/static/spinner.gif (100%) diff --git a/archivebox/__init__.py b/archivebox/__init__.py index 0fb9e6f8..ab53f570 100644 --- a/archivebox/__init__.py +++ b/archivebox/__init__.py @@ -1,5 +1,5 @@ -__name__ = 'archivebox' -__package__ = 'archivebox' +#__name__ = 'archivebox' +#__package__ = 'archivebox' diff --git a/archivebox/archivebox/VERSION b/archivebox/archivebox/VERSION new file mode 120000 index 00000000..6ff19de4 --- /dev/null +++ b/archivebox/archivebox/VERSION @@ -0,0 +1 @@ +../VERSION \ No newline at end of file diff --git a/archivebox/archivebox/__init__.py b/archivebox/archivebox/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/archivebox/archivebox/settings.py b/archivebox/archivebox/settings.py new file mode 100644 index 00000000..e027de02 --- /dev/null +++ b/archivebox/archivebox/settings.py @@ -0,0 +1,123 @@ +""" +Django settings for archivebox project. + +Generated by 'django-admin startproject' using Django 2.1.7. + +For more information on this file, see +https://docs.djangoproject.com/en/2.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/2.1/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(COLLECTION_DIR, ...) +REPO_DIR = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')) +COLLECTION_DIR = os.path.abspath(os.curdir) + +print(REPO_DIR) +print(COLLECTION_DIR) +raise SystemExit(0) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'm-ma!-z^0b5w4%**le#ig!7-d@h($t02q*96h*-ua+$lm9bvao' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + + 'core', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'archivebox.urls' + +ACTIVE_THEME = 'default' +TEMPLATES_DIR = os.path.join(REPO_DIR, 'themes', ACTIVE_THEME) +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [TEMPLATES_DIR], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'archivebox.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/2.1/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(COLLECTION_DIR, 'database.sqlite3'), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/2.1/topics/i18n/ +LANGUAGE_CODE = 'en-us' +TIME_ZONE = 'UTC' +USE_I18N = True +USE_L10N = True +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/2.1/howto/static-files/ +STATIC_URL = '/static/' diff --git a/archivebox/archivebox/urls.py b/archivebox/archivebox/urls.py new file mode 100644 index 00000000..a077ec78 --- /dev/null +++ b/archivebox/archivebox/urls.py @@ -0,0 +1,21 @@ +"""archivebox URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/2.1/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] diff --git a/archivebox/archivebox/wsgi.py b/archivebox/archivebox/wsgi.py new file mode 100644 index 00000000..f933afae --- /dev/null +++ b/archivebox/archivebox/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for archivebox project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'archivebox.settings') + +application = get_wsgi_application() diff --git a/archivebox/core/__init__.py b/archivebox/core/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/archivebox/core/admin.py b/archivebox/core/admin.py new file mode 100644 index 00000000..8c38f3f3 --- /dev/null +++ b/archivebox/core/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/archivebox/core/apps.py b/archivebox/core/apps.py new file mode 100644 index 00000000..26f78a8e --- /dev/null +++ b/archivebox/core/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class CoreConfig(AppConfig): + name = 'core' diff --git a/archivebox/archive.py b/archivebox/core/archive.py similarity index 95% rename from archivebox/archive.py rename to archivebox/core/archive.py index b0a28428..e74b2644 100755 --- a/archivebox/archive.py +++ b/archivebox/core/archive.py @@ -16,11 +16,11 @@ import shutil from typing import List, Optional -from .schema import Link -from .links import links_after_timestamp -from .index import write_links_index, load_links_index -from .archive_methods import archive_link -from .config import ( +from core.schema import Link +from core.links import links_after_timestamp +from core.index import write_links_index, load_links_index +from core.archive_methods import archive_link +from core.config import ( ONLY_NEW, OUTPUT_DIR, VERSION, @@ -41,12 +41,12 @@ from .config import ( FETCH_GIT, FETCH_MEDIA, ) -from .util import ( +from core.util import ( enforce_types, handle_stdin_import, handle_file_import, ) -from .logs import ( +from core.logs import ( log_archiving_started, log_archiving_paused, log_archiving_finished, @@ -142,7 +142,7 @@ def main(args=None) -> None: " If you're trying to create a new archive, you must run archivebox inside a completely empty directory." "\n\n" " {lightred}Hint:{reset} To import a data folder created by an older version of ArchiveBox, \n" - " just cd into the folder and run the archivebox comamnd to pick up where you left off.\n\n" + " just cd into the folder and run the archivebox command to pick up where you left off.\n\n" " (Always make sure your data folder is backed up first before updating ArchiveBox)" ).format(OUTPUT_DIR, **ANSI) ) diff --git a/archivebox/archive_methods.py b/archivebox/core/archive_methods.py similarity index 99% rename from archivebox/archive_methods.py rename to archivebox/core/archive_methods.py index d30d008d..add5a069 100644 --- a/archivebox/archive_methods.py +++ b/archivebox/core/archive_methods.py @@ -4,13 +4,13 @@ from typing import Dict, List, Tuple, Optional from collections import defaultdict from datetime import datetime -from .schema import Link, ArchiveResult, ArchiveOutput -from .index import ( +from core.schema import Link, ArchiveResult, ArchiveOutput +from core.index import ( write_link_index, patch_links_index, load_json_link_index, ) -from .config import ( +from core.config import ( CURL_BINARY, GIT_BINARY, WGET_BINARY, @@ -40,7 +40,7 @@ from .config import ( YOUTUBEDL_VERSION, WGET_AUTO_COMPRESSION, ) -from .util import ( +from core.util import ( enforce_types, domain, extension, @@ -54,7 +54,7 @@ from .util import ( chrome_args, run, PIPE, DEVNULL, ) -from .logs import ( +from core.logs import ( log_link_archiving_started, log_link_archiving_finished, log_archive_method_started, diff --git a/archivebox/config.py b/archivebox/core/config.py similarity index 100% rename from archivebox/config.py rename to archivebox/core/config.py diff --git a/archivebox/index.py b/archivebox/core/index.py similarity index 97% rename from archivebox/index.py rename to archivebox/core/index.py index b3cd350e..516e4304 100644 --- a/archivebox/index.py +++ b/archivebox/core/index.py @@ -5,8 +5,8 @@ from datetime import datetime from string import Template from typing import List, Tuple, Iterator, Optional, Mapping -from .schema import Link, ArchiveResult -from .config import ( +from core.schema import Link, ArchiveResult +from core.config import ( OUTPUT_DIR, TEMPLATES_DIR, VERSION, @@ -14,7 +14,8 @@ from .config import ( FOOTER_INFO, TIMEOUT, ) -from .util import ( +from core.util import ( + ts_to_date, merge_links, urlencode, htmlencode, @@ -26,9 +27,9 @@ from .util import ( copy_and_overwrite, atomic_write, ) -from .parse import parse_links -from .links import validate_links -from .logs import ( +from core.parse import parse_links +from core.links import validate_links +from core.logs import ( log_indexing_process_started, log_indexing_started, log_indexing_finished, @@ -284,6 +285,7 @@ def write_html_link_index(link: Link, link_dir: Optional[str]=None) -> None: 'tags': link.tags or 'untagged', 'status': 'archived' if link.is_archived else 'not yet archived', 'status_color': 'success' if link.is_archived else 'danger', + 'oldest_archive_date': ts_to_date(link.oldest_archive_date), } html_index = Template(link_html).substitute(**template_vars) diff --git a/archivebox/links.py b/archivebox/core/links.py similarity index 96% rename from archivebox/links.py rename to archivebox/core/links.py index 914c3575..fa4f53e6 100644 --- a/archivebox/links.py +++ b/archivebox/core/links.py @@ -1,14 +1,14 @@ from typing import Iterable from collections import OrderedDict -from .schema import Link -from .util import ( +from core.schema import Link +from core.util import ( scheme, fuzzy_url, merge_links, ) -from .config import URL_BLACKLIST_PTN +from core.config import URL_BLACKLIST_PTN def validate_links(links: Iterable[Link]) -> Iterable[Link]: diff --git a/archivebox/logs.py b/archivebox/core/logs.py similarity index 98% rename from archivebox/logs.py rename to archivebox/core/logs.py index d9b92422..0b9243c2 100644 --- a/archivebox/logs.py +++ b/archivebox/core/logs.py @@ -5,8 +5,8 @@ from datetime import datetime from dataclasses import dataclass from typing import Optional -from .schema import Link, ArchiveResult -from .config import ANSI, OUTPUT_DIR +from core.schema import Link, ArchiveResult +from core.config import ANSI, OUTPUT_DIR @dataclass diff --git a/archivebox/core/management/commands/archivebox.py b/archivebox/core/management/commands/archivebox.py new file mode 100644 index 00000000..1764e4e2 --- /dev/null +++ b/archivebox/core/management/commands/archivebox.py @@ -0,0 +1,10 @@ +from django.core.management.base import BaseCommand + + +from core.archive import main + +class Command(BaseCommand): + help = 'ArchiveBox test.bee' + + def handle(self, *args, **kwargs): + main() diff --git a/archivebox/core/migrations/__init__.py b/archivebox/core/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/archivebox/core/models.py b/archivebox/core/models.py new file mode 100644 index 00000000..71a83623 --- /dev/null +++ b/archivebox/core/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/archivebox/parse.py b/archivebox/core/parse.py similarity index 99% rename from archivebox/parse.py rename to archivebox/core/parse.py index 49ffa7fd..9a6936c0 100644 --- a/archivebox/parse.py +++ b/archivebox/core/parse.py @@ -24,8 +24,8 @@ from typing import Tuple, List, IO, Iterable from datetime import datetime import xml.etree.ElementTree as etree -from .config import TIMEOUT -from .util import ( +from core.config import TIMEOUT +from core.util import ( htmldecode, str_between, URL_REGEX, diff --git a/archivebox/purge.py b/archivebox/core/purge.py similarity index 93% rename from archivebox/purge.py rename to archivebox/core/purge.py index ddc64b6b..d9a5deda 100755 --- a/archivebox/purge.py +++ b/archivebox/core/purge.py @@ -6,8 +6,8 @@ from os.path import exists, join from shutil import rmtree from typing import List -from .config import ARCHIVE_DIR, OUTPUT_DIR -from .index import parse_json_links_index, write_html_links_index, write_json_links_index +from core.config import ARCHIVE_DIR, OUTPUT_DIR +from core.index import parse_json_links_index, write_html_links_index, write_json_links_index def cleanup_index(regexes: List[str], proceed: bool, delete: bool) -> None: diff --git a/archivebox/schema.py b/archivebox/core/schema.py similarity index 94% rename from archivebox/schema.py rename to archivebox/core/schema.py index a4d3a836..c2da775d 100644 --- a/archivebox/schema.py +++ b/archivebox/core/schema.py @@ -221,28 +221,20 @@ class Link: return ts_to_date(self.updated) if self.updated else None @property - def oldest_archive_date(self) -> Optional[datetime]: - from .util import ts_to_date + def archive_dates(self) -> List[datetime]: + return [ + result.start_ts + for method in self.history.keys() + for result in self.history[method] + ] - most_recent = min( - (ts_to_date(result.start_ts) - for method in self.history.keys() - for result in self.history[method]), - default=None, - ) - return ts_to_date(most_recent) if most_recent else None + @property + def oldest_archive_date(self) -> Optional[datetime]: + return min(self.archive_dates, default=None) @property def newest_archive_date(self) -> Optional[datetime]: - from .util import ts_to_date - - most_recent = max( - (ts_to_date(result.start_ts) - for method in self.history.keys() - for result in self.history[method]), - default=None, - ) - return ts_to_date(most_recent) if most_recent else None + return max(self.archive_dates, default=None) ### Archive Status Helpers @property diff --git a/archivebox/core/tests.py b/archivebox/core/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/archivebox/core/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/archivebox/util.py b/archivebox/core/util.py similarity index 99% rename from archivebox/util.py rename to archivebox/core/util.py index ec8c256b..cf314287 100644 --- a/archivebox/util.py +++ b/archivebox/core/util.py @@ -26,8 +26,8 @@ from subprocess import ( from base32_crockford import encode as base32_encode # type: ignore -from .schema import Link -from .config import ( +from core.schema import Link +from core.config import ( ANSI, TERM_WIDTH, SOURCES_DIR, @@ -40,7 +40,7 @@ from .config import ( CHROME_OPTIONS, PYTHON_DIR, ) -from .logs import pretty_path +from core.logs import pretty_path ### Parsing Helpers @@ -62,17 +62,17 @@ base_url = lambda url: without_scheme(url) # uniq base url used to dedupe links without_www = lambda url: url.replace('://www.', '://', 1) without_trailing_slash = lambda url: url[:-1] if url[-1] == '/' else url.replace('/?', '?') fuzzy_url = lambda url: without_trailing_slash(without_www(without_scheme(url.lower()))) - -short_ts = lambda ts: str(parse_date(ts).timestamp()).split('.')[0] -ts_to_date = lambda ts: parse_date(ts).strftime('%Y-%m-%d %H:%M') -ts_to_iso = lambda ts: parse_date(ts).isoformat() +hashurl = lambda url: base32_encode(int(sha256(base_url(url).encode('utf-8')).hexdigest(), 16))[:20] urlencode = lambda s: s and quote(s, encoding='utf-8', errors='replace') urldecode = lambda s: s and unquote(s) htmlencode = lambda s: s and escape(s, quote=True) htmldecode = lambda s: s and unescape(s) -hashurl = lambda url: base32_encode(int(sha256(base_url(url).encode('utf-8')).hexdigest(), 16))[:20] +short_ts = lambda ts: str(parse_date(ts).timestamp()).split('.')[0] +ts_to_date = lambda ts: ts and parse_date(ts).strftime('%Y-%m-%d %H:%M') +ts_to_iso = lambda ts: ts and parse_date(ts).isoformat() + URL_REGEX = re.compile( r'http[s]?://' # start matching from allowed schemes @@ -357,11 +357,11 @@ def str_between(string: str, start: str, end: str=None) -> str: def parse_date(date: Any) -> Optional[datetime]: """Parse unix timestamps, iso format, and human-readable strings""" - if isinstance(date, datetime): - return date - if date is None: return None + + if isinstance(date, datetime): + return date if isinstance(date, (float, int)): date = str(date) diff --git a/archivebox/core/views.py b/archivebox/core/views.py new file mode 100644 index 00000000..91ea44a2 --- /dev/null +++ b/archivebox/core/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/archivebox/manage.py b/archivebox/manage.py new file mode 100755 index 00000000..cc70dfd5 --- /dev/null +++ b/archivebox/manage.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == '__main__': + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'archivebox.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) diff --git a/archivebox/templates/static/archive.png b/archivebox/static/archive.png similarity index 100% rename from archivebox/templates/static/archive.png rename to archivebox/static/archive.png diff --git a/archivebox/templates/static/bootstrap.min.css b/archivebox/static/bootstrap.min.css similarity index 100% rename from archivebox/templates/static/bootstrap.min.css rename to archivebox/static/bootstrap.min.css diff --git a/archivebox/templates/static/external.png b/archivebox/static/external.png similarity index 100% rename from archivebox/templates/static/external.png rename to archivebox/static/external.png diff --git a/archivebox/templates/static/jquery.dataTables.min.css b/archivebox/static/jquery.dataTables.min.css similarity index 100% rename from archivebox/templates/static/jquery.dataTables.min.css rename to archivebox/static/jquery.dataTables.min.css diff --git a/archivebox/templates/static/jquery.dataTables.min.js b/archivebox/static/jquery.dataTables.min.js similarity index 100% rename from archivebox/templates/static/jquery.dataTables.min.js rename to archivebox/static/jquery.dataTables.min.js diff --git a/archivebox/templates/static/jquery.min.js b/archivebox/static/jquery.min.js similarity index 100% rename from archivebox/templates/static/jquery.min.js rename to archivebox/static/jquery.min.js diff --git a/archivebox/templates/static/sort_asc.png b/archivebox/static/sort_asc.png similarity index 100% rename from archivebox/templates/static/sort_asc.png rename to archivebox/static/sort_asc.png diff --git a/archivebox/templates/static/sort_both.png b/archivebox/static/sort_both.png similarity index 100% rename from archivebox/templates/static/sort_both.png rename to archivebox/static/sort_both.png diff --git a/archivebox/templates/static/sort_desc.png b/archivebox/static/sort_desc.png similarity index 100% rename from archivebox/templates/static/sort_desc.png rename to archivebox/static/sort_desc.png diff --git a/archivebox/templates/static/spinner.gif b/archivebox/static/spinner.gif similarity index 100% rename from archivebox/templates/static/spinner.gif rename to archivebox/static/spinner.gif diff --git a/requirements.txt b/requirements.txt index 6c12aee4..42fba851 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +django base32-crockford setuptools