[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#481061: python-apt: Rename API methods to conform with PEP 8



On Tue, May 13, 2008 at 11:00:00PM +1000, Ben Finney wrote:
> Package: python-apt
> Version: 0.7.5
> Severity: normal
> 
> The coding style guide for Python 
> <URL:http://www.python.org/dev/peps/pep-0008> is also a convention for 
> code in the Python community.
> 
> Please rename the API methods of python-apt to conform with PEP 8 
> guidelines. E.g.:
> 
> * 'apt.SizeToString' is a function, so should be named 
>   'apt.size_to_string'
> 
> * 'apt.package.Package.markKeep' is a method, so should be named 
>   'apt.package.Package.mark_keep'
> 
> * 'apt.cache.FilteredCache.filterCachePostChange' should be named
>   'apt.cache.FilteredCache.filter_cache_post_change'
> 
> * 'apt.package.Dependency.candidateInstalledSize' is an attribute, so 
>   should be named 'apt.package.Dependency.candidate_installed_size'
> 
> I'm happy to create patches to address this bug if that would be 
> useful.

I am attaching the current state of a apt.deprecation module, which will
be used for this. This can be used for apt.** and aptsources.*, but not
for apt_pkg and apt_inst. As you can see, parts are written by you.

For apt_pkg and apt_inst, I am not sure how to do this. Being written in C++,
it may be to hard to warn about every deprecated method and attribute.

Therefore, I suggest that we just warn on using the top-level functions like
GetCache() and not every where else.

I'm currently working on exporting the classes in apt_pkg, and making them 
instanciable. Therefore, the way to create e.g. a cache object in 0.8.0 (or
whatever it will be named) would be apt_pkg.Cache() instead of
apt_pkg.GetCache().

The attributes available on those classes will be exported as GetSet properties,
just without a setter. The methods will be exported the standard way, too, which
leads to much more readable classes.

Every class,attribute,method,function will be documented with 1 short sentence
in the extension itself, and completely documented in doc/source/apt_pkg.rst
(which has to be created).


-- Example of apt_pkg.Cache, missing most properties.

Help on module apt_pkg:

NAME
    apt_pkg

FILE
    /home/jak/Desktop/python-apt/jak/apt_pkg.so

CLASSES
    __builtin__.object
        Cache
    
    class Cache(__builtin__.object)
     |  The cache class, provide access to the cache.
     |  
     |  Methods defined here:
     |  
     |  __getitem__(...)
     |      x.__getitem__(y) <==> x[y]
     |  
     |  close(...)
     |      Close the cache
     |  
     |  open(...)
     |      Open the cache
     |  
     |  update(...)
     |      Update the cache
     |  
     |  ----------------------------------------------------------------------
     |  Data descriptors defined here:
     |  
     |  packages
     |      Get the packages.


-- 
Julian Andres Klode  - Free Software Developer
   Debian Developer  - Contributing Member of SPI
   Ubuntu Member     - Fellow of FSFE

Website: http://jak-linux.org/   XMPP: juliank@jabber.org
Debian:  http://www.debian.org/  SPI:  http://www.spi-inc.org/
Ubuntu:  http://www.ubuntu.com/  FSFE: http://www.fsfe.org/
# deprecation.py - Module providing classes and functions for deprecation.
# -*- coding: utf-8 -*-
#
#  Copyright (c) 2009 Julian Andres Klode <jak@debian.org>
#  Copyright (c) 2009 Ben Finney <ben+debian@benfinney.id.au>
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License as
#  published by the Free Software Foundation; either version 2 of the
#  License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
#  USA
"""Classes and functions for deprecating features.

My deprecation stuff, use 2to3 if you want to try on Python 3.1
"""
import re
import operator
import warnings

# A compiled regular expression for finding uppercase letters.
_SUB = re.compile('([A-Z])').sub
# A mapping of old-name => new-name
_OVERRIDE = {}

def _convert_name(name):
    """Convert a name from mixedCase to lowercase_with_underscores.

    We also support CamelCase by stripping the first underscore from the
    return value.
    """
    try:
        return _OVERRIDE[name]
    except KeyError:
        ret = _OVERRIDE[name] = _SUB('_\\1', name).lower().lstrip('_')
        return ret
        
class AttributeDeprecatedBy(object):
    """Property acting as a proxy for a new attribute.

    When accessed, the property issues a DeprecationWarning and (on get) calls
    attrgetter() for the attribute 'attribute' on the current object or (on
    set) uses setattr to set the value of the wrapped attribute.
    """

    def __init__(self, attribute):
        """Initialize the property."""
        self.attribute = attribute
        self.__doc__ = 'Deprecated, please use \'%s\' instead' % attribute
        self.getter = operator.attrgetter(attribute)

    def __get__(self, obj, type=None):
        """Issue a  DeprecationWarning and return the requested value."""
        if obj is None:
            return getattr(type, self.attribute, self)
        warnings.warn(self.__doc__, DeprecationWarning, stacklevel=2)
        return self.getter(obj or type)

    def __set__(self, obj, value):
        """Issue a  DeprecationWarning and set the requested value."""
        warnings.warn(self.__doc__, DeprecationWarning, stacklevel=2)
        return setattr(obj, self.attribute, value)

def function_deprecated_by(func, convert_names=True):
    """Return a function that warns it is deprecated by another function.

    Returns a new function that warns it is deprecated by function 'func',
    then acts as a pass-through wrapper for 'func'.

    This function also converts all keyword argument names from mixedCase to
    lowercase_with_underscores, but only if 'convert_names' is True (default).
    """
    warning = 'Deprecated, please use \'%s\' instead' % func.__name__
    
    def deprecated_function(*args, **kwds):
        warnings.warn(warning, DeprecationWarning, stacklevel=2)
        if convert_names:
            for key in kwds.keys():
                kwds[_convert_name(key)] = kwds.pop(key)
        return func(*args, **kwds)
    return deprecated_function

class Alpha(object):

    def __init__(self):
        self.my_greeting = 'Hello'

    def get_cool(self):
        return 'Cool'

    myGreeting = AttributeDeprecatedBy('my_greeting')
    getCool = function_deprecated_by(get_cool)
    getCool1 = function_deprecated_by(get_cool, False)
    getCool2 = AttributeDeprecatedBy('get_cool')





if __name__ == '__main__':
    def bench(stmt, number=10**4):
        t= timeit.Timer(stmt, 'from __main__ import alpha,warnings')
        return "%-30s │ %7d nanoseconds/pass" % (stmt, 10**9 * t.timeit(number)
                                                       / number)
    import timeit

    alpha = Alpha()
    print '─' * 31 + '┐' + '─' * 25
    print bench('alpha.my_greeting')
    print bench('alpha.myGreeting')
    print '─' * 31 + '┘' + '─' * 25
    print bench('alpha.get_cool()')
    print bench('alpha.getCool()')
    print bench('alpha.getCool1()')
    print bench('alpha.getCool2()')
    print '─' * 31 + '┘' + '─' * 25
    print bench('alpha.get_cool')
    print bench('alpha.getCool')
    print bench('alpha.getCool1')
    print bench('alpha.getCool2')
    print '─' * 31 + '┘' + '─' * 25
    print bench('warnings.warn("HELLO")')

    alpha.getCool()

Attachment: signature.asc
Description: Digital signature


Reply to: