jenkins-bot submitted this change.
[bugfix] Add 'yue' code_aliases to wikipedia_family.py
- call a __post_init__() class method in Family.__new__ class if present
- raise a RuntimeError if the __post_init__() method is not a class method
- update deprecation message when using Family.__init__()
- add a __post_init__() class method to wikipedia_family.py and
wiktionary_family.py to add the 'yue'/'zh-yue' alias to cls.code_aliases
- add __init__() and __post_init__ descriptions to documentation
Bug: T341960
Change-Id: Ie8dbb0b5f3c9a40cd1f3bf61e64f7e8f1bbf1076
---
M docs/api_ref/family.rst
M pywikibot/family.py
M pywikibot/families/wiktionary_family.py
M pywikibot/families/wikipedia_family.py
4 files changed, 97 insertions(+), 4 deletions(-)
diff --git a/docs/api_ref/family.rst b/docs/api_ref/family.rst
index 042b337..3a61f22 100644
--- a/docs/api_ref/family.rst
+++ b/docs/api_ref/family.rst
@@ -4,3 +4,48 @@
.. automodule:: family
:synopsis: Objects representing MediaWiki families
+
+ .. autoclass:: Family
+
+ .. method:: __init__()
+
+ Initializer
+
+ .. deprecated:: 3.0.20180710
+ Use :meth:`__post_init__` instead.
+ .. versionchanged:: 8.3
+ A FutureWarning is printed instead of a ``NotImplementedWarning``.
+ The deprecation may be removed in a future release and a
+ ``RuntimeError`` will be thrown instead.
+
+ .. method:: __post_init__()
+ :classmethod:
+
+ Post-init processing for Family class.
+
+ The allocator will call this class method after the Family class was
+ created and no :meth:`__init__()` method is used and ``__post_init__()``
+ is defined in your Family subclass. This can be used for example to
+ expand Family attribute lists.
+
+ .. warning:: The ``__post_init__()`` classmethod cannot be inherited
+ from a superclass. The current family file class is considered
+ only.
+
+ .. caution:: Never modify the current attributes directly; always use
+ a copy. Otherwise the base class is modified which leads to
+ unwanted side-effects.
+
+ **Example:**
+
+ .. code-block:: Python
+
+ @classmethod
+ def __post_init__(cls):
+ """Add 'yue' code alias."""
+ aliases = cls.code_aliases.copy()
+ aliases['yue'] = 'zh-yue'
+ cls.code_aliases = aliases
+
+ .. versionadded:: 8.3
+
diff --git a/pywikibot/families/wikipedia_family.py b/pywikibot/families/wikipedia_family.py
index a972c83..e7a542c 100644
--- a/pywikibot/families/wikipedia_family.py
+++ b/pywikibot/families/wikipedia_family.py
@@ -216,6 +216,16 @@
'de': ('Archiv',),
}
+ @classmethod
+ def __post_init__(cls):
+ """Add 'yue' code alias due to :phab:`T341960`.
+
+ .. versionadded:: 8.3
+ """
+ aliases = cls.code_aliases.copy()
+ aliases['yue'] = 'zh-yue'
+ cls.code_aliases = aliases
+
def encodings(self, code):
"""Return a list of historical encodings for a specific site."""
# Historic compatibility
diff --git a/pywikibot/families/wiktionary_family.py b/pywikibot/families/wiktionary_family.py
index eb92bc2..5478747 100644
--- a/pywikibot/families/wiktionary_family.py
+++ b/pywikibot/families/wiktionary_family.py
@@ -87,3 +87,13 @@
'ar': ('/شرح', '/doc'),
'sr': ('/док', ),
}
+
+ @classmethod
+ def __post_init__(cls):
+ """Add 'zh-yue' code alias due to :phab:`T341960`.
+
+ .. versionadded:: 8.3
+ """
+ aliases = cls.code_aliases.copy()
+ aliases['zh-yue'] = 'yue'
+ cls.code_aliases = aliases
diff --git a/pywikibot/family.py b/pywikibot/family.py
index 6a1e26e..9660c83 100644
--- a/pywikibot/family.py
+++ b/pywikibot/family.py
@@ -5,6 +5,7 @@
# Distributed under the terms of the MIT license.
#
import collections
+import inspect
import logging
import string
import sys
@@ -13,6 +14,7 @@
import warnings
from importlib import import_module
from itertools import chain
+from textwrap import fill
from os.path import basename, dirname, splitext
from typing import Optional
@@ -55,9 +57,8 @@
"""Allocator."""
# any Family class defined in this file are abstract
if cls in globals().values():
- raise TypeError(
- 'Abstract Family class {} cannot be instantiated; '
- 'subclass it instead'.format(cls.__name__))
+ raise TypeError(f'Abstract Family class {cls.__name__} cannot be'
+ ' instantiated; subclass it instead')
# Override classproperty
cls.instance = super().__new__(cls)
@@ -67,13 +68,23 @@
if '__init__' in cls.__dict__:
# Initializer deprecated. Families should be immutable and any
# instance / class modification should go to allocator (__new__).
- cls.__init__ = deprecated(cls.__init__)
+ cls.__init__ = deprecated(instead='__post_init__() classmethod',
+ since='3.0.20180710')(cls.__init__)
# Invoke initializer immediately and make initializer no-op.
# This is to avoid repeated initializer invocation on repeated
# invocations of the metaclass's __call__.
cls.instance.__init__()
cls.__init__ = lambda self: None # no-op
+ elif '__post_init__' not in cls.__dict__:
+ pass
+ elif inspect.ismethod(cls.__post_init__): # classmethod check
+ cls.__post_init__()
+ else:
+ raise RuntimeError(fill(
+ f'__post_init__() method of {cls.__module__}.{cls.__name__}'
+ ' class or its superclass must be a classmethod. Please check'
+ ' your family file.', width=66))
return cls.instance
To view, visit change 938812. To unsubscribe, or for help writing mail filters, visit settings.