lanscape 1.3.9__tar.gz → 1.4.0b1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of lanscape might be problematic. Click here for more details.

Files changed (86) hide show
  1. {lanscape-1.3.9/lanscape.egg-info → lanscape-1.4.0b1}/PKG-INFO +1 -1
  2. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/libraries/decorators.py +29 -3
  3. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/libraries/net_tools.py +10 -25
  4. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/libraries/version_manager.py +15 -18
  5. {lanscape-1.3.9 → lanscape-1.4.0b1/lanscape.egg-info}/PKG-INFO +1 -1
  6. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape.egg-info/SOURCES.txt +1 -0
  7. {lanscape-1.3.9 → lanscape-1.4.0b1}/pyproject.toml +1 -1
  8. lanscape-1.4.0b1/tests/test_decorators.py +29 -0
  9. {lanscape-1.3.9 → lanscape-1.4.0b1}/LICENSE +0 -0
  10. {lanscape-1.3.9 → lanscape-1.4.0b1}/MANIFEST.in +0 -0
  11. {lanscape-1.3.9 → lanscape-1.4.0b1}/README.md +0 -0
  12. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/__init__.py +0 -0
  13. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/__main__.py +0 -0
  14. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/libraries/__init__.py +0 -0
  15. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/libraries/app_scope.py +0 -0
  16. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/libraries/device_alive.py +0 -0
  17. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/libraries/errors.py +0 -0
  18. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/libraries/ip_parser.py +0 -0
  19. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/libraries/logger.py +0 -0
  20. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/libraries/mac_lookup.py +0 -0
  21. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/libraries/port_manager.py +0 -0
  22. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/libraries/runtime_args.py +0 -0
  23. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/libraries/scan_config.py +0 -0
  24. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/libraries/service_scan.py +0 -0
  25. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/libraries/subnet_scan.py +0 -0
  26. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/libraries/web_browser.py +0 -0
  27. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/resources/mac_addresses/convert_csv.py +0 -0
  28. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/resources/mac_addresses/mac_db.json +0 -0
  29. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/resources/ports/convert_csv.py +0 -0
  30. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/resources/ports/full.json +0 -0
  31. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/resources/ports/large.json +0 -0
  32. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/resources/ports/medium.json +0 -0
  33. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/resources/ports/small.json +0 -0
  34. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/resources/services/definitions.jsonc +0 -0
  35. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/__init__.py +0 -0
  36. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/app.py +0 -0
  37. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/blueprints/__init__.py +0 -0
  38. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/blueprints/api/__init__.py +0 -0
  39. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/blueprints/api/port.py +0 -0
  40. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/blueprints/api/scan.py +0 -0
  41. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/blueprints/api/tools.py +0 -0
  42. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/blueprints/web/__init__.py +0 -0
  43. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/blueprints/web/routes.py +0 -0
  44. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/main.py +0 -0
  45. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/shutdown_handler.py +0 -0
  46. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/css/style.css +0 -0
  47. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/img/ico/android-chrome-192x192.png +0 -0
  48. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/img/ico/android-chrome-512x512.png +0 -0
  49. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/img/ico/apple-touch-icon.png +0 -0
  50. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/img/ico/favicon-16x16.png +0 -0
  51. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/img/ico/favicon-32x32.png +0 -0
  52. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/img/ico/favicon.ico +0 -0
  53. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/img/ico/site.webmanifest +0 -0
  54. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/js/core.js +0 -0
  55. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/js/layout-sizing.js +0 -0
  56. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/js/main.js +0 -0
  57. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/js/on-tab-close.js +0 -0
  58. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/js/quietReload.js +0 -0
  59. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/js/scan-config.js +0 -0
  60. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/js/shutdown-server.js +0 -0
  61. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/js/subnet-info.js +0 -0
  62. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/js/subnet-selector.js +0 -0
  63. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/static/lanscape.webmanifest +0 -0
  64. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/templates/base.html +0 -0
  65. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/templates/core/head.html +0 -0
  66. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/templates/core/scripts.html +0 -0
  67. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/templates/error.html +0 -0
  68. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/templates/info.html +0 -0
  69. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/templates/main.html +0 -0
  70. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/templates/scan/config.html +0 -0
  71. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/templates/scan/export.html +0 -0
  72. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/templates/scan/ip-table-row.html +0 -0
  73. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/templates/scan/ip-table.html +0 -0
  74. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/templates/scan/overview.html +0 -0
  75. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/templates/scan/scan-error.html +0 -0
  76. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/templates/scan.html +0 -0
  77. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape/ui/templates/shutdown.html +0 -0
  78. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape.egg-info/dependency_links.txt +0 -0
  79. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape.egg-info/requires.txt +0 -0
  80. {lanscape-1.3.9 → lanscape-1.4.0b1}/lanscape.egg-info/top_level.txt +0 -0
  81. {lanscape-1.3.9 → lanscape-1.4.0b1}/setup.cfg +0 -0
  82. {lanscape-1.3.9 → lanscape-1.4.0b1}/tests/test_api.py +0 -0
  83. {lanscape-1.3.9 → lanscape-1.4.0b1}/tests/test_env.py +0 -0
  84. {lanscape-1.3.9 → lanscape-1.4.0b1}/tests/test_library.py +0 -0
  85. {lanscape-1.3.9 → lanscape-1.4.0b1}/tests/test_logging.py +0 -0
  86. {lanscape-1.3.9 → lanscape-1.4.0b1}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lanscape
3
- Version: 1.3.9
3
+ Version: 1.4.0b1
4
4
  Summary: A python based local network scanner
5
5
  Author-email: Michael Dennis <michael@dipduo.com>
6
6
  License-Expression: MIT
@@ -1,7 +1,5 @@
1
1
 
2
- """
3
- Decorators and job tracking utilities for Lanscape.
4
- """
2
+ """Decorators and job tracking utilities for Lanscape."""
5
3
 
6
4
  from time import time
7
5
  from dataclasses import dataclass, field
@@ -10,9 +8,37 @@ from collections import defaultdict
10
8
  import inspect
11
9
  import functools
12
10
  import concurrent.futures
11
+ import logging
13
12
  from tabulate import tabulate
14
13
 
15
14
 
15
+ log = logging.getLogger(__name__)
16
+
17
+
18
+ def run_once(func):
19
+ """Ensure a function executes only once and cache the result."""
20
+
21
+ cache_attr = "_run_once_cache"
22
+ ran_attr = "_run_once_ran"
23
+
24
+ @functools.wraps(func)
25
+ def wrapper(*args, **kwargs):
26
+ if getattr(wrapper, ran_attr, False):
27
+ return getattr(wrapper, cache_attr)
28
+
29
+ start = time()
30
+ result = func(*args, **kwargs)
31
+ elapsed = time() - start
32
+
33
+ setattr(wrapper, cache_attr, result)
34
+ setattr(wrapper, ran_attr, True)
35
+
36
+ log.debug("run_once executed %s in %.4fs", func.__qualname__, elapsed)
37
+ return result
38
+
39
+ return wrapper
40
+
41
+
16
42
  @dataclass
17
43
  class JobStats:
18
44
  """
@@ -18,7 +18,7 @@ from lanscape.libraries.service_scan import scan_service
18
18
  from lanscape.libraries.mac_lookup import MacLookup, get_macs
19
19
  from lanscape.libraries.ip_parser import get_address_count, MAX_IPS_ALLOWED
20
20
  from lanscape.libraries.errors import DeviceError
21
- from lanscape.libraries.decorators import job_tracker
21
+ from lanscape.libraries.decorators import job_tracker, run_once
22
22
 
23
23
  log = logging.getLogger('NetTools')
24
24
  mac_lookup = MacLookup()
@@ -459,32 +459,17 @@ def smart_select_primary_subnet(subnets: List[dict] = None) -> str:
459
459
  return selected.get("subnet", "")
460
460
 
461
461
 
462
- class ArpSupportChecker:
463
- """
464
- Singleton class to check if ARP requests are supported on the current system.
465
- The check is only performed once.
466
- """
467
- _supported = None
468
-
469
- @classmethod
470
- def is_supported(cls):
471
- """one time check if ARP requests are supported on this system"""
472
- if cls._supported is not None:
473
- return cls._supported
474
- try:
475
- arp_request = ARP(pdst='0.0.0.0')
476
- broadcast = Ether(dst="ff:ff:ff:ff:ff:ff")
477
- packet = broadcast / arp_request
478
- srp(packet, timeout=0, verbose=False)
479
- cls._supported = True
480
- except (Scapy_Exception, PermissionError, RuntimeError):
481
- cls._supported = False
482
- return cls._supported
483
-
484
-
462
+ @run_once
485
463
  def is_arp_supported():
486
464
  """
487
465
  Check if ARP requests are supported on the current system.
488
466
  Only runs the check once.
489
467
  """
490
- return ArpSupportChecker.is_supported()
468
+ try:
469
+ arp_request = ARP(pdst='0.0.0.0')
470
+ broadcast = Ether(dst="ff:ff:ff:ff:ff:ff")
471
+ packet = broadcast / arp_request
472
+ srp(packet, timeout=0, verbose=False)
473
+ return True
474
+ except (Scapy_Exception, PermissionError, RuntimeError):
475
+ return False
@@ -11,17 +11,14 @@ from random import randint
11
11
 
12
12
  import requests
13
13
 
14
- from .app_scope import is_local_run
14
+ from lanscape.libraries.app_scope import is_local_run
15
+ from lanscape.libraries.decorators import run_once
15
16
 
16
17
  log = logging.getLogger('VersionManager')
17
18
 
18
19
  PACKAGE = 'lanscape'
19
20
  LOCAL_VERSION = '0.0.0'
20
21
 
21
- # Used to cache PyPI version during runtime
22
- LATEST_VERSION = None
23
-
24
-
25
22
  def is_update_available(package=PACKAGE) -> bool:
26
23
  """
27
24
  Check if an update is available for the package.
@@ -49,6 +46,7 @@ def is_update_available(package=PACKAGE) -> bool:
49
46
  return installed != available
50
47
 
51
48
 
49
+ @run_once
52
50
  def lookup_latest_version(package=PACKAGE):
53
51
  """
54
52
  Retrieve the latest version of the package from PyPI.
@@ -62,19 +60,18 @@ def lookup_latest_version(package=PACKAGE):
62
60
  The latest version string from PyPI or None if retrieval fails
63
61
  """
64
62
  # Fetch the latest version from PyPI
65
- global LATEST_VERSION # pylint: disable=global-statement
66
- if not LATEST_VERSION:
67
- no_cache = f'?cachebust={randint(0, 6969)}'
68
- url = f"https://pypi.org/pypi/{package}/json{no_cache}"
69
- try:
70
- response = requests.get(url, timeout=5)
71
- response.raise_for_status() # Raise an exception for HTTP errors
72
- LATEST_VERSION = response.json()['info']['version']
73
- log.debug(f'Latest pypi version: {LATEST_VERSION}')
74
- except BaseException:
75
- log.debug(traceback.format_exc())
76
- log.warning('Unable to fetch package version from PyPi')
77
- return LATEST_VERSION
63
+ no_cache = f'?cachebust={randint(0, 6969)}'
64
+ url = f"https://pypi.org/pypi/{package}/json{no_cache}"
65
+ try:
66
+ response = requests.get(url, timeout=3)
67
+ response.raise_for_status() # Raise an exception for HTTP errors
68
+ latest_version = response.json()['info']['version']
69
+ log.debug(f'Latest pypi version: {latest_version}')
70
+ return latest_version
71
+ except BaseException:
72
+ log.debug(traceback.format_exc())
73
+ log.warning('Unable to fetch package version from PyPi')
74
+ return None
78
75
 
79
76
 
80
77
  def get_installed_version(package=PACKAGE):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lanscape
3
- Version: 1.3.9
3
+ Version: 1.4.0b1
4
4
  Summary: A python based local network scanner
5
5
  Author-email: Michael Dennis <michael@dipduo.com>
6
6
  License-Expression: MIT
@@ -77,6 +77,7 @@ lanscape/ui/templates/scan/ip-table.html
77
77
  lanscape/ui/templates/scan/overview.html
78
78
  lanscape/ui/templates/scan/scan-error.html
79
79
  tests/test_api.py
80
+ tests/test_decorators.py
80
81
  tests/test_env.py
81
82
  tests/test_library.py
82
83
  tests/test_logging.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "lanscape"
3
- version = "1.3.9"
3
+ version = "1.4.0b1"
4
4
  authors = [
5
5
  { name="Michael Dennis", email="michael@dipduo.com" },
6
6
  ]
@@ -0,0 +1,29 @@
1
+ """Tests for helper decorators used throughout the project."""
2
+
3
+ import logging
4
+
5
+ from lanscape.libraries.decorators import run_once
6
+
7
+
8
+ def test_run_once_caches_result_and_logs_once(caplog):
9
+ """run_once should execute only one time and cache the return value."""
10
+
11
+ caplog.set_level(logging.DEBUG)
12
+
13
+ call_count = {"count": 0}
14
+
15
+ @run_once
16
+ def sample_function(value):
17
+ call_count["count"] += 1
18
+ return value * 2
19
+
20
+ first = sample_function(3)
21
+ second = sample_function(5)
22
+
23
+ assert first == 6
24
+ assert second == 6
25
+ assert call_count["count"] == 1
26
+
27
+ messages = [record.message for record in caplog.records]
28
+ assert any("run_once executed" in record and "sample_function" in record for record in messages)
29
+ assert sum("run_once executed" in record for record in messages) == 1
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes