|
| 1 | +phonenumbers Python Library |
| 2 | + |
| 3 | +This is a Python port of libphonenumber, originally from: |
| 4 | + http://code.google.com/p/libphonenumber/. |
| 5 | + |
| 6 | +Original Java code is Copyright (C) 2009-2011 Google Inc. |
| 7 | + |
| 8 | +=========================== |
| 9 | +phonenumbers Installation |
| 10 | +=========================== |
| 11 | + |
| 12 | +Install using setup.py: |
| 13 | + $ tar xfz phonenumbers-3.1a1.tar.gz |
| 14 | + $ cd phonenumbers-3.1a1 |
| 15 | + $ python setup.py build |
| 16 | + $ sudo python setup.py install # or su first |
| 17 | + |
| 18 | + |
| 19 | +=========================== |
| 20 | +Running Tests |
| 21 | +=========================== |
| 22 | + |
| 23 | +With phonenumbers on the Python path, run: |
| 24 | + $ python tests/__init__.py |
| 25 | + |
| 26 | + |
| 27 | +=========================== |
| 28 | +Auto-Generating Python Code |
| 29 | +=========================== |
| 30 | + |
| 31 | +The code within the phonenumbers/data subdirectory is automatically |
| 32 | +generated from the master XML metadata file |
| 33 | +(resources/PhoneNumberMetadata.xml). |
| 34 | + |
| 35 | +The script buildmetadatafromxml.py performs this autogeneration. |
| 36 | +Run it with: |
| 37 | + python buildmetadatafromxml.py resources/PhoneNumberMetadata.xml phonenumbers/data/ |
| 38 | + |
| 39 | +This script requires the lxml Python package to be installed. |
| 40 | + |
| 41 | +This will: |
| 42 | + - Create the phonenumbers/data/ directory if not present. |
| 43 | + - Create a collection of files, one for each region code: |
| 44 | + phonenumbers/data/region_<code>.py |
| 45 | + Each file contains the Python constructors for the metadata for that |
| 46 | + region. |
| 47 | + - Create a file phonenumbers/data/__init__.py which |
| 48 | + accumulates all of the per-region files. |
| 49 | + |
| 50 | +This approach results in a large set of Python files, but makes it easy |
| 51 | +to apply local fixes to the formatting metadata. |
| 52 | + |
| 53 | + |
| 54 | +=========================== |
| 55 | +Library Developer Internals |
| 56 | +=========================== |
| 57 | + |
| 58 | +The Python code is derived from the original Java code, and |
| 59 | +mostly sticks to the structure of that code to make it easier |
| 60 | +to include future changes to the upstream code. |
| 61 | + |
| 62 | +However, there are a number of differences: |
| 63 | + - Naming conventions are converted to Python standards; in |
| 64 | + particular, method names are connected_with_underscores |
| 65 | + rather than beingInCamelCase. |
| 66 | + - The PhoneNumber and PhoneMetadata classes are written by hand |
| 67 | + based on the Java code and the protocol buffer definitions, |
| 68 | + rather than by using the the Python protocol buffer library. |
| 69 | + This makes the mapping to the Java code easier to follow, and |
| 70 | + allows for the custom modifications that have been made to |
| 71 | + the base protocol buffer. Attribute values of None are used |
| 72 | + to indicate that a particular (optional) attribute is not |
| 73 | + present (instead of hasAttribute() methods). |
| 74 | + - The Java PhoneNumberUtil class was a singleton, and so its |
| 75 | + contents are included at the top level in phonenumberutil.py. |
| 76 | + Static methods from the PhoneNumberUtil class thus become |
| 77 | + functions in phonenumberutil.py; private and package methods |
| 78 | + get a leading underscore in their name. |
| 79 | + - Accessor functions (setAttribute() and getAttribute() are |
| 80 | + avoided, and direct access to attributes is used instead. |
| 81 | + - Methods named get_something_from(object) are typically renamed |
| 82 | + to something_from(object). |
| 83 | + - The format() methods in PhoneNumberUtil were renamed to |
| 84 | + format_number() to avoid clashing with the Python built-in |
| 85 | + format(). |
| 86 | + - The internals of phonenumberutil.py do not have logging. |
| 87 | + - The PhoneNumber and PhoneMetadata classes are written by hand. |
| 88 | + |
| 89 | +Much of the functionality of this library depends on regular |
| 90 | +expressions, so it's worth highlighting the translation between |
| 91 | +Java and Python regexps: |
| 92 | + - Java replacement group references are "$1 $2" etc, Python's are |
| 93 | + "\1 \2" etc. |
| 94 | + - Java Matcher(x).lookingAt() translates to Python re_obj.match(x) |
| 95 | + - Java Matcher(x).find() translates to Python m = re.search(x). |
| 96 | + - Java Matcher(x).matches() translates to Python m = re_obj.match(x) |
| 97 | + together with a check that m.end() == len(x). |
| 98 | +The last of these is encapsulated in the fullmatch() function in |
| 99 | +re_util.py. |
0 commit comments