mirror of
https://github.com/DarrenOfficial/dpaste.git
synced 2024-12-23 23:23:06 +11:00
Quote cleanup, fStrings and Deprecation fixes.
This commit is contained in:
parent
cd586f62fe
commit
e54790c8f9
17 changed files with 411 additions and 415 deletions
2
Pipfile
2
Pipfile
|
@ -10,5 +10,5 @@ docutils = "==0.15"
|
|||
[scripts]
|
||||
runserver = "sh -c \"./manage.py migrate && ./manage.py runserver 0:8000\""
|
||||
test = "pytest dpaste"
|
||||
cleanup = "sh -c \"isort -rc dpaste && black --skip-string-normalization --line-length=80 --exclude='/(migrations)/' dpaste\""
|
||||
cleanup = "sh -c \"isort -rc dpaste && black --line-length=80 --exclude='/(migrations)/' dpaste\""
|
||||
docs = "sphinx-build docs docs/_build/html"
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
VERSION = (3, 4, 'a0')
|
||||
VERSION = (3, 4, "a0")
|
||||
|
||||
__version__ = '{major}.{minor}{rest}'.format(
|
||||
__version__ = "{major}.{minor}{rest}".format(
|
||||
major=VERSION[0],
|
||||
minor=VERSION[1],
|
||||
rest=''.join(str(i) for i in VERSION[2:]),
|
||||
rest="".join(str(i) for i in VERSION[2:]),
|
||||
)
|
||||
|
||||
default_app_config = 'dpaste.apps.dpasteAppConfig'
|
||||
default_app_config = "dpaste.apps.dpasteAppConfig"
|
||||
|
|
170
dpaste/apps.py
170
dpaste/apps.py
|
@ -1,14 +1,14 @@
|
|||
from django.apps import AppConfig, apps
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class dpasteAppConfig(AppConfig):
|
||||
name = 'dpaste'
|
||||
verbose_name = 'dpaste'
|
||||
name = "dpaste"
|
||||
verbose_name = "dpaste"
|
||||
|
||||
# The application title used throughout the user interface.
|
||||
APPLICATION_NAME = 'dpaste'
|
||||
APPLICATION_NAME = "dpaste"
|
||||
|
||||
# This content is loaded in the <head> section of each template.
|
||||
# You can use it to add any HTML tags, specifically custom CSS styles.
|
||||
|
@ -24,7 +24,7 @@ class dpasteAppConfig(AppConfig):
|
|||
# .btn { background-color: blue; border: 3px solid yellow; }
|
||||
# </style>
|
||||
# """
|
||||
EXTRA_HEAD_HTML = ''
|
||||
EXTRA_HEAD_HTML = ""
|
||||
|
||||
# Integer. Length of the random slug for each new snippet. In the rare
|
||||
# case an existing slug is generated again, the length will increase by
|
||||
|
@ -35,12 +35,12 @@ class dpasteAppConfig(AppConfig):
|
|||
# This is intentionally missing l and I as they look too similar with
|
||||
# sans-serif fonts.
|
||||
SLUG_CHOICES = (
|
||||
'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ1234567890'
|
||||
"abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ1234567890"
|
||||
)
|
||||
|
||||
# String. The lexer key that is pre-selected in the dropdown. Note that
|
||||
# this is only used if the user has not saved a snippet before, otherwise
|
||||
LEXER_DEFAULT = 'python'
|
||||
LEXER_DEFAULT = "python"
|
||||
|
||||
# Integer. Maximum number of bytes per snippet.
|
||||
MAX_CONTENT_LENGTH = 250 * 1024 * 1024
|
||||
|
@ -48,7 +48,7 @@ class dpasteAppConfig(AppConfig):
|
|||
# A tuple of seconds and a descriptive string used in the lexer
|
||||
# expiration dropdown. Example::
|
||||
#
|
||||
# from django.utils.translation import ugettext_lazy as _
|
||||
# from django.utils.translation import gettext_lazy as _
|
||||
# DPASTE_EXPIRE_CHOICES = (
|
||||
# (3600, _('In one hour')),
|
||||
# (3600 * 24 * 7, _('In one week')),
|
||||
|
@ -60,17 +60,17 @@ class dpasteAppConfig(AppConfig):
|
|||
# you set the choice key to ``never``. The management command will ignore
|
||||
# these snippets::
|
||||
#
|
||||
# from django.utils.translation import ugettext_lazy as _
|
||||
# from django.utils.translation import gettext_lazy as _
|
||||
# DPASTE_EXPIRE_CHOICES = (
|
||||
# (3600, _('In one hour')),
|
||||
# ('never', _('Never')),
|
||||
# )
|
||||
EXPIRE_CHOICES = (
|
||||
('onetime', _('One-Time snippet')),
|
||||
(3600, _('In one hour')),
|
||||
(3600 * 24 * 7, _('In one week')),
|
||||
(3600 * 24 * 30, _('In one month')),
|
||||
('never', _('Never')),
|
||||
("onetime", _("One-Time snippet")),
|
||||
(3600, _("In one hour")),
|
||||
(3600 * 24 * 7, _("In one week")),
|
||||
(3600 * 24 * 30, _("In one month")),
|
||||
("never", _("Never")),
|
||||
)
|
||||
|
||||
# Default value for ``EXPIRE_CHOICES``
|
||||
|
@ -81,7 +81,7 @@ class dpasteAppConfig(AppConfig):
|
|||
# enable one-time snippets you have to add a choice ``onetime`` to the
|
||||
# expire choices::
|
||||
#
|
||||
# from django.utils.translation import ugettext_lazy as _
|
||||
# from django.utils.translation import gettext_lazy as _
|
||||
# DPASTE_EXPIRE_CHOICES = (
|
||||
# ('onetime', _('One-Time snippet')),
|
||||
# (3600, _('In one hour')),
|
||||
|
@ -102,11 +102,11 @@ class dpasteAppConfig(AppConfig):
|
|||
RAW_MODE_PLAIN_TEXT = True
|
||||
|
||||
# Lexers which have wordwrap enabled by default
|
||||
LEXER_WORDWRAP = ('rst',)
|
||||
LEXER_WORDWRAP = ("rst",)
|
||||
|
||||
# Key names of the default text and code lexer.
|
||||
PLAIN_TEXT_SYMBOL = '_text'
|
||||
PLAIN_CODE_SYMBOL = '_code'
|
||||
PLAIN_TEXT_SYMBOL = "_text"
|
||||
PLAIN_CODE_SYMBOL = "_code"
|
||||
|
||||
@property
|
||||
def TEXT_FORMATTER(self):
|
||||
|
@ -129,9 +129,9 @@ class dpasteAppConfig(AppConfig):
|
|||
)
|
||||
|
||||
return [
|
||||
(self.PLAIN_TEXT_SYMBOL, 'Plain Text', PlainTextHighlighter),
|
||||
('_markdown', 'Markdown', MarkdownHighlighter),
|
||||
('_rst', 'reStructuredText', RestructuredTextHighlighter),
|
||||
(self.PLAIN_TEXT_SYMBOL, "Plain Text", PlainTextHighlighter),
|
||||
("_markdown", "Markdown", MarkdownHighlighter),
|
||||
("_rst", "reStructuredText", RestructuredTextHighlighter),
|
||||
]
|
||||
|
||||
@property
|
||||
|
@ -159,7 +159,7 @@ class dpasteAppConfig(AppConfig):
|
|||
from jsx.lexer import JsxLexer
|
||||
|
||||
return [
|
||||
(self.PLAIN_CODE_SYMBOL, 'Plain Code', PlainCodeHighlighter),
|
||||
(self.PLAIN_CODE_SYMBOL, "Plain Code", PlainCodeHighlighter),
|
||||
# ('abap', 'ABAP'),
|
||||
# ('abnf', 'ABNF'),
|
||||
# ('ada', 'Ada'),
|
||||
|
@ -180,8 +180,8 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('antlr-ruby', 'ANTLR With Ruby Target'),
|
||||
# ('apacheconf', 'ApacheConf'),
|
||||
# ('apl', 'APL'),
|
||||
('applescript', 'AppleScript'),
|
||||
('arduino', 'Arduino'),
|
||||
("applescript", "AppleScript"),
|
||||
("arduino", "Arduino"),
|
||||
# ('as', 'ActionScript'),
|
||||
# ('as3', 'ActionScript 3'),
|
||||
# ('aspectj', 'AspectJ'),
|
||||
|
@ -192,8 +192,8 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('autoit', 'AutoIt'),
|
||||
# ('awk', 'Awk'),
|
||||
# ('basemake', 'Base Makefile'),
|
||||
('bash', 'Bash'),
|
||||
('bat', 'Batchfile'),
|
||||
("bash", "Bash"),
|
||||
("bat", "Batchfile"),
|
||||
# ('bbcode', 'BBCode'),
|
||||
# ('bc', 'BC'),
|
||||
# ('befunge', 'Befunge'),
|
||||
|
@ -207,7 +207,7 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('bro', 'Bro'),
|
||||
# ('bst', 'BST'),
|
||||
# ('bugs', 'BUGS'),
|
||||
('c', 'C'),
|
||||
("c", "C"),
|
||||
# ('c-objdump', 'c-objdump'),
|
||||
# ('ca65', 'ca65 assembler'),
|
||||
# ('cadl', 'cADL'),
|
||||
|
@ -226,15 +226,15 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('cirru', 'Cirru'),
|
||||
# ('clay', 'Clay'),
|
||||
# ('clean', 'Clean'),
|
||||
('clojure', 'Clojure'),
|
||||
("clojure", "Clojure"),
|
||||
# ('clojurescript', 'ClojureScript'),
|
||||
('cmake', 'CMake'),
|
||||
("cmake", "CMake"),
|
||||
# ('cobol', 'COBOL'),
|
||||
# ('cobolfree', 'COBOLFree'),
|
||||
('coffee-script', 'CoffeeScript'),
|
||||
('common-lisp', 'Common Lisp'),
|
||||
("coffee-script", "CoffeeScript"),
|
||||
("common-lisp", "Common Lisp"),
|
||||
# ('componentpascal', 'Component Pascal'),
|
||||
('console', 'Console/Bash Session'),
|
||||
("console", "Console/Bash Session"),
|
||||
# ('control', 'Debian Control file'),
|
||||
# ('coq', 'Coq'),
|
||||
# ('cpp', 'C++'),
|
||||
|
@ -244,11 +244,11 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('crmsh', 'Crmsh'),
|
||||
# ('croc', 'Croc'),
|
||||
# ('cryptol', 'Cryptol'),
|
||||
('csharp', 'C#'),
|
||||
("csharp", "C#"),
|
||||
# ('csound', 'Csound Orchestra'),
|
||||
# ('csound-document', 'Csound Document'),
|
||||
# ('csound-score', 'Csound Score'),
|
||||
('css', 'CSS'),
|
||||
("css", "CSS"),
|
||||
# ('css+django', 'CSS+Django/Jinja'),
|
||||
# ('css+erb', 'CSS+Ruby'),
|
||||
# ('css+genshitext', 'CSS+Genshi Text'),
|
||||
|
@ -259,17 +259,17 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('css+php', 'CSS+PHP'),
|
||||
# ('css+smarty', 'CSS+Smarty'),
|
||||
# ('cucumber', 'Gherkin'),
|
||||
('cuda', 'CUDA'),
|
||||
("cuda", "CUDA"),
|
||||
# ('cypher', 'Cypher'),
|
||||
# ('cython', 'Cython'),
|
||||
# ('d', 'D'),
|
||||
# ('d-objdump', 'd-objdump'),
|
||||
('dart', 'Dart'),
|
||||
('delphi', 'Delphi'),
|
||||
("dart", "Dart"),
|
||||
("delphi", "Delphi"),
|
||||
# ('dg', 'dg'),
|
||||
('diff', 'Diff'),
|
||||
('django', 'Django/Jinja'),
|
||||
('docker', 'Docker'),
|
||||
("diff", "Diff"),
|
||||
("django", "Django/Jinja"),
|
||||
("docker", "Docker"),
|
||||
# ('doscon', 'MSDOS Session'),
|
||||
# ('dpatch', 'Darcs Patch'),
|
||||
# ('dtd', 'DTD'),
|
||||
|
@ -283,12 +283,12 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('ec', 'eC'),
|
||||
# ('ecl', 'ECL'),
|
||||
# ('eiffel', 'Eiffel'),
|
||||
('elixir', 'Elixir'),
|
||||
("elixir", "Elixir"),
|
||||
# ('elm', 'Elm'),
|
||||
# ('emacs', 'EmacsLisp'),
|
||||
# ('erb', 'ERB'),
|
||||
# ('erl', 'Erlang erl session'),
|
||||
('erlang', 'Erlang'),
|
||||
("erlang", "Erlang"),
|
||||
# ('evoque', 'Evoque'),
|
||||
# ('extempore', 'xtlang'),
|
||||
# ('ezhil', 'Ezhil'),
|
||||
|
@ -310,7 +310,7 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('genshitext', 'Genshi Text'),
|
||||
# ('glsl', 'GLSL'),
|
||||
# ('gnuplot', 'Gnuplot'),
|
||||
('go', 'Go'),
|
||||
("go", "Go"),
|
||||
# ('golo', 'Golo'),
|
||||
# ('gooddata-cl', 'GoodData-CL'),
|
||||
# ('gosu', 'Gosu'),
|
||||
|
@ -318,15 +318,15 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('groovy', 'Groovy'),
|
||||
# ('gst', 'Gosu Template'),
|
||||
# ('haml', 'Haml'),
|
||||
('handlebars', 'Handlebars'),
|
||||
('haskell', 'Haskell'),
|
||||
("handlebars", "Handlebars"),
|
||||
("haskell", "Haskell"),
|
||||
# ('haxeml', 'Hxml'),
|
||||
# ('hexdump', 'Hexdump'),
|
||||
# ('hlsl', 'HLSL'),
|
||||
# ('hsail', 'HSAIL'),
|
||||
('html', 'HTML'),
|
||||
("html", "HTML"),
|
||||
# ('html+cheetah', 'HTML+Cheetah'),
|
||||
('html+django', 'HTML + Django/Jinja'),
|
||||
("html+django", "HTML + Django/Jinja"),
|
||||
# ('html+evoque', 'HTML+Evoque'),
|
||||
# ('html+genshi', 'HTML+Genshi'),
|
||||
# ('html+handlebars', 'HTML+Handlebars'),
|
||||
|
@ -349,22 +349,22 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('igor', 'Igor'),
|
||||
# ('inform6', 'Inform 6'),
|
||||
# ('inform7', 'Inform 7'),
|
||||
('ini', 'INI'),
|
||||
("ini", "INI"),
|
||||
# ('io', 'Io'),
|
||||
# ('ioke', 'Ioke'),
|
||||
# ('ipython2', 'IPython'),
|
||||
# ('ipython3', 'IPython3'),
|
||||
('ipythonconsole', 'IPython console session'),
|
||||
('irc', 'IRC logs'),
|
||||
("ipythonconsole", "IPython console session"),
|
||||
("irc", "IRC logs"),
|
||||
# ('isabelle', 'Isabelle'),
|
||||
# ('j', 'J'),
|
||||
# ('jags', 'JAGS'),
|
||||
# ('jasmin', 'Jasmin'),
|
||||
('java', 'Java'),
|
||||
("java", "Java"),
|
||||
# ('javascript+mozpreproc', 'Javascript+mozpreproc'),
|
||||
# ('jcl', 'JCL'),
|
||||
# ('jlcon', 'Julia console'),
|
||||
('js', 'JavaScript'),
|
||||
("js", "JavaScript"),
|
||||
# ('js+cheetah', 'JavaScript+Cheetah'),
|
||||
# ('js+django', 'JavaScript+Django/Jinja'),
|
||||
# ('js+erb', 'JavaScript+Ruby'),
|
||||
|
@ -375,8 +375,8 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('js+php', 'JavaScript+PHP'),
|
||||
# ('js+smarty', 'JavaScript+Smarty'),
|
||||
# ('jsgf', 'JSGF'),
|
||||
('json', 'JSON'),
|
||||
('jsx', 'JSX/React'),
|
||||
("json", "JSON"),
|
||||
("jsx", "JSX/React"),
|
||||
# ('json-object', 'JSONBareObject'),
|
||||
# ('jsonld', 'JSON-LD'),
|
||||
# ('jsp', 'Java Server Page'),
|
||||
|
@ -385,12 +385,12 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('kal', 'Kal'),
|
||||
# ('kconfig', 'Kconfig'),
|
||||
# ('koka', 'Koka'),
|
||||
('kotlin', 'Kotlin'),
|
||||
("kotlin", "Kotlin"),
|
||||
# ('lagda', 'Literate Agda'),
|
||||
# ('lasso', 'Lasso'),
|
||||
# ('lcry', 'Literate Cryptol'),
|
||||
# ('lean', 'Lean'),
|
||||
('less', 'LessCSS'),
|
||||
("less", "LessCSS"),
|
||||
# ('lhs', 'Literate Haskell'),
|
||||
# ('lidr', 'Literate Idris'),
|
||||
# ('lighty', 'Lighttpd configuration file'),
|
||||
|
@ -401,14 +401,14 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('logos', 'Logos'),
|
||||
# ('logtalk', 'Logtalk'),
|
||||
# ('lsl', 'LSL'),
|
||||
('lua', 'Lua'),
|
||||
('make', 'Makefile'),
|
||||
("lua", "Lua"),
|
||||
("make", "Makefile"),
|
||||
# ('mako', 'Mako'),
|
||||
# ('maql', 'MAQL'),
|
||||
# ('mask', 'Mask'),
|
||||
# ('mason', 'Mason'),
|
||||
# ('mathematica', 'Mathematica'),
|
||||
('matlab', 'Matlab'),
|
||||
("matlab", "Matlab"),
|
||||
# ('matlabsession', 'Matlab session'),
|
||||
# ('md', 'markdown'),
|
||||
# ('minid', 'MiniD'),
|
||||
|
@ -433,16 +433,16 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('newlisp', 'NewLisp'),
|
||||
# ('newspeak', 'Newspeak'),
|
||||
# ('ng2', 'Angular2'),
|
||||
('nginx', 'Nginx configuration file'),
|
||||
("nginx", "Nginx configuration file"),
|
||||
# ('nim', 'Nimrod'),
|
||||
# ('nit', 'Nit'),
|
||||
# ('nixos', 'Nix'),
|
||||
# ('nsis', 'NSIS'),
|
||||
('numpy', 'NumPy'),
|
||||
("numpy", "NumPy"),
|
||||
# ('nusmv', 'NuSMV'),
|
||||
# ('objdump', 'objdump'),
|
||||
# ('objdump-nasm', 'objdump-nasm'),
|
||||
('objective-c', 'Objective-C'),
|
||||
("objective-c", "Objective-C"),
|
||||
# ('objective-c++', 'Objective-C++'),
|
||||
# ('objective-j', 'Objective-J'),
|
||||
# ('ocaml', 'OCaml'),
|
||||
|
@ -455,14 +455,14 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('pan', 'Pan'),
|
||||
# ('parasail', 'ParaSail'),
|
||||
# ('pawn', 'Pawn'),
|
||||
('perl', 'Perl'),
|
||||
("perl", "Perl"),
|
||||
# ('perl6', 'Perl6'),
|
||||
('php', 'PHP'),
|
||||
("php", "PHP"),
|
||||
# ('pig', 'Pig'),
|
||||
# ('pike', 'Pike'),
|
||||
# ('pkgconfig', 'PkgConfig'),
|
||||
# ('plpgsql', 'PL/pgSQL'),
|
||||
('postgresql', 'PostgreSQL SQL dialect'),
|
||||
("postgresql", "PostgreSQL SQL dialect"),
|
||||
# ('postscript', 'PostScript'),
|
||||
# ('pot', 'Gettext Catalog'),
|
||||
# ('pov', 'POVRay'),
|
||||
|
@ -479,7 +479,7 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('pycon', 'Python console session'),
|
||||
# ('pypylog', 'PyPy Log'),
|
||||
# ('pytb', 'Python Traceback'),
|
||||
('python', 'Python'),
|
||||
("python", "Python"),
|
||||
# ('python3', 'Python 3'),
|
||||
# ('qbasic', 'QBasic'),
|
||||
# ('qml', 'QML'),
|
||||
|
@ -494,7 +494,7 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('ragel-objc', 'Ragel in Objective C Host'),
|
||||
# ('ragel-ruby', 'Ragel in Ruby Host'),
|
||||
# ('raw', 'Raw token data'),
|
||||
('rb', 'Ruby'),
|
||||
("rb", "Ruby"),
|
||||
# ('rbcon', 'Ruby irb session'),
|
||||
# ('rconsole', 'RConsole'),
|
||||
# ('rd', 'Rd'),
|
||||
|
@ -511,17 +511,17 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('robotframework', 'RobotFramework'),
|
||||
# ('rql', 'RQL'),
|
||||
# ('rsl', 'RSL'),
|
||||
('rst', 'reStructuredText'),
|
||||
("rst", "reStructuredText"),
|
||||
# ('rts', 'TrafficScript'),
|
||||
('rust', 'Rust'),
|
||||
("rust", "Rust"),
|
||||
# ('sas', 'SAS'),
|
||||
('sass', 'Sass'),
|
||||
("sass", "Sass"),
|
||||
# ('sc', 'SuperCollider'),
|
||||
# ('scala', 'Scala'),
|
||||
# ('scaml', 'Scaml'),
|
||||
# ('scheme', 'Scheme'),
|
||||
# ('scilab', 'Scilab'),
|
||||
('scss', 'SCSS'),
|
||||
("scss", "SCSS"),
|
||||
# ('shen', 'Shen'),
|
||||
# ('silver', 'Silver'),
|
||||
# ('slim', 'Slim'),
|
||||
|
@ -531,19 +531,19 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('sml', 'Standard ML'),
|
||||
# ('snobol', 'Snobol'),
|
||||
# ('snowball', 'Snowball'),
|
||||
('sol', 'Solidity'),
|
||||
("sol", "Solidity"),
|
||||
# ('sourceslist', 'Debian Sourcelist'),
|
||||
# ('sp', 'SourcePawn'),
|
||||
# ('sparql', 'SPARQL'),
|
||||
# ('spec', 'RPMSpec'),
|
||||
# ('splus', 'S'),
|
||||
('sql', 'SQL'),
|
||||
("sql", "SQL"),
|
||||
# ('sqlite3', 'sqlite3con'),
|
||||
# ('squidconf', 'SquidConf'),
|
||||
# ('ssp', 'Scalate Server Page'),
|
||||
# ('stan', 'Stan'),
|
||||
# ('stata', 'Stata'),
|
||||
('swift', 'Swift'),
|
||||
("swift", "Swift"),
|
||||
# ('swig', 'SWIG'),
|
||||
# ('systemverilog', 'systemverilog'),
|
||||
# ('tads3', 'TADS 3'),
|
||||
|
@ -556,7 +556,7 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('termcap', 'Termcap'),
|
||||
# ('terminfo', 'Terminfo'),
|
||||
# ('terraform', 'Terraform'),
|
||||
('tex', 'TeX'),
|
||||
("tex", "TeX"),
|
||||
# ('text', 'Text only'),
|
||||
# ('thrift', 'Thrift'),
|
||||
# ('todotxt', 'Todotxt'),
|
||||
|
@ -566,7 +566,7 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('tsql', 'Transact-SQL'),
|
||||
# ('turtle', 'Turtle'),
|
||||
# ('twig', 'Twig'),
|
||||
('typoscript', 'TypoScript'),
|
||||
("typoscript", "TypoScript"),
|
||||
# ('typoscriptcssdata', 'TypoScriptCssData'),
|
||||
# ('typoscripthtmldata', 'TypoScriptHtmlData'),
|
||||
# ('urbiscript', 'UrbiScript'),
|
||||
|
@ -579,11 +579,11 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('verilog', 'verilog'),
|
||||
# ('vgl', 'VGL'),
|
||||
# ('vhdl', 'vhdl'),
|
||||
('vim', 'VimL'),
|
||||
("vim", "VimL"),
|
||||
# ('wdiff', 'WDiff'),
|
||||
# ('whiley', 'Whiley'),
|
||||
# ('x10', 'X10'),
|
||||
('xml', 'XML'),
|
||||
("xml", "XML"),
|
||||
# ('xml+cheetah', 'XML+Cheetah'),
|
||||
# ('xml+django', 'XML+Django/Jinja'),
|
||||
# ('xml+erb', 'XML+Ruby'),
|
||||
|
@ -596,10 +596,10 @@ class dpasteAppConfig(AppConfig):
|
|||
# ('xml+velocity', 'XML+Velocity'),
|
||||
# ('xorg.conf', 'Xorg'),
|
||||
# ('xquery', 'XQuery'),
|
||||
('xslt', 'XSLT'),
|
||||
("xslt", "XSLT"),
|
||||
# ('xtend', 'Xtend'),
|
||||
# ('xul+mozpreproc', 'XUL+mozpreproc'),
|
||||
('yaml', 'YAML'),
|
||||
("yaml", "YAML"),
|
||||
# ('yaml+jinja', 'YAML+Jinja'),
|
||||
# ('zephir', 'Zephir')
|
||||
]
|
||||
|
@ -612,13 +612,13 @@ class dpasteAppConfig(AppConfig):
|
|||
framework is installed, it uses the current Site domain. Otherwise
|
||||
it falls back to 'https://dpaste.de'
|
||||
"""
|
||||
if apps.is_installed('django.contrib.sites'):
|
||||
if apps.is_installed("django.contrib.sites"):
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
|
||||
site = get_current_site(request)
|
||||
if site:
|
||||
return 'https://{0}'.format(site.domain)
|
||||
return 'https://dpaste.de'
|
||||
return f"https://{site.domain}"
|
||||
return "https://dpaste.de"
|
||||
|
||||
@property
|
||||
def extra_template_context(self):
|
||||
|
@ -627,6 +627,6 @@ class dpasteAppConfig(AppConfig):
|
|||
all Template Views.
|
||||
"""
|
||||
return {
|
||||
'dpaste_application_name': self.APPLICATION_NAME,
|
||||
'dpaste_extra_head_html': mark_safe(self.EXTRA_HEAD_HTML),
|
||||
"dpaste_application_name": self.APPLICATION_NAME,
|
||||
"dpaste_extra_head_html": mark_safe(self.EXTRA_HEAD_HTML),
|
||||
}
|
||||
|
|
|
@ -2,19 +2,19 @@ import datetime
|
|||
|
||||
from django import forms
|
||||
from django.apps import apps
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .highlight import LEXER_CHOICES, LEXER_DEFAULT, LEXER_KEYS
|
||||
from .models import Snippet
|
||||
|
||||
config = apps.get_app_config('dpaste')
|
||||
config = apps.get_app_config("dpaste")
|
||||
|
||||
|
||||
def get_expire_values(expires):
|
||||
if expires == 'never':
|
||||
if expires == "never":
|
||||
expire_type = Snippet.EXPIRE_KEEP
|
||||
expires = None
|
||||
elif expires == 'onetime':
|
||||
elif expires == "onetime":
|
||||
expire_type = Snippet.EXPIRE_ONETIME
|
||||
expires = None
|
||||
else:
|
||||
|
@ -28,63 +28,63 @@ def get_expire_values(expires):
|
|||
|
||||
class SnippetForm(forms.ModelForm):
|
||||
content = forms.CharField(
|
||||
label=_('Content'),
|
||||
label=_("Content"),
|
||||
widget=forms.Textarea(
|
||||
attrs={'placeholder': _('Awesome code goes here...')}
|
||||
attrs={"placeholder": _("Awesome code goes here...")}
|
||||
),
|
||||
max_length=config.MAX_CONTENT_LENGTH,
|
||||
strip=False,
|
||||
)
|
||||
|
||||
lexer = forms.ChoiceField(
|
||||
label=_('Lexer'), initial=LEXER_DEFAULT, choices=LEXER_CHOICES
|
||||
label=_("Lexer"), initial=LEXER_DEFAULT, choices=LEXER_CHOICES
|
||||
)
|
||||
|
||||
expires = forms.ChoiceField(
|
||||
label=_('Expires'),
|
||||
label=_("Expires"),
|
||||
choices=config.EXPIRE_CHOICES,
|
||||
initial=config.EXPIRE_DEFAULT,
|
||||
)
|
||||
|
||||
rtl = forms.BooleanField(label=_('Right to Left'), required=False)
|
||||
rtl = forms.BooleanField(label=_("Right to Left"), required=False)
|
||||
|
||||
# Honeypot field
|
||||
title = forms.CharField(
|
||||
label=_('Title'),
|
||||
label=_("Title"),
|
||||
required=False,
|
||||
widget=forms.TextInput(attrs={'autocomplete': 'off'}),
|
||||
widget=forms.TextInput(attrs={"autocomplete": "off"}),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Snippet
|
||||
fields = ('content', 'lexer', 'rtl')
|
||||
fields = ("content", "lexer", "rtl")
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(SnippetForm, self).__init__(*args, **kwargs)
|
||||
self.request = request
|
||||
|
||||
# Set the recently used lexer if we have any
|
||||
session_lexer = self.request.session.get('lexer')
|
||||
session_lexer = self.request.session.get("lexer")
|
||||
if session_lexer and session_lexer in LEXER_KEYS:
|
||||
self.fields['lexer'].initial = session_lexer
|
||||
self.fields["lexer"].initial = session_lexer
|
||||
|
||||
# if the lexer is given via GET, set it
|
||||
if 'l' in request.GET and request.GET['l'] in LEXER_KEYS:
|
||||
self.fields['lexer'].initial = request.GET['l']
|
||||
if "l" in request.GET and request.GET["l"] in LEXER_KEYS:
|
||||
self.fields["lexer"].initial = request.GET["l"]
|
||||
|
||||
def clean_content(self):
|
||||
content = self.cleaned_data.get('content', '')
|
||||
content = self.cleaned_data.get("content", "")
|
||||
if not content.strip():
|
||||
raise forms.ValidationError(_('This field is required.'))
|
||||
raise forms.ValidationError(_("This field is required."))
|
||||
return content
|
||||
|
||||
def clean_expires(self):
|
||||
"""
|
||||
Extract the 'expire_type' from the choice of expire choices.
|
||||
"""
|
||||
expires = self.cleaned_data['expires']
|
||||
expires = self.cleaned_data["expires"]
|
||||
expires, expire_type = get_expire_values(expires)
|
||||
self.cleaned_data['expire_type'] = expire_type
|
||||
self.cleaned_data["expire_type"] = expire_type
|
||||
return expires
|
||||
|
||||
def clean(self):
|
||||
|
@ -92,8 +92,8 @@ class SnippetForm(forms.ModelForm):
|
|||
The `title` field is a hidden honeypot field. If its filled,
|
||||
this is likely spam.
|
||||
"""
|
||||
if self.cleaned_data.get('title'):
|
||||
raise forms.ValidationError('This snippet was identified as Spam.')
|
||||
if self.cleaned_data.get("title"):
|
||||
raise forms.ValidationError("This snippet was identified as Spam.")
|
||||
return self.cleaned_data
|
||||
|
||||
def save(self, parent=None, *args, **kwargs):
|
||||
|
@ -102,17 +102,17 @@ class SnippetForm(forms.ModelForm):
|
|||
|
||||
# Add expire timestamp. None indicates 'keep forever', use the default
|
||||
# null state of the db column for that.
|
||||
self.instance.expires = self.cleaned_data['expires']
|
||||
self.instance.expire_type = self.cleaned_data['expire_type']
|
||||
self.instance.expires = self.cleaned_data["expires"]
|
||||
self.instance.expire_type = self.cleaned_data["expire_type"]
|
||||
|
||||
# Save snippet in the db
|
||||
super(SnippetForm, self).save(*args, **kwargs)
|
||||
|
||||
# Add the snippet to the user session list
|
||||
self.request.session.setdefault('snippet_list', [])
|
||||
self.request.session['snippet_list'] += [self.instance.pk]
|
||||
self.request.session.setdefault("snippet_list", [])
|
||||
self.request.session["snippet_list"] += [self.instance.pk]
|
||||
|
||||
# Save the lexer in the session so we can use it later again
|
||||
self.request.session['lexer'] = self.cleaned_data['lexer']
|
||||
self.request.session["lexer"] = self.cleaned_data["lexer"]
|
||||
|
||||
return self.instance
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.apps import apps
|
|||
from django.template.defaultfilters import escape, linebreaksbr
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from pygments import highlight
|
||||
from pygments.formatters.html import HtmlFormatter
|
||||
from pygments.lexers import get_lexer_by_name
|
||||
|
@ -12,7 +12,7 @@ from pygments.lexers.python import PythonLexer
|
|||
from pygments.util import ClassNotFound
|
||||
|
||||
logger = getLogger(__file__)
|
||||
config = apps.get_app_config('dpaste')
|
||||
config = apps.get_app_config("dpaste")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
@ -21,14 +21,14 @@ config = apps.get_app_config('dpaste')
|
|||
|
||||
|
||||
class Highlighter(object):
|
||||
template_name = 'dpaste/highlight/code.html'
|
||||
template_name = "dpaste/highlight/code.html"
|
||||
|
||||
def highlight(self, code_string, lexer_name=None):
|
||||
"""Subclasses need to override this."""
|
||||
return code_string
|
||||
|
||||
@staticmethod
|
||||
def get_lexer_display_name(lexer_name, fallback=_('(Deprecated Lexer)')):
|
||||
def get_lexer_display_name(lexer_name, fallback=_("(Deprecated Lexer)")):
|
||||
for l in config.TEXT_FORMATTER + config.CODE_FORMATTER:
|
||||
if l[0] == lexer_name:
|
||||
return l[1]
|
||||
|
@ -37,11 +37,11 @@ class Highlighter(object):
|
|||
def render(self, code_string, lexer_name, direction=None, **kwargs):
|
||||
highlighted_string = self.highlight(code_string, lexer_name=lexer_name)
|
||||
context = {
|
||||
'highlighted': highlighted_string,
|
||||
'highlighted_splitted': highlighted_string.splitlines(),
|
||||
'lexer_name': lexer_name,
|
||||
'lexer_display_name': self.get_lexer_display_name(lexer_name),
|
||||
'direction': direction,
|
||||
"highlighted": highlighted_string,
|
||||
"highlighted_splitted": highlighted_string.splitlines(),
|
||||
"lexer_name": lexer_name,
|
||||
"lexer_display_name": self.get_lexer_display_name(lexer_name),
|
||||
"direction": direction,
|
||||
}
|
||||
context.update(kwargs)
|
||||
return render_to_string(self.template_name, context)
|
||||
|
@ -50,7 +50,7 @@ class Highlighter(object):
|
|||
class PlainTextHighlighter(Highlighter):
|
||||
"""Plain Text. Just replace linebreaks."""
|
||||
|
||||
template_name = 'dpaste/highlight/text.html'
|
||||
template_name = "dpaste/highlight/text.html"
|
||||
|
||||
def highlight(self, code_string, **kwargs):
|
||||
return linebreaksbr(code_string)
|
||||
|
@ -60,17 +60,17 @@ class MarkdownHighlighter(PlainTextHighlighter):
|
|||
"""Markdown"""
|
||||
|
||||
extensions = (
|
||||
'tables',
|
||||
'fenced-code',
|
||||
'footnotes',
|
||||
'autolink,',
|
||||
'strikethrough',
|
||||
'underline',
|
||||
'quote',
|
||||
'superscript',
|
||||
'math',
|
||||
"tables",
|
||||
"fenced-code",
|
||||
"footnotes",
|
||||
"autolink,",
|
||||
"strikethrough",
|
||||
"underline",
|
||||
"quote",
|
||||
"superscript",
|
||||
"math",
|
||||
)
|
||||
render_flags = ('skip-html',)
|
||||
render_flags = ("skip-html",)
|
||||
|
||||
def highlight(self, code_string, **kwargs):
|
||||
import misaka
|
||||
|
@ -87,22 +87,22 @@ class MarkdownHighlighter(PlainTextHighlighter):
|
|||
class RestructuredTextHighlighter(PlainTextHighlighter):
|
||||
"""Restructured Text"""
|
||||
|
||||
rst_part_name = 'html_body'
|
||||
rst_part_name = "html_body"
|
||||
publish_args = {
|
||||
'writer_name': 'html5_polyglot',
|
||||
'settings_overrides': {
|
||||
'raw_enabled': False,
|
||||
'file_insertion_enabled': False,
|
||||
'halt_level': 5,
|
||||
'report_level': 2,
|
||||
'warning_stream': '/dev/null',
|
||||
"writer_name": "html5_polyglot",
|
||||
"settings_overrides": {
|
||||
"raw_enabled": False,
|
||||
"file_insertion_enabled": False,
|
||||
"halt_level": 5,
|
||||
"report_level": 2,
|
||||
"warning_stream": "/dev/null",
|
||||
},
|
||||
}
|
||||
|
||||
def highlight(self, code_string, **kwargs):
|
||||
from docutils.core import publish_parts
|
||||
|
||||
self.publish_args['source'] = code_string
|
||||
self.publish_args["source"] = code_string
|
||||
parts = publish_parts(**self.publish_args)
|
||||
return mark_safe(parts[self.rst_part_name])
|
||||
|
||||
|
@ -126,9 +126,9 @@ class PlainCodeHighlighter(Highlighter):
|
|||
"""
|
||||
|
||||
def highlight(self, code_string, **kwargs):
|
||||
return '\n'.join(
|
||||
return "\n".join(
|
||||
[
|
||||
'<span class="plain">{}</span>'.format(escape(l) or '​')
|
||||
'<span class="plain">{}</span>'.format(escape(l) or "​")
|
||||
for l in code_string.splitlines()
|
||||
]
|
||||
)
|
||||
|
@ -149,7 +149,7 @@ class PygmentsHighlighter(Highlighter):
|
|||
try:
|
||||
self.lexer = get_lexer_by_name(lexer_name)
|
||||
except ClassNotFound:
|
||||
logger.warning('Lexer for given name %s not found', lexer_name)
|
||||
logger.warning("Lexer for given name %s not found", lexer_name)
|
||||
self.lexer = self.lexer_fallback
|
||||
|
||||
return highlight(code_string, self.lexer, self.formatter)
|
||||
|
@ -190,8 +190,8 @@ def get_highlighter_class(lexer_name):
|
|||
|
||||
# Generate a list of Form choices of all lexer.
|
||||
LEXER_CHOICES = (
|
||||
(_('Text'), [i[:2] for i in config.TEXT_FORMATTER]),
|
||||
(_('Code'), [i[:2] for i in config.CODE_FORMATTER]),
|
||||
(_("Text"), [i[:2] for i in config.TEXT_FORMATTER]),
|
||||
(_("Code"), [i[:2] for i in config.CODE_FORMATTER]),
|
||||
)
|
||||
|
||||
# List of all Lexer Keys
|
||||
|
|
|
@ -9,10 +9,10 @@ class Command(BaseCommand):
|
|||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'--dry-run',
|
||||
action='store_true',
|
||||
dest='dry_run',
|
||||
help='Don\'t do anything.',
|
||||
"--dry-run",
|
||||
action="store_true",
|
||||
dest="dry_run",
|
||||
help="Don't do anything.",
|
||||
),
|
||||
|
||||
def handle(self, *args, **options):
|
||||
|
@ -29,7 +29,7 @@ class Command(BaseCommand):
|
|||
)
|
||||
for d in deleteable_snippets:
|
||||
self.stdout.write(u"- %s (%s)\n" % (d.secret_id, d.expires))
|
||||
if options.get('dry_run'):
|
||||
self.stdout.write('Dry run - Not actually deleting snippets!\n')
|
||||
if options.get("dry_run"):
|
||||
self.stdout.write("Dry run - Not actually deleting snippets!\n")
|
||||
else:
|
||||
deleteable_snippets.delete()
|
||||
|
|
|
@ -4,12 +4,12 @@ from random import SystemRandom
|
|||
from django.apps import apps
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from six import python_2_unicode_compatible
|
||||
|
||||
from dpaste import highlight
|
||||
|
||||
config = apps.get_app_config('dpaste')
|
||||
config = apps.get_app_config("dpaste")
|
||||
logger = getLogger(__file__)
|
||||
R = SystemRandom()
|
||||
|
||||
|
@ -17,11 +17,11 @@ R = SystemRandom()
|
|||
def generate_secret_id(length):
|
||||
if length > config.SLUG_LENGTH:
|
||||
logger.warning(
|
||||
'Slug creation triggered a duplicate, '
|
||||
'consider increasing the SLUG_LENGTH.'
|
||||
"Slug creation triggered a duplicate, "
|
||||
"consider increasing the SLUG_LENGTH."
|
||||
)
|
||||
|
||||
secret_id = ''.join(
|
||||
secret_id = "".join(
|
||||
[
|
||||
R.choice(config.SLUG_CHOICES)
|
||||
for i in range(length or config.SLUG_LENGTH)
|
||||
|
@ -45,37 +45,37 @@ class Snippet(models.Model):
|
|||
EXPIRE_KEEP = 2
|
||||
EXPIRE_ONETIME = 3
|
||||
EXPIRE_CHOICES = (
|
||||
(EXPIRE_TIME, _('Expire by timestamp')),
|
||||
(EXPIRE_KEEP, _('Keep Forever')),
|
||||
(EXPIRE_ONETIME, _('One-Time snippet')),
|
||||
(EXPIRE_TIME, _("Expire by timestamp")),
|
||||
(EXPIRE_KEEP, _("Keep Forever")),
|
||||
(EXPIRE_ONETIME, _("One-Time snippet")),
|
||||
)
|
||||
|
||||
secret_id = models.CharField(
|
||||
_('Secret ID'), max_length=255, blank=True, null=True, unique=True
|
||||
_("Secret ID"), max_length=255, blank=True, null=True, unique=True
|
||||
)
|
||||
content = models.TextField(_('Content'))
|
||||
content = models.TextField(_("Content"))
|
||||
lexer = models.CharField(
|
||||
_('Lexer'), max_length=30, default=highlight.LEXER_DEFAULT
|
||||
_("Lexer"), max_length=30, default=highlight.LEXER_DEFAULT
|
||||
)
|
||||
published = models.DateTimeField(_('Published'), auto_now_add=True)
|
||||
published = models.DateTimeField(_("Published"), auto_now_add=True)
|
||||
expire_type = models.PositiveSmallIntegerField(
|
||||
_('Expire Type'), choices=EXPIRE_CHOICES, default=EXPIRE_CHOICES[0][0]
|
||||
_("Expire Type"), choices=EXPIRE_CHOICES, default=EXPIRE_CHOICES[0][0]
|
||||
)
|
||||
expires = models.DateTimeField(_('Expires'), blank=True, null=True)
|
||||
view_count = models.PositiveIntegerField(_('View count'), default=0)
|
||||
rtl = models.BooleanField(_('Right-to-left'), default=False)
|
||||
expires = models.DateTimeField(_("Expires"), blank=True, null=True)
|
||||
view_count = models.PositiveIntegerField(_("View count"), default=0)
|
||||
rtl = models.BooleanField(_("Right-to-left"), default=False)
|
||||
parent = models.ForeignKey(
|
||||
'self',
|
||||
"self",
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name=_('Parent Snippet'),
|
||||
related_name='children',
|
||||
verbose_name=_("Parent Snippet"),
|
||||
related_name="children",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
ordering = ('-published',)
|
||||
db_table = 'dpaste_snippet'
|
||||
ordering = ("-published",)
|
||||
db_table = "dpaste_snippet"
|
||||
|
||||
def __str__(self):
|
||||
return self.secret_id
|
||||
|
@ -86,14 +86,14 @@ class Snippet(models.Model):
|
|||
super(Snippet, self).save(*args, **kwargs)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('snippet_details', kwargs={'snippet_id': self.secret_id})
|
||||
return reverse("snippet_details", kwargs={"snippet_id": self.secret_id})
|
||||
|
||||
def highlight(self):
|
||||
HighlighterClass = highlight.get_highlighter_class(self.lexer)
|
||||
return HighlighterClass().render(
|
||||
code_string=self.content,
|
||||
lexer_name=self.lexer,
|
||||
direction='rtl' if self.rtl else 'ltr',
|
||||
direction="rtl" if self.rtl else "ltr",
|
||||
)
|
||||
|
||||
@property
|
||||
|
|
|
@ -14,17 +14,17 @@ PROJECT_DIR, PROJECT_MODULE_NAME = os.path.split(
|
|||
)
|
||||
|
||||
PYTHON_BIN = os.path.dirname(sys.executable)
|
||||
if os.path.exists(os.path.join(PYTHON_BIN, 'activate_this.py')):
|
||||
if os.path.exists(os.path.join(PYTHON_BIN, "activate_this.py")):
|
||||
# Assume that the presence of 'activate_this.py' in the python bin/
|
||||
# directory means that we're running in a virtual environment. Set the
|
||||
# variable root to $VIRTUALENV/var.
|
||||
VAR_ROOT = os.path.join(os.path.dirname(PYTHON_BIN), 'var')
|
||||
VAR_ROOT = os.path.join(os.path.dirname(PYTHON_BIN), "var")
|
||||
if not os.path.exists(VAR_ROOT):
|
||||
os.mkdir(VAR_ROOT)
|
||||
else:
|
||||
# Set the variable root to the local configuration location (which is
|
||||
# ignored by the repository).
|
||||
VAR_ROOT = os.path.join(PROJECT_DIR, PROJECT_MODULE_NAME, 'conf', 'local')
|
||||
VAR_ROOT = os.path.join(PROJECT_DIR, PROJECT_MODULE_NAME, "conf", "local")
|
||||
|
||||
# ==============================================================================
|
||||
# Generic Django project settings
|
||||
|
@ -34,13 +34,13 @@ DEBUG = False
|
|||
|
||||
# Local time zone for this installation. Choices can be found here:
|
||||
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
||||
TIME_ZONE = 'UTC'
|
||||
TIME_ZONE = "UTC"
|
||||
SITE_ID = 1
|
||||
|
||||
# Make this unique, and don't share it with anybody.
|
||||
SECRET_KEY = ''
|
||||
SECRET_KEY = ""
|
||||
|
||||
ALLOWED_HOSTS = ['*']
|
||||
ALLOWED_HOSTS = ["*"]
|
||||
|
||||
# ==============================================================================
|
||||
# I18N
|
||||
|
@ -49,8 +49,8 @@ ALLOWED_HOSTS = ['*']
|
|||
USE_I18N = True
|
||||
USE_L10N = False
|
||||
|
||||
LANGUAGE_CODE = 'en'
|
||||
LANGUAGES = (('en', 'English'),)
|
||||
LANGUAGE_CODE = "en"
|
||||
LANGUAGES = (("en", "English"),)
|
||||
|
||||
# LOCALE_PATHS = (
|
||||
# os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'locale')),
|
||||
|
@ -61,59 +61,59 @@ LANGUAGES = (('en', 'English'),)
|
|||
# ==============================================================================
|
||||
|
||||
STATICFILES_STORAGE = (
|
||||
'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'
|
||||
"django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
|
||||
)
|
||||
|
||||
STATICFILES_FINDERS = (
|
||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||
"django.contrib.staticfiles.finders.FileSystemFinder",
|
||||
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
|
||||
)
|
||||
|
||||
STATIC_ROOT = os.path.join(VAR_ROOT, 'static')
|
||||
STATIC_ROOT = os.path.join(VAR_ROOT, "static")
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
ADMIN_MEDIA_PREFIX = '/static/admin/'
|
||||
STATIC_URL = "/static/"
|
||||
ADMIN_MEDIA_PREFIX = "/static/admin/"
|
||||
|
||||
ROOT_URLCONF = 'dpaste.urls'
|
||||
ROOT_URLCONF = "dpaste.urls"
|
||||
|
||||
LOGIN_URL = '/accounts/login/'
|
||||
LOGOUT_URL = '/accounts/logout/'
|
||||
LOGIN_REDIRECT_URL = '/'
|
||||
LOGIN_URL = "/accounts/login/"
|
||||
LOGOUT_URL = "/accounts/logout/"
|
||||
LOGIN_REDIRECT_URL = "/"
|
||||
|
||||
# ==============================================================================
|
||||
# Templates
|
||||
# ==============================================================================
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.locale.LocaleMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'csp.middleware.CSPMiddleware',
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.locale.LocaleMiddleware",
|
||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
"csp.middleware.CSPMiddleware",
|
||||
]
|
||||
|
||||
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.template.context_processors.i18n',
|
||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||
"DIRS": [],
|
||||
"APP_DIRS": True,
|
||||
"OPTIONS": {
|
||||
"context_processors": [
|
||||
"django.template.context_processors.debug",
|
||||
"django.template.context_processors.request",
|
||||
"django.template.context_processors.i18n",
|
||||
]
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'django.contrib.staticfiles',
|
||||
'django.contrib.sessions',
|
||||
'staticinline.apps.StaticInlineAppConfig',
|
||||
'dpaste.apps.dpasteAppConfig',
|
||||
"django.contrib.staticfiles",
|
||||
"django.contrib.sessions",
|
||||
"staticinline.apps.StaticInlineAppConfig",
|
||||
"dpaste.apps.dpasteAppConfig",
|
||||
]
|
||||
|
||||
# DATABASES = {
|
||||
|
@ -132,7 +132,7 @@ INSTALLED_APPS = [
|
|||
SESSION_COOKIE_SECURE = True
|
||||
CSRF_COOKIE_SECURE = True
|
||||
|
||||
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
||||
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
||||
SECURE_BROWSER_XSS_FILTER = True
|
||||
SECURE_CONTENT_TYPE_NOSNIFF = True
|
||||
|
||||
|
@ -141,23 +141,23 @@ CSP_SCRIPT_SRC = ("'self'", "'unsafe-inline'")
|
|||
CSP_STYLE_SRC = ("'self'", "'unsafe-inline'")
|
||||
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'filters': {
|
||||
'require_debug_false': {'()': 'django.utils.log.RequireDebugFalse'}
|
||||
"version": 1,
|
||||
"disable_existing_loggers": False,
|
||||
"filters": {
|
||||
"require_debug_false": {"()": "django.utils.log.RequireDebugFalse"}
|
||||
},
|
||||
'handlers': {
|
||||
'mail_admins': {
|
||||
'level': 'ERROR',
|
||||
'filters': ['require_debug_false'],
|
||||
'class': 'django.utils.log.AdminEmailHandler',
|
||||
"handlers": {
|
||||
"mail_admins": {
|
||||
"level": "ERROR",
|
||||
"filters": ["require_debug_false"],
|
||||
"class": "django.utils.log.AdminEmailHandler",
|
||||
}
|
||||
},
|
||||
'loggers': {
|
||||
'django.request': {
|
||||
'handlers': ['mail_admins'],
|
||||
'level': 'ERROR',
|
||||
'propagate': True,
|
||||
"loggers": {
|
||||
"django.request": {
|
||||
"handlers": ["mail_admins"],
|
||||
"level": "ERROR",
|
||||
"propagate": True,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ if not 'runsslserver' in sys.argv:
|
|||
#
|
||||
|
||||
# from dpaste.apps import dpasteAppConfig
|
||||
# from django.utils.translation import ugettext_lazy as _
|
||||
# from django.utils.translation import gettext_lazy as _
|
||||
#
|
||||
# class ProductionDpasteAppConfig(dpasteAppConfig):
|
||||
# SLUG_LENGTH = 8
|
||||
|
|
|
@ -5,13 +5,13 @@ import django
|
|||
|
||||
from .base import *
|
||||
|
||||
SECRET_KEY = 'test-key'
|
||||
SECRET_KEY = "test-key"
|
||||
|
||||
DATABASES = {
|
||||
'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}
|
||||
"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}
|
||||
}
|
||||
|
||||
# Drop CSP middleware for Django 3.0 until it was fixed upstream
|
||||
# https://github.com/mozilla/django-csp/issues/129
|
||||
if django.get_version().startswith('3.'):
|
||||
MIDDLEWARE.remove('csp.middleware.CSPMiddleware')
|
||||
if django.get_version().startswith("3."):
|
||||
MIDDLEWARE.remove("csp.middleware.CSPMiddleware")
|
||||
|
|
|
@ -7,12 +7,12 @@ from django.urls import reverse
|
|||
|
||||
from ..models import Snippet
|
||||
|
||||
config = apps.get_app_config('dpaste')
|
||||
config = apps.get_app_config("dpaste")
|
||||
|
||||
|
||||
class SnippetAPITestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.api_url = reverse('dpaste_api_create_snippet')
|
||||
self.api_url = reverse("dpaste_api_create_snippet")
|
||||
self.client = Client(enforce_csrf_checks=True)
|
||||
|
||||
def test_empty(self):
|
||||
|
@ -27,19 +27,19 @@ class SnippetAPITestCase(TestCase):
|
|||
self.assertEqual(Snippet.objects.count(), 0)
|
||||
|
||||
# No content
|
||||
data['content'] = ''
|
||||
data["content"] = ""
|
||||
response = self.client.post(self.api_url, data)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(Snippet.objects.count(), 0)
|
||||
|
||||
# Just some spaces
|
||||
data['content'] = ' '
|
||||
data["content"] = " "
|
||||
response = self.client.post(self.api_url, data)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(Snippet.objects.count(), 0)
|
||||
|
||||
# Linebreaks or tabs only are not valid either
|
||||
data['content'] = '\n\t '
|
||||
data["content"] = "\n\t "
|
||||
response = self.client.post(self.api_url, data)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(Snippet.objects.count(), 0)
|
||||
|
@ -48,10 +48,10 @@ class SnippetAPITestCase(TestCase):
|
|||
"""
|
||||
A valid snippet, contains Unicode, tabs, spaces, linebreaks etc.
|
||||
"""
|
||||
data = {'content': u"Hello Wörld.\n\tGood Bye"}
|
||||
data = {"content": u"Hello Wörld.\n\tGood Bye"}
|
||||
|
||||
response = self.client.post(self.api_url, data)
|
||||
content = response.content.decode('utf-8')
|
||||
content = response.content.decode("utf-8")
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
@ -65,36 +65,36 @@ class SnippetAPITestCase(TestCase):
|
|||
response = self.client.get(content[1:-1])
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, data['content'])
|
||||
self.assertContains(response, data["content"])
|
||||
|
||||
def test_new_url_format(self):
|
||||
"""
|
||||
The 'new' url format is just the link with a linebreak.
|
||||
"""
|
||||
data = {'content': u"Hello Wörld.\n\tGood Bye", 'format': 'url'}
|
||||
data = {"content": u"Hello Wörld.\n\tGood Bye", "format": "url"}
|
||||
|
||||
response = self.client.post(self.api_url, data)
|
||||
content = response.content.decode('utf-8')
|
||||
content = response.content.decode("utf-8")
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
||||
# Response is just the link starting with http(s) and ends with a linebreak
|
||||
self.assertTrue(content.startswith('http'))
|
||||
self.assertTrue(content.endswith('\n'))
|
||||
self.assertTrue(content.startswith("http"))
|
||||
self.assertTrue(content.endswith("\n"))
|
||||
|
||||
def test_json_format(self):
|
||||
"""
|
||||
The 'new' url format is just the link with a linebreak.
|
||||
"""
|
||||
data = {
|
||||
'content': u"Hello Wörld.\n\tGood Bye",
|
||||
'format': 'json',
|
||||
'lexer': 'haskell',
|
||||
"content": u"Hello Wörld.\n\tGood Bye",
|
||||
"format": "json",
|
||||
"lexer": "haskell",
|
||||
}
|
||||
|
||||
response = self.client.post(self.api_url, data)
|
||||
content = response.content.decode('utf-8')
|
||||
content = response.content.decode("utf-8")
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
@ -104,9 +104,9 @@ class SnippetAPITestCase(TestCase):
|
|||
json_data = loads(content)
|
||||
|
||||
# Response is valid json, containing, content, lexer and url
|
||||
self.assertEqual(json_data['content'], data['content'])
|
||||
self.assertEqual(json_data['lexer'], data['lexer'])
|
||||
self.assertTrue(json_data['url'].startswith('http'))
|
||||
self.assertEqual(json_data["content"], data["content"])
|
||||
self.assertEqual(json_data["lexer"], data["lexer"])
|
||||
self.assertTrue(json_data["url"].startswith("http"))
|
||||
|
||||
def test_invalid_format(self):
|
||||
"""
|
||||
|
@ -115,9 +115,9 @@ class SnippetAPITestCase(TestCase):
|
|||
"""
|
||||
|
||||
data = {
|
||||
'content': u"Hello Wörld.\n\tGood Bye",
|
||||
'format': 'broken-format',
|
||||
'lexer': 'haskell',
|
||||
"content": u"Hello Wörld.\n\tGood Bye",
|
||||
"format": "broken-format",
|
||||
"lexer": "haskell",
|
||||
}
|
||||
|
||||
response = self.client.post(self.api_url, data)
|
||||
|
@ -128,7 +128,7 @@ class SnippetAPITestCase(TestCase):
|
|||
"""
|
||||
A broken lexer will fail loudly.
|
||||
"""
|
||||
data = {'content': u"Hello Wörld.\n\tGood Bye", 'lexer': 'foobar'}
|
||||
data = {"content": u"Hello Wörld.\n\tGood Bye", "lexer": "foobar"}
|
||||
response = self.client.post(self.api_url, data)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(Snippet.objects.count(), 0)
|
||||
|
@ -136,7 +136,7 @@ class SnippetAPITestCase(TestCase):
|
|||
def test_expire_choices_none_given(self):
|
||||
# No expire choice given will set a default expiration of one month
|
||||
response = self.client.post(
|
||||
self.api_url, {'content': u"Hello Wörld.\n\tGood Bye"}
|
||||
self.api_url, {"content": u"Hello Wörld.\n\tGood Bye"}
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
@ -146,7 +146,7 @@ class SnippetAPITestCase(TestCase):
|
|||
# A expire choice that does not exist returns a BadRequest
|
||||
response = self.client.post(
|
||||
self.api_url,
|
||||
{'content': u"Hello Wörld.\n\tGood Bye", 'expires': 'foobar'},
|
||||
{"content": u"Hello Wörld.\n\tGood Bye", "expires": "foobar"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(Snippet.objects.count(), 0)
|
||||
|
@ -159,7 +159,7 @@ class SnippetAPITestCase(TestCase):
|
|||
def test_valid_expiration_choices_onetime(self):
|
||||
response = self.client.post(
|
||||
self.api_url,
|
||||
{'content': u"Hello Wörld.\n\tGood Bye", 'expires': 'onetime'},
|
||||
{"content": u"Hello Wörld.\n\tGood Bye", "expires": "onetime"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
@ -170,7 +170,7 @@ class SnippetAPITestCase(TestCase):
|
|||
def test_valid_expiration_choices_never(self):
|
||||
response = self.client.post(
|
||||
self.api_url,
|
||||
{'content': u"Hello Wörld.\n\tGood Bye", 'expires': 'never'},
|
||||
{"content": u"Hello Wörld.\n\tGood Bye", "expires": "never"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
@ -181,7 +181,7 @@ class SnippetAPITestCase(TestCase):
|
|||
def test_valid_expiration_choices_hour(self):
|
||||
response = self.client.post(
|
||||
self.api_url,
|
||||
{'content': u"Hello Wörld.\n\tGood Bye", 'expires': 3600},
|
||||
{"content": u"Hello Wörld.\n\tGood Bye", "expires": 3600},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
@ -190,7 +190,7 @@ class SnippetAPITestCase(TestCase):
|
|||
def test_valid_expiration_choices_week(self):
|
||||
response = self.client.post(
|
||||
self.api_url,
|
||||
{'content': u"Hello Wörld.\n\tGood Bye", 'expires': 3600 * 24 * 7},
|
||||
{"content": u"Hello Wörld.\n\tGood Bye", "expires": 3600 * 24 * 7},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
@ -199,7 +199,7 @@ class SnippetAPITestCase(TestCase):
|
|||
def test_valid_expiration_choices_month(self):
|
||||
response = self.client.post(
|
||||
self.api_url,
|
||||
{'content': u"Hello Wörld.\n\tGood Bye", 'expires': 3600 * 24 * 30},
|
||||
{"content": u"Hello Wörld.\n\tGood Bye", "expires": 3600 * 24 * 30},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
@ -212,9 +212,9 @@ class SnippetAPITestCase(TestCase):
|
|||
response = self.client.post(
|
||||
self.api_url,
|
||||
{
|
||||
'content': u"Hello Wörld.\n\tGood Bye",
|
||||
'lexer': '',
|
||||
'filename': '',
|
||||
"content": u"Hello Wörld.\n\tGood Bye",
|
||||
"lexer": "",
|
||||
"filename": "",
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
@ -226,14 +226,14 @@ class SnippetAPITestCase(TestCase):
|
|||
response = self.client.post(
|
||||
self.api_url,
|
||||
{
|
||||
'content': u"Hello Wörld.\n\tGood Bye",
|
||||
'lexer': '',
|
||||
'filename': 'helloworld.py',
|
||||
"content": u"Hello Wörld.\n\tGood Bye",
|
||||
"lexer": "",
|
||||
"filename": "helloworld.py",
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
self.assertEqual(Snippet.objects.all()[0].lexer, 'python')
|
||||
self.assertEqual(Snippet.objects.all()[0].lexer, "python")
|
||||
|
||||
def test_awkward_filename_given(self):
|
||||
"""
|
||||
|
@ -242,9 +242,9 @@ class SnippetAPITestCase(TestCase):
|
|||
response = self.client.post(
|
||||
self.api_url,
|
||||
{
|
||||
'content': u"Hello Wörld.\n\tGood Bye",
|
||||
'lexer': '',
|
||||
'filename': 'helloworld.helloworld',
|
||||
"content": u"Hello Wörld.\n\tGood Bye",
|
||||
"lexer": "",
|
||||
"filename": "helloworld.helloworld",
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
@ -260,19 +260,19 @@ class SnippetAPITestCase(TestCase):
|
|||
response = self.client.post(
|
||||
self.api_url,
|
||||
{
|
||||
'content': u"Hello Wörld.\n\tGood Bye",
|
||||
'lexer': 'php',
|
||||
'filename': 'helloworld.py',
|
||||
"content": u"Hello Wörld.\n\tGood Bye",
|
||||
"lexer": "php",
|
||||
"filename": "helloworld.py",
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
self.assertEqual(Snippet.objects.all()[0].lexer, 'php')
|
||||
self.assertEqual(Snippet.objects.all()[0].lexer, "php")
|
||||
|
||||
def test_leading_white_is_retained(self):
|
||||
"""
|
||||
Leading Whitespace is retained in the db.
|
||||
"""
|
||||
content = ' one\n two\n three\n four'
|
||||
self.client.post(self.api_url, {'content': content})
|
||||
content = " one\n two\n three\n four"
|
||||
self.client.post(self.api_url, {"content": content})
|
||||
self.assertEqual(Snippet.objects.all()[0].content, content)
|
||||
|
|
|
@ -16,7 +16,7 @@ class HighlightAPITestCase(TestCase):
|
|||
"""
|
||||
PLAIN_CODE is not run through Pygments, test it separately.
|
||||
"""
|
||||
input = 'vär'
|
||||
input = "vär"
|
||||
expected = '<span class="plain">vär</span>'
|
||||
value = PlainCodeHighlighter().highlight(input)
|
||||
self.assertEqual(value, expected)
|
||||
|
@ -25,7 +25,7 @@ class HighlightAPITestCase(TestCase):
|
|||
"""
|
||||
Whitespace on the first line is retained.
|
||||
"""
|
||||
input = ' vär=1'
|
||||
input = " vär=1"
|
||||
expected = '<span class="plain"> vär=1</span>'
|
||||
value = PlainCodeHighlighter().highlight(input)
|
||||
self.assertEqual(value, expected)
|
||||
|
@ -34,7 +34,7 @@ class HighlightAPITestCase(TestCase):
|
|||
"""
|
||||
Whitespace on the first line is retained, also on subsequent lines.
|
||||
"""
|
||||
input = ' vär=1\n' ' vär=2\n' ' vär=3\n' ' vär=4'
|
||||
input = " vär=1\n" " vär=2\n" " vär=3\n" " vär=4"
|
||||
expected = (
|
||||
'<span class="plain"> vär=1</span>\n'
|
||||
'<span class="plain"> vär=2</span>\n'
|
||||
|
@ -49,32 +49,32 @@ class HighlightAPITestCase(TestCase):
|
|||
Pygemnts highlights the variable name, and also generally adds
|
||||
a trailing \n to all its result.
|
||||
"""
|
||||
input = 'var'
|
||||
input = "var"
|
||||
expected = '<span class="n">var</span>\n'
|
||||
value = PygmentsHighlighter().highlight(input, 'python')
|
||||
value = PygmentsHighlighter().highlight(input, "python")
|
||||
self.assertEqual(value, expected)
|
||||
|
||||
def test_pygments_leading_whitespace(self):
|
||||
"""
|
||||
Whitespace on the first line is retained.
|
||||
"""
|
||||
input = ' var'
|
||||
input = " var"
|
||||
expected = ' <span class="n">var</span>\n'
|
||||
value = PygmentsHighlighter().highlight(input, 'python')
|
||||
value = PygmentsHighlighter().highlight(input, "python")
|
||||
self.assertEqual(value, expected)
|
||||
|
||||
def test_pygments_leading_whitespace_multiline(self):
|
||||
"""
|
||||
Whitespace on the first line is retained, also on subsequent lines.
|
||||
"""
|
||||
input = ' var\n' ' var\n' ' var\n' ' var'
|
||||
input = " var\n" " var\n" " var\n" " var"
|
||||
expected = (
|
||||
' <span class="n">var</span>\n'
|
||||
' <span class="n">var</span>\n'
|
||||
' <span class="n">var</span>\n'
|
||||
' <span class="n">var</span>\n'
|
||||
)
|
||||
value = PygmentsHighlighter().highlight(input, 'python')
|
||||
value = PygmentsHighlighter().highlight(input, "python")
|
||||
self.assertEqual(value, expected)
|
||||
|
||||
def test_broken_rst_syntax(self):
|
||||
|
@ -93,4 +93,4 @@ class HighlightAPITestCase(TestCase):
|
|||
try:
|
||||
RestructuredTextHighlighter().highlight(input)
|
||||
except Exception as e:
|
||||
self.fail('rst syntax raised unexpected exception: {}'.format(e))
|
||||
self.fail(f"rst syntax raised unexpected exception: {e}")
|
||||
|
|
|
@ -11,26 +11,26 @@ from django.urls import reverse
|
|||
from ..highlight import PygmentsHighlighter
|
||||
from ..models import Snippet
|
||||
|
||||
config = apps.get_app_config('dpaste')
|
||||
config = apps.get_app_config("dpaste")
|
||||
|
||||
|
||||
class SnippetTestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.client = Client()
|
||||
self.new_url = reverse('snippet_new')
|
||||
self.new_url = reverse("snippet_new")
|
||||
|
||||
def valid_form_data(self, **kwargs):
|
||||
data = {
|
||||
'content': u"Hello Wörld.\n\tGood Bye",
|
||||
'lexer': config.LEXER_DEFAULT,
|
||||
'expires': config.EXPIRE_DEFAULT,
|
||||
"content": u"Hello Wörld.\n\tGood Bye",
|
||||
"lexer": config.LEXER_DEFAULT,
|
||||
"expires": config.EXPIRE_DEFAULT,
|
||||
}
|
||||
if kwargs:
|
||||
data.update(kwargs)
|
||||
return data
|
||||
|
||||
def test_about(self):
|
||||
response = self.client.get(reverse('dpaste_about'))
|
||||
response = self.client.get(reverse("dpaste_about"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
@ -47,17 +47,17 @@ class SnippetTestCase(TestCase):
|
|||
data = self.valid_form_data()
|
||||
|
||||
# No content
|
||||
data['content'] = ''
|
||||
data["content"] = ""
|
||||
self.client.post(self.new_url, data)
|
||||
self.assertEqual(Snippet.objects.count(), 0)
|
||||
|
||||
# Just some spaces
|
||||
data['content'] = ' '
|
||||
data["content"] = " "
|
||||
self.client.post(self.new_url, data)
|
||||
self.assertEqual(Snippet.objects.count(), 0)
|
||||
|
||||
# Linebreaks or tabs only are not valid either
|
||||
data['content'] = '\n\t '
|
||||
data["content"] = "\n\t "
|
||||
self.client.post(self.new_url, data)
|
||||
self.assertEqual(Snippet.objects.count(), 0)
|
||||
|
||||
|
@ -70,7 +70,7 @@ class SnippetTestCase(TestCase):
|
|||
response = self.client.post(self.new_url, data, follow=True)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
self.assertContains(response, data['content'])
|
||||
self.assertContains(response, data["content"])
|
||||
|
||||
# The unicode method contains the snippet id so we can easily print
|
||||
# the id using {{ snippet }}
|
||||
|
@ -80,7 +80,7 @@ class SnippetTestCase(TestCase):
|
|||
def test_new_snippet_custom_lexer(self):
|
||||
# You can pass a lexer key in GET.l
|
||||
data = self.valid_form_data()
|
||||
url = '%s?l=haskell' % self.new_url
|
||||
url = "%s?l=haskell" % self.new_url
|
||||
response = self.client.post(url, data, follow=True)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
@ -89,7 +89,7 @@ class SnippetTestCase(TestCase):
|
|||
# If you pass an invalid key it wont fail and just fallback
|
||||
# to the default lexer.
|
||||
data = self.valid_form_data()
|
||||
url = '%s?l=invalid-lexer' % self.new_url
|
||||
url = "%s?l=invalid-lexer" % self.new_url
|
||||
response = self.client.post(url, data, follow=True)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
@ -101,7 +101,7 @@ class SnippetTestCase(TestCase):
|
|||
the snippet is considered as spam. We let the user know its spam.
|
||||
"""
|
||||
data = self.valid_form_data()
|
||||
data['title'] = 'Any content'
|
||||
data["title"] = "Any content"
|
||||
response = self.client.post(self.new_url, data, follow=True)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 0)
|
||||
|
@ -112,27 +112,27 @@ class SnippetTestCase(TestCase):
|
|||
"""
|
||||
# POST data
|
||||
data = self.valid_form_data()
|
||||
data['expires'] = 'onetime'
|
||||
data["expires"] = "onetime"
|
||||
|
||||
# First view, the author gets redirected after posting
|
||||
response = self.client.post(self.new_url, data, follow=True)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
self.assertContains(response, data['content'])
|
||||
self.assertContains(response, data["content"])
|
||||
|
||||
# Second View, another user looks at the snippet
|
||||
response = self.client.get(response.request['PATH_INFO'], follow=True)
|
||||
response = self.client.get(response.request["PATH_INFO"], follow=True)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
self.assertContains(response, data['content'])
|
||||
self.assertContains(response, data["content"])
|
||||
|
||||
# Third/Further View, another user looks at the snippet but it was deleted
|
||||
response = self.client.get(response.request['PATH_INFO'], follow=True)
|
||||
response = self.client.get(response.request["PATH_INFO"], follow=True)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
self.assertEqual(Snippet.objects.count(), 0)
|
||||
|
||||
def test_snippet_notfound(self):
|
||||
url = reverse('snippet_details', kwargs={'snippet_id': 'abcd'})
|
||||
url = reverse("snippet_details", kwargs={"snippet_id": "abcd"})
|
||||
response = self.client.get(url, follow=True)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
|
@ -143,18 +143,18 @@ class SnippetTestCase(TestCase):
|
|||
data = self.valid_form_data()
|
||||
response = self.client.post(self.new_url, data, follow=True)
|
||||
response = self.client.post(
|
||||
response.request['PATH_INFO'], data, follow=True
|
||||
response.request["PATH_INFO"], data, follow=True
|
||||
)
|
||||
self.assertContains(response, data['content'])
|
||||
self.assertContains(response, data["content"])
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 2)
|
||||
|
||||
def test_reply_invalid(self):
|
||||
data = self.valid_form_data()
|
||||
response = self.client.post(self.new_url, data, follow=True)
|
||||
del data['content']
|
||||
del data["content"]
|
||||
response = self.client.post(
|
||||
response.request['PATH_INFO'], data, follow=True
|
||||
response.request["PATH_INFO"], data, follow=True
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
@ -170,8 +170,8 @@ class SnippetTestCase(TestCase):
|
|||
self.client.post(self.new_url, data, follow=True)
|
||||
|
||||
snippet_id = Snippet.objects.all()[0].secret_id
|
||||
url = reverse('snippet_details', kwargs={'snippet_id': snippet_id})
|
||||
response = self.client.post(url, {'delete': 1}, follow=True)
|
||||
url = reverse("snippet_details", kwargs={"snippet_id": snippet_id})
|
||||
response = self.client.post(url, {"delete": 1}, follow=True)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 0)
|
||||
|
@ -180,8 +180,8 @@ class SnippetTestCase(TestCase):
|
|||
data = self.valid_form_data()
|
||||
self.client.post(self.new_url, data, follow=True)
|
||||
|
||||
url = reverse('snippet_details', kwargs={'snippet_id': 'doesnotexist'})
|
||||
response = self.client.post(url, {'delete': 1}, follow=True)
|
||||
url = reverse("snippet_details", kwargs={"snippet_id": "doesnotexist"})
|
||||
response = self.client.post(url, {"delete": 1}, follow=True)
|
||||
|
||||
self.assertEqual(response.status_code, 404)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
@ -192,7 +192,7 @@ class SnippetTestCase(TestCase):
|
|||
|
||||
# Do not pass delete=1
|
||||
snippet_id = Snippet.objects.all()[0].secret_id
|
||||
url = reverse('snippet_details', kwargs={'snippet_id': snippet_id})
|
||||
url = reverse("snippet_details", kwargs={"snippet_id": snippet_id})
|
||||
response = self.client.post(url, {}, follow=True)
|
||||
|
||||
# Returns regular snippet details page
|
||||
|
@ -210,7 +210,7 @@ class SnippetTestCase(TestCase):
|
|||
|
||||
# Next time its fetched its automatically deleted.
|
||||
snippet_id = Snippet.objects.all()[0].secret_id
|
||||
url = reverse('snippet_details', kwargs={'snippet_id': snippet_id})
|
||||
url = reverse("snippet_details", kwargs={"snippet_id": snippet_id})
|
||||
response = self.client.get(url, follow=True)
|
||||
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
@ -224,19 +224,19 @@ class SnippetTestCase(TestCase):
|
|||
self.client.post(self.new_url, data, follow=True)
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
'snippet_details_raw',
|
||||
kwargs={'snippet_id': Snippet.objects.all()[0].secret_id},
|
||||
"snippet_details_raw",
|
||||
kwargs={"snippet_id": Snippet.objects.all()[0].secret_id},
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, data['content'])
|
||||
self.assertContains(response, data["content"])
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# XSS and correct escaping
|
||||
# -------------------------------------------------------------------------
|
||||
XSS_ORIGINAL = '<script>hello</script>'
|
||||
XSS_ESCAPED = '<script>hello</script>'
|
||||
XSS_ORIGINAL = "<script>hello</script>"
|
||||
XSS_ESCAPED = "<script>hello</script>"
|
||||
|
||||
def test_xss_text_lexer(self):
|
||||
# Simple 'text' lexer
|
||||
|
@ -256,7 +256,7 @@ class SnippetTestCase(TestCase):
|
|||
|
||||
def test_xss_pygments_lexer(self):
|
||||
# Pygments based lexer
|
||||
data = self.valid_form_data(content=self.XSS_ORIGINAL, lexer='python')
|
||||
data = self.valid_form_data(content=self.XSS_ORIGINAL, lexer="python")
|
||||
response = self.client.post(self.new_url, data, follow=True)
|
||||
self.assertContains(response, self.XSS_ESCAPED)
|
||||
|
||||
|
@ -264,13 +264,13 @@ class SnippetTestCase(TestCase):
|
|||
# History
|
||||
# -------------------------------------------------------------------------
|
||||
def test_snippet_history(self):
|
||||
response = self.client.get(reverse('snippet_history'))
|
||||
response = self.client.get(reverse("snippet_history"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 0)
|
||||
|
||||
data = self.valid_form_data()
|
||||
self.client.post(self.new_url, data, follow=True)
|
||||
response = self.client.get(reverse('snippet_history'))
|
||||
response = self.client.get(reverse("snippet_history"))
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
@ -278,7 +278,7 @@ class SnippetTestCase(TestCase):
|
|||
def test_snippet_history_delete_all(self):
|
||||
# Empty list, delete all raises no error
|
||||
response = self.client.post(
|
||||
reverse('snippet_history'), {'delete': 1}, follow=True
|
||||
reverse("snippet_history"), {"delete": 1}, follow=True
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 0)
|
||||
|
@ -292,7 +292,7 @@ class SnippetTestCase(TestCase):
|
|||
|
||||
# Delete all of them
|
||||
response = self.client.post(
|
||||
reverse('snippet_history'), {'delete': 1}, follow=True
|
||||
reverse("snippet_history"), {"delete": 1}, follow=True
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Snippet.objects.count(), 0)
|
||||
|
@ -316,11 +316,11 @@ class SnippetTestCase(TestCase):
|
|||
|
||||
# You can call the management command with --dry-run which will
|
||||
# list snippets to delete, but wont actually do.
|
||||
management.call_command('cleanup_snippets', dry_run=True)
|
||||
management.call_command("cleanup_snippets", dry_run=True)
|
||||
self.assertEqual(Snippet.objects.count(), 2)
|
||||
|
||||
# Calling the management command will delete this one
|
||||
management.call_command('cleanup_snippets')
|
||||
management.call_command("cleanup_snippets")
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
||||
def test_delete_management_snippet_that_never_expires_will_not_get_deleted(
|
||||
|
@ -330,18 +330,18 @@ class SnippetTestCase(TestCase):
|
|||
Snippets without an expiration date wont get deleted automatically.
|
||||
"""
|
||||
data = self.valid_form_data()
|
||||
data['expires'] = 'never'
|
||||
data["expires"] = "never"
|
||||
self.client.post(self.new_url, data, follow=True)
|
||||
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
management.call_command('cleanup_snippets')
|
||||
management.call_command("cleanup_snippets")
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
||||
def test_highlighting(self):
|
||||
# You can pass any lexer to the pygmentize function and it will
|
||||
# never fail loudly.
|
||||
PygmentsHighlighter().highlight('code', 'python')
|
||||
PygmentsHighlighter().highlight('code', 'doesnotexist')
|
||||
PygmentsHighlighter().highlight("code", "python")
|
||||
PygmentsHighlighter().highlight("code", "doesnotexist")
|
||||
|
||||
def test_random_slug_generation(self):
|
||||
"""
|
||||
|
@ -351,17 +351,17 @@ class SnippetTestCase(TestCase):
|
|||
slugs are extended now.
|
||||
"""
|
||||
for i in range(0, 100):
|
||||
Snippet.objects.create(content='foobar')
|
||||
Snippet.objects.create(content="foobar")
|
||||
slug_list = Snippet.objects.values_list(
|
||||
'secret_id', flat=True
|
||||
).order_by('published')
|
||||
"secret_id", flat=True
|
||||
).order_by("published")
|
||||
self.assertEqual(len(set(slug_list)), 100)
|
||||
|
||||
def test_leading_white_is_retained_in_db(self):
|
||||
"""
|
||||
Leading Whitespace is retained in the db.
|
||||
"""
|
||||
content = ' one\n two\n three\n four'
|
||||
content = " one\n two\n three\n four"
|
||||
data = self.valid_form_data(content=content)
|
||||
self.client.post(self.new_url, data, follow=True)
|
||||
self.assertEqual(Snippet.objects.all()[0].content, content)
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
from django.conf.urls import include, url
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^', include('dpaste.urls.dpaste_api')),
|
||||
url(r'^', include('dpaste.urls.dpaste')),
|
||||
url(r'^i18n/', include('django.conf.urls.i18n')),
|
||||
url(r"^", include("dpaste.urls.dpaste_api")),
|
||||
url(r"^", include("dpaste.urls.dpaste")),
|
||||
url(r"^i18n/", include("django.conf.urls.i18n")),
|
||||
]
|
||||
|
||||
# Custom error handlers which load `dpaste/<code>.html` instead of `<code>.html`
|
||||
handler404 = 'dpaste.views.page_not_found'
|
||||
handler500 = 'dpaste.views.server_error'
|
||||
handler404 = "dpaste.views.page_not_found"
|
||||
handler500 = "dpaste.views.server_error"
|
||||
|
|
|
@ -6,37 +6,37 @@ from django.views.generic import TemplateView
|
|||
|
||||
from .. import views
|
||||
|
||||
L = getattr(settings, 'DPASTE_SLUG_LENGTH', 4)
|
||||
config = apps.get_app_config('dpaste')
|
||||
L = getattr(settings, "DPASTE_SLUG_LENGTH", 4)
|
||||
config = apps.get_app_config("dpaste")
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', views.SnippetView.as_view(), name='snippet_new'),
|
||||
url(r"^$", views.SnippetView.as_view(), name="snippet_new"),
|
||||
url(
|
||||
r'^about/$',
|
||||
r"^about/$",
|
||||
TemplateView.as_view(
|
||||
template_name='dpaste/about.html',
|
||||
template_name="dpaste/about.html",
|
||||
extra_context=config.extra_template_context,
|
||||
),
|
||||
name='dpaste_about',
|
||||
name="dpaste_about",
|
||||
),
|
||||
url(r'^history/$', views.SnippetHistory.as_view(), name='snippet_history'),
|
||||
url(r"^history/$", views.SnippetHistory.as_view(), name="snippet_history"),
|
||||
url(
|
||||
r'^(?P<snippet_id>[a-zA-Z0-9]{%d,})/?$' % L,
|
||||
r"^(?P<snippet_id>[a-zA-Z0-9]{%d,})/?$" % L,
|
||||
views.SnippetDetailView.as_view(),
|
||||
name='snippet_details',
|
||||
name="snippet_details",
|
||||
),
|
||||
url(
|
||||
r'^(?P<snippet_id>[a-zA-Z0-9]{%d,})/raw/?$' % L,
|
||||
r"^(?P<snippet_id>[a-zA-Z0-9]{%d,})/raw/?$" % L,
|
||||
views.SnippetRawView.as_view(),
|
||||
name='snippet_details_raw',
|
||||
name="snippet_details_raw",
|
||||
),
|
||||
url(
|
||||
r'^(?P<snippet_id>[a-zA-Z0-9]{%d,})/slim/?$' % L,
|
||||
r"^(?P<snippet_id>[a-zA-Z0-9]{%d,})/slim/?$" % L,
|
||||
xframe_options_exempt(
|
||||
views.SnippetDetailView.as_view(
|
||||
template_name='dpaste/details_slim.html'
|
||||
template_name="dpaste/details_slim.html"
|
||||
)
|
||||
),
|
||||
name='snippet_details_slim',
|
||||
name="snippet_details_slim",
|
||||
),
|
||||
]
|
||||
|
|
|
@ -5,8 +5,8 @@ from ..views import APIView
|
|||
|
||||
urlpatterns = [
|
||||
url(
|
||||
r'^api/$',
|
||||
r"^api/$",
|
||||
csrf_exempt(APIView.as_view()),
|
||||
name='dpaste_api_create_snippet',
|
||||
name="dpaste_api_create_snippet",
|
||||
)
|
||||
]
|
||||
|
|
100
dpaste/views.py
100
dpaste/views.py
|
@ -27,7 +27,7 @@ from dpaste.forms import SnippetForm, get_expire_values
|
|||
from dpaste.highlight import PygmentsHighlighter
|
||||
from dpaste.models import Snippet
|
||||
|
||||
config = apps.get_app_config('dpaste')
|
||||
config = apps.get_app_config("dpaste")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
@ -41,11 +41,11 @@ class SnippetView(FormView):
|
|||
"""
|
||||
|
||||
form_class = SnippetForm
|
||||
template_name = 'dpaste/new.html'
|
||||
template_name = "dpaste/new.html"
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super(SnippetView, self).get_form_kwargs()
|
||||
kwargs.update({'request': self.request})
|
||||
kwargs.update({"request": self.request})
|
||||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
|
@ -65,9 +65,9 @@ class SnippetDetailView(SnippetView, DetailView):
|
|||
"""
|
||||
|
||||
queryset = Snippet.objects.all()
|
||||
template_name = 'dpaste/details.html'
|
||||
slug_url_kwarg = 'snippet_id'
|
||||
slug_field = 'secret_id'
|
||||
template_name = "dpaste/details.html"
|
||||
slug_url_kwarg = "snippet_id"
|
||||
slug_field = "secret_id"
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
|
@ -76,14 +76,14 @@ class SnippetDetailView(SnippetView, DetailView):
|
|||
reasons and the chance to abuse this is not given anyway, since snippets
|
||||
always expire.
|
||||
"""
|
||||
if 'delete' in self.request.POST:
|
||||
if "delete" in self.request.POST:
|
||||
snippet = get_object_or_404(
|
||||
Snippet, secret_id=self.kwargs['snippet_id']
|
||||
Snippet, secret_id=self.kwargs["snippet_id"]
|
||||
)
|
||||
snippet.delete()
|
||||
|
||||
# Append `#` so #delete goes away in Firefox
|
||||
url = '{0}#'.format(reverse('snippet_new'))
|
||||
url = "{0}#".format(reverse("snippet_new"))
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
return super(SnippetDetailView, self).post(request, *args, **kwargs)
|
||||
|
@ -104,16 +104,16 @@ class SnippetDetailView(SnippetView, DetailView):
|
|||
|
||||
# Increase the view count of the snippet
|
||||
snippet.view_count += 1
|
||||
snippet.save(update_fields=['view_count'])
|
||||
snippet.save(update_fields=["view_count"])
|
||||
|
||||
return super(SnippetDetailView, self).get(request, *args, **kwargs)
|
||||
|
||||
def get_initial(self):
|
||||
snippet = self.get_object()
|
||||
return {
|
||||
'content': snippet.content,
|
||||
'lexer': snippet.lexer,
|
||||
'rtl': snippet.rtl,
|
||||
"content": snippet.content,
|
||||
"lexer": snippet.lexer,
|
||||
"rtl": snippet.rtl,
|
||||
}
|
||||
|
||||
def form_valid(self, form):
|
||||
|
@ -132,12 +132,12 @@ class SnippetDetailView(SnippetView, DetailView):
|
|||
d = difflib.unified_diff(
|
||||
snippet.parent.content.splitlines(),
|
||||
snippet.content.splitlines(),
|
||||
ugettext('Previous Snippet'),
|
||||
ugettext('Current Snippet'),
|
||||
ugettext("Previous Snippet"),
|
||||
ugettext("Current Snippet"),
|
||||
n=1,
|
||||
)
|
||||
diff_code = '\n'.join(d).strip()
|
||||
highlighted = PygmentsHighlighter().render(diff_code, 'diff')
|
||||
diff_code = "\n".join(d).strip()
|
||||
highlighted = PygmentsHighlighter().render(diff_code, "diff")
|
||||
|
||||
# Remove blank lines
|
||||
return highlighted
|
||||
|
@ -148,9 +148,9 @@ class SnippetDetailView(SnippetView, DetailView):
|
|||
ctx = super(SnippetDetailView, self).get_context_data(**kwargs)
|
||||
ctx.update(
|
||||
{
|
||||
'wordwrap': self.object.lexer in highlight.LEXER_WORDWRAP,
|
||||
'diff': self.get_snippet_diff(),
|
||||
'raw_mode': config.RAW_MODE_ENABLED,
|
||||
"wordwrap": self.object.lexer in highlight.LEXER_WORDWRAP,
|
||||
"diff": self.get_snippet_diff(),
|
||||
"raw_mode": config.RAW_MODE_ENABLED,
|
||||
}
|
||||
)
|
||||
ctx.update(config.extra_template_context)
|
||||
|
@ -162,22 +162,20 @@ class SnippetRawView(SnippetDetailView):
|
|||
Display the raw content of a snippet
|
||||
"""
|
||||
|
||||
template_name = 'dpaste/raw.html'
|
||||
template_name = "dpaste/raw.html"
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not config.RAW_MODE_ENABLED:
|
||||
return HttpResponseForbidden(
|
||||
ugettext(
|
||||
'This dpaste installation has Raw view mode disabled.'
|
||||
)
|
||||
ugettext("This dpaste installation has Raw view mode disabled.")
|
||||
)
|
||||
return super(SnippetRawView, self).dispatch(request, *args, **kwargs)
|
||||
|
||||
def render_plain_text(self, context, **response_kwargs):
|
||||
snippet = self.get_object()
|
||||
response = HttpResponse(snippet.content)
|
||||
response['Content-Type'] = 'text/plain;charset=UTF-8'
|
||||
response['X-Content-Type-Options'] = 'nosniff'
|
||||
response["Content-Type"] = "text/plain;charset=UTF-8"
|
||||
response["X-Content-Type-Options"] = "nosniff"
|
||||
return response
|
||||
|
||||
def render_to_response(self, context, **response_kwargs):
|
||||
|
@ -199,26 +197,26 @@ class SnippetHistory(TemplateView):
|
|||
session).
|
||||
"""
|
||||
|
||||
template_name = 'dpaste/history.html'
|
||||
template_name = "dpaste/history.html"
|
||||
|
||||
def get_user_snippets(self):
|
||||
snippet_id_list = self.request.session.get('snippet_list', [])
|
||||
snippet_id_list = self.request.session.get("snippet_list", [])
|
||||
return Snippet.objects.filter(pk__in=snippet_id_list)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
Delete all user snippets at once.
|
||||
"""
|
||||
if 'delete' in self.request.POST:
|
||||
if "delete" in self.request.POST:
|
||||
self.get_user_snippets().delete()
|
||||
|
||||
# Append `#` so #delete goes away in Firefox
|
||||
url = '{0}#'.format(reverse('snippet_history'))
|
||||
url = "{0}#".format(reverse("snippet_history"))
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super(SnippetHistory, self).get_context_data(**kwargs)
|
||||
ctx.update({'snippet_list': self.get_user_snippets()})
|
||||
ctx.update({"snippet_list": self.get_user_snippets()})
|
||||
ctx.update(config.extra_template_context)
|
||||
return ctx
|
||||
|
||||
|
@ -238,7 +236,7 @@ class APIView(View):
|
|||
The default response is the snippet URL wrapped in quotes.
|
||||
"""
|
||||
base_url = config.get_base_url(request=self.request)
|
||||
return '"{url}{path}"'.format(url=base_url, path=s.get_absolute_url())
|
||||
return f'"{base_url}{s.get_absolute_url()}"'
|
||||
|
||||
def _format_url(self, s):
|
||||
"""
|
||||
|
@ -246,7 +244,7 @@ class APIView(View):
|
|||
no quotes, but a linebreak at the end.
|
||||
"""
|
||||
base_url = config.get_base_url(request=self.request)
|
||||
return '{url}{path}\n'.format(url=base_url, path=s.get_absolute_url())
|
||||
return f"{base_url}{s.get_absolute_url()}\n"
|
||||
|
||||
def _format_json(self, s):
|
||||
"""
|
||||
|
@ -255,37 +253,35 @@ class APIView(View):
|
|||
base_url = config.get_base_url(request=self.request)
|
||||
return json.dumps(
|
||||
{
|
||||
'url': '{url}{path}'.format(
|
||||
url=base_url, path=s.get_absolute_url()
|
||||
),
|
||||
'content': s.content,
|
||||
'lexer': s.lexer,
|
||||
"url": f"{base_url}{s.get_absolute_url()}",
|
||||
"content": s.content,
|
||||
"lexer": s.lexer,
|
||||
}
|
||||
)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
content = request.POST.get('content', '')
|
||||
lexer = request.POST.get('lexer', highlight.LEXER_DEFAULT).strip()
|
||||
filename = request.POST.get('filename', '').strip()
|
||||
expires = request.POST.get('expires', '').strip()
|
||||
response_format = request.POST.get('format', 'default').strip()
|
||||
content = request.POST.get("content", "")
|
||||
lexer = request.POST.get("lexer", highlight.LEXER_DEFAULT).strip()
|
||||
filename = request.POST.get("filename", "").strip()
|
||||
expires = request.POST.get("expires", "").strip()
|
||||
response_format = request.POST.get("format", "default").strip()
|
||||
|
||||
if not content.strip():
|
||||
return HttpResponseBadRequest('No content given')
|
||||
return HttpResponseBadRequest("No content given")
|
||||
|
||||
# We need at least a lexer or a filename
|
||||
if not lexer and not filename:
|
||||
return HttpResponseBadRequest(
|
||||
'No lexer or filename given. Unable to '
|
||||
'determine a highlight. Valid lexers are: %s'
|
||||
% ', '.join(highlight.LEXER_KEYS)
|
||||
"No lexer or filename given. Unable to "
|
||||
"determine a highlight. Valid lexers are: %s"
|
||||
% ", ".join(highlight.LEXER_KEYS)
|
||||
)
|
||||
|
||||
# A lexer is given, check if its valid at all
|
||||
if lexer and lexer not in highlight.LEXER_KEYS:
|
||||
return HttpResponseBadRequest(
|
||||
'Invalid lexer "%s" given. Valid lexers are: %s'
|
||||
% (lexer, ', '.join(highlight.LEXER_KEYS))
|
||||
% (lexer, ", ".join(highlight.LEXER_KEYS))
|
||||
)
|
||||
|
||||
# No lexer is given, but we have a filename, try to get the lexer
|
||||
|
@ -303,7 +299,7 @@ class APIView(View):
|
|||
if expires not in expire_options:
|
||||
return HttpResponseBadRequest(
|
||||
'Invalid expire choice "{}" given. Valid values are: {}'.format(
|
||||
expires, ', '.join(expire_options)
|
||||
expires, ", ".join(expire_options)
|
||||
)
|
||||
)
|
||||
expires, expire_type = get_expire_values(expires)
|
||||
|
@ -321,7 +317,7 @@ class APIView(View):
|
|||
)
|
||||
|
||||
# Custom formatter for the API response
|
||||
formatter = getattr(self, '_format_{0}'.format(response_format), None)
|
||||
formatter = getattr(self, f"_format_{response_format}", None)
|
||||
if callable(formatter):
|
||||
return HttpResponse(formatter(snippet))
|
||||
|
||||
|
@ -335,13 +331,13 @@ class APIView(View):
|
|||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def page_not_found(request, exception=None, template_name='dpaste/404.html'):
|
||||
def page_not_found(request, exception=None, template_name="dpaste/404.html"):
|
||||
return django_page_not_found(
|
||||
request, exception, template_name=template_name
|
||||
)
|
||||
|
||||
|
||||
def server_error(request, template_name='dpaste/500.html'):
|
||||
def server_error(request, template_name="dpaste/500.html"):
|
||||
return django_server_error(
|
||||
request, template_name=template_name
|
||||
) # pragma: no cover
|
||||
|
|
Loading…
Reference in a new issue