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

  • From: Alex Hall <ahall@xxxxxxxxxxxx>
  • To: nvda-addons@xxxxxxxxxxxxx
  • Date: Fri, 8 Apr 2016 11:07:18 -0400

An object is just an instance of a class in Python, same as other OOP
languages. The main difference in Python is that it treats everything
like an object, letting you pass, say, an entire function to another
function as a parameter, because the passed-in function is itself an
object.

You absolutely must install Python on your system. Technically, yes,
NVDA will run your add-ons. But the value of practicing Python cannot
be overstated. Once you really see how importing, declaring things,
and other aspects work, you'll have a much easier time with add-ons.
For example, importing AppModuleHandler and then making a class that
inherits from AppModuleHandler.AppModule is plain as day to me, not
because I know NVDA development, but because I know Python. I see that
code and immediately know that somewhere in the AppModuleHandler file
is
class AppModule(something):
because that's just how Python works. When you import, you get access
to everything in the imported file (no private methods or variables
here). Thus, you can access them by using dot syntax, such as
importedFile.itemYouWant. Because you're making a class in your
example, the stuff in the parentheses has to be itself a class, so I
know exactly what's going on.

I'm not saying that I can then take that understanding and go make an
add-on. What I'm saying is that having a solid grasp of Python is
vital; once you can see what's going on by reading code, source or
example, you've removed a huge obstacle. Knowing the concepts of NVDA
is hard enough, but trying to learn them while trying to learn Python
at the same time is twice as hard. As others have said, you should
learn Python itself first, *then* tackle add-ons. Since you know other
languages, what I would do is pick a language you know well and make a
relatively simple program in that. Then, try to make the exact same
program, but in Python. See how it works, see where Python makes
things easier or requires more work, and use the experience to get to
know Python's handling of classes, inheritance, parameters,
constructors, and everything else.

On 4/8/16, Damien Sykes-Pendleton <damien@xxxxxxxxxxxxxxxxxxxx> wrote:

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

----------------------------------------------------------------
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: