Initial
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
[run]
|
||||
source = base
|
||||
@@ -0,0 +1,9 @@
|
||||
*.pyc
|
||||
.coverage
|
||||
geckodriver.log
|
||||
|
||||
.idea/
|
||||
django_test.egg-info/
|
||||
|
||||
env/
|
||||
tmp/
|
||||
@@ -0,0 +1 @@
|
||||
NOT IMPLEMENTED YET
|
||||
@@ -0,0 +1,3 @@
|
||||
recursive-include base/console_scripts/django_project_config *.py
|
||||
recursive-include base/static *
|
||||
recursive-include base/templates *
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
ABOUT
|
||||
=====
|
||||
This is the heinzel django project.
|
||||
|
||||
|
||||
REQUIREMENTS
|
||||
============
|
||||
See INSTALL.rst
|
||||
|
||||
|
||||
INSTALLATION
|
||||
============
|
||||
See INSTALL.rst
|
||||
|
||||
|
||||
LICENCE
|
||||
=======
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted.
|
||||
@@ -0,0 +1,95 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
import argparse
|
||||
import os
|
||||
import pkg_resources
|
||||
import sys
|
||||
|
||||
DJANGO_MAIN_MODULE = 'main'
|
||||
VERSION = '0.1'
|
||||
|
||||
|
||||
class AdminCommand(object):
|
||||
@staticmethod
|
||||
def _setup_argparser():
|
||||
kwargs = {
|
||||
'description': 'Tool to manage your test django installation.',
|
||||
}
|
||||
parser = argparse.ArgumentParser(**kwargs)
|
||||
|
||||
parser.add_argument('-V', '--version', action='version',
|
||||
version='%(prog)s ' + VERSION)
|
||||
|
||||
subparsers = parser.add_subparsers(dest='subcmd', metavar='CMD',
|
||||
title='subcommands',
|
||||
description="Use '%(prog)s CMD -h' to show help for a subcommand")
|
||||
subparser = subparsers.add_parser('setup', help='Setup the installation.')
|
||||
subparser.add_argument('path', metavar='PATH',
|
||||
help='A directory, where the project files will be installed.')
|
||||
|
||||
return parser
|
||||
|
||||
def _parse_args(self, argv=None):
|
||||
if argv is None:
|
||||
argv = sys.argv[1:]
|
||||
if not argv:
|
||||
argv = ['--help']
|
||||
|
||||
return self._argparser.parse_args(argv)
|
||||
|
||||
@staticmethod
|
||||
def _subcmd_setup(cmd_args):
|
||||
django_main_module = DJANGO_MAIN_MODULE
|
||||
django_base_dir = cmd_args.path
|
||||
|
||||
sys.stdout.write('Setup installation in \'{path}\'...\n'.format(path=django_base_dir))
|
||||
|
||||
if os.path.exists(django_base_dir):
|
||||
if not os.path.isdir(django_base_dir):
|
||||
sys.stderr.write('{path}: Not a directory.\n'.format(path=django_base_dir))
|
||||
return os.EX_USAGE
|
||||
else:
|
||||
os.makedirs(django_base_dir)
|
||||
|
||||
sys.stdout.write('Creating django project...\n')
|
||||
django_cmd = 'django-admin startproject {name} "{path}"'.format(name=django_main_module,
|
||||
path=django_base_dir)
|
||||
exitval = os.system(django_cmd)
|
||||
if exitval != os.EX_OK:
|
||||
return exitval
|
||||
|
||||
sys.stdout.write('Configure django project...\n')
|
||||
|
||||
input_file = os.path.join('django_project_config', 'additional_settings.py')
|
||||
output_file = os.path.join(django_base_dir, django_main_module, 'settings.py')
|
||||
with open(output_file, 'ab') as f:
|
||||
f.write(pkg_resources.resource_string(__package__, input_file))
|
||||
|
||||
sys.stdout.write('Creating directories...\n')
|
||||
dirs = [
|
||||
os.path.join(django_base_dir, 'var', 'log'),
|
||||
os.path.join(django_base_dir, 'var', 'www', 'static'),
|
||||
]
|
||||
|
||||
for d in dirs:
|
||||
sys.stdout.write(' - %s\n' % d)
|
||||
os.makedirs(d)
|
||||
|
||||
return os.EX_OK
|
||||
|
||||
def __init__(self):
|
||||
self._argparser = self._setup_argparser()
|
||||
|
||||
def __call__(self, argv=None):
|
||||
cmd_args = self._parse_args(argv)
|
||||
subcmd = cmd_args.subcmd
|
||||
method_name = '_subcmd_{}'.format(subcmd)
|
||||
method = getattr(self, method_name)
|
||||
exitval = method(cmd_args)
|
||||
return exitval
|
||||
|
||||
|
||||
def main():
|
||||
cmd = AdminCommand()
|
||||
exitval = cmd()
|
||||
sys.exit(exitval)
|
||||
@@ -0,0 +1,64 @@
|
||||
|
||||
#
|
||||
# Additional settings for django-test
|
||||
#
|
||||
|
||||
BASE_VAR_DIR = os.path.join(BASE_DIR, 'var')
|
||||
LOG_DIR = os.path.join(BASE_VAR_DIR, 'log')
|
||||
|
||||
INSTALLED_APPS += [
|
||||
'django_extensions',
|
||||
# Our main app
|
||||
'base',
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'base.urls'
|
||||
STATIC_ROOT = os.path.join(BASE_VAR_DIR, 'www', 'static')
|
||||
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'formatters': {
|
||||
'default': {
|
||||
'format': '%(asctime)s - %(name)s - %(levelname)s: %(message)s'
|
||||
},
|
||||
'verbose': {
|
||||
'format': ('%(asctime)s -- %(processName)s[%(process)d]:%(threadName)s[%(thread)d] -- '
|
||||
'%(name)s -- %(module)s...%(funcName)s() -- %(pathname)s:%(lineno)d -- '
|
||||
'%(levelname)s: %(message)s')
|
||||
},
|
||||
},
|
||||
'filters': {
|
||||
'require_debug_true': {
|
||||
'()': 'django.utils.log.RequireDebugTrue',
|
||||
},
|
||||
'require_debug_false': {
|
||||
'()': 'django.utils.log.RequireDebugFalse',
|
||||
},
|
||||
},
|
||||
'handlers': {
|
||||
'null': {
|
||||
'class': 'logging.NullHandler',
|
||||
},
|
||||
'console_debug': {
|
||||
'level': 'DEBUG',
|
||||
'filters': ['require_debug_true'],
|
||||
'class': 'logging.StreamHandler',
|
||||
},
|
||||
'console_default': {
|
||||
'level': 'INFO',
|
||||
'filters': ['require_debug_false'],
|
||||
'class': 'logging.StreamHandler',
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'django': {
|
||||
'level': 'INFO',
|
||||
'propagate': True,
|
||||
},
|
||||
},
|
||||
'root': {
|
||||
'level': 'DEBUG',
|
||||
'handlers': ['console_debug', 'console_default'],
|
||||
},
|
||||
}
|
||||
+3719
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+331
@@ -0,0 +1,331 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2019 The Bootstrap Authors
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: sans-serif;
|
||||
line-height: 1.15;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #212529;
|
||||
text-align: left;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
[tabindex="-1"]:focus {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
hr {
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title],
|
||||
abbr[data-original-title] {
|
||||
text-decoration: underline;
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
border-bottom: 0;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: .5rem;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #007bff;
|
||||
text-decoration: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #0056b3;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:not([href]):not([tabindex]) {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:not([href]):not([tabindex]):focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img {
|
||||
vertical-align: middle;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
svg {
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.75rem;
|
||||
padding-bottom: 0.75rem;
|
||||
color: #6c757d;
|
||||
text-align: left;
|
||||
caption-side: bottom;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: 1px dotted;
|
||||
outline: 5px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
input {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
||||
button,
|
||||
[type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
button:not(:disabled),
|
||||
[type="button"]:not(:disabled),
|
||||
[type="reset"]:not(:disabled),
|
||||
[type="submit"]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
input[type="radio"],
|
||||
input[type="checkbox"] {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
input[type="date"],
|
||||
input[type="time"],
|
||||
input[type="datetime-local"],
|
||||
input[type="month"] {
|
||||
-webkit-appearance: listbox;
|
||||
}
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: .5rem;
|
||||
font-size: 1.5rem;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type="search"] {
|
||||
outline-offset: -2px;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
/*# sourceMappingURL=bootstrap-reboot.css.map */
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2019 The Bootstrap Authors
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
|
||||
/*# sourceMappingURL=bootstrap-reboot.min.css.map */
|
||||
File diff suppressed because one or more lines are too long
+10038
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+7013
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+4435
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,14 @@
|
||||
#page-header {
|
||||
padding-left: 1rem;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 2px;
|
||||
border-bottom-color: #000;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
#page-footer {
|
||||
padding-right: 1rem;
|
||||
}
|
||||
#page-footer > div.signum {
|
||||
float: right;
|
||||
}
|
||||
Vendored
+5
File diff suppressed because one or more lines are too long
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
{% load static %}
|
||||
<html lang="{{ LANGUAGE_CODE|default:'de' }}">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<link type="text/css" href="{% static 'base/bootstrap/css/bootstrap.min.css' %}" rel="stylesheet" />
|
||||
<link type="text/css" href="{% static 'base/css/local.css' %}" rel="stylesheet" />
|
||||
|
||||
<script type="text/javascript" src="{% static 'base/js/jquery.min.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'base/bootstrap/js/bootstrap.min.js' %}"></script>
|
||||
|
||||
<title>django-test</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="page">
|
||||
<div id="page-header">
|
||||
<h1>
|
||||
<a href="{% url 'root' %}">django-test</a>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div id="page-body">
|
||||
{% block page-body %}{% endblock %}
|
||||
</div>
|
||||
|
||||
<div id="page-footer">
|
||||
<div class="signum">{% block signum %}{% include 'signum.html' %}{% endblock %}</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,15 @@
|
||||
{% extends "base/base.html" %}
|
||||
|
||||
{% block page-body %}
|
||||
<div class="container">
|
||||
<div class="jumbotron">
|
||||
<h1>Hello,</h1>
|
||||
<p>
|
||||
my name is {{ hostname|capfirst }} and I am your server right now.
|
||||
</p>
|
||||
<p>
|
||||
By the way, my clock says {{ time|time:'TIME_FORMAT'|default:'nothing' }}.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock page-body %}
|
||||
@@ -0,0 +1 @@
|
||||
<a href="mailto:heinzel@heinzelwelt.de">heinzel@heinzelwelt.de</a>
|
||||
@@ -0,0 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
import os
|
||||
import shutil
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from ..console_scripts.admin import DJANGO_MAIN_MODULE, AdminCommand
|
||||
|
||||
from .utils import mkdtemp
|
||||
|
||||
|
||||
class AdminTestCase(SimpleTestCase):
|
||||
def setUp(self):
|
||||
super(AdminTestCase, self).setUp()
|
||||
self.tmp_dir = mkdtemp(prefix='AdminTestCase')
|
||||
|
||||
def tearDown(self):
|
||||
super(AdminTestCase, self).tearDown()
|
||||
if os.path.isdir(self.tmp_dir):
|
||||
shutil.rmtree(self.tmp_dir)
|
||||
|
||||
def test_setup(self):
|
||||
path = self.tmp_dir
|
||||
cmd = AdminCommand()
|
||||
argv = ['setup', path]
|
||||
exitval = cmd(argv)
|
||||
self.assertEqual(exitval, os.EX_OK)
|
||||
self.assertTrue(os.path.isfile(os.path.join(path, 'manage.py')))
|
||||
self.assertTrue(os.path.isfile(os.path.join(path, DJANGO_MAIN_MODULE, 'settings.py')))
|
||||
self.assertTrue(os.path.isdir(os.path.join(path, 'var', 'log')))
|
||||
self.assertTrue(os.path.isdir(os.path.join(path, 'var', 'www', 'static')))
|
||||
@@ -0,0 +1,76 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
from django.conf import settings
|
||||
from django.template.context import Context
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
|
||||
class BaseTemplateTestCase(SimpleTestCase):
|
||||
def assertInHTML_multi(self, response, needles, format_kwargs=None):
|
||||
content = response.content.decode('utf-8')
|
||||
for needle in needles:
|
||||
if format_kwargs is not None:
|
||||
needle = needle.format(**format_kwargs)
|
||||
self.assertInHTML(needle, content)
|
||||
|
||||
def setUp(self):
|
||||
super(BaseTemplateTestCase, self).setUp()
|
||||
self.response = self.client.get('/')
|
||||
self.static_url = settings.STATIC_URL
|
||||
self.base_prefix = 'base/'
|
||||
|
||||
def test_template_usage(self):
|
||||
response = self.response
|
||||
self.assertTemplateUsed(response, 'base/base.html')
|
||||
|
||||
def test_local_css_link(self):
|
||||
response = self.response
|
||||
|
||||
format_kwargs = {
|
||||
'static_url': self.static_url,
|
||||
'base_prefix': self.base_prefix,
|
||||
}
|
||||
|
||||
needles = (
|
||||
'<link type="text/css" href="{static_url}{base_prefix}css/local.css" rel="stylesheet" />',
|
||||
)
|
||||
|
||||
self.assertInHTML_multi(response, needles, format_kwargs)
|
||||
|
||||
def test_bootstrap_css_links(self):
|
||||
response = self.response
|
||||
|
||||
format_kwargs = {
|
||||
'static_url': self.static_url,
|
||||
'base_prefix': self.base_prefix,
|
||||
}
|
||||
|
||||
needles = (
|
||||
# bootstrap css
|
||||
'<link type="text/css" href="{static_url}{base_prefix}bootstrap/css/bootstrap.min.css"'
|
||||
' rel="stylesheet" />',
|
||||
# jquery.js file
|
||||
'<script type="text/javascript" src="{static_url}{base_prefix}js/jquery.min.js"></script>',
|
||||
# bootstrap js file
|
||||
'<script type="text/javascript" src="{static_url}{base_prefix}bootstrap/js/bootstrap.min.js"></script>',
|
||||
)
|
||||
|
||||
self.assertInHTML_multi(response, needles, format_kwargs)
|
||||
|
||||
def test_page_footer(self):
|
||||
response = self.response
|
||||
self.assertTemplateUsed(response, 'signum.html')
|
||||
for template in response.templates:
|
||||
if template.name == 'signum.html':
|
||||
signum = template.render(Context({}))
|
||||
break
|
||||
else: # pragma: no cover
|
||||
self.fail('Cannot find signum template.')
|
||||
|
||||
needle = """
|
||||
<div id="page-footer">
|
||||
<div class="signum">{signum}</div>
|
||||
</div>
|
||||
""".format(signum=signum)
|
||||
|
||||
self.assertInHTML(needle, response.content.decode('utf-8'))
|
||||
@@ -0,0 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
import socket
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
|
||||
class DjangoAdminTestCase(SimpleTestCase):
|
||||
def test_djangoadmin(self):
|
||||
response = self.client.get('/djangoadmin', follow=True)
|
||||
self.assertContains(response, 'Django administration')
|
||||
|
||||
|
||||
class RootTestCase(SimpleTestCase):
|
||||
def setUp(self):
|
||||
super(RootTestCase, self).setUp()
|
||||
self.response = self.client.get('/')
|
||||
|
||||
def test_root_template(self):
|
||||
response = self.response
|
||||
self.assertTemplateUsed(response, 'base/root.html')
|
||||
|
||||
def test_root_context(self):
|
||||
response = self.response
|
||||
self.assertIn('hostname', response.context)
|
||||
hostname = socket.gethostname()
|
||||
self.assertEqual(response.context['hostname'], hostname)
|
||||
|
||||
def test_root_content(self):
|
||||
response = self.response
|
||||
hostname = socket.gethostname().capitalize()
|
||||
self.assertContains(response, hostname)
|
||||
@@ -0,0 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
import os
|
||||
from tempfile import mkdtemp as _mkdtmp
|
||||
|
||||
|
||||
def mkdtemp(prefix):
|
||||
dirname = os.path.dirname
|
||||
pkg_base_dir = dirname(dirname(dirname(__file__)))
|
||||
tmp_dir = os.path.join(pkg_base_dir, 'tmp')
|
||||
os.makedirs(tmp_dir, exist_ok=True)
|
||||
return _mkdtmp(prefix=prefix, dir=tmp_dir)
|
||||
@@ -0,0 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
from django.contrib import admin
|
||||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.RootView.as_view(), name='root'),
|
||||
path('djangoadmin/', admin.site.urls),
|
||||
]
|
||||
@@ -0,0 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
import socket
|
||||
from django.utils import timezone
|
||||
from django.views import generic
|
||||
|
||||
|
||||
class RootView(generic.TemplateView):
|
||||
template_name = 'base/root.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
if 'hostname' not in kwargs:
|
||||
kwargs['hostname'] = socket.gethostname()
|
||||
if 'time' not in kwargs:
|
||||
kwargs['time'] = timezone.now()
|
||||
return super(RootView, self).get_context_data(**kwargs)
|
||||
Executable
+82
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
import argparse
|
||||
import coverage
|
||||
import datetime
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
|
||||
class Command(object):
|
||||
default_browser = 'firefox'
|
||||
|
||||
@staticmethod
|
||||
def _setup_argparser():
|
||||
kwargs = {
|
||||
'description': 'Tool to create html coverage report.',
|
||||
}
|
||||
parser = argparse.ArgumentParser(**kwargs)
|
||||
return parser
|
||||
|
||||
def _parse_args(self, argv=None):
|
||||
if argv is None:
|
||||
argv = sys.argv[1:]
|
||||
|
||||
return self._argparser.parse_args(argv)
|
||||
|
||||
@staticmethod
|
||||
def _create_report_directory(path=None):
|
||||
if path is None:
|
||||
timestamp = datetime.datetime.now().strftime('%Y%m%d-%H%M')
|
||||
dirname = 'coverage-report-{}'.format(timestamp)
|
||||
path = os.path.join('tmp', dirname)
|
||||
os.makedirs(path)
|
||||
return path
|
||||
|
||||
def _remove_report_directory(self, path=None):
|
||||
if path is None:
|
||||
path = self._report_directory
|
||||
if path is not None:
|
||||
if os.path.isdir(path):
|
||||
sys.stdout.write('Removing report directory {}\n'.format(path))
|
||||
shutil.rmtree(path)
|
||||
|
||||
def _create_report(self, path):
|
||||
return self._coverage.html_report(directory=path, skip_covered=True)
|
||||
|
||||
def _show_report(self, path):
|
||||
start_file = os.path.join(path, 'index.html')
|
||||
browser = os.environ.get('BROWSER', self.default_browser)
|
||||
cmd = '{browser} --new-window "{file}"'.format(browser=browser, file=start_file)
|
||||
return os.system(cmd)
|
||||
|
||||
def __init__(self):
|
||||
self._argparser = self._setup_argparser()
|
||||
self._report_directory = self._create_report_directory()
|
||||
self._coverage = coverage.Coverage()
|
||||
self._coverage.load()
|
||||
|
||||
def __call__(self, argv=None):
|
||||
self._parse_args(argv)
|
||||
report_dir = self._report_directory
|
||||
sys.stdout.write('Report directory: {}\n'.format(report_dir))
|
||||
try:
|
||||
self._create_report(report_dir)
|
||||
except Exception as e1:
|
||||
self._remove_report_directory(report_dir)
|
||||
raise e1
|
||||
|
||||
exitval = self._show_report(report_dir)
|
||||
return exitval
|
||||
|
||||
|
||||
def main():
|
||||
cmd = Command()
|
||||
exitval = cmd()
|
||||
sys.exit(exitval)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
import os
|
||||
import sys
|
||||
from setuptools import setup, find_packages
|
||||
from setuptools import Command
|
||||
|
||||
|
||||
class MyCommand(Command):
|
||||
user_options = []
|
||||
|
||||
def initialize_options(self):
|
||||
pass
|
||||
|
||||
def finalize_options(self):
|
||||
pass
|
||||
|
||||
|
||||
class SetupPythonEnvironment(MyCommand):
|
||||
description = 'create a (virtual) python environment'
|
||||
|
||||
@staticmethod
|
||||
def run():
|
||||
python_bin = sys.executable if sys.executable else 'python'
|
||||
python_ver = sys.version_info.major
|
||||
if python_ver == 2:
|
||||
path = os.path.join('env', 'python2')
|
||||
symlink_path = os.path.join('env', 'python')
|
||||
venv_module = 'virtualenv'
|
||||
prompt = '(py2-django) '
|
||||
elif python_ver == 3:
|
||||
path = os.path.join('env', 'python3')
|
||||
symlink_path = os.path.join('env', 'python')
|
||||
venv_module = 'venv'
|
||||
prompt = 'py3-django'
|
||||
else:
|
||||
sys.stderr.write('Python {} is not supported.\n'.format(python_ver))
|
||||
sys.exit(os.EX_USAGE)
|
||||
|
||||
sys.stdout.write('Creating new python environment in {path}\n'.format(path=path))
|
||||
cmd = ('{bin} -m {venv_module}'
|
||||
' --prompt="{prompt}"'
|
||||
' {path}'.format(bin=python_bin, path=path,
|
||||
venv_module=venv_module, prompt=prompt))
|
||||
os.system(cmd)
|
||||
|
||||
if symlink_path and not os.path.exists(symlink_path):
|
||||
symlink_dir = os.path.dirname(symlink_path)
|
||||
relpath = os.path.relpath(path, symlink_dir)
|
||||
os.symlink(relpath, symlink_path)
|
||||
|
||||
print('')
|
||||
print('Depending on your operating system or command shell,')
|
||||
print('you should activate the new environment for this shell session')
|
||||
print('by running ONE of the following commands:')
|
||||
print('- Windows: %s' % os.path.join(path, 'Scripts', 'activate'))
|
||||
print('- C Shell: source %s/bin/activate.csh' % path)
|
||||
print('- All others: source %s/bin/activate' % path)
|
||||
|
||||
|
||||
class SetupDjangoEnvironment(MyCommand):
|
||||
description = 'create a typical installation for developing'
|
||||
|
||||
@staticmethod
|
||||
def run():
|
||||
# python_bin = sys.executable if sys.executable else 'python'
|
||||
django_project_path = 'env/django'
|
||||
# mgmt_script = os.path.join(django_project_path, 'manage.py')
|
||||
|
||||
sys.stdout.write('Install distribution in development mode...\n')
|
||||
cmd = 'pip install -e .'
|
||||
os.system(cmd)
|
||||
|
||||
sys.stdout.write('Setup django project in {}...\n'.format(django_project_path))
|
||||
cmd = 'django-test-admin setup {}'.format(django_project_path)
|
||||
os.system(cmd)
|
||||
|
||||
# sys.stdout.write('Make database migrations...\n')
|
||||
# cmd = '{bin} {mgmt} makemigrations'.format(bin=python_bin, mgmt=mgmt_script)
|
||||
# os.system(cmd)
|
||||
|
||||
# sys.stdout.write('Create database...\n')
|
||||
# cmd = '{bin} {mgmt} migrate'.format(bin=python_bin, mgmt=mgmt_script)
|
||||
# os.system(cmd)
|
||||
|
||||
# sys.stdout.write('Create superuser \'root\'...\n')
|
||||
# cmd = ('{bin} {mgmt} createsuperuser'
|
||||
# ' --username root').format(bin=python_bin, mgmt=mgmt_script)
|
||||
# os.system(cmd)
|
||||
|
||||
|
||||
setup(
|
||||
name='django-test',
|
||||
version='1.0',
|
||||
description='An example django based web application.',
|
||||
url='https://heinzelwelt.de',
|
||||
maintainer='Jens Kleineheismann',
|
||||
maintainer_email='heinzel@heinzelwelt.de',
|
||||
cmdclass={
|
||||
'mkpyenv': SetupPythonEnvironment,
|
||||
'mkdjangoenv': SetupDjangoEnvironment,
|
||||
},
|
||||
packages=find_packages(),
|
||||
include_package_data=True,
|
||||
test_suite='tests.test_suite',
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'django-test-admin = base.console_scripts.admin:main',
|
||||
],
|
||||
},
|
||||
install_requires=[
|
||||
'coverage',
|
||||
'django',
|
||||
'django-extensions',
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,2 @@
|
||||
from .test_suite import TestSuite
|
||||
test_suite = TestSuite()
|
||||
@@ -0,0 +1,71 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
import datetime
|
||||
import django
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
from django.test.utils import get_runner
|
||||
|
||||
from base.console_scripts.admin import DJANGO_MAIN_MODULE
|
||||
from base.tests.utils import mkdtemp
|
||||
|
||||
|
||||
class DjangoEnvironment(object):
|
||||
@staticmethod
|
||||
def _install_djangoproject(path):
|
||||
cmd = 'django-test-admin setup "{}"'.format(path)
|
||||
os.system(cmd)
|
||||
|
||||
def __init__(self, path=None, remove_after=True):
|
||||
self.path = path
|
||||
|
||||
self._remove_after = remove_after
|
||||
self._original_sys_path = None
|
||||
self._modified_sys_path = None
|
||||
|
||||
def __enter__(self):
|
||||
if self.path is None:
|
||||
prefix = 'testrun-{datetime}-'.format(
|
||||
datetime=datetime.datetime.now().strftime('%Y%m%d-%H%M')
|
||||
)
|
||||
self.path = mkdtemp(prefix=prefix)
|
||||
|
||||
self._install_djangoproject(self.path)
|
||||
|
||||
self._original_sys_path = sys.path
|
||||
sys.path.append(self.path)
|
||||
self._modified_sys_path = sys.path
|
||||
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = '{}.settings'.format(DJANGO_MAIN_MODULE)
|
||||
django.setup()
|
||||
|
||||
from django.conf import settings
|
||||
self.settings = settings
|
||||
|
||||
return self
|
||||
|
||||
def __exit__(self, *args):
|
||||
if self._modified_sys_path is not None and self._original_sys_path is not None:
|
||||
if sys.path == self._modified_sys_path:
|
||||
sys.path = self._original_sys_path
|
||||
if self._remove_after:
|
||||
shutil.rmtree(self.path)
|
||||
|
||||
|
||||
class TestSuite(object):
|
||||
@staticmethod
|
||||
def run():
|
||||
tests = ['base']
|
||||
test_tags = None
|
||||
exclude_test_tags = None
|
||||
|
||||
with DjangoEnvironment() as env:
|
||||
test_runner_class = get_runner(env.settings)
|
||||
test_runner = test_runner_class(tags=test_tags, exclude_tags=exclude_test_tags)
|
||||
failures = test_runner.run_tests(tests)
|
||||
|
||||
return bool(failures)
|
||||
|
||||
def __call__(self):
|
||||
sys.exit(self.run())
|
||||
Reference in New Issue
Block a user