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 %} +
+
+ +
+
+ + + + + + + + + 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 == {}