Repository: scrapy/scrapy

Issue:
BaseSettings.__repr__ is too verbose for scrapy shell
Settings object got `__repr__` in https://github.com/scrapy/scrapy/pull/1149, but it looks weird in `scrapy shell`:

> [s] Available Scrapy objects:
[s]   crawler    &lt;scrapy.crawler.Crawler object at 0x10c042fd0>
[s]   item       {}
[s]   request    &lt;GET http://yellowpages.co.th>
[s]   response   &lt;302 http://yellowpages.co.th>
[s]   settings   {'CLOSESPIDER_ITEMCOUNT': &lt;SettingsAttribute value=0 priority=0>, 'RETRY_HTTP_CODES': &lt;SettingsAttribute value=[500, 502, 503, 504, 408] priority=0>, 'HTTPCACHE_DIR': &lt;SettingsAttribute value='httpcache-2' priority=20>, 'MEMUSAGE_REPORT': &lt;SettingsAttribute value=False priority=0>, 'DOWNLOAD_HANDLERS_BASE': &lt;SettingsAttribute value=&lt;BaseSettings {'s3': &lt;SettingsAttribute value='scrapy.core.downloader.handlers.s3.S3DownloadHandler' priority=0>, 'ftp': &lt;SettingsAttribute value='scrapy.core.downloader.handlers.ftp.FTPDownloadHandler' priority=0>, 'http': &lt;SettingsAttribute value='scrapy.core.downloader.handlers.http.HTTPDownloadHandler' priority=0>, 'https': &lt;SettingsAttribute value='scrapy.core.downloader.handlers.http.HTTPDownloadHandler' priority=0>, 'file': &lt;SettingsAttribute value='scrapy.core.downloader.handlers.file.FileDownloadHandler' priority=0>}> priority=0>, 'RETRY_PRIORITY_ADJUST': &lt;SettingsAttribute value=-1 priority=0>, 'MAIL_FROM': &lt;SettingsAttribute value='scrapy@localhost' priority=0>, 'HTTPCACHE_EXPIRATION_SECS': &lt;SettingsAttribute value=86400 priority=20>, 'SPIDER_LOADER_CLASS': &lt;SettingsAttribute value='scrapy.spiderloader.SpiderLoader' priority=0>, 'COMPRESSION_ENABLED': &lt;SettingsAttribute value=True priority=0>, 'DOWNLOAD_TIMEOUT': &lt;SettingsAttribute value=180 priority=0>, 'MAIL_PASS': &lt;SettingsAttribute value=None priority=0>, 'MEMUSAGE_LIMIT_MB': &lt;SettingsAttribute value=0 priority=0>, 'EXTENSIONS': &lt;SettingsAttribute value=&lt;BaseSettings {}> priority=0>, 'DEPTH_PRIORITY': &lt;SettingsAttribute value=0 priority=0>, 'TELNETCONSOLE_HOST': &lt;SettingsAttribute value='127.0.0.1' priority=0>, 'MEMDEBUG_NOTIFY': &lt;SettingsAttribute value=[] priority=0>, 'HTTPPROXY_AUTH_ENCODING': &lt;SettingsAttribute value='latin-1' priority=0>, 'DOWNLOAD_WARNSIZE': &lt;SettingsAttribute value=33554432 priority=0>, 'SPIDER_MODULES': &lt;SettingsAttribute value=['acrawler.spiders'] priority=20>, 'RETRY_TIMES': &lt;SettingsAttribute value=2 priority=0>, 'TELNETCONSOLE_PORT': &lt;SettingsAttribute value=[6023, 6073] priority=0>, 'TELNETCONSOLE_ENABLED': &lt;SettingsAttribute value=False priority=20>, 'DOWNLOADER_MIDDLEWARES': &lt;SettingsAttribute value=&lt;BaseSettings {}> priority=0>, 'HTTPCACHE_DBM_MODULE': &lt;SettingsAttribute value='anydbm' priority=0>, 'ROBOTSTXT_OBEY': &lt;SettingsAttribute value=True priority=20>, 'DEPTH_LIMIT': &lt;SettingsAttribute value=0 priority=0>, 'REACTOR_THREADPOOL_MAXSIZE': &lt;SettingsAttribute value=10 priority=0>, 'FEED_EXPORT_FIELDS': &lt;SettingsAttribute value=None priority=0>, 'CLOSESPIDER_PAGECOUNT': &lt;SettingsAttribute value=0 priority=0>, 'LOG_SHORT_NAMES': &lt;SettingsAttribute value=False priority=0>, 'AUTOTHROTTLE_MAX_DELAY': &lt;SettingsAttribute value=60 priority=20>, 'URLLENGTH_LIMIT': &lt;SettingsAttribute value=2083 priority=0>, 'FEED_EXPORTERS': &lt;SettingsAttribute value=&lt;BaseSettings {}> priority=0>, 'LOG_ENCODING': &lt;SettingsAttribute value='utf-8' priority=0>, 'FEED_EXPORTERS_BASE': &lt;SettingsAttribute value=&lt;BaseSettings {'xml': &lt;SettingsAttribute value='scrapy.exporters.XmlItemExporter' priority=0>, 'jsonlines': &lt;SettingsAttribute value='scrapy.exporters.JsonLinesItemExporter' priority=0>, 'jl': &lt;SettingsAttribute value='scrapy.exporters.JsonLinesItemExporter' priority=0>, 'json': &lt;SettingsAttribute value='scrapy.exporters.JsonItemExporter' priority=0>, 'csv': &lt;SettingsAttribute value='scrapy.exporters.CsvItemExporter' priority=0>, 'pickle': &lt;SettingsAttribute value='scrapy.exporters.PickleItemExporter' priority=0>, 'marshal': &lt;SettingsAttribute value='scrapy.exporters.MarshalItemExporter' priority=0>}> priority=0>, 'FEED_FORMAT': &lt;SettingsAttribute value='jsonlines' priority=0>, 'DOWNLOAD_DELAY': &lt;SettingsAttribute value=0 priority=0>, 'HTTPCACHE_GZIP': &lt;SettingsAttribute value=False priority=0>, 'DOWNLOADER_MIDDLEWARES_BASE': &lt;SettingsAttribute value=&lt;BaseSettings {'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': &lt;SettingsAttribute value=400 priority=0>, 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware': &lt;SettingsAttribute value=550 priority=0>, 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': &lt;SettingsAttribute value=590 priority=0>, 'scrapy.downloadermiddlewares.chunked.ChunkedTransferMiddleware': &lt;SettingsAttribute value=830 priority=0>, 'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware': &lt;SettingsAttribute value=100 priority=0>, 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware': &lt;SettingsAttribute value=350 priority=0>, 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware': &lt;SettingsAttribute value=600 priority=0>, 'scrapy.downloadermiddlewares.ajaxcrawl.AjaxCrawlMiddleware': &lt;SettingsAttribute value=560 priority=0>, 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': &lt;SettingsAttribute value=750 priority=0>, 'scrapy.downloadermiddlewares.httpcache.HttpCacheMiddleware': &lt;SettingsAttribute value=900 priority=0>, 'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware': &lt;SettingsAttribute value=300 priority=0>, 'scrapy.downloadermiddlewares.retry.RetryMiddleware': &lt;SettingsAttribute value=500 priority=0>, 'scrapy.downloadermiddlewares.stats.DownloaderStats': &lt;SettingsAttribute value=850 priority=0>, 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware': &lt;SettingsAttribute value=700 priority=0>, 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware': &lt;SettingsAttribute value=580 priority=0>}> priority=0>, 'DNSCACHE_ENABLED': &lt;SettingsAttribute value=True priority=0>, 'CONCURRENT_REQUESTS_PER_IP': &lt;SettingsAttribute value=0 priority=0>, 'EDITOR': &lt;SettingsAttribute value='nano' priority=0>, 'MAIL_HOST': &lt;SettingsAttribute value='localhost' priority=0>, 'CONCURRENT_REQUESTS': &lt;SettingsAttribute value=100 priority=20>, 'AUTOTHROTTLE_START_DELAY': &lt;SettingsAttribute value=1 priority=20>, 'CLOSESPIDER_ERRORCOUNT': &lt;SettingsAttribute value=0 priority=0>, 'STATS_CLASS': &lt;SettingsAttribute value='scrapy.statscollectors.MemoryStatsCollector' priority=0>, 'FEED_STORAGES_BASE': &lt;SettingsAttribute value=&lt;BaseSettings {'': &lt;SettingsAttribute value='scrapy.extensions.feedexport.FileFeedStorage' priority=0>, 's3': &lt;SettingsAttribute value='scrapy.extensions.feedexport.S3FeedStorage' priority=0>, 'ftp': &lt;SettingsAttribute value='scrapy.extensions.feedexport.FTPFeedStorage' priority=0>, 'file': &lt;SettingsAttribute value='scrapy.extensions.feedexport.FileFeedStorage' priority=0>, 'stdout': &lt;SettingsAttribute value='scrapy.extensions.feedexport.StdoutFeedStorage' priority=0>}> priority=0>, 'REDIRECT_ENABLED': &lt;SettingsAttribute value=True priority=0>, 'AUTOTHROTTLE_ENABLED': &lt;SettingsAttribute value=True priority=20>, 'COMMANDS_MODULE': &lt;SettingsAttribute value='' priority=0>, 'AUTOTHROTTLE_DEBUG': &lt;SettingsAttribute value=False priority=0>, 'NEWSPIDER_MODULE': &lt;SettingsAttribute value='acrawler.spiders' priority=20>, 'LOG_UNSERIALIZABLE_REQUESTS': &lt;SettingsAttribute value=False priority=0>, 'DOWNLOAD_MAXSIZE': &lt;SettingsAttribute value=1073741824 priority=0>, 'MAIL_PORT': &lt;SettingsAttribute value=25 priority=0>, 'REFERER_ENABLED': &lt;SettingsAttribute value=True priority=0>, 'HTTPCACHE_POLICY': &lt;SettingsAttribute value='scrapy.extensions.httpcache.DummyPolicy' priority=0>, 'STATS_DUMP': &lt;SettingsAttribute value=True priority=0>, 'MEMUSAGE_NOTIFY_MAIL': &lt;SettingsAttribute value=[] priority=0>, 'DOWNLOAD_HANDLERS': &lt;SettingsAttribute value=&lt;BaseSettings {}> priority=0>, 'LOG_DATEFORMAT': &lt;SettingsAttribute value='%Y-%m-%d %H:%M:%S' priority=0>, 'LOG_LEVEL': &lt;SettingsAttribute value='DEBUG' priority=0>, 'DOWNLOADER_HTTPCLIENTFACTORY': &lt;SettingsAttribute value='scrapy.core.downloader.webclient.ScrapyHTTPClientFactory' priority=0>, 'REDIRECT_MAX_TIMES': &lt;SettingsAttribute value=20 priority=0>, 'REDIRECT_PRIORITY_ADJUST': &lt;SettingsAttribute value=2 priority=0>, 'DUPEFILTER_CLASS': &lt;SettingsAttribute value='scrapy.dupefilters.BaseDupeFilter' priority=10>, 'RETRY_ENABLED': &lt;SettingsAttribute value=True priority=0>, 'SPIDER_CONTRACTS': &lt;SettingsAttribute value=&lt;BaseSettings {}> priority=0>, 'HTTPCACHE_ENABLED': &lt;SettingsAttribute value=True priority=20>, 'LOG_ENABLED': &lt;SettingsAttribute value=True priority=0>, 'MAIL_USER': &lt;SettingsAttribute value=None priority=0>, 'HTTPCACHE_ALWAYS_STORE': &lt;SettingsAttribute value=False priority=0>, 'LOGSTATS_INTERVAL': &lt;SettingsAttribute value=0 priority=10>, 'DEFAULT_ITEM_CLASS': &lt;SettingsAttribute value='scrapy.item.Item' priority=0>, 'DNS_TIMEOUT': &lt;SettingsAttribute value=60 priority=0>, 'DEPTH_STATS': &lt;SettingsAttribute value=True priority=0>, 'DOWNLOADER_CLIENTCONTEXTFACTORY': &lt;SettingsAttribute value='scrapy.core.downloader.contextfactory.ScrapyClientContextFactory' priority=0>, 'MEMUSAGE_CHECK_INTERVAL_SECONDS': &lt;SettingsAttribute value=60.0 priority=0>, 'EXTENSIONS_BASE': &lt;SettingsAttribute value=&lt;BaseSettings {'scrapy.extensions.corestats.CoreStats': &lt;SettingsAttribute value=0 priority=0>, 'scrapy.extensions.feedexport.FeedExporter': &lt;SettingsAttribute value=0 priority=0>, 'scrapy.extensions.memdebug.MemoryDebugger': &lt;SettingsAttribute value=0 priority=0>, 'scrapy.extensions.memusage.MemoryUsage': &lt;SettingsAttribute value=0 priority=0>, 'scrapy.extensions.logstats.LogStats': &lt;SettingsAttribute value=0 priority=0>, 'scrapy.extensions.telnet.TelnetConsole': &lt;SettingsAttribute value=0 priority=0>, 'scrapy.extensions.closespider.CloseSpider': &lt;SettingsAttribute value=0 priority=0>, 'scrapy.extensions.spiderstate.SpiderState': &lt;SettingsAttribute value=0 priority=0>, 'scrapy.extensions.throttle.AutoThrottle': &lt;SettingsAttribute value=0 priority=0>}> priority=0>, 'FEED_STORAGES': &lt;SettingsAttribute value=&lt;BaseSettings {}> priority=0>, 'BOT_NAME': &lt;SettingsAttribute value='acrawler' priority=20>, 'SPIDER_CONTRACTS_BASE': &lt;SettingsAttribute value=&lt;BaseSettings {'scrapy.contracts.default.ScrapesContract': &lt;SettingsAttribute value=3 priority=0>, 'scrapy.contracts.default.UrlContract': &lt;SettingsAttribute value=1 priority=0>, 'scrapy.contracts.default.ReturnsContract': &lt;SettingsAttribute value=2 priority=0>}> priority=0>, 'METAREFRESH_MAXDELAY': &lt;SettingsAttribute value=100 priority=0>, 'CONCURRENT_REQUESTS_PER_DOMAIN': &lt;SettingsAttribute value=8 priority=0>, 'HTTPCACHE_IGNORE_HTTP_CODES': &lt;SettingsAttribute value=[] priority=0>, 'KEEP_ALIVE': &lt;SettingsAttribute value=True priority=10>, 'ITEM_PROCESSOR': &lt;SettingsAttribute value='scrapy.pipelines.ItemPipelineManager' priority=0>, 'MEMUSAGE_WARNING_MB': &lt;SettingsAttribute value=0 priority=0>, 'FEED_STORE_EMPTY': &lt;SettingsAttribute value=False priority=0>, 'COOKIES_DEBUG': &lt;SettingsAttribute value=False priority=0>, 'FEED_URI': &lt;SettingsAttribute value=None priority=0>, 'SPIDER_MIDDLEWARES': &lt;SettingsAttribute value=&lt;BaseSettings {}> priority=0>, 'DOWNLOADER': &lt;SettingsAttribute value='scrapy.core.downloader.Downloader' priority=0>, 'AUTOTHROTTLE_TARGET_CONCURRENCY': &lt;SettingsAttribute value=1.0 priority=20>, 'USER_AGENT': &lt;SettingsAttribute value='acrawler' priority=20>, 'AJAXCRAWL_ENABLED': &lt;SettingsAttribute value=False priority=0>, 'COOKIES_ENABLED': &lt;SettingsAttribute value=False priority=20>, 'DNSCACHE_SIZE': &lt;SettingsAttribute value=10000 priority=0>, 'LOG_FORMAT': &lt;SettingsAttribute value='%(asctime)s [%(name)s] %(levelname)s: %(message)s' priority=0>, 'ITEM_PIPELINES': &lt;SettingsAttribute value=&lt;BaseSettings {}> priority=0>, 'LOG_FORMATTER': &lt;SettingsAttribute value='scrapy.logformatter.LogFormatter' priority=0>, 'HTTPCACHE_IGNORE_RESPONSE_CACHE_CONTROLS': &lt;SettingsAttribute value=[] priority=0>, 'METAREFRESH_ENABLED': &lt;SettingsAttribute value=True priority=0>, 'HTTPCACHE_IGNORE_MISSING': &lt;SettingsAttribute value=False priority=0>, 'HTTPCACHE_IGNORE_SCHEMES': &lt;SettingsAttribute value=['file'] priority=0>, 'SCHEDULER_MEMORY_QUEUE': &lt;SettingsAttribute value='scrapy.squeues.LifoMemoryQueue' priority=0>, 'SCHEDULER_DISK_QUEUE': &lt;SettingsAttribute value='scrapy.squeues.PickleLifoDiskQueue' priority=0>, 'RANDOMIZE_DOWNLOAD_DELAY': &lt;SettingsAttribute value=True priority=0>, 'SETTINGS_MODULE': &lt;SettingsAttribute value='acrawler.settings' priority=20>, 'TEMPLATES_DIR': &lt;SettingsAttribute value='/Users/kmike/svn/scrapy/scrapy/templates' priority=0>, 'LOG_STDOUT': &lt;SettingsAttribute value=False priority=0>, 'CONCURRENT_ITEMS': &lt;SettingsAttribute value=100 priority=0>, 'DOWNLOADER_STATS': &lt;SettingsAttribute value=True priority=0>, 'LOG_FILE': &lt;SettingsAttribute value=None priority=0>, 'HTTPCACHE_STORAGE': &lt;SettingsAttribute value='scrapy.extensions.httpcache.FilesystemCacheStorage' priority=20>, 'MEMDEBUG_ENABLED': &lt;SettingsAttribute value=False priority=0>, 'FEED_URI_PARAMS': &lt;SettingsAttribute value=None priority=0>, 'DEFAULT_REQUEST_HEADERS': &lt;SettingsAttribute value=&lt;BaseSettings {'Accept-Language': &lt;SettingsAttribute value='en' priority=0>, 'Accept': &lt;SettingsAttribute value='text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' priority=0>}> priority=0>, 'CLOSESPIDER_TIMEOUT': &lt;SettingsAttribute value=0 priority=0>, 'SCHEDULER': &lt;SettingsAttribute value='scrapy.core.scheduler.Scheduler' priority=0>, 'SPIDER_MIDDLEWARES_BASE': &lt;SettingsAttribute value=&lt;BaseSettings {'scrapy.spidermiddlewares.referer.RefererMiddleware': &lt;SettingsAttribute value=700 priority=0>, 'scrapy.spidermiddlewares.httperror.HttpErrorMiddleware': &lt;SettingsAttribute value=50 priority=0>, 'scrapy.spidermiddlewares.depth.DepthMiddleware': &lt;SettingsAttribute value=900 priority=0>, 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware': &lt;SettingsAttribute value=800 priority=0>, 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware': &lt;SettingsAttribute value=500 priority=0>}> priority=0>, 'ITEM_PIPELINES_BASE': &lt;SettingsAttribute value=&lt;BaseSettings {}> priority=0>, 'STATSMAILER_RCPTS': &lt;SettingsAttribute value=[] priority=0>, 'MEMUSAGE_ENABLED': &lt;SettingsAttribute value=False priority=0>}
[s]   spider     &lt;DefaultSpider 'default' at 0x10ebdcf90>
[s] Useful shortcuts:
[s]   shelp()           Shell help (print this help)
[s]   fetch(req_or_url) Fetch request (or URL) and update local objects
[s]   view(response)    View response in a browser

Discussion:

Patch:
diff --git a/scrapy/commands/settings.py b/scrapy/commands/settings.py
index 0e73f4f58..bce4e6086 100644
--- a/scrapy/commands/settings.py
+++ b/scrapy/commands/settings.py
@@ -1,5 +1,8 @@
 from __future__ import print_function
+import json
+
 from scrapy.commands import ScrapyCommand
+from scrapy.settings import BaseSettings
 
 class Command(ScrapyCommand):
 
@@ -28,7 +31,11 @@ class Command(ScrapyCommand):
     def run(self, args, opts):
         settings = self.crawler_process.settings
         if opts.get:
-            print(settings.get(opts.get))
+            s = settings.get(opts.get)
+            if isinstance(s, BaseSettings):
+                print(json.dumps(s.copy_to_dict()))
+            else:
+                print(s)
         elif opts.getbool:
             print(settings.getbool(opts.getbool))
         elif opts.getint:
diff --git a/scrapy/settings/__init__.py b/scrapy/settings/__init__.py
index 342d2585e..7b7808959 100644
--- a/scrapy/settings/__init__.py
+++ b/scrapy/settings/__init__.py
@@ -4,6 +4,7 @@ import copy
 import warnings
 from collections import MutableMapping
 from importlib import import_module
+from pprint import pformat
 
 from scrapy.utils.deprecate import create_deprecated_class
 from scrapy.exceptions import ScrapyDeprecationWarning
@@ -368,11 +369,31 @@ class BaseSettings(MutableMapping):
     def __len__(self):
         return len(self.attributes)
 
-    def __str__(self):
-        return str(self.attributes)
+    def _to_dict(self):
+        return {k: (v._to_dict() if isinstance(v, BaseSettings) else v)
+                for k, v in six.iteritems(self)}
+
+    def copy_to_dict(self):
+        """
+        Make a copy of current settings and convert to a dict.
 
-    def __repr__(self):
-        return "<%s %s>" % (self.__class__.__name__, self.attributes)
+        This method returns a new dict populated with the same values
+        and their priorities as the current settings.
+
+        Modifications to the returned dict won't be reflected on the original
+        settings.
+
+        This method can be useful for example for printing settings
+        in Scrapy shell.
+        """
+        settings = self.copy()
+        return settings._to_dict()
+
+    def _repr_pretty_(self, p, cycle):
+        if cycle:
+            p.text(repr(self))
+        else:
+            p.text(pformat(self.copy_to_dict()))
 
     @property
     def overrides(self):


Test patch:
diff --git a/tests/test_cmdline/__init__.py b/tests/test_cmdline/__init__.py
index c2de4fbc8..7733e7180 100644
--- a/tests/test_cmdline/__init__.py
+++ b/tests/test_cmdline/__init__.py
@@ -68,4 +68,4 @@ class CmdlineTest(unittest.TestCase):
             settingsstr = settingsstr.replace(char, '"')
         settingsdict = json.loads(settingsstr)
         six.assertCountEqual(self, settingsdict.keys(), EXTENSIONS.keys())
-        self.assertIn('value=200', settingsdict[EXT_PATH])
+        self.assertEquals(200, settingsdict[EXT_PATH])
diff --git a/tests/test_settings/__init__.py b/tests/test_settings/__init__.py
index 44b9b6df3..4acf22cba 100644
--- a/tests/test_settings/__init__.py
+++ b/tests/test_settings/__init__.py
@@ -302,6 +302,21 @@ class BaseSettingsTest(unittest.TestCase):
         self.assertListEqual(copy.get('TEST_LIST_OF_LISTS')[0],
                              ['first_one', 'first_two'])
 
+    def test_copy_to_dict(self):
+        s = BaseSettings({'TEST_STRING': 'a string',
+                          'TEST_LIST': [1, 2],
+                          'TEST_BOOLEAN': False,
+                          'TEST_BASE': BaseSettings({1: 1, 2: 2}, 'project'),
+                          'TEST': BaseSettings({1: 10, 3: 30}, 'default'),
+                          'HASNOBASE': BaseSettings({3: 3000}, 'default')})
+        self.assertDictEqual(s.copy_to_dict(),
+                            {'HASNOBASE': {3: 3000},
+                             'TEST': {1: 10, 3: 30},
+                             'TEST_BASE': {1: 1, 2: 2},
+                             'TEST_BOOLEAN': False,
+                             'TEST_LIST': [1, 2],
+                             'TEST_STRING': 'a string'})
+
     def test_freeze(self):
         self.settings.freeze()
         with self.assertRaises(TypeError) as cm:
@@ -343,14 +358,6 @@ class BaseSettingsTest(unittest.TestCase):
             self.assertEqual(self.settings.defaults.get('BAR'), 'foo')
             self.assertIn('BAR', self.settings.defaults)
 
-    def test_repr(self):
-        settings = BaseSettings()
-        self.assertEqual(repr(settings), "<BaseSettings {}>")
-        attr = SettingsAttribute('testval', 15)
-        settings['testkey'] = attr
-        self.assertEqual(repr(settings),
-                         "<BaseSettings {'testkey': %s}>" % repr(attr))
-
 
 class SettingsTest(unittest.TestCase):