jenkins-bot has submitted this change. ( 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1327506?usp=email )

Change subject: families: Add support for all existing Beta Cluster wikis
......................................................................

families: Add support for all existing Beta Cluster wikis

- Add support for all existing Beta Cluster wikis. Beta sites of
  Wikipedia, Wiktionary, Wikibooks, Wikiquote, Wikisource, Wikiversity
  and Wikivoyage get their own beta* family file.
- Add beta wiki support for foundation and incubator families
- Deprecate support for wikisource:beta; betawikisource:en should be
  used instead.
- Update tests
- Update GitHub workflows. This also solves T435023
- Update documentation

Bug: T225892
Bug: T435023
Change-Id: I624cd6785a5d69547e93ae9c4388b00fa6746369
---
M .github/workflows/login_tests-ci.yml
M .github/workflows/oauth_tests-ci.yml
M .github/workflows/pywikibot-ci.yml
R docs/api_ref/families/1_family.rst
A docs/api_ref/families/2_overview.rst
R docs/api_ref/families/3_wikimedia_families.rst
A docs/api_ref/families/4_betawiki_families.rst
A docs/api_ref/families/5_other_families.rst
M docs/api_ref/index.rst
M pywikibot/__init__.py
M pywikibot/families/__init__.py
A pywikibot/families/betawikibooks_family.py
A pywikibot/families/betawikipedia_family.py
A pywikibot/families/betawikiquotes_family.py
A pywikibot/families/betawikisource_family.py
A pywikibot/families/betawikiversity_family.py
A pywikibot/families/betawikivoyage_family.py
A pywikibot/families/betawiktionary_family.py
M pywikibot/families/foundation_family.py
M pywikibot/families/incubator_family.py
M pywikibot/families/wikisource_family.py
M pywikibot/family.py
M tests/family_tests.py
M tests/pagegenerators_tests.py
M tests/site_generators_tests.py
M tests/site_tests.py
26 files changed, 366 insertions(+), 116 deletions(-)

Approvals:
  jenkins-bot: Verified
  Xqt: Looks good to me, approved




diff --git a/.github/workflows/login_tests-ci.yml 
b/.github/workflows/login_tests-ci.yml
index 701b5a1..fc21905 100644
--- a/.github/workflows/login_tests-ci.yml
+++ b/.github/workflows/login_tests-ci.yml
@@ -57,17 +57,13 @@
         site: ['wikipedia:en', 'wikisource:zh', 'wikipedia:test']
         include:
           - python-version: '3.9'
-            site: false
-            family: wpbeta
-            code: en
+            site: betawikipedia:en
             os: ubuntu-22.04
           - python-version: '3.9'
-            site: false
-            family: wpbeta
-            code: zh
+            site: betawikipedia:zh
             os: ubuntu-22.04
           - python-version: '3.10'
-            site: wikisource:beta
+            site: betawikisource:en
           - python-version: '3.9'
             site: wikidata:test
             os: ubuntu-22.04
@@ -107,23 +103,9 @@
         with:
           ssh_user: ${{ secrets.WMCS_USER }}
           ssh_key: ${{ secrets.WMCS_SSH_KEY }}
-      - name: Generate family files
-        env:
-          HTTP_PROXY: socks5h://127.0.0.1:1080
-          HTTPS_PROXY: socks5h://127.0.0.1:1080
-          ALL_PROXY: socks5h://127.0.0.1:1080
-          NO_PROXY: ""
-        run: |
-          if  [ ${{matrix.family || 0}} == wpbeta ]; then
-            python pwb.py generate_family_file 
https://${{matrix.code}}.wikipedia.beta.wmcloud.org/ wpbeta y
-          fi
       - name: Generate user files
         run: |
-          if [ ${{matrix.site}} != false ]; then
-            python -Werror::UserWarning -m pwb generate_user_files 
-site:${{matrix.site}} -user:${{ env.PYWIKIBOT_USERNAME }} -v -debug;
-          else
-            python -Werror::UserWarning -m pwb generate_user_files 
-family:${{matrix.family}} -code:${{matrix.code}} -user:${{ 
env.PYWIKIBOT_USERNAME }} -v -debug;
-          fi
+          python -Werror::UserWarning -m pwb generate_user_files 
-site:${{matrix.site}} -user:${{ env.PYWIKIBOT_USERNAME }} -v -debug;
           echo "usernames['wikipedia']['en'] = '${{ env.PYWIKIBOT_USERNAME 
}}'" >> user-config.py
           echo "usernames['wikisource']['zh'] = '${{ env.PYWIKIBOT_USERNAME 
}}'" >> user-config.py
           echo "usernames['wikipedia']['test'] = '${{ env.PYWIKIBOT_USERNAME 
}}'" >> user-config.py
diff --git a/.github/workflows/oauth_tests-ci.yml 
b/.github/workflows/oauth_tests-ci.yml
index e9bac7a..76671e0 100644
--- a/.github/workflows/oauth_tests-ci.yml
+++ b/.github/workflows/oauth_tests-ci.yml
@@ -40,11 +40,11 @@
         domain: [test.wikipedia.org]
         include:
           - python-version: '3.9'
-            family: wpbeta
+            family: betawikipedia
             code: en
             domain: en.wikipedia.beta.wmcloud.org
           - python-version: '3.9'
-            family: wpbeta
+            family: betawikipedia
             code: zh
             domain: zh.wikipedia.beta.wmcloud.org
     steps:
@@ -90,15 +90,6 @@
         with:
           ssh_user: ${{ secrets.WMCS_USER }}
           ssh_key: ${{ secrets.WMCS_SSH_KEY }}
-      - name: Generate family files
-        if: ${{ matrix.family == 'wpbeta' }}
-        env:
-          HTTP_PROXY: socks5h://127.0.0.1:1080
-          HTTPS_PROXY: socks5h://127.0.0.1:1080
-          ALL_PROXY: socks5h://127.0.0.1:1080
-          NO_PROXY: ""
-        run: |
-          python pwb.py generate_family_file 
https://${{matrix.code}}.wikipedia.beta.wmcloud.org/ wpbeta y
       - name: Generate user files
         run: |
           python -Werror::UserWarning -m pwb generate_user_files  \
diff --git a/.github/workflows/pywikibot-ci.yml 
b/.github/workflows/pywikibot-ci.yml
index 50acb80..9de4418 100644
--- a/.github/workflows/pywikibot-ci.yml
+++ b/.github/workflows/pywikibot-ci.yml
@@ -42,15 +42,11 @@
           - python-version: '3.9'
             site: wikipedia:test
           - python-version: '3.9'
-            site: false
-            family: wpbeta
-            code: en
+            site: betawikipedia:en
           - python-version: '3.9'
-            site: false
-            family: wpbeta
-            code: zh
+            site: betawikipedia:zh
           - python-version: '3.10'
-            site: wikisource:beta
+            site: betawikisource:en
           - python-version: '3.9'
             site: wikidata:test
           - python-version: '3.11'
@@ -108,23 +104,9 @@
         with:
           ssh_user: ${{ secrets.WMCS_USER }}
           ssh_key: ${{ secrets.WMCS_SSH_KEY }}
-      - name: Generate family files
-        env:
-          HTTP_PROXY: socks5h://127.0.0.1:1080
-          HTTPS_PROXY: socks5h://127.0.0.1:1080
-          ALL_PROXY: socks5h://127.0.0.1:1080
-          NO_PROXY: ""
-        run: |
-          if  [ ${{matrix.family || 0}} == wpbeta ]; then
-            python pwb.py generate_family_file 
https://${{matrix.code}}.wikipedia.beta.wmcloud.org/ wpbeta y
-          fi
       - name: Generate user files
         run: |
-          if [ ${{matrix.site}} != false ]; then
-            python -Werror::UserWarning -m pwb generate_user_files 
-site:${{matrix.site}} -user:${{ env.PYWIKIBOT_USERNAME }} -v -debug;
-          else
-            python -Werror::UserWarning -m pwb generate_user_files 
-family:${{matrix.family}} -code:${{matrix.code}} -user:${{ 
env.PYWIKIBOT_USERNAME }} -v -debug;
-          fi
+          python -Werror::UserWarning -m pwb generate_user_files 
-site:${{matrix.site}} -user:${{ env.PYWIKIBOT_USERNAME }} -v -debug;
           echo "usernames['wikipedia']['en'] = '${{ env.PYWIKIBOT_USERNAME 
}}'" >> user-config.py
           echo "usernames['wikisource']['zh'] = '${{ env.PYWIKIBOT_USERNAME 
}}'" >> user-config.py
           echo "usernames['wikipedia']['test'] = '${{ env.PYWIKIBOT_USERNAME 
}}'" >> user-config.py
diff --git a/docs/api_ref/family.rst b/docs/api_ref/families/1_family.rst
similarity index 88%
rename from docs/api_ref/family.rst
rename to docs/api_ref/families/1_family.rst
index 25cb8ea..c9edc68 100644
--- a/docs/api_ref/family.rst
+++ b/docs/api_ref/families/1_family.rst
@@ -1,9 +1,9 @@
-************************************
-:mod:`family` --- MediaWiki families
-************************************
+*************************************
+:mod:`family` --- Base Family classes
+*************************************
 
 .. automodule:: family
-   :synopsis: Objects representing MediaWiki families
+   :synopsis: Objects representing MediaWiki Base Familiy classes
    :exclude-members: Family

    .. autoclass:: Family
diff --git a/docs/api_ref/families/2_overview.rst 
b/docs/api_ref/families/2_overview.rst
new file mode 100644
index 0000000..b5487b7
--- /dev/null
+++ b/docs/api_ref/families/2_overview.rst
@@ -0,0 +1,12 @@
+Families overview
+=================
+
+.. automodule:: families
+   :synopsis: Config files for Wikimedia families
+
+.. toctree::
+   :maxdepth: 1
+
+   3_wikimedia_families
+   4_betawiki_families
+   5_other_families
diff --git a/docs/api_ref/pywikibot.families.rst 
b/docs/api_ref/families/3_wikimedia_families.rst
similarity index 79%
rename from docs/api_ref/pywikibot.families.rst
rename to docs/api_ref/families/3_wikimedia_families.rst
index edf1e40..df7e075 100644
--- a/docs/api_ref/pywikibot.families.rst
+++ b/docs/api_ref/families/3_wikimedia_families.rst
@@ -1,9 +1,12 @@
-***************************************
-:mod:`families` --- Family Config Files
-***************************************
+*************************************************
+:mod:`families` --- Wikimedia Family Config Files
+*************************************************

-.. automodule:: families
-   :synopsis: Families package
+:mod:`families.abstract\_family` --- Abstract Wikipedia
+=======================================================
+
+.. automodule:: families.abstract_family
+   :synopsis: Family module for Abstract Wikipedia

 :mod:`families.commons\_family` --- Commons
 ===========================================
@@ -17,12 +20,6 @@
 .. automodule:: families.foundation_family
    :synopsis: Family module for Foundation Wiki

-:mod:`families.i18n\_family` --- Translate Wiki
-===============================================
-
-.. automodule:: families.i18n_family
-   :synopsis: Family module for Translate Wiki
-
 :mod:`families.incubator\_family` --- Incubator
 ===============================================

@@ -47,12 +44,6 @@
 .. automodule:: families.meta_family
    :synopsis: Family module for Meta Wiki

-:mod:`families.osm\_family` --- OpenStreetMap
-=============================================
-
-.. automodule:: families.osm_family
-   :synopsis: Family module for OpenStreetMap Wiki
-
 :mod:`families.outreach\_family` --- Outreach
 =============================================

@@ -65,12 +56,6 @@
 .. automodule:: families.species_family
    :synopsis: Family module for Wikimedia Species Wiki

-:mod:`families.vikidia\_family` --- Vikidia
-===========================================
-
-.. automodule:: families.vikidia_family
-   :synopsis: Family module for Vikidia Wiki
-
 :mod:`families.wikibooks\_family` --- Wikibooks
 ===============================================

@@ -89,18 +74,6 @@
 .. automodule:: families.wikifunctions_family
    :synopsis: Family module for Wikifunctions

-:mod:`families.abstract\_family` --- Abstract Wikipedia
-=======================================================
-
-.. automodule:: families.abstract_family
-   :synopsis: Family module for Abstract Wikipedia
-
-:mod:`families.wikihow\_family` --- Wikihow
-===========================================
-
-.. automodule:: families.wikihow_family
-   :synopsis: Family module for Wikihow Wiki
-
 :mod:`families.wikimania\_family` --- Wikimania
 ===============================================

@@ -166,9 +139,3 @@

 .. automodule:: families.wiktionary_family
    :synopsis: Family module for Wiktionary
-
-:mod:`families.wowwiki\_family` --- Fandom WOW
-==============================================
-
-.. automodule:: families.wowwiki_family
-   :synopsis: Family module for Fandom WOW Wiki
diff --git a/docs/api_ref/families/4_betawiki_families.rst 
b/docs/api_ref/families/4_betawiki_families.rst
new file mode 100644
index 0000000..f48bc8c
--- /dev/null
+++ b/docs/api_ref/families/4_betawiki_families.rst
@@ -0,0 +1,98 @@
+********************************************
+:mod:`families` --- Beta Family Config Files
+********************************************
+
+Family configuration files for the Wikimedia Beta Cluster hosted at
+``beta.wmcloud.org``.
+
+The Beta Cluster is a testing environment. See the `Beta Meta-Wiki
+<https://meta.wikimedia.beta.wmcloud.org/wiki/Main_Page>`_
+for further information about the Beta Cluster.
+
+The name of a Beta family is formed by prefixing the regular Wikimedia family
+name with ``beta``. For example, the family ``wikipedia`` becomes
+``betawikipedia`` and ``wikisource becomes ``betawikisource``.
+
+A Beta wiki can be selected by specifying the family and language code:
+
+.. code-block:: python
+
+   site = pywikibot.Site('de', 'betawikipedia')
+
+Alternatively, the ``family:code`` notation, as used for the
+:attr:`BaseSite.sitename`, can be used:
+
+.. code-block:: python
+
+   site = pywikibot.Site('betawikipedia:de')
+
+.. note::
+   Not all Wikimedia Beta wikis have a separate Beta family. Some Beta sites
+   are available through their regular family using the ``beta`` code, for
+   example :attr:`commons:beta<families.commons_family.Family.test_codes>`,
+   :attr:`meta:beta<families.meta_family.Family.test_codes>`, and
+   :attr:`wikidata:beta<families.wikidata_family.Family.test_codes>`.
+
+   For projects with a separate Beta family, the Beta family should be used
+   instead of the ``beta`` code of the regular family if they refer to the
+   same URI. For example, use :mod:`betawikisource:en<betawikisource_family>`
+   instead of :attr:`wikisource:beta
+   <families.wikisource_family.Family.test_codes>`.
+
+   Some sites have the same code in the regular and Beta families but refer
+   to different wikis. For example, :attr:`wikipedia:test
+   <families.wikipedia_family.Family.test_codes>` and :mod:`betawikipedia:test
+   <families.betawikipedia_family>` refer to https://test.wikipedia.org and
+   https://test.wikipedia.beta.wmcloud.org, respectively. The same applies to
+   ``wikipedia:test2`` and ``betawikipedia:test2``.
+
+   :mod:`Wikiversity<families.wikiversity_family>` provides different testing
+   environments under the beta code and their Beta family. ``wikiversity:beta``
+   refers to https://beta.wikiversity.org, while :mod:`betawikiversity:en
+   <families.betawikiversity_family>` refers
+   to https://en.wikiversity.beta.wmcloud.org. These are separate wikis.
+
+   Beta :mod:`Wikinews<families.wikinews_familiy>` is not supported because all
+   Wikinews sites are marked as closed since version 11.3. See :phab:`T421796`.
+
+:mod:`families.betawikibooks\_family` --- Beta Wikibooks
+========================================================
+
+.. automodule:: families.betawikibooks_family
+   :synopsis: Family module for Beta Wikibooks
+
+:mod:`families.betawikipedia\_family` --- Beta Wikipedia
+========================================================
+
+.. automodule:: families.betawikipedia_family
+   :synopsis: Family module for Beta Wikipedia
+
+:mod:`families.betawikiquotes\_family` --- Beta Wikiquotes
+==========================================================
+
+.. automodule:: families.betawikiquotes_family
+   :synopsis: Family module for Beta Wikiquotes
+
+:mod:`families.betawikisource\_family` --- Beta Wikisource
+==========================================================
+
+.. automodule:: families.betawikisource_family
+   :synopsis: Family module for Beta Wikisource
+
+:mod:`families.betawikiversity\_family` --- Beta Wikiversity
+============================================================
+
+.. automodule:: families.betawikiversity_family
+   :synopsis: Family module for Beta Wikiversity
+
+:mod:`families.betawikivoyage\_family` --- Beta Wikivoyage
+==========================================================
+
+.. automodule:: families.betawikivoyage_family
+   :synopsis: Family module for Beta Wikivoyage
+
+:mod:`families.betawiktionary\_family` --- Beta Wiktionary
+==========================================================
+
+.. automodule:: families.betawiktionary_family
+   :synopsis: Family module for Beta Wiktionary
diff --git a/docs/api_ref/families/5_other_families.rst 
b/docs/api_ref/families/5_other_families.rst
new file mode 100644
index 0000000..9b44aee
--- /dev/null
+++ b/docs/api_ref/families/5_other_families.rst
@@ -0,0 +1,33 @@
+*********************************************
+:mod:`families` --- Other Family Config Files
+*********************************************
+
+:mod:`families.i18n\_family` --- Translate Wiki
+===============================================
+
+.. automodule:: families.i18n_family
+   :synopsis: Family module for Translate Wiki
+
+:mod:`families.osm\_family` --- OpenStreetMap
+=============================================
+
+.. automodule:: families.osm_family
+   :synopsis: Family module for OpenStreetMap Wiki
+
+:mod:`families.vikidia\_family` --- Vikidia
+===========================================
+
+.. automodule:: families.vikidia_family
+   :synopsis: Family module for Vikidia Wiki
+
+:mod:`families.wikihow\_family` --- Wikihow
+===========================================
+
+.. automodule:: families.wikihow_family
+   :synopsis: Family module for Wikihow Wiki
+
+:mod:`families.wowwiki\_family` --- Fandom WOW
+==============================================
+
+.. automodule:: families.wowwiki_family
+   :synopsis: Family module for Fandom WOW Wiki
diff --git a/docs/api_ref/index.rst b/docs/api_ref/index.rst
index 80a967a..75331d2 100644
--- a/docs/api_ref/index.rst
+++ b/docs/api_ref/index.rst
@@ -31,8 +31,7 @@
    pywikibot.site
    login
    logentries
-   family
-   pywikibot.families
+   families/*
    pywikibot.data
    pywikibot.comms
    exceptions
diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py
index 49c3678..f2e1a52 100644
--- a/pywikibot/__init__.py
+++ b/pywikibot/__init__.py
@@ -64,6 +64,7 @@
 from pywikibot.tools import (
     PYTHON_VERSION,
     deprecated_signature,
+    issue_deprecation_warning,
     normalize_username,
 )
 
@@ -249,6 +250,10 @@
     # config.usernames is initialised with a defaultdict for each family name
     family_name = str(fam)

+    if code == 'beta' and family_name == 'wikisource':
+        issue_deprecation_warning(
+            'wikisource:beta', 'betawikisource:en', since='11.8.0')
+
     code_to_user = {}
     if '*' in _config.usernames:  # T253127: usernames is a defaultdict
         code_to_user = _config.usernames['*'].copy()
diff --git a/pywikibot/families/__init__.py b/pywikibot/families/__init__.py
index 4c22fa8..7621056 100644
--- a/pywikibot/families/__init__.py
+++ b/pywikibot/families/__init__.py
@@ -3,4 +3,9 @@
 #
 # Distributed under the terms of the MIT license.
 #
-"""Families package."""
+"""Families package for families directly supported by Pywikibot.
+
+For other MediaWiki families, use
+:mod:`generate_family_file<pywikibot.scripts.generate_family_file>`
+script or :class:`family.AutoFamily` class.
+"""
diff --git a/pywikibot/families/betawikibooks_family.py 
b/pywikibot/families/betawikibooks_family.py
new file mode 100644
index 0000000..e5dc9da
--- /dev/null
+++ b/pywikibot/families/betawikibooks_family.py
@@ -0,0 +1,18 @@
+#
+# (C) Pywikibot team, 2026
+#
+# Distributed under the terms of the MIT license.
+#
+"""Family module for Beta Wikibooks."""
+from __future__ import annotations
+
+from pywikibot import family
+
+
+class Family(family.BetaSubdomainFamily):
+
+    """Family class for Beta Wikibooks."""
+
+    name = 'betawikibooks'
+
+    test_codes = ['en', 'es', 'he']
diff --git a/pywikibot/families/betawikipedia_family.py 
b/pywikibot/families/betawikipedia_family.py
new file mode 100644
index 0000000..809286b
--- /dev/null
+++ b/pywikibot/families/betawikipedia_family.py
@@ -0,0 +1,24 @@
+#
+# (C) Pywikibot team, 2026
+#
+# Distributed under the terms of the MIT license.
+#
+"""Family module for Beta Wikipedia."""
+from __future__ import annotations
+
+from pywikibot import family
+
+
+class Family(family.BetaSubdomainFamily):
+
+    """Family class for Beta Wikipedia."""
+
+    name = 'betawikipedia'
+
+    closed_wikis = ['aa']
+
+    test_codes = [
+        'ar', 'bn', 'ca', 'crh', 'cs', 'de', 'en', 'eo', 'es', 'fa', 'fr',
+        'he', 'hi', 'ja', 'ko', 'nl', 'ru', 'simple', 'sq', 'sr', 'sv',
+        'test', 'test2', 'uk', 'vi', 'zh'
+    ]
diff --git a/pywikibot/families/betawikiquotes_family.py 
b/pywikibot/families/betawikiquotes_family.py
new file mode 100644
index 0000000..8f1e4c9
--- /dev/null
+++ b/pywikibot/families/betawikiquotes_family.py
@@ -0,0 +1,18 @@
+#
+# (C) Pywikibot team, 2026
+#
+# Distributed under the terms of the MIT license.
+#
+"""Family module for Beta Wikiquotes."""
+from __future__ import annotations
+
+from pywikibot import family
+
+
+class Family(family.BetaSubdomainFamily):
+
+    """Family class for Beta Wikiquotes."""
+
+    name = 'betawikiquotes'
+
+    test_codes = ['en']
diff --git a/pywikibot/families/betawikisource_family.py 
b/pywikibot/families/betawikisource_family.py
new file mode 100644
index 0000000..39ff2f1
--- /dev/null
+++ b/pywikibot/families/betawikisource_family.py
@@ -0,0 +1,23 @@
+#
+# (C) Pywikibot team, 2026
+#
+# Distributed under the terms of the MIT license.
+#
+"""Family module for Beta Wikisource."""
+from __future__ import annotations
+
+from pywikibot import family
+
+
+class Family(family.BetaSubdomainFamily):
+
+    """Family class for Beta Wikisource."""
+
+    name = 'betawikisource'
+
+    test_codes = ['en']
+
+    authornamespaces = {
+        '_default': [0],
+        'beta': [102],
+    }
diff --git a/pywikibot/families/betawikiversity_family.py 
b/pywikibot/families/betawikiversity_family.py
new file mode 100644
index 0000000..2773d9c
--- /dev/null
+++ b/pywikibot/families/betawikiversity_family.py
@@ -0,0 +1,18 @@
+#
+# (C) Pywikibot team, 2026
+#
+# Distributed under the terms of the MIT license.
+#
+"""Family module for Beta Wikiversity."""
+from __future__ import annotations
+
+from pywikibot import family
+
+
+class Family(family.BetaSubdomainFamily):
+
+    """Family class for Beta Wikiversity."""
+
+    name = 'betawikiversity'
+
+    test_codes = ['en']
diff --git a/pywikibot/families/betawikivoyage_family.py 
b/pywikibot/families/betawikivoyage_family.py
new file mode 100644
index 0000000..00667f3
--- /dev/null
+++ b/pywikibot/families/betawikivoyage_family.py
@@ -0,0 +1,18 @@
+#
+# (C) Pywikibot team, 2026
+#
+# Distributed under the terms of the MIT license.
+#
+"""Family module for Beta Wikivoyage."""
+from __future__ import annotations
+
+from pywikibot import family
+
+
+class Family(family.BetaSubdomainFamily):
+
+    """Family class for Beta Wikivoyage."""
+
+    name = 'betawikivoyage'
+
+    test_codes = ['en', 'pl', 'zh']
diff --git a/pywikibot/families/betawiktionary_family.py 
b/pywikibot/families/betawiktionary_family.py
new file mode 100644
index 0000000..7cd369a
--- /dev/null
+++ b/pywikibot/families/betawiktionary_family.py
@@ -0,0 +1,18 @@
+#
+# (C) Pywikibot team, 2026
+#
+# Distributed under the terms of the MIT license.
+#
+"""Family module for Beta Wiktionary."""
+from __future__ import annotations
+
+from pywikibot import family
+
+
+class Family(family.BetaSubdomainFamily):
+
+    """Family class for Beta Wiktionary."""
+
+    name = 'betawiktionary'
+
+    test_codes = ['de', 'en', 'fr', 'he']
diff --git a/pywikibot/families/foundation_family.py 
b/pywikibot/families/foundation_family.py
index 817c25b..516357e 100644
--- a/pywikibot/families/foundation_family.py
+++ b/pywikibot/families/foundation_family.py
@@ -12,14 +12,19 @@
 from pywikibot import family


-class Family(family.WikimediaFamily, family.SingleSiteFamily):
+class Family(family.WikimediaFamily):

     """Family class for Foundation wiki.

-    .. version-added:: 3.0
+    .. version-changed:: 11.8
+       beta site code was added.
     """

     name = 'foundation'
-    domain = 'foundation.wikimedia.org'
+    langs = {
+        'foundation': 'foundation.wikimedia.org',
+        'beta': 'foundation.wikimedia.beta.wmcloud.org',
+    }

+    test_codes = ['beta']
     interwiki_forward = 'wmf'
diff --git a/pywikibot/families/incubator_family.py 
b/pywikibot/families/incubator_family.py
index 4d7c73e..3ac5446 100644
--- a/pywikibot/families/incubator_family.py
+++ b/pywikibot/families/incubator_family.py
@@ -10,10 +10,20 @@


 # The Wikimedia Incubator family
-class Family(family.WikimediaOrgFamily):
+class Family(family.WikimediaFamily):

-    """Family class for Incubator Wiki."""
+    """Family class for Incubator Wiki.
+
+    .. version-changed:: 11.8
+       beta site code was added.
+    """

     name = 'incubator'

+    langs = {
+        'incubator': 'incubator.wikimedia.org',
+        'beta': 'incubator.wikimedia.beta.wmcloud.org',
+    }
+
+    test_codes = ['beta']
     interwiki_forward = 'wikipedia'
diff --git a/pywikibot/families/wikisource_family.py 
b/pywikibot/families/wikisource_family.py
index 87fe192..c488247 100644
--- a/pywikibot/families/wikisource_family.py
+++ b/pywikibot/families/wikisource_family.py
@@ -37,6 +37,8 @@
     }

     # Sites we want to edit but not count as real languages
+    # Note: wikisource:beta is deprecated since 11.8.0 in favour of
+    # betawikisource:en.
     test_codes = ['beta']

     category_redirect_templates = {
diff --git a/pywikibot/family.py b/pywikibot/family.py
index 4e4fa21..0a50fb4 100644
--- a/pywikibot/family.py
+++ b/pywikibot/family.py
@@ -1111,6 +1111,21 @@
     """


+class BetaSubdomainFamily(SubdomainFamily):
+
+    """Family class for Beta projects using subdomains.
+
+    .. version-added:: 11.8
+    """
+
+    codes = set()
+
+    @classproperty
+    def domain(cls) -> str:
+        """Return the parents domain with a subdomain prefix."""
+        return f"{cls.name.removeprefix('beta')}.beta.wmcloud.org"
+
+
 class WikibaseFamily(Family):

     """A base class for a Wikibase Family.
diff --git a/tests/family_tests.py b/tests/family_tests.py
index 805932c..313ccf6 100755
--- a/tests/family_tests.py
+++ b/tests/family_tests.py
@@ -34,13 +34,20 @@
                 self.assertTrue(f.langs)

                 if name == 'wikinews':
-                    self.assertFalse(f.codes)
-                    self.assertTrue(f.closed_wikis)
+                    self.assertIsEmpty(f.codes)
+                    self.assertIsNotEmpty(f.closed_wikis)
                     self.assertTrue(iter(f.closed_wikis))
                     self.assertIsInstance(next(iter(f.closed_wikis)), str)
                     self.assertIsInstance(f.closed_wikis, list)
+                elif name.startswith('beta'):
+                    self.assertIsEmpty(f.codes)
+                    self.assertIsNotEmpty(f.test_codes)
+                    self.assertTrue(iter(f.test_codes))
+                    self.assertIsInstance(next(iter(f.test_codes)), str)
+                    self.assertIsInstance(f.test_codes, list)
+                    self.assertIn('en', f.test_codes)
                 else:
-                    self.assertTrue(f.codes)
+                    self.assertIsNotEmpty(f.codes)
                     self.assertTrue(iter(f.codes))
                     self.assertIsInstance(next(iter(f.codes)), str)

diff --git a/tests/pagegenerators_tests.py b/tests/pagegenerators_tests.py
index 69dba1f..9f25f37 100755
--- a/tests/pagegenerators_tests.py
+++ b/tests/pagegenerators_tests.py
@@ -1274,8 +1274,7 @@

     def test_recentchanges_default(self) -> None:
         """Test recentchanges generator with default namespace setting."""
-        if (self.site.family.name == 'wpbeta'
-                or self.site.sitename == 'wikisource:beta'):
+        if self.site.family.name.startswith('beta'):
             self.skipTest(
                 f'Skipping {self.site} due to too many autoblocked users')
         gf = pagegenerators.GeneratorFactory(site=self.site)
diff --git a/tests/site_generators_tests.py b/tests/site_generators_tests.py
index 190881c..b66c757 100755
--- a/tests/site_generators_tests.py
+++ b/tests/site_generators_tests.py
@@ -1245,7 +1245,7 @@
                 self.skipTest(
                     f'gsrsearch is disabled on site {mysite}:\n{e!r}')
             if (e.code == 'cirrussearch-backend-error'
-                    and mysite.family.name == 'wpbeta'):  # T426529
+                    and mysite.family.name == 'betawikipedia'):  # T426529
                 self.skipTest(
                     f'cirrussearch-backend-error on site {mysite}:\n{e!r}')
             raise
@@ -1268,7 +1268,7 @@
                 self.assertEqual(hit.namespace(), 0)
         except APIError as e:  # pragma: no cover
             if (e.code == 'cirrussearch-backend-error'
-                    and self.site.family.name == 'wpbeta'):  # T426529
+                    and self.site.family.name == 'betawikipedia'):  # T426529
                 self.skipTest(
                     f'cirrussearch-backend-error on site {self.site}:\n{e!r}')
             raise
diff --git a/tests/site_tests.py b/tests/site_tests.py
index e830e33..d199898 100755
--- a/tests/site_tests.py
+++ b/tests/site_tests.py
@@ -77,7 +77,8 @@

         site = (
             self.site
-            if isinstance(self.site.family, pywikibot.family.WikimediaFamily)
+            if not isinstance(self.site.family,
+                              pywikibot.family.BetaSubdomainFamily)
             and self.site.code != 'beta'  # exclude Beta Cluster sites
             else None
         )

--
To view, visit 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1327506?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.wikimedia.org/r/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: I624cd6785a5d69547e93ae9c4388b00fa6746369
Gerrit-Change-Number: 1327506
Gerrit-PatchSet: 8
Gerrit-Owner: Xqt <[email protected]>
Gerrit-Reviewer: GergÅ‘ Tisza <[email protected]>
Gerrit-Reviewer: Xqt <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
Pywikibot-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to