Commits

rblank  committed 45fc11e

0.12.2dev: Refactored all uses of `trac.config._TRUE_VALUES` to use `trac.util.as_bool()` instead, and refactored the latter so that it behaves like `Configuration.getbool()`, except for the following:

* Strings representing non-zero numbers are interpreted as true, whereas before only "1" was. This will break for users who disable options by setting them to "2", but hey...
* The value "aye" was removed from the list of values interpreted as true, as it's not really useful and wasn't documented anyway.

Part of #9721.

  • Participants
  • Parent commits 6e3330b
  • Branches 0.12-stable

Comments (0)

Files changed (8)

File trac/config.py

 
 from trac.admin import IAdminCommandProvider
 from trac.core import *
-from trac.util import AtomicFile
+from trac.util import AtomicFile, as_bool
 from trac.util.compat import any
 from trac.util.text import printout, to_unicode, CRLF
 from trac.util.translation import _, N_
            'ListOption', 'ChoiceOption', 'PathOption', 'ExtensionOption',
            'OrderedExtensionsOption', 'ConfigurationError']
 
+# Retained for backward-compatibility, use as_bool() instead
 _TRUE_VALUES = ('yes', 'true', 'enabled', 'on', 'aye', '1', 1, True)
 
 _use_default = object()
         """Return the value of the specified option as boolean.
         
         This method returns `True` if the option value is one of "yes", "true",
-        "enabled", "on", or "1", ignoring case. Otherwise `False` is returned.
+        "enabled", "on", or non-zero numbers, ignoring case. Otherwise `False`
+        is returned.
 
         Valid default input is a string or a bool. Returns a bool.
         """
-        value = self.get(key, default)
-        if isinstance(value, basestring):
-            value = value.lower() in _TRUE_VALUES
-        return bool(value)
+        return as_bool(self.get(key, default))
 
     def getint(self, key, default=''):
         """Return the value of the specified option as integer.

File trac/tests/config.py

         self.assertEquals('y', config.get('b', u'öption2', 'y'))
 
     def test_read_and_getbool(self):
-        self._write(['[a]', 'option = yes'])
+        self._write(['[a]', 'option = yes', 'option2 = true',
+                     'option3 = eNaBlEd', 'option4 = on',
+                     'option5 = 1', 'option6 = 123', 'option7 = 123.456',
+                     'option8 = disabled', 'option9 = 0', 'option10 = 0.0'])
         config = self._read()
         self.assertEquals(True, config.getbool('a', 'option'))
         self.assertEquals(True, config.getbool('a', 'option', False))
-        self.assertEquals(False, config.getbool('b', 'option2'))
-        self.assertEquals(False, config.getbool('b', 'option2', False))
-        self.assertEquals(False, config.getbool('b', 'option2', 'disabled'))
+        self.assertEquals(True, config.getbool('a', 'option2'))
+        self.assertEquals(True, config.getbool('a', 'option3'))
+        self.assertEquals(True, config.getbool('a', 'option4'))
+        self.assertEquals(True, config.getbool('a', 'option5'))
+        self.assertEquals(True, config.getbool('a', 'option6'))
+        self.assertEquals(True, config.getbool('a', 'option7'))
+        self.assertEquals(False, config.getbool('a', 'option8'))
+        self.assertEquals(False, config.getbool('a', 'option9'))
+        self.assertEquals(False, config.getbool('a', 'option10'))
+        self.assertEquals(False, config.getbool('b', 'option_b'))
+        self.assertEquals(False, config.getbool('b', 'option_b', False))
+        self.assertEquals(False, config.getbool('b', 'option_b', 'disabled'))
 
     def test_read_and_getint(self):
         self._write(['[a]', 'option = 42'])

File trac/ticket/roadmap.py

 
 from trac import __version__
 from trac.attachment import AttachmentModule
-from trac.config import ExtensionOption, _TRUE_VALUES
+from trac.config import ExtensionOption
 from trac.core import *
 from trac.mimeview import Context
 from trac.perm import IPermissionRequestor
 from trac.resource import *
 from trac.search import ISearchSource, search_to_sql, shorten_result
+from trac.util import as_bool
 from trac.util.datefmt import parse_date, utc, to_utimestamp, \
                               get_datetime_format_hint, format_date, \
                               format_datetime, from_utimestamp
             stat.add_interval(group.get('label', group['name']), 
                               group_cnt, query_args,
                               group.get('css_class', group['name']),
-                              group.get('overall_completion') in _TRUE_VALUES)
+                              as_bool(group.get('overall_completion')))
         stat.refresh_calcs()
         return stat
 

File trac/ticket/web_ui.py

 from genshi.builder import tag
 
 from trac.attachment import AttachmentModule
-from trac.config import BoolOption, Option, IntOption, _TRUE_VALUES
+from trac.config import BoolOption, Option, IntOption
 from trac.core import *
 from trac.mimeview.api import Mimeview, IContentConverter, Context
 from trac.resource import Resource, ResourceNotFound, get_resource_url, \
 from trac.ticket.model import Milestone, Ticket, group_milestones
 from trac.ticket.notification import TicketNotifyEmail
 from trac.timeline.api import ITimelineEventProvider
-from trac.util import get_reporter_id
+from trac.util import as_bool, get_reporter_id
 from trac.util.compat import any
 from trac.util.datefmt import format_datetime, from_utimestamp, \
                               to_utimestamp, utc
         preserve_newlines = self.preserve_newlines
         if preserve_newlines == 'default':
             preserve_newlines = self.env.get_version(initial=True) >= 21 # 0.11
-        return preserve_newlines in _TRUE_VALUES
+        return as_bool(preserve_newlines)
     must_preserve_newlines = property(_must_preserve_newlines)
 
     # IContentConverter methods

File trac/util/__init__.py

         value = max
     return value
 
-def as_bool(s):
-    """Convert s to a `bool`."""
+def as_bool(value):
+    """Convert the given value to a `bool`.
+    
+    If `value` is a string, return `True` for any of "yes", "true", "enabled",
+    "on" or non-zero numbers, ignoring case. For non-string arguments, return
+    the argument converted to a `bool`, or `False` if the conversion fails.
+    """
+    if isinstance(value, basestring):
+        try:
+            return bool(float(value))
+        except ValueError:
+            return value.strip().lower() in ('yes', 'true', 'enabled', 'on')
     try:
-        return bool(int(s))
+        return bool(value)
     except (TypeError, ValueError):
-        return bool(s and s.lower() in ('true', 'yes', 'on'))
+        return False
 
 def pathjoin(*args):
     """Strip `/` from the arguments and join them with a single `/`."""

File trac/versioncontrol/admin.py

 from genshi.builder import tag
 
 from trac.admin import IAdminCommandProvider, IAdminPanelProvider
-from trac.config import _TRUE_VALUES, ListOption
+from trac.config import ListOption
 from trac.core import *
 from trac.perm import IPermissionRequestor
-from trac.util import is_path_below
+from trac.util import as_bool, is_path_below
 from trac.util.compat import any
 from trac.util.text import breakable_path, normalize_whitespace, print_table, \
                            printout
         info['name'] = reponame
         if info.get('dir') is not None:
             info['prettydir'] = breakable_path(info['dir']) or ''
-        info['hidden'] = info.get('hidden') in _TRUE_VALUES
+        info['hidden'] = as_bool(info.get('hidden'))
         info['editable'] = editable
         if not info.get('alias'):
             try:

File trac/versioncontrol/web_ui/browser.py

 
 from genshi.builder import tag
 
-from trac.config import ListOption, BoolOption, Option, _TRUE_VALUES
+from trac.config import ListOption, BoolOption, Option
 from trac.core import *
 from trac.mimeview.api import Mimeview, is_binary, \
                               IHTMLPreviewAnnotator, Context
         # Repository index
         show_index = not reponame and path == '/'
         if show_index:
-            if repos and (all_repositories[''].get('hidden') in _TRUE_VALUES
+            if repos and (as_bool(all_repositories[''].get('hidden'))
                           or not repos.can_view(req.perm)):
                 repos = None
 
         rm = RepositoryManager(self.env)
         repositories = []
         for reponame, repoinfo in all_repositories.iteritems():
-            if not reponame or repoinfo.get('hidden') in _TRUE_VALUES:
+            if not reponame or as_bool(repoinfo.get('hidden')):
                 continue
             try:
                 repos = rm.get_repository(reponame)
                      for reponame in all_repos]
         all_repos = sorted(((reponame, repos) for reponame, repos in all_repos
                             if repos
-                            and repos.params.get('hidden') not in _TRUE_VALUES
+                            and as_bool(repos.params.get('hidden'))
                             and repos.can_view(formatter.perm)),
                            reverse=desc)
 

File trac/versioncontrol/web_ui/changeset.py

 
 from genshi.builder import tag
 
-from trac.config import Option, BoolOption, IntOption, _TRUE_VALUES
+from trac.config import Option, BoolOption, IntOption
 from trac.core import *
 from trac.mimeview import Context, Mimeview
 from trac.perm import IPermissionRequestor
 from trac.resource import Resource, ResourceNotFound
 from trac.search import ISearchSource, search_to_sql, shorten_result
 from trac.timeline.api import ITimelineEventProvider
-from trac.util import content_disposition, embedded_numbers, pathjoin
+from trac.util import as_bool, content_disposition, embedded_numbers, pathjoin
 from trac.util.compat import any
 from trac.util.datefmt import from_utimestamp, pretty_timedelta
 from trac.util.text import exception_to_unicode, to_unicode, \
                     ('repo-' + repos.reponame,
                      u"\xa0\xa0-\xa0" + (repos.reponame or _('(default)')))
                     for repos in repositories
-                    if repos.params.get('hidden') not in _TRUE_VALUES
+                    if as_bool(repos.params.get('hidden'))
                     and repos.can_view(req.perm)]
                 filters.sort()
                 add_script(req, 'common/js/timeline_multirepos.js')