Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Python declarative

197 views
Skip to first unread message

Sergio Tortosa Benedito

unread,
Jan 15, 2014, 12:02:08 PM1/15/14
to pytho...@python.org
Hi I'm developing a sort of language extension for writing GUI programs
called guilang, right now it's written in Lua but I'm considreing Python
instead (because it's more tailored to alone applications). My question
it's if I can achieve this declarative-thing in python. Here's an
example:

Window "myWindow" {
title="Hello world";
Button "myButton" {
label="I'm a button";
onClick=exit
}
}
print(myWindow.myButton.label)

Of course it doesn't need to be 100% equal. Thanks in advance

Sergio


Chris Angelico

unread,
Jan 15, 2014, 12:33:21 PM1/15/14
to pytho...@python.org
On Thu, Jan 16, 2014 at 4:02 AM, Sergio Tortosa Benedito
<sert...@gmail.com> wrote:
> Hi I'm developing a sort of language extension for writing GUI programs
> called guilang, right now it's written in Lua but I'm considreing Python
> instead (because it's more tailored to alone applications). My question
> it's if I can achieve this declarative-thing in python. Here's an
> example:
>
> Window "myWindow" {
> title="Hello world";
> Button "myButton" {
> label="I'm a button";
> onClick=exit
> }
> }
> print(myWindow.myButton.label)

Probably the easiest way to do that would be with dictionaries or
function named arguments. It'd be something like this:

myWindow = Window(
title="Hello World",
myButton=Button(
label="I'm a button",
onClick=exit
)
)
print(myWindow.myButton.label)

For this to work, you'd need a Window class that recognizes a number
of keyword arguments (eg for title and other attributes), and then
takes all other keyword arguments and turns them into its children.
Possible, but potentially messy; if you happen to name your button
"icon", it might be misinterpreted as an attempt to set the window's
icon, and cause a very strange and incomprehensible error.

The syntax you describe there doesn't allow any flexibility in
placement. I don't know how you'd organize that; but what you could do
is something like GTK uses: a Window contains exactly one child, which
will usually be a layout manager. Unfortunately the Python GTK
bindings don't allow such convenient syntax as you use here, so you'd
need some sort of wrapper. But it wouldn't be hard to set up something
like this:


def clickme(obj):
print("You clicked me!")
obj.set_label("Click me again!")

myWindow = Window(
title="Hello World",
signal_delete=exit
).add(Vbox(spacing=10)
.add(Button(label="I'm a button!", signal_clicked=exit))
.add(Button(label="Click me", signal_clicked=clickme))
)

This is broadly similar to how I create a window using GTK with Pike,
and it's easy to structure the code the same way the window is
structured.

If the number of helper classes you'd have to make gets daunting, you
could possibly do this:

myWindow = GTK(Gtk.Window,
title="Hello World",
signal_delete=exit
).add(GTK(Gtk.Vbox, spacing=10)
.add(GTK(Gtk.Button, label="I'm a button!", signal_clicked=exit))
.add(GTK(Gtk.Button, label="Click me", signal_clicked=clickme))
)

so there's a single "GTK" class, which takes as its first positional
argument a GTK object type to clone. This is all perfectly valid
Python syntax, but I don't know of a convenient way to do this with
the current modules, so it may require writing a small amount of
wrapper code.

ChrisA

Terry Reedy

unread,
Jan 15, 2014, 5:58:05 PM1/15/14
to pytho...@python.org
On 1/15/2014 12:33 PM, Chris Angelico wrote:
> On Thu, Jan 16, 2014 at 4:02 AM, Sergio Tortosa Benedito
> <sert...@gmail.com> wrote:
>> Hi I'm developing a sort of language extension for writing GUI programs
>> called guilang, right now it's written in Lua but I'm considreing Python
>> instead (because it's more tailored to alone applications). My question
>> it's if I can achieve this declarative-thing in python. Here's an
>> example:
>>
>> Window "myWindow" {
>> title="Hello world";
>> Button "myButton" {
>> label="I'm a button";
>> onClick=exit
>> }
>> }
>> print(myWindow.myButton.label)
>
> Probably the easiest way to do that would be with dictionaries or
> function named arguments. It'd be something like this:
>
> myWindow = Window(
> title="Hello World",
> myButton=Button(
> label="I'm a button",
> onClick=exit
> )
> )
> print(myWindow.myButton.label)

This is exactly what I was going to suggest.

> For this to work, you'd need a Window class that recognizes a number
> of keyword arguments (eg for title and other attributes), and then
> takes all other keyword arguments and turns them into its children.

I would make the required args positional-or-keyword, with or without a
default. Something like (tested)

class Window:
def __init__(self, title, *kwds) # or title='Window title'
self.title = title
self.__dict__.update(kwds)

class Button:
def __init__(self, label, **kwds):
self.label = label
self.__dict__.update(kwds)

<add Chris' code above>
>>>
I'm a button

> Possible, but potentially messy; if you happen to name your button
> "icon", it might be misinterpreted as an attempt to set the window's
> icon, and cause a very strange and incomprehensible error.

Puns are always a problem with such interfaces. Validate the args as
much as possible. An icon should be a bitmap of appropriate size.
Optional args should perhaps all be widgets (instances of a Widget
baseclass).

--
Terry Jan Reedy

Chris Angelico

unread,
Jan 15, 2014, 6:09:47 PM1/15/14
to pytho...@python.org
On Thu, Jan 16, 2014 at 9:58 AM, Terry Reedy <tjr...@udel.edu> wrote:
> class Window:
> def __init__(self, title, *kwds) # or title='Window title'
> self.title = title
> self.__dict__.update(kwds)

Does that want a second asterisk, matching the Button definition?

>> Possible, but potentially messy; if you happen to name your button
>> "icon", it might be misinterpreted as an attempt to set the window's
>> icon, and cause a very strange and incomprehensible error.
>
> Puns are always a problem with such interfaces. Validate the args as much as
> possible. An icon should be a bitmap of appropriate size. Optional args
> should perhaps all be widgets (instances of a Widget baseclass).

Yeah, but you'd still get back an error saying "icon should be a
bitmap" where the real problem is "icon should be called something
else". It might be worth explicitly adorning properties, or separating
them into two categories. Since the keyword-named-children system has
the other problem of being hard to lay out (how do you specify the
order?), I'd look at keyword args for properties and something
separate for children - either the layout I used above with .add(),
which allows extra args as necessary, or something like this:

myWindow = Window(
title="Hello World",
children=[Button(
label="I'm a button",
onClick=exit
)]
)

Or maybe allow "child=" as a shortcut, since a lot of widgets will
have exactly one child.

ChrisA

Tim Chase

unread,
Jan 15, 2014, 7:48:39 PM1/15/14
to pytho...@python.org
On 2014-01-16 10:09, Chris Angelico wrote:
> myWindow = Window(
> title="Hello World",
> children=[Button(
> label="I'm a button",
> onClick=exit
> )]
> )

This also solves the problem that **kwargs are just a dict, which is
inherently unordered. So with the previous scheme, you'd just get an
unordered bag of controls that Python could then dump into your
containing window as its dict-traversal algorithms saw fit. :-)

-tkc



Chris Angelico

unread,
Jan 15, 2014, 8:38:51 PM1/15/14
to pytho...@python.org
Yeah, I don't really want my window layout to randomize every Python startup :)

Actually... I'm really REALLY glad code like the previous version
wasn't prevalent. It would have made for intense opposition to hash
randomization - as I recall, the strongest voice against randomization
was that tests would start to fail (IMO, a simple way to print a
dictionary with its keys sorted would both solve that and provide an
aesthetically-pleasing display). Imagine if someone spent hours
crafting child object names in order to force the children to be added
in the right order, and then along comes the new Python and it's all
broken...

But I still think it should be a method (as it is in GTK, not familiar
enough with the others), as there's no way with the parameter system
to (a) add children after object creation, or (b) specify parameters
(GTK's boxes let you choose, per-child, whether they'll be expanded to
fill any spare space - by default they all will, ie spare room is
split between them, but often you want to choose one to be expanded
and another not). PyGTK is mostly there, but since its .add() method
returns None, chaining isn't possible. Method chaining like that is
somewhat controversial... I would love to have some kind of syntax
that says "and the value of this expression is the bit before the
dot", but I have no idea what would be clean.

ChrisA

Terry Reedy

unread,
Jan 15, 2014, 10:35:43 PM1/15/14
to pytho...@python.org
On 1/15/2014 6:09 PM, Chris Angelico wrote:
> On Thu, Jan 16, 2014 at 9:58 AM, Terry Reedy <tjr...@udel.edu> wrote:
>> class Window:
>> def __init__(self, title, *kwds) # or title='Window title'
>> self.title = title
>> self.__dict__.update(kwds)
>
> Does that want a second asterisk, matching the Button definition?

I must have changed to **kwds after copying.
>
>>> Possible, but potentially messy; if you happen to name your button
>>> "icon", it might be misinterpreted as an attempt to set the window's
>>> icon, and cause a very strange and incomprehensible error.
>>
>> Puns are always a problem with such interfaces. Validate the args as much as
>> possible. An icon should be a bitmap of appropriate size. Optional args
>> should perhaps all be widgets (instances of a Widget baseclass).
>
> Yeah, but you'd still get back an error saying "icon should be a
> bitmap" where the real problem is "icon should be called something
> else".

One could say so in the message

InterfaceError("The icon object must be a bitmap or else the non-bitmap
object should be called something else.)

> It might be worth explicitly adorning properties, or separating
> them into two categories. Since the keyword-named-children system has
> the other problem of being hard to lay out (how do you specify the
> order?), I'd look at keyword args for properties and something
> separate for children - either the layout I used above with .add(),
> which allows extra args as necessary, or something like this:
>
> myWindow = Window(
> title="Hello World",
> children=[Button(
> label="I'm a button",
> onClick=exit
> )]
> )
> Or maybe allow "child=" as a shortcut, since a lot of widgets will
> have exactly one child.


--
Terry Jan Reedy

Francesco Bochicchio

unread,
Jan 17, 2014, 9:22:11 AM1/17/14
to
Some time ago I played with Tkinter trying a more declarative way of coding the GUI building part and I come out with this:

top = Tk( 'top' ).add (
Frame( 'frame' ).add (
Pack( side = 'top' ),
Frame ( 'panel1' ).add (
Pack( side='left'),
Label ( 'label', text="Entry 1 : " ),
Entry ( 'entry' )
),
Frame( 'panel2' ).add (
Pack( side='left'),
Label ( 'label', text="Entry 2 : " ),
Entry( 'entry' )
),
Pack( side = 'bottom' ), # packing change
Button( 'button',
text='Click Me' ))
)

top.frame.button["command"] = functools.partial(button_cb, top)
top.realize().mainloop()

which, without changing the underlying plumbing, may also be written this way, which avoid nesting but still looks declarative-ish :

top = Tk( 'top' )
top.add( Frame( 'frame' ) )
top.frame.add (
Pack( side = 'top' ),
Frame ( 'panel1' ),
Frame( 'panel2' ),
Pack( side = 'bottom' ), # packing change
Button( 'button',
text='Click Me',
command = functools.partial(button_cb, top) ) )

top.frame.panel1.add(
Pack( side='left'),
Label ( 'label', text="Entry 1 : " ),
Entry ( 'entry' ) )

top.frame.panel2.add(
Pack( side='left'),
Label ( 'label', text="Entry 1 : " ),
Entry( 'entry' ) )

top.realize().mainloop()


The underlying plumbing for those two examples is just two classes amounting to about fifty lines of code, plus one-liner wrappers for each kind of widgets/geometry

This just to tell you that yes, with python you can write declarative-looking code ... if you don't mind parenthesis :-)

sert...@gmail.com

unread,
Jan 17, 2014, 9:47:47 AM1/17/14
to
Wow thank you very much, really. I wasn't expecting that much from everyone. BTW, sorry for no answering earlier , I'm receiving no e-mails from the list (I'll look later what happens). First, I don't like that all parenthesis, I like to differentiate which type of delimiter is, this is not so bad if using spaces but anyways it's a little more difficult.Second, In regard, to using something like myWindow=Window rather than Window "myWindow", at first I didn't liked it that much, but in the end it does tell the user that the attributes can be accesed just like anything else. Finally , the project I'm developing (guilang) it's toolkit-independent so I don't mind having to do some wrappers.

Sergio

Tim Roberts

unread,
Jan 18, 2014, 4:13:26 PM1/18/14
to
sert...@gmail.com wrote:
>
>First, I don't like that all parenthesis, I like to differentiate
>which type of delimiter is, this is not so bad if using spaces but
>anyways it's a little more difficult. Second, In regard, to using
>something like myWindow=Window rather than Window "myWindow", at
>first I didn't liked it that much, but in the end it does tell the
>user that the attributes can be accesed just like anything else.

Well, this all depends on whether you want this code to BE Python code, or
just to be READ BY Python code. That's a huge difference. If you want
your layout to BE Python code, then you have little alternative except to
use the suggestions offered. But if you simply want your scripts to be
interpreted by a Python program, then you can do whatever you want.
--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

sert...@gmail.com

unread,
Jan 19, 2014, 5:27:38 AM1/19/14
to
El miércoles, 15 de enero de 2014 18:02:08 UTC+1, Sergio Tortosa Benedito escribió:
OK, thanks, maybe the to be read by python may be interesting .Anyway, I think I'll have to consider all the options I have right now (Lua,Python,A file readed by Python). Really, thanks, you are awesome.

Sergio.

Francesco Bochicchio

unread,
Jan 20, 2014, 2:25:40 AM1/20/14
to
Looking at my own code after four years, I just realized that most of parentheses can be avoided by redefining the += operators to be a synonym of the add method.

Go figure, I guess that with age it _does_ come a little wisdom ... :-)

Ciao
-----
FB

sert...@gmail.com

unread,
Jan 22, 2014, 3:38:44 PM1/22/14
to
El miércoles, 15 de enero de 2014 18:02:08 UTC+1, Sergio Tortosa Benedito escribió:
Hi again, just wrote to announce that I'm going to rewrite guilang in Python. Again thanks you are all awesome :).

Asaf Las

unread,
Jan 22, 2014, 4:16:53 PM1/22/14
to
Hi Sergio

i am novice in python, but let me suggest you something:
it would be beneficial to use json text file to specify
your gui so composite data structure can be created using
json and then your program can construct window giving
its content will be based on simple text file?
You can add every parameter to json encoded window system
once your window construction will be using as interpreter
for that. JSON is very structured and quite presentable for
such kind of things.

What Gurus do think about this suggestion?

/Asaf

Chris Angelico

unread,
Jan 22, 2014, 9:29:06 PM1/22/14
to pytho...@python.org
On Thu, Jan 23, 2014 at 8:16 AM, Asaf Las <roe...@gmail.com> wrote:
> i am novice in python, but let me suggest you something:
> it would be beneficial to use json text file to specify
> your gui so composite data structure can be created using
> json and then your program can construct window giving
> its content will be based on simple text file?
> You can add every parameter to json encoded window system
> once your window construction will be using as interpreter
> for that. JSON is very structured and quite presentable for
> such kind of things.
>
> What Gurus do think about this suggestion?

JSON is better than XML for that, but in my opinion, both are
unnecessary. Python code is easy to edit. (See [1] for more on Python
and XML.) When you're writing compiled code, it makes good sense to
drop out of code and use a simple text file when you can; but when
your code *is* a simple text file, why go to the effort of making a
JSON-based window builder? (Unless you already have one. GladeXML may
well be exactly what you want, in which case, go ahead and use it. But
personally, I don't.) JSON is a fantastic format for transmitting
complex objects around the internet; it's compact (unlike XML),
readable in many languages (like XML), easily readable by humans
(UNLIKE XML!), and can represent all the most common data structures
(subtly, XML can't technically do this). It's superb at what it
does... but it doesn't do Python GUIs. For those, use Python itself.

ChrisA

[1] http://dirtsimple.org/2004/12/python-is-not-java.html

Terry Reedy

unread,
Jan 22, 2014, 11:08:06 PM1/22/14
to pytho...@python.org
On 1/22/2014 9:29 PM, Chris Angelico wrote:
> On Thu, Jan 23, 2014 at 8:16 AM, Asaf Las <roe...@gmail.com> wrote:
>> i am novice in python, but let me suggest you something:
>> it would be beneficial to use json text file to specify
>> your gui so composite data structure can be created using
>> json and then your program can construct window giving
>> its content will be based on simple text file?
>> You can add every parameter to json encoded window system
>> once your window construction will be using as interpreter
>> for that. JSON is very structured and quite presentable for
>> such kind of things.

> JSON is better than XML for that, but in my opinion, both are
> unnecessary. Python code is easy to edit. (See [1] for more on Python
> and XML.) When you're writing compiled code, it makes good sense to
> drop out of code and use a simple text file when you can; but when
> your code *is* a simple text file, why go to the effort of making a
> JSON-based window builder? (Unless you already have one. GladeXML may
> well be exactly what you want, in which case, go ahead and use it. But
> personally, I don't.) JSON is a fantastic format for transmitting
> complex objects around the internet; it's compact (unlike XML),
> readable in many languages (like XML), easily readable by humans
> (UNLIKE XML!), and can represent all the most common data structures
> (subtly, XML can't technically do this). It's superb at what it
> does... but it doesn't do Python GUIs. For those, use Python itself.

I would only use JSON if I wanted a declaration format that was
independent of implementation languages, that could be read and turned
into application objects by as least two languages.

--
Terry Jan Reedy

Frank Millman

unread,
Jan 24, 2014, 4:21:12 AM1/24/14
to pytho...@python.org

"Chris Angelico" <ros...@gmail.com> wrote in message
news:CAPTjJmokZUHta7Y3x_=6eUjKpv2Td2iaqr...@mail.gmail.com...
> On Thu, Jan 23, 2014 at 8:16 AM, Asaf Las <roe...@gmail.com> wrote:
>> i am novice in python, but let me suggest you something:
>> it would be beneficial to use json text file to specify
>> your gui so composite data structure can be created using
>> json and then your program can construct window giving
>> its content will be based on simple text file?
>> You can add every parameter to json encoded window system
>> once your window construction will be using as interpreter
>> for that. JSON is very structured and quite presentable for
>> such kind of things.
>>
>> What Gurus do think about this suggestion?
>
> JSON is better than XML for that, but in my opinion, both are
> unnecessary. Python code is easy to edit. (See [1] for more on Python
> and XML.) When you're writing compiled code, it makes good sense to
> drop out of code and use a simple text file when you can; but when
> your code *is* a simple text file, why go to the effort of making a
> JSON-based window builder? (Unless you already have one. GladeXML may
> well be exactly what you want, in which case, go ahead and use it. But
> personally, I don't.) JSON is a fantastic format for transmitting
> complex objects around the internet; it's compact (unlike XML),
> readable in many languages (like XML), easily readable by humans
> (UNLIKE XML!), and can represent all the most common data structures
> (subtly, XML can't technically do this). It's superb at what it
> does... but it doesn't do Python GUIs. For those, use Python itself.
>

I find that I am using JSON and XML more and more in my project, so I
thought I would explain what I am doing to see if others think this is an
acceptable approach or if I have taken a wrong turn.

I have various data structures, some simple, some more complex, of which I
have many instances. I want to serialise and store them in a database. This
has two benefits. Firstly, I just have to write one piece of python code
that interprets and deals with each structure, so it avoids duplicate code.
Secondly, I can design a gui that exposes the structures to non-programmers,
giving them the ability to modify them or create new ones. Simple structures
can be expressed in JSON. I use XML to represent the more complex ones.

I will give two examples, one simple and one complex.

I store database metadata in the database itself. I have a table that
defines each table in the database, and I have a table that defines each
column. Column definitions include information such as data type, allow
null, allow amend, maximum length, etc. Some columns require that the value
is constrained to a subset of allowable values (e.g. 'title' must be one of
'Mr', 'Mrs', etc.). I know that this can be handled by a 'check' constraint,
but I have added some additional features which can't be handled by that. So
I have a column in my column-definition table called 'choices', which
contains a JSON'd list of allowable choices. It is actually more complex
than that, but this will suffice for a simple example.

For my more complex example, I should explain that my project involves
writing a generalised business/accounting system. Anyone who has worked on
these knows that you quickly end up with hundreds of database tables storing
business data, and hundreds of forms allowing users to CRUD the data
(create/read/update/delete). Each form is unique, and yet they all share a
lot of common characteristics. I have abstracted the contents of a form
sufficiently that I can represent at least 90% of it in XML. This is not
just the gui, but all the other elements - the tables required, any input
parameters, any output parameters, creating any variables to be used while
entering the form, any business logic to be applied at each point, etc. Each
form definition is stored as gzip'd XML in a database, and linked to the
menu system. There is just one python program that responds to the selection
of a menu option, retrieves the form from the database, unpacks it and runs
it.

Incidentally, I would take issue with the comment that 'JSON is easily
readable by humans (UNLIKE XML)'. Here is a more complete example of my
'choices' definition.

[true, true, [["admin", "System administrator", [], []], ["ind",
"Individual", [["first_name", true], ["surname", true]], [["first_name", "
"], ["surname", ""]]], ["comp", "Company", [["comp_name", true], ["reg_no",
true], ["vat_no", false]], [["comp_name", ""]]]]]

You can read it, but what does it mean?

This is what it would look like if I stored it in XML -

<choices use_subtypes="true" use_displaynames="true">
<choice code="admin" descr="System administrator">
<subtype_columns/>
<displaynames/>
</choice>
<choice code="ind" descr="Individual">
<subtype_columns>
<subtype_column col_name="first_name" required="true"/>
<subtype_column col_name="surname" required="true"/>
</subtype_columns>
<displaynames>
<displayname col_name="first_name" separator=" "/>
<displayname col_name="surname" separator=""/>
</displaynames>
</choice>
<choice code="comp" descr="Company">
<subtype_columns>
<subtype_column col_name="comp_name" required="true"/>
<subtype_column col_name="reg_no" required="true"/>
<subtype_column col_name="vat_no" required="false"/>
</subtype_columns>
<displaynames>
<displayname col_name="comp_name" separator=""/>
</displaynames>
</choice>
</choices>

More verbose - sure. Less human-readable - I don't think so.

Also, intuitively one would think it would take much longer to process the
XML version compared with the JSON version. I have not done any benchmarks,
but I use lxml, and I am astonished at the speed. Admittedly a typical
form-processor spends most of its time waiting for user input. Even so, for
my purposes, I have never felt the slightest slowdown caused by XML.

Comments welcome.

Frank Millman



Rustom Mody

unread,
Jan 24, 2014, 4:53:40 AM1/24/14
to
On Friday, January 24, 2014 2:51:12 PM UTC+5:30, Frank Millman wrote:

> Incidentally, I would take issue with the comment that 'JSON is easily
> readable by humans (UNLIKE XML)'. Here is a more complete example of my
> 'choices' definition.

> [true, true, [["admin", "System administrator", [], []], ["ind",
> "Individual", [["first_name", true], ["surname", true]], [["first_name", "
> "], ["surname", ""]]], ["comp", "Company", [["comp_name", true], ["reg_no",
> true], ["vat_no", false]], [["comp_name", ""]]]]]

> You can read it, but what does it mean?

> This is what it would look like if I stored it in XML -


> More verbose - sure. Less human-readable - I don't think so.

> Also, intuitively one would think it would take much longer to process the
> XML version compared with the JSON version. I have not done any benchmarks,
> but I use lxml, and I am astonished at the speed. Admittedly a typical
> form-processor spends most of its time waiting for user input. Even so, for
> my purposes, I have never felt the slightest slowdown caused by XML.

> Comments welcome.

Of json/XML/yml I prefer yml because it has the terseness of json and the
structuredness of xml -- well almost

The flipside is that pyyaml needs to be installed unlike json.
But then you are installing lxml anyway

Chris Angelico

unread,
Jan 24, 2014, 6:18:01 AM1/24/14
to pytho...@python.org
On Fri, Jan 24, 2014 at 8:21 PM, Frank Millman <fr...@chagford.com> wrote:
> I find that I am using JSON and XML more and more in my project, so I
> thought I would explain what I am doing to see if others think this is an
> acceptable approach or if I have taken a wrong turn.

Please don't take this the wrong way, but the uses of JSON and XML
that you describe are still completely inappropriate. Python does not
need this sort of thing.

> I store database metadata in the database itself. I have a table that
> defines each table in the database, and I have a table that defines each
> column. Column definitions include information such as data type, allow
> null, allow amend, maximum length, etc. Some columns require that the value
> is constrained to a subset of allowable values (e.g. 'title' must be one of
> 'Mr', 'Mrs', etc.). I know that this can be handled by a 'check' constraint,
> but I have added some additional features which can't be handled by that. So
> I have a column in my column-definition table called 'choices', which
> contains a JSON'd list of allowable choices. It is actually more complex
> than that, but this will suffice for a simple example.

This is MySQL-style of thinking, that a database is a thing that's
interpreted by an application. The better way to do it is to craft a
check constraint; I don't know what features you're trying to use that
can't be handled by that, but (at least in PostgreSQL) I've never had
anything that can't be expressed that way. With the simple example you
give, incidentally, it might be better to use an enumeration rather
than a CHECK constraint, but whichever way.

> For my more complex example, I should explain that my project involves
> writing a generalised business/accounting system. Anyone who has worked on
> these knows that you quickly end up with hundreds of database tables storing
> business data, and hundreds of forms allowing users to CRUD the data
> (create/read/update/delete). Each form is unique, and yet they all share a
> lot of common characteristics. I have abstracted the contents of a form
> sufficiently that I can represent at least 90% of it in XML. This is not
> just the gui, but all the other elements - the tables required, any input
> parameters, any output parameters, creating any variables to be used while
> entering the form, any business logic to be applied at each point, etc. Each
> form definition is stored as gzip'd XML in a database, and linked to the
> menu system. There is just one python program that responds to the selection
> of a menu option, retrieves the form from the database, unpacks it and runs
> it.

Write your rendering engine as a few simple helper functions, and then
put all the rest in as code instead of XML. The easiest way to go
about it is to write three forms, from scratch, and then look at the
common parts and figure out which bits can go into helper functions.
You'll find that you can craft a powerful system with just a little
bit of code, if you build it right, and it'll mean _less_ library code
than you currently have as XML. If you currently represent 90% of it
in XML, then you could represent 90% of it with simple calls to helper
functions, which is every bit as readable (probably more so), and much
*much* easier to tweak. Does your XML parsing engine let you embed
arbitrary expressions into your code? Can you put a calculated value
somewhere? With Python, everything's code, so there's no difference
between saying "foo(3)" and saying "foo(1+2)".

> Incidentally, I would take issue with the comment that 'JSON is easily
> readable by humans (UNLIKE XML)'. Here is a more complete example of my
> 'choices' definition.
>
> [true, true, [["admin", "System administrator", [], []], ["ind",
> "Individual", [["first_name", true], ["surname", true]], [["first_name", "
> "], ["surname", ""]]], ["comp", "Company", [["comp_name", true], ["reg_no",
> true], ["vat_no", false]], [["comp_name", ""]]]]]
>
> You can read it, but what does it mean?
>
> This is what it would look like if I stored it in XML -
>
> More verbose - sure. Less human-readable - I don't think so.

Well, that's because you elided all the names in the JSON version. Of
course that's not a fair comparison. :) Here's how I'd render that XML
in JSON. I assume that this is stored in a variable, database field,
or whatever, named "choices", and so I skip that first-level name.

{"use_subtypes":true, "use_displaynames":true, "choice":[
{"code":"admin", "descr":"System administrator",
"subtype_columns":[], "displaynames":[]},
{"code":"ind", "descr":"Individual",
"subtype_columns":[
{"col_name":"first_name", "required":true},
{"col_name":"surname", "required":true}
], "displaynames":[
{"col_name":"first_name", "separator":" "},
{"col_name":"surname", "separator":""}
]
},
{"code":"comp", "descr":"Company",
"subtype_columns":[
{"col_name":"comp_name", "required":true},
{"col_name":"reg_no", "required":true},
{"col_name":"vat_no", "required":false}
], "displaynames":[
{"col_name":"comp_name", "separator":""}
]
}
]}

You can mix and match the two styles to get the readability level you
need. I think the "col_name" and "required" tags are probably better
omitted, which would make the JSON block look like this:

{"use_subtypes":true, "use_displaynames":true, "choice":[
{"code":"admin", "descr":"System administrator",
"subtype_columns":[], "displaynames":[]},
{"code":"ind", "descr":"Individual",
"subtype_columns":[
["first_name", "required"],
["surname", "required"]
], "displaynames":[
["first_name", " "]
["surname", ""]
]
},
{"code":"comp", "descr":"Company",
"subtype_columns":[
["comp_name", "required"]
["reg_no", "required"]
["vat_no", "optional"]
], "displaynames":[
["comp_name", ""]
]
}
]}

Note that instead of "true" or "false", I've simply used "required" or
"optional". Easy readability without excessive verbosity. And you
could probably make "required" the default, so you just have
[["comp_name"], ["reg_no"], ["vat_no", "optional"]] for the last
block.

Now, here's the real killer. You can take this JSON block and turn it
into Python code like this:

choices = ... block of JSON ...

And now it's real code. It's that simple. You can't do that with XML.
And once it's code, you can add functionality to it to improve
readability even more.

> Also, intuitively one would think it would take much longer to process the
> XML version compared with the JSON version. I have not done any benchmarks,
> but I use lxml, and I am astonished at the speed. Admittedly a typical
> form-processor spends most of its time waiting for user input. Even so, for
> my purposes, I have never felt the slightest slowdown caused by XML.

On this, I absolutely agree. You will almost never see a performance
difference between any of the above. Don't pick based on performance -
pick based on what makes sense and is readable. The pure-code version
might suffer terribly (interpreted Python with several levels of
helper functions, each one having its overhead - though personally, I
expect it'd be comparable to the others), but you would still do
better with it, because the difference will be on the scale of
microseconds.

I've built GUIs in a number of frameworks, including building
frameworks myself. I've built a system for creating CRUD databases.
(It's still in use, incidentally, though only on our legacy OS/2
systems. One of the costs of writing in REXX rather than Python, but I
didn't know Python back in the early 1990s when I wrote Hudson.)
Frameworks that boast that it doesn't take code to use them tend to
suffer from the Inner-Platform Effect [1] [2] if they get sufficiently
powerful, and it quickly becomes necessary to drop to code somewhere.
(Or, if they DON'T get powerful enough to hit the IPE, they overly
restrain what you can do with them. That's fine if all you want is
simple, but what if 99.9% of what you want fits into the framework and
0.1% simply can't be done?)

With Hudson, I handled the "easy bits" with a single program (basic
table view display with some options, database/table selection, etc,
etc), and then dropped to actual GUI code to handle the custom parts
(the main form for displaying one record; optionally the Search
dialog, though a basic one was provided "for free"), with a library of
handy functions available to call on. Okay, I did a terrible job of
the "library" part back in those days - some of them were copied and
pasted into each file :| - but the concept is there.

In Gypsum (a current project, MUD client for Linux/Windows/Mac OS),
all GUI work is done through GTK. But there are a few parts that get
really clunky, like populating a Table layout, so I made a helper
function that creates a table based on a list of lists: effectively, a
2D array of cell values, where a cell could have a string (becomes a
label), a widget (gets placed there), or nothing (the label/widget to
the left spans this cell too). That doesn't cover _every_ possible
use-case (there's no way to span multiple rows), but if I need
something it can't do, I'm writing code already right there, so I can
just use the Table methods directly. There was actually one extremely
common sub-case where even my GTK2Table function got clunky, so I made
a second level of wrapper that takes a simple list of elements and
creates a 2D array of elements, with labels right-justified. Once
again, if I'm doing the same thing three times, it's a prime candidate
for a helper.

The cool thing about doing everything in code is that you can create
helpers at the scope where they're most needed. To build the character
sheet module for Gypsum (one of its uses is Dungeons and Dragons), I
had to build up a more complex and repetitive GUI than most, so I
ended up making a handful of helpers that existed right there in the
charsheet module. (A couple of them have since been promoted to
global; GTK2Table mentioned above started out in charsheet.) Anyone
reading code anywhere _else_ in the project doesn't need to understand
those functions; but they improve readability in that module
enormously. That's something that's fundamentally impossible in an
interpreted/structured system like an XML GUI - at least, impossible
without some horrible form of inner-platform effect.

Python code is more readable than most data structures you could come
up with, because you don't have to predict everything in advance.

ChrisA

[1] http://en.wikipedia.org/wiki/Inner-platform_effect
[2] http://thedailywtf.com/Articles/The_Inner-Platform_Effect.aspx

Asaf Las

unread,
Jan 24, 2014, 7:04:09 AM1/24/14
to
On Wednesday, January 15, 2014 7:02:08 PM UTC+2, Sergio Tortosa Benedito wrote:
you can also encode widget event handler
function names into same text file and module names where
functions are written so they will be called by string name.
The only thing will be left - creation of those module(s).py
and writing functions there and of course the subject of your
project interpreter/mapper/creator of encoded text to graphical
primitives.
For convenience text encoding can retain properties of
widget library you will choose. or you can/should
also create derived widgets with some predefined look and feel
and properties to make encoding simpler and typing faster.

Frank Millman

unread,
Jan 24, 2014, 7:49:16 AM1/24/14
to pytho...@python.org

"Chris Angelico" <ros...@gmail.com> wrote in message
news:CAPTjJmo+EuY439wB0C8or+ZA...@mail.gmail.com...
> On Fri, Jan 24, 2014 at 8:21 PM, Frank Millman <fr...@chagford.com> wrote:
>> I find that I am using JSON and XML more and more in my project, so I
>> thought I would explain what I am doing to see if others think this is an
>> acceptable approach or if I have taken a wrong turn.
>
> Please don't take this the wrong way, but the uses of JSON and XML
> that you describe are still completely inappropriate. Python does not
> need this sort of thing.
>

Chris, I really am very grateful for your detailed response. There is much
food for thought there and I will have to read it a few times to glean as
much as possible from it.

Here are some initial thoughts.

1. I don't really understand how your system actually works! You mention
Python code and helper functions, but I cannot picture the overall structure
of the program. I don't know if it is possible to provide a siimple example,
but it would certainly help.

2. I am not sure if you have created this to make it easy for *you* to
create forms, or for others. And if the latter, must they be programmers?
One of my goals is to allow non-programmers to modify forms and even create
them from scratch. I did mention that one benefit of my approach is that I
can design a gui that allows this, but I don't get the sense that your's
does.

3. Thanks for the links to the Inner Platform Effect. I had not heard of it,
but I recognise the symptoms, and I realise that I am skirting close to it
in some areas.

4. You are right that some things cannot be totally abstracted, and can only
be handled by code. My approach is as follows. If at least 80% of the
structure can be handled without resorting to code, I think it is
worthwhile, and I think I have more than achieved that. Of the balance, if
at least 80% of requirements are 'standard', I can write the standard
functions in Python, and create an XML tag that will cause the function to
be invoked at run-time. The 'designer' still does not have to worry about
Python. For the remainder, I have created an XML tag called 'pyfunc' that
provides a path to a custom-written function. For this, a Python programmer
will be required. So far I have only made use of this in my 'form designer',
which is quite complex as it has to take the XML definition and 'explode' it
into a number of in-memory tables so that it can be presented in gui form.
However, the average user is not going to get their hands that dirty.

Thanks again

Frank



Frank Millman

unread,
Jan 24, 2014, 8:06:00 AM1/24/14
to pytho...@python.org

"Rustom Mody" <rusto...@gmail.com> wrote in message
news:39e1dd33-2162-40ea...@googlegroups.com...
Thanks for that, Rustom. I had a quick look and I like it. Probably too big
a change for me to consider at the moment, but at least I am now aware of
it.

Frank



Burak Arslan

unread,
Jan 24, 2014, 8:40:07 AM1/24/14
to Frank Millman, pytho...@python.org
On 01/24/14 11:21, Frank Millman wrote:
> I store database metadata in the database itself. I have a table that
> defines each table in the database, and I have a table that defines each
> column. Column definitions include information such as data type, allow
> null, allow amend, maximum length, etc. Some columns require that the value
> is constrained to a subset of allowable values (e.g. 'title' must be one of
> 'Mr', 'Mrs', etc.). I know that this can be handled by a 'check' constraint,
> but I have added some additional features which can't be handled by that. So
> I have a column in my column-definition table called 'choices', which
> contains a JSON'd list of allowable choices. It is actually more complex
> than that, but this will suffice for a simple example.


I wonder whether your use cases can be fully handled by Xml Schema
standard. It's quite robust and easy to use. You are already doing
validation at the app level so I don't think it'd be much of a problem
for you to adopt it.

e.g.

>>> from spyne.model import *
>>> class C(ComplexModel):
... title = Unicode(values=['Mr', 'Mrs', 'Ms'])
...
>>> from lxml import etree
>>> from spyne.util.xml import get_validation_schema
>>> schema = get_validation_schema([C], 'some_ns')
>>> doc1 = etree.fromstring('<C xmlns="some_ns"><title>Mr</title></C>')
>>> print schema.validate(doc1)
True
>>> doc2 = etree.fromstring('<C xmlns="some_ns"><title>xyz</title></C>')
>>> print schema.validate(doc2)
False
>>> print schema.error_log
<string>:1:0:ERROR:SCHEMASV:SCHEMAV_CVC_ENUMERATION_VALID: Element
'{some_ns}title': [facet 'enumeration'] The value 'xyz' is not an
element of the set {'Mr', 'Mrs', 'Ms'}.
<string>:1:0:ERROR:SCHEMASV:SCHEMAV_CVC_DATATYPE_VALID_1_2_1: Element
'{some_ns}title': 'xyz' is not a valid value of the atomic type
'{some_ns}C_titleType'.
>>>


Also, if you need conversion between various serialization formats and
Python object hierarchies, I put together an example for you:
https://gist.github.com/plq/8596519

I hope these help.

Best,
Burak

Chris Angelico

unread,
Jan 24, 2014, 8:55:27 AM1/24/14
to pytho...@python.org
On Fri, Jan 24, 2014 at 11:49 PM, Frank Millman <fr...@chagford.com> wrote:
>
> "Chris Angelico" <ros...@gmail.com> wrote in message
> news:CAPTjJmo+EuY439wB0C8or+ZA...@mail.gmail.com...
>> On Fri, Jan 24, 2014 at 8:21 PM, Frank Millman <fr...@chagford.com> wrote:
>>> I find that I am using JSON and XML more and more in my project, so I
>>> thought I would explain what I am doing to see if others think this is an
>>> acceptable approach or if I have taken a wrong turn.
>>
>> Please don't take this the wrong way, but the uses of JSON and XML
>> that you describe are still completely inappropriate. Python does not
>> need this sort of thing.
>>
>
> Chris, I really am very grateful for your detailed response. There is much
> food for thought there and I will have to read it a few times to glean as
> much as possible from it.

Thanks for taking it the right way :) If I thought you were doing a
terrible job, I'd just archive the thread and move on. The detailed
response means I think you're very close to the mark, but could
improve. :)

> Here are some initial thoughts.
>
> 1. I don't really understand how your system actually works! You mention
> Python code and helper functions, but I cannot picture the overall structure
> of the program. I don't know if it is possible to provide a siimple example,
> but it would certainly help.

Yeah, it was a bit vague. Unfortunately I haven't actually built any
complex UI in Python, ever, so I'll have to use C, C++, REXX, or Pike,
for the example. In C, it would be using the OS/2 APIs, not very
useful to anyone else. In C++, either Borland's ancient "Object
Windows Library", or the Win32 APIs - either way, not particularly
helpful. REXX you probably don't even know as a language, and you're
unlikely to know any of the GUI libraries I've used - GpfRexx, VREXX,
VX-REXX, VisPro REXX, DrRexx, or a handful of others. So the best bet
is Pike, where I've used GTK, which is also available for Python - but
there are distinct differences. (Oh, I've also used DBExpert, which is
a superb example of how frustrating it can be to try to create a
complex GUI in a "look how easy, it's just drag and drop, no code
needed" system. But that's more arcane stuff from the 1990s that you
most likely don't know, and definitely don't need to know.)

So, here's some code from Gypsum. Firstly, here's a simple window
layout (not strictly what I had in Gypsum):

mainwindow = GTK2.Window(0)->add(GTK2.Vbox(0,0)
->add(GTK2.Label("About Gypsum: big long multi-line string"))
->add(GTK2.HbuttonBox()
->add(GTK2.Button("Close"))
->add(GTK2.Button("Foobar"))
)
);

The window has a simple structure. It contains a vertical box, which
contains a label and a horizontal button box; the latter contains two
buttons. (The real about dialog has only one button, making it a poor
example. I've no idea what clicking Foobar on an about dialog should
do.)

There's a nested structure to it, and it's all code. (It's actually
all one single expression. The add() methods return the parent object,
so they chain nicely.) This gives maximum flexibility, but it gets
repetitive at times, especially when I do up the character sheet.
Here's a screenshot of just the first page:

http://rosuav.com/charsheet.png

(That's how it appears on Windows, since I'm currently testing it for
support there. It also has to work - and look right - on Linux and Mac
OS.)

It's particularly complicated when laying out a table, because the
table is so powerful and flexible.

GTK2.Table(6,2,0)

->attach(GTK2.Label((["label":"Keyword","xalign":1.0])),0,1,0,1,GTK2.Fill,GTK2.Fill,5,0)
->attach_defaults(win->kwd=GTK2.Entry(),1,2,0,1)

->attach(GTK2.Label((["label":"Name","xalign":1.0])),0,1,1,2,GTK2.Fill,GTK2.Fill,5,0)
->attach_defaults(win->name=GTK2.Entry(),1,2,1,2)
->attach(GTK2.Label((["label":"Host
name","xalign":1.0])),0,1,2,3,GTK2.Fill,GTK2.Fill,5,0)
->attach_defaults(win->hostname=GTK2.Entry(),1,2,2,3)

->attach(GTK2.Label((["label":"Port","xalign":1.0])),0,1,3,4,GTK2.Fill,GTK2.Fill,5,0)
->attach_defaults(win->port=GTK2.Entry(),1,2,3,4)

->attach(GTK2.Label((["label":"Auto-log","xalign":1.0])),0,1,4,5,GTK2.Fill,GTK2.Fill,5,0)
->attach_defaults(win->logfile=GTK2.Entry(),1,2,4,5)
->attach(win->use_ka=GTK2.CheckButton("Use
keep-alive"),1,2,5,6,GTK2.Fill,GTK2.Fill,5,0) //No separate label

Horribly repetitive, and requires care to ensure that the
left/right/top/bottom boundaries are correct in all cases. Technically
it's possible for widgets to span rows or columns, and even to
overlap, but that's extremely rare compared to the common case of just
"lay these things out in a grid". (Though spanning columns was easy
enough to implement, so I did it.)

Here's the version with the first helper function:

GTK2Table(({
({"Keyword",win->kwd=GTK2.Entry()}),
({"Name",win->name=GTK2.Entry()}),
({"Host name",win->hostname=GTK2.Entry()}),
({"Port",win->port=GTK2.Entry()}),
({"Auto-log",win->logfile=GTK2.Entry()}),
({"",win->use_ka=GTK2.CheckButton("Use keep-alive")}),
}),(["xalign":1.0]))

I have to create a blank label in there to keep the positioning right
(the previous version simply didn't attach anything in that slot), but
that's a small price to pay. The readability has gone up hugely. And
yet, there's still a little more that can be done, as I realized when
I found myself duplicating the above structure a few times.

two_column(({
"Keyword",win->kwd=GTK2.Entry(),
"Name",win->name=GTK2.Entry(),
"Host name",win->hostname=GTK2.Entry(),
"Port",win->port=GTK2.Entry(),
"Auto-log",win->logfile=GTK2.Entry(),
"",win->use_ka=GTK2.CheckButton("Use keep-alive"),
}))

This is something that I could give to a non-programmer and expect him
to be able to edit, as it's about as clear as the equivalent JSON or
XML would be; there could be a few more tweaks done, perhaps, but it's
pretty readable like that. A non-programmer could, for instance, put
the "Auto-log" line above the "Host name", simply by reordering the
lines of code; it would do exactly what he expects. There's as much
fragility/rigidity in this as there is in any other structured system
(eg if you leave out a comma, this won't work - same with JSON or
XML).

In the specific case of the character sheet, I frequently create entry
fields (GTK2.Entry()) that are bound to specific data attributes. So
in any context where it's legal to write GTK2.Entry(), you can instead
write ef("some_name") and it'll make a properly bound entry field. And
if it's a numeric field, num("some_name") will shrink the default size
and center the text in it as well, which is what people expect of the
numeric fields. Shorthand for the common cases. And then there are
complex cases like the weapon stats block - it needs its keyword,
name, damage roll, enchantment bonus, etc, etc, all laid out nicely;
and there might be three of those weapon blocks. So that's broken out
into a function.

The thing is, if your XML window structure has enough power... well,
that's more part of the next two points:

> 2. I am not sure if you have created this to make it easy for *you* to
> create forms, or for others. And if the latter, must they be programmers?
> One of my goals is to allow non-programmers to modify forms and even create
> them from scratch. I did mention that one benefit of my approach is that I
> can design a gui that allows this, but I don't get the sense that your's
> does.
>
> 3. Thanks for the links to the Inner Platform Effect. I had not heard of it,
> but I recognise the symptoms, and I realise that I am skirting close to it
> in some areas.

If your XML window structure has enough power, it'll be nearly
impossible for a non-programmer to make anything but the most trivial
changes to it. (Changing a literal string is usually easy enough. Any
decent system will make _that_ possible, at least.) If a
non-programmer can truly create a form from scratch, that's a sign
that the forms are extremely simple and, if you'll excuse the pun,
formulaic; and if that's the case, it should be possible to make a
really easy-to-use helper function like my two_column() above.
Challenge: Without knowing anything about Pike, or the connect dialog,
add another check box called "Passive mode" called win->passive and
positioned just after the hostname and port. Like the other check box,
it doesn't need a separate label. Can you do it? Could someone who
knows enough to edit XML do it? I suspect probably they could. There's
some boilerplate to copy and paste (same in XML or code), there's some
readable text strings (names, labels, types), and there's punctuation
that makes decent sense.

> 4. You are right that some things cannot be totally abstracted, and can only
> be handled by code. My approach is as follows. If at least 80% of the
> structure can be handled without resorting to code, I think it is
> worthwhile, and I think I have more than achieved that. Of the balance, if
> at least 80% of requirements are 'standard', I can write the standard
> functions in Python, and create an XML tag that will cause the function to
> be invoked at run-time. The 'designer' still does not have to worry about
> Python.

That's nice in theory, but it means you have to plan everything out.
That also means you have to predict your names etc, and then deprecate
old names if you ever find that you made a mistake. When you start
with code, you have the flexibility of looking at actual existing
forms and deciding what should be broken out for simplicity.

> For the remainder, I have created an XML tag called 'pyfunc' that
> provides a path to a custom-written function. For this, a Python programmer
> will be required. So far I have only made use of this in my 'form designer',
> which is quite complex as it has to take the XML definition and 'explode' it
> into a number of in-memory tables so that it can be presented in gui form.
> However, the average user is not going to get their hands that dirty.

That's what I meant when I said a "drop to code" system. Depending on
how smooth the boundary is, that could be either horribly clunky or
reasonably clean; the clean one usually requires a lot of work. On the
flip side, if your GUI creation is *all* code, there's no boundary at
all, and no work.

My system starts by writing an absolute minimum of code and forcing
the form designer to do more work, and then progressively adds code
*that is actually useful* and makes the form design work easier.
Trying to do it all in XML means you have to first predict what will
be needed, and that inevitably means writing a whole lot of code that
isn't, as it turns out, useful. That's an up-front cost before you can
do anything, plus you can't get rid of any of it later without first
making sure no forms are using those tags. Ultimately, a full-featured
GUI is going to require that its form designer understand the
underlying system anyway (in my case that's GTK), because nothing will
change that; and if your forms designers have to understand how GTK
works, they probably have to understand how to write GTK-using code.
At very least, the basics of code (names, structure, etc) will be
critical, and that's true of any GUI builder. DBExpert required that
you think about all that sort of thing, and that's as close as I've
ever seen to a pure "no code needed, build a UI to view a database
table" system. So... instead of fighting that, embrace it! Let it
truly be code.

The structure (your XML interpreter) is code that has a maintenance
cost. The less of that you have, the less it takes to make changes.
And as a rule of thumb, less code means less bugs; and less
development prior to usage means less bugs, too. Let real-world usage
guide your code, and you'll spend less time building stuff you don't
need.

ChrisA

Matěj Cepl

unread,
Jan 24, 2014, 11:28:41 AM1/24/14
to pytho...@python.org
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 2014-01-24, 11:18 GMT, you wrote:
> Write your rendering engine as a few simple helper functions,
> and then put all the rest in as code instead of XML. The
> easiest way to go about it is to write three forms, from
> scratch, and then look at the common parts and figure out
> which bits can go into helper functions.

Perhaps what's missing is full acknowledgment that Python has
dual-inheritance and thus it can have mixin classes (which seems
to me to be the only useful use of dual inheritance). You know
you can have mixins in Python, right?

Also, I wrote my share of XML parsing/writing code, but more and
more I am persuaded that if the answer is “XML” then there is
some wrong with the question. Python is a way more expressive
language than XML, so it is almost always more useful to write
in Python, than to pass any problems to XML.

Matěj

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)

iD8DBQFS4pS54J/vJdlkhKwRApdcAJ48PRgDz6ccnq1YFD9zx8EDDH3JjgCghU2x
3CV+D0LvquzgYRux2GslZ0E=
=Y3/F
-----END PGP SIGNATURE-----

Chris Angelico

unread,
Jan 24, 2014, 11:33:27 AM1/24/14
to pytho...@python.org
On Sat, Jan 25, 2014 at 3:28 AM, Matěj Cepl <mc...@redhat.com> wrote:
> On 2014-01-24, 11:18 GMT, you wrote:
>> Write your rendering engine as a few simple helper functions,
>> and then put all the rest in as code instead of XML. The
>> easiest way to go about it is to write three forms, from
>> scratch, and then look at the common parts and figure out
>> which bits can go into helper functions.
>
> Perhaps what's missing is full acknowledgment that Python has
> dual-inheritance and thus it can have mixin classes (which seems
> to me to be the only useful use of dual inheritance). You know
> you can have mixins in Python, right?

Hmm, I've never really felt the need to work that way. Usually it's
functions I want, not classes; but if they're classes, then generally
they're just to add a couple of methods, or change the construction
args, so single inheritance is plenty. (I created a
MultiLineEntryField class as a thin wrapper around TextView, adding
get_text() and set_text() with the same signatures as GTK2.Entry()'s
methods of the same names. That wouldn't apply to anything else, so a
mixin wouldn't help much.) But sure. If you want mixins, go for it.

ChrisA

sert...@gmail.com

unread,
Jan 24, 2014, 1:51:42 PM1/24/14
to
Hi again , I'm sorry I dind't reply earlier I still hav enot added myself to the list (I'm doing this trhough google groups).

Thanks Asaf, but I don't like having the code and the GUI separated.

First,I'm not aiming to not programmers (or people qho don't want to be one) because they may be able to write the layout but not the actual program's function so there's no reason to do that.

Second, I wouldn't like to have code and GUI separated since it's a hassle when try to change something like the name.

XML and JSON are pretty cool but they serve for loading info which can vary to a fixed engine not for when that info does not change, and that's even more true when you are speaking about an interpreted language.

I've been reasearching a bit myself and this is what I got: a way of having a nice syntax in python itself (no external files, no new language...) with metaclasses, so the same example which was used in Lua (and I think in original's python syntax) would look like this with metaclasses and classes:

class myWindow(Window):
title="Hello World"
class myButton(Button):
label="Hello World"

It's just like what I was looking for, with the added benefit that functions can be defined right there. It has it's own problems (like having to access variables from the global scope), but I think they are either solvable or minor.

Sergio

Frank Millman

unread,
Jan 25, 2014, 2:18:44 AM1/25/14
to pytho...@python.org

"Chris Angelico" <ros...@gmail.com> wrote in message
news:CAPTjJmpi-kvJAVs2gK+nH5n6q3REkJaKR=CZeRfzUg...@mail.gmail.com...
> On Fri, Jan 24, 2014 at 11:49 PM, Frank Millman <fr...@chagford.com>
> wrote:
>>
>

[...]

I have realised that we unlikely to come to an agreement on this in the near
future, as our philosophies are completely different.

You have stated that your objective is to express as much as possible in
Python code.

I have stated that my objective is to express as little as possible in
Python code.

We would have to resolve that difference of opinion first, before discussing
our respective approaches in detail, and that is way beyond the scope of
this thread.

As a brief example of my approach, here is how I would write your simple
'About' box.

Here is your version -

mainwindow = GTK2.Window(0)->add(GTK2.Vbox(0,0)
->add(GTK2.Label("About Gypsum: big long multi-line string"))
->add(GTK2.HbuttonBox()
->add(GTK2.Button("Close"))
->add(GTK2.Button("Foobar"))
)
);

Here is my version -

<form name="ChrisAbout_form">
<data_objects/>
<input_params/>
<output_params/>
<rules/>
<frame>
<body>
<block/> <!-- an html div -->
<panel/> <!-- an html table -->
<row/>
<col/>
<text value="This is line one of a multi-line string"/>
<row/>
<col/>
<text value="This is line two of a multi-line string"/>
<row/>
<col/>
<text value="This is line three of a multi-line string"/>
</body>
<button_row> <!-- an html div -->
<button btn_id="btn_close" btn_label="Close" len="60"
btn_enabled="true" btn_validate="false" btn_default="true">
<end_form state="completed"/>
</button>
<button btn_id="btn_foo" btn_label="Foobar" len="60"
btn_enabled="true" btn_validate="false" btn_default="false">
<pyfunc name="path1.path2.foobar"/>
</button>
</button_row>
<frame_methods>
<method name="on_req_close"> <!-- user clicked [X] or pressed
Shift_F4 -->
<end_form state="completed"/>
</method>
<method name="on_req_cancel"> <!-- user pressed Escape -->
<end_form state="completed"/>
</method>
</frame_methods>
</frame>
</form>

Currently I do not have a widget for a multi-line label, so I just show
three separate lines. If I ever needed one, it would not take long to
create.

I took two screenshots, but I don't know the best way to upload and share
them. I found a site called tinypic, which works, but the screen is
cluttered with a lot of other stuff. Still, it shows what I want.

First, here is the screen as rendered in Internet Explorer (it works in
other browsers as well - even on my smart phone, though I have not done any
optimising for mobile devices yet) -

http://tinypic.com/r/ip15xx/5



Second, here is the screen designer, showing a portion of the screen
definition - one of the buttons. As you can see, the designer does not have
to worry about XML at all -


http://tinypic.com/r/1j7sdh/5



I am not claiming that I am 'right', or that this is a perfect solution. It
is just 'where I am' right now, after quite a long period of evolution, and
it is achieving a large portion of what I am aiming for, so I will press on
with my current approach for now.



Hopefully it will not take *too* long before I am in a position to release
something, and then I will be very interested in any feedback.



Thanks for the interesting discussion.



Frank





Chris Angelico

unread,
Jan 25, 2014, 2:33:57 AM1/25/14
to pytho...@python.org
On Sat, Jan 25, 2014 at 6:18 PM, Frank Millman <fr...@chagford.com> wrote:
> I have realised that we unlikely to come to an agreement on this in the near
> future, as our philosophies are completely different.
>
> You have stated that your objective is to express as much as possible in
> Python code.
>
> I have stated that my objective is to express as little as possible in
> Python code.

Ah but the question is *why* you want to minimize code. I write
everything in code because it minimizes unnecessary coding - yes,
that's right, I maximize code to minimize code :) - because all that
code that isn't written also isn't debugged, isn't maintained, and
isn't placing unnecessary restrictions on anything. What's the
advantage of doing it in XML?

Your GUI builder is all very well, but it could as easily write Python
code as XML, so it doesn't give a strong incentive for XML. And
personally, I think it's more likely to be a waste of effort, too, but
that's more because a good GUI builder takes a *ton* of effort to
build. That's time that has to be spent up-front, before you have
experience with the system, before you _can get_ experience with the
system - and, see above, it's code that has to be debugged and
maintained.

Every framework has to justify itself. Just "it lets people not write
code" isn't enough unless not-writing-code can justify the costs.

ChrisA

Matěj Cepl

unread,
Jan 25, 2014, 6:23:58 AM1/25/14
to pytho...@python.org
[This message has also been posted to gmane.comp.python.general.]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 2014-01-25, 07:18 GMT, Frank Millman wrote:
> I have stated that my objective is to express as little as
> possible in Python code.

Yes, and I believe that it is very wrong. But anyway, if you are
so passionate about GUI-via-XML, what’s wrong with Glade
(http://www.pygtk.org/pygtk2reference/class-gladexml.html)? You
have editors for that XML etc.

Matěj

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)

iD8DBQFS457O4J/vJdlkhKwRAlA7AJ9nTl4v+FoiNZb3NLaSsIZMd2HO5wCeNYwe
EVLDNqlw3YaQtloF1RGWP8Y=
=AloI
-----END PGP SIGNATURE-----

Steven D'Aprano

unread,
Jan 25, 2014, 9:33:32 PM1/25/14
to
On Sat, 25 Jan 2014 09:18:44 +0200, Frank Millman wrote:

> I have realised that we unlikely to come to an agreement on this in the
> near future, as our philosophies are completely different.
>
> You [Chris Angelo] have stated that your objective is to express as
> much as possible in Python code.
>
> I have stated that my objective is to express as little as possible in
> Python code.

Interesting perspective.


> We would have to resolve that difference of opinion first, before
> discussing our respective approaches in detail, and that is way beyond
> the scope of this thread.
>
> As a brief example of my approach, here is how I would write your simple
> 'About' box.
>
> Here is your version -
>
> mainwindow = GTK2.Window(0)->add(GTK2.Vbox(0,0)
> ->add(GTK2.Label("About Gypsum: big long multi-line string"))
> ->add(GTK2.HbuttonBox()
> ->add(GTK2.Button("Close"))
> ->add(GTK2.Button("Foobar"))
> )
> );

That's not Python code, but it's reasonably concise and readable. (By the
way, what language is it?) The meaning is fairly obvious, and it's all
pretty simple. I'd like to see a more human readable GUI designer
language:

# hypothetical code in a DSL for creating GUI elements
create new window mainwindow
with mainwindow
add vbox at 0,0
add label "About Gypsum: big long multi-line string"
add hbuttonbox
add button "Close"
add button "Foobar"

but what you've got there is okay. Seven lines of readable code.
Thirty. Seven. Lines. Of. XML.

You've got to be kidding me. How can you *possibly* prefer that?

First rule of XML: it is not human-writable. It's barely human-readable.
It's a *document* interchange language which happens to use mostly human-
readable elements, which is not the same thing at all. It's designed to
be machine written. Using XML for *data* is abusive to both the XML
design goals and to the poor schmuck who has to read your config file.
Using XML *as a programming language* is not just abuse, it's getting
into grievous bodily harm territory.

Here's a simple programming expression, familiar to most people, common
to hundreds of programming languages:

3+4*5

Here it is written as XML:

<add><int>3</int><mult><int>4</int><int>5</int></mult></add>


Source:
http://www.ibm.com/developerworks/xml/library/x-sbxml/index.html

More here:

http://www.codinghorror.com/blog/2008/05/xml-the-angle-bracket-tax.html
http://myarch.com/why-xml-is-bad-for-humans/


If you expect a human being to routinely *read*, let alone *write*, XML
in preference to some real programming language, that is a horrible,
horrible thing. Using XML as an internal, machine-generated, format not
intended for humans is not too bad. Anything else is abusive.



--
Steven

Mark Lawrence

unread,
Jan 25, 2014, 9:45:59 PM1/25/14
to pytho...@python.org
On 26/01/2014 02:33, Steven D'Aprano wrote:
> Here's a simple programming expression, familiar to most people, common
> to hundreds of programming languages:
>
> 3+4*5
>
> Here it is written as XML:
>
> <add><int>3</int><mult><int>4</int><int>5</int></mult></add>
>
> Source:
> http://www.ibm.com/developerworks/xml/library/x-sbxml/index.html
>
> More here:
>
> http://www.codinghorror.com/blog/2008/05/xml-the-angle-bracket-tax.html
> http://myarch.com/why-xml-is-bad-for-humans/
>
> If you expect a human being to routinely *read*, let alone *write*, XML
> in preference to some real programming language, that is a horrible,
> horrible thing. Using XML as an internal, machine-generated, format not
> intended for humans is not too bad. Anything else is abusive.
>

If I worked as a consultant I'd much prefer the XML version as I'd be
able to charge much more on the grounds that I'd done much more, hoping
that the people paying didn't bother with design reviews or the like :)

--
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

Chris Angelico

unread,
Jan 25, 2014, 10:38:42 PM1/25/14
to pytho...@python.org
On Sun, Jan 26, 2014 at 1:33 PM, Steven D'Aprano
<steve+comp....@pearwood.info> wrote:
>> Here is your version -
>>
>> mainwindow = GTK2.Window(0)->add(GTK2.Vbox(0,0)
>> ->add(GTK2.Label("About Gypsum: big long multi-line string"))
>> ->add(GTK2.HbuttonBox()
>> ->add(GTK2.Button("Close"))
>> ->add(GTK2.Button("Foobar"))
>> )
>> );
>
> That's not Python code, but it's reasonably concise and readable. (By the
> way, what language is it?) The meaning is fairly obvious, and it's all
> pretty simple.

It's Pike, and the above example is pure Pike without any of my own
helpers. If you fire up Pike's interactive mode and type two commands
"GTK2.setup_gtk();" and "start backend" first, you can paste that in
and it'll create you a window. (It won't DO anything, but it'll sit
there looking like a window.) It tends to get a little verbose after a
while (hence the need for helper functions to combat the complexity),
but the advantage of this system is that it took me absolutely zero
code. I didn't have to write any framework.

> I'd like to see a more human readable GUI designer
> language:
>
> # hypothetical code in a DSL for creating GUI elements
> create new window mainwindow
> with mainwindow
> add vbox at 0,0
> add label "About Gypsum: big long multi-line string"
> add hbuttonbox
> add button "Close"
> add button "Foobar"
>
> but what you've got there is okay. Seven lines of readable code.

Sure. That would make reasonable sense, as a DSL. And, in fact, if I
were making a Python GUI, I would want to add something that would let
me do it that way - at least compared to PyGTK, which insists on every
box getting a temporary name, since the add() methods don't chain. But
that's a cost, that has to be written. I'm happy with the no-code
version to start with. Now, with something as complicated as the
character sheet, well, that's different. I think if I did all the
charsheet code as pure no-helpers Pike, it would be a dozen pages of
code and indented about fifty tabs. At that point, it's worth putting
some effort into taming the beast :) Here's an actual example from the
charsheet:

GTK2.Hbox(0,10)->add(GTK2Table(({
({"Name",ef("name",12),0,0,"Char level",num("level",8)}),
({"Race",ef("race",8),"HD",ef("race_hd"),"Experience",num("xp",8)}),
({"Class",ef("class1",12),"Level",num("level1"),"To next
lvl",calc("`+(@enumerate(level,1000,1000))-xp")}),
({"Class",ef("class2",12),"Level",num("level2"),"Size",select("size",sizes)}),
({"Class",ef("class3",12),"Level",num("level3"),
"Grapple",calc(grapple_formula,"grapple","string")
}),
({"Class",ef("class4",12),"Level",num("level4")}),
}))->set_col_spacings(4))
->add(GTK2.Frame("Wealth")->add(GTK2Table(({
({"Platinum",num("wealth_plat",7)}),
({"Gold",num("wealth_gold",7)}),
({"Silver",num("wealth_silver",7)}),
({"Copper",num("wealth_copper",7)}),
({"Total gp",calc("(wealth_plat*1000+wealth_gold*100+wealth_silver*10+wealth_copper)/100")}),
}))))


It's a mix of basic Pike and GTK functions (GTK2.Frame is one of the
standard widgets) and helpers (num, ef, and calc) that return widgets,
maybe with child widgets. GTK2Table takes an array and plops
everything into it at appropriate locations. I use that function
*everywhere* in the charsheet - mainly because I was porting from a
spreadsheet, but D&D character sheets are inherently tabular.

(Note that I've reformatted this a bit from the original, and it might
be disrupted a bit by the email/newsgroup format. In the original,
this is all a few tabs in, but as long as your editor isn't wrapping
the lines, it's pretty readable.)

At what point is it a DSL rather than just "Pike code with helper
functions"? This is particularly true with Python code; it wouldn't be
hard to make a DSL that's derived from Python.

(By the way, your translation "add a vbox at 0,0" isn't accurate; the
0,0 are parameters to the Vbox itself, being the homogenous flag (if
it's nonzero, it forces its children to the same height and/or width,
but 0 means each child gets what it asks for) and the padding (0 puts
children hard up against one another, nonzero puts that much room
between them). A window has only a single child, which occupies its
entire space; that's why it's conventional to add a layout manager as
the one child, and then add multiple children to that. Means the
window needn't care about the minutiae of child positioning. But if
you call that "add a vbox 0,0", that'd work fine; and if you're making
a DSL, I'd make 0,0 the defaults and say "add a vbox padding 10" if I
want to override.)

The only problem with your DSL as I see it is that it doesn't mark the
beginning and end of child widget layouts. This needs to be a tree.
But Python already has a notation for that: indent! So if the two
buttons are indented, they'll be inside the hbuttonbox (which is a
type of horizontal box), which is within the vertical box (again,
indent everything that's inside it), which is within the main window.

Of course, then you need to work out how to attach code to buttons,
but let's leave that aside... mainly because it's a nightmare to do in
XML, but pretty easy (if a little tedious in large quantities) in
code. :)

ChrisA

Chris Angelico

unread,
Jan 25, 2014, 11:06:15 PM1/25/14
to pytho...@python.org
On Sun, Jan 26, 2014 at 1:45 PM, Mark Lawrence <bream...@yahoo.co.uk> wrote:
> If I worked as a consultant I'd much prefer the XML version as I'd be able
> to charge much more on the grounds that I'd done much more, hoping that the
> people paying didn't bother with design reviews or the like :)

And that's very true. If someone wants something infinitely
customizeable, the best solution might be an empty file with a shebang
at the top - but that's hardly something you can charge oodles for.
This is where soft-coding comes from.

http://thedailywtf.com/Articles/Soft_Coding.aspx

The business logic examples given there are best served by hard code.
Suppose you need to calculate this-value plus that-value times
other-value; is there any difference between writing that in Python
(ugh, that's hard code!) and putting the formula in a config file,
where it'll get parsed and evaluated (oh, that's a config file, that's
fine)? As you'll see in my other post, there's a formula evaluator
routine there; it takes a string of code and compiles it:

(wealth_plat*1000+wealth_gold*100+wealth_silver*10+wealth_copper)/100

It's straight code, and it's embedded. If ever the rules change, I can
edit the code. For instance, here's the D&D Fourth Edition version of
that:

(wealth_plat*10000+wealth_gold*100+wealth_silver*10+wealth_copper)/100

Should the value of a platinum coin be moved out into a config file?
Maybe. MAYBE. Should the value of a silver piece be? Definitely not!
There's no use-case for silver pieces being worth anything other than
ten copper. If and when there is one, the code can simply be edited.
There is no value in soft-coding this formula.

Code isn't something to be afraid of. It's just text files like any
other. After all, Python code is a config file for /usr/bin/python, so
if you want to change what Python does, just edit its config file!

ChrisA

Rustom Mody

unread,
Jan 25, 2014, 11:47:27 PM1/25/14
to
On Sunday, January 26, 2014 9:36:15 AM UTC+5:30, Chris Angelico wrote:
> Code isn't something to be afraid of. It's just text files like any
> other. After all, Python code is a config file for /usr/bin/python, so
> if you want to change what Python does, just edit its config file!

Windows stores configuration in the registry -- by fiat
Linux (posix) stores configuration in /etc + ~/.files -- by convention

Which do you think is preferable?

Chris Angelico

unread,
Jan 26, 2014, 12:23:32 AM1/26/14
to pytho...@python.org
Not exclusively, in either case. Many many things are config files of
various sorts. The terms of the GPL specifically state that a GPL'd
language does not enforce that code written in it is GPL'd, because
it's just (to the GPL code) data files.

Plenty of Windows programs store config files outside the registry.

ChrisA

Frank Millman

unread,
Jan 26, 2014, 1:03:18 AM1/26/14
to pytho...@python.org

"Steven D'Aprano" <steve+comp....@pearwood.info> wrote in message
news:52e473fc$0$29999$c3e8da3$5496...@news.astraweb.com...
> On Sat, 25 Jan 2014 09:18:44 +0200, Frank Millman wrote:
>
>> I have realised that we unlikely to come to an agreement on this in the
>> near future, as our philosophies are completely different.
>>
>> You [Chris Angelo] have stated that your objective is to express as
>> much as possible in Python code.
>>
>> I have stated that my objective is to express as little as possible in
>> Python code.
>
> Interesting perspective.
>

[...]

I did not really want to continue this, but I have to respond to that.

There is a sub-context within which I made my statement.

Here is a quote from one of my earlier posts -

> Each form definition is stored as gzip'd XML in a database, and linked to
> the
> menu system. There is just one python program that responds to the
> selection
> of a menu option, retrieves the form from the database, unpacks it and
> runs it.

I do not expect anyone to read or edit the XML - it is just a storage
format. I am sure it could be done in JSON or YAML as well.

One objective is to make it easy for non-programmers to modify forms and
create new ones. I showed a screenshot earlier that illustrated a 'button'
definition.

Frank



Rustom Mody

unread,
Jan 26, 2014, 3:05:02 AM1/26/14
to
On Sunday, January 26, 2014 10:53:32 AM UTC+5:30, Chris Angelico wrote:
> On Sun, Jan 26, 2014 at 3:47 PM, Rustom Mody wrote:
> > On Sunday, January 26, 2014 9:36:15 AM UTC+5:30, Chris Angelico wrote:
> >> Code isn't something to be afraid of. It's just text files like any
> >> other. After all, Python code is a config file for /usr/bin/python, so
> >> if you want to change what Python does, just edit its config file!
> > Windows stores configuration in the registry -- by fiat
> > Linux (posix) stores configuration in /etc + ~/.files -- by convention
> > Which do you think is preferable?

> Not exclusively, in either case. Many many things are config files of
> various sorts. The terms of the GPL specifically state that a GPL'd
> language does not enforce that code written in it is GPL'd, because
> it's just (to the GPL code) data files.

Ok so you are being careful and hedging your bets!!
[And Ive no idea what the gpl has to do with this]

If you see the 'Principle of Least Power here:
http://www.w3.org/DesignIssues/Principles.html
there is a spectrum of power from narrow data format to universal data
format to Turing complete programming language. And a strong case is
made for minimizing the 'power' in any application.

By decreeing things about the registry, windows solves many problems
that create unnecessary headaches for developers, packagers, uses with
the laissez-faire approach of 'put whatever you like in /etc.' This
follows from the principle: "Anything goes" applied to /etc means messes
go in. Its harder to push messes into a dictat-ed registry

Steven's link
http://www.codinghorror.com/blog/2008/05/xml-the-angle-bracket-tax.html
linked to
http://nothing-more.blogspot.in/2004/10/where-xml-goes-astray.html
explains what the real problem is:

Xml, originally a document format, is nowadays used as a data-format.
This conduces to humongous messing, first for the xml-library writers, and
thence to the users of those libraries because library messes inevitably
leak past abstraction barriers to cause user-programmer headaches.

tl;dr
Frank's principle: "Express little as possible in <programming language>"
is correct.
"And therefore XML is the solution"
is bad logic
[Unless <programming language> == "java" !]

Frank Millman

unread,
Jan 26, 2014, 4:12:57 AM1/26/14
to pytho...@python.org

"Rustom Mody" <rusto...@gmail.com> wrote in message
news:3683cd10-592b-4a3d...@googlegroups.com...
>
> Xml, originally a document format, is nowadays used as a data-format.
> This conduces to humongous messing, first for the xml-library writers, and
> thence to the users of those libraries because library messes inevitably
> leak past abstraction barriers to cause user-programmer headaches.
>
> tl;dr
> Frank's principle: "Express little as possible in <programming language>"
> is correct.
> "And therefore XML is the solution"
> is bad logic
> [Unless <programming language> == "java" !]

If that is the case, what is 'good logic'? JSON or YAML?

It does not make much difference which format I use. However, I will say
that I found it a useful discipline to create an xml schema to describe my
form definition, for two reasons.

Firstly, I was hand-crafting my form definitions initially, and as I added
features it became unwieldy. Forcing myself to create the schema highlighted
a lot of anomalies and I ended up with a much cleaner structure as a result.

Secondly, it has picked up a lot of errors in the resulting documents which
would otherwise have generated hard-to-find runtime exceptions.

Frank



Steven D'Aprano

unread,
Jan 26, 2014, 7:05:29 AM1/26/14
to
On Sun, 26 Jan 2014 15:06:15 +1100, Chris Angelico wrote:

> Code isn't something to be afraid of.

Not according to the Laundry series by Charles Stross. The protagonist of
the series was "recruited" to the Laundry after the computer program he
was working on almost summoned Nyarlathotep the Crawling Chaos Elder God
to Wolverhampton.


--
Steven

Steven D'Aprano

unread,
Jan 26, 2014, 7:21:18 AM1/26/14
to
On Sun, 26 Jan 2014 08:03:18 +0200, Frank Millman wrote:

> I do not expect anyone to read or edit the XML - it is just a storage
> format. I am sure it could be done in JSON or YAML as well.

But that's not what you originally said. You stated:

"here is how I would write your simple 'About' box"

and compared your XML to actual code written by Chris.

As I said in my previous post, if the XML is intended as a purely
internal document, written by and read by your application, it's not so
bad. (But then XML is intended for document *exchange*, i.e. from one
application to another. If your XML is just used *internally*, with no
interchange needed, why not use a more efficient internal format?

XML's strength is that it is a well-known standard that allows
application A to interchange documents with application B. But it's
weaknesses include, it is neither efficient like a custom-designed binary
format, not human-editable.

It seems to me that if I were in your position, I would have the GUI
designer generate source code in some language directly, rather than XML.
Ah, wait! An idea strikes... if your GUI designer generates XML, you
could then have a plug-in system to convert the XML to source code in
whatever languages the plug-in supports. So that's a possible good use
for XML as an intermediate language.


> One objective is to make it easy for non-programmers to modify forms and
> create new ones. I showed a screenshot earlier that illustrated a
> 'button' definition.

The idea of drag-and-drop GUI designers is hardly new. I was using one
back in 1986 or '88, Apple's Hypercard. Now that was a user-friendly
programming language/environment/toolkit.


--
Steven

Rustom Mody

unread,
Jan 26, 2014, 9:36:25 AM1/26/14
to
On Sunday, January 26, 2014 2:42:57 PM UTC+5:30, Frank Millman wrote:
There are json/yaml 'schema'* validators if you want eg
https://github.com/alecthomas/voluptuous
http://rx.codesimply.com/

* if you want to call them that!

Asaf Las

unread,
Feb 2, 2014, 9:17:55 PM2/2/14
to
On Sunday, January 26, 2014 4:45:59 AM UTC+2, Mark Lawrence wrote:
> On 26/01/2014 02:33, Steven D'Aprano wrote:
>
> If I worked as a consultant I'd much prefer the XML version as I'd be
> able to charge much more on the grounds that I'd done much more, hoping
> that the people paying didn't bother with design reviews or the like :)
>
> My fellow Pythonistas, ask not what our language can do for you, ask
> what you can do for our language.
> Mark Lawrence

Google's android uses XML for GUI widget definitions.
/Asaf
0 new messages