Python port of Google's libphonenumber

Overview

phonenumbers Python Library

Coverage Status

This is a Python port of Google's libphonenumber library It supports Python 2.5-2.7 and Python 3.x (in the same codebase, with no 2to3 conversion needed).

Original Java code is Copyright (C) 2009-2015 The Libphonenumber Authors.

Release HISTORY, derived from upstream release notes.

Installation

Install using pip with:

pip install phonenumbers

Example Usage

The main object that the library deals with is a PhoneNumber object. You can create this from a string representing a phone number using the parse function, but you also need to specify the country that the phone number is being dialled from (unless the number is in E.164 format, which is globally unique).

>>> import phonenumbers
>>> x = phonenumbers.parse("+442083661177", None)
>>> print(x)
Country Code: 44 National Number: 2083661177 Leading Zero: False
>>> type(x)
<class 'phonenumbers.phonenumber.PhoneNumber'>
>>> y = phonenumbers.parse("020 8366 1177", "GB")
>>> print(y)
Country Code: 44 National Number: 2083661177 Leading Zero: False
>>> x == y
True
>>> z = phonenumbers.parse("00 1 650 253 2222", "GB")  # as dialled from GB, not a GB number
>>> print(z)
Country Code: 1 National Number: 6502532222 Leading Zero(s): False

The PhoneNumber object that parse produces typically still needs to be validated, to check whether it's a possible number (e.g. it has the right number of digits) or a valid number (e.g. it's in an assigned exchange).

>>> z = phonenumbers.parse("+120012301", None)
>>> print(z)
Country Code: 1 National Number: 20012301 Leading Zero: False
>>> phonenumbers.is_possible_number(z)  # too few digits for USA
False
>>> phonenumbers.is_valid_number(z)
False
>>> z = phonenumbers.parse("+12001230101", None)
>>> print(z)
Country Code: 1 National Number: 2001230101 Leading Zero: False
>>> phonenumbers.is_possible_number(z)
True
>>> phonenumbers.is_valid_number(z)  # NPA 200 not used
False

The parse function will also fail completely (with a NumberParseException) on inputs that cannot be uniquely parsed, or that can't possibly be phone numbers.

>>> z = phonenumbers.parse("02081234567", None)  # no region, no + => unparseable
Traceback (most recent call last):
  File "phonenumbers/phonenumberutil.py", line 2350, in parse
    "Missing or invalid default region.")
phonenumbers.phonenumberutil.NumberParseException: (0) Missing or invalid default region.
>>> z = phonenumbers.parse("gibberish", None)
Traceback (most recent call last):
  File "phonenumbers/phonenumberutil.py", line 2344, in parse
    "The string supplied did not seem to be a phone number.")
phonenumbers.phonenumberutil.NumberParseException: (1) The string supplied did not seem to be a phone number.

Once you've got a phone number, a common task is to format it in a standardized format. There are a few formats available (under PhoneNumberFormat), and the format_number function does the formatting.

>>> phonenumbers.format_number(x, phonenumbers.PhoneNumberFormat.NATIONAL)
'020 8366 1177'
>>> phonenumbers.format_number(x, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
'+44 20 8366 1177'
>>> phonenumbers.format_number(x, phonenumbers.PhoneNumberFormat.E164)
'+442083661177'

If your application has a UI that allows the user to type in a phone number, it's nice to get the formatting applied as the user types. The AsYouTypeFormatter object allows this.

>>> formatter = phonenumbers.AsYouTypeFormatter("US")
>>> formatter.input_digit("6")
'6'
>>> formatter.input_digit("5")
'65'
>>> formatter.input_digit("0")
'650'
>>> formatter.input_digit("2")
'650 2'
>>> formatter.input_digit("5")
'650 25'
>>> formatter.input_digit("3")
'650 253'
>>> formatter.input_digit("2")
'650-2532'
>>> formatter.input_digit("2")
'(650) 253-22'
>>> formatter.input_digit("2")
'(650) 253-222'
>>> formatter.input_digit("2")
'(650) 253-2222'

Sometimes, you've got a larger block of text that may or may not have some phone numbers inside it. For this, the PhoneNumberMatcher object provides the relevant functionality; you can iterate over it to retrieve a sequence of PhoneNumberMatch objects. Each of these match objects holds a PhoneNumber object together with information about where the match occurred in the original string.

>>> text = "Call me at 510-748-8230 if it's before 9:30, or on 703-4800500 after 10am."
>>> for match in phonenumbers.PhoneNumberMatcher(text, "US"):
...     print(match)
...
PhoneNumberMatch [11,23) 510-748-8230
PhoneNumberMatch [51,62) 703-4800500
>>> for match in phonenumbers.PhoneNumberMatcher(text, "US"):
...     print(phonenumbers.format_number(match.number, phonenumbers.PhoneNumberFormat.E164))
...
+15107488230
+17034800500

You might want to get some information about the location that corresponds to a phone number. The geocoder.area_description_for_number does this, when possible.

>>> from phonenumbers import geocoder
>>> ch_number = phonenumbers.parse("0431234567", "CH")
>>> geocoder.description_for_number(ch_number, "de")
'Zürich'
>>> geocoder.description_for_number(ch_number, "en")
'Zurich'
>>> geocoder.description_for_number(ch_number, "fr")
'Zurich'
>>> geocoder.description_for_number(ch_number, "it")
'Zurigo'

For mobile numbers in some countries, you can also find out information about which carrier originally owned a phone number.

>>> from phonenumbers import carrier
>>> ro_number = phonenumbers.parse("+40721234567", "RO")
>>> carrier.name_for_number(ro_number, "en")
'Vodafone'

You might also be able to retrieve a list of time zone names that the number potentially belongs to.

>>> from phonenumbers import timezone
>>> gb_number = phonenumbers.parse("+447986123456", "GB")
>>> timezone.time_zones_for_number(gb_number)
('Atlantic/Reykjavik', 'Europe/London')

For more information about the other functionality available from the library, look in the unit tests or in the original libphonenumber project.

Memory Usage

The library includes a lot of metadata, potentially giving a significant memory overhead. There are two mechanisms for dealing with this.

  • The normal metadata (just over 2 MiB of generated Python code) for the core functionality of the library is loaded on-demand, on a region-by-region basis (i.e. the metadata for a region is only loaded on the first time it is needed).
  • Metadata for extended functionality is held in separate packages, which therefore need to be explicitly loaded separately. This affects:
    • The geocoding metadata (~19 MiB), which is held in phonenumbers.geocoder and used by the geocoding functions (geocoder.description_for_number, geocoder.description_for_valid_number or geocoder.country_name_for_number).
    • The carrier metadata (~1 MiB), which is held in phonenumbers.carrier and used by the mapping functions (carrier.name_for_number or carrier.name_for_valid_number).
    • The timezone metadata (~100 KiB), which is held in phonenumbers.timezone and used by the timezone functions (time_zones_for_number or time_zones_for_geographical_number).

The phonenumberslite version of the library does not include the geocoder, carrier and timezone packages, which can be useful if you have problems installing the main phonenumbers library due to space/memory limitations.

If you need to ensure that the metadata memory use is accounted for at start of day (i.e. that a subsequent on-demand load of metadata will not cause a pause or memory exhaustion):

  • Force-load the normal metadata by calling phonenumbers.PhoneMetadata.load_all().
  • Force-load the extended metadata by importing the appropriate packages (phonenumbers.geocoder, phonenumbers.carrier, phonenumbers.timezone).

The phonenumberslite version of the package does not include the geocoding, carrier and timezone metadata, which can be useful if you have problems installing the main phonenumbers package due to space/memory limitations.

Static Typing

The library includes a set of type stub files to support static type checking by library users. These stub files signal the types that should be used, and may also be of use in IDEs which have integrated type checking functionalities.

These files are written for Python 3, and as such type checking the library with these stubs on Python 2.5-2.7 is unsupported.

Project Layout

  • The python/ directory holds the Python code.
  • The resources/ directory is a copy of the resources/ directory from libphonenumber. This is not needed to run the Python code, but is needed when upstream changes to the master metadata need to be incorporated.
  • The tools/ directory holds the tools that are used to process upstream changes to the master metadata.
Owner
David Drysdale
David Drysdale
Simple tagging for django

django-taggit This is a Jazzband project. By contributing you agree to abide by the Contributor Code of Conduct and follow the guidelines. django-tagg

Jazzband 3k Jan 02, 2023
a little task queue for python

a lightweight alternative. huey is: a task queue (2019-04-01: version 2.0 released) written in python (2.7+, 3.4+) clean and simple API redis, sqlite,

Charles Leifer 4.3k Dec 29, 2022
The friendly PIL fork (Python Imaging Library)

Pillow Python Imaging Library (Fork) Pillow is the friendly PIL fork by Alex Clark and Contributors. PIL is the Python Imaging Library by Fredrik Lund

Pillow 10.4k Jan 03, 2023
Django backend of Helium's planner application

Helium Platform Project Prerequisites Python (= 3.6) Pip (= 9.0) MySQL (= 5.7) Redis (= 3.2) Getting Started The Platform is developed using Pytho

Helium Edu 17 Dec 14, 2022
Dockerizing Django with Postgres, Gunicorn, Nginx and Certbot. A fully Django starter project.

Dockerizing Django with Postgres, Gunicorn, Nginx and Certbot 🚀 Features A Django stater project with fully basic requirements for a production-ready

8 Jun 27, 2022
A clone of https://virgool.io written in django

Virgool clone A clone of virgool blog written in django Installation first rename the .env.sample to .env and fill it. with docker docker-compose up -

Danial Selmipoor 7 Dec 23, 2022
The little ASGI framework that shines. 🌟

✨ The little ASGI framework that shines. ✨ Documentation: https://www.starlette.io/ Community: https://discuss.encode.io/c/starlette Starlette Starlet

Encode 7.7k Dec 31, 2022
django-dashing is a customisable, modular dashboard application framework for Django to visualize interesting data about your project. Inspired in the dashboard framework Dashing

django-dashing django-dashing is a customisable, modular dashboard application framework for Django to visualize interesting data about your project.

talPor Solutions 703 Dec 22, 2022
Pinax is an open-source platform built on the Django Web Framework.

Symposion Pinax Pinax is an open-source platform built on the Django Web Framework. It is an ecosystem of reusable Django apps, themes, and starter pr

Pinax Project 295 Mar 20, 2022
Faker is a Python package that generates fake data for you.

Faker is a Python package that generates fake data for you. Whether you need to bootstrap your database, create good-looking XML documents, fill-in yo

Daniele Faraglia 15.2k Jan 01, 2023
A real-time photo feed using Django and Pusher

BUILD A PHOTO FEED USING DJANGO Here, we will learn about building a photo feed using Django. This is similar to instagram, but a stripped off version

samuel ogundipe 4 Jan 01, 2020
Blog focused on skills enhancement and knowledge sharing. Tech Stack's: Vue.js, Django and Django-Ninja

Blog focused on skills enhancement and knowledge sharing. Tech Stack's: Vue.js, Django and Django-Ninja

Wanderson Fontes 2 Sep 21, 2022
pytest-django allows you to test your Django project/applications with the pytest testing tool.

pytest-django allows you to test your Django project/applications with the pytest testing tool.

pytest-dev 1.1k Dec 14, 2022
Customize the behavior of django.contrib.auth permissions.

Customizando o comportamento do django.contrib.auth. O que queremos? Não criar as permissões padrões automaticamente (add, delete, view, read). Criar

Henrique Bastos 7 Nov 26, 2022
GeoDjango provides geospatial extensions to the Django web dev framework

Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. All documentation is in the "docs" directo

Paul Smith 20 Sep 20, 2022
Wagtail - Vue - Django : The initial environment of full-stack local dev web app with wagtail and vue

Wagtail - Vue - Django : The initial environment of full-stack local dev web app with wagtail and vue. A demo to show how to use .vue files inside django app.

Quang PHAM 2 Oct 20, 2022
A GitHub Action for checking Django migrations

🔍 Django migrations checker A GitHub Action for checking Django migrations About This repository contains a Github Action that checks Django migratio

Oda 5 Nov 15, 2022
A web app which allows user to query the weather info of any place in the world

weather-app This is a web app which allows user to get the weather info of any place in the world as soon as possible. It makes use of OpenWeatherMap

Oladipo Adesiyan 3 Sep 20, 2021
Django-Docker - Django Installation Guide on Docker

Guía de instalación del Framework Django en Docker Introducción: Con esta guía p

Victor manuel torres 3 Dec 02, 2022
Radically simplified static file serving for Python web apps

WhiteNoise Radically simplified static file serving for Python web apps With a couple of lines of config WhiteNoise allows your web app to serve its o

Dave Evans 2.1k Dec 15, 2022