diff --git a/CHANGES.txt b/CHANGES.txt
new file mode 100644
index 0000000..14b902f
--- /dev/null
+++ b/CHANGES.txt
@@ -0,0 +1,4 @@
+0.0
+---
+
+- Initial version.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..38a4f90
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,5 @@
+include *.txt *.ini *.cfg *.rst
+recursive-include cleanup_html *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml *.jinja2
+recursive-include tests *
+recursive-exclude * __pycache__
+recursive-exclude * *.py[co]
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..63a12fc
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,30 @@
+cleanup_html
+============
+
+Getting Started
+---------------
+
+- Change directory into your newly created project if not already there. Your
+ current directory should be the same as this README.txt file and setup.py.
+
+ cd cleanup_html
+
+- Create a Python virtual environment, if not already created.
+
+ python3 -m venv env
+
+- Upgrade packaging tools, if necessary.
+
+ env/bin/pip install --upgrade pip setuptools
+
+- Install the project in editable mode with its testing requirements.
+
+ env/bin/pip install -e ".[testing]"
+
+- Run your project's tests.
+
+ env/bin/pytest
+
+- Run your project.
+
+ env/bin/pserve development.ini
diff --git a/cleanup_html/__init__.py b/cleanup_html/__init__.py
new file mode 100644
index 0000000..a3d5a64
--- /dev/null
+++ b/cleanup_html/__init__.py
@@ -0,0 +1,11 @@
+from pyramid.config import Configurator
+
+
+def main(global_config, **settings):
+ """ This function returns a Pyramid WSGI application.
+ """
+ with Configurator(settings=settings) as config:
+ config.include('pyramid_jinja2')
+ config.include('.routes')
+ config.scan()
+ return config.make_wsgi_app()
diff --git a/cleanup_html/routes.py b/cleanup_html/routes.py
new file mode 100644
index 0000000..25504ad
--- /dev/null
+++ b/cleanup_html/routes.py
@@ -0,0 +1,3 @@
+def includeme(config):
+ config.add_static_view('static', 'static', cache_max_age=3600)
+ config.add_route('home', '/')
diff --git a/cleanup_html/static/pyramid-16x16.png b/cleanup_html/static/pyramid-16x16.png
new file mode 100644
index 0000000..9792031
Binary files /dev/null and b/cleanup_html/static/pyramid-16x16.png differ
diff --git a/cleanup_html/static/pyramid.png b/cleanup_html/static/pyramid.png
new file mode 100644
index 0000000..4ab837b
Binary files /dev/null and b/cleanup_html/static/pyramid.png differ
diff --git a/cleanup_html/static/theme.css b/cleanup_html/static/theme.css
new file mode 100644
index 0000000..6d03c6e
--- /dev/null
+++ b/cleanup_html/static/theme.css
@@ -0,0 +1,32 @@
+@import url(//fonts.googleapis.com/css?family=Open+Sans:300,400,600,700);
+body {
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-weight: 300;
+ color: #1c1b1b;
+ background: #ffffff;
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-weight: 300;
+}
+p {
+ font-weight: 300;
+}
+button, input, optgroup, select, textarea {
+ color: black;
+}
+.font-normal {
+ font-weight: 400;
+}
+.font-semi-bold {
+ font-weight: 600;
+}
+.font-bold {
+ font-weight: 700;
+}
+
diff --git a/cleanup_html/templates/404.jinja2 b/cleanup_html/templates/404.jinja2
new file mode 100644
index 0000000..aaf1241
--- /dev/null
+++ b/cleanup_html/templates/404.jinja2
@@ -0,0 +1,8 @@
+{% extends "layout.jinja2" %}
+
+{% block content %}
+
+
Pyramid Starter project
+
404 Page Not Found
+
+{% endblock content %}
diff --git a/cleanup_html/templates/layout.jinja2 b/cleanup_html/templates/layout.jinja2
new file mode 100644
index 0000000..4aadb90
--- /dev/null
+++ b/cleanup_html/templates/layout.jinja2
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+ Cookiecutter Starter project for the Pyramid Web Framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% block content %}
+
No content
+ {% endblock content %}
+
+
+
+ Copyright © Pylons Project
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cleanup_html/templates/mytemplate.jinja2 b/cleanup_html/templates/mytemplate.jinja2
new file mode 100644
index 0000000..f2e7283
--- /dev/null
+++ b/cleanup_html/templates/mytemplate.jinja2
@@ -0,0 +1,8 @@
+{% extends "layout.jinja2" %}
+
+{% block content %}
+
+
Pyramid Starter project
+
Welcome to {{project}}, a Pyramid application generated by
Cookiecutter.
+
+{% endblock content %}
diff --git a/cleanup_html/views/__init__.py b/cleanup_html/views/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/cleanup_html/views/default.py b/cleanup_html/views/default.py
new file mode 100644
index 0000000..a765fc8
--- /dev/null
+++ b/cleanup_html/views/default.py
@@ -0,0 +1,6 @@
+from pyramid.view import view_config
+
+
+@view_config(route_name='home', renderer='cleanup_html:templates/mytemplate.jinja2')
+def my_view(request):
+ return {'project': 'cleanup_html'}
diff --git a/cleanup_html/views/notfound.py b/cleanup_html/views/notfound.py
new file mode 100644
index 0000000..2a8fcd2
--- /dev/null
+++ b/cleanup_html/views/notfound.py
@@ -0,0 +1,7 @@
+from pyramid.view import notfound_view_config
+
+
+@notfound_view_config(renderer='cleanup_html:templates/404.jinja2')
+def notfound_view(request):
+ request.response.status = 404
+ return {}
diff --git a/development.ini b/development.ini
new file mode 100644
index 0000000..f948eb1
--- /dev/null
+++ b/development.ini
@@ -0,0 +1,59 @@
+###
+# app configuration
+# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
+[app:main]
+use = egg:cleanup_html
+
+pyramid.reload_templates = true
+pyramid.debug_authorization = false
+pyramid.debug_notfound = false
+pyramid.debug_routematch = false
+pyramid.default_locale_name = en
+pyramid.includes =
+ pyramid_debugtoolbar
+
+# By default, the toolbar only appears for clients from IP addresses
+# '127.0.0.1' and '::1'.
+# debugtoolbar.hosts = 127.0.0.1 ::1
+
+###
+# wsgi server configuration
+###
+
+[server:main]
+use = egg:waitress#main
+listen = localhost:6543
+
+###
+# logging configuration
+# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
+
+[loggers]
+keys = root, cleanup_html
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[logger_cleanup_html]
+level = DEBUG
+handlers =
+qualname = cleanup_html
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
diff --git a/production.ini b/production.ini
new file mode 100644
index 0000000..e6adb1b
--- /dev/null
+++ b/production.ini
@@ -0,0 +1,53 @@
+###
+# app configuration
+# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
+[app:main]
+use = egg:cleanup_html
+
+pyramid.reload_templates = false
+pyramid.debug_authorization = false
+pyramid.debug_notfound = false
+pyramid.debug_routematch = false
+pyramid.default_locale_name = en
+
+###
+# wsgi server configuration
+###
+
+[server:main]
+use = egg:waitress#main
+listen = *:6543
+
+###
+# logging configuration
+# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
+
+[loggers]
+keys = root, cleanup_html
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = WARN
+handlers = console
+
+[logger_cleanup_html]
+level = WARN
+handlers =
+qualname = cleanup_html
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
diff --git a/pytest.ini b/pytest.ini
new file mode 100644
index 0000000..d39aa9a
--- /dev/null
+++ b/pytest.ini
@@ -0,0 +1,6 @@
+[pytest]
+addopts = --strict-markers
+
+testpaths =
+ cleanup_html
+ tests
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..f8118dd
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,52 @@
+import os
+
+from setuptools import setup, find_packages
+
+here = os.path.abspath(os.path.dirname(__file__))
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
+
+requires = [
+ 'plaster_pastedeploy',
+ 'pyramid',
+ 'pyramid_jinja2',
+ 'pyramid_debugtoolbar',
+ 'waitress',
+]
+
+tests_require = [
+ 'WebTest',
+ 'pytest',
+ 'pytest-cov',
+]
+
+setup(
+ name='cleanup_html',
+ version='0.0',
+ description='cleanup_html',
+ long_description=README + '\n\n' + CHANGES,
+ classifiers=[
+ 'Programming Language :: Python',
+ 'Framework :: Pyramid',
+ 'Topic :: Internet :: WWW/HTTP',
+ 'Topic :: Internet :: WWW/HTTP :: WSGI :: Application',
+ ],
+ author='',
+ author_email='',
+ url='',
+ keywords='web pyramid pylons',
+ packages=find_packages(exclude=['tests']),
+ include_package_data=True,
+ zip_safe=False,
+ extras_require={
+ 'testing': tests_require,
+ },
+ install_requires=requires,
+ entry_points={
+ 'paste.app_factory': [
+ 'main = cleanup_html:main',
+ ],
+ },
+)
diff --git a/testing.ini b/testing.ini
new file mode 100644
index 0000000..9b02cd4
--- /dev/null
+++ b/testing.ini
@@ -0,0 +1,53 @@
+###
+# app configuration
+# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
+[app:main]
+use = egg:cleanup_html
+
+pyramid.reload_templates = false
+pyramid.debug_authorization = false
+pyramid.debug_notfound = false
+pyramid.debug_routematch = false
+pyramid.default_locale_name = en
+
+###
+# wsgi server configuration
+###
+
+[server:main]
+use = egg:waitress#main
+listen = localhost:6543
+
+###
+# logging configuration
+# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
+
+[loggers]
+keys = root, cleanup_html
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[logger_cleanup_html]
+level = DEBUG
+handlers =
+qualname = cleanup_html
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 0000000..4f9c866
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,76 @@
+import os
+from pyramid.paster import get_appsettings
+from pyramid.scripting import prepare
+from pyramid.testing import DummyRequest, testConfig
+import pytest
+import webtest
+
+from cleanup_html import main
+
+
+def pytest_addoption(parser):
+ parser.addoption('--ini', action='store', metavar='INI_FILE')
+
+@pytest.fixture(scope='session')
+def ini_file(request):
+ # potentially grab this path from a pytest option
+ return os.path.abspath(request.config.option.ini or 'testing.ini')
+
+@pytest.fixture(scope='session')
+def app_settings(ini_file):
+ return get_appsettings(ini_file)
+
+@pytest.fixture(scope='session')
+def app(app_settings):
+ return main({}, **app_settings)
+
+@pytest.fixture
+def testapp(app):
+ testapp = webtest.TestApp(app, extra_environ={
+ 'HTTP_HOST': 'example.com',
+ })
+
+ return testapp
+
+@pytest.fixture
+def app_request(app):
+ """
+ A real request.
+
+ This request is almost identical to a real request but it has some
+ drawbacks in tests as it's harder to mock data and is heavier.
+
+ """
+ with prepare(registry=app.registry) as env:
+ request = env['request']
+ request.host = 'example.com'
+ yield request
+
+@pytest.fixture
+def dummy_request():
+ """
+ A lightweight dummy request.
+
+ This request is ultra-lightweight and should be used only when the request
+ itself is not a large focus in the call-stack. It is much easier to mock
+ and control side-effects using this object, however:
+
+ - It does not have request extensions applied.
+ - Threadlocals are not properly pushed.
+
+ """
+ request = DummyRequest()
+ request.host = 'example.com'
+
+ return request
+
+@pytest.fixture
+def dummy_config(dummy_request):
+ """
+ A dummy :class:`pyramid.config.Configurator` object. This allows for
+ mock configuration, including configuration for ``dummy_request``, as well
+ as pushing the appropriate threadlocals.
+
+ """
+ with testConfig(request=dummy_request) as config:
+ yield config
diff --git a/tests/test_functional.py b/tests/test_functional.py
new file mode 100644
index 0000000..bac5d63
--- /dev/null
+++ b/tests/test_functional.py
@@ -0,0 +1,7 @@
+def test_root(testapp):
+ res = testapp.get('/', status=200)
+ assert b'Pyramid' in res.body
+
+def test_notfound(testapp):
+ res = testapp.get('/badurl', status=404)
+ assert res.status_code == 404
diff --git a/tests/test_views.py b/tests/test_views.py
new file mode 100644
index 0000000..afe889d
--- /dev/null
+++ b/tests/test_views.py
@@ -0,0 +1,13 @@
+from cleanup_html.views.default import my_view
+from cleanup_html.views.notfound import notfound_view
+
+
+def test_my_view(app_request):
+ info = my_view(app_request)
+ assert app_request.response.status_int == 200
+ assert info['project'] == 'cleanup_html'
+
+def test_notfound_view(app_request):
+ info = notfound_view(app_request)
+ assert app_request.response.status_int == 404
+ assert info == {}