diff options
Diffstat (limited to 'wiki')
-rw-r--r-- | wiki/ExampleUsage-1x.wiki | 124 | ||||
-rw-r--r-- | wiki/ExampleUsage.wiki | 60 | ||||
-rw-r--r-- | wiki/ReleaseNotes.wiki | 285 | ||||
-rw-r--r-- | wiki/Releasing.wiki | 21 | ||||
-rw-r--r-- | wiki/UpgradingTo2x.wiki | 105 | ||||
-rw-r--r-- | wiki/Using3144.wiki | 261 |
6 files changed, 856 insertions, 0 deletions
diff --git a/wiki/ExampleUsage-1x.wiki b/wiki/ExampleUsage-1x.wiki new file mode 100644 index 0000000..3a978ac --- /dev/null +++ b/wiki/ExampleUsage-1x.wiki @@ -0,0 +1,124 @@ + +Examples of the functionality of the 1.x version of the ipaddr library. Documentation for the current version (2.x) will be coming shortly. + +A lot of the functionality of the IPv4 class is derived from the BaseIP class. The same is true for the IPv6 class. that means that all of the functionality you see here is exactly the same when dealing with IPv6 addresses. + +=== IPv4 === +_using ipaddr with IPv4 addresses_ + +Start by creating your address object. +You can create an IPv4 object with: + +netmask +{{{ +>>> addr = ipaddr.IPv4('1.1.1.1/255.255.255.0') +>>> addr +IPv4('1.1.1.1/24') +}}} + +hostmask +{{{ +>>> addr = ipaddr.IPv4('1.1.1.1/0.0.0.255') +>>> addr +IPv4('1.1.1.1/24') +}}} + +prefix length +{{{ +>>> addr = ipaddr.IPv4('1.1.1.1/24') +>>> addr +IPv4('1.1.1.1/24') +}}} + +nothing (nothing implies a /32 netmask) +{{{ +>>> addr = ipaddr.IPv4('1.1.1.1') +>>> addr +IPv4('1.1.1.1/32') +}}} + +Many of the standard Python operations are supported +{{{ +# comparisons +>>> ipaddr.IPv4('1.1.1.1') == ipaddr.IPv4('1.1.1.2') +False +>>> ipaddr.IPv4('1.1.1.1') < ipaddr.IPv4('1.1.1.2') +True + +# list inclusion +>>> a = ipaddr.IPv4('1.1.1.1') +>>> b = ipaddr.IPv4('1.1.1.2') +>>> c = ipaddr.IPv4('1.1.1.3') +>>> a in [a, b, c] +True + +# inclusion +>>> ipaddr.IPv4('1.1.1.1') in ipaddr.IPv4("1.0.0.0/8") +True + +# sorting +>>> a = ipaddr.IPv4('1.1.1.10') +>>> b = ipaddr.IPv4('1.10.1.10') +>>> c = ipaddr.IPv4('1.1.10.10') +>>> d = ipaddr.IPv4('1.1.1.1') +>>> sorted([a, b, c, d]) +[IPv4('1.1.1.1/32'), IPv4('1.1.1.10/32'), IPv4('1.1.10.10/32'), IPv4('1.10.1.10/32')] + +# str +>>> str(ipaddr.IP('1.2.3.4')) +'1.2.3.4/32' + +# int/hex. +>>> int(ipaddr.IP('1.2.3.4')) +16909060 +>>> hex(ipaddr.IP('1.2.3.4')) +'0x1020304' +}}} + +Additionally, there are quite a few network-specific features available to ipaddr. +{{{ +>>> ipaddr.IPv4('10.0.0.0/8').Supernet() +IPv4('10.0.0.0/7') + +>>> ipaddr.IPv4('10.0.0.0/8').Subnet() +[IPv4('10.0.0.0/9'), IPv4('10.128.0.0/9')] + +>>> ipaddr.IPv4('10.0.0.0/8').Subnet(prefixlen_diff=2) # this returns networks with a prefix length of /10 +[IPv4('10.0.0.0/10'), IPv4('10.64.0.0/10'), + IPv4('10.128.0.0/10'), IPv4('10.192.0.0/10')] + +# AddressExclude removes an address from a superblock. +>>> ipaddr.IPv4('10.0.0.0/24').AddressExclude(ipaddr.IPv4('10.0.0.0/32')) +[IPv4('10.0.0.1/32'), IPv4('10.0.0.2/31'), + IPv4('10.0.0.4/30'), IPv4('10.0.0.8/29'), + IPv4('10.0.0.16/28'), IPv4('10.0.0.32/27'), + IPv4('10.0.0.64/26'), IPv4('10.0.0.128/25')] + +}}} + +=== IPv6 === + +IPv6 methods are exactly the same as their IPv4 counterparts. this is because a lot of the functionality for both the IPv4 and IPv6 classes is inherited from the BaseIP class. For example: + +{{{ +>>> addr = ipaddr.IPv6('ffff::1/120') +>>> addr +IPv6('ffff::1/120') +>>> addr.prefixlen +120 +>>> addr == ipaddr.IPv6('ffff::2/120') +False +>>> addr > ipaddr.IPv6('ffff::2/120') +False +>>> addr < ipaddr.IPv6('ffff::2/120') +True +>>> addr in ipaddr.IPv6('ffff::1/119') +True +>>> hex(addr) +'0xFFFF0000000000000000000000000001L' +>>> int(addr) +340277174624079928635746076935438991361L +}}} + + +As always, consult your local help(ipaddr) pydoc documentation with questions.
\ No newline at end of file diff --git a/wiki/ExampleUsage.wiki b/wiki/ExampleUsage.wiki new file mode 100644 index 0000000..cbc49f2 --- /dev/null +++ b/wiki/ExampleUsage.wiki @@ -0,0 +1,60 @@ +Examples for the functionality of the 2.x version of the ipaddr library. + +(*work in progress*) + +By far the best way to get to know a new library is to test it out; download it, run it in the python shell, write scripts with it, etc. + +Rather than just say RTFCode, some simple examples follow: + +the following was taken from PEP 3144: + + ipaddr has four main classes most people will use: + + # IPv4Address. (eg, '192.168.1.1') + # IPv4Network (eg, '192.168.0.0/16') + # IPv6Address (eg, '::1') + # IPv6Network (eg, '2001::/32') + +Most of the operations a network administrator performs on networks are +similar for both IPv4 and IPv6 networks. Ie. finding subnets, supernets, +determining if an address is contained in a given network, etc. Similarly, +both addresses and networks (of the same ip version!) have much in common; +the process for turning a given 32 or 128 bit number into a human readable +string notation, determining if the ip is within the valid specified range, +etc. Finally, there are some pythonic abstractions which are valid for all +addresses and networks, both IPv4 and IPv6. In short, there is common +functionality shared between (ipaddr class names in parentheses): + + # all IP addresses and networks, both IPv4 and IPv6. (`_IPAddrBase`) + # all IP addresses of both versions. (`_BaseIP`) + # all IP networks of both version. (`_BaseNet`) + # all IPv4 objects, both addresses and networks. (`_BaseV4`) + # all IPv6 objects, both addresses and networks. (`_BaseV6`) + +Seeing this as a clear hierarchy is important for recognizing how much +code is common between the four main classes. For this reason, ipaddr uses +class inheritance to abstract out as much common code is possible and +appropriate. This lack of duplication and very clean layout also makes +the job of the developer much easier should they need to debug code (either +theirs or mine). + +Knowing that there might be cases where the developer doesn't so much care +as to the types of IP they might be receiving, ipaddr comes with two +important helper functions, IPAddress() and IPNetwork(). These, as you +might guess, return the appropriately typed address or network objects for +the given argument. + +Finally, as mentioned earlier, there is no meaningful natural ordering +between IPv4 and IPv6 addresses and networks [2]. Rather than invent a +standard, ipaddr follows Ordering Comparisons and returns a TypeError +when asked to compare objects of differing IP versions. In practice, there +are many ways a programmer may wish to order the addresses, so this this + shouldn't pose a problem for the developer who can easily write: + + `v4 = [x for x in mixed_list if x._version == 4]` + `v6 = [x for x in mixed_list if x._version == 6]` + + `# perform operations on v4 and v6 here.` + + `return v4_return + v6_return` + diff --git a/wiki/ReleaseNotes.wiki b/wiki/ReleaseNotes.wiki new file mode 100644 index 0000000..25ea003 --- /dev/null +++ b/wiki/ReleaseNotes.wiki @@ -0,0 +1,285 @@ +#summary notes from releases past. + += Release Notes = + +Here are the visible changes for each release. + +== 2.1.10 == + +(2012-01-20) + +Friday night, LAUNCH LAUNCH LAUNCH! + + * i84, fix iterhosts for /31's or /127's + * private method arg cleanup. + * i83, docstring issue. + * i87, new ipv4/ipv6 parser. patch from pmarks + * i90, fix copyright. + * bytes fix. patch from pmarks. + +== 2.1.9 == + +(2011-02-22) + +The last outstanding issues. + + * fix warnings from python3.2 + * fix bug in _is_shorthand_ip resulting in bad teredo addresses. + +== 2.1.8 == + +(2011-02-09) + +This release fixes regressions. + + * Address and networks now again compare true, if the address matches. + * ipaddr works again on Python 2.4 and 2.5. + +== 2.1.7 == + +(2011-01-13) + + * turn teredo and sixtofour into properties as opposed to normal methods. + +== 2.1.6 == + +(2011-01-13) + + * typo fixes. + * fix for ipaddr_test referring to an old version of ipaddr. + * add test cases for r176 and r196. + * fix for recognizing IPv6 addresses with embedded IPv4 address not being recognized. + * additional unit tests for network comparisons and sorting. + * force hash() to long to ensure consistency + * turn v4_int_to_packed and v6_int_to_packed into public functions to aid converting between integers and network objects. + * add support for pulling teredo and 6to4 embedded addresses out of an IPv6 address. + +== 2.1.5 == + +(2010-09-11) + + * containment test should always return false on mixed-type tests. + +== 2.1.4 == + +(2010-08-15) + + * fix for issue66, more invalid IPv6 addresses will be rejected + +== 2.1.3 == + +(2010-06-12) + + * fix for issue61, incorrect network containment (thanks bw.default) + +== 2.1.2 == + +(2010-05-31) + + * Happy Memorial day. + * arithmetic for v4 and v6 address objects and ints (issue 57). + * fix address_exclude issue where excluding an address from itself puked. + * make sure addresses and networks don't compare. + * doc-string fixes (issue60) + * and masked() method to _BaseNet to return a network object with the host bits masked out (issue58) + * fix v6 subnet representation (email to ipaddr-py-dev) + + +== 2.1.1 == + +(2010-03-02) + + * bug with list comprehension in {{{ IPv4Network._is_valid_netmask() }}} + * kill the last remaining instances of the old exceptions in the docstrings(thanks Scott Kitterman) + +== 2.1.0 == + +(2010-02-13) + +Easier change this time :) + + * networks and addresses are unsortable by default (see https://groups.google.com/group/ipaddr-py-dev/browse_thread/thread/8fbc5166be71adbc for discussion). + * exception text cleanup. + * fixing inconsistent behavior of v4/v6 address/network comparisons. + * add IPv4Network().is_unspecified (thanks rep.dot.net) + * fix for decoding mapped addresses (thanks rlaager) + * docstring updates (thanks Scott Kitterman) + * fix errant ref to non-existent variable(s) (thanks Harry Bock) + * fix exceptions (most exceptions are subclassed from ValueError now, so this can easily be caught) + * iterator for looping through subnets (thanks Marco Giutsi) + +That's mostly it. there were quite a few other minor changes, but this should cover the major bits. Usage.wiki will be updated in the coming days. + +== 2.0.0 == + +First and foremost, this is a backwards incompatible change. Code written for ipaddr-1.x will likely not work stock with ipaddr-2.0. For users of the 1.x branch, I'll continue to provide support, but new-feature development has ceased. But it's not so bad, take a look.All in all, I think this new version of ipaddr is much more intuitive and easy to use. + +The best way to get a feel for this code is to download it and try and out, but I've tried to list some of the more important changes below to help you out. + +The major changes. + + # IPvXAddress and IPvXNetwork classes. + + * Individual addresses are now (IPv4|IPv6)Address objects. Network attributes that are actually addresses (eg, broadcast, network, hostmask) are now (IPv4|IPv6)Address objects. That means no more IPv4/IPv6 classes handling only networks. +{{{ +In [3]: ipaddr.IPv4Network("1.1.1.0/24") +Out[3]: IPv4Network('1.1.1.0/24') + +In [4]: ipaddr.IPv4Network("1.1.1.0/24").network +Out[4]: IPv4Address('1.1.1.0') + +In [5]: ipaddr.IPv4Network("1.1.1.0/24").broadcast +Out[5]: IPv4Address('1.1.1.255') +}}} + + * no more ext methods. To reference the stringified version of any attribute, you call str() on (similar for the numeric value with int()). +{{{ +In [6]: str(ipaddr.IPv4Network("1.1.1.0/24").broadcast) +Out[6]: '1.1.1.255' + +In [7]: int(ipaddr.IPv4Network("1.1.1.0/24").broadcast) +Out[7]: 16843263 + +In [8]: int(ipaddr.IPv4Network("1.1.1.0/24").network) +Out[8]: 16843008 + +In [9]: str(ipaddr.IPv4Network("1.1.1.0/24").network) +Out[9]: '1.1.1.0' +}}} + + * IP() everything-constructor has been replaced by IPAddress() and IPNetwork() constructors. It seems reasonable to assume that an application programmer will know when they are dealing strictly with ip addresses vs. networks and making this separation de-clutters the code. IPNetwork still assumes a default prefixlength of 32 for IPv4 and 128 for IPv6 if none is supplied (just like IP() used to), so when in doubt, you can always use IPNetwork. +{{{ +In [16]: ipaddr.IPNetwork('1.1.1.1') +Out[16]: IPv4Network('1.1.1.1/32') + +In [17]: ipaddr.IPNetwork('1.1.1.1/12') +Out[17]: IPv4Network('1.1.1.1/12') + +In [18]: ipaddr.IPNetwork('::1') +Out[18]: IPv6Network('::1/128') + +In [19]: ipaddr.IPNetwork('::1/64') +Out[19]: IPv6Network('::1/64') +}}} + + # Some other (but no less important) bug fixes/improvements: + + * __ contains __ accepts strings/ints as well as (IPv4|IPv6)Address objects. +{{{ +In [9]: ipaddr.IPAddress('1.1.1.1') in ipaddr.IPNetwork('1.1.1.0/24') +Out[9]: True + +In [10]: '1.1.1.1' in ipaddr.IPv4Network("1.1.1.0/24") +Out[10]: True + +In [11]: '1' in ipaddr.IPv4Network("0.0.0.0/0") +Out[11]: True + +In [12]: 1 in ipaddr.IPv4Network("0.0.0.0/0") +Out[12]: True +}}} + * summarize_address_range. You can now get a list of all of the networks between two distinct (IPv4|IPv6)Address'es (results in potentially huge speed boosts for address collapsing) +{{{ +In [14]: ipaddr.summarize_address_range(ipaddr.IPAddress('1.1.0.0'), ipaddr.IPAddress('1.1.255.255')) +Out[14]: [IPv4Network('1.1.0.0/16')] + +In [15]: ipaddr.summarize_address_range(ipaddr.IPAddress('1.1.0.0'), ipaddr.IPAddress('1.1.255.254')) +Out[15]: +[IPv4Network('1.1.0.0/17'), + IPv4Network('1.1.128.0/18'), + IPv4Network('1.1.192.0/19'), + IPv4Network('1.1.224.0/20'), + IPv4Network('1.1.240.0/21'), + IPv4Network('1.1.248.0/22'), + IPv4Network('1.1.252.0/23'), + IPv4Network('1.1.254.0/24'), + IPv4Network('1.1.255.0/25'), + IPv4Network('1.1.255.128/26'), + IPv4Network('1.1.255.192/27'), + IPv4Network('1.1.255.224/28'), + IPv4Network('1.1.255.240/29'), + IPv4Network('1.1.255.248/30'), + IPv4Network('1.1.255.252/31'), + IPv4Network('1.1.255.254/32')] +}}} + + * network iterators. the (IPv4|IPv6)Network classes now implement iterators to help quickly access each member of a network in sequence: +{{{ + +In [24]: for addr in iter(ipaddr.IPNetwork('1.1.1.1/28')): addr + ....: +Out[24]: IPv4Address('1.1.1.0') +Out[24]: IPv4Address('1.1.1.1') +Out[24]: IPv4Address('1.1.1.2') +Out[24]: IPv4Address('1.1.1.3') +Out[24]: IPv4Address('1.1.1.4') +Out[24]: IPv4Address('1.1.1.5') +Out[24]: IPv4Address('1.1.1.6') +Out[24]: IPv4Address('1.1.1.7') +Out[24]: IPv4Address('1.1.1.8') +Out[24]: IPv4Address('1.1.1.9') +Out[24]: IPv4Address('1.1.1.10') +Out[24]: IPv4Address('1.1.1.11') +Out[24]: IPv4Address('1.1.1.12') +Out[24]: IPv4Address('1.1.1.13') +Out[24]: IPv4Address('1.1.1.14') +Out[24]: IPv4Address('1.1.1.15') +}}} + + * additionally, an iterhosts() method has been added to allow for iterating over all of the usable addresses on a network (everything except the network and broadcast addresses) +{{{ +In [26]: for addr in ipaddr.IPNetwork('1.1.1.1/28').iterhosts(): addr + ....: +Out[26]: IPv4Address('1.1.1.1') +Out[26]: IPv4Address('1.1.1.2') +Out[26]: IPv4Address('1.1.1.3') +Out[26]: IPv4Address('1.1.1.4') +Out[26]: IPv4Address('1.1.1.5') +Out[26]: IPv4Address('1.1.1.6') +Out[26]: IPv4Address('1.1.1.7') +Out[26]: IPv4Address('1.1.1.8') +Out[26]: IPv4Address('1.1.1.9') +Out[26]: IPv4Address('1.1.1.10') +Out[26]: IPv4Address('1.1.1.11') +Out[26]: IPv4Address('1.1.1.12') +Out[26]: IPv4Address('1.1.1.13') +Out[26]: IPv4Address('1.1.1.14') +}}} + +Thanks to the python community and everyone who's made feature suggestions or submitted patches. Please continue to send bugs/enhancements/patches to the mailing list. + +== 1.1.1 == + +This release contains a single important bugfix. All users of 1.1.0 should upgrade. + + * r77 A logical error caused ordering operators to behave incorrectly. + +== 1.1.0 == + +`ipaddr.py` is now part of the standard library in Python 2.7 and 3.1! This release is compatible with the `ipaddr` from future versions of Python. + +Special thanks to Philipp Hagemeister for making most of the improvements to this release, and to Gregory P. Smith for shepherding this into the Python standard library. + + * r59 Method names are now PEP-8 compliant, instead of Google-style camel case. The old method names remain, but are deprecated; you should use the lowercase names to be compatible with Python 2.7/3.1. (pmoody) + * r63 .prefixlen is now a property. (pmoody) + * r64 Stronger validation. (Philipp Hagemeister) + * r65 1.2.3.4 is not a valid v6 address, so we can simplify the constructor. (Philipp Hagemeister) + * r66 Expand rich comparison operations and their tests, with a goal of supporting 2to3. Add a new method .networks_key(). Add a new script to run through 2to3 and make sure tests pass under Python 3 with the converted version. (Philipp Hagemeister) + * r68 New method .packed(). (Philipp Hagemeister) + * r69 Add `is_multicast`, `is_unspecified`, `is_loopback`, `is_link_local`, `is_site_local`, and `is_private` for IPv6. Make more methods into properties. Improved documentation and tests for `is_*` properties for IPv4 and IPv6. Rename `networks_key()` to `_get_networks_key()`. + * r71 Fix off-by-one bug (issue 15). (gpsmith) + +== 1.0.2 == + * r52 Force the return value in testHexRepresentation to uppercase to workaround Python version. (smart) + * r51 Fix testHexRepresentation(). Hex representations of longs are uppercase. (smart) + * r50 Remove trailing whitespace and update docstrings. (smart) + * r44. this makes the spacing and docstrings pep8 compliant. (pmoody) + * r43. When processing the IPv4 mapped address 16 bits at a time, the components are stored in the reverse order. Updated the test to use a non-symmetric IPv4 address, which exhibited the bug. (smart) + * r40. implment __int__ and __hex__. will need to be updated for py3k (to use __index__) (pmoody) + * r38 A cleanup from issue 9 : Make exception messages consistent for IP(''), IPv4(''), IPv6('') (smart) + * r37 Fix for issue 9 : ipaddr.IP('') should raise ValueError (mshields) + +== 1.0.1 == + + * str() now produces lowercase for IPv6 addresses, to match inet_pton(3). (http://codereview.appspot.com/7678) + * repr() now produces strings that can be pasted back into the interpreter. diff --git a/wiki/Releasing.wiki b/wiki/Releasing.wiki new file mode 100644 index 0000000..1162867 --- /dev/null +++ b/wiki/Releasing.wiki @@ -0,0 +1,21 @@ +#summary Release instructions + += How to make releases = + +Choose a release number; see [http://www.producingoss.com/en/development-cycle.html#release-number-simple-strategy here]. + +If preparing for an a.b.0 release, create a [http://www.producingoss.com/en/release-branches.html release branch] called `a.b.x` (literal `x`): `svn copy -m'Creating 1.0.x release branch' https://ipaddr-py.googlecode.com/svn/trunk/ https://ipaddr-py.googlecode.com/svn/branches/1.0.x` + +If preparing for a micro release, first switch your client to the release branch: `svn switch https://ipaddr-py.googlecode.com/svn/branches/1.0.x` (or `svn co` to a new directory). Then [http://svnbook.red-bean.com/en/1.1/ch04s03.html merge] the changes you want from the trunk (`svn merge -r6:7 https://ipaddr-py.googlecode.com/svn/trunk`), and commit them. + +== Actually making a release == + + # Run `python2.4 ipaddr_test.py; python2.6 ipaddr_test.py' to double-check that everything passes. + # Write ReleaseNotes in the wiki. + # Copy the release notes to ./RELEASENOTES and commit. + # Update `__version__` in ipaddr.py to a string like `'1.0.0'`, and commit to the release branch. + # Tag the version: `svn copy -m'Tagging 1.0.0 release' https://ipaddr-py.googlecode.com/svn/branches/1.0.x https://ipaddr-py.googlecode.com/svn/tags/1.0.0` + # Prepare tarball: `./setup.py sdist`. It will appear in `./dist`. + # Create a [http://code.google.com/p/ipaddr-py/downloads/entry new download] on Google Code. Use the labels `Featured`, `Type-Source`, and `OpSys-All`. + # Remove the `Featured` label from the previous release. Files with this label will appear on the project front page in a green box. + # Make an announcement to ipaddr-py-dev@googlegroups.com and (if an a.b.0 release) to Freshmeat. Be sure to mention notable changes.
\ No newline at end of file diff --git a/wiki/UpgradingTo2x.wiki b/wiki/UpgradingTo2x.wiki new file mode 100644 index 0000000..a8cbfbd --- /dev/null +++ b/wiki/UpgradingTo2x.wiki @@ -0,0 +1,105 @@ +This page describes the major differences between the 1.x and 2.x branches of ipaddr and what changes you need to make to your code to begin using the new versions. + += Introduction = + +Lots of work has gone into making the 2.x branch of ipaddr easier to use and better overall. Since we'd like as many people as possible to use to new version, here's a short summary of the major changes and what you'll have to do to your code to make it work with the new version. + += Details = + +=== Design Changes === + +First and foremost, the overall design of ipaddr changed. In the 1.x branch, there was no concept of the Address, as strict 32 bit (IPv4) or 128 bit (IPv6) addresses. This lead to confusion when the broadcast attribute of IPv4('1.1.1.0/24') was returned as 1.1.1.255/32. The /32 implied that this was a network object being returned, albeit a network with only one host, when in fact it's not a network at all. + +So, in 2.x the concept of an address was introduced. These are individual 32 bit (IPv4) or 128 bit (IPv6) IPs. Networks can contain them, eg + +{{{ +>>> ipaddr.IPv4Address('1.1.1.1') in ipaddr.IPv4Network('1.1.1.0/24') +True +}}} + +Since Addresses and Networks are fundamentally different object types now, they're no longer comparable by default. + +{{{ +>>> address = ipaddr.IPv4Address('192.0.2.1') +>>> network = ipaddr.IPv4Network('192.0.2.0/24') +>>> sorted([address, network]) +Traceback (most recent call last): + File "<stdin>", line 1, in <module> + File "ipaddr.py", line 539, in __lt__ + str(self), str(other))) +TypeError: 192.0.2.0/24 and 192.0.2.1 are not of the same type + +}}} + +IPv4 and IPv6 objects are also no longer comparable by default: + +{{{ +>>> four = ipaddr.IPNetwork('192.0.2.0/24') +>>> six = ipaddr.IPNetwork('2001:db8::/32') +>>> sorted([four, six]) +Traceback (most recent call last): + File "<stdin>", line 1, in <module> + File "ipaddr.py", line 536, in __lt__ + str(self), str(other))) +TypeError: 2001:db8::/32 and 192.0.2.0/24 are not of the same version + +}}} + +However they can be sorted by using {{{ ipaddr.get_mixed_type_key() }}} key indexing function to sorted(). E.g., + +{{{ +>>> sorted([address, network], key=ipaddr.get_mixed_type_key) +[IPv4Network('192.0.2.0/24'), IPv4Address('192.0.2.1')] +>>> sorted([four, six], key=ipaddr.get_mixed_type_key) +[IPv4Network('192.0.2.0/24'), IPv6Network('2001:db8::/32')] +}}} + +=== Classes === + +With IPv4 and IPv6, the addition of the concept of the Address give ipaddr 4 public classes. + +{{{ +IPv4Address +IPv4Network +IPv6Address +IPv6Network +}}} + +The network and address methods between the various IP versions are identical, so from the standpoint of the developer, they're mostly interchangeable. + +=== Constructors === + +ipaddr 1.x relied mostly on the monolithic IP(string) constructor. This would return either a IPv4 or IPv6 object. There are now two main constructors, {{{ IPAddress(address_string) }}} and {{{ IPNetwork(address_string) }}}. These constructors try to determine the type, either v4 or v6, of string or int and then return an appropriately-typed object. + + +*more to come* + +=== Accessors === + +2.x makes much greater use of Python's special methods for returning the integer or string representations of an object. + +|| 1.x || 2.x || +|| str(network) || str(network) || +|| network.ip || int(network.ip) or int(network) || +|| network.ip_ext || str(network.ip) || +|| network.ip_ext_full || network.exploded (for IPv6 only) || +|| network.netmask || int(network.netmask) || +|| network.netmask_ext || str(network.netmask) || +|| network.broadcast || int(network.broadcast) || +|| network.broadcast_ext || str(network.broadcast) || + +Additionally, the various network attributes ({{{ .ip, .ip_ext, .network, .network_ext, .broadcast, .broadcast_ext }}}) used to return either strings or ints. As mentioned before, they return ipaddr address objects, either of type {{{IPv4Address}}} or {{{IPv6Address}}}. + +=== Exceptions === + +In general, the exceptions are much more Pythonic. No more inventing exceptions for every corner case since Python politely furnishes us with almost every exception type we already need. In the couple of cases where it does actually make sense for us to have our own exceptions, they're now subclassed from ValueError so you can shortcut the exception catching if you'd like and just catch ValueError. + + +|| 1.x || 2.x || +|| ipaddr.IPv4IpValidationError || ipaddr.AddressValueError || +|| ipaddr.IPv6IpValidationError || ipaddr.AddressValueError || +|| ipaddr.IPv4NetmaskValidationError || ipaddr.NetmaskValueError || +|| ipaddr.IPv6NetmaskValidationError || ipaddr.NetmaskValueError || +|| ipaddr.IPTypeError || TypeError || +|| ipaddr.IPAddressExclussionError || ValueError || +|| ipaddr.PrefixLenDiffInvalidError || ValueError ||
\ No newline at end of file diff --git a/wiki/Using3144.wiki b/wiki/Using3144.wiki new file mode 100644 index 0000000..f3cb793 --- /dev/null +++ b/wiki/Using3144.wiki @@ -0,0 +1,261 @@ +# Information and examples on using ipaddr from branches/3144 + += Using ipaddr = + +What follows is an introducion to using ipaddr-py. These exmples use the version from branches/3144. + +== Creating Address/Network/Interface objects == + + Since ipaddr-py is library for inspecting and manipulating IP address, the first thing you'll want to do is create some objects. You can use ipaddr to create objects from strings, integers or other ipaddr objects. + + * Creating Addresses. + + Addresses are the most basic unit. They are indivisable. + + IPv4 Address: + + {{{ + # string constructor. + >>> ipaddr.IPv4Address('192.0.2.1') + IPv4Address('192.0.2.1') + + # integer constructor. + >>> ipaddr.IPv4Address(3221225985) + IPv4Address('192.0.2.1') + + # copy constructor. + >>> addr = ipaddr.IPv4Address('192.0.2.1') + >>> ipaddr.IPv4Address(addr) + IPv4Address('192.0.2.1') + }}} + + IPv6 Address: + + {{{ + # string constructor. + >>> ipaddr.IPv6Address('2001:DB8::1') + IPv6Address('2001:db8::1') + + # integer constructor - this one's a mouthful. + >>> ipaddr.IPv6Address(42540766411282592856903984951653826561L) + IPv6Address('2001:db8::1') + + # copy constructor + >>> ipaddr.IPv6Address(addr) + IPv6Address('2001:db8::1') + }}} + + * Creating Networks. + + Addresses are usually grouped together in Networks, so ipaddr provides a way to create, inspect and maniuplate those as well. The constructors look identical to their corresponding address constructor. + + IPv4 Network: + {{{ + >>> ipaddr.IPv4Network('192.0.2.0/24') + IPv4Network('192.0.2.0/24') + >>> ipaddr.IPv4Network(3221225984) + IPv4Network('192.0.2.0/32') + >>> addr = ipaddr.IPv4Network('192.0.2.0/24') + >>> ipaddr.IPv4Network(addr) + IPv4Network('192.0.2.0/24') + }}} + + IPv6 Network: + {{{ + >>> ipaddr.IPv6Network('2001:db8::0/96') + IPv6Network('2001:db8::/96') + >>> ipaddr.IPv6Network(42540766411282592856903984951653826560L) + IPv6Network('2001:db8::/128') + >>> addr = ipaddr.IPv6Network('2001:db8::0/96') + >>> ipaddr.IPv6Network(addr) + IPv6Network('2001:db8::/96') + }}} + + Network objects cannot have any host bits set. The practical effect of this is that, '192.0.2.1/24' does not describe a network. It's referred to as an interface object since the ip-on-a-network notation is commonly used to describe network interfaces of a computer on a given network. + +Note: when creating a network object from an integer, the prefix length +(netmask) is assumed to be all ones. So IPv4 networks will have a /32 netmask +and IPv6 networks will have a /128 netmask. + + * Creating hybrid objects. + + As mentioned just above, if you need to describe an address on a particular network, neither the address nor the network classes is appropriate. Since the notation 192.0.2.1/24 is so common among network engineers and the people who write tools for firewalls and routers, ipaddr provides a set of hybrid classes. By now, the constructor syntax should look familair. + + IPv4Interface: + {{{ + >>> ipaddr.IPv4Interface('192.0.2.1/24') + IPv4Interface('192.0.2.1/24') + >>> ipaddr.IPv4Interface(3221225985) + IPv4Interface('192.0.2.1/32') + >>> addr = ipaddr.IPv4Interface('192.0.2.1/24') + >>> ipaddr.IPv4Interface(addr) + IPv4Interface('192.0.2.1/24') + }}} + + IPv6Interface: + {{{ + >>> ipaddr.IPv6Interface('2001:db8::1/96') + IPv6Interface('2001:db8::1/96') + >>> ipaddr.IPv6Interface(42540766411282592856903984951653826561L) + IPv6Interface('2001:db8::1/128') + >>> addr = ipaddr.IPv6Interface('2001:db8::1/96') + >>> ipaddr.IPv6Interface(addr) + IPv6Interface('2001:db8::1/96') + }}} + +Note: Just like with the network objects, when you create an interface object with an integer, the netmask is assumed to be all ones. + + Finally, if you don't know at the time coding what type of addresses you might be handling, or you don't really care and you'd like the same code to handle both, ipaddr provides generic factory functions which look at the address and try to return an object of the correct for you. + + * Addresses + {{{ + >>> ipaddr.ip_address('192.0.2.1') + IPv4Address('192.0.2.1') + >>> ipaddr.ip_address('2001:db8::1') + IPv6Address('2001:db8::1') + >>> ipaddr.ip_address(1) + IPv4Address('0.0.0.1') + >>> addr = ipaddr.ip_address('2001:db8::1') + >>> ipaddr.ip_address(addr) + IPv6Address('2001:db8::1') + }}} + + * Networks + {{{ + >>> ipaddr.ip_network('192.0.2.0/24') + IPv4Network('192.0.2.0/24') + >>> addr = ipaddr.ip_network('192.0.2.0/24') + >>> ipaddr.ip_network(addr) + IPv4Network('192.0.2.0/24') + >>> ipaddr.ip_network('2001:db8::0/96') + IPv6Network('2001:db8::/96') + }}} + + * Interfaces + {{{ + >>> ipaddr.ip_interface('192.0.2.1/24') + IPv4Interface('192.0.2.1/24') + >>> ipaddr.ip_interface('2001:db8::1/96') + IPv6Interface('2001:db8::1/96') + }}} + +Note: Since IPv4 addresses are 2^32^ bits and IPv6 addresses are 2^128^ bits, all integers <= 2^32^ - 1 are assumed to be IPv4. If you know that an address is an IPv6 address, you should pass version=6 to ip_address(). + + * explicit versioning + {{{ + >>> ipaddr.ip_address(3221225985) + IPv4Address('192.0.2.1') + >>> ipaddr.ip_address(3221225985, version=6) + IPv6Address('::c000:201') + }}} + +== Inspecting Address/Network/Interface Objects == + + You've gone to the trouble of creating an IPv(4|6)(Address|Network|Interface) object, so you probably want to get information about it. ipaddr tries to make doing this easy and intuitive. + + * IP version. + {{{ + >>> addr4 = ipaddr.ip_address('192.0.2.1') + >>> addr6 = ipaddr.ip_address('2001:db8::1') + >>> addr6.version + 6 + >>> addr4.version + 4 + }}} + + * Network/Interface + {{{ + >>> net4 = ipaddr.ip_network('192.0.2.0/24') + >>> net6 = ipaddr.ip_network('2001:db8::0/96') + }}} + + * finding out how many individual addresses are in a network. + {{{ + >>> net4.numhosts + 256 + >>> net6.numhosts + 4294967296L + }}} + + * iterating through the 'usable' addresses on a network. + {{{ + >>> for x in net4.iterhosts(): + print x + 192.0.2.1 + 192.0.2.2 + 192.0.2.3 + 192.0.2.4 + [snip] + 192.0.2.252 + 192.0.2.253 + 192.0.2.254 + }}} + + * host/netmask + {{{ + >>> net6.netmask + IPv6Address('ffff:ffff:ffff:ffff:ffff:ffff::') + >>> net6.hostmask + IPv6Address('::ffff:ffff') + }}} + + * Exploding or compressing the address + {{{ + >>> net6.exploded + '2001:0000:0000:0000:0000:0000:0000:0000/96' + >>> addr6.exploded + '2001:0000:0000:0000:0000:0000:0000:0001' + }}} + +== Networks/Interfaces as lists == + + It's sometimes useful to treat networks (and interfaces) as lists. This allows us to index them like this: + + {{{ + >>> net6[1] + IPv6Address('2001::1') + >>> net6[-1] + IPv6Address('2001::ffff:ffff') + >>> ipaddr.ip_interface('192.0.2.1/24')[-1] + IPv4Address('192.0.2.255') + }}} + +This also means that network and interface objects lend themselves to using the list membership test syntax {{{ in }}} like this: + + {{{ + if address in network: + # do something + }}} + + Address, Network and Interface objects can be 'in' a network or an interface object. + + {{{ + >>> net4 = ipaddr.ip_network('192.0.2.0/25') + >>> net4 in ipaddr.ip_network('192.0.2.0/24') + True + >>> net4 in ipaddr.ip_interface('192.0.2.0/25') + True + net4 in ipaddr.ip_interface('192.0.2.0/26') + }}} + +== Comparisons == + + ipaddr provides some simply, hopefully intuitive ways to compare objects, where it makes sense. + + {{{ + >>> ipaddr.ip_address('192.0.2.1') < ipaddr.ip_address('192.0.2.2') + True + }}} + + A TypeError exception is raised if you try to compare objects of different versions or different types. + +== Exceptions raised by ipaddr == + + If you try to create an address/network/interface object with an invalid value for either the address or netmask, ipaddr will raise an AddressValueError or NetmaskValueError respectively. Both of these exceptions have ValueError as their parent class, so if you're not concerned with the particular type of error, you can do the following: + + {{{ + try: + ipaddr.ip_address(address) + except ValueError: + print 'address/netmask is invalid: %s' % address + }}}
\ No newline at end of file |