Skip to content

Commit

Permalink
Merge branch 'edgar24.1-upd2' of github.com:/hermfischer-wf/Arelle in…
Browse files Browse the repository at this point in the history
…to edgar24.1-upd2
  • Loading branch information
austinmatherne-wk committed Apr 3, 2024
2 parents 86b9b8b + 9974473 commit 3b84c83
Show file tree
Hide file tree
Showing 14 changed files with 1,436 additions and 636 deletions.
3 changes: 2 additions & 1 deletion arelle/CntlrWebMain.py
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,8 @@ def helpREST() -> str:
<tr><td style="text-indent: 1em;">media</td><td><code>html</code> or <code>xhtml</code>: Html text results. (default)
<br/><code>xml</code>: XML structured results.
<br/><code>json</code>: JSON results.
<br/><code>text</code>: Plain text results (no markup).</td></tr>
<br/><code>text</code>: Plain text results (no markup).
<br/><code>zip</code>: Zip results (for multi-file results, such as from EdgarRenderer).</td></tr>
<tr><td style="text-indent: 1em;">file</td><td>Alternate way to specify file name or url by a parameter. Files ending in .json will be loaded as xBRL-JSON.</td></tr>
<tr><td style="text-indent: 1em;">import</td><td>A list of files to import to the DTS, such as additional formula
or label linkbases. Multiple file names are separated by a '|' character.</td></tr>
Expand Down
23 changes: 11 additions & 12 deletions arelle/ModelDocument.py
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,7 @@ def updateFileHistoryIfNeeded(self):
except AttributeError:
pass

def save(self, overrideFilepath=None, outputZip=None, outputFile=None, updateFileHistory=True, encoding="utf-8", **kwargs) -> None:
def save(self, overrideFilepath=None, outputZip=None, outputFile=None, updateFileHistory=True, encoding="utf-8", zipDir=None, **kwargs) -> None:
"""Saves current document file.
:param overrideFilepath: specify to override saving in instance's modelDocument.filepath
Expand All @@ -800,7 +800,7 @@ def save(self, overrideFilepath=None, outputZip=None, outputFile=None, updateFil
XmlUtil.writexml(fh, self.xmlDocument, encoding=encoding, **kwargs)
if outputZip:
fh.seek(0)
outputZip.writestr(os.path.basename(overrideFilepath or self.filepath),fh.read())
outputZip.writestr((zipDir or "") + os.path.basename(overrideFilepath or self.filepath),fh.read())
if outputFile is None:
fh.close()
if overrideFilepath:
Expand Down Expand Up @@ -1286,9 +1286,9 @@ def instanceContentsDiscover(self,xbrlElement):
modelObject=undefFacts,
elements=", ".join(sorted(set(str(f.prefixedName) for f in undefFacts))))

def contextDiscover(self, modelContext, targetModelXbrl=None) -> None:
def contextDiscover(self, modelContext, setTargetModelXbrl=False) -> None:
if not self.skipDTS:
xmlValidate(self.modelXbrl, modelContext) # validation may have not completed due to errors elsewhere
xmlValidate(self.modelXbrl, modelContext, setTargetModelXbrl=setTargetModelXbrl) # validation may have not completed due to errors elsewhere
id = modelContext.id
self.modelXbrl.contexts[id] = modelContext
for container in (("{http://www.xbrl.org/2003/instance}segment", modelContext.segDimValues, modelContext.segNonDimValues),
Expand All @@ -1300,10 +1300,11 @@ def contextDiscover(self, modelContext, targetModelXbrl=None) -> None:
if sElt.namespaceURI == XbrlConst.xbrldi and sElt.localName in ("explicitMember","typedMember"):
dimQn = sElt.dimensionQname
if dimQn: # may be null if schema error omits dimension element
if targetModelXbrl is not None: # ixds possibly-shared context
sElt.targetModelXbrl = targetModelXbrl
if setTargetModelXbrl: # ixds possibly-shared context
if hasattr(sElt, "_dimension") and sElt._dimension is None:
del sElt._dimension
if hasattr(sElt, "_member") and sElt._member is None:
del sElt._member
modelContext.qnameDims[dimQn] = sElt # both seg and scen
if not self.skipDTS:
dimension = sElt.dimension
Expand All @@ -1314,12 +1315,10 @@ def contextDiscover(self, modelContext, targetModelXbrl=None) -> None:
else:
containerNonDimValues.append(sElt)

def unitDiscover(self, unitElement, targetModelXbrl=None) -> None:
def unitDiscover(self, unitElement, setTargetModelXbrl=False) -> None:
if not self.skipDTS:
xmlValidate(self.modelXbrl, unitElement) # validation may have not completed due to errors elsewhere
xmlValidate(self.modelXbrl, unitElement, setTargetModelXbrl=setTargetModelXbrl) # validation may have not completed due to errors elsewhere
self.modelXbrl.units[unitElement.id] = unitElement
if targetModelXbrl is not None: # ixds possibly-shared context
unitElement.targetModelXbrl = targetModelXbrl

def inlineXbrlDiscover(self, htmlElement):
ixNS = None
Expand Down Expand Up @@ -1641,11 +1640,11 @@ def inlineIxdsDiscover(modelXbrl, modelIxdsDocument, setTargetModelXbrl=False):
for elt in inlineElement.iterchildren("{http://www.xbrl.org/2003/instance}context"):
id = elt.get("id")
if id in contextRefs or (assignUnusedContextsUnits and id not in allContextRefs):
modelIxdsDocument.contextDiscover(elt, targetModelXbrl=targetModelXbrl)
modelIxdsDocument.contextDiscover(elt, setTargetModelXbrl)
for elt in inlineElement.iterchildren("{http://www.xbrl.org/2003/instance}unit"):
id = elt.get("id")
if id in unitRefs or (assignUnusedContextsUnits and id not in allUnitRefs):
modelIxdsDocument.unitDiscover(elt, targetModelXbrl=targetModelXbrl)
modelIxdsDocument.unitDiscover(elt, setTargetModelXbrl)
for refElement in inlineElement.iterchildren("{http://www.xbrl.org/2003/linkbase}roleRef"):
r = refElement.get("roleURI")
if r in targetRoleUris[ixdsTarget]:
Expand Down
7 changes: 6 additions & 1 deletion arelle/ModelRelationshipSet.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ def rootConcepts(self):

# if modelFrom and modelTo are provided determine that they have specified relationship
# if only modelFrom, determine that there are relationships present of specified axis
def isRelated(self, modelFrom, axis, modelTo=None, visited=None, isDRS=False): # either model concept or qname
def isRelated(self, modelFrom, axis, modelTo=None, visited=None, isDRS=False, consecutiveLinkrole=False): # either model concept or qname
assert self.modelXbrl is not None
if getattr(self.modelXbrl, "isSupplementalIxdsTarget", False):
if modelFrom is not None and modelFrom.modelXbrl != self.modelXbrl:
Expand Down Expand Up @@ -339,6 +339,11 @@ def isRelated(self, modelFrom, axis, modelTo=None, visited=None, isDRS=False): #
modelRel.consecutiveLinkrole, self.linkqname, self.arcqname)
.isRelated(toConcept, axis, modelTo, visited, isDRS)):
return True
elif consecutiveLinkrole: # allows starting at relationship set with ELR None
if (self.modelXbrl.relationshipSet(modelRel.arcrole,
modelRel.consecutiveLinkrole, self.linkqname, self.arcqname)
.isRelated(toConcept, axis, modelTo, visited, isDRS, consecutiveLinkrole)):
return True
else:
if self.isRelated(toConcept, axis, modelTo, visited, isDRS):
return True
Expand Down
11 changes: 7 additions & 4 deletions arelle/XmlValidate.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ def validate(
recurse: bool = True,
attrQname: QName | None = None,
ixFacts: bool = False,
setTargetModelXbrl: bool = False, # when true also revalidate previously validated elements
) -> None:
global ModelInlineValueObject, ixMsgCode
if ModelInlineValueObject is None:
Expand All @@ -126,8 +127,10 @@ def validate(
facets = None

# attrQname can be provided for attributes that are global and LAX
if (getattr(elt,"xValid", UNVALIDATED) == UNVALIDATED) and (not isIxFact or ixFacts):
if (getattr(elt,"xValid", UNVALIDATED) == UNVALIDATED or setTargetModelXbrl) and (not isIxFact or ixFacts):
assert modelXbrl is not None
if setTargetModelXbrl and modelXbrl != elt.modelXbrl: # change of element's targetModelXbrl
elt.targetModelXbrl = modelXbrl
qnElt = elt.qname if ixFacts and isIxFact else elt.elementQname
modelConcept = modelXbrl.qnameConcepts.get(qnElt)
isAbstract = False
Expand Down Expand Up @@ -322,7 +325,7 @@ def validate(
modelObject=elt,
element=qnElt)
else:
errResult = validateElementSequence(modelXbrl, type, childElts, ixFacts)
errResult = validateElementSequence(modelXbrl, type, childElts, ixFacts, setTargetModelXbrl)
if errResult is not None and errResult[2]:
iElt, occured, errDesc, errArgs = errResult
errElt1 = childElts[iElt] if iElt < len(childElts) else elt
Expand All @@ -337,15 +340,15 @@ def validate(
if qnElt.namespaceURI == XbrlConst.xbrli and iElt < len(childElts):
for childElt in childElts[iElt:]:
if (getattr(childElt,"xValid", UNVALIDATED) == UNVALIDATED):
validate(modelXbrl, childElt, ixFacts=ixFacts)
validate(modelXbrl, childElt, ixFacts=ixFacts, setTargetModelXbrl=setTargetModelXbrl)
recurse = False # cancel child element validation below, recursion was within validateElementSequence
except AttributeError as ex:
raise ex
#pass # HF Why is this here????
if recurse: # if there is no complex or simple type (such as xbrli:measure) then this code is used
for child in (cast('ModelFact', elt).modelTupleFacts if ixFacts and isIxFact else elt):
if isinstance(child, ModelObject):
validate(modelXbrl, child, recurse, attrQname, ixFacts)
validate(modelXbrl, child, recurse, attrQname, ixFacts, setTargetModelXbrl)

def validateValue(
modelXbrl: ModelXbrl | None,
Expand Down
6 changes: 3 additions & 3 deletions arelle/XmlValidateParticles.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from arelle.XmlValidate import validate


def validateElementSequence(modelXbrl, compositor, children, ixFacts, iNextChild=0):
def validateElementSequence(modelXbrl, compositor, children, ixFacts, setTargetModelXbrl, iNextChild=0):
if compositor.modelDocument.targetNamespace == xsd:
return (iNextChild, True, None, None)
particles = compositor.dereference().particles
Expand Down Expand Up @@ -41,7 +41,7 @@ def validateElementSequence(modelXbrl, compositor, children, ixFacts, iNextChild
(vQname in modelXbrl.qnameConcepts and
modelXbrl.qnameConcepts[vQname].substitutesForQname(elementDeclaration.qname))))):
occurrences += 1
validate(modelXbrl, elt, ixFacts=ixFacts)
validate(modelXbrl, elt, ixFacts=ixFacts, setTargetModelXbrl=setTargetModelXbrl)
iNextChild += 1
if occurrences == particle.maxOccurs:
break
Expand All @@ -50,7 +50,7 @@ def validateElementSequence(modelXbrl, compositor, children, ixFacts, iNextChild
else: # group definition or compositor
while occurrences < particle.maxOccurs:
iPrevChild = iNextChild
iNextChild, occurred, errDesc, errArgs = validateElementSequence(modelXbrl, particle, children, ixFacts, iNextChild)
iNextChild, occurred, errDesc, errArgs = validateElementSequence(modelXbrl, particle, children, ixFacts, setTargetModelXbrl, iNextChild)
if occurred:
# test if occurrence was because of minOccurs zero but no match occurred (HF 2012-09-07)
if occurred and iNextChild == iPrevChild and particle.minOccurs == 0: # nothing really occurred
Expand Down

0 comments on commit 3b84c83

Please sign in to comment.