Repository: miurahr/aqtinstall
Issue: Failure to decompress Qt 6.4.3 source archives packaged as `*.tar.gz`, not `*.7z`

**Describe the bug**
Today, I noticed that in Qt 6.4.3, the Qt maintainers have started packaging source and doc archives as `.tar.gz` instead of `.7z`. Since `aqtinstall` only knows how to decompress 7z files, it raises `py7zr.exceptions.Bad7zFile` instead of decompressing the archive.

I have not checked exhaustively, but Qt 6.4.2 does not appear to be affected by this. For Qt 6.4.3, both `install-src` and `install-doc` are affected; `install-example` is not.

I do not know the extent of this problem; it is possible that other versions and commands are affected by this as well.

**To Reproduce**
1. install `aqt` using `pip install aqtinstall`
2. run `aqt` with this command: `python -m aqt install-src mac 6.4.3` (or `python -m aqt install-doc mac 6.4.3`)
3. See error: `py7zr.exceptions.Bad7zFile: not a 7z file`

**Expected behavior**
I expected `aqt` to install the source code for Qt 6.4.3.

**`aqt` output**

```
❯ python -m aqt install-src mac 6.4.3
INFO    : aqtinstall(aqt) v3.1.3 on Python 3.11.2 [CPython Clang 14.0.0 (clang-1400.0.29.202)]
WARNING : Specified Qt version "6.4.3" did not exist when this version of aqtinstall was released. This may not install properly, but we will try our best.
INFO    : Downloading qtdoc...
INFO    : Downloading qt5compat...
INFO    : Downloading qtsvg...
INFO    : Downloading qtquick3dphysics...
INFO    : Redirected: qt.mirror.constant.com
INFO    : Redirected: qt.mirror.constant.com
INFO    : Redirected: qt.mirror.constant.com
INFO    : Redirected: qt.mirror.constant.com
INFO    : Downloading qtdatavis3d...
INFO    : Redirected: qt.mirror.constant.com
INFO    : Downloading qtcharts...
INFO    : Downloading qt5...
INFO    : Downloading qtlanguageserver...
INFO    : Redirected: qt.mirror.constant.com
INFO    : Redirected: qt.mirror.constant.com
INFO    : Redirected: qt.mirror.constant.com
INFO    : Downloading qtpositioning...
INFO    : Redirected: qt.mirror.constant.com
INFO    : Downloading qtsensors...
INFO    : Downloading qtmultimedia...
INFO    : Redirected: qt.mirror.constant.com
INFO    : Redirected: qt.mirror.constant.com
INFO    : Downloading qtspeech...
INFO    : Redirected: qt.mirror.constant.com
INFO    : Downloading qtwebengine...
INFO    : Redirected: qt.mirror.constant.com
WARNING : Caught Bad7zFile, terminating installer workers
ERROR   : not a 7z file
Traceback (most recent call last):
  File "/opt/homebrew/lib/python3.11/site-packages/aqt/installer.py", line 177, in run
    args.func(args)
  File "/opt/homebrew/lib/python3.11/site-packages/aqt/installer.py", line 511, in run_install_src
    self._run_src_doc_examples("src", args)
  File "/opt/homebrew/lib/python3.11/site-packages/aqt/installer.py", line 498, in _run_src_doc_examples
    run_installer(srcdocexamples_archives.get_packages(), base_dir, sevenzip, keep, _archive_dest)
  File "/opt/homebrew/lib/python3.11/site-packages/aqt/installer.py", line 1151, in run_installer
    raise e from e
  File "/opt/homebrew/lib/python3.11/site-packages/aqt/installer.py", line 1127, in run_installer
    pool.starmap(installer, tasks)
  File "/opt/homebrew/Cellar/python@3.11/3.11.2/Frameworks/Python.framework/Versions/3.11/lib/python3.11/multiprocessing/pool.py", line 375, in starmap
    return self._map_async(func, iterable, starmapstar, chunksize).get()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.11/3.11.2/Frameworks/Python.framework/Versions/3.11/lib/python3.11/multiprocessing/pool.py", line 774, in get
    raise self._value
py7zr.exceptions.Bad7zFile: not a 7z file
ERROR   : aqtinstall(aqt) v3.1.3 on Python 3.11.2 [CPython Clang 14.0.0 (clang-1400.0.29.202)]
Working dir: `/Users/dave/qt_test`
Arguments: `['/opt/homebrew/lib/python3.11/site-packages/aqt/__main__.py', 'install-src', 'mac', '6.4.3']` Host: `uname_result(system='Darwin', node='Daves-MBP.hsd1.ca.comcast.net', release='22.3.0', version='Darwin Kernel Version 22.3.0: Mon Jan 30 20:38:37 PST 2023; root:xnu-8792.81.3~2/RELEASE_ARM64_T6000', machine='arm64')`
===========================PLEASE FILE A BUG REPORT===========================
You have discovered a bug in aqt.
Please file a bug report at https://github.com/miurahr/aqtinstall/issues
Please remember to include a copy of this program's output in your report.
```

**Desktop (please complete the following information):**
 - OS: mac
 - `aqt` version `INFO    : aqtinstall(aqt) v3.1.3 on Python 3.11.2 [CPython Clang 14.0.0 (clang-1400.0.29.202)]`

**Additional context**
Here's the relevant PackageUpdate from [the Updates.xml file](https://download.qt.io/online/qtsdkrepository/mac_x64/desktop/qt6_643_src_doc_examples/Updates.xml). Please note the `.tar.xz` file extension:
```xml
<PackageUpdate>
 <Name>qt.qt6.643.src</Name>
 <DisplayName>Sources</DisplayName>
 <Description>Qt 6.4.3 Source Components</Description>
 <Version>6.4.3-0-202303121118</Version>
 <ReleaseDate>2023-03-12</ReleaseDate>
 <SortingPriority>100</SortingPriority>
 <DownloadableArchives>
  qtdoc-everywhere-src-6.4.3.tar.xz, qtwayland-everywhere-src-6.4.3.tar.xz, qtbase-everywhere-src-6.4.3.tar.xz, qtsvg-everywhere-src-6.4.3.tar.xz, qtdeclarative-everywhere-src-6.4.3.tar.xz, qttools-everywhere-src-6.4.3.tar.xz, qt5compat-everywhere-src-6.4.3.tar.xz, qtshadertools-everywhere-src-6.4.3.tar.xz, qtquick3d-everywhere-src-6.4.3.tar.xz, qtquick3dphysics-everywhere-src-6.4.3.tar.xz, qtquicktimeline-everywhere-src-6.4.3.tar.xz, qttranslations-everywhere-src-6.4.3.tar.xz, qt5-everywhere-src-6.4.3.tar.xz, qt3d-everywhere-src-6.4.3.tar.xz, qtactiveqt-everywhere-src-6.4.3.tar.xz, qtcharts-everywhere-src-6.4.3.tar.xz, qtcoap-everywhere-src-6.4.3.tar.xz, qtconnectivity-everywhere-src-6.4.3.tar.xz, qtdatavis3d-everywhere-src-6.4.3.tar.xz, qthttpserver-everywhere-src-6.4.3.tar.xz, qtimageformats-everywhere-src-6.4.3.tar.xz, qtlanguageserver-everywhere-src-6.4.3.tar.xz, qtlottie-everywhere-src-6.4.3.tar.xz, qtmqtt-everywhere-src-6.4.3.tar.xz, qtmultimedia-everywhere-src-6.4.3.tar.xz, qtnetworkauth-everywhere-src-6.4.3.tar.xz, qtopcua-everywhere-src-6.4.3.tar.xz, qtpositioning-everywhere-src-6.4.3.tar.xz, qtremoteobjects-everywhere-src-6.4.3.tar.xz, qtscxml-everywhere-src-6.4.3.tar.xz, qtsensors-everywhere-src-6.4.3.tar.xz, qtserialbus-everywhere-src-6.4.3.tar.xz, qtserialport-everywhere-src-6.4.3.tar.xz, qtspeech-everywhere-src-6.4.3.tar.xz, qtvirtualkeyboard-everywhere-src-6.4.3.tar.xz, qtwebchannel-everywhere-src-6.4.3.tar.xz, qtwebengine-everywhere-src-6.4.3.tar.xz, qtwebsockets-everywhere-src-6.4.3.tar.xz, qtwebview-everywhere-src-6.4.3.tar.xz
 </DownloadableArchives>
 <UpdateFile OS="Any" CompressedSize="736456112" UncompressedSize="3552029494"/>
 <SHA1>fad59af06e0bb615e9ff36ca010ae57d3255e1e0</SHA1>
</PackageUpdate>
```


Changed files:
ci/generate_azure_pipelines_matrices.py, tests/test_install.py, aqt/installer.py

diff --git a/aqt/installer.py b/aqt/installer.py
index a27fd2e..f53ee06 100644
--- a/aqt/installer.py
+++ b/aqt/installer.py
@@ -31,6 +31,7 @@ import posixpath
 import signal
 import subprocess
 import sys
+import tarfile
 import time
 from logging import getLogger
 from logging.handlers import QueueHandler
@@ -1221,7 +1222,11 @@ def installer(
         name=f"Downloading {name}",
     )
     gc.collect()
-    if command is None:
+
+    if tarfile.is_tarfile(archive):
+        with tarfile.open(archive) as tar_archive:
+            tar_archive.extractall(path=base_dir)
+    elif command is None:
         with py7zr.SevenZipFile(archive, "r") as szf:
             szf.extractall(path=base_dir)
     else:
diff --git a/ci/generate_azure_pipelines_matrices.py b/ci/generate_azure_pipelines_matrices.py
index 6480402..3ce5779 100644
--- a/ci/generate_azure_pipelines_matrices.py
+++ b/ci/generate_azure_pipelines_matrices.py
@@ -217,10 +217,17 @@ linux_build_jobs.extend(
             subarchives="qtbase qttools qt icu",
         ),
         BuildJob(
+            # Archives stored as .7z
             "install-src", "6.1.0", "linux", "desktop", "gcc_64", "gcc_64", subarchives="qtlottie",
             # Fail the job if this path does not exist:
             check_output_cmd="ls -lh ./6.1.0/Src/qtlottie/",
         ),
+        BuildJob(
+            # Archives stored as .tar.gz
+            "install-src", "6.4.3", "linux", "desktop", "gcc_64", "gcc_64", subarchives="qtlottie",
+            # Fail the job if this path does not exist:
+            check_output_cmd="ls -lh ./6.4.3/Src/qtlottie/",
+        ),
         # Should install the `qtlottie` module, even though the archive `qtlottieanimation` is not specified:
         BuildJob(
             "install-doc", "6.1.0", "linux", "desktop", "gcc_64", "gcc_64",
diff --git a/tests/test_install.py b/tests/test_install.py
index 45e4535..34df83b 100644
--- a/tests/test_install.py
+++ b/tests/test_install.py
@@ -1260,6 +1260,8 @@ def test_install_installer_archive_extraction_err(monkeypatch):
     monkeypatch.setattr("aqt.installer.subprocess.run", mock_extractor_that_fails)
 
     with pytest.raises(ArchiveExtractionError) as err, TemporaryDirectory() as temp_dir:
+        with open(Path(temp_dir) / "archive", "w"):
+            pass
         installer(
             qt_package=QtPackage(
                 "name",