diff options
-rw-r--r-- | Doc/library/collections.rst | 37 | ||||
-rw-r--r-- | Doc/library/getopt.rst | 2 | ||||
-rw-r--r-- | Doc/library/imp.rst | 62 | ||||
-rw-r--r-- | Doc/library/logging.rst | 23 | ||||
-rw-r--r-- | Doc/library/socket.rst | 27 | ||||
-rw-r--r-- | Doc/library/stdtypes.rst | 12 | ||||
-rw-r--r-- | Doc/tutorial/controlflow.rst | 53 | ||||
-rw-r--r-- | Doc/tutorial/introduction.rst | 2 | ||||
-rw-r--r-- | Lib/abc.py | 2 | ||||
-rw-r--r-- | Lib/collections.py | 22 | ||||
-rw-r--r-- | Lib/test/test_abc.py | 14 | ||||
-rw-r--r-- | Lib/test/test_socket.py | 82 | ||||
-rw-r--r-- | Misc/NEWS | 1 | ||||
-rw-r--r-- | Misc/developers.txt | 3 | ||||
-rw-r--r-- | Modules/socketmodule.c | 154 | ||||
-rw-r--r-- | Modules/socketmodule.h | 4 | ||||
-rw-r--r-- | Python/future.c | 2 | ||||
-rwxr-xr-x | configure | 5 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | pyconfig.h.in | 4 |
20 files changed, 465 insertions, 48 deletions
diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 5b625ee..cb3a029 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -489,7 +489,7 @@ three additional methods and one attribute. >>> Point._make(t) Point(x=11, y=22) -.. method:: somenamedtuple._asdict() +.. method:: namedtuple._asdict() Return a new dict which maps field names to their corresponding values: @@ -498,7 +498,7 @@ three additional methods and one attribute. >>> p._asdict() {'x': 11, 'y': 22} -.. method:: somenamedtuple._replace(kwargs) +.. method:: namedtuple._replace(kwargs) Return a new instance of the named tuple replacing specified fields with new values: @@ -511,7 +511,7 @@ three additional methods and one attribute. >>> for partnum, record in inventory.items(): ... inventory[partnum] = record._replace(price=newprices[partnum], updated=time.now()) -.. attribute:: somenamedtuple._fields +.. attribute:: namedtuple._fields Tuple of strings listing the field names. This is useful for introspection and for creating new named tuple types from existing named tuples. @@ -541,15 +541,28 @@ When casting a dictionary to a named tuple, use the double-star-operator [#]_:: Point(x=11, y=22) Since a named tuple is a regular Python class, it is easy to add or change -functionality. For example, the display format can be changed by overriding -the :meth:`__repr__` method: - -:: - - >>> Point = namedtuple('Point', 'x y') - >>> Point.__repr__ = lambda self: 'Point(%.3f, %.3f)' % self - >>> Point(x=11, y=22) - Point(11.000, 22.000) +functionality with a subclass. Here is how to add a calculated field and +a fixed-width print format:: + + >>> class Point(namedtuple('Point', 'x y')): + @property + def hypot(self): + return (self.x ** 2 + self.y ** 2) ** 0.5 + def __repr__(self): + return 'Point(x=%.3f, y=%.3f, hypot=%.3f)' % (self.x, self.y, self.hypot) + + >>> print Point(3, 4),'\n', Point(2, 5), '\n', Point(9./7, 6) + Point(x=3.000, y=4.000, hypot=5.000) + Point(x=2.000, y=5.000, hypot=5.385) + Point(x=1.286, y=6.000, hypot=6.136) + +Another use for subclassing is to replace performance critcal methods with +faster versions that bypass error-checking and localize variable access:: + + >>> class Point(namedtuple('Point', 'x y')): + _make = classmethod(tuple.__new__) + def _replace(self, _map=map, **kwds): + return self._make(_map(kwds.pop, ('x', 'y'), self)) Default values can be implemented by starting with a prototype instance and customizing it with :meth:`_replace`: diff --git a/Doc/library/getopt.rst b/Doc/library/getopt.rst index 35d91d2..8b8e326 100644 --- a/Doc/library/getopt.rst +++ b/Doc/library/getopt.rst @@ -11,7 +11,7 @@ This module helps scripts to parse the command line arguments in ``sys.argv``. It supports the same conventions as the Unix :cfunc:`getopt` function (including the special meanings of arguments of the form '``-``' and '``--``'). Long options similar to those supported by GNU software may be used as well via an -optional third argument. This module provides a single function and an +optional third argument. This module provides two functions and an exception: diff --git a/Doc/library/imp.rst b/Doc/library/imp.rst index 7b8133b..831d1a7 100644 --- a/Doc/library/imp.rst +++ b/Doc/library/imp.rst @@ -123,6 +123,68 @@ This module provides an interface to the mechanisms used to implement the function does nothing. +.. function:: reload(module) + + Reload a previously imported *module*. The argument must be a module object, so + it must have been successfully imported before. This is useful if you have + edited the module source file using an external editor and want to try out the + new version without leaving the Python interpreter. The return value is the + module object (the same as the *module* argument). + + When ``reload(module)`` is executed: + + * Python modules' code is recompiled and the module-level code reexecuted, + defining a new set of objects which are bound to names in the module's + dictionary. The ``init`` function of extension modules is not called a second + time. + + * As with all other objects in Python the old objects are only reclaimed after + their reference counts drop to zero. + + * The names in the module namespace are updated to point to any new or changed + objects. + + * Other references to the old objects (such as names external to the module) are + not rebound to refer to the new objects and must be updated in each namespace + where they occur if that is desired. + + There are a number of other caveats: + + If a module is syntactically correct but its initialization fails, the first + :keyword:`import` statement for it does not bind its name locally, but does + store a (partially initialized) module object in ``sys.modules``. To reload the + module you must first :keyword:`import` it again (this will bind the name to the + partially initialized module object) before you can :func:`reload` it. + + When a module is reloaded, its dictionary (containing the module's global + variables) is retained. Redefinitions of names will override the old + definitions, so this is generally not a problem. If the new version of a module + does not define a name that was defined by the old version, the old definition + remains. This feature can be used to the module's advantage if it maintains a + global table or cache of objects --- with a :keyword:`try` statement it can test + for the table's presence and skip its initialization if desired:: + + try: + cache + except NameError: + cache = {} + + It is legal though generally not very useful to reload built-in or dynamically + loaded modules, except for :mod:`sys`, :mod:`__main__` and :mod:`__builtin__`. + In many cases, however, extension modules are not designed to be initialized + more than once, and may fail in arbitrary ways when reloaded. + + If a module imports objects from another module using :keyword:`from` ... + :keyword:`import` ..., calling :func:`reload` for the other module does not + redefine the objects imported from it --- one way around this is to re-execute + the :keyword:`from` statement, another is to use :keyword:`import` and qualified + names (*module*.*name*) instead. + + If a module instantiates instances of a class, reloading the module that defines + the class does not affect the method definitions of the instances --- they + continue to use the old class definition. The same is true for derived classes. + + The following constants with integer values, defined in this module, are used to indicate the search result of :func:`find_module`. diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index a95e2b5..bf6ad71 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -688,7 +688,8 @@ functions. Does basic configuration for the logging system by creating a :class:`StreamHandler` with a default :class:`Formatter` and adding it to the - root logger. The functions :func:`debug`, :func:`info`, :func:`warning`, + root logger. The function does nothing if any handlers have been defined for + the root logger. The functions :func:`debug`, :func:`info`, :func:`warning`, :func:`error` and :func:`critical` will call :func:`basicConfig` automatically if no handlers are defined for the root logger. @@ -2384,24 +2385,24 @@ Here is the auxiliary module:: The output looks like this:: - 2005-03-23 23:47:11,663 - spam_application - INFO - + 2005-03-23 23:47:11,663 - spam_application - INFO - creating an instance of auxiliary_module.Auxiliary - 2005-03-23 23:47:11,665 - spam_application.auxiliary.Auxiliary - INFO - + 2005-03-23 23:47:11,665 - spam_application.auxiliary.Auxiliary - INFO - creating an instance of Auxiliary - 2005-03-23 23:47:11,665 - spam_application - INFO - + 2005-03-23 23:47:11,665 - spam_application - INFO - created an instance of auxiliary_module.Auxiliary - 2005-03-23 23:47:11,668 - spam_application - INFO - + 2005-03-23 23:47:11,668 - spam_application - INFO - calling auxiliary_module.Auxiliary.do_something - 2005-03-23 23:47:11,668 - spam_application.auxiliary.Auxiliary - INFO - + 2005-03-23 23:47:11,668 - spam_application.auxiliary.Auxiliary - INFO - doing something - 2005-03-23 23:47:11,669 - spam_application.auxiliary.Auxiliary - INFO - + 2005-03-23 23:47:11,669 - spam_application.auxiliary.Auxiliary - INFO - done doing something - 2005-03-23 23:47:11,670 - spam_application - INFO - + 2005-03-23 23:47:11,670 - spam_application - INFO - finished auxiliary_module.Auxiliary.do_something - 2005-03-23 23:47:11,671 - spam_application - INFO - + 2005-03-23 23:47:11,671 - spam_application - INFO - calling auxiliary_module.some_function() - 2005-03-23 23:47:11,672 - spam_application.auxiliary - INFO - + 2005-03-23 23:47:11,672 - spam_application.auxiliary - INFO - received a call to "some_function" - 2005-03-23 23:47:11,673 - spam_application - INFO - + 2005-03-23 23:47:11,673 - spam_application - INFO - done with auxiliary_module.some_function() diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index cc16150..406c136 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -65,6 +65,27 @@ numeric address in *host* portion. AF_NETLINK sockets are represented as pairs ``pid, groups``. + +Linux-only support for TIPC is also available using the :const:`AF_TIPC` +address family. TIPC is an open, non-IP based networked protocol designed +for use in clustered computer environments. Addresses are represented by a +tuple, and the fields depend on the address type. The general tuple form is +``(addr_type, v1, v2, v3 [, scope])``, where: + + - *addr_type* is one of TIPC_ADDR_NAMESEQ, TIPC_ADDR_NAME, or + TIPC_ADDR_ID. + - *scope* is one of TIPC_ZONE_SCOPE, TIPC_CLUSTER_SCOPE, and + TIPC_NODE_SCOPE. + - If *addr_type* is TIPC_ADDR_NAME, then *v1* is the server type, *v2* is + the port identifier, and *v3* should be 0. + + If *addr_type* is TIPC_ADDR_NAMESEQ, then *v1* is the server type, *v2* + is the lower port number, and *v3* is the upper port number. + + If *addr_type* is TIPC_ADDR_ID, then *v1* is the node, *v2* is the + reference, and *v3* should be set to 0. + + All errors raise exceptions. The normal exceptions for invalid argument types and out-of-memory conditions can be raised; errors related to socket or address semantics raise the error :exc:`socket.error`. @@ -162,6 +183,12 @@ The module :mod:`socket` exports the following constants and functions: :meth:`ioctl` method of socket objects. +.. data:: TIPC_* + + TIPC related constants, matching the ones exported by the C socket API. See + the TIPC documentation for more information. + + .. data:: has_ipv6 This constant contains a boolean value which indicates if IPv6 is supported on diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 7a4938c..4a1d566 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -389,9 +389,9 @@ This table lists the bit-string operations sorted in ascending priority | ``x & y`` | bitwise :dfn:`and` of *x* and | | | | *y* | | +------------+--------------------------------+----------+ -| ``x << n`` | *x* shifted left by *n* bits | (1), (2) | +| ``x << n`` | *x* shifted left by *n* bits | (1)(2) | +------------+--------------------------------+----------+ -| ``x >> n`` | *x* shifted right by *n* bits | (1), (3) | +| ``x >> n`` | *x* shifted right by *n* bits | (1)(3) | +------------+--------------------------------+----------+ | ``~x`` | the bits of *x* inverted | | +------------+--------------------------------+----------+ @@ -436,7 +436,7 @@ One method needs to be defined for container objects to provide iteration support: -.. method:: container.__iter__() +.. method:: object.__iter__() Return an iterator object. The object is required to support the iterator protocol described below. If a container supports different types of @@ -537,7 +537,7 @@ support slicing, concatenation or repetition, and using ``in``, ``not in``, Most sequence types support the following operations. The ``in`` and ``not in`` operations have the same priorities as the comparison operations. The ``+`` and ``*`` operations have the same priority as the corresponding numeric operations. -[#]_ +[#]_ Additional methods are provided for :ref:`typesseq-mutable`. This table lists the sequence operations sorted in ascending priority (operations in the same box have the same priority). In the table, *s* and *t* @@ -560,9 +560,9 @@ are sequences of the same type; *n*, *i* and *j* are integers: +------------------+--------------------------------+----------+ | ``s[i]`` | *i*'th item of *s*, origin 0 | \(3) | +------------------+--------------------------------+----------+ -| ``s[i:j]`` | slice of *s* from *i* to *j* | (3), (4) | +| ``s[i:j]`` | slice of *s* from *i* to *j* | (3)(4) | +------------------+--------------------------------+----------+ -| ``s[i:j:k]`` | slice of *s* from *i* to *j* | (3), (5) | +| ``s[i:j:k]`` | slice of *s* from *i* to *j* | (3)(5) | | | with step *k* | | +------------------+--------------------------------+----------+ | ``len(s)`` | length of *s* | | diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst index 5b05aed..3fedb56 100644 --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -595,10 +595,57 @@ Here is an example of a multi-line docstring:: No, really, it doesn't do anything. +.. _tut-codingstyle: + +Intermezzo: Coding Style +======================== + +.. sectionauthor:: Georg Brandl <georg@python.org> +.. index:: pair: coding; style + +Now that you are about to write longer, more complex pieces of Python, it is a +good time to talk about *coding style*. Most languages can be written (or more +concise, *formatted*) in different styles; some are more readable than others. +Making it easy for others to read your code is always a good idea, and adopting +a nice coding style helps tremendously for that. + +For Python, :pep:`8` has emerged as the style guide that most projects adher to; +it promotes a very readable and eye-pleasing coding style. Every Python +developer should read it at some point; here are the most important points +extracted for you: + +* Use 4-space indentation, and no tabs. + + 4 spaces are a good compromise between small indentation (allows greater + nesting depth) and large indentation (easier to read). Tabs introduce + confusion, and are best left out. + +* Wrap lines so that they don't exceed 79 characters. + + This helps users with small displays and makes it possible to have several + code files side-by-side on larger displays. + +* Use blank lines to separate functions and classes, and larger blocks of + code inside functions. + +* When possible, put comments on a line of their own. + +* Use docstrings. + +* Use spaces around operators and after commas, but not directly inside + bracketing constructs: ``a = f(1, 2) + g(3, 4)``. + +* Name your classes and functions consistently; the convention is to use + ``CamelCase`` for classes and ``lower_case_with_underscores`` for functions + and methods. Always use ``self`` as the name for the first method argument. + +* Don't use fancy encodings if your code is meant to be used in international + environments. Plain ASCII works best in any case. + .. rubric:: Footnotes -.. [#] Actually, *call by object reference* would be a better description, since if a - mutable object is passed, the caller will see any changes the callee makes to it - (items inserted into a list). +.. [#] Actually, *call by object reference* would be a better description, + since if a mutable object is passed, the caller will see any changes the + callee makes to it (items inserted into a list). diff --git a/Doc/tutorial/introduction.rst b/Doc/tutorial/introduction.rst index a99e7d2..1189ce8 100644 --- a/Doc/tutorial/introduction.rst +++ b/Doc/tutorial/introduction.rst @@ -548,7 +548,7 @@ series as follows:: ... # the sum of two elements defines the next ... a, b = 0, 1 >>> while b < 10: - ... print(b) + ... print b ... a, b = b, a+b ... 1 @@ -187,7 +187,7 @@ class ABCMeta(type): cls._abc_negative_cache.add(subclass) return ok # Check if it's a direct subclass - if cls in subclass.__mro__: + if cls in getattr(subclass, '__mro__', ()): cls._abc_cache.add(subclass) return True # Check if it's a subclass of a registered class (recursive) diff --git a/Lib/collections.py b/Lib/collections.py index 504ae19..884c91f 100644 --- a/Lib/collections.py +++ b/Lib/collections.py @@ -65,9 +65,9 @@ def namedtuple(typename, field_names, verbose=False): def __new__(cls, %(argtxt)s): return tuple.__new__(cls, (%(argtxt)s)) \n @classmethod - def _make(cls, iterable): + def _make(cls, iterable, new=tuple.__new__, len=len): 'Make a new %(typename)s object from a sequence or iterable' - result = tuple.__new__(cls, iterable) + result = new(cls, iterable) if len(result) != %(numfields)d: raise TypeError('Expected %(numfields)d arguments, got %%d' %% len(result)) return result \n @@ -115,8 +115,22 @@ if __name__ == '__main__': assert p == loads(dumps(p)) # test and demonstrate ability to override methods - Point.__repr__ = lambda self: 'Point(%.3f, %.3f)' % self - print(p) + class Point(namedtuple('Point', 'x y')): + @property + def hypot(self): + return (self.x ** 2 + self.y ** 2) ** 0.5 + def __repr__(self): + return 'Point(x=%.3f, y=%.3f, hypot=%.3f)' % (self.x, self.y, self.hypot) + + print(Point(3, 4),'\n', Point(2, 5), '\n', Point(9./7, 6)) + + class Point(namedtuple('Point', 'x y')): + 'Point class with optimized _make() and _replace() without error-checking' + _make = classmethod(tuple.__new__) + def _replace(self, _map=map, **kwds): + return self._make(_map(kwds.pop, ('x', 'y'), self)) + + print(Point(11, 22)._replace(x=100)) import doctest TestResults = namedtuple('TestResults', 'failed attempted') diff --git a/Lib/test/test_abc.py b/Lib/test/test_abc.py index e6c8415..884dd32 100644 --- a/Lib/test/test_abc.py +++ b/Lib/test/test_abc.py @@ -56,10 +56,18 @@ class TestABC(unittest.TestCase): self.assertEqual(F.__abstractmethods__, {"bar"}) self.assertRaises(TypeError, F) # because bar is abstract now + def test_subclass_oldstyle_class(self): + class A: + __metaclass__ = abc.ABCMeta + class OldstyleClass: + pass + self.assertFalse(issubclass(OldstyleClass, A)) + self.assertFalse(issubclass(A, OldstyleClass)) + def test_registration_basics(self): class A(metaclass=abc.ABCMeta): pass - class B: + class B(object): pass b = B() self.assertEqual(issubclass(B, A), False) @@ -94,7 +102,7 @@ class TestABC(unittest.TestCase): class A1(A): pass self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed - class B: + class B(object): pass A1.register(B) # ok A1.register(B) # should pass silently @@ -135,7 +143,7 @@ class TestABC(unittest.TestCase): def test_all_new_methods_are_called(self): class A(metaclass=abc.ABCMeta): pass - class B: + class B(object): counter = 0 def __new__(cls): B.counter += 1 diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 535f0ef..facf9fd 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1114,6 +1114,85 @@ class BufferIOTest(SocketConnectedTest): buf = bytes(MSG) self.serv_conn.send(buf) + +TIPC_STYPE = 2000 +TIPC_LOWER = 200 +TIPC_UPPER = 210 + +def isTipcAvailable(): + """Check if the TIPC module is loaded + + The TIPC module is not loaded automatically on Ubuntu and probably + other Linux distros. + """ + if not hasattr(socket, "AF_TIPC"): + return False + if not os.path.isfile("/proc/modules"): + return False + with open("/proc/modules") as f: + for line in f: + if line.startswith("tipc "): + return True + if test_support.debug: + print("TIPC module is not loaded, please 'sudo modprobe tipc'") + return False + +class TIPCTest (unittest.TestCase): + def testRDM(self): + srv = socket.socket(socket.AF_TIPC, socket.SOCK_RDM) + cli = socket.socket(socket.AF_TIPC, socket.SOCK_RDM) + + srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + srvaddr = (socket.TIPC_ADDR_NAMESEQ, TIPC_STYPE, + TIPC_LOWER, TIPC_UPPER) + srv.bind(srvaddr) + + sendaddr = (socket.TIPC_ADDR_NAME, TIPC_STYPE, + TIPC_LOWER + int((TIPC_UPPER - TIPC_LOWER) / 2), 0) + cli.sendto(MSG, sendaddr) + + msg, recvaddr = srv.recvfrom(1024) + + self.assertEqual(cli.getsockname(), recvaddr) + self.assertEqual(msg, MSG) + + +class TIPCThreadableTest (unittest.TestCase, ThreadableTest): + def __init__(self, methodName = 'runTest'): + unittest.TestCase.__init__(self, methodName = methodName) + ThreadableTest.__init__(self) + + def setUp(self): + self.srv = socket.socket(socket.AF_TIPC, socket.SOCK_STREAM) + self.srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + srvaddr = (socket.TIPC_ADDR_NAMESEQ, TIPC_STYPE, + TIPC_LOWER, TIPC_UPPER) + self.srv.bind(srvaddr) + self.srv.listen(5) + self.serverExplicitReady() + self.conn, self.connaddr = self.srv.accept() + + def clientSetUp(self): + # The is a hittable race between serverExplicitReady() and the + # accept() call; sleep a little while to avoid it, otherwise + # we could get an exception + time.sleep(0.1) + self.cli = socket.socket(socket.AF_TIPC, socket.SOCK_STREAM) + addr = (socket.TIPC_ADDR_NAME, TIPC_STYPE, + TIPC_LOWER + int((TIPC_UPPER - TIPC_LOWER) / 2), 0) + self.cli.connect(addr) + self.cliaddr = self.cli.getsockname() + + def testStream(self): + msg = self.conn.recv(1024) + self.assertEqual(msg, MSG) + self.assertEqual(self.cliaddr, self.connaddr) + + def _testStream(self): + self.cli.send(MSG) + self.cli.close() + + def test_main(): tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest, TestExceptions, BufferIOTest, BasicTCPTest2] @@ -1134,6 +1213,9 @@ def test_main(): tests.append(BasicSocketPairTest) if sys.platform == 'linux2': tests.append(TestLinuxAbstractNamespace) + if isTipcAvailable(): + tests.append(TIPCTest) + tests.append(TIPCThreadableTest) thread_info = test_support.threading_setup() test_support.run_unittest(*tests) @@ -44,6 +44,7 @@ Core and Builtins Extension Modules ----------------- +- Issue #1762972: Readded the reload() function as imp.reload() Library ------- diff --git a/Misc/developers.txt b/Misc/developers.txt index 7fdfb33..ba1c16b 100644 --- a/Misc/developers.txt +++ b/Misc/developers.txt @@ -17,6 +17,9 @@ the format to accommodate documentation needs as they arise. Permissions History ------------------- +- Mark Dickinson was given SVN access on 6 January 2008 by Facundo + Batista for his work on mathemathics and number related issues. + - Amaury Forgeot d'Arc was given SVN access on 9 November 2007 by MvL, for general contributions to Python. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index b59c15d..dc05108 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -7,7 +7,8 @@ This module provides an interface to Berkeley socket IPC. Limitations: - Only AF_INET, AF_INET6 and AF_UNIX address families are supported in a - portable manner, though AF_PACKET and AF_NETLINK are supported under Linux. + portable manner, though AF_PACKET, AF_NETLINK and AF_TIPC are supported + under Linux. - No read/write operations (use sendall/recv or makefile instead). - Additional restrictions apply on some non-Unix platforms (compensated for by socket.py). @@ -51,6 +52,25 @@ Module interface: the Ethernet protocol number to be received. For example: ("eth0",0x1234). Optional 3rd,4th,5th elements in the tuple specify packet-type and ha-type/addr. +- an AF_TIPC socket address is expressed as + (addr_type, v1, v2, v3 [, scope]); where addr_type can be one of: + TIPC_ADDR_NAMESEQ, TIPC_ADDR_NAME, and TIPC_ADDR_ID; + and scope can be one of: + TIPC_ZONE_SCOPE, TIPC_CLUSTER_SCOPE, and TIPC_NODE_SCOPE. + The meaning of v1, v2 and v3 depends on the value of addr_type: + if addr_type is TIPC_ADDR_NAME: + v1 is the server type + v2 is the port identifier + v3 is ignored + if addr_type is TIPC_ADDR_NAMESEQ: + v1 is the server type + v2 is the lower port number + v3 is the upper port number + if addr_type is TIPC_ADDR_ID: + v1 is the node + v2 is the ref + v3 is ignored + Local naming conventions: @@ -1058,6 +1078,39 @@ makesockaddr(int sockfd, struct sockaddr *addr, int addrlen, int proto) } #endif +#ifdef HAVE_LINUX_TIPC_H + case AF_TIPC: + { + struct sockaddr_tipc *a = (struct sockaddr_tipc *) addr; + if (a->addrtype == TIPC_ADDR_NAMESEQ) { + return Py_BuildValue("IIIII", + a->addrtype, + a->addr.nameseq.type, + a->addr.nameseq.lower, + a->addr.nameseq.upper, + a->scope); + } else if (a->addrtype == TIPC_ADDR_NAME) { + return Py_BuildValue("IIIII", + a->addrtype, + a->addr.name.name.type, + a->addr.name.name.instance, + a->addr.name.name.instance, + a->scope); + } else if (a->addrtype == TIPC_ADDR_ID) { + return Py_BuildValue("IIIII", + a->addrtype, + a->addr.id.node, + a->addr.id.ref, + 0, + a->scope); + } else { + PyErr_SetString(PyExc_TypeError, + "Invalid address type"); + return NULL; + } + } +#endif + /* More cases here... */ default: @@ -1343,6 +1396,56 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, } #endif +#ifdef HAVE_LINUX_TIPC_H + case AF_TIPC: + { + unsigned int atype, v1, v2, v3; + unsigned int scope = TIPC_CLUSTER_SCOPE; + struct sockaddr_tipc *addr; + + if (!PyTuple_Check(args)) { + PyErr_Format( + PyExc_TypeError, + "getsockaddrarg: " + "AF_TIPC address must be tuple, not %.500s", + Py_TYPE(args)->tp_name); + return 0; + } + + if (!PyArg_ParseTuple(args, + "IIII|I;Invalid TIPC address format", + &atype, &v1, &v2, &v3, &scope)) + return 0; + + addr = (struct sockaddr_tipc *) addr_ret; + memset(addr, 0, sizeof(struct sockaddr_tipc)); + + addr->family = AF_TIPC; + addr->scope = scope; + addr->addrtype = atype; + + if (atype == TIPC_ADDR_NAMESEQ) { + addr->addr.nameseq.type = v1; + addr->addr.nameseq.lower = v2; + addr->addr.nameseq.upper = v3; + } else if (atype == TIPC_ADDR_NAME) { + addr->addr.name.name.type = v1; + addr->addr.name.name.instance = v2; + } else if (atype == TIPC_ADDR_ID) { + addr->addr.id.node = v1; + addr->addr.id.ref = v2; + } else { + /* Shouldn't happen */ + PyErr_SetString(PyExc_TypeError, "Invalid address type"); + return 0; + } + + *len_ret = sizeof(*addr); + + return 1; + } +#endif + /* More cases here... */ default: @@ -1428,6 +1531,14 @@ getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret) } #endif +#ifdef HAVE_LINUX_TIPC_H + case AF_TIPC: + { + *len_ret = sizeof (struct sockaddr_tipc); + return 1; + } +#endif + /* More cases here... */ default: @@ -4211,6 +4322,47 @@ init_socket(void) PyModule_AddIntConstant(m, "PACKET_FASTROUTE", PACKET_FASTROUTE); #endif +#ifdef HAVE_LINUX_TIPC_H + PyModule_AddIntConstant(m, "AF_TIPC", AF_TIPC); + + /* for addresses */ + PyModule_AddIntConstant(m, "TIPC_ADDR_NAMESEQ", TIPC_ADDR_NAMESEQ); + PyModule_AddIntConstant(m, "TIPC_ADDR_NAME", TIPC_ADDR_NAME); + PyModule_AddIntConstant(m, "TIPC_ADDR_ID", TIPC_ADDR_ID); + + PyModule_AddIntConstant(m, "TIPC_ZONE_SCOPE", TIPC_ZONE_SCOPE); + PyModule_AddIntConstant(m, "TIPC_CLUSTER_SCOPE", TIPC_CLUSTER_SCOPE); + PyModule_AddIntConstant(m, "TIPC_NODE_SCOPE", TIPC_NODE_SCOPE); + + /* for setsockopt() */ + PyModule_AddIntConstant(m, "SOL_TIPC", SOL_TIPC); + PyModule_AddIntConstant(m, "TIPC_IMPORTANCE", TIPC_IMPORTANCE); + PyModule_AddIntConstant(m, "TIPC_SRC_DROPPABLE", TIPC_SRC_DROPPABLE); + PyModule_AddIntConstant(m, "TIPC_DEST_DROPPABLE", + TIPC_DEST_DROPPABLE); + PyModule_AddIntConstant(m, "TIPC_CONN_TIMEOUT", TIPC_CONN_TIMEOUT); + + PyModule_AddIntConstant(m, "TIPC_LOW_IMPORTANCE", + TIPC_LOW_IMPORTANCE); + PyModule_AddIntConstant(m, "TIPC_MEDIUM_IMPORTANCE", + TIPC_MEDIUM_IMPORTANCE); + PyModule_AddIntConstant(m, "TIPC_HIGH_IMPORTANCE", + TIPC_HIGH_IMPORTANCE); + PyModule_AddIntConstant(m, "TIPC_CRITICAL_IMPORTANCE", + TIPC_CRITICAL_IMPORTANCE); + + /* for subscriptions */ + PyModule_AddIntConstant(m, "TIPC_SUB_PORTS", TIPC_SUB_PORTS); + PyModule_AddIntConstant(m, "TIPC_SUB_SERVICE", TIPC_SUB_SERVICE); + PyModule_AddIntConstant(m, "TIPC_SUB_CANCEL", TIPC_SUB_CANCEL); + PyModule_AddIntConstant(m, "TIPC_WAIT_FOREVER", TIPC_WAIT_FOREVER); + PyModule_AddIntConstant(m, "TIPC_PUBLISHED", TIPC_PUBLISHED); + PyModule_AddIntConstant(m, "TIPC_WITHDRAWN", TIPC_WITHDRAWN); + PyModule_AddIntConstant(m, "TIPC_SUBSCR_TIMEOUT", TIPC_SUBSCR_TIMEOUT); + PyModule_AddIntConstant(m, "TIPC_CFG_SRV", TIPC_CFG_SRV); + PyModule_AddIntConstant(m, "TIPC_TOP_SRV", TIPC_TOP_SRV); +#endif + /* Socket types */ PyModule_AddIntConstant(m, "SOCK_STREAM", SOCK_STREAM); PyModule_AddIntConstant(m, "SOCK_DGRAM", SOCK_DGRAM); diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h index 43c95fd..114084c 100644 --- a/Modules/socketmodule.h +++ b/Modules/socketmodule.h @@ -61,6 +61,10 @@ # include <netpacket/packet.h> #endif +#ifdef HAVE_LINUX_TIPC_H +# include <linux/tipc.h> +#endif + #ifndef Py__SOCKET_H #define Py__SOCKET_H #ifdef __cplusplus diff --git a/Python/future.c b/Python/future.c index dca1d83..80a3006 100644 --- a/Python/future.c +++ b/Python/future.c @@ -65,7 +65,7 @@ future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename) /* A subsequent pass will detect future imports that don't appear at the beginning of the file. There's one case, - however, that is easier to handl here: A series of imports + however, that is easier to handle here: A series of imports joined by semi-colons, where the first import is a future statement but some subsequent import has the future form but is preceded by a regular import. @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 59558 . +# From configure.in Revision: 59625 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 3.0. # @@ -5390,6 +5390,7 @@ done + for ac_header in asm/types.h conio.h curses.h direct.h dlfcn.h errno.h \ fcntl.h grp.h \ io.h langinfo.h libintl.h ncurses.h poll.h process.h pthread.h \ @@ -5401,7 +5402,7 @@ sys/param.h sys/poll.h sys/select.h sys/socket.h sys/statvfs.h sys/stat.h \ sys/time.h \ sys/times.h sys/types.h sys/un.h sys/utsname.h sys/wait.h pty.h libutil.h \ sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \ -bluetooth/bluetooth.h +bluetooth/bluetooth.h linux/tipc.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then diff --git a/configure.in b/configure.in index 9a1f915..a92705c 100644 --- a/configure.in +++ b/configure.in @@ -1082,7 +1082,7 @@ sys/param.h sys/poll.h sys/select.h sys/socket.h sys/statvfs.h sys/stat.h \ sys/time.h \ sys/times.h sys/types.h sys/un.h sys/utsname.h sys/wait.h pty.h libutil.h \ sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \ -bluetooth/bluetooth.h) +bluetooth/bluetooth.h linux/tipc.h) AC_HEADER_DIRENT AC_HEADER_MAJOR diff --git a/pyconfig.h.in b/pyconfig.h.in index ac6d9f6..dbd7f04 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -351,6 +351,9 @@ /* Define to 1 if you have the <linux/netlink.h> header file. */ #undef HAVE_LINUX_NETLINK_H +/* Define to 1 if you have the <linux/tipc.h> header file. */ +#undef HAVE_LINUX_TIPC_H + /* Define this if you have the type long double. */ #undef HAVE_LONG_DOUBLE @@ -1046,4 +1049,3 @@ #endif /*Py_PYCONFIG_H*/ - |