GithubHelp home page GithubHelp logo

lirmm / waves-core Goto Github PK

View Code? Open in Web Editor NEW
17.0 10.0 5.0 6.38 MB

WAVES is a reusable web application dedicated to bioinformatic tool integration

Home Page: https://waves-core.readthedocs.io

License: Other

Python 84.62% CSS 2.30% HTML 8.69% JavaScript 3.90% Shell 0.03% Smarty 0.46%
science online-tools python rest-api cluster-computing

waves-core's People

Contributors

marcoooo avatar morgan-soulie avatar sylmila avatar thomasrosnet avatar vincent-lefort avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

waves-core's Issues

Problem with conditional form field in service form preview and online submission pages

It seems a problem appears when we tune the parent field as radio button or checkbox. We can setup it with no problems in the Submission Methods form but during the display of the preview or online submission the problem appears. The child field disappears when we switch the parent field value.
All it's ok if we tune the parent field as select list.
screenshot_waves_1
screenshot_waves_2
screenshot_waves_3

output file: extension

When configuring a service with an output file, the 'extension' field behaviour is weird. If defined with 'name' and 'extension' fields, a remote output file is correctly retreived by WAVES, but is nammed on the local file system without the extension. Thus, we recommend not to use the 'extension' field.

Issue with runner parameters

On backEnd with new Django version, tick box for "forbid override" doesn't work anymore:

  • Duplicate the entry
  • Not taken into account when configuring services for this runner

Adapter Class refactoring

Adaptors code review
Moved packages layout.
Usage of new saga python stack available for python 3

Trying to access job files on results page gives "Assertion error: Model object must be export-able"

After updating our local installation to the new version, we had a few bugs.
Most of them resolved themselves as problems with our server, the wrong user launching crontab add, and other such small but annoying adjustments, and we fixed those after some work.

There are, however, two bugs that I cannot figure out, and that don't seem to come from anything on our end, as far as I've been able to tell.

This issue details one of them.


Expected :

When launching a job, the results page will normally list several files, depending on how one has configured the service.

The Inputs and output files have See Online and Download Files options, that should allow the user to consult the smaller files directly in the browser, or download them if they are too big.

Bug:

Instead of getting access or downloading the file, if I click on one of the above options I get an AssertionError saying the "Model object must be Export-able"

Example:

image

18856940

Traceback:

Environment:


Request Method: GET
Request URL: http://xx.xx.xx.xxx/waves/jobs/outputs/0ffa5f9b-8646-4995-948f-bf0ed4572bc5/

Django Version: 1.11.17
Python Version: 2.7.5
Installed Applications:
[u'polymorphic',
 u'django.contrib.admin',
 u'django.contrib.auth',
 u'django.contrib.contenttypes',
 u'django.contrib.sessions',
 u'django.contrib.messages',
 u'django.contrib.staticfiles',
 u'waves.wcore',
 u'waves.authentication',
 u'crispy_forms',
 u'rest_framework',
 u'corsheaders',
 u'adminsortable2',
 u'django_crontab']
Installed Middleware:
[u'django.middleware.security.SecurityMiddleware',
 u'django.contrib.sessions.middleware.SessionMiddleware',
 u'corsheaders.middleware.CorsMiddleware',
 u'django.middleware.common.CommonMiddleware',
 u'django.middleware.csrf.CsrfViewMiddleware',
 u'django.contrib.auth.middleware.AuthenticationMiddleware',
 u'django.contrib.messages.middleware.MessageMiddleware',
 u'django.middleware.clickjacking.XFrameOptionsMiddleware']

Traceback:

File "/usr/lib/python2.7/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/usr/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/usr/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/usr/lib/python2.7/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File "/usr/lib/python2.7/site-packages/django/views/generic/base.py" in dispatch
  88.         return handler(request, *args, **kwargs)

File "/srv/waves-core-1.6.5.1/waves/wcore/views/files.py" in get
  33.         assert isinstance(self.object, ExportAbleMixin), ' Model object must be Export-able'

Exception Type: AssertionError at /waves/jobs/outputs/0ffa5f9b-8646-4995-948f-bf0ed4572bc5/
Exception Value: Model object must be Export-able

I've checked, and the files are perfectly fine on the server itself, where I can see their contents.

Decimal step settings are ignored in Inputs

When configuring a Decimal Input for a service, one can set the minimum and maximum, as well as the steps used by said service.

The step setting is supposed to affect what the Browsers up and down buttons increment/decrement the value in the field by:

screenshot from 2019-01-11 10-50-30

As it is, no matter the value placed in the Step field in the Input configuration screen:

image

On the user's side (as well as in the Preview when logged in as Admin), the Incrementation step will always be 1.

Steps to Reproduce:

  1. Create service (using LocalShellAdaptor)
  2. Edit the Default submission method
  3. Add a Decimal Input, and configure it's step to be any value other than 1
  4. Use Preview button and the Stepper buttons to try and increment/decrement the value.

Tested on both Firefox and Chrome, so not a Browser-specific issue.

Not a high priority bug, I know, but still needs to be documented somewhere.
Once I've finished adding bugs and observations in the Issues, If I have the time I'll take a stab at fixing it on our local install and adding the fix to a Fork, then doing a Pull Request mentioning the issues, but I don't know where the different parts to fix are located, so might not be too optimal.

Have a good day, and thanks for the awesome job on Waves !

Peter.

Admin and User email notifications fof Errors both go to the same email address

When a service fails, the error messages for the admin and the user both go to the same email address.

Depending on if the "email me results" field was left blank (both go to the Admin) or the user entered their email (both go to the User).

I've gone as far as the waves/wcore/mails.py script to try and track the problem, and it seems that these two functions :

def send_job_error_email(self, job):

        """
        Send Job error email

        :return: the number of mail sent, should be 0 or 1
        :rtype: int
        """
        return self._send_job_mail(job, "waves/emails/job_error.tpl")

def send_job_admin_error(self, job):
        """ Admin mail to notify run error
        :return: the number of mail sent, should be 0 or 1
        :rtype: int
        """
        return self._send_job_mail(job, "waves/emails/job_admin_error.tpl")

both call upon _send_job_mail, with the same arguments.

def _send_job_mail(self, job, template, subject=None):
        """ Check if send mail is needed, in such case, create a template email and... send it to specified client

        :return: the number of mail sent, should be 0 or 1
        :rtype: int
        """
        if self.mail_activated and job.notify:
            context = self.get_context_data()
            context['job'] = job
            mail_subject = "[WAVES - %s] -- %s -- " % (
                job.title, job.get_status_display()) if subject is None else subject
            try:
                message = get_template(template_name=template).render(context)
                msg = EmailMessage(subject=mail_subject, body=message, to=[job.email_to],
                                   from_email=config.SERVICES_EMAIL)
                msg.send(fail_silently=True)
                job.job_history.create(message='Notification email sent', status=job.status, is_admin=True)
            except Exception as e:
                job.job_history.create(message='Notification email not sent %s' % e.message, status=job.status,
                                       is_admin=True)
                logger.exception("Failed to send mail to %s from %s :%s", job.email_to, config.SERVICES_EMAIL, e)
        else:
            logger.info('Mail not sent to %s, mails are not activated', job.email_to)
            return 0

To me it seems like to=[job.email_to] will either be the user's email if set, or the service email if not set, no matter if it's called by send_job_admin_error or send_job_error_email.

Am I missing something or is there an override missing to force to=[job.email_to] to be to=[config.ADMIN_EMAIL] when the error message is directed at the Administrator ?

File Input Issues

While migrating to python 3

  • File inputs are not submitted hence triggering exceptions while creating job
  • File inputs samples get duplicated on form display and api

Refactor Services / Submission

Swappable models seems to be an obsolete feature, hence to be remove from version 2.x.
This imply a slight refactor of code

Service asking password when ssh key provided

When creating a service associated to a 'ssh cluster' computing infrastructure which was created with a public key for authentication, WAVES asks for a password. This is the intended behaviour for a computing infrastructure with an authentication procedure using login / password. When using a public key, WAVES should not ask for a password.

Could not import 'waves.wcore.adaptors.shell.SshShellAdaptor' for WAVES settings 'AttributeError'

(venv) [sam@c02 waves]$ ./manage.py check
Traceback (most recent call last):
File "manage.py", line 22, in
execute_from_command_line(sys.argv)
File "/mnt/nfs/data/user/sam/project/waves/venv/lib/python2.7/site-packages/django/core/management/init.py", line 364, in execute_from_command_line
utility.execute()
File "/mnt/nfs/data/user/sam/project/waves/venv/lib/python2.7/site-packages/django/core/management/init.py", line 356, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/mnt/nfs/data/user/sam/project/waves/venv/lib/python2.7/site-packages/django/core/management/base.py", line 283, in run_from_argv
self.execute(*args, **cmd_options)
File "/mnt/nfs/data/user/sam/project/waves/venv/lib/python2.7/site-packages/django/core/management/base.py", line 330, in execute
output = self.handle(*args, **options)
File "/mnt/nfs/data/user/sam/project/waves/venv/lib/python2.7/site-packages/django/core/management/commands/check.py", line 68, in handle
fail_level=getattr(checks, options['fail_level']),
File "/mnt/nfs/data/user/sam/project/waves/venv/lib/python2.7/site-packages/django/core/management/base.py", line 359, in check
include_deployment_checks=include_deployment_checks,
File "/mnt/nfs/data/user/sam/project/waves/venv/lib/python2.7/site-packages/django/core/management/base.py", line 346, in _run_checks
return checks.run_checks(**kwargs)
File "/mnt/nfs/data/user/sam/project/waves/venv/lib/python2.7/site-packages/django/core/checks/registry.py", line 81, in run_checks
new_errors = check(app_configs=app_configs)
File "/mnt/nfs/data/user/sam/project/waves/waves/wcore/apps.py", line 57, in check_waves_config
elif len(waves_settings.ADAPTORS_CLASSES) == 0:
File "/mnt/nfs/data/user/sam/project/waves/waves/wcore/settings.py", line 129, in getattr
val = perform_import(val, attr)
File "/mnt/nfs/data/user/sam/project/waves/waves/wcore/settings.py", line 34, in perform_import
return [import_from_string(item) for item in val]
File "/mnt/nfs/data/user/sam/project/waves/waves/wcore/settings.py", line 49, in import_from_string
raise ImportError(msg)
ImportError: Could not import 'waves.wcore.adaptors.shell.SshShellAdaptor' for WAVES settings 'AttributeError': 'module' object has no attribute 'Configurable'.

SGE / Slurm testing

Use some SGE / Slurm docker container to enable self testing with travis-ci.

input app_short_name unavailable when nested in dependent inputs in REST API

app_short_name key is needed to declare inputs of a new job.
In services.submission and service.submissions_list app_short_name is used as the key for 'inputs' dictionary. There's no other reference of this app_short_name in an entry of 'inputs'.
But when the input is dependent of an other input, 'dependents_inputs' is a list not a dictionary. There's no key to refer as app_short_name.

Undocumented REST API connexion

It is possible to connect a client with username/password in the REST API with :

from coreapi import Client, auth
url='http://127.0.0.1:8000/api/schema'
username='toto'
password='secret123'
client = Client(
            auth=auth.BasicAuthentication(
                username=username, 
                password=password))
document = client.get(url)

But this method is not in the documentation.

Delete buttons redirects to wrong links

The delete buttons on Service, Job, Infrastructure and Api Auths configuration pages are broken.

Here's an example showing the Delete button on a Service, and the link it redirects to:

screenshot from 2019-01-11 14-38-40

Here are the links I get from the different instances of this bug, and the links I expected to get (Which, I've tested, exist and are functional, just not accessible using the Buttons)
(CAPS indicate variable elements of the links)

Actual Expected
http://SITE/admin/wcore/service/ID/change/ http://SITE/admin/wcore/service/ID/delete/
http://SITE/admin/wcore/job/ID/change/ http://SITE/admin/wcore/job/ID/delete/
http://SITE/admin/wcore/runner/ID/change/ http://SITE/admin/wcore/runner/ID/delete/
http://SITE/admin/authentication/wavesapiuser/API_KEY/change/ http://SITE/admin/authentication/wavesapiuser/API_KEY/delete/

Waves-Core deployment

Dear,

First and foremost, I'd like to congratulate you all for such a great tool! I just started to use it and in 16 hours I managed to have my pipeline in with little knowledge on Django.

Now I am trying to deploy the app to our department server, so everybody can access freely the service and do their queries to our server. This is proving to be a bit more challenging. Would it be possible for you to include a guide for deployment in Linux servers (p.e. Ubuntu 18.04 - Apache2) in your documentation?

Thank you very much and again, congratulations on your work.

~ Joan ~

REST API returned answers documentation

The returned answers of the REST API is not documented. I start a first grammar document (not perfect, unsorted and incomplete) of the expected answers.
WavesRestApiGrammar.txt

WavesRestApiGrammar.md

WAVES REST API returns

jobs

list

list all jobs of the user

JOBS_LIST=list(JOB_SHORT*)
JOB_SHORT=OrderedDict(
    'url': URL
    'slug':UID
    'title':STR
    'service':URL
    'submission':URL
    'client':MAIL
    'status':STATUS
    'created':TIMESTAMP
    'updated':TIMESTAMP
    'last_message':MSG
    )
STATUS=OrderedDict(
    'code':STATUS_CODE
    'label':STR
    )
MSG=OrderedDict(
    'timestamp':TIMESTAMP
    'message':STR
    )
TIMESTAMP=YYYY-MM-ddThh:mm:ss.ssssssGMT
GMT=(+|-)hh:mm
UID=STR
MAIL=STR
STATUS_CODE=INT

read

details of a specific job

JOBS_READ=DETAILED_JOB
DETAILED_JOB=OrderedDict(
    'url':URL
    'slug':UID
    'title':STR
    'service':URL
    'submission':URL
    'client':MAIL
    'status':STATUS
    'created':TIMESTAMP
    'updated':TIMESTAMP
    'inputs':VAL_INPUTS
    'outputs':VAL_OUTPUTS
    'history':list(HISTORY_ENTRY*)
    'last_message':MSG
    )
VAL_INPUTS=OrderedDict(VAL_INPUT*)
VAL_INPUT=INPUT_NAME:VAL_INPUT_PARAM
INPUT_NAME=STR
VAL_INPUT_PARAM=VAL_INPUT_PARAM_FILE
            |VAL_INPUT_PARAM_TEXT
            |VAL_INPUT_PARAM_DECIMAL
            |VAL_INPUT_PARAM_INT
#TODO:Complet all possible valued inputs param type
VAL_INPUT_PARAM_FILE=OrderedDict(
    'param_type':'file'
    'name':STR
    'value':BASENAME_STR
    'label':STR
    'url':URL
    )
VAL_INPUT_PARAM_TEXT=OrderedDict(
    'param_type':'text'
    'name':STR
    'value':TEXT_VALUE
    'label':STR
    )
VAL_INPUT_PARAM_DECIMAL=OrderedDict(
    'param_type':'decimal'
    'name':STR
    'value':FLOAT_STR
    'label':STR
    )
VAL_INPUT_PARAM_INT=OrderedDict(
    'param_type':'int'
    'name':STR
    'value':INT_STR
    'label':STR
    )
BASENAME_STR=STR
TEXT_VALUE=STR
FLOAT_STR=STR #float in a string
INT_STR=STR #int in a string
VAL_OUTPUTS=OrderedDict(VAL_OUTPUT*)
VAL_OUTPUT=OUTPUT_NAME:VAL_OUTPUT_PARAM
VAL_OUTPUT_PARAM=OrderedDict(
    'label':STR
    'file_name':BASENAME_STR
    'extension':FILE_EXTENSION
    'url':URL|NONE
    )
FILE_EXTENSION=STR #if not empty string, begin with '.'
HISTORY_ENTRY=OrderedDict(
    'status_txt':STR
    'status_code':STATUS_CODE
    'timestamp':TIMESTAMP
    'message':STR
)

delete

delete a job from job list

JOBS_DELETE=NONE

cancel

cancel a none finished job

TODO:JOBS_CANCEL=NONE?

inputs

List all inputs values of a job

JOBS_INPUTS=VAL_INPUTS

input

content of an input file

JOBS_INPUT=FILE_CONTENT
FILE_CONTENT=STR

outputs

List all output values of a job

JOBS_OUTPUTS=VAL_OUTPUTS

output

content of an ouput file

JOBS_OUTPUT=FILE_CONTENT

services

submissions

jobs

read

list all jobs of a user for a submission

SERVICES_SUBMISSIONS_JOBS_READ:list(JOB_SHORT*)
create

create a new jobs

SERVICES_SUBMISSIONS_JOBS_CREATE:#TODO:NONE ?

submission_form

The HTML form of the submission

SERVICES_SUBMISSIONS_SUBMISSION_FORM:HTML_FORM  #Only form, not a valid HTML page

TODO : seems to be formated to be used with bootcamp.

SERVICES_SUBMISSIONS_SUBMISSION_FORM is for services.submissions.submission_form not for services.submissions.submission.form

list

List all available services

SERVICES_LIST=list(SERVICES_SHORT*)
SERVICES_SHORT=OrderedDict(
    'url':URL
    'name':STR
    'version':VERSION_NUM
    'short_description':STR
    'service_app_name':STR
    'jobs':URL
    'submissions':list(SUBMISSION_VSHORT*)
    'form':URL
    'created':URL
    'updated':URL
    )
VERSION_NUM=STR #int.(int.)*int
SUBMISSION_VSHORT=OrderedDict(
    'url':URL
    'submission_app_name':STR
    )

read

A single service informations

SERVICES_READ=SERVICES_SHORT

form

The HTML form of the first submission of the service.

SERVICES_FORM=HTML_FORM  #Only form, not a valid HTML page

TODO : seems to be formated to be used with bootcamp.

jobs

list of the job of the user for this service

SERVICES_JOBS=list(JOB_SHORT)

submission

detail of a submission

SERVICES_SUBMISSION=DETAILED_SUBMISSION

submissions_list

list of detailed Submission of a services

SERVICES_SUBMISSIONS_LIST=list(DETAILED_SUBMISSION*)
DETAILED_SUBMISSION=OrderedDict(
    'service':URL
    'name':STR
    'submission_app_name':STR
    'form':URL
    'jobs':URL
    'inputs':INPUTS_FORM
    'outputs':OUTPUTS_FORM
    )
INPUTS_FORM=OrderedDict(INPUT_FORM*)
INPUT_FORM=INPUT_FORM_NAME:INPUT_FORM_DETAIL
INPUT_FORM_NAME=STR
INPUT_FORM_DETAIL=INPUT_FORM_DETAIL_LIST
                |INPUT_FORM_DETAIL_FILE
                |INPUT_FORM_DETAIL_INT
                |INPUT_FORM_DETAIL_DECIMAL
                |INPUT_FORM_DETAIL_TEXT
                #TODO : to complete all possibilites
INPUT_FORM_DETAIL_LIST=OrderedDict(
    'label':STR
    'default':STR|NONE
    'type':'list'
    'mandatory':BOOL
    'description':STR
    'multiple':BOOL
    'edam_formats':NONE|STR #TODO:Maybe String or list of a valid edam_format reference
    'edam_datas':NONE|STR #TODO:Maybe String or list of a valid edam_data reference
    ('dependent_inputs':DEPENDENT_INPUTS_LIST)?
    'values_list':INPUT_FORM_DETAIL_LIST_VALUES_LIST
    )
INPUT_FORM_DETAIL_LIST_VALUES_LIST=OrderedDict(
    'labels'=list(STR*)
    'values'=list(STR*)
    )#Same number of labels than values
INPUT_FORM_DETAIL_FILE=OrderedDict(
    'label':STR
    'default':STR|NONE
    'type':'file'
    'mandatory':BOOL
    'description':STR
    'multiple':BOOL
    'edam_formats':NONE|STR #TODO:Maybe String or list of a valid edam_format reference
    'edam_datas':NONE|STR #TODO:Maybe String or list of a valid edam_data reference
    'max_size':INT
    'allowed_extensions':EXTENSIONS_REGEX
    #TODO : dependent_inputs ?
    )
INPUT_FORM_DETAIL_INT=OrderedDict(
    'label':STR
    'default':STR|NONE
    'type':'int'
    'mandatory':BOOL
    'description':STR
    'multiple':BOOL
    'edam_formats':NONE|STR #TODO:Maybe String or list of a valid edam_format reference
    'edam_datas':NONE|STR #TODO:Maybe String or list of a valid edam_data reference
    'min_val':INT|NONE
    'max_val':INT|NONE
    #TODO : dependent_inputs ?
    )
INPUT_FORM_DETAIL_DECIMAL=OrderedDict(
    'label':STR
    'default':STR|NONE
    'type':'decimal'
    'mandatory':BOOL
    'description':STR
    'multiple':BOOL
    'edam_formats':NONE|STR #TODO:Maybe String or list of a valid edam_format reference
    'edam_datas':NONE|STR #TODO:Maybe String or list of a valid edam_data reference
    'min_val':FLOAT|NONE
    'max_val':FLOAT|NONE
    #TODO : dependent_inputs ?
    )
INPUT_FORM_DETAIL_TEXT=OrderedDict(
    'label':STR
    'default':STR|NONE
    'type':'text'
    'mandatory':BOOL
    'description':STR
    'multiple':BOOL
    'edam_formats':NONE|STR #TODO:Maybe String or list of a valid edam_format reference
    'edam_datas':NONE|STR #TODO:Maybe String or list of a valid edam_data reference
    'mzx_length':INT
    #TODO : dependent_inputs ?
    )
EXTENSIONS_REGEX=STR #'*' for all extension
DEPENDENT_INPUTS_LIST=list(DEPENDENT_INPUT*)
DEPENDENT_INPUT<extend(INPUT_FORM_DETAIL)>=OrderedDict( #TODO: find a better way to write this.
    'when_value':STR
    ...
)
OUTPUTS_FORM=OrderedDict(OUTPUT_FORM*)
OUTPUT_FORM=OUTPUT_FORM_NAME:OUTPUT_FORM_DETAIL
OUTPUT_FORM_NAME=STR
OUTPUT_FORM_DETAIL=OrderedDict(
    'label':STR
    'name':STR
    'file_name':FORMATED_FILE_NAME
    'help_text':STR
    'edam_format':NONE|STR #TODO:Maybe String of a valid edam_format reference
    'edam_data':NONE|STR #TODO:Maybe String of a valid edam_data reference
    'issued_from':INPUT_FORM_NAME
    )
FORMATED_FILE_NAME=STR #%s is remplaced by the 'issued_from' input value.

SERVICES_SUBMISSIONS_LIST is for service.submissions_list not for service.submissions.list

Accessing Job Details using the Admin "Jobs" page gives "TypeError vars() argument must have __dict__ attribute" error

After updating our local installation to the new version, we had a few bugs.
Most of them resolved themselves as problems with our server, the wrong user launching crontab add, and other such small but annoying adjustments, and we fixed those after some work.

There are, however, two bugs that I cannot figure out, and that don't seem to come from anything on our end, as far as I've been able to tell.

This issue details one of them.


This bug only affects jobs launched after the update to the new version.
We migrated the old database over to the new version, and the jobs already present in it from before have their details page accessible.

Expected :

When clicking the identifier of a job on the Home >WAVES CORE > Jobs page, we expect to see the job details page, that shows the details of the job in question along with links to it's results, etc.

Bug:

If I attempt to access this page, I receive a TypeError saying vars() argument must have __dict__ attribute

Example:

image

clicking the identifier of a job launched after the upgrade:

18754290

Traceback:

Environment:


Request Method: GET
Request URL: http://xx.xx.xx.xxx/admin/wcore/job/173/change/

Django Version: 1.11.17
Python Version: 2.7.5
Installed Applications:
[u'polymorphic',
 u'django.contrib.admin',
 u'django.contrib.auth',
 u'django.contrib.contenttypes',
 u'django.contrib.sessions',
 u'django.contrib.messages',
 u'django.contrib.staticfiles',
 u'waves.wcore',
 u'waves.authentication',
 u'crispy_forms',
 u'rest_framework',
 u'corsheaders',
 u'adminsortable2',
 u'django_crontab']
Installed Middleware:
[u'django.middleware.security.SecurityMiddleware',
 u'django.contrib.sessions.middleware.SessionMiddleware',
 u'corsheaders.middleware.CorsMiddleware',
 u'django.middleware.common.CommonMiddleware',
 u'django.middleware.csrf.CsrfViewMiddleware',
 u'django.contrib.auth.middleware.AuthenticationMiddleware',
 u'django.contrib.messages.middleware.MessageMiddleware',
 u'django.middleware.clickjacking.XFrameOptionsMiddleware']


Template error:
In template /usr/lib/python2.7/site-packages/django/contrib/admin/templates/admin/includes/fieldset.html, error at line 17
   vars() argument must have __dict__ attribute   7 :         <div class="form-row{% if line.fields|length_is:'1' and line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}">
   8 :             {% if line.fields|length_is:'1' %}{{ line.errors }}{% endif %}
   9 :             {% for field in line %}
   10 :                 <div{% if not line.fields|length_is:'1' %} class="field-box{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not field.is_readonly and field.errors %} errors{% endif %}{% if field.field.is_hidden %} hidden{% endif %}"{% elif field.is_checkbox %} class="checkbox-row"{% endif %}>
   11 :                     {% if not line.fields|length_is:'1' and not field.is_readonly %}{{ field.errors }}{% endif %}
   12 :                     {% if field.is_checkbox %}
   13 :                         {{ field.field }}{{ field.label_tag }}
   14 :                     {% else %}
   15 :                         {{ field.label_tag }}
   16 :                         {% if field.is_readonly %}
   17 :                             <div class="readonly"> {{ field.contents }} </div>
   18 :                         {% else %}
   19 :                             {{ field.field }}
   20 :                         {% endif %}
   21 :                     {% endif %}
   22 :                     {% if field.field.help_text %}
   23 :                         <div class="help">{{ field.field.help_text|safe }}</div>
   24 :                     {% endif %}
   25 :                 </div>
   26 :             {% endfor %}
   27 :         </div>


Traceback:

File "/usr/lib/python2.7/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/usr/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
  217.                 response = self.process_exception_by_middleware(e, request)

File "/usr/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
  215.                 response = response.render()

File "/usr/lib/python2.7/site-packages/django/template/response.py" in render
  107.             self.content = self.rendered_content

File "/usr/lib/python2.7/site-packages/django/template/response.py" in rendered_content
  84.         content = template.render(context, self._request)

File "/usr/lib/python2.7/site-packages/django/template/backends/django.py" in render
  66.             return self.template.render(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render
  207.                     return self._render(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in _render
  199.         return self.nodelist.render(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/usr/lib/python2.7/site-packages/django/template/loader_tags.py" in render
  177.             return compiled_parent._render(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in _render
  199.         return self.nodelist.render(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/usr/lib/python2.7/site-packages/django/template/loader_tags.py" in render
  177.             return compiled_parent._render(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in _render
  199.         return self.nodelist.render(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/usr/lib/python2.7/site-packages/django/template/loader_tags.py" in render
  72.                 result = block.nodelist.render(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/usr/lib/python2.7/site-packages/django/template/loader_tags.py" in render
  72.                 result = block.nodelist.render(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/usr/lib/python2.7/site-packages/django/template/defaulttags.py" in render
  216.                     nodelist.append(node.render_annotated(context))

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/usr/lib/python2.7/site-packages/django/template/loader_tags.py" in render
  216.                 return template.render(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render
  209.                 return self._render(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in _render
  199.         return self.nodelist.render(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/usr/lib/python2.7/site-packages/django/template/defaulttags.py" in render
  216.                     nodelist.append(node.render_annotated(context))

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/usr/lib/python2.7/site-packages/django/template/defaulttags.py" in render
  216.                     nodelist.append(node.render_annotated(context))

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/usr/lib/python2.7/site-packages/django/template/defaulttags.py" in render
  322.                 return nodelist.render(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/usr/lib/python2.7/site-packages/django/template/defaulttags.py" in render
  322.                 return nodelist.render(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in render
  1040.             output = self.filter_expression.resolve(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in resolve
  708.                 obj = self.var.resolve(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in resolve
  849.             value = self._resolve_lookup(context)

File "/usr/lib/python2.7/site-packages/django/template/base.py" in _resolve_lookup
  911.                             current = current()

File "/usr/lib/python2.7/site-packages/django/contrib/admin/helpers.py" in contents
  209.             f, attr, value = lookup_field(field, obj, model_admin)

File "/usr/lib/python2.7/site-packages/django/contrib/admin/utils.py" in lookup_field
  295.             value = attr(obj)

File "/srv/waves-core-1.6.5.1/waves/wcore/admin/jobs.py" in get_run_details
  143.             ['\n{}: {}'.format(det[0], det[1]) for det in vars(obj.run_details).items()]) + "</pre>")

Exception Type: TypeError at /admin/wcore/job/173/change/
Exception Value: vars() argument must have __dict__ attribute


Test Coverage improvement

Test coverage is currently lower that it should be. Add more unit test to raise this level to acceptable value.

Error on deleting a service with File inputs

It's impossible to delete a service with a "File input". It raise this error :
Cannot query "Data type (ListParam)": Must be "FileInput" instance.

There is a workaround: go on submissions methods, delete all "File inputs" one by one, then go back to services page to delete the service.

All error report**
ValueError at /admin/wcore/service/
Cannot query "Data type (ListParam)": Must be "FileInput" instance.
Request Method: POST
Request URL: http://127.0.0.1:8000/admin/wcore/service/
Django Version: 1.11.14
Exception Type: ValueError
Exception Value:
Cannot query "Data type (ListParam)": Must be "FileInput" instance.
Exception Location: /home/milanesi/.venvs/wavescoreenv/local/lib/python2.7/site-packages/django/db/models/sql/query.py in check_query_object_type, line 1054
Python Executable: /home/milanesi/.venvs/wavescoreenv/bin/python
Python Version: 2.7.12
Python Path:
['/home/milanesi/Documents/WAVES/Formations/TP_WAVES/waves',
'/home/milanesi/.venvs/wavescoreenv/lib/python2.7',
'/home/milanesi/.venvs/wavescoreenv/lib/python2.7/plat-x86_64-linux-gnu',
'/home/milanesi/.venvs/wavescoreenv/lib/python2.7/lib-tk',
'/home/milanesi/.venvs/wavescoreenv/lib/python2.7/lib-old',
'/home/milanesi/.venvs/wavescoreenv/lib/python2.7/lib-dynload',
'/usr/lib/python2.7',
'/usr/lib/python2.7/plat-x86_64-linux-gnu',
'/usr/lib/python2.7/lib-tk',
'/home/milanesi/.venvs/wavescoreenv/local/lib/python2.7/site-packages',
'/home/milanesi/.venvs/wavescoreenv/lib/python2.7/site-packages']

File Input samples are visible even when File Input is hidden

When I configure a File Input as being dependent on a certain list value, and that list value is not selected, any Sample files related to that File Input still appears in the window.

image

image

Steps to Reproduce:

  1. Create a service
  2. Create a Submission Method
  3. Create a List input with values on|1 and off|0
  4. Create a File Input without the copy-paste enabled
  5. Set the File input to have a sample file
  6. Set the File input so that Sample dependency is linked to the List Input, with value "1"

If Copy-paste is enabled in the file input, it works as expected :

image
image

Add Textarea input support

Only one row input box(namely Text Input) for service is supported,but we need multi-row input area.
image

image

Would you like to add this feature?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.