[nvda-addons] Re: Developing Addons - The best way to get started?

  • From: "Damien Sykes-Pendleton" <damien@xxxxxxxxxxxxxxxxxxxx>
  • To: <nvda-addons@xxxxxxxxxxxxx>
  • Date: Fri, 8 Apr 2016 15:51:26 +0100

Hi Joseph,
This is very helpful indeed, and already explains some of my confusions. I was thinking of an NVDA object as part of the physical interface design - a physical control on the screen was being converted to something else by NVDA so it could read it. I never linked it with object-oriented programming, because I have also heard of controls themselves, referred to as objects.
Having worked with other languages I am familiar with object-oriented programming (though I seem to remember Python somehow differentiated between classes and objects). Python also has other concepts not shared by some other languages such as list and dictionaries as opposed to arrays, packaged statements, packaged scripts and modules, its import statement I believe works slightly different to, for instance, an include preprocessor statement, and the way it works with classes seems different as well (take for instance the class of AppModule(appModuleHandler.AppModule) which I believe refers to a class inheritance, looks like it is inheriting from a class property instead of another class).
For the most part learning a new language has been easy for me, since its only difference is usually with syntactical differences, but Python seems to change more concepts than just syntax, hence the reason I find it more confusing.
I think that perhaps the other problem I am facing is that, because I generally wouldn't consider writing in Python in an everyday setting and thus would only use it for NVDA addons, and NVDA can automatically create the relevant files based on the source code, I haven't installed Python and therefore only have NVDA as a testing mechanism. I may be wrong, but I have thought before now that installing a whole component when you would possibly only use a minor percentage of it is rather pointless, especially if you then have to learn to run it as a full system. In this case Python, which relies on command line usage to run scripts, separate compilers to compile them to binary, and other dependencies for extra functionality etc. When it comes to NVDA, you also have these various unrelated subdependencies like Git, documentation and packaging systems which then start to go way above my head.
Kind regards,
Damien.
-----Original Message----- From: Joseph Lee
Sent: Friday, April 08, 2016 3:13 PM
To: nvda-addons@xxxxxxxxxxxxx
Subject: [nvda-addons] Re: Developing Addons - The best way to get started?

Hi,
May I offer some thoughts...
As James and others have pointed out, learning Python is essential, chiefly because NVDA's front end is written using Python (some parts of its back end are written in C++). When you write add-ons, you are effectively composing Python libraries NVDA will use as it runs. It could be as simple as announcing something (ui.message) when you press a key, or quite complex as some of the add-ons (SPL add-on (I'm the maintainer) is a very complex add-on, and it took me several days to explain its internals in my blog; these days, whenever I commit an important commit, I explain what I did in hopes that people would appreciate the work required to bring such an add-on to life).
As for object-oriented features: yes, you do need to know what classes, objects and modules are. This stems from the fact that GUI elements are objects (as far as NVDA sees them). Each control is an object (a class coming to life), such as a checkbox, a radio button, an edit field, a window or even the desktop. As these elements are objects, they hold various properties (termed attributes) such as name, handle (an opaque reference), type of object (MSAA, UIA, MSHTML and so on) and so forth. For some folks, writing an app module or a global plugin is equivalent to defining these classes and telling NVDA what to do (the other part is filtering various controls to make sure one is dealing with the right object).
As for documentation: I do know that we lack some important pieces of information, one of them being a series of articles detailing NVDA's internals (at a higher level). In order to write such docs, one needs to become familiar with NVDA source code and willing to investigate how NVDA Core does its job so well (you need to devote some months to study NVDA's code, and we're talking about ten years' worth of code changes). Let me give you an example of such a documentation:
Suppose you are working with an app module. Have you wondered how NVDA can locate an app module "magically"? The way it works is as follows (defined in appModuleHandler.py):
1. NVDA will keep an eye on events fired by apps (NVDA itself is event-driven).
2. If an event comes from an app that has just started, NVDA will look for its process ID (PID for short). This is a must, as the PID will be used as a key to a dictionary that records app modules in use and as the argument to be used when creating the app module (termed "constructing").
3. Once the PID is found, NVDA will look for the name of the executable associated with this PID. This is used to locate the corresponding app module and load it.
A more sophisticated scenario is as follows:
Have you wondered how configuration profiles work? Configuration profiles (the data structure itself; config.conf) uses an internal stack (a Python list) to manage profile switching routines. Whenever you use a profile associated with say all, an app-specific profile and so on, NVDA will push the profile for this context to the activation stack and will do the opposite (pop) when this profile is no longer needed. In reality, each profile is a collection of settings NVDA uses during its operation, and each profile records different settings (all but three can be profile-specific: general settings, upgrade notifications and update control). This is the inspiration behind broadcast profiles introduced in StationPlaylist Studio add-on 6.0 (last year, and I'm in the midst of designing a possible rewrite of how broadcast profiles are stored internally as part of add-on 8 or later, using a module located at Python Package Index (PyPI for short)).
As you can see, learning Python is an important aspect of writing add-ons (and in extension, when writing changes to NVDA screen reader itself). Also, if you are writing complex add-ons, it is vital that you understand how NVDA works (at least at a glance) so you can take advantage of this (one of the most interesting one being support for audio ducking by various speech synthesizers, and some synth developers have started working on this as we speak).
In regards to integrating Python and NVDA concepts together: in my opinion, one of the best strategies is writing code and seeing how Python concepts apply in NVDA Core and add-on code. Of course you do need to become familiar with concepts by writing actual Python code, and you also need to find a way to say, "aha, NVDA uses this Python concept in this interesting way". In theory you can write an add-on using a boiler plate and without knowing what classes are, but I think it is important that people should "sweat a little" when coming up with interesting add-ons (ultimately, your add-on could be used by anyone).
Lastly, although not spelled out here, I'd like to take a moment to stress something not many may have thought about: I think, often beginners worry too much about code to notice that they are going nowhere, or concentrate too much on making their code perfect and neglect design decisions. Seasoned add-on writers such as Mick, Jamie, Noelia, I and others can tell the quality of an add-on and its potential (and power) by examining source code, such as whether an add-on would be embraced by many, design problems and so on. The other day we had to ask an add-on author to "rephrase" the solution due to inconsistencies in code and due to what I would term "big picture assumptions" - assumptions that worked well for this author but not for others (for this reason, one of the things I do when designing new features is ask "what if" questions a lot as part of requirements analysis and design). In short, as a community add-ons reviewer, what I look for the most is not the complexity of the code or tricks the add-on employs, but the overall design (and more recently, user interface such as GUI's, messages to be presented to the user and so on).
I do understand that, at times, we don't know how to translate what's going on in our heads to actual artifact (code). When this happens, don't rush, don't strive for perfection, and ready to say you need help. Also, you do need to take some breaks so that what you've learned can sink in. Lastly, you should be willing to explain what's going on in your add-on and be ready to defend your position - after all, add-on construction is like writing an essay (I think not many computer science students and programmers realize this).
Regarding my last point: this can be extended to NVDA Core itself: when you do write a feature to be included into NVDA Core, you are effectively writing an essay or a part of a story NVDA seeks to impart: equal access to technology. Because NVDA has become part of lives of over a hundred thousand people, it is vital to remember that design matters (for this reason, Mick, Jamie, I, Derek and many others will not code until we explain our "essay" outline, and this is one of the reasons why NVDA developers have instituted code reviews for NVDA Core and add-on code; the current status of code reviews deserves a thread of its own, part of it being that we need more code reviewers for NVDA Core).
Hope this helps.
Cheers,
Joseph


-----Original Message-----
From: nvda-addons-bounce@xxxxxxxxxxxxx [mailto:nvda-addons-bounce@xxxxxxxxxxxxx] On Behalf Of Damien Sykes-Pendleton
Sent: Friday, April 8, 2016 4:56 AM
To: nvda-addons@xxxxxxxxxxxxx
Subject: [nvda-addons] Re: Developing Addons - The best way to get started?

Hi James,
Again. This proves just how much, or little, knowledge I have on this subject. I always assumed that the information that NVDA uses to evaluate the functionality or purpose of a control was through the Windows API. When I wrote my first addon that didn't involve copying and pasting from an example, it was to read content that NVDA didn't recognise on its own for whatever reason, that other screen readers did. This didn't work. My theory for this is that I was pretty much guessing what I had to do to get it to work, and of course that is not the way to understand your own code. It helps to understand what your code needs to do, something of which I understood very little, if not nothing at all. If you can't understand that, you need to be able to understand what you want to do. Although I know what I want to do in terms of functionality, translating that into code is very difficult, given that I don't know about all the underlying structures such as in-depth control information (ID, handle, class etc), NVDA objects, accessibility platforms, the list goes on and on.
As for learning Python itself, this is not so much the problem as remembering every single thing I'm reading. When I look at a Python tutorial, I'm thinking, yes this makes sense. Sounds good to me. Oh wow, I've finished the tutorial. Let's go back to addons. Oh wait, what did the tutorial say about this? I don't remember that part...Look back at the tutorial. Oh, it's not in here. This must be an NVDA specific reference.
Either that, or, Ah yes, I remember this now. Now how was the addon guide referencing this?
I'm trying to explain it the best way I can, because there isn't one specific example or situation that I can pinpoint without referencing something else, it's all linked, hence the massive confusion which, if we're talking code, is making my brain go into an infinite loop.
Kind regards,
Damien.
-----Original Message-----
From: James Scholes
Sent: Friday, April 08, 2016 12:25 PM
To: nvda-addons@xxxxxxxxxxxxx
Subject: [nvda-addons] Re: Developing Addons - The best way to get started?

Replies inline.

Damien Sykes-Pendleton wrote:

Well if we're constraining ourselves to the facts, I can only really
say what I have said before, in that the developer guide assumes a
good working knowledge of Python and NVDA's internal workings, neither
of which I feel I have enough of to really get going.

First, tackle Python. You need a good, working knowledge of the language to write NVDA add-ons. This will never change, no matter how much documentation is written. Create some small Python projects which make use of object-oriented programming, inheritance, wxPython.

It is incredibly important to understand that creating NVDA add-ons is not at all like writing JAWS scripts. With JAWS scripting, the language is proprietary and the creators of that language decide in advance what functionality you have access to. NVDA not only gives you the full power of the Python language, but also lets you write code which runs in the same environment as NVDA's core, meaning that you can literally do whatever you like, only constrained by your imagination and knowledge.
Naturally, this provides a lot of room for error, so NVDA add-on writing often comes with a lot of responsibility. That is why there is a higher barrier to entry. It's up to you to decide whether that barrier is worth scaling or not. But nobody, on this list or otherwise, will ever be able to create documentation that explains every possible aspect of creating NVDA add-ons. Having said that, the community has created some extra documentation, which I will leave it up to them to share.

I have looked into Python, both on the official language tutorial and
from Learn Python the Hard Way. Although these are both good
resources, they are also very extensive to the point that by the time
I have read them and gone back to the developer guide, I'm trying to
conceptualise everything else into Python terms rather than NVDA terms

I'm not entirely sure what you mean here. NVDA is Python. Granted, to write a good add-on, you have to be aware of some of NVDA's internals, but really, you need to give us examples of what you're trying to do and why it's posing a problem. If you have a good understanding of Python as I said above, writing NVDA add-on boilerplate will be easy.

some of which can be done but easily forgotten, or others which can't
be done at all.

Again, I have no idea what you mean. What Python features, functionality or concepts are you having difficulty translating into valid concepts to be used in an NVDA add-on?

Then, as I have also said before, there is the vagueness of
references, such as "Refer to the NVDA code documentation". I cannot
find this documentation anywhere, even in the NVDA source code.

If you check out the NVDA source code and read the accompanying readme files, you will see instructions on generating the NVDA code documentation. You can also browse an online copy, although I don't think it's updated on a regular basis, at:
https://files.derekriemer.com/nvda/module-tree.html

Honestly though, I think most NVDA developers will tell you that reading the code itself is usually better than the documentation. If you're hoping that the code documentation will shine a light on everything that has hitherto seemed confusing, you'll be seriously disappointed. The code documentation is constructed from Python docstrings. It's a terse reference, not a guide.

Even so, I doubt I'd be able to glean much from it, since NVDA has a
lot of in-depth interaction with the operating system which, when it
comes to development, I know hardly anything about the workings of.
This then also adds the Windows API to my reference list, and now I
feel like I am on a road of information overload.

Any portions of the Windows API that are used by NVDA have already been wrapped as simple Python functions for use in higher level abstractions.
Unless you need to use a part of it that hasn't already been defined as such, you don't need to understand the ins and outs of that.
Additionally, it's highly unlikely that, for your first add-ons, you'll even need to use such functionality. Rather, you'll interact with the abstractions that NVDA provides.

To sum up:
1. Learn Python. If you don't know the language, if you can't write scripts or small programs in it, you will have a hard time writing code for NVDA.
2. Get familiar with reading other people's Python code. You'll be doing a lot of that if you want to create high quality add-ons.
3. Give us examples of things you're finding hard. We don't need an article, we just need you to explain what you don't understand so we can point you in the right direction.
4. Don't run before you can walk. If you're struggling with how to create the most basic of add-ons, the Windows API isn't even a distant concern.
--
James Scholes
http://twitter.com/JamesScholes
----------------------------------------------------------------
NVDA add-ons: A list to discuss add-on code enhancements and for reporting bugs.

Community addons are available from: http://addons.nvda-project.org To send a message to the list: nvda-addons@xxxxxxxxxxxxx To change your list settings/unsubscribe:
//www.freelists.org/list/nvda-addons
To contact list moderators: nvda-addons-moderators@xxxxxxxxxxxxx

----------------------------------------------------------------
NVDA add-ons: A list to discuss add-on code enhancements and for reporting bugs.

Community addons are available from: http://addons.nvda-project.org To send a message to the list: nvda-addons@xxxxxxxxxxxxx To change your list settings/unsubscribe: //www.freelists.org/list/nvda-addons
To contact list moderators: nvda-addons-moderators@xxxxxxxxxxxxx

----------------------------------------------------------------
NVDA add-ons: A list to discuss add-on code enhancements and for reporting bugs.

Community addons are available from: http://addons.nvda-project.org
To send a message to the list: nvda-addons@xxxxxxxxxxxxx
To change your list settings/unsubscribe: //www.freelists.org/list/nvda-addons
To contact list moderators: nvda-addons-moderators@xxxxxxxxxxxxx
----------------------------------------------------------------
NVDA add-ons: A list to discuss add-on code enhancements and for reporting bugs.
Community addons are available from: http://addons.nvda-project.org
To send a message to the list: nvda-addons@xxxxxxxxxxxxx
To change your list settings/unsubscribe: 
//www.freelists.org/list/nvda-addons
To contact list moderators: nvda-addons-moderators@xxxxxxxxxxxxx

Other related posts: