mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-21 13:50:20 +08:00
Merge branch 'release_21.01' into dev
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: testing
|
||||
name: testing
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: test
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: test
|
||||
spec:
|
||||
containers:
|
||||
- image: postgres:12
|
||||
name: postgres
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
env:
|
||||
- name: POSTGRES_DB
|
||||
value: postgres
|
||||
- name: POSTGRES_USER
|
||||
value: postgres
|
||||
- name: POSTGRES_PASSWORD
|
||||
value: postgres
|
||||
- image: rabbitmq
|
||||
name: rabbitmq
|
||||
ports:
|
||||
- containerPort: 5672
|
||||
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
set -ex
|
||||
|
||||
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
kubectl apply -f "$SCRIPTDIR/deployment.yaml"
|
||||
kubectl expose deployment testing --type=LoadBalancer --name=testing-service
|
||||
|
||||
CLUSTER_IP=$(kubectl get service testing-service -o jsonpath='{.spec.clusterIP}')
|
||||
GALAXY_TEST_DBURI="postgresql://postgres:postgres@${CLUSTER_IP}:5432/galaxy?client_encoding=utf-8"
|
||||
GALAXY_TEST_AMQP_URL="amqp://${CLUSTER_IP}:5672)//"
|
||||
export GALAXY_TEST_DBURI
|
||||
export GALAXY_TEST_AMQP_URL
|
||||
@@ -6,7 +6,7 @@ env:
|
||||
jobs:
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
subset: ['upload_datatype', 'extended_metadata', 'kubernetes', 'not (upload_datatype or extended_metadata or kubernetes)']
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:11
|
||||
image: postgres:13
|
||||
env:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
@@ -60,8 +60,15 @@ jobs:
|
||||
run: sudo apt-get update && sudo apt-get install ffmpeg -y
|
||||
if: matrix.subset == 'upload_datatype'
|
||||
- name: Run tests
|
||||
if: matrix.subset != 'kubernetes'
|
||||
run: './run_tests.sh -integration test/integration -- -k "${{ matrix.subset }}"'
|
||||
working-directory: 'galaxy root'
|
||||
- name: Run tests
|
||||
if: matrix.subset == 'kubernetes'
|
||||
run: |
|
||||
. .ci/minikube-test-setup/start_services.sh
|
||||
./run_tests.sh -integration test/integration -- -k "${{ matrix.subset }}"
|
||||
working-directory: 'galaxy root'
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
|
||||
@@ -18,6 +18,7 @@ export default {
|
||||
props: {
|
||||
slug: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</div>
|
||||
<div v-else>
|
||||
<b-form-checkbox switch class="make-accessible" v-model="item.importable" @change="onImportable">
|
||||
Make {{ model_class }} accessible.
|
||||
Make {{ model_class }} accessible
|
||||
</b-form-checkbox>
|
||||
<b-form-checkbox
|
||||
v-if="item.importable"
|
||||
@@ -22,38 +22,38 @@
|
||||
@change="onPublish"
|
||||
>
|
||||
Make {{ model_class }} publicly available in
|
||||
<a :href="published_url" target="_top">Published {{ plural_name }}</a> section.
|
||||
<a :href="published_url" target="_top">Published {{ plural_name }}</a>
|
||||
</b-form-checkbox>
|
||||
<br />
|
||||
<div>
|
||||
<div v-if="item.importable">
|
||||
<div>
|
||||
This {{ model_class }} is currently <strong>{{ itemStatus }}</strong
|
||||
>.
|
||||
</div>
|
||||
<p>Anyone can view and import this {{ model_class }} by visiting the following URL:</p>
|
||||
<blockquote>
|
||||
<b-button title="Edit URL" @click="onEdit" v-b-tooltip.hover variant="link" size="sm">
|
||||
<font-awesome-icon icon="edit" />
|
||||
</b-button>
|
||||
<b-button id="tooltip-clipboard" @click="onCopy" @mouseout="onCopyOut" variant="link" size="sm">
|
||||
<font-awesome-icon icon="link" />
|
||||
</b-button>
|
||||
<b-tooltip target="tooltip-clipboard" triggers="hover">
|
||||
{{ tooltipClipboard }}
|
||||
</b-tooltip>
|
||||
<a v-if="showUrl" id="item-url" :href="itemUrl" target="_top" class="ml-2">
|
||||
{{ itemUrl }}
|
||||
</a>
|
||||
<span v-else id="item-url-text">
|
||||
{{ itemUrlParts[0] }}<SlugInput class="ml-1" :slug="itemUrlParts[1]" @onChange="onChange" />
|
||||
</span>
|
||||
</blockquote>
|
||||
</div>
|
||||
<div v-else>
|
||||
Access to this {{ model_class }} is currently restricted so that only you and the users listed below
|
||||
can access it. Note that sharing a History will also allow access to all of its datasets.
|
||||
<div v-if="item.importable">
|
||||
<div>
|
||||
This {{ model_class }} is currently <strong>{{ itemStatus }}</strong
|
||||
>.
|
||||
</div>
|
||||
<p>Anyone can view and import this {{ model_class }} by visiting the following URL:</p>
|
||||
<blockquote>
|
||||
<b-button title="Edit URL" @click="onEdit" v-b-tooltip.hover variant="link" size="sm">
|
||||
<font-awesome-icon icon="edit" />
|
||||
</b-button>
|
||||
<b-button id="tooltip-clipboard" @click="onCopy" @mouseout="onCopyOut" variant="link" size="sm">
|
||||
<font-awesome-icon icon="link" />
|
||||
</b-button>
|
||||
<b-tooltip target="tooltip-clipboard" triggers="hover">
|
||||
{{ tooltipClipboard }}
|
||||
</b-tooltip>
|
||||
<a v-if="showUrl" id="item-url" :href="itemUrl" target="_top" class="ml-2">
|
||||
url:
|
||||
{{ itemUrl }}
|
||||
</a>
|
||||
<span v-else id="item-url-text">
|
||||
slug:
|
||||
{{ itemUrlParts[0] }}<SlugInput class="ml-1" :slug="itemUrlParts[1]" @onChange="onChange" />
|
||||
</span>
|
||||
</blockquote>
|
||||
</div>
|
||||
<div v-else>
|
||||
Access to this {{ model_class }} is currently restricted so that only you and the users listed below can
|
||||
access it. Note that sharing a History will also allow access to all of its datasets.
|
||||
</div>
|
||||
<br />
|
||||
<h4>Share {{ model_class }} with Individual Users</h4>
|
||||
@@ -127,7 +127,7 @@ export default {
|
||||
errMsg: null,
|
||||
item: {
|
||||
title: "title",
|
||||
username_and_slug: "username_and_slug",
|
||||
username_and_slug: "username/slug",
|
||||
importable: false,
|
||||
published: false,
|
||||
users_shared_with: [],
|
||||
@@ -205,16 +205,10 @@ export default {
|
||||
},
|
||||
onImportable(importable) {
|
||||
if (importable) {
|
||||
this.setSharing("make_accessible_via_link");
|
||||
if (this.item.published) {
|
||||
this.setSharing("publish");
|
||||
} else {
|
||||
this.setSharing("unpublish");
|
||||
}
|
||||
this.setSharing(`make_accessible_via_link-${this.item.published ? "publish" : "unpublish"}`);
|
||||
} else {
|
||||
this.item.published = false;
|
||||
this.setSharing("disable_link_access");
|
||||
this.setSharing("unpublish");
|
||||
this.setSharing("disable_link_access-unpublish");
|
||||
}
|
||||
},
|
||||
onPublish(published) {
|
||||
@@ -253,12 +247,14 @@ export default {
|
||||
action: action,
|
||||
user_id: user_id,
|
||||
};
|
||||
axios
|
||||
return axios
|
||||
.post(`${getAppRoot()}api/${this.pluralNameLower}/${this.id}/sharing`, data)
|
||||
.then((response) => {
|
||||
if (response.data.skipped) {
|
||||
this.errMsg = "Some of the items within this object were not published due to an error.";
|
||||
}
|
||||
this.item = response.data;
|
||||
this.ready = true;
|
||||
})
|
||||
.catch((error) => (this.errMsg = error.response.data.err_msg));
|
||||
},
|
||||
|
||||
@@ -44,8 +44,8 @@ export function standardInit(label = "Galaxy", appFactory = defaultAppFactory) {
|
||||
// functions even if they are registered super-late because combineLatest
|
||||
// will not remake a the existing Galaxy or config objects, it'll just run
|
||||
// the new batch of freshly registered init functions
|
||||
combineLatest(config$, galaxy$, initializations$).subscribe(([config, galaxy, inits]) => {
|
||||
console.groupCollapsed(`runInitializations`, label, serverPath());
|
||||
combineLatest([config$, galaxy$, initializations$]).subscribe(([config, galaxy, inits]) => {
|
||||
console.group(`runInitializations`, label, serverPath());
|
||||
inits.forEach((fn) => fn(galaxy, config));
|
||||
clearInitQueue();
|
||||
console.groupEnd();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var gtnWebhookLoaded = false;
|
||||
var lastUpdate = 0;
|
||||
|
||||
function removeOverlay() {
|
||||
document.getElementById("gtn-container").style.visibility = "hidden";
|
||||
@@ -8,9 +9,43 @@ function showOverlay() {
|
||||
document.getElementById("gtn-container").style.visibility = "visible";
|
||||
}
|
||||
|
||||
function getIframeUrl() {
|
||||
var loc;
|
||||
try {
|
||||
loc = document.getElementById("gtn-embed").contentWindow.location.pathname;
|
||||
} catch (e) {
|
||||
loc = null;
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
|
||||
function getIframeScroll() {
|
||||
var loc;
|
||||
try {
|
||||
loc = parseInt(document.getElementById("gtn-embed").contentWindow.scrollY);
|
||||
} catch (e) {
|
||||
loc = 0;
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
|
||||
function restoreLocation() {}
|
||||
|
||||
function persistLocation() {
|
||||
// Don't save every scroll event.
|
||||
var time = new Date().getTime();
|
||||
if (time - lastUpdate < 1000) {
|
||||
return;
|
||||
}
|
||||
lastUpdate = time;
|
||||
window.localStorage.setItem("gtn-in-galaxy", `${getIframeScroll()} ${getIframeUrl()}`);
|
||||
}
|
||||
|
||||
function addIframe() {
|
||||
let url, message;
|
||||
let url, message, onloadscroll;
|
||||
gtnWebhookLoaded = true;
|
||||
let storedData = false;
|
||||
let safe = false;
|
||||
|
||||
// Test for the presence of /training-material/. If that is available we
|
||||
// can opt in the fancy click-to-run features. Otherwise we fallback to
|
||||
@@ -24,7 +59,19 @@ function addIframe() {
|
||||
<a href="https://docs.galaxyproject.org/en/master/admin/special_topics/gtn.html">Click to run</a> unavailable.
|
||||
</span>`;
|
||||
} else {
|
||||
url = "/training-material/";
|
||||
safe = true;
|
||||
|
||||
var storedLocation = window.localStorage.getItem("gtn-in-galaxy");
|
||||
if (
|
||||
storedLocation !== null &&
|
||||
storedLocation.split(" ")[1] !== undefined &&
|
||||
storedLocation.split(" ")[1].startsWith("/training-material/")
|
||||
) {
|
||||
onloadscroll = storedLocation.split(" ")[0];
|
||||
url = storedLocation.split(" ")[1];
|
||||
} else {
|
||||
url = "/training-material/";
|
||||
}
|
||||
message = "";
|
||||
}
|
||||
})
|
||||
@@ -48,8 +95,25 @@ function addIframe() {
|
||||
removeOverlay();
|
||||
});
|
||||
|
||||
// Only setup the listener if it won't crash things.
|
||||
if (safe) {
|
||||
// Listen to the scroll position
|
||||
document.getElementById("gtn-embed").contentWindow.addEventListener("scroll", () => {
|
||||
persistLocation();
|
||||
});
|
||||
}
|
||||
|
||||
// Depends on the iframe being present
|
||||
document.getElementById("gtn-embed").addEventListener("load", () => {
|
||||
// Save our current location when possible
|
||||
if (onloadscroll !== undefined) {
|
||||
document.getElementById("gtn-embed").contentWindow.scrollTo(0, parseInt(onloadscroll));
|
||||
onloadscroll = undefined;
|
||||
}
|
||||
|
||||
if (safe) {
|
||||
persistLocation();
|
||||
}
|
||||
var gtn_tools = $("#gtn-embed").contents().find("span[data-tool]");
|
||||
// Buttonify
|
||||
gtn_tools.addClass("galaxy-proxy-active");
|
||||
|
||||
@@ -3851,13 +3851,13 @@
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description:
|
||||
Determines how metadata will be set. Valid values are `directory`,
|
||||
`extended` and `legacy`. In extended mode jobs will decide if a
|
||||
tool run failed, the object stores configuration is serialized and
|
||||
made available to the job and is used for writing output datasets
|
||||
to the object store as part of the job and dynamic output
|
||||
discovery (e.g. discovered datasets <discover_datasets>,
|
||||
unpopulated collections, etc) happens as part of the job.
|
||||
Determines how metadata will be set. Valid values are `directory`
|
||||
and `extended`. In extended mode jobs will decide if a tool run
|
||||
failed, the object stores configuration is serialized and made
|
||||
available to the job and is used for writing output datasets to
|
||||
the object store as part of the job and dynamic output discovery
|
||||
(e.g. discovered datasets <discover_datasets>, unpopulated
|
||||
collections, etc) happens as part of the job.
|
||||
:Default: ``directory``
|
||||
:Type: str
|
||||
|
||||
|
||||
@@ -4,9 +4,6 @@ import shutil
|
||||
import string
|
||||
import sys
|
||||
import tempfile
|
||||
from collections import (
|
||||
OrderedDict
|
||||
)
|
||||
from io import StringIO
|
||||
from textwrap import TextWrapper
|
||||
from typing import Any, List, NamedTuple
|
||||
@@ -52,7 +49,7 @@ YAML_COMMENT_WRAPPER = TextWrapper(initial_indent="# ", subsequent_indent="# ",
|
||||
RST_DESCRIPTION_WRAPPER = TextWrapper(initial_indent=" ", subsequent_indent=" ", break_long_words=False, break_on_hyphens=False)
|
||||
UWSGI_SCHEMA_PATH = "lib/galaxy/webapps/uwsgi_schema.yml"
|
||||
|
||||
UWSGI_OPTIONS = OrderedDict([
|
||||
UWSGI_OPTIONS = dict([
|
||||
('http', {
|
||||
'desc': """The address and port on which to listen. By default, only listen to localhost ($app_name will not be accessible over the network). Use ':$default_port' to listen on all available network interfaces.""",
|
||||
'default': '127.0.0.1:$default_port',
|
||||
@@ -441,7 +438,7 @@ def _build_uwsgi_schema(args, app_desc):
|
||||
last_line = None
|
||||
current_opt = None
|
||||
|
||||
options = OrderedDict({})
|
||||
options = {}
|
||||
option = None
|
||||
for line in rst_options.splitlines():
|
||||
line = line.strip()
|
||||
@@ -506,9 +503,9 @@ def _find_app_options(app_desc, path):
|
||||
def _find_app_options_from_config_parser(p):
|
||||
if not p.has_section("app:main"):
|
||||
_warn(NO_APP_MAIN_MESSAGE)
|
||||
app_items = OrderedDict()
|
||||
app_items = {}
|
||||
else:
|
||||
app_items = OrderedDict(p.items("app:main"))
|
||||
app_items = dict(p.items("app:main"))
|
||||
|
||||
return app_items
|
||||
|
||||
@@ -604,9 +601,9 @@ def _run_conversion(args, app_desc):
|
||||
|
||||
if not server_section:
|
||||
_warn("No server section found, using default uwsgi server definition.")
|
||||
server_config = OrderedDict()
|
||||
server_config = {}
|
||||
else:
|
||||
server_config = OrderedDict(p.items(server_section))
|
||||
server_config = dict(p.items(server_section))
|
||||
|
||||
app_items = _find_app_options_from_config_parser(p)
|
||||
applied_filters = []
|
||||
@@ -621,7 +618,7 @@ def _run_conversion(args, app_desc):
|
||||
|
||||
uwsgi_dict = _server_paste_to_uwsgi(app_desc, server_config, applied_filters)
|
||||
|
||||
app_dict = OrderedDict({})
|
||||
app_dict = {}
|
||||
schema = app_desc.schema
|
||||
for key, value in app_items.items():
|
||||
if key in ["__file__", "here"]:
|
||||
@@ -778,7 +775,7 @@ def _parse_option_value(option_value):
|
||||
|
||||
|
||||
def _server_paste_to_uwsgi(app_desc, server_config, applied_filters):
|
||||
uwsgi_dict = OrderedDict()
|
||||
uwsgi_dict = {}
|
||||
port = server_config.get("port", app_desc.default_port)
|
||||
host = server_config.get("host", "127.0.0.1")
|
||||
|
||||
|
||||
@@ -1902,9 +1902,9 @@ galaxy:
|
||||
# database.
|
||||
#enable_job_recovery: true
|
||||
|
||||
# Determines how metadata will be set. Valid values are `directory`,
|
||||
# `extended` and `legacy`. In extended mode jobs will decide if a tool
|
||||
# run failed, the object stores configuration is serialized and made
|
||||
# Determines how metadata will be set. Valid values are `directory`
|
||||
# and `extended`. In extended mode jobs will decide if a tool run
|
||||
# failed, the object stores configuration is serialized and made
|
||||
# available to the job and is used for writing output datasets to the
|
||||
# object store as part of the job and dynamic output discovery (e.g.
|
||||
# discovered datasets <discover_datasets>, unpopulated collections,
|
||||
|
||||
@@ -12,7 +12,6 @@ import sys
|
||||
import tarfile
|
||||
import tempfile
|
||||
import zipfile
|
||||
from collections import OrderedDict
|
||||
from json import dumps
|
||||
from typing import Optional
|
||||
|
||||
@@ -320,7 +319,7 @@ class BamNative(CompressedArchive):
|
||||
# TODO: Reference names, lengths, read_groups and headers can become very large, truncate when necessary
|
||||
dataset.metadata.reference_names = list(bam_file.references)
|
||||
dataset.metadata.reference_lengths = list(bam_file.lengths)
|
||||
dataset.metadata.bam_header = OrderedDict((k, v) for k, v in bam_file.header.items())
|
||||
dataset.metadata.bam_header = dict(bam_file.header.items())
|
||||
dataset.metadata.read_groups = [read_group['ID'] for read_group in dataset.metadata.bam_header.get('RG', []) if 'ID' in read_group]
|
||||
dataset.metadata.sort_order = dataset.metadata.bam_header.get('HD', {}).get('SO', None)
|
||||
dataset.metadata.bam_version = dataset.metadata.bam_header.get('HD', {}).get('VN', None)
|
||||
|
||||
@@ -5,7 +5,6 @@ import os
|
||||
import shutil
|
||||
import string
|
||||
import tempfile
|
||||
from collections import OrderedDict
|
||||
from inspect import isclass
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
@@ -125,7 +124,7 @@ class Data(metaclass=DataMeta):
|
||||
is_binary = True
|
||||
# Composite datatypes
|
||||
composite_type: Optional[str] = None
|
||||
composite_files: Dict[str, Any] = OrderedDict()
|
||||
composite_files: Dict[str, Any] = {}
|
||||
primary_file_name = 'index'
|
||||
# Allow user to change between this datatype and others. If left to None,
|
||||
# datatype change is allowed if the datatype is not composite.
|
||||
@@ -144,7 +143,7 @@ class Data(metaclass=DataMeta):
|
||||
object.__init__(self, **kwd)
|
||||
self.supported_display_apps = self.supported_display_apps.copy()
|
||||
self.composite_files = self.composite_files.copy()
|
||||
self.display_applications = OrderedDict()
|
||||
self.display_applications = {}
|
||||
|
||||
@classmethod
|
||||
def is_datatype_change_allowed(cls):
|
||||
@@ -565,7 +564,7 @@ class Data(metaclass=DataMeta):
|
||||
return self.display_applications.get(key, default)
|
||||
|
||||
def get_display_applications_by_dataset(self, dataset, trans):
|
||||
rval = OrderedDict()
|
||||
rval = {}
|
||||
for key, value in self.display_applications.items():
|
||||
value = value.filter_by_dataset(dataset, trans)
|
||||
if value.links:
|
||||
@@ -685,7 +684,7 @@ class Data(metaclass=DataMeta):
|
||||
|
||||
@property
|
||||
def writable_files(self):
|
||||
files = OrderedDict()
|
||||
files = {}
|
||||
if self.composite_type != 'auto_primary_file':
|
||||
files[self.primary_file_name] = self.__new_composite_file(self.primary_file_name)
|
||||
for key, value in self.get_composite_files().items():
|
||||
@@ -701,7 +700,7 @@ class Data(metaclass=DataMeta):
|
||||
meta_value = self.metadata_spec[composite_file.substitute_name_with_metadata].default
|
||||
return key % meta_value
|
||||
return key
|
||||
files = OrderedDict()
|
||||
files = {}
|
||||
for key, value in self.composite_files.items():
|
||||
files[substitute_composite_key(key, value)] = value
|
||||
return files
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# Contains objects for using external display applications
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
from copy import deepcopy
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
@@ -46,7 +45,7 @@ class DisplayApplicationLink:
|
||||
|
||||
def __init__(self, display_application):
|
||||
self.display_application = display_application
|
||||
self.parameters = OrderedDict() # parameters are populated in order, allowing lower listed ones to have values of higher listed ones
|
||||
self.parameters = {}
|
||||
self.url_param_name_map = {}
|
||||
self.url = None
|
||||
self.id = None
|
||||
@@ -64,9 +63,9 @@ class DisplayApplicationLink:
|
||||
|
||||
def get_inital_values(self, data, trans):
|
||||
if self.other_values:
|
||||
rval = OrderedDict(self.other_values)
|
||||
rval = dict(self.other_values)
|
||||
else:
|
||||
rval = OrderedDict()
|
||||
rval = {}
|
||||
rval.update({'BASE_URL': trans.request.base, 'APP': trans.app}) # trans automatically appears as a response, need to add properties of trans that we want here
|
||||
BASE_PARAMS = {'qp': quote_plus_string, 'url_for': trans.app.url_for}
|
||||
for key, value in BASE_PARAMS.items(): # add helper functions/variables
|
||||
@@ -289,7 +288,7 @@ class DisplayApplication:
|
||||
if version is None:
|
||||
version = "1.0.0"
|
||||
self.version = version
|
||||
self.links = OrderedDict()
|
||||
self.links = {}
|
||||
self._filename = filename
|
||||
self._elem = elem
|
||||
self._data_table_versions = {}
|
||||
|
||||
@@ -5,7 +5,6 @@ Provides mapping between extensions and datatypes, mime-types, etc.
|
||||
import imp
|
||||
import logging
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
from string import Template
|
||||
|
||||
import yaml
|
||||
@@ -41,7 +40,7 @@ class Registry:
|
||||
self.config = config
|
||||
self.datatypes_by_extension = {}
|
||||
self.mimetypes_by_extension = {}
|
||||
self.datatype_converters = OrderedDict()
|
||||
self.datatype_converters = {}
|
||||
# Converters defined in local datatypes_conf.xml
|
||||
self.converters = []
|
||||
self.converter_tools = set()
|
||||
@@ -58,7 +57,7 @@ class Registry:
|
||||
# tool shed repositories that contain display applications.
|
||||
self.proprietary_display_app_containers = []
|
||||
# Map a display application id to a display application
|
||||
self.display_applications = OrderedDict()
|
||||
self.display_applications = {}
|
||||
# The following 2 attributes are used in the to_xml_file()
|
||||
# method to persist the current state into an xml file.
|
||||
self.display_path_attr = None
|
||||
@@ -638,7 +637,7 @@ class Registry:
|
||||
else:
|
||||
toolbox.register_tool(converter)
|
||||
if source_datatype not in self.datatype_converters:
|
||||
self.datatype_converters[source_datatype] = OrderedDict()
|
||||
self.datatype_converters[source_datatype] = {}
|
||||
self.datatype_converters[source_datatype][target_datatype] = converter
|
||||
if not hasattr(toolbox.app, 'tool_cache') or converter.id in toolbox.app.tool_cache._new_tool_ids:
|
||||
self.log.debug("Loaded converter: %s", converter.id)
|
||||
@@ -863,7 +862,7 @@ class Registry:
|
||||
def get_converters_by_datatype(self, ext):
|
||||
"""Returns available converters by source type"""
|
||||
if ext not in self._converters_by_datatype:
|
||||
converters = OrderedDict()
|
||||
converters = {}
|
||||
source_datatype = type(self.get_datatype_by_extension(ext))
|
||||
for ext2, converters_dict in self.datatype_converters.items():
|
||||
converter_datatype = type(self.get_datatype_by_extension(ext2))
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
Provides utilities for working with GFF files.
|
||||
"""
|
||||
import copy
|
||||
from collections import OrderedDict
|
||||
|
||||
from bx.intervals.io import GenomicInterval, GenomicIntervalReader, MissingFieldError, NiceReaderWrapper, ParseError
|
||||
from bx.tabular.io import Comment, Header
|
||||
@@ -428,7 +427,7 @@ def read_unordered_gtf(iterator, strict=False):
|
||||
return fields[0] + '_' + get_transcript_id(fields)
|
||||
|
||||
# Aggregate intervals by transcript_id and collect comments.
|
||||
feature_intervals = OrderedDict()
|
||||
feature_intervals = {}
|
||||
comments = []
|
||||
for line in iterator:
|
||||
if line.startswith('#'):
|
||||
|
||||
@@ -161,6 +161,7 @@ six==1.15.0; python_version >= "3.6" and python_full_version < "3.0.0" and pytho
|
||||
social-auth-core==3.3.0
|
||||
sortedcontainers==2.3.0
|
||||
sqlalchemy-migrate==0.13.0
|
||||
sqlalchemy-mutable==0.0.11
|
||||
sqlalchemy-utils==0.36.7
|
||||
sqlalchemy==1.3.22; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.4.0")
|
||||
sqlitedict==1.7.0
|
||||
|
||||
@@ -4,7 +4,6 @@ import logging
|
||||
import operator
|
||||
import os
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
import galaxy.model
|
||||
@@ -173,7 +172,7 @@ class BaseJobContext:
|
||||
pass
|
||||
|
||||
def find_files(self, output_name, collection, dataset_collectors):
|
||||
filenames = OrderedDict()
|
||||
filenames = {}
|
||||
for discovered_file in discover_files(output_name, self.tool_provided_metadata, dataset_collectors, self.job_working_directory, collection):
|
||||
filenames[discovered_file.path] = discovered_file
|
||||
return filenames
|
||||
@@ -373,7 +372,7 @@ def collect_primary_datasets(job_context, output, input_ext):
|
||||
output_def = job_context.output_def(name)
|
||||
if output_def is not None:
|
||||
dataset_collectors = [dataset_collector(description) for description in output_def.dataset_collector_descriptions]
|
||||
filenames = OrderedDict()
|
||||
filenames = {}
|
||||
for discovered_file in discover_files(name, job_context.tool_provided_metadata, dataset_collectors, job_working_directory, outdata):
|
||||
filenames[discovered_file.path] = discovered_file
|
||||
for filename_index, (filename, discovered_file) in enumerate(filenames.items()):
|
||||
@@ -400,7 +399,7 @@ def collect_primary_datasets(job_context, output, input_ext):
|
||||
primary_output_assigned = True
|
||||
continue
|
||||
if name not in primary_datasets:
|
||||
primary_datasets[name] = OrderedDict()
|
||||
primary_datasets[name] = {}
|
||||
visible = fields_match.visible
|
||||
# Create new primary dataset
|
||||
new_primary_name = fields_match.name or f"{outdata.name} ({designation})"
|
||||
|
||||
@@ -3,6 +3,9 @@ import os
|
||||
|
||||
from galaxy.util import safe_makedirs
|
||||
|
||||
TOOL_PROVIDED_JOB_METADATA_FILE = 'galaxy.json'
|
||||
TOOL_PROVIDED_JOB_METADATA_KEYS = ['name', 'info', 'dbkey', 'created_from_basename']
|
||||
|
||||
|
||||
def ensure_configs_directory(work_dir):
|
||||
configs_dir = os.path.join(work_dir, "configs")
|
||||
|
||||
@@ -40,9 +40,12 @@ from galaxy.job_execution.datasets import (
|
||||
TaskPathRewriter
|
||||
)
|
||||
from galaxy.job_execution.output_collect import collect_extra_files
|
||||
from galaxy.job_execution.setup import (
|
||||
from galaxy.job_execution.setup import ( # noqa: F401
|
||||
create_working_directory_for_job,
|
||||
ensure_configs_directory,
|
||||
# This is read by certain misbehaving tool wrappers that import Galaxy internals
|
||||
TOOL_PROVIDED_JOB_METADATA_FILE,
|
||||
TOOL_PROVIDED_JOB_METADATA_KEYS,
|
||||
)
|
||||
from galaxy.jobs.actions.post import ActionBox
|
||||
from galaxy.jobs.mapper import (
|
||||
@@ -72,12 +75,6 @@ from galaxy.web_stack.handlers import ConfiguresHandlers
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# Legacy definition - this is read by certain misbehaving tool wrappers
|
||||
# that import Galaxy internals - but it shouldn't be used in Galaxy's code
|
||||
# itself.
|
||||
TOOL_PROVIDED_JOB_METADATA_FILE = 'galaxy.json'
|
||||
TOOL_PROVIDED_JOB_METADATA_KEYS = ['name', 'info', 'dbkey', 'created_from_basename']
|
||||
|
||||
# Override with config.default_job_shell.
|
||||
DEFAULT_JOB_SHELL = '/bin/bash'
|
||||
DEFAULT_LOCAL_WORKERS = 4
|
||||
|
||||
@@ -593,6 +593,8 @@ class PulsarJobRunner(AsynchronousJobRunner):
|
||||
files_endpoint=files_endpoint,
|
||||
env=env
|
||||
)
|
||||
# Turn MutableDict into standard dict for pulsar consumption
|
||||
job_destination_params = dict(job_destination_params.items())
|
||||
return self.client_manager.get_client(job_destination_params, **get_client_kwds)
|
||||
|
||||
def finish_job(self, job_state):
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
|
||||
from sqlalchemy.orm import joinedload, Query
|
||||
|
||||
@@ -378,7 +377,7 @@ class DatasetCollectionManager:
|
||||
if elements is self.ELEMENTS_UNINITIALIZED:
|
||||
return
|
||||
|
||||
new_elements = OrderedDict()
|
||||
new_elements = {}
|
||||
for key, element in elements.items():
|
||||
if isinstance(element, model.DatasetCollection):
|
||||
continue
|
||||
@@ -387,7 +386,7 @@ class DatasetCollectionManager:
|
||||
continue
|
||||
|
||||
# element is a dict with src new_collection and
|
||||
# and OrderedDict of named elements
|
||||
# and dict of named elements
|
||||
collection_type = element.get("collection_type")
|
||||
sub_elements = element["elements"]
|
||||
collection = self.create_dataset_collection(
|
||||
@@ -402,7 +401,7 @@ class DatasetCollectionManager:
|
||||
elements.update(new_elements)
|
||||
|
||||
def __load_elements(self, trans, element_identifiers, hide_source_items=False, copy_elements=False, history=None):
|
||||
elements = OrderedDict()
|
||||
elements = {}
|
||||
for element_identifier in element_identifiers:
|
||||
elements[element_identifier["name"]] = self.__load_element(trans,
|
||||
element_identifier=element_identifier,
|
||||
@@ -500,7 +499,7 @@ class DatasetCollectionManager:
|
||||
def _build_elements_from_rule_data(self, collection_type_description, rule_set, data, sources, handle_dataset):
|
||||
identifier_columns = rule_set.identifier_columns
|
||||
mapping_as_dict = rule_set.mapping_as_dict
|
||||
elements = OrderedDict()
|
||||
elements = {}
|
||||
for data_index, row_data in enumerate(data):
|
||||
# For each row, find place in depth for this element.
|
||||
collection_type_at_depth = collection_type_description
|
||||
@@ -546,7 +545,7 @@ class DatasetCollectionManager:
|
||||
sub_collection = {}
|
||||
sub_collection["src"] = "new_collection"
|
||||
sub_collection["collection_type"] = collection_type_at_depth.collection_type
|
||||
sub_collection["elements"] = OrderedDict()
|
||||
sub_collection["elements"] = {}
|
||||
elements_at_depth[identifier] = sub_collection
|
||||
elements_at_depth = sub_collection["elements"]
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Utilities for loading tools and workflows from paths for admin user requests."""
|
||||
|
||||
from gxformat2.converter import ordered_load
|
||||
import yaml
|
||||
|
||||
from galaxy import exceptions
|
||||
|
||||
@@ -13,7 +13,7 @@ def artifact_class(trans, as_dict):
|
||||
|
||||
workflow_path = as_dict.get("path")
|
||||
with open(workflow_path) as f:
|
||||
as_dict = ordered_load(f)
|
||||
as_dict = yaml.safe_load(f)
|
||||
|
||||
artifact_class = as_dict.get("class", None)
|
||||
if artifact_class is None and "$graph" in as_dict:
|
||||
|
||||
@@ -18,7 +18,6 @@ import os
|
||||
import re
|
||||
import shutil
|
||||
import tempfile
|
||||
from collections import OrderedDict
|
||||
|
||||
import markdown
|
||||
import pkg_resources
|
||||
@@ -448,11 +447,11 @@ class ToBasicMarkdownDirectiveHandler(GalaxyInternalMarkdownDirectiveHandler):
|
||||
|
||||
def handle_job_metrics(self, line, job):
|
||||
job_metrics = summarize_job_metrics(self.trans, job)
|
||||
metrics_by_plugin = OrderedDict()
|
||||
metrics_by_plugin = {}
|
||||
for job_metric in job_metrics:
|
||||
plugin = job_metric["plugin"]
|
||||
if plugin not in metrics_by_plugin:
|
||||
metrics_by_plugin[plugin] = OrderedDict()
|
||||
metrics_by_plugin[plugin] = {}
|
||||
metrics_by_plugin[plugin][job_metric["title"]] = job_metric["value"]
|
||||
markdown = ""
|
||||
for metric_plugin, metrics_for_plugin in metrics_by_plugin.items():
|
||||
|
||||
+17
-223
@@ -3,17 +3,14 @@
|
||||
import abc
|
||||
import json
|
||||
import os
|
||||
import pickle
|
||||
import shutil
|
||||
import tempfile
|
||||
from logging import getLogger
|
||||
from os.path import abspath
|
||||
|
||||
import galaxy.model
|
||||
from galaxy.model import store
|
||||
from galaxy.model.metadata import FileParameter, MetadataTempFile
|
||||
from galaxy.model.store import DirectoryModelExportStore
|
||||
from galaxy.util import in_directory, safe_makedirs
|
||||
from galaxy.util import safe_makedirs
|
||||
|
||||
log = getLogger(__name__)
|
||||
|
||||
@@ -23,7 +20,7 @@ SET_METADATA_SCRIPT = 'from galaxy_ext.metadata.set_metadata import set_metadata
|
||||
def get_metadata_compute_strategy(config, job_id, metadata_strategy_override=None, tool_id=None):
|
||||
metadata_strategy = metadata_strategy_override or config.metadata_strategy
|
||||
if metadata_strategy == "legacy":
|
||||
return JobExternalOutputMetadataWrapper(job_id)
|
||||
raise Exception('legacy metadata_strategy has been removed')
|
||||
elif metadata_strategy == "extended" and tool_id != "__SET_METADATA__":
|
||||
return ExtendedDirectoryMetadataGenerator(job_id)
|
||||
else:
|
||||
@@ -130,23 +127,22 @@ class PortableDirectoryMetadataGenerator(MetadataCollectionStrategy):
|
||||
outputs = {}
|
||||
output_collections = {}
|
||||
|
||||
real_metadata_object = self.write_object_store_conf
|
||||
for name, dataset in datasets_dict.items():
|
||||
assert name is not None
|
||||
assert name not in outputs
|
||||
|
||||
key = name
|
||||
|
||||
def _metadata_path(what):
|
||||
return os.path.join(metadata_dir, f"metadata_{what}_{key}")
|
||||
|
||||
_initialize_metadata_inputs(dataset, _metadata_path, tmp_dir, kwds, real_metadata_object=real_metadata_object)
|
||||
_initialize_metadata_inputs(dataset, _metadata_path, tmp_dir, kwds, real_metadata_object=self.write_object_store_conf)
|
||||
|
||||
outputs[name] = {
|
||||
"filename_override": _get_filename_override(output_fnames, dataset.file_name),
|
||||
"validate": validate_outputs,
|
||||
"object_store_store_by": dataset.dataset.store_by,
|
||||
'id': dataset.id,
|
||||
'model_class': 'LibraryDatasetDatasetAssociation' if isinstance(dataset, galaxy.model.LibraryDatasetDatasetAssociation) else 'HistoryDatasetAssociation'
|
||||
}
|
||||
|
||||
metadata_params_path = os.path.join(metadata_dir, "params.json")
|
||||
@@ -159,19 +155,19 @@ class PortableDirectoryMetadataGenerator(MetadataCollectionStrategy):
|
||||
"outputs": outputs,
|
||||
}
|
||||
|
||||
# export model objects and object store configuration for extended metadata also.
|
||||
export_directory = os.path.join(metadata_dir, "outputs_new")
|
||||
with DirectoryModelExportStore(export_directory, for_edit=True, serialize_dataset_objects=True) as export_store:
|
||||
for dataset in datasets_dict.values():
|
||||
export_store.add_dataset(dataset)
|
||||
|
||||
for name, dataset_collection in out_collections.items():
|
||||
export_store.add_dataset_collection(dataset_collection)
|
||||
output_collections[name] = {
|
||||
'id': dataset_collection.id,
|
||||
}
|
||||
|
||||
if self.write_object_store_conf:
|
||||
# export model objects and object store configuration for extended metadata also.
|
||||
export_directory = os.path.join(metadata_dir, "outputs_new")
|
||||
with DirectoryModelExportStore(export_directory, for_edit=True, serialize_dataset_objects=True) as export_store:
|
||||
for dataset in datasets_dict.values():
|
||||
export_store.add_dataset(dataset)
|
||||
|
||||
for name, dataset_collection in out_collections.items():
|
||||
export_store.add_dataset_collection(dataset_collection)
|
||||
output_collections[name] = {
|
||||
'id': dataset_collection.id,
|
||||
}
|
||||
|
||||
with open(os.path.join(metadata_dir, "object_store_conf.json"), "w") as f:
|
||||
json.dump(object_store_conf, f)
|
||||
|
||||
@@ -241,195 +237,12 @@ class ExtendedDirectoryMetadataGenerator(PortableDirectoryMetadataGenerator):
|
||||
return dataset
|
||||
|
||||
|
||||
class JobExternalOutputMetadataWrapper(MetadataCollectionStrategy):
|
||||
"""
|
||||
Class with methods allowing set_meta() to be called externally to the
|
||||
Galaxy head.
|
||||
This class allows access to external metadata filenames for all outputs
|
||||
associated with a job.
|
||||
We will use JSON as the medium of exchange of information, except for the
|
||||
DatasetInstance object which will use pickle (in the future this could be
|
||||
JSONified as well)
|
||||
"""
|
||||
portable = False
|
||||
|
||||
def __init__(self, job_id):
|
||||
self.job_id = job_id
|
||||
|
||||
def _get_output_filenames_by_dataset(self, dataset, sa_session):
|
||||
if isinstance(dataset, galaxy.model.HistoryDatasetAssociation):
|
||||
return sa_session.query(galaxy.model.JobExternalOutputMetadata) \
|
||||
.filter_by(job_id=self.job_id,
|
||||
history_dataset_association_id=dataset.id,
|
||||
is_valid=True) \
|
||||
.first() # there should only be one or None
|
||||
elif isinstance(dataset, galaxy.model.LibraryDatasetDatasetAssociation):
|
||||
return sa_session.query(galaxy.model.JobExternalOutputMetadata) \
|
||||
.filter_by(job_id=self.job_id,
|
||||
library_dataset_dataset_association_id=dataset.id,
|
||||
is_valid=True) \
|
||||
.first() # there should only be one or None
|
||||
return None
|
||||
|
||||
def _get_dataset_metadata_key(self, dataset):
|
||||
# Set meta can be called on library items and history items,
|
||||
# need to make different keys for them, since ids can overlap
|
||||
return "%s_%d" % (dataset.__class__.__name__, dataset.id)
|
||||
|
||||
def invalidate_external_metadata(self, datasets, sa_session):
|
||||
for dataset in datasets:
|
||||
jeom = self._get_output_filenames_by_dataset(dataset, sa_session)
|
||||
# shouldn't be more than one valid, but you never know
|
||||
while jeom:
|
||||
jeom.is_valid = False
|
||||
sa_session.add(jeom)
|
||||
sa_session.flush()
|
||||
jeom = self._get_output_filenames_by_dataset(dataset, sa_session)
|
||||
|
||||
def setup_external_metadata(self, datasets_dict, out_collections, sa_session, exec_dir=None,
|
||||
tmp_dir=None, dataset_files_path=None,
|
||||
output_fnames=None, config_root=None, use_bin=False,
|
||||
config_file=None, datatypes_config=None,
|
||||
job_metadata=None, provided_metadata_style=None, compute_tmp_dir=None,
|
||||
include_command=True, max_metadata_value_size=0,
|
||||
validate_outputs=False,
|
||||
object_store_conf=None, tool=None, job=None,
|
||||
kwds=None):
|
||||
kwds = kwds or {}
|
||||
if not job:
|
||||
job = sa_session.query(galaxy.model.Job).get(self.job_id)
|
||||
tmp_dir = _init_tmp_dir(tmp_dir)
|
||||
_assert_datatypes_config(datatypes_config)
|
||||
|
||||
# path is calculated for Galaxy, may be different on compute - rewrite
|
||||
# for the compute server.
|
||||
def metadata_path_on_compute(path):
|
||||
compute_path = path
|
||||
if compute_tmp_dir and tmp_dir and in_directory(path, tmp_dir):
|
||||
path_relative = os.path.relpath(path, tmp_dir)
|
||||
compute_path = os.path.join(compute_tmp_dir, path_relative)
|
||||
return compute_path
|
||||
|
||||
# fill in metadata_files_dict and return the command with args required to set metadata
|
||||
def __metadata_files_list_to_cmd_line(metadata_files):
|
||||
line = '"{},{},{},{},{},{}"'.format(
|
||||
metadata_path_on_compute(metadata_files.filename_in),
|
||||
metadata_path_on_compute(metadata_files.filename_kwds),
|
||||
metadata_path_on_compute(metadata_files.filename_out),
|
||||
metadata_path_on_compute(metadata_files.filename_results_code),
|
||||
_get_filename_override(output_fnames, metadata_files.dataset.file_name),
|
||||
metadata_path_on_compute(metadata_files.filename_override_metadata),
|
||||
)
|
||||
return line
|
||||
|
||||
datasets = list(datasets_dict.values())
|
||||
if exec_dir is None:
|
||||
exec_dir = os.path.abspath(os.getcwd())
|
||||
if dataset_files_path is None:
|
||||
dataset_files_path = galaxy.model.Dataset.file_path
|
||||
if config_root is None:
|
||||
config_root = os.path.abspath(os.getcwd())
|
||||
metadata_files_list = []
|
||||
for dataset in datasets:
|
||||
key = self._get_dataset_metadata_key(dataset)
|
||||
# future note:
|
||||
# wonkiness in job execution causes build command line to be called more than once
|
||||
# when setting metadata externally, via 'auto-detect' button in edit attributes, etc.,
|
||||
# we don't want to overwrite (losing the ability to cleanup) our existing dataset keys and files,
|
||||
# so we will only populate the dictionary once
|
||||
metadata_files = self._get_output_filenames_by_dataset(dataset, sa_session)
|
||||
if not metadata_files:
|
||||
metadata_files = galaxy.model.JobExternalOutputMetadata(job=job, dataset=dataset)
|
||||
# we are using tempfile to create unique filenames, tempfile always returns an absolute path
|
||||
# we will use pathnames relative to the galaxy root, to accommodate instances where the galaxy root
|
||||
# is located differently, i.e. on a cluster node with a different filesystem structure
|
||||
|
||||
def _metadata_path(what):
|
||||
return abspath(tempfile.NamedTemporaryFile(dir=tmp_dir, prefix=f"metadata_{what}_{key}_").name)
|
||||
|
||||
filename_in, filename_out, filename_results_code, filename_kwds, filename_override_metadata = _initialize_metadata_inputs(dataset, _metadata_path, tmp_dir, kwds)
|
||||
|
||||
# file to store existing dataset
|
||||
metadata_files.filename_in = filename_in
|
||||
|
||||
# file to store metadata results of set_meta()
|
||||
metadata_files.filename_out = filename_out
|
||||
|
||||
# file to store a 'return code' indicating the results of the set_meta() call
|
||||
# results code is like (True/False - if setting metadata was successful/failed , exception or string of reason of success/failure )
|
||||
metadata_files.filename_results_code = filename_results_code
|
||||
|
||||
# file to store kwds passed to set_meta()
|
||||
metadata_files.filename_kwds = filename_kwds
|
||||
|
||||
# existing metadata file parameters need to be overridden with cluster-writable file locations
|
||||
metadata_files.filename_override_metadata = filename_override_metadata
|
||||
|
||||
# add to session and flush
|
||||
sa_session.add(metadata_files)
|
||||
sa_session.flush()
|
||||
metadata_files_list.append(metadata_files)
|
||||
args = '"{}" "{}" {} {}'.format(metadata_path_on_compute(datatypes_config),
|
||||
job_metadata,
|
||||
" ".join(map(__metadata_files_list_to_cmd_line, metadata_files_list)),
|
||||
max_metadata_value_size)
|
||||
assert not use_bin
|
||||
if include_command:
|
||||
# return command required to build
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', dir=tmp_dir, prefix="set_metadata_", delete=False) as temp:
|
||||
temp.write(SET_METADATA_SCRIPT)
|
||||
return 'python "{}" {}'.format(metadata_path_on_compute(temp.name), args)
|
||||
else:
|
||||
# return args to galaxy_ext.metadata.set_metadata required to build
|
||||
return args
|
||||
|
||||
def external_metadata_set_successfully(self, dataset, name, sa_session, working_directory):
|
||||
metadata_files = self._get_output_filenames_by_dataset(dataset, sa_session)
|
||||
if not metadata_files:
|
||||
return False # this file doesn't exist
|
||||
return self._metadata_results_from_file(dataset, metadata_files.filename_results_code)
|
||||
|
||||
def cleanup_external_metadata(self, sa_session):
|
||||
log.debug('Cleaning up external metadata files')
|
||||
for metadata_files in sa_session.query(galaxy.model.Job).get(self.job_id).external_output_metadata:
|
||||
# we need to confirm that any MetadataTempFile files were removed, if not we need to remove them
|
||||
# can occur if the job was stopped before completion, but a MetadataTempFile is used in the set_meta
|
||||
MetadataTempFile.cleanup_from_JSON_dict_filename(metadata_files.filename_out)
|
||||
dataset_key = self._get_dataset_metadata_key(metadata_files.dataset)
|
||||
for key, fname in [('filename_in', metadata_files.filename_in),
|
||||
('filename_out', metadata_files.filename_out),
|
||||
('filename_results_code', metadata_files.filename_results_code),
|
||||
('filename_kwds', metadata_files.filename_kwds),
|
||||
('filename_override_metadata', metadata_files.filename_override_metadata)]:
|
||||
try:
|
||||
os.remove(fname)
|
||||
except Exception as e:
|
||||
log.debug(f'Failed to cleanup external metadata file ({key}) for {dataset_key}: {e}')
|
||||
|
||||
def set_job_runner_external_pid(self, pid, sa_session):
|
||||
for metadata_files in sa_session.query(galaxy.model.Job).get(self.job_id).external_output_metadata:
|
||||
metadata_files.job_runner_external_pid = pid
|
||||
sa_session.add(metadata_files)
|
||||
sa_session.flush()
|
||||
|
||||
def load_metadata(self, dataset, name, sa_session, working_directory, remote_metadata_directory=None):
|
||||
# load metadata from file
|
||||
# we need to no longer allow metadata to be edited while the job is still running,
|
||||
# since if it is edited, the metadata changed on the running output will no longer match
|
||||
# the metadata that was stored to disk for use via the external process,
|
||||
# and the changes made by the user will be lost, without warning or notice
|
||||
output_filename = self._get_output_filenames_by_dataset(dataset, sa_session).filename_out
|
||||
self._load_metadata_from_path(dataset, output_filename, working_directory, remote_metadata_directory)
|
||||
|
||||
|
||||
def _initialize_metadata_inputs(dataset, path_for_part, tmp_dir, kwds, real_metadata_object=True):
|
||||
filename_in = path_for_part("in")
|
||||
filename_out = path_for_part("out")
|
||||
filename_results_code = path_for_part("results")
|
||||
filename_kwds = path_for_part("kwds")
|
||||
filename_override_metadata = path_for_part("override")
|
||||
|
||||
_dump_dataset_instance_to(dataset, filename_in)
|
||||
open(filename_out, 'wt+') # create the file on disk, so it cannot be reused by tempfile (unlikely, but possible)
|
||||
# create the file on disk, so it cannot be reused by tempfile (unlikely, but possible)
|
||||
json.dump((False, 'External set_meta() not called'), open(filename_results_code, 'wt+'))
|
||||
@@ -446,26 +259,7 @@ def _initialize_metadata_inputs(dataset, path_for_part, tmp_dir, kwds, real_meta
|
||||
|
||||
json.dump(override_metadata, open(filename_override_metadata, 'wt+'))
|
||||
|
||||
return filename_in, filename_out, filename_results_code, filename_kwds, filename_override_metadata
|
||||
|
||||
|
||||
def _assert_datatypes_config(datatypes_config):
|
||||
if datatypes_config is None:
|
||||
raise Exception('In setup_external_metadata, the received datatypes_config is None.')
|
||||
|
||||
|
||||
def _dump_dataset_instance_to(dataset_instance, file_path):
|
||||
# FIXME: HACK
|
||||
# sqlalchemy introduced 'expire_on_commit' flag for sessionmaker at version 0.5x
|
||||
# This may be causing the dataset attribute of the dataset_association object to no-longer be loaded into memory when needed for pickling.
|
||||
# For now, we'll simply 'touch' dataset_association.dataset to force it back into memory.
|
||||
dataset_instance.dataset # force dataset_association.dataset to be loaded before pickling
|
||||
# A better fix could be setting 'expire_on_commit=False' on the session, or modifying where commits occur, or ?
|
||||
|
||||
# Touch also deferred column
|
||||
dataset_instance._metadata
|
||||
|
||||
pickle.dump(dataset_instance, open(file_path, 'wb+'))
|
||||
return filename_out, filename_results_code, filename_kwds, filename_override_metadata
|
||||
|
||||
|
||||
def _get_filename_override(output_fnames, file_name):
|
||||
|
||||
@@ -3,7 +3,7 @@ Execute an external process to set_meta() on a provided list of pickled datasets
|
||||
|
||||
This was formerly scripts/set_metadata.py and expects these arguments:
|
||||
|
||||
%prog datatypes_conf.xml job_metadata_file metadata_in,metadata_kwds,metadata_out,metadata_results_code,output_filename_override,metadata_override... max_metadata_value_size
|
||||
%prog datatypes_conf.xml job_metadata_file metadata_kwds,metadata_out,metadata_results_code,output_filename_override,metadata_override... max_metadata_value_size
|
||||
|
||||
Galaxy should be importable on sys.path and output_filename_override should be
|
||||
set to the path of the dataset on which metadata is being set
|
||||
@@ -13,27 +13,55 @@ constructed automatically).
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import pickle
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from sqlalchemy.orm import clear_mappers
|
||||
try:
|
||||
from pulsar.client.staging import COMMAND_VERSION_FILENAME
|
||||
except ImportError:
|
||||
# Package unit tests
|
||||
COMMAND_VERSION_FILENAME = 'COMMAND_VERSION'
|
||||
|
||||
import galaxy.model.mapping # need to load this before we unpickle, in order to setup properties assigned by the mappers
|
||||
from galaxy.model import store
|
||||
from galaxy.model.custom_types import total_size
|
||||
from galaxy.tool_util.provided_metadata import parse_tool_provided_metadata
|
||||
from galaxy.util import (
|
||||
stringify_dictionary_keys,
|
||||
unicodify,
|
||||
import galaxy.datatypes.registry
|
||||
import galaxy.model.mapping
|
||||
from galaxy.datatypes import sniff
|
||||
from galaxy.datatypes.data import validate
|
||||
from galaxy.job_execution.output_collect import (
|
||||
collect_dynamic_outputs,
|
||||
collect_extra_files,
|
||||
collect_primary_datasets,
|
||||
default_exit_code_file,
|
||||
read_exit_code_from,
|
||||
SessionlessJobContext,
|
||||
)
|
||||
from galaxy.job_execution.setup import TOOL_PROVIDED_JOB_METADATA_KEYS
|
||||
from galaxy.model import (
|
||||
Dataset,
|
||||
HistoryDatasetAssociation,
|
||||
HistoryDatasetCollectionAssociation,
|
||||
Job,
|
||||
store,
|
||||
)
|
||||
from galaxy.model.custom_types import total_size
|
||||
from galaxy.model.metadata import MetadataTempFile
|
||||
from galaxy.objectstore import build_object_store_from_config
|
||||
from galaxy.tool_util.output_checker import (
|
||||
check_output,
|
||||
DETECTED_JOB_STATE,
|
||||
)
|
||||
from galaxy.tool_util.parser.stdio import (
|
||||
ToolStdioExitCode,
|
||||
ToolStdioRegex,
|
||||
)
|
||||
from galaxy.tool_util.provided_metadata import parse_tool_provided_metadata
|
||||
from galaxy.util import stringify_dictionary_keys
|
||||
from galaxy.util.expressions import ExpressionContext
|
||||
|
||||
logging.basicConfig()
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def set_validated_state(dataset_instance):
|
||||
from galaxy.datatypes.data import validate
|
||||
datatype_validation = validate(dataset_instance)
|
||||
|
||||
dataset_instance.validated_state = datatype_validation.state
|
||||
@@ -53,7 +81,6 @@ def set_meta_with_tool_provided(dataset_instance, file_dict, set_meta_kwds, data
|
||||
extension = dataset_instance.extension
|
||||
if extension == "_sniff_":
|
||||
try:
|
||||
from galaxy.datatypes import sniff
|
||||
extension = sniff.handle_uploaded_dataset_file(dataset_instance.dataset.external_filename, datatypes_registry)
|
||||
# We need to both set the extension so it is available to set_meta
|
||||
# and record it in the metadata so it can be reloaded on the server
|
||||
@@ -78,17 +105,13 @@ def set_meta_with_tool_provided(dataset_instance, file_dict, set_meta_kwds, data
|
||||
|
||||
|
||||
def set_metadata():
|
||||
if len(sys.argv) == 1:
|
||||
set_metadata_portable()
|
||||
else:
|
||||
set_metadata_legacy()
|
||||
set_metadata_portable()
|
||||
|
||||
|
||||
def set_metadata_portable():
|
||||
import galaxy.model
|
||||
tool_job_working_directory = os.path.abspath(os.getcwd())
|
||||
metadata_tmp_files_dir = os.path.join(tool_job_working_directory, "metadata")
|
||||
galaxy.model.metadata.MetadataTempFile.tmp_dir = metadata_tmp_files_dir
|
||||
MetadataTempFile.tmp_dir = metadata_tmp_files_dir
|
||||
|
||||
metadata_params_path = os.path.join("metadata", "params.json")
|
||||
try:
|
||||
@@ -117,7 +140,6 @@ def set_metadata_portable():
|
||||
|
||||
export_store = None
|
||||
if extended_metadata_collection:
|
||||
from galaxy.tool_util.parser.stdio import ToolStdioRegex, ToolStdioExitCode
|
||||
tool_dict = metadata_params["tool"]
|
||||
stdio_exit_code_dicts, stdio_regex_dicts = tool_dict["stdio_exit_codes"], tool_dict["stdio_regexes"]
|
||||
stdio_exit_codes = list(map(ToolStdioExitCode, stdio_exit_code_dicts))
|
||||
@@ -125,10 +147,9 @@ def set_metadata_portable():
|
||||
|
||||
with open(object_store_conf_path) as f:
|
||||
config_dict = json.load(f)
|
||||
from galaxy.objectstore import build_object_store_from_config
|
||||
assert config_dict is not None
|
||||
object_store = build_object_store_from_config(None, config_dict=config_dict)
|
||||
galaxy.model.Dataset.object_store = object_store
|
||||
Dataset.object_store = object_store
|
||||
|
||||
outputs_directory = os.path.join(tool_job_working_directory, "outputs")
|
||||
if not os.path.exists(outputs_directory):
|
||||
@@ -151,38 +172,35 @@ def set_metadata_portable():
|
||||
|
||||
job_id_tag = metadata_params["job_id_tag"]
|
||||
|
||||
# TODO: this clearly needs to be refactored, nothing in runners should be imported here..
|
||||
from galaxy.job_execution.output_collect import default_exit_code_file, read_exit_code_from
|
||||
exit_code_file = default_exit_code_file(".", job_id_tag)
|
||||
tool_exit_code = read_exit_code_from(exit_code_file, job_id_tag)
|
||||
|
||||
from galaxy.tool_util.output_checker import check_output, DETECTED_JOB_STATE
|
||||
check_output_detected_state, tool_stdout, tool_stderr, job_messages = check_output(stdio_regexes, stdio_exit_codes, tool_stdout, tool_stderr, tool_exit_code, job_id_tag)
|
||||
if check_output_detected_state == DETECTED_JOB_STATE.OK and not tool_provided_metadata.has_failed_outputs():
|
||||
final_job_state = galaxy.model.Job.states.OK
|
||||
final_job_state = Job.states.OK
|
||||
else:
|
||||
final_job_state = galaxy.model.Job.states.ERROR
|
||||
final_job_state = Job.states.ERROR
|
||||
|
||||
from pulsar.client.staging import COMMAND_VERSION_FILENAME
|
||||
version_string = ""
|
||||
if os.path.exists(COMMAND_VERSION_FILENAME):
|
||||
version_string = open(COMMAND_VERSION_FILENAME).read()
|
||||
|
||||
from galaxy.util.expressions import ExpressionContext
|
||||
job_context = ExpressionContext(dict(stdout=tool_stdout, stderr=tool_stderr))
|
||||
|
||||
# Load outputs.
|
||||
import_model_store = store.imported_store_for_metadata('metadata/outputs_new', object_store=object_store)
|
||||
export_store = store.DirectoryModelExportStore('metadata/outputs_populated', serialize_dataset_objects=True, for_edit=True, strip_metadata_files=False)
|
||||
import_model_store = store.imported_store_for_metadata('metadata/outputs_new', object_store=object_store)
|
||||
|
||||
for output_name, output_dict in outputs.items():
|
||||
if extended_metadata_collection:
|
||||
dataset_instance_id = output_dict["id"]
|
||||
dataset = import_model_store.sa_session.query(galaxy.model.HistoryDatasetAssociation).find(dataset_instance_id)
|
||||
assert dataset is not None
|
||||
else:
|
||||
dataset_instance_id = output_dict["id"]
|
||||
klass = getattr(galaxy.model, output_dict.get('model_class', 'HistoryDatasetAssociation'))
|
||||
dataset = import_model_store.sa_session.query(klass).find(dataset_instance_id)
|
||||
if dataset is None:
|
||||
# legacy check for jobs that started before 21.01, remove on 21.05
|
||||
filename_in = os.path.join("metadata/metadata_in_%s" % output_name)
|
||||
import pickle
|
||||
dataset = pickle.load(open(filename_in, 'rb')) # load DatasetInstance
|
||||
assert dataset is not None
|
||||
|
||||
filename_kwds = os.path.join("metadata/metadata_kwds_%s" % output_name)
|
||||
filename_out = os.path.join("metadata/metadata_out_%s" % output_name)
|
||||
@@ -206,8 +224,8 @@ def set_metadata_portable():
|
||||
# Metadata FileParameter types may not be writable on a cluster node, and are therefore temporarily substituted with MetadataTempFiles
|
||||
override_metadata = json.load(open(override_metadata))
|
||||
for metadata_name, metadata_file_override in override_metadata:
|
||||
if galaxy.datatypes.metadata.MetadataTempFile.is_JSONified_value(metadata_file_override):
|
||||
metadata_file_override = galaxy.datatypes.metadata.MetadataTempFile.from_JSON(metadata_file_override)
|
||||
if MetadataTempFile.is_JSONified_value(metadata_file_override):
|
||||
metadata_file_override = MetadataTempFile.from_JSON(metadata_file_override)
|
||||
setattr(dataset.metadata, metadata_name, metadata_file_override)
|
||||
if output_dict.get("validate", False):
|
||||
set_validated_state(dataset)
|
||||
@@ -240,9 +258,8 @@ def set_metadata_portable():
|
||||
# This has to be a job with outputs_to_working_directory set.
|
||||
# We update the object store with the created output file.
|
||||
object_store.update_from_file(dataset.dataset, file_name=dataset_filename_override, create=True)
|
||||
from galaxy.job_execution.output_collect import collect_extra_files
|
||||
collect_extra_files(object_store, dataset, ".")
|
||||
if galaxy.model.Job.states.ERROR == final_job_state:
|
||||
if Job.states.ERROR == final_job_state:
|
||||
dataset.blurb = "error"
|
||||
dataset.mark_unhidden()
|
||||
else:
|
||||
@@ -262,7 +279,6 @@ def set_metadata_portable():
|
||||
# ... and others don't
|
||||
dataset.set_peek()
|
||||
|
||||
from galaxy.jobs import TOOL_PROVIDED_JOB_METADATA_KEYS
|
||||
for context_key in TOOL_PROVIDED_JOB_METADATA_KEYS:
|
||||
if context_key in context:
|
||||
context_value = context[context_key]
|
||||
@@ -279,7 +295,6 @@ def set_metadata_portable():
|
||||
|
||||
if extended_metadata_collection:
|
||||
# discover extra outputs...
|
||||
from galaxy.job_execution.output_collect import collect_dynamic_outputs, collect_primary_datasets, SessionlessJobContext
|
||||
|
||||
job_context = SessionlessJobContext(
|
||||
metadata_params,
|
||||
@@ -293,10 +308,11 @@ def set_metadata_portable():
|
||||
|
||||
output_collections = {}
|
||||
for name, output_collection in metadata_params["output_collections"].items():
|
||||
output_collections[name] = import_model_store.sa_session.query(galaxy.model.HistoryDatasetCollectionAssociation).find(output_collection["id"])
|
||||
output_collections[name] = import_model_store.sa_session.query(HistoryDatasetCollectionAssociation).find(output_collection["id"])
|
||||
outputs = {}
|
||||
for name, output in metadata_params["outputs"].items():
|
||||
outputs[name] = import_model_store.sa_session.query(galaxy.model.HistoryDatasetAssociation).find(output["id"])
|
||||
klass = getattr(galaxy.model, output.get('model_class', 'HistoryDatasetAssociation'))
|
||||
outputs[name] = import_model_store.sa_session.query(klass).find(output["id"])
|
||||
|
||||
input_ext = json.loads(metadata_params["job_params"].get("__input_ext", '"data"'))
|
||||
collect_primary_datasets(
|
||||
@@ -311,64 +327,6 @@ def set_metadata_portable():
|
||||
write_job_metadata(tool_job_working_directory, job_metadata, set_meta, tool_provided_metadata)
|
||||
|
||||
|
||||
def set_metadata_legacy():
|
||||
import galaxy.model
|
||||
galaxy.model.metadata.MetadataTempFile.tmp_dir = tool_job_working_directory = os.path.abspath(os.getcwd())
|
||||
|
||||
# This is ugly, but to transition from existing jobs without this parameter
|
||||
# to ones with, smoothly, it has to be the last optional parameter and we
|
||||
# have to sniff it.
|
||||
try:
|
||||
max_metadata_value_size = int(sys.argv[-1])
|
||||
sys.argv = sys.argv[:-1]
|
||||
except ValueError:
|
||||
max_metadata_value_size = 0
|
||||
# max_metadata_value_size is unspecified and should be 0
|
||||
|
||||
# Set up datatypes registry
|
||||
datatypes_config = sys.argv.pop(1)
|
||||
datatypes_registry = validate_and_load_datatypes_config(datatypes_config)
|
||||
|
||||
job_metadata = sys.argv.pop(1)
|
||||
tool_provided_metadata = load_job_metadata(job_metadata, None)
|
||||
|
||||
def set_meta(new_dataset_instance, file_dict):
|
||||
set_meta_with_tool_provided(new_dataset_instance, file_dict, set_meta_kwds, datatypes_registry, max_metadata_value_size)
|
||||
|
||||
for filenames in sys.argv[1:]:
|
||||
fields = filenames.split(',')
|
||||
filename_in = fields.pop(0)
|
||||
filename_kwds = fields.pop(0)
|
||||
filename_out = fields.pop(0)
|
||||
filename_results_code = fields.pop(0)
|
||||
dataset_filename_override = fields.pop(0)
|
||||
override_metadata = fields.pop(0)
|
||||
set_meta_kwds = stringify_dictionary_keys(json.load(open(filename_kwds))) # load kwds; need to ensure our keywords are not unicode
|
||||
try:
|
||||
dataset = pickle.load(open(filename_in, 'rb')) # load DatasetInstance
|
||||
dataset.dataset.external_filename = dataset_filename_override
|
||||
store_by = "id"
|
||||
extra_files_dir_name = "dataset_%s_files" % getattr(dataset.dataset, store_by)
|
||||
files_path = os.path.abspath(os.path.join(tool_job_working_directory, "working", extra_files_dir_name))
|
||||
dataset.dataset.external_extra_files_path = files_path
|
||||
file_dict = tool_provided_metadata.get_dataset_meta(None, dataset.dataset.id, dataset.dataset.uuid)
|
||||
if 'ext' in file_dict:
|
||||
dataset.extension = file_dict['ext']
|
||||
# Metadata FileParameter types may not be writable on a cluster node, and are therefore temporarily substituted with MetadataTempFiles
|
||||
override_metadata = json.load(open(override_metadata))
|
||||
for metadata_name, metadata_file_override in override_metadata:
|
||||
if galaxy.datatypes.metadata.MetadataTempFile.is_JSONified_value(metadata_file_override):
|
||||
metadata_file_override = galaxy.datatypes.metadata.MetadataTempFile.from_JSON(metadata_file_override)
|
||||
setattr(dataset.metadata, metadata_name, metadata_file_override)
|
||||
set_meta(dataset, file_dict)
|
||||
dataset.metadata.to_JSON_dict(filename_out) # write out results of set_meta
|
||||
json.dump((True, 'Metadata has been set successfully'), open(filename_results_code, 'wt+')) # setting metadata has succeeded
|
||||
except Exception as e:
|
||||
json.dump((False, unicodify(e)), open(filename_results_code, 'wt+')) # setting metadata has failed somehow
|
||||
|
||||
write_job_metadata(tool_job_working_directory, job_metadata, set_meta, tool_provided_metadata)
|
||||
|
||||
|
||||
def validate_and_load_datatypes_config(datatypes_config):
|
||||
galaxy_root = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir))
|
||||
|
||||
@@ -379,7 +337,6 @@ def validate_and_load_datatypes_config(datatypes_config):
|
||||
if not os.path.exists(datatypes_config):
|
||||
print("Metadata setting failed because registry.xml [%s] could not be found. You may retry setting metadata." % datatypes_config)
|
||||
sys.exit(1)
|
||||
import galaxy.datatypes.registry
|
||||
datatypes_registry = galaxy.datatypes.registry.Registry()
|
||||
datatypes_registry.load_datatypes(root_dir=galaxy_root, config=datatypes_config, use_build_sites=False, use_converters=False, use_display_applications=False)
|
||||
galaxy.model.set_datatypes_registry(datatypes_registry)
|
||||
@@ -394,14 +351,13 @@ def write_job_metadata(tool_job_working_directory, job_metadata, set_meta, tool_
|
||||
for i, file_dict in enumerate(tool_provided_metadata.get_new_datasets_for_metadata_collection(), start=1):
|
||||
filename = file_dict["filename"]
|
||||
new_dataset_filename = os.path.join(tool_job_working_directory, "working", filename)
|
||||
new_dataset = galaxy.model.Dataset(id=-i, external_filename=new_dataset_filename)
|
||||
new_dataset = Dataset(id=-i, external_filename=new_dataset_filename)
|
||||
extra_files = file_dict.get('extra_files', None)
|
||||
if extra_files is not None:
|
||||
new_dataset._extra_files_path = os.path.join(tool_job_working_directory, "working", extra_files)
|
||||
new_dataset.state = new_dataset.states.OK
|
||||
new_dataset_instance = galaxy.model.HistoryDatasetAssociation(id=-i, dataset=new_dataset, extension=file_dict.get('ext', 'data'))
|
||||
new_dataset_instance = HistoryDatasetAssociation(id=-i, dataset=new_dataset, extension=file_dict.get('ext', 'data'))
|
||||
set_meta(new_dataset_instance, file_dict)
|
||||
file_dict['metadata'] = json.loads(new_dataset_instance.metadata.to_JSON_dict()) # storing metadata in external form, need to turn back into dict, then later jsonify
|
||||
|
||||
tool_provided_metadata.rewrite()
|
||||
clear_mappers()
|
||||
|
||||
@@ -4139,7 +4139,7 @@ class DatasetCollection(Dictifiable, UsesAnnotations, RepresentById):
|
||||
select_stmt = select(list(map(lambda dc: dc.c.populated_state, collection_depth_aliases))).select_from(select_from).where(dc.c.id == self.id).distinct()
|
||||
for populated_states in db_session.execute(select_stmt).fetchall():
|
||||
for populated_state in populated_states:
|
||||
if populated_state != DatasetCollection.populated_states.OK:
|
||||
if populated_state and populated_state != DatasetCollection.populated_states.OK:
|
||||
_populated_optimized = False
|
||||
|
||||
self._populated_optimized = _populated_optimized
|
||||
|
||||
@@ -9,13 +9,15 @@ from sys import getsizeof
|
||||
|
||||
import numpy
|
||||
import sqlalchemy
|
||||
from sqlalchemy.ext.mutable import Mutable
|
||||
from sqlalchemy.types import (
|
||||
CHAR,
|
||||
LargeBinary,
|
||||
String,
|
||||
TypeDecorator
|
||||
)
|
||||
from sqlalchemy_mutable.mutable import Mutable
|
||||
# For compatibility with custom yaml dumping in gxformat2
|
||||
from sqlalchemy_mutable.mutable_dict import MutableDict as MutationDict # noqa: F401
|
||||
|
||||
from galaxy.util import (
|
||||
smart_str,
|
||||
@@ -77,7 +79,7 @@ class GalaxyLargeBinary(LargeBinary):
|
||||
return process
|
||||
|
||||
|
||||
class JSONType(sqlalchemy.types.TypeDecorator):
|
||||
class BaseJSONType(sqlalchemy.types.TypeDecorator):
|
||||
"""
|
||||
Represents an immutable structure as a json-encoded string.
|
||||
|
||||
@@ -113,149 +115,17 @@ class JSONType(sqlalchemy.types.TypeDecorator):
|
||||
return (x == y)
|
||||
|
||||
|
||||
class MutationObj(Mutable):
|
||||
"""
|
||||
Mutable JSONType for SQLAlchemy from original gist:
|
||||
https://gist.github.com/dbarnett/1730610
|
||||
|
||||
Using minor changes from this fork of the gist:
|
||||
https://gist.github.com/miracle2k/52a031cced285ba9b8cd
|
||||
|
||||
And other minor changes to make it work for us.
|
||||
"""
|
||||
@classmethod
|
||||
def coerce(cls, key, value):
|
||||
if isinstance(value, dict) and not isinstance(value, MutationDict):
|
||||
return MutationDict.coerce(key, value)
|
||||
if isinstance(value, list) and not isinstance(value, MutationList):
|
||||
return MutationList.coerce(key, value)
|
||||
return value
|
||||
|
||||
@classmethod
|
||||
def _listen_on_attribute(cls, attribute, coerce, parent_cls):
|
||||
key = attribute.key
|
||||
if parent_cls is not attribute.class_:
|
||||
return
|
||||
|
||||
# rely on "propagate" here
|
||||
parent_cls = attribute.class_
|
||||
|
||||
def load(state, *args):
|
||||
val = state.dict.get(key, None)
|
||||
if coerce and key not in state.unloaded:
|
||||
val = cls.coerce(key, val)
|
||||
state.dict[key] = val
|
||||
if isinstance(val, cls):
|
||||
val._parents[state.obj()] = key
|
||||
|
||||
def set(target, value, oldvalue, initiator):
|
||||
if not isinstance(value, cls):
|
||||
value = cls.coerce(key, value)
|
||||
if isinstance(value, cls):
|
||||
value._parents[target.obj()] = key
|
||||
if isinstance(oldvalue, cls):
|
||||
oldvalue._parents.pop(target.obj(), None)
|
||||
return value
|
||||
|
||||
def pickle(state, state_dict):
|
||||
val = state.dict.get(key, None)
|
||||
if isinstance(val, cls):
|
||||
if 'ext.mutable.values' not in state_dict:
|
||||
state_dict['ext.mutable.values'] = []
|
||||
state_dict['ext.mutable.values'].append(val)
|
||||
|
||||
def unpickle(state, state_dict):
|
||||
if 'ext.mutable.values' in state_dict:
|
||||
for val in state_dict['ext.mutable.values']:
|
||||
val._parents[state.obj()] = key
|
||||
|
||||
sqlalchemy.event.listen(parent_cls, 'load', load, raw=True, propagate=True)
|
||||
sqlalchemy.event.listen(parent_cls, 'refresh', load, raw=True, propagate=True)
|
||||
sqlalchemy.event.listen(attribute, 'set', set, raw=True, retval=True, propagate=True)
|
||||
sqlalchemy.event.listen(parent_cls, 'pickle', pickle, raw=True, propagate=True)
|
||||
sqlalchemy.event.listen(parent_cls, 'unpickle', unpickle, raw=True, propagate=True)
|
||||
class SimpleJSONType(BaseJSONType):
|
||||
"""SQLAlchemy column type that does not track mutations to mutable data."""
|
||||
pass
|
||||
|
||||
|
||||
class MutationDict(MutationObj, dict):
|
||||
@classmethod
|
||||
def coerce(cls, key, value):
|
||||
"""Convert plain dictionary to MutationDict"""
|
||||
self = MutationDict((k, MutationObj.coerce(key, v)) for (k, v) in value.items())
|
||||
self._key = key
|
||||
return self
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if hasattr(self, '_key'):
|
||||
value = MutationObj.coerce(self._key, value)
|
||||
dict.__setitem__(self, key, value)
|
||||
self.changed()
|
||||
|
||||
def __delitem__(self, key):
|
||||
dict.__delitem__(self, key)
|
||||
self.changed()
|
||||
|
||||
def __getstate__(self):
|
||||
return dict(self)
|
||||
|
||||
def __setstate__(self, state):
|
||||
self.update(state)
|
||||
class JSONType(BaseJSONType):
|
||||
"""SQLAlchemy column type that tracks mutations to mutable data."""
|
||||
pass
|
||||
|
||||
|
||||
class MutationList(MutationObj, list):
|
||||
@classmethod
|
||||
def coerce(cls, key, value):
|
||||
"""Convert plain list to MutationList"""
|
||||
self = MutationList(MutationObj.coerce(key, v) for v in value)
|
||||
self._key = key
|
||||
return self
|
||||
|
||||
def __setitem__(self, idx, value):
|
||||
list.__setitem__(self, idx, MutationObj.coerce(self._key, value))
|
||||
self.changed()
|
||||
|
||||
def __setslice__(self, start, stop, values):
|
||||
list.__setslice__(self, start, stop, (MutationObj.coerce(self._key, v) for v in values))
|
||||
self.changed()
|
||||
|
||||
def __delitem__(self, idx):
|
||||
list.__delitem__(self, idx)
|
||||
self.changed()
|
||||
|
||||
def __delslice__(self, start, stop):
|
||||
list.__delslice__(self, start, stop)
|
||||
self.changed()
|
||||
|
||||
def __copy__(self):
|
||||
return MutationList(MutationObj.coerce(self._key, self[:]))
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
return MutationList(MutationObj.coerce(self._key, copy.deepcopy(self[:])))
|
||||
|
||||
def append(self, value):
|
||||
list.append(self, MutationObj.coerce(self._key, value))
|
||||
self.changed()
|
||||
|
||||
def insert(self, idx, value):
|
||||
list.insert(self, idx, MutationObj.coerce(self._key, value))
|
||||
self.changed()
|
||||
|
||||
def extend(self, values):
|
||||
if hasattr(self, '_key'):
|
||||
values = (MutationObj.coerce(self._key, value) for value in values)
|
||||
list.extend(self, values)
|
||||
self.changed()
|
||||
|
||||
def pop(self, *args, **kw):
|
||||
value = list.pop(self, *args, **kw)
|
||||
self.changed()
|
||||
return value
|
||||
|
||||
def remove(self, value):
|
||||
list.remove(self, value)
|
||||
self.changed()
|
||||
|
||||
|
||||
MutationObj.associate_with(JSONType)
|
||||
Mutable.associate_with(JSONType)
|
||||
|
||||
metadata_pickler = AliasPickleModule({
|
||||
("cookbook.patterns", "Bunch"): ("galaxy.util.bunch", "Bunch")
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from collections import OrderedDict
|
||||
|
||||
from galaxy import model
|
||||
from .type_description import COLLECTION_TYPE_DESCRIPTION_FACTORY
|
||||
|
||||
@@ -34,7 +32,7 @@ class CollectionBuilder:
|
||||
|
||||
def __init__(self, collection_type_description):
|
||||
self._collection_type_description = collection_type_description
|
||||
self._current_elements = OrderedDict()
|
||||
self._current_elements = {}
|
||||
|
||||
def replace_elements_in_collection(self, template_collection, replacement_dict):
|
||||
self._current_elements = self._replace_elements_in_collection(
|
||||
@@ -43,7 +41,7 @@ class CollectionBuilder:
|
||||
)
|
||||
|
||||
def _replace_elements_in_collection(self, template_collection, replacement_dict):
|
||||
elements = OrderedDict()
|
||||
elements = {}
|
||||
for element in template_collection.elements:
|
||||
if element.is_collection:
|
||||
collection_builder = CollectionBuilder(
|
||||
@@ -77,7 +75,7 @@ class CollectionBuilder:
|
||||
def build_elements(self):
|
||||
elements = self._current_elements
|
||||
if self._nested_collection:
|
||||
new_elements = OrderedDict()
|
||||
new_elements = {}
|
||||
for identifier, element in elements.items():
|
||||
new_elements[identifier] = element.build()
|
||||
elements = new_elements
|
||||
|
||||
@@ -40,7 +40,13 @@ from sqlalchemy.types import BigInteger
|
||||
|
||||
from galaxy import model
|
||||
from galaxy.model.base import ModelMapping
|
||||
from galaxy.model.custom_types import JSONType, MetadataType, TrimmedString, UUIDType
|
||||
from galaxy.model.custom_types import (
|
||||
JSONType,
|
||||
MetadataType,
|
||||
SimpleJSONType,
|
||||
TrimmedString,
|
||||
UUIDType,
|
||||
)
|
||||
from galaxy.model.orm.engine_factory import build_engine
|
||||
from galaxy.model.orm.now import now
|
||||
from galaxy.model.security import GalaxyRBACAgent
|
||||
@@ -860,7 +866,7 @@ model.PostJobAction.table = Table(
|
||||
Column("workflow_step_id", Integer, ForeignKey("workflow_step.id"), index=True, nullable=True),
|
||||
Column("action_type", String(255), nullable=False),
|
||||
Column("output_name", String(255), nullable=True),
|
||||
Column("action_arguments", JSONType, nullable=True))
|
||||
Column("action_arguments", SimpleJSONType, nullable=True))
|
||||
|
||||
model.PostJobActionAssociation.table = Table(
|
||||
"post_job_action_association", metadata,
|
||||
@@ -1037,7 +1043,7 @@ model.WorkflowStepInput.table = Table(
|
||||
Column("scatter_type", TEXT),
|
||||
Column("value_from", JSONType),
|
||||
Column("value_from_type", TEXT),
|
||||
Column("default_value", JSONType),
|
||||
Column("default_value", SimpleJSONType),
|
||||
Column("default_value_set", Boolean, default=False),
|
||||
Column("runtime_value", Boolean, default=False),
|
||||
Index('ix_workflow_step_input_workflow_step_id_name_unique', "workflow_step_id", "name", unique=True, mysql_length={'name': 200}),
|
||||
@@ -1066,7 +1072,7 @@ model.WorkflowRequestInputStepParameter.table = Table(
|
||||
Column("id", Integer, primary_key=True),
|
||||
Column("workflow_invocation_id", Integer, ForeignKey("workflow_invocation.id"), index=True),
|
||||
Column("workflow_step_id", Integer, ForeignKey("workflow_step.id")),
|
||||
Column("parameter_value", JSONType),
|
||||
Column("parameter_value", SimpleJSONType),
|
||||
)
|
||||
|
||||
model.WorkflowRequestToInputDatasetAssociation.table = Table(
|
||||
@@ -1125,7 +1131,7 @@ model.WorkflowInvocationStep.table = Table(
|
||||
Column("state", TrimmedString(64), index=True),
|
||||
Column("job_id", Integer, ForeignKey("job.id"), index=True, nullable=True),
|
||||
Column("implicit_collection_jobs_id", Integer, ForeignKey("implicit_collection_jobs.id"), index=True, nullable=True),
|
||||
Column("action", JSONType, nullable=True))
|
||||
Column("action", SimpleJSONType, nullable=True))
|
||||
|
||||
model.WorkflowInvocationOutputDatasetAssociation.table = Table(
|
||||
"workflow_invocation_output_dataset_association", metadata,
|
||||
|
||||
@@ -370,7 +370,11 @@ class ModelImportStore(metaclass=abc.ABCMeta):
|
||||
assert 'id' in dataset_attrs
|
||||
object_import_tracker.hdas_by_id[dataset_attrs['id']] = dataset_instance
|
||||
else:
|
||||
object_import_tracker.lddas_by_key[dataset_attrs[object_key]] = dataset_instance
|
||||
if object_key in dataset_attrs:
|
||||
object_import_tracker.lddas_by_key[dataset_attrs[object_key]] = dataset_instance
|
||||
else:
|
||||
assert 'id' in dataset_attrs
|
||||
object_import_tracker.lddas_by_key[dataset_attrs['id']] = dataset_instance
|
||||
|
||||
def _import_libraries(self, object_import_tracker):
|
||||
object_key = self.object_key
|
||||
@@ -486,29 +490,32 @@ class ModelImportStore(metaclass=abc.ABCMeta):
|
||||
return dc
|
||||
|
||||
for collection_attrs in collections_attrs:
|
||||
dc = import_collection(collection_attrs["collection"])
|
||||
if 'id' in collection_attrs and self.import_options.allow_edit and not self.sessionless:
|
||||
hdca = self.sa_session.query(model.HistoryDatasetCollectionAssociation).get(collection_attrs["id"])
|
||||
# TODO: edit attributes...
|
||||
else:
|
||||
hdca = model.HistoryDatasetCollectionAssociation(collection=dc,
|
||||
visible=True,
|
||||
name=collection_attrs['display_name'],
|
||||
implicit_output_name=collection_attrs.get("implicit_output_name"))
|
||||
self._attach_raw_id_if_editing(hdca, collection_attrs)
|
||||
|
||||
hdca.history = history
|
||||
if new_history and self.trust_hid(collection_attrs):
|
||||
hdca.hid = collection_attrs['hid']
|
||||
if 'collection' in collection_attrs:
|
||||
dc = import_collection(collection_attrs["collection"])
|
||||
if 'id' in collection_attrs and self.import_options.allow_edit and not self.sessionless:
|
||||
hdca = self.sa_session.query(model.HistoryDatasetCollectionAssociation).get(collection_attrs["id"])
|
||||
# TODO: edit attributes...
|
||||
else:
|
||||
object_import_tracker.requires_hid.append(hdca)
|
||||
hdca = model.HistoryDatasetCollectionAssociation(collection=dc,
|
||||
visible=True,
|
||||
name=collection_attrs['display_name'],
|
||||
implicit_output_name=collection_attrs.get("implicit_output_name"))
|
||||
self._attach_raw_id_if_editing(hdca, collection_attrs)
|
||||
|
||||
self._session_add(hdca)
|
||||
if object_key in collection_attrs:
|
||||
object_import_tracker.hdcas_by_key[collection_attrs[object_key]] = hdca
|
||||
hdca.history = history
|
||||
if new_history and self.trust_hid(collection_attrs):
|
||||
hdca.hid = collection_attrs['hid']
|
||||
else:
|
||||
object_import_tracker.requires_hid.append(hdca)
|
||||
|
||||
self._session_add(hdca)
|
||||
if object_key in collection_attrs:
|
||||
object_import_tracker.hdcas_by_key[collection_attrs[object_key]] = hdca
|
||||
else:
|
||||
assert 'id' in collection_attrs
|
||||
object_import_tracker.hdcas_by_id[collection_attrs['id']] = hdca
|
||||
else:
|
||||
assert 'id' in collection_attrs
|
||||
object_import_tracker.hdcas_by_id[collection_attrs['id']] = hdca
|
||||
import_collection(collection_attrs)
|
||||
|
||||
def _attach_raw_id_if_editing(self, obj, attrs):
|
||||
if self.sessionless and 'id' in attrs and self.import_options.allow_edit:
|
||||
@@ -1251,7 +1258,8 @@ class DirectoryModelExportStore(ModelExportStore):
|
||||
def record_associated_jobs(obj):
|
||||
# Get the job object.
|
||||
job = None
|
||||
for assoc in obj.creating_job_associations:
|
||||
for assoc in getattr(obj, 'creating_job_associations', []):
|
||||
# For mapped over jobs obj could be DatasetCollection, which has no creating_job_association
|
||||
job = assoc.job
|
||||
break
|
||||
if not job:
|
||||
|
||||
@@ -10,7 +10,6 @@ import logging
|
||||
import os
|
||||
from collections import (
|
||||
namedtuple,
|
||||
OrderedDict
|
||||
)
|
||||
from typing import Any, NamedTuple, Optional
|
||||
|
||||
@@ -517,7 +516,7 @@ def persist_target_to_export_store(target_dict, export_store, object_store, work
|
||||
|
||||
|
||||
def persist_elements_to_hdca(model_persistence_context, elements, hdca, collector=None):
|
||||
filenames = OrderedDict()
|
||||
filenames = {}
|
||||
|
||||
def add_to_discovered_files(elements, parent_identifiers=None):
|
||||
parent_identifiers = parent_identifiers or []
|
||||
|
||||
@@ -12,7 +12,6 @@ import random
|
||||
import shutil
|
||||
import threading
|
||||
import time
|
||||
from collections import OrderedDict
|
||||
|
||||
import yaml
|
||||
|
||||
@@ -183,6 +182,9 @@ class ObjectStore(metaclass=abc.ABCMeta):
|
||||
|
||||
To accommodate nested objectstores, obj is passed in so this metadata can
|
||||
be returned for the ConcreteObjectStore corresponding to the object.
|
||||
|
||||
If the dataset is in a new or discarded state and an object_store_id has not
|
||||
yet been set, this may return ``None``.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
@@ -191,6 +193,9 @@ class ObjectStore(metaclass=abc.ABCMeta):
|
||||
|
||||
To accommodate nested objectstores, obj is passed in so this metadata can
|
||||
be returned for the ConcreteObjectStore corresponding to the object.
|
||||
|
||||
If the dataset is in a new or discarded state and an object_store_id has not
|
||||
yet been set, this may return ``None``.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
@@ -701,10 +706,10 @@ class NestedObjectStore(BaseObjectStore):
|
||||
return self._call_method('_get_object_url', obj, None, False, **kwargs)
|
||||
|
||||
def _get_concrete_store_name(self, obj):
|
||||
return self._call_method('_get_concrete_store_name', obj, None, True)
|
||||
return self._call_method('_get_concrete_store_name', obj, None, False)
|
||||
|
||||
def _get_concrete_store_description_markdown(self, obj):
|
||||
return self._call_method('_get_concrete_store_description_markdown', obj, None, True)
|
||||
return self._call_method('_get_concrete_store_description_markdown', obj, None, False)
|
||||
|
||||
def _get_store_by(self, obj):
|
||||
return self._call_method('_get_store_by', obj, None, False)
|
||||
@@ -932,7 +937,7 @@ class HierarchicalObjectStore(NestedObjectStore):
|
||||
"""The default constructor. Extends `NestedObjectStore`."""
|
||||
super().__init__(config, config_dict)
|
||||
|
||||
backends = OrderedDict()
|
||||
backends = {}
|
||||
for order, backend_def in enumerate(config_dict["backends"]):
|
||||
backends[order] = build_object_store_from_config(config, config_dict=backend_def, fsmon=fsmon)
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ Contains OpenID provider functionality
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
|
||||
|
||||
from galaxy.util import parse_xml, string_as_bool
|
||||
@@ -115,7 +114,7 @@ class OpenIDProviders:
|
||||
@classmethod
|
||||
def from_elem(cls, xml_root):
|
||||
oid_elem = xml_root
|
||||
providers = OrderedDict()
|
||||
providers = {}
|
||||
for elem in oid_elem.findall('provider'):
|
||||
try:
|
||||
provider = OpenIDProvider.from_file(os.path.join('lib/galaxy/openid', elem.get('file')))
|
||||
@@ -129,7 +128,7 @@ class OpenIDProviders:
|
||||
if providers:
|
||||
self.providers = providers
|
||||
else:
|
||||
self.providers = OrderedDict()
|
||||
self.providers = {}
|
||||
self._banned_identifiers = [provider.op_endpoint_url for provider in self.providers.values() if provider.never_associate_with_user]
|
||||
|
||||
def __iter__(self):
|
||||
|
||||
@@ -2,7 +2,6 @@ import logging
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from collections import OrderedDict
|
||||
|
||||
from migrate.versioning import repository, schema
|
||||
from sqlalchemy import create_engine, MetaData, Table
|
||||
@@ -34,7 +33,7 @@ def verify_tools(app, url, galaxy_config_file=None, engine_options=None):
|
||||
tool_shed_accessible = False
|
||||
if app.new_installation:
|
||||
# New installations will not be missing tools, so we don't need to worry about them.
|
||||
missing_tool_configs_dict = OrderedDict()
|
||||
missing_tool_configs_dict = {}
|
||||
else:
|
||||
tool_panel_configs = common_util.get_non_shed_tool_panel_configs(app)
|
||||
if tool_panel_configs:
|
||||
@@ -48,7 +47,7 @@ def verify_tools(app, url, galaxy_config_file=None, engine_options=None):
|
||||
# we have to set the value of tool_shed_accessible to True so that the value of migrate_tools.version can be correctly set in
|
||||
# the database.
|
||||
tool_shed_accessible = True
|
||||
missing_tool_configs_dict = OrderedDict()
|
||||
missing_tool_configs_dict = {}
|
||||
have_tool_dependencies = False
|
||||
for v in missing_tool_configs_dict.values():
|
||||
if v:
|
||||
|
||||
@@ -8,7 +8,6 @@ import os
|
||||
import shutil
|
||||
import tempfile
|
||||
import threading
|
||||
from collections import OrderedDict
|
||||
|
||||
from galaxy import util
|
||||
from galaxy.tool_shed.galaxy_install import install_manager
|
||||
@@ -113,7 +112,7 @@ class ToolMigrationManager:
|
||||
# tool_shed_accessible to True so that the value of migrate_tools.version can
|
||||
# be correctly set in the database.
|
||||
tool_shed_accessible = True
|
||||
missing_tool_configs_dict = OrderedDict()
|
||||
missing_tool_configs_dict = {}
|
||||
if tool_shed_accessible:
|
||||
if len(self.proprietary_tool_confs) == 1:
|
||||
plural = ''
|
||||
@@ -387,7 +386,7 @@ class ToolMigrationManager:
|
||||
entries are automatically added to the reserved migrated_tools_conf.xml file as part of the migration process.
|
||||
"""
|
||||
tool_configs_to_filter = []
|
||||
tool_panel_dict_for_display = OrderedDict()
|
||||
tool_panel_dict_for_display = {}
|
||||
if self.tool_path:
|
||||
repo_install_dir = os.path.join(self.tool_path, relative_install_dir)
|
||||
else:
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import logging
|
||||
from collections import (
|
||||
namedtuple,
|
||||
OrderedDict,
|
||||
)
|
||||
from collections import namedtuple
|
||||
|
||||
from galaxy.util import parse_xml_string
|
||||
from galaxy.util.tool_shed.common_util import remove_protocol_from_tool_shed_url
|
||||
@@ -22,8 +19,8 @@ AUTH_TUPLE = namedtuple('AuthSetting', 'username password')
|
||||
class Registry:
|
||||
|
||||
def __init__(self, config=None):
|
||||
self.tool_sheds = OrderedDict()
|
||||
self.tool_sheds_auth = OrderedDict()
|
||||
self.tool_sheds = {}
|
||||
self.tool_sheds_auth = {}
|
||||
if config:
|
||||
# Parse tool_sheds_conf.xml
|
||||
tree, error_message = parse_xml(config)
|
||||
|
||||
@@ -11,7 +11,6 @@ import logging
|
||||
import os
|
||||
import pickle
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from collections import OrderedDict
|
||||
from uuid import uuid4
|
||||
|
||||
|
||||
@@ -1214,7 +1213,7 @@ class ConditionalInstance:
|
||||
name=self.name,
|
||||
type=INPUT_TYPE.CONDITIONAL,
|
||||
test=self.case.to_dict(),
|
||||
when=OrderedDict(),
|
||||
when={},
|
||||
)
|
||||
for value, block in self.whens:
|
||||
as_dict["when"][value] = [i.to_dict() for i in block]
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
""" This module is responsible for converting between Galaxy's tool
|
||||
input description and the CWL description for a job json. """
|
||||
|
||||
import collections
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
@@ -210,7 +209,7 @@ def collection_wrapper_to_array(inputs_dir, wrapped_value):
|
||||
|
||||
|
||||
def collection_wrapper_to_record(inputs_dir, wrapped_value):
|
||||
rval = collections.OrderedDict()
|
||||
rval = {}
|
||||
for key, value in wrapped_value.items():
|
||||
rval[key] = dataset_wrapper_to_file_json(inputs_dir, value)
|
||||
return rval
|
||||
|
||||
@@ -6,7 +6,6 @@ import json
|
||||
import logging
|
||||
import os.path
|
||||
import shutil
|
||||
from collections import OrderedDict
|
||||
|
||||
from galaxy.util import (
|
||||
hash_util,
|
||||
@@ -201,7 +200,7 @@ class DependencyManager:
|
||||
|
||||
def _requirements_to_dependencies_dict(self, requirements, search=False, **kwds):
|
||||
"""Build simple requirements to dependencies dict for resolution."""
|
||||
requirement_to_dependency = OrderedDict()
|
||||
requirement_to_dependency = {}
|
||||
index = kwds.get('index')
|
||||
install = kwds.get('install', False)
|
||||
resolver_type = kwds.get('resolver_type')
|
||||
@@ -233,7 +232,7 @@ class DependencyManager:
|
||||
if container_type is not None and getattr(resolver, "container_type", None) != container_type:
|
||||
continue
|
||||
|
||||
_requirement_to_dependency = OrderedDict([(k, v) for k, v in requirement_to_dependency.items() if not isinstance(v, NullDependency)])
|
||||
_requirement_to_dependency = {k: v for k, v in requirement_to_dependency.items() if not isinstance(v, NullDependency)}
|
||||
|
||||
if len(_requirement_to_dependency) == len(resolvable_requirements):
|
||||
# Shortcut - resolution complete.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import logging
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
|
||||
from galaxy.tool_util.cwl.parser import tool_proxy
|
||||
from galaxy.tool_util.deps import requirements
|
||||
@@ -113,14 +112,14 @@ class CwlToolSource(ToolSource):
|
||||
|
||||
def parse_outputs(self, tool):
|
||||
output_instances = self.tool_proxy.output_instances()
|
||||
outputs = OrderedDict()
|
||||
outputs = {}
|
||||
output_defs = []
|
||||
for output_instance in output_instances:
|
||||
output_defs.append(self._parse_output(tool, output_instance))
|
||||
# TODO: parse outputs collections
|
||||
for output_def in output_defs:
|
||||
outputs[output_def.name] = output_def
|
||||
return outputs, OrderedDict()
|
||||
return outputs, {}
|
||||
|
||||
def _parse_output(self, tool, output_instance):
|
||||
name = output_instance.name
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from collections import OrderedDict
|
||||
|
||||
from galaxy.util.dictifiable import Dictifiable
|
||||
from .output_actions import ToolOutputActionGroup
|
||||
from .output_collection_def import dataset_collector_descriptions_from_output_dict
|
||||
@@ -156,7 +154,7 @@ class ToolOutputCollection(ToolOutputBase):
|
||||
self.collection = True
|
||||
self.default_format = default_format
|
||||
self.structure = structure
|
||||
self.outputs = OrderedDict()
|
||||
self.outputs = {}
|
||||
|
||||
self.inherit_format = inherit_format
|
||||
self.inherit_metadata = inherit_metadata
|
||||
|
||||
@@ -2,7 +2,6 @@ import json
|
||||
import logging
|
||||
import re
|
||||
import uuid
|
||||
from collections import OrderedDict
|
||||
from math import isinf
|
||||
|
||||
import packaging.version
|
||||
@@ -290,12 +289,12 @@ class XmlToolSource(ToolSource):
|
||||
|
||||
def parse_outputs(self, tool):
|
||||
out_elem = self.root.find("outputs")
|
||||
outputs = OrderedDict()
|
||||
output_collections = OrderedDict()
|
||||
outputs = {}
|
||||
output_collections = {}
|
||||
if out_elem is None:
|
||||
return outputs, output_collections
|
||||
|
||||
data_dict = OrderedDict()
|
||||
data_dict = {}
|
||||
|
||||
def _parse(data_elem, **kwds):
|
||||
output_def = self._parse_output(data_elem, tool, **kwds)
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from collections import OrderedDict
|
||||
|
||||
import packaging.version
|
||||
|
||||
from galaxy.tool_util.deps import requirements
|
||||
@@ -117,10 +115,10 @@ class YamlToolSource(ToolSource):
|
||||
else:
|
||||
message = "Unknown output_type [%s] encountered." % output_type
|
||||
raise Exception(message)
|
||||
outputs = OrderedDict()
|
||||
outputs = {}
|
||||
for output in output_defs:
|
||||
outputs[output.name] = output
|
||||
output_collections = OrderedDict()
|
||||
output_collections = {}
|
||||
for output in output_collection_defs:
|
||||
output_collections[output.name] = output
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import tarfile
|
||||
import tempfile
|
||||
import time
|
||||
import zipfile
|
||||
from collections import OrderedDict
|
||||
from json import dumps
|
||||
from logging import getLogger
|
||||
|
||||
@@ -43,7 +42,7 @@ DEFAULT_FTYPE = 'auto'
|
||||
DEFAULT_DBKEY = os.environ.get("GALAXY_TEST_DEFAULT_DBKEY", "?")
|
||||
|
||||
|
||||
class OutputsDict(OrderedDict):
|
||||
class OutputsDict(dict):
|
||||
"""Ordered dict that can also be accessed by index.
|
||||
|
||||
>>> out = OutputsDict()
|
||||
@@ -57,12 +56,7 @@ class OutputsDict(OrderedDict):
|
||||
if isinstance(item, int):
|
||||
return self[list(self.keys())[item]]
|
||||
else:
|
||||
# ideally we'd do `return super(OutputsDict, self)[item]`,
|
||||
# but this fails because OrderedDict has no `__getitem__`. (!?)
|
||||
item = self.get(item)
|
||||
if item is None:
|
||||
raise KeyError(item)
|
||||
return item
|
||||
return super().__getitem__(item)
|
||||
|
||||
|
||||
def stage_data_in_history(galaxy_interactor, tool_id, all_test_data, history=None, force_path_paste=False, maxseconds=DEFAULT_TOOL_TEST_WAIT):
|
||||
@@ -497,7 +491,7 @@ class GalaxyInteractorApi:
|
||||
return element_identifiers
|
||||
|
||||
def __dictify_output_collections(self, submit_response):
|
||||
output_collections_dict = OrderedDict()
|
||||
output_collections_dict = {}
|
||||
for output_collection in submit_response['output_collections']:
|
||||
output_collections_dict[output_collection.get("output_name")] = output_collection
|
||||
return output_collections_dict
|
||||
|
||||
@@ -10,7 +10,6 @@ import re
|
||||
import tarfile
|
||||
import tempfile
|
||||
import threading
|
||||
from collections import OrderedDict
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import List, Type
|
||||
@@ -1124,7 +1123,7 @@ class Tool(Dictifiable):
|
||||
This implementation supports multiple pages and grouping constructs.
|
||||
"""
|
||||
# Load parameters (optional)
|
||||
self.inputs = OrderedDict()
|
||||
self.inputs = {}
|
||||
pages = tool_source.parse_input_pages()
|
||||
enctypes = set()
|
||||
if pages.inputs_defined:
|
||||
@@ -1237,7 +1236,7 @@ class Tool(Dictifiable):
|
||||
groups (repeat, conditional) or param elements. Groups will be parsed
|
||||
recursively.
|
||||
"""
|
||||
rval = OrderedDict()
|
||||
rval = {}
|
||||
context = ExpressionContext(rval, context)
|
||||
for input_source in page_source.parse_input_sources():
|
||||
# Repeat group
|
||||
@@ -1277,7 +1276,7 @@ class Tool(Dictifiable):
|
||||
page_source = XmlPageSource(XML("<when>%s</when>" % case_inputs))
|
||||
case.inputs = self.parse_input_elem(page_source, enctypes, context)
|
||||
else:
|
||||
case.inputs = OrderedDict()
|
||||
case.inputs = {}
|
||||
group.cases.append(case)
|
||||
else:
|
||||
# Should have one child "input" which determines the case
|
||||
@@ -1305,7 +1304,7 @@ class Tool(Dictifiable):
|
||||
(self.id, group.name, group.test_param.name, unspecified_case))
|
||||
case = ConditionalWhen()
|
||||
case.value = unspecified_case
|
||||
case.inputs = OrderedDict()
|
||||
case.inputs = {}
|
||||
group.cases.append(case)
|
||||
rval[group.name] = group
|
||||
elif input_type == "section":
|
||||
@@ -1673,7 +1672,7 @@ class Tool(Dictifiable):
|
||||
log.exception("Exception caught while attempting to execute tool with id '%s':", self.id)
|
||||
message = "Error executing tool with id '{}': {}".format(self.id, unicodify(e))
|
||||
return False, message
|
||||
if isinstance(out_data, OrderedDict):
|
||||
if isinstance(out_data, dict):
|
||||
return job, list(out_data.items())
|
||||
else:
|
||||
if isinstance(out_data, str):
|
||||
@@ -2807,7 +2806,7 @@ class DatabaseOperationTool(Tool):
|
||||
return self._outputs_dict()
|
||||
|
||||
def _outputs_dict(self):
|
||||
return OrderedDict()
|
||||
return {}
|
||||
|
||||
|
||||
class UnzipCollectionTool(DatabaseOperationTool):
|
||||
@@ -2839,7 +2838,7 @@ class ZipCollectionTool(DatabaseOperationTool):
|
||||
reverse_o = incoming["input_reverse"]
|
||||
|
||||
forward, reverse = forward_o.copy(), reverse_o.copy()
|
||||
new_elements = OrderedDict()
|
||||
new_elements = {}
|
||||
new_elements["forward"] = forward
|
||||
new_elements["reverse"] = reverse
|
||||
self._add_datasets_to_history(history, [forward, reverse])
|
||||
@@ -2852,7 +2851,7 @@ class BuildListCollectionTool(DatabaseOperationTool):
|
||||
tool_type = 'build_list'
|
||||
|
||||
def produce_outputs(self, trans, out_data, output_collections, incoming, history, tags=None, **kwds):
|
||||
new_elements = OrderedDict()
|
||||
new_elements = {}
|
||||
|
||||
for i, incoming_repeat in enumerate(incoming["datasets"]):
|
||||
if incoming_repeat["input"]:
|
||||
@@ -2912,7 +2911,7 @@ class MergeCollectionTool(DatabaseOperationTool):
|
||||
if dupl_actions in ['suffix_conflict', 'suffix_every', 'suffix_conflict_rest']:
|
||||
suffix_pattern = advanced['conflict']['suffix_pattern']
|
||||
|
||||
new_element_structure = OrderedDict()
|
||||
new_element_structure = {}
|
||||
|
||||
# Which inputs does the identifier appear in.
|
||||
identifiers_map = {}
|
||||
@@ -2964,7 +2963,7 @@ class MergeCollectionTool(DatabaseOperationTool):
|
||||
new_element_structure[effective_identifer] = element
|
||||
|
||||
# Don't copy until we know everything is fine and we have the structure of the list ready to go.
|
||||
new_elements = OrderedDict()
|
||||
new_elements = {}
|
||||
for key, value in new_element_structure.items():
|
||||
if getattr(value, "history_content_type", None) == "dataset":
|
||||
copied_value = value.copy(flush=False)
|
||||
@@ -2981,7 +2980,7 @@ class MergeCollectionTool(DatabaseOperationTool):
|
||||
class FilterDatasetsTool(DatabaseOperationTool):
|
||||
|
||||
def _get_new_elements(self, history, elements_to_copy):
|
||||
new_elements = OrderedDict()
|
||||
new_elements = {}
|
||||
for dce in elements_to_copy:
|
||||
element_identifier = dce.element_identifier
|
||||
if getattr(dce.element_object, "history_content_type", None) == "dataset":
|
||||
@@ -3049,7 +3048,7 @@ class FlattenTool(DatabaseOperationTool):
|
||||
def produce_outputs(self, trans, out_data, output_collections, incoming, history, **kwds):
|
||||
hdca = incoming["input"]
|
||||
join_identifier = incoming["join_identifier"]
|
||||
new_elements = OrderedDict()
|
||||
new_elements = {}
|
||||
copied_datasets = []
|
||||
|
||||
def add_elements(collection, prefix=""):
|
||||
@@ -3077,7 +3076,7 @@ class SortTool(DatabaseOperationTool):
|
||||
def produce_outputs(self, trans, out_data, output_collections, incoming, history, **kwds):
|
||||
hdca = incoming["input"]
|
||||
sorttype = incoming["sort_type"]["sort_type"]
|
||||
new_elements = OrderedDict()
|
||||
new_elements = {}
|
||||
elements = hdca.collection.elements
|
||||
presort_elements = []
|
||||
if sorttype == 'alpha':
|
||||
@@ -3090,7 +3089,7 @@ class SortTool(DatabaseOperationTool):
|
||||
hda = incoming["sort_type"]["sort_file"]
|
||||
data_lines = hda.metadata.get('data_lines', 0)
|
||||
if data_lines == len(elements):
|
||||
old_elements_dict = OrderedDict()
|
||||
old_elements_dict = {}
|
||||
for element in elements:
|
||||
old_elements_dict[element.element_identifier] = element
|
||||
try:
|
||||
@@ -3123,7 +3122,7 @@ class RelabelFromFileTool(DatabaseOperationTool):
|
||||
how_type = incoming["how"]["how_select"]
|
||||
new_labels_dataset_assoc = incoming["how"]["labels"]
|
||||
strict = string_as_bool(incoming["how"]["strict"])
|
||||
new_elements = OrderedDict()
|
||||
new_elements = {}
|
||||
|
||||
def add_copied_value_to_new_elements(new_label, dce_object):
|
||||
new_label = new_label.strip()
|
||||
@@ -3199,7 +3198,7 @@ class TagFromFileTool(DatabaseOperationTool):
|
||||
hdca = incoming["input"]
|
||||
how = incoming['how']
|
||||
new_tags_dataset_assoc = incoming["tags"]
|
||||
new_elements = OrderedDict()
|
||||
new_elements = {}
|
||||
new_datasets = []
|
||||
|
||||
def add_copied_value_to_new_elements(new_tags_dict, dce):
|
||||
@@ -3260,8 +3259,8 @@ class FilterFromFileTool(DatabaseOperationTool):
|
||||
hdca = incoming["input"]
|
||||
how_filter = incoming["how"]["how_filter"]
|
||||
filter_dataset_assoc = incoming["how"]["filter_source"]
|
||||
filtered_elements = OrderedDict()
|
||||
discarded_elements = OrderedDict()
|
||||
filtered_elements = {}
|
||||
discarded_elements = {}
|
||||
|
||||
filtered_path = filter_dataset_assoc.file_name
|
||||
with open(filtered_path) as fh:
|
||||
|
||||
@@ -2,7 +2,6 @@ import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
from json import dumps
|
||||
|
||||
|
||||
@@ -69,7 +68,7 @@ class DefaultToolAction:
|
||||
"""
|
||||
if current_user_roles is None:
|
||||
current_user_roles = trans.get_current_user_roles()
|
||||
input_datasets = OrderedDict()
|
||||
input_datasets = {}
|
||||
all_permissions = {}
|
||||
|
||||
def record_permission(action, role_id):
|
||||
@@ -357,7 +356,7 @@ class DefaultToolAction:
|
||||
# wrapped params are used by change_format action and by output.label; only perform this wrapping once, as needed
|
||||
wrapped_params = self._wrapped_params(trans, tool, incoming, inp_data)
|
||||
|
||||
out_data = OrderedDict()
|
||||
out_data = {}
|
||||
input_collections = {k: v[0][0] for k, v in inp_dataset_collections.items()}
|
||||
output_collections = OutputCollections(
|
||||
trans,
|
||||
@@ -852,7 +851,7 @@ class OutputCollections:
|
||||
# We don't care about the repeat index, we just need to find the correct DataCollectionToolParameter
|
||||
else:
|
||||
key = group
|
||||
if isinstance(data_param, OrderedDict):
|
||||
if isinstance(data_param, dict):
|
||||
data_param = data_param.get(key)
|
||||
else:
|
||||
data_param = data_param.inputs.get(key)
|
||||
|
||||
@@ -2,7 +2,6 @@ import datetime
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
from collections import OrderedDict
|
||||
|
||||
from galaxy.job_execution.setup import create_working_directory_for_job
|
||||
from galaxy.tools.actions import ToolAction
|
||||
@@ -73,7 +72,7 @@ class ImportHistoryToolAction(ToolAction):
|
||||
trans.app.job_manager.enqueue(job, tool=tool)
|
||||
trans.log_event("Added import history job to the job queue, id: %s" % str(job.id), tool_id=job.tool_id)
|
||||
|
||||
return job, OrderedDict()
|
||||
return job, {}
|
||||
|
||||
|
||||
class ExportHistoryToolAction(ToolAction):
|
||||
@@ -173,4 +172,4 @@ class ExportHistoryToolAction(ToolAction):
|
||||
trans.app.job_manager.enqueue(job, tool=tool)
|
||||
trans.log_event("Added export history job to the job queue, id: %s" % str(job.id), tool_id=job.tool_id)
|
||||
|
||||
return job, OrderedDict()
|
||||
return job, {}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import logging
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
from json import dumps
|
||||
|
||||
from galaxy.job_execution.datasets import DatasetPath
|
||||
@@ -129,4 +128,4 @@ class SetMetadataToolAction(ToolAction):
|
||||
# clear e.g. converted files
|
||||
dataset.datatype.before_setting_metadata(dataset)
|
||||
|
||||
return job, OrderedDict()
|
||||
return job, {}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
|
||||
from galaxy.tools.actions import (
|
||||
DefaultToolAction,
|
||||
@@ -38,7 +37,7 @@ class ModelOperationToolAction(DefaultToolAction):
|
||||
# wrapped params are used by change_format action and by output.label; only perform this wrapping once, as needed
|
||||
wrapped_params = self._wrapped_params(trans, tool, incoming)
|
||||
|
||||
out_data = OrderedDict()
|
||||
out_data = {}
|
||||
input_collections = {k: v[0][0] for k, v in inp_dataset_collections.items()}
|
||||
output_collections = OutputCollections(
|
||||
trans,
|
||||
|
||||
@@ -3,7 +3,6 @@ import logging
|
||||
import os
|
||||
import socket
|
||||
import tempfile
|
||||
from collections import OrderedDict
|
||||
from io import StringIO
|
||||
from json import dump, dumps
|
||||
from urllib.parse import urlparse
|
||||
@@ -442,7 +441,7 @@ def create_job(trans, params, tool, json_file_path, outputs, folder=None, histor
|
||||
# Queue the job for execution
|
||||
trans.app.job_manager.enqueue(job, tool=tool)
|
||||
trans.log_event("Added job to the job queue, id: %s" % str(job.id), tool_id=job.tool_id)
|
||||
output = OrderedDict()
|
||||
output = {}
|
||||
for i, v in enumerate(outputs):
|
||||
if not hasattr(output_object, "collection_type"):
|
||||
output['output%i' % i] = v
|
||||
|
||||
@@ -14,7 +14,6 @@ import os.path
|
||||
import re
|
||||
import string
|
||||
import time
|
||||
from collections import OrderedDict
|
||||
from glob import glob
|
||||
from tempfile import NamedTemporaryFile
|
||||
from typing import List
|
||||
@@ -256,7 +255,7 @@ class ToolDataTable:
|
||||
self.empty_field_values = {}
|
||||
self.allow_duplicate_entries = util.asbool(config_element.get('allow_duplicate_entries', True))
|
||||
self.here = filename and os.path.dirname(filename)
|
||||
self.filenames = OrderedDict()
|
||||
self.filenames = {}
|
||||
self.tool_data_path = tool_data_path
|
||||
self.tool_data_path_files = tool_data_path_files
|
||||
self.other_config_dict = other_config_dict or {}
|
||||
|
||||
@@ -2,7 +2,6 @@ import errno
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
|
||||
|
||||
from galaxy import util
|
||||
@@ -19,8 +18,8 @@ DEFAULT_VALUE_TRANSLATION_TYPE = 'template'
|
||||
class DataManagers:
|
||||
def __init__(self, app, xml_filename=None):
|
||||
self.app = app
|
||||
self.data_managers = OrderedDict()
|
||||
self.managed_data_tables = OrderedDict()
|
||||
self.data_managers = {}
|
||||
self.managed_data_tables = {}
|
||||
self.tool_path = None
|
||||
self._reload_count = 0
|
||||
self.filename = xml_filename or self.app.config.data_manager_config_file
|
||||
@@ -123,7 +122,7 @@ class DataManager:
|
||||
self.version = self.DEFAULT_VERSION
|
||||
self.guid = None
|
||||
self.tool = None
|
||||
self.data_tables = OrderedDict()
|
||||
self.data_tables = {}
|
||||
self.output_ref_by_data_table = {}
|
||||
self.move_by_data_table_column = {}
|
||||
self.value_translation_by_data_table_column = {}
|
||||
@@ -171,7 +170,7 @@ class DataManager:
|
||||
data_table_name = data_table_elem.get("name")
|
||||
assert data_table_name is not None, "A name is required for a data table entry"
|
||||
if data_table_name not in self.data_tables:
|
||||
self.data_tables[data_table_name] = OrderedDict()
|
||||
self.data_tables[data_table_name] = {}
|
||||
output_elem = data_table_elem.find('output')
|
||||
if output_elem is not None:
|
||||
for column_elem in output_elem.findall('column'):
|
||||
|
||||
@@ -152,7 +152,7 @@ class ExecutionTracker:
|
||||
self.output_datasets = []
|
||||
self.output_collections = []
|
||||
|
||||
self.implicit_collections = collections.OrderedDict()
|
||||
self.implicit_collections = {}
|
||||
|
||||
@property
|
||||
def param_combinations(self):
|
||||
|
||||
@@ -27,7 +27,6 @@ def visit_input_values(inputs, input_values, callback, name_prefix='', label_pre
|
||||
|
||||
If the callback returns a value, it will be replace the old value.
|
||||
|
||||
>>> from collections import OrderedDict
|
||||
>>> from galaxy.util import XML
|
||||
>>> from galaxy.util.bunch import Bunch
|
||||
>>> from galaxy.tools.parameters.basic import TextToolParameter, BooleanToolParameter
|
||||
@@ -43,9 +42,9 @@ def visit_input_values(inputs, input_values, callback, name_prefix='', label_pre
|
||||
>>> i = TextToolParameter(None, XML('<param name="i"/>'))
|
||||
>>> j = TextToolParameter(None, XML('<param name="j"/>'))
|
||||
>>> b.name = b.title = 'b'
|
||||
>>> b.inputs = OrderedDict([ ('c', c), ('d', d) ])
|
||||
>>> b.inputs = dict([ ('c', c), ('d', d) ])
|
||||
>>> d.name = d.title = 'd'
|
||||
>>> d.inputs = OrderedDict([ ('e', e), ('f', f) ])
|
||||
>>> d.inputs = dict([ ('e', e), ('f', f) ])
|
||||
>>> f.test_param = g
|
||||
>>> f.name = 'f'
|
||||
>>> f.cases = [Bunch(value='true', inputs= {'h': h}), Bunch(value='false', inputs= { 'i': i })]
|
||||
@@ -54,8 +53,8 @@ def visit_input_values(inputs, input_values, callback, name_prefix='', label_pre
|
||||
... print('name=%s, prefix=%s, prefixed_name=%s, prefixed_label=%s, value=%s' % (input.name, prefix, prefixed_name, prefixed_label, value))
|
||||
... if error:
|
||||
... print(error)
|
||||
>>> inputs = OrderedDict([('a', a),('b', b)])
|
||||
>>> nested = OrderedDict([('a', 1), ('b', [OrderedDict([('c', 3), ('d', [OrderedDict([ ('e', 5), ('f', OrderedDict([ ('g', True), ('h', 7)]))])])])])])
|
||||
>>> inputs = dict([('a', a),('b', b)])
|
||||
>>> nested = dict([('a', 1), ('b', [dict([('c', 3), ('d', [dict([ ('e', 5), ('f', dict([ ('g', True), ('h', 7)]))])])])])])
|
||||
>>> visit_input_values(inputs, nested, visitor)
|
||||
name=a, prefix=, prefixed_name=a, prefixed_label=a, value=1
|
||||
name=c, prefix=b_0|, prefixed_name=b_0|c, prefixed_label=b 1 > c, value=3
|
||||
@@ -103,7 +102,7 @@ def visit_input_values(inputs, input_values, callback, name_prefix='', label_pre
|
||||
No value found for 'b 1 > d 1 > j'.
|
||||
|
||||
>>> # Other parameters are missing in state
|
||||
>>> nested = OrderedDict([('b', [OrderedDict([( 'd', [OrderedDict([('f', OrderedDict([('g', True), ('h', 7)]))])])])])])
|
||||
>>> nested = dict([('b', [dict([( 'd', [dict([('f', dict([('g', True), ('h', 7)]))])])])])])
|
||||
>>> visit_input_values(inputs, nested, visitor)
|
||||
name=a, prefix=, prefixed_name=a, prefixed_label=a, value=None
|
||||
No value found for 'a'.
|
||||
@@ -282,7 +281,6 @@ def update_dataset_ids(input_values, translate_values, src):
|
||||
def populate_state(request_context, inputs, incoming, state, errors=None, context=None, check=True, simple_errors=True, input_format='legacy'):
|
||||
"""
|
||||
Populates nested state dict from incoming parameter values.
|
||||
>>> from collections import OrderedDict
|
||||
>>> from galaxy.util import XML
|
||||
>>> from galaxy.util.bunch import Bunch
|
||||
>>> from galaxy.tools.parameters.basic import TextToolParameter, BooleanToolParameter
|
||||
@@ -302,15 +300,15 @@ def populate_state(request_context, inputs, incoming, state, errors=None, contex
|
||||
>>> h = TextToolParameter(None, XML('<param name="h"/>'))
|
||||
>>> i = TextToolParameter(None, XML('<param name="i"/>'))
|
||||
>>> b.name = 'b'
|
||||
>>> b.inputs = OrderedDict([('c', c), ('d', d)])
|
||||
>>> b.inputs = dict([('c', c), ('d', d)])
|
||||
>>> d.name = 'd'
|
||||
>>> d.inputs = OrderedDict([('e', e), ('f', f)])
|
||||
>>> d.inputs = dict([('e', e), ('f', f)])
|
||||
>>> f.test_param = g
|
||||
>>> f.name = 'f'
|
||||
>>> f.cases = [Bunch(value='true', inputs= { 'h': h }), Bunch(value='false', inputs= { 'i': i })]
|
||||
>>> inputs = OrderedDict([('a',a),('b',b)])
|
||||
>>> flat = OrderedDict([('a', 1), ('b_0|c', 2), ('b_0|d_0|e', 3), ('b_0|d_0|f|h', 4), ('b_0|d_0|f|g', True)])
|
||||
>>> state = OrderedDict()
|
||||
>>> inputs = dict([('a',a),('b',b)])
|
||||
>>> flat = dict([('a', 1), ('b_0|c', 2), ('b_0|d_0|e', 3), ('b_0|d_0|f|h', 4), ('b_0|d_0|f|g', True)])
|
||||
>>> state = {}
|
||||
>>> populate_state(trans, inputs, flat, state, check=False)
|
||||
>>> print(state['a'])
|
||||
1
|
||||
@@ -322,7 +320,7 @@ def populate_state(request_context, inputs, incoming, state, errors=None, contex
|
||||
4
|
||||
>>> # now test with input_format='21.01'
|
||||
>>> nested = {'a': 1, 'b': [{'c': 2, 'd': [{'e': 3, 'f': {'h': 4, 'g': True}}]}]}
|
||||
>>> state_new = OrderedDict()
|
||||
>>> state_new = {}
|
||||
>>> populate_state(trans, inputs, nested, state_new, check=False, input_format='21.01')
|
||||
>>> print(state_new['a'])
|
||||
1
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import copy
|
||||
import itertools
|
||||
import logging
|
||||
from collections import namedtuple, OrderedDict
|
||||
from collections import namedtuple
|
||||
|
||||
from galaxy import (
|
||||
exceptions,
|
||||
@@ -178,7 +178,7 @@ def expand_meta_parameters(trans, tool, incoming):
|
||||
if not incoming_key.startswith('__'):
|
||||
process_key(incoming_key, incoming_value=incoming_value, d=nested_dict)
|
||||
|
||||
reordered_incoming = OrderedDict()
|
||||
reordered_incoming = {}
|
||||
|
||||
def visitor(input, value, prefix, prefixed_name, prefixed_label, error, **kwargs):
|
||||
if prefixed_name in incoming_copy:
|
||||
|
||||
@@ -4,10 +4,7 @@ import os
|
||||
import string
|
||||
import time
|
||||
import urllib.request
|
||||
from collections import (
|
||||
namedtuple,
|
||||
OrderedDict
|
||||
)
|
||||
from collections import namedtuple
|
||||
from errno import ENOENT
|
||||
from urllib.parse import urlparse
|
||||
|
||||
@@ -103,7 +100,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin):
|
||||
# In-memory dictionary that defines the layout of the tool panel.
|
||||
self._tool_panel = ToolPanelElements()
|
||||
self._index = 0
|
||||
self.data_manager_tools = OrderedDict()
|
||||
self.data_manager_tools = {}
|
||||
self._lineage_map = LineageMap(app)
|
||||
# Sets self._integrated_tool_panel and self._integrated_tool_panel_config_has_contents
|
||||
self._init_integrated_tool_panel(app.config)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import logging
|
||||
import shlex
|
||||
import tempfile
|
||||
from collections import OrderedDict
|
||||
from functools import total_ordering
|
||||
|
||||
from galaxy import exceptions
|
||||
@@ -453,7 +452,7 @@ class DatasetCollectionWrapper(ToolParameterValueWrapper, HasDatasets):
|
||||
self.collection = collection
|
||||
|
||||
elements = collection.elements
|
||||
element_instances = OrderedDict()
|
||||
element_instances = {}
|
||||
|
||||
element_instance_list = []
|
||||
for dataset_collection_element in elements:
|
||||
|
||||
@@ -1086,19 +1086,6 @@ def strip_control_characters(s):
|
||||
return "".join(c for c in unicodify(s) if unicodedata.category(c) != "Cc")
|
||||
|
||||
|
||||
def strip_control_characters_nested(item):
|
||||
"""Recursively strips control characters from lists, dicts, tuples."""
|
||||
|
||||
def visit(path, key, value):
|
||||
if isinstance(key, str):
|
||||
key = strip_control_characters(key)
|
||||
if isinstance(value, str):
|
||||
value = strip_control_characters(value)
|
||||
return key, value
|
||||
|
||||
return remap(item, visit)
|
||||
|
||||
|
||||
def object_to_string(obj):
|
||||
return binascii.hexlify(obj)
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ first.
|
||||
Maybe this doesn't make sense and maybe much of this stuff could be replaced
|
||||
with itertools product and permutations. These are open questions.
|
||||
"""
|
||||
from collections import OrderedDict
|
||||
|
||||
from galaxy.exceptions import MessageException
|
||||
from galaxy.util.bunch import Bunch
|
||||
@@ -42,9 +41,9 @@ def expand_multi_inputs(inputs, classifier, key_filter=None):
|
||||
def __split_inputs(inputs, classifier, key_filter):
|
||||
key_filter = key_filter or (lambda x: True)
|
||||
|
||||
single_inputs = OrderedDict()
|
||||
matched_multi_inputs = OrderedDict()
|
||||
multiplied_multi_inputs = OrderedDict()
|
||||
single_inputs = {}
|
||||
matched_multi_inputs = {}
|
||||
multiplied_multi_inputs = {}
|
||||
|
||||
for input_key in filter(key_filter, inputs):
|
||||
input_type, expanded_val = classifier(input_key)
|
||||
|
||||
@@ -6,8 +6,6 @@ from typing import List, Type
|
||||
import yaml
|
||||
from pkg_resources import resource_stream
|
||||
|
||||
from galaxy.util import strip_control_characters_nested
|
||||
|
||||
|
||||
def get_rules_specification():
|
||||
return yaml.safe_load(resource_stream(__name__, 'rules_dsl_spec.yml'))
|
||||
@@ -498,7 +496,7 @@ def flat_map(f, items):
|
||||
class RuleSet:
|
||||
|
||||
def __init__(self, rule_set_as_dict):
|
||||
self.raw_rules = strip_control_characters_nested(rule_set_as_dict["rules"])
|
||||
self.raw_rules = rule_set_as_dict["rules"]
|
||||
self.raw_mapping = rule_set_as_dict.get("mapping", [])
|
||||
|
||||
@property
|
||||
|
||||
@@ -3,8 +3,6 @@ Fencepost-simple graph structure implementation.
|
||||
"""
|
||||
# Currently (2013.7.12) only used in easing the parsing of graph datatype data.
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
|
||||
class SimpleGraphNode:
|
||||
"""
|
||||
@@ -58,7 +56,7 @@ class SimpleGraph:
|
||||
|
||||
def __init__(self, nodes=None, edges=None):
|
||||
# use an odict so that edge indeces actually match the final node list indeces
|
||||
self.nodes = nodes or OrderedDict()
|
||||
self.nodes = nodes or {}
|
||||
self.edges = edges or []
|
||||
|
||||
def add_node(self, node_id, **data):
|
||||
|
||||
@@ -2,7 +2,6 @@ import errno
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
from urllib.parse import urljoin
|
||||
|
||||
from routes import url_for
|
||||
@@ -36,16 +35,16 @@ def check_for_missing_tools(app, tool_panel_configs, latest_tool_migration_scrip
|
||||
'migrate', 'scripts',
|
||||
'%04d_tools.xml' % latest_tool_migration_script_number))
|
||||
# Parse the XML and load the file attributes for later checking against the proprietary tool_panel_config.
|
||||
migrated_tool_configs_dict = OrderedDict()
|
||||
migrated_tool_configs_dict = {}
|
||||
tree, error_message = xml_util.parse_xml(tools_xml_file_path)
|
||||
if tree is None:
|
||||
return False, OrderedDict()
|
||||
return False, {}
|
||||
root = tree.getroot()
|
||||
tool_shed = root.get('name')
|
||||
tool_shed_url = get_tool_shed_url_from_tool_shed_registry(app, tool_shed)
|
||||
# The default behavior is that the tool shed is down.
|
||||
tool_shed_accessible = False
|
||||
missing_tool_configs_dict = OrderedDict()
|
||||
missing_tool_configs_dict = {}
|
||||
if tool_shed_url:
|
||||
for elem in root:
|
||||
if elem.tag == 'repository':
|
||||
|
||||
@@ -36,7 +36,6 @@ then CycleError is raised, and the exception object supports
|
||||
many methods to help analyze and break the cycles. This requires
|
||||
a good deal more code than topsort itself!
|
||||
"""
|
||||
from collections import OrderedDict
|
||||
|
||||
|
||||
class CycleError(Exception):
|
||||
@@ -88,7 +87,7 @@ class CycleError(Exception):
|
||||
def get_preds(self):
|
||||
if self.preds is not None:
|
||||
return self.preds
|
||||
self.preds = preds = OrderedDict()
|
||||
self.preds = preds = {}
|
||||
remaining_elts = self.get_elements()
|
||||
for x in remaining_elts:
|
||||
preds[x] = []
|
||||
@@ -117,7 +116,7 @@ class CycleError(Exception):
|
||||
from random import choice
|
||||
x = choice(remaining_elts)
|
||||
answer = []
|
||||
index = OrderedDict()
|
||||
index = {}
|
||||
in_answer = index.has_key
|
||||
while not in_answer(x):
|
||||
index[x] = len(answer) # index of x in answer
|
||||
@@ -130,8 +129,8 @@ class CycleError(Exception):
|
||||
|
||||
|
||||
def _numpreds_and_successors_from_pairlist(pairlist):
|
||||
numpreds = OrderedDict() # elt -> # of predecessors
|
||||
successors = OrderedDict() # elt -> list of successors
|
||||
numpreds = {} # elt -> # of predecessors
|
||||
successors = {} # elt -> list of successors
|
||||
for first, second in pairlist:
|
||||
# make sure every elt is a key in numpreds
|
||||
if first not in numpreds:
|
||||
|
||||
@@ -29,7 +29,7 @@ class OrderedLoader(SafeLoader):
|
||||
def ordered_load(stream, merge_duplicate_keys=False):
|
||||
"""
|
||||
Parse the first YAML document in a stream and produce the corresponding
|
||||
Python object, using OrderedDicts instead of dicts.
|
||||
Python object.
|
||||
|
||||
If merge_duplicate_keys is True, merge the values of duplicate mapping keys
|
||||
into a list, as the uWSGI "dumb" YAML parser would do.
|
||||
@@ -38,7 +38,7 @@ def ordered_load(stream, merge_duplicate_keys=False):
|
||||
"""
|
||||
def construct_mapping(loader, node, deep=False):
|
||||
loader.flatten_mapping(node)
|
||||
mapping = OrderedDict()
|
||||
mapping = {}
|
||||
merged_duplicate = {}
|
||||
for key_node, value_node in node.value:
|
||||
key = loader.construct_object(key_node, deep=deep)
|
||||
|
||||
@@ -7,7 +7,6 @@ Lower level of visualization framework which does three main things:
|
||||
import logging
|
||||
import os
|
||||
import weakref
|
||||
from collections import OrderedDict
|
||||
|
||||
from galaxy.exceptions import ObjectNotFound
|
||||
from galaxy.util import (
|
||||
@@ -66,7 +65,7 @@ class VisualizationsRegistry:
|
||||
self.additional_template_paths = []
|
||||
self.directories = []
|
||||
self.skip_bad_plugins = skip_bad_plugins
|
||||
self.plugins = OrderedDict()
|
||||
self.plugins = {}
|
||||
self.directories = config_directories_from_setting(directories_setting, app.config.root)
|
||||
self._load_configuration()
|
||||
self._load_plugins()
|
||||
@@ -107,8 +106,6 @@ class VisualizationsRegistry:
|
||||
"""
|
||||
Search ``self.directories`` for potential plugins, load them, and cache
|
||||
in ``self.plugins``.
|
||||
:rtype: OrderedDict
|
||||
:returns: ``self.plugins``
|
||||
"""
|
||||
for plugin_path in self._find_plugins():
|
||||
try:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import logging
|
||||
import math
|
||||
from collections import OrderedDict
|
||||
from json import dumps, loads
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
@@ -492,7 +491,7 @@ class SharingStatusColumn(GridColumn):
|
||||
|
||||
def get_accepted_filters(self):
|
||||
""" Returns a list of accepted filters for this column. """
|
||||
accepted_filter_labels_and_vals = OrderedDict()
|
||||
accepted_filter_labels_and_vals = {}
|
||||
accepted_filter_labels_and_vals["private"] = "private"
|
||||
accepted_filter_labels_and_vals["shared"] = "shared"
|
||||
accepted_filter_labels_and_vals["accessible"] = "accessible"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import logging
|
||||
import math
|
||||
from collections import OrderedDict
|
||||
from json import dumps, loads
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
@@ -457,7 +456,7 @@ class SharingStatusColumn(GridColumn):
|
||||
|
||||
def get_accepted_filters(self):
|
||||
""" Returns a list of accepted filters for this column. """
|
||||
accepted_filter_labels_and_vals = OrderedDict()
|
||||
accepted_filter_labels_and_vals = {}
|
||||
accepted_filter_labels_and_vals["private"] = "private"
|
||||
accepted_filter_labels_and_vals["shared"] = "shared"
|
||||
accepted_filter_labels_and_vals["accessible"] = "accessible"
|
||||
|
||||
@@ -1413,8 +1413,10 @@ class SharableMixin:
|
||||
skipped = False
|
||||
class_name = self.manager.model_class.__name__
|
||||
item = self.get_object(trans, id, class_name, check_ownership=True, check_accessible=True, deleted=False)
|
||||
if payload and payload.get("action"):
|
||||
action = payload.get("action")
|
||||
actions = []
|
||||
if payload:
|
||||
actions += payload.get("action").split("-")
|
||||
for action in actions:
|
||||
if action == "make_accessible_via_link":
|
||||
self._make_item_accessible(trans.sa_session, item)
|
||||
if hasattr(item, "has_possible_members") and item.has_possible_members:
|
||||
|
||||
@@ -5,7 +5,6 @@ import copy
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
|
||||
from markupsafe import escape
|
||||
from sqlalchemy import (
|
||||
@@ -713,9 +712,9 @@ class UserAPIController(BaseAPIController, UsesTagsMixin, BaseUIController, Uses
|
||||
inputs.append({'type': 'section', 'title': filter_title, 'name': filter_type, 'expanded': True, 'inputs': filter_inputs})
|
||||
|
||||
def _get_filter_types(self, trans):
|
||||
return OrderedDict([('toolbox_tool_filters', {'title': 'Tools', 'config': trans.app.config.user_tool_filters}),
|
||||
('toolbox_section_filters', {'title': 'Sections', 'config': trans.app.config.user_tool_section_filters}),
|
||||
('toolbox_label_filters', {'title': 'Labels', 'config': trans.app.config.user_tool_label_filters})])
|
||||
return {'toolbox_tool_filters': {'title': 'Tools', 'config': trans.app.config.user_tool_filters},
|
||||
'toolbox_section_filters': {'title': 'Sections', 'config': trans.app.config.user_tool_section_filters},
|
||||
'toolbox_label_filters': {'title': 'Labels', 'config': trans.app.config.user_tool_label_filters}}
|
||||
|
||||
@expose_api
|
||||
def api_key(self, trans, id, payload=None, **kwd):
|
||||
|
||||
@@ -2817,7 +2817,7 @@ mapping:
|
||||
required: false
|
||||
default: directory
|
||||
desc: |
|
||||
Determines how metadata will be set. Valid values are `directory`, `extended` and `legacy`.
|
||||
Determines how metadata will be set. Valid values are `directory` and `extended`.
|
||||
In extended mode jobs will decide if a tool run failed, the object stores
|
||||
configuration is serialized and made available to the job and is used for
|
||||
writing output datasets to the object store as part of the job and dynamic
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import imp
|
||||
import logging
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from sqlalchemy import and_, false, or_
|
||||
@@ -882,7 +881,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP
|
||||
def review_tool_migration_stages(self, trans, **kwd):
|
||||
message = escape(util.restore_text(kwd.get('message', '')))
|
||||
status = util.restore_text(kwd.get('status', 'done'))
|
||||
migration_stages_dict = OrderedDict()
|
||||
migration_stages_dict = {}
|
||||
# FIXME: this isn't valid in an installed context
|
||||
migration_scripts_dir = os.path.abspath(os.path.join(trans.app.config.root, 'lib', 'galaxy', 'tool_shed', 'galaxy_install', 'migrate', 'versions'))
|
||||
modules = os.listdir(migration_scripts_dir)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
|
||||
from markupsafe import escape
|
||||
from sqlalchemy import (
|
||||
@@ -485,7 +484,7 @@ class HistoryController(BaseUIController, SharableMixin, UsesAnnotations, UsesIt
|
||||
items = []
|
||||
# First go through and group hdas by job, if there is no job they get
|
||||
# added directly to items
|
||||
jobs = OrderedDict()
|
||||
jobs = {}
|
||||
for hda in history.active_datasets:
|
||||
if hda.visible is False:
|
||||
continue
|
||||
@@ -509,7 +508,7 @@ class HistoryController(BaseUIController, SharableMixin, UsesAnnotations, UsesIt
|
||||
else:
|
||||
jobs[job] = [(hda, None)]
|
||||
# Second, go through the jobs and connect to workflows
|
||||
wf_invocations = OrderedDict()
|
||||
wf_invocations = {}
|
||||
for job, hdas in jobs.items():
|
||||
# Job is attached to a workflow step, follow it to the
|
||||
# workflow_invocation and group
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import collections
|
||||
import logging
|
||||
|
||||
import sqlalchemy as sa
|
||||
@@ -111,7 +110,7 @@ class History(BaseUIController):
|
||||
users = users[:user_cutoff]
|
||||
|
||||
# to keep ordered
|
||||
data = collections.OrderedDict()
|
||||
data = {}
|
||||
for user in users:
|
||||
dataset = datasets.get(user, [0, 0])
|
||||
history = histories.get(user, 0)
|
||||
@@ -172,8 +171,7 @@ class History(BaseUIController):
|
||||
possible_status = {"ok": 0, "upload": 1, "paused": 2, "queued": 3, "error": 4, "discarded": 5}
|
||||
number_of_possible_status = len(possible_status) + 1 # + 1 to handle unknown status!
|
||||
|
||||
# to keep ordered
|
||||
datas = collections.OrderedDict()
|
||||
datas = {}
|
||||
for no, name in enumerate(names):
|
||||
if name not in datas:
|
||||
if user_cutoff > 0:
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import collections
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
@@ -85,7 +84,7 @@ class Tools(BaseUIController):
|
||||
lambda v: tools_and_jobs_ok.get(v, 0),
|
||||
lambda v: tools_and_jobs_error.get(v, 0))
|
||||
|
||||
data = collections.OrderedDict()
|
||||
data = {}
|
||||
|
||||
# select count(id), tool_id from job where state='ok' group by tool_id;
|
||||
tools_and_jobs_ok = sa.select((galaxy.model.Job.table.c.tool_id .label('tool'),
|
||||
@@ -139,7 +138,7 @@ class Tools(BaseUIController):
|
||||
if tool is None:
|
||||
raise TypeError("Tool can't be None")
|
||||
|
||||
data = collections.OrderedDict()
|
||||
data = {}
|
||||
|
||||
# select count(id), create_time from job where state='ok' and tool_id=$tool group by date;
|
||||
date_and_jobs_ok = sa.select((sa.func.date(galaxy.model.Job.table.c.create_time).label('date'),
|
||||
@@ -194,7 +193,7 @@ class Tools(BaseUIController):
|
||||
color = True if kwd.get("color", '') == "True" else False
|
||||
|
||||
data = {}
|
||||
ordered_data = collections.OrderedDict()
|
||||
ordered_data = {}
|
||||
|
||||
sort_keys = (
|
||||
lambda v: v.lower(),
|
||||
@@ -260,7 +259,7 @@ class Tools(BaseUIController):
|
||||
if tool is None:
|
||||
raise ValueError("Tool can't be None")
|
||||
|
||||
ordered_data = collections.OrderedDict()
|
||||
ordered_data = {}
|
||||
sort_keys = [(lambda v, i=i: v[i]) for i in range(4)]
|
||||
|
||||
jobs_times = sa.select((sa.func.date_trunc('month', galaxy.model.Job.table.c.create_time).label('date'),
|
||||
@@ -314,7 +313,7 @@ class Tools(BaseUIController):
|
||||
else:
|
||||
counter[error[0]] = [1, error[1]]
|
||||
|
||||
data = collections.OrderedDict()
|
||||
data = {}
|
||||
keys = list(counter.keys())
|
||||
if cutoff:
|
||||
keys = keys[:cutoff]
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
histories.
|
||||
"""
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
|
||||
from galaxy import exceptions, model
|
||||
from galaxy.tool_util.parser import ToolOutputCollectionPart
|
||||
@@ -196,7 +195,7 @@ class WorkflowSummary:
|
||||
history = trans.get_history()
|
||||
self.history = history
|
||||
self.warnings = set()
|
||||
self.jobs = OrderedDict()
|
||||
self.jobs = {}
|
||||
self.job_id2representative_job = {} # map a non-fake job id to its representative job
|
||||
self.implicit_map_jobs = []
|
||||
self.collection_types = {}
|
||||
|
||||
@@ -4,7 +4,7 @@ Modules used in building workflows
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
from collections import defaultdict, OrderedDict
|
||||
from collections import defaultdict
|
||||
|
||||
import packaging.version
|
||||
|
||||
@@ -707,7 +707,7 @@ class InputDataModule(InputModule):
|
||||
def get_inputs(self):
|
||||
parameter_def = self._parse_state_into_dict()
|
||||
optional = parameter_def["optional"]
|
||||
inputs = OrderedDict()
|
||||
inputs = {}
|
||||
inputs["optional"] = optional_param(optional)
|
||||
inputs["format"] = format_param(self.trans, parameter_def.get("format"))
|
||||
return inputs
|
||||
@@ -730,7 +730,7 @@ class InputDataCollectionModule(InputModule):
|
||||
{"value": "list:paired", "label": "List of Dataset Pairs"},
|
||||
]
|
||||
input_collection_type = TextToolParameter(None, collection_type_source)
|
||||
inputs = OrderedDict()
|
||||
inputs = {}
|
||||
inputs["collection_type"] = input_collection_type
|
||||
inputs["optional"] = optional_param(optional)
|
||||
inputs["format"] = format_param(self.trans, parameter_def.get("format"))
|
||||
@@ -859,7 +859,7 @@ class InputParameterModule(WorkflowModule):
|
||||
|
||||
when_this_type = ConditionalWhen()
|
||||
when_this_type.value = param_type
|
||||
when_this_type.inputs = OrderedDict()
|
||||
when_this_type.inputs = {}
|
||||
when_this_type.inputs["optional"] = optional_cond
|
||||
|
||||
specify_default_checked = "default" in parameter_def
|
||||
@@ -871,24 +871,24 @@ class InputParameterModule(WorkflowModule):
|
||||
|
||||
when_specify_default_true = ConditionalWhen()
|
||||
when_specify_default_true.value = "true"
|
||||
when_specify_default_true.inputs = OrderedDict()
|
||||
when_specify_default_true.inputs = {}
|
||||
when_specify_default_true.inputs["default"] = input_default_value
|
||||
|
||||
when_specify_default_false = ConditionalWhen()
|
||||
when_specify_default_false.value = "false"
|
||||
when_specify_default_false.inputs = OrderedDict()
|
||||
when_specify_default_false.inputs = {}
|
||||
|
||||
specify_default_cond_cases = [when_specify_default_true, when_specify_default_false]
|
||||
specify_default_cond.cases = specify_default_cond_cases
|
||||
|
||||
when_true = ConditionalWhen()
|
||||
when_true.value = "true"
|
||||
when_true.inputs = OrderedDict()
|
||||
when_true.inputs = {}
|
||||
when_true.inputs["default"] = specify_default_cond
|
||||
|
||||
when_false = ConditionalWhen()
|
||||
when_false.value = "false"
|
||||
when_false.inputs = OrderedDict()
|
||||
when_false.inputs = {}
|
||||
|
||||
optional_cases = [when_true, when_false]
|
||||
optional_cond.cases = optional_cases
|
||||
@@ -916,19 +916,19 @@ class InputParameterModule(WorkflowModule):
|
||||
|
||||
when_restrict_none = ConditionalWhen()
|
||||
when_restrict_none.value = "none"
|
||||
when_restrict_none.inputs = OrderedDict()
|
||||
when_restrict_none.inputs = {}
|
||||
|
||||
when_restrict_connections = ConditionalWhen()
|
||||
when_restrict_connections.value = "onConnections"
|
||||
when_restrict_connections.inputs = OrderedDict()
|
||||
when_restrict_connections.inputs = {}
|
||||
|
||||
when_restrict_static_restrictions = ConditionalWhen()
|
||||
when_restrict_static_restrictions.value = "staticRestrictions"
|
||||
when_restrict_static_restrictions.inputs = OrderedDict()
|
||||
when_restrict_static_restrictions.inputs = {}
|
||||
|
||||
when_restrict_static_suggestions = ConditionalWhen()
|
||||
when_restrict_static_suggestions.value = "staticSuggestions"
|
||||
when_restrict_static_suggestions.inputs = OrderedDict()
|
||||
when_restrict_static_suggestions.inputs = {}
|
||||
|
||||
# Repeats don't work - so use common separated list for now.
|
||||
|
||||
@@ -953,7 +953,7 @@ class InputParameterModule(WorkflowModule):
|
||||
cases.append(when_this_type)
|
||||
|
||||
parameter_type_cond.cases = cases
|
||||
return OrderedDict([("parameter_definition", parameter_type_cond)])
|
||||
return {"parameter_definition": parameter_type_cond}
|
||||
|
||||
def get_runtime_inputs(self, connections=None, **kwds):
|
||||
parameter_def = self._parse_state_into_dict()
|
||||
@@ -1445,12 +1445,10 @@ class ToolModule(WorkflowModule):
|
||||
if not collection_type and tool_output.structure.collection_type_from_rules:
|
||||
rule_param = tool_output.structure.collection_type_from_rules
|
||||
if rule_param in self.state.inputs:
|
||||
rule_json_str = self.state.inputs[rule_param]
|
||||
if rule_json_str: # initialized to None...
|
||||
rules = rule_json_str
|
||||
if rules:
|
||||
rule_set = RuleSet(rules)
|
||||
collection_type = rule_set.collection_type
|
||||
rules = self.state.inputs[rule_param]
|
||||
if rules:
|
||||
rule_set = RuleSet(rules)
|
||||
collection_type = rule_set.collection_type
|
||||
extra_kwds["collection_type"] = collection_type
|
||||
extra_kwds["collection_type_source"] = tool_output.structure.collection_type_source
|
||||
formats = ['input'] # TODO: fix
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import logging
|
||||
import uuid
|
||||
from collections import OrderedDict
|
||||
|
||||
from galaxy import model
|
||||
from galaxy.util import ExecutionTimer
|
||||
@@ -274,7 +273,7 @@ STEP_OUTPUT_DELAYED = object()
|
||||
class WorkflowProgress:
|
||||
|
||||
def __init__(self, workflow_invocation, inputs_by_step_id, module_injector, param_map, jobs_per_scheduling_iteration=-1):
|
||||
self.outputs = OrderedDict()
|
||||
self.outputs = {}
|
||||
self.module_injector = module_injector
|
||||
self.workflow_invocation = workflow_invocation
|
||||
self.inputs_by_step_id = inputs_by_step_id
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import copy
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
|
||||
from galaxy.util import asbool
|
||||
from galaxy.web import url_for
|
||||
@@ -71,8 +70,8 @@ class RepositoryDependencyAttributeHandler:
|
||||
if len(sub_elems) > 0:
|
||||
# At this point, a <repository> tag will point only to a package.
|
||||
# <package name="xorg_macros" version="1.17.1" />
|
||||
# Coerce the list to an OrderedDict().
|
||||
sub_elements = OrderedDict()
|
||||
# Coerce the list to dict.
|
||||
sub_elements = {}
|
||||
packages = []
|
||||
for sub_elem in sub_elems:
|
||||
sub_elem_type = sub_elem.tag
|
||||
@@ -88,7 +87,7 @@ class RepositoryDependencyAttributeHandler:
|
||||
# We're exporting the repository, so eliminate all toolshed and changeset_revision attributes
|
||||
# from the <repository> tag.
|
||||
if toolshed or changeset_revision:
|
||||
attributes = OrderedDict()
|
||||
attributes = {}
|
||||
attributes['name'] = name
|
||||
attributes['owner'] = owner
|
||||
prior_installation_required = elem.get('prior_installation_required')
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import json
|
||||
import logging
|
||||
|
||||
from markupsafe import escape as escape_html
|
||||
@@ -181,7 +180,7 @@ class RepositoryGrid(grids.Grid):
|
||||
class EmailAlertsColumn(grids.TextColumn):
|
||||
|
||||
def get_value(self, trans, grid, repository):
|
||||
if trans.user and repository.email_alerts and trans.user.email in json.loads(repository.email_alerts):
|
||||
if trans.user and trans.user.email in repository.email_alerts:
|
||||
return 'yes'
|
||||
return ''
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
|
||||
from . import (
|
||||
repository_suite_definition,
|
||||
@@ -13,7 +12,7 @@ log = logging.getLogger(__name__)
|
||||
class Registry:
|
||||
|
||||
def __init__(self):
|
||||
self.repository_types_by_label = OrderedDict()
|
||||
self.repository_types_by_label = {}
|
||||
self.repository_types_by_label['unrestricted'] = unrestricted.Unrestricted()
|
||||
self.repository_types_by_label['repository_suite_definition'] = repository_suite_definition.RepositorySuiteDefinition()
|
||||
self.repository_types_by_label['tool_dependency_definition'] = tool_dependency_definition.ToolDependencyDefinition()
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import bz2
|
||||
import gzip
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
@@ -72,8 +71,7 @@ def check_file_contents_for_email_alerts(app):
|
||||
admin_users = app.config.get("admin_users", "").split(",")
|
||||
for repository in sa_session.query(app.model.Repository) \
|
||||
.filter(app.model.Repository.table.c.email_alerts != null()):
|
||||
email_alerts = json.loads(repository.email_alerts)
|
||||
for user_email in email_alerts:
|
||||
for user_email in repository.email_alerts:
|
||||
if user_email in admin_users:
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
|
||||
from sqlalchemy import and_
|
||||
|
||||
@@ -74,7 +73,7 @@ def get_previous_repository_reviews(app, repository, changeset_revision):
|
||||
"""
|
||||
repo = repository.hg_repo
|
||||
reviewed_revision_hashes = [review.changeset_revision for review in repository.reviews]
|
||||
previous_reviews_dict = OrderedDict()
|
||||
previous_reviews_dict = {}
|
||||
for changeset in hg_util.reversed_upper_bounded_changelog(repo, changeset_revision):
|
||||
previous_changeset_revision = str(repo[changeset])
|
||||
if previous_changeset_revision in reviewed_revision_hashes:
|
||||
|
||||
@@ -385,7 +385,7 @@ def handle_email_alerts(app, host, repository, content_alert_str='', new_repo_al
|
||||
email_alerts.append(user.email)
|
||||
else:
|
||||
subject = "Galaxy tool shed update alert for repository named %s" % str(repository.name)
|
||||
email_alerts = json.loads(repository.email_alerts)
|
||||
email_alerts = repository.email_alerts
|
||||
for email in email_alerts:
|
||||
to = email.strip()
|
||||
# Send it
|
||||
|
||||
@@ -1658,10 +1658,6 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings):
|
||||
alerts = kwd.get('alerts', '')
|
||||
alerts_checked = CheckboxField.is_checked(alerts)
|
||||
category_ids = util.listify(kwd.get('category_id', ''))
|
||||
if repository.email_alerts:
|
||||
email_alerts = json.loads(repository.email_alerts)
|
||||
else:
|
||||
email_alerts = []
|
||||
allow_push = kwd.get('allow_push', '')
|
||||
error = False
|
||||
user = trans.user
|
||||
@@ -1714,14 +1710,12 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings):
|
||||
elif kwd.get('receive_email_alerts_button', False):
|
||||
flush_needed = False
|
||||
if alerts_checked:
|
||||
if user.email not in email_alerts:
|
||||
email_alerts.append(user.email)
|
||||
repository.email_alerts = json.dumps(email_alerts)
|
||||
if user.email not in repository.email_alerts:
|
||||
repository.email_alerts.append(user.email)
|
||||
flush_needed = True
|
||||
else:
|
||||
if user.email in email_alerts:
|
||||
email_alerts.remove(user.email)
|
||||
repository.email_alerts = json.dumps(email_alerts)
|
||||
if user.email in repository.email_alerts:
|
||||
repository.email_alerts.remove(user.email)
|
||||
flush_needed = True
|
||||
if flush_needed:
|
||||
trans.sa_session.add(repository)
|
||||
@@ -1743,7 +1737,7 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings):
|
||||
for obj in options:
|
||||
label = obj.username
|
||||
allow_push_select_field.add_option(label, trans.security.encode_id(obj.id))
|
||||
checked = alerts_checked or user.email in email_alerts
|
||||
checked = alerts_checked or user.email in repository.email_alerts
|
||||
alerts_check_box = CheckboxField('alerts', value=checked)
|
||||
changeset_revision_select_field = grids_util.build_changeset_revision_select_field(trans,
|
||||
repository,
|
||||
@@ -2273,19 +2267,14 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings):
|
||||
flush_needed = False
|
||||
for repository_id in repository_ids:
|
||||
repository = repository_util.get_repository_in_tool_shed(trans.app, repository_id)
|
||||
if repository.email_alerts:
|
||||
email_alerts = json.loads(repository.email_alerts)
|
||||
else:
|
||||
email_alerts = []
|
||||
email_alerts = repository.email_alerts
|
||||
if user.email in email_alerts:
|
||||
email_alerts.remove(user.email)
|
||||
repository.email_alerts = json.dumps(email_alerts)
|
||||
trans.sa_session.add(repository)
|
||||
flush_needed = True
|
||||
total_alerts_removed += 1
|
||||
else:
|
||||
email_alerts.append(user.email)
|
||||
repository.email_alerts = json.dumps(email_alerts)
|
||||
trans.sa_session.add(repository)
|
||||
flush_needed = True
|
||||
total_alerts_added += 1
|
||||
@@ -2568,10 +2557,7 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings):
|
||||
display_reviews = kwd.get('display_reviews', False)
|
||||
alerts = kwd.get('alerts', '')
|
||||
alerts_checked = CheckboxField.is_checked(alerts)
|
||||
if repository.email_alerts:
|
||||
email_alerts = json.loads(repository.email_alerts)
|
||||
else:
|
||||
email_alerts = []
|
||||
email_alerts = repository.email_alerts
|
||||
repository_dependencies = None
|
||||
user = trans.user
|
||||
if user and kwd.get('receive_email_alerts_button', False):
|
||||
@@ -2579,12 +2565,10 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings):
|
||||
if alerts_checked:
|
||||
if user.email not in email_alerts:
|
||||
email_alerts.append(user.email)
|
||||
repository.email_alerts = json.dumps(email_alerts)
|
||||
flush_needed = True
|
||||
else:
|
||||
if user.email in email_alerts:
|
||||
email_alerts.remove(user.email)
|
||||
repository.email_alerts = json.dumps(email_alerts)
|
||||
flush_needed = True
|
||||
if flush_needed:
|
||||
trans.sa_session.add(repository)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
|
||||
from sqlalchemy import (
|
||||
and_,
|
||||
@@ -240,7 +239,7 @@ class RepositoryReviewController(BaseUIController, ratings_util.ItemRatings):
|
||||
status = kwd.get('status', 'done')
|
||||
review_id = kwd.get('id', None)
|
||||
review = review_util.get_review(trans.app, review_id)
|
||||
components_dict = OrderedDict()
|
||||
components_dict = {}
|
||||
for component in review_util.get_components(trans.app):
|
||||
components_dict[component.name] = dict(component=component, component_review=None)
|
||||
repository = review.repository
|
||||
@@ -487,7 +486,7 @@ class RepositoryReviewController(BaseUIController, ratings_util.ItemRatings):
|
||||
repo = repository.hg_repo
|
||||
metadata_revision_hashes = [metadata_revision.changeset_revision for metadata_revision in repository.metadata_revisions]
|
||||
reviewed_revision_hashes = [review.changeset_revision for review in repository.reviews]
|
||||
reviews_dict = OrderedDict()
|
||||
reviews_dict = {}
|
||||
for changeset in hg_util.get_reversed_changelog_changesets(repo):
|
||||
changeset_revision = str(repo[changeset])
|
||||
if changeset_revision in metadata_revision_hashes or changeset_revision in reviewed_revision_hashes:
|
||||
|
||||
@@ -118,7 +118,7 @@ Repository.table = Table("repository", metadata,
|
||||
Column("user_id", Integer, ForeignKey("galaxy_user.id"), index=True),
|
||||
Column("private", Boolean, default=False),
|
||||
Column("deleted", Boolean, index=True, default=False),
|
||||
Column("email_alerts", JSONType, nullable=True),
|
||||
Column("email_alerts", JSONType, nullable=True, default=list),
|
||||
Column("times_downloaded", Integer),
|
||||
Column("deprecated", Boolean, default=False))
|
||||
|
||||
|
||||
@@ -13,5 +13,6 @@ pysam
|
||||
social-auth-core[openidconnect]==3.3.0
|
||||
SQLAlchemy
|
||||
sqlalchemy-migrate
|
||||
sqlalchemy-mutable
|
||||
sqlalchemy-utils
|
||||
WebOb
|
||||
|
||||
@@ -64,6 +64,7 @@ social-auth-core = {version = "==3.3.0", extras = ["openidconnect"]}
|
||||
sortedcontainers = "*"
|
||||
SQLAlchemy = "*"
|
||||
sqlalchemy-migrate = "*"
|
||||
sqlalchemy-mutable = "*"
|
||||
SQLAlchemy-Utils = "!=0.36.8" # https://github.com/kvesteri/sqlalchemy-utils/issues/462
|
||||
sqlitedict = "*"
|
||||
sqlparse = "*"
|
||||
|
||||
@@ -273,6 +273,15 @@ def test_hierarchical_store():
|
||||
_assert_key_has_value(as_dict, "type", "hierarchical")
|
||||
|
||||
|
||||
def test_concrete_name_without_objectstore_id():
|
||||
for config_str in [HIERARCHICAL_TEST_CONFIG, HIERARCHICAL_TEST_CONFIG_YAML]:
|
||||
with TestConfig(config_str) as (directory, object_store):
|
||||
files1_desc = object_store.get_concrete_store_description_markdown(MockDataset(3))
|
||||
files1_name = object_store.get_concrete_store_name(MockDataset(3))
|
||||
assert files1_desc is None
|
||||
assert files1_name is None
|
||||
|
||||
|
||||
MIXED_STORE_BY_HIERARCHICAL_TEST_CONFIG = """<?xml version="1.0"?>
|
||||
<object_store type="hierarchical">
|
||||
<backends>
|
||||
|
||||
@@ -33,10 +33,6 @@ class MetadataTestCase(unittest.TestCase, tools_support.UsesApp, tools_support.U
|
||||
super().tearDown()
|
||||
self.metadata_compute_strategy = None
|
||||
|
||||
def test_simple_output_legacy(self):
|
||||
self.app.config.metadata_strategy = "legacy"
|
||||
self._test_simple_output()
|
||||
|
||||
def test_simple_output_directory(self):
|
||||
self.app.config.metadata_strategy = "directory"
|
||||
self._test_simple_output()
|
||||
@@ -66,10 +62,6 @@ class MetadataTestCase(unittest.TestCase, tools_support.UsesApp, tools_support.U
|
||||
assert output_dataset.metadata.data_lines == 2
|
||||
assert output_dataset.metadata.sequences == 1
|
||||
|
||||
def test_primary_dataset_output_extension_legacy(self):
|
||||
self.app.config.metadata_strategy = "legacy"
|
||||
self._test_primary_dataset_output_extension()
|
||||
|
||||
def test_primary_dataset_output_extension_directory(self):
|
||||
self.app.config.metadata_strategy = "directory"
|
||||
self._test_primary_dataset_output_extension()
|
||||
@@ -99,10 +91,6 @@ class MetadataTestCase(unittest.TestCase, tools_support.UsesApp, tools_support.U
|
||||
assert output_dataset.metadata.data_lines == 2
|
||||
assert output_dataset.metadata.sequences == 1
|
||||
|
||||
def test_primary_dataset_output_metadata_override_legacy(self):
|
||||
self.app.config.metadata_strategy = "legacy"
|
||||
self._test_primary_dataset_output_metadata_override()
|
||||
|
||||
def test_primary_dataset_output_metadata_override_directory(self):
|
||||
self.app.config.metadata_strategy = "directory"
|
||||
self._test_primary_dataset_output_metadata_override()
|
||||
|
||||
@@ -21,17 +21,6 @@ def test_strip_control_characters():
|
||||
assert util.strip_control_characters(s) == 'bla'
|
||||
|
||||
|
||||
def test_strip_control_characters_nested():
|
||||
s = '\x00bla'
|
||||
stripped_s = 'bla'
|
||||
list_ = [s]
|
||||
t = (s, 'blub')
|
||||
d = {42: s}
|
||||
assert util.strip_control_characters_nested(list_)[0] == stripped_s
|
||||
assert util.strip_control_characters_nested(t)[0] == stripped_s
|
||||
assert util.strip_control_characters_nested(d)[42] == stripped_s
|
||||
|
||||
|
||||
def test_parse_xml_string():
|
||||
section = util.parse_xml_string(SECTION_XML)
|
||||
_verify_section(section)
|
||||
|
||||
Reference in New Issue
Block a user