Using python functions within Mayan EDMS

146 views
Skip to first unread message

Gary D Walborn

unread,
Sep 4, 2014, 3:48:38 PM9/4/14
to mayan...@googlegroups.com
I have written a python function (lets call it 'options') that returns a list of strings.  I would like to use this function to populate the drop-down lists in a metadata type.  I have tried all sorts of ways to do this, and none of them seem to work.  The documentation is very scant on this subject.  Can anyone provide any information on how this is supposed to work?

Thanks,

Gary Walborn

Gary D Walborn

unread,
Sep 5, 2014, 12:10:42 PM9/5/14
to mayan...@googlegroups.com
I've done some experimentation and it seems that the reason my attempts to use a python function to populate a drop-down is that the code seems to only see two names at that point, "User" and "__builtins__".  Obviously I can put anything I want into one module. So the question becomes, "How do I make my module a visible to the code that is interpreting the metadata definition?".  Any ideas?  (I'm going to keep experimenting and I'll let everyone know if I come up with some workable method.)

Thanks,

Gary W.

Gary D Walborn

unread,
Sep 9, 2014, 8:59:02 AM9/9/14
to mayan...@googlegroups.com
I found a work-around for this, but I think it is also a huge security hole in Mayan-EDMS.  I think I'll use it, but it will probably go away when (if) the security hole is fixed. :-( 

On Thursday, September 4, 2014 3:48:38 PM UTC-4, Gary D Walborn wrote:

Roberto Rosario

unread,
Sep 9, 2014, 2:16:54 PM9/9/14
to mayan...@googlegroups.com
You can pass a snippet of code that will produce a list of option which will populate the metadata with a drop down list. The code is a straight Python 'exec' so anything you put here will be execute as-is, so caution, only admins have access to change this. Reference code here: https://github.com/mayan-edms/mayan-edms/blob/master/mayan/apps/metadata/forms.py#L37. The code has a limited namespace with only the User model being passed to it, but since it is a settings option you can pass more things to the namespace of your snippets: https://github.com/mayan-edms/mayan-edms/blob/master/mayan/apps/metadata/conf/settings.py.  Hope this helps.


On Thursday, September 4, 2014 3:48:38 PM UTC-4, Gary D Walborn wrote:

Roberto Rosario

unread,
Sep 9, 2014, 2:22:12 PM9/9/14
to mayan...@googlegroups.com
Create you own custom settings.py file in mayan/settings directory:

# my_settings.py file
from my_custom_module import my_function

METADATA_AVAILABLE_MODELS = {'my_function': my_function}

and launch Mayan with --settings=mayan.settings.my_settings.py

now my_function should be available in the namespace of your metadata lookup snippets.

Gary D Walborn

unread,
Sep 10, 2014, 9:26:09 AM9/10/14
to mayan...@googlegroups.com
Roberto,

  Thanks.  I should have mentioned that I figured that out the other day by looking at the source code.   Be aware that the current code does not override "__builtins__", so it is possible to enter code in the LOOKUP area to do anything that you want.  For example,

__import__('my_custom_module').my_function()

I think that is probably not intended, but it works.

Gary W.

Christoph H. Larsen

unread,
Oct 8, 2014, 4:07:56 AM10/8/14
to mayan...@googlegroups.com
Dear All,

I am afraid I need a wee bit more help here, which is entirely related to my limited experience with Django. Apologies.
Here is what I would like to do:
Imagine you have documents uploaded into Mayan EDMS that expire after a given period of time, such as warranty documents.
So, I should be able to create a metadata set, that contains both the date the documents gets uploaded into an "valid" folder, and and automatically completed expiry metatdata field which, in Python speak, would do something like as a minimum:
from datetime import timedelta
VALIDITY_PERIOD
= 365
expiry_date
= date_of_purchase + timedelta(days=VALIDITY_PERIOD)
In the stanza above, expiry_date should be calculated from another metadata field called, for instance date_of_purchase. How can this be achieved (for dummies!) in Mayan EDMS?
I guess once I have a worknig example on how to include Python functions in detail, I can easily do other things.
Thanks a million!
Chris



Christoph H. Larsen

unread,
Oct 8, 2014, 6:36:12 AM10/8/14
to mayan...@googlegroups.com
Dear Roberto, dear Gary,

I thought I posted a reply earlier today but it seems it did not get through. If it did, my apologies for double-posting.
Due to my lack of in-depth experience with Django, I beg for some more detailed information how to get Python functions working with automatic metadata.
Here is a use case:
I plan to have time-constrained documentation sitting inside Mayan EDMS, such as warranty certificates, or performance verification certificates, which are valid for only N days.
Ideally, the "Valid through" metadata should automagically calculate a default expiry date from different metadata, e.g. purchase date, or revision date.
Also, it would of course be great to then automatically change flags from green to yellow, or whatever.
This needs a wee bit of Python magic (which I am OK with on the Python side) with the default metadata as a function. But how can I, as Django dummy, implement this (step by step) inside Mayan EDMS.

Thanks a million!

Chris


On Wednesday, 10 September 2014 16:26:09 UTC+3, Gary D Walborn wrote:

Mathias Behrle

unread,
Oct 8, 2014, 7:06:40 AM10/8/14
to mayan...@googlegroups.com
* Christoph H. Larsen: " [Mayan EDMS: 882] Re: Using python functions within
Mayan EDMS" (Wed, 8 Oct 2014 03:36:12 -0700 (PDT)):

Hi Chris,

did you have a look at:

https://github.com/mayan-edms/mayan-edms/pull/58

Cheers,
Mathias
--

Mathias Behrle
PGP/GnuPG key availabable from any keyserver, ID: 0x8405BBF6
signature.asc

Christoph H. Larsen

unread,
Oct 8, 2014, 7:32:05 AM10/8/14
to mayan...@googlegroups.com
Dear Mathias,

Thanks a lot for your quick reply and the link, which is clearly an more elaborate version of the rather terse earlier discussion here.
However (did I say Django dummy before? ;-)!), allow me to ask some stupid questions:
While I am clear about the additional settings in the local_settings.py file, I am note sure where to stick the function itself. Gary mentioned that the "validator function [...]
is placed in a module read by the settings routine". Here comes the dummy question: How do I do that?
Placing a my_settings.py with the contents of Gary's function into the mayan/settings folder does not work... Seems I got stuck with the module creation issue.
Sorry for pestering you. Any assistance is hugely appreciated.
Chris

Gary D Walborn

unread,
Oct 8, 2014, 12:37:46 PM10/8/14
to mayan...@googlegroups.com
Chris,

  You need to put your functions into a module (e.g., my_settings.py).  That module must be on your Python path.  I think I placed the file in the "mayan" sub-directory, but any directory in the path should work.  In addition, you must have the "import my_settings" statement in your "local_settings.py" local settings file. (Note: you must specify that Mayan-EDMS should read your local settings upon startup.)  Finally, you must make a dictionary entry for your function in the METADATA_AVAILABLE_VALIDATORS.  Your function should raise an exception if the data is not correct and your function MAY return a value if you want to normalize data.  Having your function use other metadata in the validation is somewhat tricky.  Your function will have to access the data that is returned by the form. It took me a lot of poking around to find how this can be done and I am not sure to this day whether the method will work reliably in all cases.

Gary

Christoph H. Larsen

unread,
Oct 8, 2014, 12:41:06 PM10/8/14
to mayan...@googlegroups.com
Dear Gary,
Thanks a lot for your help, hugely appreciated. I am glad to hear it is
not that straightforward, as I did feel stupid.
Should we make "Easy Python functions imbedding into metadata" a feature
request?
Stay well, and bests from Uganda,
Chris

Gary D Walborn

unread,
Oct 9, 2014, 12:50:55 PM10/9/14
to mayan...@googlegroups.com
Chris,

  I think this is something that you should probably do on the database side.  Nonetheless, I did get the following code to work. 

import datetime
global_contract_date = datetime.datetime.now().date()

def is_valid_contract_date(value):
  from dateutil import parser
  from django.core.exceptions import ValidationError
  try:
    dt = parser.parse(value)
  except ValueError:
    raise ValidationError('Invalid date')
  global global_contract_date
  global_contract_date = dt.date()
  return dt.date().isoformat()

def is_valid_expiry_date(value):
  import datetime
  global global_contract_date
  if global_contract_date:
    expiry_date = global_contract_date+datetime.timedelta(days=365)
  else:
    expiry_date = datetime.datetime.not().date()
  return expiry_date.isoformat()

I would highly recommend that you do not do this! There are just too many things that can go wrong with this code. For example, because there is an "Update" checkbox when editing metadata,  I can bring up the metadata, change the "contract_date", uncheck the "Update" box behind "contract_date", and click "Save".  The "expiry_date" will be updated with the new value of "contract_date", but "contract_date" will not actually change.  The end result is that the dates no longer correspond.  Also, there are not constraints to make the "expiry_date" dependent on the "contract_date".  As a result, I could add the "expiry_date" metadata type to a document that does not even possess the "contract_date" metadata type, making it completely meaningless.  There would have to be a major "overhaul" of the metadata subsystem to make these kinds of things work correctly.  

   I think the use of validators (as I have implemented them) should be limited to validating and, perhaps, normalizing the data (as there is little harm that can be done by the latter).  

Gary

--

---
You received this message because you are subscribed to a topic in the Google Groups "Mayan EDMS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mayan-edms/p-d9PvY3mc4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to mayan-edms+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Gary D. Walborn
gwal...@gmail.com

Christoph H. Larsen

unread,
Oct 11, 2014, 3:01:45 PM10/11/14
to mayan...@googlegroups.com
Dear Gary,
Thank you so much for your help with this. Yes, I agree, it would  be good to have a standardised way of embedding Python functions (mainly for validations and automatic metadata field contents) available. As mentioned before, this should maybe become a feature request.
Bests, Chris
Reply all
Reply to author
Forward
0 new messages