lanscape 1.5.0__py3-none-any.whl → 2.0.0a1__py3-none-any.whl

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.
Files changed (36) hide show
  1. lanscape/__init__.py +5 -4
  2. lanscape/__main__.py +1 -0
  3. lanscape/{libraries → core}/app_scope.py +1 -0
  4. lanscape/{libraries → core}/decorators.py +85 -51
  5. lanscape/{libraries → core}/device_alive.py +4 -3
  6. lanscape/{libraries → core}/errors.py +1 -0
  7. lanscape/{libraries → core}/ip_parser.py +2 -1
  8. lanscape/{libraries → core}/logger.py +1 -0
  9. lanscape/{libraries → core}/mac_lookup.py +1 -0
  10. lanscape/{libraries → core}/net_tools.py +7 -6
  11. lanscape/{libraries → core}/port_manager.py +1 -0
  12. lanscape/{libraries → core}/runtime_args.py +1 -0
  13. lanscape/{libraries → core}/scan_config.py +3 -2
  14. lanscape/{libraries → core}/service_scan.py +3 -2
  15. lanscape/{libraries → core}/subnet_scan.py +6 -5
  16. lanscape/{libraries → core}/version_manager.py +3 -2
  17. lanscape/{libraries → core}/web_browser.py +1 -0
  18. lanscape/resources/mac_addresses/convert_csv.py +1 -0
  19. lanscape/resources/ports/convert_csv.py +1 -0
  20. lanscape/ui/app.py +5 -4
  21. lanscape/ui/blueprints/__init__.py +2 -1
  22. lanscape/ui/blueprints/api/__init__.py +1 -0
  23. lanscape/ui/blueprints/api/port.py +2 -1
  24. lanscape/ui/blueprints/api/scan.py +2 -1
  25. lanscape/ui/blueprints/api/tools.py +5 -4
  26. lanscape/ui/blueprints/web/__init__.py +1 -0
  27. lanscape/ui/blueprints/web/routes.py +2 -1
  28. lanscape/ui/main.py +5 -4
  29. lanscape/ui/shutdown_handler.py +2 -1
  30. {lanscape-1.5.0.dist-info → lanscape-2.0.0a1.dist-info}/METADATA +7 -2
  31. {lanscape-1.5.0.dist-info → lanscape-2.0.0a1.dist-info}/RECORD +36 -35
  32. lanscape-2.0.0a1.dist-info/entry_points.txt +2 -0
  33. /lanscape/{libraries → core}/__init__.py +0 -0
  34. {lanscape-1.5.0.dist-info → lanscape-2.0.0a1.dist-info}/WHEEL +0 -0
  35. {lanscape-1.5.0.dist-info → lanscape-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
  36. {lanscape-1.5.0.dist-info → lanscape-2.0.0a1.dist-info}/top_level.txt +0 -0
lanscape/__init__.py CHANGED
@@ -1,13 +1,13 @@
1
1
  """
2
2
  Local network scanner
3
3
  """
4
- from lanscape.libraries.subnet_scan import (
4
+ from lanscape.core.subnet_scan import (
5
5
  SubnetScanner,
6
6
  ScannerResults,
7
7
  ScanManager
8
8
  )
9
9
 
10
- from lanscape.libraries.scan_config import (
10
+ from lanscape.core.scan_config import (
11
11
  ScanConfig,
12
12
  ArpConfig,
13
13
  PingConfig,
@@ -19,6 +19,7 @@ from lanscape.libraries.scan_config import (
19
19
  ScanType
20
20
  )
21
21
 
22
- from lanscape.libraries.port_manager import PortManager
22
+ from lanscape.core.port_manager import PortManager
23
+
24
+ from lanscape.core import net_tools
23
25
 
24
- from lanscape.libraries import net_tools
lanscape/__main__.py CHANGED
@@ -7,3 +7,4 @@ from lanscape.ui.main import main
7
7
 
8
8
  if __name__ == "__main__":
9
9
  main()
10
+
@@ -90,3 +90,4 @@ def is_local_run() -> bool:
90
90
  if any(parts):
91
91
  return False
92
92
  return True # Installed package
93
+
@@ -2,13 +2,11 @@
2
2
  """Decorators and job tracking utilities for Lanscape."""
3
3
 
4
4
  from time import time
5
- from dataclasses import dataclass, field
6
- from typing import DefaultDict
7
5
  from collections import defaultdict
8
- import inspect
9
6
  import functools
10
7
  import concurrent.futures
11
8
  import logging
9
+ import threading
12
10
  from tabulate import tabulate
13
11
 
14
12
 
@@ -39,31 +37,74 @@ def run_once(func):
39
37
  return wrapper
40
38
 
41
39
 
42
- @dataclass
43
40
  class JobStats:
44
41
  """
42
+ Thread-safe singleton for tracking job statistics across all classes.
45
43
  Tracks statistics for job execution, including running, finished, and timing data.
46
44
  """
47
- running: DefaultDict[str, int] = field(
48
- default_factory=lambda: defaultdict(int))
49
- finished: DefaultDict[str, int] = field(
50
- default_factory=lambda: defaultdict(int))
51
- timing: DefaultDict[str, float] = field(
52
- default_factory=lambda: defaultdict(float))
53
45
 
54
46
  _instance = None
47
+ _lock = threading.Lock()
48
+
49
+ def __new__(cls):
50
+ if cls._instance is None:
51
+ with cls._lock:
52
+ if cls._instance is None: # Double-checked locking
53
+ cls._instance = super().__new__(cls)
54
+ return cls._instance
55
55
 
56
56
  def __init__(self):
57
- # Only initialize once
58
- if not hasattr(self, "running"):
57
+ if not hasattr(self, '_initialized'):
58
+ self._stats_lock = threading.RLock()
59
59
  self.running = defaultdict(int)
60
60
  self.finished = defaultdict(int)
61
61
  self.timing = defaultdict(float)
62
-
63
- def __new__(cls, *args, **kwargs):
64
- if cls._instance is None:
65
- cls._instance = super(JobStats, cls).__new__(cls)
66
- return cls._instance
62
+ self._initialized = True
63
+
64
+ def start_job(self, func_name: str):
65
+ """Thread-safe increment of running counter."""
66
+ with self._stats_lock:
67
+ self.running[func_name] += 1
68
+
69
+ def finish_job(self, func_name: str, elapsed_time: float):
70
+ """Thread-safe update of job completion and timing."""
71
+ with self._stats_lock:
72
+ self.running[func_name] -= 1
73
+ self.finished[func_name] += 1
74
+
75
+ # Calculate running average
76
+ count = self.finished[func_name]
77
+ old_avg = self.timing[func_name]
78
+ new_avg = (old_avg * (count - 1) + elapsed_time) / count
79
+ self.timing[func_name] = round(new_avg, 4)
80
+
81
+ # Cleanup running if zero
82
+ if self.running[func_name] <= 0:
83
+ self.running.pop(func_name, None)
84
+
85
+ def clear_stats(self):
86
+ """Clear all statistics (useful between scans)."""
87
+ with self._stats_lock:
88
+ self.running.clear()
89
+ self.finished.clear()
90
+ self.timing.clear()
91
+
92
+ def get_stats_copy(self) -> dict:
93
+ """Get a thread-safe copy of current statistics."""
94
+ with self._stats_lock:
95
+ return {
96
+ 'running': dict(self.running),
97
+ 'finished': dict(self.finished),
98
+ 'timing': dict(self.timing)
99
+ }
100
+
101
+ @classmethod
102
+ def reset_for_testing(cls):
103
+ """Reset singleton instance for testing purposes only."""
104
+ with cls._lock:
105
+ if cls._instance:
106
+ cls._instance.clear_stats()
107
+ cls._instance = None
67
108
 
68
109
  def __str__(self):
69
110
  """Return a formatted string representation of the job statistics."""
@@ -106,48 +147,40 @@ def job_tracker(func):
106
147
  Return the function name with the class name prepended if available.
107
148
  """
108
149
  qual_parts = func.__qualname__.split(".")
109
- cls_name = qual_parts[-2] if len(qual_parts) > 1 else None
110
- cls_obj = None # resolved lazily
111
- if cls_obj is None and cls_name:
112
- mod = inspect.getmodule(func)
113
- cls_obj = getattr(mod, cls_name, None)
114
- if cls_obj and first_arg is not None:
115
- if (first_arg is cls_obj or isinstance(first_arg, cls_obj)):
116
- return f"{cls_name}.{func.__name__}"
150
+
151
+ # If function has class context (e.g., "ClassName.method_name")
152
+ if len(qual_parts) > 1:
153
+ cls_name = qual_parts[-2]
154
+
155
+ # Check if first_arg is an instance and has the expected class name
156
+ if first_arg is not None and hasattr(first_arg, '__class__'):
157
+ if first_arg.__class__.__name__ == cls_name:
158
+ return f"{cls_name}.{func.__name__}"
159
+
117
160
  return func.__name__
118
161
 
162
+ @functools.wraps(func)
119
163
  def wrapper(*args, **kwargs):
120
164
  """Wrap the function to update job statistics before and after execution."""
121
- class_instance = args[0]
122
165
  job_stats = JobStats()
123
- fxn = get_fxn_src_name(
124
- func,
125
- class_instance
126
- )
127
-
128
- # Increment running counter and track execution time
129
- job_stats.running[fxn] += 1
130
- start = time()
131
166
 
132
- result = func(*args, **kwargs) # Execute the wrapped function
167
+ # Determine function name for tracking
168
+ if args:
169
+ fxn = get_fxn_src_name(func, args[0])
170
+ else:
171
+ fxn = func.__name__
133
172
 
134
- # Update statistics after function execution
135
- elapsed = time() - start
136
- job_stats.running[fxn] -= 1
137
- job_stats.finished[fxn] += 1
138
-
139
- # Calculate the new average timing for the function
140
- job_stats.timing[fxn] = round(
141
- ((job_stats.finished[fxn] - 1) * job_stats.timing[fxn] + elapsed)
142
- / job_stats.finished[fxn],
143
- 4
144
- )
145
-
146
- # Clean up if no more running instances of this function
147
- if job_stats.running[fxn] == 0:
148
- job_stats.running.pop(fxn)
173
+ # Start job tracking
174
+ job_stats.start_job(fxn)
175
+ start = time()
149
176
 
150
- return result
177
+ try:
178
+ result = func(*args, **kwargs) # Execute the wrapped function
179
+ return result
180
+ finally:
181
+ # Always update statistics, even if function raises exception
182
+ elapsed = time() - start
183
+ job_stats.finish_job(fxn, elapsed)
151
184
 
152
185
  return wrapper
153
186
 
@@ -196,3 +229,4 @@ def timeout_enforcer(timeout: int, raise_on_timeout: bool = True):
196
229
  return None # Return None if not raising an exception
197
230
  return wrapper
198
231
  return decorator
232
+
@@ -13,12 +13,12 @@ from scapy.sendrecv import srp
13
13
  from scapy.layers.l2 import ARP, Ether
14
14
  from icmplib import ping
15
15
 
16
- from lanscape.libraries.net_tools import Device
17
- from lanscape.libraries.scan_config import (
16
+ from lanscape.core.net_tools import Device
17
+ from lanscape.core.scan_config import (
18
18
  ScanConfig, ScanType, PingConfig,
19
19
  ArpConfig, PokeConfig, ArpCacheConfig
20
20
  )
21
- from lanscape.libraries.decorators import timeout_enforcer, job_tracker
21
+ from lanscape.core.decorators import timeout_enforcer, job_tracker
22
22
 
23
23
 
24
24
  def is_device_alive(device: Device, scan_config: ScanConfig) -> bool:
@@ -227,3 +227,4 @@ class Poker():
227
227
  sock.close()
228
228
 
229
229
  do_poke()
230
+
@@ -40,3 +40,4 @@ class DeviceError(Exception):
40
40
 
41
41
  def __str__(self):
42
42
  return f'Error(source={self.method}, msg={self.base})'
43
+
@@ -12,7 +12,7 @@ It also includes validation to prevent processing excessively large IP ranges.
12
12
  import ipaddress
13
13
  import re
14
14
 
15
- from lanscape.libraries.errors import SubnetTooLargeError
15
+ from lanscape.core.errors import SubnetTooLargeError
16
16
 
17
17
  MAX_IPS_ALLOWED = 100000
18
18
 
@@ -139,3 +139,4 @@ def ip_range_to_list(start_ip, end_ip):
139
139
  # Yield the range of IPs
140
140
  for ip_int in range(int(start_ip), int(end_ip) + 1):
141
141
  yield ipaddress.IPv4Address(ip_int)
142
+
@@ -72,3 +72,4 @@ def disable_flask_logging() -> None:
72
72
  werkzeug_log.setLevel(logging.ERROR)
73
73
 
74
74
  override_click_logging()
75
+
@@ -105,3 +105,4 @@ def lookup_mac(mac: str) -> Optional[str]:
105
105
  def get_macs(ip: str) -> List[str]:
106
106
  """Backward compatibility function for MAC resolution."""
107
107
  return MacResolver().get_macs(ip)
108
+
@@ -29,12 +29,12 @@ else:
29
29
  COMPUTED_FIELD = computed_field # pylint: disable=invalid-name
30
30
  MODEL_SERIALIZER = model_serializer # pylint: disable=invalid-name
31
31
 
32
- from lanscape.libraries.service_scan import scan_service
33
- from lanscape.libraries.mac_lookup import MacLookup, get_macs
34
- from lanscape.libraries.ip_parser import get_address_count, MAX_IPS_ALLOWED
35
- from lanscape.libraries.errors import DeviceError
36
- from lanscape.libraries.decorators import job_tracker, run_once, timeout_enforcer
37
- from lanscape.libraries.scan_config import ServiceScanConfig, PortScanConfig
32
+ from lanscape.core.service_scan import scan_service
33
+ from lanscape.core.mac_lookup import MacLookup, get_macs
34
+ from lanscape.core.ip_parser import get_address_count, MAX_IPS_ALLOWED
35
+ from lanscape.core.errors import DeviceError
36
+ from lanscape.core.decorators import job_tracker, run_once, timeout_enforcer
37
+ from lanscape.core.scan_config import ServiceScanConfig, PortScanConfig
38
38
 
39
39
  log = logging.getLogger('NetTools')
40
40
  mac_lookup = MacLookup()
@@ -566,3 +566,4 @@ def is_arp_supported():
566
566
  return True
567
567
  except (Scapy_Exception, PermissionError, RuntimeError):
568
568
  return False
569
+
@@ -148,3 +148,4 @@ class PortManager:
148
148
  return True
149
149
  except BaseException:
150
150
  return False
151
+
@@ -63,3 +63,4 @@ def parse_args() -> RuntimeArgs:
63
63
 
64
64
  # Return the dataclass instance with the dynamically assigned values
65
65
  return RuntimeArgs(**filtered_args)
66
+
@@ -11,8 +11,8 @@ from enum import Enum
11
11
 
12
12
  from pydantic import BaseModel, Field
13
13
 
14
- from lanscape.libraries.port_manager import PortManager
15
- from lanscape.libraries.ip_parser import parse_ip_input
14
+ from lanscape.core.port_manager import PortManager
15
+ from lanscape.core.ip_parser import parse_ip_input
16
16
 
17
17
 
18
18
  class PingConfig(BaseModel):
@@ -395,3 +395,4 @@ DEFAULT_CONFIGS: Dict[str, ScanConfig] = {
395
395
  )
396
396
  )
397
397
  }
398
+
@@ -7,8 +7,8 @@ import asyncio
7
7
  import logging
8
8
  import traceback
9
9
 
10
- from lanscape.libraries.app_scope import ResourceManager
11
- from lanscape.libraries.scan_config import ServiceScanConfig, ServiceScanStrategy
10
+ from lanscape.core.app_scope import ResourceManager
11
+ from lanscape.core.scan_config import ServiceScanConfig, ServiceScanStrategy
12
12
 
13
13
  log = logging.getLogger('ServiceScan')
14
14
  SERVICES = ResourceManager('services').get_jsonc('definitions.jsonc')
@@ -202,3 +202,4 @@ def asyncio_logger_suppression():
202
202
 
203
203
 
204
204
  asyncio_logger_suppression()
205
+
@@ -20,11 +20,11 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
20
20
  from tabulate import tabulate
21
21
 
22
22
  # Local imports
23
- from lanscape.libraries.scan_config import ScanConfig
24
- from lanscape.libraries.decorators import job_tracker, terminator, JobStats
25
- from lanscape.libraries.net_tools import Device
26
- from lanscape.libraries.errors import SubnetScanTerminationFailure
27
- from lanscape.libraries.device_alive import is_device_alive
23
+ from lanscape.core.scan_config import ScanConfig
24
+ from lanscape.core.decorators import job_tracker, terminator, JobStats
25
+ from lanscape.core.net_tools import Device
26
+ from lanscape.core.errors import SubnetScanTerminationFailure
27
+ from lanscape.core.device_alive import is_device_alive
28
28
 
29
29
 
30
30
  class SubnetScanner():
@@ -428,3 +428,4 @@ class ScanManager:
428
428
  t = threading.Thread(target=scan.start)
429
429
  t.start()
430
430
  return t
431
+
@@ -11,8 +11,8 @@ from random import randint
11
11
 
12
12
  import requests
13
13
 
14
- from lanscape.libraries.app_scope import is_local_run
15
- from lanscape.libraries.decorators import run_once
14
+ from lanscape.core.app_scope import is_local_run
15
+ from lanscape.core.decorators import run_once
16
16
 
17
17
  log = logging.getLogger('VersionManager')
18
18
 
@@ -95,3 +95,4 @@ def get_installed_version(package=PACKAGE):
95
95
  log.debug(traceback.format_exc())
96
96
  log.warning(f'Cannot find {package} installation')
97
97
  return LOCAL_VERSION
98
+
@@ -208,3 +208,4 @@ def windows_get_browser_from_registry() -> Optional[str]:
208
208
  system_browser = get_system_default_browser()
209
209
  if system_browser:
210
210
  return extract_executable(system_browser)
211
+
@@ -39,3 +39,4 @@ def csv_to_dict(data):
39
39
 
40
40
 
41
41
  main()
42
+
@@ -38,3 +38,4 @@ def csv_to_dict(data):
38
38
 
39
39
 
40
40
  main()
41
+
lanscape/ui/app.py CHANGED
@@ -8,12 +8,12 @@ import logging
8
8
  from flask import Flask, render_template
9
9
  from lanscape.ui.blueprints.web import web_bp, routes # pylint: disable=unused-import
10
10
  from lanscape.ui.blueprints.api import api_bp, tools, port, scan # pylint: disable=unused-import
11
- from lanscape.libraries.runtime_args import RuntimeArgs, parse_args
12
- from lanscape.libraries.version_manager import (
11
+ from lanscape.core.runtime_args import RuntimeArgs, parse_args
12
+ from lanscape.core.version_manager import (
13
13
  is_update_available, get_installed_version, lookup_latest_version
14
14
  )
15
- from lanscape.libraries.app_scope import is_local_run
16
- from lanscape.libraries.net_tools import is_arp_supported
15
+ from lanscape.core.app_scope import is_local_run
16
+ from lanscape.core.net_tools import is_arp_supported
17
17
  from lanscape.ui.shutdown_handler import FlaskShutdownHandler
18
18
 
19
19
  app = Flask(
@@ -122,3 +122,4 @@ def start_webserver(args: RuntimeArgs) -> int:
122
122
  'use_reloader': args.reloader
123
123
  }
124
124
  app.run(**run_args)
125
+
@@ -1,10 +1,11 @@
1
1
  """Source for all things blueprint related in LANscape UI"""
2
2
  import logging
3
3
 
4
- from lanscape.libraries.subnet_scan import ScanManager
4
+ from lanscape.core.subnet_scan import ScanManager
5
5
 
6
6
  # defining here so blueprints can access the same
7
7
  # manager instance
8
8
  scan_manager = ScanManager()
9
9
 
10
10
  log = logging.getLogger('Blueprints')
11
+
@@ -3,3 +3,4 @@
3
3
  from flask import Blueprint
4
4
 
5
5
  api_bp = Blueprint('api', __name__)
6
+
@@ -4,7 +4,7 @@ Provides CRUD operations for managing port lists used in network scans.
4
4
  """
5
5
  from flask import request, jsonify
6
6
  from lanscape.ui.blueprints.api import api_bp
7
- from lanscape.libraries.port_manager import PortManager
7
+ from lanscape.core.port_manager import PortManager
8
8
 
9
9
  # Port Manager API
10
10
  ############################################
@@ -77,3 +77,4 @@ def delete_port_list(port_list):
77
77
  JSON response indicating success or failure
78
78
  """
79
79
  return jsonify(PortManager().delete_port_list(port_list))
80
+
@@ -9,7 +9,7 @@ import traceback
9
9
  from flask import request, jsonify
10
10
 
11
11
  from lanscape.ui.blueprints.api import api_bp
12
- from lanscape.libraries.subnet_scan import ScanConfig
12
+ from lanscape.core.subnet_scan import ScanConfig
13
13
  from lanscape.ui.blueprints import scan_manager
14
14
 
15
15
  # Subnet Scanner API
@@ -121,3 +121,4 @@ def get_scan_config():
121
121
  """
122
122
  data = request.get_json()
123
123
  return ScanConfig.from_dict(data)
124
+
@@ -5,10 +5,10 @@ API endpoints for subnet testing and listing.
5
5
  import traceback
6
6
  from flask import request, jsonify
7
7
  from lanscape.ui.blueprints.api import api_bp
8
- from lanscape.libraries.net_tools import get_all_network_subnets, is_arp_supported
9
- from lanscape.libraries.ip_parser import parse_ip_input
10
- from lanscape.libraries.errors import SubnetTooLargeError
11
- from lanscape.libraries.scan_config import DEFAULT_CONFIGS
8
+ from lanscape.core.net_tools import get_all_network_subnets, is_arp_supported
9
+ from lanscape.core.ip_parser import parse_ip_input
10
+ from lanscape.core.errors import SubnetTooLargeError
11
+ from lanscape.core.scan_config import DEFAULT_CONFIGS
12
12
 
13
13
 
14
14
  @api_bp.route('/api/tools/subnet/test')
@@ -69,3 +69,4 @@ def get_default_configs():
69
69
  configs[key] = config_dict
70
70
 
71
71
  return jsonify(configs)
72
+
@@ -5,3 +5,4 @@ Blueprint for web-related routes and views.
5
5
  from flask import Blueprint
6
6
 
7
7
  web_bp = Blueprint('web', __name__)
8
+
@@ -4,7 +4,7 @@ Handles UI views including the main dashboard, scan results, error display, and
4
4
  """
5
5
  from flask import render_template, request, redirect, url_for
6
6
  from lanscape.ui.blueprints.web import web_bp
7
- from lanscape.libraries.net_tools import (
7
+ from lanscape.core.net_tools import (
8
8
  get_all_network_subnets,
9
9
  smart_select_primary_subnet
10
10
  )
@@ -150,3 +150,4 @@ def app_info():
150
150
  Rendered info template
151
151
  """
152
152
  return render_template('info.html')
153
+
lanscape/ui/main.py CHANGED
@@ -9,10 +9,10 @@ import traceback
9
9
  import os
10
10
  import requests
11
11
 
12
- from lanscape.libraries.logger import configure_logging
13
- from lanscape.libraries.runtime_args import parse_args
14
- from lanscape.libraries.web_browser import open_webapp
15
- from lanscape.libraries.version_manager import get_installed_version, is_update_available
12
+ from lanscape.core.logger import configure_logging
13
+ from lanscape.core.runtime_args import parse_args
14
+ from lanscape.core.web_browser import open_webapp
15
+ from lanscape.core.version_manager import get_installed_version, is_update_available
16
16
  from lanscape.ui.app import start_webserver_daemon, start_webserver
17
17
  # do this so any logs generated on import are displayed
18
18
  args = parse_args()
@@ -136,3 +136,4 @@ def terminate():
136
136
 
137
137
  if __name__ == "__main__":
138
138
  main()
139
+
@@ -5,7 +5,7 @@ import os
5
5
  from flask import request
6
6
 
7
7
 
8
- from lanscape.libraries.runtime_args import parse_args
8
+ from lanscape.core.runtime_args import parse_args
9
9
 
10
10
 
11
11
  log = logging.getLogger('shutdown_handler')
@@ -55,3 +55,4 @@ class FlaskShutdownHandler:
55
55
  """Exits the application if a shutdown request has been made."""
56
56
  if self._exiting:
57
57
  os._exit(0)
58
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lanscape
3
- Version: 1.5.0
3
+ Version: 2.0.0a1
4
4
  Summary: A python based local network scanner
5
5
  Author-email: Michael Dennis <michael@dipduo.com>
6
6
  License-Expression: MIT
@@ -8,8 +8,13 @@ Project-URL: Homepage, https://github.com/mdennis281/py-lanscape
8
8
  Project-URL: Issues, https://github.com/mdennis281/py-lanscape/issues
9
9
  Keywords: network,scanner,lan,local,python
10
10
  Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
11
16
  Classifier: Operating System :: OS Independent
12
- Requires-Python: >=3.8
17
+ Requires-Python: >=3.10
13
18
  Description-Content-Type: text/markdown
14
19
  License-File: LICENSE
15
20
  Requires-Dist: Flask<5.0,>=3.0
@@ -1,40 +1,40 @@
1
- lanscape/__init__.py,sha256=D_p_XRcRDibcGQVZYLVSeWDdM__bGL3lYglq-K8njvk,443
2
- lanscape/__main__.py,sha256=PuY42yuCLAwHrOREJ6u2DgVyGX5hZKRQeoE9pajkNfM,170
3
- lanscape/libraries/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- lanscape/libraries/app_scope.py,sha256=qfzX8Ed4bFdxHMGjgnLlWuLZDTCBKObermz91KbGVn0,3298
5
- lanscape/libraries/decorators.py,sha256=Ve6xgLCTBSH8r_QGDNd1WUZnForvoBpkYZLENBFZkko,6141
6
- lanscape/libraries/device_alive.py,sha256=mwvHJp9rWV1_zfrE57aPKOsGp06fHdzrXOuGDWiZ2T8,6851
7
- lanscape/libraries/errors.py,sha256=QTf42UzR9Zxj1t1mdwfLvZIp0c9a5EItELOdCR7kTmE,1322
8
- lanscape/libraries/ip_parser.py,sha256=RgIEvHw_oQEcjUYOrvcpbfm4KThtH8L68WyhSOJNOfE,4201
9
- lanscape/libraries/logger.py,sha256=nzo6J8UdlMdhRkOJEDOIHKztoE3Du8PQZad7ixvNgeM,2534
10
- lanscape/libraries/mac_lookup.py,sha256=PxBSMe3wEVDtivCsh5NclSAguZz9rqdAS7QshBiuWvM,3519
11
- lanscape/libraries/net_tools.py,sha256=_fXtz9XBZPIIBs2ooWhBmEYkYlLuNx3q5BHpQiSxxxc,19706
12
- lanscape/libraries/port_manager.py,sha256=3_ROOb6JEiB0NByZVtADuGcldFkgZwn1RKtvwgs9AIk,4479
13
- lanscape/libraries/runtime_args.py,sha256=2vIqRrcWr-NHRSBlZGrxh1PdkPY0ytkPguu8KZqy2L8,2543
14
- lanscape/libraries/scan_config.py,sha256=T-xCKwSxtPXBCD1b8EjlWyqKa0UPBq9VpNBG8Sfzp8M,11124
15
- lanscape/libraries/service_scan.py,sha256=neWUu54t-TF8yk4VGb3EOMsY3ceiM8C3Km8vMdBvoMU,6958
16
- lanscape/libraries/subnet_scan.py,sha256=XUTDptKxuGf2X1O_d_6tscvL_ktY6tD-x4KNXj0Uh2s,14469
17
- lanscape/libraries/version_manager.py,sha256=tsdFx2V312mVpcRres1W1jPVFJFfpDPA4E7FNkjPY9w,2851
18
- lanscape/libraries/web_browser.py,sha256=23MuGIrBYdGhw6ejj6OWxwReeKIlWhtWukc1dKV_3_0,6736
19
- lanscape/resources/mac_addresses/convert_csv.py,sha256=hvlyLs0XmuuhBuvXBNRGP1cKJzYVRSf8VfUJ1VqROms,1189
1
+ lanscape/__init__.py,sha256=XFRrhe1uiIw7WpYvnx-5wbBKR9P_wjWl5gNHrUtZP4w,424
2
+ lanscape/__main__.py,sha256=yJpYmbQpYmXgtya-cSZmgNKVSYnyT1lO463R6k-5IPw,171
3
+ lanscape/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ lanscape/core/app_scope.py,sha256=kiKDWjkIf8SYluTmPm5JYEWa4t47ax0XRFoR3kKNM_o,3299
5
+ lanscape/core/decorators.py,sha256=3sNGj-pKqYlY_yAlFNLuAXACwqdPGPdbsLEinNkUTVc,7265
6
+ lanscape/core/device_alive.py,sha256=o5MdqkrbA9UjJ4xMd0yNI_p7C5PrR6xdhrellF9azNQ,6837
7
+ lanscape/core/errors.py,sha256=TnifbydUzT2i_aMz9iU_A7vwdWmbYbOclgJDdHwnj-I,1323
8
+ lanscape/core/ip_parser.py,sha256=U7BqZWKpsmD43WUuephqkxIlMW4EdziRZ-WUdh3zEJA,4197
9
+ lanscape/core/logger.py,sha256=pdaCJ41pEMzA9PImFY0eJ_uRaMDRv0Eb87Wr9_5dN0A,2535
10
+ lanscape/core/mac_lookup.py,sha256=1y-WQ9CLvHTItu9kJrFja6iClLZ_ABYGRi_mFF1PQFY,3520
11
+ lanscape/core/net_tools.py,sha256=3dzo0OWMBX7eg3S_iAxUpixXy72kn0eNIbR9Phi8Sto,19677
12
+ lanscape/core/port_manager.py,sha256=dbeQEhVqKmI7CYPEgW1UFcCa7HxkyJwy8ms9Jajk-ss,4480
13
+ lanscape/core/runtime_args.py,sha256=BASAsIZgZwMi3GHO_oY3oeehVrywVAXUip-Bi51Ocjo,2544
14
+ lanscape/core/scan_config.py,sha256=lG093Gn-j6NIK9JVn7JPMxkkX-9P6fFWP_ghec6-dB0,11115
15
+ lanscape/core/service_scan.py,sha256=m3cI9cYUsP5s3rDYtpp7k2ZiqXddF3Akd_4zlgZVyrg,6949
16
+ lanscape/core/subnet_scan.py,sha256=2HHQH2RVdHdAOwnppKrGr0JHvgNSXTAt-Rheo7-KV1s,14445
17
+ lanscape/core/version_manager.py,sha256=dd7B89L--Zi-0-aqSngM1co6Le7SVePzUJ3GKN3-Ud0,2842
18
+ lanscape/core/web_browser.py,sha256=Uv8isfQk7iTiH5YtBd-aDO9kYQdBhnapA0hM0xM-NKo,6737
19
+ lanscape/resources/mac_addresses/convert_csv.py,sha256=NE2WLgFL4Rw-8zm2YGJ1ZnK19MUR9xwVv3Yg4vNcOVA,1190
20
20
  lanscape/resources/mac_addresses/mac_db.json,sha256=Lng2yJerwO7vjefzxzgtE203hry1lIsCadHL1A5Rptg,2136137
21
- lanscape/resources/ports/convert_csv.py,sha256=MMLDa-5pGMsn4A2_k45jHsRYffrRY_0Z2D1ziiikeQA,1143
21
+ lanscape/resources/ports/convert_csv.py,sha256=JG4kFZ_suoKL8WlkpGlkG0QEbNTEN9J0oBTsdxXB7hQ,1144
22
22
  lanscape/resources/ports/full.json,sha256=O8XBW52QvEVSGMQDbXe4-c4qq6XAecw6KJW4m2HkTLo,1441444
23
23
  lanscape/resources/ports/large.json,sha256=CzlCcIGCBW1QAgjz4NDerCYA8HcYf6lNxehh7F928y0,138410
24
24
  lanscape/resources/ports/medium.json,sha256=T5Rc7wa47MtroHxuZrHSftOqRWbQzhZULJdE1vpsTvU,3518
25
25
  lanscape/resources/ports/small.json,sha256=F_lo_5xHwHBfOVfVgxP7ejblR3R62SNtC1Mm33brhYc,376
26
26
  lanscape/resources/services/definitions.jsonc,sha256=M9BDeK-mh25sEVj8xDEYbU2ix7EETVWhbiYmMb14Gjg,20905
27
27
  lanscape/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
- lanscape/ui/app.py,sha256=bL3K3NkGV1RY67kGHEQIWUl-Jm_MVN4WsIlsRQuK-SU,3760
29
- lanscape/ui/main.py,sha256=8Be2UL_ezWLpaEYYejjd8iyM2_hG1pXlkHdVjn-lySc,4196
30
- lanscape/ui/shutdown_handler.py,sha256=eJC9A0MDMgLv_KQnJlUy3Kz2xCGDAf5opVdd8nBtABE,1710
31
- lanscape/ui/blueprints/__init__.py,sha256=WLnPfPE06684wArgKDDLfsW-1hKFlLe75AR7uLAPlKc,270
32
- lanscape/ui/blueprints/api/__init__.py,sha256=5Z4Y7B36O-bNFenpomfuNhPuJ9dW_MC0TPUU3pCFVfA,103
33
- lanscape/ui/blueprints/api/port.py,sha256=8FuNcjF56wmgjoCZeaYrIakTGdshAmDjUmkjXHbaZ8I,1981
34
- lanscape/ui/blueprints/api/scan.py,sha256=lbwV5AciMGP-S2J_EaXcPOHeHywImzQ_bm2ZSJg-H5U,3331
35
- lanscape/ui/blueprints/api/tools.py,sha256=IhY_ldrnVYuZKFv6gsevr9LL5gfTnmVuR95zFc05Tlo,2452
36
- lanscape/ui/blueprints/web/__init__.py,sha256=NvgnjP0X4LwqVhSEyh5RUzoG45N44kHK1MEFlfvBxTg,118
37
- lanscape/ui/blueprints/web/routes.py,sha256=R4ebdKDNWAwWo0JZcBVjCg5Q7VLZL0hQXV5cn834fuU,4539
28
+ lanscape/ui/app.py,sha256=aAS21f8361oAcGKwvD1W5oLbTk7f9_H5EJEANBnvAHQ,3741
29
+ lanscape/ui/main.py,sha256=teeiGumDG--zU4fBF9nen9q65vhSl7CvIxzkibwSt1c,4177
30
+ lanscape/ui/shutdown_handler.py,sha256=4B5gEaRBucYZZvVKSF8Unq1hQhJDC2W3_W5JK7wyMUE,1706
31
+ lanscape/ui/blueprints/__init__.py,sha256=rEtm7ZT_K5Hd9UYFvsjP-cqmA01RBhKybjMhhUNVwCY,266
32
+ lanscape/ui/blueprints/api/__init__.py,sha256=9G0qtzcSmV2qjLNx4nedsUGU7rKkEGSuFAIbRIWWSyI,104
33
+ lanscape/ui/blueprints/api/port.py,sha256=2QLq03HOMz9y_7q41rah8kOOXF0oKCOczoUfJ3j-QFI,1977
34
+ lanscape/ui/blueprints/api/scan.py,sha256=_kg9qtshoUHTU8b9a2gzEfNWQsx8uixLNE3PO_o8uRA,3327
35
+ lanscape/ui/blueprints/api/tools.py,sha256=wrn3OG-SyUhgiHHovovwbhKIPI7db1iYOIXKnGx5DMY,2433
36
+ lanscape/ui/blueprints/web/__init__.py,sha256=_83Mu7yUAME-lEsK82U_WNEMyfZwQGc9M1LPSDOO4so,119
37
+ lanscape/ui/blueprints/web/routes.py,sha256=WmKFPgslMXoxfy9C6NQqKNvc6Lf1pWSOLbnYL2WqzaI,4535
38
38
  lanscape/ui/static/lanscape.webmanifest,sha256=07CqA-PQsO35KJD8R96sI3Pxix6UuBjijPDCuy9vM3s,446
39
39
  lanscape/ui/static/css/style.css,sha256=qXDshNhj77__06AuL-RhsxlrqZ5S0JFAmy3M1sk1Sm8,21098
40
40
  lanscape/ui/static/img/ico/android-chrome-192x192.png,sha256=JmFT6KBCCuoyxMV-mLNtF9_QJbVBvfWPUizKN700fi8,18255
@@ -68,8 +68,9 @@ lanscape/ui/templates/scan/ip-table-row.html,sha256=nO5ZMhl3Gnlc8lg5nWmE05_6_5oz
68
68
  lanscape/ui/templates/scan/ip-table.html,sha256=AT2ZvCPYdKl-XJiAkEAawPOVuQw-w0MXumGQTr3zyKM,926
69
69
  lanscape/ui/templates/scan/overview.html,sha256=xWj9jWDPg2KcPLvS8fnSins23_UXjKCdb2NJwNG2U2Q,1176
70
70
  lanscape/ui/templates/scan/scan-error.html,sha256=wmAYQ13IJHUoO8fAGNDjMvNml7tu4rsIU3Vav71ETlA,999
71
- lanscape-1.5.0.dist-info/licenses/LICENSE,sha256=VLoE0IrNTIc09dFm7hMN0qzk4T3q8V0NaPcFQqMemDs,1070
72
- lanscape-1.5.0.dist-info/METADATA,sha256=Wc0xAn1Klumi0wg0tsVyhPOpzJuTvAMd24WH-Kehl7Q,3121
73
- lanscape-1.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
74
- lanscape-1.5.0.dist-info/top_level.txt,sha256=E9D4sjPz_6H7c85Ycy_pOS2xuv1Wm-ilKhxEprln2ps,9
75
- lanscape-1.5.0.dist-info/RECORD,,
71
+ lanscape-2.0.0a1.dist-info/licenses/LICENSE,sha256=VLoE0IrNTIc09dFm7hMN0qzk4T3q8V0NaPcFQqMemDs,1070
72
+ lanscape-2.0.0a1.dist-info/METADATA,sha256=cV6SLhKrEqhVDFUHUalq11D09qVtp6fa7NkGi7ieJgw,3379
73
+ lanscape-2.0.0a1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
74
+ lanscape-2.0.0a1.dist-info/entry_points.txt,sha256=evxSxUikFa1OEd4e0Boky9sLH87HdgM0YqB_AbB2HYc,51
75
+ lanscape-2.0.0a1.dist-info/top_level.txt,sha256=E9D4sjPz_6H7c85Ycy_pOS2xuv1Wm-ilKhxEprln2ps,9
76
+ lanscape-2.0.0a1.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ lanscape = lanscape.ui.main:main
File without changes