summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGoogle Code Exporter <GoogleCodeExporter@users.noreply.github.com>2015-03-18 19:12:25 -0400
committerGoogle Code Exporter <GoogleCodeExporter@users.noreply.github.com>2015-03-18 19:12:25 -0400
commit4f9b3a6ed943a170425aa53a636267cfba0fe3a3 (patch)
treedaad009255d1d7d7e9bfe961b5b4e8f79a17404e
downloadipaddr-py-wiki.tar.gz
Migrating wiki contents from Google Codewiki
-rw-r--r--ProjectHome.md28
-rw-r--r--ReleaseNotes.md293
-rw-r--r--Using3144.md261
3 files changed, 582 insertions, 0 deletions
diff --git a/ProjectHome.md b/ProjectHome.md
new file mode 100644
index 0000000..14847a2
--- /dev/null
+++ b/ProjectHome.md
@@ -0,0 +1,28 @@
+An IPv4/IPv6 manipulation library in Python. This library is used to create/poke/manipulate IPv4 and IPv6 addresses and prefixes.
+
+## Releases now on google drive ##
+
+Releases for ipaddr-py can be found on google drive [here](https://googledrive.com/host/0B6wLlfdySbEUMkh1ZWhpZk1pZmc/), or on Pypi [here](https://pypi.python.org/pypi/ipaddr/).
+
+The current version is [2.1.11](https://googledrive.com/host/0B6wLlfdySbEUMkh1ZWhpZk1pZmc/ipaddr-2.1.11.tar.gz) ([on pypi](https://pypi.python.org/packages/source/i/ipaddr/ipaddr-2.1.11.tar.gz))
+
+## Contributing ##
+
+Join the [development mailing list](http://groups.google.com/group/ipaddr-py-dev), which is cc'd on all bugs and commits.
+
+## Patches ##
+
+We review patches before commit, using [Rietveld](http://codereview.appspot.com/). Use [upload.py](http://codereview.appspot.com/static/upload.py) to upload your patch.
+
+Please do not change the version number in your patch.
+
+## Legal issues ##
+
+Before we can accept a patch from you (if you are not a Google employee), you must sign a Contributor License Agreement (CLA). The CLA protects you and us.
+
+ * If you are an individual writing original source code and you're sure you own the intellectual property, then you'll need to sign an [individual CLA](http://code.google.com/legal/individual-cla-v1.0.html). Individual CLAs can be signed electronically.
+ * If you work for a company that wants to allow you to contribute your work, then you'll need to sign a [corporate CLA](http://code.google.com/legal/corporate-cla-v1.0.html).
+
+The Google CLA is based on Apache's. Note that unlike some projects (notably GNU projects), we do _not_ require a transfer of copyright. You still own the patch.
+
+Sadly, our lawyers say that even the smallest patch needs a CLA.
diff --git a/ReleaseNotes.md b/ReleaseNotes.md
new file mode 100644
index 0000000..f1dd547
--- /dev/null
+++ b/ReleaseNotes.md
@@ -0,0 +1,293 @@
+# Release Notes #
+
+Here are the visible changes for each release.
+
+## 2.1.11 ##
+
+(2014-01-31)
+
+ * hostmask parsing bug fixed by pmarks (a nearly complete rewrite of the mask parsing code)
+ * i97, incorrectly parses some v6 addresses.
+ * docstring typos.
+ * i95, refer to the nets in the exception raised by collapse\_address\_list
+ * add license to boilerplate to test-2to3.sh
+
+## 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](https://code.google.com/p/ipaddr-py/source/detail?r=176) and [r196](https://code.google.com/p/ipaddr-py/source/detail?r=196).
+ * 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](https://code.google.com/p/ipaddr-py/issues/detail?id=66), more invalid IPv6 addresses will be rejected
+
+## 2.1.3 ##
+
+(2010-06-12)
+
+ * fix for [issue61](https://code.google.com/p/ipaddr-py/issues/detail?id=61), 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](https://code.google.com/p/ipaddr-py/issues/detail?id=57)).
+ * fix address\_exclude issue where excluding an address from itself puked.
+ * make sure addresses and networks don't compare.
+ * doc-string fixes ([issue60](https://code.google.com/p/ipaddr-py/issues/detail?id=60))
+ * and masked() method to _BaseNet to return a network object with the host bits masked out ([issue58](https://code.google.com/p/ipaddr-py/issues/detail?id=58))
+ * 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.
+
+ 1. 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')
+```
+
+ 1. 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](https://code.google.com/p/ipaddr-py/source/detail?r=77) 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](https://code.google.com/p/ipaddr-py/source/detail?r=59) 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](https://code.google.com/p/ipaddr-py/source/detail?r=63) .prefixlen is now a property. (pmoody)
+ * [r64](https://code.google.com/p/ipaddr-py/source/detail?r=64) Stronger validation. (Philipp Hagemeister)
+ * [r65](https://code.google.com/p/ipaddr-py/source/detail?r=65) 1.2.3.4 is not a valid v6 address, so we can simplify the constructor. (Philipp Hagemeister)
+ * [r66](https://code.google.com/p/ipaddr-py/source/detail?r=66) 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](https://code.google.com/p/ipaddr-py/source/detail?r=68) New method .packed(). (Philipp Hagemeister)
+ * [r69](https://code.google.com/p/ipaddr-py/source/detail?r=69) 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](https://code.google.com/p/ipaddr-py/source/detail?r=71) Fix off-by-one bug ([issue 15](https://code.google.com/p/ipaddr-py/issues/detail?id=15)). (gpsmith)
+
+## 1.0.2 ##
+ * [r52](https://code.google.com/p/ipaddr-py/source/detail?r=52) Force the return value in testHexRepresentation to uppercase to workaround Python version. (smart)
+ * [r51](https://code.google.com/p/ipaddr-py/source/detail?r=51) Fix testHexRepresentation(). Hex representations of longs are uppercase. (smart)
+ * [r50](https://code.google.com/p/ipaddr-py/source/detail?r=50) Remove trailing whitespace and update docstrings. (smart)
+ * [r44](https://code.google.com/p/ipaddr-py/source/detail?r=44). this makes the spacing and docstrings pep8 compliant. (pmoody)
+ * [r43](https://code.google.com/p/ipaddr-py/source/detail?r=43). 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](https://code.google.com/p/ipaddr-py/source/detail?r=40). implment int and hex. will need to be updated for py3k (to use index) (pmoody)
+ * [r38](https://code.google.com/p/ipaddr-py/source/detail?r=38) A cleanup from [issue 9](https://code.google.com/p/ipaddr-py/issues/detail?id=9) : Make exception messages consistent for IP(''), IPv4(''), IPv6('') (smart)
+ * [r37](https://code.google.com/p/ipaddr-py/source/detail?r=37) Fix for [issue 9](https://code.google.com/p/ipaddr-py/issues/detail?id=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. \ No newline at end of file
diff --git a/Using3144.md b/Using3144.md
new file mode 100644
index 0000000..b871dea
--- /dev/null
+++ b/Using3144.md
@@ -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<sup>32</sup> bits and IPv6 addresses are 2<sup>128</sup> bits, all integers <= 2<sup>32</sup> - 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