diff --git a/Makefile b/Makefile index bf1d87e9..d628746a 100644 --- a/Makefile +++ b/Makefile @@ -63,13 +63,15 @@ test: #: format - Run the PEP8 formatter. .PHONY: format format: - ruff format helpdesk + ruff check --fix # Fix linting errors + ruff format # fix formatting errors #: checkformat - checks formatting against configured format specifications for the project. .PHONY: checkformat checkformat: - ruff check helpdesk + ruff check # linting check + ruff format --check # format check #: documentation - Build documentation (Sphinx, README, ...). diff --git a/demo/demodesk/config/settings.py b/demo/demodesk/config/settings.py index 6e99d4f0..ec7ebe42 100644 --- a/demo/demodesk/config/settings.py +++ b/demo/demodesk/config/settings.py @@ -14,7 +14,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = '_crkn1+fnzu5$vns_-d+^ayiq%z4k*s!!ag0!mfy36(y!vrazd' +SECRET_KEY = "_crkn1+fnzu5$vns_-d+^ayiq%z4k*s!!ag0!mfy36(y!vrazd" # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True @@ -25,69 +25,73 @@ ALLOWED_HOSTS = [] # to use HTTPS with secure cookies, then you'd want to set # the following settings: # -#SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') -#SESSION_COOKIE_SECURE = True -#CSRF_COOKIE_SECURE = True +# SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +# SESSION_COOKIE_SECURE = True +# CSRF_COOKIE_SECURE = True # # We leave them commented out here because most likely for # an internal demo you don't need such security, but please # remember when setting up your own development / production server! # Default teams mode to enabled unless overridden by an environment variable set to "false" -HELPDESK_TEAMS_MODE_ENABLED=os.getenv("HELPDESK_TEAMS_MODE_ENABLED", "true").lower() == "true" +HELPDESK_TEAMS_MODE_ENABLED = ( + os.getenv("HELPDESK_TEAMS_MODE_ENABLED", "true").lower() == "true" +) # Application definition INSTALLED_APPS = [ - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'django.contrib.sites', - 'django.contrib.humanize', - 'bootstrap4form', - 'helpdesk', # This is us! - 'rest_framework', # required for the API + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.sites", + "django.contrib.humanize", + "bootstrap4form", + "helpdesk", # This is us! + "rest_framework", # required for the API ] if HELPDESK_TEAMS_MODE_ENABLED: - INSTALLED_APPS.extend([ - 'account', # Required by pinax-teams - 'pinax.invitations', # required by pinax-teams - 'pinax.teams', # team support - 'reversion', # required by pinax-teams - ]) + INSTALLED_APPS.extend( + [ + "account", # Required by pinax-teams + "pinax.invitations", # required by pinax-teams + "pinax.teams", # team support + "reversion", # required by pinax-teams + ] + ) 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', + "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 = 'demodesk.config.urls' +ROOT_URLCONF = "demodesk.config.urls" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'debug': True, - '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": { + "debug": True, + "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 = 'demodesk.config.wsgi.application' +WSGI_APPLICATION = "demodesk.config.wsgi.application" # django-helpdesk configuration settings @@ -97,13 +101,13 @@ WSGI_APPLICATION = 'demodesk.config.wsgi.application' # Some common settings are below. HELPDESK_DEFAULT_SETTINGS = { - 'use_email_as_submitter': True, - 'email_on_ticket_assign': True, - 'email_on_ticket_change': True, - 'login_view_ticketlist': True, - 'email_on_ticket_apichange': True, - 'preset_replies': True, - 'tickets_per_page': 25 + "use_email_as_submitter": True, + "email_on_ticket_assign": True, + "email_on_ticket_change": True, + "login_view_ticketlist": True, + "email_on_ticket_apichange": True, + "preset_replies": True, + "tickets_per_page": 25, } # Should the public web portal be enabled? @@ -122,8 +126,8 @@ HELPDESK_SHOW_CHANGE_PASSWORD = True # Instead of showing the public web portal first, # we can instead redirect users straight to the login page. HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT = False -LOGIN_URL = 'helpdesk:login' -LOGIN_REDIRECT_URL = 'helpdesk:home' +LOGIN_URL = "helpdesk:login" +LOGIN_REDIRECT_URL = "helpdesk:home" # You can also redirect to a specific page after logging out (instead of logout page) # LOGOUT_REDIRECT_URL = 'helpdesk:home' @@ -133,9 +137,9 @@ LOGIN_REDIRECT_URL = 'helpdesk:home' # https://docs.djangoproject.com/en/1.11/ref/settings/#databases DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": os.path.join(BASE_DIR, "db.sqlite3"), } } @@ -156,10 +160,10 @@ SESSION_COOKIE_AGE = 86400 # = 1 day # For better default security, set these cookie flags, but # these are likely to cause problems when testing locally -#CSRF_COOKIE_SECURE = True -#SESSION_COOKIE_SECURE = True -#CSRF_COOKIE_HTTPONLY = True -#SESSION_COOKIE_HTTPONLY = True +# CSRF_COOKIE_SECURE = True +# SESSION_COOKIE_SECURE = True +# CSRF_COOKIE_HTTPONLY = True +# SESSION_COOKIE_HTTPONLY = True # Password validation @@ -167,16 +171,16 @@ SESSION_COOKIE_AGE = 86400 # = 1 day 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", }, ] @@ -185,14 +189,14 @@ AUTH_PASSWORD_VALIDATORS = [ # This demo uses the console backend, which simply prints emails to the console # rather than actually sending them out. -DEFAULT_FROM_EMAIL = 'helpdesk@example.com' -SERVER_EMAIL = 'helpdesk@example.com' -EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' +DEFAULT_FROM_EMAIL = "helpdesk@example.com" +SERVER_EMAIL = "helpdesk@example.com" +EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" # If you want to test sending real emails, uncomment and modify the following: -#EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' -#EMAIL_HOST = 'smtp.example.com' -#EMAIL_PORT = '25' +# EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +# EMAIL_HOST = 'smtp.example.com' +# EMAIL_PORT = '25' # Internationalization # https://docs.djangoproject.com/en/1.11/topics/i18n/ @@ -201,9 +205,9 @@ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' # The most complete translations are: es-MX, ru, zh-Hans # Contribute to our translations via Transifex if you can! # See CONTRIBUTING.rst for more info. -LANGUAGE_CODE = 'en-US' +LANGUAGE_CODE = "en-US" -TIME_ZONE = 'UTC' +TIME_ZONE = "UTC" USE_I18N = True @@ -215,27 +219,27 @@ USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.11/howto/static-files/ -STATIC_URL = '/static/' +STATIC_URL = "/static/" # static root needs to be defined in order to use collectstatic -STATIC_ROOT = os.path.join(BASE_DIR, 'static') +STATIC_ROOT = os.path.join(BASE_DIR, "static") # MEDIA_ROOT is where media uploads are stored. # We set this to a directory to host file attachments created # with tickets. -MEDIA_URL = '/media/' -MEDIA_ROOT = os.path.join(BASE_DIR, 'media') +MEDIA_URL = "/media/" +MEDIA_ROOT = os.path.join(BASE_DIR, "media") # Fixtures # https://docs.djangoproject.com/en/1.11/ref/settings/#std:setting-FIXTURE_DIRS # - This is only necessary to make the demo project work, not needed for # your own projects unless you make your own fixtures -FIXTURE_DIRS = [os.path.join(BASE_DIR, 'fixtures')] +FIXTURE_DIRS = [os.path.join(BASE_DIR, "fixtures")] # for Django 3.2+, set default for autofields: -DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' +DEFAULT_AUTO_FIELD = "django.db.models.AutoField" try: - from .local_settings import * + from .local_settings import * # noqa except ImportError: pass diff --git a/demo/demodesk/config/urls.py b/demo/demodesk/config/urls.py index 2fb2a3d7..c8d7f521 100644 --- a/demo/demodesk/config/urls.py +++ b/demo/demodesk/config/urls.py @@ -13,6 +13,7 @@ Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ + from django.conf import settings from django.conf.urls.static import static from django.contrib import admin @@ -26,7 +27,7 @@ from django.urls import include, path # https://docs.djangoproject.com/en/1.10/howto/static-files/ urlpatterns = [ - path('admin/', admin.site.urls), - path('', include('helpdesk.urls', namespace='helpdesk')), - path('api/auth/', include('rest_framework.urls', namespace='rest_framework')) + path("admin/", admin.site.urls), + path("", include("helpdesk.urls", namespace="helpdesk")), + path("api/auth/", include("rest_framework.urls", namespace="rest_framework")), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/demo/demodesk/config/wsgi.py b/demo/demodesk/config/wsgi.py index 3fb82a46..cfe4442e 100644 --- a/demo/demodesk/config/wsgi.py +++ b/demo/demodesk/config/wsgi.py @@ -7,7 +7,6 @@ For more information on this file, see https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/ """ - from django.core.wsgi import get_wsgi_application import os diff --git a/demo/demodesk/manage.py b/demo/demodesk/manage.py index 0bc07500..7ec51f99 100755 --- a/demo/demodesk/manage.py +++ b/demo/demodesk/manage.py @@ -12,7 +12,7 @@ def main(): # issue is really that Django is missing to avoid masking other # exceptions on Python 2. try: - import django + import django # noqa except ImportError: raise ImportError( "Couldn't import Django. Are you sure it's installed and " diff --git a/demo/manage.py b/demo/manage.py index 0bc07500..7ec51f99 100755 --- a/demo/manage.py +++ b/demo/manage.py @@ -12,7 +12,7 @@ def main(): # issue is really that Django is missing to avoid masking other # exceptions on Python 2. try: - import django + import django # noqa except ImportError: raise ImportError( "Couldn't import Django. Are you sure it's installed and " diff --git a/demo/setup.py b/demo/setup.py index b3e8e6ea..fbded55f 100644 --- a/demo/setup.py +++ b/demo/setup.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- """Python packaging.""" + import os from setuptools import setup @@ -8,42 +9,42 @@ here = os.path.abspath(os.path.dirname(__file__)) project_root = os.path.dirname(here) -NAME = 'django-helpdesk-demodesk' -DESCRIPTION = 'A demo Django project using django-helpdesk' -README = open(os.path.join(here, 'README.rst')).read() -VERSION = '0.5.0' -#VERSION = open(os.path.join(project_root, 'VERSION')).read().strip() -AUTHOR = 'django-helpdesk team' -URL = 'https://github.com/django-helpdesk/django-helpdesk' -CLASSIFIERS = ['Development Status :: 4 - Beta', - 'License :: OSI Approved :: BSD License', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Framework :: Django :: 3.2', - 'Framework :: Django :: 4.0'] -KEYWORDS = [] -PACKAGES = ['demodesk'] -REQUIREMENTS = [ - 'django-helpdesk' +NAME = "django-helpdesk-demodesk" +DESCRIPTION = "A demo Django project using django-helpdesk" +README = open(os.path.join(here, "README.rst")).read() +VERSION = "0.5.0" +# VERSION = open(os.path.join(project_root, 'VERSION')).read().strip() +AUTHOR = "django-helpdesk team" +URL = "https://github.com/django-helpdesk/django-helpdesk" +CLASSIFIERS = [ + "Development Status :: 4 - Beta", + "License :: OSI Approved :: BSD License", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Framework :: Django :: 3.2", + "Framework :: Django :: 4.0", ] -ENTRY_POINTS = { - 'console_scripts': ['demodesk = demodesk.manage:main'] -} +KEYWORDS = [] +PACKAGES = ["demodesk"] +REQUIREMENTS = ["django-helpdesk"] +ENTRY_POINTS = {"console_scripts": ["demodesk = demodesk.manage:main"]} -if __name__ == '__main__': # Don't run setup() when we import this module. - setup(name=NAME, - version=VERSION, - description=DESCRIPTION, - long_description=README, - classifiers=CLASSIFIERS, - keywords=' '.join(KEYWORDS), - author=AUTHOR, - url=URL, - license='BSD', - packages=PACKAGES, - include_package_data=True, - zip_safe=False, - install_requires=REQUIREMENTS, - entry_points=ENTRY_POINTS) +if __name__ == "__main__": # Don't run setup() when we import this module. + setup( + name=NAME, + version=VERSION, + description=DESCRIPTION, + long_description=README, + classifiers=CLASSIFIERS, + keywords=" ".join(KEYWORDS), + author=AUTHOR, + url=URL, + license="BSD", + packages=PACKAGES, + include_package_data=True, + zip_safe=False, + install_requires=REQUIREMENTS, + entry_points=ENTRY_POINTS, + ) diff --git a/docs/conf.py b/docs/conf.py index b3adfb08..01070afb 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -11,201 +11,203 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import os -import sys - # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) +# sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = u'django-helpdesk' -copyright = u'2011-2023, Django-helpdesk Contributors' +project = "django-helpdesk" +copyright = "2011-2023, Django-helpdesk Contributors" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '1.x' +version = "1.x" # The full version, including alpha/beta/rc tags. -release = '1.x' +release = "1.x" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -#language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'default' +html_theme = "default" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'django-helpdeskdoc' +htmlhelp_basename = "django-helpdeskdoc" # -- Options for LaTeX output -------------------------------------------- # The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' +# latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' +# latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'django-helpdesk.tex', u'django-helpdesk Documentation', - u'django-helpdesk Contributors', 'manual'), + ( + "index", + "django-helpdesk.tex", + "django-helpdesk Documentation", + "django-helpdesk Contributors", + "manual", + ), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Additional stuff for the LaTeX preamble. -#latex_preamble = '' +# latex_preamble = '' # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output -------------------------------------- @@ -213,6 +215,11 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'django-helpdesk', u'django-helpdesk Documentation', - [u'django-helpdesk Contributors'], 1) + ( + "index", + "django-helpdesk", + "django-helpdesk Documentation", + ["django-helpdesk Contributors"], + 1, + ) ] diff --git a/helpdesk/email.py b/helpdesk/email.py index 893859a7..046bc72f 100644 --- a/helpdesk/email.py +++ b/helpdesk/email.py @@ -442,7 +442,8 @@ def process_queue(q, logger): q.email_box_port = mail_defaults[email_box_type][encryption]["port"] server = mail_defaults[email_box_type][encryption]["init"]( - q.email_box_host or helpdesk_settings.QUEUE_EMAIL_BOX_HOST, int(q.email_box_port) + q.email_box_host or helpdesk_settings.QUEUE_EMAIL_BOX_HOST, + int(q.email_box_port), ) logger.info("Attempting %s server login" % email_box_type.upper()) mail_defaults[email_box_type]["sync"](q, logger, server) diff --git a/helpdesk/migrations/0002_populate_usersettings.py b/helpdesk/migrations/0002_populate_usersettings.py index 4dfd8d7e..98cf4e1c 100644 --- a/helpdesk/migrations/0002_populate_usersettings.py +++ b/helpdesk/migrations/0002_populate_usersettings.py @@ -37,7 +37,8 @@ def populate_usersettings(apps, schema_editor): UserSettings.objects.create(user=u, settings_pickled=settings_pickled) -noop = lambda *args, **kwargs: None +def noop(*args, **kwargs): + return None class Migration(migrations.Migration): diff --git a/helpdesk/query.py b/helpdesk/query.py index e2681927..cfe24ba5 100644 --- a/helpdesk/query.py +++ b/helpdesk/query.py @@ -41,16 +41,16 @@ def get_search_filter_args(search): if not subsearch: continue my_filter |= ( - Q(id__icontains=subsearch) | - Q(title__icontains=subsearch) | - Q(description__icontains=subsearch) | - Q(priority__icontains=subsearch) | - Q(resolution__icontains=subsearch) | - Q(submitter_email__icontains=subsearch) | - Q(assigned_to__email__icontains=subsearch) | - Q(ticketcustomfieldvalue__value__icontains=subsearch) | - Q(created__icontains=subsearch) | - Q(due_date__icontains=subsearch) + Q(id__icontains=subsearch) + | Q(title__icontains=subsearch) + | Q(description__icontains=subsearch) + | Q(priority__icontains=subsearch) + | Q(resolution__icontains=subsearch) + | Q(submitter_email__icontains=subsearch) + | Q(assigned_to__email__icontains=subsearch) + | Q(ticketcustomfieldvalue__value__icontains=subsearch) + | Q(created__icontains=subsearch) + | Q(due_date__icontains=subsearch) ) return my_filter diff --git a/helpdesk/settings.py b/helpdesk/settings.py index 8f4e904d..426cf1dd 100644 --- a/helpdesk/settings.py +++ b/helpdesk/settings.py @@ -49,11 +49,15 @@ HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT = getattr( ) HELPDESK_PUBLIC_VIEW_PROTECTOR = getattr( - settings, "HELPDESK_PUBLIC_VIEW_PROTECTOR", lambda _: None + settings, + "HELPDESK_PUBLIC_VIEW_PROTECTOR", + lambda _: None, # noqa ) HELPDESK_STAFF_VIEW_PROTECTOR = getattr( - settings, "HELPDESK_STAFF_VIEW_PROTECTOR", lambda _: None + settings, + "HELPDESK_STAFF_VIEW_PROTECTOR", + lambda _: None, # noqa ) # Enable ticket and Email attachments @@ -390,7 +394,7 @@ if HELPDESK_TEAMS_MODE_ENABLED: else: HELPDESK_TEAMS_MODEL = settings.AUTH_USER_MODEL HELPDESK_TEAMS_MIGRATION_DEPENDENCIES = [] - HELPDESK_KBITEM_TEAM_GETTER = lambda _: None + HELPDESK_KBITEM_TEAM_GETTER = lambda _: None # noqa # show knowledgebase links? # If Teams mode is enabled then it has to be on diff --git a/helpdesk/tests/test_get_email.py b/helpdesk/tests/test_get_email.py index 35d8bf43..7d225f5b 100644 --- a/helpdesk/tests/test_get_email.py +++ b/helpdesk/tests/test_get_email.py @@ -512,8 +512,7 @@ class GetEmailCommonTests(TestCase): ticket = helpdesk.email.extract_email_metadata( message.as_string(), self.queue_public, self.logger ) - self.assertIsNone(ticket, f"Ticket was created when it should not be: {ticket}" - ) + self.assertIsNone(ticket, f"Ticket was created when it should not be: {ticket}") class EmailTaskTests(TestCase): diff --git a/pyproject.toml b/pyproject.toml index 5a18348a..8f993590 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,3 @@ [tool.ruff] [tool.ruff.lint] -ignore = ["E501", "E731", "E721"] +ignore = [] diff --git a/quicktest.py b/quicktest.py index 901ac63a..f905d85a 100755 --- a/quicktest.py +++ b/quicktest.py @@ -25,42 +25,43 @@ class QuickDjangoTest: Based on a script published by Lukasz Dziedzia at: http://stackoverflow.com/questions/3841725/how-to-launch-tests-for-django-reusable-app """ + DIRNAME = os.path.dirname(__file__) INSTALLED_APPS = ( - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.humanize', - 'django.contrib.messages', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.staticfiles', - 'bootstrap4form', + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.humanize", + "django.contrib.messages", + "django.contrib.sessions", + "django.contrib.sites", + "django.contrib.staticfiles", + "bootstrap4form", # The following commented apps are optional, # related to teams functionalities # 'account', # 'pinax.invitations', # 'pinax.teams', - 'rest_framework', - 'helpdesk', + "rest_framework", + "helpdesk", # 'reversion', ) 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', + "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", ] TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': ( + "BACKEND": "django.template.backends.django.DjangoTemplates", + "APP_DIRS": True, + "OPTIONS": { + "context_processors": ( # Defaults: "django.contrib.auth.context_processors.auth", "django.template.context_processors.debug", @@ -82,37 +83,39 @@ class QuickDjangoTest: self._tests() def _tests(self): - settings.configure( DEBUG=True, - TIME_ZONE='UTC', + TIME_ZONE="UTC", DATABASES={ - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(self.DIRNAME, 'database.db'), - 'USER': '', - 'PASSWORD': '', - 'HOST': '', - 'PORT': '', + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": os.path.join(self.DIRNAME, "database.db"), + "USER": "", + "PASSWORD": "", + "HOST": "", + "PORT": "", } }, INSTALLED_APPS=self.INSTALLED_APPS, MIDDLEWARE=self.MIDDLEWARE, - ROOT_URLCONF='helpdesk.tests.urls', - STATIC_URL='/static/', - LOGIN_URL='/login/', + ROOT_URLCONF="helpdesk.tests.urls", + STATIC_URL="/static/", + LOGIN_URL="/login/", TEMPLATES=self.TEMPLATES, SITE_ID=1, - SECRET_KEY='wowdonotusethisfakesecuritykeyyouneedarealsecure1', + SECRET_KEY="wowdonotusethisfakesecuritykeyyouneedarealsecure1", # The following settings disable teams - HELPDESK_TEAMS_MODEL='auth.User', + HELPDESK_TEAMS_MODEL="auth.User", HELPDESK_TEAMS_MIGRATION_DEPENDENCIES=[], HELPDESK_KBITEM_TEAM_GETTER=lambda _: None, # Set IMAP Server Debug Verbosity - HELPDESK_IMAP_DEBUG_LEVEL=int(os.environ.get("HELPDESK_IMAP_DEBUG_LEVEL", "0")), + HELPDESK_IMAP_DEBUG_LEVEL=int( + os.environ.get("HELPDESK_IMAP_DEBUG_LEVEL", "0") + ), ) from django.test.runner import DiscoverRunner + test_runner = DiscoverRunner(verbosity=self.kwargs["verbosity"]) django.setup() @@ -121,7 +124,7 @@ class QuickDjangoTest: sys.exit(failures) -if __name__ == '__main__': +if __name__ == "__main__": """ What do when the user hits this file from the shell. @@ -130,13 +133,10 @@ if __name__ == '__main__': $ python quicktest.py test1 test2 """ - parser = argparse.ArgumentParser( - usage="[args]", - description="Run Django tests." - ) - parser.add_argument('tests', nargs="*", type=str) + parser = argparse.ArgumentParser(usage="[args]", description="Run Django tests.") + parser.add_argument("tests", nargs="*", type=str) parser.add_argument("--verbosity", "-v", nargs="?", type=int, default=1) args = parser.parse_args() if not args.tests: - args.tests = ['helpdesk'] + args.tests = ["helpdesk"] QuickDjangoTest(*args.tests, verbosity=args.verbosity) diff --git a/setup.py b/setup.py index b0ec8dbd..d8ebe85f 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,5 @@ """django-helpdesk setup""" + from distutils.util import convert_path from fnmatch import fnmatchcase import os @@ -6,7 +7,7 @@ from setuptools import find_packages, setup import sys -version = '1.4.0' +version = "1.4.0" # Provided as an attribute, so you can append to these instead @@ -77,8 +78,7 @@ def find_package_data( bad_name = True if show_ignored: print( - "Directory %s ignored by pattern %s" % ( - fn, pattern), + "Directory %s ignored by pattern %s" % (fn, pattern), file=sys.stderr, ) @@ -92,8 +92,7 @@ def find_package_data( new_package = package + "." + name stack.append((fn, "", new_package, False)) else: - stack.append((fn, prefix + name + "/", - package, only_in_packages)) + stack.append((fn, prefix + name + "/", package, only_in_packages)) elif package or not only_in_packages: # is a file bad_name = False @@ -102,8 +101,7 @@ def find_package_data( bad_name = True if show_ignored: print( - "File %s ignored by pattern %s" % ( - fn, pattern), + "File %s ignored by pattern %s" % (fn, pattern), file=sys.stderr, ) break diff --git a/standalone/config/local_settings.py b/standalone/config/local_settings.py index 7d7765a7..edbb5e5f 100644 --- a/standalone/config/local_settings.py +++ b/standalone/config/local_settings.py @@ -1 +1 @@ -from .settings import * +from .settings import * # noqa diff --git a/standalone/config/local_urls.py b/standalone/config/local_urls.py index bc2562cb..0774e7b3 100644 --- a/standalone/config/local_urls.py +++ b/standalone/config/local_urls.py @@ -1,2 +1 @@ -local_urlpatterns = [ -] +local_urlpatterns = [] diff --git a/standalone/config/settings.py b/standalone/config/settings.py index b658baaa..c1f18361 100644 --- a/standalone/config/settings.py +++ b/standalone/config/settings.py @@ -8,8 +8,8 @@ For the full list of settings and their values, see https://docs.djangoproject.com/en/1.11/ref/settings/ """ - import os +from django.core.exceptions import ImproperlyConfigured # Build paths inside the project like this: os.path.join(BASE_DIR, ...) @@ -21,70 +21,72 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Read SECRET_KEY from DJANGO_HELPDESK_SECRET_KEY env var try: - SECRET_KEY = os.environ['DJANGO_HELPDESK_SECRET_KEY'] + SECRET_KEY = os.environ["DJANGO_HELPDESK_SECRET_KEY"] except KeyError: raise Exception("DJANGO_HELPDESK_SECRET_KEY environment variable is not set") # SECURITY WARNING: don't run with debug turned on in production! DEBUG = False -ALLOWED_HOSTS = os.environ.get("DJANGO_HELPDESK_ALLOWED_HOSTS", "*, localhost, 0.0.0.0").split(",") +ALLOWED_HOSTS = os.environ.get( + "DJANGO_HELPDESK_ALLOWED_HOSTS", "*, localhost, 0.0.0.0" +).split(",") -SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True # Application definition INSTALLED_APPS = [ - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'django.contrib.sites', - 'django.contrib.humanize', - 'bootstrap4form', - 'account', # Required by pinax-teams - 'pinax.invitations', # required by pinax-teams - 'pinax.teams', # team support - 'reversion', # required by pinax-teams - 'helpdesk', # This is us! - 'rest_framework', # required for the API + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.sites", + "django.contrib.humanize", + "bootstrap4form", + "account", # Required by pinax-teams + "pinax.invitations", # required by pinax-teams + "pinax.teams", # team support + "reversion", # required by pinax-teams + "helpdesk", # This is us! + "rest_framework", # required for the API ] 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', + "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", "whitenoise.middleware.WhiteNoiseMiddleware", ] -ROOT_URLCONF = 'standalone.config.urls' +ROOT_URLCONF = "standalone.config.urls" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'debug': True, - '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": { + "debug": True, + "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 = 'standalone.config.wsgi.application' +WSGI_APPLICATION = "standalone.config.wsgi.application" # django-helpdesk configuration settings @@ -94,43 +96,57 @@ WSGI_APPLICATION = 'standalone.config.wsgi.application' # Some common settings are below. HELPDESK_DEFAULT_SETTINGS = { - 'use_email_as_submitter': os.environ.get('HELPDESK_USE_EMAIL_AS_SUBMITTER', 'True') == 'True', - 'email_on_ticket_assign': os.environ.get('HELPDESK_EMAIL_ON_TICKET_ASSIGN', 'True') == 'True', - 'email_on_ticket_change': os.environ.get('HELPDESK_EMAIL_ON_TICKET_CHANGE', 'True') == 'True', - 'login_view_ticketlist': os.environ.get('HELPDESK_LOGIN_VIEW_TICKETLIST', 'True') == 'True', - 'preset_replies': os.environ.get('HELPDESK_PRESET_REPLIES', 'True') == 'True', - 'tickets_per_page': os.environ.get('HELPDESK_TICKETS_PER_PAGE', '25'), + "use_email_as_submitter": os.environ.get("HELPDESK_USE_EMAIL_AS_SUBMITTER", "True") + == "True", + "email_on_ticket_assign": os.environ.get("HELPDESK_EMAIL_ON_TICKET_ASSIGN", "True") + == "True", + "email_on_ticket_change": os.environ.get("HELPDESK_EMAIL_ON_TICKET_CHANGE", "True") + == "True", + "login_view_ticketlist": os.environ.get("HELPDESK_LOGIN_VIEW_TICKETLIST", "True") + == "True", + "preset_replies": os.environ.get("HELPDESK_PRESET_REPLIES", "True") == "True", + "tickets_per_page": os.environ.get("HELPDESK_TICKETS_PER_PAGE", "25"), } # Should the public web portal be enabled? -HELPDESK_PUBLIC_ENABLED = os.environ.get('HELPDESK_PUBLIC_ENABLED', 'True') == 'True' -HELPDESK_VIEW_A_TICKET_PUBLIC = os.environ.get('HELPDESK_VIEW_A_TICKET_PUBLIC', 'True') == 'True' -HELPDESK_SUBMIT_A_TICKET_PUBLIC = os.environ.get('HELPDESK_SUBMIT_A_TICKET_PUBLIC', 'True') == 'True' +HELPDESK_PUBLIC_ENABLED = os.environ.get("HELPDESK_PUBLIC_ENABLED", "True") == "True" +HELPDESK_VIEW_A_TICKET_PUBLIC = ( + os.environ.get("HELPDESK_VIEW_A_TICKET_PUBLIC", "True") == "True" +) +HELPDESK_SUBMIT_A_TICKET_PUBLIC = ( + os.environ.get("HELPDESK_SUBMIT_A_TICKET_PUBLIC", "True") == "True" +) # Should the Knowledgebase be enabled? -HELPDESK_KB_ENABLED = os.environ.get('HELPDESK_KB_ENABLED', 'True') == 'True' +HELPDESK_KB_ENABLED = os.environ.get("HELPDESK_KB_ENABLED", "True") == "True" -HELPDESK_TICKETS_TIMELINE_ENABLED = os.environ.get('HELPDESK_TICKETS_TIMELINE_ENABLED', 'True') == 'True' +HELPDESK_TICKETS_TIMELINE_ENABLED = ( + os.environ.get("HELPDESK_TICKETS_TIMELINE_ENABLED", "True") == "True" +) # Allow users to change their passwords -HELPDESK_SHOW_CHANGE_PASSWORD = os.environ.get('HELPDESK_SHOW_CHANGE_PASSWORD', 'True') == 'True' +HELPDESK_SHOW_CHANGE_PASSWORD = ( + os.environ.get("HELPDESK_SHOW_CHANGE_PASSWORD", "True") == "True" +) # Instead of showing the public web portal first, # we can instead redirect users straight to the login page. -HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT = os.environ.get('HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT', 'False') == 'True' -LOGIN_URL = 'helpdesk:login' -LOGIN_REDIRECT_URL = 'helpdesk:home' +HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT = ( + os.environ.get("HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT", "False") == "True" +) +LOGIN_URL = "helpdesk:login" +LOGIN_REDIRECT_URL = "helpdesk:home" DATABASES = { - # Setup postgress db with postgres as host and db name and read password from env var - 'default': { - 'ENGINE': 'django.db.backends.postgresql', - 'NAME': os.environ.get('POSTGRES_DB', 'postgres'), - 'USER': os.environ.get('POSTGRES_USER', 'postgres'), - 'PASSWORD': os.environ.get('POSTGRES_PASSWORD', 'postgres'), - 'HOST': os.environ.get('POSTGRES_HOST', 'postgres'), - 'PORT': os.environ.get('POSTGRES_PORT', '5432'), + # Setup postgress db with postgres as host and db name and read password from env var + "default": { + "ENGINE": "django.db.backends.postgresql", + "NAME": os.environ.get("POSTGRES_DB", "postgres"), + "USER": os.environ.get("POSTGRES_USER", "postgres"), + "PASSWORD": os.environ.get("POSTGRES_PASSWORD", "postgres"), + "HOST": os.environ.get("POSTGRES_HOST", "postgres"), + "PORT": os.environ.get("POSTGRES_PORT", "5432"), } } @@ -154,16 +170,16 @@ SESSION_COOKIE_AGE = 86400 # = 1 day 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", }, ] @@ -172,21 +188,21 @@ AUTH_PASSWORD_VALIDATORS = [ # This demo uses the console backend, which simply prints emails to the console # rather than actually sending them out. -DEFAULT_FROM_EMAIL = os.environ.get('DEFAULT_FROM_EMAIL', 'example@example.com') -SERVER_EMAIL = os.environ.get('SERVER_EMAIL', 'example@example.com') +DEFAULT_FROM_EMAIL = os.environ.get("DEFAULT_FROM_EMAIL", "example@example.com") +SERVER_EMAIL = os.environ.get("SERVER_EMAIL", "example@example.com") -if os.environ.get('EMAIL_HOST', None): - EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +if os.environ.get("EMAIL_HOST", None): + EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" try: - EMAIL_HOST = os.environ['EMAIL_HOST'] + EMAIL_HOST = os.environ["EMAIL_HOST"] except KeyError: - raise ImproperlyConfigured('Please set the EMAIL_HOST environment variable.') + raise ImproperlyConfigured("Please set the EMAIL_HOST environment variable.") try: - EMAIL_PORT = os.environ['EMAIL_PORT'] + EMAIL_PORT = os.environ["EMAIL_PORT"] except KeyError: - raise ImproperlyConfigured('Please set the EMAIL_PORT environment variable.') + raise ImproperlyConfigured("Please set the EMAIL_PORT environment variable.") else: - EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' + EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" # Internationalization # https://docs.djangoproject.com/en/1.11/topics/i18n/ @@ -195,9 +211,9 @@ else: # The most complete translations are: es-MX, ru, zh-Hans # Contribute to our translations via Transifex if you can! # See CONTRIBUTING.rst for more info. -LANGUAGE_CODE = 'en-US' +LANGUAGE_CODE = "en-US" -TIME_ZONE = 'UTC' +TIME_ZONE = "UTC" USE_I18N = True @@ -213,32 +229,34 @@ def normpath(*args): PROJECT_ROOT = normpath(__file__, "..", "..") -STATIC_ROOT = os.environ.get("DJANGO_HELPDESK_STATIC_ROOT", normpath(PROJECT_ROOT, "static")) +STATIC_ROOT = os.environ.get( + "DJANGO_HELPDESK_STATIC_ROOT", normpath(PROJECT_ROOT, "static") +) STATIC_URL = os.environ.get("DJANGO_HELPDESK_STATIC_URL", "/static/") # MEDIA_ROOT is where media uploads are stored. # We set this to a directory to host file attachments created # with tickets. -MEDIA_URL = '/media/' -MEDIA_ROOT = '/data/media' +MEDIA_URL = "/media/" +MEDIA_ROOT = "/data/media" # for Django 3.2+, set default for autofields: -DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' +DEFAULT_AUTO_FIELD = "django.db.models.AutoField" LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'handlers': { - 'console': { - 'class': 'logging.StreamHandler', + "version": 1, + "disable_existing_loggers": False, + "handlers": { + "console": { + "class": "logging.StreamHandler", }, }, - 'loggers': { - 'django': { - 'handlers': ['console'], - 'level': 'ERROR', # Change to 'DEBUG' if you want to print all debug messages as well - 'propagate': True, + "loggers": { + "django": { + "handlers": ["console"], + "level": "ERROR", # Change to 'DEBUG' if you want to print all debug messages as well + "propagate": True, }, }, } diff --git a/standalone/config/urls.py b/standalone/config/urls.py index 58a7b37e..49f23ddd 100644 --- a/standalone/config/urls.py +++ b/standalone/config/urls.py @@ -5,8 +5,12 @@ from django.contrib import admin from django.urls import include, path -urlpatterns = [ - path('admin/', admin.site.urls), - path('', include('helpdesk.urls', namespace='helpdesk')), - path('api/auth/', include('rest_framework.urls', namespace='rest_framework')) -] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + local_urlpatterns +urlpatterns = ( + [ + path("admin/", admin.site.urls), + path("", include("helpdesk.urls", namespace="helpdesk")), + path("api/auth/", include("rest_framework.urls", namespace="rest_framework")), + ] + + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + + local_urlpatterns +) diff --git a/standalone/config/wsgi.py b/standalone/config/wsgi.py index 1d41adf4..a010265f 100644 --- a/standalone/config/wsgi.py +++ b/standalone/config/wsgi.py @@ -7,7 +7,6 @@ For more information on this file, see https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/ """ - from django.core.wsgi import get_wsgi_application import os diff --git a/standalone/manage.py b/standalone/manage.py index 0de07659..4e17158a 100755 --- a/standalone/manage.py +++ b/standalone/manage.py @@ -12,7 +12,7 @@ def main(): # issue is really that Django is missing to avoid masking other # exceptions on Python 2. try: - import django + import django # noqa except ImportError: raise ImportError( "Couldn't import Django. Are you sure it's installed and "