Format Python code with black

This commit is contained in:
kpj
2022-02-27 15:26:41 +01:00
parent f0ffc69010
commit c56cb25b5f
136 changed files with 6142 additions and 3811 deletions

View File

@@ -1,6 +1,7 @@
import os
from django.core.asgi import get_asgi_application
# Fetch Django ASGI application early to ensure AppRegistry is populated
# before importing consumers and AuthMiddlewareStack that may import ORM
# models.
@@ -13,11 +14,9 @@ from channels.routing import ProtocolTypeRouter, URLRouter # NOQA: E402
from paperless.urls import websocket_urlpatterns # NOQA: E402
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
websocket_urlpatterns
)
),
})
application = ProtocolTypeRouter(
{
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(URLRouter(websocket_urlpatterns)),
}
)

View File

@@ -7,23 +7,25 @@ from django.contrib.auth.middleware import RemoteUserMiddleware
class AutoLoginMiddleware(MiddlewareMixin):
def process_request(self, request):
try:
request.user = User.objects.get(
username=settings.AUTO_LOGIN_USERNAME)
request.user = User.objects.get(username=settings.AUTO_LOGIN_USERNAME)
auth.login(request, request.user)
except User.DoesNotExist:
pass
class AngularApiAuthenticationOverride(authentication.BaseAuthentication):
""" This class is here to provide authentication to the angular dev server
during development. This is disabled in production.
"""This class is here to provide authentication to the angular dev server
during development. This is disabled in production.
"""
def authenticate(self, request):
if settings.DEBUG and 'Referer' in request.headers and request.headers['Referer'].startswith('http://localhost:4200/'): # NOQA: E501
if (
settings.DEBUG
and "Referer" in request.headers
and request.headers["Referer"].startswith("http://localhost:4200/")
): # NOQA: E501
user = User.objects.filter(is_staff=True).first()
print("Auto-Login with user {}".format(user))
return (user, None)
@@ -32,7 +34,8 @@ class AngularApiAuthenticationOverride(authentication.BaseAuthentication):
class HttpRemoteUserMiddleware(RemoteUserMiddleware):
""" This class allows authentication via HTTP_REMOTE_USER which is set for
example by certain SSO applications.
"""This class allows authentication via HTTP_REMOTE_USER which is set for
example by certain SSO applications.
"""
header = settings.HTTP_REMOTE_USER_HEADER_NAME

View File

@@ -18,24 +18,26 @@ def path_check(var, directory):
messages = []
if directory:
if not os.path.isdir(directory):
messages.append(Error(
exists_message.format(var),
exists_hint.format(directory)
))
messages.append(
Error(exists_message.format(var), exists_hint.format(directory))
)
else:
test_file = os.path.join(
directory, f'__paperless_write_test_{os.getpid()}__'
directory, f"__paperless_write_test_{os.getpid()}__"
)
try:
with open(test_file, 'w'):
with open(test_file, "w"):
pass
except PermissionError:
messages.append(Error(
writeable_message.format(var),
writeable_hint.format(
f'\n{stat.filemode(os.stat(directory).st_mode)} '
f'{directory}\n')
))
messages.append(
Error(
writeable_message.format(var),
writeable_hint.format(
f"\n{stat.filemode(os.stat(directory).st_mode)} "
f"{directory}\n"
),
)
)
finally:
if os.path.isfile(test_file):
os.remove(test_file)
@@ -49,10 +51,12 @@ def paths_check(app_configs, **kwargs):
Check the various paths for existence, readability and writeability
"""
return path_check("PAPERLESS_DATA_DIR", settings.DATA_DIR) + \
path_check("PAPERLESS_TRASH_DIR", settings.TRASH_DIR) + \
path_check("PAPERLESS_MEDIA_ROOT", settings.MEDIA_ROOT) + \
path_check("PAPERLESS_CONSUMPTION_DIR", settings.CONSUMPTION_DIR)
return (
path_check("PAPERLESS_DATA_DIR", settings.DATA_DIR)
+ path_check("PAPERLESS_TRASH_DIR", settings.TRASH_DIR)
+ path_check("PAPERLESS_MEDIA_ROOT", settings.MEDIA_ROOT)
+ path_check("PAPERLESS_CONSUMPTION_DIR", settings.CONSUMPTION_DIR)
)
@register()
@@ -65,11 +69,7 @@ def binaries_check(app_configs, **kwargs):
error = "Paperless can't find {}. Without it, consumption is impossible."
hint = "Either it's not in your ${PATH} or it's not installed."
binaries = (
settings.CONVERT_BINARY,
settings.OPTIPNG_BINARY,
"tesseract"
)
binaries = (settings.CONVERT_BINARY, settings.OPTIPNG_BINARY, "tesseract")
check_messages = []
for binary in binaries:
@@ -82,11 +82,14 @@ def binaries_check(app_configs, **kwargs):
@register()
def debug_mode_check(app_configs, **kwargs):
if settings.DEBUG:
return [Warning(
"DEBUG mode is enabled. Disable Debug mode. This is a serious "
"security issue, since it puts security overides in place which "
"are meant to be only used during development. This "
"also means that paperless will tell anyone various "
"debugging information when something goes wrong.")]
return [
Warning(
"DEBUG mode is enabled. Disable Debug mode. This is a serious "
"security issue, since it puts security overides in place which "
"are meant to be only used during development. This "
"also means that paperless will tell anyone various "
"debugging information when something goes wrong."
)
]
else:
return []

View File

@@ -6,24 +6,25 @@ from channels.generic.websocket import WebsocketConsumer
class StatusConsumer(WebsocketConsumer):
def _authenticated(self):
return 'user' in self.scope and self.scope['user'].is_authenticated
return "user" in self.scope and self.scope["user"].is_authenticated
def connect(self):
if not self._authenticated():
raise DenyConnection()
else:
async_to_sync(self.channel_layer.group_add)(
'status_updates', self.channel_name)
"status_updates", self.channel_name
)
raise AcceptConnection()
def disconnect(self, close_code):
async_to_sync(self.channel_layer.group_discard)(
'status_updates', self.channel_name)
"status_updates", self.channel_name
)
def status_update(self, event):
if not self._authenticated():
self.close()
else:
self.send(json.dumps(event['data']))
self.send(json.dumps(event["data"]))

View File

@@ -4,17 +4,14 @@ from paperless import version
class ApiVersionMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
if request.user.is_authenticated:
versions = settings.REST_FRAMEWORK['ALLOWED_VERSIONS']
response['X-Api-Version'] = versions[len(versions)-1]
response['X-Version'] = ".".join(
[str(_) for _ in version.__version__]
)
versions = settings.REST_FRAMEWORK["ALLOWED_VERSIONS"]
response["X-Api-Version"] = versions[len(versions) - 1]
response["X-Version"] = ".".join([str(_) for _ in version.__version__])
return response

View File

@@ -27,7 +27,7 @@ elif os.path.exists("/usr/local/etc/paperless.conf"):
# OCR threads may exceed the number of available cpu cores, which will
# dramatically slow down the consumption process. This settings limits each
# Tesseract process to one thread.
os.environ['OMP_THREAD_LIMIT'] = "1"
os.environ["OMP_THREAD_LIMIT"] = "1"
def __get_boolean(key, default="NO"):
@@ -50,14 +50,14 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_ROOT = os.getenv("PAPERLESS_STATICDIR", os.path.join(BASE_DIR, "..", "static"))
MEDIA_ROOT = os.getenv('PAPERLESS_MEDIA_ROOT', os.path.join(BASE_DIR, "..", "media"))
MEDIA_ROOT = os.getenv("PAPERLESS_MEDIA_ROOT", os.path.join(BASE_DIR, "..", "media"))
ORIGINALS_DIR = os.path.join(MEDIA_ROOT, "documents", "originals")
ARCHIVE_DIR = os.path.join(MEDIA_ROOT, "documents", "archive")
THUMBNAIL_DIR = os.path.join(MEDIA_ROOT, "documents", "thumbnails")
DATA_DIR = os.getenv('PAPERLESS_DATA_DIR', os.path.join(BASE_DIR, "..", "data"))
DATA_DIR = os.getenv("PAPERLESS_DATA_DIR", os.path.join(BASE_DIR, "..", "data"))
TRASH_DIR = os.getenv('PAPERLESS_TRASH_DIR')
TRASH_DIR = os.getenv("PAPERLESS_TRASH_DIR")
# Lock file for synchronizing changes to the MEDIA directory across multiple
# threads.
@@ -65,9 +65,11 @@ MEDIA_LOCK = os.path.join(MEDIA_ROOT, "media.lock")
INDEX_DIR = os.path.join(DATA_DIR, "index")
MODEL_FILE = os.path.join(DATA_DIR, "classification_model.pickle")
LOGGING_DIR = os.getenv('PAPERLESS_LOGGING_DIR', os.path.join(DATA_DIR, "log"))
LOGGING_DIR = os.getenv("PAPERLESS_LOGGING_DIR", os.path.join(DATA_DIR, "log"))
CONSUMPTION_DIR = os.getenv("PAPERLESS_CONSUMPTION_DIR", os.path.join(BASE_DIR, "..", "consume"))
CONSUMPTION_DIR = os.getenv(
"PAPERLESS_CONSUMPTION_DIR", os.path.join(BASE_DIR, "..", "consume")
)
# This will be created if it doesn't exist
SCRATCH_DIR = os.getenv("PAPERLESS_SCRATCH_DIR", "/tmp/paperless")
@@ -80,75 +82,68 @@ env_apps = os.getenv("PAPERLESS_APPS").split(",") if os.getenv("PAPERLESS_APPS")
INSTALLED_APPS = [
"whitenoise.runserver_nostatic",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"corsheaders",
"django_extensions",
"paperless",
"documents.apps.DocumentsConfig",
"paperless_tesseract.apps.PaperlessTesseractConfig",
"paperless_text.apps.PaperlessTextConfig",
"paperless_mail.apps.PaperlessMailConfig",
"django.contrib.admin",
"rest_framework",
"rest_framework.authtoken",
"django_filters",
"django_q",
] + env_apps
if DEBUG:
INSTALLED_APPS.append("channels")
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication'
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework.authentication.BasicAuthentication",
"rest_framework.authentication.SessionAuthentication",
"rest_framework.authentication.TokenAuthentication",
],
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.AcceptHeaderVersioning',
'DEFAULT_VERSION': '1',
"DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.AcceptHeaderVersioning",
"DEFAULT_VERSION": "1",
# Make sure these are ordered and that the most recent version appears
# last
'ALLOWED_VERSIONS': ['1', '2']
"ALLOWED_VERSIONS": ["1", "2"],
}
if DEBUG:
REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'].append(
'paperless.auth.AngularApiAuthenticationOverride'
REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"].append(
"paperless.auth.AngularApiAuthenticationOverride"
)
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'paperless.middleware.ApiVersionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
"django.middleware.security.SecurityMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"corsheaders.middleware.CorsMiddleware",
"django.middleware.locale.LocaleMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"paperless.middleware.ApiVersionMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = 'paperless.urls'
ROOT_URLCONF = "paperless.urls"
FORCE_SCRIPT_NAME = os.getenv("PAPERLESS_FORCE_SCRIPT_NAME")
BASE_URL = (FORCE_SCRIPT_NAME or "") + "/"
LOGIN_URL = BASE_URL + "accounts/login/"
LOGOUT_REDIRECT_URL = os.getenv("PAPERLESS_LOGOUT_REDIRECT_URL")
WSGI_APPLICATION = 'paperless.wsgi.application'
WSGI_APPLICATION = "paperless.wsgi.application"
ASGI_APPLICATION = "paperless.asgi.application"
STATIC_URL = os.getenv("PAPERLESS_STATIC_URL", BASE_URL + "static/")
@@ -157,15 +152,15 @@ WHITENOISE_STATIC_PREFIX = "/static/"
# TODO: what is this used for?
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'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',
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"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",
],
},
},
@@ -189,45 +184,46 @@ CHANNEL_LAYERS = {
AUTO_LOGIN_USERNAME = os.getenv("PAPERLESS_AUTO_LOGIN_USERNAME")
if AUTO_LOGIN_USERNAME:
_index = MIDDLEWARE.index('django.contrib.auth.middleware.AuthenticationMiddleware')
_index = MIDDLEWARE.index("django.contrib.auth.middleware.AuthenticationMiddleware")
# This overrides everything the auth middleware is doing but still allows
# regular login in case the provided user does not exist.
MIDDLEWARE.insert(_index+1, 'paperless.auth.AutoLoginMiddleware')
MIDDLEWARE.insert(_index + 1, "paperless.auth.AutoLoginMiddleware")
ENABLE_HTTP_REMOTE_USER = __get_boolean("PAPERLESS_ENABLE_HTTP_REMOTE_USER")
HTTP_REMOTE_USER_HEADER_NAME = os.getenv("PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME", "HTTP_REMOTE_USER")
HTTP_REMOTE_USER_HEADER_NAME = os.getenv(
"PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME", "HTTP_REMOTE_USER"
)
if ENABLE_HTTP_REMOTE_USER:
MIDDLEWARE.append(
'paperless.auth.HttpRemoteUserMiddleware'
)
MIDDLEWARE.append("paperless.auth.HttpRemoteUserMiddleware")
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.RemoteUserBackend',
'django.contrib.auth.backends.ModelBackend'
"django.contrib.auth.backends.RemoteUserBackend",
"django.contrib.auth.backends.ModelBackend",
]
REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'].append(
'rest_framework.authentication.RemoteUserAuthentication'
REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"].append(
"rest_framework.authentication.RemoteUserAuthentication"
)
# X-Frame options for embedded PDF display:
if DEBUG:
X_FRAME_OPTIONS = 'ANY'
X_FRAME_OPTIONS = "ANY"
else:
X_FRAME_OPTIONS = 'SAMEORIGIN'
X_FRAME_OPTIONS = "SAMEORIGIN"
# We allow CORS from localhost:8080
CORS_ALLOWED_ORIGINS = tuple(os.getenv("PAPERLESS_CORS_ALLOWED_HOSTS", "http://localhost:8000").split(","))
CORS_ALLOWED_ORIGINS = tuple(
os.getenv("PAPERLESS_CORS_ALLOWED_HOSTS", "http://localhost:8000").split(",")
)
if DEBUG:
# Allow access from the angular development server during debugging
CORS_ALLOWED_ORIGINS += ('http://localhost:4200',)
CORS_ALLOWED_ORIGINS += ("http://localhost:4200",)
# The secret key has a default that should be fine so long as you're hosting
# Paperless on a closed network. However, if you're putting this anywhere
# public, you should change the key to something unique and verbose.
SECRET_KEY = os.getenv(
"PAPERLESS_SECRET_KEY",
"e11fl1oa-*ytql8p)(06fbj4ukrlo+n7k&q5+$1md7i+mge=ee"
"PAPERLESS_SECRET_KEY", "e11fl1oa-*ytql8p)(06fbj4ukrlo+n7k&q5+$1md7i+mge=ee"
)
_allowed_hosts = os.getenv("PAPERLESS_ALLOWED_HOSTS")
@@ -238,16 +234,16 @@ else:
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
@@ -271,17 +267,14 @@ LANGUAGE_COOKIE_NAME = f"{COOKIE_PREFIX}django_language"
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.path.join(
DATA_DIR,
"db.sqlite3"
)
"NAME": os.path.join(DATA_DIR, "db.sqlite3"),
}
}
if os.getenv("PAPERLESS_DBHOST"):
# Have sqlite available as a second option for management commands
# This is important when migrating to/from sqlite
DATABASES['sqlite'] = DATABASES['default'].copy()
DATABASES["sqlite"] = DATABASES["default"].copy()
DATABASES["default"] = {
"ENGINE": "django.db.backends.postgresql_psycopg2",
@@ -289,21 +282,21 @@ if os.getenv("PAPERLESS_DBHOST"):
"NAME": os.getenv("PAPERLESS_DBNAME", "paperless"),
"USER": os.getenv("PAPERLESS_DBUSER", "paperless"),
"PASSWORD": os.getenv("PAPERLESS_DBPASS", "paperless"),
'OPTIONS': {'sslmode': os.getenv("PAPERLESS_DBSSLMODE", "prefer")},
"OPTIONS": {"sslmode": os.getenv("PAPERLESS_DBSSLMODE", "prefer")},
}
if os.getenv("PAPERLESS_DBPORT"):
DATABASES["default"]["PORT"] = os.getenv("PAPERLESS_DBPORT")
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
###############################################################################
# Internationalization #
###############################################################################
LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = "en-us"
LANGUAGES = [
("en-us", _("English (US)")), # needs to be first to act as fallback language
("en-us", _("English (US)")), # needs to be first to act as fallback language
("cs-cz", _("Czech")),
("da-dk", _("Danish")),
("de-de", _("German")),
@@ -321,9 +314,7 @@ LANGUAGES = [
("sv-se", _("Swedish")),
]
LOCALE_PATHS = [
os.path.join(BASE_DIR, "locale")
]
LOCALE_PATHS = [os.path.join(BASE_DIR, "locale")]
TIME_ZONE = os.getenv("PAPERLESS_TIME_ZONE", "UTC")
@@ -341,20 +332,20 @@ setup_logging_queues()
os.makedirs(LOGGING_DIR, exist_ok=True)
LOGROTATE_MAX_SIZE = os.getenv("PAPERLESS_LOGROTATE_MAX_SIZE", 1024*1024)
LOGROTATE_MAX_SIZE = os.getenv("PAPERLESS_LOGROTATE_MAX_SIZE", 1024 * 1024)
LOGROTATE_MAX_BACKUPS = os.getenv("PAPERLESS_LOGROTATE_MAX_BACKUPS", 20)
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
'formatters': {
'verbose': {
'format': '[{asctime}] [{levelname}] [{name}] {message}',
'style': '{',
"formatters": {
"verbose": {
"format": "[{asctime}] [{levelname}] [{name}] {message}",
"style": "{",
},
'simple': {
'format': '{levelname} {message}',
'style': '{',
"simple": {
"format": "{levelname} {message}",
"style": "{",
},
},
"handlers": {
@@ -368,29 +359,21 @@ LOGGING = {
"formatter": "verbose",
"filename": os.path.join(LOGGING_DIR, "paperless.log"),
"maxBytes": LOGROTATE_MAX_SIZE,
"backupCount": LOGROTATE_MAX_BACKUPS
"backupCount": LOGROTATE_MAX_BACKUPS,
},
"file_mail": {
"class": "concurrent_log_handler.ConcurrentRotatingFileHandler",
"formatter": "verbose",
"filename": os.path.join(LOGGING_DIR, "mail.log"),
"maxBytes": LOGROTATE_MAX_SIZE,
"backupCount": LOGROTATE_MAX_BACKUPS
}
},
"root": {
"handlers": ["console"]
},
"loggers": {
"paperless": {
"handlers": ["file_paperless"],
"level": "DEBUG"
"backupCount": LOGROTATE_MAX_BACKUPS,
},
"paperless_mail": {
"handlers": ["file_mail"],
"level": "DEBUG"
}
}
},
"root": {"handlers": ["console"]},
"loggers": {
"paperless": {"handlers": ["file_paperless"], "level": "DEBUG"},
"paperless_mail": {"handlers": ["file_mail"], "level": "DEBUG"},
},
}
###############################################################################
@@ -412,10 +395,7 @@ def default_task_workers():
try:
if available_cores < 4:
return available_cores
return max(
math.floor(math.sqrt(available_cores)),
1
)
return max(math.floor(math.sqrt(available_cores)), 1)
except NotImplementedError:
return 1
@@ -423,13 +403,13 @@ def default_task_workers():
TASK_WORKERS = int(os.getenv("PAPERLESS_TASK_WORKERS", default_task_workers()))
Q_CLUSTER = {
'name': 'paperless',
'catch_up': False,
'recycle': 1,
'retry': 1800,
'timeout': int(os.getenv("PAPERLESS_WORKER_TIMEOUT", 1800)),
'workers': TASK_WORKERS,
'redis': os.getenv("PAPERLESS_REDIS", "redis://localhost:6379")
"name": "paperless",
"catch_up": False,
"recycle": 1,
"retry": 1800,
"timeout": int(os.getenv("PAPERLESS_WORKER_TIMEOUT", 1800)),
"workers": TASK_WORKERS,
"redis": os.getenv("PAPERLESS_REDIS", "redis://localhost:6379"),
}
@@ -437,15 +417,14 @@ def default_threads_per_worker(task_workers):
# always leave one core open
available_cores = max(multiprocessing.cpu_count(), 1)
try:
return max(
math.floor(available_cores / task_workers),
1
)
return max(math.floor(available_cores / task_workers), 1)
except NotImplementedError:
return 1
THREADS_PER_WORKER = os.getenv("PAPERLESS_THREADS_PER_WORKER", default_threads_per_worker(TASK_WORKERS))
THREADS_PER_WORKER = os.getenv(
"PAPERLESS_THREADS_PER_WORKER", default_threads_per_worker(TASK_WORKERS)
)
###############################################################################
# Paperless Specific Settings #
@@ -466,14 +445,18 @@ CONSUMER_RECURSIVE = __get_boolean("PAPERLESS_CONSUMER_RECURSIVE")
# Ignore glob patterns, relative to PAPERLESS_CONSUMPTION_DIR
CONSUMER_IGNORE_PATTERNS = list(
json.loads(
os.getenv("PAPERLESS_CONSUMER_IGNORE_PATTERNS",
'[".DS_STORE/*", "._*", ".stfolder/*"]')))
os.getenv(
"PAPERLESS_CONSUMER_IGNORE_PATTERNS",
'[".DS_STORE/*", "._*", ".stfolder/*"]',
)
)
)
CONSUMER_SUBDIRS_AS_TAGS = __get_boolean("PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS")
OPTIMIZE_THUMBNAILS = __get_boolean("PAPERLESS_OPTIMIZE_THUMBNAILS", "true")
OCR_PAGES = int(os.getenv('PAPERLESS_OCR_PAGES', 0))
OCR_PAGES = int(os.getenv("PAPERLESS_OCR_PAGES", 0))
# The default language that tesseract will attempt to use when parsing
# documents. It should be a 3-letter language code consistent with ISO 639.
@@ -495,7 +478,9 @@ OCR_DESKEW = __get_boolean("PAPERLESS_OCR_DESKEW", "true")
OCR_ROTATE_PAGES = __get_boolean("PAPERLESS_OCR_ROTATE_PAGES", "true")
OCR_ROTATE_PAGES_THRESHOLD = float(os.getenv("PAPERLESS_OCR_ROTATE_PAGES_THRESHOLD", 12.0))
OCR_ROTATE_PAGES_THRESHOLD = float(
os.getenv("PAPERLESS_OCR_ROTATE_PAGES_THRESHOLD", 12.0)
)
OCR_USER_ARGS = os.getenv("PAPERLESS_OCR_USER_ARGS", "{}")
@@ -542,7 +527,10 @@ for t in json.loads(os.getenv("PAPERLESS_FILENAME_PARSE_TRANSFORMS", "[]")):
# Specify the filename format for out files
PAPERLESS_FILENAME_FORMAT = os.getenv("PAPERLESS_FILENAME_FORMAT")
THUMBNAIL_FONT_NAME = os.getenv("PAPERLESS_THUMBNAIL_FONT_NAME", "/usr/share/fonts/liberation/LiberationSerif-Regular.ttf")
THUMBNAIL_FONT_NAME = os.getenv(
"PAPERLESS_THUMBNAIL_FONT_NAME",
"/usr/share/fonts/liberation/LiberationSerif-Regular.ttf",
)
# Tika settings
PAPERLESS_TIKA_ENABLED = __get_boolean("PAPERLESS_TIKA_ENABLED", "NO")

View File

@@ -9,7 +9,6 @@ from paperless.checks import debug_mode_check
class TestChecks(DirectoriesMixin, TestCase):
def test_binaries(self):
self.assertEqual(binaries_check(None), [])
@@ -20,9 +19,9 @@ class TestChecks(DirectoriesMixin, TestCase):
def test_paths_check(self):
self.assertEqual(paths_check(None), [])
@override_settings(MEDIA_ROOT="uuh",
DATA_DIR="whatever",
CONSUMPTION_DIR="idontcare")
@override_settings(
MEDIA_ROOT="uuh", DATA_DIR="whatever", CONSUMPTION_DIR="idontcare"
)
def test_paths_check_dont_exist(self):
msgs = paths_check(None)
self.assertEqual(len(msgs), 3, str(msgs))

View File

@@ -8,14 +8,13 @@ from paperless.asgi import application
TEST_CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels.layers.InMemoryChannelLayer',
"default": {
"BACKEND": "channels.layers.InMemoryChannelLayer",
},
}
class TestWebSockets(TestCase):
@override_settings(CHANNEL_LAYERS=TEST_CHANNEL_LAYERS)
async def test_no_auth(self):
communicator = WebsocketCommunicator(application, "/ws/status/")
@@ -43,15 +42,12 @@ class TestWebSockets(TestCase):
connected, subprotocol = await communicator.connect()
self.assertTrue(connected)
message = {
"task_id": "test"
}
message = {"task_id": "test"}
channel_layer = get_channel_layer()
await channel_layer.group_send("status_updates", {
"type": "status_update",
"data": message
})
await channel_layer.group_send(
"status_updates", {"type": "status_update", "data": message}
)
response = await communicator.receive_json_from()

View File

@@ -25,7 +25,7 @@ from documents.views import (
SavedViewViewSet,
BulkEditView,
SelectionDataView,
BulkDownloadView
BulkDownloadView,
)
from paperless.views import FaviconView
@@ -39,82 +39,101 @@ api_router.register(r"saved_views", SavedViewViewSet)
urlpatterns = [
re_path(r"^api/", include([
re_path(r"^auth/",
include(('rest_framework.urls', 'rest_framework'),
namespace="rest_framework")),
re_path(r"^search/autocomplete/",
SearchAutoCompleteView.as_view(),
name="autocomplete"),
re_path(r"^statistics/",
StatisticsView.as_view(),
name="statistics"),
re_path(r"^documents/post_document/", PostDocumentView.as_view(),
name="post_document"),
re_path(r"^documents/bulk_edit/", BulkEditView.as_view(),
name="bulk_edit"),
re_path(r"^documents/selection_data/", SelectionDataView.as_view(),
name="selection_data"),
re_path(r"^documents/bulk_download/", BulkDownloadView.as_view(),
name="bulk_download"),
path('token/', views.obtain_auth_token)
] + api_router.urls)),
re_path(
r"^api/",
include(
[
re_path(
r"^auth/",
include(
("rest_framework.urls", "rest_framework"),
namespace="rest_framework",
),
),
re_path(
r"^search/autocomplete/",
SearchAutoCompleteView.as_view(),
name="autocomplete",
),
re_path(r"^statistics/", StatisticsView.as_view(), name="statistics"),
re_path(
r"^documents/post_document/",
PostDocumentView.as_view(),
name="post_document",
),
re_path(
r"^documents/bulk_edit/", BulkEditView.as_view(), name="bulk_edit"
),
re_path(
r"^documents/selection_data/",
SelectionDataView.as_view(),
name="selection_data",
),
re_path(
r"^documents/bulk_download/",
BulkDownloadView.as_view(),
name="bulk_download",
),
path("token/", views.obtain_auth_token),
]
+ api_router.urls
),
),
re_path(r"^favicon.ico$", FaviconView.as_view(), name="favicon"),
re_path(r"admin/", admin.site.urls),
re_path(r"^fetch/", include([
re_path(
r"^doc/(?P<pk>\d+)$",
RedirectView.as_view(url=settings.BASE_URL +
'api/documents/%(pk)s/download/'),
re_path(
r"^fetch/",
include(
[
re_path(
r"^doc/(?P<pk>\d+)$",
RedirectView.as_view(
url=settings.BASE_URL + "api/documents/%(pk)s/download/"
),
),
re_path(
r"^thumb/(?P<pk>\d+)$",
RedirectView.as_view(
url=settings.BASE_URL + "api/documents/%(pk)s/thumb/"
),
),
re_path(
r"^preview/(?P<pk>\d+)$",
RedirectView.as_view(
url=settings.BASE_URL + "api/documents/%(pk)s/preview/"
),
),
]
),
re_path(
r"^thumb/(?P<pk>\d+)$",
RedirectView.as_view(url=settings.BASE_URL +
'api/documents/%(pk)s/thumb/'),
),
re_path(
r"^push$",
csrf_exempt(
RedirectView.as_view(url=settings.BASE_URL + "api/documents/post_document/")
),
re_path(
r"^preview/(?P<pk>\d+)$",
RedirectView.as_view(url=settings.BASE_URL +
'api/documents/%(pk)s/preview/'),
),
])),
re_path(r"^push$", csrf_exempt(
RedirectView.as_view(url=settings.BASE_URL +
'api/documents/post_document/'))),
),
# Frontend assets TODO: this is pretty bad, but it works.
path('assets/<path:path>',
RedirectView.as_view(url=settings.STATIC_URL +
'frontend/en-US/assets/%(path)s')),
path(
"assets/<path:path>",
RedirectView.as_view(
url=settings.STATIC_URL + "frontend/en-US/assets/%(path)s"
),
),
# TODO: with localization, this is even worse! :/
# login, logout
path('accounts/', include('django.contrib.auth.urls')),
path("accounts/", include("django.contrib.auth.urls")),
# Root of the Frontent
re_path(r".*", login_required(IndexView.as_view()), name='base'),
re_path(r".*", login_required(IndexView.as_view()), name="base"),
]
websocket_urlpatterns = [
re_path(r'ws/status/$', StatusConsumer.as_asgi()),
re_path(r"ws/status/$", StatusConsumer.as_asgi()),
]
# Text in each page's <h1> (and above login form).
admin.site.site_header = 'Paperless-ng'
admin.site.site_header = "Paperless-ng"
# Text at the end of each page's <title>.
admin.site.site_title = 'Paperless-ng'
admin.site.site_title = "Paperless-ng"
# Text at the top of the admin index page.
admin.site.index_title = _('Paperless-ng administration')
admin.site.index_title = _("Paperless-ng administration")

View File

@@ -12,14 +12,9 @@ class StandardPagination(PageNumberPagination):
class FaviconView(View):
def get(self, request, *args, **kwargs):
favicon = os.path.join(
os.path.dirname(__file__),
"static",
"paperless",
"img",
"favicon.ico"
os.path.dirname(__file__), "static", "paperless", "img", "favicon.ico"
)
with open(favicon, "rb") as f:
return HttpResponse(f, content_type="image/x-icon")