Skip to content

Commit bf1f649

Browse files
authored
Merge pull request #1 from bt-cryptomancer/ping
Ping function
2 parents 8e04438 + 154a69f commit bf1f649

6 files changed

Lines changed: 44 additions & 7 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
ping
2+
====
3+
4+
.. currentmodule:: privex.helpers.net
5+
6+
.. autofunction:: ping

docs/source/helpers/privex.helpers.net.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ privex.helpers.net
1616
ip_is_v4
1717
ip_is_v6
1818
ip_to_rdns
19-
19+
ping
2020

2121

2222

@@ -25,4 +25,4 @@ privex.helpers.net
2525

2626

2727

28-
28+

docs/source/helpers/tests/tests.TestGeneral.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ TestGeneral
8181
~TestGeneral.test_async_decorator
8282
~TestGeneral.test_async_decorator_return
8383
~TestGeneral.test_chunked
84+
~TestGeneral.test_ping
8485
~TestGeneral.test_retry_on_err
8586
~TestGeneral.test_retry_on_err_return
8687
~TestGeneral.test_run_sync
@@ -102,4 +103,4 @@ TestGeneral
102103
~TestGeneral.maxDiff
103104
~TestGeneral.truthy
104105

105-
106+

privex/helpers/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def _setup_logging(level=logging.WARNING):
6464
log = _setup_logging()
6565
name = 'helpers'
6666

67-
VERSION = '1.3.3'
67+
VERSION = '1.3.4'
6868

6969

7070
class ImproperlyConfigured(Exception):

privex/helpers/net.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
3939
"""
4040
import logging
41+
import subprocess
4142
from privex.helpers.exceptions import BoundaryException
4243
from ipaddress import ip_address, IPv4Address, IPv6Address
4344
from typing import Union
@@ -212,3 +213,18 @@ def ip_is_v6(ip: str) -> bool:
212213
:return bool: True if IPv6, False if not (i.e. probably IPv4)
213214
"""
214215
return type(ip_address(ip)) == IPv6Address
216+
217+
def ping(ip: str, timeout: int = 30) -> bool:
218+
"""
219+
Sends a ping to a given IP
220+
221+
:param str ip: An IP address as a string, e.g. 192.168.1.1
222+
:param int timeout: Number of seconds to wait for a response from the ping before timing out
223+
:raises ValueError: When the given IP address ``ip`` is invalid or ``timeout`` < 1
224+
:return bool: True if ping got a response from the given IP, False if not
225+
"""
226+
ip_obj = ip_address(ip) # verify IP is valid (this will throw if it isn't)
227+
if timeout < 1:
228+
raise ValueError('timeout value cannot be less than 1 second')
229+
with subprocess.Popen(["/bin/ping", "-c1", "-w{}".format(timeout), ip], stdout=subprocess.PIPE) as proc:
230+
return 'bytes from {}'.format(ip) in proc.stdout.read().decode('utf-8')

tests.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282

8383
from privex import helpers
8484
from privex.loghelper import LogHelper
85-
from privex.helpers import ip_to_rdns, BoundaryException, plugin, r_cache, random_str, CacheAdapter, env_bool
85+
from privex.helpers import ping, ip_to_rdns, BoundaryException, plugin, r_cache, random_str, CacheAdapter, env_bool
8686

8787
if env_bool('DEBUG', False) is True:
8888
LogHelper('privex.helpers', level=logging.DEBUG).add_console_handler(logging.DEBUG)
@@ -426,7 +426,7 @@ class TestCacheDecoratorRedis(TestCacheDecoratorMemory):
426426
@classmethod
427427
def setUpClass(cls):
428428
if not plugin.HAS_REDIS:
429-
print('The package "redis" is not installed, skipping Redis dependent tests.')
429+
print(f'The package "redis" is not installed, skipping Redis dependent tests ({cls.__name__}).')
430430
return cls.tearDownClass()
431431
helpers.cache.adapter_set(helpers.RedisCache())
432432

@@ -437,6 +437,17 @@ class TestGeneral(PrivexBaseCase):
437437
def setUp(self):
438438
self.tries = 0
439439

440+
def test_ping(self):
441+
"""Test success & failure cases for ping function, as well as input validation"""
442+
with self.assertRaises(ValueError):
443+
ping('127.0.0.1', -1)
444+
with self.assertRaises(ValueError):
445+
ping('127.0.0.1', 0)
446+
with self.assertRaises(ValueError):
447+
ping('notavalidip', 1)
448+
self.assertTrue(ping('127.0.0.1', 3))
449+
self.assertFalse(ping('192.0.2.0', 3))
450+
440451
def test_chunked(self):
441452
"""Create a 20 element long list, split it into 4 chunks, and verify the chunks are correctly made"""
442453
x = list(range(0, 20))
@@ -602,6 +613,9 @@ class TestRedisCache(TestMemoryCache):
602613
@classmethod
603614
def setUpClass(cls):
604615
"""Set the current cache adapter to an instance of RedisCache() and make it available through ``self.cache``"""
616+
if not plugin.HAS_REDIS:
617+
print(f'The package "redis" is not installed, skipping Redis dependent tests ({cls.__name__}).')
618+
return cls.tearDownClass()
605619
helpers.cache.adapter_set(helpers.RedisCache())
606620
cls.cache = helpers.cache
607621

@@ -642,4 +656,4 @@ def setUpClass(cls):
642656
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
643657
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
644658
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
645-
"""
659+
"""

0 commit comments

Comments
 (0)