Path: csiph.com!usenet.pasdenom.info!gegeweb.org!de-l.enfer-du-nord.net!feeder1.enfer-du-nord.net!feeds.phibee-telecom.net!newsfeed.xs4all.nl!newsfeed5.news.xs4all.nl!newsgate.cistron.nl!newsgate.news.xs4all.nl!194.109.133.85.MISMATCH!newsfeed.xs4all.nl!newsfeed6.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.005 X-Spam-Evidence: '*H*': 0.99; '*S*': 0.00; 'method.': 0.05; 'arguments': 0.07; 'doctest': 0.07; 'python': 0.09; '@property': 0.09; 'command-line': 0.09; 'command.': 0.09; 'derived': 0.09; 'files:': 0.09; 'list...': 0.09; 'subclass': 0.09; 'subclasses': 0.09; 'url:github': 0.09; 'cc:addr:python-list': 0.10; 'def': 0.10; 'instantiate': 0.16; 'oct': 0.16; 'received:192.168.11': 0.16; 'url:py': 0.16; 'wrote:': 0.17; 'module,': 0.17; 'import': 0.21; 'cc:2**0': 0.23; 'this:': 0.23; "i've": 0.23; 'command': 0.24; 'pass': 0.25; 'cc:addr:python.org': 0.25; 'header:In-Reply- To:1': 0.25; 'header:User-Agent:1': 0.26; 'developers': 0.26; 'fit': 0.26; 'skip:@ 10': 0.27; 'interface': 0.27; "doesn't": 0.28; 'skip:( 20': 0.28; '-0700,': 0.29; 'leverage': 0.29; 'yields': 0.29; 'url:mailman': 0.29; 'skip:_ 10': 0.29; 'class': 0.29; "i'm": 0.29; 'classes': 0.30; "skip:' 10": 0.30; 'feedback': 0.30; 'stuff': 0.30; 'implement': 0.32; 'url:python': 0.32; 'running': 0.32; 'url:listinfo': 0.32; 'getting': 0.33; 'skip:s 30': 0.33; 'curious': 0.33; 'skip:d 20': 0.34; 'version': 0.34; 'project': 0.34; 'thanks': 0.34; 'decisions': 0.35; 'generic': 0.35; 'mine': 0.35; 'subject:?': 0.35; 'ability': 0.36; 'but': 0.36; 'url:org': 0.36; '(i.e.': 0.36; 'charset:us-ascii': 0.36; 'subject:: ': 0.38; 'fact': 0.38; 'received:192': 0.39; 'called': 0.39; 'little': 0.39; 'received:192.168': 0.40; 'subject:-': 0.40; 'help': 0.40; 'url:mail': 0.40; 'enable': 0.60; 'your': 0.60; 'skip:a 30': 0.60; 'content-disposition:inline': 0.60; 'skip:u 10': 0.60; 'great': 0.64; 'useful.': 0.65; 'lives': 0.71; 'opinions': 0.72; 'ships': 0.84; 'url:admin': 0.84; 'url:master': 0.84; 'abc': 0.91; 'subject:Are': 0.93; 'anymore,': 0.95; 'incredibly': 0.96; 'instant': 0.98 Date: Fri, 5 Oct 2012 15:58:37 -0400 From: Trent Nelson To: Demian Brecht Subject: Re: Are ABCs an anti-pattern? References: <506AF8C9.8060406@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Disposition: inline In-Reply-To: <506AF8C9.8060406@gmail.com> User-Agent: Mutt/1.5.21 (2010-09-15) Cc: Python X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 111 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1349467129 news.xs4all.nl 6945 [2001:888:2000:d::a6]:39044 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:30832 On Tue, Oct 02, 2012 at 07:23:05AM -0700, Demian Brecht wrote: > I don't use them anymore, but I'm curious about others opinions on this > list... I like them. In particular, I like that I can enumerate all the subclasses that happen to implement the ABC via the metaclass's __subclasses__() method. I also like that I can trust Python not to instantiate a subclass of an ABC unless it meets all the interface criteria I've stipulated. Both of these aspects make ABCs a great fit when your base classes will be subclassed by other users/libraries (i.e. that you have no control over). For example, I use them in a project of mine called Enversion in order to automatically generate command-line scaffolding with as little effort (programming/typing-wise as possible). The ABC stuff lives in 'evn.cli' and provides a set of generic classes for command-line tools. One of the command line tools that ships with Enversion is the 'evnadmin' command. Thanks to all the ABC scaffolding in the 'evn.cli/command' module, all I need to write is the following to get an 'evnadmin' command-line interface: from evn.cli import ( CLI, CommandLine, ) class AdminCommandLine(CommandLine): @property def commands_module(self): return evn.admin.commands class AdminCLI(CLI): @property def program_name(self): return 'evnadmin' @property def commandline_subclasses(self): return AdminCommandLine.__subclasses__() class DoctestCommandLine(AdminCommandLine): _quiet_ = True class DumpDefaultConfigCommandLine(AdminCommandLine): pass class DumpConfigCommandLine(AdminCommandLine): _conf_ = True class ShowConfigFileLoadOrderCommandLine(AdminCommandLine): _conf_ = True class DumpHookCodeCommandLine(AdminCommandLine): _conf_ = True _repo_ = True [snip] Running 'evnadmin' with no arguments yields this: % evnadmin Type 'evnadmin help' for help on a specific subcommand. Available subcommands: analyze create disable-remote-debug (drd) doctest dump-config (dc) dump-default-config (ddc) dump-hook-code (dhc) enable enable-remote-debug (erd) find-merges (fm) fix-hooks (fh) root-info (ri) run-hook (rh) show-config-file-load-order (scflo) show-repo-hook-status (srhs) show-repo-remote-debug-sessions (srrds) show-roots (sr) toggle-remote-debug (trd) version The scaffolding can generate all of that automatically thanks to the ability to enumerate __subclasses__() of a metaclass. The fact that Python will bomb out if a derived class doesn't implement all the required methods/properties is icing on the cake. When you are expecting other developers to leverage your ABCs, getting instant feedback when you forget to implement a required method/property is incredibly useful. It's definitely not a case of battling the design decisions made by the ABC author... Relevant Python files: https://github.com/tpn/enversion/blob/master/evn/cli.py https://github.com/tpn/enversion/blob/master/evn/admin/cli.py Regards, Trent. > Demian Brecht > @demianbrecht > http://demianbrecht.github.com > -- > http://mail.python.org/mailman/listinfo/python-list