Python Source Code Beautifier

  • Thread starter Franz Steinhaeusler
  • Start date
F

Franz Steinhaeusler

Hello, I did not find any reasonable pyhton source code beautifier
program (preferable gui).

Some would ask why? Program it immediatly good.

(BTW: Would be a nice project, if I would have more spare time).

Ich have some foreign source, which are programed in a way
I don't like, so I would like to have a tool, which automatically
processes following options:


Use Spaces, size: 4
convert structs like: if (a > b): to if a > b:
fill in spaces, but not in functions between operators:

a+=1 => a += 1
p(t + 1) => p(t+1)

convert:

self.scriptcount = self.scriptcount + 1 => self.scriptcount += 1

from "is" to "==" and "is not" to "!=" (ok a find replace could do that
easily also), but in a program that would be more comfortable.

break long lines (in a reasonable way)

make from:
if len(string) > 0: => if string:
and
if if len(string) < 1 orr if string == "" => if not string

detect mixed line ending
detect tabs mixed with space
trim trailing whitespaces.

.....
.....


Is there such a tool around?

Running Pylint or Pycheck automatically afterwards
would be the coronation. :)
 
N

Neil Hodgson

Franz Steinhaeusler:
Hello, I did not find any reasonable pyhton source code beautifier
program (preferable gui).
...
convert:
...
from "is" to "==" and "is not" to "!=" (ok a find replace could do that
easily also), but in a program that would be more comfortable.

That's an unsafe conversion. I don't think it is possible for a
reasonable program to determine statically that "is" is equivalent to
"==" except for trivial pieces of code.

Neil
 
C

Chuck Rhode

Franz Steinhaeusler wrote this on Tue, 27 Feb 2007 09:45:42 +0100. My
reply is below.
Hello, I did not find any reasonable pyhton source code beautifier
program (preferable gui).
-snip-

Is there such a tool around?

Why, yes! Yes, there is:

o http://lacusveris.com/PythonTidy/PythonTidy.python

It doesn't have a graphical user interface, and it doesn't do
everything you want, and it isn't reasonable (It's of an unreasonable
size.), but it is a beginning.

For future reference, look in:

o http://cheeseshop.python.org/pypi

.... under "reformat."
 
A

Alan Franzoni

Il Tue, 27 Feb 2007 09:45:42 +0100, Franz Steinhaeusler ha scritto:
Hello, I did not find any reasonable pyhton source code beautifier
program (preferable gui).

Well, most of the things you ask should be written as such, not written and
then beautified!
Use Spaces, size: 4

Your editor should support this.
convert structs like: if (a > b): to if a > b:

Well... that's a matter of fact, not just style. Sometimes parentheses help
the reading; if a,b are not just plain names but somewhat complex
instructions, parentheses should stay.
fill in spaces, but not in functions between operators:

a+=1 => a += 1
p(t + 1) => p(t+1)

Code should be written this way.
self.scriptcount = self.scriptcount + 1 => self.scriptcount += 1

the += operator is syntactic sugar just to save time... if one doesn't use
it I don't think it's a matter of beauty.
from "is" to "==" and "is not" to "!=" (ok a find replace could do that
easily also), but in a program that would be more comfortable.

what? No, I think you're missing the difference between 'is' and '=='. You
could say it the other way for None, True, False, e.g. if there's a 'a ==
None' it could be safely converted to 'a is None', but again: this should
be done while writing the code.
break long lines (in a reasonable way)

well... this could be useful sometimes, but again... 'reason' is usually
something human beings should employ, and shouldn't be 'outsourced' to
computer programs.
make from:
if len(string) > 0: => if string:
and
if if len(string) < 1 orr if string == "" => if not string

That's impossibile! Python is dynamically typed! How could the 'beautifier'
understand what the 'string' name is bound to? It could be whatever object!
detect mixed line ending
detect tabs mixed with space
trim trailing whitespaces.

Those are editor tasks.

Get a good Editor or IDE. You haven't told us what OS are you on. If you're
on Windows, UltraEdit can do most of the things you'd like. And don't rely
on a software to correct human behaviours ^_^.

--
Alan Franzoni <[email protected]>
-
Togli .xyz dalla mia email per contattarmi.
Remove .xyz from my address in order to contact me.
-
GPG Key Fingerprint (Key ID = FE068F3E):
5C77 9DC3 BD5B 3A28 E7BC 921A 0255 42AA FE06 8F3E
 
M

Michael Spencer

Franz said:
Use Spaces, size: 4
> detect mixed line ending
> detect tabs mixed with space
> trim trailing whitespaces.

look at: tools/scripts/reindent.py
convert structs like: if (a > b): to if a > b:
fill in spaces, but not in functions between operators:

a+=1 => a += 1
p(t + 1) => p(t+1)
an ast pretty printer could do this sort of thing. I saw someone post about one
on this list a couple of years ago, but can't quickly turn up the link.

from "is" to "==" and "is not" to "!=" (ok a find replace could do that
easily also), but in a program that would be more comfortable.
careful!

Michael
 
S

sjdevnull

Hello, I did not find any reasonable pyhton source code beautifier
program (preferable gui).

Some would ask why? Program it immediatly good.

(BTW: Would be a nice project, if I would have more spare time).

Ich have some foreign source, which are programed in a way
I don't like, so I would like to have a tool, which automatically
processes following options:

Use Spaces, size: 4

reindent.py or your editor should handle this, or PythonTidy
convert structs like: if (a > b): to if a > b:

If someone put the () around it, they probably have good reason (e.g.
clarity or they anticipate it being a multiline condition in the near
future)
fill in spaces, but not in functions between operators:

a+=1 => a += 1
p(t + 1) => p(t+1)
PythonTidy

convert:

self.scriptcount = self.scriptcount + 1 => self.scriptcount += 1

Those mean different things:
a=[1]
b=a
a += [2]
a [1, 2]
b [1, 2]
a=[1]
b=a
a = a + [2]
a [1, 2]
b
[1]


from "is" to "==" and "is not" to "!=" (ok a find replace could do that
easily also), but in a program that would be more comfortable. False


break long lines (in a reasonable way)

Not sure how this would be done.
make from:
if len(string) > 0: => if string:
and
if if len(string) < 1 orr if string == "" => if not string

Impossible in a dynamically typed system, you could hack up something
that works sometimes with type inference and/or type logging after
running the program but it'd be unreliable and hardly seems worth the
effort and danger. Especially since it might break other stringlike
classes depending on their semantics.
detect mixed line ending
detect tabs mixed with space
trim trailing whitespaces.

reindent.py handles those.
Running Pylint or Pycheck automatically afterwards
would be the coronation. :)

I have vim automatically call PyFlakes every time I hit enter and
highlight any errors (so stupidities like "if a=1:" are caught
immediately as I'm editing)
 
A

Alan Franzoni

Il 27 Feb 2007 16:14:20 -0800, (e-mail address removed) ha scritto:
Those mean different things:
a=[1]
b=a
a += [2]
a [1, 2]
b [1, 2]
a=[1]
b=a
a = a + [2]
a [1, 2]
b
[1]

This is a really nasty one! I just answered to Tim above here, and then I
saw your example... I had never realized that kind of list behaviour.
That's probably because i never use + and += on lists (i prefer the more
explicit append() or extend() and i do copy list explictly when I want to)
, BTW I think this behaviour is tricky!


--
Alan Franzoni <[email protected]>
-
Togli .xyz dalla mia email per contattarmi.
Remove .xyz from my address in order to contact me.
-
GPG Key Fingerprint (Key ID = FE068F3E):
5C77 9DC3 BD5B 3A28 E7BC 921A 0255 42AA FE06 8F3E
 
S

sjdevnull

Il 27 Feb 2007 16:14:20 -0800, (e-mail address removed) ha scritto:


Those mean different things:
a=[1]
b=a
a += [2]
a [1, 2]
b [1, 2]
a=[1]
b=a
a = a + [2]
a [1, 2]
b
[1]

This is a really nasty one! I just answered to Tim above here, and then I
saw your example... I had never realized that kind of list behaviour.
That's probably because i never use + and += on lists (i prefer the more
explicit append() or extend() and i do copy list explictly when I want to)
, BTW I think this behaviour is tricky!

Seems obvious and desirable to me. Bare "=" is the way you assign a
name to an object; saying "NAME =" will rebind the name, breaking the
connection between a and b. Without it, they continue to refer to the
same object; extending the list (via += or .extend) mutates the
object, but doesn't change which objects a and b are referencing.

It would be very counterintuitive to me if "=" didn't change the
name's binding, or if other operators did.
 
F

Franz Steinhaeusler

Hello,

thanks.

pythontidy (with maybe some patches could be useful)

not directly related but:
pyflakes looks quite interesting too.
and I try out (again) pylint and pychecker or a combination
of these could bring good results, I assume. ;)
 
G

Gabriel Genellina

En Wed, 28 Feb 2007 19:09:09 -0300, (e-mail address removed)
Il 27 Feb 2007 16:14:20 -0800, (e-mail address removed) ha scritto:
Those mean different things:
a=[1]
b=a
a += [2]
a
[1, 2]
b
[1, 2]
a=[1]
b=a
a = a + [2]
a
[1, 2]
b
[1]

This is a really nasty one! I just answered to Tim above here, and then
I
saw your example... I had never realized that kind of list behaviour.
That's probably because i never use + and += on lists (i prefer the more
explicit append() or extend() and i do copy list explictly when I want
to)
, BTW I think this behaviour is tricky!

Seems obvious and desirable to me. Bare "=" is the way you assign a
name to an object; saying "NAME =" will rebind the name, breaking the
connection between a and b. Without it, they continue to refer to the
same object; extending the list (via += or .extend) mutates the
object, but doesn't change which objects a and b are referencing.

It would be very counterintuitive to me if "=" didn't change the
name's binding, or if other operators did.

Note that a += b first tries to use __iadd__ if it is available, if not,
behaves like a = a + b.
And even if __iadd__ exists, there is no restriction on it to mutate the
object in place; it may return a new instance if desired.
So, a += b may involve a name rebinding anyway. Try the example above
using immutable objects like tuples or strings.
 
A

Alan Franzoni

Il 28 Feb 2007 14:09:09 -0800, (e-mail address removed) ha scritto:

Seems obvious and desirable to me. Bare "=" is the way you assign a
name to an object; saying "NAME =" will rebind the name, breaking the
connection between a and b. Without it, they continue to refer to the
same object; extending the list (via += or .extend) mutates the
object, but doesn't change which objects a and b are referencing.

Well... the main problem is not with the '+=' operators themselves, it's
with the 'global coherence'. I would assume then, that if the '+=' operator
is assumed to modify objects in-place, it would just fail on immutable
objects, wouldn't I?

I mean... I don't like that. I'm not really a Python expert, I found this
behaviour is documented in the language reference itself:

http://docs.python.org/ref/augassign.html

But... I don't know, still think it's confusing and not going to use it.

--
Alan Franzoni <[email protected]>
-
Togli .xyz dalla mia email per contattarmi.
Remove .xyz from my address in order to contact me.
-
GPG Key Fingerprint (Key ID = FE068F3E):
5C77 9DC3 BD5B 3A28 E7BC 921A 0255 42AA FE06 8F3E
 
G

greg

Alan said:
I would assume then, that if the '+=' operator
is assumed to modify objects in-place, it would just fail on immutable
objects, wouldn't I?

Then you wouldn't be able to do things like

x = 3
x += 1

which would result in howls of outrage from the
*other* half of the Python community.

The x += y syntax is designed to fill two different
but equally useful roles: one is to modify objects
in-place, the other is to be a short hand for
x = x + y.

This was all discussed at *very* great length many
years ago, and the addition of in-place operators
to the language was held up for a long time until
the present compromise was devised. You might not
like it, but it's here to stay.
 
A

Alan Franzoni

Il Sat, 03 Mar 2007 17:34:35 +1300, greg ha scritto:
This was all discussed at *very* great length many
years ago, and the addition of in-place operators
to the language was held up for a long time until
the present compromise was devised. You might not
like it, but it's here to stay.

Sure. I'm not a great programmer and I never thought about asking for such
a removal. I'm sure that there're people smarter and more experienced than
me out there designing Python, I'm glad I got it and I won't use such
shortcuts on mutable objects in my own programs.

At least, this is I what I think today; tomorrow, when I'm more
experienced, I could think about them and say 'Hey! They're really cute,
why haven't I used them before?'

Bye!

--
Alan Franzoni <[email protected]>
-
Togli .xyz dalla mia email per contattarmi.
Remove .xyz from my address in order to contact me.
-
GPG Key Fingerprint (Key ID = FE068F3E):
5C77 9DC3 BD5B 3A28 E7BC 921A 0255 42AA FE06 8F3E
 
P

Paul Boddie

I mean... I don't like that. I'm not really a Python expert, I found this
behaviour is documented in the language reference itself:

http://docs.python.org/ref/augassign.html

But... I don't know, still think it's confusing and not going to use it.

One way to think of it is this:

a += b

....is more or less the same as...

if hasattr(a, "__iadd__"):
a = a.__iadd__(b)
else:
a = a + b

Since __iadd__ might mutate an object, returning the same object, it's
possible to say that the name "a" still points to the same object in
such circumstances using the above scheme. Whether any rebinding or
resetting of "a" actually takes place in such a situation (in CPython)
might be considered an issue of optimisation, but I suppose augmented
assignments with attributes might bring out some semantic differences,
too, as can be seen by the note about class attributes at the end of
the referenced section of the manual.

Paul
 
G

Gabriel Genellina

En Mon, 05 Mar 2007 07:07:57 -0300, Alan Franzoni
Il Sat, 03 Mar 2007 17:34:35 +1300, greg ha scritto:


Sure. I'm not a great programmer and I never thought about asking for
such a removal. I'm sure that there're people smarter and more
experienced than me out there designing Python, I'm glad I got it and I
won't use such
shortcuts on mutable objects in my own programs.

The problem is that other people -not necesarily "smarter and more
experienced" than you- may use those features, and perhaps you have to
read, understand and modify some code written by someone else.
So, you should at least know what "a += b" means, even if you are not
going to use it.
 
A

Alan Franzoni

Il Tue, 06 Mar 2007 01:55:54 -0300, Gabriel Genellina ha scritto:

The problem is that other people -not necesarily "smarter and more
experienced" than you- may use those features, and perhaps you have to
read, understand and modify some code written by someone else.
So, you should at least know what "a += b" means, even if you are not
going to use it.

That's sure, and I'm in fact glad to know that by now. I still think it's
risky, BTW. Python is dynamically typed, after all, and there's no 'a
priori' way to know if 'a' is a list or another type, especially another
container type.

If we rely on duck typing, by the way, we may encounter two types quacking
like ducks, flying like ducks, but in fact acting as slightly different
ducks. I should remember as well, when designing a container type that I
want to use in place of a list, to carefully craft an __iadd__ method which
works just like the a list's own __iadd__ method; if I forget, I may
introduce a subtle error.


--
Alan Franzoni <[email protected]>
-
Togli .xyz dalla mia email per contattarmi.
Remove .xyz from my address in order to contact me.
-
GPG Key Fingerprint (Key ID = FE068F3E):
5C77 9DC3 BD5B 3A28 E7BC 921A 0255 42AA FE06 8F3E
 
G

Gabriel Genellina

En Wed, 07 Mar 2007 10:29:29 -0300, Alan Franzoni
Il Tue, 06 Mar 2007 01:55:54 -0300, Gabriel Genellina ha scritto:
If we rely on duck typing, by the way, we may encounter two types
quacking
like ducks, flying like ducks, but in fact acting as slightly different
ducks. I should remember as well, when designing a container type that I
want to use in place of a list, to carefully craft an __iadd__ method
which
works just like the a list's own __iadd__ method; if I forget, I may
introduce a subtle error.

I'm not sure of your concerns. If you want to provide your own container
that mimics a list, there are a lot more things to consider than __iadd__
(See the UserList class or this ListMixin recipe:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440656).

__iadd__, in general, is not *required* to modify the instance in place
(but should try to do that, if possible). After this code:
b = a
a += c
you can't assert than a and b both refer to the *same* object, as before.
If you need that, don't use += at all. (For a generic object, I mean. The
built-in list "does the right thing", of course)
 
A

Alan Franzoni

Il Wed, 07 Mar 2007 14:13:28 -0300, Gabriel Genellina ha scritto:
__iadd__, in general, is not *required* to modify the instance in place
(but should try to do that, if possible). After this code:
b = a
a += c
you can't assert than a and b both refer to the *same* object, as before.
If you need that, don't use += at all. (For a generic object, I mean. The
built-in list "does the right thing", of course)

Surely _I_ can't, and _I_ won't. But take the opposite example.

Let's say I'm using an external library, and that library's author provides
any kind of 'convenience' container type he feels useful for the library's
purposes, but without forcing a type constraint to the parameters passed to
a certain function - as should be done in a language like python, and this
container does create a copy of the object even employing incremental
operators.

Now, let's suppose I find that container type not useful for my purposes,
*or* I have already written a different container type which mimicks a
list's behaviour (adding some kind of functionality, of course).

Now, let's suppose a certain function in that library should give a certain
result based on the contents of that container, but without modifying the
original object, but it needs to modify it in order to do some operations.

if the function looks like this:

def foo(container):
container += [1, 2, 3]
...

it might happen that the original object gets modified even when it
shouldn't, depending on the actual object passed to the library.

What I just mean... I don't see calling extend() to be that painful in
respect to += . If there were no other way to do it, I would agree it would
be useful. But if there're such methods, do we really need this syntactic
sugar to introduce confusion?

--
Alan Franzoni <[email protected]>
-
Togli .xyz dalla mia email per contattarmi.
Remove .xyz from my address in order to contact me.
-
GPG Key Fingerprint (Key ID = FE068F3E):
5C77 9DC3 BD5B 3A28 E7BC 921A 0255 42AA FE06 8F3E
 
G

Gabriel Genellina

En Thu, 08 Mar 2007 13:13:23 -0300, Alan Franzoni
this
container does create a copy of the object even employing incremental
operators.

Now, let's suppose I find that container type not useful for my purposes,
*or* I have already written a different container type which mimicks a
list's behaviour (adding some kind of functionality, of course).

If the library relies on that behavior, it should be documented as such.
If you provide an alternative container that does not respect that
interfase, it's your fault. It it was not documented, it's theirs.
Now, let's suppose a certain function in that library should give a
certain
result based on the contents of that container, but without modifying the
original object, but it needs to modify it in order to do some
operations.

if the function looks like this:

def foo(container):
container += [1, 2, 3]
...

it might happen that the original object gets modified even when it
shouldn't, depending on the actual object passed to the library.

And that would be bad coding style in the library. += is an augmented
assignment, *can* be carried in place, or not. If they want a different
value for the container, why not just write:

extended_container = container + [1,2,3]

You can't write bulletproof code, but some constructs are safer than
others.
What I just mean... I don't see calling extend() to be that painful in
respect to += . If there were no other way to do it, I would agree it
would
be useful. But if there're such methods, do we really need this syntactic
sugar to introduce confusion?

Feel free to write a PEP suggesting removal of += and *= from lists.
http://www.python.org/dev/peps/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top