. bin/activate
pip install -r requirements.txt
```
-Then edit config.py.example into config.py with your database connection
+Then edit config.py.example into config.py with your database connection and web site settings
## Development and debug
fastcgi_pass unix:/motion-socket/motion.fcgi;
}
```
+
+# Configuration for a Jenkins Freestyle Project
+
+## Preconditions for Jenkins system
+
+* Python 3 installed with:
+
+ python3 virtualenv python3-pip
+
+* PostgreSQL server installed with motion database and database user
+
+
+## Add freestyle project
+
+### Source-Code-Management
+
+Adjust Git settings
+
+### Build Environment
+
+Add Bindings
+
+Add Username and password (separated)
+
+Enter username (DB_USER) and password (DB_PW) according to database credentials
+
+### Build
+
+Add build step shell
+
+Add the command
+
+```
+rm -rf env
+virtualenv -p python3 env
+. env/bin/activate
+pip3 install -r requirements.txt
+
+
+cat > config.py << EOF
+DATABASE="pq://IP-ADDRESS/motion"
+USER="${DB_USER}"
+PASSWORD="${DB_PW}"
+EOF
+
+python3 jenkins_job.py
+```
+
+If an IPv6 address is used the following needs to be added to the script to fix a bug of the IPv6 literal translation:
+(https://github.com/python-postgres/fe/issues/104)
+
+```
+patch env/lib/python3*/site-packages/postgresql/versionstring.py <<EOF
+diff --git a/postgresql/versionstring.py b/postgresql/versionstring.py
+index ccb3953..2503013 100644
+--- a/postgresql/versionstring.py
++++ b/postgresql/versionstring.py
+@@ -15,7 +15,7 @@ def split(vstr : str) -> (
+ Split a PostgreSQL version string into a tuple
+ (major,minor,patch,...,state_class,state_level)
+ """
+- v = vstr.strip().split('.')
++ v = vstr.strip().split(' ')[0].split('.')
+
+ # Get rid of the numbers around the state_class (beta,a,dev,alpha, etc)
+ state_class = v[-1].strip('0123456789')
+EOF
+```
+
+### Post build actions
+
+Add Publish JUnit test result report - test report XMLs
+
+```
+python_tests_xml/*
+```
USER="..."
PASSWORD="..."
+# Footer data: remove # at beginning of lines and adjust if needed
+#COPYRIGHTSTART="2017"
+#COPYRIGHTNAME="WPIA"
+#COPYRIGHTLINK="https://wpia.club"
+#IMPRINTLINK="https://documents.wpia.club/imprint.html"
+#DATAPROTECTIONLINK="https://documents.wpia.club/data_privacy_policy_html_pages_en.html"
+
DEFAULT_HOST="hostname for migration from db version < 2"
GROUP_PREFIX={'hostname': {'group1': 'g1', 'group2': 'g2'}} # motion types and their id-prefixes
--- /dev/null
+import unittest
+import xmlrunner
+
+def runner(output='python_tests_xml'):
+ return xmlrunner.XMLTestRunner(
+ output=output
+ )
+
+def find_tests():
+ return unittest.TestLoader().discover('tests', 'test_motion.py')
+
+if __name__ == "__main__":
+ runner().run(find_tests())
md = Markdown(app, extensions=[EscapeHtml()])
+class default_settings(object):
+ COPYRIGHTSTART="2017"
+ COPYRIGHTNAME="WPIA"
+ COPYRIGHTLINK="https://wpia.club"
+ IMPRINTLINK="https://documents.wpia.club/imprint.html"
+ DATAPROTECTIONLINK="https://documents.wpia.club/data_privacy_policy_html_pages_en.html"
+
+
# Load config
+app.config.from_object('motion.default_settings')
app.config.from_pyfile('config.py')
g.roles[a[0]].append(val)
return None
+@app.context_processor
+def init_footer_variables():
+ if int(app.config.get("COPYRIGHTSTART"))<datetime.now().year:
+ version_year = "%s - %s" % (app.config.get("COPYRIGHTSTART"), datetime.now().year)
+ else:
+ version_year = datetime.now().year
+
+ return dict(
+ footer = dict( version_year=version_year,
+ copyright_link=app.config.get("COPYRIGHTLINK"),
+ copyright_name=app.config.get("COPYRIGHTNAME"),
+ imprint_link=app.config.get("DATAPROTECTIONLINK"),
+ dataprotection_link=app.config.get("DATAPROTECTIONLINK")
+ )
+ )
+
+
def get_allowed_cats(action):
return g.roles.get(action, []);
db.prepare("ALTER TABLE \"motion\" ALTER COLUMN \"host\" SET NOT NULL")()
db.prepare("UPDATE \"schema_version\" SET \"version\"=3")()
-
init_db()
@app.route("/")
py-postgresql==1.2.1
Werkzeug==0.12.2
Flask-Markdown==0.3
+xmlrunner>=1.7.7
<body>
{%- block body %}
{% endblock %}
+<!-- Footer -->
+ <footer class="page-footer">
+ <div class="footer-copyright text-center py-3">
+ <p>© {{footer.version_year}} Copyright: <a href="{{footer.copyright_link}}">{{footer.copyright_name}}</a>
+ | <a href="{{footer.imprint_link}}">Imprint</a>
+ | <a href="{{footer.dataprotection_link}}">Data protection</a></p>
+ </div>
+ </footer>
</body>
</html>
def test_basic_results_data_details(self):
motion='g1.20200402.002'
result = self.app.get('/motion/' + motion, environ_base={'USER_ROLES': user}, follow_redirects=True)
- testtext= '<p>A second motion</p></p>\n </div>\n</div>\n<a href=\"/?start=2#motion-2\" class=\"btn btn-primary\">Back</a>\n</body>'
+ testtext= '<p>A second motion</p></p>\n </div>\n</div>\n<a href=\"/?start=2#motion-2\" class=\"btn btn-primary\">Back</a>'
self.assertIn(str.encode(testtext), result.data)
def test_vote(self):