summaryrefslogtreecommitdiffstats
path: root/doc/development/compat.txt
blob: 14522b6b3818df71b815c6681fdc78d4d763b527 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
.. -*- mode: rst -*-

.. _development-compat:

====================
Python Compatibility
====================

Bcfg2 maintains compatibility with a wide range of Python versions --
currently 2.4 through 3.2  This requires some (often significant)
compatibility interfaces.  This page documents the compatibility
library, ``Bcfg2.Compat``, and its contents.

Note that, due to limitations in Sphinx (the Bcfg2 documentation
tool), this documentation is *not* automatically generated.
``Compat.py`` should always be considered the authoritative source.

There are several basic types of symbols found in ``Bcfg2.Compat``:

* Symbols whose names have changed, e.g., ``MutableMapping``.
* Symbols whose modules have changed names, e.g., ``urljoin``/``urlparse``
* Symbols that have been added or removed, e.g., ``any``/``all``, ``reduce``,
  ``walk_packages``
* Symbols that need some significant workaround to function
  identically in all versions, e.g., ``b64encode``/``b64decode``.
* Helper functions and classes for compatibility, e.g., ``CmpMixin``.

Using ``Bcfg2.Compat``
======================

To use the compatibility libraries, simply import them as such:

.. code-block:: python

    from Bcfg2.Compat import StringIO, all

The individual symbol import is preferred over just importing
``Bcfg2.Compat`` as a whole, since in the future we will be able to
remove some items from the library and this makes that process
easier.  A wildcard import is definitely discouraged.

Bcfg2.Compat symbols
====================

``Bcfg2.Compat`` defines the following symbols:

Py3K compatibility imports
--------------------------

The following symbols are imported to provide compatibility with
Python 3.  In cases where the newer symbols has also been backported
to Python 2, the older symbol will be used unless otherwise noted.
This is to ensure that functions or modules with radically different
behavior (e.g., :func:`input`) do not cause unexpected side-effects.

+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| Name                            | Python 2                                         | Python 3                                                |
+=================================+==================================================+=========================================================+
| urljoin                         | :func:`urlparse.urljoin`                         | :func:`urllib.parse.urljoin`                            |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| urlparse                        | :func:`urlparse.urlparse`                        | :func:`urllib.parse.urlparse`                           |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| urlretrieve                     | :func:`urllib.urlretrieve`                       | :func:`urllib.request.urlretrieve`                      |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| HTTPBasicAuthHandler            | :class:`urllib2.HTTPBasicAuthHandler`            | :class:`urllib.request.HTTPBasicAuthHandler`            |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| HTTPPasswordMgrWithDefaultRealm | :class:`urllib2.HTTPPasswordMgrWithDefaultRealm` | :class:`urllib.request.HTTPPasswordMgrWithDefaultRealm` |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| build_opener                    | :func:`urllib2.build_opener`                     | :func:`urllib.request.build_opener`                     |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| install_opener                  | :func:`urllib2.install_opener`                   | :func:`urllib.request.install_opener`                   |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| urlopen                         | :func:`urllib2.urlopen`                          | :func:`urllib.request.urlopen`                          |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| HTTPError                       | :exc:`urllib2.HTTPError`                         | :exc:`urllib.error.HTTPError`                           |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| URLError                        | :exc:`urllib2.URLError`                          | :exc:`urllib.error.URLError`                            |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| StringIO                        | :func:`cStringIO.StringIO`                       | :class:`io.StringIO`                                    |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| ConfigParser                    | :mod:`ConfigParser`                              | :mod:`configparser`                                     |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| cPickle                         | :mod:`cPickle`                                   | :mod:`pickle`                                           |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| Queue                           | :class:`Queue.Queue`                             | :class:`queue.Queue`                                    |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| Empty                           | :exc:`Queue.Empty`                               | :exc:`queue.Empty`                                      |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| Full                            | :exc:`Queue.Full`                                | :exc:`queue.Full`                                       |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| xmlrpclib                       | :mod:`xmlrpclib`                                 | :mod:`xmlrpc.client`                                    |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| SimpleXMLRPCServer              | :mod:`SimpleXMLRPCServer`                        | :mod:`xmlrpc.server`                                    |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| SocketServer                    | :mod:`SocketServer`                              | :mod:`socketserver`                                     |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| httplib                         | :mod:`httplib`                                   | :mod:`http.client`                                      |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| input                           | :func:`raw_input`                                | :func:`input`                                           |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| reduce                          | :func:`reduce`                                   | :func:`functools.reduce`                                |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| long                            | :func:`long`                                     | :func:`int`                                             |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+
| cmp                             | :func:`cmp`                                      | Not implemented                                         |
+---------------------------------+--------------------------------------------------+---------------------------------------------------------+

Python 2.4 compatibility
------------------------

The following symbols are imported or defined to provide compatibility
with Python 2.4 (and occasionally 2.5).  Be sure to read the notes
below, since some of these implementations may be feature-incomplete.

+----------------+--------------------------------+--------------------------------------------+
| Name           | Python 2.4                     | Python 2.5+                                |
+================+================================+============================================+
| formatdate     | :func:`email.Utils.formatdate` | :func:`email.utils.formatdate`             |
+----------------+--------------------------------+--------------------------------------------+
| walk_packages  | Not implemented                | :func:`pkgutil.walk_packages` (2.6+)       |
+----------------+--------------------------------+--------------------------------------------+
| any            | Not implemented                | :func:`any`                                |
+----------------+--------------------------------+--------------------------------------------+
| all            | Not implemented                | :func:`all`                                |
+----------------+--------------------------------+--------------------------------------------+
| wraps          | Not implemented                | :func:`functools.wraps`                    |
+----------------+--------------------------------+--------------------------------------------+
| md5            | :func:`md5.md5`                | :class:`hashlib.md5`                       |
+----------------+--------------------------------+--------------------------------------------+
| MutableMapping | :class:`UserDict.DictMixin`    | :class:`collections.MutableMapping` (2.6+) |
+----------------+--------------------------------+--------------------------------------------+
| literal_eval   | :func:`eval`                   | :func:`ast.literal_eval`                   |
+----------------+--------------------------------+--------------------------------------------+

walk_packages
~~~~~~~~~~~~~

The ``walk_packages`` implementation for Python 2.5 is
feature-complete.  The implementation for Python 2.4 is *not*.
Differences:

* Requires a full path, not a path relative to something in sys.path.
  Anywhere we care about that shouldn't be an issue.
* The first element of each tuple is None instead of an importer
  object.

wraps
~~~~~

The ``wraps`` implementation for Python 2.4 is a no-op.  It does not
attempt to copy the docstring or other details from the original
function to the wrapped function.

md5
~~~

:mod:`hashlib` is available for Python 2.4, but it is not part of the
standard base.  If it is installed, it will be used.  If you are doing
something fancy with MD5 sums, you may need to determine which object
is in use, since they are not equivalent.  For the majority of simple
cases -- finding the MD5 sum of a string -- they are equivalent
enough.

MutableMapping
~~~~~~~~~~~~~~

:class:`collections.MutableMapping` provides a subset of the
functionality of :class:`UserDict.DictMixin`; that is, any object that
is written to work with ``MutableMapping`` will also work with
``DictMixin``, so you should write classes with ``MutableMapping`` in
mind.

:class:`collections.MutableMapping` is available in Python 2.6+, and
will be used if available.

literal_eval
~~~~~~~~~~~~

:func:`ast.literal_eval` is a safe version of :func:`eval` that will only 
allow delaration of literal strings, ints, list, dicts, etc.  This was 
introduced in Python 2.6, and as such Python 2.4 uses the plain-old 
:func:`eval`.

Other Symbols
-------------

The following functions, classes, and symbols are provided for other
miscellaneous reasons.

u_str
~~~~~

.. autofunction:: Bcfg2.Compat.u_str

b64encode/b64decode
~~~~~~~~~~~~~~~~~~~

In Python 2, :func:`base64.b64encode` and :func:`base64.b64decode`
expect strings and return strings.  In Python 3, they expect bytes and
return bytes.  For Python 3, ``Bcfg2.Compat`` provides ``b64encode``
and ``b64encode`` that transparently encode strings into bytes, then
decode bytes into strings, so that those functions can be used
identically to their use in Python 2.

CmpMixin
~~~~~~~~

.. autoclass:: Bcfg2.Compat.CmpMixin

unicode
~~~~~~~

In Py3k, the :func:`unicode` class is not defined, because all
strings are unicode.  ``Bcfg2.Compat`` defines ``unicode`` as
equivalent to :func:`str` in Python 3.

oct_mode
~~~~~~~~

.. autofunction:: Bcfg2.Compat.oct_mode