-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Self
narrows with custom element class
#51
Comments
@scanny It looks like you want to construct a heterogeneous tree (please correct me otherwise). Current implementation is geared towards creating homogeneous tree. With the changes you suggested, it is indeed smoother for manipulation of heterogeneous tree. Actually The reason was that using I'll try to think through it in these few days. Please feel free to suggest any idea alleviating the situation if you have any. |
@abelcheung I think it's fair to say that the general case is that XML trees are heterogenous, at least as far as element-types ("tags") are concerned. Consider a garden-variety XML structure: <person>
<name>Bob</name>
<street_address apt=false>123 Main Street</street_address>
...
</person> as opposed to a homogenous: <thing>
<thing>abc</thing>
<thing>
def
<thing>ghi</thing>
</thing>
</thing> I'm not sure what a "homogenous" tree would model. While it is possible to use the same custom element class to model all element types (xsd:complexType definitions in XML Schema), this a degenerate case, even if it is more common (I've seen no evidence to suggest this btw). The general case is that you can use an arbitrary custom element class for any element, and the only thing those elements are guaranteed to have in common is So specializing these stubs to Let me know what you decide. This would be a deal-breaker for me and I think relegate this project to special-case use. |
@abelcheung Regarding the "loss of context" problem, I definitely know what you mean, I have certainly encountered this in my own code (I'm the author of In my view, this is unavoidable and I remedy it by casting (there are one or two other ways). As a contrived example, a run is a child of a paragraph, so I would need something like this when using def fn(r: CT_R):
"""CT_R is the custom element-class for a Run in python-docx.
Its semantics are described by the XML Schema complex-type of the same name.
"""
p = cast(CT_P, r.getparent())
# ... do things with CT_P element, representing a paragraph This sort of thing occasionally happens in all the code bases I work in. There is nothing in the type system that can tell me the specific type that This could be mitigated by adding a property class CT_R:
@property
def enclosing_p(self) -> CT_P:
return cast(CT_P, self.getparent() And I do have mechanisms for that sort of thing in the docx and pptx projects. But I would see using As far as an underlying principle is concerned, I'd say the governing principle is that the type annotations should be truthful (faithfully represent the facts), before they are convenient. There is some leeway for convenience, but promising more than the annotated code can deliver will generally exclude use-cases and therefore users. |
When you provided this absurd example: <thing>
<thing>abc</thing>
<thing>
def
<thing>ghi</thing>
</thing>
</thing> I immediately realized we have discrepancy in terms and understanding of situation. There are lots of opinions I want to rebuke, but it's a pure waste of time. Let me only rephrase what I intended to express originally. In my understand there are 3 major situation about element class lookup usage:
I tried to combine (1) and (2), and you convinced me I haven't been paying attention to (3). The solution I come up so far, is to create 2 packages in every release, one being (1+2) as originally have been doing, and a new package of (1+3), so that you can pick the latter one. If you have no objection to that, I'll finish that by next release, hopefully on June or July. It's definitely after May, as I have personal matters that need immediate attention during the whole month. |
Ah, yes, I see, apologies, I misunderstood what you meant by "homogenous". I agree with your case-analysis. I'm sure using a single custom element-class is a common case. I'm okay with a separate package. As long as there is a package that does the needful it doesn't matter much to me what it is named. One thought occurs to me that might be worth considering, as a way to avoid a "branched" library: In the single custom-element-class case, one way to avoid casting every return value from methods like class CustomElementClass:
def getparent(self) -> CustomElementClass:
return super().getparent() In my own experience, while For my purposes, I need to cast from Anyway, something to consider :) |
…ookup This patch is intended to apply only during alternative build stage, hopefully solving issue #51. Not using another git branch due to easier maintenance.
@scanny Do you have any idea for new tarball name? I'm going for something like Next batches of changes will conflict with main branch so I'm merging sooner than normal. |
@abelcheung I think the latter name |
@scanny Sorry for the long wait, package is available for testing now. |
Thanks for this @abelcheung it seems to work great! Thanks for all your work on this :) Just having a browse through, this is definitely a "rich" interface :) There's a lot more to it than I've had occasion to use in my projects :) |
element: Self
is used in multiple places in the stub foretree._Element
. Here's a typical example:https://github.com/abelcheung/types-lxml/blob/main/lxml-stubs/etree/_element.pyi#L97
This produces over-narrowing of the type when used with custom element classes, like this:
This is because
Self
takes the type ofself
(Frombus
in this case) and only wants to allow elements of the same type to be inserted.I think the solution is to use
"_Element"
in most (or maybe all) places whereSelf
appears within the_Element
stub, which I expect was the original intent (thatelement
can be any subtype of_Element
). If you addfrom __future__ import annotations
at the top of the file I believe you can leave off the double-quotes.This works as intended when I patch in these changes locally.
The text was updated successfully, but these errors were encountered: