lanscape 1.2.8a2__tar.gz → 1.2.9a1__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.
Files changed (74) hide show
  1. {lanscape-1.2.8a2/src/lanscape.egg-info → lanscape-1.2.9a1}/PKG-INFO +2 -12
  2. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/README.md +1 -11
  3. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/pyproject.toml +1 -1
  4. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/libraries/subnet_scan.py +16 -15
  5. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/tests/test_library.py +1 -1
  6. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/app.py +0 -2
  7. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/blueprints/api/scan.py +1 -1
  8. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/blueprints/web/routes.py +1 -1
  9. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/main.py +16 -5
  10. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/templates/base.html +1 -1
  11. {lanscape-1.2.8a2 → lanscape-1.2.9a1/src/lanscape.egg-info}/PKG-INFO +2 -12
  12. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/LICENSE +0 -0
  13. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/MANIFEST.in +0 -0
  14. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/setup.cfg +0 -0
  15. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/__init__.py +0 -0
  16. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/__main__.py +0 -0
  17. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/libraries/app_scope.py +0 -0
  18. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/libraries/decorators.py +0 -0
  19. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/libraries/errors.py +0 -0
  20. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/libraries/ip_parser.py +0 -0
  21. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/libraries/logger.py +0 -0
  22. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/libraries/mac_lookup.py +0 -0
  23. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/libraries/net_tools.py +0 -0
  24. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/libraries/port_manager.py +0 -0
  25. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/libraries/runtime_args.py +0 -0
  26. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/libraries/version_manager.py +0 -0
  27. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/resources/mac_addresses/convert_csv.py +0 -0
  28. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/resources/mac_addresses/mac_db.json +0 -0
  29. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/resources/ports/convert_csv.py +0 -0
  30. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/resources/ports/full.json +0 -0
  31. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/resources/ports/large.json +0 -0
  32. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/resources/ports/medium.json +0 -0
  33. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/resources/ports/small.json +0 -0
  34. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/tests/__init__.py +0 -0
  35. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/tests/_helpers.py +0 -0
  36. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/tests/test_api.py +0 -0
  37. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/tests/test_env.py +0 -0
  38. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/blueprints/__init__.py +0 -0
  39. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/blueprints/api/__init__.py +0 -0
  40. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/blueprints/api/port.py +0 -0
  41. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/blueprints/api/tools.py +0 -0
  42. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/blueprints/web/__init__.py +0 -0
  43. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/static/css/style.css +0 -0
  44. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/static/img/ico/android-chrome-192x192.png +0 -0
  45. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/static/img/ico/android-chrome-512x512.png +0 -0
  46. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/static/img/ico/apple-touch-icon.png +0 -0
  47. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/static/img/ico/favicon-16x16.png +0 -0
  48. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/static/img/ico/favicon-32x32.png +0 -0
  49. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/static/img/ico/favicon.ico +0 -0
  50. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/static/img/ico/site.webmanifest +0 -0
  51. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/static/js/core.js +0 -0
  52. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/static/js/layout-sizing.js +0 -0
  53. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/static/js/main.js +0 -0
  54. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/static/js/quietReload.js +0 -0
  55. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/static/js/shutdown-server.js +0 -0
  56. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/static/js/subnet-info.js +0 -0
  57. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/static/js/subnet-selector.js +0 -0
  58. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/static/lanscape.webmanifest +0 -0
  59. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/templates/core/head.html +0 -0
  60. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/templates/core/scripts.html +0 -0
  61. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/templates/error.html +0 -0
  62. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/templates/info.html +0 -0
  63. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/templates/main.html +0 -0
  64. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/templates/scan/export.html +0 -0
  65. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/templates/scan/ip-table-row.html +0 -0
  66. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/templates/scan/ip-table.html +0 -0
  67. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/templates/scan/overview.html +0 -0
  68. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/templates/scan/scan-error.html +0 -0
  69. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/templates/scan.html +0 -0
  70. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape/ui/templates/shutdown.html +0 -0
  71. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape.egg-info/SOURCES.txt +0 -0
  72. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape.egg-info/dependency_links.txt +0 -0
  73. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape.egg-info/requires.txt +0 -0
  74. {lanscape-1.2.8a2 → lanscape-1.2.9a1}/src/lanscape.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lanscape
3
- Version: 1.2.8a2
3
+ Version: 1.2.9a1
4
4
  Summary: A python based local network scanner
5
5
  Author-email: Michael Dennis <michael@dipduo.com>
6
6
  Project-URL: Homepage, https://github.com/mdennis281/py-lanscape
@@ -32,17 +32,15 @@ python -m lanscape
32
32
 
33
33
  ## Flags
34
34
  - `--port <port number>` port of the flask app (default: 5001)
35
- - `--nogui` run in web mode (default: false)
36
35
  - `--reloader` essentially flask debug mode- good for local development (default: false)
37
36
  - `--logfile` save log output to lanscape.log
38
37
  - `--loglevel <level>` set the logger's log level (default: INFO)
39
- - `--headless` similar to nogui but doesnt try to open a browser (default: false)
40
38
 
41
39
 
42
40
  Examples:
43
41
  ```shell
44
42
  python -m lanscape --reloader
45
- python -m lanscape --nogui --port 5002
43
+ python -m lanscape --port 5002
46
44
  python -m lanscape --logfile --loglevel DEBUG
47
45
  ```
48
46
 
@@ -57,14 +55,6 @@ can sometimes require admin-level permissions to retrieve accurate results.
57
55
  This is a missing dependency related to the ARP lookup. This is handled in the code, but you would get marginally faster/better results with this installed: [npcap download](https://npcap.com/#download)
58
56
 
59
57
 
60
- ### Unable to start webview client. Try --nogui (Linux)
61
- Linux and QT (GUI package) dont seem to play well with each other very well. If you really want the gui (`python -m lanscape --nogui` is almost as good) I had success on ubuntu desktop by running these:
62
- ```sh
63
- sudo apt install libcairo2-dev libxt-dev libgirepository1.0-dev
64
- pip install pycairo PyGObject qtpy PyQt5 PyQtWebEngine
65
- ```
66
-
67
-
68
58
  ### Something else
69
59
  Feel free to submit a github issue detailing your experience.
70
60
 
@@ -11,17 +11,15 @@ python -m lanscape
11
11
 
12
12
  ## Flags
13
13
  - `--port <port number>` port of the flask app (default: 5001)
14
- - `--nogui` run in web mode (default: false)
15
14
  - `--reloader` essentially flask debug mode- good for local development (default: false)
16
15
  - `--logfile` save log output to lanscape.log
17
16
  - `--loglevel <level>` set the logger's log level (default: INFO)
18
- - `--headless` similar to nogui but doesnt try to open a browser (default: false)
19
17
 
20
18
 
21
19
  Examples:
22
20
  ```shell
23
21
  python -m lanscape --reloader
24
- python -m lanscape --nogui --port 5002
22
+ python -m lanscape --port 5002
25
23
  python -m lanscape --logfile --loglevel DEBUG
26
24
  ```
27
25
 
@@ -36,14 +34,6 @@ can sometimes require admin-level permissions to retrieve accurate results.
36
34
  This is a missing dependency related to the ARP lookup. This is handled in the code, but you would get marginally faster/better results with this installed: [npcap download](https://npcap.com/#download)
37
35
 
38
36
 
39
- ### Unable to start webview client. Try --nogui (Linux)
40
- Linux and QT (GUI package) dont seem to play well with each other very well. If you really want the gui (`python -m lanscape --nogui` is almost as good) I had success on ubuntu desktop by running these:
41
- ```sh
42
- sudo apt install libcairo2-dev libxt-dev libgirepository1.0-dev
43
- pip install pycairo PyGObject qtpy PyQt5 PyQtWebEngine
44
- ```
45
-
46
-
47
37
  ### Something else
48
38
  Feel free to submit a github issue detailing your experience.
49
39
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "lanscape"
3
- version = "1.2.8a2"
3
+ version = "1.2.9a1"
4
4
  authors = [
5
5
  { name="Michael Dennis", email="michael@dipduo.com" },
6
6
  ]
@@ -27,7 +27,14 @@ TCNT_DEVICE_ISALIVE = 256
27
27
  class ScanConfig:
28
28
  subnet: str
29
29
  port_list: str
30
- parallelism: float = 1.0
30
+ t_multiplier: float = 1.0
31
+ t_cnt_port_scan: int = 10
32
+ t_cnt_port_test: int = 128
33
+ t_cnt_isalive: int = 256
34
+
35
+ def t_cnt(self, id: str) -> int:
36
+ return int(int(getattr(self, f't_cnt_{id}')) * float(self.t_multiplier))
37
+
31
38
 
32
39
 
33
40
 
@@ -40,8 +47,9 @@ class SubnetScanner:
40
47
  self.port_list = config.port_list
41
48
  self.ports: list = PortManager().get_port_list(config.port_list).keys()
42
49
  self.running = False
43
- self.parallelism: float = float(config.parallelism)
44
50
  self.subnet_str = config.subnet
51
+
52
+ self.cfg = config
45
53
  self.job_stats = JobStats()
46
54
  self.uid = str(uuid.uuid4())
47
55
  self.results = ScannerResults(self)
@@ -58,7 +66,7 @@ class SubnetScanner:
58
66
  """
59
67
  self._set_stage('scanning devices')
60
68
  self.running = True
61
- with ThreadPoolExecutor(max_workers=self._t_cnt(TCNT_DEVICE_ISALIVE)) as executor:
69
+ with ThreadPoolExecutor(max_workers=self.cfg.t_cnt('isalive')) as executor:
62
70
  futures = {executor.submit(self._get_host_details, str(ip)): str(ip) for ip in self.subnet}
63
71
  for future in futures:
64
72
  ip = futures[future]
@@ -104,7 +112,7 @@ class SubnetScanner:
104
112
  remaining_isalive_sec = (self.results.devices_total - self.results.devices_scanned) * avg_host_detail_sec
105
113
  total_isalive_sec = self.results.devices_total * avg_host_detail_sec
106
114
 
107
- isalive_multiplier = self._t_cnt(TCNT_DEVICE_ISALIVE)
115
+ isalive_multiplier = self.cfg.t_cnt('isalive')
108
116
 
109
117
  # --- Port scanning calculations ---
110
118
  device_ports_scanned = self.job_stats.finished.get('_test_port', 0)
@@ -116,7 +124,7 @@ class SubnetScanner:
116
124
  remaining_port_test_sec = device_ports_unscanned * avg_port_test_sec
117
125
  total_port_test_sec = est_subnet_devices * len(self.ports) * avg_port_test_sec
118
126
 
119
- port_test_multiplier = self._t_cnt(TCNT_PORT_SCANS) * self._t_cnt(TCNT_PORT_TEST)
127
+ port_test_multiplier = self.cfg.t_cnt('port_scan') * self.cfg.t_cnt('port_test')
120
128
 
121
129
  # --- Overall progress ---
122
130
  est_total_time = (total_isalive_sec / isalive_multiplier) + (total_port_test_sec / port_test_multiplier)
@@ -157,7 +165,7 @@ class SubnetScanner:
157
165
 
158
166
  @terminator
159
167
  def _scan_network_ports(self):
160
- with ThreadPoolExecutor(max_workers=self._t_cnt(TCNT_PORT_SCANS)) as executor:
168
+ with ThreadPoolExecutor(max_workers=self.cfg.t_cnt('port_scan')) as executor:
161
169
  futures = {executor.submit(self._scan_ports, device): device for device in self.results.devices}
162
170
  for future in futures:
163
171
  future.result()
@@ -167,7 +175,7 @@ class SubnetScanner:
167
175
  def _scan_ports(self, device: Device):
168
176
  self.log.debug(f'[{device.ip}] Initiating port scan')
169
177
  device.stage = 'scanning'
170
- with ThreadPoolExecutor(max_workers=self._t_cnt(TCNT_PORT_TEST)) as executor:
178
+ with ThreadPoolExecutor(max_workers=self.cfg.t_cnt('port_test')) as executor:
171
179
  futures = {executor.submit(self._test_port, device, int(port)): port for port in self.ports}
172
180
  for future in futures:
173
181
  future.result()
@@ -192,13 +200,6 @@ class SubnetScanner:
192
200
  """
193
201
  return host.is_alive(host.ip)
194
202
 
195
- def _t_cnt(self, base_threads: int) -> int:
196
- """
197
- Calculate the number of threads to use based on the base number
198
- of threads and the parallelism factor.
199
- """
200
- return int(base_threads * self.parallelism)
201
-
202
203
  def _set_stage(self,stage):
203
204
  self.log.debug(f'[{self.uid}] Moving to Stage: {stage}')
204
205
  self.results.stage = stage
@@ -210,7 +211,6 @@ class ScannerResults:
210
211
  self.scan = scan
211
212
  self.port_list: str = scan.port_list
212
213
  self.subnet: str = scan.subnet_str
213
- self.parallelism: float = scan.parallelism
214
214
  self.uid = scan.uid
215
215
 
216
216
  self.devices_total: int = len(list(scan.subnet))
@@ -249,6 +249,7 @@ class ScannerResults:
249
249
  out = vars(self).copy()
250
250
  out.pop('scan')
251
251
  out.pop('log')
252
+ out['cfg'] = vars(self.scan.cfg)
252
253
 
253
254
  devices: List[Device] = out.pop('devices')
254
255
  sortedDevices = sorted(devices, key=lambda obj: ipaddress.IPv4Address(obj.ip))
@@ -11,7 +11,7 @@ class LibraryTestCase(unittest.TestCase):
11
11
  self.assertIsNotNone(subnet)
12
12
  cfg = ScanConfig(
13
13
  subnet = right_size_subnet(subnet),
14
- parallelism=1.0,
14
+ t_multiplier=1.0,
15
15
  port_list='small'
16
16
  )
17
17
  scan = sm.new_scan(cfg)
@@ -106,8 +106,6 @@ def start_webserver(args: RuntimeArgs) -> int:
106
106
 
107
107
  app.run(**run_args)
108
108
 
109
-
110
-
111
109
  if __name__ == "__main__":
112
110
  start_webserver(True)
113
111
 
@@ -61,5 +61,5 @@ def get_scan_config():
61
61
  return ScanConfig(
62
62
  subnet = data['subnet'],
63
63
  port_list= data['port_list'],
64
- parallelism=data.get('parallelism',1.0)
64
+ t_multiplier=data.get('parallelism',1.0)
65
65
  )
@@ -22,7 +22,7 @@ def index():
22
22
  scan = scanner.results.export()
23
23
  subnet = scan['subnet']
24
24
  port_list = scan['port_list']
25
- parallelism = scan['parallelism']
25
+ parallelism = scan['cfg']['t_multiplier']
26
26
  else:
27
27
  log.debug(f'Redirecting, scan {scan_id} doesnt exist in memory')
28
28
  return redirect('/')
@@ -13,6 +13,7 @@ configure_logging(args.loglevel, args.logfile)
13
13
 
14
14
  from ..libraries.version_manager import get_installed_version, is_update_available
15
15
  from .app import start_webserver
16
+ import socket
16
17
 
17
18
 
18
19
  log = logging.getLogger('core')
@@ -27,9 +28,12 @@ def main():
27
28
  if not IS_FLASK_RELOAD:
28
29
  log.info(f'LANscape v{get_installed_version()}')
29
30
  try_check_update()
30
- else:
31
+
32
+ else:
31
33
  log.info('Flask reloaded app.')
32
34
 
35
+ args.port = get_valid_port(args.port)
36
+
33
37
 
34
38
  try:
35
39
 
@@ -63,9 +67,8 @@ def open_browser(url: str,wait=2):
63
67
  time.sleep(wait)
64
68
  webbrowser.open(url, new=2)
65
69
  except:
66
- srv_url = f"0.0.0.0:{url.split(':')[1]}"
67
70
  log.debug(traceback.format_exc())
68
- log.info(f'unable to open web browser, server running on {srv_url}')
71
+ log.info(f'Unable to open web browser, server running on {url}')
69
72
 
70
73
  threading.Thread(target=do_open).start()
71
74
 
@@ -74,13 +77,21 @@ def no_gui(args: RuntimeArgs):
74
77
  # if it was, dont open the browser again
75
78
  if not IS_FLASK_RELOAD:
76
79
  open_browser(f'http://127.0.0.1:{args.port}')
77
-
78
- log.info(f'Server started: http://127.0.0.1:{args.port}')
80
+ log.info(f'Flask started: http://127.0.0.1:{args.port}')
79
81
 
80
82
  start_webserver(
81
83
  args
82
84
  )
83
85
 
86
+ def get_valid_port(port: int):
87
+ """
88
+ Get the first available port starting from the specified port
89
+ """
90
+ while True:
91
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
92
+ if s.connect_ex(('localhost', port)) != 0:
93
+ return port
94
+ port += 1
84
95
 
85
96
  if __name__ == "__main__":
86
97
  main()
@@ -11,7 +11,7 @@
11
11
  <div class="version">
12
12
  v{{app_version}}
13
13
  {% if is_local %}
14
- <span class="text-info">(Local Run)</span>
14
+ <span class="text-info">(Local)</span>
15
15
  {% elif update_available %}
16
16
  <span>(Update Available)</span>
17
17
  {% endif %}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lanscape
3
- Version: 1.2.8a2
3
+ Version: 1.2.9a1
4
4
  Summary: A python based local network scanner
5
5
  Author-email: Michael Dennis <michael@dipduo.com>
6
6
  Project-URL: Homepage, https://github.com/mdennis281/py-lanscape
@@ -32,17 +32,15 @@ python -m lanscape
32
32
 
33
33
  ## Flags
34
34
  - `--port <port number>` port of the flask app (default: 5001)
35
- - `--nogui` run in web mode (default: false)
36
35
  - `--reloader` essentially flask debug mode- good for local development (default: false)
37
36
  - `--logfile` save log output to lanscape.log
38
37
  - `--loglevel <level>` set the logger's log level (default: INFO)
39
- - `--headless` similar to nogui but doesnt try to open a browser (default: false)
40
38
 
41
39
 
42
40
  Examples:
43
41
  ```shell
44
42
  python -m lanscape --reloader
45
- python -m lanscape --nogui --port 5002
43
+ python -m lanscape --port 5002
46
44
  python -m lanscape --logfile --loglevel DEBUG
47
45
  ```
48
46
 
@@ -57,14 +55,6 @@ can sometimes require admin-level permissions to retrieve accurate results.
57
55
  This is a missing dependency related to the ARP lookup. This is handled in the code, but you would get marginally faster/better results with this installed: [npcap download](https://npcap.com/#download)
58
56
 
59
57
 
60
- ### Unable to start webview client. Try --nogui (Linux)
61
- Linux and QT (GUI package) dont seem to play well with each other very well. If you really want the gui (`python -m lanscape --nogui` is almost as good) I had success on ubuntu desktop by running these:
62
- ```sh
63
- sudo apt install libcairo2-dev libxt-dev libgirepository1.0-dev
64
- pip install pycairo PyGObject qtpy PyQt5 PyQtWebEngine
65
- ```
66
-
67
-
68
58
  ### Something else
69
59
  Feel free to submit a github issue detailing your experience.
70
60
 
File without changes
File without changes
File without changes