geoip2-2.7.0/0000755000175000017500000000000013230142214012567 5ustar greggreg00000000000000geoip2-2.7.0/MANIFEST.in0000664000175000017500000000015712766603306014353 0ustar greggreg00000000000000include HISTORY.rst README.rst LICENSE requirements.txt tests/*.py tests/data/test-data/*.mmdb graft docs/html geoip2-2.7.0/requirements.txt0000664000175000017500000000003712766603306016076 0ustar greggreg00000000000000requests>=2.9 maxminddb>=1.2.1 geoip2-2.7.0/HISTORY.rst0000644000175000017500000001561413230141656014502 0ustar greggreg00000000000000.. :changelog: History ------- 2.7.0 (2018-01-18) ++++++++++++++++++ * The ``is_in_european_union`` attribute was added to ``geoip2.record.Country`` and ``geoip2.record.RepresentedCountry``. This attribute is ``True`` if the country is a member state of the European Union. 2.6.0 (2017-10-27) ++++++++++++++++++ * The following new anonymizer attributes were added to ``geoip2.record.Traits`` for use with GeoIP2 Precision Insights: ``is_anonymous``, ``is_anonymous_vpn``, ``is_hosting_provider``, ``is_public_proxy``, and ``is_tor_exit_node``. 2.5.0 (2017-05-08) ++++++++++++++++++ * Added support for GeoLite2 ASN database. * Corrected documentation of errors raised when using the database reader. Reported by Radek Holý. GitHub #42. 2.4.2 (2016-12-08) ++++++++++++++++++ * Recent releases of ``requests`` (2.12.2 and 2.12.3) require that the username for basic authentication be a string or bytes. The documentation for this module uses an integer for the ``user_id``, which will break with these ``requests`` versions. The ``user_id`` is now converted to bytes before being passed to ``requests``. 2.4.1 (2016-11-21) ++++++++++++++++++ * Updated documentation to clarify what the accuracy radius refers to. * Fixed classifiers in ``setup.py``. 2.4.0 (2016-06-10) ++++++++++++++++++ * This module now uses ``ipaddress`` on Python 2 rather than ``ipaddr`` to validate IP addresses before sending them to the web service. * Added handling of additional error codes that the web service may return. * PEP 257 documentation fixes. * Updated documentation to reflect that the accuracy radius is now included in City. * Previously, the source distribution was missing some tests and test databases. This has been corrected. Reported by Lumir Balhar. 2.3.0 (2016-04-15) ++++++++++++++++++ * Added support for the GeoIP2 Enterprise database. * ``geoip2.database.Reader`` now supports being used in a ``with`` statement (PEP 343). (PR from Nguyễn Hồng Quân. GitHub #29) 2.2.0 (2015-06-29) ++++++++++++++++++ * The ``geoip2.records.Location`` class has been updated to add attributes for the ``average_income`` and ``population_density`` fields provided by the Insights web service. * The ``is_anonymous_proxy`` and ``is_satellite_provider`` properties on ``geoip2.records.Traits`` have been deprecated. Please use our `GeoIP2 Anonymous IP database `_ to determine whether an IP address is used by an anonymizing service. 2.1.0 (2014-12-09) ++++++++++++++++++ * The reader now supports pure Python file and memory modes. If you are not using the C extension and your Python does not provide the ``mmap`` module, the file mode will be used by default. You can explicitly set the mode using the ``mode`` keyword argument with the ``MODE_AUTO``, ``MODE_MMAP``, ``MODE_MMAP_EXT``, ``MODE_FILE``, and ``MODE_MEMORY`` constants exported by ``geoip2.database``. 2.0.2 (2014-10-28) ++++++++++++++++++ * Added support for the GeoIP2 Anonymous IP database. The ``geoip2.database.Reader`` class now has an ``anonymous_ip()`` method which returns a ``geoip2.models.AnonymousIP`` object. * Added ``__repr__`` and ``__eq__`` methods to the model and record classes to aid in debugging and using the library from a REPL. 2.0.1 (2014-10-17) ++++++++++++++++++ * The constructor for ``geoip2.webservice.Client`` now takes an optional ``timeout`` parameter. (PR from arturro. GitHub #15) 2.0.0 (2014-09-22) ++++++++++++++++++ * First production release. 0.7.0 (2014-09-15) ++++++++++++++++++ * BREAKING CHANGES: - The deprecated ``city_isp_org()`` and ``omni()`` methods have been removed. - The ``geoip2.database.Reader`` lookup methods (e.g., ``city()``, ``isp()``) now raise a ``TypeError`` if they are used with a database that does not match the method. In particular, doing a ``city()`` lookup on a GeoIP2 Country database will result in an error and vice versa. * A ``metadata()`` method has been added to the ``geoip2.database.Reader`` class. This returns a ``maxminddb.reader.Metadata`` object with information about the database. 0.6.0 (2014-07-22) ++++++++++++++++++ * The web service client API has been updated for the v2.1 release of the web service. In particular, the ``city_isp_org`` and ``omni`` methods on ``geoip2.webservice.Client`` should be considered deprecated. The ``city`` method now provides all of the data formerly provided by ``city_isp_org``, and the ``omni`` method has been replaced by the ``insights`` method. **Note:** In v2.1 of the web service, ``accuracy_radius``, ``autonomous_system_number``, and all of the ``confidence`` values were changed from unicode to integers. This may affect how you use these values from this API. * Support was added for the GeoIP2 Connection Type, Domain, and ISP databases. 0.5.1 (2014-03-28) ++++++++++++++++++ * Switched to Apache 2.0 license. 0.5.0 (2014-02-11) ++++++++++++++++++ * Fixed missing import statements for geoip2.errors and geoip2.models. (Gustavo J. A. M. Carneiro) * Minor documentation and code cleanup * Added requirement for maxminddb v0.3.0, which includes a pure Python database reader. Removed the ``extras_require`` for maxminddb. 0.4.2 (2013-12-20) ++++++++++++++++++ * Added missing geoip2.models import to geoip.database. * Documentation updates. 0.4.1 (2013-10-25) ++++++++++++++++++ * Read in ``README.rst`` as UTF-8 in ``setup.py``. 0.4.0 (2013-10-21) ++++++++++++++++++ * API CHANGE: Changed the ``languages`` keyword argument to ``locales`` on the constructors for ``geoip.webservice.Client`` and ``geoip.database.Reader``. 0.3.1 (2013-10-15) ++++++++++++++++++ * Fixed packaging issue with extras_require. 0.3.0 (2013-10-15) ++++++++++++++++++ * IMPORTANT: ``geoip.webservices`` was renamed ``geoip.webservice`` as it contains only one class. * Added GeoIP2 database reader using ``maxminddb``. This does not work with PyPy as it relies on a C extension. * Added more specific exceptions for web service client. 0.2.2 (2013-06-20) ++++++++++++++++++ * Fixed a bug in the model objects that prevented ``longitude`` and ``metro_code`` from being used. 0.2.1 (2013-06-10) ++++++++++++++++++ * First official beta release. * Documentation updates and corrections. 0.2.0 (2013-05-29) ++++++++++++++++++ * Support for Python 3.2 was dropped. * The methods to call the web service on the ``Client`` object now validate the IP addresses before calling the web service. This requires the ``ipaddr`` module on Python 2.x. * We now support more languages. The new languages are de, es, fr, and pt-BR. * The REST API now returns a record with data about your account. There is a new geoip.records.MaxMind class for this data. * Rename model.continent.continent_code to model.continent.code. * Documentation updates. 0.1.1 (2013-05-14) ++++++++++++++++++ * Documentation and packaging updates 0.1.0 (2013-05-13) ++++++++++++++++++ * Initial release geoip2-2.7.0/LICENSE0000664000175000017500000002613612301446773013625 0ustar greggreg00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. geoip2-2.7.0/README.rst0000644000175000017500000003072013104141142014257 0ustar greggreg00000000000000========================= MaxMind GeoIP2 Python API ========================= Description ----------- This package provides an API for the GeoIP2 `web services `_ and `databases `_. The API also works with MaxMind's free `GeoLite2 databases `_. Installation ------------ To install the ``geoip2`` module, type: .. code-block:: bash $ pip install geoip2 If you are not able to use pip, you may also use easy_install from the source directory: .. code-block:: bash $ easy_install . Database Reader Extension ^^^^^^^^^^^^^^^^^^^^^^^^^ If you wish to use the C extension for the database reader, you must first install the `libmaxminddb C API `_. Please `see the instructions distributed with it `_. IP Geolocation Usage -------------------- IP geolocation is inherently imprecise. Locations are often near the center of the population. Any location provided by a GeoIP2 database or web service should not be used to identify a particular address or household. Usage ----- To use this API, you first create either a web service object with your MaxMind ``user_id`` and ``license_key`` or a database reader object with the path to your database file. After doing this, you may call the method corresponding to request type (e.g., ``city`` or ``country``), passing it the IP address you want to look up. If the request succeeds, the method call will return a model class for the end point you called. This model in turn contains multiple record classes, each of which represents part of the data returned by the web service. If the request fails, the client class throws an exception. Web Service Example ------------------- .. code-block:: pycon >>> import geoip2.webservice >>> >>> # This creates a Client object that can be reused across requests. >>> # Replace "42" with your user ID and "license_key" with your license >>> # key. >>> client = geoip2.webservice.Client(42, 'license_key') >>> >>> # Replace "insights" with the method corresponding to the web service >>> # that you are using, e.g., "country", "city". >>> response = client.insights('128.101.101.101') >>> >>> response.country.iso_code 'US' >>> response.country.name 'United States' >>> response.country.names['zh-CN'] u'美国' >>> >>> response.subdivisions.most_specific.name 'Minnesota' >>> response.subdivisions.most_specific.iso_code 'MN' >>> >>> response.city.name 'Minneapolis' >>> >>> response.postal.code '55455' >>> >>> response.location.latitude 44.9733 >>> response.location.longitude -93.2323 Web Service Client Exceptions ----------------------------- For details on the possible errors returned by the web service itself, see http://dev.maxmind.com/geoip/geoip2/web-services for the GeoIP2 Precision web service docs. If the web service returns an explicit error document, this is thrown as a ``AddressNotFoundError``, ``AuthenticationError``, ``InvalidRequestError``, or ``OutOfQueriesError`` as appropriate. These all subclass ``GeoIP2Error``. If some other sort of error occurs, this is thrown as an ``HTTPError``. This is thrown when some sort of unanticipated error occurs, such as the web service returning a 500 or an invalid error document. If the web service returns any status code besides 200, 4xx, or 5xx, this also becomes an ``HTTPError``. Finally, if the web service returns a 200 but the body is invalid, the client throws a ``GeoIP2Error``. Database Example ------------------- City Database ^^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> reader = geoip2.database.Reader('/path/to/GeoLite2-City.mmdb') >>> >>> # Replace "city" with the method corresponding to the database >>> # that you are using, e.g., "country". >>> response = reader.city('128.101.101.101') >>> >>> response.country.iso_code 'US' >>> response.country.name 'United States' >>> response.country.names['zh-CN'] u'美国' >>> >>> response.subdivisions.most_specific.name 'Minnesota' >>> response.subdivisions.most_specific.iso_code 'MN' >>> >>> response.city.name 'Minneapolis' >>> >>> response.postal.code '55455' >>> >>> response.location.latitude 44.9733 >>> response.location.longitude -93.2323 >>> reader.close() Anonymous IP Database ^^^^^^^^^^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> reader = geoip2.database.Reader('/path/to/GeoIP2-Anonymous-IP.mmdb') >>> >>> response = reader.anonymous_ip('85.25.43.84') >>> >>> response.is_anonymous True >>> response.is_anonymous_vpn False >>> response.is_hosting_provider False >>> response.is_public_proxy False >>> response.is_tor_exit_node True >>> response.ip_address '128.101.101.101' >>> reader.close() ASN Database ^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> with geoip2.database.Reader('/path/to/GeoLite2-ASN.mmdb') as reader: >>> response = reader.asn('1.128.0.0') >>> response.autonomous_system_number 1221 >>> response.autonomous_system_organization 'Telstra Pty Ltd' Connection-Type Database ^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> reader = geoip2.database.Reader('/path/to/GeoIP2-Connection-Type.mmdb') >>> >>> response = reader.connection_type('128.101.101.101') >>> >>> response.connection_type 'Corporate' >>> response.ip_address '128.101.101.101' >>> reader.close() Domain Database ^^^^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> reader = geoip2.database.Reader('/path/to/GeoIP2-Domain.mmdb') >>> >>> response = reader.domain('128.101.101.101') >>> >>> response.domain 'umn.edu' >>> response.ip_address '128.101.101.101' >>> reader.close() Enterprise Database ^^^^^^^^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> with geoip2.database.Reader('/path/to/GeoIP2-Enterprise.mmdb') as reader: >>> >>> # Use the .enterprise method to do a lookup in the Enterprise database >>> response = reader.enterprise('128.101.101.101') >>> >>> response.country.confidence 99 >>> response.country.iso_code 'US' >>> response.country.name 'United States' >>> response.country.names['zh-CN'] u'美国' >>> >>> response.subdivisions.most_specific.name 'Minnesota' >>> response.subdivisions.most_specific.iso_code 'MN' >>> response.subdivisions.most_specific.confidence 77 >>> >>> response.city.name 'Minneapolis' >>> response.country.confidence 11 >>> >>> response.postal.code '55455' >>> >>> response.location.accuracy_radius 50 >>> response.location.latitude 44.9733 >>> response.location.longitude -93.2323 ISP Database ^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> reader = geoip2.database.Reader('/path/to/GeoIP2-ISP.mmdb') >>> >>> response = reader.isp('1.128.0.0') >>> >>> response.autonomous_system_number 1221 >>> response.autonomous_system_organization 'Telstra Pty Ltd' >>> response.isp 'Telstra Internet' >>> response.organization 'Telstra Internet' >>> response.ip_address '128.101.101.101' >>> reader.close() Database Reader Exceptions -------------------------- If the database file does not exist or is not readable, the constructor will raise a ``FileNotFoundError`` on Python 3 or an ``IOError`` on Python 2. If the IP address passed to a method is invalid, a ``ValueError`` will be raised. If the file is invalid or there is a bug in the reader, a ``maxminddb.InvalidDatabaseError`` will be raised with a description of the problem. If an IP address is not in the database, a ``AddressNotFoundError`` will be raised. Values to use for Database or Dictionary Keys --------------------------------------------- **We strongly discourage you from using a value from any ``names`` property as a key in a database or dictionaries.** These names may change between releases. Instead we recommend using one of the following: * ``geoip2.records.City`` - ``city.geoname_id`` * ``geoip2.records.Continent`` - ``continent.code`` or ``continent.geoname_id`` * ``geoip2.records.Country`` and ``geoip2.records.RepresentedCountry`` - ``country.iso_code`` or ``country.geoname_id`` * ``geoip2.records.subdivision`` - ``subdivision.iso_code`` or ``subdivision.geoname_id`` What data is returned? ---------------------- While many of the models contain the same basic records, the attributes which can be populated vary between web service end points or databases. In addition, while a model may offer a particular piece of data, MaxMind does not always have every piece of data for any given IP address. Because of these factors, it is possible for any request to return a record where some or all of the attributes are unpopulated. The only piece of data which is always returned is the ``ip_address`` attribute in the ``geoip2.records.Traits`` record. Integration with GeoNames ------------------------- `GeoNames `_ offers web services and downloadable databases with data on geographical features around the world, including populated places. They offer both free and paid premium data. Each feature is uniquely identified by a ``geoname_id``, which is an integer. Many of the records returned by the GeoIP web services and databases include a ``geoname_id`` field. This is the ID of a geographical feature (city, region, country, etc.) in the GeoNames database. Some of the data that MaxMind provides is also sourced from GeoNames. We source things like place names, ISO codes, and other similar data from the GeoNames premium data set. Reporting Data Problems ----------------------- If the problem you find is that an IP address is incorrectly mapped, please `submit your correction to MaxMind `_. If you find some other sort of mistake, like an incorrect spelling, please check the `GeoNames site `_ first. Once you've searched for a place and found it on the GeoNames map view, there are a number of links you can use to correct data ("move", "edit", "alternate names", etc.). Once the correction is part of the GeoNames data set, it will be automatically incorporated into future MaxMind releases. If you are a paying MaxMind customer and you're not sure where to submit a correction, please `contact MaxMind support `_ for help. Requirements ------------ This code requires Python 2.6+ or 3.3+. Older versions are not supported. This library has been tested with CPython and PyPy. The Requests HTTP library is also required. See for details. Versioning ---------- The GeoIP2 Python API uses `Semantic Versioning `_. Support ------- Please report all issues with this code using the `GitHub issue tracker `_ If you are having an issue with a MaxMind service that is not specific to the client API, please contact `MaxMind support `_ for assistance. geoip2-2.7.0/PKG-INFO0000644000175000017500000004116613230142214013674 0ustar greggreg00000000000000Metadata-Version: 1.1 Name: geoip2 Version: 2.7.0 Summary: MaxMind GeoIP2 API Home-page: http://www.maxmind.com/ Author: Gregory Oschwald Author-email: goschwald@maxmind.com License: Apache License, Version 2.0 Description-Content-Type: UNKNOWN Description: ========================= MaxMind GeoIP2 Python API ========================= Description ----------- This package provides an API for the GeoIP2 `web services `_ and `databases `_. The API also works with MaxMind's free `GeoLite2 databases `_. Installation ------------ To install the ``geoip2`` module, type: .. code-block:: bash $ pip install geoip2 If you are not able to use pip, you may also use easy_install from the source directory: .. code-block:: bash $ easy_install . Database Reader Extension ^^^^^^^^^^^^^^^^^^^^^^^^^ If you wish to use the C extension for the database reader, you must first install the `libmaxminddb C API `_. Please `see the instructions distributed with it `_. IP Geolocation Usage -------------------- IP geolocation is inherently imprecise. Locations are often near the center of the population. Any location provided by a GeoIP2 database or web service should not be used to identify a particular address or household. Usage ----- To use this API, you first create either a web service object with your MaxMind ``user_id`` and ``license_key`` or a database reader object with the path to your database file. After doing this, you may call the method corresponding to request type (e.g., ``city`` or ``country``), passing it the IP address you want to look up. If the request succeeds, the method call will return a model class for the end point you called. This model in turn contains multiple record classes, each of which represents part of the data returned by the web service. If the request fails, the client class throws an exception. Web Service Example ------------------- .. code-block:: pycon >>> import geoip2.webservice >>> >>> # This creates a Client object that can be reused across requests. >>> # Replace "42" with your user ID and "license_key" with your license >>> # key. >>> client = geoip2.webservice.Client(42, 'license_key') >>> >>> # Replace "insights" with the method corresponding to the web service >>> # that you are using, e.g., "country", "city". >>> response = client.insights('128.101.101.101') >>> >>> response.country.iso_code 'US' >>> response.country.name 'United States' >>> response.country.names['zh-CN'] u'美国' >>> >>> response.subdivisions.most_specific.name 'Minnesota' >>> response.subdivisions.most_specific.iso_code 'MN' >>> >>> response.city.name 'Minneapolis' >>> >>> response.postal.code '55455' >>> >>> response.location.latitude 44.9733 >>> response.location.longitude -93.2323 Web Service Client Exceptions ----------------------------- For details on the possible errors returned by the web service itself, see http://dev.maxmind.com/geoip/geoip2/web-services for the GeoIP2 Precision web service docs. If the web service returns an explicit error document, this is thrown as a ``AddressNotFoundError``, ``AuthenticationError``, ``InvalidRequestError``, or ``OutOfQueriesError`` as appropriate. These all subclass ``GeoIP2Error``. If some other sort of error occurs, this is thrown as an ``HTTPError``. This is thrown when some sort of unanticipated error occurs, such as the web service returning a 500 or an invalid error document. If the web service returns any status code besides 200, 4xx, or 5xx, this also becomes an ``HTTPError``. Finally, if the web service returns a 200 but the body is invalid, the client throws a ``GeoIP2Error``. Database Example ------------------- City Database ^^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> reader = geoip2.database.Reader('/path/to/GeoLite2-City.mmdb') >>> >>> # Replace "city" with the method corresponding to the database >>> # that you are using, e.g., "country". >>> response = reader.city('128.101.101.101') >>> >>> response.country.iso_code 'US' >>> response.country.name 'United States' >>> response.country.names['zh-CN'] u'美国' >>> >>> response.subdivisions.most_specific.name 'Minnesota' >>> response.subdivisions.most_specific.iso_code 'MN' >>> >>> response.city.name 'Minneapolis' >>> >>> response.postal.code '55455' >>> >>> response.location.latitude 44.9733 >>> response.location.longitude -93.2323 >>> reader.close() Anonymous IP Database ^^^^^^^^^^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> reader = geoip2.database.Reader('/path/to/GeoIP2-Anonymous-IP.mmdb') >>> >>> response = reader.anonymous_ip('85.25.43.84') >>> >>> response.is_anonymous True >>> response.is_anonymous_vpn False >>> response.is_hosting_provider False >>> response.is_public_proxy False >>> response.is_tor_exit_node True >>> response.ip_address '128.101.101.101' >>> reader.close() ASN Database ^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> with geoip2.database.Reader('/path/to/GeoLite2-ASN.mmdb') as reader: >>> response = reader.asn('1.128.0.0') >>> response.autonomous_system_number 1221 >>> response.autonomous_system_organization 'Telstra Pty Ltd' Connection-Type Database ^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> reader = geoip2.database.Reader('/path/to/GeoIP2-Connection-Type.mmdb') >>> >>> response = reader.connection_type('128.101.101.101') >>> >>> response.connection_type 'Corporate' >>> response.ip_address '128.101.101.101' >>> reader.close() Domain Database ^^^^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> reader = geoip2.database.Reader('/path/to/GeoIP2-Domain.mmdb') >>> >>> response = reader.domain('128.101.101.101') >>> >>> response.domain 'umn.edu' >>> response.ip_address '128.101.101.101' >>> reader.close() Enterprise Database ^^^^^^^^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> with geoip2.database.Reader('/path/to/GeoIP2-Enterprise.mmdb') as reader: >>> >>> # Use the .enterprise method to do a lookup in the Enterprise database >>> response = reader.enterprise('128.101.101.101') >>> >>> response.country.confidence 99 >>> response.country.iso_code 'US' >>> response.country.name 'United States' >>> response.country.names['zh-CN'] u'美国' >>> >>> response.subdivisions.most_specific.name 'Minnesota' >>> response.subdivisions.most_specific.iso_code 'MN' >>> response.subdivisions.most_specific.confidence 77 >>> >>> response.city.name 'Minneapolis' >>> response.country.confidence 11 >>> >>> response.postal.code '55455' >>> >>> response.location.accuracy_radius 50 >>> response.location.latitude 44.9733 >>> response.location.longitude -93.2323 ISP Database ^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> reader = geoip2.database.Reader('/path/to/GeoIP2-ISP.mmdb') >>> >>> response = reader.isp('1.128.0.0') >>> >>> response.autonomous_system_number 1221 >>> response.autonomous_system_organization 'Telstra Pty Ltd' >>> response.isp 'Telstra Internet' >>> response.organization 'Telstra Internet' >>> response.ip_address '128.101.101.101' >>> reader.close() Database Reader Exceptions -------------------------- If the database file does not exist or is not readable, the constructor will raise a ``FileNotFoundError`` on Python 3 or an ``IOError`` on Python 2. If the IP address passed to a method is invalid, a ``ValueError`` will be raised. If the file is invalid or there is a bug in the reader, a ``maxminddb.InvalidDatabaseError`` will be raised with a description of the problem. If an IP address is not in the database, a ``AddressNotFoundError`` will be raised. Values to use for Database or Dictionary Keys --------------------------------------------- **We strongly discourage you from using a value from any ``names`` property as a key in a database or dictionaries.** These names may change between releases. Instead we recommend using one of the following: * ``geoip2.records.City`` - ``city.geoname_id`` * ``geoip2.records.Continent`` - ``continent.code`` or ``continent.geoname_id`` * ``geoip2.records.Country`` and ``geoip2.records.RepresentedCountry`` - ``country.iso_code`` or ``country.geoname_id`` * ``geoip2.records.subdivision`` - ``subdivision.iso_code`` or ``subdivision.geoname_id`` What data is returned? ---------------------- While many of the models contain the same basic records, the attributes which can be populated vary between web service end points or databases. In addition, while a model may offer a particular piece of data, MaxMind does not always have every piece of data for any given IP address. Because of these factors, it is possible for any request to return a record where some or all of the attributes are unpopulated. The only piece of data which is always returned is the ``ip_address`` attribute in the ``geoip2.records.Traits`` record. Integration with GeoNames ------------------------- `GeoNames `_ offers web services and downloadable databases with data on geographical features around the world, including populated places. They offer both free and paid premium data. Each feature is uniquely identified by a ``geoname_id``, which is an integer. Many of the records returned by the GeoIP web services and databases include a ``geoname_id`` field. This is the ID of a geographical feature (city, region, country, etc.) in the GeoNames database. Some of the data that MaxMind provides is also sourced from GeoNames. We source things like place names, ISO codes, and other similar data from the GeoNames premium data set. Reporting Data Problems ----------------------- If the problem you find is that an IP address is incorrectly mapped, please `submit your correction to MaxMind `_. If you find some other sort of mistake, like an incorrect spelling, please check the `GeoNames site `_ first. Once you've searched for a place and found it on the GeoNames map view, there are a number of links you can use to correct data ("move", "edit", "alternate names", etc.). Once the correction is part of the GeoNames data set, it will be automatically incorporated into future MaxMind releases. If you are a paying MaxMind customer and you're not sure where to submit a correction, please `contact MaxMind support `_ for help. Requirements ------------ This code requires Python 2.6+ or 3.3+. Older versions are not supported. This library has been tested with CPython and PyPy. The Requests HTTP library is also required. See for details. Versioning ---------- The GeoIP2 Python API uses `Semantic Versioning `_. Support ------- Please report all issues with this code using the `GitHub issue tracker `_ If you are having an issue with a MaxMind service that is not specific to the client API, please contact `MaxMind support `_ for assistance. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python Classifier: Topic :: Internet :: Proxy Servers Classifier: Topic :: Internet geoip2-2.7.0/docs/0000755000175000017500000000000013230142214013517 5ustar greggreg00000000000000geoip2-2.7.0/geoip2/0000755000175000017500000000000013230142214013754 5ustar greggreg00000000000000geoip2-2.7.0/geoip2/records.py0000644000175000017500000004300513230141446015777 0ustar greggreg00000000000000""" Records ======= """ # pylint:disable=R0903 from abc import ABCMeta from geoip2.mixins import SimpleEquality class Record(SimpleEquality): """All records are subclasses of the abstract class ``Record``.""" __metaclass__ = ABCMeta _valid_attributes = set() def __init__(self, **kwargs): valid_args = dict((k, kwargs.get(k)) for k in self._valid_attributes) self.__dict__.update(valid_args) def __setattr__(self, name, value): raise AttributeError("can't set attribute") def __repr__(self): args = ', '.join('%s=%r' % x for x in self.__dict__.items()) return '{module}.{class_name}({data})'.format( module=self.__module__, class_name=self.__class__.__name__, data=args) class PlaceRecord(Record): """All records with :py:attr:`names` subclass :py:class:`PlaceRecord`.""" __metaclass__ = ABCMeta def __init__(self, locales=None, **kwargs): if locales is None: locales = ['en'] if kwargs.get('names') is None: kwargs['names'] = {} object.__setattr__(self, '_locales', locales) super(PlaceRecord, self).__init__(**kwargs) @property def name(self): """Dict with locale codes as keys and localized name as value.""" # pylint:disable=E1101 return next((self.names.get(x) for x in self._locales if x in self.names), None) class City(PlaceRecord): """Contains data for the city record associated with an IP address. This class contains the city-level data associated with an IP address. This record is returned by ``city``, ``enterprise``, and ``insights``. Attributes: .. attribute:: confidence A value from 0-100 indicating MaxMind's confidence that the city is correct. This attribute is only available from the Insights end point and the GeoIP2 Enterprise database. :type: int .. attribute:: geoname_id The GeoName ID for the city. :type: int .. attribute:: name The name of the city based on the locales list passed to the constructor. :type: unicode .. attribute:: names A dictionary where the keys are locale codes and the values are names. :type: dict """ _valid_attributes = set(['confidence', 'geoname_id', 'names']) class Continent(PlaceRecord): """Contains data for the continent record associated with an IP address. This class contains the continent-level data associated with an IP address. Attributes: .. attribute:: code A two character continent code like "NA" (North America) or "OC" (Oceania). :type: unicode .. attribute:: geoname_id The GeoName ID for the continent. :type: int .. attribute:: name Returns the name of the continent based on the locales list passed to the constructor. :type: unicode .. attribute:: names A dictionary where the keys are locale codes and the values are names. :type: dict """ _valid_attributes = set(['code', 'geoname_id', 'names']) class Country(PlaceRecord): """Contains data for the country record associated with an IP address. This class contains the country-level data associated with an IP address. Attributes: .. attribute:: confidence A value from 0-100 indicating MaxMind's confidence that the country is correct. This attribute is only available from the Insights end point and the GeoIP2 Enterprise database. :type: int .. attribute:: geoname_id The GeoName ID for the country. :type: int .. attribute:: is_in_european_union This is true if the country is a member state of the European Union. :type: bool .. attribute:: iso_code The two-character `ISO 3166-1 `_ alpha code for the country. :type: unicode .. attribute:: name The name of the country based on the locales list passed to the constructor. :type: unicode .. attribute:: names A dictionary where the keys are locale codes and the values are names. :type: dict """ _valid_attributes = set([ 'confidence', 'geoname_id', 'is_in_european_union', 'iso_code', 'names' ]) def __init__(self, locales=None, **kwargs): if 'is_in_european_union' not in kwargs: kwargs['is_in_european_union'] = False super(Country, self).__init__(locales, **kwargs) class RepresentedCountry(Country): """Contains data for the represented country associated with an IP address. This class contains the country-level data associated with an IP address for the IP's represented country. The represented country is the country represented by something like a military base. Attributes: .. attribute:: confidence A value from 0-100 indicating MaxMind's confidence that the country is correct. This attribute is only available from the Insights end point and the GeoIP2 Enterprise database. :type: int .. attribute:: geoname_id The GeoName ID for the country. :type: int .. attribute:: is_in_european_union This is true if the country is a member state of the European Union. :type: bool .. attribute:: iso_code The two-character `ISO 3166-1 `_ alpha code for the country. :type: unicode .. attribute:: name The name of the country based on the locales list passed to the constructor. :type: unicode .. attribute:: names A dictionary where the keys are locale codes and the values are names. :type: dict .. attribute:: type A string indicating the type of entity that is representing the country. Currently we only return ``military`` but this could expand to include other types in the future. :type: unicode """ _valid_attributes = set([ 'confidence', 'geoname_id', 'is_in_european_union', 'iso_code', 'names', 'type' ]) class Location(Record): """Contains data for the location record associated with an IP address. This class contains the location data associated with an IP address. This record is returned by ``city``, ``enterprise``, and ``insights``. Attributes: .. attribute:: average_income The average income in US dollars associated with the requested IP address. This attribute is only available from the Insights end point. :type: int .. attribute:: accuracy_radius The approximate accuracy radius in kilometers around the latitude and longitude for the IP address. This is the radius where we have a 67% confidence that the device using the IP address resides within the circle centered at the latitude and longitude with the provided radius. :type: int .. attribute:: latitude The approximate latitude of the location associated with the IP address. This value is not precise and should not be used to identify a particular address or household. :type: float .. attribute:: longitude The approximate longitude of the location associated with the IP address. This value is not precise and should not be used to identify a particular address or household. :type: float .. attribute:: metro_code The metro code of the location if the location is in the US. MaxMind returns the same metro codes as the `Google AdWords API `_. :type: int .. attribute:: population_density The estimated population per square kilometer associated with the IP address. This attribute is only available from the Insights end point. :type: int .. attribute:: time_zone The time zone associated with location, as specified by the `IANA Time Zone Database `_, e.g., "America/New_York". :type: unicode """ _valid_attributes = set([ 'average_income', 'accuracy_radius', 'latitude', 'longitude', 'metro_code', 'population_density', 'postal_code', 'postal_confidence', 'time_zone' ]) class MaxMind(Record): """Contains data related to your MaxMind account. Attributes: .. attribute:: queries_remaining The number of remaining queries you have for the end point you are calling. :type: int """ _valid_attributes = set(['queries_remaining']) class Postal(Record): """Contains data for the postal record associated with an IP address. This class contains the postal data associated with an IP address. This attribute is returned by ``city``, ``enterprise``, and ``insights``. Attributes: .. attribute:: code The postal code of the location. Postal codes are not available for all countries. In some countries, this will only contain part of the postal code. :type: unicode .. attribute:: confidence A value from 0-100 indicating MaxMind's confidence that the postal code is correct. This attribute is only available from the Insights end point and the GeoIP2 Enterprise database. :type: int """ _valid_attributes = set(['code', 'confidence']) class Subdivision(PlaceRecord): """Contains data for the subdivisions associated with an IP address. This class contains the subdivision data associated with an IP address. This attribute is returned by ``city``, ``enterprise``, and ``insights``. Attributes: .. attribute:: confidence This is a value from 0-100 indicating MaxMind's confidence that the subdivision is correct. This attribute is only available from the Insights end point and the GeoIP2 Enterprise database. :type: int .. attribute:: geoname_id This is a GeoName ID for the subdivision. :type: int .. attribute:: iso_code This is a string up to three characters long contain the subdivision portion of the `ISO 3166-2 code `_. :type: unicode .. attribute:: name The name of the subdivision based on the locales list passed to the constructor. :type: unicode .. attribute:: names A dictionary where the keys are locale codes and the values are names :type: dict """ _valid_attributes = set(['confidence', 'geoname_id', 'iso_code', 'names']) class Subdivisions(tuple): """A tuple-like collection of subdivisions associated with an IP address. This class contains the subdivisions of the country associated with the IP address from largest to smallest. For instance, the response for Oxford in the United Kingdom would have England as the first element and Oxfordshire as the second element. This attribute is returned by ``city``, ``enterprise``, and ``insights``. """ def __new__(cls, locales, *subdivisions): subdivisions = [Subdivision(locales, **x) for x in subdivisions] obj = super(cls, Subdivisions).__new__(cls, subdivisions) return obj def __init__(self, locales, *subdivisions): # pylint:disable=W0613 self._locales = locales super(Subdivisions, self).__init__() @property def most_specific(self): """The most specific (smallest) subdivision available. If there are no :py:class:`Subdivision` objects for the response, this returns an empty :py:class:`Subdivision`. :type: :py:class:`Subdivision` """ try: return self[-1] except IndexError: return Subdivision(self._locales) class Traits(Record): """Contains data for the traits record associated with an IP address. This class contains the traits data associated with an IP address. This class has the following attributes: .. attribute:: autonomous_system_number The `autonomous system number `_ associated with the IP address. This attribute is only available from the City and Insights web service end points and the GeoIP2 Enterprise database. :type: int .. attribute:: autonomous_system_organization The organization associated with the registered `autonomous system number `_ for the IP address. This attribute is only available from the City and Insights web service end points and the GeoIP2 Enterprise database. :type: unicode .. attribute:: connection_type The connection type may take the following values: - Dialup - Cable/DSL - Corporate - Cellular Additional values may be added in the future. This attribute is only available in the GeoIP2 Enterprise database. :type: unicode .. attribute:: domain The second level domain associated with the IP address. This will be something like "example.com" or "example.co.uk", not "foo.example.com". This attribute is only available from the City and Insights web service end points and the GeoIP2 Enterprise database. :type: unicode .. attribute:: ip_address The IP address that the data in the model is for. If you performed a "me" lookup against the web service, this will be the externally routable IP address for the system the code is running on. If the system is behind a NAT, this may differ from the IP address locally assigned to it. :type: unicode .. attribute:: is_anonymous This is true if the IP address belongs to any sort of anonymous network. This attribute is only available from GeoIP2 Precision Insights. :type: bool .. attribute:: is_anonymous_proxy This is true if the IP is an anonymous proxy. See http://dev.maxmind.com/faq/geoip#anonproxy for further details. :type: bool .. deprecated:: 2.2.0 Use our our `GeoIP2 Anonymous IP database `_ instead. .. attribute:: is_anonymous_vpn This is true if the IP address belongs to an anonymous VPN system. This attribute is only available from GeoIP2 Precision Insights. :type: bool .. attribute:: is_hosting_provider This is true if the IP address belongs to a hosting provider. This attribute is only available from GeoIP2 Precision Insights. :type: bool .. attribute:: is_legitimate_proxy This attribute is true if MaxMind believes this IP address to be a legitimate proxy, such as an internal VPN used by a corporation. This attribute is only available in the GeoIP2 Enterprise database. :type: bool .. attribute:: is_public_proxy This is true if the IP address belongs to a public proxy. This attribute is only available from GeoIP2 Precision Insights. :type: bool .. attribute:: is_satellite_provider This is true if the IP address is from a satellite provider that provides service to multiple countries. :type: bool .. deprecated:: 2.2.0 Due to the increased coverage by mobile carriers, very few satellite providers now serve multiple countries. As a result, the output does not provide sufficiently relevant data for us to maintain it. .. attribute:: is_tor_exit_node This is true if the IP address is a Tor exit node. This attribute is only available from GeoIP2 Precision Insights. :type: bool .. attribute:: isp The name of the ISP associated with the IP address. This attribute is only available from the City and Insights web service end points and the GeoIP2 Enterprise database. :type: unicode .. attribute:: organization The name of the organization associated with the IP address. This attribute is only available from the City and Insights web service end points and the GeoIP2 Enterprise database. :type: unicode .. attribute:: user_type The user type associated with the IP address. This can be one of the following values: * business * cafe * cellular * college * content_delivery_network * dialup * government * hosting * library * military * residential * router * school * search_engine_spider * traveler This attribute is only available from the Insights end point and the GeoIP2 Enterprise database. :type: unicode """ _valid_attributes = set([ 'autonomous_system_number', 'autonomous_system_organization', 'connection_type', 'domain', 'is_anonymous', 'is_anonymous_proxy', 'is_anonymous_vpn', 'is_hosting_provider', 'is_legitimate_proxy', 'is_public_proxy', 'is_satellite_provider', 'is_tor_exit_node', 'is_satellite_provider', 'isp', 'ip_address', 'organization', 'user_type' ]) def __init__(self, **kwargs): for k in [ 'is_anonymous', 'is_anonymous_proxy', 'is_anonymous_vpn', 'is_hosting_provider', 'is_legitimate_proxy', 'is_public_proxy', 'is_satellite_provider', 'is_tor_exit_node', ]: kwargs[k] = bool(kwargs.get(k, False)) super(Traits, self).__init__(**kwargs) geoip2-2.7.0/geoip2/mixins.py0000644000175000017500000000063213227444157015657 0ustar greggreg00000000000000"""This package contains utility mixins""" # pylint: disable=too-few-public-methods from abc import ABCMeta class SimpleEquality(object): """Naive __dict__ equality mixin""" __metaclass__ = ABCMeta def __eq__(self, other): return (isinstance(other, self.__class__) and self.__dict__ == other.__dict__) def __ne__(self, other): return not self.__eq__(other) geoip2-2.7.0/geoip2/errors.py0000664000175000017500000000227512766603306015673 0ustar greggreg00000000000000""" Errors ====== """ class GeoIP2Error(RuntimeError): """There was a generic error in GeoIP2. This class represents a generic error. It extends :py:exc:`RuntimeError` and does not add any additional attributes. """ class AddressNotFoundError(GeoIP2Error): """The address you were looking up was not found.""" class AuthenticationError(GeoIP2Error): """There was a problem authenticating the request.""" class HTTPError(GeoIP2Error): """There was an error when making your HTTP request. This class represents an HTTP transport error. It extends :py:exc:`GeoIP2Error` and adds attributes of its own. :ivar http_status: The HTTP status code returned :ivar uri: The URI queried """ def __init__(self, message, http_status=None, uri=None): super(HTTPError, self).__init__(message) self.http_status = http_status self.uri = uri class InvalidRequestError(GeoIP2Error): """The request was invalid.""" class OutOfQueriesError(GeoIP2Error): """Your account is out of funds for the service queried.""" class PermissionRequiredError(GeoIP2Error): """Your account does not have permission to access this service.""" geoip2-2.7.0/geoip2/webservice.py0000644000175000017500000002060413227444157016507 0ustar greggreg00000000000000""" ============================ WebServices Client API ============================ This class provides a client API for all the GeoIP2 Precision web service end points. The end points are Country, City, and Insights. Each end point returns a different set of data about an IP address, with Country returning the least data and Insights the most. Each web service end point is represented by a different model class, and these model classes in turn contain multiple record classes. The record classes have attributes which contain data about the IP address. If the web service does not return a particular piece of data for an IP address, the associated attribute is not populated. The web service may not return any information for an entire record, in which case all of the attributes for that record class will be empty. SSL --- Requests to the GeoIP2 Precision web service are always made with SSL. """ import requests from requests.utils import default_user_agent import geoip2 import geoip2.models from .compat import compat_ip_address from .errors import (AddressNotFoundError, AuthenticationError, GeoIP2Error, HTTPError, InvalidRequestError, OutOfQueriesError, PermissionRequiredError) class Client(object): """Creates a new client object. It accepts the following required arguments: :param user_id: Your MaxMind User ID. :param license_key: Your MaxMind license key. Go to https://www.maxmind.com/en/my_license_key to see your MaxMind User ID and license key. The following keyword arguments are also accepted: :param host: The hostname to make a request against. This defaults to "geoip.maxmind.com". In most cases, you should not need to set this explicitly. :param locales: This is list of locale codes. This argument will be passed on to record classes to use when their name properties are called. The default value is ['en']. The order of the locales is significant. When a record class has multiple names (country, city, etc.), its name property will return the name in the first locale that has one. Note that the only locale which is always present in the GeoIP2 data is "en". If you do not include this locale, the name property may end up returning None even when the record has an English name. Currently, the valid locale codes are: * de -- German * en -- English names may still include accented characters if that is the accepted spelling in English. In other words, English does not mean ASCII. * es -- Spanish * fr -- French * ja -- Japanese * pt-BR -- Brazilian Portuguese * ru -- Russian * zh-CN -- Simplified Chinese. """ def __init__(self, user_id, license_key, host='geoip.maxmind.com', locales=None, timeout=None): """Construct a Client.""" # pylint: disable=too-many-arguments if locales is None: locales = ['en'] self._locales = locales # requests 2.12.2 requires that the username passed to auth be bytes # or a string, with the former being preferred. self._user_id = user_id if isinstance(user_id, bytes) else str(user_id) self._license_key = license_key self._base_uri = 'https://%s/geoip/v2.1' % host self._timeout = timeout def city(self, ip_address='me'): """Call GeoIP2 Precision City endpoint with the specified IP. :param ip_address: IPv4 or IPv6 address as a string. If no address is provided, the address that the web service is called from will be used. :returns: :py:class:`geoip2.models.City` object """ return self._response_for('city', geoip2.models.City, ip_address) def country(self, ip_address='me'): """Call the GeoIP2 Country endpoint with the specified IP. :param ip_address: IPv4 or IPv6 address as a string. If no address is provided, the address that the web service is called from will be used. :returns: :py:class:`geoip2.models.Country` object """ return self._response_for('country', geoip2.models.Country, ip_address) def insights(self, ip_address='me'): """Call the GeoIP2 Precision: Insights endpoint with the specified IP. :param ip_address: IPv4 or IPv6 address as a string. If no address is provided, the address that the web service is called from will be used. :returns: :py:class:`geoip2.models.Insights` object """ return self._response_for('insights', geoip2.models.Insights, ip_address) def _response_for(self, path, model_class, ip_address): if ip_address != 'me': ip_address = str(compat_ip_address(ip_address)) uri = '/'.join([self._base_uri, path, ip_address]) response = requests.get( uri, auth=(self._user_id, self._license_key), headers={ 'Accept': 'application/json', 'User-Agent': self._user_agent() }, timeout=self._timeout) if response.status_code != 200: raise self._exception_for_error(response, uri) body = self._handle_success(response, uri) return model_class(body, locales=self._locales) def _user_agent(self): return 'GeoIP2 Python Client v%s (%s)' % (geoip2.__version__, default_user_agent()) def _handle_success(self, response, uri): try: return response.json() except ValueError as ex: raise GeoIP2Error('Received a 200 response for %(uri)s' ' but could not decode the response as ' 'JSON: ' % locals() + ', '.join(ex.args), 200, uri) def _exception_for_error(self, response, uri): status = response.status_code if 400 <= status < 500: return self._exception_for_4xx_status(response, status, uri) elif 500 <= status < 600: return self._exception_for_5xx_status(status, uri) return self._exception_for_non_200_status(status, uri) def _exception_for_4xx_status(self, response, status, uri): if not response.content: return HTTPError('Received a %(status)i error for %(uri)s ' 'with no body.' % locals(), status, uri) elif response.headers['Content-Type'].find('json') == -1: return HTTPError('Received a %i for %s with the following ' 'body: %s' % (status, uri, response.content), status, uri) try: body = response.json() except ValueError as ex: return HTTPError( 'Received a %(status)i error for %(uri)s but it did' ' not include the expected JSON body: ' % locals() + ', '.join(ex.args), status, uri) else: if 'code' in body and 'error' in body: return self._exception_for_web_service_error( body.get('error'), body.get('code'), status, uri) return HTTPError('Response contains JSON but it does not specify ' 'code or error keys', status, uri) def _exception_for_web_service_error(self, message, code, status, uri): if code in ('IP_ADDRESS_NOT_FOUND', 'IP_ADDRESS_RESERVED'): return AddressNotFoundError(message) elif code in ('AUTHORIZATION_INVALID', 'LICENSE_KEY_REQUIRED', 'USER_ID_REQUIRED', 'USER_ID_UNKNOWN'): return AuthenticationError(message) elif code in ('INSUFFICIENT_FUNDS', 'OUT_OF_QUERIES'): return OutOfQueriesError(message) elif code == 'PERMISSION_REQUIRED': return PermissionRequiredError(message) return InvalidRequestError(message, code, status, uri) def _exception_for_5xx_status(self, status, uri): return HTTPError('Received a server error (%(status)i) for ' '%(uri)s' % locals(), status, uri) def _exception_for_non_200_status(self, status, uri): return HTTPError('Received a very surprising HTTP status ' '(%(status)i) for %(uri)s' % locals(), status, uri) geoip2-2.7.0/geoip2/database.py0000644000175000017500000001620713104136363016110 0ustar greggreg00000000000000""" ====================== GeoIP2 Database Reader ====================== """ import inspect import maxminddb # pylint: disable=unused-import from maxminddb import (MODE_AUTO, MODE_MMAP, MODE_MMAP_EXT, MODE_FILE, MODE_MEMORY) import geoip2 import geoip2.models import geoip2.errors class Reader(object): """GeoIP2 database Reader object. Instances of this class provide a reader for the GeoIP2 database format. IP addresses can be looked up using the ``country`` and ``city`` methods. The basic API for this class is the same for every database. First, you create a reader object, specifying a file name. You then call the method corresponding to the specific database, passing it the IP address you want to look up. If the request succeeds, the method call will return a model class for the method you called. This model in turn contains multiple record classes, each of which represents part of the data returned by the database. If the database does not contain the requested information, the attributes on the record class will have a ``None`` value. If the address is not in the database, an ``geoip2.errors.AddressNotFoundError`` exception will be thrown. If the database is corrupt or invalid, a ``maxminddb.InvalidDatabaseError`` will be thrown. """ def __init__(self, filename, locales=None, mode=MODE_AUTO): """Create GeoIP2 Reader. :param filename: The path to the GeoIP2 database. :param locales: This is list of locale codes. This argument will be passed on to record classes to use when their name properties are called. The default value is ['en']. The order of the locales is significant. When a record class has multiple names (country, city, etc.), its name property will return the name in the first locale that has one. Note that the only locale which is always present in the GeoIP2 data is "en". If you do not include this locale, the name property may end up returning None even when the record has an English name. Currently, the valid locale codes are: * de -- German * en -- English names may still include accented characters if that is the accepted spelling in English. In other words, English does not mean ASCII. * es -- Spanish * fr -- French * ja -- Japanese * pt-BR -- Brazilian Portuguese * ru -- Russian * zh-CN -- Simplified Chinese. :param mode: The mode to open the database with. Valid mode are: * MODE_MMAP_EXT - use the C extension with memory map. * MODE_MMAP - read from memory map. Pure Python. * MODE_FILE - read database as standard file. Pure Python. * MODE_MEMORY - load database into memory. Pure Python. * MODE_AUTO - try MODE_MMAP_EXT, MODE_MMAP, MODE_FILE in that order. Default. """ if locales is None: locales = ['en'] self._db_reader = maxminddb.open_database(filename, mode) self._locales = locales def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.close() def country(self, ip_address): """Get the Country object for the IP address. :param ip_address: IPv4 or IPv6 address as a string. :returns: :py:class:`geoip2.models.Country` object """ return self._model_for(geoip2.models.Country, 'Country', ip_address) def city(self, ip_address): """Get the City object for the IP address. :param ip_address: IPv4 or IPv6 address as a string. :returns: :py:class:`geoip2.models.City` object """ return self._model_for(geoip2.models.City, 'City', ip_address) def anonymous_ip(self, ip_address): """Get the AnonymousIP object for the IP address. :param ip_address: IPv4 or IPv6 address as a string. :returns: :py:class:`geoip2.models.AnonymousIP` object """ return self._flat_model_for(geoip2.models.AnonymousIP, 'GeoIP2-Anonymous-IP', ip_address) def asn(self, ip_address): """Get the ASN object for the IP address. :param ip_address: IPv4 or IPv6 address as a string. :returns: :py:class:`geoip2.models.ASN` object """ return self._flat_model_for(geoip2.models.ASN, 'GeoLite2-ASN', ip_address) def connection_type(self, ip_address): """Get the ConnectionType object for the IP address. :param ip_address: IPv4 or IPv6 address as a string. :returns: :py:class:`geoip2.models.ConnectionType` object """ return self._flat_model_for(geoip2.models.ConnectionType, 'GeoIP2-Connection-Type', ip_address) def domain(self, ip_address): """Get the Domain object for the IP address. :param ip_address: IPv4 or IPv6 address as a string. :returns: :py:class:`geoip2.models.Domain` object """ return self._flat_model_for(geoip2.models.Domain, 'GeoIP2-Domain', ip_address) def enterprise(self, ip_address): """Get the Enterprise object for the IP address. :param ip_address: IPv4 or IPv6 address as a string. :returns: :py:class:`geoip2.models.Enterprise` object """ return self._model_for(geoip2.models.Enterprise, 'Enterprise', ip_address) def isp(self, ip_address): """Get the ISP object for the IP address. :param ip_address: IPv4 or IPv6 address as a string. :returns: :py:class:`geoip2.models.ISP` object """ return self._flat_model_for(geoip2.models.ISP, 'GeoIP2-ISP', ip_address) def _get(self, database_type, ip_address): if database_type not in self.metadata().database_type: caller = inspect.stack()[2][3] raise TypeError("The %s method cannot be used with the " "%s database" % (caller, self.metadata().database_type)) record = self._db_reader.get(ip_address) if record is None: raise geoip2.errors.AddressNotFoundError( "The address %s is not in the database." % ip_address) return record def _model_for(self, model_class, types, ip_address): record = self._get(types, ip_address) record.setdefault('traits', {})['ip_address'] = ip_address return model_class(record, locales=self._locales) def _flat_model_for(self, model_class, types, ip_address): record = self._get(types, ip_address) record['ip_address'] = ip_address return model_class(record) def metadata(self): """The metadata for the open database. :returns: :py:class:`maxminddb.reader.Metadata` object """ return self._db_reader.metadata() def close(self): """Closes the GeoIP2 database.""" self._db_reader.close() geoip2-2.7.0/geoip2/models.py0000644000175000017500000003225213174206213015624 0ustar greggreg00000000000000""" Models ====== These classes provide models for the data returned by the GeoIP2 web service and databases. The only difference between the City and Insights model classes is which fields in each record may be populated. See http://dev.maxmind.com/geoip/geoip2/web-services for more details. """ # pylint: disable=too-many-instance-attributes,too-few-public-methods from abc import ABCMeta import geoip2.records from geoip2.mixins import SimpleEquality class Country(SimpleEquality): """Model for the GeoIP2 Precision: Country and the GeoIP2 Country database. This class provides the following attributes: .. attribute:: continent Continent object for the requested IP address. :type: :py:class:`geoip2.records.Continent` .. attribute:: country Country object for the requested IP address. This record represents the country where MaxMind believes the IP is located. :type: :py:class:`geoip2.records.Country` .. attribute:: maxmind Information related to your MaxMind account. :type: :py:class:`geoip2.records.MaxMind` .. attribute:: registered_country The registered country object for the requested IP address. This record represents the country where the ISP has registered a given IP block in and may differ from the user's country. :type: :py:class:`geoip2.records.Country` .. attribute:: represented_country Object for the country represented by the users of the IP address when that country is different than the country in ``country``. For instance, the country represented by an overseas military base. :type: :py:class:`geoip2.records.RepresentedCountry` .. attribute:: traits Object with the traits of the requested IP address. :type: :py:class:`geoip2.records.Traits` """ def __init__(self, raw_response, locales=None): if locales is None: locales = ['en'] self._locales = locales self.continent = \ geoip2.records.Continent(locales, **raw_response.get('continent', {})) self.country = \ geoip2.records.Country(locales, **raw_response.get('country', {})) self.registered_country = \ geoip2.records.Country(locales, **raw_response.get('registered_country', {})) self.represented_country \ = geoip2.records.RepresentedCountry(locales, **raw_response.get( 'represented_country', {})) self.maxmind = \ geoip2.records.MaxMind(**raw_response.get('maxmind', {})) self.traits = geoip2.records.Traits(**raw_response.get('traits', {})) self.raw = raw_response def __repr__(self): return '{module}.{class_name}({data}, {locales})'.format( module=self.__module__, class_name=self.__class__.__name__, data=self.raw, locales=self._locales) class City(Country): """Model for the GeoIP2 Precision: City and the GeoIP2 City database. .. attribute:: city City object for the requested IP address. :type: :py:class:`geoip2.records.City` .. attribute:: continent Continent object for the requested IP address. :type: :py:class:`geoip2.records.Continent` .. attribute:: country Country object for the requested IP address. This record represents the country where MaxMind believes the IP is located. :type: :py:class:`geoip2.records.Country` .. attribute:: location Location object for the requested IP address. .. attribute:: maxmind Information related to your MaxMind account. :type: :py:class:`geoip2.records.MaxMind` .. attribute:: registered_country The registered country object for the requested IP address. This record represents the country where the ISP has registered a given IP block in and may differ from the user's country. :type: :py:class:`geoip2.records.Country` .. attribute:: represented_country Object for the country represented by the users of the IP address when that country is different than the country in ``country``. For instance, the country represented by an overseas military base. :type: :py:class:`geoip2.records.RepresentedCountry` .. attribute:: subdivisions Object (tuple) representing the subdivisions of the country to which the location of the requested IP address belongs. :type: :py:class:`geoip2.records.Subdivisions` .. attribute:: traits Object with the traits of the requested IP address. :type: :py:class:`geoip2.records.Traits` """ def __init__(self, raw_response, locales=None): super(City, self).__init__(raw_response, locales) self.city = \ geoip2.records.City(locales, **raw_response.get('city', {})) self.location = \ geoip2.records.Location(**raw_response.get('location', {})) self.postal = \ geoip2.records.Postal(**raw_response.get('postal', {})) self.subdivisions = \ geoip2.records.Subdivisions(locales, *raw_response.get('subdivisions', [])) class Insights(City): """Model for the GeoIP2 Precision: Insights web service endpoint. .. attribute:: city City object for the requested IP address. :type: :py:class:`geoip2.records.City` .. attribute:: continent Continent object for the requested IP address. :type: :py:class:`geoip2.records.Continent` .. attribute:: country Country object for the requested IP address. This record represents the country where MaxMind believes the IP is located. :type: :py:class:`geoip2.records.Country` .. attribute:: location Location object for the requested IP address. .. attribute:: maxmind Information related to your MaxMind account. :type: :py:class:`geoip2.records.MaxMind` .. attribute:: registered_country The registered country object for the requested IP address. This record represents the country where the ISP has registered a given IP block in and may differ from the user's country. :type: :py:class:`geoip2.records.Country` .. attribute:: represented_country Object for the country represented by the users of the IP address when that country is different than the country in ``country``. For instance, the country represented by an overseas military base. :type: :py:class:`geoip2.records.RepresentedCountry` .. attribute:: subdivisions Object (tuple) representing the subdivisions of the country to which the location of the requested IP address belongs. :type: :py:class:`geoip2.records.Subdivisions` .. attribute:: traits Object with the traits of the requested IP address. :type: :py:class:`geoip2.records.Traits` """ class Enterprise(City): """Model for the GeoIP2 Enterprise database. .. attribute:: city City object for the requested IP address. :type: :py:class:`geoip2.records.City` .. attribute:: continent Continent object for the requested IP address. :type: :py:class:`geoip2.records.Continent` .. attribute:: country Country object for the requested IP address. This record represents the country where MaxMind believes the IP is located. :type: :py:class:`geoip2.records.Country` .. attribute:: location Location object for the requested IP address. .. attribute:: maxmind Information related to your MaxMind account. :type: :py:class:`geoip2.records.MaxMind` .. attribute:: registered_country The registered country object for the requested IP address. This record represents the country where the ISP has registered a given IP block in and may differ from the user's country. :type: :py:class:`geoip2.records.Country` .. attribute:: represented_country Object for the country represented by the users of the IP address when that country is different than the country in ``country``. For instance, the country represented by an overseas military base. :type: :py:class:`geoip2.records.RepresentedCountry` .. attribute:: subdivisions Object (tuple) representing the subdivisions of the country to which the location of the requested IP address belongs. :type: :py:class:`geoip2.records.Subdivisions` .. attribute:: traits Object with the traits of the requested IP address. :type: :py:class:`geoip2.records.Traits` """ class SimpleModel(SimpleEquality): """Provides basic methods for non-location models""" __metaclass__ = ABCMeta def __repr__(self): # pylint: disable=no-member return '{module}.{class_name}({data})'.format( module=self.__module__, class_name=self.__class__.__name__, data=str(self.raw)) class AnonymousIP(SimpleModel): """Model class for the GeoIP2 Anonymous IP. This class provides the following attribute: .. attribute:: is_anonymous This is true if the IP address belongs to any sort of anonymous network. :type: bool .. attribute:: is_anonymous_vpn This is true if the IP address belongs to an anonymous VPN system. :type: bool .. attribute:: is_hosting_provider This is true if the IP address belongs to a hosting provider. :type: bool .. attribute:: is_public_proxy This is true if the IP address belongs to a public proxy. :type: bool .. attribute:: is_tor_exit_node This is true if the IP address is a Tor exit node. :type: bool .. attribute:: ip_address The IP address used in the lookup. :type: unicode """ def __init__(self, raw): self.is_anonymous = raw.get('is_anonymous', False) self.is_anonymous_vpn = raw.get('is_anonymous_vpn', False) self.is_hosting_provider = raw.get('is_hosting_provider', False) self.is_public_proxy = raw.get('is_public_proxy', False) self.is_tor_exit_node = raw.get('is_tor_exit_node', False) self.ip_address = raw.get('ip_address') self.raw = raw class ASN(SimpleModel): """Model class for the GeoLite2 ASN. This class provides the following attribute: .. attribute:: autonomous_system_number The autonomous system number associated with the IP address. :type: int .. attribute:: autonomous_system_organization The organization associated with the registered autonomous system number for the IP address. :type: unicode .. attribute:: ip_address The IP address used in the lookup. :type: unicode """ # pylint:disable=too-many-arguments def __init__(self, raw): self.autonomous_system_number = raw.get('autonomous_system_number') self.autonomous_system_organization = raw.get( 'autonomous_system_organization') self.ip_address = raw.get('ip_address') self.raw = raw class ConnectionType(SimpleModel): """Model class for the GeoIP2 Connection-Type. This class provides the following attribute: .. attribute:: connection_type The connection type may take the following values: - Dialup - Cable/DSL - Corporate - Cellular Additional values may be added in the future. :type: unicode .. attribute:: ip_address The IP address used in the lookup. :type: unicode """ def __init__(self, raw): self.connection_type = raw.get('connection_type') self.ip_address = raw.get('ip_address') self.raw = raw class Domain(SimpleModel): """Model class for the GeoIP2 Domain. This class provides the following attribute: .. attribute:: domain The domain associated with the IP address. :type: unicode .. attribute:: ip_address The IP address used in the lookup. :type: unicode """ def __init__(self, raw): self.domain = raw.get('domain') self.ip_address = raw.get('ip_address') self.raw = raw class ISP(ASN): """Model class for the GeoIP2 ISP. This class provides the following attribute: .. attribute:: autonomous_system_number The autonomous system number associated with the IP address. :type: int .. attribute:: autonomous_system_organization The organization associated with the registered autonomous system number for the IP address. :type: unicode .. attribute:: isp The name of the ISP associated with the IP address. :type: unicode .. attribute:: organization The name of the organization associated with the IP address. :type: unicode .. attribute:: ip_address The IP address used in the lookup. :type: unicode """ # pylint:disable=too-many-arguments def __init__(self, raw): super(ISP, self).__init__(raw) self.isp = raw.get('isp') self.organization = raw.get('organization') geoip2-2.7.0/geoip2/compat.py0000644000175000017500000000071213104136363015621 0ustar greggreg00000000000000"""Intended for internal use only.""" import sys import ipaddress # pylint: skip-file if sys.version_info[0] == 2: def compat_ip_address(address): """Intended for internal use only.""" if isinstance(address, bytes): address = address.decode() return ipaddress.ip_address(address) else: def compat_ip_address(address): """Intended for internal use only.""" return ipaddress.ip_address(address) geoip2-2.7.0/geoip2/__init__.py0000644000175000017500000000030713230142163016070 0ustar greggreg00000000000000# pylint:disable=C0111 __title__ = 'geoip2' __version__ = '2.7.0' __author__ = 'Gregory Oschwald' __license__ = 'Apache License, Version 2.0' __copyright__ = 'Copyright (c) 2013-2018 Maxmind, Inc.' geoip2-2.7.0/tests/0000755000175000017500000000000013230142214013731 5ustar greggreg00000000000000geoip2-2.7.0/tests/webservice_test.py0000644000175000017500000002570013230141446017512 0ustar greggreg00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- import sys sys.path.append('..') import geoip2 import requests_mock from geoip2.errors import (AddressNotFoundError, AuthenticationError, GeoIP2Error, HTTPError, InvalidRequestError, OutOfQueriesError, PermissionRequiredError) from geoip2.webservice import Client if sys.version_info[:2] == (2, 6): import unittest2 as unittest else: import unittest if sys.version_info[0] == 2: unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp unittest.TestCase.assertRegex = unittest.TestCase.assertRegexpMatches class TestClient(unittest.TestCase): def setUp(self): self.client = Client(42, 'abcdef123456') base_uri = 'https://geoip.maxmind.com/geoip/v2.1/' country = { 'continent': { 'code': 'NA', 'geoname_id': 42, 'names': { 'en': 'North America' } }, 'country': { 'geoname_id': 1, 'iso_code': 'US', 'names': { 'en': 'United States of America' } }, 'maxmind': { 'queries_remaining': 11 }, 'registered_country': { 'geoname_id': 2, 'is_in_european_union': True, 'iso_code': 'DE', 'names': { 'en': 'Germany' } }, 'traits': { 'ip_address': '1.2.3.4' }, } def _content_type(self, endpoint): return ('application/vnd.maxmind.com-' + endpoint + '+json; charset=UTF-8; version=1.0') @requests_mock.mock() def test_country_ok(self, mock): mock.get( self.base_uri + 'country/1.2.3.4', json=self.country, status_code=200, headers={ 'Content-Type': self._content_type('country') }) country = self.client.country('1.2.3.4') self.assertEqual( type(country), geoip2.models.Country, 'return value of client.country') self.assertEqual(country.continent.geoname_id, 42, 'continent geoname_id is 42') self.assertEqual(country.continent.code, 'NA', 'continent code is NA') self.assertEqual(country.continent.name, 'North America', 'continent name is North America') self.assertEqual(country.country.geoname_id, 1, 'country geoname_id is 1') self.assertIs(country.country.is_in_european_union, False, 'country is_in_european_union is False') self.assertEqual(country.country.iso_code, 'US', 'country iso_code is US') self.assertEqual(country.country.names, {'en': 'United States of America'}, 'country names') self.assertEqual(country.country.name, 'United States of America', 'country name is United States of America') self.assertEqual(country.maxmind.queries_remaining, 11, 'queries_remaining is 11') self.assertIs(country.registered_country.is_in_european_union, True, 'registered_country is_in_european_union is True') self.assertEqual(country.raw, self.country, 'raw response is correct') @requests_mock.mock() def test_me(self, mock): mock.get( self.base_uri + 'country/me', json=self.country, status_code=200, headers={ 'Content-Type': self._content_type('country') }) implicit_me = self.client.country() self.assertEqual( type(implicit_me), geoip2.models.Country, 'country() returns Country object') explicit_me = self.client.country() self.assertEqual( type(explicit_me), geoip2.models.Country, 'country(\'me\') returns Country object') @requests_mock.mock() def test_200_error(self, mock): mock.get( self.base_uri + 'country/1.1.1.1', status_code=200, headers={ 'Content-Type': self._content_type('country') }) with self.assertRaisesRegex(GeoIP2Error, 'could not decode the response as JSON'): self.client.country('1.1.1.1') def test_bad_ip_address(self): with self.assertRaisesRegex(ValueError, "'1.2.3' does not appear to be an IPv4 " "or IPv6 address"): self.client.country('1.2.3') @requests_mock.mock() def test_no_body_error(self, mock): mock.get( self.base_uri + 'country/' + '1.2.3.7', text='', status_code=400, headers={ 'Content-Type': self._content_type('country') }) with self.assertRaisesRegex( HTTPError, 'Received a 400 error for .* with no body'): self.client.country('1.2.3.7') @requests_mock.mock() def test_weird_body_error(self, mock): mock.get( self.base_uri + 'country/' + '1.2.3.8', text='{"wierd": 42}', status_code=400, headers={ 'Content-Type': self._content_type('country') }) with self.assertRaisesRegex(HTTPError, 'Response contains JSON but it does not ' 'specify code or error keys'): self.client.country('1.2.3.8') @requests_mock.mock() def test_bad_body_error(self, mock): mock.get( self.base_uri + 'country/' + '1.2.3.9', text='bad body', status_code=400, headers={ 'Content-Type': self._content_type('country') }) with self.assertRaisesRegex( HTTPError, 'it did not include the expected JSON body'): self.client.country('1.2.3.9') @requests_mock.mock() def test_500_error(self, mock): mock.get(self.base_uri + 'country/' + '1.2.3.10', status_code=500) with self.assertRaisesRegex(HTTPError, 'Received a server error \(500\) for'): self.client.country('1.2.3.10') @requests_mock.mock() def test_300_error(self, mock): mock.get( self.base_uri + 'country/' + '1.2.3.11', status_code=300, headers={ 'Content-Type': self._content_type('country') }) with self.assertRaisesRegex(HTTPError, 'Received a very surprising HTTP status ' '\(300\) for'): self.client.country('1.2.3.11') @requests_mock.mock() def test_ip_address_required(self, mock): self._test_error(mock, 400, 'IP_ADDRESS_REQUIRED', InvalidRequestError) @requests_mock.mock() def test_ip_address_not_found(self, mock): self._test_error(mock, 404, 'IP_ADDRESS_NOT_FOUND', AddressNotFoundError) @requests_mock.mock() def test_ip_address_reserved(self, mock): self._test_error(mock, 400, 'IP_ADDRESS_RESERVED', AddressNotFoundError) @requests_mock.mock() def test_permission_required(self, mock): self._test_error(mock, 403, 'PERMISSION_REQUIRED', PermissionRequiredError) @requests_mock.mock() def test_auth_invalid(self, mock): self._test_error(mock, 400, 'AUTHORIZATION_INVALID', AuthenticationError) @requests_mock.mock() def test_license_key_required(self, mock): self._test_error(mock, 401, 'LICENSE_KEY_REQUIRED', AuthenticationError) @requests_mock.mock() def test_user_id_required(self, mock): self._test_error(mock, 401, 'USER_ID_REQUIRED', AuthenticationError) @requests_mock.mock() def test_user_id_unkown(self, mock): self._test_error(mock, 401, 'USER_ID_UNKNOWN', AuthenticationError) @requests_mock.mock() def test_out_of_queries_error(self, mock): self._test_error(mock, 402, 'OUT_OF_QUERIES', OutOfQueriesError) def _test_error(self, mock, status, error_code, error_class): msg = 'Some error message' body = {'error': msg, 'code': error_code} mock.get( self.base_uri + 'country/1.2.3.18', json=body, status_code=status, headers={ 'Content-Type': self._content_type('country') }) with self.assertRaisesRegex(error_class, msg): self.client.country('1.2.3.18') @requests_mock.mock() def test_unknown_error(self, mock): msg = 'Unknown error type' ip = '1.2.3.19' body = {'error': msg, 'code': 'UNKNOWN_TYPE'} mock.get( self.base_uri + 'country/' + ip, json=body, status_code=400, headers={ 'Content-Type': self._content_type('country') }) with self.assertRaisesRegex(InvalidRequestError, msg): self.client.country(ip) @requests_mock.mock() def test_request(self, mock): mock.get( self.base_uri + 'country/' + '1.2.3.4', json=self.country, status_code=200, headers={ 'Content-Type': self._content_type('country') }) self.client.country('1.2.3.4') request = mock.request_history[-1] self.assertEqual(request.path, '/geoip/v2.1/country/1.2.3.4', 'correct URI is used') self.assertEqual(request.headers['Accept'], 'application/json', 'correct Accept header') self.assertRegex(request.headers['User-Agent'], '^GeoIP2 Python Client v', 'Correct User-Agent') self.assertEqual(request.headers['Authorization'], 'Basic NDI6YWJjZGVmMTIzNDU2', 'correct auth') @requests_mock.mock() def test_city_ok(self, mock): mock.get( self.base_uri + 'city/' + '1.2.3.4', json=self.country, status_code=200, headers={ 'Content-Type': self._content_type('city') }) city = self.client.city('1.2.3.4') self.assertEqual( type(city), geoip2.models.City, 'return value of client.city') @requests_mock.mock() def test_insights_ok(self, mock): mock.get( self.base_uri + 'insights/1.2.3.4', json=self.country, status_code=200, headers={ 'Content-Type': self._content_type('country') }) insights = self.client.insights('1.2.3.4') self.assertEqual( type(insights), geoip2.models.Insights, 'return value of client.insights') if __name__ == '__main__': unittest.main() geoip2-2.7.0/tests/database_test.py0000644000175000017500000001767513230141446017134 0ustar greggreg00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import unicode_literals import sys sys.path.append('..') import geoip2.database import maxminddb try: import maxminddb.extension except ImportError: maxminddb.extension = None if sys.version_info[:2] == (2, 6): import unittest2 as unittest else: import unittest if sys.version_info[0] == 2: unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp unittest.TestCase.assertRegex = unittest.TestCase.assertRegexpMatches class BaseTestReader(object): def test_language_list(self): reader = geoip2.database.Reader( 'tests/data/test-data/GeoIP2-Country-Test.mmdb', ['xx', 'ru', 'pt-BR', 'es', 'en']) record = reader.country('81.2.69.160') self.assertEqual(record.country.name, 'Великобритания') reader.close() def test_unknown_address(self): reader = geoip2.database.Reader( 'tests/data/test-data/GeoIP2-City-Test.mmdb') with self.assertRaisesRegex(geoip2.errors.AddressNotFoundError, 'The address 10.10.10.10 is not in the ' 'database.'): reader.city('10.10.10.10') reader.close() def test_wrong_database(self): reader = geoip2.database.Reader( 'tests/data/test-data/GeoIP2-City-Test.mmdb') with self.assertRaisesRegex(TypeError, 'The country method cannot be used with ' 'the GeoIP2-City database'): reader.country('1.1.1.1') reader.close() def test_invalid_address(self): reader = geoip2.database.Reader( 'tests/data/test-data/GeoIP2-City-Test.mmdb') with self.assertRaisesRegex(ValueError, "u?'invalid' does not appear to be an " "IPv4 or IPv6 address"): reader.city('invalid') reader.close() def test_anonymous_ip(self): reader = geoip2.database.Reader( 'tests/data/test-data/GeoIP2-Anonymous-IP-Test.mmdb') ip_address = '1.2.0.1' record = reader.anonymous_ip(ip_address) self.assertEqual(record.is_anonymous, True) self.assertEqual(record.is_anonymous_vpn, True) self.assertEqual(record.is_hosting_provider, False) self.assertEqual(record.is_public_proxy, False) self.assertEqual(record.is_tor_exit_node, False) self.assertEqual(record.ip_address, ip_address) reader.close() def test_asn(self): reader = geoip2.database.Reader( 'tests/data/test-data/GeoLite2-ASN-Test.mmdb') ip_address = '1.128.0.0' record = reader.asn(ip_address) self.assertEqual(record.autonomous_system_number, 1221) self.assertEqual(record.autonomous_system_organization, 'Telstra Pty Ltd') self.assertEqual(record.ip_address, ip_address) self.assertRegex( str(record), r'geoip2.models.ASN\(.*1\.128\.0\.0.*\)', 'str representation is correct') self.assertEqual(record, eval(repr(record)), "ASN repr can be eval'd") reader.close() def test_city(self): reader = geoip2.database.Reader( 'tests/data/test-data/GeoIP2-City-Test.mmdb') record = reader.city('81.2.69.160') self.assertEqual(record.country.name, 'United Kingdom', 'The default locale is en') self.assertEqual(record.country.is_in_european_union, True) self.assertEqual(record.location.accuracy_radius, 100, 'The accuracy_radius is populated') self.assertEqual(record.registered_country.is_in_european_union, False) reader.close() def test_connection_type(self): reader = geoip2.database.Reader( 'tests/data/test-data/GeoIP2-Connection-Type-Test.mmdb') ip_address = '1.0.1.0' record = reader.connection_type(ip_address) self.assertEqual(record.connection_type, 'Cable/DSL') self.assertEqual(record.ip_address, ip_address) self.assertRegex( str(record), r'ConnectionType\(\{.*Cable/DSL.*\}\)', 'ConnectionType str representation is reasonable') self.assertEqual(record, eval(repr(record)), "ConnectionType repr can be eval'd") reader.close() def test_country(self): reader = geoip2.database.Reader( 'tests/data/test-data/GeoIP2-Country-Test.mmdb') record = reader.country('81.2.69.160') self.assertEqual(record.traits.ip_address, '81.2.69.160', 'IP address is added to model') self.assertEqual(record.country.is_in_european_union, True) self.assertEqual(record.registered_country.is_in_european_union, False) reader.close() def test_domain(self): reader = geoip2.database.Reader( 'tests/data/test-data/GeoIP2-Domain-Test.mmdb') ip_address = '1.2.0.0' record = reader.domain(ip_address) self.assertEqual(record.domain, 'maxmind.com') self.assertEqual(record.ip_address, ip_address) self.assertRegex( str(record), r'Domain\(\{.*maxmind.com.*\}\)', 'Domain str representation is reasonable') self.assertEqual(record, eval(repr(record)), "Domain repr can be eval'd") reader.close() def test_enterprise(self): with geoip2.database.Reader( 'tests/data/test-data/GeoIP2-Enterprise-Test.mmdb') as reader: ip_address = '74.209.24.0' record = reader.enterprise(ip_address) self.assertEqual(record.city.confidence, 11) self.assertEqual(record.country.confidence, 99) self.assertEqual(record.country.geoname_id, 6252001) self.assertEqual(record.country.is_in_european_union, False) self.assertEqual(record.location.accuracy_radius, 27) self.assertEqual(record.registered_country.is_in_european_union, False) self.assertEqual(record.traits.connection_type, 'Cable/DSL') self.assertTrue(record.traits.is_legitimate_proxy) self.assertEqual(record.traits.ip_address, ip_address) def test_isp(self): reader = geoip2.database.Reader( 'tests/data/test-data/GeoIP2-ISP-Test.mmdb') ip_address = '1.128.0.0' record = reader.isp(ip_address) self.assertEqual(record.autonomous_system_number, 1221) self.assertEqual(record.autonomous_system_organization, 'Telstra Pty Ltd') self.assertEqual(record.isp, 'Telstra Internet') self.assertEqual(record.organization, 'Telstra Internet') self.assertEqual(record.ip_address, ip_address) self.assertRegex( str(record), r'ISP\(\{.*Telstra.*\}\)', 'ISP str representation is reasonable') self.assertEqual(record, eval(repr(record)), "ISP repr can be eval'd") reader.close() def test_context_manager(self): with geoip2.database.Reader( 'tests/data/test-data/GeoIP2-Country-Test.mmdb') as reader: record = reader.country('81.2.69.160') self.assertEqual(record.traits.ip_address, '81.2.69.160') @unittest.skipUnless(maxminddb.extension, 'No C extension module found. Skipping tests') class TestExtensionReader(BaseTestReader, unittest.TestCase): mode = geoip2.database.MODE_MMAP_EXT class TestMMAPReader(BaseTestReader, unittest.TestCase): mode = geoip2.database.MODE_MMAP class TestFileReader(BaseTestReader, unittest.TestCase): mode = geoip2.database.MODE_FILE class TestMemoryReader(BaseTestReader, unittest.TestCase): mode = geoip2.database.MODE_MEMORY class TestAutoReader(BaseTestReader, unittest.TestCase): mode = geoip2.database.MODE_AUTO geoip2-2.7.0/tests/models_test.py0000644000175000017500000003603513230141446016642 0ustar greggreg00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import unicode_literals import sys sys.path.append('..') import geoip2.models if sys.version_info[:2] == (2, 6): import unittest2 as unittest else: import unittest if sys.version_info[0] == 2: unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp unittest.TestCase.assertRegex = unittest.TestCase.assertRegexpMatches class TestModels(unittest.TestCase): def test_insights_full(self): raw = { 'city': { 'confidence': 76, 'geoname_id': 9876, 'names': { 'en': 'Minneapolis' }, }, 'continent': { 'code': 'NA', 'geoname_id': 42, 'names': { 'en': 'North America' }, }, 'country': { 'confidence': 99, 'geoname_id': 1, 'iso_code': 'US', 'names': { 'en': 'United States of America' }, }, 'location': { 'average_income': 24626, 'accuracy_radius': 1500, 'latitude': 44.98, 'longitude': 93.2636, 'metro_code': 765, 'population_density': 1341, 'time_zone': 'America/Chicago', }, 'postal': { 'code': '55401', 'confidence': 33, }, 'subdivisions': [{ 'confidence': 88, 'geoname_id': 574635, 'iso_code': 'MN', 'names': { 'en': 'Minnesota' }, }, { 'geoname_id': 123, 'iso_code': 'HP', 'names': { 'en': 'Hennepin' }, }], 'registered_country': { 'geoname_id': 2, 'iso_code': 'CA', 'names': { 'en': 'Canada' }, }, 'represented_country': { 'geoname_id': 3, 'is_in_european_union': True, 'iso_code': 'GB', 'names': { 'en': 'United Kingdom' }, 'type': 'military', }, 'traits': { 'autonomous_system_number': 1234, 'autonomous_system_organization': 'AS Organization', 'domain': 'example.com', 'ip_address': '1.2.3.4', 'is_anonymous': True, 'is_anonymous_proxy': True, 'is_anonymous_vpn': True, 'is_hosting_provider': True, 'is_public_proxy': True, 'is_satellite_provider': True, 'is_tor_exit_node': True, 'isp': 'Comcast', 'network_speed': 'cable/DSL', 'organization': 'Blorg', 'user_type': 'college', }, } model = geoip2.models.Insights(raw) self.assertEqual( type(model), geoip2.models.Insights, 'geoip2.models.Insights object') self.assertEqual( type(model.city), geoip2.records.City, 'geoip2.records.City object') self.assertEqual( type(model.continent), geoip2.records.Continent, 'geoip2.records.Continent object') self.assertEqual( type(model.country), geoip2.records.Country, 'geoip2.records.Country object') self.assertEqual( type(model.registered_country), geoip2.records.Country, 'geoip2.records.Country object') self.assertEqual( type(model.represented_country), geoip2.records.RepresentedCountry, 'geoip2.records.RepresentedCountry object') self.assertEqual( type(model.location), geoip2.records.Location, 'geoip2.records.Location object') self.assertEqual( type(model.subdivisions[0]), geoip2.records.Subdivision, 'geoip2.records.Subdivision object') self.assertEqual( type(model.traits), geoip2.records.Traits, 'geoip2.records.Traits object') self.assertEqual(model.raw, raw, 'raw method returns raw input') self.assertEqual(model.subdivisions[0].iso_code, 'MN', 'div 1 has correct iso_code') self.assertEqual(model.subdivisions[0].confidence, 88, 'div 1 has correct confidence') self.assertEqual(model.subdivisions[0].geoname_id, 574635, 'div 1 has correct geoname_id') self.assertEqual(model.subdivisions[0].names, {'en': 'Minnesota'}, 'div 1 names are correct') self.assertEqual(model.subdivisions[1].name, 'Hennepin', 'div 2 has correct name') self.assertEqual(model.subdivisions.most_specific.iso_code, 'HP', 'subdivisions.most_specific returns HP') self.assertEqual(model.represented_country.name, 'United Kingdom', 'represented_country name is correct') self.assertEqual(model.represented_country.type, 'military', 'represented_country type is correct') self.assertEqual(model.location.average_income, 24626, 'correct average_income') self.assertEqual(model.location.latitude, 44.98, 'correct latitude') self.assertEqual(model.location.longitude, 93.2636, 'correct longitude') self.assertEqual(model.location.metro_code, 765, 'correct metro_code') self.assertEqual(model.location.population_density, 1341, 'correct population_density') self.assertRegex( str(model), r'^geoip2.models.Insights\(\{.*geoname_id.*\}, \[.*en.*\]\)', 'Insights str representation looks reasonable') self.assertEqual(model, eval(repr(model)), "Insights repr can be eval'd") self.assertRegex( str(model.location), r'^geoip2.records.Location\(.*longitude=.*\)', 'Location str representation is reasonable') self.assertEqual(model.location, eval(repr(model.location)), "Location repr can be eval'd") self.assertIs(model.country.is_in_european_union, False) self.assertIs(model.registered_country.is_in_european_union, False) self.assertIs(model.represented_country.is_in_european_union, True) self.assertIs(model.traits.is_anonymous, True) self.assertIs(model.traits.is_anonymous_proxy, True) self.assertIs(model.traits.is_anonymous_vpn, True) self.assertIs(model.traits.is_hosting_provider, True) self.assertIs(model.traits.is_public_proxy, True) self.assertIs(model.traits.is_satellite_provider, True) self.assertIs(model.traits.is_tor_exit_node, True) def test_insights_min(self): model = geoip2.models.Insights({'traits': {'ip_address': '5.6.7.8'}}) self.assertEqual( type(model), geoip2.models.Insights, 'geoip2.models.Insights object') self.assertEqual( type(model.city), geoip2.records.City, 'geoip2.records.City object') self.assertEqual( type(model.continent), geoip2.records.Continent, 'geoip2.records.Continent object') self.assertEqual( type(model.country), geoip2.records.Country, 'geoip2.records.Country object') self.assertEqual( type(model.registered_country), geoip2.records.Country, 'geoip2.records.Country object') self.assertEqual( type(model.location), geoip2.records.Location, 'geoip2.records.Location object') self.assertEqual( type(model.traits), geoip2.records.Traits, 'geoip2.records.Traits object') self.assertEqual( type(model.subdivisions.most_specific), geoip2.records.Subdivision, 'geoip2.records.Subdivision object returned even' 'when none are available.') self.assertEqual(model.subdivisions.most_specific.names, {}, 'Empty names hash returned') def test_city_full(self): raw = { 'continent': { 'code': 'NA', 'geoname_id': 42, 'names': { 'en': 'North America' }, }, 'country': { 'geoname_id': 1, 'iso_code': 'US', 'names': { 'en': 'United States of America' }, }, 'registered_country': { 'geoname_id': 2, 'iso_code': 'CA', 'names': { 'en': 'Canada' }, }, 'traits': { 'ip_address': '1.2.3.4', 'is_satellite_provider': True, }, } model = geoip2.models.City(raw) self.assertEqual( type(model), geoip2.models.City, 'geoip2.models.City object') self.assertEqual( type(model.city), geoip2.records.City, 'geoip2.records.City object') self.assertEqual( type(model.continent), geoip2.records.Continent, 'geoip2.records.Continent object') self.assertEqual( type(model.country), geoip2.records.Country, 'geoip2.records.Country object') self.assertEqual( type(model.registered_country), geoip2.records.Country, 'geoip2.records.Country object') self.assertEqual( type(model.location), geoip2.records.Location, 'geoip2.records.Location object') self.assertEqual( type(model.traits), geoip2.records.Traits, 'geoip2.records.Traits object') self.assertEqual(model.raw, raw, 'raw method returns raw input') self.assertEqual(model.continent.geoname_id, 42, 'continent geoname_id is 42') self.assertEqual(model.continent.code, 'NA', 'continent code is NA') self.assertEqual(model.continent.names, {'en': 'North America'}, 'continent names is correct') self.assertEqual(model.continent.name, 'North America', 'continent name is correct') self.assertEqual(model.country.geoname_id, 1, 'country geoname_id is 1') self.assertEqual(model.country.iso_code, 'US', 'country iso_code is US') self.assertEqual(model.country.names, {'en': 'United States of America'}, 'country names is correct') self.assertEqual(model.country.name, 'United States of America', 'country name is correct') self.assertEqual(model.country.confidence, None, 'country confidence is None') self.assertEqual(model.registered_country.iso_code, 'CA', 'registered_country iso_code is CA') self.assertEqual(model.registered_country.names, {'en': 'Canada'}, 'registered_country names is correct') self.assertEqual(model.registered_country.name, 'Canada', 'registered_country name is correct') self.assertEqual(model.traits.is_anonymous_proxy, False, 'traits is_anonymous_proxy returns False by default') self.assertEqual(model.traits.is_satellite_provider, True, 'traits is_setellite_provider is True') self.assertEqual(model.raw, raw, 'raw method produces raw output') self.assertRegex( str(model), r'^geoip2.models.City\(\{.*geoname_id.*\}, \[.*en.*\]\)') self.assertFalse(model == True, '__eq__ does not blow up on weird input') def test_unknown_keys(self): model = geoip2.models.City({ 'traits': { 'ip_address': '1.2.3.4', 'invalid': 'blah' }, 'unk_base': { 'blah': 1 } }) with self.assertRaises(AttributeError): model.unk_base with self.assertRaises(AttributeError): model.traits.invalid self.assertEqual(model.traits.ip_address, '1.2.3.4', 'correct ip') class TestNamess(unittest.TestCase): raw = { 'continent': { 'code': 'NA', 'geoname_id': 42, 'names': { 'de': 'Nordamerika', 'en': 'North America', 'es': 'América del Norte', 'ja': '北アメリカ', 'pt-BR': 'América do Norte', 'ru': 'Северная Америка', 'zh-CN': '北美洲', }, }, 'country': { 'geoname_id': 1, 'iso_code': 'US', 'names': { 'en': 'United States of America', 'fr': 'États-Unis', 'zh-CN': '美国', }, }, 'traits': { 'ip_address': '1.2.3.4', }, } def test_names(self): model = geoip2.models.Country(self.raw, locales=['sq', 'ar']) self.assertEqual(model.continent.names, self.raw['continent']['names'], 'Correct names dict for continent') self.assertEqual(model.country.names, self.raw['country']['names'], 'Correct names dict for country') def test_three_locales(self): model = geoip2.models.Country(self.raw, locales=['fr', 'zh-CN', 'en']) self.assertEqual(model.continent.name, '北美洲', 'continent name is in Chinese (no French available)') self.assertEqual(model.country.name, 'États-Unis', 'country name is in French') def test_two_locales(self): model = geoip2.models.Country(self.raw, locales=['ak', 'fr']) self.assertEqual(model.continent.name, None, 'continent name is undef (no Akan or French ' 'available)') self.assertEqual(model.country.name, 'États-Unis', 'country name is in French') def test_unknown_locale(self): model = geoip2.models.Country(self.raw, locales=['aa']) self.assertEqual(model.continent.name, None, 'continent name is undef (no Afar available)') self.assertEqual(model.country.name, None, 'country name is in None (no Afar available)') def test_german(self): model = geoip2.models.Country(self.raw, locales=['de']) self.assertEqual(model.continent.name, 'Nordamerika', 'Correct german name for continent') if __name__ == '__main__': unittest.main() geoip2-2.7.0/tests/__init__.py0000664000175000017500000000000012144244616016046 0ustar greggreg00000000000000geoip2-2.7.0/tests/data/0000755000175000017500000000000013230142214014642 5ustar greggreg00000000000000geoip2-2.7.0/tests/data/test-data/0000755000175000017500000000000013230142214016530 5ustar greggreg00000000000000geoip2-2.7.0/tests/data/test-data/GeoLite2-ASN-Test.mmdb0000644000175000017500000000614013227476051022357 0ustar greggreg00000000000000|A      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab~cdekfghijlnmopqrstuvwxyz{|}`     !"#$%&'()*+,-./0123456789:;<=>?@BCDjEFGHIJKLMiNOPQRS^TUVWXYZ[\]`_`abcdefgh`klmnopqrstuvwxyz{}~Xautonomous_system_number]autonomous_system_organizationOTelstra Pty Ltd j j MAT&T Services  RMerit Network Inc.  XHurricane Electric, Inc.MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeLGeoLite2-ASNKdescriptionBen]+GeoLite2 ASN Test Database (fake GeoIP2 data, for example purposes only)Jip_versionIlanguagesBenJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/GeoIP2-Anonymous-IP-Test.mmdb0000644000175000017500000001014013227476051023642 0ustar greggreg00000000000000*z****B * * * * ******************* *!*"*#*$*%*&*'*(*)***+*,*-*.*/*0*1*2*3*4*5*6*7*8*9*:*;*<*=*>*?*@*A*B*C*D*E*F*G*H*I*J*K*L*M*N*O*P*Q3R*S*T*U*V*W*X*Y*Z*[*\*]*^*_*`*absc*d*epf*g*hi*j*k*l*m*n**o+*q**r*tuv*w~x**yz*{*|*}*N*******************f********************************************************************2* *******************************************  * * ****************** **!*"#*$*%*&*'*(*)***+**,*-*./*0*1***4*5*6*7*8*9*:*;*<*=*>*?*@*A*`C*D*E*F*G*H*I*J*K*L*M*N*O*P*Q*R*S*T*U*V*W*X*Y*Z*[*\*]*^*_*`*a*b*c*d*e*f*g*h*i*j*k*l*m*n*o*p*q*r*s*t*u*v*w*x*y**{*|*}*~***************`***********`***************************************************************************************************** * * * * ************Lis_anonymousPis_anonymous_vpn   Pis_tor_exit_node   Sis_hosting_provider      A Ois_public_proxy  )    d MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeSGeoIP2-Anonymous-IPKdescriptionBen]2GeoIP2 Anonymous IP Test Database (fake GeoIP2 data, for example purposes only)Jip_versionIlanguagesBenJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/MaxMind-DB-test-metadata-pointers.mmdb0000644000175000017500000000422613227476051025630 0ustar greggreg00000000000000=VVVVV V V V V VVVVVVVVVVVVVVVVVVV V!V"V#V$V%V&V'V(V)V*V+V,V-V.V/V0V1V2V3V4V5V6V7V8V9V:V;V<V=V>V?V@VAVBVCVDVEVFVGVHVIVJVKVLVMVNVOVPVQVRVSVTVUVVVWVXVYVZV[V\V]V^V_V`VawbkcVdVehfVgVFViVVjFVVlmsnVVopVqVrVVFVtVuVvVFxVyzVV{|}VV~VVVVVVVFVVVVVVVFFVVVVVVVVVVVVVVVVVVVVFVFVVVVVVVVVVVVVVVFVVVVVVFVVVVVVVVVFVVVVVVVVVVVVFVVVVVVVVVVVVVVVVVVVVFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV V V V V VVVVVVVVVVVVVVVVVFVV V!V"V#V$V%V&V'V(V)V*VV+,V-V.V/V021VFVV34VV5V67VV8V9V:;V<VFVV>V?V@VAVBFCDFVEFVMaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZٲMdatabase_type\Lots of pointers in metadataKdescriptionBen \Bes \Bzh \Jip_versionIlanguagesBenBesBzhJnode_countFKrecord_sizegeoip2-2.7.0/tests/data/test-data/GeoIP2-Domain-Test.mmdb0000644000175000017500000001426613227476051022570 0ustar greggreg00000000000000*33333_ 3 3 3 3 3333333333333333333 3!3"3#3$3%3&3'3(3)3*3+3,3-3.3/303132333435363738393:3;3<3=3>3?3@3A3B3C3D3E3F3G3H3I3J3K3L3M3N3O3P3QPR3S3T3U3V3W3X3Y3Z3[3\3]3^3_3`3absc3d3epf3g33hi3j3k3l3m3n33oC3q33r33tuKv wx3yz3{|33}~3333333W333333333d3333333d3d33333333q3qq333qqqqqq3q333333333333333333333333333333333333333333W3333W3W333333333333333333333 3 3 3 343&3333333333 3!"3#$%3'33()3*33+3,-33./W301W323W3W35637383933:3;<33=>3?33@AFBCD3E3G3HIJ3LcM3NZ3OP3Q3R3S3T3U33VW3X33Y33[3\3]^3_33`3a3b3d3e33fgu3hi33j3k3lmnopqrs3t33v33wx3y3z3{3|3}3~333333333333333333333333333333333333333333333333333333333333333333333333,3O*33333333333333333333333333333333333333333333333333 33 3333  3 33333333333333333333 3!3"3#33$3%3&'3(3)333+>,3-3.3/330312333343563373893:<3;<<=<3<3?3@A33B3C3DE3F33G3HI33JK3L3M33NS3333Q3R3S3T3U3V3W3X3Y3Z3[3\3]3^3``3a3b3c3d3e3f3g3h3i3j3k3l3m3n3o3p3q3r3s3t3u3v3w3x3y3z3{3|3}3~3333333333333333333333333333333333333333333333333333`3333333333333`3333333333333333333333333333333333333333333333333333333333`33333333333333 3 3 33  3333333333333333333 3!3"3#3$3%3&3'3(3)3n33+3,3-3.3/30133233FdomainKmaxmind.com Inuvox.net Iqwest.net Mspeakeasy.net Lshoesfin.NET Mameritech.net Kpacbell.net Kverizon.net Icovad.net Jpopwifi.it Lin-addr.arpa Ioleane.fr Gbbox.fr Mbredband2.com Stelebecinternet.net Lreplaced.com Scomcastbusiness.net Igol.ne.jp Jsgotti.org Gsfr.netMaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeMGeoIP2-DomainKdescriptionBen],GeoIP2 Domain Test Database (fake GeoIP2 data, for example purposes only)Jip_versionIlanguagesBenJnode_count3Krecord_sizegeoip2-2.7.0/tests/data/test-data/MaxMind-DB-string-value-entries.mmdb0000644000175000017500000000247513227476051025325 0ustar greggreg000000000000004(%  !"#$&')*0+,-./1235I6789C:;<=>?@ABDEFGHJKLMzNOPsQeRSTUVWXYZ[\]^d_`abcfghijklmnopqrtuvwxy{|}~K1.1.1.16/28J1.1.1.8/29J1.1.1.4/30J1.1.1.2/31J1.1.1.1/32K1.1.1.32/32MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_type]MaxMind DB String Value EntriesKdescriptionBen] MaxMind DB String Value Entries (no maps or arrays as values)Jip_versionIlanguagesBenJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/MaxMind-DB-test-mixed-32.mmdb0000644000175000017500000000756413227476051023547 0ustar greggreg00000000000000S      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQDRSTUVWXYZ[\]^_$`abcdefghijklmnopqrstuvwxyz{|}~      !"##%&'()*+,-./0123456789:;<=>5?@AANBC[EFGHIJKLMNOPQR`TUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~``BipJ::1.1.1.16BipI::1.1.1.8BipI::1.1.1.4BipI::1.1.1.2BipI::1.1.1.1BipJ::1.1.1.32BipM::1:ffff:ffffBipG::2:0:0BipH::2:0:40BipH::2:0:50BipH::2:0:58MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeDTestKdescriptionBenMTest DatabaseBzhUTest Database ChineseJip_versionIlanguagesBenBzhJnode_countKrecord_size geoip2-2.7.0/tests/data/test-data/MaxMind-DB-test-ipv6-32.mmdb0000644000175000017500000000706613227476051023322 0ustar greggreg00000000000000n6      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ'RSTUVWXYZ[\]^_`awbkcdehfgijlmsnopqrtuvxyz{|}~      !"#$%&()*+,-./012345`789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmopqrstuvwxyz{|}~``BipM::1:ffff:ffffBipG::2:0:0BipH::2:0:40BipH::2:0:50BipH::2:0:58MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeDTestKdescriptionBenMTest DatabaseBzhUTest Database ChineseJip_versionIlanguagesBenBzhJnode_countKrecord_size geoip2-2.7.0/tests/data/test-data/GeoIP2-Enterprise-Test.mmdb0000644000175000017500000001737213227476051023502 0ustar greggreg00000000000000      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcde~fghijklmnopqrstuvwxyz{|}*,9 ( I ikL 6   / ! "#$%&'()*+,-.012345789:;?<=>@ABCDEFGHIJKMNO[PQRSTUVWXYZ\]^_`abcdefghijlmnopqrstuvwxyz{|}~``     `DcityJconfidence2Jgeoname_id(EEnamesBenGBoxfordIcontinentDcodeBEU _r, #BdeFEuropaBenFEuropeBes TBfr ^BjaOヨーロッパEpt-BR TBruLЕвропаEzh-CNF欧洲Gcountry _ (5Tis_in_european_unionHiso_codeBGB #BdeWVereinigtes KönigreichBenNUnited KingdomBesKReino UnidoBfrKRoyaume-UniBjaLイギリス !Bru\Великобритания F英国HlocationOaccuracy_radiusdHlatitudeh@IIlongitudehItime_zoneMEurope/LondonFpostal @COX1 Rregistered_country . BFR #BdeJFrankreichBenFFranceBesGFranciaBfr" BjaUフランス共和国 GFrançaBruNФранция F法国Lsubdivisions F _ CENG #BenGEnglandBesJInglaterraBfrJAngleterre " 2a CWBK #BenNWest BerkshireBru]Западный Беркшир L西伯克郡 5 @BAS _r+ #BdeEAsienBenDAsiaBes# BfrDAsieBjaIアジア EÁsiaBruHАзия F亚洲 c  BBT #BdeFBhutanBen#tBesFButánBfr#tBjaRブータン王国 FButãoBruJБутан F不丹!h!r!h@;!h@V!LAsia/Thimphu!  /U BRO #BdeIRumänienBenGRomaniaBesHRumaníaBfrHRoumanieBjaOルーマニア HRomêniaBruNРумыния L罗马尼亚FtraitsXautonomous_system_numberŒDFdomainLshoesfin.NETRis_anonymous_proxy CispKLoud PacketLorganizationOzudoarichikito_Iuser_typeTsearch_engine_spider   N #BenGChatham 5 @BNA _r- #BdeKNordamerikaBenMNorth AmericaBesMNorteaméricaBfrQAmérique du NordBjaO北アメリカ QAmérica do NorteBru]Северная Америка I北美洲 c _e BUS #BdeCUSABenMUnited StatesBesNEstados UnidosBfrKÉtats-UnisBjaUアメリカ合衆国 & BruFСША F美国!h!r!h@E,?!hRc{J#:Jmetro_code!PAmerica/New_York! @E12037  ! _e BUS #%"_ ] NA BNY #BdeHNew YorkBen&BesJNueva YorkBfr&BjaUニューヨーク州 KNova IorqueBruOНью-Йорк I纽约州$v$~9O]autonomous_system_organizationXFairPoint CommunicationsOconnection_typeICable/DSL$Hfrpt.net$ Sis_legitimate_proxy Uis_satellite_provider CispXFairpoint Communications$'$Kresidential  * (W #BdeFLondonBen(BesGLondresBfr("BjaLロンドン ("BruLЛондон 5 ? c (5 BGB # !h!rd!h@IN;6!hfA!!! _e BUS #%"_ * _ CENG #"$v'xICorporate$Lin-addr.arpaCispTAndrews & Arnold Ltd$YSTONEHOUSE office network$Jgovernment  3 )j #BdeJLinköpingBen(3Bfr(3BjaXリンシェーピング I林雪平 5 ? c ( BSE #BdeHSchwedenBenFSwedenBesFSueciaBfrFSuèdeBjaXスウェーデン王国 GSuéciaBruLШвеция F瑞典!h!rL!h@M5Vl!!h@/;6!PEurope/Stockholm! ,T BDE #BdeKDeutschlandBenGGermanyBesHAlemaniaBfrIAllemagneBjaXドイツ連邦共和国 HAlemanhaBruPГермания F德国"_ 3 ( AE #BenUÖstergötland CountyBfrWComté d'Östergötland$v$~sN'?LBredband2 AB'x($Mbredband2.comCisp($FBevtec$(  2  #BdeKChángchūnBenIChangchunBfr(bBjaI長春市BruNЧанчунь F长春 5# _  BCN #BdeEChinaBen(Bes(BfrEChineBjaF中国 (BruJКитай (!h!rd!h@E =q!h@_TTɆ!KAsia/Harbin!  BCN #("_ F  B22 #BenKJilin Sheng F吉林$v$Fdialup 5# _ 8 BPH #BdeKPhilippinenBenKPhilippinesBesIFilipinasBfr(BjaXフィリピン共和国 (BruRФилиппины I菲律宾!h!ry!h@*!h@^!KAsia/Manila! @E34021 ! 8 BPH #(Srepresented_country _e BUS #%DtypeHmilitary$v$ $v'  ( X$ #BenFMiltonBruNМильтон 5 @BNA _r- #Bde%?Ben%NBesRAmérica del NorteBfr%pBja% %Bru% % c _e BUS #%!h!r!h@G*0!h^'RT`&t3!SAmerica/Los_Angeles! @E98354 (! (5 BGB # "_ c X_ BWA #BenJWashingtonBes(BfrSÉtat de WashingtonBjaRワシントン州BruRВашингтон L华盛顿州$v$~'x'CispLCentury Link$OLariat Software$(MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeQGeoIP2-EnterpriseKdescriptionBen]0GeoIP2 Enterprise Test Database (fake GeoIP2 data, for example purposes only)Jip_versionIlanguagesBenJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/GeoIP2-DensityIncome-Test.mmdb0000644000175000017500000000577113227476051024134 0ustar greggreg00000000000000{R      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ RSTUVWXYZ[\]^_`ab{cdexfhgijklmnopqrstuvwyz|}~    ` !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQSTUVWXYZ[\]^z_`abcdoefghijklmn`pqrstuvwxy`|}~Naverage_income~CRpopulation_density `2 =MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeTGeoIP2-DensityIncomeKdescriptionBen]3GeoIP2 DensityIncome Test Database (fake GeoIP2 data, for example purposes only)Jip_versionIlanguagesBenJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/MaxMind-DB-test-ipv6-28.mmdb0000644000175000017500000000622613227476051023324 0ustar greggreg00000000000000n6      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ'RSTUVWXYZ[\]^_`awbkcdehfgijlmsnopqrtuvxyz{|}~      !"#$%&()*+,-./012345`789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmopqrstuvwxyz{|}~``BipM::1:ffff:ffffBipG::2:0:0BipH::2:0:40BipH::2:0:50BipH::2:0:58MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeDTestKdescriptionBenMTest DatabaseBzhUTest Database ChineseJip_versionIlanguagesBenBzhJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/MaxMind-DB-test-mixed-24.mmdb0000644000175000017500000000577213227476051023547 0ustar greggreg00000000000000S      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQDRSTUVWXYZ[\]^_$`abcdefghijklmnopqrstuvwxyz{|}~      !"##%&'()*+,-./0123456789:;<=>5?@AANBC[EFGHIJKLMNOPQR`TUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~``BipJ::1.1.1.16BipI::1.1.1.8BipI::1.1.1.4BipI::1.1.1.2BipI::1.1.1.1BipJ::1.1.1.32BipM::1:ffff:ffffBipG::2:0:0BipH::2:0:40BipH::2:0:50BipH::2:0:58MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeDTestKdescriptionBenMTest DatabaseBzhUTest Database ChineseJip_versionIlanguagesBenBzhJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/GeoIP2-Country-Test.mmdb0000644000175000017500000004321213227476051023015 0ustar greggreg00000000000000      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcde~fghijklmnopqrstuvwxyz{|} 8 8 8 8 E E T     uV@9+ !"#$*%&'(),-./012345678:;<=>?ABCDEIFGHJKLMNOPQRSTUWXYeZ[\]^_`abcd fghijklmnopqrstvwxyz{|}~  `x`  <    !  2-# !" !$*%' T& T() T T+, !.5/201 !34 !6978 :; !=\>M?F@CAB DE2GJHI KL !NUORPQ !ST !VYWX Z[ ]i^e_b`a !cd !fgh jqknlmop !rust !vw !yz{|}~`+  8         x$!  "#%(&')*,k-L.=/60312 45 7:89 ;<>E?B@ACDFIGHJKM\NUORPQ STVYWX#Z[ ]d^a_` bc ehfg ij lm|nuorpq stvywx z{}~   D3]#  8        $ ! "# %,&)'(*+ -0./124p5Q6B7>8;9: <= ?@A CJDGEFHI KNLMOPRaSZTWUVXY[^\]_`bicfde ghjmkl noqrsztwuvxy {~|}     7     T       !h(! "%#$ &' )0*-+,D./1423568w9X:I;B<?=> @ACFDE GHJQKNLMOPRUSTVWYhZa[^\]_`becd fgipjmkl noqtrsuvxyz{~|}! !#"y  IcontinentDcodeBEUJgeoname_id_r,EnamesBdeFEuropaBenFEuropeBes -Bfr 7BjaOヨーロッパEpt-BR -BruLЕвропаEzh-CNF欧洲Gcountry (5Tis_in_european_unionHiso_codeBGB #BdeWVereinigtes KönigreichBenNUnited KingdomBesKReino UnidoBfrKRoyaume-UniBjaLイギリス [ Bru\Великобритания sF英国Fpostal COX1Rregistered_country . BFR #BdeJFrankreichBenFFranceBesGFranciaBfr!BjaUフランス共和国 [GFrançaBruNФранция sF法国  BNA _r- #BdeKNordamerikaBenMNorth AmericaBesRAmérica del NorteBfrQAmérique du NordBjaO北アメリカ [QAmérica do NorteBru]Северная Америка sI北美洲 _e BUS #BdeCUSABenMUnited StatesBesNEstados UnidosBfrKÉtats-UnisBjaUアメリカ合衆国 ["BruFСША sF美国!K"  BAS _r+ #BdeEAsienBenDAsiaBes#'BfrDAsieBjaIアジア [EÁsiaBruHАзия sF亚洲  BBT #BdeFBhutanBen#wBesFButánBfr#wBjaRブータン王国 [FButãoBruJБутан sF不丹!K  /U BRO #BdeIRumänienBenGRomaniaBesHRumaníaBfrHRoumanieBjaOルーマニア [HRomêniaBruNРумыния sL罗马尼亚FtraitsRis_anonymous_proxy  !K"  ( BSE #BdeHSchwedenBenFSwedenBesFSueciaBfrFSuèdeBjaXスウェーデン王国 [GSuéciaBruLШвеция sF瑞典!K ,T BDE #BdeKDeutschlandBenGGermanyBesHAlemaniaBfrIAllemagneBjaXドイツ連邦共和国 [HAlemanhaBruPГермания sF德国 #  BCN #BdeEChinaBenZPeople's Republic of ChinaBesXRepública Popular ChinaBfrEChineBjaF中国 [%BruJКитай s%!K% # 8 BPH #BdeKPhilippinenBenKPhilippinesBesIFilipinasBfr&3BjaXフィリピン共和国 [&BBruRФилиппины sI菲律宾!= E34021!K&Srepresented_country _e BUS #"DtypeHmilitary ! "!= E98354!K  $B BGI #BdeIGibraltarBen'Bes'Bfr'BjaRジブラルタル ['BruRГибралтар!K& # e BJP #BdeEJapanBen'kBesFJapónBfrEJaponBjaF日本 [FJapãoBruLЯпония s'!K'Y # A BKR #BdeNRepublik KoreaBenKSouth KoreaBesTCorea, República deBfrMCorée du SudBjaL大韓民国 [VCoréia, República daBruUЮжная Корея sF韩国!K' # t BTW #BdeFTaiwanBen(|BesGTaiwánBfrGTaïwanBjaF台湾 [(|BruNТайвань s(!K(j # R BHK #BdeHHongkongBenIHong KongBes(Bfr(BjaF香港 [(BruNГонконг s(!K(  / BNO #BdeHNorwegenBenFNorwayBesGNoruegaBfrHNorvègeBjaUノルウェー王国 [(_BruPНорвегия sF挪威!K(7 # ~ BIL #BdeFIsraelBen(Bes(BfrGIsraëlBjaRイスラエル国 [(BruNИзраиль sI以色列!K(  !^!K!^  ( BCH #BdeGSchweizBenKSwitzerlandBesESuizaBfrFSuisseBjaOスイス連邦 [GSuíçaBruRШвейцария sF瑞士!K(<  $}!K$} # m BBH #BdeGBahrainBen(BesHBahréinBfrHBahreïnBjaOバーレーン [(BruNБахрейн sF巴林!K(  Z BRU #BdeHRusslandBenFRussiaBesERusiaBfrFRussieBjaIロシア [GRússiaBruLРоссия sI俄罗斯!K(D   /P BPL #BdeEPolenBenFPolandBesGPoloniaBfrGPologneBjaXポーランド共和国 [HPolôniaBruLПольша sF波兰!K(  $!K$  0s BIT #BdeGItalienBenEItalyBesFItaliaBfrFItalieBjaUイタリア共和国 [GItáliaBruLИталия sI意大利!K(P   - BFI #BdeHFinnlandBenGFinlandBesIFinlandiaBfrHFinlandeBja[フィンランド共和国 [JFinlândiaBruRФинляндия sF芬兰!K(   @ BBY #BdeMWeißrusslandBenGBelarusBesKBielorrusiaBfrLBiélorussieBjaXベラルーシ共和国 [MBielo-RússiaBruPБеларусь sL白俄罗斯!K(p  . BCZ #BdeUTschechische RepublikBenNCzech RepublicBesPRepública ChecaBfrITchéquieBjaRチェコ共和国 [(VBru]Чешская Республика sO捷克共和国!K( #  BIR #BdeZIran (Islamische Republik)BenDIranBes\Irán (República Islámica)Bfr]Iran (République islamique de)Bja]イラン・イスラム共和国 [\República Islâmica do IrãBruHИран sX伊朗伊斯兰共和国!K(   g BUA #BdeGUkraineBen(BesGUcraniaBfr(BjaXウクライナ共和国 [HUcrâniaBruNУкраина sI乌克兰!K(  !K   BHU #BdeFUngarnBenGHungaryBesHHungríaBfrGHongrieBjaXハンガリー共和国 [GHungriaBruNВенгрия sI匈牙利!K(U  HlocationHlatitudeh@HXq`l Ilongitudeh@"GX:SItime_zoneLEurope/Vaduz  &O BES #BdeGSpanienBenESpainBesGEspañaBfrGEspagneBjaLスペイン [GEspanhaBruNИспания sI西班牙!K( /   . BBG #BdeIBulgarienBenHBulgariaBes( BfrHBulgarieBjaXブルガリア共和国 [IBulgáriaBruPБолгария sL保加利亚!K(  #!K#  *¹ BBE #BdeGBelgienBenGBelgiumBesHBélgicaBfrHBelgiqueBjaRベルギー王国 [( ~BruNБельгия sI比利时!K( R # + BTR #BdeGTürkeiBenFTurkeyBesHTurquíaBfrGTurquieBjaRトルコ共和国 [GTurquiaBruLТурция sI土耳其!K(  *s BAT #BdeKÖsterreichBenGAustriaBes( BfrHAutricheBja[オーストリア共和国 [HÁustriaBruNАвстрия sI奥地利!K( [   BAL #BdeHAlbanienBenGAlbaniaBes( BfrGAlbanieBjaXアルバニア共和国 [HAlbâniaBruNАлбания sO阿尔巴尼亚!K( # & BLB #BdeGLibanonBenGLebanonBesGLíbanoBfrELibanBjaUレバノン共和国 [( BruJЛиван sI黎巴嫩!K( |  ) BNL #BdeKNiederlandeBenKNetherlandsBesGHolandaBfrHPays-BasBjaRオランダ王国 [NPaíses BaixosBruTНидерланды sF荷兰!K( # [ BKW #BdeFKuwaitBen( Bes( BfrGKoweïtBjaOクウェート [( BruLКувейт sI科威特!K( #  BSA #BdeMSaudi-ArabienBenLSaudi ArabiaBesNArabia SauditaBfrOArabie saouditeBja[サウジアラビア王国 [OArábia SauditaBru]Саудовская Аравия sO沙特阿拉伯!K(  _L BRS #BdeGSerbienBenFSerbiaBes(BfrFSerbieBjaLセルビア [GSérviaBruLСербия sL塞尔维亚!K( #  BJO #BdeIJordanienBen[Hashemite Kingdom of JordanBesHJordaniaBfrHJordanieBja]ヨルダン・ハシミテ王国 [IJordâniaBruPИордания sF约旦!K(H  BAF _r* #BdeFAfrikaBenFAfricaBesGÁfricaBfrGAfriqueBjaLアフリカ [(BruLАфрика sF非洲 ! BLY #Bde]Libysch-Arabische DschamahirijaBenELibyaBesXLibia, República ÁrabeBfrELibyeBja] 社会主義人民リビア・アラブ国 [XLíbia Árabe JamahiriyaBruJЛивия s[阿拉伯利比亚民众国!K([  -8 BIE #BdeFIrlandBenGIrelandBesURepública de IrlandaBfrGIrlandeBjaRアイルランド [GIrlandaBruPИрландия sI爱尔兰!K(> # l BAZ #BdeMAserbaidschanBenJAzerbaijanBesKAzerbaiyánBfrLAzerbaïdjanBja]アゼルバイジャン共和国 [KAzerbaijãoBruVАзербайджан sL阿塞拜疆!K( # n BAE #Bde\Vereinigte Arabische EmirateBenTUnited Arab EmiratesBesWEmiratos Árabes UnidosBfrTÉmirats Arabes UnisBjaXアラブ首長国連邦 [WEmirados Árabes UnidosBru]Объединенные Арабские Эмираты sX阿拉伯联合酋长国!K( #  BAM #BdeHArmenienBenGArmeniaBes(BfrHArménieBjaXアルメニア共和国 [HArmêniaBruNАрмения sL亚美尼亚!K(  (8 BDK #BdeIDänemarkBenGDenmarkBesIDinamarcaBfrHDanemarkBjaUデンマーク王国 [(ZBruJДания sF丹麦!K(,  .k BIM #BdeIInsel ManBenKIsle of ManBesKIsla de ManBfrKÎle de ManBjaIマン島 [KIlha de ManBruMМэн, о-в sF曼岛!K(MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeNGeoIP2-CountryKdescriptionBen]-GeoIP2 Country Test Database (fake GeoIP2 data, for example purposes only)Jip_versionIlanguagesBenJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/MaxMind-DB-test-ipv4-24.mmdb0000644000175000017500000000242213227476051023310 0ustar greggreg000000000000004(%  !"#$&')*0+,-./1235I6789C:;<=>?@ABDEFGHJKLMzNOPsQeRSTUVWXYZ[\]^d_`abcfghijklmnopqrtuvwxy{|}~BipH1.1.1.16BipG1.1.1.8BipG1.1.1.4BipG1.1.1.2BipG1.1.1.1BipH1.1.1.32MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeDTestKdescriptionBenMTest DatabaseBzhUTest Database ChineseJip_versionIlanguagesBenBzhJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/GeoIP2-ISP-Test.mmdb0000644000175000017500000022462113227476051022012 0ustar greggreg00000000000000O      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a bcdefsghiqjklmnopr=tuvwxyz{|}~CCl{ aW$     cC/" !#($&%'),*+-.0;162435798:<?=>@ABDSELFIGHJKMQNOPRT^UYVWXZ[\]_`abdevfjghikplnmoqsrtuw~x{yz|}d~     " #!"D {%<&'()*;+,-./0123456789:=>?@ABCDEFGHIJKLMNOPQRSTUVXzYwZ^[\]1_`Xabcdefghijklmnopqrstuvxy{|} ~  8 8 k       !! !UU/     !!!!!!!!! !"#$%&'()*+,-.!0D123456789:@;<>=!?!ABC!EFGHIJKLMNOPQRST!VWmXYZ[\]^_`!a!bc!d!!e!f!gh!!i!j!kl!!!nopq{rstuvwx"#y"#z"#"#|}~"#"#"#"#"#"#"#"#"#"("("#"#"#"E"""""""""""""""##&#&#;#;#;#;#;#A#i##X~A#######;-    # $ $$'!# #"#$%&#()*+,#.1/0$=2345687#9:#<=>@?##BeCGDFE$H$eHYIJKQLMNOP$$RSVTU$WX$Z[b\$]^$$_`$a$$$cd%%D%cfgohijklm%yn%%pqrystuvwx#z{|}#%%%%%%%%%%%%%%%%%%%%!!!!!!!!!!!!!!!!!!!!!&&8&d&"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&X&d&8&8&8&8&8&8&8&8&8&8&8 &8  &8 &8&8 &8&8&8&8&8'&8W?0'+'+ !."'+'+#$'+%'+'+&'+''+()'+*'++'+,'+'+-'1'+/'+123456789:;<=>'U@A'`B'`CDEFGHIJKLMNOPQRSTUV'XY&Z[\w]^_`ablcdiegf!h!jk!mntorpq!!s!uv!xyz{|}~!!!!!!!!!!!!!!!!!!!'!&dXX&''('('('('('('('('('(:('('('('('({(((  f : 8 0)#(() !")*$%&'()h*+,-./)1234567)9;O<=>?@ABCDEFGHIJKLMN)P*QRSTUVWXYZ[\]^_`abcde*@gh{ij*Uklmnopqrs*l*ltu*lv*lw*l*lxy*l*lz*l*||}~*({* k+++++++++++++$+++i+++++++++*U++(@({   +  ++++++++++++' !"#$%&,(9)*+,-.,/,,01,,23,4,5,,6,7,8,,,:;<=>?,GABCDEeFPGHIJKLMNO,[QZRSTUVWXY,m[\]^_`abcd,fgzhpijklmno,qrstuvwxy,{|}~,+i,,,G,(,, B X&d&dX jA ---7-L-e-z-- ---  ..*.J.] .t...../*//2/I/^/x//-/ //00#!$"#0?0Y0t0%'0&00()011+314,-0./1N1d1u1121111472 52&62B2Z8;9:2s222<>2=22?@3333NBCD\EMFIGH3f333JK33/L34 NUORPQ4#494PST4k444VYWX4445Z[535M5f]b^_5`a55cdgef555hi66'6Cklmn6Zo6wpq~rxs6t6u6vw774y7Uz7s{|}77777s88.78S8S8S8q8S8888888899399q9999::4:N::::;;.;\;;;;;;;;<<<:;;>P>s>;>>? >?5?W??W?=.??@ ;@@E@s@@@E@AA3 :   AX    A AA A  A A  A       <  4    !     A B " # - $ ' % &B3BJ ( , ) * +B^B^By . 1 / 0BB 2 3BBC 5 6 7 8 9 : ;C> = > E ? @ A B C DCM F  G _ H R I L J KCb M P N OCC QC S Y T W U VCC XD/ Z ] [ \DfD ^D ` p a i b d cD e h f gEE2 j n k lEK mEj oE q y r w s t u vByBy xE z } { |EF ~FD   D F[   Fy   F  F  FG  G= G= G= G= G= G= G= G= G=G= Gc      A    G       G           G      G    GH H- HJ HJ HJ HJHpHp HpH} HH HHH I HI!IG IG IG IGIe Ir H H I I II     J+Jd JqJJ  JK)KI  KiKKK K L L;LOHLi              ! "  # $% % X & L ' / ( ) * + , - .# 0 F 1 ; 2 3 7 4 5 6# 8 9 :# < A = > ? @# B C D E# G H I J K# M N O S P Q R# T U V W# Y q Z i [ b \ ] ^ _ ` a# c d e f g h# j k l m n o p# r y s t u v w x# z { | } ~  # L~    L LL LM M MI   Md  Mu  M%D   M  %DM M MM# ## ## N# ## # ## ## N+NO            Nq  '             N 3   "     N  N N   N  N  N N       N  N   N  N      N   N N   !NN # $ % & ' ( ) * +N , - 0 . /NN 1 2N 4N 5 6 7 8 9 : ; < = > AO, ? @O;O; C { D E F ] GN H I U J K L T M N O P R QOg SOgOgO V W X Y Z [ \O ^ | _ ` s a b c d e f g j h iOO k l:: m n o q p:: r: t u v w x y z {P } ~        P8P8 PO PO  PO PO           Ph  P  P   P       PP P        P             Q   Q-        QA  QA -        QT    Q       Q          Q    Q  Q  ,  ! " # $ % & ' ( ) * +QQN . L / A 0 1 2 : 3 4 5 6 7 8R# 9R#R6 ; < = > ? @RE B C D E F G H I J KQ M o N c O Z P Q R S T U V W X YR^ [ \ ] ^ _ ` a bPO d e f g h i j k l m nO; p q r s t u v w x y zG | } ~      R{ N            R          R R         P          R R       R        PO        PO              R    R        QA QA 8     :        R        S   ,    ! " # $ ' % &SJ ( * )SJ +S  - . / 0 1 2 3 4 5 6 7 8 9S} ; E < = > ? @ A B C DS F \ G T H I J O K L M NS P Q R SS U V W X Y Z [T% ] r ^ _ ` a b c d e f g h m i jTGTG kTG lTMTG nTG oTG pTG qTG s t z u v w x yT { | } ~  TT U      UU      UrU     U   U  V(   V9             Vi      V~     V       V   V   VVW WJWtW W W W W W W WWX X+XiXX XY#YCYg YYZZ; ZgZZ .Z ZZZ  Z ZZZ[Z ZZZZZZ[FZZ[_ZZZZ[ZZ[ZZZZ !ZZ"#Z$+%ZZ&Z'Z(Z)Z*[ZZ,-Z\Z/Z01k2J3;4Z5\#69Z78Z\4\K:ZZ\[<C=Z>Z?Z@ZZABZZ\ZDEZFHZG\ZZI\ZKULP\MNZOZ]ZZQRZSZ] T]:ZV]ZWZXZYZZ[ZZ\]\Z^g_d`baZZ]Zc]ZeZfZZ]hZZijZ^ZlmnwZoptqZrs^ZZ^.uZvZ^?^XxZy|Zz{Z^tZZ}~Z^ZZZZZ]Z^ZZZZZZZ^ZZ^ZZZ_ZZZ_2ZZZ_XZZZ_yZ__ZZ]__Z` ZZ`Z`IZ`_`` k`J``     a('a1 !"#$%&a\()I*@+,-./0123456789:;<=>?apABCDEFGHa}&dKLMNPOaQRSTUVaWXYyZh[`\^a]a_b bAacbbcdebfgbbccKiqjoknlmc|ccpcrvstd2dnudwxdde!z{|}~e`eeef fBfBfvfBfffgg?gwgggh#hNh{hhhiiAipiiijj"jHjujjjk k k*kgkkkllHlcllmm7m]mmmn n9n^nnnno)oLowooojulHp     p>1NqL=/ !"#$%&'()*+,-.pI0123456789:;<G>?@ABCDEFGHIJKpbMYNOPQRSTUVWXpuZ[\d]^_`abcpefghijklmnopprstuvwxyz{|}~ppppqq*q<qK kH *    qhq| !"#$%&'()q+5,0-./q1234q678@9:;<=>?,[ABCDEFGqItJ[KLMNOPQRSTUVWXYZr\h]^_`abcdefgr6ijklmnopqrsrbuvw|xyz{r}~rr<r,mrrrrss8sW, ,    s}({( !"#$%&'s)*+q-./0123456978ss:;s=S>?G@ABCDEFsHIMJKLsNOPQRtTfUVWbX]YZ[\tU^_`atkcdetghi|jklmwnopqrstuvtxyz{t}~+tuuAu]utututuuuuuuuuuuvvvv4vvrvvvvvvww7wNwNw     wwxx4xOxux !"a#$V%E&'(C)>*+=,6-./012345x789:;<xxy?@AByDy=FGHILJKyQMNyrOPyryrQRyrSyrTyrUyryyrWX]HpYHpZHp[\HpHpy^_`yblcdefighzjkzmnopqurstz.vwzlxzlyzlzlzzl{zl|zl}~zlzlzlzlzzz{{{8{MHpHpHp{n{{{| | |'|@|`||||||e !    }  } "<#$.%&'()*+,-}//0123456789:;}==Z>L?@ABCDEFGHIJKMNOPQRSTUVWXY}=[\]^_`abcd}Qfghijklmnopqrstuvwxyz{|}~}`!!}q}i3}}}}}}}}}}}}}}}}}}}}}"!     } !"#$%&'()*+,-./012p4g567n8V9O:E;@<=>?~ABCD~'FGHLIJK MN~e~PQRSTU~WXYcZ[\]^_`ab kdefghijkl~m~opqrs|tuvwxyz{,}~~~ Ek( < )    % !"#$*&'(5*+,-./0123456789:;a=H>?@ABCDEFGITJKLMNOPQRSUVcWXYZ[\]^_`abdefhjklmnopqrstuvwxy|z{}~)W"#"#"#"#"#"#"#"#"#"#"#"#"#"#"#"#"#"#"#;x     H <!"#$%&0'()*+,-./123456789:;=>?@ABCDEFGISJLKMNOPQRETUVWXyYrZk[\]b^_`adcgdefhijlmnopqstuvwxz{|}~<f(Nr/ 8 8bpbbbbbbb     ` !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNPQ3RSTUVWXYZ[\]^_`walbcdefghijk`mnopqrstuvx~yz{|} Nj`%/9D/q J)     T_$ !"#%&'(*+,-./01245L6789:;<B=>?@ACDEFGHIJKMNOPQRSTUeVWX_YZ[\]^`ab"c"d"Jf}gh|i{jqklmnopUrtsuxvwryz~j 5OZ1NgzCispZTOT Public Company LimitedLorganization Xautonomous_system_number]autonomous_system_organizationOTelstra Pty LtdCispPTelstra Internet CispVLevel 3 Communications CispJWifiNetComCispGFinecomCisp MCo-Mo ConnectCispMAT&T Services 0jCisp 0jCisp VAT&T Worldnet Services 0G LWHewlett-Packard CompanyCisp!< ! ('>CispGVodacom ('iCispPAirtel Broadband ('{Cisp]Second segment of Broadband IPs ('Cisp]Third segment of Airtel Broadband IPs ('Cisp]Reserved for Internet APN Allocation ('Cisp]MTC - Mobile Telecommunications, Ltd. JMTC NetmanCisp((" (("CispJCybersmart ((hCisp((h ]Cybersmart-ADSL-DBN ADSL IP numbers assigned to DbCisp((h ]Cybersmart-ADSL-JHB ADSL IP for Northern regiosCisp]Airtel Malawi GPRS subscribers ((CispUAirtel Malawi network () CispUMTN Cote d'Ivoire S.A ()@CispXWataniya Telecom Algerie ()`CispIEmtel Ltd ()Cisp]Bytes Connect, a Division of Bytes Technology Grou ()CispLTelecel Faso ()CispLIcsl Network ()Cisp]Abari Communications Mozambique Lda (*CispIGuineanet (*2CispOOrange Botswana (*FCispJZain Sudan (*`Cisp" "CispHTelebeep (*CispISebastian (*Cisp]Quadro Communications Co-Operative (*Cisp]Region 14 Education Service Center (*CispISingleHop (+Cisp]The Cosmopolitan of Las Vegas (+CispPAce Data Centers (+@CispFGoogle (+[CispRSmart Solutions IT (+lCispLCogeco Cable (+CispHVolusion (+CispQTime Warner Cable (+CispYSpeedVM Network Group LLC (+CispUBright House Networks (+Cisp( DAT&TCisp( YLisle IDC - Silver LiningCisp( WAtlanta - Silver Lining MNavigadsl srl REncryption LimitedCispSSK Broadband Co Ltd (,Cisp]CMB Daejeon Broadcasting Co,.Ltd (, 0&P L] Guangdong Mobile Communication Co.Ltd.CispPGuangdong Mobile (-CispCNHN CNHNCisp]Korea Cable TV Kwangju Broadcast (-2Cisp]Hyundai Communications & Network (-^CispPDacom-pubnetplus (-Cisp]Tbroad Abc Broadcasting Co.,ltd. (-Cisp]TBROAD Dongdaemun cable networks,Inc. (-Cisp]Korea Cable TV Jeonboog Broadcast (.CispLONSE Telecom (./CispNCj-hellovision (.FCispWSwiift Internet LimitedCispWHO Nam Cable TV co.,LTD (.|Cisp]korea cable pohang broadcasting (.CispJHyosungITX (.CispMLg Dacom Kidc (.CispOPiranha Systems (.CispISmileserv (/CispIG&j, Ltd. (/$CispHHAIonNet (/8Cisp] National Computing & Information Agency (/KCispYKorea Nazarene University (/~Cisp\Catholic University of DAEGU (/Cisp[Korea Telecom Freetel Corp. (/Cisp]TCN Daegu Broadcasting Co., Ltd (/CispHNURILINK (0Cisp(0 DSRUNCispNTbroad Gangseo (0VCispUAxtel, S.A.B. de C.V. (>{Cisp]Informacion Al Dia Y Comput SA (> UWireless Connect Ltd. FHKTNETCisp]Centro Nacional de Intercambio Automatizado (> EF-KOM 0 LXAOL Transit Data NetworkCisp&y &y PCircle 1 Network IGoversoftCispQCondointernet.net 02, L( Cisp( ( CispKOi Internet (?Cisp[Regency Comunicações Ltda (?CispWM.A. Informática Ltda. (?Cisp]Banner Serviços de Telecom e Internet Ltda. (@CispWHoinaski & Sklasky Ltda (@8CispZSilveira & Ziquinatti Ltda (@ZCisp]Naja Telecomunicações Ltda. (@Cisp]Eletrosul Centrais Elétricas S.A. (@Cisp]Space Net Serv. De TelecomunicaÇÃo Em Inf. Ltda-me (@Cisp]JF Soluções Informática Ltda. (ACisp]Info House Informática e Papeis Ltda (ABCispWP3 Host Internet Brasil (AsCisp]Bluephone Solucoes Tecnologicas Ltda (ACisp]NETWS Telecomunicações Ltda. (ACisp]Chapeco Tecnologia em Telecomunicações Ltda. (ACisp]Afinet Solucoes Em Tecnologia Da Informacao Ltda (B)CispRMil Negocios Ltda. (BeCisp]Fox Conect Provedor de Internet LTDA (BCisp]G30 Telecom ServiÇos Em TelecomunicaÇÕes Ltda (BCisp]Midasnet Telecomunicacoes Ltda (BCisp]Viveiros & Araujo Serviços de Provedores da Intern (CCisp] Rodolfo Romao De Oliveira Neto & Cia Ltda (CWCisp]Ajaxtel Telecomunicações Ltda. (CCisp] Mcnet Serviços de Comunicações Ltda (CCisp]R.D.S. Bortoluzzi & Cia Ltda - ME (CCispWTolrs Informática Ltda (DCisp] Digicontrol ServiÇos De Provedores Ltda (D9Cisp(D9 ]Pablo William Silva Tavares de LiraCispXPRIMEHOST do BRASIL Ltda (DCisp]Minas Turbo Provedor de Internet (DCispQBr2 Internet Ltda (DCisp]Conexis Internet Provider Ltda - Me (ECisp]Nolasco & Nonnenmacher Comercio e Rep. Ltda. (E6CispZInterneith Via Radio Ltda. (EnCisp]Apn - Processamento de Dados e Soluçoes em Interne (ECispQMinas Net Ldta Me (ECisp]Netway Provedor De Internet Ltda (ECisp]Catanduva sistemas a cabo ltda. (FCisp]Telecomunicacões Minas Mais Ltda (FECisp[Bom Tempo Informática Ltda (FrCisp\Arikinet Internet Ltda - EPP (FCisp]E&L Producoes de Software Ltda (FCispYMicrofox Informatica Ltda (FCisp]Mapfre Vera Cruz Seguradora S/a (G Cisp]Norte Line Telecomunicações Ltda. (G8Cisp]Predialnet Provedor De Internet Ltda (GgCispPPronto Net Ltda. (GCisp]W r de bel entreterimentos s/s ltda (G RIPV6 Internet LtdaCispWAlonso Oliveira Neto Me (GCisp[IP2 Telecomunicação Ltda. (HCisp]TURBO 10 Telecomunicações Ltda. (H?CispDVivo (HlCisp[Vcb Provedor De Acesso Ltda (H{Cisp]Click.com telecomunicações ltda-me (HCisp]Universidade Estadual De Ponta Grossa (HCispTUnica Tecnology Ltda (ICisp(I ]Microtell Informatica - Comercio & Prestacao De SCispXT.p.a. InformÁtica Ltda (I^Cisp]Intercol - Internet Colatina Ltda-ME (ICisp]Sul Americana Tecnologia e Informática Ltda. (ICisp]Ampernet Telecomunicações Ltda (ICisp]Mar Provedor de Internet Ltda (JCispPTim Celular S.A. (J?Cisp]Jgm Brasil TelecomunicaÇÕes Ltda (JZCisp]Inetsafe Comercio De Equipamentos Eletronicos Ltda (JCisp]Infoline - Comunicações e Informações Eletrônicas (JCisp[J W Mateus Informatica - Me (KCisp[Brasconect Informatica LTDA (K.Cisp] Tech Cable do Brasil Sist. de Telec. Ltda (KTCisp]Ufla - Universidade Federal De Lavras (KCispYNetprimus Tecnologia Ltda (KCisp[Evanildo Barbeta Boituva ME (KCisp]LB Redes Telecomunicações LTDA (LCispZSidys Comunicações Ltda. (L0Cisp[Portalmail Informatica Ltda (LUCisp]Internet Pinheirense Ltda - ME (L{CispDCTBC (LCisp] Byteweb Comunicação Multimídia Ltda. (LCisp]Redenilf Serviços de Telecomunicações Ltda (LCispXStar Conect Telecom Ltda (M Cisp]OpçãoNet Informática Ltda ME (MCCispRLink Sol LTDA - ME (MnCisp] New Master Provedor De Acesso A Internet (MCisp]Gigalink de Nova Friburgo Soluções em Rede Multimi (M 0i L]NTT Communications CorporationCispCNTT CNTT GGPLHost UTrans Canada InternetCispMSmartLabs LLC ]WE Radio Comunicação LTDA EPP YVoax Provedor de Internet KRedeTeleSulCispLCityLink ISP LCityLink Ltd (N Jindtelecom RMitiHost Solutions VFiberXpress DominicanaCispLFIX WIRELESS KHostVDS-NETCispRGolden Lines Cable (OB PP.P.H.U Multicom [FOP Molochko Nina Vasilevna FAmdocsCispVVerizon Nederland B.V. (OCisp]Agence Tunisienne Internet - ATI (OCispYSLW Internet Service Ltd. (OCispUBuckhaven High school (P Cisp]University of Technology, Vienna (P- YH & M Hennes & Mauritz ABCisp]Egyptian Universities Network (PvCispOAB Svenska Spel (P FCDcorp Gw3 GmbHCisp(NCispRForestry Commision (PCispQWEB Hotel, Moscow (PCispUHotel Astoria network (QCispTSeaside Hotels, S.A. (Q/ ]Small Private Enterprise Kvant-II ISevonlineCisp]Rawdat Al-Ma'aref Schools & College (QCispFCASPUR (QCisp]TELECOM ITALIA SPARKLE S.p.A. (QCispYOfficine Informatiche Srl (QCisp]Egyptian National Scientific & Technical Informati (RCispKTiscali SpA (RLCisp]Interoute Communications Limited (RbCispRTiscali UK Limited (RCisp\Blackpool Sixth Form College (RCispPAberdeen College (RCispQVerizon Sweden AB (RCisp]Egyptian Universities Network (EUN) (S CispQFrogfoot Networks (S8CispLCMC Networks (STCispVGlobal Internet Access (SkCispKGkn Chep SA (SCispNWana Corporate (SCispMRwandatel, SA (SCisp(S [Wireless Broadband CustomerCispDMWEB (SCispXData Pro Business Online (TCisp(T ]JHB Waverley MetroEthernet, Hosting and Lease LineCisp] Durban Lease Line and Hosting Zone Range (TiCispOZimbabwe Online (TCispFONATEL (TCisp\Al Salam Rotana Hotel- sudan (TCispTUniversite de Bamako (TCispUAmobia Communications (UCispLSarl ICOSNET (U.Cisp]Allocated to Broad band internet in the following (UECisp]Research and Education Network of Uganda - RENU (UCisp]Association of African Universities (UCispXZimbabwe Open University (UCispQNigeria Air Force (VCispPBowen University (V+Cisp[University of Dar es Salaam (VFCispJYo! Africa (VlCispNMTN RwandaCell (VCisp]The Institute for Social Accou (VCispKTribe Hotel (VCispUAccesskenya Group Ltd (VCispOWananchi Online (VCispUAfribone - Universite (WCispIIkatel SA (W4CispVOrange Broadband Kenya (WHCispYTelecom Lesotho (PTY) LTD (WiCisp(Wi ]Sub allocation to Lerotholi Polytechnic InstituteCisp(&A LMarocTelecomCisp\Communication Solutions Ltd. (WCispRInternet Solutions (XCisp]Network assigned to Silver Customers in Luanda, An (X%CispZSwift Global Kenya Limited (XcCisp(Xc RPushMobileMediaSGKCisp] Grindrod Management Services (Pty) Ltd (XCispUZenith Bank Ghana Ltd (XCispKFinbank PLC (XCispWCentral Bank of Nigeria (Y CispJSeacom Ltd (Y/CispVCairo American College (YDCisp]National University of Science and Technology (YeCispYBeehive Social Enterprise (YCispYUniversity of Jos Nigeria (YCispSUniversity of Lagos (YCispORT-ADSL-project (ZCispNFiber Grid Inc (ZCispUNorth West University (Z7Cisp\University of the Free State (ZWCispPGranite NetworksCispWSilverIP CommunicationsCispWAllo Communications LLC VPremier Communications # OAlamo Broadband ]Argentina Virtual Networks S.R.L. JDIGINET-NZ PLATELZ Co., Ltd. KLGCNS ChinaCispKYourHomeISP \Lytton Area Wireless SocietyCispPCMS Internet LLC THilite International 0+ 0+CispQComcast - Houston ([ \International Business TimesCispVNet By Net Holding LLC ([Cisp]Nonprofit Partnership for the Development of Finan (\CispUMoscow Mayor's Office (\\CispFSPSNET (\|Cisp] COLT Technology Services Group Limited (\CispMSlovanet a.s. (\CispNScan Plus GmbH (\CispOICM NetServ Ltd (\CispGAltecomCispZSt Andrew's Primary School (]Cisp[Ufi Army Torch Hub Nuneaton (]?@ABDEFGHJKLMzNOPsQeRSTUVWXYZ[\]^d_`abcfghijklmnopqrtuvwxy{|}~BipH1.1.1.16BipG1.1.1.8BipG1.1.1.4BipG1.1.1.2BipG1.1.1.1BipH1.1.1.32MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeDTestKdescriptionBenMTest DatabaseBzhUTest Database ChineseJip_versionIlanguagesBenBzhJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/MaxMind-DB-test-ipv4-32.mmdb0000644000175000017500000000313213227476051023306 0ustar greggreg000000000000004(%  !"#$&')*0+,-./1235I6789C:;<=>?@ABDEFGHJKLMzNOPsQeRSTUVWXYZ[\]^d_`abcfghijklmnopqrtuvwxy{|}~BipH1.1.1.16BipG1.1.1.8BipG1.1.1.4BipG1.1.1.2BipG1.1.1.1BipH1.1.1.32MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeDTestKdescriptionBenMTest DatabaseBzhUTest Database ChineseJip_versionIlanguagesBenBzhJnode_countKrecord_size geoip2-2.7.0/tests/data/test-data/GeoIP2-City-Test.mmdb0000644000175000017500000005053713227476051022272 0ustar greggreg00000000000000      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ|RSTUVWXYZ[\]^_`abcde~fghijklmnopqrstuvwxyz{|}   >  f f 7{bC-&      !"#$%'()*+,./0126345789:;<=>?@ABDEFRGHIJKLMNOPQ9STUVWXYZ[\]^_`acdefghijklmnopqrstuvwxyz0}~`\[P`hhB     h4%hB" !h#$&-'*()+,.1/0h23h5A6=7:89;<>?@hBICFDEfGHJMKLNOQRSTUVWXYZ`]^_`abcdefghijk{lmnoptqrsuxvwyzK|}~5cO:K|5O:Oh|KOK|O7OKC$     5 5!  "# %4&-'*()O+,|.1/0!235<6978O:;=@>?ABDcETFMGJHIKL NQOPRSU\VYWX"\Z[|]`^_5abdselfighjkmpnoqr#t{uxvwyz |}~| K#$||#!%&OOK5O#K&KK&'O    H )O") !#&$%'(5*9+2,/-.01|364578:A;><=?@|BECDFGKIhJYKRLOMNKPQSVTUhWX)Za[^\]_` becdOfg%&ixjqknlmoprust#vw5yz}{|~ c|&|OKOKO|*||+####    5 O0!#O ")#&$%'(*-+,|./|1@293645%&78 :=;<O>?AHBECDOFG|ILJKMNPoQ`RYSVTU5WX,Z][\^_|ahbecdOfgiljk,mn!pqxrust#vw|y|z{}~|-aO.DcityJgeoname_id(EEnamesBenGBoxfordIcontinentDcodeBEU _r, BdeFEuropaBenFEuropeBes GBfr QBjaOヨーロッパEpt-BR GBruLЕвропаEzh-CNF欧洲Gcountry (5Tis_in_european_unionHiso_codeBGB BdeWVereinigtes KönigreichBenNUnited KingdomBesKReino UnidoBfrKRoyaume-UniBjaLイギリス u Bru\Великобритания F英国HlocationOaccuracy_radiusdHlatitudeh@IIlongitudehItime_zoneMEurope/LondonFpostal 3COX1Rregistered_country . BFR BdeJFrankreichBenFFranceBesGFranciaBfr!BjaUフランス共和国 uGFrançaBruNФранция F法国Lsubdivisions _ CENG BenGEnglandBesJInglaterraBfrJAngleterre u"w 2a CWBK BenNWest BerkshireBru]Западный Беркшир L西伯克郡 ( 3BAS _r+ BdeEAsienBenDAsiaBes#BfrDAsieBjaIアジア uEÁsiaBruHАзия F亚洲  BBT BdeFBhutanBen#WBesFButánBfr#WBjaRブータン王国 uFButãoBruJБутан F不丹!W!a!sh@;!h@V!LAsia/Thimphu!  /U BRO BdeIRumänienBenGRomaniaBesHRumaníaBfrHRoumanieBjaOルーマニア uHRomêniaBruNРумыния L罗马尼亚FtraitsRis_anonymous_proxy  (W BdeFLondonBen$BesGLondresBfr$BjaLロンドン u$BruLЛондон ( 2 !W!ad!sh@IN;6!hfA!!! _e BUS BdeCUSABenMUnited StatesBesNEstados UnidosBfrKÉtats-UnisBjaUアメリカ合衆国 u%BruFСША F美国"J"Y $y ( 2 !W!a!s$!$!!!$"J%k $y ( 2 !W!a !s$!$!!!$"J%k  )j BdeJLinköpingBen%Bfr%BjaXリンシェーピング I林雪平 ( 2 ( BSE BdeHSchwedenBenFSwedenBesFSueciaBfrFSuèdeBjaXスウェーデン王国 uGSuéciaBruLШвеция F瑞典!W!aL!sh@M5Vl!!h@/;6!PEurope/Stockholm! ,T BDE BdeKDeutschlandBenGGermanyBesHAlemaniaBfrIAllemagneBjaXドイツ連邦共和国 uHAlemanhaBruPГермания F德国"J ( AE BenUÖstergötland CountyBfrWComté d'Östergötland   BdeKChángchūnBenIChangchunBfr'BjaI長春市BruNЧанчунь F长春 ("  BCN BdeEChinaBen'Bes'BfrEChineBjaF中国 u'BruJКитай (!W!ad!sh@E =q!h@_TTɆ!KAsia/Harbin!'"J  B22 BenKJilin Sheng F吉林 (" 8 BPH BdeKPhilippinenBenKPhilippinesBesIFilipinasBfr(BjaXフィリピン共和国 u(BruRФилиппины I菲律宾!W!ay!sh@*!h@^!KAsia/Manila! 3E34021!(Srepresented_country _e BUS $DtypeHmilitary  X$ BenFMiltonBruNМильтон ( 3BNA _r- BdeKNordamerikaBenMNorth AmericaBesRAmérica del NorteBfrQAmérique du NordBjaO北アメリカ uQAmérica do NorteBru]Северная Америка I北美洲 $!W!a!sh@G*0!h^'RT`Jmetro_code3!SAmerica/Los_Angeles! 3E98354! "J X_ BWA BenJWashingtonBes(BfrSÉtat de WashingtonBjaRワシントン州BruRВашингтон L华盛顿州 (" e BJP BdeEJapanBen(KBesFJapónBfrEJaponBjaF日本 uFJapãoBruLЯпония (m!W!ad!sh@A׹`H!h@axP3:!JAsia/Tokyo!(9 (" A BKR BdeNRepublik KoreaBenKSouth KoreaBesTCorea, República deBfrMCorée du SudBjaL大韓民国 uVCoréia, República daBruUЮжная Корея F韩国!W!ad!sh@B!h@_!JAsia/Seoul!( (" t BTW BdeFTaiwanBen(BesGTaiwánBfrGTaïwanBjaF台湾 u(BruNТайвань (!W!ad!sh@8!h@^@!KAsia/Taipei!( ("  BCN Bde'BenZPeople's Republic of ChinaBesXRepública Popular ChinaBfr(Bja( u'Bru(( (!W!ad!sh@A!h@Z@!(4 (" R BHK BdeHHongkongBenIHong KongBes(Bfr(BjaF香港 u(BruNГонконг (!W!ad!sh@6@!h@\[!NAsia/Hong_Kong!( ( 2 / BNO BdeHNorwegenBenFNorwayBesGNoruegaBfrHNorvègeBjaUノルウェー王国 u(BruPНорвегия F挪威!W!ad!sh@O!h@$!KEurope/Oslo!(Z (" ~ BIL BdeFIsraelBen(Bes(BfrGIsraëlBjaRイスラエル国 u(BruNИзраиль I以色列!W!ad!sh@?!h@A`!NAsia/Jerusalem!( ( 2 !!W!ad!sh@G!h@!LEurope/Paris!! ( 2 ( BCH BdeGSchweizBenKSwitzerlandBesESuizaBfrFSuisseBjaOスイス連邦 uGSuíçaBruRШвейцария F瑞士!W!ad!sh@G>-b9!h@ Ne!MEurope/Zurich!( ( 2 &!W!ad!sh@O!h@.!&!& (" m BBH BdeGBahrainBen(BesHBahréinBfrHBahreïnBjaOバーレーン u(BruNБахрейн F巴林!W!ad!sh@:!h@I@!LAsia/Bahrain!( ( 2 Z BRU BdeHRusslandBenFRussiaBesERusiaBfrFRussieBjaIロシア uGRússiaBruLРоссия I俄罗斯!W!ad!sh@N!h@Y!( f ( 2  /P BPL BdeEPolenBenFPolandBesGPoloniaBfrGPologneBjaXポーランド共和国 uHPolôniaBruLПольша F波兰!W!ad!sh@J!h@4!MEurope/Warsaw!( ( 2 &!W!ad!sh@I!h@%!MEurope/Berlin!& ( 2 0s BIT BdeGItalienBenEItalyBesFItaliaBfrFItalieBjaUイタリア共和国 uGItáliaBruLИталия I意大利!W!ad!sh@EjcI!h@):э&!KEurope/Rome!( ( 2  - BFI BdeHFinnlandBenGFinlandBesIFinlandiaBfrHFinlandeBja[フィンランド共和国 uJFinlândiaBruRФинляндия F芬兰!W!ad!sh@P!h@:!OEurope/Helsinki!( ( 2  @ BBY BdeMWeißrusslandBenGBelarusBesKBielorrusiaBfrLBiélorussieBjaXベラルーシ共和国 uMBielo-RússiaBruPБеларусь L白俄罗斯!W!ad!sh@J!h@<!LEurope/Minsk!( c ( 2 . BCZ BdeUTschechische RepublikBenNCzech RepublicBesPRepública ChecaBfrITchéquieBjaRチェコ共和国 u( uBru]Чешская Республика O捷克共和国!W!ad!sh@H!h@.!MEurope/Prague!( 4 ("  BIR BdeZIran (Islamische Republik)BenDIranBes\Irán (República Islámica)Bfr]Iran (République islamique de)Bja]イラン・イスラム共和国 u\República Islâmica do IrãBruHИран X伊朗伊斯兰共和国!W!ad!sh@@!h@J!KAsia/Tehran!(! ( 2  g BUA BdeGUkraineBen(OBesGUcraniaBfr(OBjaXウクライナ共和国 uHUcrâniaBruNУкраина I乌克兰!W!ad!sh@H!h@@!(= ( 2 !W!ad!sh@Ka7!htr!!! ( 2  BHU BdeFUngarnBenGHungaryBesHHungríaBfrGHongrieBjaXハンガリー共和国 uGHungriaBruNВенгрия I匈牙利!W!ad!sh@G!h@4!OEurope/Budapest!( ( 2!W!ad!sh@HXq`l !h@"GX:S!LEurope/Vaduz ( 2 &O BES BdeGSpanienBenESpainBesGEspañaBfrGEspagneBjaLスペイン uGEspanhaBruNИспания I西班牙!W!ad!sh@D!h!( ( 2  . BBG BdeIBulgarienBenHBulgariaBes(BfrHBulgarieBjaXブルガリア共和国 uIBulgáriaBruPБолгария L保加利亚!W!ad!sh@E!h@9!LEurope/Sofia!( ( 2 #!W!ad!sh@G!h@9!PEurope/Bucharest!# ( 2 *¹ BBE BdeGBelgienBenGBelgiumBesHBélgicaBfrHBelgiqueBjaRベルギー王国 u(BruNБельгия I比利时!W!ad!sh@IjcI!h@!OEurope/Brussels!( (" + BTR BdeGTürkeiBenFTurkeyBesHTurquíaBfrGTurquieBjaRトルコ共和国 uGTurquiaBruLТурция I土耳其!W!ad!sh@C!h@AtU!OEurope/Istanbul!(J ( 2 *s BAT BdeKÖsterreichBenGAustriaBes(!BfrHAutricheBja[オーストリア共和国 uHÁustriaBruNАвстрия I奥地利!W!ad!sh@GcI!h@*:э&!MEurope/Vienna!( ( 2  BAL BdeHAlbanienBenGAlbaniaBes(BfrGAlbanieBjaXアルバニア共和国 uHAlbâniaBruNАлбания O阿尔巴尼亚!W!ad!sh@D!h@4!MEurope/Tirane!( (" & BLB BdeGLibanonBenGLebanonBesGLíbanoBfrELibanBjaUレバノン共和国 u(BruJЛиван I黎巴嫩!W!ad!sh@@ꪎcI!h@AꪎcI!KAsia/Beirut!(w ( 2 ) BNL BdeKNiederlandeBenKNetherlandsBesGHolandaBfrHPays-BasBjaRオランダ王国 uNPaíses BaixosBruTНидерланды F荷兰!W!ad!sh@J@!h@!PEurope/Amsterdam!( (" [ BKW BdeFKuwaitBen(Bes(BfrGKoweïtBjaOクウェート u(BruLКувейт I科威特!W!ad!sh@=!h@G!KAsia/Kuwait!( ("  BSA BdeMSaudi-ArabienBenLSaudi ArabiaBesNArabia SauditaBfrOArabie saouditeBja[サウジアラビア王国 uOArábia SauditaBru]Саудовская Аравия O沙特阿拉伯!W!ad!sh@9!h@F!KAsia/Riyadh!( ( 2 _L BRS BdeGSerbienBenFSerbiaBes(BfrFSerbieBjaLセルビア uGSérviaBruLСербия L塞尔维亚!W!ad!sh@Fh^)!h@4u?h!OEurope/Belgrade!({ ("  BJO BdeIJordanienBen[Hashemite Kingdom of JordanBesHJordaniaBfrHJordanieBja]ヨルダン・ハシミテ王国 uIJordâniaBruPИордания F约旦!W!ad!sh@?!h@B!JAsia/Amman!(# ( 3BAF _r* BdeFAfrikaBenFAfricaBesGÁfricaBfrGAfriqueBjaLアフリカ u(BruLАфрика F非洲 ! BLY Bde]Libysch-Arabische DschamahirijaBenELibyaBesXLibia, República ÁrabeBfrELibyeBja] 社会主義人民リビア・アラブ国 uXLíbia Árabe JamahiriyaBruJЛивия [阿拉伯利比亚民众国!W!ad!sh@<!h@1!NAfrica/Tripoli!(` ( 2 -8 BIE BdeFIrlandBenGIrelandBesURepública de IrlandaBfrGIrlandeBjaRアイルランド uGIrlandaBruPИрландия I爱尔兰!W!ad!sh@J!h !MEurope/Dublin!(q (" l BAZ BdeMAserbaidschanBenJAzerbaijanBesKAzerbaiyánBfrLAzerbaïdjanBja]アゼルバイジャン共和国 uKAzerbaijãoBruVАзербайджан L阿塞拜疆!W!ad!sh@D@!h@G!IAsia/Baku!(6 (" n BAE Bde\Vereinigte Arabische EmirateBenTUnited Arab EmiratesBesWEmiratos Árabes UnidosBfrTÉmirats Arabes UnisBjaXアラブ首長国連邦 uWEmirados Árabes UnidosBru]Объединенные Арабские Эмираты X阿拉伯联合酋长国!W!ad!sh@8!h@K!JAsia/Dubai!( ("  BAM BdeHArmenienBenGArmeniaBes(qBfrHArménieBjaXアルメニア共和国 uHArmêniaBruNАрмения L亚美尼亚!W!ad!sh@D!h@F!LAsia/Yerevan!(S ( 2 (8 BDK BdeIDänemarkBenGDenmarkBesIDinamarcaBfrHDanemarkBjaUデンマーク王国 u(9BruJДания F丹麦!W!ad!sh@L!h@$!QEurope/Copenhagen!( ( 2 .k BIM BdeIInsel ManBenKIsle of ManBesKIsla de ManBfrKÎle de ManBjaIマン島 uKIlha de ManBruMМэн, о-в F曼岛!W!ad!sh@K !h!REurope/Isle_of_Man!( ( 2 $B BGI BdeIGibraltarBen( Bes( Bfr( BjaRジブラルタル u( BruRГибралтар!W!ad!sh@Bɰ!hffffff!PEurope/Gibraltar!( }MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeKGeoIP2-CityKdescriptionBen]*GeoIP2 City Test Database (fake GeoIP2 data, for example purposes only)BzhO小型数据库Jip_versionIlanguagesBenBzhJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/GeoIP2-City-Test-Invalid-Node-Count.mmdb0000644000175000017500000005056313227476051025626 0ustar greggreg00000000000000      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ|RSTUVWXYZ[\]^_`abcde~fghijklmnopqrstuvwxyz{|}   >  f f 7{bC-&      !"#$%'()*+,./0126345789:;<=>?@ABDEFRGHIJKLMNOPQ9STUVWXYZ[\]^_`acdefghijklmnopqrstuvwxyz0}~`\[P`hhB     h4%hB" !h#$&-'*()+,.1/0h23h5A6=7:89;<>?@hBICFDEfGHJMKLNOQRSTUVWXYZ`]^_`abcdefghijk{lmnoptqrsuxvwyzK|}~5cO:K|5O:Oh|KOK|O7OKC$     5 5!  "# %4&-'*()O+,|.1/0!235<6978O:;=@>?ABDcETFMGJHIKL NQOPRSU\VYWX"\Z[|]`^_5abdselfighjkmpnoqr#t{uxvwyz |}~| K#$||#!%&OOK5O#K&KK&'O    H )O") !#&$%'(5*9+2,/-.01|364578:A;><=?@|BECDFGKIhJYKRLOMNKPQSVTUhWX)Za[^\]_` becdOfg%&ixjqknlmoprust#vw5yz}{|~ c|&|OKOKO|*||+####    5 O0!#O ")#&$%'(*-+,|./|1@293645%&78 :=;<O>?AHBECDOFG|ILJKMNPoQ`RYSVTU5WX,Z][\^_|ahbecdOfgiljk,mn!pqxrust#vw|y|z{}~|-aO.DcityJgeoname_id(EEnamesBenGBoxfordIcontinentDcodeBEU _r, BdeFEuropaBenFEuropeBes GBfr QBjaOヨーロッパEpt-BR GBruLЕвропаEzh-CNF欧洲Gcountry (5Tis_in_european_unionHiso_codeBGB BdeWVereinigtes KönigreichBenNUnited KingdomBesKReino UnidoBfrKRoyaume-UniBjaLイギリス u Bru\Великобритания F英国HlocationOaccuracy_radiusdHlatitudeh@IIlongitudehItime_zoneMEurope/LondonFpostal 3COX1Rregistered_country . BFR BdeJFrankreichBenFFranceBesGFranciaBfr!BjaUフランス共和国 uGFrançaBruNФранция F法国Lsubdivisions _ CENG BenGEnglandBesJInglaterraBfrJAngleterre u"w 2a CWBK BenNWest BerkshireBru]Западный Беркшир L西伯克郡 ( 3BAS _r+ BdeEAsienBenDAsiaBes#BfrDAsieBjaIアジア uEÁsiaBruHАзия F亚洲  BBT BdeFBhutanBen#WBesFButánBfr#WBjaRブータン王国 uFButãoBruJБутан F不丹!W!a!sh@;!h@V!LAsia/Thimphu!  /U BRO BdeIRumänienBenGRomaniaBesHRumaníaBfrHRoumanieBjaOルーマニア uHRomêniaBruNРумыния L罗马尼亚FtraitsRis_anonymous_proxy  (W BdeFLondonBen$BesGLondresBfr$BjaLロンドン u$BruLЛондон ( 2 !W!ad!sh@IN;6!hfA!!! _e BUS BdeCUSABenMUnited StatesBesNEstados UnidosBfrKÉtats-UnisBjaUアメリカ合衆国 u%BruFСША F美国"J"Y $y ( 2 !W!a!s$!$!!!$"J%k $y ( 2 !W!a !s$!$!!!$"J%k  )j BdeJLinköpingBen%Bfr%BjaXリンシェーピング I林雪平 ( 2 ( BSE BdeHSchwedenBenFSwedenBesFSueciaBfrFSuèdeBjaXスウェーデン王国 uGSuéciaBruLШвеция F瑞典!W!aL!sh@M5Vl!!h@/;6!PEurope/Stockholm! ,T BDE BdeKDeutschlandBenGGermanyBesHAlemaniaBfrIAllemagneBjaXドイツ連邦共和国 uHAlemanhaBruPГермания F德国"J ( AE BenUÖstergötland CountyBfrWComté d'Östergötland   BdeKChángchūnBenIChangchunBfr'BjaI長春市BruNЧанчунь F长春 ("  BCN BdeEChinaBen'Bes'BfrEChineBjaF中国 u'BruJКитай (!W!ad!sh@E =q!h@_TTɆ!KAsia/Harbin!'"J  B22 BenKJilin Sheng F吉林 (" 8 BPH BdeKPhilippinenBenKPhilippinesBesIFilipinasBfr(BjaXフィリピン共和国 u(BruRФилиппины I菲律宾!W!ay!sh@*!h@^!KAsia/Manila! 3E34021!(Srepresented_country _e BUS $DtypeHmilitary  X$ BenFMiltonBruNМильтон ( 3BNA _r- BdeKNordamerikaBenMNorth AmericaBesRAmérica del NorteBfrQAmérique du NordBjaO北アメリカ uQAmérica do NorteBru]Северная Америка I北美洲 $!W!a!sh@G*0!h^'RT`Jmetro_code3!SAmerica/Los_Angeles! 3E98354! "J X_ BWA BenJWashingtonBes(BfrSÉtat de WashingtonBjaRワシントン州BruRВашингтон L华盛顿州 (" e BJP BdeEJapanBen(KBesFJapónBfrEJaponBjaF日本 uFJapãoBruLЯпония (m!W!ad!sh@A׹`H!h@axP3:!JAsia/Tokyo!(9 (" A BKR BdeNRepublik KoreaBenKSouth KoreaBesTCorea, República deBfrMCorée du SudBjaL大韓民国 uVCoréia, República daBruUЮжная Корея F韩国!W!ad!sh@B!h@_!JAsia/Seoul!( (" t BTW BdeFTaiwanBen(BesGTaiwánBfrGTaïwanBjaF台湾 u(BruNТайвань (!W!ad!sh@8!h@^@!KAsia/Taipei!( ("  BCN Bde'BenZPeople's Republic of ChinaBesXRepública Popular ChinaBfr(Bja( u'Bru(( (!W!ad!sh@A!h@Z@!(4 (" R BHK BdeHHongkongBenIHong KongBes(Bfr(BjaF香港 u(BruNГонконг (!W!ad!sh@6@!h@\[!NAsia/Hong_Kong!( ( 2 / BNO BdeHNorwegenBenFNorwayBesGNoruegaBfrHNorvègeBjaUノルウェー王国 u(BruPНорвегия F挪威!W!ad!sh@O!h@$!KEurope/Oslo!(Z (" ~ BIL BdeFIsraelBen(Bes(BfrGIsraëlBjaRイスラエル国 u(BruNИзраиль I以色列!W!ad!sh@?!h@A`!NAsia/Jerusalem!( ( 2 !!W!ad!sh@G!h@!LEurope/Paris!! ( 2 ( BCH BdeGSchweizBenKSwitzerlandBesESuizaBfrFSuisseBjaOスイス連邦 uGSuíçaBruRШвейцария F瑞士!W!ad!sh@G>-b9!h@ Ne!MEurope/Zurich!( ( 2 &!W!ad!sh@O!h@.!&!& (" m BBH BdeGBahrainBen(BesHBahréinBfrHBahreïnBjaOバーレーン u(BruNБахрейн F巴林!W!ad!sh@:!h@I@!LAsia/Bahrain!( ( 2 Z BRU BdeHRusslandBenFRussiaBesERusiaBfrFRussieBjaIロシア uGRússiaBruLРоссия I俄罗斯!W!ad!sh@N!h@Y!( f ( 2  /P BPL BdeEPolenBenFPolandBesGPoloniaBfrGPologneBjaXポーランド共和国 uHPolôniaBruLПольша F波兰!W!ad!sh@J!h@4!MEurope/Warsaw!( ( 2 &!W!ad!sh@I!h@%!MEurope/Berlin!& ( 2 0s BIT BdeGItalienBenEItalyBesFItaliaBfrFItalieBjaUイタリア共和国 uGItáliaBruLИталия I意大利!W!ad!sh@EjcI!h@):э&!KEurope/Rome!( ( 2  - BFI BdeHFinnlandBenGFinlandBesIFinlandiaBfrHFinlandeBja[フィンランド共和国 uJFinlândiaBruRФинляндия F芬兰!W!ad!sh@P!h@:!OEurope/Helsinki!( ( 2  @ BBY BdeMWeißrusslandBenGBelarusBesKBielorrusiaBfrLBiélorussieBjaXベラルーシ共和国 uMBielo-RússiaBruPБеларусь L白俄罗斯!W!ad!sh@J!h@<!LEurope/Minsk!( c ( 2 . BCZ BdeUTschechische RepublikBenNCzech RepublicBesPRepública ChecaBfrITchéquieBjaRチェコ共和国 u( uBru]Чешская Республика O捷克共和国!W!ad!sh@H!h@.!MEurope/Prague!( 4 ("  BIR BdeZIran (Islamische Republik)BenDIranBes\Irán (República Islámica)Bfr]Iran (République islamique de)Bja]イラン・イスラム共和国 u\República Islâmica do IrãBruHИран X伊朗伊斯兰共和国!W!ad!sh@@!h@J!KAsia/Tehran!(! ( 2  g BUA BdeGUkraineBen(OBesGUcraniaBfr(OBjaXウクライナ共和国 uHUcrâniaBruNУкраина I乌克兰!W!ad!sh@H!h@@!(= ( 2 !W!ad!sh@Ka7!htr!!! ( 2  BHU BdeFUngarnBenGHungaryBesHHungríaBfrGHongrieBjaXハンガリー共和国 uGHungriaBruNВенгрия I匈牙利!W!ad!sh@G!h@4!OEurope/Budapest!( ( 2!W!ad!sh@HXq`l !h@"GX:S!LEurope/Vaduz ( 2 &O BES BdeGSpanienBenESpainBesGEspañaBfrGEspagneBjaLスペイン uGEspanhaBruNИспания I西班牙!W!ad!sh@D!h!( ( 2  . BBG BdeIBulgarienBenHBulgariaBes(BfrHBulgarieBjaXブルガリア共和国 uIBulgáriaBruPБолгария L保加利亚!W!ad!sh@E!h@9!LEurope/Sofia!( ( 2 #!W!ad!sh@G!h@9!PEurope/Bucharest!# ( 2 *¹ BBE BdeGBelgienBenGBelgiumBesHBélgicaBfrHBelgiqueBjaRベルギー王国 u(BruNБельгия I比利时!W!ad!sh@IjcI!h@!OEurope/Brussels!( (" + BTR BdeGTürkeiBenFTurkeyBesHTurquíaBfrGTurquieBjaRトルコ共和国 uGTurquiaBruLТурция I土耳其!W!ad!sh@C!h@AtU!OEurope/Istanbul!(J ( 2 *s BAT BdeKÖsterreichBenGAustriaBes(!BfrHAutricheBja[オーストリア共和国 uHÁustriaBruNАвстрия I奥地利!W!ad!sh@GcI!h@*:э&!MEurope/Vienna!( ( 2  BAL BdeHAlbanienBenGAlbaniaBes(BfrGAlbanieBjaXアルバニア共和国 uHAlbâniaBruNАлбания O阿尔巴尼亚!W!ad!sh@D!h@4!MEurope/Tirane!( (" & BLB BdeGLibanonBenGLebanonBesGLíbanoBfrELibanBjaUレバノン共和国 u(BruJЛиван I黎巴嫩!W!ad!sh@@ꪎcI!h@AꪎcI!KAsia/Beirut!(w ( 2 ) BNL BdeKNiederlandeBenKNetherlandsBesGHolandaBfrHPays-BasBjaRオランダ王国 uNPaíses BaixosBruTНидерланды F荷兰!W!ad!sh@J@!h@!PEurope/Amsterdam!( (" [ BKW BdeFKuwaitBen(Bes(BfrGKoweïtBjaOクウェート u(BruLКувейт I科威特!W!ad!sh@=!h@G!KAsia/Kuwait!( ("  BSA BdeMSaudi-ArabienBenLSaudi ArabiaBesNArabia SauditaBfrOArabie saouditeBja[サウジアラビア王国 uOArábia SauditaBru]Саудовская Аравия O沙特阿拉伯!W!ad!sh@9!h@F!KAsia/Riyadh!( ( 2 _L BRS BdeGSerbienBenFSerbiaBes(BfrFSerbieBjaLセルビア uGSérviaBruLСербия L塞尔维亚!W!ad!sh@Fh^)!h@4u?h!OEurope/Belgrade!({ ("  BJO BdeIJordanienBen[Hashemite Kingdom of JordanBesHJordaniaBfrHJordanieBja]ヨルダン・ハシミテ王国 uIJordâniaBruPИордания F约旦!W!ad!sh@?!h@B!JAsia/Amman!(# ( 3BAF _r* BdeFAfrikaBenFAfricaBesGÁfricaBfrGAfriqueBjaLアフリカ u(BruLАфрика F非洲 ! BLY Bde]Libysch-Arabische DschamahirijaBenELibyaBesXLibia, República ÁrabeBfrELibyeBja] 社会主義人民リビア・アラブ国 uXLíbia Árabe JamahiriyaBruJЛивия [阿拉伯利比亚民众国!W!ad!sh@<!h@1!NAfrica/Tripoli!(` ( 2 -8 BIE BdeFIrlandBenGIrelandBesURepública de IrlandaBfrGIrlandeBjaRアイルランド uGIrlandaBruPИрландия I爱尔兰!W!ad!sh@J!h !MEurope/Dublin!(q (" l BAZ BdeMAserbaidschanBenJAzerbaijanBesKAzerbaiyánBfrLAzerbaïdjanBja]アゼルバイジャン共和国 uKAzerbaijãoBruVАзербайджан L阿塞拜疆!W!ad!sh@D@!h@G!IAsia/Baku!(6 (" n BAE Bde\Vereinigte Arabische EmirateBenTUnited Arab EmiratesBesWEmiratos Árabes UnidosBfrTÉmirats Arabes UnisBjaXアラブ首長国連邦 uWEmirados Árabes UnidosBru]Объединенные Арабские Эмираты X阿拉伯联合酋长国!W!ad!sh@8!h@K!JAsia/Dubai!( ("  BAM BdeHArmenienBenGArmeniaBes(qBfrHArménieBjaXアルメニア共和国 uHArmêniaBruNАрмения L亚美尼亚!W!ad!sh@D!h@F!LAsia/Yerevan!(S ( 2 (8 BDK BdeIDänemarkBenGDenmarkBesIDinamarcaBfrHDanemarkBjaUデンマーク王国 u(9BruJДания F丹麦!W!ad!sh@L!h@$!QEurope/Copenhagen!( ( 2 .k BIM BdeIInsel ManBenKIsle of ManBesKIsla de ManBfrKÎle de ManBjaIマン島 uKIlha de ManBruMМэн, о-в F曼岛!W!ad!sh@K !h!REurope/Isle_of_Man!( ( 2 $B BGI BdeIGibraltarBen( Bes( Bfr( BjaRジブラルタル u( BruRГибралтар!W!ad!sh@Bɰ!hffffff!PEurope/Gibraltar!( }MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeKGeoIP2-CityKdescriptionBen]=GeoIP2 City Test Invalid Node Count Database (fake GeoIP2 data, for example purposes only)BzhO小型数据库Jip_versionIlanguagesBenBzhJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/MaxMind-DB-test-decoder.mmdb0000644000175000017500000000556513227476051023623 0ustar greggreg00000000000000L.      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~`      !"#$%&'()*+,-/0123456789:K;<=>?@ABCDEFGHIJ``MNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~EarrayGbooleanEbytesFdoublehEfloatEint32CmapGuint128Fuint16Fuint32Fuint64Kutf8_string@   * h@Eg?[ *? 6CmapDmapXFarrayX Lutf8_stringXEhello C Md U ] fRunicode! ☯ - ♫MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeWMaxMind DB Decoder TestKdescriptionBen])MaxMind DB Decoder Test database - contains every MaxMind DB data typeJip_versionIlanguagesBenJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/GeoIP2-City-Test-Broken-Double-Format.mmdb0000644000175000017500000004776613227476051026160 0ustar greggreg00000000000000      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ|RSTUVWXYZ[\]^_`abcde~fghijklmnopqrstuvwxyz{|}   8  ` ` /{bC-&      !"#$%'()*+,./0126345789:;<=>?@ABDEFRGHIJKLMNOPQ.STUVWXYZ[\]^_`acdefghijklmnopqrstuvwxyz}~`\[P`SS$     S4%S$" !S#$&-'*()+,.1/0S23S5A6=7:89;<>?@SBICFDE2GHJMKLNOQRSTUVWXYZ`]^_`abcdefghijk{lmnoptqrsuxvwfyz|}~."k0$Y.C$     ?! "#%4&-'*()+,.1/0 235<6978:;=@>?ABDcETFMGJHIKLNQOPRS$U\VYWX!_Z[]`^_abdselfighjkfmpnoqr"t{uxvwyz|}~ "#z."" $k"$%&k  " H )"' !#&$%f'(*9+2,/-..013645"78":A;><=?@BECDFGIhJYKRLOMNPQSVTUWX(Za[^\]_`becdfg$ixjqknlm$oprust"vwyz}{|~0$%$")e*"""""     "O0!" "")#&$%'(*-+,./1@293645$78:=;<>?"AHBECDFGILJKMN"PoQ`RYSVTUWX+CZ][\^_ahbecdfgiljk+Cmn pqxrust"vwy|z{}~+,DcityJgeoname_id(EEnamesBenGBoxfordIcontinentDcodeBEU _r, BdeFEuropaBenFEuropeBes GBfr QBjaOヨーロッパEpt-BR GBruLЕвропаEzh-CNF欧洲Gcountry (5Tis_in_european_unionHiso_codeBGB BdeWVereinigtes KönigreichBenNUnited KingdomBesKReino UnidoBfrKRoyaume-UniBjaLイギリス u Bru\Великобритания F英国HlocationOaccuracy_radiusdHlatitudeg51.7500Ilongitudeg-1.2500Itime_zoneMEurope/LondonFpostal 3COX1Rregistered_country . BFR BdeJFrankreichBenFFranceBesGFranciaBfr!BjaUフランス共和国 uGFrançaBruNФранция F法国Lsubdivisions _ CENG BenGEnglandBesJInglaterraBfrJAngleterre u"u 2a CWBK BenNWest BerkshireBru]Западный Беркшир L西伯克郡 ( 3BAS _r+ BdeEAsienBenDAsiaBes#BfrDAsieBjaIアジア uEÁsiaBruHАзия F亚洲  BBT BdeFBhutanBen#UBesFButánBfr#UBjaRブータン王国 uFButãoBruJБутан F不丹!W!a!sg27.5000!g90.5000!LAsia/Thimphu!  /U BRO BdeIRumänienBenGRomaniaBesHRumaníaBfrHRoumanieBjaOルーマニア uHRomêniaBruNРумыния L罗马尼亚FtraitsRis_anonymous_proxy  (W BdeFLondonBen$BesGLondresBfr$BjaLロンドン u$BruLЛондон ( 2 !W!ad!sg51.5142!g-0.0931!!! _e BUS BdeCUSABenMUnited StatesBesNEstados UnidosBfrKÉtats-UnisBjaUアメリカ合衆国 u%BruFСША F美国"H"W $u ( 2 !W!a!s$!$!!!$"H%e $u ( 2 !W!a !s$!$!!!$"H%e  )j BdeJLinköpingBen%Bfr%BjaXリンシェーピング I林雪平 ( 2 ( BSE BdeHSchwedenBenFSwedenBesFSueciaBfrFSuèdeBjaXスウェーデン王国 uGSuéciaBruLШвеция F瑞典!W!aL!sg58.4167!g15.6167!PEurope/Stockholm! ,T BDE BdeKDeutschlandBenGGermanyBesHAlemaniaBfrIAllemagneBjaXドイツ連邦共和国 uHAlemanhaBruPГермания F德国"H ( AE BenUÖstergötland CountyBfrWComté d'Östergötland   BdeKChángchūnBenIChangchunBfr'BjaI長春市BruNЧанчунь F长春 ("  BCN BdeEChinaBen'Bes'BfrEChineBjaF中国 u'BruJКитай (!W!ad!se43.88!h125.3228!KAsia/Harbin!'"H  B22 BenKJilin Sheng F吉林 (" 8 BPH BdeKPhilippinenBenKPhilippinesBesIFilipinasBfr(BjaXフィリピン共和国 u(BruRФилиппины I菲律宾!W!ay!sb13!c122!KAsia/Manila! 3E34021!(Srepresented_country _e BUS $DtypeHmilitary  X$ BenFMiltonBruNМильтон ( 3BNA _r- BdeKNordamerikaBenMNorth AmericaBesRAmérica del NorteBfrQAmérique du NordBjaO北アメリカ uQAmérica do NorteBru]Северная Америка I北美洲 $!W!a!sg47.2513!i-122.3149Jmetro_code3!SAmerica/Los_Angeles! 3E98354! "H X_ BWA BenJWashingtonBes(BfrSÉtat de WashingtonBjaRワシントン州BruRВашингтон L华盛顿州 (" e BJP BdeEJapanBen(5BesFJapónBfrEJaponBjaF日本 uFJapãoBruLЯпония (W!W!ad!sh35.68536!i139.75309!JAsia/Tokyo!(# (" A BKR BdeNRepublik KoreaBenKSouth KoreaBesTCorea, República deBfrMCorée du SudBjaL大韓民国 uVCoréia, República daBruUЮжная Корея F韩国!W!ad!sb37!e127.5!JAsia/Seoul!( (" t BTW BdeFTaiwanBen(BesGTaiwánBfrGTaïwanBjaF台湾 u(BruNТайвань (!W!ad!sb24!c121!KAsia/Taipei!( ("  BCN Bde'BenZPeople's Republic of ChinaBesXRepública Popular ChinaBfr( Bja( u'Bru( (!W!ad!sb35!c105!( (" R BHK BdeHHongkongBenIHong KongBes(Bfr(BjaF香港 u(BruNГонконг (!W!ad!se22.25!i114.16667!NAsia/Hong_Kong!( ( 2 / BNO BdeHNorwegenBenFNorwayBesGNoruegaBfrHNorvègeBjaUノルウェー王国 u(LBruPНорвегия F挪威!W!ad!sb62!b10!KEurope/Oslo!($ (" ~ BIL BdeFIsraelBen(Bes(BfrGIsraëlBjaRイスラエル国 u(BruNИзраиль I以色列!W!ad!sd31.5!e34.75!NAsia/Jerusalem!( ( 2 !!W!ad!sb46!a2!LEurope/Paris!! ( 2 ( BCH BdeGSchweizBenKSwitzerlandBesESuizaBfrFSuisseBjaOスイス連邦 uGSuíçaBruRШвейцария F瑞士!W!ad!sh47.00016!g8.01427!MEurope/Zurich!( ( 2 & !W!ad!sb62!b15!&!& (" m BBH BdeGBahrainBen(rBesHBahréinBfrHBahreïnBjaOバーレーン u(rBruNБахрейн F巴林!W!ad!sb26!d50.5!LAsia/Bahrain!(` ( 2 Z BRU BdeHRusslandBenFRussiaBesERusiaBfrFRussieBjaIロシア uGRússiaBruLРоссия I俄罗斯!W!ad!sb60!c100!( ( 2  /P BPL BdeEPolenBenFPolandBesGPoloniaBfrGPologneBjaXポーランド共和国 uHPolôniaBruLПольша F波兰!W!ad!sb52!b20!MEurope/Warsaw!( ( 2 &!W!ad!sd51.5!d10.5!MEurope/Berlin!& ( 2 0s BIT BdeGItalienBenEItalyBesFItaliaBfrFItalieBjaUイタリア共和国 uGItáliaBruLИталия I意大利!W!ad!sh42.83333!h12.83333!KEurope/Rome!( ] ( 2  - BFI BdeHFinnlandBenGFinlandBesIFinlandiaBfrHFinlandeBja[フィンランド共和国 uJFinlândiaBruRФинляндия F芬兰!W!ad!sb64!b26!OEurope/Helsinki!(  ( 2  @ BBY BdeMWeißrusslandBenGBelarusBesKBielorrusiaBfrLBiélorussieBjaXベラルーシ共和国 uMBielo-RússiaBruPБеларусь L白俄罗斯!W!ad!sb53!b28!LEurope/Minsk!( ( 2 . BCZ BdeUTschechische RepublikBenNCzech RepublicBesPRepública ChecaBfrITchéquieBjaRチェコ共和国 u( Bru]Чешская Республика O捷克共和国!W!ad!se49.75!b15!MEurope/Prague!( ("  BIR BdeZIran (Islamische Republik)BenDIranBes\Irán (República Islámica)Bfr]Iran (République islamique de)Bja]イラン・イスラム共和国 u\República Islâmica do IrãBruHИран X伊朗伊斯兰共和国!W!ad!sb32!b53!KAsia/Tehran!( t ( 2  g BUA BdeGUkraineBen(BesGUcraniaBfr(BjaXウクライナ共和国 uHUcrâniaBruNУкраина I乌克兰!W!ad!sb49!b32!( ( 2 !W!ad!sh54.75844!h-2.69531!!! ( 2  BHU BdeFUngarnBenGHungaryBesHHungríaBfrGHongrieBjaXハンガリー共和国 uGHungriaBruNВенгрия I匈牙利!W!ad!sb47!b20!OEurope/Budapest!(E ( 2!W!ad!sh48.69096!g9.14062!LEurope/Vaduz ( 2 &O BES BdeGSpanienBenESpainBesGEspañaBfrGEspagneBjaLスペイン uGEspanhaBruNИспания I西班牙!W!ad!sb40!b-4!(' ( 2  . BBG BdeIBulgarienBenHBulgariaBes(BfrHBulgarieBjaXブルガリア共和国 uIBulgáriaBruPБолгария L保加利亚!W!ad!sb43!b25!LEurope/Sofia!( ( 2 #!W!ad!sb46!b25!PEurope/Bucharest!# ( 2 *¹ BBE BdeGBelgienBenGBelgiumBesHBélgicaBfrHBelgiqueBjaRベルギー王国 u(BruNБельгия I比利时!W!ad!sh50.83333!a4!OEurope/Brussels!( (" + BTR BdeGTürkeiBenFTurkeyBesHTurquíaBfrGTurquieBjaRトルコ共和国 uGTurquiaBruLТурция I土耳其!W!ad!sh39.05901!h34.91155!OEurope/Istanbul!(M ( 2 *s BAT BdeKÖsterreichBenGAustriaBes($BfrHAutricheBja[オーストリア共和国 uHÁustriaBruNАвстрия I奥地利!W!ad!sh47.33333!h13.33333!MEurope/Vienna!( ( 2  BAL BdeHAlbanienBenGAlbaniaBes(BfrGAlbanieBjaXアルバニア共和国 uHAlbâniaBruNАлбания O阿尔巴尼亚!W!ad!sb41!b20!MEurope/Tirane!( (" & BLB BdeGLibanonBenGLebanonBesGLíbanoBfrELibanBjaUレバノン共和国 u(BruJЛиван I黎巴嫩!W!ad!sh33.83333!h35.83333!KAsia/Beirut!(n ( 2 ) BNL BdeKNiederlandeBenKNetherlandsBesGHolandaBfrHPays-BasBjaRオランダ王国 uNPaíses BaixosBruTНидерланды F荷兰!W!ad!sd52.5!d5.75!PEurope/Amsterdam!( (" [ BKW BdeFKuwaitBen(Bes(BfrGKoweïtBjaOクウェート u(BruLКувейт I科威特!W!ad!sd29.5!e47.75!KAsia/Kuwait!( ("  BSA BdeMSaudi-ArabienBenLSaudi ArabiaBesNArabia SauditaBfrOArabie saouditeBja[サウジアラビア王国 uOArábia SauditaBru]Саудовская Аравия O沙特阿拉伯!W!ad!sb25!b45!KAsia/Riyadh!(n ( 2 _L BRS BdeGSerbienBenFSerbiaBes(tBfrFSerbieBjaLセルビア uGSérviaBruLСербия L塞尔维亚!W!ad!sh44.81892!h20.45998!OEurope/Belgrade!(W ("  BJO BdeIJordanienBen[Hashemite Kingdom of JordanBesHJordaniaBfrHJordanieBja]ヨルダン・ハシミテ王国 uIJordâniaBruPИордания F约旦!W!ad!sb31!b36!JAsia/Amman!( ( 3BAF _r* BdeFAfrikaBenFAfricaBesGÁfricaBfrGAfriqueBjaLアフリカ u(BruLАфрика F非洲 ! BLY Bde]Libysch-Arabische DschamahirijaBenELibyaBesXLibia, República ÁrabeBfrELibyeBja] 社会主義人民リビア・アラブ国 uXLíbia Árabe JamahiriyaBruJЛивия [阿拉伯利比亚民众国!W!ad!sb28!b17!NAfrica/Tripoli!(0 ( 2 -8 BIE BdeFIrlandBenGIrelandBesURepública de IrlandaBfrGIrlandeBjaRアイルランド uGIrlandaBruPИрландия I爱尔兰!W!ad!sb53!b-8!MEurope/Dublin!(5 (" l BAZ BdeMAserbaidschanBenJAzerbaijanBesKAzerbaiyánBfrLAzerbaïdjanBja]アゼルバイジャン共和国 uKAzerbaijãoBruVАзербайджан L阿塞拜疆!W!ad!sd40.5!d47.5!IAsia/Baku!( (" n BAE Bde\Vereinigte Arabische EmirateBenTUnited Arab EmiratesBesWEmiratos Árabes UnidosBfrTÉmirats Arabes UnisBjaXアラブ首長国連邦 uWEmirados Árabes UnidosBru]Объединенные Арабские Эмираты X阿拉伯联合酋长国!W!ad!sb24!b54!JAsia/Dubai!( ("  BAM BdeHArmenienBenGArmeniaBes(BfrHArménieBjaXアルメニア共和国 uHArmêniaBruNАрмения L亚美尼亚!W!ad!sb40!b45!LAsia/Yerevan!( ( 2 (8 BDK BdeIDänemarkBenGDenmarkBesIDinamarcaBfrHDanemarkBjaUデンマーク王国 u(BruJДания F丹麦!W!ad!sb56!b10!QEurope/Copenhagen!( ( 2 .k BIM BdeIInsel ManBenKIsle of ManBesKIsla de ManBfrKÎle de ManBjaIマン島 uKIlha de ManBruMМэн, о-в F曼岛!W!ad!se54.25!d-4.5!REurope/Isle_of_Man!(M ( 2 $B BGI BdeIGibraltarBen(Bes(Bfr(BjaRジブラルタル u(BruRГибралтар!W!ad!sh36.13333!e-5.35!PEurope/Gibraltar!(MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeKGeoIP2-CityKdescriptionBen]?GeoIP2 City Test Broken Double Format Database (fake GeoIP2 data, for example purposes only)BzhO小型数据库Jip_versionIlanguagesBenBzhJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/MaxMind-DB-test-ipv6-24.mmdb0000644000175000017500000000536613227476051023324 0ustar greggreg00000000000000n6      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ'RSTUVWXYZ[\]^_`awbkcdehfgijlmsnopqrtuvxyz{|}~      !"#$%&()*+,-./012345`789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmopqrstuvwxyz{|}~``BipM::1:ffff:ffffBipG::2:0:0BipH::2:0:40BipH::2:0:50BipH::2:0:58MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeDTestKdescriptionBenMTest DatabaseBzhUTest Database ChineseJip_versionIlanguagesBenBzhJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/GeoIP2-Connection-Type-Test.mmdb0000644000175000017500000000730313227476051024371 0ustar greggreg00000000000000v      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQgRSTUVWXYZ[\]^_`ab{cdexfghijklmnopqrstuvwyz|}~f4      !"#'$%&()*+,-./01235X6G789:;<=>?@ABCDEF)HIJKLMNOPQRSTUVWYZ[\]^_`abcdehijklmnopqrstu`wxyz{|}~``Oconnection_typeFDialup ICable/DSL HCellular ICorporateMaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeVGeoIP2-Connection-TypeKdescriptionBen]5GeoIP2 Connection Type Test Database (fake GeoIP2 data, for example purposes only)Jip_versionIlanguagesBenJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/MaxMind-DB-test-mixed-28.mmdb0000644000175000017500000000666713227476051023557 0ustar greggreg00000000000000S      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQDRSTUVWXYZ[\]^_$`abcdefghijklmnopqrstuvwxyz{|}~      !"##%&'()*+,-./0123456789:;<=>5?@AANBC[EFGHIJKLMNOPQR`TUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~``BipJ::1.1.1.16BipI::1.1.1.8BipI::1.1.1.4BipI::1.1.1.2BipI::1.1.1.1BipJ::1.1.1.32BipM::1:ffff:ffffBipG::2:0:0BipH::2:0:40BipH::2:0:50BipH::2:0:58MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeDTestKdescriptionBenMTest DatabaseBzhUTest Database ChineseJip_versionIlanguagesBenBzhJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/MaxMind-DB-test-nested.mmdb0000644000175000017500000000733213227476051023472 0ustar greggreg00000000000000=a===) = = = = =================== =!="=#=$=%=&='=(=)=*=+=,=-=.=/=0=1=2=3=4=5=6=7=8=9=:=;=<===>=?=@=A=B=C=D=E=F=G=H=I=J=K=L=M=N=O=P=QR=S=T=U=V=W=X=Y=Z=[=\=]=^=_=`=abc=d=efgx=hi=j=k=l=m=n=o==pq=r=s=t=u=v=w==MyMz={=|=}=~===M===========================M===============================================================================================================  = = = ====================== =!="=#=$=%=&='=(=`*=+=,=-=.=/=0=1=2=3=4=5=6=7=8=9=:=;=<===>=?=@=A=B=C=D=E=F=G=H=I=J=K=L=M=N=O=P=Q=R=S=T=U=V=W=X=Y=Z=[=\=]=^=_=`===b=c=d=e=f=g=h=i=j=k=l=m=n=o=p=q=r=s=t=u=v=w=x=y=z={=|=}=~===============================================================================M===========================`=============`=5================= = = = = =================== =!="=#=$=%=&='=(=)=*=+=,=-=.=/=0=1=2=3=4=M==6=7=8=9=:;==<==Dmap1Dmap2EarrayDmap3AaAbAcMaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_type]MaxMind DB Nested Data StructuresKdescriptionBen]@MaxMind DB Nested Data Structures Test database - contains deeply nested map/array structuresJip_versionIlanguagesBenJnode_count=Krecord_sizegeoip2-2.7.0/tests/data/test-data/GeoIP2-Precision-Enterprise-Test.mmdb0000644000175000017500000003113013227476051025417 0ustar greggreg00000000000000      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a`bcdefghijklmnopqrstuvwxyz{|}~.JLNU#} V       !"R$>%&'()*+,-./0123456789:;<=?@ABCDEFGHIJKLMNOPQRST;V\WXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~bIw~/      !"#$%&'()*+,-.0f1K23456789:;<=>?@ABCDEFGHIJLMNOPQRSTUVWXYZ[\]^_`abcdeghijklmnopqrstuvwxyz{|}``1`     zFtraitsIuser_typeHbusinessDcityJconfidence2Jgeoname_id(EEnamesBenGBoxfordIcontinentDcodeBEU 0_r, ?BdeFEuropaBenFEuropeBes pBfr zBjaOヨーロッパEpt-BR pBruLЕвропаEzh-CNF欧洲Gcountry #_ 0(5Tis_in_european_unionHiso_codeBGB ?BdeWVereinigtes KönigreichBenNUnited KingdomBesKReino UnidoBfrKRoyaume-UniBjaLイギリス !,Bru\Великобритания F英国HlocationOaccuracy_radiusdHlatitudeh@IIlongitudehItime_zoneMEurope/LondonFpostal \COX1 #Rregistered_country 0. BFR ?BdeJFrankreichBenFFranceBesGFranciaBfr"&BjaUフランス共和国 GFrançaBruNФранция F法国Lsubdivisions #F 0_ CENG ?BenGEnglandBesJInglaterraBfrJAngleterre " 02a CWBK ?BenNWest BerkshireBru]Западный Беркшир L西伯克郡! 0 /U BRO ?BdeIRumänienBenGRomaniaBesHRumaníaBfrHRoumanieBjaOルーマニア HRomêniaBruNРумыния L罗马尼亚 Ris_anonymous_proxy CispJWifiNetCom Xautonomous_system_numberjCispMAT&T ServicesLorganizationVAT&T Worldnet Services  0#) ?BenEYendi Q \BAF 0_r* ?BdeFAfrikaBenFAfricaBesGÁfricaBfrGAfriqueBjaLアフリカ $^BruLАфрика F非洲 0# BGH ?BdeEGhanaBen$Bes$Bfr$BjaRガーナ共和国 DGanaBruHГана F加纳!!!h@"b!h_o!LAfrica/Accra!$"{ 0# Q BNP ?BenONorthern Region  #( 0G ?BenGHoustonBfr%cBjaRヒューストン %cBruNХьюстон I休斯敦 Q \BNA 0_r- ?BdeKNordamerikaBenMNorth AmericaBesMNorteaméricaBfrQAmérique du NordBjaO北アメリカ QAmérica do NorteBru]Северная Америка I北美洲 #c 0_e BUS ?BdeCUSABenMUnited StatesBesNEstados UnidosBfrKÉtats-UnisBjaUアメリカ合衆国 &BruFСША F美国!!!h@=+a!hW8}HJmetro_codej!OAmerica/Chicago! \E77002 #! 0_e BUS ?&j"{ #Z 0HE BTX ?BenETexasBes'MBfr'MBjaOテキサス州BruJТехас O德克萨斯州 #]autonomous_system_organization]Qwest Communications Company, LLCOconnection_typeICable/DSLFdomainIqwest.netCispKCenturyLink#( Kresidential  # 0RG+ ?BdeISan JoséBenHSan JoseBes(BjaI長春市BruNЧанчунь F长春 Q( #_ 0 BCN ?BdeEChinaBen( Bes( BfrEChineBjaF中国 ( BruJКитай ( !!d!h@E =q!h@_TTɆ!KAsia/Harbin! 0 BCN ?( "{ #F 0 B22 ?BenKJilin Sheng F吉林  Fdialup #LCityLink Ltd Q( #_ 08 BPH ?BdeKPhilippinenBenKPhilippinesBesIFilipinasBfr( BjaXフィリピン共和国 ( BruRФилиппины I菲律宾!!y!h@*!h@^!KAsia/Manila! \E34021 #! 08 BPH ?( vSrepresented_country 0_e BUS ?&jDtypeHmilitary  # 0H?i ?BenJSugar LandBjaUシュガーランド (~BruSШугар-Ленд Q% &X!!!h@=T!hW =q&j!'! \E77487 #!'#"{ #< 0HE BTX ?'I #+']Comcast Cable Communications, LLC'''Scomcastbusiness.netCispPComcast Business#(c  # (  #( 0X$ ?BenFMiltonBruNМильтон Q \BNA 0_r- ?Bde%Ben%BesRAmérica del NorteBfr%Bja& &Bru&) &L &X!!!h@G*0!h^'RT`&3!(! \E98354 #(! 0(5 BGB ? "{ #c 0X_ BWA ?BenJWashingtonBes(mBfrSÉtat de WashingtonBjaRワシントン州BruRВашингтон L华盛顿州 #''CispLCentury Link#OLariat Software ( Q( #_ 0e BJP ?BdeEJapanBen(!BesFJapónBfrEJaponBjaF日本 FJapãoBruLЯпония (C!!d!h@A׹`H!h@axP3:!JAsia/Tokyo! 0e BJP ?( Q( #_ 0 BCN ?Bde( BenZPeople's Republic of ChinaBesXRepública Popular ChinaBfr( Bja( ( Bru( ( !!d!h@A!h@Z@! 0 BCN ?( Q [ #_ 0. BCZ ?BdeUTschechische RepublikBenNCzech RepublicBesPRepública ChecaBfrITchéquieBjaRチェコ共和国 (Bru]Чешская Республика O捷克共和国!!d!h@H!h@.!MEurope/Prague! 0. BCZ ?(iMaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_type[GeoIP2-Precision-EnterpriseKdescriptionBen]:GeoIP2 Precision Enterprise Test Database (fake GeoIP2 data, for example purposes only)Jip_versionIlanguagesBenJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/MaxMind-DB-no-ipv4-search-tree.mmdb0000644000175000017500000000115213227476051024721 0ustar greggreg00000000000000@@@@@@@@ @ @ @ @ @@@@@@@@@@@@@@@@@@@ @!@"@#@$@%@&@'@(@)@*@+@,@-@.@/@0@1@2@3@4@5@6@7@8@9@:@;@<@=@>@?@P@F::0/64MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_type]MaxMind DB No IPv4 Search TreeKdescriptionBen \Jip_versionIlanguagesBenJnode_count@Krecord_sizegeoip2-2.7.0/tests/data/test-data/MaxMind-DB-test-broken-search-tree-24.mmdb0000644000175000017500000000242213227476051026106 0ustar greggreg00000000000000(%  !"#$&')*0+,-./1235I6789C:;<=>?@ABDEFGHJKLMzNOPsQeRSTUVWXYZ[\]^d_`abcfghijklmnopqrtuvwxy{|}~BipH1.1.1.16BipG1.1.1.8BipG1.1.1.4BipG1.1.1.2BipG1.1.1.1BipH1.1.1.32MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeDTestKdescriptionBenMTest DatabaseBzhUTest Database ChineseJip_versionIlanguagesBenBzhJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/MaxMind-DB-test-broken-pointers-24.mmdb0000644000175000017500000000241113227476051025545 0ustar greggreg000000000000004(%  !"#$&')*0+,-./1235I6789C:;<=>?@ABDEFGHJKLMzNOPsQeRSTUVWXYZ[\]^d_`abcfghijklmnopqrtuvwxy{|}~0:@BipG1.1.1.8BipG1.1.1.4BipG1.1.1.2BipG1.1.1.1BipH1.1.1.32MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeDTestKdescriptionBenMTest DatabaseBzhUTest Database ChineseJip_versionIlanguagesBenBzhJnode_countKrecord_sizegeoip2-2.7.0/tests/data/test-data/GeoIP2-User-Count-Test.mmdb0000644000175000017500000000742213227476051023361 0ustar greggreg00000000000000G      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy$z${$|$}$$~,55$     ` !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFHIJKLMNOPQRSTUoVWXYdZ[\]^_`abc`efghijklmnpqrstuvwxyz{|}~>>>>>>>>>>>>>>>IIIIIIIIIIIIIIIUI>>>>>>>>>>>>>>bbbbbbbbbbbbbbbn{>>>>>>>>>>>>>>`Gipv6_32Gipv6_48Gipv6_64Gipv4_24Gipv4_32  &  &  &                       MaxMind.com[binary_format_major_version[binary_format_minor_versionKbuild_epochZ]*Mdatabase_typeQGeoIP2-User-CountKdescriptionBen]0GeoIP2 User Count Test Database (fake GeoIP2 data, for example purposes only)Jip_versionIlanguagesBenJnode_countKrecord_sizegeoip2-2.7.0/geoip2.egg-info/0000755000175000017500000000000013230142214015446 5ustar greggreg00000000000000geoip2-2.7.0/geoip2.egg-info/requires.txt0000664000175000017500000000013413230142214020046 0ustar greggreg00000000000000requests>=2.9 maxminddb>=1.2.1 [:python_version=="2.6" or python_version=="2.7"] ipaddress geoip2-2.7.0/geoip2.egg-info/SOURCES.txt0000664000175000017500000000560713230142214017344 0ustar greggreg00000000000000HISTORY.rst LICENSE MANIFEST.in README.rst requirements.txt setup.cfg setup.py docs/html/.buildinfo docs/html/genindex.html docs/html/index.html docs/html/objects.inv docs/html/py-modindex.html docs/html/search.html docs/html/searchindex.js docs/html/_sources/index.rst.txt docs/html/_sources/index.txt docs/html/_static/ajax-loader.gif docs/html/_static/basic.css docs/html/_static/comment-bright.png docs/html/_static/comment-close.png docs/html/_static/comment.png docs/html/_static/contents.png docs/html/_static/doctools.js docs/html/_static/down-pressed.png docs/html/_static/down.png docs/html/_static/file.png docs/html/_static/jquery-1.11.1.js docs/html/_static/jquery-3.1.0.js docs/html/_static/jquery.js docs/html/_static/minus.png docs/html/_static/navigation.png docs/html/_static/plus.png docs/html/_static/pygments.css docs/html/_static/searchtools.js docs/html/_static/sphinxdoc.css docs/html/_static/underscore-1.3.1.js docs/html/_static/underscore.js docs/html/_static/up-pressed.png docs/html/_static/up.png docs/html/_static/websupport.js geoip2/__init__.py geoip2/compat.py geoip2/database.py geoip2/errors.py geoip2/mixins.py geoip2/models.py geoip2/records.py geoip2/webservice.py geoip2.egg-info/PKG-INFO geoip2.egg-info/SOURCES.txt geoip2.egg-info/dependency_links.txt geoip2.egg-info/requires.txt geoip2.egg-info/top_level.txt tests/__init__.py tests/database_test.py tests/models_test.py tests/webservice_test.py tests/data/test-data/GeoIP2-Anonymous-IP-Test.mmdb tests/data/test-data/GeoIP2-City-Test-Broken-Double-Format.mmdb tests/data/test-data/GeoIP2-City-Test-Invalid-Node-Count.mmdb tests/data/test-data/GeoIP2-City-Test.mmdb tests/data/test-data/GeoIP2-Connection-Type-Test.mmdb tests/data/test-data/GeoIP2-Country-Test.mmdb tests/data/test-data/GeoIP2-DensityIncome-Test.mmdb tests/data/test-data/GeoIP2-Domain-Test.mmdb tests/data/test-data/GeoIP2-Enterprise-Test.mmdb tests/data/test-data/GeoIP2-ISP-Test.mmdb tests/data/test-data/GeoIP2-Precision-Enterprise-Test.mmdb tests/data/test-data/GeoIP2-User-Count-Test.mmdb tests/data/test-data/GeoLite2-ASN-Test.mmdb tests/data/test-data/MaxMind-DB-no-ipv4-search-tree.mmdb tests/data/test-data/MaxMind-DB-string-value-entries.mmdb tests/data/test-data/MaxMind-DB-test-broken-pointers-24.mmdb tests/data/test-data/MaxMind-DB-test-broken-search-tree-24.mmdb tests/data/test-data/MaxMind-DB-test-decoder.mmdb tests/data/test-data/MaxMind-DB-test-ipv4-24.mmdb tests/data/test-data/MaxMind-DB-test-ipv4-28.mmdb tests/data/test-data/MaxMind-DB-test-ipv4-32.mmdb tests/data/test-data/MaxMind-DB-test-ipv6-24.mmdb tests/data/test-data/MaxMind-DB-test-ipv6-28.mmdb tests/data/test-data/MaxMind-DB-test-ipv6-32.mmdb tests/data/test-data/MaxMind-DB-test-metadata-pointers.mmdb tests/data/test-data/MaxMind-DB-test-mixed-24.mmdb tests/data/test-data/MaxMind-DB-test-mixed-28.mmdb tests/data/test-data/MaxMind-DB-test-mixed-32.mmdb tests/data/test-data/MaxMind-DB-test-nested.mmdbgeoip2-2.7.0/geoip2.egg-info/PKG-INFO0000664000175000017500000004116613230142214016555 0ustar greggreg00000000000000Metadata-Version: 1.1 Name: geoip2 Version: 2.7.0 Summary: MaxMind GeoIP2 API Home-page: http://www.maxmind.com/ Author: Gregory Oschwald Author-email: goschwald@maxmind.com License: Apache License, Version 2.0 Description-Content-Type: UNKNOWN Description: ========================= MaxMind GeoIP2 Python API ========================= Description ----------- This package provides an API for the GeoIP2 `web services `_ and `databases `_. The API also works with MaxMind's free `GeoLite2 databases `_. Installation ------------ To install the ``geoip2`` module, type: .. code-block:: bash $ pip install geoip2 If you are not able to use pip, you may also use easy_install from the source directory: .. code-block:: bash $ easy_install . Database Reader Extension ^^^^^^^^^^^^^^^^^^^^^^^^^ If you wish to use the C extension for the database reader, you must first install the `libmaxminddb C API `_. Please `see the instructions distributed with it `_. IP Geolocation Usage -------------------- IP geolocation is inherently imprecise. Locations are often near the center of the population. Any location provided by a GeoIP2 database or web service should not be used to identify a particular address or household. Usage ----- To use this API, you first create either a web service object with your MaxMind ``user_id`` and ``license_key`` or a database reader object with the path to your database file. After doing this, you may call the method corresponding to request type (e.g., ``city`` or ``country``), passing it the IP address you want to look up. If the request succeeds, the method call will return a model class for the end point you called. This model in turn contains multiple record classes, each of which represents part of the data returned by the web service. If the request fails, the client class throws an exception. Web Service Example ------------------- .. code-block:: pycon >>> import geoip2.webservice >>> >>> # This creates a Client object that can be reused across requests. >>> # Replace "42" with your user ID and "license_key" with your license >>> # key. >>> client = geoip2.webservice.Client(42, 'license_key') >>> >>> # Replace "insights" with the method corresponding to the web service >>> # that you are using, e.g., "country", "city". >>> response = client.insights('128.101.101.101') >>> >>> response.country.iso_code 'US' >>> response.country.name 'United States' >>> response.country.names['zh-CN'] u'美国' >>> >>> response.subdivisions.most_specific.name 'Minnesota' >>> response.subdivisions.most_specific.iso_code 'MN' >>> >>> response.city.name 'Minneapolis' >>> >>> response.postal.code '55455' >>> >>> response.location.latitude 44.9733 >>> response.location.longitude -93.2323 Web Service Client Exceptions ----------------------------- For details on the possible errors returned by the web service itself, see http://dev.maxmind.com/geoip/geoip2/web-services for the GeoIP2 Precision web service docs. If the web service returns an explicit error document, this is thrown as a ``AddressNotFoundError``, ``AuthenticationError``, ``InvalidRequestError``, or ``OutOfQueriesError`` as appropriate. These all subclass ``GeoIP2Error``. If some other sort of error occurs, this is thrown as an ``HTTPError``. This is thrown when some sort of unanticipated error occurs, such as the web service returning a 500 or an invalid error document. If the web service returns any status code besides 200, 4xx, or 5xx, this also becomes an ``HTTPError``. Finally, if the web service returns a 200 but the body is invalid, the client throws a ``GeoIP2Error``. Database Example ------------------- City Database ^^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> reader = geoip2.database.Reader('/path/to/GeoLite2-City.mmdb') >>> >>> # Replace "city" with the method corresponding to the database >>> # that you are using, e.g., "country". >>> response = reader.city('128.101.101.101') >>> >>> response.country.iso_code 'US' >>> response.country.name 'United States' >>> response.country.names['zh-CN'] u'美国' >>> >>> response.subdivisions.most_specific.name 'Minnesota' >>> response.subdivisions.most_specific.iso_code 'MN' >>> >>> response.city.name 'Minneapolis' >>> >>> response.postal.code '55455' >>> >>> response.location.latitude 44.9733 >>> response.location.longitude -93.2323 >>> reader.close() Anonymous IP Database ^^^^^^^^^^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> reader = geoip2.database.Reader('/path/to/GeoIP2-Anonymous-IP.mmdb') >>> >>> response = reader.anonymous_ip('85.25.43.84') >>> >>> response.is_anonymous True >>> response.is_anonymous_vpn False >>> response.is_hosting_provider False >>> response.is_public_proxy False >>> response.is_tor_exit_node True >>> response.ip_address '128.101.101.101' >>> reader.close() ASN Database ^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> with geoip2.database.Reader('/path/to/GeoLite2-ASN.mmdb') as reader: >>> response = reader.asn('1.128.0.0') >>> response.autonomous_system_number 1221 >>> response.autonomous_system_organization 'Telstra Pty Ltd' Connection-Type Database ^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> reader = geoip2.database.Reader('/path/to/GeoIP2-Connection-Type.mmdb') >>> >>> response = reader.connection_type('128.101.101.101') >>> >>> response.connection_type 'Corporate' >>> response.ip_address '128.101.101.101' >>> reader.close() Domain Database ^^^^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> reader = geoip2.database.Reader('/path/to/GeoIP2-Domain.mmdb') >>> >>> response = reader.domain('128.101.101.101') >>> >>> response.domain 'umn.edu' >>> response.ip_address '128.101.101.101' >>> reader.close() Enterprise Database ^^^^^^^^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> with geoip2.database.Reader('/path/to/GeoIP2-Enterprise.mmdb') as reader: >>> >>> # Use the .enterprise method to do a lookup in the Enterprise database >>> response = reader.enterprise('128.101.101.101') >>> >>> response.country.confidence 99 >>> response.country.iso_code 'US' >>> response.country.name 'United States' >>> response.country.names['zh-CN'] u'美国' >>> >>> response.subdivisions.most_specific.name 'Minnesota' >>> response.subdivisions.most_specific.iso_code 'MN' >>> response.subdivisions.most_specific.confidence 77 >>> >>> response.city.name 'Minneapolis' >>> response.country.confidence 11 >>> >>> response.postal.code '55455' >>> >>> response.location.accuracy_radius 50 >>> response.location.latitude 44.9733 >>> response.location.longitude -93.2323 ISP Database ^^^^^^^^^^^^ .. code-block:: pycon >>> import geoip2.database >>> >>> # This creates a Reader object. You should use the same object >>> # across multiple requests as creation of it is expensive. >>> reader = geoip2.database.Reader('/path/to/GeoIP2-ISP.mmdb') >>> >>> response = reader.isp('1.128.0.0') >>> >>> response.autonomous_system_number 1221 >>> response.autonomous_system_organization 'Telstra Pty Ltd' >>> response.isp 'Telstra Internet' >>> response.organization 'Telstra Internet' >>> response.ip_address '128.101.101.101' >>> reader.close() Database Reader Exceptions -------------------------- If the database file does not exist or is not readable, the constructor will raise a ``FileNotFoundError`` on Python 3 or an ``IOError`` on Python 2. If the IP address passed to a method is invalid, a ``ValueError`` will be raised. If the file is invalid or there is a bug in the reader, a ``maxminddb.InvalidDatabaseError`` will be raised with a description of the problem. If an IP address is not in the database, a ``AddressNotFoundError`` will be raised. Values to use for Database or Dictionary Keys --------------------------------------------- **We strongly discourage you from using a value from any ``names`` property as a key in a database or dictionaries.** These names may change between releases. Instead we recommend using one of the following: * ``geoip2.records.City`` - ``city.geoname_id`` * ``geoip2.records.Continent`` - ``continent.code`` or ``continent.geoname_id`` * ``geoip2.records.Country`` and ``geoip2.records.RepresentedCountry`` - ``country.iso_code`` or ``country.geoname_id`` * ``geoip2.records.subdivision`` - ``subdivision.iso_code`` or ``subdivision.geoname_id`` What data is returned? ---------------------- While many of the models contain the same basic records, the attributes which can be populated vary between web service end points or databases. In addition, while a model may offer a particular piece of data, MaxMind does not always have every piece of data for any given IP address. Because of these factors, it is possible for any request to return a record where some or all of the attributes are unpopulated. The only piece of data which is always returned is the ``ip_address`` attribute in the ``geoip2.records.Traits`` record. Integration with GeoNames ------------------------- `GeoNames `_ offers web services and downloadable databases with data on geographical features around the world, including populated places. They offer both free and paid premium data. Each feature is uniquely identified by a ``geoname_id``, which is an integer. Many of the records returned by the GeoIP web services and databases include a ``geoname_id`` field. This is the ID of a geographical feature (city, region, country, etc.) in the GeoNames database. Some of the data that MaxMind provides is also sourced from GeoNames. We source things like place names, ISO codes, and other similar data from the GeoNames premium data set. Reporting Data Problems ----------------------- If the problem you find is that an IP address is incorrectly mapped, please `submit your correction to MaxMind `_. If you find some other sort of mistake, like an incorrect spelling, please check the `GeoNames site `_ first. Once you've searched for a place and found it on the GeoNames map view, there are a number of links you can use to correct data ("move", "edit", "alternate names", etc.). Once the correction is part of the GeoNames data set, it will be automatically incorporated into future MaxMind releases. If you are a paying MaxMind customer and you're not sure where to submit a correction, please `contact MaxMind support `_ for help. Requirements ------------ This code requires Python 2.6+ or 3.3+. Older versions are not supported. This library has been tested with CPython and PyPy. The Requests HTTP library is also required. See for details. Versioning ---------- The GeoIP2 Python API uses `Semantic Versioning `_. Support ------- Please report all issues with this code using the `GitHub issue tracker `_ If you are having an issue with a MaxMind service that is not specific to the client API, please contact `MaxMind support `_ for assistance. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python Classifier: Topic :: Internet :: Proxy Servers Classifier: Topic :: Internet geoip2-2.7.0/geoip2.egg-info/dependency_links.txt0000664000175000017500000000000113230142214021516 0ustar greggreg00000000000000 geoip2-2.7.0/geoip2.egg-info/top_level.txt0000664000175000017500000000000713230142214020177 0ustar greggreg00000000000000geoip2 geoip2-2.7.0/setup.py0000644000175000017500000000305313217000700014300 0ustar greggreg00000000000000#!/usr/bin/env python import codecs import os import sys import geoip2 from setuptools import setup packages = ['geoip2'] requirements = [i.strip() for i in open("requirements.txt").readlines()] setup( name='geoip2', version=geoip2.__version__, description='MaxMind GeoIP2 API', long_description=codecs.open('README.rst', 'r', 'utf-8').read(), author='Gregory Oschwald', author_email='goschwald@maxmind.com', url='http://www.maxmind.com/', packages=['geoip2'], package_data={'': ['LICENSE']}, package_dir={'geoip2': 'geoip2'}, include_package_data=True, install_requires=requirements, extras_require={ ':python_version=="2.6" or python_version=="2.7"': ['ipaddress'] }, tests_require=['requests_mock>=0.5'], test_suite="tests", license=geoip2.__license__, classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'Intended Audience :: System Administrators', 'License :: OSI Approved :: Apache Software License', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python', 'Topic :: Internet :: Proxy Servers', 'Topic :: Internet', ], ) geoip2-2.7.0/setup.cfg0000664000175000017500000000026713230142214014417 0ustar greggreg00000000000000[aliases] build_html = build_sphinx -b html --build-dir docs sdist = build_html sdist release = sdist bdist_wheel upload [wheel] universal = 1 [egg_info] tag_build = tag_date = 0