Repository: pygobject/pygobject-stubs (language: python)

Issue:
Encode version info in the import
require_version doesn't work, we need to switch stubs based on the import name

e.g. `from gi.repository import Gtk_3_0 as Gtk`

There also is `if typing.TYPE_CHECKING:` so we can play with this without having to change pygobject


Discussion / hints:
Other solutions for the version problem i thought of was

Provide some kind of install flag which can be passed to pip or setup.py? --gtkversion=3
and then we install only these stubs.

Python developers probably uses some kind of venv anyway and that would not be a problem to have the stubs installed in a special configuration.

further checking is often done in CI, and there its probably even less of a problem.

I don’t understand how your approach with versioned imports can work.
This would fail because pygobject does not allow such an import or are you saying you would add this to pygobject?

if not supported by pygobject then something like this would still work

```python
import typing

if typing.TYPE_CHECKING:
    from gi.repository import Gtk_3_0 as Gtk
else:
    from gi.repository import Gtk
```

but of course this is not very sexy

if you wonder if this works

```python
import typing

from gi.repository import Gtk
if typing.TYPE_CHECKING:
    from gi.repository import Gtk_3_0 as Gtk
```

no it does not. mypy does not overwrite that first import

Can't we make different packages for different versions. Like PyGobject-stubs-3, PyGobject-stubs-4. It might solve the problem. @lovetox 
no because this is not a Gtk stub package, its a stub package for all libraries where PyGObject provides bindings.

So PyGObject-stubs-3 means nothing.

Of course one could factor out all libraries into different stub packages

pygobject-gtk3-stubs
pygobject-glib-stubs
pygobject-libsoup-stubs

as most developers going to be using only a few of the libraries anyway, and the code paths for the different stubs need to be separated anyway, i see no benefit in having all of them in one package. Except of course there is a big amount of libraries and so a big amount of repositories to maintain.

Maybe a compromise would be to do it only for the libraries where we expect old versions to be used for years, like with gtk.

so only splitting out gtk for now.
19 repositories total. That will be very hard to maintain. We should split out gtk out of it. It will be easier to maintain
And also i think maintaining different package for different versions of gtk would easier than doing all versions in one package
I don't think there can be more than one stub package for another Python package, if I'm reading https://peps.python.org/pep-0561/ correctly.
ah damn, i forgot we import all from the gi namespace, that seems indeed not possible.

then im back to my suggestion with doing install magic with install flags
I dont think we can pass flags to pip during installation @lovetox 
We need to change the way we import namespaces. Instead of gtk namespace there can  be gtk3 and gtk4 namespace. As said by @lazka.  And also before making the stubs the main pygobject package should be worked on. The documentation should be updated to gtk4. I dont think people will start using stubs for gtk4 before learning how to use gtk4.
What lazka proposed is other projects that use the stubs import the stubs in a different way. This would actually force all projects to change all their gtk imports. Further as i said above it does not work without also changing pygobject itself.

As i see it we can pass flags via `--install-option` command when the package gets installed.
This would allow anyone to decide themself what gets installed.

so `pip install pygobject-stubs --install-options="--gtkversion=3"`


Fix patch:
diff --git a/README.md b/README.md
index c3b490b1..386ad75d 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,17 @@
 pip install PyGObject-stubs
 ```
 
+### Installation of Multi Version stubs
+
+Some libraries exist in multiple versions like Gtk3/4. As both libraries are
+currently imported under the namespace `Gtk` only stubs for one can be installed.
+
+You need to decide this at install time with setting the ENV var
+`PYGOBJECT_STUB_CONFIG`.
+
+Example:
+`PYGOBJECT_STUB_CONFIG=Gtk4,Soup3 pip install .`
+
 ## Contributing
 
 [Guide](./CONTRIBUTING.md)
diff --git a/gi-stubs/repository/Gtk.pyi b/gi-stubs/__multi_version_stubs/Gtk3.pyi
similarity index 100%
rename from gi-stubs/repository/Gtk.pyi
rename to gi-stubs/__multi_version_stubs/Gtk3.pyi
diff --git a/gi-stubs/repository/Soup.pyi b/gi-stubs/__multi_version_stubs/Soup2.pyi
similarity index 100%
rename from gi-stubs/repository/Soup.pyi
rename to gi-stubs/__multi_version_stubs/Soup2.pyi
diff --git a/setup.py b/setup.py
index 60684932..5528b712 100644
--- a/setup.py
+++ b/setup.py
@@ -1,3 +1,43 @@
+
+from typing import List
+
+import os
+from pathlib import Path
+
 from setuptools import setup
+from setuptools.command.build_py import build_py
+
+
+def _get_lib_config() -> List[str]:
+    libs = []
+    env_var = os.environ.get('PYGOBJECT_STUB_CONFIG')
+    if env_var is not None:
+        libs = [lib.strip() for lib in env_var.split(',')]
+    return libs
+
+
+class build(build_py):
+
+    def _copy_multi_version_stubs(self) -> None:
+        package_dir = Path(self.build_lib) / 'gi-stubs'
+        src_dir = package_dir / '__multi_version_stubs'
+        dst_dir = package_dir / 'repository'
+
+        for lib in _get_lib_config():
+            lib_wo_version = lib[:-1]
+            src = src_dir / f'{lib}.pyi'
+            dst = dst_dir / f'{lib_wo_version}.pyi'
+            if dst.exists():
+                dst.unlink()
+            self.copy_file(str(src), str(dst))
+
+    def run(self) -> None:
+        build_py.run(self)
+        self._copy_multi_version_stubs()
+
 
-setup()
+setup(
+    cmdclass={
+        'build_py': build,
+    },
+)


Test patch:
diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml
index e4ac99f7..f1ba2a4a 100644
--- a/.github/workflows/python-tests.yml
+++ b/.github/workflows/python-tests.yml
@@ -7,18 +7,18 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Setup Python
-        uses: actions/setup-python@v1
+        uses: actions/setup-python@v4
         with:
-          python-version: 3.7
+          python-version: '3.7'
 
       - name: Checkout
-        uses: actions/checkout@v1
+        uses: actions/checkout@v3
 
       - name: Install Dependencies
         run: |
           pip install -U pip
           sudo apt install libgirepository1.0-dev
-          pip install '.[dev]'
+          PYGOBJECT_STUB_CONFIG=Gtk3 pip install '.[dev]'
 
       - name: Run mypy
         run: mypy examples