
I'm thinking about defining a few classes for the interview I'm working on. 1) DiscoveryRequest 2) Interrogatory - inherits from Discovery 3) InterrogatoryList? 4) DocumentRequest - inherits from Discovery 5) DocumentRequestList? The objects should have a few properties: "Checked" to indicate if it should be shown in the template, "Name", and "Description" to be used in the interview when showing a summary of the discovery that the system recommends the user to select. For Interrogatorys, they should each have a Priority. There should be a method for the InterrogatoryList class that displays only the 30 highest priority interrogatories to comply with discovery limits. In the interview, I'd like to pre-define the 85 discovery requests with the name and description (I think as a source file?). I'll also have a list that links each discovery request to a true/false interview variable. There can be a many-to-many relationship between the claims and the discovery request that's relevant to the claim. I'm building the table with two columns right now in Google Sheets, but my plan was to convert it to a format usable in DocAssemble. The example on the website for a custom object doesn't define any properties, only the methods. I looked at the classes you've already defined in /docassemble_base/docassemble/base/util.py and it looks like again, mostly it's just the methods you've defined. I only have a thought for one method so far. Is there any real benefit for me to define a new class for this example use? Would it make more sense to just use the built-in DAObject and specify the properties as I go along? Quinten Steenhuis Senior Attorney Network Administrator Greater Boston Legal Services 197 Friend St Boston, MA 02114 (617) 603-1553 F: (617) 371-1222 Qsteenhuis@GBLS.org

Hi, I don't have a very technical answer, but my experience with this question might be helpful. I did make a couple custom classes for an interview I worked on for a while, and ultimately I realized it was more trouble than it was worth. The custom classes became impossible to maintain. I couldn't unit test them in the Playground. When I was developing the interview locally and re-installing it after every change, it didn't make sense to clutter up my interview package with unit tests that couldn't run in docassemble. So I had my classes in a separate directory, and then I needed to copy them (yeesh) from where I was testing them into my docassemble package. And then I needed compress and upload the package, which is time consuming too. It was a very painful workflow. Eventually I gave up and figured out how to just use DAObjects and DAListObjects to define my objects with whatever properties I wanted them to have, and all the logic for manipulating them stayed in the interview. I use a lot of list comprehensions now. And I actually think the code is a lot easier to read. So the lesson I drew was that I'll try very hard not to attempt custom classes for future docassemble projects. On Fri, Sep 22, 2017 at 11:22 AM Steenhuis, Quinten <QSteenhuis@gbls.org> wrote:
I’m thinking about defining a few classes for the interview I’m working on.
1) DiscoveryRequest
2) Interrogatory – inherits from Discovery
3) InterrogatoryList?
4) DocumentRequest – inherits from Discovery
5) DocumentRequestList?
The objects should have a few properties: “Checked” to indicate if it should be shown in the template, “Name”, and “Description” to be used in the interview when showing a summary of the discovery that the system recommends the user to select. For Interrogatorys, they should each have a Priority. There should be a method for the InterrogatoryList class that displays only the 30 highest priority interrogatories to comply with discovery limits.
In the interview, I’d like to pre-define the 85 discovery requests with the name and description (I think as a source file?). I’ll also have a list that links each discovery request to a true/false interview variable. There can be a many-to-many relationship between the claims and the discovery request that’s relevant to the claim. I’m building the table with two columns right now in Google Sheets, but my plan was to convert it to a format usable in DocAssemble.
The example on the website for a custom object doesn’t define any properties, only the methods. I looked at the classes you’ve already defined in /docassemble_base/docassemble/base/util.py and it looks like again, mostly it’s just the methods you’ve defined. I only have a thought for one method so far. Is there any real benefit for me to define a new class for this example use? Would it make more sense to just use the built-in DAObject and specify the properties as I go along?
Quinten Steenhuis
Senior Attorney
Network Administrator
Greater Boston Legal Services
197 Friend St
Boston, MA 02114
(617) 603-1553
F: (617) 371-1222
Qsteenhuis@GBLS.org _______________________________________________ Docassemble mailing list docassemble@python.org https://mail.python.org/mm3/mailman3/lists/docassemble.python.org/

Thanks Nate, that’s exactly the kind of experience I was looking for. Do you have any examples of the list comprehensions that you use? A pointer to the file on GitHub would work. That sounds like an elegant functional way to do it. From: Nate Vogel [mailto:nathan.c.vogel@gmail.com] Sent: Friday, September 22, 2017 11:56 AM To: Steenhuis, Quinten <QSteenhuis@gbls.org>; docassemble@python.org Subject: Re: [Docassemble] When to define a custom class Hi, I don't have a very technical answer, but my experience with this question might be helpful. I did make a couple custom classes for an interview I worked on for a while, and ultimately I realized it was more trouble than it was worth. The custom classes became impossible to maintain. I couldn't unit test them in the Playground. When I was developing the interview locally and re-installing it after every change, it didn't make sense to clutter up my interview package with unit tests that couldn't run in docassemble. So I had my classes in a separate directory, and then I needed to copy them (yeesh) from where I was testing them into my docassemble package. And then I needed compress and upload the package, which is time consuming too. It was a very painful workflow. Eventually I gave up and figured out how to just use DAObjects and DAListObjects to define my objects with whatever properties I wanted them to have, and all the logic for manipulating them stayed in the interview. I use a lot of list comprehensions now. And I actually think the code is a lot easier to read. So the lesson I drew was that I'll try very hard not to attempt custom classes for future docassemble projects. On Fri, Sep 22, 2017 at 11:22 AM Steenhuis, Quinten <QSteenhuis@gbls.org<mailto:QSteenhuis@gbls.org>> wrote: I’m thinking about defining a few classes for the interview I’m working on. 1) DiscoveryRequest 2) Interrogatory – inherits from Discovery 3) InterrogatoryList? 4) DocumentRequest – inherits from Discovery 5) DocumentRequestList? The objects should have a few properties: “Checked” to indicate if it should be shown in the template, “Name”, and “Description” to be used in the interview when showing a summary of the discovery that the system recommends the user to select. For Interrogatorys, they should each have a Priority. There should be a method for the InterrogatoryList class that displays only the 30 highest priority interrogatories to comply with discovery limits. In the interview, I’d like to pre-define the 85 discovery requests with the name and description (I think as a source file?). I’ll also have a list that links each discovery request to a true/false interview variable. There can be a many-to-many relationship between the claims and the discovery request that’s relevant to the claim. I’m building the table with two columns right now in Google Sheets, but my plan was to convert it to a format usable in DocAssemble. The example on the website for a custom object doesn’t define any properties, only the methods. I looked at the classes you’ve already defined in /docassemble_base/docassemble/base/util.py and it looks like again, mostly it’s just the methods you’ve defined. I only have a thought for one method so far. Is there any real benefit for me to define a new class for this example use? Would it make more sense to just use the built-in DAObject and specify the properties as I go along? Quinten Steenhuis Senior Attorney Network Administrator Greater Boston Legal Services 197 Friend St Boston, MA 02114 (617) 603-1553<tel:(617)%20603-1553> F: (617) 371-1222<tel:(617)%20371-1222> Qsteenhuis@GBLS.org<mailto:Qsteenhuis@GBLS.org> _______________________________________________ Docassemble mailing list docassemble@python.org<mailto:docassemble@python.org> https://mail.python.org/mm3/mailman3/lists/docassemble.python.org/

If anyone ever finds themselves with a painful workflow, talk to me and I can suggest (or code) alternatives. In the situation described (running unit tests on a Python module on a machine separate from the docassemble server), I can think of many possible workflows that do not involve copying files or working with zip files. There are features in the Playground and elsewhere that facilitate a variety of workflows, such as pushing to/pulling from GitHub, and Google Drive integration. In the documentation I have a page that describes a variety of workflows <https://docassemble.org/docs/development.html>, and there are many possible workflows that I have not yet written up. As for Quinten's question about whether to use custom classes, I think declaring custom object types is an excellent idea, even if the class is nothing more than: class InterrogatoryList(DAList): pass Because when your interview code says, e.g., objects: - eviction_rogs: InterrogatoryList then this *means something*. You can write documentation about what the attributes of an InterrogatoryList are and what they mean and how they should be used. And the module that defines InterrogatoryList can be used in different interviews in different packages. At a national level, the community can collaborate around best practices for managing lists of interrogatories. So InterrogatoryList could be an incredibly important object even if its only content is pass. And maybe its content wouldn't stay empty for long. A developer in a different jurisdiction could do a pull request and add some methods to it. A useful method might be __str__(), so that when you refer to ${ eviction_rogs } in a Mako template, a list of interrogatories appears in a standardized, attractive format. Or you could have methods that do things differently depending on the jurisdiction and the type of case. All kinds of complicated things could be done with lists of interrogatories, and the interview authors who use the InterrogatoryList object would never need to look at the source code of these complex functions; they would just read the documentation and invoke the methods. This is how computer programmers can make "coding the law" accessible to a wider audience of lawyers -- by hiding complexity behind simple APIs. But if we always work with low-level objects like DAList, we aren't doing anything to hide complexity behind convenient interfaces, and we aren't working together to make "coding the law" more accessible. If you want an object to have default attributes, you can do something like this in your interview: --- generic object: Interrogatory code: x.priority = 0 --- But what if you develop six other interviews that use the Interrogatory object; should you have to copy over this code block into each interview? If it is universally useful to have that default attribute, why not put the code in the module, and make all your interview files shorter? class Interrogatory(Discovery): def init(self, *pargs, **kwargs): self.priority = 0 return super(Interrogatory, self).init(*pargs, **kwargs) For me, the main logistical downside of putting code in modules is that you have to wait for the web server to restart every time you change a module file. This is because the code of each loaded module becomes embedded in each of the threads of the web server. While that is efficient for saving CPU cycles, it does mean that the web server needs to restart if the modules change. As for the question of how to bring the content of a Google Sheet into an interview, I have an objects_from_file() command that could be used, but I think the most convenient thing might be for me to write a convenience function that works as a front end to csv.DictReader() <https://docs.python.org/2/library/csv.html#csv.DictReader> so that you could put CSV files in the Sources folder and then write code to read the files as a list of dicts, and construct the objects with code. In many cases, data are is easier to maintain as tables in a spreadsheet than as "structured data." (On a development server, you could write code to talk to Google Sheets directly, but I don't think that is a good idea in production...) I would recommend giving each claim and each discovery request a short code name, and then these code names could be the keys of dicts that map key names to actual objects. As for list comprehensions <http://www.secnetix.de/olli/Python/list_comprehensions.hawk>, I like writing list comprehensions too because I find they make it easier for me to read my own code, but often when I try to read other people's list comprehensions, they just make my head hurt. If the audience for readability is other people, a more readable alternative may be to substitute a variable in place of the list comprehension and then write a short code block that defines that variable (as a list() or whatever) and uses a for loop to build it. The variable name itself is helpful because it conveys to the reader what the variable means, whereas if all you can see is the inline list comprehension, you have to figure out the meaning from the code. Also, one of my goals when I write docassemble interviews is to try to make sure that it is readable by people who may only have a rudimentary knowledge of Python. I might be wrong, but I get the impression that list comprehensions are a relatively advanced technique. On Fri, Sep 22, 2017 at 1:09 PM, Steenhuis, Quinten <QSteenhuis@gbls.org> wrote:
Thanks Nate, that’s exactly the kind of experience I was looking for.
Do you have any examples of the list comprehensions that you use? A pointer to the file on GitHub would work. That sounds like an elegant functional way to do it.
*From:* Nate Vogel [mailto:nathan.c.vogel@gmail.com] *Sent:* Friday, September 22, 2017 11:56 AM *To:* Steenhuis, Quinten <QSteenhuis@gbls.org>; docassemble@python.org *Subject:* Re: [Docassemble] When to define a custom class
Hi,
I don't have a very technical answer, but my experience with this question might be helpful. I did make a couple custom classes for an interview I worked on for a while, and ultimately I realized it was more trouble than it was worth.
The custom classes became impossible to maintain. I couldn't unit test them in the Playground. When I was developing the interview locally and re-installing it after every change, it didn't make sense to clutter up my interview package with unit tests that couldn't run in docassemble. So I had my classes in a separate directory, and then I needed to copy them (yeesh) from where I was testing them into my docassemble package. And then I needed compress and upload the package, which is time consuming too. It was a very painful workflow.
Eventually I gave up and figured out how to just use DAObjects and DAListObjects to define my objects with whatever properties I wanted them to have, and all the logic for manipulating them stayed in the interview. I use a lot of list comprehensions now. And I actually think the code is a lot easier to read.
So the lesson I drew was that I'll try very hard not to attempt custom classes for future docassemble projects.
On Fri, Sep 22, 2017 at 11:22 AM Steenhuis, Quinten <QSteenhuis@gbls.org> wrote:
I’m thinking about defining a few classes for the interview I’m working on.
1) DiscoveryRequest
2) Interrogatory – inherits from Discovery
3) InterrogatoryList?
4) DocumentRequest – inherits from Discovery
5) DocumentRequestList?
The objects should have a few properties: “Checked” to indicate if it should be shown in the template, “Name”, and “Description” to be used in the interview when showing a summary of the discovery that the system recommends the user to select. For Interrogatorys, they should each have a Priority. There should be a method for the InterrogatoryList class that displays only the 30 highest priority interrogatories to comply with discovery limits.
In the interview, I’d like to pre-define the 85 discovery requests with the name and description (I think as a source file?). I’ll also have a list that links each discovery request to a true/false interview variable. There can be a many-to-many relationship between the claims and the discovery request that’s relevant to the claim. I’m building the table with two columns right now in Google Sheets, but my plan was to convert it to a format usable in DocAssemble.
The example on the website for a custom object doesn’t define any properties, only the methods. I looked at the classes you’ve already defined in /docassemble_base/docassemble/base/util.py and it looks like again, mostly it’s just the methods you’ve defined. I only have a thought for one method so far. Is there any real benefit for me to define a new class for this example use? Would it make more sense to just use the built-in DAObject and specify the properties as I go along?
Quinten Steenhuis
Senior Attorney
Network Administrator
Greater Boston Legal Services
197 Friend St
Boston, MA 02114
(617) 603-1553
F: (617) 371-1222
Qsteenhuis@GBLS.org
_______________________________________________ Docassemble mailing list docassemble@python.org https://mail.python.org/mm3/mailman3/lists/docassemble.python.org/
_______________________________________________ Docassemble mailing list docassemble@python.org https://mail.python.org/mm3/mailman3/lists/docassemble.python.org/
participants (3)
-
Jonathan Pyle
-
Nate Vogel
-
Steenhuis, Quinten