diff -pruN 1.7.2-1/debian/changelog 1.10.0-1/debian/changelog --- 1.7.2-1/debian/changelog 2016-12-10 23:29:55.000000000 +0000 +++ 1.10.0-1/debian/changelog 2018-06-10 02:17:56.000000000 +0000 @@ -1,3 +1,17 @@ +yattag (1.10.0-1) unstable; urgency=medium + + [ Ondřej Nový ] + * d/control: Set Vcs-* to salsa.debian.org + + [ Sandro Tosi ] + * New upstream release + * debian/copyright + - extend packaging copyright years + * debian/control + - bump Standards-Version to 4.1.4 (no changes needed) + + -- Sandro Tosi Sat, 09 Jun 2018 22:17:56 -0400 + yattag (1.7.2-1) unstable; urgency=medium * New upstream release diff -pruN 1.7.2-1/debian/control 1.10.0-1/debian/control --- 1.7.2-1/debian/control 2016-12-10 23:29:55.000000000 +0000 +++ 1.10.0-1/debian/control 2018-06-10 02:17:56.000000000 +0000 @@ -4,10 +4,10 @@ Priority: optional Maintainer: Sandro Tosi Uploaders: Debian Python Modules Team Build-Depends: debhelper (>= 9), dh-python, python-all, python3-all -Standards-Version: 3.9.8 +Standards-Version: 4.1.4 Homepage: http://www.yattag.org/ -Vcs-Git: https://anonscm.debian.org/git/python-modules/packages/yattag.git -Vcs-Browser: https://anonscm.debian.org/cgit/python-modules/packages/yattag.git +Vcs-Git: https://salsa.debian.org/python-team/modules/yattag.git +Vcs-Browser: https://salsa.debian.org/python-team/modules/yattag Package: python-yattag Architecture: all diff -pruN 1.7.2-1/debian/copyright 1.10.0-1/debian/copyright --- 1.7.2-1/debian/copyright 2016-12-10 23:29:55.000000000 +0000 +++ 1.10.0-1/debian/copyright 2018-06-10 02:17:56.000000000 +0000 @@ -25,5 +25,5 @@ License: LGPL-2.1 Public License version 2.1 can be found in "/usr/share/common-licenses/LGPL-2.1". Files: debian/* -Copyright: 2016 Sandro Tosi +Copyright: 2016-2018 Sandro Tosi License: LGPL-2.1 diff -pruN 1.7.2-1/PKG-INFO 1.10.0-1/PKG-INFO --- 1.7.2-1/PKG-INFO 2016-11-11 11:01:47.000000000 +0000 +++ 1.10.0-1/PKG-INFO 2018-02-04 12:14:01.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: yattag -Version: 1.7.2 +Version: 1.10.0 Summary: Generate HTML or XML in a pythonic way. Pure python alternative to web template engines.Can fill HTML forms with default values and error messages. Home-page: http://www.yattag.org Author: Benjamin Le Forestier diff -pruN 1.7.2-1/setup.py 1.10.0-1/setup.py --- 1.7.2-1/setup.py 2016-11-11 10:58:13.000000000 +0000 +++ 1.10.0-1/setup.py 2018-02-04 12:11:02.000000000 +0000 @@ -5,7 +5,7 @@ with open('README.rst') as fd: setup( name='yattag', - version='1.7.2', + version='1.10.0', packages=['yattag'], author = 'Benjamin Le Forestier', author_email = 'benjamin@leforestier.org', diff -pruN 1.7.2-1/test/tests_doc.py 1.10.0-1/test/tests_doc.py --- 1.7.2-1/test/tests_doc.py 2015-02-04 15:51:18.000000000 +0000 +++ 1.10.0-1/test/tests_doc.py 2017-08-22 17:54:06.000000000 +0000 @@ -40,6 +40,16 @@ class TestDoc(unittest.TestCase): 'error' in root[1].attrib['class'] ) + def test_input_no_slash(self): + doc = Doc(stag_end = '>') + doc.input('passw', type="password") + self.assertTrue( + doc.getvalue() in ( + '', + '' + ) + ) + def test_textarea(self): doc, tag, text = Doc( defaults = { @@ -84,6 +94,29 @@ class TestDoc(unittest.TestCase): KeyError, lambda: root[0].attrib['checked'] ) + def test_input_checkbox(self): + doc, tag, text = Doc(defaults = {'gift-wrap': 'yes'}).tagtext() + with tag('body'): + doc.input('gift-wrap', type='checkbox', value = "yes") + root = ET.fromstring(doc.getvalue()) + self.assertEqual( + root[0].attrib['checked'], 'checked' + ) + + doc, tag, text = Doc(defaults = {'extras': ['fast-shipping', 'gift-wrap']}).tagtext() + with tag('body'): + for extra in ('fast-shipping', 'extension-of-warranty', 'gift-wrap'): + doc.input('extras', type="checkbox", value = extra) + root = ET.fromstring(doc.getvalue()) + self.assertEqual( + root[0].attrib['checked'], 'checked' + ) + self.assertRaises( + KeyError, lambda: root[1].attrib['checked'] + ) + self.assertEqual( + root[2].attrib['checked'], 'checked' + ) if __name__ == '__main__': unittest.main() diff -pruN 1.7.2-1/test/tests_indentation.py 1.10.0-1/test/tests_indentation.py --- 1.7.2-1/test/tests_indentation.py 2014-06-30 10:47:28.000000000 +0000 +++ 1.10.0-1/test/tests_indentation.py 2018-02-04 11:22:02.000000000 +0000 @@ -1,9 +1,14 @@ import unittest +import yattag from yattag import indent + class TestIndent(unittest.TestCase): def setUp(self): + + self.maxDiff = None + self.targets = { '

aaa

': '

aaa

', '

1

2

': """\ @@ -58,6 +63,80 @@ class TestIndent(unittest.TestCase):

""" } + self.source_code = """\ +\ +package com.google.android.gms.auth.api.signin.internal; + +import android.os.Parcel; +import android.os.Parcelable.Creator; +import android.text.TextUtils; +import com.google.android.gms.auth.api.signin.EmailSignInOptions; +import com.google.android.gms.auth.api.signin.GoogleSignInOptions; +import com.google.android.gms.common.internal.safeparcel.SafeParcelable; +import com.google.android.gms.common.internal.zzx; +import org.json.JSONObject; + +public final class SignInConfiguration implements SafeParcelable { + public static final Creator<SignInConfiguration> CREATOR = new zzp(); + final int versionCode; + private final String zzXL; + private EmailSignInOptions zzXM; + private GoogleSignInOptions zzXN; + private String zzXO; + private String zzXd; + + SignInConfiguration(int versionCode, String consumerPkgName, String serverClientId, EmailSignInOptions emailConfig, GoogleSignInOptions googleConfig, String apiKey) { + this.versionCode = versionCode; + this.zzXL = zzx.zzcM(consumerPkgName); + this.zzXd = serverClientId; + this.zzXM = emailConfig; + this.zzXN = googleConfig; + this.zzXO = apiKey; + } + + public SignInConfiguration(String consumerPkgName) { + this(2, consumerPkgName, null, null, null, null); + } +""" + + self.source_code_target = """\ + + + package com.google.android.gms.auth.api.signin.internal; + + import android.os.Parcel; + import android.os.Parcelable.Creator; + import android.text.TextUtils; + import com.google.android.gms.auth.api.signin.EmailSignInOptions; + import com.google.android.gms.auth.api.signin.GoogleSignInOptions; + import com.google.android.gms.common.internal.safeparcel.SafeParcelable; + import com.google.android.gms.common.internal.zzx; + import org.json.JSONObject; + + public final class SignInConfiguration implements SafeParcelable { + public static final Creator<SignInConfiguration> CREATOR = new zzp(); + final int versionCode; + private final String zzXL; + private EmailSignInOptions zzXM; + private GoogleSignInOptions zzXN; + private String zzXO; + private String zzXd; + + SignInConfiguration(int versionCode, String consumerPkgName, String serverClientId, EmailSignInOptions emailConfig, GoogleSignInOptions googleConfig, String apiKey) { + this.versionCode = versionCode; + this.zzXL = zzx.zzcM(consumerPkgName); + this.zzXd = serverClientId; + this.zzXM = emailConfig; + this.zzXN = googleConfig; + this.zzXO = apiKey; + } + + public SignInConfiguration(String consumerPkgName) { + this(2, consumerPkgName, null, null, null, null); + } + +""" + def test_indent(self): @@ -80,6 +159,13 @@ class TestIndent(unittest.TestCase): indent(source, indentation = " ", indent_text = True), target ) + + def test_indent_each_line(self): + self.assertEqual( + indent(self.source_code, indentation = " ", indent_text = yattag.EACH_LINE), + self.source_code_target + ) + diff -pruN 1.7.2-1/test/tests_simpledoc.py 1.10.0-1/test/tests_simpledoc.py --- 1.7.2-1/test/tests_simpledoc.py 2016-10-08 10:45:51.000000000 +0000 +++ 1.10.0-1/test/tests_simpledoc.py 2017-03-19 17:52:16.000000000 +0000 @@ -113,5 +113,21 @@ class TestSimpledoc(unittest.TestCase): ) ) + def test_stag(self): + doc = SimpleDoc() + doc.stag('img', src = '/salmon-plays-piano.jpg') + self.assertEqual( + doc.getvalue(), + '' + ) + + doc = SimpleDoc(stag_end = '>') + doc.stag('img', src = '/salmon-plays-piano.jpg') + self.assertEqual( + doc.getvalue(), + '' + ) + + if __name__ == '__main__': unittest.main() diff -pruN 1.7.2-1/yattag/doc.py 1.10.0-1/yattag/doc.py --- 1.7.2-1/yattag/doc.py 2016-10-12 15:03:29.000000000 +0000 +++ 1.10.0-1/yattag/doc.py 2017-08-22 17:55:39.000000000 +0000 @@ -18,7 +18,7 @@ class SimpleInput(object): self.tpe = tpe self.attrs = attrs - def render(self, defaults, errors, error_wrapper): + def render(self, defaults, errors, error_wrapper, stag_end = ' />'): lst = [] attrs = dict(self.attrs) error = errors and self.name in errors @@ -31,7 +31,7 @@ class SimpleInput(object): if self.name in defaults: attrs['value'] = str(defaults[self.name]) attrs['name'] = self.name - lst.append('' % (self.tpe, dict_to_attrs(attrs))) + lst.append('' % (self.__class__.tpe, dict_to_attrs(attrs))) + lst.append('Hello

will be unchanged + +

Hello world!

will be unchanged + since ' world!' is directly contained in the

node. + + This is the default since that's generally what you want for HTML. + + if indent_text is FIRST_LINE, the first line of text nodes will be indented:

Hello

would result in

- hello + hello

+ + and: + +

Hello, + where are the keys?

+ + would result in + +

+ hello, + where are the keys? +

+ + if indent_text is EACH_LINE, each line inside the text nodes will be indented: - if False, text nodes won't be indented, and the content - of any node directly containing text will be unchanged: - -

Hello

will be unchanged + + object HelloWorld { + def main(args: Array[String]) { + println("Hello, world!") + } + } + -

Hello world!

will be unchanged - since ' world!' is directly contained in the

node. + would result in - This is the default since that's generally what you want for HTML. + + + object HelloWorld { + def main(args: Array[String]) { + println("Hello, world!") + } + } + + - blank_is_text: if False, completely blank texts are ignored. That is the default. @@ -266,13 +309,18 @@ def indent(string, indentation = ' ', n append(newline) for i in range(level): append(indentation) + def _append_text(text): + if not sameline: + _indent() + if indent_text is EACH_LINE: + append(new_line_rgx.sub(r'\1' + indentation * level, text)) + else: + append(text) for i,token in enumerate(tokens): tpe = type(token) if tpe is Text: if blank_is_text or not token.isblank: - if not sameline: - _indent() - append(token.content) + _append_text(token.content) was_just_opened = False elif tpe is OpenTag and ismatched(i): was_just_opened = True @@ -280,7 +328,7 @@ def indent(string, indentation = ' ', n sameline += 1 else: _indent() - if not indent_text and directly_contains_text(i): + if indent_text is NO and directly_contains_text(i): sameline = sameline or 1 append(token.content) level += 1 diff -pruN 1.7.2-1/yattag/__init__.py 1.10.0-1/yattag/__init__.py --- 1.7.2-1/yattag/__init__.py 2016-11-11 10:58:24.000000000 +0000 +++ 1.10.0-1/yattag/__init__.py 2018-02-04 12:10:40.000000000 +0000 @@ -55,8 +55,8 @@ Full tutorial on yattag.org_ """ __author__ = "Benjamin Le Forestier (benjamin@leforestier.org)" -__version__ = '1.7.2' +__version__ = '1.10.0' from yattag.simpledoc import SimpleDoc from yattag.doc import Doc -from yattag.indentation import indent +from yattag.indentation import indent, NO, FIRST_LINE, EACH_LINE diff -pruN 1.7.2-1/yattag/simpledoc.py 1.10.0-1/yattag/simpledoc.py --- 1.7.2-1/yattag/simpledoc.py 2016-11-11 10:56:34.000000000 +0000 +++ 1.10.0-1/yattag/simpledoc.py 2017-10-26 15:15:43.000000000 +0000 @@ -1,5 +1,8 @@ __all__ = ['SimpleDoc'] +class DocError(Exception): + pass + class SimpleDoc(object): """ @@ -41,13 +44,23 @@ class SimpleDoc(object): self.doc.current_tag = self.parent_tag class DocumentRoot(object): + + class DocumentRootError(DocError, AttributeError): + # Raising an AttributeError on __getattr__ instead of just a DocError makes it compatible + # with the pickle module (some users asked for pickling of SimpleDoc instances). + # I also keep the DocError from earlier versions to avoid possible compatibility issues + # with existing code. + pass + def __getattr__(self, item): - raise DocError("DocumentRoot here. You can't access anything here.") + raise SimpleDoc.DocumentRoot.DocumentRootError("DocumentRoot here. You can't access anything here.") - def __init__(self): + def __init__(self, stag_end = ' />'): self.result = [] self.current_tag = self.__class__.DocumentRoot() self._append = self.result.append + assert stag_end in (' />', '/>', '>') + self._stag_end = stag_end def tag(self, tag_name, *args, **kwargs): """ @@ -202,15 +215,27 @@ class SimpleDoc(object): Example:: doc.stag('img', src = '/salmon-plays-piano.jpg') - # appends to the document + + If you want to produce self closing tags without the ending slash (HTML5 style), + use the stag_end parameter of the SimpleDoc constructor at the creation of the + SimpleDoc instance. + + Example:: + + >>> doc = SimpleDoc(stag_end = '>') + >>> doc.stag('br') + >>> doc.getvalue() + '
' """ if args or kwargs: - self._append("<%s %s />" % ( + self._append("<%s %s%s" % ( tag_name, dict_to_attrs(_attributes(args, kwargs)), + self._stag_end )) else: - self._append("<%s />" % tag_name) + self._append("<%s%s" % (tag_name, self._stag_end)) def cdata(self, strg, safe = False): """ @@ -332,9 +357,6 @@ class SimpleDoc(object): del self.current_tag.attrs['class'] except KeyError: pass - -class DocError(Exception): - pass def html_escape(s): if isinstance(s,(int,float)):