arlie: (Default)
Someone on a mailing list mentioned the Wingware IDE, which they describe as "THE best Editor of Python".

I don't like Integrated Development Environments (IDEs), tending to see them as "solutions" to problems I don't have - but I'm experiencing development with python as involving numerous problems I don't normally have.

In particular, I've noticed multiple misfeatures that amount to command line tools that expect to be used from a GUI wrapper, so don't bother being convenient to use in command line mode. Moreover, the emacs python mode that installed most naturally on my linux system is broken - it regularly "types" things that violate python style rules, which I then have to correct manually; most of them involve white space, such as "blank" lines unexpectedly containing four spaces, or the definition of a function being indented when I try to introduce a blank line above it.

So maybe this is a case of "if you can't beat them, join them". I.e. I decided to at least look at wingware.

I was told that Wingware had an emacs mode, solving one potential problem for me. And a look at their web site showed lots and lots of lovely documentation, much of it intelligently organized. Moreover, two of the three versions they have are free to use.

On the negative side, they offer artificial intelligence assistance in coding and refactoring, and digging a bit I found reference to one of the GPTs.

So I decided to download it, and install it on my linux box, then try to use it with my bookmarks management project.

Read more... )

Note that the above is a positive review. I think it possible that this tool will be useful to me, particularly for running code under the control of the python debugger - which is a massive PITA when used from the command line. I haven't given up on it

The learning curve is less bad than it was for Xcode, except that I don't have people nearby who already use the tool and can show me the basics.
arlie: (Default)
In a fit of optimism, I decided it would be interesting to convert a global variable, defined as a TypedDict, into a Class.

This variable is a collection of bits of information used by a parser to keep track of the state of its input. If this were C, it would probably have started life as a collection of global variables at file scope. If the local coding style limited the use of module globals, it would have been a struct.

Python's handling of non-mutable (aka pass-by-value) variables above function or class scope is basically garbage. You can't reliably modify them, without various workarounds. If "foo" is global, and I assign a value to "foo" in a function, the value is assigned to a local variable of the same name, which goes out of scope at the end of the function. If you use the "global" keyword to fix this, the type checkers have hysterics, and the code still doesn't always work. etc. etc. ad nauseam.

So I originally implemented the parser state as a dictionary. Dictionaries are "mutable", which means pass-by-reference in python, which means they work sensibly at global scope. Of course they also have the delightful "benefit" that typos in assignments will generally silently do the wrong thing. bar[name] = x; bar[Name] = y leaves bar with two fields. (But that's true for individual variables too.) I created an ugly workaround for that issue, but then I discovered the TypedDict class - dictionary at run time, but with extra testing when running type checkers. (You *almost* get all the maintainability of a proper C struct, though not quite.)

Well, it turned out that I wanted to enhance the program to run the parser multiple times, each on its own input file, with its own parser state. I could reuse the same variable, re-initializing it after each input file.

But conceptually this looks a lot like a 'class' which had been singleton, and would now have one instance per input file. (I'm used to doing OO things in non-OO languages; this doesn't bend my brain at all.) However, Python is an OO language. Maybe I should make it into a (singleton) class, before converting the code to handle several of them.

I checked, and the type checkers handle classes about as well as they handle TypedDict - I lose type checking on the two fields previously labelled NotRequired, now described as "attributes not set by the class' __init__ method." I gain slightly in readability. There's also a negligible-in-this-case improvement in memory use and performance - not from using a class, but from using python's __slots__ function with my class, which I'd do anyway since it gets me type-checker warnings for typoed field names.

I re-implemented it, and ran the various static check modules. The first problem was the names of my attributes. Dictionary tags are supposed to be Camel Case. FooBarBaz. Class attribute names are supposed to be snake case. foo_bar_baz. The syntax for accessing either a class attribute or a dictionary member is the same, so I'd expected not to have to change the 95 places where I used one of these fields. No such luck. Every ParserState.FooBar has to be changed to ParserState.foo_bar.

Of course I could simply suppress the warning, but I'm trying to train myself to read and write "normal python".

Then I got the next pair of warnings.

parser_state.py:14:0: R0902: Too many instance attributes (9/7) (too-many-instance-attributes)
parser_state.py:14:0: R0903: Too few public methods (0/2) (too-few-public-methods)

I have 11 fields in this not-a-struct. The error says 9, but that's presumably because only 9 are set in __init__. Whoops! Can't have that.

And even though it's always legal to access class attributes from non-class code (ugh! ugh! ugh!) it's not OK to have nothing but an __init__ method.

How is this good language design? In what world should "objects" be totally unprotected from users messing with their guts - best you get is a convention that users should not mess with variables with names like __foo__ - but having less than 2 methods or more than 7 instance attributes should be a problem treated as harshly as modifying a conventionally private class/instance attribute?!
arlie: (Default)
I found myself looking for a project to work on, so I dusted off a software development project I'd already abandoned twice before, and decided to redesign for faster usefulness, then start over, using the existing code and design as a guide.

It's going much faster - last time I was working on it was too soon after chemotherapy, and I didn't have the energy to do more than a tiny bit each day. Of course I also have existing code to modify and reuse, which also speeds things up - but on the other hand, I'm making things harder on myself by trying to make the code as maintainable as possible, in spite of it being written in python.

Python is the right language for this job, since it involves parsing html files, building and manipulating complex dictionaries, and similar things. (The other obvious candidate would be perl. And there may be some languages of the same type newer and better than python, but I've never used them.)

I'm not a python expert. My "native" computer language is C. I've written python, sometimes even for money, but I don't think like a pythonista. Various python design decisions make me more or less crazy, though AFAIK, it's the best commonly used language of its general type.

click here for rant )

Profile

arlie: (Default)
arlie

February 2026

S M T W T F S
12 345 6 7
8 91011121314
1516 1718192021
22232425262728

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags