Pagina 1 di 1

[Risolto] Nome dell'add-on invariabile

MessaggioInviato: sabato 24 novembre 2018, 11:02
da giuserpe
Ciao,
da quando ho introdotto l'uso di Python nello sviluppo di LeenO (http://www.leeno.org) sono costretto a pubblicare l'estensione con il nome di LeenO.oxt perdendo, così, le informazioni relative al numero di versione nel nome del file.
Richiamo gli script dal menu Addons.xcu in questa forma:
Codice: Seleziona tutto   Espandi visualeStringi visuale
<value>vnd.sun.star.script:LeenO.oxt|pyLeenO|pyleeno.py$DlgMain?language=Python&amp;location=user:uno_packages</value>

in cui LeenO.oxt|pyLeenO|pyleeno.py indica il percorso di ricerca relativo di installazione e DlgMain è lo script da avviare. Cambiando il nome del file da installare in LeenO-3.19.1.oxt l'istallazione va a buon fine, ma tutti gli script Python vanno in errore in quanto il percorso di ricerca risulta irraggiungibile. Mentre le funzioni scritte in Basic non hanno problemi.
Per risolvere dovrei cambiare il percorso di ricerca che indico in Addon.xcu e dovrei farlo ad ogni nuova pubblicazione di LeenO.
Ho sbirciato in altri add-on scritti in Python ed ho notato che nel menù i comandi sono richiamati, ad esempio, in questa forma:
Codice: Seleziona tutto   Espandi visualeStringi visuale
<value>service:apso.python.script.organizer.impl?execute</value>

e continuano a funzionare correttamente anche cambiando il nome del file di installazione da apso.oxt a ciccio_apso.oxt.
Intuisco che in questo caso lo script è trattato come servizio.
Com'è possibile farlo?

Re: Nome dell'add-on invariabile

MessaggioInviato: mercoledì 9 gennaio 2019, 23:55
da hubert lambert
Ciao Giuserpe,

Per utilizzare una url col protocol "service:", quello servizio deve implementare l'interfaccia XJobExecutor.
L'url del tipo "service:implementation.name?argument" chiamerà il suo singolo metodo "trigger", passando in argomento il valore dato dopo il "?", qui "argument" (vedi l'esempio )
Spero di essere stato chiaro... ;) .

Cordiali saluti.

Re: Nome dell'add-on invariabile

MessaggioInviato: sabato 12 gennaio 2019, 13:15
da giuserpe
Grazie Hubert,
avevo abbandonato l'idea perché ho trovato in giro esempi con codice Python contenente un unico script, mentre LeenO ne contiene centinaia. Vedrò cosa riesco a ricavarci e se riesco ad estendere la soluzione al mio caso.

Saluti.

Re: [Risolto] Nome dell'add-on invariabile

MessaggioInviato: domenica 13 gennaio 2019, 14:11
da hubert lambert
Normalmente, il metodo unico "trigger" riceve tutte le url e, secondo l'argomento, lancia la funzione corrispondente.
Se l'argomento è il nome di quella funzione, sarà più semplice ancora, con una singola riga:
Codice: Seleziona tutto   Espandi visualeStringi visuale
def trigger(self, argomento):
    globals()[argomento]()

Re: [Risolto] Nome dell'add-on invariabile

MessaggioInviato: venerdì 23 agosto 2019, 1:06
da giuserpe
Ciao Hubert,
prima di mostrarti cosa ho fatto ed ottenuto, voglio precisare che LeenO lavora con Python attraverso un unico file che è pyLeenO/pyleeno.py.
###Configurazione corrente funzionante:
Nel META-INF/manifest.xml ho questa riga:
Codice: Seleziona tutto   Espandi visualeStringi visuale
<manifest:file-entry manifest:media-type="application/vnd.sun.star.framework-script" manifest:full-path="pyLeenO" />

In Addons.xcu indico il percorso completo dei comandi in questo modo:
Codice: Seleziona tutto   Espandi visualeStringi visuale
<value>vnd.sun.star.script:LeenO.oxt|pyLeenO|pyleeno.py$DlgMain?language=Python&amp;location=user:uno_packages</value>

in cui LeenO.oxt|pyLeenO|pyleeno.py ovviamente è il percorso relativo di installazione dell'add-on, che è ciò che mi obbliga a tenere fisso il nome del file di installazione in LeenO.oxt, e DlgMain è il nome della funzione/macro richiamata dal menù.

Per gestire il comando come servizio ho fatto un po' di prove:
###Configurazione alternativa n.1:
Ho aggiunto nel file pyLeenO/pyleeno.py la definizione di trigger:
Codice: Seleziona tutto   Espandi visualeStringi visuale
def trigger(self, arg):
    if arg=='DlgMain': DlgMain()

g_ImplementationHelper = unohelper.ImplementationHelper()
g_ImplementationHelper.addImplementation(None,
                                        "org.giuseppe-vizziello.leeno",
                                        ("org.giuseppe-vizziello.leeno",),)

quindi in Addons.xcu ho definito la voce di menù:
Codice: Seleziona tutto   Espandi visualeStringi visuale
<value>service:org.giuseppe-vizziello.leeno?DlgMain</value>

Ho ricompilato il pacchetto e reinstallato. Ho provato ad avviare la voce di menù, ma non ho ottenuto nulla, nemmeno un messaggio di errore.

###Configurazione alternativa n.2:
ho aggiunto al pacchetto un secondo file di Python con nome LeenO.py da cui richiamare i comandi definiti in pyLeenO/pyleeno.py.
Codice: Seleziona tutto   Espandi visualeStringi visuale
#LeenO.py
import uno
import unohelper
from pyLeenO.pyleeno import DlgMain
def trigger( self, args ):
    if arg=='DlgMain':
        DlgMain()
g_ImplementationHelper = unohelper.ImplementationHelper()
g_ImplementationHelper.addImplementation(None,
                                        "org.giuseppe-vizziello.leeno",
                                        ("org.giuseppe-vizziello.leeno",),)

in META-INF/manifest.xml ho aggiunto:
Codice: Seleziona tutto   Espandi visualeStringi visuale
<manifest:file-entry manifest:media-type="application/vnd.sun.star.uno-component;type=Python" manifest:full-path="LeenO.py" />

In questo caso, già in fase di installazione di LeenO.oxt ottengo questo errore:
    (com.sun.star.uno.RuntimeException) { { Message = "<class 'ImportError'>: No module named 'pyLeenO' (or 'pyLeenO.pyleeno.DlgMain' is unknown), traceback follows\X000a File \"C:\\Program Files\\LibreOffice\\program\\pythonloader.py\", line 149, in writeRegistryInfo\X000a mod = self.getModuleFromUrl( locationUrl )\X000a File \"C:\\Program Files\\LibreOffice\\program\\pythonloader.py\", line 104, in getModuleFromUrl\X000a exec(codeobject, mod.__dict__)\X000a File \"C:\\Users\\giuserpe\\AppData\\Roaming\\LibreOffice\\4\\user\\uno_packages\\cache\\uno_packages\\lu44766xfcu.tmp_\\LeenO.oxt\\LeenO.py\", line 16, in <module>\X000a from pyLeenO.pyleeno import DlgMain\X000a File \"C:\\Program Files\\LibreOffice\\program\\uno.py\", line 434, in _uno_import\X000a raise uno_import_exc\X000a File \"C:\\Program Files\\LibreOffice\\program\\uno.py\", line 356, in _uno_import\X000a return _builtin_import(name, *optargs, **kwargs)\X000a\X000a", Context = (com.sun.star.uno.XInterface) @0 } }
che mi dice che ho un errore di importazione.

###Configurazione alternativa n.3:
Ho fatto una terza prova cambiando in META-INF/manifest.xml
Codice: Seleziona tutto   Espandi visualeStringi visuale
<manifest:file-entry manifest:media-type="application/vnd.sun.star.framework-script" manifest:full-path="pyLeenO" />

con
Codice: Seleziona tutto   Espandi visualeStringi visuale
<manifest:file-entry manifest:media-type="application/vnd.sun.star.uno-component;type=Python" manifest:full-path="pyLeenO/pyleeno.py" />

alla reinstallazione del pacchetto ottengo:
    (com.sun.star.uno.RuntimeException) { { Message = "<class 'NameError'>: name 'XSCRIPTCONTEXT' is not defined, traceback follows\X000a File \"C:\\Program Files\\LibreOffice\\program\\pythonloader.py\", line 149, in writeRegistryInfo\X000a mod = self.getModuleFromUrl( locationUrl )\X000a File \"C:\\Program Files\\LibreOffice\\program\\pythonloader.py\", line 104, in getModuleFromUrl\X000a exec(codeobject, mod.__dict__)\X000a File \"C:\\Users\\giuserpe\\AppData\\Roaming\\LibreOffice\\4\\user\\uno_packages\\cache\\uno_packages\\lu44766xfd4.tmp_\\LeenO.oxt\\pyLeenO\\pyleeno.py\", line 7374, in <module>\X000a createUnoService =(XSCRIPTCONTEXT.getComponentContext().getServiceManager().createInstance)\X000a\X000a", Context = (com.sun.star.uno.XInterface) @0 } }
quindi XSCRIPTCONTEXT non risulta definito...

Cos'altro ancora non ho provato?

Re: [Risolto] Nome dell'add-on invariabile

MessaggioInviato: venerdì 23 agosto 2019, 21:35
da hubert lambert
Ciao Giuserpe,

Alcuni mesi fa, avevo fatto prove con il servizio "ProtocolHandler", che è più flessibile della mia prima proposta (vedi qui e qui).
Allego il risultato di questo lavoro: se ti va bene, possiamo andare oltre nelle spiegazioni.
Cordiali saluti.

LeenO.oxt

Re: [Risolto] Nome dell'add-on invariabile

MessaggioInviato: sabato 24 agosto 2019, 0:49
da giuserpe
hubert lambert ha scritto:Ciao Giuserpe,
....
Allego il risultato di questo lavoro: se ti va bene, possiamo andare oltre nelle spiegazioni.
Cordiali saluti.
LeenO.oxt


Grazie mille Hubert, mi sembra perfetto! Sto guardando il codice che hai aggiunto per trasferirlo (con il validissimo supporto di @mvescovi Matteo F. Vescovi) sulla versione di sviluppo di LeenO.
Certo, gradirei tantissimo qualche riga di spiegazione. Sono un abile utente del copia/incolla, ma mi piace farne un uso consapevole.
Grazie infinite.

Re: [Risolto] Nome dell'add-on invariabile

MessaggioInviato: sabato 24 agosto 2019, 17:36
da hubert lambert
Allora:

Creare un componente UNO
1. per creare un oggetto UNO con python, si deve utilizzare una class python e registrarla nel programma;
2. la class deve dipendere di interfaccie UNO già definite, seconda delle necessità (il primo esempio utilizza XInitialization, XDispatch, XDispatchProvider, il secondo XJobExecutor) ed implementare tutti loro metodi;
3. il componente nuovo va registrato aggiugendo due righe alla fine del script:
Codice: Seleziona tutto   Espandi visualeStringi visuale
# Qui registriamo il componente
g_ImplementationHelper = unohelper.ImplementationHelper()
g_ImplementationHelper.addImplementation(LaClass, "un.identificatore.unico", ("un.identificatore.unico",),)
e questa riga nel manifest.xml (script.py contiene le righe sopra):
Codice: Seleziona tutto   Espandi visualeStringi visuale
  <manifest:file-entry manifest:media-type="application/vnd.sun.star.uno-component;type=Python" manifest:full-path="path/to/script.py" />
Puoi controllare che tutto sia andato bene facendo, in basic, un
Codice: Seleziona tutto   Espandi visualeStringi visuale
createUnoService("un.identificatore.unico")

Ho fatto, per maggiore chiarezza, due piccole estensione. Inseriscono una voce di menu (GIUSERPE1 o GIUSERPE2), ciascuno con due items.

Esempio 1: protocol handler
Si tratta di registrare un "protocol handler" che reindirizza un protocole url personalizzato al componente dato. È possibile registrare più protocoli nello stesso file ProtocolHandler.xcu.
In quello esempio, utilizzo il protocol "esempio1:", che va utilizzato nel file Addons.xcu come valore di URL: "esempio1:bla.bla.1", "esempio1:bla.bla.2"...

Esempio 2: XJobExecutor
XJobExecutor contiene un metodo unico "trigger", che va chiamato ogni volta che un pulsante di menù o di toolbar con particolare URL è premuto.
Questa particolare url è: "service:un.identificatore.unico?argomento". La parte "argomento" è quella passata al metodo "trigger", che permette di identificare il pulsante sorgente.

L'opzione "protocol handler" mi pare più flessibile, ma quella con il metodo "trigger" sarà forse più semplice da implementare.
Tutte due sono totalmente indipendenti del nome del oxt.

Saluti.

Re: [Risolto] Nome dell'add-on invariabile

MessaggioInviato: martedì 27 agosto 2019, 0:32
da giuserpe
Grazie mille Hubert, sei stato molto chiaro.

Re: [Risolto] Nome dell'add-on invariabile

MessaggioInviato: martedì 27 agosto 2019, 22:04
da giuserpe
Ciao Hubert,
sto applicando le informazioni che mi hai dato alla versione di sviluppo della mia estensione utilizzando il sistema "protocol handler". Ho notato che hai ridefinito anche in python/leeno.py alcune definizioni di funzioni già presenti in python/pythonpath/pyleeno.py. Ad sesempio DlgMain che, però, in python/leeno.py è presente sotto la classe Leeno. Come mai?

Re: [Risolto] Nome dell'add-on invariabile

MessaggioInviato: mercoledì 28 agosto 2019, 10:58
da hubert lambert
Ciao Giuserpe,

Non ricordo esattamente perché l'ho fatto (sei mesi fa!). Forse une prova per reintegrare le funzioni in un file unico, oppure perchè non funzionava con l'istruzione "import pyleeno".
In ogni caso ho solo cercato a fare funzionare il protocol handler al più presto, con la bruta scorciatoia di ridefinire la variabile globale "XSCRIPTCONTEXT". Nel progetto finale, sarebbe meglio separare le funzioni di menu e toolbars (che non hanno bisogno di quella variabile) delle funzioni chiamate da pulsanti dentro documenti.

Cordiali saluti.

Re: [Risolto] Nome dell'add-on invariabile

MessaggioInviato: mercoledì 28 agosto 2019, 19:44
da giuserpe
Rieccomi ancora...
Scusa Hubert, ma l'argomento è molto interessante e non mi capita spesso di trovare qualcuno così preparato e disponibile come te.

Provando ho notato che:
- lavorando con il sistema del framework-script, che è quello al momento in uso con LeenO e che non mi consente il cambio del nome del pacchetto LeenO.oxt, posso provare al volo le modifiche che faccio al mio pyleeno.py, senza ricreare il pacchetto e reinstallare l'add-on;
- il sistema che adotta il trigger unico, per avviare e valutare le modifiche al codice, richiede il riavviao di LO;
- con il protocol-handler è indispensabile ripacchettizzare e reinstallare l'estensione perché il pyleeno.pyc venga rigenerato.

Naturalmente, per questioni di abitudine e perché mi sembra obiettivamebte comodo, a me interessa poter fare le mie prove al volo. Mi capita spesso di dover provare più opzioni mentre programmo e, per come mi sono organizzato, procedo speditamente rimanendo concentrato sulle modifiche senza le distrazioni di un riavvio o addiritura una reinstallazione.
Ritieni che ci sia rimedio alla mia questione? Secondo te è possibile conservare la mia attuale modalità di sviluppo riuscendo a produrre pacchetti .oxt di nome diverso ongi volta?

Grazie

Re: [Risolto] Nome dell'add-on invariabile

MessaggioInviato: giovedì 29 agosto 2019, 22:17
da hubert lambert
Il programma carica un componente al avvio, e dopo non è più possibile ricaricarlo (almeno non conosco nessun metodo). Ma quando il componente funziona bene, basta soltante provare le funzioni che saranno chiamate da lui, prima di avere tutto il file Addons.xcu pronto.
Il più semplice, mi pare:
1. durante il sviluppo, aggiungia la linea "framework-script" nel manifest.xml, accanto a quella "uno-component":
Codice: Seleziona tutto   Espandi visualeStringi visuale
[...]
  <manifest:file-entry manifest:media-type="application/vnd.sun.star.uno-component;type=Python" manifest:full-path="python/main.py" />
  <manifest:file-entry manifest:media-type="application/vnd.sun.star.framework-script" manifest:full-path="python" />
[...]

2. aggiungia una piccola funzione alla fine dello script contenente il componente (forse pyleeno.py), funzione che deve chiamare il metodo "trigger" o "dispatch" del componente, per esempio:
Codice: Seleziona tutto   Espandi visualeStringi visuale
def test_PyService():
    service = PyService(uno.getComponentContext())
    service.trigger('una_parola_chiave')

g_exportedScripts = test_PyService,
o
Codice: Seleziona tutto   Espandi visualeStringi visuale
from com.sun.star.util import URL
def test_PyService():
    url = URL()
    url.Complete = 'esempio1:una_parola_chiave'
    _, url = uno.getComponentContext().ServiceManager.createInstance('com.sun.star.util.URLTransformer').parseStrict(url)
    service = PyService(uno.getComponentContext())
    service.dispatch(url, None)

g_exportedScripts = test_PyService,

Così puoi provare tutte le funzioni come prima (chiamando test_PyService dal menu Macro -> Execute) e, quando tutto apposto, preparare il file Addons.xcu e ripacchettare tutto.

Non sono sicuro di essere stato chiaro questa volta ;) .

Re: [Risolto] Nome dell'add-on invariabile

MessaggioInviato: venerdì 30 agosto 2019, 10:59
da giuserpe
Sì, conosco g_exportedScripts e so che Addons.xcu va ricaricato ad ogni modifica. Il dubbio è: g_exportedScripts rimane efficace se, con trigger unico o protocol handler, uso script annidati?
Scusa, ma forse non ho ancora detto che io modifico direttamente il file pyleeno.py mentre è installato e funzionante nel suo path operativo.
La mia esigenza è provare al volo le macro che modifico mentre sono attive nei menù.

La configurazione attuale di LeenO, quindi, mi consente questo work-flow:
    - Scrivo/modifico codice
    - Provo i comandi
Con il metodo del trigger unico sarebbe:
    - Scrivo/modifico codice
    - Riavvio LibreOffice
    - Provo i comandi
Con il protocol handler:
    - Scrivo/modifico codice
    - Pacchettizzo
    - Installo, quindi riavvio LibreOffice
    - Provo i comandi
Ci sarebbe un altro sistema per rendere variabile il nome del pacchetto OXT. Toccherebbe richiamare i comandi già scritti in Python da Basic con:
Codice: Seleziona tutto   Espandi visualeStringi visuale
Function LeenO_Path
   If NOT GlobalScope.BasicLibraries.isLibraryLoaded( "Tools" ) Then
         GlobalScope.BasicLibraries.LoadLibrary( "Tools" )
   End If
   Dim pip As Object, extensionLocation As String
   Const extensionIdentifier = "org.giuseppe-vizziello.leeno"
   pip = GetDefaultContext.getValueByName("/singletons/com.sun.star.deployment.PackageInformationProvider")
   extensionLocation = pip.getPackageLocation(extensionIdentifier)
   sURL = (ConvertFromURL(extensionLocation))
   LeenO_Path = extensionLocation ' full path
End Function

Sub ScriptPy (sModulo, sFunzione, Optional arg1, Optional arg2, Optional arg3) As Variant
'questa serve ad avviare le funzioni/script di Python
   args() = Array()
   If not ismissing (arg1) Then Appenditem(args(), arg1)
   If not ismissing (arg2) Then Appenditem(args(), arg2)
   If not ismissing (arg3) Then Appenditem(args(), arg3)
   'RIF: http://bit.ly/1b4d3dF

   Dim MasterScriptProviderFactory as Object
   Dim MasterScriptProvider as Object
   Dim Script as Object
   Dim Url as String
   sName = FileNameoutofPath(LeenO_Path) 'nome oxt

   Url = "vnd.sun.star.script:" & sName & "|pyLeenO|" & sModulo & "$" & sFunzione &"?language=Python&location=user:uno_packages"
        'Print Url
   MasterScriptProviderFactory = createUnoService("com.sun.star.script.provider.MasterScriptProviderFactory")
   MasterScriptProvider = MasterScriptProviderFactory.createScriptProvider("")
   Script = MasterScriptProvider.getScript(Url)

   PythonResult = Script.invoke(args,Array(),Array())

        ScriptPy = PythonResult
End Sub

quindi con:
Codice: Seleziona tutto   Espandi visualeStringi visuale
Sub struttura_ComputoM
   ScriptPy("pyleeno.py","struttura_ComputoM")
end Sub

in cui struttura_ComputoM è un comando già definito in pyleeno.py che va richiamato in Addon.xcu con:
Codice: Seleziona tutto   Espandi visualeStringi visuale
<value>vnd.sun.star.script:UltimusFree2.Strutture.struttura_ComputoM?language=Basic&amp;location=application</value>

Il problema, però, sarebbe tornare a fare un importante uso del Basic di cui, invece, vorrei liberarmi.
Saluti.

Re: [Risolto] Nome dell'add-on invariabile

MessaggioInviato: sabato 31 agosto 2019, 17:14
da hubert lambert
Ho bene capito il tuo bisogno. Ma penso che il mio messaggio non era chiaro. Ho adattato l'esempio 2 (vedi sotto), con il metodo "trigger", che finalmente sarà meglio nel tuo caso.

Il menu conta 10 items già definiti con il loro url definitivo. È definita solo la funzione legata al primo item, col nome 'Item 1" e url "service:giuserpe.esempio_2.impl?arg1". Qui si deve ricordare che solo "arg1" è passato alla funzione "trigger".

Installare l'estensione. In modo evidente, solo il primo item funzionerà. Gli altri non funzioneranno fino a quando una nuova versione dell'estensione viene installata.

MA: con la nuova linea nel manifest.xml et la piccola funzione così esposta (nel esempio "test_PyService"), diventa davvero facile di sviluppare al volo le macro da legare nel futuro agli altri item. Basta chiamare il metodo "trigger" con lo stesso argomento dal menu, come questo lo farà, e di creare e provare la funzione corrispondente (nel mio esempio hanno il nome "do_" + valore del argomento, per commodità).

Quando tutte le funzioni sono pronte, puoi ripacchettare ed installare di nuovo, senza modificare niente nel Addons.xcu.

Re: [Risolto] Nome dell'add-on invariabile

MessaggioInviato: venerdì 15 maggio 2020, 20:10
da giuserpe
Ciao a tutti.
Ormai ho adottato con succeso il Protocol Headler su LeenO, ma solo per i rilasci ufficiali.
Voglio lasciare impostato il Protocol Headler anche per lo sviluppo. Questo servirebbe a testare il programma nelle stesse condizioni in cui viene pubblucato ufficialmente. Infatti con l'ultimo rilascio ho riscontrato alcune differenze di comportamento del codice dopo l'attivazione del PH.
Vengo al dunque. Con il PH attivato, al primo avvio, dopo l'installazione di LeenO viene creata la __pycache__. Significa che in fase di sviluppo questa deve essere rigenerata ad ogni modifica al codice, ma soprattutto deve essere ricaricata. La rigenerazione della dir __pycache__ non è un problema, però l'unico modo che conosco per ricaricarla è chiudere e riavviare LibreOffice.
Questa è la domanda: come può essere possibile rileggere __pycache__ al volo, senza riavviare LO?

Grazie