How to re-render certain object descriptions with Sphinx docs? - python-sphinx

Using Sphinx's domain-aware ObjectDescriptions I can create fancy rendered documentation for them. For example:
.. py:function:: pyfunc()
Describes a Python function.
This renders the content in a nice way, and this works really well with module indices, references and so on. Cool so far!
Now, let's say I have that directive in a source document src/mymodule/functions.rst, and I have a bunch of text in src/guide/getting-started.rst, I can reference to the objects like
:py:func:`pyfunc`
Also cool!
Now, my actual question; Could I also tell the Sphinx writer to re-render the same documentation snippet for that object? To ease the user in not having to navigating away from the Getting Started page where I just want to include a single piece of content again.
What I've tried to do:
Simply copy the contents. This results in a warning that the object is defined multiple times, hurts the index and as a result references don't point to the "authoritative" place in your project, if unlucky. Not okay.
Document each object in its own file and then use .. include:: rel/path/to/pyfunc.rst in each document where I want to render it. As those includes are literal on ReST-level, this results in the same downsides as the option above. :-(
Thus, I'm looking for a solution where I would tell the renderer/writer of Sphinx to simply re-render the contents of a reference instead of producing a link. It should not add it to the index for a simple re-render.
I'm okay with a custom extension or a domain-specific custom solution - I'm already using my own custom domain, but I just used the general Python domain above as a well-known example.
Context for the use case: I'm building a Protobuf domain. Protobuf messages and enums are reused a lot and I would like to show the context of commonly reused objects inline on pages where this is useful to the reader. This means it is repeated over the whole project on purpose where it is deemed useful rather than navigating away all the time. Yet only the reference page should be "authoritative".

I've been successful with a dirty hack: abusing the XRef role logic. Cross-references in Sphinx render dynamically (e.g. Table 23) by producing arbitrary 'nodes'. By:
keeping a copy of the parent node during parsing in a custom Domain
registering a custom Sphinx/ReST XRef role to render a whole set of nodes (the saved parent node)
re-running the ReferencesResolver another time
... this basically does what I need. But yuck, it's rather ugly.
Working example I implemented in a Protobuf Domain extension.

Related

Using Page Objects vs Config Files in Selenium

I've been using Ruby Selenium-Webdriver for one of the automation scripts I'm developing and I'm being asked to use Page Objects, we use page objects a lot however for this application I am using CSV file instead, I have defined all the xpaths that I'm using in my application in a CSV file and I'm parsing that CSV file in my script to refer to those objects, I would like to know is there much of a difference in using a class for defining Page Objects or using a CSV file instead apart from performance concern? I believe using a CSV file will be an addon for us from configuration standpoint and will make it much easier to maintain, any suggestions on this?
Edit - In our use case, we're actually automating applications built on a cloud based tool, so basically all the applications share same design structure from HTML standpoint so we define xpath patterns in CSV and then we pass certain parameters to some custom methods that we've developed to generate xpath's automatically using the CSV instead of finding those manually as its overhead for us because we already know that all the applications will share similar xpath pattern for all elements.
Thanks
I think, POM is better than CSV approach. In POM, you put elements for a page in a separate class file. So, if any change is to make then it's easier to find where to change/maintain. Moreover, it won't get too messy as CSV file and you don't need to use extra utility function to parse those.
There is also a pageobjects gem that provides a set of libraries over and above webdriver/watir, simplifying the code.
Plus, why xpaths? Its one of the last recommended ways to identify an element.
As for the frameork aspect, csv should be more of a maintenance problem than PageObjects. Its the basic difference between text and code. You enforce Object oriented approach on your elements in PageObjects but that is not possible with csv.
In the best case scenario, you have created a column/separate sheets defining which page that element xpath belongs to. That sounds like an overhead. As your application / suite grows there can be thousands of elements. Imagine parsing/ manually updating a csv with that kind of data.
Instead in PageObjects, your elements will be restricted to the Page. Any changes to the app will also specify which elements may get impacted. Now, when define your element as an object in PageObject, rather than css, you also dont need to explicitly create your elements by reading the csv.
It completely depends on the application and the type of test you might perform.
Since it is an automated test script, you do not have to really worry about the performance of the script (it might take few more milli seconds to parse, which should be OK).
Maintaining all the elements identification properties & corresponding actions in a CSV file will make the maintenance easier and make the framework application independent which are nice. But maintaining your framework is bit difficult to make it more robust. Both approaches have its own pros and cons.
Refer to below posts [examples are in java - but you will get the idea]:
Keyword driven framework
Advanced Page Objects
Update:
If you like both, you can comeup with your implementation to easily integrate these too.
#ObjectRepository(src="/login.csv")
public class LoginPage{
private Map<String, WebElement> elements;
public void login(){
elements.get("username").sendKeys('');
elements.get("password").sendKeys('');
elements.get("signin").click();
}
}
Ie, define all the elements in a config file like csv/json etc. Let the page object refer to the class for the page elements. All the methods will be part of the page class.

Velocity IncludeEventHandler dilemma

Here is an interesting problem regarding the IncludeEventHandler.
I am developing a Spring-Based application which uses velocity which has different VENDORS having a separate portfolio site. I am letting vendors customize the pages by providing them the Velocity templates which are being stored the database and are picked up by the velocity engine using a DataSourceResourceLoader.
My table is organized like this.
The vendors may parse other templates by calling the macro #parse and passing their vendorid/template-name so that it looks like this.
#parse("20160109144/common-css.vm")
Now the actual problem is picking up the template according to vendorid.
I have a class (extending IncludeEventHandler) which overrides the includeEvent method. Now what can I do to return the desired template? I dont want to change the names and make them look like 20160109144/home.vm
With OP's question, the intent was to provide an alternate behavior to the DataSourceResourceLoader.
Unfortunately, the Velocity Engine version 1.7 doesn't have ability to change the SQL statement that is used to retrieve the template.
The DataSourceResourceLoader extends the ResourceLoader abstract class. That said, if you reference the source, you should be able to implement a custom ResourceLoader that behaves the way you want it to.
One option, glom most of the code from DataSourceResourceLoader and change the way it determines the template content to load from the database.
I would dump all of the query related material as you will be determining the specific columns you want to load for content. The DataSourceResourceLoader essentially maps the name of a template to a database entry and your implementation essentially revolves around the rules you've defined above.
Hopefully that can provide enough assistance to move forward. I would recommend pulling this in a debugger as well and determine what is and is-not passed in to the related load methods.

How to use ruby on rails to construct a scaffold that also contains a different scaffold that can be added to it multiple times?

I'm new to ruby on rails and in the efforts of "not repeating myself" in my code, I am trying to create a scaffold that contains one or more (decided by user) of a different scaffold. But I am lost and Im not sure that it can be done.
Example:
1. There is an "article" scaffold that contains "sections" along with standard information (title, date of article, main image, main topics, etc)
2. The "article" type can has_many "sections". Each section contains an order reference, header text and body text of the section. But the sections are small.
3. In this example, the article will be displayed with it's overview text AND each section that is assigned to it.
I am trying to construct this through ruby but do not know how to architect it. What is the best practice? Creating an article that has many sections built into it (some not used) would be a waste of memory for the article. Creating the "section" data point would allow me to easily create sections, but they would not be visibly connected and the editor would have to do a lot of work to make sure that it makes sense.
The best idea I had, which ruby does not seem to support, is the create an "article" type that has as many "sections" as the editor see's fit. Theoretically this would allow the editor to create a new article and while filling in the article information, be able to write the individual sections one at a time, with the ability to add additional sections on the same screen. But again I am new and not sure if that is even possible...
Thanks
Copied from my comment:
This can be done but not as a "scaffold" which is a rails generator for quickly building a controller, model and views in 1 shot. What you are looking for is a rendered partial. Take a look at nested_form Or cocoon gems to get an idea of how to implement these dynamically.

Generating Navigation for different user types, MVC, PHP

I have this idea of generating an array of user-links that will depend on user-roles.
The user can be a student or an admin.
What I have in mind is use a foreach loop to generate a list of links that is only available for certain users.
My problem is, I created a helper class called Navigation, but I am so certain that I MUST NOT hard-code the links in there, instead I want that helper class to just read an object sent from somewhere, and then will return the desired navigation array to a page.
Follow up questions, where do you think should i keep the links that will only be available for students, for admins. Should i just keep them in a text-file?
or if it is possible to create a controller that passes an array of links, for example
a method in nav_controller class -> studentLinks(){} that will send an array of links to the helper class, the the helper class will then send it to the view..
Sorry if I'm quite crazy at explaining. Do you have any related resources?
From your description it seems that you are building some education-related system. It would make sense to create implementation in such way, that you can later expand the project. Seems reasonable to expect addition of "lectors" as a role later.
Then again .. I am not sure how extensive your knowledge about MVC design pattern is.
That said, in this situation I would consider two ways to solve this:
View requests current user's status from model layer and, based on the response, requests additional data. Then view uses either admin or user templates and creates the response.
You can either hardcode the specific navigation items in the templates, from which you build the response, or the lit of available navigation items can be a part of the additional information that you requested from model layer.
The downside for this method is, that every time you need, when you need to add another group, you will have to rewrite some (if not all) view classes.
Wrap the structures from model layer in a containment object (the basis of implementation available in this post), which would let you restrict, what data is returned.
When using this approach, the views aways request all the available information from model layer, but some of it will return null, in which case the template would not be applied. To implement this, the list of available navigation items would have to be provided by model layer.
P.S. As you might have noticed from this description, view is not a template and model is not a class.
It really depends on what you're already using and the scale of your project. If you're using a db - stick it there. If you're using xml/json/yaml/whatever - store it in a file with corresponding format. If you have neither - hardcode it. What I mean - avoid using multiple technologies to store data. Also, if the links won't be updated frequently and the users won't be able to customize them I'd hardcode them. There's no point in creating something very complex for the sake of dynamics if the app will be mostly static.
Note that this question doesn't quite fit in stackoverflow. programmers.stackexchange.com would probably be a better fit

Cocoa Application Framework with Packages

Ok, I am creating a document-based application in Cocoa and the document's file type is actually a package. Within that package is an XML settings file, a SQLite database and a zip file which is downloaded at runtime. Now the only thing that changes, really, is the XML settings file as the other ones can be recreated at run-time.
Each one of these packages will have one and only one window, hence my desire to use document-based. These files can also be copied, renamed, moved, etc. just like any other file that is part of such an architecture.
But I am completely lost as how to implement this in the Documentation Framework! It seems everywhere I look in the docs it's always talking about in-memory representations of the files which you then write out using the path presented to you in one of the NSDocument overrides (since Cocoa may move it, etc.) But again, I'm using a SQLite database that sits on disk, not in memory.
I have looked all over for overridable methods that would still give me things like dirty-state checking of the doc, open and save file dialog support and the like, but I can't seem to find anything that just says 'Here's a file URL... Open it as you see fit' althought I did get close at the application's delegate level, at least for the opening.
So let's assume that's working as expected. How do I implement the save/save-as where I want to control everything that is written to disk or not? I don't want to (not can I) mess around with data structures or the like. I just want to be given a psth that the user selects in the 'Save As' dialog (for new) and be able to write what I need to there. Simple. But again, the 50+ page document from developer.apple.com about Document-based architecture tells me where to overload a lot of things, but every one seems to stem from some in-memory representation of the document, which again, is not what my package is. Technically, only the internal XML file is what would be tied to the document. Everything else is just support for it.
So? Anyone? Takers?
Mark
I can't seem to find anything that just says 'Here's a file URL... Open it as you see fit'
Implement the readFromURL:ofType:error: method in your document class. Alternatively, since your document type is a package type, implement the readFromFileWrapper:ofType:error: method.
You don't have to read the data into memory; you can do whatever you want in whichever method you implement, including opening the database.
How do I implement the save/save-as where I want to control everything that is written to disk or not?
Implement the writeToURL:ofType:error: method or the fileWrapperOfType:error: method.
If you had or could easily create data in memory, you would implement the readFromData:ofType:error: and dataOfType:error: methods. The URL-based and file-wrapper-based methods are for cases where data in memory is not an option. And the primary use of file wrappers is for package types like yours.
Actually, I found it. It's not the 'writeTo' methods, but rather the 'saveTo' methods you want to override. When I did that, the saving code worked as I expected, including automatic save panel support. For clarity, this is the one I chose...
saveToURL:ofType:forSaveOperation:error:
and it works like a champ! Not too confusing now, was it! Sheesh!!!
That was of course the very first thing that I tried, but if you read the developer documentation--specifically the Cocoa Document-Based Architecture--here's what it says about those very methods...
During writing, your document may be asked to write its contents to a different location or using a different file type. Again, your overridden method should be able to determine everything it needs to do the writing from the passed-in parameters.
If your override cannot determine all of the information it needs from the passed-in parameters, consider overriding another method. For example, if you see the need to invoke fileURL from within an override of readFromData:ofType:error:, perhaps you should instead override readFromURL:ofType:error:. For another example, if you see the need to invoke fileURL from within an override of writeToURL:ofType:error:, perhaps you should instead override writeToURL:ofType:forSaveOperation:originalContentsURL:error:.
In other words, it seems to say that you can't assume the URL that is passed to you is the actual place on disk where the 'something' is eventually written to, which wreaks havoc when dealing with database files that are opened by URL. Maybe I'm missing something.
But ok... forget I read that and simply even try to just override those methods. I do and return TRUE for each, (I log the URL so I can see what is being passed in), I get this error on 'Save As' after you have chosen a filename...
2009-10-28 14:31:51.548 XPanel[1001:a0f] dataOfType:error: is a subclass responsibility but has not been overridden.
...but when you look at the documentation for that it says the default implementation throws an exception because you must override one of the other implementations above... which I obviously just did! Plus, again, this can't be represented as simple data!
So grasping at straws here, I overrode that one too and just returned nil, since again, you can't represent what I'm doing with a NSData object. Then I get a 'Can't be saved' message.
WTF?! Why is it calling that thing anyway??!!
...and that's when I gave up and posted this here.
Now if YOU can give me a simple example that perhaps doesn't even actually read or write a file but instead just logs the URL, that would be perfect. Not to useful but still, it should work... I just can't seem to implement get it to.

Resources