Previous Thread
Next Thread
Print Thread
Text Scripts #28785 29 Jan 16 05:31 AM
Joined: Oct 2015
Posts: 230
S
Stuart Offline OP
Member
OP Offline
Member
S
Joined: Oct 2015
Posts: 230
Is it possible to change the format for the Text Clip date system variable (PN_DATE)?

In particular, for whatever reason, it has been common practice here to use '.' rather than '/' as a seperator character.

Re: Text Scripts #28786 31 Jan 16 11:31 PM
Joined: Jun 2001
Posts: 11,645
J
Jack McGregor Online Content
Member
Online Content
Member
J
Joined: Jun 2001
Posts: 11,645
It's certainly possible, but it will require some work on my end, either to implement some kind of local configuration option to specify the desired date format (probably via a mask), or to implement one or more alternate forms of the PN_Date variable, or perhaps to redirect the PN_Date variable to a script that you could then provide.

I was hoping to look into it this afternoon, but we were without power for most of the day, forcing me to find other ways to spend the time. Perhaps tomorrow...

Re: Text Scripts #28787 01 Feb 16 01:36 AM
Joined: Jun 2001
Posts: 11,645
J
Jack McGregor Online Content
Member
Online Content
Member
J
Joined: Jun 2001
Posts: 11,645
Ok, here's a preliminary solution:

Add the following to the end of the \pypn\glue.py file:

Code
import datetime
def printToday():
    """ May be called by text clip handler as alternative to $PN_Date; 
        usage: print `runScript(printToday())`
    """
    today = datetime.date.today()
    print today.strftime('%d.%m.%y')
Then, in your text clip, in place of ${PN_DATE} insert `runScript(printToday())`

For example:
Code
![${1}] `runScript(printToday())` ${PN_TIME}      Edited by Stuart
!	${2}
I say preliminary, because I don't think the glue.py module is the 'proper' place for this kind of thing, but offhand I'm not sure what the best place would be. Probably better to put it in your own script file, but that would then need to be imported into glue.py, since your script would be called by glue.runScript().

Note that this script is a bit weird in that it simply 'prints' the date (which would normally go to stdout and be lost to APN). But in this case, the text clip handler intercepts it. For a more traditional script that just inserts the date directly into the document, you could use something like this:

Code
#import datetime
@script("Todays Date", "Text")
def insertToday():
    editor = scintilla.Scintilla(pn.CurrentDoc())
    editor.BeginUndoAction()
    today = datetime.date.today()
    editor.AddText(8, today.strftime('%d.%m.%y'))
    editor.EndUndoAction()
This kind of generic text, non ASB-specific script should probably go in the scripts directory.

Re: Text Scripts #28788 01 Feb 16 03:48 AM
Joined: Oct 2015
Posts: 230
S
Stuart Offline OP
Member
OP Offline
Member
S
Joined: Oct 2015
Posts: 230
Thanks, the 'preliminary solution' does the job.

The latter 'generic' option would perhaps be preferable as it would appear to be a more locally implementable solution (a local script module rather than a local version of the 'glue.py' module).

However, this then requires 'glue.py' to be able to read/run a local script, which, unless there is something that I haven't found yet, would still require a change to 'glue.py' and does not appear to be a straightforward import of the respective script file or function.

Re: Text Scripts #28789 01 Feb 16 08:11 AM
Joined: Nov 2006
Posts: 2,192
S
Stephen Funkhouser Online Content
Member
Online Content
Member
S
Joined: Nov 2006
Posts: 2,192
Wouldn't any local code changes to glue.py get overridden from an APN update?

We could designate a glue module under the %APN%\scripts directory, so %APN%\scripts\glue. Then modify \pypn\glue.py to import any scripts in that module.


Stephen Funkhouser
Diversified Data Solutions
Re: Text Scripts #28790 01 Feb 16 11:35 AM
Joined: Jun 2001
Posts: 11,645
J
Jack McGregor Online Content
Member
Online Content
Member
J
Joined: Jun 2001
Posts: 11,645
Indeed, putting this kind of thing directly in the pypn\glue.py file is not practical for distribution. As I said, it was preliminary experiment. I think the proper solution is probably something along the lines of what Stephen suggests. But I had some difficulties when I tried it (perhaps the same difficulties alluded to by Stuart), and as it was getting late, decided to revisit later.

Another option might be to modify the text clip handler within APN to support a new system variable along the lines of $PN_SCRIPT(scriptname) that effectively worked like the regular script interface, simplifying the syntax (eliminating the back apostrophes and 'runScript') and eliminating the need to modify pypn\glue.py at all.

I haven't studied the code yet and am not sure how messy that would be. But I'm not sure I like the idea of commingling these text-clip-helper scripts with regular ones, since they are not interchangeable. (The text-clip-helper scripts return text through stdout, while the normal ones act on the document object directly.) So it probably makes sense to separate the text-clip-helper scripts into either a single file (tchelper.py?) or even a directory. (And we definitely don't want such scripts to show up in the script window, since executing them directly would have no apparent effect.)

At some point, all this effort to get the text clip system to interface with the scripts begins to seem a bit over the top, sort of like trying to engineer an interface between your knapsack and your wagon. Either one will carry groceries home from the market. For a few items, the knapsack (text clip) is easier. But if you need a lot of stuff, use the wagon (script).

In other words, anything you can do with a text clip, you can do with a script (but it takes more effort). So if the text clip system doesn't offer the flexibility needed for a particular task, rather than trying to augment it via an interface to the script, why not just replace it entirely with a script?

Re: Text Scripts #28791 02 Feb 16 04:09 AM
Joined: Oct 2015
Posts: 230
S
Stuart Offline OP
Member
OP Offline
Member
S
Joined: Oct 2015
Posts: 230
I agree that we don't want to go over the top on this. After all, this started from a desire for an optional format to allow '.' separated date elements, rather than '/'. It is not hard to overtype the relevant characters.

For any significant need, the 'script' option already allows for a 'local' solution without having to worry about it being lost with an APN update.

Although the 'runScript' syntax isn't ideal it does allow for additions. Therefore an option that might be worthwhile, would be for glue.py to be changed to import a named module, if it exists. This would then allow locally sourced scripts to be run via runScript without having to change glue.py each time, which might otherwise get lost on a subsequent APN update.

Something like:
Code
import os
if os.path.isfile(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test.py')):
    import test

Re: Text Scripts #28792 02 Feb 16 10:58 AM
Joined: Jun 2001
Posts: 11,645
J
Jack McGregor Online Content
Member
Online Content
Member
J
Joined: Jun 2001
Posts: 11,645
That seems like a good idea.

And regarding the superiority of scripts over text clips, clearly the latter are a lot more convenient to create. And in particular, the input variables feature, i.e. ${1}, is much more simple/elegant in the text clip that trying to figure out how to code the equivalent in a script.

So a mechanism to extend the power of text clips while preserving most of their simplicity probably does make more sense than my knapsack/wagon analogy suggests. I'm not sure it's worth implementing a more elegant syntax than `runScript()`, but making a slight change to glue.py to create a framework for organized local extensions does seem like a reasonable compromise.

Let me experiment a bit with it before deciding on an official change.

Re: Text Scripts #28793 02 Feb 16 11:28 AM
Joined: Nov 2006
Posts: 2,192
S
Stephen Funkhouser Online Content
Member
Online Content
Member
S
Joined: Nov 2006
Posts: 2,192
If you import one file test.py via "import test"; the functions imported will have to be referenced as `runScript(test.printToday())`. That's probably a good thing to keep a proper namespace for these functions.


Stephen Funkhouser
Diversified Data Solutions
Re: Text Scripts #28794 02 Feb 16 12:28 PM
Joined: Jun 2001
Posts: 11,645
J
Jack McGregor Online Content
Member
Online Content
Member
J
Joined: Jun 2001
Posts: 11,645
Right. So how does this sound:

1. You put your special text clip helper scripts into a module pypn\tchelpers.py

2. We include a sample version called pypn\tchelpers_example.py in the release which you can rename or use as an example but which won't interfere with your modified version on subsequent releases.

3. We permanently update glue.py to conditionally import the tchelpers.py module :

Code
# [103] import tchelpers.py if present
try:
	import tchelpers
except:
	pass
I'm not sure but using the try/except mechanism seems slightly lighter than importing os and using the os.path.isfile() script. And as long as the tchelpers.py file is in the pypn (or scripts) directory, it will be found in the standard PYPN import path.

4. You specify the tchelpers namespace in the runScript command within the text clip definition, e.g.:

Code
Timestamp: `runScript(tchelpers.printToday())` ${PN_Time}
Assuming that tchelpers.py contained the following script:

Code
import datetime

def printToday():
    """ May be called by text clip handler as alternative to $PN_Date; 
        usage: `runScript(tchelpers.printToday())`
    """
    today = datetime.date.today()
    print today.strftime('%d.%m.%y')
That text clip would output something like:

Code
Timestamp: 02.02.16 10:17:33
`runScript(tchelpers.printToday())` is a bit clumsy compared to ${PN_DATE} or even ${printToday()} but you're either going to need to type it only once, or you'll cut and paste from a prior clip, so the savings of a few characters doesn't seem to justify modifying the text clip internals.

Re: Text Scripts #28795 02 Feb 16 12:53 PM
Joined: Nov 2006
Posts: 2,192
S
Stephen Funkhouser Online Content
Member
Online Content
Member
S
Joined: Nov 2006
Posts: 2,192
Sounds flexible enough without having to modify too much.


Stephen Funkhouser
Diversified Data Solutions
Re: Text Scripts #28796 03 Feb 16 03:10 AM
Joined: Oct 2015
Posts: 230
S
Stuart Offline OP
Member
OP Offline
Member
S
Joined: Oct 2015
Posts: 230
Good. A flexible, simple solution that uses existing code/features with minimal extra work.

One extra idea I'll throw into the pot: is it worth allowing for an import of all/any scripts in a 'local' named directory, rather than just one named script file?

It's possible, but maybe again, the code overhead may not be worth the effort. How many 'local' scripts are going to be wanted?

Re: Text Scripts #28797 03 Feb 16 06:40 AM
Joined: Nov 2006
Posts: 2,192
S
Stephen Funkhouser Online Content
Member
Online Content
Member
S
Joined: Nov 2006
Posts: 2,192
You can put as many functions in tchelpers.py as you like, so in this case I'm not sure what adding support for a directory of scripts to import gets you?


Stephen Funkhouser
Diversified Data Solutions
Re: Text Scripts #28798 03 Feb 16 11:43 AM
Joined: Jun 2001
Posts: 11,645
J
Jack McGregor Online Content
Member
Online Content
Member
J
Joined: Jun 2001
Posts: 11,645
I guess that was my thinking too, i.e. that these text clip helper scripts are likely to be quite simple, given that they are limited to returning a single text string. So putting them all in one file seems sensible and practical.

On the other hand, I suppose there's still no limit to how complex they might be. Maybe you want a text clip which analyzes the current program and returns an estimated percentage complete, or which compares the current program to all the others in the project and returns a list of related programs, i.e.

Code
Also see `runScript(tchelpers.relatedModules())`
You may not want to put all that code in the one tchelpers.py file.

But even then, it would seem to make just as much sense for tchelpers.py to import other modules, as to have glue.py do it.

I think I'm going to proceed with the implementation as described in my Feb 02 10:28 post above. I'll post it to the APN repository when ready.

Thanks for question/suggestion and all the feedback along the way.

Re: Text Scripts #28799 04 Feb 16 02:41 AM
Joined: Oct 2015
Posts: 230
S
Stuart Offline OP
Member
OP Offline
Member
S
Joined: Oct 2015
Posts: 230
One final thought on this from myself.

Although the local tchelpers.py can be found in either location and it does perhaps, more directly apply to pypn, any other local scripts would I believe, usually go in the scripts directory.

Is it better therefore to locate tchelpers_example.py in scripts rather than pypn, to encourage the use of one location for local additions?

Re: Text Scripts #28800 04 Feb 16 01:52 PM
Joined: Jun 2001
Posts: 11,645
J
Jack McGregor Online Content
Member
Online Content
Member
J
Joined: Jun 2001
Posts: 11,645
That sounds right. Let's put tchelpers.py in /scripts/, and if you want to import additional modules into it, put them in /scripts/ as well. That way we leave /pypn/ alone.

Note however, that in order to be able to directly invoke a function in one of the other local scripts, it would have to be imported into tchelpers.py (since that is the only script explicitly imported into glue.py). And you'd have to invoke it with the full tchelpers.otherscript.function() namespace. Or call it indirectly via a function in tchelpers.py

For example, let's say our tchelpers.py contains this:

Code
import tcdatetime

def printMMDDYY():
	tcdatetime.subprintMMDDYY()
and tcdatetime.py contains:

Code
import datetime

def subprintMMDDYY():
    """ Return date in mm-dd-yy format  """
    today = datetime.date.today()
    print today.strftime('%m-%d-%y')
You could then invoke the subprintMMDDYY() function using either of the following text clip syntaxes:

Code
Date: `runScript(tchelpers.printMMDDYY())`
Date: `runScript(tchelpers.tcdatetime.subprintMMDDYY())`
We could perhaps eliminate the need for the tchelpers.py file to explicitly import any of your other local text clip helper scripts by having glue.py do some fancy dynamic importing of any scripts that it finds. (In that case we'd probably need to put them in a subdirectory of their own, perhaps scripts/tchelpers). But I'm not sure the marginal benefit justifies the extra complexity.

If it gets to the point that there is a vast after-market of text-clip helper scripts floating around the Internet, that you'd like to be able to install just by dropping them into a particular directory, we could then add the necessary dynamic import logic to glue.py, without needing any further changes in the tchelpers.py scheme.

Re: Text Scripts #28801 06 Feb 16 04:30 PM
Joined: Jun 2001
Posts: 11,645
J
Jack McGregor Online Content
Member
Online Content
Member
J
Joined: Jun 2001
Posts: 11,645
FYI, I pushed the changes to the APN repository in MicroSabio\'s BitBucket , including an improved version of the sample script which now takes an optional format string for specifying the desired date and/or time format.

Note that you may need to log in before the APN repository appears as an option. Please contact us to obtain the login info if you don't have it and/or need help getting started with or updating APN.


Powered by UBB.threads™ PHP Forum Software 7.7.3