Changeset 12721


Ignore:
Timestamp:
Mar 14, 2013, 8:55:12 PM (11 years ago)
Author:
Steffen Hoffmann
Message:

AccountManagerPlugin: Change class doc-string extraction for i18n to actually work.

This especially reverts and reworks parts of [12589] and [12663].
The exploration after cboos's hint in t:#11088 made me turn round and use an
approach closely resembling what already had been done to translate docs for
Trac core WikiMacros, although I changed it to fit for Trac 0.12 as well.

Trac core functions are used by default, but the configuration is tweaked
intentionally to not create catalogs in the '*-js' and 'tracini' domain.
So everything is still collected in 'messages', even if three compiler runs
on the same set of catalogs and generating unneeded message javascripts look
a bit awkward.

Because compatibility code predominated in acct_mgr.util it was about time
to re-arrange and form a dedicated acct_mgr.compat module.

Location:
accountmanagerplugin/trunk
Files:
2 added
10 edited
1 moved

Legend:

Unmodified
Added
Removed
  • accountmanagerplugin/trunk/acct_mgr/admin.py

    r12706 r12721  
    3030from acct_mgr.api import IUserIdChanger
    3131from acct_mgr.api import _, N_, dgettext, gettext, ngettext, tag_
     32from acct_mgr.compat import as_int, is_enabled, exception_to_unicode
     33from acct_mgr.compat import get_pretty_dateinfo
    3234from acct_mgr.guard import AccountGuard
    3335from acct_mgr.model import change_uid, del_user_attribute, email_verified
     
    3638from acct_mgr.register import RegistrationModule
    3739from acct_mgr.web_ui import AccountModule, LoginModule
    38 from acct_mgr.util import as_int, is_enabled, exception_to_unicode
    39 from acct_mgr.util import get_pretty_dateinfo, pretty_precise_timedelta
     40from acct_mgr.util import pretty_precise_timedelta
    4041
    4142
     
    696697            # acct_mgr.register.GenericRegistrationInspector.
    697698            try:
    698                 doc = gettext(check.doc)
     699                if check._description:
     700                    doc = gettext(check._description)
    699701            except AttributeError:
    700702                doc = check.__class__.__doc__
     
    819821        data.update(dict(roundup=roundup, roundup_defaults=roundup_defaults))
    820822
    821         add_script(req, 'acct_mgr/acctmgr_admin.js')
     823        add_script(req, 'acct_mgr/js/acctmgr_admin.js')
    822824        add_stylesheet(req, 'acct_mgr/acctmgr.css')
    823825        add_stylesheet(req, 'common/css/report.css')
  • accountmanagerplugin/trunk/acct_mgr/api.py

    r12706 r12721  
    4848                pass
    4949        return string
     50
     51from acct_mgr.compat import cleandoc
     52cleandoc_ = cleandoc
    5053
    5154
  • accountmanagerplugin/trunk/acct_mgr/macros.py

    r11930 r12721  
    2020from acct_mgr.admin import fetch_user_data
    2121from acct_mgr.api import AccountManager, CommonTemplateProvider, _
     22from acct_mgr.compat import get_pretty_dateinfo
    2223from acct_mgr.guard import AccountGuard
    23 from acct_mgr.util import get_pretty_dateinfo
    2424
    2525
  • accountmanagerplugin/trunk/acct_mgr/model.py

    r12706 r12721  
    1616
    1717from acct_mgr.api import GenericUserIdChanger
     18from acct_mgr.compat import as_int, exception_to_unicode
    1819from acct_mgr.hashlib_compat import md5
    19 from acct_mgr.util import as_int, exception_to_unicode
    2020
    2121
  • accountmanagerplugin/trunk/acct_mgr/register.py

    r12689 r12721  
    2727from acct_mgr.api import AccountManager, CommonTemplateProvider
    2828from acct_mgr.api import IAccountRegistrationInspector
    29 from acct_mgr.api import _, N_, dgettext, gettext, tag_
     29from acct_mgr.api import _, N_, cleandoc_, dgettext, gettext, tag_
     30from acct_mgr.compat import is_enabled
    3031from acct_mgr.model import email_associated, get_user_attribute
    3132from acct_mgr.model import set_user_attribute
    32 from acct_mgr.util import containsAny, is_enabled
     33from acct_mgr.util import containsAny
    3334
    3435
     
    5253class GenericRegistrationInspector(Component):
    5354    """Generic check class, great for creating simple checks quickly."""
     55    _description = ''
    5456
    5557    implements(IAccountRegistrationInspector)
    5658
    5759    abstract = True
    58 
    59     @property
    60     def doc(self):
    61         return N_(self.__class__.__doc__)
    6260
    6361    def render_registration_fields(self, req, data):
     
    8583
    8684class BasicCheck(GenericRegistrationInspector):
     85    _description = cleandoc_(
    8786    """A collection of basic checks.
    8887
    89 This includes checking for
    90  * emptiness (no user input for username and/or password)
    91  * some blacklisted username characters
    92  * upper-cased usernames (reserved for Trac permission actions)
    93  * some reserved usernames
    94  * a username duplicate in configured password stores
    95 
    96 ''This check is bypassed for requests regarding user's own preferences.''
    97 """
     88    This includes checking for
     89     * emptiness (no user input for username and/or password)
     90     * some blacklisted username characters
     91     * upper-cased usernames (reserved for Trac permission actions)
     92     * some reserved usernames
     93     * a username duplicate in configured password stores
     94
     95    ''This check is bypassed for requests regarding user's own preferences.''
     96    """)
    9897
    9998    def validate_registration(self, req):
     
    162161
    163162class BotTrapCheck(GenericRegistrationInspector):
     163    _description = cleandoc_(
    164164    """A collection of simple bot checks.
    165165
    166 ''This check is bypassed for requests by an authenticated user.''
    167 """
     166    ''This check is bypassed for requests by an authenticated user.''
     167    """)
    168168
    169169    reg_basic_token = Option('account-manager', 'register_basic_token', '',
     
    212212
    213213class EmailCheck(GenericRegistrationInspector):
     214    _description = cleandoc_(
    214215    """A collection of checks for email addresses.
    215216
    216 ''This check is bypassed, if account verification is disabled.''
    217 """
     217    ''This check is bypassed, if account verification is disabled.''
     218    """)
    218219
    219220    def render_registration_fields(self, req, data):
     
    273274
    274275class RegExpCheck(GenericRegistrationInspector):
     276    _description = cleandoc_(
    275277    """A collection of checks based on regular expressions.
    276278
    277 ''It depends on !EmailCheck being enabled too for using it's input field.
    278 Likewise email checking is bypassed, if account verification is disabled.''
    279 """
     279    ''It depends on !EmailCheck being enabled too for using it's input field.
     280    Likewise email checking is bypassed, if account verification is disabled.''
     281    """)
    280282
    281283    username_regexp = Option('account-manager', 'username_regexp',
     
    312314
    313315class UsernamePermCheck(GenericRegistrationInspector):
     316    _description = cleandoc_(
    314317    """Check for usernames referenced in the permission system.
    315318
    316 ''This check is bypassed for requests by an authenticated user.''
    317 """
     319    ''This check is bypassed for requests by an authenticated user.''
     320    """)
    318321
    319322    def validate_registration(self, req):
  • accountmanagerplugin/trunk/acct_mgr/tests/admin.py

    r12663 r12721  
    3939
    4040class DummyCheck(GenericRegistrationInspector):
    41     @property
    42     def doc(self):
    43         return "A dummy check for unit-testing the interface."
     41    _description = \
     42    """A dummy check for unit-testing the interface."""
    4443
    4544    def validate_registration(self, req):
  • accountmanagerplugin/trunk/acct_mgr/util.py

    r12615 r12721  
    1414import sys
    1515
    16 from genshi.builder import tag
    17 
    1816from trac.config import Option
    1917from trac.util.datefmt import format_datetime, pretty_timedelta
    2018from trac.util.datefmt import to_datetime, utc
    21 from trac.util.text import to_unicode
    22 from trac.web.chrome import Chrome
    2319
    2420from acct_mgr.api import _, ngettext
     21
     22
     23class EnvRelativePathOption(Option):
     24
     25    def __get__(self, instance, owner):
     26        if instance is None:
     27            return self
     28        path = super(EnvRelativePathOption, self).__get__(instance, owner)
     29        if not path:
     30            return path
     31        return os.path.normpath(os.path.join(instance.env.path, path))
    2532
    2633
     
    6067
    6168
    62 class EnvRelativePathOption(Option):
    63 
    64     def __get__(self, instance, owner):
    65         if instance is None:
    66             return self
    67         path = super(EnvRelativePathOption, self).__get__(instance, owner)
    68         if not path:
    69             return path
    70         return os.path.normpath(os.path.join(instance.env.path, path))
    71 
    72 
    73 try:
    74     from trac.util import as_int
    75 # Provide the function for compatibility (available since Trac 0.12).
    76 except ImportError:
    77     def as_int(s, default, min=None, max=None):
    78         """Convert s to an int and limit it to the given range, or
    79         return default if unsuccessful (copied verbatim from Trac0.12dev).
    80         """
    81         try:
    82             value = int(s)
    83         except (TypeError, ValueError):
    84             return default
    85         if min is not None and value < min:
    86             value = min
    87         if max is not None and value > max:
    88             value = max
    89         return value
    90 
    9169# taken from a comment of Horst Hansen
    9270# at http://code.activestate.com/recipes/65441
     
    10381        return func(self, *args, **kwds)
    10482    return wrap
    105 
    106 try:
    107     from trac.util.text import exception_to_unicode
    108 # Provide the function for compatibility (available since Trac 0.11.3).
    109 except:
    110     def exception_to_unicode(e, traceback=False):
    111         """Convert an `Exception` to an `unicode` object.
    112 
    113         In addition to `to_unicode`, this representation of the exception
    114         also contains the class name and optionally the traceback.
    115         This replicates the Trac core function for backwards-compatibility.
    116         """
    117         message = '%s: %s' % (e.__class__.__name__, to_unicode(e))
    118         if traceback:
    119             from trac.util import get_last_traceback
    120             traceback_only = get_last_traceback().split('\n')[:-2]
    121             message = '\n%s\n%s' % (to_unicode('\n'.join(traceback_only)),
    122                                     message)
    123         return message
    124 
    125 # Compatibility code for `pretty_dateinfo` from template data dict
    126 # (available since Trac 1.0)
    127 def get_pretty_dateinfo(env, req):
    128     """Return the function defined in trac.web.chrome.Chrome.populate_data .
    129 
    130     For Trac 0.11 and 0.12 it still provides a slightly simplified version.
    131     """
    132     # Function is not a class attribute, must be extracted from data dict.
    133     fn = Chrome(env).populate_data(req, {}).get('pretty_dateinfo')
    134     if not fn:
    135         def _pretty_dateinfo(date, format=None, dateonly=False):
    136             absolute = format_datetime(date, tzinfo=req.tz)
    137             relative = pretty_timedelta(date)
    138             if format == 'absolute':
    139                 label = absolute
    140                 # TRANSLATOR: Sync with same msgid in Trac 0.13, please.
    141                 title = _("%(relativetime)s ago", relativetime=relative)
    142             else:
    143                 if dateonly:
    144                     label = relative
    145                 else:
    146                     label = _("%(relativetime)s ago", relativetime=relative)
    147                 title = absolute
    148             return tag.span(label, title=title)
    149     return fn and fn or _pretty_dateinfo
    150 
    151 # Compatibility code for `ComponentManager.is_enabled`
    152 # (available since Trac 0.12)
    153 def is_enabled(env, cls):
    154     """Return whether the given component class is enabled.
    155 
    156     For Trac 0.11 the missing algorithm is included as fallback.
    157     """
    158     try:
    159         return env.is_enabled(cls)
    160     except AttributeError:
    161         if cls not in env.enabled:
    162             env.enabled[cls] = env.is_component_enabled(cls)
    163         return env.enabled[cls]
    16483
    16584def pretty_precise_timedelta(time1, time2=None, resolution=None, diff=0):
  • accountmanagerplugin/trunk/acct_mgr/web_ui.py

    r12672 r12721  
    3333from acct_mgr.api import AccountManager, CommonTemplateProvider
    3434from acct_mgr.api import _, dgettext, ngettext, tag_
     35from acct_mgr.compat import is_enabled
    3536from acct_mgr.db import SessionStore
    3637from acct_mgr.guard import AccountGuard
    3738from acct_mgr.model import set_user_attribute, user_known
    3839from acct_mgr.register import EmailVerificationModule, RegistrationModule
    39 from acct_mgr.util import if_enabled, is_enabled
     40from acct_mgr.util import if_enabled
    4041
    4142
  • accountmanagerplugin/trunk/setup.cfg

    r9403 r12721  
    77msgid_bugs_address = hoff.st@shaas.net
    88output_file = acct_mgr/locale/messages.pot
    9 keywords = _ ngettext:1,2 N_ tag_
     9keywords = _ ngettext:1,2 N_ tag_  cleandoc_
    1010width = 72
    1111
     
    2323output_dir = acct_mgr/locale
    2424domain = acct_mgr
     25
     26[compile_catalog_js]
     27directory = acct_mgr/locale
     28domain = acct_mgr
     29
     30[generate_messages_js]
     31domain = acct_mgr
     32input_dir = acct_mgr/locale
     33output_dir = acct_mgr/htdocs
     34
     35[compile_catalog_tracini]
     36directory = acct_mgr/locale
     37domain = acct_mgr
  • accountmanagerplugin/trunk/setup.py

    r12658 r12721  
    1010extra = {}
    1111
     12has_trac_extract_python = False
    1213try:
    13     from trac.util.dist  import  get_l10n_cmdclass
    14     cmdclass = get_l10n_cmdclass()
     14    from trac.util.dist import get_l10n_cmdclass
     15    try:
     16        from trac.dist import get_l10n_trac_cmdclass
     17        cmdclass = get_l10n_trac_cmdclass()
     18        has_trac_extract_python = True
     19    except ImportError:
     20        # Trac < 1.0, using other compatibility code here.
     21        cmdclass = get_l10n_cmdclass()
    1522    if cmdclass:
    1623        extra['cmdclass'] = cmdclass
    1724        extractors = [
    18             ('**.py',                'python', None),
    1925            ('**/templates/**.html', 'genshi', None),
    2026        ]
     27        if has_trac_extract_python:
     28            extractors.append(
     29                ('**.py', 'trac.dist:extract_python', None))
     30        else:
     31            extractors.append(
     32                ('**.py', 'acct_mgr.compat:extract_python', None))
    2133        extra['message_extractors'] = {
    2234            'acct_mgr': extractors,
    2335        }
    24 # i18n is implemented to be optional here
     36# Trac < 0.12, i18n is implemented to be optional here.
    2537except ImportError:
    2638    pass
     
    4254    package_data={
    4355        'acct_mgr': [
    44             'htdocs/*', 'locale/*/LC_MESSAGES/*.mo', 'locale/.placeholder',
     56            'htdocs/*.css', 'htdocs/js/*', 'htdocs/*.png',
     57            'locale/*/LC_MESSAGES/*.mo', 'locale/.placeholder',
    4558            'templates/*.html', 'templates/*.txt'
    4659        ]
Note: See TracChangeset for help on using the changeset viewer.