Skip to content

Commit

Permalink
Merge branch 'requests_dependency'
Browse files Browse the repository at this point in the history
  • Loading branch information
Pablo O Vieira committed Apr 25, 2015
2 parents 378341a + c3b7272 commit 8a68532
Show file tree
Hide file tree
Showing 15 changed files with 289 additions and 185 deletions.
13 changes: 13 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# .coveragerc to control coverage.py
[run]
branch = True

[report]
# Regexes for lines to exclude from consideration
exclude_lines =
# Have to re-enable the standard pragma
pragma: no cover

# Don't complain if non-runnable code isn't run:
if 0:
if __name__ == .__main__.:
13 changes: 10 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
*.pyc
*.py[co]

# packages
build
dist
*egg-info
.eggs
*.egg-info
*.egg

# tests/coverage
.tox
.coverage

# IDE/SO files
*~
.DS_Store
.idea
.project
.pydevproject
.settings

31 changes: 16 additions & 15 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,25 @@ before_install:

language: python

python:
- 2.7
- 3.3
- 3.4
- pypy
- pypy3

matrix:
allow_failures:
- python: pypy
- python: pypy3
fast_finish: true
env:
- TOXENV=py26
- TOXENV=py27
- TOXENV=py32
- TOXENV=py33
- TOXENV=py34
- TOXENV=pypy
- TOXENV=pypy3
- TOXENV=pep8

install:
- pip install coveralls
- pip install tox coveralls

script:
- coverage run --source=noipy setup.py test
script:
- tox

after_success:
- coveralls

notifications:
email:
on_success: never
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
Changelog
=========

1.4.0 (2015-04-25)
------------------

- Using the awesome `Requests HTTP library <https://github.com/kennethreitz/requests>`_
- Using `tox <http://tox.readthedocs.org/en/latest/>`_ in order to ease test against multiple Python versions

1.3.1 (2014-12-19)
------------------

Expand Down
33 changes: 31 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ To install **noipy**, simply:
$ pip install noipy
**Note**: **noipy** will also install the `Requests HTTP library <https://github.com/kennethreitz/requests>`_ if you haven't yet.


Usage
-----
Expand Down Expand Up @@ -124,15 +126,42 @@ If you have any enhancement suggestions or find a bug, please:

#. Open an `issue <https://github.com/povieira/noipy/issues>`_
#. `Fork <https://github.com/povieira/noipy/fork>`_ the project
#. Do your magic (+ `PEP8 <https://www.python.org/dev/peps/pep-0008/>`_ + test)
#. Do your magic
#. Please, `PEP8 <https://www.python.org/dev/peps/pep-0008/>`_ and test your code
#. Is everything working? Send a `pull request <https://github.com/povieira/noipy/pulls>`_

Running tests
~~~~~~~~~~~~~

First, install tests dependencies (`tox <http://tox.readthedocs.org/en/latest/>`_
and `flake8 <https://flake8.readthedocs.org/>`_):

.. code-block:: bash
$ pip install -r dev-requirements.txt
To test against all supported Python versions (if you have them installed):

.. code-block:: bash
$ tox
Or you can to test against a specific version:

.. code-block:: bash
$ tox -e {version}
Where ``{version}`` can be ``py26``, ``py27``, ``py33``, ``py34``, ``pypy`` and ``pypy3``.


Don't forget to run ``pep8``:

.. code-block:: bash
$ python setup.py test
$ tox -e pep8
Copyright & License
Expand Down
3 changes: 3 additions & 0 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
flake8>=2.3
tox>=1.8.1
requests>=2.0
2 changes: 1 addition & 1 deletion noipy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"""

__title__ = "noipy"
__version_info__ = ('1', '3', '1')
__version_info__ = ('1', '4', '0')
__version__ = ".".join(__version_info__)
__author__ = "Pablo O Vieira"
__email__ = "[email protected]"
Expand Down
8 changes: 4 additions & 4 deletions noipy/authinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import base64

NOIPY_CONFIG = ".noipy"
DEFAULT_CONFIG_LOCATION = os.path.expanduser("~")
DEFAULT_CONFIG_DIR = os.path.expanduser("~")


class ApiAuth(object):
Expand Down Expand Up @@ -50,7 +50,7 @@ def __eq__(self, other):
return str(self) == str(other)


def store(auth, provider, config_location=DEFAULT_CONFIG_LOCATION):
def store(auth, provider, config_location=DEFAULT_CONFIG_DIR):
"""Store auth info in file for specified provider """

auth_file = None
Expand Down Expand Up @@ -85,7 +85,7 @@ def store(auth, provider, config_location=DEFAULT_CONFIG_LOCATION):
raise e


def load(provider, config_location=DEFAULT_CONFIG_LOCATION):
def load(provider, config_location=DEFAULT_CONFIG_DIR):
"""Load provider specific auth info from file """

auth = None
Expand All @@ -105,7 +105,7 @@ def load(provider, config_location=DEFAULT_CONFIG_LOCATION):
return auth


def exists(provider, config_location=DEFAULT_CONFIG_LOCATION):
def exists(provider, config_location=DEFAULT_CONFIG_DIR):
"""Check whether provider info is already stored """

config_dir = os.path.join(config_location, NOIPY_CONFIG)
Expand Down
92 changes: 42 additions & 50 deletions noipy/dnsupdater.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,10 @@

from __future__ import print_function

try:
import urllib.request as urllib2
except ImportError:
import urllib2

import re

import requests

AVAILABLE_PLUGINS = {
'noip': 'NoipDnsUpdater',
'dyn': 'DynDnsUpdater',
Expand All @@ -24,6 +21,27 @@
DEFAULT_PLUGIN = 'generic'


error_messages = {
'badauth': "ERROR: Invalid username or password (badauth).",
'nochg': "ERROR: Invalid username or password (nochg).",
'401': "ERROR: Invalid username or password (401).",
'403': "ERROR: Invalid username or password (403).",
'!donator': "ERROR: Update request include a feature that is not "
"available to informed user.",
'notfqdn': "ERROR: The hostname specified is not a fully-qualified domain"
" name (not in the form hostname.dyndns.org or domain.com).",
'nohost': "ERROR: Hostname specified does not exist in this user account.",
'numhost': "ERROR: Too many hosts (more than 20) specified in an update. "
"Also returned if trying to update a round robin (which is "
"not allowed).",
'abuse': "ERROR: Username/hostname is blocked due to update abuse.",
'badagent': "ERROR: User agent not sent or HTTP method not permitted.",
'dnserr': "ERROR: DNS error encountered.",
'911': "ERROR: Problem on server side. Retry update in a few minutes.",
'KO': "ERROR: Hostname and/or token incorrect.",
}


class DnsUpdaterPlugin(object):
""" Base class for any DDNS updater
"""
Expand All @@ -37,7 +55,7 @@ def __init__(self, auth, hostname, options=None):
self._auth = auth
self._hostname = hostname
self._options = {} if options is None else options
self.last_status_code = ''
self.last_ddns_response = ""

@property
def auth(self):
Expand All @@ -61,71 +79,45 @@ def update_dns(self, new_ip):
"""Call No-IP API based on dict login_info and return the status code.
"""

headers = None
if self.auth_type == 'T':
api_call_url = self._get_base_url().format(hostname=self.hostname,
token=self.auth.token,
ip=new_ip)
request = urllib2.Request(api_call_url)
else:
api_call_url = self._get_base_url().format(hostname=self.hostname,
ip=new_ip)
request = urllib2.Request(api_call_url)
request.add_header('Authorization', 'Basic %s' %
self.auth.base64key.decode('utf-8'))
headers = {
'Authorization': 'Basic %s' %
self.auth.base64key.decode('utf-8'),
}

r = requests.get(api_call_url, headers=headers)
self.last_ddns_response = str(r.text)

try:
response = urllib2.urlopen(request)
self.last_status_code = response.read().decode('utf-8')
except urllib2.HTTPError as e:
self.last_status_code = str(e.code)
return r.status_code, r.text

@property
def status_message(self):
"""Return friendly response from API based on response code. """

msg = None
if self.last_status_code in ['badauth', 'nochg', '401', '403']:
msg = "ERROR: Invalid username or password (%s)." % \
self.last_status_code
elif 'good' in self.last_status_code \
or 'nochg' in self.last_status_code:
ip = re.search(r'(\d{1,3}\.?){4}', self.last_status_code).group()
if 'good' in self.last_status_code:
if self.last_ddns_response in error_messages.keys():
msg = error_messages.get(self.last_ddns_response)
elif self.last_ddns_response == 'OK':
msg = "SUCCESS: DNS hostname successfully updated."
elif 'good' in self.last_ddns_response \
or 'nochg' in self.last_ddns_response:
ip = re.search(r'(\d{1,3}\.?){4}', self.last_ddns_response).group()
if 'good' in self.last_ddns_response:
msg = "SUCCESS: DNS hostname IP (%s) successfully updated." % \
ip
else:
msg = "SUCCESS: IP address (%s) is up to date, nothing was " \
"changed. Additional 'nochg' updates may be considered" \
" abusive." % ip
elif self.last_status_code == '!donator':
msg = "ERROR: Update request include a feature that is not " \
"available to informed user."
elif self.last_status_code == 'notfqdn':
msg = "ERROR: The hostname specified is not a fully-qualified " \
"domain name (not in the form hostname.dyndns.org or " \
"domain.com)."
elif self.last_status_code == 'nohost':
msg = "ERROR: Hostname specified does not exist in this user " \
"account."
elif self.last_status_code == 'numhost':
msg = "ERROR: Too many hosts (more than 20) specified in an " \
"update. Also returned if trying to update a round robin " \
"(which is not allowed)."
elif self.last_status_code == 'abuse':
msg = "ERROR: Username/hostname is blocked due to update abuse."
elif self.last_status_code == 'badagent':
msg = "ERROR: User agent not sent or HTTP method not permitted."
elif self.last_status_code == 'dnserr':
msg = "ERROR: DNS error encountered."
elif self.last_status_code == '911':
msg = "ERROR: Problem on server side. Retry update in a few " \
"minutes."
elif self.last_status_code == 'OK':
msg = "SUCCESS: DNS hostname successfully updated."
elif self.last_status_code == 'KO':
msg = "ERROR: Hostname and/or token incorrect."
else:
msg = "WARNING: Ooops! Something went wrong !!!"
msg = "ERROR: Ooops! Something went wrong !!!"

return msg

Expand Down
Loading

0 comments on commit 8a68532

Please sign in to comment.