Skip to content

Commit

Permalink
Merge pull request #92 from sydoluciani/Add_Unofficial-Deformdemo
Browse files Browse the repository at this point in the history
Add unofficial deformdemo
  • Loading branch information
stevepiercy authored Oct 31, 2020
2 parents 869d68e + bbbbfc2 commit 5ca2bc5
Show file tree
Hide file tree
Showing 12 changed files with 574 additions and 8 deletions.
5 changes: 5 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
2.0.15 (unreleased)
-------------------

- Added unofficial deformdemo. This provides a space for contributors to add
their widgets without requiring tests, especially when the functional tests
cannot pass using Selenium. [sydoluciani]
https://github.com/Pylons/deformdemo/pull/92

- Changed dateparts widget to use ``type="number"`` instead of default `text`.
https://github.com/Pylons/deform/issues/442

Expand Down
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
graft deformdemo
graft unofficial-deformdemo

include *.py
include *.sh
Expand Down
10 changes: 8 additions & 2 deletions deformdemo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2892,13 +2892,19 @@ def translator(term):
return get_localizer(get_current_request()).translate(term)

# Configure renderer
configure_zpt_renderer(("deformdemo:custom_widgets",), translator)

configure_zpt_renderer(
("deformdemo:custom_widgets", "unofficial-deformdemo:custom_widgets"),
translator,
)
config.add_static_view("static_deform", "deform:static")
config.add_route(
"unofficial-deformdemo", "/unofficial-deformdemo*traverse"
)
config.add_route("deformdemo", "*traverse")

def onerror(*arg):
pass

config.scan("deformdemo", onerror=onerror)
config.include("..unofficial-deformdemo")
return config.make_wsgi_app()
9 changes: 6 additions & 3 deletions deformdemo/templates/index.pt
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@
<div metal:fill-slot="main" tal:omit-tag="">
<div class="page-header">
<h1><a href="https://docs.pylonsproject.org/projects/deform/en/latest/">Deform</a> is a Python library for generating HTML
forms<br/><small>Each link on the left demonstrates a capability</small>
forms.<br/>
<small>Each link on the left demonstrates a capability.</small>
</h1>
</div>

<div class="well">

<p>The <a href="/">official Deform Demo</a> supports tested and documented widgets.
The <a href="/unofficial-deformdemo">unofficial Deform Demo</a> provides a space for contributors to add custom widgets that are not supported with the usual rigorous tests and documentation that is required by the Pylons Project.</p>
<p>
This demo is written using <a
href="https://trypyramid.com/">Pyramid</a>. Note that Deform does
not depend on any particular web framework,
we just had to write a demo application in <em>something</em>.
not depend on any particular web framework.
We had to write a demo application in <em>something</em>.
If you would like to run this demo application locally,
please read the <a href="https://github.com/Pylons/deformdemo">README
file for installation of this application</a>.
Expand Down
11 changes: 8 additions & 3 deletions deformdemo/templates/main.pt
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,14 @@

<div class="navbar navbar-default" role="navigation">
<div class="container">
<a class="navbar-brand" href="/"><span class="glyphicon glyphicon-info-sign"></span>
<span i18n:translate=""> Deform Demo</span>
</a>
<ul class="nav nav-pills">
<li class="nav-item active">
<a class="nav-link active" href="/"><span i18n:translate="">Deform Demo</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="/unofficial-deformdemo"><span i18n:translate="">Unofficial Deform Demo</span></a>
</li>
</ul>
</div>
</div>

Expand Down
231 changes: 231 additions & 0 deletions unofficial-deformdemo/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
# -*- coding: utf-8 -*-

""" A Pyramid app that demonstrates various Deform widgets and
capabilities and which provides a functional test suite """

import inspect
import logging
import pprint
import sys

import colander
from pyramid.i18n import TranslationStringFactory
from pyramid.i18n import get_locale_name
from pyramid.renderers import get_renderer
from pyramid.response import Response
from pyramid.view import view_config
from pyramid.view import view_defaults

import deform
from pygments import highlight
from pygments.formatters import HtmlFormatter
from pygments.lexers import PythonLexer


log = logging.getLogger(__name__)


PY3 = sys.version_info[0] == 3
PY38MIN = sys.version_info[0] == 3 and sys.version_info[1] >= 8

if PY3:

def unicode(val, encoding="utf-8"):
return val


_ = TranslationStringFactory("unofficial-deformdemo")

formatter = HtmlFormatter(nowrap=True)
css = formatter.get_style_defs()

# the zpt_renderer above is referred to within the demo.ini file by dotted name


class demonstrate(object):
def __init__(self, title):
self.title = title

def __call__(self, method):
method.demo = self.title
return method


# Py2/Py3 compat
# http://stackoverflow.com/a/16888673/315168
# eliminate u''
def my_safe_repr(obj, context, maxlevels, level, sort_dicts=True):

if type(obj) == unicode:
obj = obj.encode("utf-8")

# Python 3.8 changed the call signature of pprint._safe_repr.
# by adding sort_dicts.
if PY38MIN:
return pprint._safe_repr(obj, context, maxlevels, level, sort_dicts)
else:
return pprint._safe_repr(obj, context, maxlevels, level)


@view_defaults(route_name="unofficial-deformdemo")
class UnofficialDeformDemo(object):
def __init__(self, request):
self.request = request
self.macros = get_renderer("templates/main.pt").implementation().macros

def render_form(
self,
form,
appstruct=colander.null,
submitted="submit",
success=None,
readonly=False,
is_i18n=False,
):

captured = None

if submitted in self.request.POST:
# the request represents a form submission
try:
# try to validate the submitted values
controls = self.request.POST.items()
captured = form.validate(controls)
if success:
response = success()
if response is not None:
return response
html = form.render(captured)
except deform.ValidationFailure as e:
# the submitted values could not be validated
html = e.render()

else:
# the request requires a simple form rendering
html = form.render(appstruct, readonly=readonly)

if self.request.is_xhr:
return Response(html)

code, start, end = self.get_code(2)
locale_name = get_locale_name(self.request)

reqts = form.get_widget_resources()

printer = pprint.PrettyPrinter()
printer.format = my_safe_repr
output = printer.pformat(captured)
captured = highlight(output, PythonLexer(), formatter)

# values passed to template for rendering
return {
"form": html,
"captured": captured,
"code": code,
"start": start,
"end": end,
"is_i18n": is_i18n,
"locale": locale_name,
"demos": self.get_demos(),
"title": self.get_title(),
"css_links": reqts["css"],
"js_links": reqts["js"],
}

def get_code(self, level):
frame = sys._getframe(level)
lines, start = inspect.getsourcelines(frame.f_code)
end = start + len(lines)
code = "".join(lines)
if not PY3:
code = unicode(code, "utf-8")
return highlight(code, PythonLexer(), formatter), start, end

@view_config(name="thanks.html", route_name="unofficial-deformdemo")
def thanks(self):
return Response(
"<html><body><p>Thanks!</p><small>"
'<a href="..">Up</a></small></body></html>'
)

@view_config(name="allcode",
renderer="templates/code.pt",
route_name="unofficial-deformdemo")
def allcode(self):
params = self.request.params
start = params.get("start")
end = params.get("end")
hl_lines = None
if start and end:
start = int(start)
end = int(end)
hl_lines = list(range(start, end))
code = open(inspect.getsourcefile(self.__class__), "r").read()
code = code.encode("utf-8")
formatter = HtmlFormatter(
linenos="table",
lineanchors="line",
cssclass="hightlight ",
hl_lines=hl_lines,
)
html = highlight(code, PythonLexer(), formatter)
return {"code": html, "demos": self.get_demos()}

def get_title(self):
# gross hack; avert your eyes
frame = sys._getframe(3)
attr = frame.f_locals["attr"]
inst = frame.f_locals["inst"]
method = getattr(inst, attr)
return method.demo

@view_config(name="pygments.css", route_name="unofficial-deformdemo")
def cssview(self):
response = Response(body=css, content_type="text/css")
response.cache_expires = 360
return response

@view_config(renderer="templates/index.pt",
route_name="unofficial-deformdemo")
def index(self):
return {"demos": self.get_demos()}

def get_demos(self):
def predicate(value):
if getattr(value, "demo", None) is not None:
return True

demos = inspect.getmembers(self, predicate)
L = []
for name, method in demos:
url = self.request.resource_url(
self.request.root, name, route_name="unofficial-deformdemo"
)
L.append((method.demo, url))
L.sort()
return L

# Unofficial Deform Demo Forms Start Here.

@view_config(name="textinput",
renderer="templates/form.pt",
route_name="unofficial-deformdemo")
@demonstrate("Text Input Widget")
def textinput(self):
class Schema(colander.Schema):
text = colander.SchemaNode(
colander.String(),
validator=colander.Length(max=100),
widget=deform.widget.TextInputWidget(),
description="Enter some text",
)

schema = Schema()
form = deform.Form(schema, buttons=("submit",))

return self.render_form(form)


def includeme(config):

config.scan("unofficial-deformdemo")
6 changes: 6 additions & 0 deletions unofficial-deformdemo/templates/code.pt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<div metal:use-macro="view.macros['master']">
<div metal:fill-slot="main">
<h2>Module Code</h2>
<span tal:replace="structure code"/>
</div>
</div>
46 changes: 46 additions & 0 deletions unofficial-deformdemo/templates/form.pt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!DOCTYPE html>
<div metal:use-macro="view.macros['master']"
i18n:domain="deformdemo">
<div metal:fill-slot="main">
<div class="btn-group" tal:condition="is_i18n|False">
<a tal:attributes="class locale == 'en' and 'active btn btn-default' or 'btn btn-default'" href="${request.path_url}?_LOCALE_=en">English</a>
<a tal:attributes="class locale == 'de' and 'active btn btn-default' or 'btn btn-default'" href="${request.path_url}?_LOCALE_=de">Deutsch</a>
<a tal:attributes="class locale == 'nl' and 'active btn btn-default' or 'btn btn-default'" href="${request.path_url}?_LOCALE_=nl">Nederlands</a>
<a tal:attributes="class locale == 'ru' and 'active btn btn-default' or 'btn btn-default'" href="${request.path_url}?_LOCALE_=ru">Russian</a>
<a tal:attributes="class locale == 'es' and 'active btn btn-default' or 'btn btn-default'" href="${request.path_url}?_LOCALE_=es">Español</a>
<br />
<br />
</div>


<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Demo: ${title}</h3>
</div>
<div class="panel-body">
<div id="form" tal:content="structure form"/>
</div>
</div>

<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">Captured submission</h3>
</div>
<div class="panel-body">
<pre style="border: none; background-color: #FFF" class="highlight" id="captured" tal:content="structure captured"/>
</div>
</div>

<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Code <a href="${request.resource_url(request.root, 'allcode', query={'start':start, 'end':end}, anchor='line-%s' % start)}"><small>
(click to show in context)</small></a>
</h3>
</div>
<div class="panel-body highlight">
<pre style="border: none; background-color: #FFF" tal:content="structure code"/>
</div>
</div>
</div>
</div>

Loading

0 comments on commit 5ca2bc5

Please sign in to comment.