Skip to content

Commit 60af4fc

Browse files
committed
Add initial Python implementation.
This includes a full set of functionality, with all unit tests passing (although there's a couple of UT failures when they're run from setup.py).
1 parent ddabb77 commit 60af4fc

27 files changed

Lines changed: 27438 additions & 0 deletions

python/.cvsignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.coverage
2+
*.pyc
3+
dist
4+
MANIFEST
5+
phonenumbers.egg-info

python/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.coverage
2+
*.pyc
3+
dist
4+
MANIFEST
5+
phonenumbers.egg-info

python/.svnignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.coverage
2+
*.pyc
3+
dist
4+
MANIFEST
5+
phonenumbers.egg-info

python/HISTORY

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
=====================
3+
What's new in 3.1a1
4+
=====================
5+
6+
Initial port of libphonenumber, based on upstream version 3.1,
7+
from http://code.google.com/p/libphonenumber/
8+
9+
Subversion revision 169 of
10+
http://libphonenumber.googlecode.com/svn/trunk/java

python/MANIFEST.in

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
recursive-include tests *.py
2+
include MANIFEST.in
3+
include MANIFEST
4+
include HISTORY
5+
include setup.py
6+
include buildmetadatafromxml.py
7+
exclude .*ignore

python/README

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
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

Comments
 (0)