lanscape 1.3.8a1__py3-none-any.whl → 2.4.0a2__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.

Potentially problematic release.


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

Files changed (58) hide show
  1. lanscape/__init__.py +8 -4
  2. lanscape/{libraries → core}/app_scope.py +21 -3
  3. lanscape/core/decorators.py +231 -0
  4. lanscape/{libraries → core}/device_alive.py +83 -16
  5. lanscape/{libraries → core}/ip_parser.py +2 -26
  6. lanscape/{libraries → core}/net_tools.py +209 -66
  7. lanscape/{libraries → core}/runtime_args.py +6 -0
  8. lanscape/{libraries → core}/scan_config.py +103 -5
  9. lanscape/core/service_scan.py +222 -0
  10. lanscape/{libraries → core}/subnet_scan.py +30 -14
  11. lanscape/{libraries → core}/version_manager.py +15 -17
  12. lanscape/resources/ports/test_port_list_scan.json +4 -0
  13. lanscape/resources/services/definitions.jsonc +576 -400
  14. lanscape/ui/app.py +17 -5
  15. lanscape/ui/blueprints/__init__.py +1 -1
  16. lanscape/ui/blueprints/api/port.py +15 -1
  17. lanscape/ui/blueprints/api/scan.py +1 -1
  18. lanscape/ui/blueprints/api/tools.py +4 -4
  19. lanscape/ui/blueprints/web/routes.py +29 -2
  20. lanscape/ui/main.py +46 -19
  21. lanscape/ui/shutdown_handler.py +2 -2
  22. lanscape/ui/static/css/style.css +186 -20
  23. lanscape/ui/static/js/core.js +14 -0
  24. lanscape/ui/static/js/main.js +30 -2
  25. lanscape/ui/static/js/quietReload.js +3 -0
  26. lanscape/ui/static/js/scan-config.js +56 -6
  27. lanscape/ui/templates/base.html +6 -8
  28. lanscape/ui/templates/core/head.html +1 -1
  29. lanscape/ui/templates/info.html +20 -5
  30. lanscape/ui/templates/main.html +33 -36
  31. lanscape/ui/templates/scan/config.html +214 -176
  32. lanscape/ui/templates/scan/device-detail.html +111 -0
  33. lanscape/ui/templates/scan/ip-table-row.html +17 -83
  34. lanscape/ui/templates/scan/ip-table.html +5 -5
  35. lanscape/ui/ws/__init__.py +31 -0
  36. lanscape/ui/ws/delta.py +170 -0
  37. lanscape/ui/ws/handlers/__init__.py +20 -0
  38. lanscape/ui/ws/handlers/base.py +145 -0
  39. lanscape/ui/ws/handlers/port.py +184 -0
  40. lanscape/ui/ws/handlers/scan.py +352 -0
  41. lanscape/ui/ws/handlers/tools.py +145 -0
  42. lanscape/ui/ws/protocol.py +86 -0
  43. lanscape/ui/ws/server.py +375 -0
  44. {lanscape-1.3.8a1.dist-info → lanscape-2.4.0a2.dist-info}/METADATA +18 -3
  45. lanscape-2.4.0a2.dist-info/RECORD +85 -0
  46. {lanscape-1.3.8a1.dist-info → lanscape-2.4.0a2.dist-info}/WHEEL +1 -1
  47. lanscape-2.4.0a2.dist-info/entry_points.txt +2 -0
  48. lanscape/libraries/decorators.py +0 -170
  49. lanscape/libraries/service_scan.py +0 -50
  50. lanscape/libraries/web_browser.py +0 -210
  51. lanscape-1.3.8a1.dist-info/RECORD +0 -74
  52. /lanscape/{libraries → core}/__init__.py +0 -0
  53. /lanscape/{libraries → core}/errors.py +0 -0
  54. /lanscape/{libraries → core}/logger.py +0 -0
  55. /lanscape/{libraries → core}/mac_lookup.py +0 -0
  56. /lanscape/{libraries → core}/port_manager.py +0 -0
  57. {lanscape-1.3.8a1.dist-info → lanscape-2.4.0a2.dist-info}/licenses/LICENSE +0 -0
  58. {lanscape-1.3.8a1.dist-info → lanscape-2.4.0a2.dist-info}/top_level.txt +0 -0
@@ -1,50 +0,0 @@
1
- """Service scanning module for identifying services running on network ports."""
2
- import asyncio
3
- import logging
4
- import traceback
5
- from lanscape.libraries.app_scope import ResourceManager
6
-
7
- log = logging.getLogger('ServiceScan')
8
- SERVICES = ResourceManager('services').get_jsonc('definitions.jsonc')
9
-
10
- # skip printer ports because they cause blank pages to be printed
11
- PRINTER_PORTS = [9100, 631]
12
-
13
-
14
- def scan_service(ip: str, port: int, timeout=10) -> str:
15
- """
16
- Synchronous function that attempts to identify the service running on a given port.
17
- """
18
-
19
- async def _async_scan_service(ip: str, port: int, timeout) -> str:
20
- if port in PRINTER_PORTS:
21
- return "Printer"
22
-
23
- try:
24
- # Add a timeout to prevent hanging
25
- reader, writer = await asyncio.wait_for(asyncio.open_connection(ip, port), timeout=5)
26
-
27
- # Send a probe appropriate for common services
28
- probe = f"GET / HTTP/1.1\r\nHost: {ip}\r\n\r\n".encode("utf-8")
29
- writer.write(probe)
30
- await writer.drain()
31
-
32
- # Receive the response with a timeout
33
- response = await asyncio.wait_for(reader.read(1024), timeout=timeout)
34
- writer.close()
35
- await writer.wait_closed()
36
-
37
- # Analyze the response to identify the service
38
- response_str = response.decode("utf-8", errors="ignore")
39
- for service, hints in SERVICES.items():
40
- if any(hint.lower() in response_str.lower() for hint in hints):
41
- return service
42
- except asyncio.TimeoutError:
43
- log.warning(f"Timeout scanning {ip}:{port}")
44
- except Exception as e:
45
- log.error(f"Error scanning {ip}:{port}: {str(e)}")
46
- log.debug(traceback.format_exc())
47
- return "Unknown"
48
-
49
- # Use asyncio.run to execute the asynchronous logic synchronously
50
- return asyncio.run(_async_scan_service(ip, port, timeout=timeout))
@@ -1,210 +0,0 @@
1
- """
2
- Get the executable path of the system’s default web browser.
3
-
4
- Supports:
5
- - Windows (reads from the registry)
6
- - Linux (uses xdg-mime / xdg-settings + .desktop file parsing)
7
- """
8
-
9
- import sys
10
- import os
11
- import subprocess
12
- import webbrowser
13
- import logging
14
- import re
15
- import time
16
- from typing import Optional
17
-
18
- log = logging.getLogger('WebBrowser')
19
-
20
-
21
- def open_webapp(url: str) -> bool:
22
- """
23
- will try to open the web page as an app
24
- on failure, will open as a tab in default browser
25
-
26
- returns:
27
- """
28
- start = time.time()
29
- try:
30
- exe = get_default_browser_executable()
31
- if not exe:
32
- raise RuntimeError('Unable to find browser binary')
33
- log.debug(f'Opening {url} with {exe}')
34
-
35
- cmd = f'"{exe}" --app="{url}"'
36
- subprocess.run(cmd, check=True, shell=True)
37
-
38
- if time.time() - start < 2:
39
- log.debug(
40
- 'Unable to hook into closure of UI, listening for flask shutdown')
41
- return False
42
- return True
43
-
44
- except Exception as e:
45
- log.warning(
46
- 'Failed to open webpage as app, falling back to browser tab')
47
- log.debug(f'As app error: {e}')
48
- try:
49
- success = webbrowser.open(url)
50
- log.debug(f'Opened {url} in browser tab: {success}')
51
- if not success:
52
- # pylint: disable=raise-missing-from
53
- raise RuntimeError(
54
- 'Unknown error while opening browser tab') from e
55
- except Exception as e2:
56
- log.warning(
57
- 'Exhausted all options to open browser, you need to open manually')
58
- log.debug(f'As tab error: {e2}')
59
- log.info(f'LANScape UI is running on {url}')
60
- return False
61
-
62
-
63
- def get_default_browser_executable() -> Optional[str]:
64
- """Platform-agnostic method to get the default browser executable path."""
65
- if sys.platform.startswith("win"):
66
- return windows_get_browser_from_registry()
67
-
68
- if sys.platform.startswith("linux"):
69
- return linux_get_browser_executable()
70
-
71
- if sys.platform.startswith("darwin"):
72
- # macOS: try to find Chrome first for app mode support, fallback to default
73
- try:
74
- p = subprocess.run(
75
- ["mdfind", "kMDItemCFBundleIdentifier == 'com.google.Chrome'"],
76
- capture_output=True, text=True, check=True
77
- )
78
- chrome_paths = p.stdout.strip().split('\n')
79
- if chrome_paths and chrome_paths[0]:
80
- return f"{chrome_paths[0]}/Contents/MacOS/Google Chrome"
81
- except subprocess.CalledProcessError:
82
- pass
83
-
84
- # Fallback to system default
85
- return "/usr/bin/open"
86
-
87
- # Unsupported platform
88
- return None
89
-
90
-
91
- def linux_get_browser_executable() -> Optional[str]:
92
- """Get the default web browser executable path on Linux."""
93
- # First, find the .desktop file name
94
- desktop_file = None
95
- try:
96
- # Try xdg-mime
97
- p = subprocess.run(
98
- ["xdg-mime", "query", "default", "x-scheme-handler/http"],
99
- capture_output=True, text=True,
100
- check=True
101
- )
102
- desktop_file = p.stdout.strip()
103
- except subprocess.CalledProcessError:
104
- pass
105
-
106
- if not desktop_file:
107
- # Fallback to xdg-settings
108
- try:
109
- p = subprocess.run(
110
- ["xdg-settings", "get", "default-web-browser"],
111
- capture_output=True, text=True,
112
- check=True
113
- )
114
- desktop_file = p.stdout.strip()
115
- except subprocess.CalledProcessError:
116
- pass
117
-
118
- # Final fallback: BROWSER environment variable
119
- if not desktop_file:
120
- return os.environ.get("BROWSER")
121
-
122
- # Look for that .desktop file in standard locations
123
- search_paths = [
124
- os.path.expanduser("~/.local/share/applications"),
125
- "/usr/local/share/applications",
126
- "/usr/share/applications",
127
- ]
128
-
129
- exec_cmd = None
130
- for path in search_paths:
131
- full_path = os.path.join(path, desktop_file)
132
- if os.path.isfile(full_path):
133
- with open(full_path, encoding="utf-8", errors="ignore") as f:
134
- for line in f:
135
- if line.startswith("Exec="):
136
- exec_cmd = line[len("Exec="):].strip()
137
- # strip arguments like "%u", "--flag", etc.
138
- exec_cmd = exec_cmd.split()[0]
139
- exec_cmd = exec_cmd.split("%")[0]
140
- return exec_cmd
141
-
142
- return exec_cmd
143
-
144
-
145
- def windows_get_browser_from_registry() -> Optional[str]:
146
- """Get the default web browser executable path on Windows."""
147
- # Import winreg only on Windows platforms
148
- if not sys.platform.startswith("win"):
149
- return None
150
-
151
- try:
152
- import winreg # pylint: disable=import-outside-toplevel
153
- except ImportError:
154
- log.debug("winreg module not available")
155
- return None
156
-
157
- def get_reg(base, path, key=None):
158
- """Helper function to read a registry key."""
159
- try:
160
- with winreg.OpenKey(base, path) as reg:
161
- return winreg.QueryValueEx(reg, key)[0]
162
- except FileNotFoundError:
163
- return None
164
-
165
- def extract_executable(cmd: str) -> Optional[str]:
166
- """Extract the executable path from a command string."""
167
- match = re.match(r'"?([^"]+)"?', cmd)
168
- return match.group(1) if match else None
169
-
170
- def get_user_preferred_browser():
171
- """Get the user preferred browser from the registry."""
172
- progid = get_reg(
173
- winreg.HKEY_CURRENT_USER,
174
- r'Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice',
175
- 'ProgId'
176
- )
177
- if not progid:
178
- log.debug('No user preferred browser found in registry')
179
- return None
180
-
181
- browser_path = get_reg(
182
- winreg.HKEY_CLASSES_ROOT,
183
- f'{progid}\\shell\\open\\command'
184
- )
185
-
186
- if not browser_path:
187
- log.debug(f'progid {progid} does not have a command in registry')
188
- return None
189
-
190
- return extract_executable(browser_path)
191
-
192
- def get_system_default_browser():
193
- """Get the system default browser from the registry."""
194
- reg = get_reg(
195
- winreg.HKEY_CLASSES_ROOT,
196
- r'http\shell\open\command'
197
- )
198
- if not reg:
199
- log.debug('No system default browser found in registry')
200
- return None
201
-
202
- return extract_executable(reg)
203
-
204
- user_browser = get_user_preferred_browser()
205
- if user_browser:
206
- return extract_executable(user_browser)
207
-
208
- system_browser = get_system_default_browser()
209
- if system_browser:
210
- return extract_executable(system_browser)
@@ -1,74 +0,0 @@
1
- lanscape/__init__.py,sha256=YVrshFIK9GR9JrtpvJSg3BmsYcffuAdXJVxCoRCGmTE,355
2
- lanscape/__main__.py,sha256=PuY42yuCLAwHrOREJ6u2DgVyGX5hZKRQeoE9pajkNfM,170
3
- lanscape/libraries/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- lanscape/libraries/app_scope.py,sha256=EqYQRQcbjOPPcIOhFkIepcz2cKHmoUHxWj2JSoRJmzk,2542
5
- lanscape/libraries/decorators.py,sha256=SoNqfEInPyL-rrUKY6njK5d6Mwqu7Ix6He-BZRu2VKQ,5394
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=nIvOV_qYXmWIBYEd5PqWH1Mkadg3I1T0vbcHPkzlw6I,15853
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=IOtwAaiy_f1r1KcsyTUVurOmo3kUmWdquAxWh8Gv39A,8329
15
- lanscape/libraries/service_scan.py,sha256=ZF4LL2gSI0T5oYEMjc8pCVtJkV1KIk4xP-AeEAkSdLc,1944
16
- lanscape/libraries/subnet_scan.py,sha256=lL2LzuxoTgPyvsdkPPEcZDqQPbCAGMHAjoX2slKGUKc,14136
17
- lanscape/libraries/version_manager.py,sha256=fIAv6bVHb_VCOrqT8Do53trxwEgR2mnZV82v3YGxJ14,2944
18
- lanscape/libraries/web_browser.py,sha256=23MuGIrBYdGhw6ejj6OWxwReeKIlWhtWukc1dKV_3_0,6736
19
- lanscape/resources/mac_addresses/convert_csv.py,sha256=hvlyLs0XmuuhBuvXBNRGP1cKJzYVRSf8VfUJ1VqROms,1189
20
- lanscape/resources/mac_addresses/mac_db.json,sha256=Lng2yJerwO7vjefzxzgtE203hry1lIsCadHL1A5Rptg,2136137
21
- lanscape/resources/ports/convert_csv.py,sha256=MMLDa-5pGMsn4A2_k45jHsRYffrRY_0Z2D1ziiikeQA,1143
22
- lanscape/resources/ports/full.json,sha256=O8XBW52QvEVSGMQDbXe4-c4qq6XAecw6KJW4m2HkTLo,1441444
23
- lanscape/resources/ports/large.json,sha256=CzlCcIGCBW1QAgjz4NDerCYA8HcYf6lNxehh7F928y0,138410
24
- lanscape/resources/ports/medium.json,sha256=T5Rc7wa47MtroHxuZrHSftOqRWbQzhZULJdE1vpsTvU,3518
25
- lanscape/resources/ports/small.json,sha256=F_lo_5xHwHBfOVfVgxP7ejblR3R62SNtC1Mm33brhYc,376
26
- lanscape/resources/services/definitions.jsonc,sha256=4k7XnqIpWr1xuF7EUMgZf7y6aVDxOL_if7GGsT-JEuY,8387
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=883puFTHePUEgwS4a2-Co6-gdLwr5NbOx0goUck7054,3571
38
- lanscape/ui/static/lanscape.webmanifest,sha256=07CqA-PQsO35KJD8R96sI3Pxix6UuBjijPDCuy9vM3s,446
39
- lanscape/ui/static/css/style.css,sha256=O2BA0DiLlXYe_wLxM_uzrCc1VjV_SxSWQEHLCghy_0A,17598
40
- lanscape/ui/static/img/ico/android-chrome-192x192.png,sha256=JmFT6KBCCuoyxMV-mLNtF9_QJbVBvfWPUizKN700fi8,18255
41
- lanscape/ui/static/img/ico/android-chrome-512x512.png,sha256=88Jjx_1-4XAnZYz64KP6FdTl_kYkNG2_kQIKteQwSh4,138055
42
- lanscape/ui/static/img/ico/apple-touch-icon.png,sha256=tEJlLwBZtF4v-NC90YCfRJQ2prTsF4i3VQLK_hnv2Mw,16523
43
- lanscape/ui/static/img/ico/favicon-16x16.png,sha256=HpQOZk3rziZjT1xQxKuy5WourXsfrdwuzQY1hChzBJQ,573
44
- lanscape/ui/static/img/ico/favicon-32x32.png,sha256=UpgiDPIHckK19udHtACiaI3ZPbmImUUcN1GcrjpEg9s,1302
45
- lanscape/ui/static/img/ico/favicon.ico,sha256=rs5vq0MPJ1LzzioOzOz5aQLVfrtS2nLRc920dOeReTw,15406
46
- lanscape/ui/static/img/ico/site.webmanifest,sha256=ep4Hzh9zhmiZF2At3Fp1dQrYQuYF_3ZPZxc1KcGBvwQ,263
47
- lanscape/ui/static/js/core.js,sha256=J37LcjchyiNirSkicraoWr-TsW2QeQX_zUwo5mGMmoM,1073
48
- lanscape/ui/static/js/layout-sizing.js,sha256=U2dsyJi-YKpOpudu3kg2whiU4047ghzDTY3ExYUhpPs,810
49
- lanscape/ui/static/js/main.js,sha256=zCT_4Vql-XzmoMq9fDjC1p4W8WowjIuctwNJ2ymeonI,6538
50
- lanscape/ui/static/js/on-tab-close.js,sha256=3icxYWlLpY81iLoW7kQTJeWQ3UnyyboG0dESHF2wLPQ,1376
51
- lanscape/ui/static/js/quietReload.js,sha256=8POH0t1KVzGCJas9fNsOVbBG-ULwZT2wiS14URgkeAU,702
52
- lanscape/ui/static/js/scan-config.js,sha256=EOPo-0liYn3UPuhm2kaQrT7G-UumxQ25_rh1c1DaTj4,6021
53
- lanscape/ui/static/js/shutdown-server.js,sha256=Mx8UGmmktHaCK7DL8TVUxah6VEcN0wwLFfhbCId-K8U,453
54
- lanscape/ui/static/js/subnet-info.js,sha256=osZM6CGs-TC5QpBJWkNWCtXNOKzjyIiWKHwKi4vlDf8,559
55
- lanscape/ui/static/js/subnet-selector.js,sha256=2YKCAuKU2Ti1CmJrqi4_vNTD2LQbxx7chIDqND_1eAY,358
56
- lanscape/ui/templates/base.html,sha256=cnKU-kHUBpt6Xg4gPLE4dWkcXr3H-K4Vz1Im8xDKdOQ,1448
57
- lanscape/ui/templates/error.html,sha256=bqGJbf_ix9wtpUlXk5zvz_XyFpeTbEO-4f0ImgLtUGk,1033
58
- lanscape/ui/templates/info.html,sha256=gu8SGFUaFQc46Rm4TkZD8HM4Tnls-ZWsJ0FJNhx9wEs,2545
59
- lanscape/ui/templates/main.html,sha256=ubxKUQcWQ27A0YpvBgj6AnIqgVSfW3exYXyn7EgrKJM,3895
60
- lanscape/ui/templates/scan.html,sha256=00QX2_1S_1wGzk42r00LjEkJvoioCLs6JgjOibi6r20,376
61
- lanscape/ui/templates/shutdown.html,sha256=iXVCq2yl5TjZfNFl4esbDJra3gJA2VQpae0jj4ipy9w,701
62
- lanscape/ui/templates/core/head.html,sha256=eZiebt24xYd_NALe-fFL25rb4uFjUrF4XJjxFH61MgM,779
63
- lanscape/ui/templates/core/scripts.html,sha256=rSRi4Ut8iejajMPhOc5bzEz-Z3EHxpj_3PxwwyyhmTQ,640
64
- lanscape/ui/templates/scan/config.html,sha256=WK0kOq7EintAvch8ospSofFLYB3qCmQ4i-xnVOj-4l0,11376
65
- lanscape/ui/templates/scan/export.html,sha256=Nvs_unojzT3qhN_ZnEgYHou2C9wqWGr3dVr2UiLnYjY,749
66
- lanscape/ui/templates/scan/ip-table-row.html,sha256=RANDsfW4xBATdtiLrxUlRouFSjgwetZqdzH-MJgj2mE,4740
67
- lanscape/ui/templates/scan/ip-table.html,sha256=CP7AG8WHOgy3AyYCIN0wA2wO6n0H1X0F9IOncQtpPvE,914
68
- lanscape/ui/templates/scan/overview.html,sha256=xWj9jWDPg2KcPLvS8fnSins23_UXjKCdb2NJwNG2U2Q,1176
69
- lanscape/ui/templates/scan/scan-error.html,sha256=wmAYQ13IJHUoO8fAGNDjMvNml7tu4rsIU3Vav71ETlA,999
70
- lanscape-1.3.8a1.dist-info/licenses/LICENSE,sha256=VLoE0IrNTIc09dFm7hMN0qzk4T3q8V0NaPcFQqMemDs,1070
71
- lanscape-1.3.8a1.dist-info/METADATA,sha256=i4IgCfXfa-omCT8BHlfD8anoaH8jHeUuqCmY3XPlI5o,3123
72
- lanscape-1.3.8a1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
73
- lanscape-1.3.8a1.dist-info/top_level.txt,sha256=E9D4sjPz_6H7c85Ycy_pOS2xuv1Wm-ilKhxEprln2ps,9
74
- lanscape-1.3.8a1.dist-info/RECORD,,
File without changes
File without changes
File without changes
File without changes
File without changes