arelle-release 2.36.40__py3-none-any.whl → 2.37.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of arelle-release might be problematic. Click here for more details.

arelle/CntlrCmdLine.py CHANGED
@@ -486,7 +486,7 @@ def parseArgs(args):
486
486
  "\n Python(r) {pythonVersion} (c) 2001-2013 Python Software Foundation"
487
487
  "\n PyParsing (c) 2003-2013 Paul T. McGuire"
488
488
  "\n lxml {lxmlVersion} (c) 2004 Infrae, ElementTree (c) 1999-2004 by Fredrik Lundh"
489
- "{bottleCopyright}"
489
+ "\n Bottle (c) 2009-2024 Marcel Hellkamp"
490
490
  "\n May include installable plug-in modules with author-specific license terms").format(
491
491
  version=Version.__version__,
492
492
  wordSize=getSystemWordSize(),
@@ -494,7 +494,6 @@ def parseArgs(args):
494
494
  copyrightLabel=Version.copyrightLabel,
495
495
  pythonVersion=f'{sys.version_info[0]}.{sys.version_info[1]}.{sys.version_info[2]}',
496
496
  lxmlVersion=f'{etree.LXML_VERSION[0]}.{etree.LXML_VERSION[1]}.{etree.LXML_VERSION[2]}',
497
- bottleCopyright="\n Bottle (c) 2011-2013 Marcel Hellkamp" if hasWebServer() else ""
498
497
  ))
499
498
  parser.exit() # Printing the message in parser.exit sends it to stderr NOT stdout
500
499
  elif options.diagnostics:
arelle/CntlrWebMain.py CHANGED
@@ -15,16 +15,16 @@ import zipfile
15
15
  from collections.abc import Iterable
16
16
  from copy import deepcopy
17
17
 
18
+ from bottle import Bottle, HTTPResponse, request, response, static_file # type: ignore[import-untyped]
19
+
18
20
  from arelle import Version
19
21
  from arelle.CntlrCmdLine import CntlrCmdLine
20
22
  from arelle.FileSource import FileNamedStringIO
21
- from arelle.PluginManager import pluginClassMethods
22
- from arelle.RuntimeOptions import RuntimeOptions
23
23
  from arelle.logging.formatters.LogFormatter import LogFormatter
24
24
  from arelle.logging.handlers.LogToBufferHandler import LogToBufferHandler
25
+ from arelle.PluginManager import pluginClassMethods
26
+ from arelle.RuntimeOptions import RuntimeOptions
25
27
  from arelle.typing import TypeGetText
26
- from arelle.webserver.bottle import (Bottle, HTTPResponse, request, response,
27
- static_file)
28
28
 
29
29
  _: TypeGetText
30
30
 
@@ -136,13 +136,13 @@ def startWebserver(cntlr: CntlrCmdLine, options: RuntimeOptions) -> Bottle | Non
136
136
  elif server == "cgi":
137
137
  if sys.stdin is None:
138
138
  sys.stdin = open(os.devnull, 'r')
139
- app.run(server=server) # type: ignore[no-untyped-call]
139
+ app.run(server=server)
140
140
  sys.exit(0)
141
141
  elif server:
142
142
  sys.path.insert(0,os.path.join(os.path.dirname(__file__),"webserver"))
143
- app.run(host=host, port=port or 80, server=server) # type: ignore[no-untyped-call]
143
+ app.run(host=host, port=port or 80, server=server)
144
144
  else:
145
- app.run(host=host, port=port or 80) # type: ignore[no-untyped-call]
145
+ app.run(host=host, port=port or 80)
146
146
  return None
147
147
 
148
148
  def cgiInterface(cgiAppPath: str) -> str | HTTPResponse:
arelle/CntlrWinMain.py CHANGED
@@ -1486,7 +1486,8 @@ class CntlrWinMain (Cntlr.Cntlr):
1486
1486
  "\n Tcl/Tk {tcltkVersion} \u00a9 Univ. of Calif., Sun, Scriptics, ActiveState, and others"
1487
1487
  "\n PyParsing \u00a9 2003-2013 Paul T. McGuire"
1488
1488
  "\n lxml {lxmlVersion} \u00a9 2004 Infrae, ElementTree \u00a9 1999-2004 by Fredrik Lundh"
1489
- "{bottleCopyright}"
1489
+ "\n Bottle \u00a9 2009-2024 Marcel Hellkamp"
1490
+ "\n CherryPy \u00a9 2004-2019 CherryPy Team"
1490
1491
  "\n May include installable plug-in modules with author-specific license terms").format(
1491
1492
  version=Version.__version__,
1492
1493
  wordSize=self.systemWordSize,
@@ -1495,8 +1496,6 @@ class CntlrWinMain (Cntlr.Cntlr):
1495
1496
  pythonVersion=f'{sys.version_info[0]}.{sys.version_info[1]}.{sys.version_info[2]}',
1496
1497
  tcltkVersion=Tcl().eval('info patchlevel'),
1497
1498
  lxmlVersion=f'{etree.LXML_VERSION[0]}.{etree.LXML_VERSION[1]}.{etree.LXML_VERSION[2]}',
1498
- bottleCopyright=_("\n Bottle \u00a9 2011-2013 Marcel Hellkamp"
1499
- "\n CherryPy \u00a9 2002-2013 CherryPy Team") if self.hasWebServer else ""
1500
1499
  ))
1501
1500
 
1502
1501
 
arelle/FileSource.py CHANGED
@@ -20,6 +20,7 @@ from lxml import etree
20
20
 
21
21
  import arelle.PluginManager
22
22
  from arelle import PackageManager, XmlUtil
23
+ from arelle.PythonUtil import isLegacyAbs
23
24
  from arelle.packages.report.DetectReportPackage import isReportPackageExtension
24
25
  from arelle.packages.report.ReportPackage import ReportPackage
25
26
  from arelle.typing import TypeGetText
@@ -769,7 +770,7 @@ class FileSource:
769
770
 
770
771
  def basedUrl(self, selection: str) -> str:
771
772
  baseurl = getattr(self, "baseurl", None)
772
- if not baseurl or isHttpUrl(selection) or os.path.isabs(selection):
773
+ if not baseurl or isHttpUrl(selection) or isLegacyAbs(selection):
773
774
  return selection
774
775
  assert isinstance(baseurl, str)
775
776
  if self.baseIsHttp or os.sep == '/':
arelle/LocalViewer.py CHANGED
@@ -4,8 +4,14 @@ See COPYRIGHT.md for copyright information.
4
4
  Provides infrastructure for local viewers of GUI applications such as inline XBRL viewers
5
5
 
6
6
  '''
7
- from arelle.webserver.bottle import Bottle, request, static_file, HTTPResponse
8
- import threading, time, logging, sys, traceback
7
+ import logging
8
+ import sys
9
+ import threading
10
+ import time
11
+ import traceback
12
+
13
+ from bottle import Bottle, HTTPResponse, request
14
+
9
15
 
10
16
  class LocalViewer:
11
17
  noCacheHeaders = {'Cache-Control': 'no-cache, no-store, must-revalidate',
arelle/ModelDocument.py CHANGED
@@ -20,7 +20,7 @@ from arelle.ModelInstanceObject import ModelFact
20
20
  from arelle.ModelObjectFactory import parser
21
21
  from arelle.PrototypeDtsObject import LinkPrototype, LocPrototype, ArcPrototype, DocumentPrototype, PrototypeElementTree
22
22
  from arelle.PluginManager import pluginClassMethods
23
- from arelle.PythonUtil import OrderedDefaultDict, normalizeSpace
23
+ from arelle.PythonUtil import OrderedDefaultDict, isLegacyAbs, normalizeSpace
24
24
  from arelle.XhtmlValidate import ixMsgCode
25
25
  from arelle.XmlValidateConst import VALID
26
26
  from arelle.XmlValidate import validate as xmlValidate, lxmlSchemaValidate
@@ -1106,7 +1106,7 @@ class ModelDocument:
1106
1106
  break # break because it is now absolute
1107
1107
  baseElt = baseElt.getparent()
1108
1108
  if base: # neither None nor ''
1109
- if base.startswith('http://') or os.path.isabs(base):
1109
+ if base.startswith('http://') or isLegacyAbs(base):
1110
1110
  return base
1111
1111
  else:
1112
1112
  return os.path.dirname(self.uri) + "/" + base
arelle/PackageManager.py CHANGED
@@ -15,6 +15,7 @@ from urllib.parse import urljoin
15
15
  from lxml import etree
16
16
 
17
17
  from arelle import Locale
18
+ from arelle.PythonUtil import isLegacyAbs
18
19
  from arelle.packages import PackageValidation
19
20
  from arelle.packages.PackageType import PackageType
20
21
  from arelle.typing import TypeGetText
@@ -314,7 +315,7 @@ def _parseCatalog(
314
315
  replaceValue = os.path.join(base, replaceValue)
315
316
  if replaceValue and not isAbsolute(replaceValue):
316
317
  # neither None nor ''
317
- if not os.path.isabs(replaceValue):
318
+ if not isLegacyAbs(replaceValue):
318
319
  replaceValue = fileBase + replaceValue
319
320
  if not isHttpUrl(replaceValue):
320
321
  replaceValue = replaceValue.replace("/", os.sep)
arelle/PluginManager.py CHANGED
@@ -15,6 +15,7 @@ from types import ModuleType
15
15
  from typing import TYPE_CHECKING, Any, cast
16
16
  from arelle.Locale import getLanguageCodes
17
17
  import arelle.FileSource
18
+ from arelle.PythonUtil import isLegacyAbs
18
19
  from arelle.UrlUtil import isAbsolute
19
20
  from pathlib import Path
20
21
  from collections import OrderedDict, defaultdict
@@ -447,7 +448,7 @@ def moduleModuleInfo(
447
448
  mergedImportURLs.append(moduleImport + ".py")
448
449
  imports = []
449
450
  for _url in mergedImportURLs:
450
- if isAbsolute(_url) or os.path.isabs(_url):
451
+ if isAbsolute(_url) or isLegacyAbs(_url):
451
452
  _importURL = _url # URL is absolute http or local file system
452
453
  else: # check if exists relative to this module's directory
453
454
  _importURL = os.path.join(os.path.dirname(moduleURL), os.path.normpath(_url))
arelle/PythonUtil.py CHANGED
@@ -6,6 +6,7 @@ do not convert 3 to 2
6
6
  '''
7
7
  from __future__ import annotations
8
8
 
9
+ import os
9
10
  import subprocess
10
11
  import sys
11
12
  from collections import OrderedDict
@@ -269,3 +270,15 @@ def tryRunCommand(*args: str) -> str | None:
269
270
  ).stdout.strip()
270
271
  except (OSError, subprocess.SubprocessError):
271
272
  return None
273
+
274
+ def isLegacyAbs(path: str) -> bool:
275
+ """
276
+ Implements legacy behavior of os.path.isabs() prior to Python 3.13
277
+ where True was returned for paths beginning with single slashes on Windows.
278
+ """
279
+ if os.path.isabs(path):
280
+ return True
281
+ from arelle.SystemInfo import PlatformOS
282
+ if PlatformOS.getPlatformOS() == PlatformOS.WINDOWS:
283
+ return path.startswith(("/", "\\"))
284
+ return False
arelle/Validate.py CHANGED
@@ -12,6 +12,7 @@ from collections import defaultdict, OrderedDict
12
12
  from arelle import (FileSource, ModelXbrl, ModelDocument, ModelVersReport, XbrlConst,
13
13
  ValidateXbrl, ValidateVersReport,
14
14
  ValidateInfoset, ViewFileRenderedLayout, UrlUtil)
15
+ from arelle.PythonUtil import isLegacyAbs
15
16
  from arelle.formula import ValidateFormula
16
17
  from arelle.ModelDocument import Type, ModelDocumentReference, load as modelDocumentLoad
17
18
  from arelle.ModelDtsObject import ModelResource
@@ -157,7 +158,7 @@ class Validate:
157
158
  modelXbrl = None
158
159
  try:
159
160
  rssItemUrl = rssItem.zippedUrl
160
- if self.useFileSource.isArchive and (os.path.isabs(rssItemUrl) or not rssItemUrl.endswith(".zip")):
161
+ if self.useFileSource.isArchive and (isLegacyAbs(rssItemUrl) or not rssItemUrl.endswith(".zip")):
161
162
  modelXbrl = ModelXbrl.load(self.modelXbrl.modelManager,
162
163
  openFileSource(rssItemUrl, self.modelXbrl.modelManager.cntlr, reloadCache=reloadCache),
163
164
  _("validating"), rssItem=rssItem)
@@ -337,7 +338,7 @@ class Validate:
337
338
  PackageManager.packageInfo(self.modelXbrl.modelManager.cntlr, readMeFirstUri, reload=True, errors=modelXbrl.errors)
338
339
  else: # not a multi-schemaRef versioning report
339
340
  readMeFirstUriIsEmbeddedZipFile = False
340
- if self.useFileSource.isArchive and not os.path.isabs(readMeFirstUri):
341
+ if self.useFileSource.isArchive and not isLegacyAbs(readMeFirstUri):
341
342
  if isReportPackageExtension(readMeFirstUri):
342
343
  readMeFirstUriIsEmbeddedZipFile = True
343
344
  else:
@@ -360,7 +361,7 @@ class Validate:
360
361
  newSourceFileSource = False
361
362
  if (
362
363
  self.useFileSource
363
- and not os.path.isabs(readMeFirstUri)
364
+ and not isLegacyAbs(readMeFirstUri)
364
365
  and (readMeFirstUriIsEmbeddedZipFile or isReportPackageExtension(readMeFirstUri))
365
366
  ):
366
367
  if self.useFileSource.isArchive:
@@ -9,6 +9,7 @@ from PIL import Image as pilImage
9
9
  import os, io, base64
10
10
  import regex as re
11
11
  import string
12
+ from arelle.PythonUtil import isLegacyAbs
12
13
  from arelle.XbrlConst import ixbrlAll, xhtml
13
14
  from arelle.XmlUtil import setXmlns, xmlstring, xmlDeclarationPattern, XmlDeclarationLocationException
14
15
  from arelle.ModelObject import ModelObject
@@ -1007,7 +1008,7 @@ def referencedFiles(modelXbrl, localFilesOnly=True):
1007
1008
  if (attrTag in ("href", "src") and
1008
1009
  scheme(attrValue) not in ("data", "javascript") and (
1009
1010
  not localFilesOnly or
1010
- (not isHttpUrl(attrValue) and not os.path.isabs(attrValue)))):
1011
+ (not isHttpUrl(attrValue) and not isLegacyAbs(attrValue)))):
1011
1012
  attrValue = attrValue.partition('#')[0].strip() # remove anchor
1012
1013
  if attrValue not in ("", "."): # ignore anchor references to base document
1013
1014
  base = docElt.modelDocument.baseForElement(docElt)
arelle/WebCache.py CHANGED
@@ -21,6 +21,8 @@ from urllib import request as proxyhandlers
21
21
 
22
22
  import certifi
23
23
 
24
+ from arelle.PythonUtil import isLegacyAbs
25
+
24
26
  try:
25
27
  import ssl
26
28
  except ImportError:
@@ -315,7 +317,7 @@ class WebCache:
315
317
  if url:
316
318
  if url.startswith("file://"): url = url[7:]
317
319
  elif url.startswith("file:\\"): url = url[6:]
318
- if url and not (isHttpUrl(url) or os.path.isabs(url)):
320
+ if url and not (isHttpUrl(url) or isLegacyAbs(url)):
319
321
  if base is not None and not isHttpUrl(base) and '%' in url:
320
322
  url = unquote(url)
321
323
  if base:
@@ -332,7 +334,7 @@ class WebCache:
332
334
  elif normedPath.startswith("file:\\"): normedPath = normedPath[6:]
333
335
 
334
336
  # no base, not normalized, must be relative to current working directory
335
- if base is None and not os.path.isabs(url):
337
+ if base is None and not isLegacyAbs(url):
336
338
  normedPath = os.path.abspath(normedPath)
337
339
  else:
338
340
  normedPath = url
arelle/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '2.36.40'
21
- __version_tuple__ = version_tuple = (2, 36, 40)
20
+ __version__ = version = '2.37.0'
21
+ __version_tuple__ = version_tuple = (2, 37, 0)
arelle/oim/Load.py CHANGED
@@ -24,7 +24,7 @@ from arelle.ModelValue import (DATETIME, dateTime, dayTimeDuration, qname,
24
24
  yearMonthDuration)
25
25
  from arelle.PluginManager import pluginClassMethods
26
26
  from arelle.PrototypeInstanceObject import DimValuePrototype
27
- from arelle.PythonUtil import attrdict, strTruncate
27
+ from arelle.PythonUtil import attrdict, isLegacyAbs, strTruncate
28
28
  from arelle.typing import TypeGetText
29
29
  from arelle.ValidateDuplicateFacts import (DuplicateTypeArg,
30
30
  getDuplicateFactSetsWithType)
@@ -1769,7 +1769,7 @@ def _loadFromOIM(cntlr, error, warning, modelXbrl, oimFile, mappedUri):
1769
1769
  # relativize taxonomyRefs to base where feasible
1770
1770
  txBase = os.path.dirname(documentBase or (modelXbrl.entryLoadingUrl if modelXbrl else ""))
1771
1771
  for i, tUrl in enumerate(taxonomyRefs or ()):
1772
- if not UrlUtil.isAbsolute(tUrl) and os.path.isabs(tUrl) and not UrlUtil.isAbsolute(txBase) and os.path.isabs(txBase):
1772
+ if not UrlUtil.isAbsolute(tUrl) and isLegacyAbs(tUrl) and not UrlUtil.isAbsolute(txBase) and isLegacyAbs(txBase):
1773
1773
  taxonomyRefs[i] = os.path.relpath(tUrl, txBase)
1774
1774
  prevErrLen = len(modelXbrl.errors) # track any xbrl validation errors
1775
1775
  xbrliNamespacePrefix = None
@@ -139,7 +139,7 @@ from arelle.ModelObject import ModelObject
139
139
  from arelle.ModelValue import INVALIDixVALUE, qname
140
140
  from arelle.PluginManager import pluginClassMethods
141
141
  from arelle.PrototypeDtsObject import ArcPrototype, LocPrototype
142
- from arelle.PythonUtil import attrdict
142
+ from arelle.PythonUtil import attrdict, isLegacyAbs
143
143
  from arelle.RuntimeOptions import RuntimeOptions
144
144
  from arelle.UrlUtil import isHttpUrl
145
145
  from arelle.ValidateDuplicateFacts import DeduplicationType
@@ -305,7 +305,7 @@ def createTargetInstance(
305
305
  def addLocallyReferencedFile(elt,filingFiles):
306
306
  if elt.tag in ("a", "img"):
307
307
  for attrTag, attrValue in elt.items():
308
- if attrTag in ("href", "src") and not isHttpUrl(attrValue) and not os.path.isabs(attrValue):
308
+ if attrTag in ("href", "src") and not isHttpUrl(attrValue) and not isLegacyAbs(attrValue):
309
309
  attrValue = attrValue.partition('#')[0] # remove anchor
310
310
  if attrValue: # ignore anchor references to base document
311
311
  attrValue = os.path.normpath(attrValue) # change url path separators to host separators
@@ -11,7 +11,7 @@ import regex as re
11
11
  from fnmatch import fnmatch
12
12
  from collections import defaultdict, OrderedDict
13
13
  from arelle import PythonUtil, XbrlConst, ModelDocument, UrlUtil
14
- from arelle.PythonUtil import OrderedDefaultDict, OrderedSet
14
+ from arelle.PythonUtil import OrderedDefaultDict, OrderedSet, isLegacyAbs
15
15
  from arelle.ModelDocument import Type, create as createModelDocument
16
16
  from arelle.ModelValue import qname, QName
17
17
  from arelle.Version import authorLabel, copyrightLabel
@@ -212,7 +212,7 @@ def loadFromExcel(cntlr, modelXbrl, excelFile, mappedUri):
212
212
  if baseDir is None:
213
213
  baseDir = thisDoc.extensionSchemaRelDirname
214
214
  if (baseDir is not None and
215
- not (UrlUtil.isAbsolute(filename) or os.path.isabs(filename))):
215
+ not (UrlUtil.isAbsolute(filename) or isLegacyAbs(filename))):
216
216
  return posixpath.relpath(filename, baseDir)
217
217
  return filename
218
218
 
@@ -279,7 +279,7 @@ def loadFromExcel(cntlr, modelXbrl, excelFile, mappedUri):
279
279
  thisDoc.extensionSchemaPrefix = prefix
280
280
  thisDoc.extensionSchemaFilename = filename
281
281
  thisDoc.extensionSchemaNamespaceURI = namespaceURI
282
- if not UrlUtil.isAbsolute(filename) and not os.path.isabs(filename):
282
+ if not UrlUtil.isAbsolute(filename) and not isLegacyAbs(filename):
283
283
  thisDoc.extensionSchemaRelDirname = posixpath.dirname(filename)
284
284
  else:
285
285
  thisDoc.extensionSchemaRelDirname = None
@@ -1893,7 +1893,7 @@ def saveDts(cntlr, modelXbrl, outputDtsDir):
1893
1893
  import shutil
1894
1894
  excelFileDir = os.path.dirname(modelXbrl.fileSource.url)
1895
1895
  def saveToFile(url):
1896
- if os.path.isabs(url):
1896
+ if isLegacyAbs(url):
1897
1897
  return url
1898
1898
  filepath = os.path.join(outputDtsDir, url)
1899
1899
  os.makedirs(os.path.dirname(filepath), exist_ok=True)
@@ -1908,7 +1908,7 @@ def saveDts(cntlr, modelXbrl, outputDtsDir):
1908
1908
  if refDoc.type == ModelDocument.Type.LINKBASE:
1909
1909
  cntlr.showStatus(_("Saving XBRL DTS: {0}").format(os.path.basename(refDoc.uri)))
1910
1910
  refDoc.save(saveToFile(refDoc.uri), updateFileHistory=False)
1911
- elif not (UrlUtil.isAbsolute(doc.uri) or os.path.isabs(doc.uri) or outputDtsDir == excelFileDir):
1911
+ elif not (UrlUtil.isAbsolute(doc.uri) or isLegacyAbs(doc.uri) or outputDtsDir == excelFileDir):
1912
1912
  srcfile = os.path.join(excelFileDir, doc.uri)
1913
1913
  destfile = saveToFile(doc.uri)
1914
1914
  if os.path.exists(srcfile):
@@ -22,7 +22,7 @@ from arelle.ModelInstanceObject import ModelInlineFootnote
22
22
  from arelle.ModelObject import ModelObject
23
23
  from arelle.ModelRelationshipSet import ModelRelationshipSet
24
24
  from arelle.ModelValue import QName, qname
25
- from arelle.PythonUtil import strTruncate
25
+ from arelle.PythonUtil import isLegacyAbs, strTruncate
26
26
  from arelle.utils.validate.DetectScriptsInXhtml import containsScriptMarkers
27
27
  from arelle.UrlUtil import decodeBase64DataImage, isHttpUrl, scheme
28
28
  from arelle.ValidateFilingText import parseImageDataURL
@@ -365,7 +365,7 @@ def validateXbrlFinally(val: ValidateXbrl, *args: Any, **kwargs: Any) -> None:
365
365
  modelObject=elt, element=eltTag)
366
366
  elif len(modelXbrl.ixdsHtmlElements) > 1:
367
367
  _file = elt.get("href")
368
- if not _file or isHttpUrl(_file) or os.path.isabs(_file):
368
+ if not _file or isHttpUrl(_file) or isLegacyAbs(_file):
369
369
  modelXbrl.warning("ESEF.2.5.4.externalCssReportPackage",
370
370
  _("The CSS file should be physically stored within the report package: %{file}s."),
371
371
  modelObject=elt, file=_file)
@@ -26,7 +26,7 @@ from arelle.ModelValue import QName
26
26
  from arelle.ModelValue import qname
27
27
  from arelle.ModelXbrl import ModelXbrl
28
28
 
29
- from arelle.PythonUtil import normalizeSpace
29
+ from arelle.PythonUtil import isLegacyAbs, normalizeSpace
30
30
  from arelle.PythonUtil import strTruncate
31
31
  from arelle.utils.validate.DetectScriptsInXhtml import containsScriptMarkers
32
32
  from arelle.UrlUtil import isHttpUrl
@@ -378,7 +378,7 @@ def validateXbrlFinally(val: ValidateXbrl, *args: Any, **kwargs: Any) -> None:
378
378
  modelObject=elt, element=eltTag)
379
379
  elif len(modelXbrl.ixdsHtmlElements) > 1:
380
380
  _file = elt.get("href")
381
- if not _file or isHttpUrl(_file) or os.path.isabs(_file):
381
+ if not _file or isHttpUrl(_file) or isLegacyAbs(_file):
382
382
  modelXbrl.warning("ESEF.2.5.4.externalCssReportPackage",
383
383
  _("The CSS file should be physically stored within the report package: %{file}s."),
384
384
  modelObject=elt, file=_file)
@@ -36,7 +36,7 @@ try:
36
36
  mysqlProgrammingError = pymysql.ProgrammingError
37
37
  mysqlInterfaceError = pymysql.InterfaceError
38
38
  mysqlInternalError = pymysql.InternalError
39
- except ImportError:
39
+ except (ImportError, OSError):
40
40
  try :
41
41
  import MySQLdb # LGPL License and used on GAE, Python 2.7 only
42
42
  hasMySql = True
@@ -15,6 +15,8 @@ if TYPE_CHECKING:
15
15
  from optparse import OptionParser
16
16
  from tkinter import Menu
17
17
 
18
+ from bottle import Bottle # type: ignore[import-untyped]
19
+
18
20
  from arelle.Cntlr import Cntlr
19
21
  from arelle.CntlrCmdLine import CntlrCmdLine
20
22
  from arelle.CntlrWinMain import CntlrWinMain
@@ -25,7 +27,6 @@ if TYPE_CHECKING:
25
27
  from arelle.ModelManager import ModelManager
26
28
  from arelle.ModelXbrl import ModelXbrl
27
29
  from arelle.ValidateXbrl import ValidateXbrl
28
- from arelle.webserver.bottle import Bottle
29
30
 
30
31
 
31
32
  class ValidationHook(Enum):
@@ -191,7 +192,7 @@ class PluginHooks(ABC):
191
192
  app.route('/rest/my-run/<file:path>', ("GET", "POST"), my_run)
192
193
  ```
193
194
 
194
- :param app: The [Bottle](#arelle.webserver.bottle.Bottle) server.
195
+ :param app: The Bottle server.
195
196
  :param cntlr: The [controller](#arelle.CntlrCmdLine.CntlrCmdLine) for the server.
196
197
  :param host: The webserver host.
197
198
  :param port: The webserver port.