Repository: nvaccess/nvda

Issue:
Core: Don't Refuse to Start if Add-On Manifest is Missing
STR:

1. Download the OCR add-on, and install using the Add-Ons Manager.
2. Restart NVDA with all add-ons disabled, and remove everything within the "ocr" directory (but not the directory itself) from within the "nvda" data directory.
3. Restart NVDA; you should note that it refuses to launch, and outputs something like the following in the log:

```
INFO - __main__ (13:35:20.844):
Starting NVDA
INFO - core.main (13:35:21.078):
Config dir: C:\Users\Username\AppData\Roaming\nvda
INFO - config.ConfigManager._loadConfig (13:35:21.078):
Loading config: C:\Users\Username\AppData\Roaming\nvda\nvda.ini
INFO - core.main (13:35:21.128):
NVDA version next-14528,b476430a
INFO - core.main (13:35:21.128):
Using Windows version 10.0.15063 workstation
INFO - core.main (13:35:21.128):
Using Python version 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:42:59) [MSC v.1500 32 bit (Intel)]
INFO - core.main (13:35:21.128):
Using comtypes version 0.6.2
CRITICAL - __main__ (13:35:21.134):
core failure
Traceback (most recent call last):
  File "nvda.pyw", line 202, in <module>
  File "core.pyc", line 202, in main
  File "addonHandler.pyc", line 124, in initialize
  File "addonHandler.pyc", line 74, in completePendingAddonRemoves
  File "addonHandler.pyc", line 215, in __init__
IOError: [Errno 2] No such file or directory: u'C:\\Users\\Username\\AppData\\Roaming\\nvda\\addons\\ocr\\manifest.ini'
```


Discussion:
Though it is quite an unusual and unsupported way to destroy an add-on this way, it is indeed quite drastic and probably not very difficult to fix. I'd suggest a p3.
Hi, either we can use a try/except test and ignore the add-on, or let the add-on user know about this fact. This also means future add-on update will not work either. Thanks.

What about the old dodge of putting a home made app module manually in to 
see if it fixes a problem with a program?
 Brian
This actually occurred after removing an add-on via the Add-Ons Manager, but for whatever reason the main directory wasn't removed at which point I received the error detailed in the issue description.
I agree with P3. One thing that is probably worth thinking about, is how resolving this will impact an add-on developer. One thing that is good about the current behaviour, is that it's clear that there is a problem.
What is a p3 ?
Hi, priority level 3, usually assigned for minor changes. Thanks.

 

From: Vishesh <notifications@github.com> 
Sent: Sunday, March 10, 2019 10:40 AM
To: nvaccess/nvda <nvda@noreply.github.com>
Cc: Joseph Lee <joseph.lee22590@gmail.com>; Comment <comment@noreply.github.com>
Subject: Re: [nvaccess/nvda] Core: Don't Refuse to Start if Add-On Manifest is Missing (#7686)

 

What is a p3 ?

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub <https://github.com/nvaccess/nvda/issues/7686#issuecomment-471327113> , or mute the thread <https://github.com/notifications/unsubscribe-auth/AHgLkCBloYvsI8oT4leS5-lelOGpehkBks5vVUN7gaJpZM4QDVPr> .


Oh gotcha thanks.

Resolving patch:
diff --git a/source/addonHandler/__init__.py b/source/addonHandler/__init__.py
--- a/source/addonHandler/__init__.py
+++ b/source/addonHandler/__init__.py
@@ -181,26 +181,29 @@ def _getAvailableAddonsFromPath(path):
 		if p.endswith(DELETEDIR_SUFFIX): continue
 		addon_path = os.path.join(path, p)
 		if os.path.isdir(addon_path) and addon_path not in ('.', '..'):
-			log.debug("Loading add-on from %s", addon_path)
-			try:
-				a = Addon(addon_path)
-				name = a.manifest['name']
-				log.debug(
-					"Found add-on {name} - {a.version}."
-					" Requires API: {a.minimumNVDAVersion}."
-					" Last-tested API: {a.lastTestedNVDAVersion}".format(
-						name=name,
-						a=a
-					))
-				if a.isDisabled:
-					log.debug("Disabling add-on %s", name)
-				if not isAddonCompatible(a):
-					log.debugWarning("Add-on %s is considered incompatible", name)
-					_blockedAddons.add(a.name)
-				yield a
-			except:
-				log.error("Error loading Addon from path: %s", addon_path, exc_info=True)
-
+			if not len(os.listdir(addon_path)):
+				log.error("Error loading Addon from path: %s", addon_path)
+			else:
+				log.debug("Loading add-on from %s", addon_path)
+				try:
+					a = Addon(addon_path)
+					name = a.manifest['name']
+					log.debug(
+						"Found add-on {name} - {a.version}."
+						" Requires API: {a.minimumNVDAVersion}."
+						" Last-tested API: {a.lastTestedNVDAVersion}".format(
+							name=name,
+							a=a
+						))
+					if a.isDisabled:
+						log.debug("Disabling add-on %s", name)
+					if not isAddonCompatible(a):
+						log.debugWarning("Add-on %s is considered incompatible", name)
+						_blockedAddons.add(a.name)
+					yield a
+				except:
+					log.error("Error loading Addon from path: %s", addon_path, exc_info=True)
+				
 _availableAddons = collections.OrderedDict()
 def getAvailableAddons(refresh=False, filterFunc=None):
 	""" Gets all available addons on the system.


Test patch: