Ubuntu

Merge lp:~logan/ubuntu/quantal/python-ipcalc/new-upstream into lp:ubuntu/quantal/python-ipcalc

Proposed by Logan Rosen on 2012-07-25
Status: Merged
Merge reported by: Dimitri John Ledkov
Merged at revision: not available
Proposed branch: lp:~logan/ubuntu/quantal/python-ipcalc/new-upstream
Merge into: lp:ubuntu/quantal/python-ipcalc
Diff against target: 546 lines (+256/-74) 5 files modified
To merge this branch: bzr merge lp:~logan/ubuntu/quantal/python-ipcalc/new-upstream
Reviewer Review Type Date Requested Status
Barry Warsaw Approve on 2012-08-14
Ubuntu branches 2012-07-25 Pending
Review via email: mp+116586@code.launchpad.net
To post a comment you must log in.
Barry Warsaw (barry) wrote :

Thanks for another fine contribution to Ubuntu. As with your others, please do file a bug in Debian, link it to a bug in Launchpad, and include your diff in the Debian bug. This way, it will be easier for us to resync to Debian once the newer version is available there.

One other thing I should mention. You bumped Standards-Version but it's not entirely clear to me that you verified that the package adheres to the updated version. Here's a good checklist for ensuring that your package is properly compatible with the newer version:

http://www.debian.org/doc/packaging-manuals/upgrading-checklist.txt

It's okay not to include the details of that in your changelog, but it would be helpful if you did provide the details in your merge proposal.

review: Approve

Preview Diff

1=== modified file 'PKG-INFO'
2--- PKG-INFO 2009-06-17 01:33:25 +0000
3+++ PKG-INFO 2012-07-25 06:05:20 +0000
4@@ -1,13 +1,44 @@
5 Metadata-Version: 1.0
6 Name: ipcalc
7-Version: 0.3
8+Version: 0.5.2
9 Summary: IP subnet calculator
10-Home-page: http://dev.tehmaze.com/projects/ipcalc
11+Home-page: http://tehmaze.github.com/ipcalc
12 Author: Wijnand Modderman
13 Author-email: python@tehmaze.com
14 License: UNKNOWN
15 Description:
16- This module allows you to perform IP subnet calculations, there is support
17- for both IPv4 and IPv6 CIDR notation.
18+ About
19+ =====
20+
21+ This module allows you to perform IP subnet calculations, there is support for
22+ both IPv4 and IPv6 CIDR notation.
23+
24+ Example Usage
25+ =============
26+
27+ ::
28+
29+ >>> import ipcalc
30+ >>> for x in ipcalc.Network('172.16.42.0/30'):
31+ ... print str(x)
32+ ...
33+ 172.16.42.0
34+ 172.16.42.1
35+ 172.16.42.2
36+ 172.16.42.3
37+ >>> subnet = ipcalc.Network('2001:beef:babe::/48')
38+ >>> print str(subnet.network())
39+ 2001:beef:babe:0000:0000:0000:0000:0000
40+ >>> print str(subnet.netmask())
41+ ffff:ffff:ffff:0000:0000:0000:0000:0000
42+ >>> '192.168.42.23' in Network('192.168.42.0/24')
43+ True
44+ >>> long(IP('fe80::213:ceff:fee8:c937'))
45+ 338288524927261089654168587652869703991L
46+
47+ Bugs/Features
48+ =============
49+
50+ You can issue a ticket in GitHub: https://github.com/tehmaze/ipcalc/issues
51
52 Platform: UNKNOWN
53
54=== modified file 'debian/changelog'
55--- debian/changelog 2012-04-14 13:44:30 +0000
56+++ debian/changelog 2012-07-25 06:05:20 +0000
57@@ -1,3 +1,10 @@
58+python-ipcalc (0.5.2-0ubuntu1) quantal; urgency=low
59+
60+ * New upstream release.
61+ * Bump Standards-Version to 3.9.3.
62+
63+ -- Logan Rosen <logatronico@gmail.com> Wed, 25 Jul 2012 02:00:29 -0400
64+
65 python-ipcalc (0.3-1build1) precise; urgency=low
66
67 * Rebuild to drop python2.6 dependencies and provides.
68
69=== modified file 'debian/control'
70--- debian/control 2009-06-17 01:33:25 +0000
71+++ debian/control 2012-07-25 06:05:20 +0000
72@@ -1,9 +1,10 @@
73 Source: python-ipcalc
74 Section: python
75 Priority: optional
76-Maintainer: MEZGANI Ali <mezgani@linuxmail.org>
77+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
78+XSBC-Original-Maintainer: MEZGANI Ali <mezgani@linuxmail.org>
79 Build-Depends: debhelper (>= 7), python-support, python-dev
80-Standards-Version: 3.8.2
81+Standards-Version: 3.9.3
82 Homepage: http://dev.tehmaze.com/projects/ipcalc
83 XB-Python-Version: ${python:Versions}
84
85
86=== modified file 'setup.py'
87--- setup.py 2009-06-17 01:33:25 +0000
88+++ setup.py 2012-07-25 06:05:20 +0000
89@@ -2,18 +2,47 @@
90
91 from distutils.core import setup
92
93-long_description = '''
94-This module allows you to perform IP subnet calculations, there is support
95-for both IPv4 and IPv6 CIDR notation.
96-'''
97-
98 setup(name='ipcalc',
99- version='0.3',
100+ version='0.5.2',
101 description='IP subnet calculator',
102- long_description=long_description,
103+ long_description='''
104+About
105+=====
106+
107+This module allows you to perform IP subnet calculations, there is support for
108+both IPv4 and IPv6 CIDR notation.
109+
110+Example Usage
111+=============
112+
113+::
114+
115+ >>> import ipcalc
116+ >>> for x in ipcalc.Network('172.16.42.0/30'):
117+ ... print str(x)
118+ ...
119+ 172.16.42.0
120+ 172.16.42.1
121+ 172.16.42.2
122+ 172.16.42.3
123+ >>> subnet = ipcalc.Network('2001:beef:babe::/48')
124+ >>> print str(subnet.network())
125+ 2001:beef:babe:0000:0000:0000:0000:0000
126+ >>> print str(subnet.netmask())
127+ ffff:ffff:ffff:0000:0000:0000:0000:0000
128+ >>> '192.168.42.23' in Network('192.168.42.0/24')
129+ True
130+ >>> long(IP('fe80::213:ceff:fee8:c937'))
131+ 338288524927261089654168587652869703991L
132+
133+Bugs/Features
134+=============
135+
136+You can issue a ticket in GitHub: https://github.com/tehmaze/ipcalc/issues
137+''',
138 author='Wijnand Modderman',
139 author_email='python@tehmaze.com',
140- url='http://dev.tehmaze.com/projects/ipcalc',
141+ url='http://tehmaze.github.com/ipcalc',
142 packages = [''],
143 package_dir = {'': 'src'},
144 )
145
146=== modified file 'src/ipcalc.py'
147--- src/ipcalc.py 2009-06-17 01:33:25 +0000
148+++ src/ipcalc.py 2012-07-25 06:05:20 +0000
149@@ -1,44 +1,96 @@
150-# IP subnet calculator
151-# (C) 2007 Wijnand 'tehmaze' Modderman - http://tehmaze.com
152-# BSD License
153-#
154-# ABOUT
155-# This module allows you to perform network calculations.
156-#
157-# CHANGELOG
158-# 2009-03-23: Added IPv4 short-hand form support, thanks to VeXocide.
159-# 2007-10-26: Added IPv6 support, as well as a lot of other functions,
160-# refactored the calculations.
161-# 2007-10-25: Initial writeup, because I could not find any other workable
162-# implementation.
163-#
164-# TODO
165-# * add CLI parser
166-#
167-# REFERENCES
168-# * http://www.estoile.com/links/ipv6.pdf
169-# * http://www.iana.org/assignments/ipv4-address-space
170-# * http://www.iana.org/assignments/multicast-addresses
171-# * http://www.iana.org/assignments/ipv6-address-space
172-# * http://www.iana.org/assignments/ipv6-tla-assignments
173-# * http://www.iana.org/assignments/ipv6-multicast-addresses
174-# * http://www.iana.org/assignments/ipv6-anycast-addresses
175-#
176-# THANKS (testing, tips)
177-# * Bastiaan (trbs)
178-# * Peter van Dijk (Habbie)
179-# * Hans van Kranenburg (Knorrie)
180-# * Jeroen Habraken (VeXocide)
181-#
182-
183-__version__ = '0.3'
184-
185-import types, socket
186+# -*- coding: utf-8 -*-
187+
188+'''
189+====================================
190+ :mod:`ipcalc` IP subnet calculator
191+====================================
192+.. moduleauthor:: Wijnand Modderman <http://tehmaze.com/>
193+.. note:: BSD License
194+
195+About
196+=====
197+
198+This module allows you to perform network calculations.
199+
200+Changelog
201+=========
202+
203+ ========== ===============================================================
204+ Date Changes
205+ ========== ===============================================================
206+ 2009-04-11 Added docstrings.
207+ 2009-03-23 Added IPv4 short-hand form support, thanks to VeXocide.
208+ 2007-10-26 Added IPv6 support, as well as a lot of other functions,
209+ refactored the calculations.
210+ 2007-10-25 Initial writeup, because I could not find any other workable
211+ implementation.
212+ ========== ===============================================================
213+
214+Todo
215+====
216+
217+Todo:
218+ * add CLI parser
219+
220+References
221+==========
222+
223+References:
224+ * http://www.estoile.com/links/ipv6.pdf
225+ * http://www.iana.org/assignments/ipv4-address-space
226+ * http://www.iana.org/assignments/multicast-addresses
227+ * http://www.iana.org/assignments/ipv6-address-space
228+ * http://www.iana.org/assignments/ipv6-tla-assignments
229+ * http://www.iana.org/assignments/ipv6-multicast-addresses
230+ * http://www.iana.org/assignments/ipv6-anycast-addresses
231+
232+Thanks
233+======
234+
235+I wish to thank the following people for their input:
236+ * Bastiaan (trbs)
237+ * Peter van Dijk (Habbie)
238+ * Hans van Kranenburg (Knorrie)
239+ * Jeroen Habraken (VeXocide)
240+ * Torbjörn Lönnemark
241+
242+'''
243+
244+__version__ = '0.5.2'
245+
246+import socket
247+
248+
249+try:
250+ bin(42)
251+except NameError:
252+ def bin(x):
253+ '''
254+ Stringifies an int or long in base 2.
255+ '''
256+ if x < 0:
257+ return '-' + bin(-x)
258+ out = []
259+ if x == 0:
260+ out.append('0')
261+ while x > 0:
262+ out.append('01'[x & 1])
263+ x >>= 1
264+ pass
265+ try:
266+ return '0b' + ''.join(reversed(out))
267+ except NameError, ne2:
268+ out.reverse()
269+ return '0b' + ''.join(out)
270+
271
272 class IP(object):
273 '''
274 Represents a single IP address.
275
276+ :param ip: the ip address
277+ :type ip: :class:`IP` or str or long or int
278+
279 >>> localhost = IP("127.0.0.1")
280 >>> print localhost
281 127.0.0.1
282@@ -109,12 +161,14 @@
283 self.mask = mask
284 self.v = 0
285 # Parse input
286- if isinstance(ip, IP):
287+ if ip is None:
288+ raise ValueError, "Can not pass None"
289+ elif isinstance(ip, IP):
290 self.ip = ip.ip
291 self.dq = ip.dq
292 self.v = ip.v
293 self.mask = ip.mask
294- elif type(ip) in [types.IntType, types.LongType]:
295+ elif isinstance(ip, (int, long)):
296 self.ip = long(ip)
297 if self.ip <= 0xffffffff:
298 self.v = version or 4
299@@ -123,10 +177,10 @@
300 self.v = version or 4
301 self.dq = self._itodq(ip)
302 else:
303- # If string is in CIDR notation
304+ # If string is in CIDR or netmask notation
305 if '/' in ip:
306 ip, mask = ip.split('/', 1)
307- self.mask = int(mask)
308+ self.mask = mask
309 self.v = version or 0
310 self.dq = ip
311 self.ip = self._dqtoi(ip)
312@@ -134,13 +188,26 @@
313 # Netmask defaults to one ip
314 if self.mask is None:
315 self.mask = self.v == 4 and 32 or 128
316+ # Netmask is numeric CIDR subnet
317+ elif isinstance(self.mask, (int, long)) or self.mask.isdigit():
318+ self.mask = int(self.mask)
319+ # Netmask is in subnet notation
320+ elif isinstance(self.mask, basestring):
321+ limit = [32, 128][':' in self.mask]
322+ inverted = ~self._dqtoi(self.mask)
323+ count = 0
324+ while inverted & 2**count:
325+ count += 1
326+ self.mask = (limit - count)
327+ else:
328+ raise ValueError, "Invalid netmask"
329 # Validate subnet size
330 if self.v == 6:
331 self.dq = self._itodq(self.ip)
332- if self.mask < 0 or self.mask > 128:
333+ if not 0 <= self.mask <= 128:
334 raise ValueError, "IPv6 subnet size must be between 0 and 128"
335 elif self.v == 4:
336- if self.mask < 0 or self.mask > 32:
337+ if not 0 <= self.mask <= 32:
338 raise ValueError, "IPv4 subnet size must be between 0 and 32"
339
340 def bin(self):
341@@ -151,10 +218,7 @@
342 >>> print ip.bin()
343 01111111000000000000000000000001
344 '''
345- h = hex(self.ip).lower().rstrip('l')
346- b = ''.join(self._bitmask[x] for x in h[2:])
347- l = self.v == 4 and 32 or 128
348- return ''.join('0' for x in xrange(len(b), l)) + b
349+ return bin(self.ip).split('b')[1].rjust(self.mask, '0')
350
351 def hex(self):
352 '''
353@@ -181,7 +245,7 @@
354 4
355 '''
356 return self.v
357-
358+
359 def info(self):
360 '''
361 Show IANA allocation information for the current IP address.
362@@ -196,7 +260,7 @@
363 if self._range[self.v].has_key(b[:i]):
364 return self._range[self.v][b[:i]]
365 return 'UNKNOWN'
366-
367+
368 def _dqtoi(self, dq):
369 '''
370 Convert dotquad or hextet to long.
371@@ -241,7 +305,7 @@
372 for h in hx:
373 if len(h) < 4:
374 h = '%04x' % int(h, 16)
375- if 0 > int(h, 16) > 0xffff:
376+ if not 0 <= int(h, 16) <= 0xffff:
377 raise ValueError, "%r: IPv6 address invalid: hextets should be between 0x0000 and 0xffff" % dq
378 ip += h
379 self.v = 6
380@@ -250,7 +314,7 @@
381 # Assume full heximal notation
382 self.v = 6
383 return long(h, 16)
384-
385+
386 # IPv4
387 if '.' in dq:
388 q = dq.split('.')
389@@ -258,15 +322,15 @@
390 if len(q) > 4:
391 raise ValueError, "%r: IPv4 address invalid: more than 4 bytes" % dq
392 for x in q:
393- if 0 > int(x) > 255:
394+ if not 0 <= int(x) <= 255:
395 raise ValueError, "%r: IPv4 address invalid: bytes should be between 0 and 255" % dq
396 while len(q) < 4:
397 q.insert(1, '0')
398 self.v = 4
399 return sum(long(byte) << 8 * index for index, byte in enumerate(q))
400-
401+
402 raise ValueError, "Invalid address input"
403-
404+
405 def _itodq(self, n):
406 '''
407 Convert long to dotquad or hextet.
408@@ -293,6 +357,21 @@
409 def __long__(self):
410 return self.ip
411
412+ def __lt__(self, other):
413+ return long(self) < long(IP(other))
414+
415+ def __le__(self, other):
416+ return long(self) <= long(IP(other))
417+
418+ def __ge__(self, other):
419+ return long(self) >= long(IP(other))
420+
421+ def __gt__(self, other):
422+ return long(self) > long(IP(other))
423+
424+ def __eq__(self, other):
425+ return long(self) == long(IP(other))
426+
427 def size(self):
428 return 1
429
430@@ -301,8 +380,8 @@
431 Return a new <IP> object with a copy of this one.
432
433 >>> ip = IP('127.0.0.1')
434- >>> ip.clone()
435- <ipcalc.IP object at 0xb7d4d18c>
436+ >>> ip.clone() # doctest: +ELLIPSIS
437+ <ipcalc.IP object at 0x...>
438 '''
439 return IP(self)
440
441@@ -325,6 +404,25 @@
442 else:
443 return ValueError, "%r: IPv6 address is not IPv4 compatible, nor a 6-to-4 IP" % self.dq
444
445+ @classmethod
446+ def from_bin(cls, value):
447+ value = value.lstrip('b')
448+ if len(value) == 32:
449+ return cls(int(value, 2))
450+ elif len(value) == 128:
451+ return cls(long(value, 2))
452+ else:
453+ return ValueError, "%r: invalid binary notation" % (value,)
454+
455+ @classmethod
456+ def from_hex(cls, value):
457+ if len(value) == 8:
458+ return cls(int(value, 16))
459+ elif len(value) == 32:
460+ return cls(long(value, 16))
461+ else:
462+ raise ValueError, "%r: invalid hexadecimal notation" % (value,)
463+
464 def to_ipv6(self, type='6-to-4'):
465 '''
466 Convert (an IPv4) IP address to an IPv6 address.
467@@ -347,11 +445,18 @@
468 Used for comparisons.
469 '''
470 return (self.dq, self.mask)
471-
472+
473+
474 class Network(IP):
475 '''
476 Network slice calculations.
477
478+ :param ip: network address
479+ :type ip: :class:`IP` or str or long or int
480+ :param mask: netmask
481+ :type mask: int or str
482+
483+
484 >>> localnet = Network('127.0.0.1/8')
485 >>> print localnet
486 127.0.0.1
487@@ -379,7 +484,7 @@
488 127.0.0.0
489 '''
490 return IP(self.ip & long(self.netmask()), version=self.version())
491-
492+
493 def broadcast(self):
494 '''
495 Broadcast address.
496@@ -441,6 +546,9 @@
497 def __ge__(self, other):
498 return self.size() >= IP(other).size()
499
500+ def __eq__(self, other):
501+ return self.size() == IP(other).size()
502+
503 def __iter__(self):
504 '''
505 Generate a range of ip addresses within the network.
506@@ -453,13 +561,16 @@
507 192.168.114.2
508 192.168.114.3
509 '''
510- for ip in [IP(long(self)+x) for x in xrange(0, self.size())]:
511+ for ip in (IP(long(self)+x) for x in xrange(0, self.size())):
512 yield ip
513
514 def has_key(self, ip):
515 '''
516 Check if the given ip is part of the network.
517
518+ :param ip: the ip address
519+ :type ip: :class:`IP` or str or long or int
520+
521 >>> net = Network('192.0.2.0/24')
522 >>> net.has_key('192.168.2.0')
523 False
524@@ -478,12 +589,16 @@
525 '''
526 return 2 ** ((self.version() == 4 and 32 or 128) - self.mask)
527
528+
529 if __name__ == '__main__':
530 tests = [
531 ('192.168.114.42', 23, ['192.168.0.1', '192.168.114.128', '10.0.0.1']),
532 ('123::', 128, ['123:456::', '::1', '123::456']),
533 ('::42', 64, ['::1', '1::']),
534- ('2001:dead:beef:1:c01d:c01a::', 48, ['2001:dead:beef:babe::'])
535+ ('2001:dead:beef:1:c01d:c01a::', 48, ['2001:dead:beef:babe::']),
536+ ('10.10.0.0', '255.255.255.0', ['10.10.0.20', '10.10.10.20']),
537+ ('2001:dead:beef:1:c01d:c01a::', 'ffff:ffff:ffff::', ['2001:dead:beef:babe::']),
538+ ('10.10.0.0/255.255.240.0', None, ['10.10.0.20', '10.10.250.0']),
539 ]
540
541 for ip, mask, test_ip in tests:
542@@ -506,4 +621,3 @@
543 print 'last host.:', net.host_last()
544 for ip in test_ip:
545 print '%s in network: ' % ip, ip in net
546-

Subscribers

People subscribed via source and target branches

to all changes: