[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Gnu-arch-users] PyArch newbie observations/questions
Re: [Gnu-arch-users] PyArch newbie observations/questions
Mon, 24 May 2004 19:43:27 +0200
Yeah! Feedback on PyArch :-)
On Mon, May 24, 2004 at 07:42:53AM -0500, Charles Duffy wrote:
> >>> arch.arch.SourceTree()
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> TypeError: __init__() takes exactly 2 arguments (1 given)
By the way, "arch.SourceTree()" is the blessed way to do it. It's just
that I could not convince myself to put all the interesting code in a
file called "__init__.py".
> My expectations was that '.' would be used as default if no arguments
> were provided.
Supposedly, that's what it should do. Actually, I'm none to happy about
the SourceTree class, because it uses some fancy DWIM logic in
SourceTree.__new__ to instanciate the appropriate concrete class, but I
thought it would make things more simple and intuitive to use.
Here is how it's supposed to work:
1. SourceTree() is used
2. SourceTree.__new__(SourceTree, None) is called
3. Since the class parameter to __init__ is SourceTree, the factory
code is used.
4. Since "root" is None, it is set to the tree-root of the current
5. Root is checked to be a Arch source tree root, and if it is, it is
the path is checked to be in the revision library (yeah, multiple
revision libraries are not supported yet, patches welcome).
Eventually, one of LibraryTree(root), WorkingTree(root) or
ForeignTree(root) is called.
6. SourceTree.__new__(cls, root) is called, where cls is the selected
concrete class and root is the not-None root previously computed.
Since cls is not SourceTree, the inherited __new__ is called.
7. Object creation proceeds as usual, and cls.__init__ is called with
the given root parameter.
The error you get suggests that this logic is bypassed. What version of
Python are you using? You need a version which supports __new__, I not
sure exactly what version of Python that got in, but anything before 2.3
is likely to be problematic.
> Are there mappings to changes/what-changed? (If nothing else, I'm
> frequently going to want to know if a working tree has uncommitted
> changes; I may or may not care what they are).
No there are not. Patches welcome.
That should be a method in WorkingTree, something like:
def changes(self, link=False, output=None)
If output is not set, it would return True if there are changes, False
if there is no change, and raise an exception if something goes wrong.
If output is set, it should be a string, and the changeset will be saved
under this name. On normal termination, the method returns a Changeset
object whose string value (remember, changesets are DirName objects, so
they are string objects) is equal to output.
It might make sense to special-case output=True and use the filesystem
name given by tla when the option --keep is given without --output
option. That's an option if the changeset name is predictible in a
Obviously, the "link" option enable source tree relinking with the
> How about tree-lint? Parsing the output may not be a trivial feature to
> add, but even an output status indicating errors/warnings/clean output
> could be useful.
tree-lint is a big problem...
Without any option, the output is difficult to parse and is prone to
changes, so that's not really reliable.
A more robust way, would be running tree-lint for every option which is
known to PyArch, so the output is easier to parse, but at the cost of
multiple, expensive, inventories. So that's not really an option either.
A practicable solution might be returning an error/warning/clean
indicator if no option was given, and do some parsing if a specific
option (broken_symlinks, unrecognized_files, untagged_files,
missing_files, duplicate_ids) is set to true...
Frankly, I have not considered the issue yet, so any contribution which
is not obviously broken will go in. But, please, please, also provide
More generally, PyArch is something public. It's vocation is to
concentrate all the arch-python foundation work in one place so we will
eventually get one good thing for everyone instead of several bad things
for each project. That's a magic cauldron.
> Presuming I have a Version or Revision, how do I get the associated
> Category object? How do I get just the name of the category (without the
> archive name)? [yes, I can pull the full name and parse it, but
> something that puts knowledge about how the names work outside my code
> would be nicer]
One solution would be to add "archive", "category", "branch" and
"version" read-only properties to the relevant archive objects (Archive,
Category, Branch, Version, Revision) which return an instance of the
corresponding container. That could be factored out into the
RevisionIterable, VersionIterable, BranchIterable, and CategoryIterable
The solution I would prefer would be overloading the __init__ of the
archive objects. It could use the *Iterable hierarchy to provide a
common framework to get the name of containing archive structures (as
logical name tuples, see below), but then this would be made of
protected methods, to respect the Python Zen "There should be one-- and
preferably only one --obvious way to do it".
Getting the non-arch name part of an archive object is trivial, since
the objects already store the logical parts of the name (archive,
package-version, patchlevel) in separate attributes. Check the
get_fullname method for the names of those attributes.
A "nonarch" readonly property which returns the value of the
appropriate attribute, and glue the version and patchlevel in Revision
objects, would we welcome.
If that does not make sense to you, you are welcome to comment. I
have not been giving these suggestions the amount of meditation they
deserve. Meditation which includes staring at the code wondering whether
that is Beautiful.