From 22e76016539c90854cc86b8013cff4c3e4c383a9 Mon Sep 17 00:00:00 2001 From: Dannon Baker Date: Tue, 2 Mar 2021 15:30:27 -0500 Subject: [PATCH 1/7] First pass fstring conversion --- lib/galaxy/actions/admin.py | 18 ++-- lib/galaxy/actions/library.py | 14 +-- lib/galaxy/app.py | 2 +- lib/galaxy/auth/__init__.py | 6 +- lib/galaxy/auth/providers/alwaysreject.py | 2 +- lib/galaxy/auth/providers/ldap_ad.py | 2 +- lib/galaxy/auth/providers/localdb.py | 2 +- lib/galaxy/auth/providers/pam_auth.py | 8 +- lib/galaxy/auth/util.py | 2 +- lib/galaxy/authnz/custos_authnz.py | 14 +-- lib/galaxy/authnz/psa_authnz.py | 2 +- lib/galaxy/config/__init__.py | 28 +++--- lib/galaxy/config/config_manage.py | 32 +++--- lib/galaxy/config/script.py | 8 +- lib/galaxy/containers/__init__.py | 10 +- lib/galaxy/containers/docker.py | 8 +- lib/galaxy/containers/docker_model.py | 6 +- lib/galaxy/datatypes/annotation.py | 4 +- lib/galaxy/datatypes/anvio.py | 4 +- lib/galaxy/datatypes/assembly.py | 20 ++-- lib/galaxy/datatypes/binary.py | 88 ++++++++--------- lib/galaxy/datatypes/blast.py | 20 ++-- .../datatypes/constructive_solid_geometry.py | 8 +- .../datatypes/converters/cram_to_bam.py | 2 +- .../converters/fasta_to_tabular_converter.py | 2 +- .../datatypes/converters/fastq_to_fqtoc.py | 2 +- .../fastqsolexa_to_fasta_converter.py | 6 +- .../fastqsolexa_to_qual_converter.py | 10 +- .../converters/gff_to_bed_converter.py | 2 +- .../converters/interval_to_bed_converter.py | 6 +- .../interval_to_bedstrict_converter.py | 8 +- .../converters/lped_to_fped_converter.py | 10 +- .../converters/lped_to_pbed_converter.py | 8 +- .../converters/maf_to_fasta_converter.py | 2 +- .../converters/maf_to_interval_converter.py | 2 +- .../converters/pbed_ldreduced_converter.py | 6 +- .../converters/pbed_to_lped_converter.py | 4 +- .../picard_interval_list_to_bed6_converter.py | 2 +- .../ref_to_seq_taxonomy_converter.py | 2 +- lib/galaxy/datatypes/data.py | 32 +++--- lib/galaxy/datatypes/dataproviders/base.py | 2 +- lib/galaxy/datatypes/dataproviders/dataset.py | 6 +- .../datatypes/dataproviders/exceptions.py | 6 +- .../datatypes/dataproviders/external.py | 14 +-- .../display_applications/application.py | 10 +- .../display_applications/parameters.py | 8 +- lib/galaxy/datatypes/genetics.py | 38 +++---- lib/galaxy/datatypes/gis.py | 2 +- lib/galaxy/datatypes/images.py | 26 ++--- lib/galaxy/datatypes/interval.py | 14 +-- lib/galaxy/datatypes/isa.py | 24 ++--- lib/galaxy/datatypes/molecules.py | 32 +++--- lib/galaxy/datatypes/mothur.py | 6 +- lib/galaxy/datatypes/msa.py | 12 +-- lib/galaxy/datatypes/ngsindex.py | 6 +- lib/galaxy/datatypes/phylip.py | 2 +- lib/galaxy/datatypes/plant_tribes.py | 6 +- lib/galaxy/datatypes/proteomics.py | 10 +- lib/galaxy/datatypes/registry.py | 38 +++---- lib/galaxy/datatypes/sequence.py | 30 +++--- lib/galaxy/datatypes/sniff.py | 2 +- lib/galaxy/datatypes/tabular.py | 28 +++--- lib/galaxy/datatypes/text.py | 18 ++-- lib/galaxy/datatypes/util/gff_util.py | 4 +- lib/galaxy/datatypes/util/maf_utilities.py | 6 +- lib/galaxy/files/__init__.py | 6 +- lib/galaxy/files/sources/__init__.py | 2 +- lib/galaxy/files/sources/posix.py | 4 +- lib/galaxy/forms/forms.py | 2 +- lib/galaxy/job_execution/datasets.py | 2 +- lib/galaxy/job_execution/output_collect.py | 4 +- lib/galaxy/job_execution/ports/view.py | 2 +- lib/galaxy/job_metrics/collectl/cli.py | 22 ++--- lib/galaxy/job_metrics/collectl/processes.py | 6 +- .../job_metrics/instrumenters/collectl.py | 13 +-- lib/galaxy/job_metrics/instrumenters/core.py | 8 +- .../job_metrics/instrumenters/cpuinfo.py | 4 +- lib/galaxy/job_metrics/instrumenters/env.py | 2 +- .../job_metrics/instrumenters/hostname.py | 2 +- .../job_metrics/instrumenters/meminfo.py | 2 +- lib/galaxy/job_metrics/instrumenters/uname.py | 2 +- lib/galaxy/jobs/__init__.py | 32 +++--- lib/galaxy/jobs/actions/post.py | 16 +-- lib/galaxy/jobs/command_factory.py | 15 +-- lib/galaxy/jobs/dynamic_tool_destination.py | 6 +- lib/galaxy/jobs/handler.py | 26 ++--- lib/galaxy/jobs/manager.py | 2 +- lib/galaxy/jobs/mapper.py | 4 +- lib/galaxy/jobs/runners/__init__.py | 24 ++--- lib/galaxy/jobs/runners/cli.py | 4 +- lib/galaxy/jobs/runners/condor.py | 12 +-- lib/galaxy/jobs/runners/drmaa.py | 26 ++--- lib/galaxy/jobs/runners/godocker.py | 2 +- lib/galaxy/jobs/runners/kubernetes.py | 4 +- lib/galaxy/jobs/runners/local.py | 4 +- lib/galaxy/jobs/runners/pbs.py | 26 +++-- lib/galaxy/jobs/runners/pulsar.py | 20 ++-- .../jobs/runners/state_handlers/_safe_eval.py | 2 +- .../jobs/runners/state_handlers/resubmit.py | 4 +- lib/galaxy/jobs/runners/tasks.py | 10 +- lib/galaxy/jobs/runners/univa.py | 12 +-- lib/galaxy/jobs/runners/util/cli/__init__.py | 8 +- lib/galaxy/jobs/runners/util/cli/job/lsf.py | 10 +- lib/galaxy/jobs/runners/util/cli/job/slurm.py | 8 +- .../jobs/runners/util/cli/job/torque.py | 10 +- .../jobs/runners/util/condor/__init__.py | 2 +- lib/galaxy/jobs/runners/util/env.py | 2 +- .../jobs/runners/util/job_script/__init__.py | 2 +- lib/galaxy/jobs/runners/util/sudo.py | 2 +- lib/galaxy/jobs/splitters/multi.py | 16 +-- lib/galaxy/managers/base.py | 10 +- lib/galaxy/managers/citations.py | 4 +- lib/galaxy/managers/cloud.py | 10 +- lib/galaxy/managers/collections.py | 8 +- lib/galaxy/managers/collections_util.py | 2 +- lib/galaxy/managers/datasets.py | 4 +- lib/galaxy/managers/folders.py | 2 +- lib/galaxy/managers/history_contents.py | 4 +- lib/galaxy/managers/interactivetool.py | 14 +-- lib/galaxy/managers/jobs.py | 6 +- lib/galaxy/managers/library_datasets.py | 2 +- lib/galaxy/managers/licenses.py | 4 +- lib/galaxy/managers/markdown_util.py | 32 +++--- lib/galaxy/managers/pages.py | 24 ++--- lib/galaxy/managers/secured.py | 4 +- lib/galaxy/managers/taggable.py | 4 +- lib/galaxy/managers/users.py | 8 +- lib/galaxy/managers/workflows.py | 22 ++--- lib/galaxy/metadata/__init__.py | 6 +- lib/galaxy/metadata/set_metadata.py | 18 ++-- lib/galaxy/model/__init__.py | 54 +++++----- lib/galaxy/model/database_heartbeat.py | 2 +- .../model/dataset_collections/registry.py | 2 +- .../model/dataset_collections/structure.py | 6 +- .../dataset_collections/type_description.py | 4 +- lib/galaxy/model/item_attrs.py | 8 +- lib/galaxy/model/metadata.py | 6 +- lib/galaxy/model/migrate/check.py | 14 +-- .../versions/0004_indexes_and_defaults.py | 4 +- ...column_to_library_template_assoc_tables.py | 6 +- ...column_to_library_template_assoc_tables.py | 4 +- ...isualization_sharing_tagging_annotating.py | 6 +- .../0048_dataset_instance_state_column.py | 2 +- .../0051_imported_col_for_jobs_table.py | 2 +- .../versions/0060_history_archive_import.py | 2 +- .../versions/0067_populate_sequencer_table.py | 4 +- ..._purged_column_to_library_dataset_table.py | 4 +- .../0076_fix_form_values_data_corruption.py | 10 +- ..._add_tool_shed_repository_table_columns.py | 4 +- ..._add_installed_changeset_revison_column.py | 4 +- .../0089_add_object_store_id_columns.py | 2 +- ..._add_tool_shed_repository_table_columns.py | 4 +- .../migrate/versions/0096_openid_provider.py | 2 +- ..._available_col_add_tool_shed_status_col.py | 2 +- .../0160_hda_set_deleted_if_purged_again.py | 2 +- lib/galaxy/model/migrate/versions/util.py | 10 +- lib/galaxy/model/orm/engine_factory.py | 2 +- lib/galaxy/model/orm/scripts.py | 4 +- lib/galaxy/model/search.py | 30 +++--- lib/galaxy/model/security.py | 10 +- lib/galaxy/model/store/__init__.py | 10 +- lib/galaxy/model/store/discover.py | 2 +- lib/galaxy/model/tags.py | 4 +- .../model/tool_shed_install/__init__.py | 2 +- .../model/tool_shed_install/migrate/check.py | 2 +- lib/galaxy/objectstore/__init__.py | 18 ++-- lib/galaxy/objectstore/azure_blob.py | 10 +- lib/galaxy/objectstore/cloud.py | 6 +- lib/galaxy/objectstore/irods.py | 4 +- lib/galaxy/objectstore/pithos.py | 21 ++-- lib/galaxy/objectstore/s3.py | 6 +- lib/galaxy/objectstore/s3_multipart_upload.py | 8 +- lib/galaxy/openid/providers.py | 6 +- lib/galaxy/queue_worker.py | 12 +-- lib/galaxy/queues.py | 6 +- lib/galaxy/security/__init__.py | 2 +- lib/galaxy/security/passwords.py | 2 +- lib/galaxy/security/validate_user_input.py | 2 +- lib/galaxy/selenium/components.py | 10 +- lib/galaxy/selenium/has_driver.py | 28 +++--- lib/galaxy/selenium/navigates_galaxy.py | 74 +++++++------- .../galaxy_install/install_manager.py | 12 +-- .../installed_repository_manager.py | 6 +- .../installed_repository_metadata_manager.py | 10 +- .../tool_shed/galaxy_install/migrate/check.py | 10 +- .../galaxy_install/migrate/common.py | 2 +- .../migrate/scripts/migrate_tools.py | 4 +- .../repository_dependency_manager.py | 16 +-- .../recipe/env_file_builder.py | 4 +- .../recipe/install_environment.py | 12 +-- .../tool_dependencies/recipe/step_handler.py | 40 ++++---- .../tool_dependencies/recipe/tag_handler.py | 10 +- .../galaxy_install/tools/data_manager.py | 10 +- .../tools/tool_panel_manager.py | 2 +- .../update_repository_manager.py | 2 +- .../tool_shed/metadata/metadata_generator.py | 28 +++--- lib/galaxy/tool_shed/tool_shed_registry.py | 10 +- .../tool_shed/tools/data_table_manager.py | 2 +- lib/galaxy/tool_shed/tools/tool_validator.py | 6 +- lib/galaxy/tool_shed/util/basic_util.py | 12 +-- lib/galaxy/tool_shed/util/hg_util.py | 12 +-- lib/galaxy/tool_shed/util/repository_util.py | 10 +- lib/galaxy/tool_shed/util/shed_util_common.py | 4 +- .../tool_shed/util/tool_dependency_util.py | 10 +- lib/galaxy/tool_shed/util/tool_util.py | 12 +-- lib/galaxy/tool_util/client/staging.py | 6 +- lib/galaxy/tool_util/cwl/parser.py | 16 +-- lib/galaxy/tool_util/cwl/representation.py | 12 +-- lib/galaxy/tool_util/cwl/runtime_actions.py | 10 +- lib/galaxy/tool_util/cwl/util.py | 10 +- lib/galaxy/tool_util/deps/__init__.py | 2 +- lib/galaxy/tool_util/deps/brew_exts.py | 16 +-- lib/galaxy/tool_util/deps/conda_util.py | 20 ++-- .../tool_util/deps/container_classes.py | 23 ++--- .../deps/container_resolvers/__init__.py | 2 +- .../deps/container_resolvers/explicit.py | 2 +- .../deps/container_resolvers/mulled.py | 24 ++--- lib/galaxy/tool_util/deps/containers.py | 14 +-- lib/galaxy/tool_util/deps/docker_util.py | 2 +- lib/galaxy/tool_util/deps/installable.py | 6 +- lib/galaxy/tool_util/deps/mulled/get_tests.py | 33 +++---- .../tool_util/deps/mulled/mulled_build.py | 34 +++---- .../deps/mulled/mulled_build_channel.py | 4 +- .../deps/mulled/mulled_build_files.py | 2 +- .../tool_util/deps/mulled/mulled_list.py | 8 +- .../tool_util/deps/mulled/mulled_search.py | 22 ++--- .../mulled_update_singularity_containers.py | 10 +- lib/galaxy/tool_util/deps/mulled/util.py | 18 ++-- .../tool_util/deps/resolvers/__init__.py | 2 +- .../resolvers/brewed_tool_shed_packages.py | 2 +- lib/galaxy/tool_util/deps/resolvers/conda.py | 18 ++-- lib/galaxy/tool_util/deps/resolvers/lmod.py | 4 +- .../deps/resolvers/resolver_mixins.py | 2 +- lib/galaxy/tool_util/deps/singularity_util.py | 2 +- lib/galaxy/tool_util/lint.py | 8 +- lib/galaxy/tool_util/linters/citations.py | 4 +- lib/galaxy/tool_util/linters/command.py | 6 +- lib/galaxy/tool_util/linters/cwl.py | 4 +- lib/galaxy/tool_util/linters/help.py | 2 +- lib/galaxy/tool_util/linters/inputs.py | 2 +- lib/galaxy/tool_util/linters/outputs.py | 6 +- lib/galaxy/tool_util/linters/stdio.py | 4 +- lib/galaxy/tool_util/linters/xml_order.py | 2 +- lib/galaxy/tool_util/locations/dockstore.py | 10 +- lib/galaxy/tool_util/output_checker.py | 2 +- lib/galaxy/tool_util/parser/factory.py | 2 +- lib/galaxy/tool_util/parser/interface.py | 4 +- lib/galaxy/tool_util/parser/output_actions.py | 20 ++-- .../tool_util/parser/output_collection_def.py | 2 +- lib/galaxy/tool_util/parser/xml.py | 15 ++- lib/galaxy/tool_util/parser/yaml.py | 2 +- lib/galaxy/tool_util/provided_metadata.py | 16 +-- lib/galaxy/tool_util/verify/__init__.py | 16 +-- .../tool_util/verify/asserts/__init__.py | 2 +- lib/galaxy/tool_util/verify/asserts/text.py | 14 +-- lib/galaxy/tool_util/verify/asserts/xml.py | 4 +- lib/galaxy/tool_util/verify/interactor.py | 70 ++++++------- lib/galaxy/tool_util/verify/script.py | 2 +- lib/galaxy/tool_util/verify/test_data.py | 2 +- lib/galaxy/tools/__init__.py | 52 +++++----- lib/galaxy/tools/actions/__init__.py | 22 ++--- lib/galaxy/tools/actions/data_manager.py | 2 +- lib/galaxy/tools/actions/history_imp_exp.py | 2 +- lib/galaxy/tools/actions/metadata.py | 2 +- lib/galaxy/tools/actions/model_operations.py | 2 +- lib/galaxy/tools/actions/upload.py | 6 +- lib/galaxy/tools/actions/upload_common.py | 4 +- lib/galaxy/tools/cache.py | 2 +- lib/galaxy/tools/data/__init__.py | 14 +-- lib/galaxy/tools/data_fetch.py | 12 +-- lib/galaxy/tools/data_manager/manager.py | 20 ++-- .../tools/error_reports/plugins/email.py | 2 +- .../tools/error_reports/plugins/github.py | 4 +- .../tools/error_reports/plugins/gitlab.py | 10 +- .../tools/error_reports/plugins/json.py | 2 +- .../tools/error_reports/plugins/sentry.py | 2 +- lib/galaxy/tools/errors.py | 10 +- lib/galaxy/tools/evaluation.py | 8 +- lib/galaxy/tools/execute.py | 2 +- lib/galaxy/tools/expressions/script.py | 2 +- lib/galaxy/tools/imp_exp/__init__.py | 2 +- lib/galaxy/tools/imp_exp/export_history.py | 4 +- .../tools/imp_exp/unpack_tar_gz_archive.py | 4 +- lib/galaxy/tools/parameters/__init__.py | 6 +- lib/galaxy/tools/parameters/basic.py | 24 ++--- .../tools/parameters/dynamic_options.py | 12 +-- lib/galaxy/tools/parameters/grouping.py | 22 ++--- lib/galaxy/tools/parameters/meta.py | 2 +- lib/galaxy/tools/parameters/sanitize.py | 12 +-- lib/galaxy/tools/parameters/validation.py | 4 +- lib/galaxy/tools/parameters/wrapped_json.py | 2 +- lib/galaxy/tools/recommendations.py | 2 +- lib/galaxy/tools/test.py | 6 +- lib/galaxy/tools/toolbox/base.py | 34 +++---- lib/galaxy/tools/toolbox/filters/__init__.py | 2 +- lib/galaxy/tools/toolbox/integrated_panel.py | 12 +-- lib/galaxy/tools/toolbox/panel.py | 20 ++-- lib/galaxy/tools/util/galaxyops/__init__.py | 2 +- lib/galaxy/tools/wrappers.py | 4 +- lib/galaxy/tours/_impl.py | 4 +- lib/galaxy/util/__init__.py | 34 +++---- lib/galaxy/util/bunch.py | 2 +- lib/galaxy/util/compression_utils.py | 14 +-- lib/galaxy/util/dbkeys.py | 4 +- lib/galaxy/util/dictifiable.py | 2 +- lib/galaxy/util/filelock.py | 2 +- lib/galaxy/util/form_builder.py | 2 +- lib/galaxy/util/heartbeat.py | 4 +- lib/galaxy/util/json.py | 8 +- lib/galaxy/util/jstree.py | 6 +- lib/galaxy/util/object_wrapper.py | 4 +- lib/galaxy/util/oset.py | 2 +- lib/galaxy/util/pastescript/loadwsgi.py | 22 ++--- lib/galaxy/util/pastescript/serve.py | 50 +++++----- lib/galaxy/util/path/__init__.py | 4 +- lib/galaxy/util/plugin_config.py | 2 +- lib/galaxy/util/properties.py | 4 +- lib/galaxy/util/rules_dsl.py | 6 +- lib/galaxy/util/submodules.py | 2 +- lib/galaxy/util/template.py | 2 +- lib/galaxy/util/tool_shed/common_util.py | 4 +- lib/galaxy/util/tool_shed/xml_util.py | 4 +- lib/galaxy/util/watcher.py | 2 +- lib/galaxy/util/xml_macros.py | 2 +- lib/galaxy/util/yaml_util.py | 2 +- .../visualization/data_providers/genome.py | 6 +- .../visualization/plugins/config_parser.py | 2 +- .../plugins/interactive_environments.py | 8 +- lib/galaxy/visualization/plugins/plugin.py | 4 +- lib/galaxy/visualization/plugins/registry.py | 4 +- .../visualization/plugins/resource_parser.py | 4 +- lib/galaxy/web/framework/base.py | 2 +- lib/galaxy/web/framework/decorators.py | 4 +- lib/galaxy/web/framework/helpers/grids.py | 6 +- lib/galaxy/web/framework/helpers/tags.py | 2 +- lib/galaxy/web/framework/middleware/error.py | 3 +- .../web/framework/middleware/profile.py | 20 ++-- .../web/framework/middleware/remoteuser.py | 4 +- lib/galaxy/web/framework/middleware/sentry.py | 2 +- lib/galaxy/web/legacy_framework/grids.py | 6 +- lib/galaxy/web/proxy/__init__.py | 6 +- lib/galaxy/web_stack/__init__.py | 4 +- lib/galaxy/web_stack/handlers.py | 8 +- lib/galaxy/web_stack/message.py | 4 +- lib/galaxy/web_stack/transport.py | 2 +- lib/galaxy/webapps/base/controller.py | 40 ++++---- lib/galaxy/webapps/base/webapp.py | 2 +- lib/galaxy/webapps/galaxy/api/_fetch_util.py | 6 +- lib/galaxy/webapps/galaxy/api/cloudauthz.py | 6 +- lib/galaxy/webapps/galaxy/api/datasets.py | 2 +- lib/galaxy/webapps/galaxy/api/forms.py | 4 +- lib/galaxy/webapps/galaxy/api/histories.py | 4 +- .../webapps/galaxy/api/history_contents.py | 10 +- lib/galaxy/webapps/galaxy/api/job_files.py | 2 +- lib/galaxy/webapps/galaxy/api/jobs.py | 8 +- .../webapps/galaxy/api/library_contents.py | 6 +- .../webapps/galaxy/api/library_datasets.py | 4 +- .../galaxy/api/tool_shed_repositories.py | 12 +-- lib/galaxy/webapps/galaxy/api/tools.py | 14 +-- lib/galaxy/webapps/galaxy/api/toolshed.py | 2 +- lib/galaxy/webapps/galaxy/api/users.py | 36 +++---- .../webapps/galaxy/api/visualizations.py | 12 +-- lib/galaxy/webapps/galaxy/api/workflows.py | 18 ++-- lib/galaxy/webapps/galaxy/buildapp.py | 36 +++---- .../controllers/_create_history_template.py | 2 +- .../webapps/galaxy/controllers/admin.py | 80 +++++++-------- .../galaxy/controllers/admin_toolshed.py | 28 +++--- .../webapps/galaxy/controllers/async.py | 30 +++--- .../webapps/galaxy/controllers/authnz.py | 2 +- .../galaxy/controllers/data_manager.py | 10 +- .../webapps/galaxy/controllers/dataset.py | 62 ++++++------ .../webapps/galaxy/controllers/forms.py | 30 +++--- .../webapps/galaxy/controllers/history.py | 24 ++--- .../webapps/galaxy/controllers/openid.py | 10 +- lib/galaxy/webapps/galaxy/controllers/page.py | 8 +- lib/galaxy/webapps/galaxy/controllers/root.py | 30 +++--- lib/galaxy/webapps/galaxy/controllers/tag.py | 2 +- .../webapps/galaxy/controllers/tool_runner.py | 8 +- lib/galaxy/webapps/galaxy/controllers/user.py | 16 +-- .../galaxy/controllers/visualization.py | 26 ++--- .../webapps/galaxy/controllers/workflow.py | 44 ++++----- lib/galaxy/webapps/reports/app.py | 2 +- lib/galaxy/webapps/reports/config.py | 2 +- .../webapps/reports/controllers/history.py | 4 +- .../webapps/reports/controllers/system.py | 4 +- .../webapps/reports/controllers/tools.py | 6 +- lib/galaxy/workflow/extract.py | 10 +- lib/galaxy/workflow/modules.py | 26 ++--- lib/galaxy/workflow/refactor/execute.py | 2 +- lib/galaxy/workflow/reports/__init__.py | 2 +- .../workflow/reports/generators/markdown.py | 2 +- lib/galaxy/workflow/resources/__init__.py | 4 +- lib/galaxy/workflow/run.py | 14 +-- lib/galaxy/workflow/run_request.py | 22 ++--- lib/galaxy/workflow/scheduling_manager.py | 4 +- lib/galaxy/workflow/trs_proxy.py | 2 +- lib/galaxy_ext/container_monitor/monitor.py | 2 +- lib/galaxy_test/api/conftest.py | 4 +- lib/galaxy_test/api/test_api_batch.py | 2 +- .../api/test_dataset_collections.py | 20 ++-- lib/galaxy_test/api/test_datasets.py | 4 +- lib/galaxy_test/api/test_histories.py | 22 ++--- lib/galaxy_test/api/test_history_contents.py | 64 ++++++------ .../api/test_history_contents_provenance.py | 2 +- lib/galaxy_test/api/test_jobs.py | 36 +++---- lib/galaxy_test/api/test_libraries.py | 46 ++++----- lib/galaxy_test/api/test_page_revisions.py | 8 +- lib/galaxy_test/api/test_pages.py | 14 +-- lib/galaxy_test/api/test_roles.py | 4 +- lib/galaxy_test/api/test_search.py | 2 +- lib/galaxy_test/api/test_tool_data.py | 2 +- lib/galaxy_test/api/test_tools.py | 48 ++++----- lib/galaxy_test/api/test_tools_upload.py | 2 +- lib/galaxy_test/api/test_users.py | 40 ++++---- lib/galaxy_test/api/test_visualizations.py | 6 +- .../api/test_workflow_extraction.py | 8 +- lib/galaxy_test/api/test_workflows.py | 98 +++++++++---------- .../api/test_workflows_from_yaml.py | 4 +- lib/galaxy_test/base/api.py | 4 +- lib/galaxy_test/base/populators.py | 72 +++++++------- lib/galaxy_test/driver/driver_util.py | 48 ++++----- lib/galaxy_test/driver/integration_util.py | 2 +- lib/galaxy_test/selenium/framework.py | 16 +-- lib/galaxy_test/selenium/test_admin_app.py | 2 +- .../selenium/test_custom_builds.py | 2 +- .../selenium/test_histories_list.py | 5 +- .../selenium/test_history_dataset_state.py | 4 +- .../selenium/test_history_sharing.py | 10 +- lib/galaxy_test/selenium/test_jupyter.py | 2 +- .../selenium/test_library_contents.py | 2 +- .../selenium/test_published_histories_grid.py | 2 +- lib/galaxy_test/selenium/test_tool_form.py | 2 +- lib/galaxy_test/selenium/test_workflow_run.py | 2 +- .../dependencies/attribute_handlers.py | 6 +- .../repository/relation_builder.py | 4 +- .../galaxy_install/dependency_display.py | 6 +- .../grids/admin_toolshed_grids.py | 24 ++--- .../utility_containers/__init__.py | 2 +- .../grids/repository_grid_filter_manager.py | 10 +- lib/tool_shed/grids/repository_grids.py | 30 +++--- .../grids/repository_review_grids.py | 14 +-- .../metadata/repository_metadata_manager.py | 6 +- lib/tool_shed/test/base/test_db_util.py | 8 +- lib/tool_shed/test/base/twilltestcase.py | 78 +++++++-------- .../test_0000_basic_repository_features.py | 14 +-- ..._0010_repository_with_tool_dependencies.py | 4 +- ...test_0020_basic_repository_dependencies.py | 4 +- ...st_0030_repository_dependency_revisions.py | 4 +- ...t_0040_repository_circular_dependencies.py | 4 +- ...est_0050_circular_dependencies_4_levels.py | 4 +- .../test/functional/test_0070_invalid_tool.py | 6 +- ...est_0080_advanced_circular_dependencies.py | 4 +- .../test/functional/test_0090_tool_search.py | 4 +- ...st_0100_complex_repository_dependencies.py | 4 +- ..._invalid_simple_repository_dependencies.py | 4 +- ...e_repository_dependency_multiple_owners.py | 6 +- .../test_0130_datatype_converters.py | 4 +- .../functional/test_0140_tool_help_images.py | 6 +- .../test_0150_prior_installation_required.py | 4 +- ...60_circular_prior_installation_required.py | 4 +- ...170_complex_prior_installation_required.py | 4 +- .../test_0300_reset_all_metadata.py | 6 +- .../functional/test_0310_hg_api_features.py | 6 +- .../test_0400_repository_component_reviews.py | 6 +- ...ository_component_review_access_control.py | 8 +- ...test_0420_citable_urls_for_repositories.py | 6 +- .../functional/test_0430_browse_utilities.py | 4 +- ...st_0440_deleting_dependency_definitions.py | 6 +- .../test_0460_upload_to_repository.py | 6 +- ...st_0470_tool_dependency_repository_type.py | 6 +- ...t_0480_tool_dependency_xml_verification.py | 6 +- .../test_0530_repository_admin_feature.py | 10 +- .../test_0540_get_all_metadata_from_api.py | 10 +- ...test_0550_metadata_updated_dependencies.py | 10 +- .../test_1000_install_basic_repository.py | 6 +- ...stall_repository_with_tool_dependencies.py | 6 +- ...repository_with_repository_dependencies.py | 6 +- ...ll_repository_with_dependency_revisions.py | 6 +- ..._repository_basic_circular_dependencies.py | 4 +- ...est_1050_circular_dependencies_4_levels.py | 6 +- .../test/functional/test_1070_invalid_tool.py | 6 +- ...vanced_circular_dependency_installation.py | 6 +- ...est_1090_repository_dependency_handling.py | 6 +- ...install_updated_repository_dependencies.py | 6 +- ...ll_repository_with_complex_dependencies.py | 10 +- ...tory_with_invalid_repository_dependency.py | 4 +- ...e_repository_dependency_multiple_owners.py | 6 +- .../test_1150_datatype_converters.py | 6 +- .../functional/test_1160_tool_help_images.py | 6 +- .../test_1170_prior_installation_required.py | 6 +- ...80_circular_prior_installation_required.py | 6 +- ...190_complex_prior_installation_required.py | 4 +- ...ninstall_and_reinstall_basic_repository.py | 6 +- ...stall_repository_with_tool_dependencies.py | 6 +- ...repository_with_repository_dependencies.py | 6 +- ...ll_repository_with_dependency_revisions.py | 6 +- .../test_1300_reset_all_metadata.py | 4 +- .../functional/test_1410_update_manager.py | 6 +- ...tool_dependency_environment_inheritance.py | 6 +- .../test_1430_repair_installed_repository.py | 6 +- .../test_1440_missing_env_sh_files.py | 6 +- ...test_1450_installing_datatypes_sniffers.py | 6 +- .../functional/test_1460_data_managers.py | 8 +- ...st_1470_updating_installed_repositories.py | 4 +- lib/tool_shed/util/admin_util.py | 42 ++++---- lib/tool_shed/util/commit_util.py | 6 +- lib/tool_shed/util/hg_util.py | 44 ++++----- lib/tool_shed/util/hgweb_config.py | 4 +- lib/tool_shed/util/repository_util.py | 16 +-- lib/tool_shed/util/shed_index.py | 2 +- lib/tool_shed/util/shed_util_common.py | 8 +- lib/tool_shed/utility_containers/__init__.py | 2 +- .../utility_container_manager.py | 4 +- lib/tool_shed/webapp/api/categories.py | 6 +- lib/tool_shed/webapp/api/groups.py | 2 +- lib/tool_shed/webapp/api/repositories.py | 20 ++-- .../webapp/api/repository_revisions.py | 8 +- lib/tool_shed/webapp/api/tools.py | 2 +- lib/tool_shed/webapp/api/users.py | 6 +- lib/tool_shed/webapp/app.py | 2 +- lib/tool_shed/webapp/config.py | 4 +- lib/tool_shed/webapp/controllers/admin.py | 14 +-- .../webapp/controllers/repository.py | 32 +++--- .../webapp/controllers/repository_review.py | 12 +-- lib/tool_shed/webapp/controllers/upload.py | 6 +- lib/tool_shed/webapp/controllers/user.py | 18 ++-- lib/tool_shed/webapp/model/__init__.py | 8 +- lib/tool_shed/webapp/model/migrate/check.py | 2 +- .../versions/0002_add_tool_suite_column.py | 2 +- .../versions/0009_add_malicious_column.py | 2 +- .../0010_add_new_repo_alert_column.py | 2 +- .../versions/0012_add_downloadable_column.py | 2 +- .../versions/0013_add_review_tables.py | 44 ++++----- .../versions/0014_add_deprecated_column.py | 2 +- ...ols_functionally_correct_errors_columns.py | 4 +- ...ty_columns_to_repository_metadata_table.py | 10 +- ...18_add_repository_metadata_flag_columns.py | 2 +- ...est_table_and_test_install_error_column.py | 2 +- .../0022_add_repository_admin_roles.py | 36 +++---- lib/tool_shed/webapp/security/__init__.py | 4 +- scripts/galaxy_main.py | 6 +- 541 files changed, 2748 insertions(+), 2776 deletions(-) diff --git a/lib/galaxy/actions/admin.py b/lib/galaxy/actions/admin.py index e7eb173092a..6a54762b98e 100644 --- a/lib/galaxy/actions/admin.py +++ b/lib/galaxy/actions/admin.py @@ -45,7 +45,7 @@ class AdminActions: # If this is a default quota, create the DefaultQuotaAssociation if params.default != 'no': self.app.quota_agent.set_default_quota(params.default, quota) - message = "Default quota '%s' has been created." % quota.name + message = f"Default quota '{quota.name}' has been created." else: # Create the UserQuotaAssociations in_users = [self.sa_session.query(self.app.model.User).get(decode_id(x) if decode_id else x) for x in util.listify(params.in_users)] @@ -113,7 +113,7 @@ class AdminActions: quota.operation = params.operation self.sa_session.add(quota) self.sa_session.flush() - message = "Quota '{}' is now '{}'.".format(quota.name, quota.operation + quota.display_amount) + message = f"Quota '{quota.name}' is now '{quota.operation + quota.display_amount}'." return message def _set_quota_default(self, quota, params): @@ -125,19 +125,19 @@ class AdminActions: message = f"Quota '{quota.name}' is now the default for {params.default} users." else: if quota.default: - message = "Quota '{}' is no longer the default for {} users.".format(quota.name, quota.default[0].type) + message = f"Quota '{quota.name}' is no longer the default for {quota.default[0].type} users." for dqa in quota.default: self.sa_session.delete(dqa) self.sa_session.flush() else: - message = "Quota '%s' is not a default." % quota.name + message = f"Quota '{quota.name}' is not a default." return message def _unset_quota_default(self, quota, params=None): if not quota.default: - raise ActionInputError("Quota '%s' is not a default." % quota.name) + raise ActionInputError(f"Quota '{quota.name}' is not a default.") else: - message = "Quota '{}' is no longer the default for {} users.".format(quota.name, quota.default[0].type) + message = f"Quota '{quota.name}' is no longer the default for {quota.default[0].type} users." for dqa in quota.default: self.sa_session.delete(dqa) self.sa_session.flush() @@ -150,7 +150,7 @@ class AdminActions: if q.default: names.append(q.name) if len(names) == 1: - raise ActionInputError("Quota '%s' is a default, please unset it as a default before deleting it." % (names[0])) + raise ActionInputError(f"Quota '{names[0]}' is a default, please unset it as a default before deleting it.") elif len(names) > 1: raise ActionInputError("Quotas are defaults, please unset them as defaults before deleting them: " + ', '.join(names)) message = "Deleted %d quotas: " % len(quotas) @@ -169,7 +169,7 @@ class AdminActions: if not q.deleted: names.append(q.name) if len(names) == 1: - raise ActionInputError("Quota '%s' has not been deleted, so it cannot be undeleted." % (names[0])) + raise ActionInputError(f"Quota '{names[0]}' has not been deleted, so it cannot be undeleted.") elif len(names) > 1: raise ActionInputError("Quotas have not been deleted so they cannot be undeleted: " + ', '.join(names)) message = "Undeleted %d quotas: " % len(quotas) @@ -194,7 +194,7 @@ class AdminActions: if not q.deleted: names.append(q.name) if len(names) == 1: - raise ActionInputError("Quota '%s' has not been deleted, so it cannot be purged." % (names[0])) + raise ActionInputError(f"Quota '{names[0]}' has not been deleted, so it cannot be purged.") elif len(names) > 1: raise ActionInputError("Quotas have not been deleted so they cannot be undeleted: " + ', '.join(names)) message = "Purged %d quotas: " % len(quotas) diff --git a/lib/galaxy/actions/library.py b/lib/galaxy/actions/library.py index bd3d6f009d9..ef371cb7cc9 100644 --- a/lib/galaxy/actions/library.py +++ b/lib/galaxy/actions/library.py @@ -169,11 +169,11 @@ class LibraryActions: if os.path.isfile(path): files.append(path) except Exception as e: - message = "Unable to get file list for configured {}, error: {}".format(import_dir_desc, util.unicodify(e)) + message = f"Unable to get file list for configured {import_dir_desc}, error: {util.unicodify(e)}" response_code = 500 return None, response_code, message if not files: - message = "The directory '%s' contains no valid files" % full_dir + message = f"The directory '{full_dir}' contains no valid files" response_code = 400 return None, response_code, message return files, None, None @@ -296,15 +296,15 @@ class LibraryActions: if isinstance(item, trans.model.HistoryDatasetAssociation): # Make sure the user has the DATASET_ACCESS permission on the history_dataset_association. if not item: - message = "Invalid history dataset (%s) specified." % escape(str(item)) + message = f"Invalid history dataset ({escape(str(item))}) specified." can_access = False elif not trans.app.security_agent.can_access_dataset(current_user_roles, item.dataset) and item.history.user == trans.user: - message = "You do not have permission to access the history dataset with id (%s)." % str(item.id) + message = f"You do not have permission to access the history dataset with id ({str(item.id)})." can_access = False else: # Make sure the user has the LIBRARY_ACCESS permission on the library item. if not item: - message = "Invalid library item (%s) specified." % escape(str(item)) + message = f"Invalid library item ({escape(str(item))}) specified." can_access = False elif not (is_admin or trans.app.security_agent.can_access_library_item(current_user_roles, item, trans.user)): if isinstance(item, trans.model.Library): @@ -313,7 +313,7 @@ class LibraryActions: item_type = 'folder' else: item_type = '(unknown item type)' - message = "You do not have permission to access the {} with id ({}).".format(escape(item_type), str(item.id)) + message = f"You do not have permission to access the {escape(item_type)} with id ({str(item.id)})." can_access = False if not can_access: return 400, message @@ -321,5 +321,5 @@ class LibraryActions: def _check_add(self, trans, is_admin, item, current_user_roles): # Deny access if the user is not an admin and does not have the LIBRARY_ADD permission. if not (is_admin or trans.app.security_agent.can_add_library_item(current_user_roles, item)): - message = "You are not authorized to add an item to (%s)." % escape(item.name) + message = f"You are not authorized to add an item to ({escape(item.name)})." return 403, message diff --git a/lib/galaxy/app.py b/lib/galaxy/app.py index fa6b7e6b62a..ca604776c54 100644 --- a/lib/galaxy/app.py +++ b/lib/galaxy/app.py @@ -350,7 +350,7 @@ class UniverseApplication(StructuredApp, GalaxyManagerApplication): self.url_for = url_for self.server_starttime = int(time.time()) # used for cachebusting - log.info("Galaxy app startup finished %s" % startup_timer) + log.info(f"Galaxy app startup finished {startup_timer}") def _shutdown_queue_worker(self): self.queue_worker.shutdown() diff --git a/lib/galaxy/auth/__init__.py b/lib/galaxy/auth/__init__.py index f7976ea32a1..064ae8af2af 100644 --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -56,7 +56,7 @@ class AuthManager: } for provider, options in self.active_authenticators(email, username, password): if provider is None: - log.debug("Unable to find module: %s" % options) + log.debug(f"Unable to find module: {options}") else: options['no_password_check'] = no_password_check auth_results = provider.authenticate(email, username, password, options) @@ -76,7 +76,7 @@ class AuthManager: """Checks the username/email and password using auth providers.""" for provider, options in self.active_authenticators(user.email, user.username, password): if provider is None: - log.debug("Unable to find module: %s" % options) + log.debug(f"Unable to find module: {options}") else: auth_result = provider.authenticate_user(user, password, options) if auth_result is True: @@ -91,7 +91,7 @@ class AuthManager: """ for provider, options in self.active_authenticators(user.email, user.username, current_password): if provider is None: - log.debug("Unable to find module: %s" % options) + log.debug(f"Unable to find module: {options}") else: auth_result = provider.authenticate_user(user, current_password, options) if auth_result is True: diff --git a/lib/galaxy/auth/providers/alwaysreject.py b/lib/galaxy/auth/providers/alwaysreject.py index 9e5ec450389..e39990ae977 100644 --- a/lib/galaxy/auth/providers/alwaysreject.py +++ b/lib/galaxy/auth/providers/alwaysreject.py @@ -26,7 +26,7 @@ class AlwaysReject(AuthProvider): """ See abstract method documentation. """ - log.debug("User: %s, ALWAYSREJECT: None" % (user.id if options['redact_username_in_logs'] else user.email)) + log.debug(f"User: {user.id if options['redact_username_in_logs'] else user.email}, ALWAYSREJECT: None") return None diff --git a/lib/galaxy/auth/providers/ldap_ad.py b/lib/galaxy/auth/providers/ldap_ad.py index 91088748f86..dac936f7386 100644 --- a/lib/galaxy/auth/providers/ldap_ad.py +++ b/lib/galaxy/auth/providers/ldap_ad.py @@ -25,7 +25,7 @@ log = logging.getLogger(__name__) def _get_subs(d, k, params): if k not in d or not d[k]: - raise ConfigurationError("Missing '%s' parameter in LDAP options" % k) + raise ConfigurationError(f"Missing '{k}' parameter in LDAP options") return str(d[k]).format(**params) diff --git a/lib/galaxy/auth/providers/localdb.py b/lib/galaxy/auth/providers/localdb.py index 61095352780..d17d865a7dc 100644 --- a/lib/galaxy/auth/providers/localdb.py +++ b/lib/galaxy/auth/providers/localdb.py @@ -25,7 +25,7 @@ class LocalDB(AuthProvider): See abstract method documentation. """ user_ok = user.check_password(password) - log.debug("User: {}, LOCALDB: {}".format(user.id if options['redact_username_in_logs'] else user.email, user_ok)) + log.debug(f"User: {user.id if options['redact_username_in_logs'] else user.email}, LOCALDB: {user_ok}") return user_ok diff --git a/lib/galaxy/auth/providers/pam_auth.py b/lib/galaxy/auth/providers/pam_auth.py index 4037d6d91f0..69a56186935 100644 --- a/lib/galaxy/auth/providers/pam_auth.py +++ b/lib/galaxy/auth/providers/pam_auth.py @@ -64,7 +64,7 @@ class PAM(AuthProvider): auto_register_email = None force_fail = False if not options['redact_username_in_logs']: - log.debug("use username: {} use email {} email {} username {}".format(options.get('login-use-username'), options.get('login-use-email', False), email, username)) + log.debug(f"use username: {options.get('login-use-username')} use email {options.get('login-use-email', False)} email {email} username {username}") # check email based login first because if email exists in Galaxy DB # we will be given the "public name" as username if string_as_bool(options.get('login-use-email', False)) and email is not None: @@ -95,7 +95,7 @@ class PAM(AuthProvider): elif options.get('maildomain', None) is not None: # we can register a user with this username and mail domain # if auto registration is enabled - auto_register_email = '{}@{}'.format(username, options['maildomain']) + auto_register_email = f"{username}@{options['maildomain']}" auto_register_username = username else: log.debug('PAM authenticate: username login selected but no username provided') @@ -142,10 +142,10 @@ class PAM(AuthProvider): authenticated = p_auth.authenticate(pam_username, password, service=pam_service) if authenticated: - log.debug('PAM authentication successful for {}'.format('redacted' if options['redact_username_in_logs'] else pam_username)) + log.debug(f"PAM authentication successful for {'redacted' if options['redact_username_in_logs'] else pam_username}") return True, auto_register_email, auto_register_username else: - log.debug('PAM authentication failed for {}'.format('redacted' if options['redact_username_in_logs'] else pam_username)) + log.debug(f"PAM authentication failed for {'redacted' if options['redact_username_in_logs'] else pam_username}") return False, '', '' def authenticate_user(self, user, password, options): diff --git a/lib/galaxy/auth/util.py b/lib/galaxy/auth/util.py index 09ad3e8d53d..7f9f0f2dd1b 100644 --- a/lib/galaxy/auth/util.py +++ b/lib/galaxy/auth/util.py @@ -47,7 +47,7 @@ def get_authenticators(auth_config_file, auth_config_file_set): type_elem_text = auth_elem.find('type').text plugin_class = __plugins_dict.get(type_elem_text) if not plugin_class: - raise Exception("Authenticator type '{}' not recognized, should be one of {}".format(type_elem_text, ', '.join(__plugins_dict))) + raise Exception(f"Authenticator type '{type_elem_text}' not recognized, should be one of {', '.join(__plugins_dict)}") plugin = plugin_class() # check filterelem diff --git a/lib/galaxy/authnz/custos_authnz.py b/lib/galaxy/authnz/custos_authnz.py index 92c3074becd..4fa2fc5c4ea 100644 --- a/lib/galaxy/authnz/custos_authnz.py +++ b/lib/galaxy/authnz/custos_authnz.py @@ -110,7 +110,7 @@ class CustosAuthnz(IdentityProvider): and len(trans.app.auth_manager.authenticators) == 0): user = existing_user else: - message = "There already exists a user with email %s. To associate this external login, you must first be logged in as that existing account." % email + message = f"There already exists a user with email {email}. To associate this external login, you must first be logged in as that existing account." log.exception(message) raise exceptions.AuthenticationFailed(message) else: @@ -180,7 +180,7 @@ class CustosAuthnz(IdentityProvider): # Find CustosAuthnzToken record for this provider (should only be one) provider_tokens = [token for token in user.custos_auth if token.provider == self.config["provider"]] if len(provider_tokens) == 0: - raise Exception("User is not associated with provider {}".format(self.config["provider"])) + raise Exception(f"User is not associated with provider {self.config['provider']}") if len(provider_tokens) > 1: for idx, token in enumerate(provider_tokens): id_token_decoded = self._decode_token_no_signature(token.id_token) @@ -190,13 +190,13 @@ class CustosAuthnz(IdentityProvider): trans.sa_session.flush() return True, "", disconnect_redirect_url except Exception as e: - return False, "Failed to disconnect provider {}: {}".format(provider, util.unicodify(e)), None + return False, f"Failed to disconnect provider {provider}: {util.unicodify(e)}", None def logout(self, trans, post_logout_redirect_url=None): try: redirect_url = self.config['end_session_endpoint'] if post_logout_redirect_url is not None: - redirect_url += "?redirect_uri={}".format(quote(post_logout_redirect_url)) + redirect_url += f"?redirect_uri={quote(post_logout_redirect_url)}" return redirect_url except Exception as e: log.error("Failed to generate logout redirect_url", exc_info=e) @@ -229,7 +229,7 @@ class CustosAuthnz(IdentityProvider): token_endpoint, client_secret=client_secret, authorization_response=trans.request.url, - headers={"Authorization": "Basic %s" % util.unicodify(base64.b64encode(util.smart_str(clientIdAndSec)))}, # for custos + headers={"Authorization": f"Basic {util.unicodify(base64.b64encode(util.smart_str(clientIdAndSec)))}"}, # for custos verify=self._get_verify_param()) def _get_userinfo(self, oauth2_session): @@ -265,7 +265,7 @@ class CustosAuthnz(IdentityProvider): # Set custos endpoints clientIdAndSec = self.config['client_id'] + ":" + self.config['client_secret'] eps = requests.get(self.config['well_known_oidc_config_uri'], - headers={"Authorization": "Basic %s" % util.unicodify(base64.b64encode(util.smart_str(clientIdAndSec)))}, + headers={"Authorization": f"Basic {util.unicodify(base64.b64encode(util.smart_str(clientIdAndSec)))}"}, verify=False, params={'client_id': self.config['client_id']}) well_known_oidc_config = eps.json() self._load_well_known_oidc_config(well_known_oidc_config) @@ -278,7 +278,7 @@ class CustosAuthnz(IdentityProvider): def _get_custos_credentials(self): clientIdAndSec = self.config['client_id'] + ":" + self.config['client_secret'] creds = requests.get(self.config['credential_url'], - headers={"Authorization": "Basic %s" % util.unicodify(base64.b64encode(util.smart_str(clientIdAndSec)))}, + headers={"Authorization": f"Basic {util.unicodify(base64.b64encode(util.smart_str(clientIdAndSec)))}"}, verify=False, params={'client_id': self.config['client_id']}) credentials = creds.json() self.config['iam_client_secret'] = credentials['iam_client_secret'] diff --git a/lib/galaxy/authnz/psa_authnz.py b/lib/galaxy/authnz/psa_authnz.py index 00223a60404..f42dbe2b6cf 100644 --- a/lib/galaxy/authnz/psa_authnz.py +++ b/lib/galaxy/authnz/psa_authnz.py @@ -355,7 +355,7 @@ def verify(strategy=None, response=None, details=None, **kwargs): result = requests.post( f"https://iam.googleapis.com/v1/projects/-/serviceAccounts/{endpoint}:getIamPolicy", headers={ - 'Authorization': 'Bearer {}'.format(response.get("access_token")), + 'Authorization': f"Bearer {response.get('access_token')}", 'Accept': 'application/json'}) res = json.loads(result.content) if result.status_code == requests.codes.ok: diff --git a/lib/galaxy/config/__init__.py b/lib/galaxy/config/__init__.py index 1134db7e5d6..8d0dd87117f 100644 --- a/lib/galaxy/config/__init__.py +++ b/lib/galaxy/config/__init__.py @@ -176,7 +176,7 @@ class BaseAppConfiguration: # NOTE: This will check all supplied keyword arguments, including those not in the schema. # To check only schema options, change the line below to `if property not in self._raw_config:` if key not in self._raw_config: - log.warning("Configuration option does not exist: '%s'" % key) + log.warning(f"Configuration option does not exist: '{key}'") return key in self._kwargs def resolve_path(self, path): @@ -257,7 +257,7 @@ class BaseAppConfiguration: for key in self.add_sample_file_to_defaults: if not self.is_set(key): defaults = listify(getattr(self, key), do_strip=True) - sample = '%s.sample' % defaults[-1] # if there are multiple defaults, use last as template + sample = f'{defaults[-1]}.sample' # if there are multiple defaults, use last as template sample = self._in_sample_dir(sample) # resolve w.r.t sample_dir defaults.append(sample) setattr(self, key, defaults) @@ -356,7 +356,7 @@ class BaseAppConfiguration: if not hasattr(self, key): setattr(self, key, value) elif key not in base_configs: - raise ConfigurationError("Attempting to override existing attribute '%s'" % key) + raise ConfigurationError(f"Attempting to override existing attribute '{key}'") def _resolve_paths(self): @@ -486,7 +486,7 @@ class CommonConfigurationMixin: try: os.makedirs(path) except Exception as e: - raise ConfigurationError("Unable to create missing directory: {}\n{}".format(path, unicodify(e))) + raise ConfigurationError(f"Unable to create missing directory: {path}\n{unicodify(e)}") class GalaxyAppConfiguration(BaseAppConfiguration, CommonConfigurationMixin): @@ -581,7 +581,7 @@ class GalaxyAppConfiguration(BaseAppConfiguration, CommonConfigurationMixin): self.check_migrate_databases = kwargs.get('check_migrate_databases', True) if not self.database_connection: # Provide default if not supplied by user db_path = self._in_data_dir('universe.sqlite') - self.database_connection = 'sqlite:///%s?isolation_level=IMMEDIATE' % db_path + self.database_connection = f'sqlite:///{db_path}?isolation_level=IMMEDIATE' self.database_engine_options = get_database_engine_options(kwargs) self.database_create_tables = string_as_bool(kwargs.get('database_create_tables', 'True')) self.database_encoding = kwargs.get('database_encoding') # Create new databases with this encoding @@ -817,14 +817,14 @@ class GalaxyAppConfiguration(BaseAppConfiguration, CommonConfigurationMixin): elif 'database_connection' in kwargs: self.amqp_internal_connection = "sqlalchemy+" + self.database_connection else: - self.amqp_internal_connection = "sqlalchemy+sqlite:///%s?isolation_level=IMMEDIATE" % self._in_data_dir("control.sqlite") + self.amqp_internal_connection = f"sqlalchemy+sqlite:///{self._in_data_dir('control.sqlite')}?isolation_level=IMMEDIATE" self.pretty_datetime_format = expand_pretty_datetime_format(self.pretty_datetime_format) try: with open(self.user_preferences_extra_conf_path) as stream: self.user_preferences_extra = yaml.safe_load(stream) except Exception: if self.is_set('user_preferences_extra_conf_path'): - log.warning('Config file (%s) could not be found or is malformed.' % self.user_preferences_extra_conf_path) + log.warning(f'Config file ({self.user_preferences_extra_conf_path}) could not be found or is malformed.') self.user_preferences_extra = {'preferences': {}} # Experimental: This will not be enabled by default and will hide @@ -840,7 +840,7 @@ class GalaxyAppConfiguration(BaseAppConfiguration, CommonConfigurationMixin): ie_dirs = self.interactive_environment_plugins_directory self.gie_dirs = [d.strip() for d in (ie_dirs.split(",") if ie_dirs else [])] if ie_dirs: - self.visualization_plugins_directory += ",%s" % ie_dirs + self.visualization_plugins_directory += f",{ie_dirs}" self.proxy_session_map = self.dynamic_proxy_session_map self.manage_dynamic_proxy = self.dynamic_proxy_manage # Set to false if being launched externally @@ -991,14 +991,14 @@ class GalaxyAppConfiguration(BaseAppConfiguration, CommonConfigurationMixin): tool_configs = self.tool_configs for path in tool_configs: if not os.path.exists(path) and path not in (self.shed_tool_config_file, self.migrated_tools_config): - raise ConfigurationError("Tool config file not found: %s" % path) + raise ConfigurationError(f"Tool config file not found: {path}") for datatypes_config in listify(self.datatypes_config): if not os.path.isfile(datatypes_config): - raise ConfigurationError("Datatypes config file not found: %s" % datatypes_config) + raise ConfigurationError(f"Datatypes config file not found: {datatypes_config}") # Check for deprecated options. for key in self.config_dict.keys(): if key in self.deprecated_options: - log.warning("Config option '%s' is deprecated and will be removed in a future release. Please consult the latest version of the sample configuration file." % key) + log.warning(f"Config option '{key}' is deprecated and will be removed in a future release. Please consult the latest version of the sample configuration file.") @staticmethod def _parse_allowed_origin_hostnames(allowed_origin_hostnames): @@ -1033,7 +1033,7 @@ def reload_config_options(current_config): if current_config._raw_config[option] != modified_config[option]: current_config._raw_config[option] = modified_config[option] setattr(current_config, option, modified_config[option]) - log.info('Reloaded %s' % option) + log.info(f'Reloaded {option}') def get_database_engine_options(kwargs, model_prefix=''): @@ -1052,7 +1052,7 @@ def get_database_engine_options(kwargs, model_prefix=''): 'pool_threadlocal': string_as_bool, 'server_side_cursors': string_as_bool } - prefix = "%sdatabase_engine_option_" % model_prefix + prefix = f"{model_prefix}database_engine_option_" prefix_len = len(prefix) rval = {} for key, value in kwargs.items(): @@ -1306,7 +1306,7 @@ class ConfiguresGalaxyMixin: else: from galaxy.model.tool_shed_install import mapping as install_mapping install_db_url = self.config.install_database_connection - log.info("Install database using its own connection %s" % install_db_url) + log.info(f"Install database using its own connection {install_db_url}") self.install_model = install_mapping.init(install_db_url, install_database_options) diff --git a/lib/galaxy/config/config_manage.py b/lib/galaxy/config/config_manage.py index da8c5bbf0ce..309cebc5200 100644 --- a/lib/galaxy/config/config_manage.py +++ b/lib/galaxy/config/config_manage.py @@ -201,29 +201,29 @@ class _OptionAction: class _DeprecatedAction(_OptionAction): def lint(self, args, app_desc, key, value): - print("Option [%s] has been deprecated, this will likely be dropped in future releases of Galaxy." % key) + print(f"Option [{key}] has been deprecated, this will likely be dropped in future releases of Galaxy.") class _DeprecatedAndDroppedAction(_OptionAction): def converted(self, args, app_desc, key, value): - print("Option [%s] has been deprecated and dropped. It is not included in converted configuration." % key) + print(f"Option [{key}] has been deprecated and dropped. It is not included in converted configuration.") return DROP_OPTION_VALUE def lint(self, args, app_desc, key, value): - print("Option [%s] has been deprecated. Option should be dropped without replacement." % key) + print(f"Option [{key}] has been deprecated. Option should be dropped without replacement.") class _PasteAppFactoryAction(_OptionAction): def converted(self, args, app_desc, key, value): if value not in app_desc.expected_app_factories: - raise Exception("Ending convert process - unknown paste factory encountered [%s]" % value) + raise Exception(f"Ending convert process - unknown paste factory encountered [{value}]") return DROP_OPTION_VALUE def lint(self, args, app_desc, key, value): if value not in app_desc.expected_app_factories: - print("Problem - unknown paste app factory encountered [%s]" % value) + print(f"Problem - unknown paste app factory encountered [{value}]") class _ProductionUnsafe(_OptionAction): @@ -409,7 +409,7 @@ def _to_rst(args, app_desc, heading_level="~"): def _write_option_rst(args, rst, key, heading_level, option_value): - title = "``%s``" % key + title = f"``{key}``" heading = heading_level * len(title) rst.write(f"{heading}\n{title}\n{heading}\n\n") option, value = _parse_option_value(option_value) @@ -426,9 +426,9 @@ def _write_option_rst(args, rst, key, heading_level, option_value): default = "false" elif default == "": default = '""' - rst.write(":Default: ``%s``\n" % default) + rst.write(f":Default: ``{default}``\n") if type: - rst.write(":Type: %s\n" % type) + rst.write(f":Type: {type}\n") rst.write("\n\n") @@ -513,7 +513,7 @@ def _find_app_options_from_config_parser(p): def _lint(args, app_desc): path = _find_config(args, app_desc) if not os.path.exists(path): - raise Exception("Expected configuration file [%s] not found." % path) + raise Exception(f"Expected configuration file [{path}] not found.") app_items = _find_app_options(app_desc, path) for key, value in app_items.items(): option_action = OPTION_ACTIONS.get(key) @@ -564,7 +564,7 @@ class GzipFilter: def _run_conversion(args, app_desc): ini_config = _find_config(args, app_desc) if ini_config and not _is_ini(ini_config): - _warn("Cannot convert YAML file %s, this option is only for ini config files." % ini_config) + _warn(f"Cannot convert YAML file {ini_config}, this option is only for ini config files.") sys.exit(1) elif not ini_config: _warn("Failed to find a config to convert - exiting without changes.") @@ -613,7 +613,7 @@ def _run_conversion(args, app_desc): if value in filters: applied_filters.append(filters[value]) else: - _warn("Unknown filter found [%s], exiting..." % value) + _warn(f"Unknown filter found [{value}], exiting...") sys.exit(1) uwsgi_dict = _server_paste_to_uwsgi(app_desc, server_config, applied_filters) @@ -656,7 +656,7 @@ def _is_ini(path): def _replace_file(args, f, app_desc, from_path, to_path): _write_to_file(args, f, to_path) - backup_path = "%s.backup" % from_path + backup_path = f"{from_path}.backup" print(f"Moving [{from_path}] to [{backup_path}]") if args.dry_run: print("... skipping because --dry-run is enabled.") @@ -704,7 +704,7 @@ def _write_to_file(args, f, path): print(f"Overwriting {path} with the following contents:\n{contents_indented}") print("... skipping because --dry-run is enabled.") else: - print("Overwriting %s" % path) + print(f"Overwriting {path}") safe_makedirs(os.path.dirname(path)) with open(path, "w") as to_f: to_f.write(contents) @@ -736,7 +736,7 @@ def _write_section(args, f, section_header, section_dict, uwsgi_hack=False): def _write_header(f, section_header): - f.write("%s:\n\n" % section_header) + f.write(f"{section_header}:\n\n") def _write_option(args, f, key, option_value, as_comment=False, uwsgi_hack=False): @@ -756,7 +756,7 @@ def _write_option(args, f, key, option_value, as_comment=False, uwsgi_hack=False key_val_str = yaml.dump({key: value}, width=float("inf")).lstrip("{").rstrip("\n}") lines = f"{comment}{as_comment_str}{key_val_str}" lines_idented = "\n".join(f" {line}" for line in lines.split("\n")) - f.write("%s\n\n" % lines_idented) + f.write(f"{lines_idented}\n\n") def _parse_option_value(option_value): @@ -807,7 +807,7 @@ def _server_paste_to_uwsgi(app_desc, server_config, applied_filters): def _warn(message): - print("WARNING: %s" % message) + print(f"WARNING: {message}") def _get_option_desc(option): diff --git a/lib/galaxy/config/script.py b/lib/galaxy/config/script.py index b8ce2e46ba5..ec44e7d7a2d 100644 --- a/lib/galaxy/config/script.py +++ b/lib/galaxy/config/script.py @@ -90,7 +90,7 @@ def main(argv=None): if not os.path.exists(directory): os.makedirs(directory) - print("Bootstrapping Galaxy configuration into directory %s" % relative_config_dir) + print(f"Bootstrapping Galaxy configuration into directory {relative_config_dir}") _handle_galaxy_yml(args, config_dir, data_dir) _handle_install(args, dependencies) _print_config_summary(args, mode, relative_config_dir) @@ -104,7 +104,7 @@ def _print_config_summary(args, mode, relative_config_dir): def _print_galaxy_yml_info(args, mode): print(" - galaxy.yml created, update to configure Galaxy.") - print(" * Target web server %s" % mode) + print(f" * Target web server {mode}") if args.host == DEFAULT_HOST: print(" * Binding to host localhost, remote clients will not be able to connect.") elif _determine_host(args) == "0.0.0.0": @@ -117,7 +117,7 @@ def _print_galaxy_run(mode): if mode.startswith("uwsgi"): print(" uwsgi --yaml galaxy.yml") else: - raise Exception("Unknown mode: %s" % mode) + raise Exception(f"Unknown mode: {mode}") def _determine_mode(args): @@ -178,7 +178,7 @@ def _handle_install(args, dependencies): def _check_file(path, force): if os.path.exists(path) and not force: - print("File %s exists, exiting. Run with --force to replace configuration." % path, file=sys.stderr) + print(f"File {path} exists, exiting. Run with --force to replace configuration.", file=sys.stderr) sys.exit(1) diff --git a/lib/galaxy/containers/__init__.py b/lib/galaxy/containers/__init__.py index ac416914177..97cf6e6cec1 100644 --- a/lib/galaxy/containers/__init__.py +++ b/lib/galaxy/containers/__init__.py @@ -45,7 +45,7 @@ class ContainerVolume(metaclass=ABCMeta): self.host_path = host_path self.mode = mode if mode and not self.mode_is_valid: - raise ValueError("Invalid container volume mode: %s" % mode) + raise ValueError(f"Invalid container volume mode: {mode}") @abstractmethod def from_str(cls, as_str): @@ -205,7 +205,7 @@ class ContainerInterface(metaclass=ABCMeta): return opttype def _guess_kwopt_flag(self, opt): - return '--%s' % opt.replace('_', '-') + return f"--{opt.replace('_', '-')}" def _stringify_kwopts(self, kwopts): opts = [] @@ -225,12 +225,12 @@ class ContainerInterface(metaclass=ABCMeta): def _stringify_kwopt_boolean(self, flag, val): """ """ - return '{flag}={value}'.format(flag=flag, value=str(val).lower()) + return f'{flag}={str(val).lower()}' def _stringify_kwopt_string(self, flag, val): """ """ - return '{flag} {value}'.format(flag=flag, value=shlex.quote(str(val))) + return f'{flag} {shlex.quote(str(val))}' def _stringify_kwopt_list(self, flag, val): """ @@ -346,7 +346,7 @@ def build_container_interfaces(containers_config_file, containers_conf=None): interfaces = {} for k, conf in containers_conf.items(): container_type = conf.get('type', DEFAULT_CONTAINER_TYPE) - assert container_type in interface_classes, "unknown container interface type: %s" % container_type + assert container_type in interface_classes, f"unknown container interface type: {container_type}" interfaces[k] = interface_classes[container_type](conf, k, containers_config_file) return interfaces diff --git a/lib/galaxy/containers/docker.py b/lib/galaxy/containers/docker.py index 7b1d23d8594..aaf2c9cde4d 100644 --- a/lib/galaxy/containers/docker.py +++ b/lib/galaxy/containers/docker.py @@ -198,7 +198,7 @@ class DockerCLIInterface(DockerInterface): try: return self._run_docker(subcommand='inspect', args=container_id)[0] except (IndexError, ContainerCLIError) as exc: - msg = "Invalid container id: %s" % container_id + msg = f"Invalid container id: {container_id}" if exc.stdout == '[]' and exc.stderr == f'Error: no such object: {container_id}': log.warning(msg) return [] @@ -210,7 +210,7 @@ class DockerCLIInterface(DockerInterface): try: return self._run_docker(subcommand='image inspect', args=image)[0] except (IndexError, ContainerCLIError) as exc: - msg = "%s not pulled, cannot get digest" % image + msg = f"{image} not pulled, cannot get digest" if exc.stdout == '[]' and exc.stderr == f'Error: no such image: {image}': log.warning(msg, image) return [] @@ -585,10 +585,10 @@ class DockerAPIInterface(DockerInterface): try: return self._client.inspect_container(container_id) except docker.errors.NotFound: - raise ContainerNotFound("Invalid container id: %s" % container_id, container_id=container_id) + raise ContainerNotFound(f"Invalid container id: {container_id}", container_id=container_id) def image_inspect(self, image): try: return self._client.inspect_image(image) except docker.errors.NotFound: - raise ContainerImageNotFound("%s not pulled, cannot get digest" % image, image=image) + raise ContainerImageNotFound(f"{image} not pulled, cannot get digest", image=image) diff --git a/lib/galaxy/containers/docker_model.py b/lib/galaxy/containers/docker_model.py index 65c9cabeca1..ebb62a016b9 100644 --- a/lib/galaxy/containers/docker_model.py +++ b/lib/galaxy/containers/docker_model.py @@ -85,7 +85,7 @@ class DockerVolume(ContainerVolume): Docker volume syntax. """ if not as_str: - raise ValueError("Failed to parse Docker volume from %s" % as_str) + raise ValueError(f"Failed to parse Docker volume from {as_str}") parts = as_str.split(":", 2) kwds = dict(host_path=parts[0]) if len(parts) == 1: @@ -109,7 +109,7 @@ class DockerVolume(ContainerVolume): volume_for_cmd_line = shlex.quote(volume_str) else: # e.g. $_GALAXY_JOB_TMP_DIR:$_GALAXY_JOB_TMP_DIR:rw so don't single quote. - volume_for_cmd_line = '"%s"' % volume_str + volume_for_cmd_line = f'"{volume_str}"' return volume_for_cmd_line def to_native(self): @@ -406,7 +406,7 @@ class DockerServiceConstraint: if len(t[0]) < len(constraint[0]): constraint = t if constraint[0] == constraint_str: - raise Exception('Unable to parse constraint string: %s' % constraint_str) + raise Exception(f'Unable to parse constraint string: {constraint_str}') return [x.strip() for x in constraint] @classmethod diff --git a/lib/galaxy/datatypes/annotation.py b/lib/galaxy/datatypes/annotation.py index 64ed7220c91..98f14d1959e 100644 --- a/lib/galaxy/datatypes/annotation.py +++ b/lib/galaxy/datatypes/annotation.py @@ -26,7 +26,7 @@ class SnapHmm(Text): try: return dataset.peek except Exception: - return "SNAP HMM model (%s)" % (nice_size(dataset.get_size())) + return f"SNAP HMM model ({nice_size(dataset.get_size())})" def sniff_prefix(self, file_prefix): """ @@ -55,7 +55,7 @@ class Augustus(CompressedArchive): try: return dataset.peek except Exception: - return "Augustus model (%s)" % (nice_size(dataset.get_size())) + return f"Augustus model ({nice_size(dataset.get_size())})" def sniff(self, filename): """ diff --git a/lib/galaxy/datatypes/anvio.py b/lib/galaxy/datatypes/anvio.py index 6825be459e0..f88e9e0c788 100644 --- a/lib/galaxy/datatypes/anvio.py +++ b/lib/galaxy/datatypes/anvio.py @@ -28,7 +28,7 @@ class AnvioComposite(Html): cannot rename the datasets here - they come with the default unfortunately """ defined_files = self.get_composite_files(dataset=dataset).items() - rval = ["Files for Anvi'o Composite Dataset (%s)" % (self.file_ext)] + rval = [f"Files for Anvi'o Composite Dataset ({self.file_ext})"] if defined_files: rval.append("

This composite dataset is composed of the following defined files:

') @@ -324,13 +324,13 @@ class Rgenetics(Html): efp = dataset.extra_files_path except Exception: if verbose: - gal_Log.debug('@@@rgenetics set_meta failed {} - dataset {} has no efp ?'.format(sys.exc_info()[0], dataset.name)) + gal_Log.debug(f'@@@rgenetics set_meta failed {sys.exc_info()[0]} - dataset {dataset.name} has no efp ?') return False try: flist = os.listdir(efp) except Exception: if verbose: - gal_Log.debug('@@@rgenetics set_meta failed {} - dataset {} has no efp ?'.format(sys.exc_info()[0], dataset.name)) + gal_Log.debug(f'@@@rgenetics set_meta failed {sys.exc_info()[0]} - dataset {dataset.name} has no efp ?') return False if len(flist) == 0: if verbose: @@ -659,7 +659,7 @@ class RexpBase(Html): for j in range(i + 1, nuse): kdict = {} for row in phe: # row is a list of lists - k = '{}{}'.format(row[i], row[j]) # composite key + k = f'{row[i]}{row[j]}' # composite key kdict[k] = k if (len(kdict.keys()) == len(concordance[useCols[j]])): # i and j are always matched delme.append(j) @@ -707,12 +707,12 @@ class RexpBase(Html): note that R is weird and does not include the row.name in the header. why?""" if not dataset.dataset.purged: - pp = os.path.join(dataset.extra_files_path, '%s.pheno' % dataset.metadata.base_name) + pp = os.path.join(dataset.extra_files_path, f'{dataset.metadata.base_name}.pheno') try: with open(pp) as f: p = f.readlines() except Exception: - p = ['##failed to find %s' % pp, ] + p = [f'##failed to find {pp}', ] dataset.peek = ''.join(p[:5]) dataset.blurb = 'Galaxy Rexpression composite file' else: @@ -723,12 +723,12 @@ class RexpBase(Html): """ expects a .pheno file in the extra_files_dir - ugh """ - pp = os.path.join(dataset.extra_files_path, '%s.pheno' % dataset.metadata.base_name) + pp = os.path.join(dataset.extra_files_path, f'{dataset.metadata.base_name}.pheno') try: with open(pp) as f: p = f.readlines() except Exception: - p = ['##failed to find %s' % pp] + p = [f'##failed to find {pp}'] return ''.join(p[:5]) def get_file_peek(self, filename): @@ -749,7 +749,7 @@ class RexpBase(Html): """ bn = dataset.metadata.base_name flist = os.listdir(dataset.extra_files_path) - rval = ['Files for Composite Dataset %s

Comprises the following files:

') @@ -600,10 +600,10 @@ class Laj(data.Text): if not dataset.dataset.purged: if hasattr(dataset, 'history_id'): params = { - "alignfile1": "display?id=%s" % dataset.id, + "alignfile1": f"display?id={dataset.id}", "buttonlabel": "Launch LAJ", "title": "LAJ in Galaxy", - "posturl": quote_plus("history_add_to?%s" % "&".join(f"{key}={value}" for key, value in {'history_id': dataset.history_id, 'ext': 'lav', 'name': 'LAJ Output', 'info': 'Added by LAJ', 'dbkey': dataset.dbkey, 'copy_access_from': dataset.id}.items())), + "posturl": quote_plus(f"history_add_to?{'&'.join(f'{key}={value}' for key, value in {'history_id': dataset.history_id, 'ext': 'lav', 'name': 'LAJ Output', 'info': 'Added by LAJ', 'dbkey': dataset.dbkey, 'copy_access_from': dataset.id}.items())}"), "noseq": "true" } class_name = "edu.psu.cse.bio.laj.LajApplet.class" diff --git a/lib/galaxy/datatypes/interval.py b/lib/galaxy/datatypes/interval.py index ec4c443c65a..9ad9822b4cb 100644 --- a/lib/galaxy/datatypes/interval.py +++ b/lib/galaxy/datatypes/interval.py @@ -190,7 +190,7 @@ class Interval(Tabular): # Make sure we are at the next new line readline_count = VIEWPORT_MAX_READS_PER_LINE while line.rstrip('\n\r') == line: - assert readline_count > 0, Exception('Viewport readline count exceeded for dataset %s.' % dataset.id) + assert readline_count > 0, Exception(f'Viewport readline count exceeded for dataset {dataset.id}.') line = fh.readline(VIEWPORT_READLINE_BUFFER_SIZE) if not line: break # EOF @@ -605,7 +605,7 @@ class _RemoteCallMixin: the data available, followed by redirecting to the remote site with a link back to the available information. """ - internal_url = "%s" % app.url_for(controller='dataset', dataset_id=dataset.id, action='display_at', filename=f'{type}_{site_name}') + internal_url = f"{app.url_for(controller='dataset', dataset_id=dataset.id, action='display_at', filename=f'{type}_{site_name}')}" base_url = app.config.get("display_at_callback", base_url) display_url = quote_plus("%s%s/display_as?id=%i&display_app=%s&authz_method=display_at" % (base_url, app.url_for(controller='root'), dataset.id, type)) @@ -734,7 +734,7 @@ class Gff(Tabular, _RemoteCallMixin): stop = int(elems[1].split('..')[1]) break # use location declared in file else: - log.debug("line (%s) uses an unsupported ##sequence-region definition." % str(line)) + log.debug(f"line ({str(line)}) uses an unsupported ##sequence-region definition.") # break #no break, if bad definition, we try another line elif line.startswith("browser position"): # Allow UCSC style browser and track info in the GFF file @@ -759,7 +759,7 @@ class Gff(Tabular, _RemoteCallMixin): # make sure we are at the next new line readline_count = VIEWPORT_MAX_READS_PER_LINE while line.rstrip('\n\r') == line: - assert readline_count > 0, Exception('Viewport readline count exceeded for dataset %s.' % dataset.id) + assert readline_count > 0, Exception(f'Viewport readline count exceeded for dataset {dataset.id}.') line = fh.readline(VIEWPORT_READLINE_BUFFER_SIZE) if not line: break # EOF @@ -1139,7 +1139,7 @@ class Wiggle(Tabular, _RemoteCallMixin): # make sure we are at the next new line readline_count = VIEWPORT_MAX_READS_PER_LINE while line.rstrip('\n\r') == line: - assert readline_count > 0, Exception('Viewport readline count exceeded for dataset %s.' % dataset.id) + assert readline_count > 0, Exception(f'Viewport readline count exceeded for dataset {dataset.id}.') line = fh.readline(VIEWPORT_READLINE_BUFFER_SIZE) if not line: break # EOF @@ -1319,7 +1319,7 @@ class CustomTrack(Tabular): # make sure we are at the next new line readline_count = VIEWPORT_MAX_READS_PER_LINE while line.rstrip('\n\r') == line: - assert readline_count > 0, Exception('Viewport readline count exceeded for dataset %s.' % dataset.id) + assert readline_count > 0, Exception(f'Viewport readline count exceeded for dataset {dataset.id}.') line = fh.readline(VIEWPORT_READLINE_BUFFER_SIZE) if not line: break # EOF @@ -1338,7 +1338,7 @@ class CustomTrack(Tabular): if chrom is not None: for site_name, site_url in app.datatypes_registry.get_legacy_sites_by_build('ucsc', dataset.dbkey): if site_name in app.datatypes_registry.get_display_sites('ucsc'): - internal_url = "%s" % app.url_for(controller='dataset', dataset_id=dataset.id, action='display_at', filename='ucsc_' + site_name) + internal_url = f"{app.url_for(controller='dataset', dataset_id=dataset.id, action='display_at', filename='ucsc_' + site_name)}" display_url = quote_plus("%s%s/display_as?id=%i&display_app=%s&authz_method=display_at" % (base_url, app.url_for(controller='root'), dataset.id, type)) redirect_url = quote_plus(f"{site_url}db={dataset.dbkey}&position={chrom}:{start}-{stop}&hgt.customText=%s") link = f'{internal_url}?redirect_url={redirect_url}&display_url={display_url}' diff --git a/lib/galaxy/datatypes/isa.py b/lib/galaxy/datatypes/isa.py index 6da11a8dc0c..1511023ca84 100644 --- a/lib/galaxy/datatypes/isa.py +++ b/lib/galaxy/datatypes/isa.py @@ -179,11 +179,11 @@ class _Isa(data.Data): line = line.strip() if not line: continue - out.append('%s' % escape(util.unicodify(line, 'utf-8'))) + out.append(f"{escape(util.unicodify(line, 'utf-8'))}") out.append('') out = "".join(out) except Exception as exc: - out = "Can't create peek: %s" % util.unicodify(exc) + out = f"Can't create peek: {util.unicodify(exc)}" return out # Generate primary file {{{2 @@ -198,7 +198,7 @@ class _Isa(data.Data): if hasattr(dataset, "extra_files_path"): rval.append('
ISA Dataset composed of the following files:

') else: rval.append('
ISA Dataset is empty!

') @@ -835,7 +835,7 @@ class ThermoRAW(Binary): try: return dataset.peek except Exception: - return "Thermo Finnigan RAW file (%s)" % (nice_size(dataset.get_size())) + return f"Thermo Finnigan RAW file ({nice_size(dataset.get_size())})" @build_sniff_from_prefix @@ -898,7 +898,7 @@ class SPLib(Msp): if composite_file.optional: opt_text = ' (optional)' if composite_file.get('description'): - rval.append('
  • {} ({}){}
  • '.format(fn, fn, composite_file.get('description'), opt_text)) + rval.append(f"
  • {fn} ({composite_file.get('description')}){opt_text}
  • ") else: rval.append(f'
  • {fn}{opt_text}
  • ') rval.append('') @@ -942,7 +942,7 @@ class Ms2(Text): for header_field in ['CreationDate', 'Extractor', 'ExtractorVersion', 'ExtractorOptions']: found_header = False for header_line in header_lines: - if header_line.startswith('H\t%s' % (header_field)): + if header_line.startswith(f'H\t{header_field}'): found_header = True break if not found_header: @@ -993,7 +993,7 @@ class ImzML(Binary): fn = composite_name opt_text = '' if composite_file.get('description'): - rval.append('
  • {} ({}){}
  • '.format(fn, fn, composite_file.get('description'), opt_text)) + rval.append(f"
  • {fn} ({composite_file.get('description')}){opt_text}
  • ") else: rval.append(f'
  • {fn}{opt_text}
  • ') rval.append('') diff --git a/lib/galaxy/datatypes/registry.py b/lib/galaxy/datatypes/registry.py index 15c3293b16a..a2669f872ea 100644 --- a/lib/galaxy/datatypes/registry.py +++ b/lib/galaxy/datatypes/registry.py @@ -112,9 +112,9 @@ class Registry: root = tree.getroot() # Load datatypes and converters from config if deactivate: - self.log.debug('Deactivating datatypes from %s' % config) + self.log.debug(f'Deactivating datatypes from {config}') else: - self.log.debug('Loading datatypes from %s' % config) + self.log.debug(f'Loading datatypes from {config}') else: root = config registration = root.find('registration') @@ -131,7 +131,7 @@ class Registry: self.converters_path_attr = os.path.abspath(os.path.join(os.path.dirname(__file__), 'converters')) self.converters_path = self.converters_path_attr if not os.path.isdir(self.converters_path): - raise ConfigurationError("Directory does not exist: %s" % self.converters_path) + raise ConfigurationError(f"Directory does not exist: {self.converters_path}") if use_display_applications: if not self.display_applications_path: self.display_path_attr = registration.get('display_path', 'display_applications') @@ -204,7 +204,7 @@ class Registry: del self.datatypes_by_extension[extension] if extension in self.upload_file_formats: self.upload_file_formats.remove(extension) - self.log.debug("Removed datatype with extension '%s' from the registry." % extension) + self.log.debug(f"Removed datatype with extension '{extension}' from the registry.") else: # We are loading new datatype, so we'll make sure it is correctly defined before proceeding. can_process_datatype = False @@ -247,14 +247,14 @@ class Registry: for mod in fields: module = getattr(module, mod) datatype_class = getattr(module, datatype_class_name) - self.log.debug('Retrieved datatype module {}:{} from the datatype registry for extension {}.'.format(str(datatype_module), datatype_class_name, extension)) + self.log.debug(f'Retrieved datatype module {str(datatype_module)}:{datatype_class_name} from the datatype registry for extension {extension}.') except Exception: self.log.exception('Error importing datatype module %s', str(datatype_module)) ok = False elif type_extension is not None: try: datatype_class = self.datatypes_by_extension[type_extension].__class__ - self.log.debug('Retrieved datatype module {} from type_extension {} for extension {}.'.format(str(datatype_class.__name__), type_extension, extension)) + self.log.debug(f'Retrieved datatype module {str(datatype_class.__name__)} from type_extension {type_extension} for extension {extension}.') except Exception: self.log.exception('Error determining datatype_class for type_extension %s', str(type_extension)) ok = False @@ -307,7 +307,7 @@ class Registry: for composite_file in elem.findall('composite_file'): name = composite_file.get('name', None) if name is None: - self.log.warning("You must provide a name for your composite_file (%s)." % composite_file) + self.log.warning(f"You must provide a name for your composite_file ({composite_file}).") optional = composite_file.get('optional', False) mimetype = composite_file.get('mimetype', None) self.datatypes_by_extension[extension].add_composite_file(name, optional=optional, mimetype=mimetype) @@ -339,7 +339,7 @@ class Registry: elif auto_compressed_type == "bz2": dynamic_parent = binary.Bz2DynamicCompressedArchive else: - raise Exception("Unknown auto compression type [%s]" % auto_compressed_type) + raise Exception(f"Unknown auto compression type [{auto_compressed_type}]") attributes["file_ext"] = compressed_extension attributes["uncompressed_datatype_instance"] = datatype_instance compressed_datatype_class = type(auto_compressed_type_name, (datatype_class, dynamic_parent, ), attributes) @@ -357,7 +357,7 @@ class Registry: "description": description, "description_url": description_url, }) - self.converters.append(("%s_to_uncompressed.xml" % auto_compressed_type, compressed_extension, extension)) + self.converters.append((f"{auto_compressed_type}_to_uncompressed.xml", compressed_extension, extension)) if datatype_class not in compressed_sniffers: compressed_sniffers[datatype_class] = [] if sniff_compressed_types: @@ -411,7 +411,7 @@ class Registry: site_type = build_site_config.get('type') path = build_site_config.get('file') if not os.path.exists(path): - sample_path = "%s.sample" % path + sample_path = f"{path}.sample" if os.path.exists(sample_path): self.log.debug(f"Build site file [{path}] not found using sample [{sample_path}].") path = sample_path @@ -511,12 +511,12 @@ class Registry: if sniffer_class == s_e_c: del self.sniffer_elems[index] sniffer_elem_classes = [elem.attrib['type'] for elem in self.sniffer_elems] - self.log.debug("Removed sniffer element for datatype '%s'" % str(dtype)) + self.log.debug(f"Removed sniffer element for datatype '{str(dtype)}'") break for sniffer_class in self.sniff_order: if sniffer_class.__class__ == aclass.__class__: self.sniff_order.remove(sniffer_class) - self.log.debug("Removed sniffer class for datatype '%s' from sniff order" % str(dtype)) + self.log.debug(f"Removed sniffer class for datatype '{str(dtype)}' from sniff order") break else: # We are loading new sniffer, so see if we have a conflicting sniffer already loaded. @@ -527,14 +527,14 @@ class Registry: conflict = True if override: del self.sniff_order[conflict_loc] - self.log.debug("Removed conflicting sniffer for datatype '%s'" % dtype) + self.log.debug(f"Removed conflicting sniffer for datatype '{dtype}'") break if not conflict or override: if compressed_sniffers and aclass.__class__ in compressed_sniffers: for compressed_sniffer in compressed_sniffers[aclass.__class__]: self.sniff_order.append(compressed_sniffer) self.sniff_order.append(aclass) - self.log.debug("Loaded sniffer for datatype '%s'" % dtype) + self.log.debug(f"Loaded sniffer for datatype '{dtype}'") # Processing the new sniffer elem is now complete, so make sure the element defining it is loaded if necessary. sniffer_class = elem.get('type', None) if sniffer_class is not None: @@ -573,7 +573,7 @@ class Registry: except KeyError: # datatype was never declared mimetype = default - self.log.warning('unknown mimetype in data factory %s' % str(ext)) + self.log.warning(f'unknown mimetype in data factory {str(ext)}') return mimetype def get_datatype_by_extension(self, ext): @@ -644,9 +644,9 @@ class Registry: self.log.debug("Loaded converter: %s", converter.id) except Exception: if deactivate: - self.log.exception("Error deactivating converter from (%s)" % converter_path) + self.log.exception(f"Error deactivating converter from ({converter_path})") else: - self.log.exception("Error loading converter (%s)" % converter_path) + self.log.exception(f"Error loading converter ({converter_path})") def load_display_applications(self, app, installed_repository_dict=None, deactivate=False): """ @@ -712,9 +712,9 @@ class Registry: self.log.debug(f"Loaded display application '{display_app.id}' for datatype '{extension}', inherit={inherit}.") except Exception: if deactivate: - self.log.exception("Error deactivating display application (%s)" % config_path) + self.log.exception(f"Error deactivating display application ({config_path})") else: - self.log.exception("Error loading display application (%s)" % config_path) + self.log.exception(f"Error loading display application ({config_path})") # Handle display_application subclass inheritance. for extension, d_type1 in self.datatypes_by_extension.items(): for d_type2, display_app in self.inherit_display_application_by_class: diff --git a/lib/galaxy/datatypes/sequence.py b/lib/galaxy/datatypes/sequence.py index 4c75f7f7101..d30f251edac 100644 --- a/lib/galaxy/datatypes/sequence.py +++ b/lib/galaxy/datatypes/sequence.py @@ -113,7 +113,7 @@ class Sequence(data.Text): if not dataset.dataset.purged: dataset.peek = data.get_file_peek(dataset.file_name) if dataset.metadata.sequences: - dataset.blurb = "%s sequences" % util.commaify(str(dataset.metadata.sequences)) + dataset.blurb = f"{util.commaify(str(dataset.metadata.sequences))} sequences" else: dataset.blurb = nice_size(dataset.get_size()) else: @@ -137,7 +137,7 @@ class Sequence(data.Text): if rem > 0: sequences_per_file.append(rem) else: - raise Exception('Unsupported split mode %s' % split_params['split_mode']) + raise Exception(f"Unsupported split mode {split_params['split_mode']}") return sequences_per_file @classmethod @@ -192,7 +192,7 @@ class Sequence(data.Text): if toc_file_datasets is not None: toc = toc_file_datasets[ds_no] split_data['args']['toc_file'] = toc.file_name - with open(os.path.join(dir, 'split_info_%s.json' % base_name), 'w') as f: + with open(os.path.join(dir, f'split_info_{base_name}.json'), 'w') as f: json.dump(split_data, f) start_sequence += sequences_per_file[part_no] return directories @@ -232,7 +232,7 @@ class Sequence(data.Text): current_sequence += int(sections[i]['sequences']) i += 1 if i == len(sections): # bad input data! - raise Exception('No FQTOC section contains starting sequence %s' % start_sequence) + raise Exception(f'No FQTOC section contains starting sequence {start_sequence}') # These two variables act as an accumulator for consecutive entire blocks that # can be copied verbatim (without decompressing) @@ -268,7 +268,7 @@ class Sequence(data.Text): result.append(copy_chunk_cmd % (start_chunk, end_chunk - start_chunk, input_name, output_name)) if sequence_count > 0: - raise Exception('%s sequences not found in file' % sequence_count) + raise Exception(f'{sequence_count} sequences not found in file') return result @@ -285,10 +285,10 @@ class Sequence(data.Text): line_count = sequence_count * 4 # TODO: verify that tail can handle 64-bit numbers if is_compressed: - cmd = 'zcat "{}" | ( tail -n +{} 2> /dev/null) | head -{} | gzip -c'.format(input_name, start_line + 1, line_count) + cmd = f'zcat "{input_name}" | ( tail -n +{start_line + 1} 2> /dev/null) | head -{line_count} | gzip -c' else: - cmd = 'tail -n +{} "{}" 2> /dev/null | head -{}'.format(start_line + 1, input_name, line_count) - cmd += ' > "%s"' % output_name + cmd = f'tail -n +{start_line + 1} "{input_name}" 2> /dev/null | head -{line_count}' + cmd += f' > "{output_name}"' return [cmd] @@ -412,7 +412,7 @@ class Fasta(Sequence): log.debug("Split %s into batches of %i records..." % (input_file, batch_size)) cls._count_split(input_file, batch_size, subdir_generator_function) else: - raise Exception('Unsupported split mode %s' % split_params['split_mode']) + raise Exception(f"Unsupported split mode {split_params['split_mode']}") @classmethod def _size_split(cls, input_file, chunk_size, subdir_generator_function): @@ -625,10 +625,10 @@ class Fastg(Sequence): if not dataset.dataset.purged: dataset.peek = data.get_file_peek(dataset.file_name) if dataset.metadata.sequences: - dataset.blurb = "%s sequences" % util.commaify(str(dataset.metadata.sequences)) + dataset.blurb = f"{util.commaify(str(dataset.metadata.sequences))} sequences" else: dataset.blurb = nice_size(dataset.get_size()) - dataset.blurb += '\nversion=%s' % dataset.metadata.version + dataset.blurb += f'\nversion={dataset.metadata.version}' for k, v in dataset.metadata.properties.items(): if k != 'version': dataset.blurb += f'\n{k}={v}' @@ -908,7 +908,7 @@ class Maf(Alignment): # The file must exist on disk for the get_file_peek() method dataset.peek = data.get_file_peek(dataset.file_name) if dataset.metadata.blocks: - dataset.blurb = "%s blocks" % util.commaify(str(dataset.metadata.blocks)) + dataset.blurb = f"{util.commaify(str(dataset.metadata.blocks))} blocks" else: # Number of blocks is not known ( this should not happen ), and auto-detect is # needed to set metadata @@ -928,7 +928,7 @@ class Maf(Alignment): try: out.append('Species: ') for species in dataset.metadata.species: - out.append('%s ' % species) + out.append(f'{species} ') out.append('') if not dataset.peek: dataset.set_peek() @@ -938,11 +938,11 @@ class Maf(Alignment): line = line.strip() if not line: continue - out.append('%s' % escape(line)) + out.append(f'{escape(line)}') out.append('') out = "".join(out) except Exception as exc: - out = "Can't create peek %s" % exc + out = f"Can't create peek {exc}" return out def sniff_prefix(self, file_prefix): diff --git a/lib/galaxy/datatypes/sniff.py b/lib/galaxy/datatypes/sniff.py index 82a4a88232f..6c8c04a75c3 100644 --- a/lib/galaxy/datatypes/sniff.py +++ b/lib/galaxy/datatypes/sniff.py @@ -710,7 +710,7 @@ def handle_compressed_file( except OSError as e: os.remove(uncompressed.name) compressed_file.close() - raise OSError('Problem uncompressing {} data, please try retrieving the data uncompressed: {}'.format(compressed_type, util.unicodify(e))) + raise OSError(f'Problem uncompressing {compressed_type} data, please try retrieving the data uncompressed: {util.unicodify(e)}') if not chunk: break uncompressed.write(chunk) diff --git a/lib/galaxy/datatypes/tabular.py b/lib/galaxy/datatypes/tabular.py index 2716e1ceea3..95d1fbf28e7 100644 --- a/lib/galaxy/datatypes/tabular.py +++ b/lib/galaxy/datatypes/tabular.py @@ -55,7 +55,7 @@ class TabularData(data.Text): def set_peek(self, dataset, line_count=None, is_multi_byte=False, WIDTH=256, skipchars=None, line_wrap=False, **kwd): super().set_peek(dataset, line_count=line_count, WIDTH=WIDTH, skipchars=skipchars, line_wrap=line_wrap) if dataset.metadata.comment_lines: - dataset.blurb = "{}, {} comments".format(dataset.blurb, util.commaify(str(dataset.metadata.comment_lines))) + dataset.blurb = f"{dataset.blurb}, {util.commaify(str(dataset.metadata.comment_lines))} comments" def displayable(self, dataset): try: @@ -137,7 +137,7 @@ class TabularData(data.Text): out.append('') out = "".join(out) except Exception as exc: - out = "Can't create peek: %s" % util.unicodify(exc) + out = f"Can't create peek: {util.unicodify(exc)}" return out def make_html_peek_header(self, dataset, skipchars=None, column_names=None, column_number_format='%s', column_parameter_alias=None, **kwargs): @@ -179,12 +179,12 @@ class TabularData(data.Text): if header is None: out.append(column_number_format % str(i + 1)) else: - out.append('{}.{}'.format(str(i + 1), escape(header))) + out.append(f'{str(i + 1)}.{escape(header)}') out.append('') out.append('') except Exception as exc: log.exception('make_html_peek_header failed on HDA %s', dataset.id) - raise Exception("Can't create peek header: %s" % util.unicodify(exc)) + raise Exception(f"Can't create peek header: {util.unicodify(exc)}") return "".join(out) def make_html_peek_rows(self, dataset, skipchars=None, **kwargs): @@ -204,7 +204,7 @@ class TabularData(data.Text): for i, line in enumerate(peek.splitlines()): if i >= self.data_line_offset: if line.startswith(tuple(skipchars)): - out.append('%s' % escape(line)) + out.append(f'{escape(line)}') elif line: elems = line.split(dataset.metadata.delimiter) elems = elems[:min(len(elems), self.max_peek_columns)] @@ -213,15 +213,15 @@ class TabularData(data.Text): elems.extend([''] * (columns - len(elems))) # we may have an invalid comment line or invalid data if len(elems) != columns: - out.append('%s' % escape(line)) + out.append(f'{escape(line)}') else: out.append('') for elem in elems: - out.append('%s' % escape(elem)) + out.append(f'{escape(elem)}') out.append('') except Exception as exc: log.exception('make_html_peek_rows failed on HDA %s', dataset.id) - raise Exception("Can't create peek rows: %s" % util.unicodify(exc)) + raise Exception(f"Can't create peek rows: {util.unicodify(exc)}") return "".join(out) def display_peek(self, dataset): @@ -344,7 +344,7 @@ class Tabular(TabularData): is_column_type = {} # Dict to store column type string to checking function for column_type in column_type_set_order: - is_column_type[column_type] = locals()["is_%s" % (column_type)] + is_column_type[column_type] = locals()[f"is_{column_type}"] def guess_column_type(column_text): for column_type in column_type_set_order: @@ -764,13 +764,13 @@ class BaseVcf(Tabular): stderr_f = tempfile.NamedTemporaryFile(prefix="bam_merge_stderr") stderr_name = stderr_f.name command = ["bcftools", "concat"] + split_files + ["-o", output_file] - log.info("Merging vcf files with command [%s]" % " ".join(command)) + log.info(f"Merging vcf files with command [{' '.join(command)}]") exit_code = subprocess.call(args=command, stderr=open(stderr_name, 'wb')) with open(stderr_name, "rb") as f: stderr = f.read().strip() # Did merge succeed? if exit_code != 0: - raise Exception("Error merging VCF files: %s" % stderr) + raise Exception(f"Error merging VCF files: {stderr}") def validate(self, dataset, **kwd): def validate_row(row): @@ -829,7 +829,7 @@ class VcfGz(BaseVcf, binary.Binary): try: pysam.tabix_index(dataset.file_name, index=index_file.file_name, preset='vcf', keep_original=True, force=True) except Exception as e: - raise Exception('Error setting VCF.gz metadata: %s' % (util.unicodify(e))) + raise Exception(f'Error setting VCF.gz metadata: {util.unicodify(e)}') dataset.metadata.tabix_index = index_file @@ -865,7 +865,7 @@ class Eland(Tabular): # Generate column header out.append('') for i, name in enumerate(self.column_names): - out.append('{}.{}'.format(str(i + 1), name)) + out.append(f'{str(i + 1)}.{name}') # This data type requires at least 11 columns in the data if dataset.metadata.columns - len(self.column_names) > 0: for i in range(len(self.column_names), max(dataset.metadata.columns, self.max_peek_columns)): @@ -875,7 +875,7 @@ class Eland(Tabular): out.append('') out = "".join(out) except Exception as exc: - out = "Can't create peek %s" % exc + out = f"Can't create peek {exc}" return out def sniff_prefix(self, file_prefix): diff --git a/lib/galaxy/datatypes/text.py b/lib/galaxy/datatypes/text.py index 56fa5b863b9..43c99941335 100644 --- a/lib/galaxy/datatypes/text.py +++ b/lib/galaxy/datatypes/text.py @@ -105,7 +105,7 @@ class Json(Text): try: return dataset.peek except Exception: - return "JSON file (%s)" % (nice_size(dataset.get_size())) + return f"JSON file ({nice_size(dataset.get_size())})" class ExpressionJson(Json): @@ -183,7 +183,7 @@ class Ipynb(Json): try: cmd = ['jupyter', 'nbconvert', '--to', 'html', '--template', 'full', dataset.file_name, '--output', ofilename] subprocess.check_call(cmd) - ofilename = '%s.html' % ofilename + ofilename = f'{ofilename}.html' except subprocess.CalledProcessError: ofilename = dataset.file_name log.exception('Command "%s" failed. Could not convert the Jupyter Notebook to HTML, defaulting to plain text.', ' '.join(map(shlex.quote, cmd))) @@ -617,12 +617,12 @@ class SnpEffDb(Text): dataset.metadata.annotation = annotations try: with open(dataset.file_name, 'w') as fh: - fh.write("%s\n" % genome_version if genome_version else 'Genome unknown') - fh.write("%s\n" % snpeff_version if snpeff_version else 'SnpEff version unknown') + fh.write(f"{genome_version}\n" if genome_version else 'Genome unknown') + fh.write(f"{snpeff_version}\n" if snpeff_version else 'SnpEff version unknown') if annotations: - fh.write("annotations: %s\n" % ','.join(annotations)) + fh.write(f"annotations: {','.join(annotations)}\n") if regulations: - fh.write("regulations: %s\n" % ','.join(regulations)) + fh.write(f"regulations: {','.join(regulations)}\n") except Exception: pass @@ -663,7 +663,7 @@ class SnpSiftDbNSFP(Text): """ cannot do this until we are setting metadata """ - annotations = "dbNSFP Annotations: %s\n" % ','.join(dataset.metadata.annotation) + annotations = f"dbNSFP Annotations: {','.join(dataset.metadata.annotation)}\n" with open(dataset.file_name, 'a') as f: if dataset.metadata.bgzip: bn = dataset.metadata.bgzip @@ -695,8 +695,8 @@ class SnpSiftDbNSFP(Text): def set_peek(self, dataset, is_multi_byte=False): if not dataset.dataset.purged: - dataset.peek = '{} : {}'.format(dataset.metadata.reference_name, ','.join(dataset.metadata.annotation)) - dataset.blurb = '%s' % dataset.metadata.reference_name + dataset.peek = f"{dataset.metadata.reference_name} : {','.join(dataset.metadata.annotation)}" + dataset.blurb = f'{dataset.metadata.reference_name}' else: dataset.peek = 'file does not exist' dataset.blurb = 'file purged from disc' diff --git a/lib/galaxy/datatypes/util/gff_util.py b/lib/galaxy/datatypes/util/gff_util.py index 7656870f02c..6a9e41ce9eb 100644 --- a/lib/galaxy/datatypes/util/gff_util.py +++ b/lib/galaxy/datatypes/util/gff_util.py @@ -371,12 +371,12 @@ def parse_gff3_attributes(attr_str): for tag_value_pair in attributes_list: pair = tag_value_pair.strip().split("=") if len(pair) == 1: - raise Exception("Attribute '%s' does not contain a '='" % tag_value_pair) + raise Exception(f"Attribute '{tag_value_pair}' does not contain a '='") if pair == '': continue tag = pair[0].strip() if tag == '': - raise Exception("Empty tag in attribute '%s'" % tag_value_pair) + raise Exception(f"Empty tag in attribute '{tag_value_pair}'") value = pair[1].strip() attributes[tag] = value return attributes diff --git a/lib/galaxy/datatypes/util/maf_utilities.py b/lib/galaxy/datatypes/util/maf_utilities.py index 5abc068e829..28fda0fd885 100644 --- a/lib/galaxy/datatypes/util/maf_utilities.py +++ b/lib/galaxy/datatypes/util/maf_utilities.py @@ -51,7 +51,7 @@ def get_species_in_block(block): def tool_fail(msg="Unknown Error"): - sys.exit("Fatal Error: %s" % msg) + sys.exit(f"Fatal Error: {msg}") class TempFileHandler: @@ -604,7 +604,7 @@ def get_starts_ends_fields_from_gene_bed(line): fields = line.split() # Requires atleast 12 BED columns if len(fields) < 12: - raise Exception("Not a proper 12 column BED line (%s)." % line) + raise Exception(f"Not a proper 12 column BED line ({line}).") tx_start = int(fields[1]) strand = fields[5] if strand != '-': @@ -688,7 +688,7 @@ def get_fasta_header(component, attributes=None, suffix=None): if suffix: header = f"{header}{suffix}" else: - header = "{}{}".format(header, src_split(component.src)[0]) + header = f"{header}{src_split(component.src)[0]}" return header diff --git a/lib/galaxy/files/__init__.py b/lib/galaxy/files/__init__.py index 15259ef831d..f73bf710cd9 100644 --- a/lib/galaxy/files/__init__.py +++ b/lib/galaxy/files/__init__.py @@ -77,10 +77,10 @@ class ConfiguredFileSources: def get_file_source_path(self, uri): """Parse uri into a FileSource object and a path relative to its base.""" if "://" not in uri: - raise exceptions.RequestParameterInvalidException("Invalid uri [%s]" % uri) + raise exceptions.RequestParameterInvalidException(f"Invalid uri [{uri}]") scheme, rest = uri.split("://", 1) if scheme not in self.get_schemes(): - raise exceptions.RequestParameterInvalidException("Unsupported URI scheme [%s]" % scheme) + raise exceptions.RequestParameterInvalidException(f"Unsupported URI scheme [{scheme}]") if scheme != "gxfiles": # prefix unused @@ -132,7 +132,7 @@ class ConfiguredFileSources: # is this string a URI this object understands how to realize if path_or_uri.startswith("gx") and "://" in path_or_uri: for scheme in self.get_schemes(): - if path_or_uri.startswith("%s://" % scheme): + if path_or_uri.startswith(f"{scheme}://"): return True return False diff --git a/lib/galaxy/files/sources/__init__.py b/lib/galaxy/files/sources/__init__.py index 455339e1043..e5d1d6d25a0 100644 --- a/lib/galaxy/files/sources/__init__.py +++ b/lib/galaxy/files/sources/__init__.py @@ -83,7 +83,7 @@ class BaseFilesSource(FilesSource): def get_uri_root(self): prefix = self.get_prefix() scheme = self.get_scheme() - root = "%s://" % scheme + root = f"{scheme}://" if prefix: root = uri_join(root, prefix) return root diff --git a/lib/galaxy/files/sources/posix.py b/lib/galaxy/files/sources/posix.py index df83b13bbc0..929765eaf61 100644 --- a/lib/galaxy/files/sources/posix.py +++ b/lib/galaxy/files/sources/posix.py @@ -33,7 +33,7 @@ class PosixFilesSource(BaseFilesSource): def _list(self, path="/", recursive=True, user_context=None): dir_path = self._to_native_path(path, user_context=user_context) if not self._safe_directory(dir_path): - raise exceptions.ObjectNotFound('The specified directory does not exist [%s].' % dir_path) + raise exceptions.ObjectNotFound(f'The specified directory does not exist [{dir_path}].') if recursive: res = [] for (p, dirs, files) in safe_walk(dir_path, allowlist=self._allowlist): @@ -107,7 +107,7 @@ class PosixFilesSource(BaseFilesSource): def _safe_directory(self, directory): if self.enforce_symlink_security: if not safe_path(directory, allowlist=self._allowlist): - raise exceptions.ConfigDoesNotAllowException('directory (%s) is a symlink to a location not on the allowlist' % directory) + raise exceptions.ConfigDoesNotAllowException(f'directory ({directory}) is a symlink to a location not on the allowlist') if not os.path.exists(directory): return False diff --git a/lib/galaxy/forms/forms.py b/lib/galaxy/forms/forms.py index 34886584914..a2a8effc116 100644 --- a/lib/galaxy/forms/forms.py +++ b/lib/galaxy/forms/forms.py @@ -62,7 +62,7 @@ class FormDefinitionFactory: if fields_elem is not None: for field_elem in fields_elem.findall('field'): field_type = field_elem.get('type') - assert field_type in self.field_type_factories, 'Invalid form field type ( %s ).' % field_type + assert field_type in self.field_type_factories, f'Invalid form field type ( {field_type} ).' fields.append(self.field_type_factories[field_type].from_elem(field_elem, layout)) # create and return new form return self.new(form_type, name, description=description, fields=fields, layout=layout, form_definition_current=form_definition_current) diff --git a/lib/galaxy/job_execution/datasets.py b/lib/galaxy/job_execution/datasets.py index afe85fae2f9..6af5d3acf9d 100644 --- a/lib/galaxy/job_execution/datasets.py +++ b/lib/galaxy/job_execution/datasets.py @@ -98,7 +98,7 @@ class OutputsToWorkingDirectoryPathRewriter: if self.outputs_directory_name is not None: base_output_directory = os.path.join(base_output_directory, self.outputs_directory_name) # set false_path to uuid, no harm even if object store uses id - false_path = os.path.join(base_output_directory, "galaxy_dataset_%s.dat" % dataset.dataset.uuid) + false_path = os.path.join(base_output_directory, f"galaxy_dataset_{dataset.dataset.uuid}.dat") return false_path else: return None diff --git a/lib/galaxy/job_execution/output_collect.py b/lib/galaxy/job_execution/output_collect.py index 979636562ab..bcc7973e6f7 100644 --- a/lib/galaxy/job_execution/output_collect.py +++ b/lib/galaxy/job_execution/output_collect.py @@ -401,7 +401,7 @@ def collect_primary_datasets(job_context, output, input_ext): fields_match = discovered_file.match if not fields_match: # Before I guess pop() would just have thrown an IndexError - raise Exception("Problem parsing metadata fields for file %s" % filename) + raise Exception(f"Problem parsing metadata fields for file {filename}") designation = fields_match.designation ext = fields_match.ext if ext == "input": @@ -610,7 +610,7 @@ def read_exit_code_from(exit_code_file, id_tag): def default_exit_code_file(files_dir, id_tag): - return os.path.join(files_dir, 'galaxy_%s.ec' % id_tag) + return os.path.join(files_dir, f'galaxy_{id_tag}.ec') def collect_extra_files(object_store, dataset, job_working_directory): diff --git a/lib/galaxy/job_execution/ports/view.py b/lib/galaxy/job_execution/ports/view.py index d9390c30496..0b4c94c5c7e 100644 --- a/lib/galaxy/job_execution/ports/view.py +++ b/lib/galaxy/job_execution/ports/view.py @@ -25,7 +25,7 @@ class JobPortsView: def __authorize_job_access(self, encoded_job_id, **kwargs): key = "job_key" if key not in kwargs: - error_message = "Job files action requires a valid '%s'." % key + error_message = f"Job files action requires a valid '{key}'." raise ObjectAttributeMissingException(error_message) job_id = self._security.decode_id(encoded_job_id) diff --git a/lib/galaxy/job_metrics/collectl/cli.py b/lib/galaxy/job_metrics/collectl/cli.py index 44d4845f2c2..bea4e4a7ba6 100644 --- a/lib/galaxy/job_metrics/collectl/cli.py +++ b/lib/galaxy/job_metrics/collectl/cli.py @@ -69,30 +69,30 @@ class CollectlCli: if self.mode == MODE_RECORD: mode_arg = "" elif self.mode == MODE_PLAYBACK: - mode_arg = "-P -p '%s'" % playback_path + mode_arg = f"-P -p '{playback_path}'" else: - raise Exception("Invalid mode supplied to CollectlCli - %s" % self.mode) + raise Exception(f"Invalid mode supplied to CollectlCli - {self.mode}") command_args["mode_arg"] = mode_arg command_args["interval_arg"] = self.__interval_arg(kwargs) destination = kwargs.get("destination_path", None) if destination: - destination_arg = "-f '%s'" % destination + destination_arg = f"-f '{destination}'" else: destination_arg = "" command_args["destination_arg"] = destination_arg procfilt = kwargs.get("procfilt", None) - command_args["procfilt_arg"] = "" if not procfilt else "--procfilt %s" % procfilt + command_args["procfilt_arg"] = "" if not procfilt else f"--procfilt {procfilt}" command_args["subsystems_arg"] = self.__subsystems_arg(kwargs.get("subsystems", [])) flush = kwargs.get("flush", None) - command_args["flush_arg"] = "--flush %s" % flush if flush else "" + command_args["flush_arg"] = f"--flush {flush}" if flush else "" sep = kwargs.get("sep", None) - command_args["sep_arg"] = "--sep=%s" % sep if sep else "" + command_args["sep_arg"] = f"--sep={sep}" if sep else "" self.command_args = command_args def __subsystems_arg(self, subsystems): if subsystems: - return "-s%s" % "".join(s.command_line_arg for s in subsystems) + return f"-s{''.join(s.command_line_arg for s in subsystems)}" else: return "" @@ -105,7 +105,7 @@ class CollectlCli: return "" self.__validate_interval_arg(interval) - interval_arg = "-i %s" % interval + interval_arg = f"-i {interval}" interval2 = kwargs.get("interval2", None) if not interval2: return interval_arg @@ -121,17 +121,17 @@ class CollectlCli: def __validate_interval_arg(self, value, multiple_of=None): if value and not str(value).isdigit(): - raise Exception("Invalid interval argument supplied, must be integer %s" % value) + raise Exception(f"Invalid interval argument supplied, must be integer {value}") if multiple_of: if int(value) % multiple_of != 0: - raise Exception("Invalid interval argument supplied, must multiple of %s" % multiple_of) + raise Exception(f"Invalid interval argument supplied, must multiple of {multiple_of}") def build_command_line(self): return COMMAND_LINE_TEMPLATE.substitute(**self.command_args) def run(self, stdout=subprocess.PIPE, stderr=subprocess.PIPE): command_line = self.build_command_line() - log.info("Executing %s" % command_line) + log.info(f"Executing {command_line}") proc = subprocess.Popen(command_line, shell=True, stdout=stdout, stderr=stderr) return_code = proc.wait() if return_code: diff --git a/lib/galaxy/job_metrics/collectl/processes.py b/lib/galaxy/job_metrics/collectl/processes.py index 17772b5fc93..c06037c0368 100644 --- a/lib/galaxy/job_metrics/collectl/processes.py +++ b/lib/galaxy/job_metrics/collectl/processes.py @@ -96,9 +96,9 @@ def parse_process_statistics(statistics): # Check for validity... for statistic in statistics: if statistic[0] not in STATISTIC_TYPES: - raise Exception("Unknown statistic type encountered %s" % statistic[0]) + raise Exception(f"Unknown statistic type encountered {statistic[0]}") if statistic[1] not in PROCESS_COLUMNS: - raise Exception("Unknown process column encountered %s" % statistic[1]) + raise Exception(f"Unknown process column encountered {statistic[1]}") return statistics @@ -119,7 +119,7 @@ def _read_process_statistics(tsv_file, pid, statistics): if current_interval is None: for header, expected_header in zip(row, PROCESS_COLUMNS): if header.lower() != expected_header.lower(): - raise Exception("Unknown header value encountered while processing collectl playback - %s" % header) + raise Exception(f"Unknown header value encountered while processing collectl playback - {header}") # First row, check contains correct header. current_interval = CollectlProcessInterval() diff --git a/lib/galaxy/job_metrics/instrumenters/collectl.py b/lib/galaxy/job_metrics/instrumenters/collectl.py index 33a18063d8a..3b696f0d89d 100644 --- a/lib/galaxy/job_metrics/instrumenters/collectl.py +++ b/lib/galaxy/job_metrics/instrumenters/collectl.py @@ -42,7 +42,7 @@ class CollectlFormatter(formatting.JobMetricFormatter): else: _, stat_type, resource_type = key.split("_", 2) if resource_type.startswith("Vm"): - value_str = "%s KB" % int(value) + value_str = f"{int(value)} KB" elif resource_type in ["RSYS", "WSYS"] and stat_type in ["count", "max", "sum"]: value_str = "%d (# system calls)" % int(value) else: @@ -63,7 +63,7 @@ class CollectlPlugin(InstrumentPlugin): self.__configure_subsystems(kwargs) saved_logs_path = kwargs.get("saved_logs_path", "") if "app" in kwargs: - log.debug("Found path for saved logs: %s" % saved_logs_path) + log.debug(f"Found path for saved logs: {saved_logs_path}") saved_logs_path = kwargs["app"].config.resolve_path(saved_logs_path) self.saved_logs_path = saved_logs_path self.__configure_collectl_recorder_args(kwargs) @@ -82,7 +82,7 @@ class CollectlPlugin(InstrumentPlugin): commands = [] # Capture PID of process so we can walk its ancestors when building # statistics for the whole job. - commands.append('''echo "$$" > '%s' ''' % self.__pid_file(job_directory)) + commands.append(f'''echo "$$" > '{self.__pid_file(job_directory)}' ''') # Run collectl in record mode to capture process and system level # statistics according to supplied subsystems. commands.append(self.__collectl_record_command(job_directory)) @@ -123,7 +123,7 @@ class CollectlPlugin(InstrumentPlugin): # Run collectl in playback and generate statistics of interest summary_statistics = self.__summarize_process_data(pid, path) for statistic, value in summary_statistics: - properties["process_%s" % "_".join(statistic)] = value + properties[f"process_{'_'.join(statistic)}"] = value return properties @@ -190,10 +190,7 @@ class CollectlPlugin(InstrumentPlugin): redirect_to = self._instrument_file_path(job_directory, "program_output") else: redirect_to = "/dev/null" - return "{} > {} 2>&1 &".format( - collectl_cli.build_command_line(), - redirect_to, - ) + return f"{collectl_cli.build_command_line()} > {redirect_to} 2>&1 &" def __pid_file(self, job_directory): return self._instrument_file_path(job_directory, "pid") diff --git a/lib/galaxy/job_metrics/instrumenters/core.py b/lib/galaxy/job_metrics/instrumenters/core.py index 17ddfe9a198..8f0419cb1f8 100644 --- a/lib/galaxy/job_metrics/instrumenters/core.py +++ b/lib/galaxy/job_metrics/instrumenters/core.py @@ -69,18 +69,18 @@ class CorePlugin(InstrumentPlugin): def __record_galaxy_slots_command(self, job_directory): galaxy_slots_file = self.__galaxy_slots_file(job_directory) - return '''echo "$GALAXY_SLOTS" > '%s' ''' % galaxy_slots_file + return f'''echo "$GALAXY_SLOTS" > '{galaxy_slots_file}' ''' def __record_galaxy_memory_mb_command(self, job_directory): galaxy_memory_mb_file = self.__galaxy_memory_mb_file(job_directory) - return '''echo "$GALAXY_MEMORY_MB" > '%s' ''' % galaxy_memory_mb_file + return f'''echo "$GALAXY_MEMORY_MB" > '{galaxy_memory_mb_file}' ''' def __record_seconds_since_epoch_to_file(self, job_directory, name): - path = self._instrument_file_path(job_directory, "epoch_%s" % name) + path = self._instrument_file_path(job_directory, f"epoch_{name}") return 'date +"%s" > ' + path def __read_seconds_since_epoch(self, job_directory, name): - path = self._instrument_file_path(job_directory, "epoch_%s" % name) + path = self._instrument_file_path(job_directory, f"epoch_{name}") return self.__read_integer(path) def __galaxy_slots_file(self, job_directory): diff --git a/lib/galaxy/job_metrics/instrumenters/cpuinfo.py b/lib/galaxy/job_metrics/instrumenters/cpuinfo.py index f6e877a95a9..9d6ed45e176 100644 --- a/lib/galaxy/job_metrics/instrumenters/cpuinfo.py +++ b/lib/galaxy/job_metrics/instrumenters/cpuinfo.py @@ -15,7 +15,7 @@ class CpuInfoFormatter(formatting.JobMetricFormatter): def format(self, key, value): if key == "processor_count": - return "Processor Count", "%s" % int(value) + return "Processor Count", f"{int(value)}" else: return key, value @@ -31,7 +31,7 @@ class CpuInfoPlugin(InstrumentPlugin): self.verbose = util.asbool(kwargs.get("verbose", False)) def pre_execute_instrument(self, job_directory): - return "cat /proc/cpuinfo > '%s'" % self.__instrument_cpuinfo_path(job_directory) + return f"cat /proc/cpuinfo > '{self.__instrument_cpuinfo_path(job_directory)}'" def job_properties(self, job_id, job_directory): properties = {} diff --git a/lib/galaxy/job_metrics/instrumenters/env.py b/lib/galaxy/job_metrics/instrumenters/env.py index a8c20455205..8e21dcd5709 100644 --- a/lib/galaxy/job_metrics/instrumenters/env.py +++ b/lib/galaxy/job_metrics/instrumenters/env.py @@ -30,7 +30,7 @@ class EnvPlugin(InstrumentPlugin): def pre_execute_instrument(self, job_directory): """ Use env to dump all environment variables to a file. """ - return "env > '%s'" % self.__env_file(job_directory) + return f"env > '{self.__env_file(job_directory)}'" def post_execute_instrument(self, job_directory): return None diff --git a/lib/galaxy/job_metrics/instrumenters/hostname.py b/lib/galaxy/job_metrics/instrumenters/hostname.py index a5c4862aa7b..f8cbe26b8d3 100644 --- a/lib/galaxy/job_metrics/instrumenters/hostname.py +++ b/lib/galaxy/job_metrics/instrumenters/hostname.py @@ -23,7 +23,7 @@ class HostnamePlugin(InstrumentPlugin): pass def pre_execute_instrument(self, job_directory): - return "hostname -f > '%s'" % self.__instrument_hostname_path(job_directory) + return f"hostname -f > '{self.__instrument_hostname_path(job_directory)}'" def job_properties(self, job_id, job_directory): with open(self.__instrument_hostname_path(job_directory)) as f: diff --git a/lib/galaxy/job_metrics/instrumenters/meminfo.py b/lib/galaxy/job_metrics/instrumenters/meminfo.py index d2a6ce13d62..7cdb212cc34 100644 --- a/lib/galaxy/job_metrics/instrumenters/meminfo.py +++ b/lib/galaxy/job_metrics/instrumenters/meminfo.py @@ -33,7 +33,7 @@ class MemInfoPlugin(InstrumentPlugin): self.verbose = util.asbool(kwargs.get("verbose", False)) def pre_execute_instrument(self, job_directory): - return "cat /proc/meminfo > '%s'" % self.__instrument_meminfo_path(job_directory) + return f"cat /proc/meminfo > '{self.__instrument_meminfo_path(job_directory)}'" def job_properties(self, job_id, job_directory): properties = {} diff --git a/lib/galaxy/job_metrics/instrumenters/uname.py b/lib/galaxy/job_metrics/instrumenters/uname.py index 8ff39e4ca7d..288ba2f5c42 100644 --- a/lib/galaxy/job_metrics/instrumenters/uname.py +++ b/lib/galaxy/job_metrics/instrumenters/uname.py @@ -20,7 +20,7 @@ class UnamePlugin(InstrumentPlugin): self.uname_args = kwargs.get("args", "-a") def pre_execute_instrument(self, job_directory): - return "uname {} > '{}'".format(self.uname_args, self.__instrument_uname_path(job_directory)) + return f"uname {self.uname_args} > '{self.__instrument_uname_path(job_directory)}'" def job_properties(self, job_id, job_directory): properties = {} diff --git a/lib/galaxy/jobs/__init__.py b/lib/galaxy/jobs/__init__.py index 9b33b3b647e..78666c1e2b2 100644 --- a/lib/galaxy/jobs/__init__.py +++ b/lib/galaxy/jobs/__init__.py @@ -130,7 +130,7 @@ class JobToolConfiguration(Bunch): def config_exception(e, file): abs_path = os.path.abspath(file) - message = 'Problem parsing the XML in file %s, ' % abs_path + message = f'Problem parsing the XML in file {abs_path}, ' message += 'please correct the indicated portion of the file and restart Galaxy. ' message += unicodify(e) log.exception(message) @@ -157,7 +157,7 @@ def job_config_xml_to_dict(config, root): kwds=runner_kwds) runners[plugin_id] = runner_info else: - log.error('Unknown plugin type: %s' % plugin.get('type')) + log.error(f"Unknown plugin type: {plugin.get('type')}") for plugin in ConfiguresHandlers._findall_with_required(plugins, 'plugin', ('id', 'type')): if plugin.get('id') == 'dynamic' and plugin.get('type') == 'runner': @@ -263,7 +263,7 @@ def job_config_xml_to_dict(config, root): limit_dict = {} for key in ['type', 'tag', 'id', 'window']: if key == 'type' and key.startswith('destination_'): - key = 'environment_%s' % key[len("destination_"):] + key = f"environment_{key[len('destination_'):]}" value = limit.get(key) if value: limit_dict[key] = value @@ -498,7 +498,7 @@ class JobConfiguration(ConfiguresHandlers): for limit_dict in job_config_dict.get("limits", []): limit_type = limit_dict.get('type') if limit_type.startswith("environment_"): - limit_type = 'destination_%s' % limit_type[len("environment_"):] + limit_type = f"destination_{limit_type[len('environment_'):]}" limit_value = limit_dict.get("value") # concurrent_jobs renamed to destination_user_concurrent_jobs in job_conf.xml @@ -536,7 +536,7 @@ class JobConfiguration(ConfiguresHandlers): :type tree: ``lxml.etree._Element`` """ root = tree.getroot() - log.debug('Loading job configuration from %s' % self.app.config.job_config_file) + log.debug(f'Loading job configuration from {self.app.config.job_config_file}') job_config_dict = job_config_xml_to_dict(self.app.config, root) return job_config_dict @@ -807,14 +807,14 @@ class JobConfiguration(ConfiguresHandlers): assert module.__all__ class_names = module.__all__ except AssertionError: - log.error('Runner "%s" does not contain a list of exported classes in __all__' % load) + log.error(f'Runner "{load}" does not contain a list of exported classes in __all__') continue for class_name in class_names: runner_class = getattr(module, class_name) try: assert issubclass(runner_class, BaseJobRunner) except TypeError: - log.warning("A non-class name was found in __all__, ignoring: %s" % id) + log.warning(f"A non-class name was found in __all__, ignoring: {id}") continue except AssertionError: log.warning(f"Job runner classes must be subclassed from BaseJobRunner, {id} has bases: {runner_class.__bases__}") @@ -1007,7 +1007,7 @@ class JobWrapper(HasResourceParameters): return self.app.config.use_tasked_jobs and self.tool.parallelism def get_job_runner_url(self): - log.warning('(%s) Job runner URLs are deprecated, use destinations instead.' % self.job_id) + log.warning(f'({self.job_id}) Job runner URLs are deprecated, use destinations instead.') return self.job_destination.url def get_parallelism(self): @@ -1079,7 +1079,7 @@ class JobWrapper(HasResourceParameters): job = self.get_job() for p in job.parameters: if p.name == "__validate_outputs__": - log.info("validate... %s" % p.value) + log.info(f"validate... {p.value}") return loads(p.value) return False @@ -1238,7 +1238,7 @@ class JobWrapper(HasResourceParameters): # Restore parameters from the database job = self.get_job() if job.user is None and job.galaxy_session is None: - raise Exception('Job %s has no user and no session.' % job.id) + raise Exception(f'Job {job.id} has no user and no session.') return job def _get_tool_evaluator(self, job): @@ -1672,7 +1672,7 @@ class JobWrapper(HasResourceParameters): else: # Prior to fail we need to set job.state job.set_state(final_job_state) - return self.fail("Job %s's output dataset(s) could not be read" % job.id) + return self.fail(f"Job {job.id}'s output dataset(s) could not be read") job_context = ExpressionContext(dict(stdout=job.stdout, stderr=job.stderr)) if extended_metadata: @@ -1860,7 +1860,7 @@ class JobWrapper(HasResourceParameters): job_metrics_directory = job_metrics_directory or self.working_directory per_plugin_properties = self.app.job_metrics.collect_properties(job.destination_id, self.job_id, job_metrics_directory) if per_plugin_properties: - log.info("Collecting metrics for {} {} in {}".format(type(has_metrics).__name__, getattr(has_metrics, 'id', None), job_metrics_directory)) + log.info(f"Collecting metrics for {type(has_metrics).__name__} {getattr(has_metrics, 'id', None)} in {job_metrics_directory}") for plugin, properties in per_plugin_properties.items(): for metric_name, metric_value in properties.items(): if metric_value is not None: @@ -2046,7 +2046,7 @@ class JobWrapper(HasResourceParameters): elif target == "pwd": return os.path.join(working_directory, "working") else: - raise Exception("Unknown target type [%s]" % target) + raise Exception(f"Unknown target type [{target}]") def get_tool_provided_job_metadata(self): if self.tool_provided_job_metadata is not None: @@ -2146,7 +2146,7 @@ class JobWrapper(HasResourceParameters): except ValueError: # File exists, but is not fully populated yet return False - log.debug("found container runtime %s" % container_runtime) + log.debug(f"found container runtime {container_runtime}") self.app.interactivetool_manager.configure_entry_points(job, container_runtime) return True container_exception_path = os.path.join(working_directory, "container_monitor_exception.txt") @@ -2192,7 +2192,7 @@ class JobWrapper(HasResourceParameters): with open(container_config, "w") as f: json.dump(container_config_dict, f) - return "(python '%s'/lib/galaxy_ext/container_monitor/monitor.py &); sleep 1 " % exec_dir + return f"(python '{exec_dir}'/lib/galaxy_ext/container_monitor/monitor.py &); sleep 1 " @property def user(self): @@ -2374,7 +2374,7 @@ class TaskWrapper(JobWrapper): return self.extra_filenames def fail(self, message, exception=False): - log.error("TaskWrapper Failure %s" % message) + log.error(f"TaskWrapper Failure {message}") self.status = 'error' # How do we want to handle task failure? Fail the job and let it clean up? diff --git a/lib/galaxy/jobs/actions/post.py b/lib/galaxy/jobs/actions/post.py index dc94ba99aef..7387500f609 100644 --- a/lib/galaxy/jobs/actions/post.py +++ b/lib/galaxy/jobs/actions/post.py @@ -30,9 +30,9 @@ class DefaultJobAction: @classmethod def get_short_str(cls, pja): if pja.action_arguments: - return "{} -> {}".format(pja.action_type, escape(pja.action_arguments)) + return f"{pja.action_type} -> {escape(pja.action_arguments)}" else: - return "%s" % pja.action_type + return f"{pja.action_type}" class EmailAction(DefaultJobAction): @@ -53,11 +53,11 @@ class EmailAction(DefaultJobAction): host = action.action_arguments['host'] else: host = socket.getfqdn() - frm = 'galaxy-no-reply@%s' % host + frm = f'galaxy-no-reply@{host}' to = job.user.email - subject = "Galaxy job completion notification from history '%s'" % (job.history.name) + subject = f"Galaxy job completion notification from history '{job.history.name}'" outdata = ',\n'.join(ds.dataset.display_name() for ds in job.output_datasets) - body = "Your Galaxy job generating dataset(s):\n\n{}\n\nis complete as of {}. Click the link below to access your data: \n{}".format(outdata, datetime.datetime.now().strftime("%I:%M"), link) + body = f"Your Galaxy job generating dataset(s):\n\n{outdata}\n\nis complete as of {datetime.datetime.now().strftime('%I:%M')}. Click the link below to access your data: \n{link}" send_mail(frm, to, subject, body, app.config) except Exception as e: log.error("EmailAction PJA Failed, exception: %s", unicodify(e)) @@ -65,7 +65,7 @@ class EmailAction(DefaultJobAction): @classmethod def get_short_str(cls, pja): if pja.action_arguments and 'host' in pja.action_arguments: - return "Email the current user from server %s when this job is complete." % escape(pja.action_arguments['host']) + return f"Email the current user from server {escape(pja.action_arguments['host'])} when this job is complete." else: return "Email the current user when this job is complete." @@ -264,7 +264,7 @@ class HideDatasetAction(DefaultJobAction): @classmethod def get_short_str(cls, pja): - return "Hide output '%s'." % escape(pja.output_name) + return f"Hide output '{escape(pja.output_name)}'." class DeleteDatasetAction(DefaultJobAction): @@ -440,7 +440,7 @@ class TagDatasetAction(DefaultJobAction): cls.direction, escape(pja.output_name)) else: - return "%s Tag action used without a tag specified. No tag will be added." % cls.action + return f"{cls.action} Tag action used without a tag specified. No tag will be added." class RemoveTagDatasetAction(TagDatasetAction): diff --git a/lib/galaxy/jobs/command_factory.py b/lib/galaxy/jobs/command_factory.py index 0fd189a7030..538ff13f1e8 100644 --- a/lib/galaxy/jobs/command_factory.py +++ b/lib/galaxy/jobs/command_factory.py @@ -124,7 +124,7 @@ def build_command( if include_metadata and job_wrapper.requires_setting_metadata: working_directory = remote_job_directory or job_wrapper.working_directory - commands_builder.append_command("cd '%s'" % working_directory) + commands_builder.append_command(f"cd '{working_directory}'") __handle_metadata(commands_builder, job_wrapper, runner, remote_command_params) return commands_builder.build() @@ -167,7 +167,7 @@ def __externalize_commands(job_wrapper, shell, commands_builder, remote_command_ # https://github.com/galaxyproject/galaxy/pull/8449 for_pulsar = False if 'script_directory' in remote_command_params: - commands = "{} {}".format(shell, join(remote_command_params['script_directory'], script_name)) + commands = f"{shell} {join(remote_command_params['script_directory'], script_name)}" for_pulsar = True if not for_pulsar: commands += " > ../outputs/tool_stdout 2> ../outputs/tool_stderr" @@ -263,9 +263,7 @@ class CommandsBuilder: def prepend_command(self, command, sep=";"): if command: - self.commands = "{}{} {}".format(command, - sep, - self.commands) + self.commands = f"{command}{sep} {self.commands}" return self def prepend_commands(self, commands): @@ -273,9 +271,7 @@ class CommandsBuilder: def append_command(self, command, sep=';'): if command: - self.commands = "{}{} {}".format(self.commands, - sep, - command) + self.commands = f"{self.commands}{sep} {command}" return self def append_commands(self, commands): @@ -288,8 +284,7 @@ trap 'rm "$out" "$err"' EXIT tee -a stdout.log < "$out" & tee -a stderr.log < "$err" >&2 &""", sep="") - self.append_command("> '{stdout_file}' 2> '{stderr_file}'".format(stdout_file=stdout_file, - stderr_file=stderr_file), + self.append_command(f"> '{stdout_file}' 2> '{stderr_file}'", sep="") def capture_return_code(self): diff --git a/lib/galaxy/jobs/dynamic_tool_destination.py b/lib/galaxy/jobs/dynamic_tool_destination.py index bc728b1ea8e..ad725a87e5b 100755 --- a/lib/galaxy/jobs/dynamic_tool_destination.py +++ b/lib/galaxy/jobs/dynamic_tool_destination.py @@ -1187,9 +1187,9 @@ def bytes_to_str(size, unit="YB"): i = 0 try: - return_str = "{:.2f} {}".format(size_changer, units[i]) + return_str = f"{size_changer:.2f} {units[i]}" except (ValueError, TypeError): - return_str = "%s" % (size_changer) + return_str = f"{size_changer}" return return_str @@ -1632,7 +1632,7 @@ def get_destination_list_from_job_config(job_config_location) -> set: possible_job_conf_path = os.path.join(config_location, f) if os.path.isfile(possible_job_conf_path): job_config_location = possible_job_conf_path - message += "using '%s'. *" % f + message += f"using '{f}'. *" break else: message += ("and no default job configs in 'config/'. " diff --git a/lib/galaxy/jobs/handler.py b/lib/galaxy/jobs/handler.py index 4c5fa582025..5116e5662e8 100644 --- a/lib/galaxy/jobs/handler.py +++ b/lib/galaxy/jobs/handler.py @@ -247,7 +247,7 @@ class JobHandlerQueue(Monitors): self.job_wrapper(job).fail('This tool was disabled before the job completed. Please contact your Galaxy administrator.') elif job.job_runner_name is not None and job.job_runner_external_id is None: # This could happen during certain revisions of Galaxy where a runner URL was persisted before the job was dispatched to a runner. - log.debug("(%s) Job runner assigned but no external ID recorded, adding to the job handler queue" % job.id) + log.debug(f"({job.id}) Job runner assigned but no external ID recorded, adding to the job handler queue") job.job_runner_name = None if self.track_jobs_in_database: job.set_state(model.Job.states.NEW) @@ -261,7 +261,7 @@ class JobHandlerQueue(Monitors): job_destination.id = 'legacy_url' job_wrapper.set_job_destination(job_destination, job.job_runner_external_id) self.dispatcher.recover(job, job_wrapper) - log.info('(%s) Converted job from a URL to a destination and recovered' % (job.id)) + log.info(f'({job.id}) Converted job from a URL to a destination and recovered') elif job.job_runner_name is None: # Never (fully) dispatched log.debug(f"({job.id}) No job runner assigned and job still in '{job.state}' state, adding to the job handler queue") @@ -512,20 +512,20 @@ class JobHandlerQueue(Monitors): if hda_deleted or dataset_deleted: if dataset_purged: # If the dataset has been purged we can't resume the job by undeleting the input - jobs_to_fail[job_id].append("Input dataset '%s' was deleted before the job started" % hda_name) + jobs_to_fail[job_id].append(f"Input dataset '{hda_name}' was deleted before the job started") else: - jobs_to_pause[job_id].append("Input dataset '%s' was deleted before the job started" % hda_name) + jobs_to_pause[job_id].append(f"Input dataset '{hda_name}' was deleted before the job started") elif hda_state == model.HistoryDatasetAssociation.states.FAILED_METADATA: - jobs_to_pause[job_id].append("Input dataset '%s' failed to properly set metadata" % hda_name) + jobs_to_pause[job_id].append(f"Input dataset '{hda_name}' failed to properly set metadata") elif dataset_state == model.Dataset.states.PAUSED: - jobs_to_pause[job_id].append("Input dataset '%s' was paused before the job started" % hda_name) + jobs_to_pause[job_id].append(f"Input dataset '{hda_name}' was paused before the job started") elif dataset_state == model.Dataset.states.ERROR: - jobs_to_pause[job_id].append("Input dataset '%s' is in error state" % hda_name) + jobs_to_pause[job_id].append(f"Input dataset '{hda_name}' is in error state") elif dataset_state != model.Dataset.states.OK: jobs_to_ignore[job_id].append(f"Input dataset '{hda_name}' is in {dataset_state} state") for job_id in sorted(jobs_to_pause): pause_message = ", ".join(jobs_to_pause[job_id]) - pause_message = "%s. To resume this job fix the input dataset(s)." % pause_message + pause_message = f"{pause_message}. To resume this job fix the input dataset(s)." job, job_wrapper = self.job_pair_for_id(job_id) try: job_wrapper.pause(job=job, message=pause_message) @@ -604,7 +604,7 @@ class JobHandlerQueue(Monitors): if failure_message == DEFAULT_JOB_PUT_FAILURE_MESSAGE: log.exception('Failed to generate job destination') else: - log.debug("Intentionally failing job with message (%s)" % failure_message) + log.debug(f"Intentionally failing job with message ({failure_message})") job_wrapper.fail(failure_message) return JOB_ERROR, job_destination # job is ready to run, check limits @@ -667,10 +667,10 @@ class JobHandlerQueue(Monitors): return JOB_INPUT_DELETED # an error in the input data causes us to bail immediately elif idata.state == idata.states.ERROR: - self.job_wrappers.pop(job.id, self.job_wrapper(job)).fail("input data %s is in error state" % (idata.hid)) + self.job_wrappers.pop(job.id, self.job_wrapper(job)).fail(f"input data {idata.hid} is in error state") return JOB_INPUT_ERROR elif idata.state == idata.states.FAILED_METADATA: - self.job_wrappers.pop(job.id, self.job_wrapper(job)).fail("input data %s failed to properly set metadata" % (idata.hid)) + self.job_wrappers.pop(job.id, self.job_wrapper(job)).fail(f"input data {idata.hid} failed to properly set metadata") return JOB_INPUT_ERROR elif idata.state != idata.states.OK and not (idata.state == idata.states.SETTING_METADATA and job.tool_id is not None and job.tool_id == self.app.datatypes_registry.set_external_metadata_tool.id): # need to requeue @@ -806,7 +806,7 @@ class JobHandlerQueue(Monitors): if count >= self.app.job_config.limits.anonymous_user_concurrent_jobs: return JOB_WAIT else: - log.warning('Job %s is not associated with a user or session so job concurrency limit cannot be checked.' % job.id) + log.warning(f'Job {job.id} is not associated with a user or session so job concurrency limit cannot be checked.') return JOB_READY def __cache_total_job_count_per_destination(self): @@ -1097,4 +1097,4 @@ class DefaultJobDispatcher: failures.append(name) log.exception("Failed to shutdown runner %s", name) if failures: - raise Exception("Failed to shutdown runners: %s" % ', '.join(failures)) + raise Exception(f"Failed to shutdown runners: {', '.join(failures)}") diff --git a/lib/galaxy/jobs/manager.py b/lib/galaxy/jobs/manager.py index fab77182b5d..f343faff787 100644 --- a/lib/galaxy/jobs/manager.py +++ b/lib/galaxy/jobs/manager.py @@ -73,7 +73,7 @@ class JobManager: tool_id = tool.id configured_handler = tool.get_configured_job_handler(job.params) if configured_handler is not None: - p = " (with job params: %s)" % str(job.params) if job.params else "" + p = f" (with job params: {str(job.params)})" if job.params else "" log.debug("(%s) Configured job handler for tool '%s'%s is: %s", job.log_str(), tool_id, p, configured_handler) queue_callback = partial(self._queue_callback, job, tool_id) message_callback = partial(self._message_callback, job) diff --git a/lib/galaxy/jobs/mapper.py b/lib/galaxy/jobs/mapper.py index 53640a8d7e8..e92b858002a 100644 --- a/lib/galaxy/jobs/mapper.py +++ b/lib/galaxy/jobs/mapper.py @@ -197,7 +197,7 @@ class JobRunnerMapper: elif expand_type in STOCK_RULES: expand_function = STOCK_RULES[expand_type] else: - raise JobMappingConfigurationException("Unhandled dynamic job runner type specified - %s" % expand_type) + raise JobMappingConfigurationException(f"Unhandled dynamic job runner type specified - {expand_type}") return self.__handle_rule(expand_function, destination) @@ -214,7 +214,7 @@ class JobRunnerMapper: def __determine_job_destination(self, params, raw_job_destination=None): if self.job_wrapper.tool is None: raise JobMappingException( - "Can't map job to destination, tool '%s' is unavailable" % self.job_wrapper.get_job().tool_id + f"Can't map job to destination, tool '{self.job_wrapper.get_job().tool_id}' is unavailable" ) if raw_job_destination is None: raw_job_destination = self.job_wrapper.tool.get_job_destination(params) diff --git a/lib/galaxy/jobs/runners/__init__.py b/lib/galaxy/jobs/runners/__init__.py index 9044dff567f..9c2267090d3 100644 --- a/lib/galaxy/jobs/runners/__init__.py +++ b/lib/galaxy/jobs/runners/__init__.py @@ -130,7 +130,7 @@ class BaseJobRunner: try: action_str = f'galaxy.jobs.runners.{self.__class__.__name__.lower()}.{name}' action_timer = self.app.execution_timer_factory.get_timer( - 'internals.%s' % action_str, + f'internals.{action_str}', 'job runner action %s for job ${job_id} executed' % (action_str) ) method(arg) @@ -540,7 +540,7 @@ class BaseJobRunner: job_wrapper.finish(tool_stdout, tool_stderr, exit_code, check_output_detected_state=check_output_detected_state, job_stdout=job_stdout, job_stderr=job_stderr) except Exception: - log.exception("({}/{}) Job wrapper finish method failed".format(job_id or '', external_job_id or '')) + log.exception(f"({job_id or ''}/{external_job_id or ''}) Job wrapper finish method failed") job_wrapper.fail("Unable to finish job", exception=True) @@ -566,19 +566,19 @@ class JobState: id_tag = self.job_wrapper.get_id_tag() if files_dir is not None: self.job_file = JobState.default_job_file(files_dir, id_tag) - self.output_file = os.path.join(files_dir, 'galaxy_%s.o' % id_tag) - self.error_file = os.path.join(files_dir, 'galaxy_%s.e' % id_tag) + self.output_file = os.path.join(files_dir, f'galaxy_{id_tag}.o') + self.error_file = os.path.join(files_dir, f'galaxy_{id_tag}.e') self.exit_code_file = default_exit_code_file(files_dir, id_tag) - job_name = 'g%s' % id_tag + job_name = f'g{id_tag}' if self.job_wrapper.tool.old_id: - job_name += '_%s' % self.job_wrapper.tool.old_id + job_name += f'_{self.job_wrapper.tool.old_id}' if not self.redact_email_in_job_name and self.job_wrapper.user: - job_name += '_%s' % self.job_wrapper.user + job_name += f'_{self.job_wrapper.user}' self.job_name = ''.join(x if x in (string.ascii_letters + string.digits + '_') else '_' for x in job_name) @staticmethod def default_job_file(files_dir, id_tag): - return os.path.join(files_dir, 'galaxy_%s.sh' % id_tag) + return os.path.join(files_dir, f'galaxy_{id_tag}.sh') def read_exit_code(self): return read_exit_code_from(self.exit_code_file, self.job_wrapper.get_id_tag()) @@ -591,10 +591,10 @@ class JobState: # TODO: Move this prefix stuff to a method so we don't have dispatch on attributes we may or may # not have. if not hasattr(self, "job_id"): - prefix = "(%s)" % self.job_wrapper.get_id_tag() + prefix = f"({self.job_wrapper.get_id_tag()})" else: prefix = f"({self.job_wrapper.get_id_tag()}/{self.job_id})" - log.debug("{} Unable to cleanup {}: {}".format(prefix, file, unicodify(e))) + log.debug(f"{prefix} Unable to cleanup {file}: {unicodify(e)}") class AsynchronousJobState(JobState): @@ -672,7 +672,7 @@ class AsynchronousJobRunner(BaseJobRunner, Monitors): self.monitor_queue = Queue() def _init_monitor_thread(self): - name = "%s.monitor_thread" % self.runner_name + name = f"{self.runner_name}.monitor_thread" super()._init_monitor_thread(name=name, target=self.monitor, start=True, config=self.app.config) def handle_stop(self): @@ -709,7 +709,7 @@ class AsynchronousJobRunner(BaseJobRunner, Monitors): def shutdown(self): """Attempts to gracefully shut down the monitor thread""" - log.info("%s: Sending stop signal to monitor thread" % self.runner_name) + log.info(f"{self.runner_name}: Sending stop signal to monitor thread") self.monitor_queue.put(STOP_SIGNAL) # Call the parent's shutdown method to stop workers self.shutdown_monitor() diff --git a/lib/galaxy/jobs/runners/cli.py b/lib/galaxy/jobs/runners/cli.py index a4b9f6fa069..629220ca664 100644 --- a/lib/galaxy/jobs/runners/cli.py +++ b/lib/galaxy/jobs/runners/cli.py @@ -83,7 +83,7 @@ class ShellJobRunner(AsynchronousJobRunner): try: self.write_executable_script(ajs.job_file, script) except Exception: - log.exception("(%s) failure writing job script" % galaxy_id_tag) + log.exception(f"({galaxy_id_tag}) failure writing job script") job_wrapper.fail("failure preparing job script", exception=True) return @@ -104,7 +104,7 @@ class ShellJobRunner(AsynchronousJobRunner): # Strip and split to get job ID. external_job_id = stdout.strip().split()[-1] if not external_job_id: - log.error('(%s) submission did not return a job identifier, failing job' % galaxy_id_tag) + log.error(f'({galaxy_id_tag}) submission did not return a job identifier, failing job') job_wrapper.fail("failure submitting job") return diff --git a/lib/galaxy/jobs/runners/condor.py b/lib/galaxy/jobs/runners/condor.py index 0aa81a8a65f..77830eca933 100644 --- a/lib/galaxy/jobs/runners/condor.py +++ b/lib/galaxy/jobs/runners/condor.py @@ -83,7 +83,7 @@ class CondorJobRunner(AsynchronousJobRunner): galaxy_slots = query_params.get('request_cpus', None) if galaxy_slots: - galaxy_slots_statement = 'GALAXY_SLOTS="%s"; export GALAXY_SLOTS; GALAXY_SLOTS_CONFIGURED="1"; export GALAXY_SLOTS_CONFIGURED;' % galaxy_slots + galaxy_slots_statement = f'GALAXY_SLOTS="{galaxy_slots}"; export GALAXY_SLOTS; GALAXY_SLOTS_CONFIGURED="1"; export GALAXY_SLOTS_CONFIGURED;' else: galaxy_slots_statement = 'GALAXY_SLOTS="1"; export GALAXY_SLOTS;' @@ -93,9 +93,9 @@ class CondorJobRunner(AsynchronousJobRunner): job_wrapper=job_wrapper ) - cjs.user_log = os.path.join(job_wrapper.working_directory, 'galaxy_%s.condor.log' % galaxy_id_tag) + cjs.user_log = os.path.join(job_wrapper.working_directory, f'galaxy_{galaxy_id_tag}.condor.log') cjs.register_cleanup_file_attribute('user_log') - submit_file = os.path.join(job_wrapper.working_directory, 'galaxy_%s.condor.desc' % galaxy_id_tag) + submit_file = os.path.join(job_wrapper.working_directory, f'galaxy_{galaxy_id_tag}.condor.desc') executable = cjs.job_file build_submit_params = dict( @@ -117,7 +117,7 @@ class CondorJobRunner(AsynchronousJobRunner): self.write_executable_script(executable, script) except Exception: job_wrapper.fail("failure preparing job script", exception=True) - log.exception("(%s) failure preparing job script" % galaxy_id_tag) + log.exception(f"({galaxy_id_tag}) failure preparing job script") return cleanup_job = job_wrapper.cleanup_job @@ -128,7 +128,7 @@ class CondorJobRunner(AsynchronousJobRunner): cjs.cleanup() # job_wrapper.fail() calls job_wrapper.cleanup() job_wrapper.fail("failure preparing submit file", exception=True) - log.exception("(%s) failure preparing submit file" % galaxy_id_tag) + log.exception(f"({galaxy_id_tag}) failure preparing submit file") return # job was deleted while we were preparing it @@ -274,7 +274,7 @@ class CondorJobRunner(AsynchronousJobRunner): cjs.command_line = job.get_command_line() cjs.job_wrapper = job_wrapper cjs.job_destination = job_wrapper.job_destination - cjs.user_log = os.path.join(job_wrapper.working_directory, 'galaxy_%s.condor.log' % galaxy_id_tag) + cjs.user_log = os.path.join(job_wrapper.working_directory, f'galaxy_{galaxy_id_tag}.condor.log') cjs.register_cleanup_file_attribute('user_log') if job.state in (model.Job.states.RUNNING, model.Job.states.STOPPED): log.debug(f"({job.id}/{job.get_job_runner_external_id()}) is still in {job.state} state, adding to the DRM queue") diff --git a/lib/galaxy/jobs/runners/drmaa.py b/lib/galaxy/jobs/runners/drmaa.py index 3b79d1f44e2..1e196031dec 100644 --- a/lib/galaxy/jobs/runners/drmaa.py +++ b/lib/galaxy/jobs/runners/drmaa.py @@ -109,7 +109,7 @@ class DRMAAJobRunner(AsynchronousJobRunner): log.debug(f"Converted URL '{url}' to destination runner=drmaa, params={params}") return JobDestination(runner='drmaa', params=params) else: - log.debug("Converted URL '%s' to destination runner=drmaa" % url) + log.debug(f"Converted URL '{url}' to destination runner=drmaa") return JobDestination(runner='drmaa') def get_native_spec(self, url): @@ -144,8 +144,8 @@ class DRMAAJobRunner(AsynchronousJobRunner): remoteCommand=ajs.job_file, jobName=ajs.job_name, workingDirectory=job_wrapper.working_directory, - outputPath=":%s" % ajs.output_file, - errorPath=":%s" % ajs.error_file + outputPath=f":{ajs.output_file}", + errorPath=f":{ajs.error_file}" ) # Avoid a jt.exitCodePath for now - it's only used when finishing. @@ -161,7 +161,7 @@ class DRMAAJobRunner(AsynchronousJobRunner): self.write_executable_script(ajs.job_file, script) except Exception: job_wrapper.fail("failure preparing job script", exception=True) - log.exception("(%s) failure writing job script" % galaxy_id_tag) + log.exception(f"({galaxy_id_tag}) failure writing job script") return # job was deleted while we were preparing it @@ -195,7 +195,7 @@ class DRMAAJobRunner(AsynchronousJobRunner): log.exception('(%s) drmaa.Session.runJob() failed unconditionally', galaxy_id_tag) trynum = 5 else: - log.error("(%s) All attempts to submit job failed" % galaxy_id_tag) + log.error(f"({galaxy_id_tag}) All attempts to submit job failed") if not fail_msg: fail_msg = DEFAULT_JOB_PUT_FAILURE_MESSAGE job_wrapper.fail(fail_msg) @@ -207,16 +207,16 @@ class DRMAAJobRunner(AsynchronousJobRunner): pwent = job_wrapper.user_system_pwent if pwent is None: if not allow_guests: - fail_msg = "User %s is not mapped to any real user, and not permitted to start jobs." % job_wrapper.user + fail_msg = f"User {job_wrapper.user} is not mapped to any real user, and not permitted to start jobs." job_wrapper.fail(fail_msg) return pwent = job_wrapper.galaxy_system_pwent - log.debug('({}) submitting with credentials: {} [uid: {}]'.format(galaxy_id_tag, pwent[0], pwent[2])) + log.debug(f'({galaxy_id_tag}) submitting with credentials: {pwent[0]} [uid: {pwent[2]}]') filename = self.store_jobtemplate(job_wrapper, jt) self.userid = pwent[2] external_job_id = self.external_runjob(external_runjob_script, filename, pwent[2]) if external_job_id is None: - job_wrapper.fail("(%s) could not queue job" % galaxy_id_tag) + job_wrapper.fail(f"({galaxy_id_tag}) could not queue job") return log.info(f"({galaxy_id_tag}) queued as {external_job_id}") @@ -332,7 +332,7 @@ class DRMAAJobRunner(AsynchronousJobRunner): if state is None: continue if state != old_state: - log.debug("({}/{}) state change: {}".format(galaxy_id_tag, external_job_id, self.drmaa_job_state_strings[state])) + log.debug(f"({galaxy_id_tag}/{external_job_id}) state change: {self.drmaa_job_state_strings[state]}") if state == drmaa.JobState.RUNNING and not ajs.running: ajs.running = True ajs.job_wrapper.change_state(model.Job.states.RUNNING) @@ -370,7 +370,7 @@ class DRMAAJobRunner(AsynchronousJobRunner): except drmaa.InvalidJobException: log.exception(f"({job.id}/{ext_id}) User killed running job, but it was already dead") except commands.CommandLineException as e: - log.error("({}/{}) User killed running job, but command execution failed: {}".format(job.id, ext_id, unicodify(e))) + log.error(f"({job.id}/{ext_id}) User killed running job, but command execution failed: {unicodify(e)}") except Exception: log.exception(f"({job.id}/{ext_id}) User killed running job, but error encountered removing from DRM queue") @@ -431,11 +431,11 @@ class DRMAAJobRunner(AsynchronousJobRunner): galaxy_id_tag = job_wrapper.get_id_tag() # define job attributes - job_name = 'g%s' % galaxy_id_tag + job_name = f'g{galaxy_id_tag}' if job_wrapper.tool.old_id: - job_name += '_%s' % job_wrapper.tool.old_id + job_name += f'_{job_wrapper.tool.old_id}' if not self.redact_email_in_job_name and external_runjob_script is None: - job_name += '_%s' % job_wrapper.user + job_name += f'_{job_wrapper.user}' job_name = ''.join(x if x in (string.ascii_letters + string.digits + '_') else '_' for x in job_name) if self.restrict_job_name_length: job_name = job_name[:self.restrict_job_name_length] diff --git a/lib/galaxy/jobs/runners/godocker.py b/lib/galaxy/jobs/runners/godocker.py index 9a997e19ae7..9f9399497e6 100644 --- a/lib/galaxy/jobs/runners/godocker.py +++ b/lib/galaxy/jobs/runners/godocker.py @@ -348,7 +348,7 @@ class GodockerJobRunner(AsynchronousJobRunner): docker_image = self._find_container(job_wrapper).container_id log.debug("GoDocker runner using container %s.", docker_image) except Exception: - log.error("Unable to find docker_image for job %s, failing." % job_wrapper.job_id) + log.error(f"Unable to find docker_image for job {job_wrapper.job_id}, failing.") return False volumes = [] diff --git a/lib/galaxy/jobs/runners/kubernetes.py b/lib/galaxy/jobs/runners/kubernetes.py index dffcfeda8cb..aaf33c98ed5 100644 --- a/lib/galaxy/jobs/runners/kubernetes.py +++ b/lib/galaxy/jobs/runners/kubernetes.py @@ -144,7 +144,7 @@ class KubernetesJobRunner(AsynchronousJobRunner): self.write_executable_script(ajs.job_file, script) except Exception: job_wrapper.fail("failure preparing job script", exception=True) - log.exception("(%s) failure writing job script" % job_wrapper.get_id_tag()) + log.exception(f"({job_wrapper.get_id_tag()}) failure writing job script") return # Construction of the Kubernetes Job object follows: http://kubernetes.io/docs/user-guide/persistent-volumes/ @@ -538,7 +538,7 @@ class KubernetesJobRunner(AsynchronousJobRunner): if isinstance(raw_id, str): cleaned_id = re.sub("[^-a-z0-9]", "-", raw_id) if cleaned_id.startswith("-") or cleaned_id.endswith("-"): - cleaned_id = "x%sx" % cleaned_id + cleaned_id = f"x{cleaned_id}x" return cleaned_id return "job-container" diff --git a/lib/galaxy/jobs/runners/local.py b/lib/galaxy/jobs/runners/local.py index c4f334cdb0b..8b230dd6a4f 100644 --- a/lib/galaxy/jobs/runners/local.py +++ b/lib/galaxy/jobs/runners/local.py @@ -137,7 +137,7 @@ class LocalJobRunner(BaseJobRunner): stderr = self._job_io_for_db(stderr_file) stdout_file.close() stderr_file.close() - log.debug('execution finished: %s' % job_file) + log.debug(f'execution finished: {job_file}') except Exception: log.exception("failure running job %d", job_wrapper.job_id) self._fail_job_local(job_wrapper, "failure running job") @@ -162,7 +162,7 @@ class LocalJobRunner(BaseJobRunner): # metadata internal or job not complete yet pid = job.get_job_runner_external_id() if pid in [None, '']: - log.warning("stop_job(): %s: no PID in database for job, unable to stop" % job.id) + log.warning(f"stop_job(): {job.id}: no PID in database for job, unable to stop") return pid = int(pid) if not check_pg(pid): diff --git a/lib/galaxy/jobs/runners/pbs.py b/lib/galaxy/jobs/runners/pbs.py index c96b4020b30..8e235c44872 100644 --- a/lib/galaxy/jobs/runners/pbs.py +++ b/lib/galaxy/jobs/runners/pbs.py @@ -109,7 +109,7 @@ class PBSJobRunner(AsynchronousJobRunner): def default_pbs_server(self): if self.__default_pbs_server is None: self.__default_pbs_server = pbs.pbs_default() - log.debug("Set default PBS server to %s" % self.default_pbs_server) + log.debug(f"Set default PBS server to {self.default_pbs_server}") return self.__default_pbs_server def url_to_destination(self, url): @@ -127,7 +127,7 @@ class PBSJobRunner(AsynchronousJobRunner): raise Exception("Could not find TORQUE server") # Determine the queue, set the PBS destination (not the same thing as a Galaxy job destination) - pbs_destination = '@%s' % server + pbs_destination = f'@{server}' pbs_queue = url_split[3] or None if pbs_queue is not None: pbs_destination = f'{pbs_queue}{pbs_destination}' @@ -167,7 +167,7 @@ class PBSJobRunner(AsynchronousJobRunner): arg = arg.lstrip('-') args[arg] = value except Exception: - log.warning('Unrecognized long argument in destination params: %s' % arg) + log.warning(f'Unrecognized long argument in destination params: {arg}') return self.__args_to_attrs(args) # Internal stuff @@ -224,7 +224,7 @@ class PBSJobRunner(AsynchronousJobRunner): pbs_options = self.parse_destination_params(job_destination.params) # Explicitly set the determined PBS destination in the persisted job destination for recovery - job_destination.params['destination'] = '{}@{}'.format(pbs_queue_name or '', pbs_server_name) + job_destination.params['destination'] = f"{pbs_queue_name or ''}@{pbs_server_name}" c = pbs.pbs_connect(util.smart_str(pbs_server_name)) if c <= 0: @@ -291,7 +291,7 @@ class PBSJobRunner(AsynchronousJobRunner): self.write_executable_script(job_file, script) # job was deleted while we were preparing it if job_wrapper.get_state() in (model.Job.states.DELETED, model.Job.states.STOPPED): - log.debug("Job %s deleted/stopped by user before it entered the PBS queue" % job_wrapper.job_id) + log.debug(f"Job {job_wrapper.job_id} deleted/stopped by user before it entered the PBS queue") pbs.pbs_disconnect(c) if job_wrapper.cleanup_job in ("always", "onsuccess"): self.cleanup((ofile, efile, ecfile, job_file)) @@ -315,7 +315,7 @@ class PBSJobRunner(AsynchronousJobRunner): log.warning("(%s) pbs_submit failed (try %d/5), PBS error %d: %s" % (galaxy_job_id, tries, errno, text)) time.sleep(2) else: - log.error("(%s) All attempts to submit job failed" % galaxy_job_id) + log.error(f"({galaxy_job_id}) All attempts to submit job failed") job_wrapper.fail("Unable to run this job due to a cluster error, please retry it later") return @@ -399,7 +399,7 @@ class PBSJobRunner(AsynchronousJobRunner): log.debug(f"({galaxy_job_id}/{job_id}) PBS job has completed successfully") except AssertionError: exit_status = int(status.exit_status) - error_message = JOB_EXIT_STATUS.get(exit_status, 'Unknown error: %s' % status.exit_status) + error_message = JOB_EXIT_STATUS.get(exit_status, f'Unknown error: {status.exit_status}') pbs_job_state.fail_message = CLUSTER_ERROR_MESSAGE % error_message log.error(f'({galaxy_job_id}/{job_id}) PBS job failed: {error_message}') pbs_job_state.stop_job = False @@ -432,7 +432,7 @@ class PBSJobRunner(AsynchronousJobRunner): for pbs_server_name in servers: c = pbs.pbs_connect(util.smart_str(pbs_server_name)) if c <= 0: - log.debug("connection to PBS server %s for state check failed" % pbs_server_name) + log.debug(f"connection to PBS server {pbs_server_name} for state check failed") failures.append(pbs_server_name) continue stat_attrl = pbs.new_attrl(3) @@ -465,7 +465,7 @@ class PBSJobRunner(AsynchronousJobRunner): """ c = pbs.pbs_connect(util.smart_str(pbs_server_name)) if c <= 0: - log.debug("connection to PBS server %s for state check failed" % pbs_server_name) + log.debug(f"connection to PBS server {pbs_server_name} for state check failed") return None stat_attrl = pbs.new_attrl(1) stat_attrl[0].name = pbs.ATTR_state @@ -505,7 +505,7 @@ class PBSJobRunner(AsynchronousJobRunner): job = job_wrapper.get_job() job_id = job.get_job_runner_external_id().encode('utf-8') job_tag = f"({job.get_id_tag()}/{job_id})" - log.debug("%s Stopping PBS job" % job_tag) + log.debug(f"{job_tag} Stopping PBS job") # Declare the connection handle c so that it can be cleaned up: c = None @@ -518,12 +518,10 @@ class PBSJobRunner(AsynchronousJobRunner): return c = pbs.pbs_connect(util.smart_str(pbs_server_name)) if c <= 0: - log.debug("(%s) Connection to PBS server for job delete failed" - % job_tag) + log.debug(f"({job_tag}) Connection to PBS server for job delete failed") return pbs.pbs_deljob(c, job_id, '') - log.debug("%s Removed from PBS queue before job completion" - % job_tag) + log.debug(f"{job_tag} Removed from PBS queue before job completion") except Exception: e = traceback.format_exc() log.debug(f"{job_tag} Unable to stop job: {e}") diff --git a/lib/galaxy/jobs/runners/pulsar.py b/lib/galaxy/jobs/runners/pulsar.py index 4813d5bbb77..34dfe33207a 100644 --- a/lib/galaxy/jobs/runners/pulsar.py +++ b/lib/galaxy/jobs/runners/pulsar.py @@ -245,7 +245,7 @@ class PulsarJobRunner(AsynchronousJobRunner): if pulsar_conf_path is None: log.info("Creating a Pulsar app with default configuration (no pulsar_conf specified).") else: - log.info("Loading Pulsar app configuration from %s" % pulsar_conf_path) + log.info(f"Loading Pulsar app configuration from {pulsar_conf_path}") with open(pulsar_conf_path) as f: conf.update(yaml.safe_load(f) or {}) if "job_metrics_config_file" not in conf: @@ -381,7 +381,7 @@ class PulsarJobRunner(AsynchronousJobRunner): config_files = job_wrapper.extra_filenames tool_script = os.path.join(job_wrapper.working_directory, "tool_script.sh") if os.path.exists(tool_script): - log.debug("Registering tool_script for Pulsar transfer [%s]" % tool_script) + log.debug(f"Registering tool_script for Pulsar transfer [{tool_script}]") job_directory_files.append(tool_script) config_files.append(tool_script) # Following is job destination environment variables @@ -414,7 +414,7 @@ class PulsarJobRunner(AsynchronousJobRunner): guest_ports=job_wrapper.guest_ports, ) job_id = pulsar_submit_job(client, client_job_description, remote_job_config) - log.info("Pulsar job submitted with job_id %s" % job_id) + log.info(f"Pulsar job submitted with job_id {job_id}") job = job_wrapper.get_job() # Set the job destination here (unlike other runners) because there are likely additional job destination # params from the Pulsar client. @@ -537,7 +537,7 @@ class PulsarJobRunner(AsynchronousJobRunner): for key, value in self.destination_defaults.items(): if key in params: if value is PARAMETER_SPECIFICATION_IGNORED: - log.warning("Pulsar runner in selected configuration ignores parameter %s" % key) + log.warning(f"Pulsar runner in selected configuration ignores parameter {key}") continue # if self.runner_params.get( key, None ): # # Let plugin define defaults for some parameters - @@ -550,7 +550,7 @@ class PulsarJobRunner(AsynchronousJobRunner): continue if value is PARAMETER_SPECIFICATION_REQUIRED: - raise Exception("Pulsar destination does not define required parameter %s" % key) + raise Exception(f"Pulsar destination does not define required parameter {key}") elif value is not PARAMETER_SPECIFICATION_IGNORED: params[key] = value updated = True @@ -697,7 +697,7 @@ class PulsarJobRunner(AsynchronousJobRunner): if not PulsarJobRunner.__remote_metadata(client) and job_ext_output_metadata: pid = job_ext_output_metadata[0].job_runner_external_pid # every JobExternalOutputMetadata has a pid set, we just need to take from one of them if pid in [None, '']: - log.warning("stop_job(): %s: no PID in database for job, unable to stop" % job.id) + log.warning(f"stop_job(): {job.id}: no PID in database for job, unable to stop") return pid = int(pid) if not self.check_pid(pid): @@ -777,7 +777,7 @@ class PulsarJobRunner(AsynchronousJobRunner): # 0.6.0 was newest Pulsar version that did not report it's version. pulsar_version = packaging.version.parse(remote_job_config.get('pulsar_version', "0.6.0")) needed_version = packaging.version.parse("0.0.0") - log.info("pulsar_version is %s" % pulsar_version) + log.info(f"pulsar_version is {pulsar_version}") for feature, needed in list(check_features.items()) + [('_default_', True)]: if not needed: continue @@ -803,7 +803,7 @@ class PulsarJobRunner(AsynchronousJobRunner): def __dependency_resolution(pulsar_client): dependency_resolution = pulsar_client.destination_params.get("dependency_resolution", "remote") if dependency_resolution not in ["none", "local", "remote"]: - raise Exception("Unknown dependency_resolution value encountered %s" % dependency_resolution) + raise Exception(f"Unknown dependency_resolution value encountered {dependency_resolution}") return dependency_resolution @staticmethod @@ -1034,14 +1034,14 @@ class PulsarComputeEnvironment(ComputeEnvironment): def input_extra_files_rewrite(self, dataset): input_path_rewrite = self.input_path_rewrite(dataset) base_input_path = input_path_rewrite[0:-len(".dat")] - remote_extra_files_path_rewrite = "%s_files" % base_input_path + remote_extra_files_path_rewrite = f"{base_input_path}_files" self.path_rewrites_input_extra[dataset.extra_files_path] = remote_extra_files_path_rewrite return remote_extra_files_path_rewrite def output_extra_files_rewrite(self, dataset): output_path_rewrite = self.output_path_rewrite(dataset) base_output_path = output_path_rewrite[0:-len(".dat")] - remote_extra_files_path_rewrite = "%s_files" % base_output_path + remote_extra_files_path_rewrite = f"{base_output_path}_files" return remote_extra_files_path_rewrite def input_metadata_rewrite(self, dataset, metadata_val): diff --git a/lib/galaxy/jobs/runners/state_handlers/_safe_eval.py b/lib/galaxy/jobs/runners/state_handlers/_safe_eval.py index be0dc92b621..e900071cde9 100644 --- a/lib/galaxy/jobs/runners/state_handlers/_safe_eval.py +++ b/lib/galaxy/jobs/runners/state_handlers/_safe_eval.py @@ -137,5 +137,5 @@ def safe_eval(expression, variables): True """ if not _check_expression(expression, allowed_variables=list(variables.keys())): - raise Exception("Invalid expression [%s], only a very simple subset of Python is allowed." % expression) + raise Exception(f"Invalid expression [{expression}], only a very simple subset of Python is allowed.") return eval(expression, globals(), variables) diff --git a/lib/galaxy/jobs/runners/state_handlers/resubmit.py b/lib/galaxy/jobs/runners/state_handlers/resubmit.py index afa51baedaf..2c09923a2e5 100644 --- a/lib/galaxy/jobs/runners/state_handlers/resubmit.py +++ b/lib/galaxy/jobs/runners/state_handlers/resubmit.py @@ -95,7 +95,7 @@ def _handle_resubmit_definitions(resubmit_definitions, app, job_runner, job_stat if external_id: job_log_prefix = f"({job_state.job_wrapper.job_id}/{job_state.job_id})" else: - job_log_prefix = "(%s)" % (job_state.job_wrapper.job_id) + job_log_prefix = f"({job_state.job_wrapper.job_id})" # Is destination needed here, might these be serialized to the database? destination = resubmit.get('environment') or resubmit.get('destination') @@ -139,7 +139,7 @@ def _handle_resubmit_definitions(resubmit_definitions, app, job_runner, job_stat float(delay) new_destination.params['__resubmit_delay_seconds'] = str(delay) except ValueError: - log.warning("Cannot delay job with delay [%s], does not appear to be a number." % delay) + log.warning(f"Cannot delay job with delay [{delay}], does not appear to be a number.") job_state.job_wrapper.set_job_destination(new_destination) # Clear external ID (state change below flushes the change) job.job_runner_external_id = None diff --git a/lib/galaxy/jobs/runners/tasks.py b/lib/galaxy/jobs/runners/tasks.py index 8acc50eb5b3..d9af589a4b9 100644 --- a/lib/galaxy/jobs/runners/tasks.py +++ b/lib/galaxy/jobs/runners/tasks.py @@ -54,7 +54,7 @@ class TaskedJobRunner(BaseJobRunner): splitter = getattr(__import__('galaxy.jobs.splitters', globals(), locals(), [parallelism.method]), parallelism.method) except Exception: job_wrapper.change_state(model.Job.states.ERROR) - job_wrapper.fail("Job Splitting Failed, no match for '%s'" % parallelism) + job_wrapper.fail(f"Job Splitting Failed, no match for '{parallelism}'") return tasks = splitter.do_split(job_wrapper) # Not an option for now. Task objects don't *do* anything @@ -111,7 +111,7 @@ class TaskedJobRunner(BaseJobRunner): if sleep_time < 8: sleep_time *= 2 job_wrapper.reclaim_ownership() # if running as the actual user, change ownership before merging. - log.debug('execution finished - beginning merge: %s' % command_line) + log.debug(f'execution finished - beginning merge: {command_line}') stdout, stderr = splitter.do_merge(job_wrapper, task_wrappers) except Exception: job_wrapper.fail("failure running job", exception=True) @@ -138,7 +138,7 @@ class TaskedJobRunner(BaseJobRunner): tasks = job.get_tasks() if (len(tasks) > 0): for task in tasks: - log.debug("Killing task's job %s" % task.id) + log.debug(f"Killing task's job {task.id}") self.app.job_manager.job_handler.dispatcher.stop(task) # There were no subtasks, so just kill the job. We'll touch @@ -152,7 +152,7 @@ class TaskedJobRunner(BaseJobRunner): else: pid = job.job_runner_external_id if pid in [None, '']: - log.warning("stop_job(): %s: no PID in database for job, unable to stop" % job.id) + log.warning(f"stop_job(): {job.id}: no PID in database for job, unable to stop") return self._stop_pid(pid, job.id) @@ -217,7 +217,7 @@ class TaskedJobRunner(BaseJobRunner): job's id (which is used for logging messages only right now). """ pid = int(pid) - log.debug("Stopping pid %s" % pid) + log.debug(f"Stopping pid {pid}") if not self._check_pid(pid): log.warning("_stop_pid(): %s: PID %d was already dead or can't be signaled" % (job_id, pid)) return diff --git a/lib/galaxy/jobs/runners/univa.py b/lib/galaxy/jobs/runners/univa.py index 742c7669e38..2fe1a5c76ca 100644 --- a/lib/galaxy/jobs/runners/univa.py +++ b/lib/galaxy/jobs/runners/univa.py @@ -106,7 +106,7 @@ class UnivaJobRunner(DRMAAJobRunner): ajs.runner_state = ajs.runner_states.MEMORY_LIMIT_REACHED drmaa_state = self.drmaa_job_states.FAILED elif state in [self.drmaa.JobState.QUEUED_ACTIVE, self.drmaa.JobState.SYSTEM_ON_HOLD, self.drmaa.JobState.USER_ON_HOLD, self.drmaa.JobState.USER_SYSTEM_ON_HOLD, self.drmaa.JobState.RUNNING, self.drmaa.JobState.SYSTEM_SUSPENDED, self.drmaa.JobState.USER_SUSPENDED]: - log.warning('({tag}/{jobid}) Job is {state}, returning to monitor queue'.format(tag=ajs.job_wrapper.get_id_tag(), jobid=ajs.job_id, state=self.drmaa_job_state_strings[state])) + log.warning(f'({ajs.job_wrapper.get_id_tag()}/{ajs.job_id}) Job is {self.drmaa_job_state_strings[state]}, returning to monitor queue') # TODO return True? return True # job was not actually terminal elif state == self.drmaa.JobState.UNDETERMINED: @@ -257,7 +257,7 @@ class UnivaJobRunner(DRMAAJobRunner): # "NONE". If qdel was called multiple times, every invocation is recorded in a comma # separated list. if "deleted_by" in qacct and qacct["deleted_by"] != "NONE": - log.info("DRMAAUniva: job {job_id} was aborted by {culprit}".format(job_id=job_id, culprit=qacct["deleted_by"])) + log.info(f"DRMAAUniva: job {job_id} was aborted by {qacct['deleted_by']}") extinfo["deleted"] = True return self.drmaa.JobState.FAILED @@ -273,14 +273,14 @@ class UnivaJobRunner(DRMAAJobRunner): if "exit_status" in qacct: qacct["exit_status"] = int(qacct["exit_status"]) if qacct["exit_status"] < 1: - log.error("DRMAAUniva: job {job_id} has exit status {status}".format(job_id=job_id, status=qacct["exit_status"])) + log.error(f"DRMAAUniva: job {job_id} has exit status {qacct['exit_status']}") state = self.drmaa.JobState.DONE elif 0 < qacct["exit_status"] < 129: - log.error("DRMAAUniva: job {job_id} has exit status {status}".format(job_id=job_id, status=qacct["exit_status"])) + log.error(f"DRMAAUniva: job {job_id} has exit status {qacct['exit_status']}") extinfo['exit_status'] = qacct["exit_status"] state = self.drmaa.JobState.FAILED else: - log.error("DRMAAUniva: job {job_id} was killed by signal {signal}".format(job_id=job_id, signal=qacct["exit_status"] - 128)) + log.error(f"DRMAAUniva: job {job_id} was killed by signal {qacct['exit_status'] - 128}") state = self.drmaa.JobState.FAILED extinfo["signal"] = signals[qacct["exit_status"] - 128] @@ -300,7 +300,7 @@ class UnivaJobRunner(DRMAAJobRunner): elif code in [24, 25]: state = self.drmaa.JobState.RUNNING else: - log.error("DRMAAUniva: job {job_id} failed with failure {failure}".format(job_id=job_id, failure=qacct["failed"])) + log.error(f"DRMAAUniva: job {job_id} failed with failure {qacct['failed']}") state = self.drmaa.JobState.FAILED # log.debug("UnivaJobRunner._get_drmaa_state_qacct ({jobid}) -> {state}".format(jobid=job_id, state=self.drmaa_job_state_strings[state])) return state diff --git a/lib/galaxy/jobs/runners/util/cli/__init__.py b/lib/galaxy/jobs/runners/util/cli/__init__.py index bfd359a6edb..c63eb070984 100644 --- a/lib/galaxy/jobs/runners/util/cli/__init__.py +++ b/lib/galaxy/jobs/runners/util/cli/__init__.py @@ -30,7 +30,7 @@ class CliInterface: for file in glob(module_pattern): if basename(file).startswith('_'): continue - module_name = '{}.{}'.format(module_path, basename(file).rsplit('.py', 1)[0]) + module_name = f"{module_path}.{basename(file).rsplit('.py', 1)[0]}" module = __import__(module_name) for comp in module_name.split(".")[1:]: module = getattr(module, comp) @@ -52,15 +52,15 @@ class CliInterface: try: d[name] = getattr(module, name) except TypeError: - raise TypeError("Invalid type for name %s" % name) + raise TypeError(f"Invalid type for name {name}") self.cli_shells = {} self.cli_job_interfaces = {} self.active_cli_shells = {} module_prefix = self.__module__ - __load('%s.shell' % module_prefix, self.cli_shells) - __load('%s.job' % module_prefix, self.cli_job_interfaces) + __load(f'{module_prefix}.shell', self.cli_shells) + __load(f'{module_prefix}.job', self.cli_job_interfaces) def get_plugins(self, shell_params, job_params): """ diff --git a/lib/galaxy/jobs/runners/util/cli/job/lsf.py b/lib/galaxy/jobs/runners/util/cli/job/lsf.py index 3565fed9c02..bce64d4120e 100644 --- a/lib/galaxy/jobs/runners/util/cli/job/lsf.py +++ b/lib/galaxy/jobs/runners/util/cli/job/lsf.py @@ -36,12 +36,12 @@ class LSF(BaseJobExec): try: if k == 'memory': # Memory requires both -m and -R rusage[mem=v] request - scriptargs['-R'] = "\"rusage[mem=%s]\"" % v + scriptargs['-R'] = f"\"rusage[mem={v}]\"" if not k.startswith('-'): k = argmap[k] scriptargs[k] = v except Exception: - log.warning('Unrecognized long argument passed to LSF CLI plugin: %s' % k) + log.warning(f'Unrecognized long argument passed to LSF CLI plugin: {k}') # Generated template. template_scriptargs = '' @@ -60,7 +60,7 @@ class LSF(BaseJobExec): return "bsub <%s | awk '{ print $2}' | sed 's/[<>]//g'" % script_file def delete(self, job_id): - return 'bkill %s' % job_id + return f'bkill {job_id}' def get_status(self, job_ids=None): return "bjobs -a -o \"id stat\" -noheader" # check this @@ -86,7 +86,7 @@ class LSF(BaseJobExec): # which would be badly handled here. So this only works well when Galaxy # is constantly monitoring the jobs. The logic here is that DONE jobs get forgotten # faster than failed jobs. - log.warning("Job id '%s' not found LSF status check" % job_id) + log.warning(f"Job id '{job_id}' not found LSF status check") return job_states.OK return self._get_job_state(status) @@ -120,7 +120,7 @@ class LSF(BaseJobExec): 'ZOMBI': job_states.ERROR }.get(state) except KeyError: - raise KeyError("Failed to map LSF status code [%s] to job state." % state) + raise KeyError(f"Failed to map LSF status code [{state}] to job state.") def _get_excluded_hosts(self): """ diff --git a/lib/galaxy/jobs/runners/util/cli/job/slurm.py b/lib/galaxy/jobs/runners/util/cli/job/slurm.py index ed26d48a1c3..ff8a6ba46d9 100644 --- a/lib/galaxy/jobs/runners/util/cli/job/slurm.py +++ b/lib/galaxy/jobs/runners/util/cli/job/slurm.py @@ -34,7 +34,7 @@ class Slurm(BaseJobExec): k = argmap[k] scriptargs[k] = v except Exception: - log.warning('Unrecognized long argument passed to Slurm CLI plugin: %s' % k) + log.warning(f'Unrecognized long argument passed to Slurm CLI plugin: {k}') # Generated template. template_scriptargs = '' @@ -43,10 +43,10 @@ class Slurm(BaseJobExec): return dict(headers=template_scriptargs) def submit(self, script_file): - return 'sbatch %s' % script_file + return f'sbatch {script_file}' def delete(self, job_id): - return 'scancel %s' % job_id + return f'scancel {job_id}' def get_status(self, job_ids=None): return "squeue -a -o '%A %t'" @@ -83,7 +83,7 @@ class Slurm(BaseJobExec): 'CD': job_states.OK }.get(state) except KeyError: - raise KeyError("Failed to map slurm status code [%s] to job state." % state) + raise KeyError(f"Failed to map slurm status code [{state}] to job state.") __all__ = ('Slurm',) diff --git a/lib/galaxy/jobs/runners/util/cli/job/torque.py b/lib/galaxy/jobs/runners/util/cli/job/torque.py index c9c854d42b5..e369afab390 100644 --- a/lib/galaxy/jobs/runners/util/cli/job/torque.py +++ b/lib/galaxy/jobs/runners/util/cli/job/torque.py @@ -55,16 +55,16 @@ class Torque(BaseJobExec): return dict(headers=template_pbsargs) def submit(self, script_file): - return 'qsub %s' % script_file + return f'qsub {script_file}' def delete(self, job_id): - return 'qdel %s' % job_id + return f'qdel {job_id}' def get_status(self, job_ids=None): return 'qstat -x' def get_single_status(self, job_id): - return 'qstat -f %s' % job_id + return f'qstat -f {job_id}' def parse_status(self, status, job_ids): # in case there's noise in the output, find the big blob 'o xml @@ -78,7 +78,7 @@ class Torque(BaseJobExec): except Exception: tree = None if tree is None: - log.warning('No valid qstat XML return from `qstat -x`, got the following: %s' % status) + log.warning(f'No valid qstat XML return from `qstat -x`, got the following: {status}') return None else: for job in tree.findall('Job'): @@ -106,7 +106,7 @@ class Torque(BaseJobExec): 'C': job_states.OK }.get(state) except KeyError: - raise KeyError("Failed to map torque status code [%s] to job state." % state) + raise KeyError(f"Failed to map torque status code [{state}] to job state.") __all__ = ('Torque',) diff --git a/lib/galaxy/jobs/runners/util/condor/__init__.py b/lib/galaxy/jobs/runners/util/condor/__init__.py index 81d8c3c7d81..2fbead6c80f 100644 --- a/lib/galaxy/jobs/runners/util/condor/__init__.py +++ b/lib/galaxy/jobs/runners/util/condor/__init__.py @@ -98,7 +98,7 @@ def condor_stop(external_id): except CalledProcessError: failure_message = "condor_rm failed" except Exception as e: - failure_message = "error encountered calling condor_rm: %s" % unicodify(e) + failure_message = f"error encountered calling condor_rm: {unicodify(e)}" return failure_message diff --git a/lib/galaxy/jobs/runners/util/env.py b/lib/galaxy/jobs/runners/util/env.py index 63e79e41513..3de52700078 100644 --- a/lib/galaxy/jobs/runners/util/env.py +++ b/lib/galaxy/jobs/runners/util/env.py @@ -23,7 +23,7 @@ def env_to_statement(env): ''' source_file = env.get('file', None) if source_file: - return '. %s' % __escape(source_file, env) + return f'. {__escape(source_file, env)}' execute = env.get('execute', None) if execute: return execute diff --git a/lib/galaxy/jobs/runners/util/job_script/__init__.py b/lib/galaxy/jobs/runners/util/job_script/__init__.py index 303f936e816..d813f53144a 100644 --- a/lib/galaxy/jobs/runners/util/job_script/__init__.py +++ b/lib/galaxy/jobs/runners/util/job_script/__init__.py @@ -153,7 +153,7 @@ def _handle_script_integrity(path, config): time.sleep(sleep_amt) if not script_integrity_verified: - raise Exception("Failed to write job script '%s', could not verify job script integrity." % path) + raise Exception(f"Failed to write job script '{path}', could not verify job script integrity.") __all__ = ( diff --git a/lib/galaxy/jobs/runners/util/sudo.py b/lib/galaxy/jobs/runners/util/sudo.py index 0cfca1619c2..72fc3f06ee2 100644 --- a/lib/galaxy/jobs/runners/util/sudo.py +++ b/lib/galaxy/jobs/runners/util/sudo.py @@ -21,6 +21,6 @@ def sudo_popen(*args, **kwargs): if user: full_command.extend([SUDO_USER_ARG, user]) full_command.extend(args) - log.info("About to execute the following sudo command - [%s]" % ' '.join(full_command)) + log.info(f"About to execute the following sudo command - [{' '.join(full_command)}]") p = Popen(full_command, shell=False, stdout=PIPE, stderr=PIPE) return p diff --git a/lib/galaxy/jobs/splitters/multi.py b/lib/galaxy/jobs/splitters/multi.py index 241f7f58cc7..3866ee90c2a 100644 --- a/lib/galaxy/jobs/splitters/multi.py +++ b/lib/galaxy/jobs/splitters/multi.py @@ -31,7 +31,7 @@ def do_split(job_wrapper): shared_inputs = [x.strip() for x in shared_inputs.split(",")] illegal_inputs = [x for x in shared_inputs if x in split_inputs] if len(illegal_inputs) > 0: - raise Exception("Inputs have conflicting parallelism attributes: %s" % str(illegal_inputs)) + raise Exception(f"Inputs have conflicting parallelism attributes: {str(illegal_inputs)}") subdir_index = [0] # use a list to get around Python 2.x lame closure support task_dirs = [] @@ -63,7 +63,7 @@ def do_split(job_wrapper): elif auto_shared_inputs: shared_inputs.append(input.name) else: - log_error = "The input '%s' does not define a method for implementing parallelism" % str(input.name) + log_error = f"The input '{str(input.name)}' does not define a method for implementing parallelism" log.exception(log_error) raise Exception(log_error) @@ -78,7 +78,7 @@ def do_split(job_wrapper): if input.name in split_inputs: this_input_files = job_wrapper.get_input_dataset_fnames(input.dataset) if len(this_input_files) > 1: - log_error = "The input '%s' is composed of multiple files - splitting is not allowed" % str(input.name) + log_error = f"The input '{str(input.name)}' is composed of multiple files - splitting is not allowed" log.error(log_error) raise Exception(log_error) input_datasets.append(input.dataset) @@ -89,7 +89,7 @@ def do_split(job_wrapper): try: input_type.split(input_datasets, get_new_working_directory_name, parallel_settings) except AttributeError: - log_error = "The type '%s' does not define a method for splitting files" % str(input_type) + log_error = f"The type '{str(input_type)}' does not define a method for splitting files" log.error(log_error) raise log.debug('do_split created %d parts' % len(task_dirs)) @@ -125,7 +125,7 @@ def do_merge(job_wrapper, task_wrappers): illegal_outputs = [x for x in merge_outputs if x in pickone_outputs] if len(illegal_outputs) > 0: - return ('Tool file error', 'Outputs have conflicting parallelism attributes: %s' % str(illegal_outputs)) + return ('Tool file error', f'Outputs have conflicting parallelism attributes: {str(illegal_outputs)}') stdout = '' stderr = '' @@ -151,7 +151,7 @@ def do_merge(job_wrapper, task_wrappers): # file f exists; some files may not exist if a task fails. output_files = [f for f in output_files if os.path.exists(f)] if output_files: - log.debug('files %s ' % output_files) + log.debug(f'files {output_files} ') if len(output_files) < len(task_dirs): log.debug('merging only %i out of expected %i files for %s' % (len(output_files), len(task_dirs), output_file_name)) @@ -162,7 +162,7 @@ def do_merge(job_wrapper, task_wrappers): if "output_dataset" in extra_merge_arg_names: extra_merge_args["output_dataset"] = output_dataset output_type.merge(output_files, output_file_name, **extra_merge_args) - log.debug('merge finished: %s' % output_file_name) + log.debug(f'merge finished: {output_file_name}') else: msg = 'nothing to merge for %s (expected %i files)' \ % (output_file_name, len(task_dirs)) @@ -175,7 +175,7 @@ def do_merge(job_wrapper, task_wrappers): shutil.move(task_file_name, output_file_name) pickone_done.append(output) else: - log_error = "The output '%s' does not define a method for implementing parallelism" % output + log_error = f"The output '{output}' does not define a method for implementing parallelism" log.exception(log_error) raise Exception(log_error) except Exception as e: diff --git a/lib/galaxy/managers/base.py b/lib/galaxy/managers/base.py index 5ec7dc4c413..a5d4f3327b7 100644 --- a/lib/galaxy/managers/base.py +++ b/lib/galaxy/managers/base.py @@ -64,7 +64,7 @@ def security_check(trans, item, check_ownership=False, check_accessible=False): if not trans.user: raise exceptions.ItemOwnershipException("Must be logged in to manage Galaxy items", type='error') if item.user != trans.user: - raise exceptions.ItemOwnershipException("%s is not owned by the current user" % item.__class__.__name__, type='error') + raise exceptions.ItemOwnershipException(f"{item.__class__.__name__} is not owned by the current user", type='error') # Verify accessible: # if it's part of a lib - can they access via security @@ -72,10 +72,10 @@ def security_check(trans, item, check_ownership=False, check_accessible=False): if check_accessible: if type(item) in (trans.app.model.LibraryFolder, trans.app.model.LibraryDatasetDatasetAssociation, trans.app.model.LibraryDataset): if not trans.app.security_agent.can_access_library_item(trans.get_current_user_roles(), item, trans.user): - raise exceptions.ItemAccessibilityException("%s is not accessible to the current user" % item.__class__.__name__, type='error') + raise exceptions.ItemAccessibilityException(f"{item.__class__.__name__} is not accessible to the current user", type='error') else: if (item.user != trans.user) and (not item.importable) and (trans.user not in item.users_shared_with_dot_users): - raise exceptions.ItemAccessibilityException("%s is not accessible to the current user" % item.__class__.__name__, type='error') + raise exceptions.ItemAccessibilityException(f"{item.__class__.__name__} is not accessible to the current user", type='error') return item @@ -88,7 +88,7 @@ def get_class(class_name): item_class = tool_shed_install.ToolShedRepository else: if not hasattr(model, class_name): - raise exceptions.MessageException("Item class '%s' not available." % class_name) + raise exceptions.MessageException(f"Item class '{class_name}' not available.") item_class = getattr(model, class_name) return item_class @@ -804,7 +804,7 @@ class ModelValidator(HasAModelManager): :raises exceptions.RequestParameterInvalidException: if not an instance. """ if not isinstance(val, types): - msg = 'must be a type: %s' % (str(types)) + msg = f'must be a type: {str(types)}' raise exceptions.RequestParameterInvalidException(msg, key=key, val=val) return val diff --git a/lib/galaxy/managers/citations.py b/lib/galaxy/managers/citations.py index 9573c911f70..a0a8dcd1818 100644 --- a/lib/galaxy/managers/citations.py +++ b/lib/galaxy/managers/citations.py @@ -64,7 +64,7 @@ def parse_citation(elem, citation_manager): citation_type = elem.attrib.get('type', None) citation_class = CITATION_CLASSES.get(citation_type, None) if not citation_class: - log.warning("Unknown or unspecified citation type: %s" % citation_type) + log.warning(f"Unknown or unspecified citation type: {citation_type}") return None try: citation = citation_class(elem, citation_manager) @@ -104,7 +104,7 @@ class BaseCitation: content=self.to_bibtex(), ) else: - raise Exception("Unknown citation format %s" % citation_format) + raise Exception(f"Unknown citation format {citation_format}") def equals(self, other_citation): if self.has_doi() and other_citation.has_doi(): diff --git a/lib/galaxy/managers/cloud.py b/lib/galaxy/managers/cloud.py index dd3697f6c1c..66af9720068 100644 --- a/lib/galaxy/managers/cloud.py +++ b/lib/galaxy/managers/cloud.py @@ -247,14 +247,14 @@ class CloudManager(sharable.SharableModelManager): if bucket is None: raise RequestParameterInvalidException(f"The bucket `{bucket_name}` not found.") except Exception as e: - raise ItemAccessibilityException("Could not get the bucket `{}`: {}".format(bucket_name, util.unicodify(e))) + raise ItemAccessibilityException(f"Could not get the bucket `{bucket_name}`: {util.unicodify(e)}") datasets = [] for obj in objects: try: key = bucket.objects.get(obj) except Exception as e: - raise MessageException("The following error occurred while getting the object {}: {}".format(obj, util.unicodify(e))) + raise MessageException(f"The following error occurred while getting the object {obj}: {util.unicodify(e)}") if key is None: log.exception( "Could not get object `{}` for user `{}`. Object may not exist, or the provided credentials are " @@ -267,7 +267,7 @@ class CloudManager(sharable.SharableModelManager): incoming = params.__dict__ history = trans.sa_session.query(trans.app.model.History).get(history_id) if not history: - raise ObjectNotFound("History with ID `{}` not found.".format(trans.app.security.encode_id(history_id))) + raise ObjectNotFound(f"History with ID `{trans.app.security.encode_id(history_id)}` not found.") output = trans.app.toolbox.get_tool('upload1').handle_input(trans, incoming, history=history) job_errors = output.get('job_errors', []) @@ -329,7 +329,7 @@ class CloudManager(sharable.SharableModelManager): history = trans.sa_session.query(trans.app.model.History).get(history_id) if not history: - raise ObjectNotFound("History with ID `{}` not found.".format(trans.app.security.encode_id(history_id))) + raise ObjectNotFound(f"History with ID `{trans.app.security.encode_id(history_id)}` not found.") sent = [] failed = [] @@ -366,7 +366,7 @@ class CloudManager(sharable.SharableModelManager): "job_id": trans.app.security.encode_id(job.id) })) except Exception as e: - err_msg = "maybe invalid or unauthorized credentials. {}".format(util.unicodify(e)) + err_msg = f"maybe invalid or unauthorized credentials. {util.unicodify(e)}" log.debug("Failed to send the dataset `{}` per user `{}` request to cloud, {}".format( object_label, trans.user.id, err_msg)) failed.append(json.dumps( diff --git a/lib/galaxy/managers/collections.py b/lib/galaxy/managers/collections.py index e3e62d33fef..acd4fea2d8c 100644 --- a/lib/galaxy/managers/collections.py +++ b/lib/galaxy/managers/collections.py @@ -169,7 +169,7 @@ class DatasetCollectionManager: ) else: - message = "Internal logic error - create called with unknown parent type %s" % type(parent) + message = f"Internal logic error - create called with unknown parent type {type(parent)}" log.exception(message) raise MessageException(message) @@ -429,7 +429,7 @@ class DatasetCollectionManager: try: src_type = element_identifier.get('src', 'hda') except AttributeError: - raise MessageException("Dataset collection element definition (%s) not dictionary-like." % element_identifier) + raise MessageException(f"Dataset collection element definition ({element_identifier}) not dictionary-like.") encoded_id = element_identifier.get('id') if not src_type or not encoded_id: message_template = "Problem decoding element identifier %s - must contain a 'src' and a 'id'." @@ -459,7 +459,7 @@ class DatasetCollectionManager: element = self.__get_history_collection_instance(trans, encoded_id).collection # TODO: ldca. else: - raise RequestParameterInvalidException("Unknown src_type parameter supplied '%s'." % src_type) + raise RequestParameterInvalidException(f"Unknown src_type parameter supplied '{src_type}'.") return element def match_collections(self, collections_to_match): @@ -522,7 +522,7 @@ class DatasetCollectionManager: columns = mapping_as_dict["group_tags"]["columns"] for tag_column in columns: tag = row_data[tag_column] - tags.append("group:%s" % tag) + tags.append(f"group:{tag}") if "tags" in mapping_as_dict: columns = mapping_as_dict["tags"]["columns"] diff --git a/lib/galaxy/managers/collections_util.py b/lib/galaxy/managers/collections_util.py index aac474d7c59..fe4f9fcd7b4 100644 --- a/lib/galaxy/managers/collections_util.py +++ b/lib/galaxy/managers/collections_util.py @@ -21,7 +21,7 @@ def api_payload_to_create_params(payload): required_parameters = ["collection_type", "element_identifiers"] missing_parameters = [p for p in required_parameters if p not in payload] if missing_parameters: - message = "Missing required parameters %s" % missing_parameters + message = f"Missing required parameters {missing_parameters}" raise exceptions.ObjectAttributeMissingException(message) params = dict( diff --git a/lib/galaxy/managers/datasets.py b/lib/galaxy/managers/datasets.py index 483e13004fc..8036962c52b 100644 --- a/lib/galaxy/managers/datasets.py +++ b/lib/galaxy/managers/datasets.py @@ -359,7 +359,7 @@ class DatasetAssociationManager(base.ModelManager, trans.sa_session.flush() self.set_metadata(trans, dataset_assoc) else: - raise exceptions.InsufficientPermissionsException('Changing datatype "%s" is not allowed.' % (data.extension)) + raise exceptions.InsufficientPermissionsException(f'Changing datatype "{data.extension}" is not allowed.') def set_metadata(self, trans, dataset_assoc, overwrite=False, validate=True): """Trigger a job that detects and sets metadata on a given dataset association (ldda or hda)""" @@ -415,7 +415,7 @@ class DatasetAssociationManager(base.ModelManager, return role_id def parameters_roles_or_none(role_type): - encoded_role_ids = kwd.get(role_type, kwd.get("%s_ids[]" % role_type, None)) + encoded_role_ids = kwd.get(role_type, kwd.get(f"{role_type}_ids[]", None)) if encoded_role_ids is not None: return list(map(to_role_id, encoded_role_ids)) else: diff --git a/lib/galaxy/managers/folders.py b/lib/galaxy/managers/folders.py index f0930bd3ead..d3c0c305f23 100644 --- a/lib/galaxy/managers/folders.py +++ b/lib/galaxy/managers/folders.py @@ -280,7 +280,7 @@ class FolderManager: if ((len(encoded_folder_id) % 16 == 1) and encoded_folder_id.startswith('F')): cut_id = encoded_folder_id[1:] else: - raise MalformedId('Malformed folder id ( %s ) specified, unable to decode.' % str(encoded_folder_id)) + raise MalformedId(f'Malformed folder id ( {str(encoded_folder_id)} ) specified, unable to decode.') return cut_id def decode_folder_id(self, trans, encoded_folder_id): diff --git a/lib/galaxy/managers/history_contents.py b/lib/galaxy/managers/history_contents.py index 0f58b4f05bb..fb87bf0a156 100644 --- a/lib/galaxy/managers/history_contents.py +++ b/lib/galaxy/managers/history_contents.py @@ -125,8 +125,8 @@ class HistoryContentsManager(containers.ContainerManagerMixin): """Return an ORM compatible order_by using the given string""" available = ['create_time', 'extension', 'hid', 'history_id', 'name', 'update_time'] for attribute in available: - attribute_dsc = '%s-dsc' % attribute - attribute_asc = '%s-asc' % attribute + attribute_dsc = f'{attribute}-dsc' + attribute_asc = f'{attribute}-asc' if order_by_string in (attribute, attribute_dsc): return desc(attribute) if order_by_string == attribute_asc: diff --git a/lib/galaxy/managers/interactivetool.py b/lib/galaxy/managers/interactivetool.py index b42392256e1..595d5db4d8d 100644 --- a/lib/galaxy/managers/interactivetool.py +++ b/lib/galaxy/managers/interactivetool.py @@ -28,9 +28,9 @@ class InteractiveToolSqlite: conn = sqlite3.connect(self.sqlite_filename) try: c = conn.cursor() - select = '''SELECT token, host, port, info - FROM %s - WHERE key=? and key_type=?''' % (DATABASE_TABLE_NAME) + select = f'''SELECT token, host, port, info + FROM {DATABASE_TABLE_NAME} + WHERE key=? and key_type=?''' c.execute(select, (key, key_type,)) try: token, host, port, info = c.fetchone() @@ -72,7 +72,7 @@ class InteractiveToolSqlite: )''' % (DATABASE_TABLE_NAME)) except Exception: pass - delete = '''DELETE FROM %s WHERE key=? and key_type=?''' % (DATABASE_TABLE_NAME) + delete = f'''DELETE FROM {DATABASE_TABLE_NAME} WHERE key=? and key_type=?''' c.execute(delete, (key, key_type,)) insert = '''INSERT INTO %s (key, key_type, token, host, port, info) @@ -95,12 +95,12 @@ class InteractiveToolSqlite: with external resources. Remove entries that match all provided key=values """ assert kwd, ValueError("You must provide some values to key upon") - delete = 'DELETE FROM %s WHERE' % (DATABASE_TABLE_NAME) + delete = f'DELETE FROM {DATABASE_TABLE_NAME} WHERE' value_list = [] for i, (key, value) in enumerate(kwd.items()): if i != 0: delete += ' and' - delete += ' %s=?' % (key) + delete += f' {key}=?' value_list.append(value) with FileLock(self.sqlite_filename): conn = sqlite3.connect(self.sqlite_filename) @@ -263,7 +263,7 @@ class InteractiveToolManager: else: rval = self.app.url_for(f'/{entry_point_prefix}/access/{entry_point_class}/{entry_point_encoded_id}/{entry_point.token}/') if entry_point.entry_url: - rval = '{}/{}'.format(rval.rstrip('/'), entry_point.entry_url.lstrip('/')) + rval = f"{rval.rstrip('/')}/{entry_point.entry_url.lstrip('/')}" return rval def get_entry_point_subdomain(self, trans, entry_point): diff --git a/lib/galaxy/managers/jobs.py b/lib/galaxy/managers/jobs.py index db08253505c..9961992f5e9 100644 --- a/lib/galaxy/managers/jobs.py +++ b/lib/galaxy/managers/jobs.py @@ -253,7 +253,7 @@ class JobSearch: name_condition = [] if identifier: data_conditions.append(and_(model.Job.id == d.job_id, - d.name.in_({"%s|__identifier__" % _ for _ in k}), + d.name.in_({f"{_}|__identifier__" for _ in k}), d.value == json.dumps(identifier))) else: stmt = stmt.where(e.name == c.name) @@ -462,7 +462,7 @@ def fetch_job_states(sa_session, job_source_ids, job_source_types): implicit_collection_job_ids.add(invocation_step_source_id) workflow_invocations_job_sources[job_source_id] = workflow_invocation_job_sources else: - raise RequestParameterInvalidException("Invalid job source type %s found." % job_source_type) + raise RequestParameterInvalidException(f"Invalid job source type {job_source_type} found.") job_summaries = {} implicit_collection_jobs_summaries = {} @@ -661,7 +661,7 @@ def summarize_job_parameters(trans, job): else: rval.append(dict(text=input.name, depth=depth, notes="The previously used value is no longer valid.", error=True)) elif input.type == "upload_dataset": - rval.append(dict(text=input.group_title(param_values), depth=depth, value="%s uploaded datasets" % len(param_values[input.name]))) + rval.append(dict(text=input.group_title(param_values), depth=depth, value=f"{len(param_values[input.name])} uploaded datasets")) elif input.type == "data": value = [] for element in listify(param_values[input.name]): diff --git a/lib/galaxy/managers/library_datasets.py b/lib/galaxy/managers/library_datasets.py index 44f45d9a791..8c761458987 100644 --- a/lib/galaxy/managers/library_datasets.py +++ b/lib/galaxy/managers/library_datasets.py @@ -132,7 +132,7 @@ class LibraryDatasetsManager(datasets.DatasetAssociationManager): if key in ('file_ext'): datatype = self.app.datatypes_registry.get_datatype_by_extension(val) if datatype is None and val not in ("auto",): - raise RequestParameterInvalidException('This Galaxy does not recognize the datatype of: %s' % (val)) + raise RequestParameterInvalidException(f'This Galaxy does not recognize the datatype of: {val}') validated_payload[key] = val if key in ('genome_build'): if len(val) < MINIMUM_STRING_LENGTH: diff --git a/lib/galaxy/managers/licenses.py b/lib/galaxy/managers/licenses.py index 7f5b2f1efcf..8af0d02e39d 100644 --- a/lib/galaxy/managers/licenses.py +++ b/lib/galaxy/managers/licenses.py @@ -89,7 +89,7 @@ SPDX_LICENSES_STRING = resource_string(__name__, 'licenses.json').decode("UTF-8" SPDX_LICENSES = json.loads(SPDX_LICENSES_STRING) for license in SPDX_LICENSES["licenses"]: license["recommended"] = license["licenseId"] in RECOMMENDED_LICENSES - license["spdxUrl"] = "https://spdx.org/licenses/%s" % license["reference"][len("./"):] + license["spdxUrl"] = f"https://spdx.org/licenses/{license['reference'][len('./'):]}" seeAlso = license.get("seeAlso", []) if len(seeAlso) > 0: url = seeAlso[0] @@ -117,7 +117,7 @@ class LicensesManager: if uri in self._by_index: return self._by_index[uri] else: - log.warning("Unknown license URI encountered [%s]" % uri) + log.warning(f"Unknown license URI encountered [{uri}]") return { "url": uri } diff --git a/lib/galaxy/managers/markdown_util.py b/lib/galaxy/managers/markdown_util.py index 278803c3fbb..53b0f5a1d0a 100644 --- a/lib/galaxy/managers/markdown_util.py +++ b/lib/galaxy/managers/markdown_util.py @@ -87,7 +87,7 @@ class GalaxyInternalMarkdownDirectiveHandler(metaclass=abc.ABCMeta): def _check_object(object_id, line): if object_id is None: - raise MalformedContents("Missing object identifier [%s]." % line) + raise MalformedContents(f"Missing object identifier [{line}].") def _remap(container, line): id_match = re.search(UNENCODED_ID_PATTERN, line) @@ -166,7 +166,7 @@ class GalaxyInternalMarkdownDirectiveHandler(metaclass=abc.ABCMeta): elif container == "visualization": rval = None else: - raise MalformedContents("Unknown Galaxy Markdown directive encountered [%s]." % container) + raise MalformedContents(f"Unknown Galaxy Markdown directive encountered [{container}].") if rval is not None: return rval else: @@ -367,7 +367,7 @@ class ToBasicMarkdownDirectiveHandler(GalaxyInternalMarkdownDirectiveHandler): def handle_dataset_display(self, line, hda): name = hda.name or "" markdown = '---\n' - markdown += "**Dataset:** %s\n\n" % name + markdown += f"**Dataset:** {name}\n\n" markdown += self._display_dataset_content(hda) markdown += '\n---\n' return (markdown, True) @@ -386,9 +386,9 @@ class ToBasicMarkdownDirectiveHandler(GalaxyInternalMarkdownDirectiveHandler): datatype = hda.datatype markdown = "" if datatype is None: - markdown += "**%s:** *cannot display - cannot format unknown datatype*\n\n" % header + markdown += f"**{header}:** *cannot display - cannot format unknown datatype*\n\n" else: - markdown += "**%s:**\n" % header + markdown += f"**{header}:**\n" markdown += datatype.display_as_markdown(hda, self.markdown_formatting_helpers) return markdown @@ -432,7 +432,7 @@ class ToBasicMarkdownDirectiveHandler(GalaxyInternalMarkdownDirectiveHandler): def handle_workflow_display(self, line, stored_workflow): # workflows/display.mako as markdown... meh... markdown = '---\n' - markdown += "**Workflow:** %s\n\n" % stored_workflow.name + markdown += f"**Workflow:** {stored_workflow.name}\n\n" markdown += "**Steps:**\n\n" markdown += "|Step|Annotation|\n" markdown += "|----|----------|\n" @@ -447,7 +447,7 @@ class ToBasicMarkdownDirectiveHandler(GalaxyInternalMarkdownDirectiveHandler): def handle_dataset_collection_display(self, line, hdca): name = hdca.name or "" # put it in a list to hack around no nonlocal on Python 2. - markdown_wrapper = ["**Dataset Collection:** %s\n\n" % name] + markdown_wrapper = [f"**Dataset Collection:** {name}\n\n"] def walk_elements(collection, element_prefix=""): if ":" in collection.collection_type: @@ -458,16 +458,16 @@ class ToBasicMarkdownDirectiveHandler(GalaxyInternalMarkdownDirectiveHandler): markdown_wrapper[0] += f"**Element:** {element_prefix}{element.element_identifier}\n\n" markdown_wrapper[0] += self._display_dataset_content(element.hda, header="Element Contents") walk_elements(hdca.collection) - markdown = '---\n%s\n---\n' % markdown_wrapper[0] + markdown = f'---\n{markdown_wrapper[0]}\n---\n' return (markdown, True) def handle_tool_stdout(self, line, job): stdout = job.tool_stdout or "*No Standard Output Available*" - return ("**Standard Output:** %s" % stdout, True) + return (f"**Standard Output:** {stdout}", True) def handle_tool_stderr(self, line, job): stderr = job.tool_stderr or "*No Standard Error Available*" - return ("**Standard Error:** %s" % stderr, True) + return (f"**Standard Error:** {stderr}", True) def handle_job_metrics(self, line, job): job_metrics = summarize_job_metrics(self.trans, job) @@ -479,7 +479,7 @@ class ToBasicMarkdownDirectiveHandler(GalaxyInternalMarkdownDirectiveHandler): metrics_by_plugin[plugin][job_metric["title"]] = job_metric["value"] markdown = "" for metric_plugin, metrics_for_plugin in metrics_by_plugin.items(): - markdown += "**%s**\n\n" % metric_plugin + markdown += f"**{metric_plugin}**\n\n" markdown += "| | |\n|---|--|\n" for title, value in metrics_for_plugin.items(): markdown += f"| {title} | {value} |\n" @@ -553,7 +553,7 @@ class MarkdownFormatHelpers: @staticmethod def pre_formatted_contents(markdown): - return "
    %s
    " % markdown + return f"
    {markdown}
    " def to_basic_markdown(trans, internal_galaxy_markdown): @@ -604,8 +604,8 @@ def internal_galaxy_markdown_to_pdf(trans, internal_galaxy_markdown, document_ty _check_can_convert_to_pdf_or_raise() basic_markdown = to_basic_markdown(trans, internal_galaxy_markdown) config = trans.app.config - document_type_prologue = getattr(config, "markdown_export_prologue_%ss" % document_type, '') or '' - document_type_epilogue = getattr(config, "markdown_export_epilogue_%ss" % document_type, '') or '' + document_type_prologue = getattr(config, f"markdown_export_prologue_{document_type}s", '') or '' + document_type_epilogue = getattr(config, f"markdown_export_epilogue_{document_type}s", '') or '' general_prologue = config.markdown_export_prologue or '' general_epilogue = config.markdown_export_epilogue or '' effective_prologue = document_type_prologue or general_prologue @@ -613,7 +613,7 @@ def internal_galaxy_markdown_to_pdf(trans, internal_galaxy_markdown, document_ty branded_markdown = effective_prologue + basic_markdown + effective_epilogue css_paths = [] general_css_path = trans.app.config.markdown_export_css - document_type_css_path = getattr(config, "markdown_export_css_%ss" % document_type, None) + document_type_css_path = getattr(config, f"markdown_export_css_{document_type}s", None) if general_css_path and os.path.exists(general_css_path): css_paths.append(general_css_path) if document_type_css_path and os.path.exists(document_type_css_path): @@ -686,7 +686,7 @@ history_dataset_collection_display(input={}) if container == "history_link": return ("history_link(history_id=%s)\n" % invocation.history.id, False) if container == "invocation_date": - return ("invocation_date(invocation_id=%s)\n" % invocation.id, False) + return (f"invocation_date(invocation_id={invocation.id})\n", False) ref_object_type = None output_match = re.search(OUTPUT_LABEL_PATTERN, line) input_match = re.search(INPUT_LABEL_PATTERN, line) diff --git a/lib/galaxy/managers/pages.py b/lib/galaxy/managers/pages.py index 18ef7921366..292a7b351ad 100644 --- a/lib/galaxy/managers/pages.py +++ b/lib/galaxy/managers/pages.py @@ -362,7 +362,7 @@ class PageManager(sharable.SharableModelManager, UsesAnnotations): if not content: raise exceptions.ObjectAttributeMissingException("content undefined or empty") if content_format not in [None, PageContentFormat.html.value, PageContentFormat.markdown.value]: - raise exceptions.RequestParameterInvalidException("content_format [%s], if specified, must be either html or markdown" % content_format) + raise exceptions.RequestParameterInvalidException(f"content_format [{content_format}], if specified, must be either html or markdown") if 'title' in payload: title = payload['title'] @@ -396,11 +396,11 @@ class PageManager(sharable.SharableModelManager, UsesAnnotations): except exceptions.MessageException: raise except Exception: - raise exceptions.RequestParameterInvalidException("problem with embedded HTML content [%s]" % content) + raise exceptions.RequestParameterInvalidException(f"problem with embedded HTML content [{content}]") elif content_format == PageContentFormat.markdown.value: content = ready_galaxy_markdown_for_import(trans, content) else: - raise exceptions.RequestParameterInvalidException("content_format [%s] must be either html or markdown" % content_format) + raise exceptions.RequestParameterInvalidException(f"content_format [{content_format}] must be either html or markdown") return content def rewrite_content_for_export(self, trans, as_dict): @@ -416,7 +416,7 @@ class PageManager(sharable.SharableModelManager, UsesAnnotations): as_dict["content"] = content as_dict.update(extra_attributes) else: - raise exceptions.RequestParameterInvalidException("content_format [%s] must be either html or markdown" % content_format) + raise exceptions.RequestParameterInvalidException(f"content_format [{content_format}] must be either html or markdown") return as_dict @@ -562,7 +562,7 @@ class PageContentProcessor(HTMLParser): # Default behavior: reconstruct the original end tag. if tag not in self.elements_no_end_tag: - self.pieces.append("" % tag) + self.pieces.append(f"") def handle_charref(self, ref): # called for each character reference, e.g. for ' ', ref will be '160' @@ -574,17 +574,17 @@ class PageContentProcessor(HTMLParser): value = int(ref) if value in _cp1252: - self.pieces.append('&#%s;' % hex(ord(_cp1252[value]))[1:]) + self.pieces.append(f'&#{hex(ord(_cp1252[value]))[1:]};') else: - self.pieces.append('&#%s;' % ref) + self.pieces.append(f'&#{ref};') def handle_entityref(self, ref): # called for each entity reference, e.g. for '©', ref will be 'copy' # Reconstruct the original entity reference. if ref in name2codepoint or ref == 'apos': - self.pieces.append('&%s;' % ref) + self.pieces.append(f'&{ref};') else: - self.pieces.append('&%s' % ref) + self.pieces.append(f'&{ref}') def handle_data(self, text): """ @@ -600,19 +600,19 @@ class PageContentProcessor(HTMLParser): def handle_comment(self, text): # called for each HTML comment, e.g. # Reconstruct the original comment. - self.pieces.append('' % text) + self.pieces.append(f'') def handle_decl(self, text): # called for the DOCTYPE, if present, e.g. # # Reconstruct original DOCTYPE - self.pieces.append('' % text) + self.pieces.append(f'') def handle_pi(self, text): # called for each processing instruction, e.g. # Reconstruct original processing instruction. - self.pieces.append('' % text) + self.pieces.append(f'') def output(self): '''Return processed HTML as a single string''' diff --git a/lib/galaxy/managers/secured.py b/lib/galaxy/managers/secured.py index a729259e22a..7e7081d628c 100644 --- a/lib/galaxy/managers/secured.py +++ b/lib/galaxy/managers/secured.py @@ -40,7 +40,7 @@ class AccessibleManagerMixin: """ if self.is_accessible(item, user, **kwargs): return item - raise exceptions.ItemAccessibilityException("%s is not accessible by user" % (self.model_class.__name__)) + raise exceptions.ItemAccessibilityException(f"{self.model_class.__name__} is not accessible by user") # TODO:?? are these even useful? def list_accessible(self, user, **kwargs): @@ -100,7 +100,7 @@ class OwnableManagerMixin: """ if self.is_owner(item, user, **kwargs): return item - raise exceptions.ItemOwnershipException("%s is not owned by user" % (self.model_class.__name__)) + raise exceptions.ItemOwnershipException(f"{self.model_class.__name__} is not owned by user") def list_owned(self, user, **kwargs): """ diff --git a/lib/galaxy/managers/taggable.py b/lib/galaxy/managers/taggable.py index 4092150485e..104f241432a 100644 --- a/lib/galaxy/managers/taggable.py +++ b/lib/galaxy/managers/taggable.py @@ -109,8 +109,8 @@ class TaggableFilterMixin: if class_name == 'HistoryDatasetCollectionAssociation': # Unfortunately we were a little inconsistent with out naming scheme class_name = 'HistoryDatasetCollection' - target_model = getattr(model, "%sTagAssociation" % class_name) - id_column = "%s_id" % target_model.table.name.rsplit('_tag_association')[0] + target_model = getattr(model, f"{class_name}TagAssociation") + id_column = f"{target_model.table.name.rsplit('_tag_association')[0]}_id" column = target_model.table.c.user_tname + ":" + target_model.table.c.user_value if op == 'eq': if ':' not in val: diff --git a/lib/galaxy/managers/users.py b/lib/galaxy/managers/users.py index cb9f4c67b73..8db7360e8d8 100644 --- a/lib/galaxy/managers/users.py +++ b/lib/galaxy/managers/users.py @@ -81,7 +81,7 @@ class UserManager(base.ModelManager, deletable.PurgableManagerMixin): if not trans.app.config.allow_user_creation and not trans.user_is_admin: message = "User registration is disabled. Please contact your local Galaxy administrator for an account." if trans.app.config.error_email_to is not None: - message += " Contact: %s" % trans.app.config.error_email_to + message += f" Contact: {trans.app.config.error_email_to}" return None, message if not email or not username or not password or not confirm: return None, "Please provide email, username and password." @@ -170,7 +170,7 @@ class UserManager(base.ModelManager, deletable.PurgableManagerMixin): for address in user.addresses: self.session().delete(address) compliance_log = logging.getLogger('COMPLIANCE') - compliance_log.info('delete-user-event: %s' % user.username) + compliance_log.info(f'delete-user-event: {user.username}') # Maybe there is some case in the future where an admin needs # to prove that a user was using a server for some reason (e.g. # a court case.) So we make this painfully hard to recover (and @@ -564,10 +564,10 @@ class UserManager(base.ModelManager, deletable.PurgableManagerMixin): util.send_mail(frm, email, subject, body, self.app.config) trans.sa_session.add(reset_user) trans.sa_session.flush() - trans.log_event('User reset password: %s' % email) + trans.log_event(f'User reset password: {email}') except Exception as e: log.debug(body) - return "Failed to submit email. Please contact the administrator: %s" % util.unicodify(e) + return f"Failed to submit email. Please contact the administrator: {util.unicodify(e)}" else: return "Failed to produce password reset token. User not found." diff --git a/lib/galaxy/managers/workflows.py b/lib/galaxy/managers/workflows.py index 2c14748468d..c44335ba73d 100644 --- a/lib/galaxy/managers/workflows.py +++ b/lib/galaxy/managers/workflows.py @@ -187,7 +187,7 @@ class WorkflowsManager: workflow_invocation = q.get(decoded_invocation_id) if not workflow_invocation: encoded_wfi_id = trans.security.encode_id(decoded_invocation_id) - message = "'%s' is not a valid workflow invocation id" % encoded_wfi_id + message = f"'{encoded_wfi_id}' is not a valid workflow invocation id" raise exceptions.ObjectNotFound(message) self.check_security(trans, workflow_invocation, check_ownership=True, check_accessible=False) return workflow_invocation @@ -750,7 +750,7 @@ class WorkflowContentsManager(UsesAnnotations): try: module_injector.inject(step, steps=workflow.steps, exact_tools=False) except exceptions.ToolMissingException as e: - step_dict["label"] = "Unknown Tool with id '%s'" % e.tool_id + step_dict["label"] = f"Unknown Tool with id '{e.tool_id}'" step_dicts.append(step_dict) continue if step.type == 'tool' or step.type is None: @@ -758,7 +758,7 @@ class WorkflowContentsManager(UsesAnnotations): if tool: step_dict["label"] = step.label or tool.name else: - step_dict["label"] = "Unknown Tool with id '%s'" % step.tool_id + step_dict["label"] = f"Unknown Tool with id '{step.tool_id}'" step_dict["inputs"] = do_inputs(tool.inputs, step.state.inputs, "", step) elif step.type == 'subworkflow': step_dict["label"] = step.label or (step.subworkflow.name if step.subworkflow else "Missing workflow.") @@ -799,7 +799,7 @@ class WorkflowContentsManager(UsesAnnotations): # Load from database representation module = module_factory.from_workflow_step(trans, step, exact_tools=False) if not module: - raise exceptions.MessageException('Unrecognized step type: %s' % step.type) + raise exceptions.MessageException(f'Unrecognized step type: {step.type}') # Load label from state of data input modules, necessary for backward compatibility self.__set_default_label(step, module, step.tool_inputs) # Fix any missing parameters @@ -875,7 +875,7 @@ class WorkflowContentsManager(UsesAnnotations): step_dict['workflow_outputs'] = outputs if len(output_label_duplicate) > 0: output_label_duplicate_string = ", ".join(output_label_duplicate) - upgrade_message_dict['output_label_duplicate'] = "Ignoring duplicate labels: %s." % output_label_duplicate_string + upgrade_message_dict['output_label_duplicate'] = f"Ignoring duplicate labels: {output_label_duplicate_string}." if upgrade_message_dict: data['upgrade_messages'][step.order_index] = upgrade_message_dict @@ -989,7 +989,7 @@ class WorkflowContentsManager(UsesAnnotations): collection_type = map_over step_data_output['collection'] = True if step_data_output.get('collection_type'): - collection_type = "{}:{}".format(map_over, step_data_output['collection_type']) + collection_type = f"{map_over}:{step_data_output['collection_type']}" step_data_output['collection_type'] = collection_type return steps @@ -1031,7 +1031,7 @@ class WorkflowContentsManager(UsesAnnotations): # Load from database representation module = module_factory.from_workflow_step(trans, step) if not module: - raise exceptions.MessageException('Unrecognized step type: %s' % step.type) + raise exceptions.MessageException(f'Unrecognized step type: {step.type}') # Get user annotation. annotation_str = self.get_item_annotation_str(trans.sa_session, trans.user, step) or '' content_id = module.get_content_id() @@ -1102,12 +1102,12 @@ class WorkflowContentsManager(UsesAnnotations): for name, val in step_state.items(): input_type = type(val) if input_type == RuntimeValue: - input_dicts.append({"name": name, "description": "runtime parameter for tool %s" % module.get_name()}) + input_dicts.append({"name": name, "description": f"runtime parameter for tool {module.get_name()}"}) elif input_type == dict: # Input type is described by a dict, e.g. indexed parameters. for partval in val.values(): if type(partval) == RuntimeValue: - input_dicts.append({"name": name, "description": "runtime parameter for tool %s" % module.get_name()}) + input_dicts.append({"name": name, "description": f"runtime parameter for tool {module.get_name()}"}) step_dict['inputs'] = input_dicts # User outputs @@ -1209,7 +1209,7 @@ class WorkflowContentsManager(UsesAnnotations): elif step_type == 'parameter_input': label = "Input Parameter" else: - raise ValueError("Invalid step_type %s" % step_type) + raise ValueError(f"Invalid step_type {step_type}") if legacy: index = step.id else: @@ -1354,7 +1354,7 @@ class WorkflowContentsManager(UsesAnnotations): workflow_output = {"output_name": workflow_output} output_name = workflow_output["output_name"] if output_name in found_output_names: - raise exceptions.ObjectAttributeInvalidException("Duplicate workflow outputs with name [%s] found." % output_name) + raise exceptions.ObjectAttributeInvalidException(f"Duplicate workflow outputs with name [{output_name}] found.") if not output_name: raise exceptions.ObjectAttributeInvalidException("Workflow output with empty name encountered.") found_output_names.add(output_name) diff --git a/lib/galaxy/metadata/__init__.py b/lib/galaxy/metadata/__init__.py index 69ea2d65029..35a70bc0d84 100644 --- a/lib/galaxy/metadata/__init__.py +++ b/lib/galaxy/metadata/__init__.py @@ -87,7 +87,7 @@ class MetadataCollectionStrategy(metaclass=abc.ABCMeta): rval, rstring = json.load(f) except OSError: rval = False - rstring = "Metadata results could not be read from '%s'" % filename_results_code + rstring = f"Metadata results could not be read from '{filename_results_code}'" if not rval: log.debug(f'setting metadata externally failed for {dataset.__class__.__name__} {dataset.id}: {rstring}') @@ -202,11 +202,11 @@ class PortableDirectoryMetadataGenerator(MetadataCollectionStrategy): return '' def load_metadata(self, dataset, name, sa_session, working_directory, remote_metadata_directory=None): - metadata_output_path = os.path.join(working_directory, "metadata", "metadata_out_%s" % name) + metadata_output_path = os.path.join(working_directory, "metadata", f"metadata_out_{name}") self._load_metadata_from_path(dataset, metadata_output_path, working_directory, remote_metadata_directory) def external_metadata_set_successfully(self, dataset, name, sa_session, working_directory): - metadata_results_path = os.path.join(working_directory, "metadata", "metadata_results_%s" % name) + metadata_results_path = os.path.join(working_directory, "metadata", f"metadata_results_{name}") try: return self._metadata_results_from_file(dataset, metadata_results_path) except Exception: diff --git a/lib/galaxy/metadata/set_metadata.py b/lib/galaxy/metadata/set_metadata.py index 39964d21bdb..50a4ee4b50e 100644 --- a/lib/galaxy/metadata/set_metadata.py +++ b/lib/galaxy/metadata/set_metadata.py @@ -100,7 +100,7 @@ def set_meta_with_tool_provided(dataset_instance, file_dict, set_meta_kwds, data if max_metadata_value_size: for k, v in list(dataset_instance.metadata.items()): if total_size(v) > max_metadata_value_size: - log.info("Key %s too large for metadata, discarding" % k) + log.info(f"Key {k} too large for metadata, discarding") dataset_instance.metadata.remove_key(k) @@ -118,7 +118,7 @@ def set_metadata_portable(): with open(metadata_params_path) as f: metadata_params = json.load(f) except OSError: - raise Exception("Failed to find metadata/params.json from cwd [%s]" % tool_job_working_directory) + raise Exception(f"Failed to find metadata/params.json from cwd [{tool_job_working_directory}]") datatypes_config = metadata_params["datatypes_config"] job_metadata = metadata_params["job_metadata"] provided_metadata_style = metadata_params.get("provided_metadata_style") @@ -216,15 +216,15 @@ def set_metadata_portable(): 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) + filename_in = os.path.join(f"metadata/metadata_in_{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) - filename_results_code = os.path.join("metadata/metadata_results_%s" % output_name) - override_metadata = os.path.join("metadata/metadata_override_%s" % output_name) + filename_kwds = os.path.join(f"metadata/metadata_kwds_{output_name}") + filename_out = os.path.join(f"metadata/metadata_out_{output_name}") + filename_results_code = os.path.join(f"metadata/metadata_results_{output_name}") + override_metadata = os.path.join(f"metadata/metadata_override_{output_name}") dataset_filename_override = output_dict["filename_override"] # pre-20.05 this was a per job parameter and not a per dataset parameter, drop in 21.XX legacy_object_store_store_by = metadata_params.get("object_store_store_by", "id") @@ -234,7 +234,7 @@ def set_metadata_portable(): try: dataset.dataset.external_filename = dataset_filename_override store_by = output_dict.get("object_store_store_by", legacy_object_store_store_by) - extra_files_dir_name = "dataset_%s_files" % getattr(dataset.dataset, store_by) + extra_files_dir_name = f"dataset_{getattr(dataset.dataset, store_by)}_files" 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(output_name, dataset.dataset.id, dataset.dataset.uuid) @@ -354,7 +354,7 @@ def validate_and_load_datatypes_config(datatypes_config): datatypes_config = "configs/registry.xml" 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) + print(f"Metadata setting failed because registry.xml [{datatypes_config}] could not be found. You may retry setting metadata.") sys.exit(1) 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) diff --git a/lib/galaxy/model/__init__.py b/lib/galaxy/model/__init__.py index 873edab4fb4..bf9e56ffb6d 100644 --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -106,7 +106,7 @@ class RepresentById(_HasTable): def __repr__(self): try: - r = ''.format(self.__class__.__name__, cached_id(self), hex(id(self))) + r = f'' except Exception: r = object.__repr__(self) log.exception("Caught exception attempting to generate repr for: %s", r) @@ -339,7 +339,7 @@ class JobLike: extra = "" safe_id = getattr(self, "id", None) if safe_id is not None: - extra += "id=%s" % safe_id + extra += f"id={safe_id}" else: extra += "unflushed" @@ -413,7 +413,7 @@ class User(Dictifiable, RepresentById): """ message = validate_password_str(cleartext) if message: - raise Exception("Invalid password: %s" % message) + raise Exception(f"Invalid password: {message}") if User.use_pbkdf2: self.password = galaxy.security.passwords.hash_password(cleartext) else: @@ -885,7 +885,7 @@ class Job(JobLike, UsesCreateAndUpdateTime, Dictifiable, RepresentById): Return a tag that can be useful in identifying a Job. This returns the Job's get_id """ - return "%s" % self.id + return f"{self.id}" def set_session_id(self, session_id): self.session_id = session_id @@ -1681,7 +1681,7 @@ class JobExportHistoryArchive(RepresentById): def export_name(self): # Stream archive. hname = ready_name_for_url(self.history.name) - hname = "Galaxy-History-%s.tar" % (hname) + hname = f"Galaxy-History-{hname}.tar" if self.compressed: hname += ".gz" return hname @@ -1916,7 +1916,7 @@ class History(HasTags, Dictifiable, UsesAnnotations, HasName, RepresentById): object_session(self).flush() elif not isinstance(dataset, (HistoryDatasetAssociation, HistoryDatasetCollectionAssociation)): raise TypeError("You can only add Dataset and HistoryDatasetAssociation instances to a history" - + " ( you tried to add %s )." % str(dataset)) + + f" ( you tried to add {str(dataset)} ).") is_dataset = is_hda(dataset) if parent_id: for data in self.datasets: @@ -2361,7 +2361,7 @@ class LibraryPermissions(RepresentById): if isinstance(library_item, Library): self.library = library_item else: - raise Exception("Invalid Library specified: %s" % library_item.__class__.__name__) + raise Exception(f"Invalid Library specified: {library_item.__class__.__name__}") self.role = role @@ -2371,7 +2371,7 @@ class LibraryFolderPermissions(RepresentById): if isinstance(library_item, LibraryFolder): self.folder = library_item else: - raise Exception("Invalid LibraryFolder specified: %s" % library_item.__class__.__name__) + raise Exception(f"Invalid LibraryFolder specified: {library_item.__class__.__name__}") self.role = role @@ -2381,7 +2381,7 @@ class LibraryDatasetPermissions(RepresentById): if isinstance(library_item, LibraryDataset): self.library_dataset = library_item else: - raise Exception("Invalid LibraryDataset specified: %s" % library_item.__class__.__name__) + raise Exception(f"Invalid LibraryDataset specified: {library_item.__class__.__name__}") self.role = role @@ -2391,7 +2391,7 @@ class LibraryDatasetDatasetAssociationPermissions(RepresentById): if isinstance(library_item, LibraryDatasetDatasetAssociation): self.library_dataset_dataset_association = library_item else: - raise Exception("Invalid LibraryDatasetDatasetAssociation specified: %s" % library_item.__class__.__name__) + raise Exception(f"Invalid LibraryDatasetDatasetAssociation specified: {library_item.__class__.__name__}") self.role = role @@ -2500,7 +2500,7 @@ class Dataset(StorableObject, RepresentById, _HasTable): def get_file_name(self): if not self.external_filename: - assert self.object_store is not None, "Object Store has not been initialized for dataset %s" % self.id + assert self.object_store is not None, f"Object Store has not been initialized for dataset {self.id}" if self.object_store.exists(self): return self.object_store.get_filename(self) else: @@ -2550,7 +2550,7 @@ class Dataset(StorableObject, RepresentById, _HasTable): def extra_files_path_name_from(self, object_store): store_by = self.store_by if store_by is not None: - return "dataset_%s_files" % getattr(self, store_by) + return f"dataset_{getattr(self, store_by)}_files" else: return None @@ -2726,7 +2726,7 @@ def datatype_for_extension(extension, datatypes_registry=None): extension = 'data' ret = datatypes_registry.get_datatype_by_extension(extension) if ret is None: - log.warning("Datatype class not found for extension '%s'" % extension) + log.warning(f"Datatype class not found for extension '{extension}'") return datatypes_registry.get_datatype_by_extension('data') return ret @@ -3011,13 +3011,13 @@ class DatasetInstance: # None means converter is running first time return None elif dep_dataset.state == Job.states.ERROR: - raise ConverterDependencyException("A dependency (%s) was in an error state." % dependency) + raise ConverterDependencyException(f"A dependency ({dependency}) was in an error state.") elif dep_dataset.state != Job.states.OK: # Pending return None deps[dependency] = dep_dataset except NoConverterException: - raise NoConverterException("A dependency (%s) is missing a converter." % dependency) + raise NoConverterException(f"A dependency ({dependency}) is missing a converter.") except KeyError: pass # No deps new_dataset = next(iter(self.datatype.convert_dataset(trans, self, target_ext, return_output=True, visible=False, deps=deps, target_context=target_context, history=history).values())) @@ -4073,13 +4073,13 @@ class ImplicitlyConvertedDatasetAssociation(RepresentById): elif isinstance(dataset, LibraryDatasetDatasetAssociation): self.dataset_ldda = dataset else: - raise AttributeError('Unknown dataset type provided for dataset: %s' % type(dataset)) + raise AttributeError(f'Unknown dataset type provided for dataset: {type(dataset)}') if isinstance(parent, HistoryDatasetAssociation): self.parent_hda = parent elif isinstance(parent, LibraryDatasetDatasetAssociation): self.parent_ldda = parent else: - raise AttributeError('Unknown dataset type provided for parent: %s' % type(parent)) + raise AttributeError(f'Unknown dataset type provided for parent: {type(parent)}') self.type = file_type self.deleted = deleted self.purged = purged @@ -4097,7 +4097,7 @@ class ImplicitlyConvertedDatasetAssociation(RepresentById): try: os.unlink(self.file_name) except Exception as e: - log.error("Failed to purge associated file ({}) from disk: {}".format(self.file_name, unicodify(e))) + log.error(f"Failed to purge associated file ({self.file_name}) from disk: {unicodify(e)}") DEFAULT_COLLECTION_NAME = "Unnamed Collection" @@ -4714,7 +4714,7 @@ class DatasetCollectionElement(Dictifiable, RepresentById): elif isinstance(element, DatasetCollection): self.child_collection = element elif element != self.UNINITIALIZED_ELEMENT: - raise AttributeError('Unknown element type provided: %s' % type(element)) + raise AttributeError(f'Unknown element type provided: {type(element)}') self.id = id self.collection = collection @@ -4987,13 +4987,13 @@ class Workflow(Dictifiable, RepresentById): for step in self.steps: if order_index == step.order_index: return step - raise KeyError("Workflow has no step with order_index '%s'" % order_index) + raise KeyError(f"Workflow has no step with order_index '{order_index}'") def step_by_label(self, label): for step in self.steps: if label == step.label: return step - raise KeyError("Workflow has no step with label '%s'" % label) + raise KeyError(f"Workflow has no step with label '{label}'") @property def input_steps(self): @@ -5072,7 +5072,7 @@ class Workflow(Dictifiable, RepresentById): def log_str(self): extra = "" if self.stored_workflow: - extra = ",name=%s" % self.stored_workflow.name + extra = f",name={self.stored_workflow.name}" return "Workflow[id=%d%s]" % (self.id, extra) @@ -5537,7 +5537,7 @@ class WorkflowInvocation(UsesCreateAndUpdateTime, Dictifiable, RepresentById): # That probably isn't good. workflow_output = self.workflow.workflow_output_for(label) if workflow_output: - raise Exception("Failed to find workflow output named [%s], one was defined but none registered during execution." % label) + raise Exception(f"Failed to find workflow output named [{label}], one was defined but none registered during execution.") else: raise Exception(f"Failed to find workflow output named [{label}], workflow doesn't define output by that name - valid names are {self.workflow.workflow_output_labels}.") @@ -5548,7 +5548,7 @@ class WorkflowInvocation(UsesCreateAndUpdateTime, Dictifiable, RepresentById): for input_dataset_collection_assoc in self.input_dataset_collections: if input_dataset_collection_assoc.workflow_step.label == label: return input_dataset_collection_assoc.dataset_collection - raise Exception("Failed to find input with label %s" % label) + raise Exception(f"Failed to find input with label {label}") @property def output_associations(self): @@ -5716,7 +5716,7 @@ class WorkflowInvocation(UsesCreateAndUpdateTime, Dictifiable, RepresentById): extra = "" safe_id = getattr(self, "id", None) if safe_id is not None: - extra += "id=%s" % safe_id + extra += f"id={safe_id}" else: extra += "unflushed" return f"{self.__class__.__name__}[{extra}]" @@ -5905,7 +5905,7 @@ class MetadataFile(StorableObject, RepresentById): if store_by == 'id' and self.id is None: self.flush() identifier = getattr(self, store_by) - alt_name = "metadata_%s.dat" % identifier + alt_name = f"metadata_{identifier}.dat" if not object_store.exists(self, extra_dir='_metadata_files', extra_dir_at_root=True, alt_name=alt_name): object_store.create(self, extra_dir='_metadata_files', extra_dir_at_root=True, alt_name=alt_name) path = object_store.get_filename(self, extra_dir='_metadata_files', extra_dir_at_root=True, alt_name=alt_name) @@ -6190,7 +6190,7 @@ class UserAuthnzToken(UserMixin, RepresentById): model = cls.user_model() instance = model(*args, **kwargs) if cls.get_users_by_email(instance.email).first(): - raise Exception("User with this email '%s' already exists." % instance.email) + raise Exception(f"User with this email '{instance.email}' already exists.") instance.set_random_password() cls.sa_session.add(instance) cls.sa_session.flush() diff --git a/lib/galaxy/model/database_heartbeat.py b/lib/galaxy/model/database_heartbeat.py index 982f3eeac01..00517752538 100644 --- a/lib/galaxy/model/database_heartbeat.py +++ b/lib/galaxy/model/database_heartbeat.py @@ -34,7 +34,7 @@ class DatabaseHeartbeat: def start(self): if not self.active: - self.thread = threading.Thread(target=self.send_database_heartbeat, name="database_heartbeart_%s.thread" % self.server_name) + self.thread = threading.Thread(target=self.send_database_heartbeat, name=f"database_heartbeart_{self.server_name}.thread") self.thread.daemon = True self.active = True self.thread.start() diff --git a/lib/galaxy/model/dataset_collections/registry.py b/lib/galaxy/model/dataset_collections/registry.py index 6c50d2c182a..dd3b83d5a10 100644 --- a/lib/galaxy/model/dataset_collections/registry.py +++ b/lib/galaxy/model/dataset_collections/registry.py @@ -18,7 +18,7 @@ class DatasetCollectionTypesRegistry: def prototype(self, plugin_type): plugin_type_object = self.get(plugin_type) if not hasattr(plugin_type_object, 'prototype_elements'): - raise Exception("Cannot pre-determine structure for collection of type %s" % plugin_type) + raise Exception(f"Cannot pre-determine structure for collection of type {plugin_type}") dataset_collection = model.DatasetCollection() for e in plugin_type_object.prototype_elements(): diff --git a/lib/galaxy/model/dataset_collections/structure.py b/lib/galaxy/model/dataset_collections/structure.py index f5ab797863a..ad2c7dee30f 100644 --- a/lib/galaxy/model/dataset_collections/structure.py +++ b/lib/galaxy/model/dataset_collections/structure.py @@ -59,7 +59,7 @@ class UninitializedTree(BaseTree): return UninitializedTree(new_collection_type) def __str__(self): - return "UninitializedTree[collection_type=%s]" % self.collection_type_description + return f"UninitializedTree[collection_type={self.collection_type_description}]" class Tree(BaseTree): @@ -137,7 +137,7 @@ class Tree(BaseTree): return Tree(cloned_children, self.collection_type_description) def __str__(self): - return "Tree[collection_type={},children={}]".format(self.collection_type_description, ",".join(map(lambda identifier_and_element: "{}={}".format(identifier_and_element[0], identifier_and_element[1]), self.children))) + return f"Tree[collection_type={self.collection_type_description},children={','.join(map(lambda identifier_and_element: '{}={}'.format(identifier_and_element[0], identifier_and_element[1]), self.children))}]" def tool_output_to_structure(get_sliced_input_collection_structure, tool_output, collections_manager): @@ -161,7 +161,7 @@ def tool_output_to_structure(get_sliced_input_collection_structure, tool_output, collection_type = get_sliced_input_collection_structure(tool_output.structure.collection_type_source).collection_type_description.collection_type if not collection_type: - raise Exception("Failed to determine collection type for mapping over output %s" % tool_output.name) + raise Exception(f"Failed to determine collection type for mapping over output {tool_output.name}") tree = UninitializedTree(collection_type_descriptions.for_collection_type(collection_type)) diff --git a/lib/galaxy/model/dataset_collections/type_description.py b/lib/galaxy/model/dataset_collections/type_description.py index 9b7e69da4f9..1297d294db5 100644 --- a/lib/galaxy/model/dataset_collections/type_description.py +++ b/lib/galaxy/model/dataset_collections/type_description.py @@ -97,7 +97,7 @@ class CollectionTypeDescription: def subcollection_type_description(self): if not self.__has_subcollections: - raise ValueError("Cannot generate subcollection type description for flat type %s" % self.collection_type) + raise ValueError(f"Cannot generate subcollection type description for flat type {self.collection_type}") subcollection_type = self.collection_type.split(":", 1)[1] return self.collection_type_description_factory.for_collection_type(subcollection_type) @@ -123,7 +123,7 @@ class CollectionTypeDescription: return self.collection_type_description_factory.for_collection_type(collection_type) def __str__(self): - return "CollectionTypeDescription[%s]" % self.collection_type + return f"CollectionTypeDescription[{self.collection_type}]" def map_over_collection_type(mapped_over_collection_type, target_collection_type): diff --git a/lib/galaxy/model/item_attrs.py b/lib/galaxy/model/item_attrs.py index 9ce45f8d259..473b3c77ae9 100644 --- a/lib/galaxy/model/item_attrs.py +++ b/lib/galaxy/model/item_attrs.py @@ -24,7 +24,7 @@ class UsesItemRatings: webapp_model = galaxy.model item_rating_assoc_class = self._get_item_rating_assoc_class(item, webapp_model=webapp_model) if not item_rating_assoc_class: - raise Exception("Item does not have ratings: %s" % item.__class__.__name__) + raise Exception(f"Item does not have ratings: {item.__class__.__name__}") item_id_filter = self._get_item_id_filter_str(item, item_rating_assoc_class) ave_rating = db_session.query(func.avg(item_rating_assoc_class.rating)).filter(item_id_filter).scalar() # Convert ave_rating to float; note: if there are no item ratings, ave rating is None. @@ -61,7 +61,7 @@ class UsesItemRatings: webapp_model = galaxy.model item_rating_assoc_class = self._get_item_rating_assoc_class(item, webapp_model=webapp_model) if not item_rating_assoc_class: - raise Exception("Item does not have ratings: %s" % item.__class__.__name__) + raise Exception(f"Item does not have ratings: {item.__class__.__name__}") # Query rating table by user and item id. item_id_filter = self._get_item_id_filter_str(item, item_rating_assoc_class) @@ -71,7 +71,7 @@ class UsesItemRatings: """ Returns an item's item-rating association class. """ if webapp_model is None: webapp_model = galaxy.model - item_rating_assoc_class = '%sRatingAssociation' % item.__class__.__name__ + item_rating_assoc_class = f'{item.__class__.__name__}RatingAssociation' return getattr(webapp_model, item_rating_assoc_class, None) def _get_item_id_filter_str(self, item, item_rating_assoc_class): @@ -170,7 +170,7 @@ def add_item_annotation(db_session, user, item, annotation): def _get_annotation_assoc_class(item): """ Returns an item's item-annotation association class. """ - class_name = '%sAnnotationAssociation' % item.__class__.__name__ + class_name = f'{item.__class__.__name__}AnnotationAssociation' return getattr(galaxy.model, class_name, None) diff --git a/lib/galaxy/model/metadata.py b/lib/galaxy/model/metadata.py index 0766119be8f..c73996e0195 100644 --- a/lib/galaxy/model/metadata.py +++ b/lib/galaxy/model/metadata.py @@ -140,7 +140,7 @@ class MetadataCollection(Mapping): if name in self.parent._metadata: del self.parent._metadata[name] else: - log.info("Attempted to delete invalid key '%s' from MetadataCollection" % name) + log.info(f"Attempted to delete invalid key '{name}' from MetadataCollection") def element_is_set(self, name): """ @@ -156,7 +156,7 @@ class MetadataCollection(Mapping): try: meta_val = self.parent._metadata[name] except KeyError: - log.debug("no metadata with name %s found" % (name)) + log.debug(f"no metadata with name {name} found") return False meta_spec = self.parent.metadata.spec[name] @@ -197,7 +197,7 @@ class MetadataCollection(Mapping): elif isinstance(json_dict, dict): JSONified_dict = json_dict else: - raise ValueError("json_dict must be either a dictionary or a string, got %s." % (type(json_dict))) + raise ValueError(f"json_dict must be either a dictionary or a string, got {type(json_dict)}.") else: raise ValueError("You must provide either a filename or a json_dict") diff --git a/lib/galaxy/model/migrate/check.py b/lib/galaxy/model/migrate/check.py index f864ad60c72..2659afeb564 100644 --- a/lib/galaxy/model/migrate/check.py +++ b/lib/galaxy/model/migrate/check.py @@ -39,12 +39,12 @@ def create_or_verify_database(url, galaxy_config_file, engine_options=None, app= encoding = app and getattr(app.config, "database_encoding", None) create_kwds = {} - message = "Creating database for URI [%s]" % url + message = f"Creating database for URI [{url}]" if template: - message += " from template [%s]" % template + message += f" from template [{template}]" create_kwds["template"] = template if encoding: - message += " with encoding [%s]" % encoding + message += f" with encoding [{encoding}]" create_kwds["encoding"] = encoding log.info(message) create_database(url, **create_kwds) @@ -125,15 +125,15 @@ def create_or_verify_database(url, galaxy_config_file, engine_options=None, app= if migrate_repository.versions.latest != db_schema.version: config_arg = '' if galaxy_config_file and os.path.abspath(os.path.join(os.getcwd(), 'config', 'galaxy.ini')) != galaxy_config_file: - config_arg = ' -c %s' % galaxy_config_file.replace(os.path.abspath(os.getcwd()), '.') + config_arg = f" -c {galaxy_config_file.replace(os.path.abspath(os.getcwd()), '.')}" expect_msg = "Your database has version '%d' but this code expects version '%d'" % (db_schema.version, migrate_repository.versions.latest) instructions = "" if db_schema.version > migrate_repository.versions.latest: instructions = "To downgrade the database schema you have to checkout the Galaxy version that you were running previously. " cmd_msg = "sh manage_db.sh%s downgrade %d" % (config_arg, migrate_repository.versions.latest) else: - cmd_msg = "sh manage_db.sh%s upgrade" % config_arg - backup_msg = "Please backup your database and then migrate the database schema by running '%s'." % cmd_msg + cmd_msg = f"sh manage_db.sh{config_arg} upgrade" + backup_msg = f"Please backup your database and then migrate the database schema by running '{cmd_msg}'." allow_future_database = os.environ.get("GALAXY_ALLOW_FUTURE_DATABASE", False) if db_schema.version > migrate_repository.versions.latest and allow_future_database: log.warning("WARNING: Database is from the future, but GALAXY_ALLOW_FUTURE_DATABASE is set, so Galaxy will continue to start.") @@ -148,7 +148,7 @@ def migrate_to_current_version(engine, schema): try: changeset = schema.changeset(None) except Exception as e: - log.error("Problem determining migration changeset for engine [%s]" % engine) + log.error(f"Problem determining migration changeset for engine [{engine}]") raise e for ver, change in changeset: nextver = ver + changeset.step diff --git a/lib/galaxy/model/migrate/versions/0004_indexes_and_defaults.py b/lib/galaxy/model/migrate/versions/0004_indexes_and_defaults.py index 2cad6a89e82..e050e1384d7 100644 --- a/lib/galaxy/model/migrate/versions/0004_indexes_and_defaults.py +++ b/lib/galaxy/model/migrate/versions/0004_indexes_and_defaults.py @@ -28,12 +28,12 @@ def upgrade(migrate_engine): add_index('ix_galaxy_user_deleted', User_table, 'deleted') add_index('ix_galaxy_user_purged', User_table, 'purged') # Set the default data in the galaxy_user table, but only for null values - cmd = "UPDATE galaxy_user SET deleted = %s WHERE deleted is null" % engine_false(migrate_engine) + cmd = f"UPDATE galaxy_user SET deleted = {engine_false(migrate_engine)} WHERE deleted is null" try: migrate_engine.execute(cmd) except Exception: log.exception("Setting default data for galaxy_user.deleted column failed.") - cmd = "UPDATE galaxy_user SET purged = %s WHERE purged is null" % engine_false(migrate_engine) + cmd = f"UPDATE galaxy_user SET purged = {engine_false(migrate_engine)} WHERE purged is null" try: migrate_engine.execute(cmd) except Exception: diff --git a/lib/galaxy/model/migrate/versions/0036_add_deleted_column_to_library_template_assoc_tables.py b/lib/galaxy/model/migrate/versions/0036_add_deleted_column_to_library_template_assoc_tables.py index f2d74c0402e..9d7d9359c59 100644 --- a/lib/galaxy/model/migrate/versions/0036_add_deleted_column_to_library_template_assoc_tables.py +++ b/lib/galaxy/model/migrate/versions/0036_add_deleted_column_to_library_template_assoc_tables.py @@ -25,7 +25,7 @@ def upgrade(migrate_engine): assert c is LibraryInfoAssociation_table.c.deleted except Exception: log.exception("Adding column 'deleted' to 'library_info_association' table failed.") - cmd = "UPDATE library_info_association SET deleted = %s" % engine_false(migrate_engine) + cmd = f"UPDATE library_info_association SET deleted = {engine_false(migrate_engine)}" try: migrate_engine.execute(cmd) except Exception: @@ -37,7 +37,7 @@ def upgrade(migrate_engine): assert c is LibraryFolderInfoAssociation_table.c.deleted except Exception: log.exception("Adding column 'deleted' to 'library_folder_info_association' table failed.") - cmd = "UPDATE library_folder_info_association SET deleted = %s" % engine_false(migrate_engine) + cmd = f"UPDATE library_folder_info_association SET deleted = {engine_false(migrate_engine)}" try: migrate_engine.execute(cmd) except Exception: @@ -49,7 +49,7 @@ def upgrade(migrate_engine): assert c is LibraryDatasetDatasetInfoAssociation_table.c.deleted except Exception: log.exception("Adding column 'deleted' to 'library_dataset_dataset_info_association' table failed.") - cmd = "UPDATE library_dataset_dataset_info_association SET deleted = %s" % engine_false(migrate_engine) + cmd = f"UPDATE library_dataset_dataset_info_association SET deleted = {engine_false(migrate_engine)}" try: migrate_engine.execute(cmd) except Exception: diff --git a/lib/galaxy/model/migrate/versions/0038_add_inheritable_column_to_library_template_assoc_tables.py b/lib/galaxy/model/migrate/versions/0038_add_inheritable_column_to_library_template_assoc_tables.py index 1ef26094e24..9a607346d2c 100644 --- a/lib/galaxy/model/migrate/versions/0038_add_inheritable_column_to_library_template_assoc_tables.py +++ b/lib/galaxy/model/migrate/versions/0038_add_inheritable_column_to_library_template_assoc_tables.py @@ -52,7 +52,7 @@ def upgrade(migrate_engine): assert c is LibraryInfoAssociation_table.c.inheritable except Exception: log.exception("Adding column 'inheritable' to 'library_info_association' table failed.") - cmd = "UPDATE library_info_association SET inheritable = %s" % engine_false(migrate_engine) + cmd = f"UPDATE library_info_association SET inheritable = {engine_false(migrate_engine)}" try: migrate_engine.execute(cmd) except Exception: @@ -64,7 +64,7 @@ def upgrade(migrate_engine): assert c is LibraryFolderInfoAssociation_table.c.inheritable except Exception: log.exception("Adding column 'inheritable' to 'library_folder_info_association' table failed.") - cmd = "UPDATE library_folder_info_association SET inheritable = %s" % engine_false(migrate_engine) + cmd = f"UPDATE library_folder_info_association SET inheritable = {engine_false(migrate_engine)}" try: migrate_engine.execute(cmd) except Exception: diff --git a/lib/galaxy/model/migrate/versions/0043_visualization_sharing_tagging_annotating.py b/lib/galaxy/model/migrate/versions/0043_visualization_sharing_tagging_annotating.py index 56846dbdf22..d0230b9a3d6 100644 --- a/lib/galaxy/model/migrate/versions/0043_visualization_sharing_tagging_annotating.py +++ b/lib/galaxy/model/migrate/versions/0043_visualization_sharing_tagging_annotating.py @@ -78,7 +78,7 @@ def upgrade(migrate_engine): add_column(deleted_column, Visualization_table, metadata, index_name="ix_visualization_deleted") try: # Fill column with default value. - cmd = "UPDATE visualization SET deleted = %s" % engine_false(migrate_engine) + cmd = f"UPDATE visualization SET deleted = {engine_false(migrate_engine)}" migrate_engine.execute(cmd) except Exception: log.exception("Updating column 'deleted' of table 'visualization' failed.") @@ -87,7 +87,7 @@ def upgrade(migrate_engine): add_column(importable_column, Visualization_table, metadata, index_name='ix_visualization_importable') try: # Fill column with default value. - cmd = "UPDATE visualization SET importable = %s" % engine_false(migrate_engine) + cmd = f"UPDATE visualization SET importable = {engine_false(migrate_engine)}" migrate_engine.execute(cmd) except Exception: log.exception("Updating column 'importable' of table 'visualization' failed.") @@ -102,7 +102,7 @@ def upgrade(migrate_engine): add_column(published_column, Visualization_table, metadata, index_name='ix_visualization_published') try: # Fill column with default value. - cmd = "UPDATE visualization SET published = %s" % engine_false(migrate_engine) + cmd = f"UPDATE visualization SET published = {engine_false(migrate_engine)}" migrate_engine.execute(cmd) except Exception: log.exception("Updating column 'published' of table 'visualization' failed.") diff --git a/lib/galaxy/model/migrate/versions/0048_dataset_instance_state_column.py b/lib/galaxy/model/migrate/versions/0048_dataset_instance_state_column.py index 253e848e574..a68b0fd7942 100644 --- a/lib/galaxy/model/migrate/versions/0048_dataset_instance_state_column.py +++ b/lib/galaxy/model/migrate/versions/0048_dataset_instance_state_column.py @@ -28,7 +28,7 @@ def upgrade(migrate_engine): for table_name in DATASET_INSTANCE_TABLE_NAMES: col = Column("state", TrimmedString(64), index=True, nullable=True) - index_name = "ix_%s_state" % table_name + index_name = f"ix_{table_name}_state" add_column(col, table_name, metadata, index_name=index_name) diff --git a/lib/galaxy/model/migrate/versions/0051_imported_col_for_jobs_table.py b/lib/galaxy/model/migrate/versions/0051_imported_col_for_jobs_table.py index 9e66a39d64b..fb547d3b30e 100644 --- a/lib/galaxy/model/migrate/versions/0051_imported_col_for_jobs_table.py +++ b/lib/galaxy/model/migrate/versions/0051_imported_col_for_jobs_table.py @@ -22,7 +22,7 @@ def upgrade(migrate_engine): c = Column("imported", Boolean, default=False, index=True) add_column(c, Jobs_table, metadata, index_name="ix_job_imported") try: - migrate_engine.execute("UPDATE job SET imported=%s" % engine_false(migrate_engine)) + migrate_engine.execute(f"UPDATE job SET imported={engine_false(migrate_engine)}") except Exception: log.exception("Updating column 'imported' of table 'job' failed.") diff --git a/lib/galaxy/model/migrate/versions/0060_history_archive_import.py b/lib/galaxy/model/migrate/versions/0060_history_archive_import.py index 8e240a30f8f..cc42c710608 100644 --- a/lib/galaxy/model/migrate/versions/0060_history_archive_import.py +++ b/lib/galaxy/model/migrate/versions/0060_history_archive_import.py @@ -38,7 +38,7 @@ def upgrade(migrate_engine): assert importing_col is History_table.c.importing # Initialize column to false. - migrate_engine.execute("UPDATE history SET importing=%s" % engine_false(migrate_engine)) + migrate_engine.execute(f"UPDATE history SET importing={engine_false(migrate_engine)}") except Exception: log.exception("Adding column 'importing' to history table failed.") diff --git a/lib/galaxy/model/migrate/versions/0067_populate_sequencer_table.py b/lib/galaxy/model/migrate/versions/0067_populate_sequencer_table.py index 2af5e935635..b23a3907299 100644 --- a/lib/galaxy/model/migrate/versions/0067_populate_sequencer_table.py +++ b/lib/galaxy/model/migrate/versions/0067_populate_sequencer_table.py @@ -30,12 +30,12 @@ metadata = MetaData() def get_latest_id(migrate_engine, table): - result = migrate_engine.execute("select id from %s order by id desc" % table) + result = migrate_engine.execute(f"select id from {table} order by id desc") row = result.fetchone() if row: return row[0] else: - raise Exception('Unable to get the latest id in the %s table.' % table) + raise Exception(f'Unable to get the latest id in the {table} table.') def create_sequencer_form_definition(migrate_engine): diff --git a/lib/galaxy/model/migrate/versions/0074_add_purged_column_to_library_dataset_table.py b/lib/galaxy/model/migrate/versions/0074_add_purged_column_to_library_dataset_table.py index 4a6b8b96b01..891aa623588 100644 --- a/lib/galaxy/model/migrate/versions/0074_add_purged_column_to_library_dataset_table.py +++ b/lib/galaxy/model/migrate/versions/0074_add_purged_column_to_library_dataset_table.py @@ -20,7 +20,7 @@ def upgrade(migrate_engine): c = Column('purged', Boolean, index=True, default=False) add_column(c, 'library_dataset', metadata, index_name='ix_library_dataset_purged') # Update the purged flag to the default False - cmd = "UPDATE library_dataset SET purged = %s;" % engine_false(migrate_engine) + cmd = f"UPDATE library_dataset SET purged = {engine_false(migrate_engine)};" try: migrate_engine.execute(cmd) except Exception: @@ -28,7 +28,7 @@ def upgrade(migrate_engine): # Update the purged flag for those LibaryDatasets whose purged flag should be True. This happens # when the LibraryDataset has no active LibraryDatasetDatasetAssociations. - cmd = "SELECT * FROM library_dataset WHERE deleted = %s;" % engine_true(migrate_engine) + cmd = f"SELECT * FROM library_dataset WHERE deleted = {engine_true(migrate_engine)};" deleted_lds = migrate_engine.execute(cmd).fetchall() for row in deleted_lds: cmd = "SELECT * FROM library_dataset_dataset_association WHERE library_dataset_id = %d AND library_dataset_dataset_association.deleted = %s;" % (int(row.id), engine_false(migrate_engine)) diff --git a/lib/galaxy/model/migrate/versions/0076_fix_form_values_data_corruption.py b/lib/galaxy/model/migrate/versions/0076_fix_form_values_data_corruption.py index ab4f141fe96..fad58b7507e 100644 --- a/lib/galaxy/model/migrate/versions/0076_fix_form_values_data_corruption.py +++ b/lib/galaxy/model/migrate/versions/0076_fix_form_values_data_corruption.py @@ -36,15 +36,15 @@ def upgrade(migrate_engine): field_values_str = _sniffnfix_pg9_hex(str(row['field_values'])) try: # Encoding errors? Just to be safe. - print("Attempting to fix row %s" % row['id']) - print("Prior to replacement: %s" % field_values_str) + print(f"Attempting to fix row {row['id']}") + print(f"Prior to replacement: {field_values_str}") except Exception: pass field_values_dict = {} # look for each field name in the values and extract its value (string) for index in range(len(fields_list)): field = fields_list[index] - field_name_key = '"%s": "' % field['name'] + field_name_key = f"\"{field['name']}\": \"" field_index = field_values_str.find(field_name_key) if field_index == -1: # if the field name is not present the field values dict then @@ -60,7 +60,7 @@ def upgrade(migrate_engine): # if this is not the last field then the value string lies between # this field name and the next field name next_field = fields_list[index + 1] - next_field_index = field_values_str.find('", "%s": "' % next_field['name']) + next_field_index = field_values_str.find(f"\", \"{next_field['name']}\": \"") value = field_values_str[field_index + len(field_name_key):next_field_index] # clean up the value string, escape the required quoutes and newline characters value = value.replace("'", "\''")\ @@ -75,7 +75,7 @@ def upgrade(migrate_engine): cmd = "UPDATE form_values SET content='%s' WHERE id=%i" % (json_values, int(row['id'])) migrate_engine.execute(cmd) try: - print("Post replacement: %s" % json_values) + print(f"Post replacement: {json_values}") except Exception: pass if corrupted_rows: diff --git a/lib/galaxy/model/migrate/versions/0086_add_tool_shed_repository_table_columns.py b/lib/galaxy/model/migrate/versions/0086_add_tool_shed_repository_table_columns.py index 0d8a6cb24ac..d916fac0476 100644 --- a/lib/galaxy/model/migrate/versions/0086_add_tool_shed_repository_table_columns.py +++ b/lib/galaxy/model/migrate/versions/0086_add_tool_shed_repository_table_columns.py @@ -33,13 +33,13 @@ def upgrade(migrate_engine): c = Column("includes_datatypes", Boolean, index=True, default=False) add_column(c, ToolShedRepository_table, metadata, index_name="ix_tool_shed_repository_includes_datatypes") try: - migrate_engine.execute("UPDATE tool_shed_repository SET includes_datatypes=%s" % engine_false(migrate_engine)) + migrate_engine.execute(f"UPDATE tool_shed_repository SET includes_datatypes={engine_false(migrate_engine)}") except Exception: log.exception("Updating column 'includes_datatypes' of table 'tool_shed_repository' failed.") c = Column("update_available", Boolean, default=False) add_column(c, ToolShedRepository_table, metadata) try: - migrate_engine.execute("UPDATE tool_shed_repository SET update_available=%s" % engine_false(migrate_engine)) + migrate_engine.execute(f"UPDATE tool_shed_repository SET update_available={engine_false(migrate_engine)}") except Exception: log.exception("Updating column 'update_available' of table 'tool_shed_repository' failed.") diff --git a/lib/galaxy/model/migrate/versions/0088_add_installed_changeset_revison_column.py b/lib/galaxy/model/migrate/versions/0088_add_installed_changeset_revison_column.py index e2fc0a92b6e..b4f806577b4 100644 --- a/lib/galaxy/model/migrate/versions/0088_add_installed_changeset_revison_column.py +++ b/lib/galaxy/model/migrate/versions/0088_add_installed_changeset_revison_column.py @@ -39,8 +39,8 @@ def upgrade(migrate_engine): update_count = 0 for row in tool_shed_repositories: cmd = "UPDATE tool_shed_repository " \ - + "SET installed_changeset_revision = '%s' " % row.changeset_revision \ - + "WHERE changeset_revision = '%s';" % row.changeset_revision + + f"SET installed_changeset_revision = '{row.changeset_revision}' " \ + + f"WHERE changeset_revision = '{row.changeset_revision}';" migrate_engine.execute(cmd) update_count += 1 print("Updated the installed_changeset_revision column for ", update_count, " rows in the tool_shed_repository table.") diff --git a/lib/galaxy/model/migrate/versions/0089_add_object_store_id_columns.py b/lib/galaxy/model/migrate/versions/0089_add_object_store_id_columns.py index dc50e69da46..660dbda7731 100644 --- a/lib/galaxy/model/migrate/versions/0089_add_object_store_id_columns.py +++ b/lib/galaxy/model/migrate/versions/0089_add_object_store_id_columns.py @@ -21,7 +21,7 @@ def upgrade(migrate_engine): t = Table(t_name, metadata, autoload=True) c = Column("object_store_id", TrimmedString(255), index=True) try: - c.create(t, index_name="ix_%s_object_store_id" % t_name) + c.create(t, index_name=f"ix_{t_name}_object_store_id") assert c is t.c.object_store_id except Exception: log.exception("Adding object_store_id column to %s table failed.", t_name) diff --git a/lib/galaxy/model/migrate/versions/0090_add_tool_shed_repository_table_columns.py b/lib/galaxy/model/migrate/versions/0090_add_tool_shed_repository_table_columns.py index 3db867cb819..e5ee9f78347 100644 --- a/lib/galaxy/model/migrate/versions/0090_add_tool_shed_repository_table_columns.py +++ b/lib/galaxy/model/migrate/versions/0090_add_tool_shed_repository_table_columns.py @@ -30,13 +30,13 @@ def upgrade(migrate_engine): c = Column("uninstalled", Boolean, default=False) add_column(c, ToolShedRepository_table, metadata) try: - migrate_engine.execute("UPDATE tool_shed_repository SET uninstalled=%s" % engine_false(migrate_engine)) + migrate_engine.execute(f"UPDATE tool_shed_repository SET uninstalled={engine_false(migrate_engine)}") except Exception: log.exception("Updating column 'uninstalled' of table 'tool_shed_repository' failed.") c = Column("dist_to_shed", Boolean, default=False) add_column(c, ToolShedRepository_table, metadata) try: - migrate_engine.execute("UPDATE tool_shed_repository SET dist_to_shed=%s" % engine_false(migrate_engine)) + migrate_engine.execute(f"UPDATE tool_shed_repository SET dist_to_shed={engine_false(migrate_engine)}") except Exception: log.exception("Updating column 'dist_to_shed' of table 'tool_shed_repository' failed.") diff --git a/lib/galaxy/model/migrate/versions/0096_openid_provider.py b/lib/galaxy/model/migrate/versions/0096_openid_provider.py index 2336b31782d..752991ff9c7 100644 --- a/lib/galaxy/model/migrate/versions/0096_openid_provider.py +++ b/lib/galaxy/model/migrate/versions/0096_openid_provider.py @@ -28,7 +28,7 @@ def upgrade(migrate_engine): log.exception("Adding provider column to galaxy_user_openid table failed.") try: - cmd = "DELETE FROM galaxy_user_openid WHERE openid='%s'" % (BAD_IDENTIFIER) + cmd = f"DELETE FROM galaxy_user_openid WHERE openid='{BAD_IDENTIFIER}'" migrate_engine.execute(cmd) except Exception: log.exception("Deleting bad Identifiers from galaxy_user_openid failed.") diff --git a/lib/galaxy/model/migrate/versions/0116_drop_update_available_col_add_tool_shed_status_col.py b/lib/galaxy/model/migrate/versions/0116_drop_update_available_col_add_tool_shed_status_col.py index f00dcbdd596..aae01d769ed 100644 --- a/lib/galaxy/model/migrate/versions/0116_drop_update_available_col_add_tool_shed_status_col.py +++ b/lib/galaxy/model/migrate/versions/0116_drop_update_available_col_add_tool_shed_status_col.py @@ -44,6 +44,6 @@ def downgrade(migrate_engine): c = Column("update_available", Boolean, default=False) add_column(c, ToolShedRepository_table, metadata) try: - migrate_engine.execute("UPDATE tool_shed_repository SET update_available=%s" % engine_false(migrate_engine)) + migrate_engine.execute(f"UPDATE tool_shed_repository SET update_available={engine_false(migrate_engine)}") except Exception: log.exception("Updating column 'update_available' of table 'tool_shed_repository' failed.") diff --git a/lib/galaxy/model/migrate/versions/0160_hda_set_deleted_if_purged_again.py b/lib/galaxy/model/migrate/versions/0160_hda_set_deleted_if_purged_again.py index 796f2a23178..45dc48954e8 100644 --- a/lib/galaxy/model/migrate/versions/0160_hda_set_deleted_if_purged_again.py +++ b/lib/galaxy/model/migrate/versions/0160_hda_set_deleted_if_purged_again.py @@ -12,7 +12,7 @@ log = logging.getLogger(__name__) def upgrade(migrate_engine): print(__doc__) - cmd = 'UPDATE history_dataset_association SET deleted=%s WHERE purged AND NOT deleted;' % engine_true(migrate_engine) + cmd = f'UPDATE history_dataset_association SET deleted={engine_true(migrate_engine)} WHERE purged AND NOT deleted;' try: migrate_engine.execute(cmd) except Exception: diff --git a/lib/galaxy/model/migrate/versions/util.py b/lib/galaxy/model/migrate/versions/util.py index a9265f9a5e1..80c7dd3be71 100644 --- a/lib/galaxy/model/migrate/versions/util.py +++ b/lib/galaxy/model/migrate/versions/util.py @@ -18,7 +18,7 @@ def engine_false(migrate_engine): elif migrate_engine.name in ['mysql', 'sqlite']: return 0 else: - raise Exception('Unknown database type: %s' % migrate_engine.name) + raise Exception(f'Unknown database type: {migrate_engine.name}') def engine_true(migrate_engine): @@ -27,7 +27,7 @@ def engine_true(migrate_engine): elif migrate_engine.name in ['mysql', 'sqlite']: return 1 else: - raise Exception('Unknown database type: %s' % migrate_engine.name) + raise Exception(f'Unknown database type: {migrate_engine.name}') def nextval(migrate_engine, table, col='id'): @@ -36,7 +36,7 @@ def nextval(migrate_engine, table, col='id'): elif migrate_engine.name in ['mysql', 'sqlite']: return "null" else: - raise Exception('Unable to convert data for unknown database type: %s' % migrate_engine.name) + raise Exception(f'Unable to convert data for unknown database type: {migrate_engine.name}') def localtimestamp(migrate_engine): @@ -45,7 +45,7 @@ def localtimestamp(migrate_engine): elif migrate_engine.name == 'sqlite': return "current_date || ' ' || current_time" else: - raise Exception('Unable to convert data for unknown database type: %s' % migrate_engine.name) + raise Exception(f'Unable to convert data for unknown database type: {migrate_engine.name}') def truncate_index_name(index_name, engine): @@ -53,7 +53,7 @@ def truncate_index_name(index_name, engine): max_index_name_length = engine.dialect.max_index_name_length or engine.dialect.max_identifier_length if len(index_name) > max_index_name_length: suffix = hashlib.md5(index_name.encode('utf-8')).hexdigest()[-4:] - index_name = "{trunc}_{suffix}".format(trunc=index_name[0:max_index_name_length - 8], suffix=suffix) + index_name = f"{index_name[0:max_index_name_length - 8]}_{suffix}" return index_name diff --git a/lib/galaxy/model/orm/engine_factory.py b/lib/galaxy/model/orm/engine_factory.py index 5748525b421..8bea073d4b4 100644 --- a/lib/galaxy/model/orm/engine_factory.py +++ b/lib/galaxy/model/orm/engine_factory.py @@ -25,7 +25,7 @@ def log_request_query_counts(req_id): try: times = QUERY_COUNT_LOCAL.times if times: - log.info("Executed [{}] SQL requests in for web request [{}] ({:0.3f} ms)".format(len(times), req_id, sum(times) * 1000.)) + log.info(f"Executed [{len(times)}] SQL requests in for web request [{req_id}] ({sum(times) * 1000.0:0.3f} ms)") except AttributeError: # Didn't record anything so don't worry. pass diff --git a/lib/galaxy/model/orm/scripts.py b/lib/galaxy/model/orm/scripts.py index 95f38a2615e..2b0da1a5986 100644 --- a/lib/galaxy/model/orm/scripts.py +++ b/lib/galaxy/model/orm/scripts.py @@ -132,8 +132,8 @@ def get_config(argv, use_argparse=True, cwd=None): config_section = None properties = load_app_properties(config_file=config_file, config_prefix=config_override, config_section=config_section) - if ("%sdatabase_connection" % config_prefix) in properties: - db_url = properties["%sdatabase_connection" % config_prefix] + if (f"{config_prefix}database_connection") in properties: + db_url = properties[f"{config_prefix}database_connection"] else: db_url = "sqlite:///%s?isolation_level=IMMEDIATE" % os.path.join(get_data_dir(properties), default_sqlite_file) install_database_connection = properties.get('install_database_connection') diff --git a/lib/galaxy/model/search.py b/lib/galaxy/model/search.py index 5e305d65f89..9237e04f7bc 100644 --- a/lib/galaxy/model/search.py +++ b/lib/galaxy/model/search.py @@ -129,19 +129,19 @@ class ViewQueryBaseClass: elif operator == "like": self.query = self.query.filter(sqlalchemy_field_value.like(right)) else: - raise GalaxyParseError("Invalid comparison operator: %s" % (operator)) + raise GalaxyParseError(f"Invalid comparison operator: {operator}") elif field.handler is not None: field.handler(self, left, operator, right) elif field.post_filter is not None: self.post_filter.append([field.post_filter, left, operator, right]) else: - raise GalaxyParseError("Unable to filter on field: %s" % (left)) + raise GalaxyParseError(f"Unable to filter on field: {left}") else: - raise GalaxyParseError("Unknown field: %s" % (left)) + raise GalaxyParseError(f"Unknown field: {left}") def search(self, trans): - raise GalaxyParseError("Unable to search view: %s" % (self.VIEW_NAME)) + raise GalaxyParseError(f"Unable to search view: {self.VIEW_NAME}") def get_results(self, force_query=False): if self.query is not None and (force_query or self.do_query): @@ -165,7 +165,7 @@ def library_extended_metadata_filter(view, left, operator, right): view.query = view.query.join(ExtendedMetadata) view.state['extended_metadata_joined'] = True alias = aliased(ExtendedMetadataIndex) - field = "/%s" % ("/".join(left.split(".")[1:])) + field = f"/{'/'.join(left.split('.')[1:])}" view.query = view.query.filter( and_( ExtendedMetadata.id == alias.extended_metadata_id, @@ -180,7 +180,7 @@ def ldda_parent_library_filter(item, left, operator, right): return right == item.library_dataset.folder.parent_library.id elif operator == '!=': return right != item.library_dataset.folder.parent_library.id - raise GalaxyParseError("Invalid comparison operator: %s" % (operator)) + raise GalaxyParseError(f"Invalid comparison operator: {operator}") class LibraryDatasetDatasetView(ViewQueryBaseClass): @@ -222,7 +222,7 @@ def library_folder_parent_library_id_filter(item, left, operator, right): return item.parent_library.id == right if operator == '!=': return item.parent_library.id != right - raise GalaxyParseError("Invalid comparison operator: %s" % (operator)) + raise GalaxyParseError(f"Invalid comparison operator: {operator}") def library_path_filter(item, left, operator, right): @@ -231,7 +231,7 @@ def library_path_filter(item, left, operator, right): return lpath == right if operator == '!=': return lpath != right - raise GalaxyParseError("Invalid comparison operator: %s" % (operator)) + raise GalaxyParseError(f"Invalid comparison operator: {operator}") class LibraryFolderView(ViewQueryBaseClass): @@ -256,7 +256,7 @@ def library_dataset_name_filter(item, left, operator, right): return item.name == right if operator == '!=': return item.name != right - raise GalaxyParseError("Invalid comparison operator: %s" % (operator)) + raise GalaxyParseError(f"Invalid comparison operator: {operator}") class LibraryDatasetView(ViewQueryBaseClass): @@ -302,7 +302,7 @@ def history_dataset_handle_tag(view, left, operator, right): if len(tmp) > 1: view.query = view.query.filter(tag_table.user_value == tmp[1]) else: - raise GalaxyParseError("Invalid comparison operator: %s" % (operator)) + raise GalaxyParseError(f"Invalid comparison operator: {operator}") def history_dataset_extended_metadata_filter(view, left, operator, right): @@ -311,7 +311,7 @@ def history_dataset_extended_metadata_filter(view, left, operator, right): view.query = view.query.join(ExtendedMetadata) view.state['extended_metadata_joined'] = True alias = aliased(ExtendedMetadataIndex) - field = "/%s" % ("/".join(left.split(".")[1:])) + field = f"/{'/'.join(left.split('.')[1:])}" view.query = view.query.filter( and_( ExtendedMetadata.id == alias.extended_metadata_id, @@ -359,7 +359,7 @@ def history_handle_tag(view, left, operator, right): if len(tmp) > 1: view.query = view.query.filter(tag_table.user_value == tmp[1]) else: - raise GalaxyParseError("Invalid comparison operator: %s" % (operator)) + raise GalaxyParseError(f"Invalid comparison operator: {operator}") def history_handle_annotation(view, left, operator, right): @@ -376,7 +376,7 @@ def history_handle_annotation(view, left, operator, right): HistoryAnnotationAssociation.annotation.like(right) )) else: - raise GalaxyParseError("Invalid comparison operator: %s" % (operator)) + raise GalaxyParseError(f"Invalid comparison operator: {operator}") class HistoryView(ViewQueryBaseClass): @@ -409,7 +409,7 @@ def workflow_tag_handler(view, left, operator, right): if len(tmp) > 1: view.query = view.query.filter(StoredWorkflowTagAssociation.user_value == tmp[1]) else: - raise GalaxyParseError("Invalid comparison operator: %s" % (operator)) + raise GalaxyParseError(f"Invalid comparison operator: {operator}") class WorkflowView(ViewQueryBaseClass): @@ -686,4 +686,4 @@ class GalaxySearchEngine: if q.table_name in view_mapping: view = view_mapping[q.table_name]() return SearchQuery(view, q) - raise GalaxyParseError("No such table %s" % (q.table_name)) + raise GalaxyParseError(f"No such table {q.table_name}") diff --git a/lib/galaxy/model/security.py b/lib/galaxy/model/security.py index ebfbddf0741..71222babfa4 100644 --- a/lib/galaxy/model/security.py +++ b/lib/galaxy/model/security.py @@ -360,7 +360,7 @@ class GalaxyRBACAgent(RBACAgent): len(new_result))) log.debug("get_actions_for_items: Test end") except Exception as e: - log.debug("Exception in test code: %s" % e) + log.debug(f"Exception in test code: {e}") return ret_permissions @@ -554,7 +554,7 @@ class GalaxyRBACAgent(RBACAgent): elif type(item) == self.model.LibraryDatasetCollectionAssociation: return self.can_access_library(roles, item.folder.parent_library) else: - log.warning('Unknown library item type: %s' % type(item)) + log.warning(f'Unknown library item type: {type(item)}') return False def can_add_library_item(self, roles, item): @@ -632,7 +632,7 @@ class GalaxyRBACAgent(RBACAgent): if 'action' in kwd: if 'dataset' in kwd and 'role' in kwd: return self.associate_action_dataset_role(kwd['action'], kwd['dataset'], kwd['role']) - raise Exception('No valid method of associating provided components: %s' % kwd) + raise Exception(f'No valid method of associating provided components: {kwd}') def associate_user_group(self, user, group): assoc = self.model.UserGroupAssociation(user, group) @@ -1144,7 +1144,7 @@ class GalaxyRBACAgent(RBACAgent): msg += "The following roles are not associated with users that have the 'access' permission on this " msg += "item, so they were incorrectly displayed: " for role in illegitimate_roles: - msg += "%s, " % role.name + msg += f"{role.name}, " msg = msg.rstrip(", ") new_in_roles = [] for role in in_roles: @@ -1369,7 +1369,7 @@ class GalaxyRBACAgent(RBACAgent): elif 'group' in kwd: if 'role' in kwd: return self.sa_session.query(self.model.GroupRoleAssociation).filter_by(role_id=kwd['role'].id, group_id=kwd['group'].id).first() - raise Exception('No valid method of associating provided components: %s' % kwd) + raise Exception(f'No valid method of associating provided components: {kwd}') def check_folder_contents(self, user, roles, folder, hidden_folder_ids=''): """ diff --git a/lib/galaxy/model/store/__init__.py b/lib/galaxy/model/store/__init__.py index 9393e51efc2..21e9b5fb6f4 100644 --- a/lib/galaxy/model/store/__init__.py +++ b/lib/galaxy/model/store/__init__.py @@ -130,7 +130,7 @@ class ModelImportStore(metaclass=abc.ABCMeta): history_properties = self.new_history_properties() history_name = history_properties.get('name') if history_name: - history_name = 'imported from archive: %s' % history_name + history_name = f'imported from archive: {history_name}' else: history_name = 'unnamed imported history' @@ -312,13 +312,13 @@ class ModelImportStore(metaclass=abc.ABCMeta): # Do security check and move/copy dataset data. archive_path = os.path.abspath(os.path.join(self.archive_dir, file_name)) if os.path.islink(archive_path): - raise MalformedContents("Invalid dataset path: %s" % archive_path) + raise MalformedContents(f"Invalid dataset path: {archive_path}") temp_dataset_file_name = \ os.path.realpath(archive_path) if not in_directory(temp_dataset_file_name, self.archive_dir): - raise MalformedContents("Invalid dataset path: %s" % temp_dataset_file_name) + raise MalformedContents(f"Invalid dataset path: {temp_dataset_file_name}") if not file_name or not os.path.exists(temp_dataset_file_name): dataset_instance.state = dataset_instance.states.DISCARDED @@ -341,7 +341,7 @@ class ModelImportStore(metaclass=abc.ABCMeta): for extra_file in files: source = os.path.join(root, extra_file) if not in_directory(source, self.archive_dir): - raise MalformedContents("Invalid dataset path: %s" % source) + raise MalformedContents(f"Invalid dataset path: {source}") self.object_store.update_from_file( dataset_instance.dataset, extra_dir=extra_dir, alt_name=extra_file, file_name=source, @@ -1118,7 +1118,7 @@ class DirectoryModelExportStore(ModelExportStore): file_list = [] if len(file_list): - arcname = os.path.join(dir_name, 'extra_files_path_%s' % dataset_hid) + arcname = os.path.join(dir_name, f'extra_files_path_{dataset_hid}') add(extra_files_path, os.path.join(export_directory, arcname)) as_dict['extra_files_path'] = arcname else: diff --git a/lib/galaxy/model/store/discover.py b/lib/galaxy/model/store/discover.py index 9a90c3d5057..601c69c7e56 100644 --- a/lib/galaxy/model/store/discover.py +++ b/lib/galaxy/model/store/discover.py @@ -237,7 +237,7 @@ class ModelPersistenceContext(metaclass=abc.ABCMeta): create_dataset_timer = ExecutionTimer() fields_match = discovered_file.match if not fields_match: - raise Exception("Problem parsing metadata fields for file %s" % filename) + raise Exception(f"Problem parsing metadata fields for file {filename}") element_identifiers = fields_match.element_identifiers designation = fields_match.designation visible = fields_match.visible diff --git a/lib/galaxy/model/tags.py b/lib/galaxy/model/tags.py index d2ec1475219..039357880ac 100644 --- a/lib/galaxy/model/tags.py +++ b/lib/galaxy/model/tags.py @@ -166,7 +166,7 @@ class TagHandler: # Create tag; if None, skip the tag (and log error). tag = self._get_or_create_tag(lc_name) if not tag: - log.warning("Failed to create tag with name %s" % lc_name) + log.warning(f"Failed to create tag with name {lc_name}") return # Create tag association based on item class. item_tag_assoc_class = self.get_tag_assoc_class(item.__class__) @@ -343,7 +343,7 @@ class TagHandler: """Get name, value pair from a tag string.""" # Use regular expression to parse name, value. if tag_str.startswith('#'): - tag_str = "name:%s" % tag_str[1:] + tag_str = f"name:{tag_str[1:]}" reg_exp = re.compile("[" + self.key_value_separators + "]") name_value_pair = reg_exp.split(tag_str, 1) # Add empty slot if tag does not have value. diff --git a/lib/galaxy/model/tool_shed_install/__init__.py b/lib/galaxy/model/tool_shed_install/__init__.py index 380e2a2bb1a..6b30da79ef7 100644 --- a/lib/galaxy/model/tool_shed_install/__init__.py +++ b/lib/galaxy/model/tool_shed_install/__init__.py @@ -385,7 +385,7 @@ class ToolShedRepository(_HasTable): try: visible_keys = self.__getattribute__('dict_' + view + '_visible_keys') except AttributeError: - raise Exception('Unknown API view: %s' % view) + raise Exception(f'Unknown API view: {view}') for key in visible_keys: try: rval[key] = self.__getattribute__(key) diff --git a/lib/galaxy/model/tool_shed_install/migrate/check.py b/lib/galaxy/model/tool_shed_install/migrate/check.py index 0e1a66248fc..bada20288ff 100644 --- a/lib/galaxy/model/tool_shed_install/migrate/check.py +++ b/lib/galaxy/model/tool_shed_install/migrate/check.py @@ -30,7 +30,7 @@ def create_or_verify_database(url, engine_options=None, app=None): # Create engine and metadata engine_options = engine_options or {} if not database_exists(url): - message = "Creating database for URI [%s]" % url + message = f"Creating database for URI [{url}]" log.info(message) create_database(url) diff --git a/lib/galaxy/objectstore/__init__.py b/lib/galaxy/objectstore/__init__.py index 3a16e3329a5..9298aecd3fd 100644 --- a/lib/galaxy/objectstore/__init__.py +++ b/lib/galaxy/objectstore/__init__.py @@ -516,8 +516,8 @@ class DiskObjectStore(ConcreteObjectStore): rel_path = os.path.join(rel_path, extra_dir) path = os.path.join(base, rel_path) if not dir_only: - assert obj_id is not None, "The effective dataset identifier consumed by object store [%s] must be set before a path can be constructed." % (self.store_by) - path = os.path.join(path, alt_name if alt_name else "dataset_%s.dat" % obj_id) + assert obj_id is not None, f"The effective dataset identifier consumed by object store [{self.store_by}] must be set before a path can be constructed." + path = os.path.join(path, alt_name if alt_name else f"dataset_{obj_id}.dat") return os.path.abspath(path) def _exists(self, obj, **kwargs): @@ -580,7 +580,7 @@ class DiskObjectStore(ConcreteObjectStore): os.remove(path) return True except OSError as ex: - log.critical('{} delete error {}'.format(self.__get_filename(obj, **kwargs), ex)) + log.critical(f'{self.__get_filename(obj, **kwargs)} delete error {ex}') return False def _get_data(self, obj, start=0, count=-1, **kwargs): @@ -626,7 +626,7 @@ class DiskObjectStore(ConcreteObjectStore): shutil.copy(file_name, path) umask_fix_perms(path, self.config.umask, 0o666) except OSError as ex: - log.critical('Error copying {} to {}: {}'.format(file_name, self.__get_filename(obj, **kwargs), ex)) + log.critical(f'Error copying {file_name} to {self.__get_filename(obj, **kwargs)}: {ex}') raise ex def _get_object_url(self, obj, **kwargs): @@ -1088,18 +1088,18 @@ def convert_bytes(bytes): if bytes >= 1099511627776: terabytes = bytes / 1099511627776 - size = '%.2fTB' % terabytes + size = f'{terabytes:.2f}TB' elif bytes >= 1073741824: gigabytes = bytes / 1073741824 - size = '%.2fGB' % gigabytes + size = f'{gigabytes:.2f}GB' elif bytes >= 1048576: megabytes = bytes / 1048576 - size = '%.2fMB' % megabytes + size = f'{megabytes:.2f}MB' elif bytes >= 1024: kilobytes = bytes / 1024 - size = '%.2fKB' % kilobytes + size = f'{kilobytes:.2f}KB' else: - size = '%.2fb' % bytes + size = f'{bytes:.2f}b' return size diff --git a/lib/galaxy/objectstore/azure_blob.py b/lib/galaxy/objectstore/azure_blob.py index e77dedaa679..24a8754a666 100644 --- a/lib/galaxy/objectstore/azure_blob.py +++ b/lib/galaxy/objectstore/azure_blob.py @@ -192,7 +192,7 @@ class AzureBlobObjectStore(ConcreteObjectStore): # rel_path = '%s/' % rel_path # assume for now we don't need this in Azure blob storage. if not dir_only: - rel_path = os.path.join(rel_path, alt_name if alt_name else "dataset_%s.dat" % self._get_object_id(obj)) + rel_path = os.path.join(rel_path, alt_name if alt_name else f"dataset_{self._get_object_id(obj)}.dat") return rel_path @@ -389,7 +389,7 @@ class AzureBlobObjectStore(ConcreteObjectStore): # self._push_to_os(s3_dir, from_string='') # If instructed, create the dataset in cache & in S3 if not dir_only: - rel_path = os.path.join(rel_path, alt_name if alt_name else "dataset_%s.dat" % self._get_object_id(obj)) + rel_path = os.path.join(rel_path, alt_name if alt_name else f"dataset_{self._get_object_id(obj)}.dat") open(os.path.join(self.staging_path, rel_path), 'w').close() self._push_to_os(rel_path, from_string='') @@ -397,7 +397,7 @@ class AzureBlobObjectStore(ConcreteObjectStore): if self._exists(obj, **kwargs): return bool(self._size(obj, **kwargs) > 0) else: - raise ObjectNotFound('objectstore.empty, object does not exist: {}, kwargs: {}'.format(str(obj), str(kwargs))) + raise ObjectNotFound(f'objectstore.empty, object does not exist: {str(obj)}, kwargs: {str(kwargs)}') def _size(self, obj, **kwargs): rel_path = self._construct_path(obj, **kwargs) @@ -493,7 +493,7 @@ class AzureBlobObjectStore(ConcreteObjectStore): # even if it does not exist. # if dir_only: # return cache_path - raise ObjectNotFound('objectstore.get_filename, no cache_path: {}, kwargs: {}'.format(str(obj), str(kwargs))) + raise ObjectNotFound(f'objectstore.get_filename, no cache_path: {str(obj)}, kwargs: {str(kwargs)}') def _update_from_file(self, obj, file_name=None, create=False, **kwargs): if create is True: @@ -518,7 +518,7 @@ class AzureBlobObjectStore(ConcreteObjectStore): self._push_to_os(rel_path, source_file) else: - raise ObjectNotFound('objectstore.update_from_file, object does not exist: {}, kwargs: {}'.format(str(obj), str(kwargs))) + raise ObjectNotFound(f'objectstore.update_from_file, object does not exist: {str(obj)}, kwargs: {str(kwargs)}') def _get_object_url(self, obj, **kwargs): if self._exists(obj, **kwargs): diff --git a/lib/galaxy/objectstore/cloud.py b/lib/galaxy/objectstore/cloud.py index 3cd34fbbef7..f7ee33baf89 100644 --- a/lib/galaxy/objectstore/cloud.py +++ b/lib/galaxy/objectstore/cloud.py @@ -366,10 +366,10 @@ class Cloud(ConcreteObjectStore, CloudConfigMixin): return os.path.join(base, rel_path) # S3 folders are marked by having trailing '/' so add it now - rel_path = '%s/' % rel_path + rel_path = f'{rel_path}/' if not dir_only: - rel_path = os.path.join(rel_path, alt_name if alt_name else "dataset_%s.dat" % self._get_object_id(obj)) + rel_path = os.path.join(rel_path, alt_name if alt_name else f"dataset_{self._get_object_id(obj)}.dat") return rel_path def _get_cache_path(self, rel_path): @@ -568,7 +568,7 @@ class Cloud(ConcreteObjectStore, CloudConfigMixin): os.makedirs(cache_dir) if not dir_only: - rel_path = os.path.join(rel_path, alt_name if alt_name else "dataset_%s.dat" % self._get_object_id(obj)) + rel_path = os.path.join(rel_path, alt_name if alt_name else f"dataset_{self._get_object_id(obj)}.dat") open(os.path.join(self.staging_path, rel_path), 'w').close() self._push_to_os(rel_path, from_string='') diff --git a/lib/galaxy/objectstore/irods.py b/lib/galaxy/objectstore/irods.py index c7872f5d181..e2cac81171b 100644 --- a/lib/galaxy/objectstore/irods.py +++ b/lib/galaxy/objectstore/irods.py @@ -282,7 +282,7 @@ class IRODSObjectStore(DiskObjectStore, CloudConfigMixin): return os.path.join(base, rel_path) if not dir_only: - rel_path = os.path.join(rel_path, alt_name if alt_name else "dataset_%s.dat" % self._get_object_id(obj)) + rel_path = os.path.join(rel_path, alt_name if alt_name else f"dataset_{self._get_object_id(obj)}.dat") log.debug("irods_pt _construct_path: %s", ipt_timer) return rel_path @@ -515,7 +515,7 @@ class IRODSObjectStore(DiskObjectStore, CloudConfigMixin): os.makedirs(cache_dir) if not dir_only: - rel_path = os.path.join(rel_path, alt_name if alt_name else "dataset_%s.dat" % self._get_object_id(obj)) + rel_path = os.path.join(rel_path, alt_name if alt_name else f"dataset_{self._get_object_id(obj)}.dat") open(os.path.join(self.staging_path, rel_path), 'w').close() self._push_to_irods(rel_path, from_string='') log.debug("irods_pt _create: %s", ipt_timer) diff --git a/lib/galaxy/objectstore/pithos.py b/lib/galaxy/objectstore/pithos.py index 9cab7fffc02..501e21afd17 100644 --- a/lib/galaxy/objectstore/pithos.py +++ b/lib/galaxy/objectstore/pithos.py @@ -51,8 +51,7 @@ def parse_config_xml(config_xml): required = tuple((k, element.get(k)) for k in required_attrs) for k, v in required: if not v: - msg = 'No value for {tag}:{k} in XML tree'.format( - tag=tag, k=k) + msg = f'No value for {tag}:{k} in XML tree' log.error(msg) raise Exception(msg) optional = tuple((k, element.get(k)) for k in optional_attrs) @@ -157,8 +156,7 @@ class PithosObjectStore(ConcreteObjectStore): if alt_name: if not safe_relpath(alt_name): log.warning( - 'alt_name would locate path outside dir: {}'.format( - alt_name)) + f'alt_name would locate path outside dir: {alt_name}') raise ObjectInvalid("The requested object is invalid") # alt_name can contain parent directory references, but S3 will not # follow them, so if they are valid we normalize them out @@ -181,7 +179,7 @@ class PithosObjectStore(ConcreteObjectStore): rel_path = f'{rel_path}/' if not dir_only: - an = alt_name if alt_name else 'dataset_{}.dat'.format(self._get_object_id(obj)) + an = alt_name if alt_name else f'dataset_{self._get_object_id(obj)}.dat' rel_path = os.path.join(rel_path, an) return rel_path @@ -283,7 +281,7 @@ class PithosObjectStore(ConcreteObjectStore): else: rel_path = os.path.join( rel_path, - alt_name if alt_name else 'dataset_{}.dat'.format(self._get_object_id(obj))) + alt_name if alt_name else f'dataset_{self._get_object_id(obj)}.dat') new_file = os.path.join(self.staging_path, rel_path) open(new_file, 'w').close() self.pithos.upload_from_string(rel_path, '') @@ -295,8 +293,7 @@ class PithosObjectStore(ConcreteObjectStore): """ if not self._exists(obj, **kwargs): raise ObjectNotFound( - 'objectstore.empty, object does not exist: {obj}, ' - 'kwargs: {kwargs}'.format(obj=obj, kwargs=kwargs)) + f'objectstore.empty, object does not exist: {obj}, kwargs: {kwargs}') return bool(self._size(obj, **kwargs)) def _size(self, obj, **kwargs): @@ -347,10 +344,9 @@ class PithosObjectStore(ConcreteObjectStore): self.pithos.del_object(path) except OSError: log.exception( - '{} delete error'.format(self._get_filename(obj, **kwargs))) + f'{self._get_filename(obj, **kwargs)} delete error') except ClientError as ce: - log.exception('Could not delete {path} from Pithos, {err}'.format( - path=path, err=ce)) + log.exception(f'Could not delete {path} from Pithos, {ce}') return False def _get_data(self, obj, start=0, count=-1, **kwargs): @@ -391,8 +387,7 @@ class PithosObjectStore(ConcreteObjectStore): self._pull_into_cache(path) return cache_path raise ObjectNotFound( - 'objectstore.get_filename, no cache_path: {obj}, ' - 'kwargs: {kwargs}'.format(obj=obj, kwargs=kwargs)) + f'objectstore.get_filename, no cache_path: {obj}, kwargs: {kwargs}') def _update_from_file(self, obj, **kwargs): """Update the store when a file is updated""" diff --git a/lib/galaxy/objectstore/s3.py b/lib/galaxy/objectstore/s3.py index 479cb31ba2d..4b739af6430 100644 --- a/lib/galaxy/objectstore/s3.py +++ b/lib/galaxy/objectstore/s3.py @@ -346,10 +346,10 @@ class S3ObjectStore(ConcreteObjectStore, CloudConfigMixin): return os.path.join(base, rel_path) # S3 folders are marked by having trailing '/' so add it now - rel_path = '%s/' % rel_path + rel_path = f'{rel_path}/' if not dir_only: - rel_path = os.path.join(rel_path, alt_name if alt_name else "dataset_%s.dat" % self._get_object_id(obj)) + rel_path = os.path.join(rel_path, alt_name if alt_name else f"dataset_{self._get_object_id(obj)}.dat") return rel_path def _get_cache_path(self, rel_path): @@ -572,7 +572,7 @@ class S3ObjectStore(ConcreteObjectStore, CloudConfigMixin): # self._push_to_os(s3_dir, from_string='') # If instructed, create the dataset in cache & in S3 if not dir_only: - rel_path = os.path.join(rel_path, alt_name if alt_name else "dataset_%s.dat" % self._get_object_id(obj)) + rel_path = os.path.join(rel_path, alt_name if alt_name else f"dataset_{self._get_object_id(obj)}.dat") open(os.path.join(self.staging_path, rel_path), 'w').close() self._push_to_os(rel_path, from_string='') diff --git a/lib/galaxy/objectstore/s3_multipart_upload.py b/lib/galaxy/objectstore/s3_multipart_upload.py index 88440560028..cf107692183 100644 --- a/lib/galaxy/objectstore/s3_multipart_upload.py +++ b/lib/galaxy/objectstore/s3_multipart_upload.py @@ -58,14 +58,14 @@ def multipart_upload(s3server, bucket, s3_key_name, tarball, mb_size): """ def split_file(in_file, mb_size, split_num=5): prefix = os.path.join(os.path.dirname(in_file), - "%sS3PART" % (os.path.basename(s3_key_name))) + f"{os.path.basename(s3_key_name)}S3PART") max_chunk = s3server['max_chunk_size'] # Split chunks so they are 5MB < chunk < 250MB(max_chunk_size) split_size = int(max(min(mb_size / (split_num * 2.0), max_chunk), 5)) - if not os.path.exists("%saa" % prefix): - cl = ["split", "-b%sm" % split_size, in_file, prefix] + if not os.path.exists(f"{prefix}aa"): + cl = ["split", f"-b{split_size}m", in_file, prefix] subprocess.check_call(cl) - return sorted(glob.glob("%s*" % prefix)) + return sorted(glob.glob(f"{prefix}*")) mp = bucket.initiate_multipart_upload(s3_key_name, reduced_redundancy=s3server['use_rr']) diff --git a/lib/galaxy/openid/providers.py b/lib/galaxy/openid/providers.py index b3f695ba6b6..151d08e59d9 100644 --- a/lib/galaxy/openid/providers.py +++ b/lib/galaxy/openid/providers.py @@ -30,7 +30,7 @@ class OpenIDProvider: op_endpoint_url = op_endpoint_url.text never_associate_with_user = string_as_bool(provider_elem.get('never_associate_with_user', 'False')) assert (provider_id and provider_name and op_endpoint_url), Exception("OpenID Provider improperly configured") - assert provider_id not in RESERVED_PROVIDER_IDS, Exception('Specified OpenID Provider uses a reserved id: %s' % (provider_id)) + assert provider_id not in RESERVED_PROVIDER_IDS, Exception(f'Specified OpenID Provider uses a reserved id: {provider_id}') sreg_required = [] sreg_optional = [] use_for = {} @@ -108,7 +108,7 @@ class OpenIDProviders: try: return cls.from_elem(parse_xml(filename).getroot()) except Exception as e: - log.error('Failed to load OpenID Providers: %s' % (e)) + log.error(f'Failed to load OpenID Providers: {e}') return cls() @classmethod @@ -121,7 +121,7 @@ class OpenIDProviders: providers[provider.id] = provider log.debug(f'Loaded OpenID provider: {provider.name} ({provider.id})') except Exception as e: - log.error('Failed to add OpenID provider: %s' % (e)) + log.error(f'Failed to add OpenID provider: {e}') return cls(providers) def __init__(self, providers=None): diff --git a/lib/galaxy/queue_worker.py b/lib/galaxy/queue_worker.py index 24fcba5e83e..73d15c5db38 100644 --- a/lib/galaxy/queue_worker.py +++ b/lib/galaxy/queue_worker.py @@ -41,7 +41,7 @@ def send_local_control_task(app, task, get_response=False, kwargs=None): """ if kwargs is None: kwargs = {} - log.info("Queuing {} task {} for {}.".format("sync" if get_response else "async", task, app.config.server_name)) + log.info(f"Queuing {'sync' if get_response else 'async'} task {task} for {app.config.server_name}.") payload = {'task': task, 'kwargs': kwargs} routing_key = f'control.{app.config.server_name}@{socket.gethostname()}' @@ -60,7 +60,7 @@ def send_control_task(app, task, noop_self=False, get_response=False, routing_ke """ if kwargs is None: kwargs = {} - log.info("Sending %s control task." % task) + log.info(f"Sending {task} control task.") payload = {'task': task, 'kwargs': kwargs} if noop_self: @@ -155,7 +155,7 @@ def create_panel_section(app, **kwargs): def reload_tool(app, **kwargs): params = util.Params(kwargs) tool_id = params.get('tool_id', None) - log.debug("Executing reload tool task for %s" % tool_id) + log.debug(f"Executing reload tool task for {tool_id}") if tool_id: app.toolbox.reload_tool_by_id(tool_id) else: @@ -215,7 +215,7 @@ def reload_data_managers(app, **kwargs): def reload_display_application(app, **kwargs): display_application_ids = kwargs.get('display_application_ids', None) - log.debug("Executing display application reload task for %s" % display_application_ids) + log.debug(f"Executing display application reload task for {display_application_ids}") app.datatypes_registry.reload_display_applications(display_application_ids) @@ -232,7 +232,7 @@ def recalculate_user_disk_usage(app, **kwargs): if user: user.calculate_and_set_disk_usage() else: - log.error("Recalculate user disk usage task failed, user %s not found" % user_id) + log.error(f"Recalculate user disk usage task failed, user {user_id} not found") else: log.error("Recalculate user disk usage task received without user_id.") @@ -396,7 +396,7 @@ class GalaxyQueueWorker(ConsumerProducerMixin, threading.Thread): else: result = 'NO_OP' else: - log.warning("Received a malformed task message:\n%s" % body) + log.warning(f"Received a malformed task message:\n{body}") if message.properties.get('reply_to'): self.producer.publish( {'result': result}, diff --git a/lib/galaxy/queues.py b/lib/galaxy/queues.py index b9191d2f993..ec654605981 100644 --- a/lib/galaxy/queues.py +++ b/lib/galaxy/queues.py @@ -23,7 +23,7 @@ def all_control_queues_for_declare(application_stack): """ # Get all active processes and construct queues for each process process_names = ("{p.server_name}@{p.hostname}".format(p=p) for p in application_stack.app.database_heartbeat.get_active_processes()) - return [Queue("control.%s" % server_name, galaxy_exchange, routing_key='control.*') for server_name in process_names] + return [Queue(f"control.{server_name}", galaxy_exchange, routing_key='control.*') for server_name in process_names] def control_queues_from_config(config): @@ -33,8 +33,8 @@ def control_queues_from_config(config): """ hostname = socket.gethostname() process_name = f"{config.server_name}@{hostname}" - exchange_queue = Queue("control.%s" % process_name, galaxy_exchange, routing_key='control.*') - non_exchange_queue = Queue("control.%s" % process_name, routing_key='control.%s' % process_name) + exchange_queue = Queue(f"control.{process_name}", galaxy_exchange, routing_key='control.*') + non_exchange_queue = Queue(f"control.{process_name}", routing_key=f'control.{process_name}') return exchange_queue, non_exchange_queue diff --git a/lib/galaxy/security/__init__.py b/lib/galaxy/security/__init__.py index 8d1b160d0ba..b58d1e10aca 100644 --- a/lib/galaxy/security/__init__.py +++ b/lib/galaxy/security/__init__.py @@ -60,7 +60,7 @@ class RBACAgent: raise Exception("Unimplemented Method") def associate_components(self, **kwd): - raise Exception('No valid method of associating provided components: %s' % kwd) + raise Exception(f'No valid method of associating provided components: {kwd}') def create_private_user_role(self, user): raise Exception("Unimplemented Method") diff --git a/lib/galaxy/security/passwords.py b/lib/galaxy/security/passwords.py index c0112177441..ad673f01ab4 100644 --- a/lib/galaxy/security/passwords.py +++ b/lib/galaxy/security/passwords.py @@ -46,7 +46,7 @@ def hash_password_PBKDF2(password): hashed_password = pbkdf2_bin(password, salt, COST_FACTOR, KEY_LENGTH, HASH_FUNCTION) encoded_password = unicodify(b64encode(hashed_password)) # Format - return 'PBKDF2${}${}${}${}'.format(HASH_FUNCTION, COST_FACTOR, unicodify(salt), encoded_password) + return f'PBKDF2${HASH_FUNCTION}${COST_FACTOR}${unicodify(salt)}${encoded_password}' def check_password_PBKDF2(guess, hashed): diff --git a/lib/galaxy/security/validate_user_input.py b/lib/galaxy/security/validate_user_input.py index d33907afc20..4f20444b3e9 100644 --- a/lib/galaxy/security/validate_user_input.py +++ b/lib/galaxy/security/validate_user_input.py @@ -64,7 +64,7 @@ def validate_email(trans, email, user=None, check_dup=True, allow_empty=False): if message: pass elif check_dup and trans.sa_session.query(trans.app.model.User).filter(func.lower(trans.app.model.User.table.c.email) == email.lower()).first(): - message = "User with email '%s' already exists." % email + message = f"User with email '{email}' already exists." # If the allowlist is not empty filter out any domain not in the list and ignore blocklist. elif trans.app.config.email_domain_allowlist_content is not None: domain = extract_domain(email) diff --git a/lib/galaxy/selenium/components.py b/lib/galaxy/selenium/components.py index 3d197626c04..5a4476f3ad0 100644 --- a/lib/galaxy/selenium/components.py +++ b/lib/galaxy/selenium/components.py @@ -108,7 +108,7 @@ class Label(Target): @property def description(self): - return "Link text [%s]" % self.text + return f"Link text [{self.text}]" @property def element_locator(self): @@ -122,7 +122,7 @@ class Text(Target): @property def description(self): - return "Text containing [%s]" % self.text + return f"Text containing [{self.text}]" @property def element_locator(self): @@ -147,7 +147,7 @@ class Component: if "_" in self._selectors: return self._selectors["_"] else: - raise Exception("No _ selector for [%s]" % self) + raise Exception(f"No _ selector for [{self}]") @staticmethod def from_dict(name, raw_value): @@ -191,9 +191,9 @@ class Component: elif attr in self._text: return self._text[attr] else: - raise AttributeError("Failed to find referenced sub-component/selector/label/text [%s]" % attr) + raise AttributeError(f"Failed to find referenced sub-component/selector/label/text [{attr}]") __getitem__ = __getattr__ def __str__(self): - return "Component[%s]" % self._name + return f"Component[{self._name}]" diff --git a/lib/galaxy/selenium/has_driver.py b/lib/galaxy/selenium/has_driver.py index 447ff3fd83d..5466a542770 100644 --- a/lib/galaxy/selenium/has_driver.py +++ b/lib/galaxy/selenium/has_driver.py @@ -53,7 +53,7 @@ class HasDriver: def wait_for_xpath(self, xpath, **kwds): element = self._wait_on( ec.presence_of_element_located((By.XPATH, xpath)), - "XPATH selector [%s] to become present" % xpath, + f"XPATH selector [{xpath}] to become present", **kwds ) return element @@ -61,7 +61,7 @@ class HasDriver: def wait_for_xpath_visible(self, xpath, **kwds): element = self._wait_on( ec.visibility_of_element_located((By.XPATH, xpath)), - "XPATH selector [%s] to become visible" % xpath, + f"XPATH selector [{xpath}] to become visible", **kwds ) return element @@ -69,7 +69,7 @@ class HasDriver: def wait_for_selector(self, selector, **kwds): element = self._wait_on( ec.presence_of_element_located((By.CSS_SELECTOR, selector)), - "CSS selector [%s] to become present" % selector, + f"CSS selector [{selector}] to become present", **kwds ) return element @@ -77,7 +77,7 @@ class HasDriver: def wait_for_present(self, selector_template, **kwds): element = self._wait_on( ec.presence_of_element_located(selector_template.element_locator), - "%s to become present" % selector_template.description, + f"{selector_template.description} to become present", **kwds ) return element @@ -85,7 +85,7 @@ class HasDriver: def wait_for_visible(self, selector_template, **kwds): element = self._wait_on( ec.visibility_of_element_located(selector_template.element_locator), - "%s to become visible" % selector_template.description, + f"{selector_template.description} to become visible", **kwds ) return element @@ -93,7 +93,7 @@ class HasDriver: def wait_for_selector_visible(self, selector, **kwds): element = self._wait_on( ec.visibility_of_element_located((By.CSS_SELECTOR, selector)), - "CSS selector [%s] to become visible" % selector, + f"CSS selector [{selector}] to become visible", **kwds ) return element @@ -101,7 +101,7 @@ class HasDriver: def wait_for_selector_clickable(self, selector, **kwds): element = self._wait_on( ec.element_to_be_clickable((By.CSS_SELECTOR, selector)), - "CSS selector [%s] to become clickable" % selector, + f"CSS selector [{selector}] to become clickable", **kwds ) return element @@ -109,7 +109,7 @@ class HasDriver: def wait_for_clickable(self, selector_template, **kwds): element = self._wait_on( ec.element_to_be_clickable(selector_template.element_locator), - "%s to become clickable" % selector_template.description, + f"{selector_template.description} to become clickable", **kwds ) return element @@ -117,7 +117,7 @@ class HasDriver: def wait_for_selector_absent_or_hidden(self, selector, **kwds): element = self._wait_on( ec.invisibility_of_element_located((By.CSS_SELECTOR, selector)), - "CSS selector [%s] to become absent or hidden" % selector, + f"CSS selector [{selector}] to become absent or hidden", **kwds ) return element @@ -125,7 +125,7 @@ class HasDriver: def wait_for_selector_absent(self, selector, **kwds): element = self._wait_on( lambda driver: len(driver.find_elements_by_css_selector(selector)) == 0, - "CSS selector [%s] to become absent" % selector, + f"CSS selector [{selector}] to become absent", **kwds ) return element @@ -133,7 +133,7 @@ class HasDriver: def wait_for_absent(self, selector_template, **kwds): element = self._wait_on( lambda driver: len(driver.find_elements(*selector_template.element_locator)) == 0, - "%s to become absent" % selector_template.description, + f"{selector_template.description} to become absent", **kwds ) return element @@ -141,7 +141,7 @@ class HasDriver: def wait_for_absent_or_hidden(self, selector_template, **kwds): element = self._wait_on( ec.invisibility_of_element_located(selector_template.element_locator), - "%s to become absent or hidden" % selector_template.description, + f"{selector_template.description} to become absent or hidden", **kwds ) return element @@ -149,7 +149,7 @@ class HasDriver: def wait_for_id(self, id, **kwds): return self._wait_on( ec.presence_of_element_located((By.ID, id)), - "presence of DOM ID [%s]" % id, + f"presence of DOM ID [{id}]", **kwds ) @@ -158,7 +158,7 @@ class HasDriver: element.click() def _timeout_message(self, on_str): - return "Timeout waiting on %s." % on_str + return f"Timeout waiting on {on_str}." def _wait_on(self, condition, on_str=None, **kwds): if on_str is None: diff --git a/lib/galaxy/selenium/navigates_galaxy.py b/lib/galaxy/selenium/navigates_galaxy.py index 3868e2101f0..809e94a4473 100644 --- a/lib/galaxy/selenium/navigates_galaxy.py +++ b/lib/galaxy/selenium/navigates_galaxy.py @@ -172,7 +172,7 @@ class NavigatesGalaxy(HasDriver): try: yield finally: - self.driver.execute_script('''window.localStorage.removeItem("%s");''' % key) + self.driver.execute_script(f'''window.localStorage.removeItem("{key}");''') @contextlib.contextmanager def main_panel(self): @@ -254,7 +254,7 @@ class NavigatesGalaxy(HasDriver): def wait_for_history(self, assert_ok=True): def history_becomes_terminal(driver): current_history_id = self.current_history_id() - state = self.api_get("histories/%s" % current_history_id)["state"] + state = self.api_get(f"histories/{current_history_id}")["state"] if state not in ["running", "queued", "new", "ready"]: return state else: @@ -291,7 +291,7 @@ class NavigatesGalaxy(HasDriver): current_history_id = self.current_history_id() def history_has_hid(driver): - contents = self.api_get("histories/%s/contents" % current_history_id) + contents = self.api_get(f"histories/{current_history_id}/contents") return any([d for d in contents if d["hid"] == hid]) timeout = self.timeout_for(wait_type=WAIT_TYPES.JOB_COMPLETION) @@ -311,7 +311,7 @@ class NavigatesGalaxy(HasDriver): def hid_to_history_item(self, hid, current_history_id=None): if current_history_id is None: current_history_id = self.current_history_id() - contents = self.api_get("histories/%s/contents" % current_history_id) + contents = self.api_get(f"histories/{current_history_id}/contents") history_item = [d for d in contents if d["hid"] == hid][0] return history_item @@ -343,7 +343,7 @@ class NavigatesGalaxy(HasDriver): def history_panel_wait_for_hid_state(self, hid, state, allowed_force_refreshes=0): history_item_selector = self.history_panel_wait_for_hid_visible(hid, allowed_force_refreshes=allowed_force_refreshes) - history_item_selector_state = history_item_selector.with_class("state-%s" % state) + history_item_selector_state = history_item_selector.with_class(f"state-{state}") try: self.history_item_wait_for(history_item_selector_state, allowed_force_refreshes) except self.TimeoutException as e: @@ -368,7 +368,7 @@ class NavigatesGalaxy(HasDriver): break if item_button is None: - raise AssertionError('Failed to find item with name [%s]' % item_name) + raise AssertionError(f'Failed to find item with name [{item_name}]') popup_menu_button = item_button.find_element_by_css_selector('.dropdown-toggle') popup_menu_button.click() @@ -387,9 +387,9 @@ class NavigatesGalaxy(HasDriver): def get_api_key(self, force=False): # If force is false, use the form inputs API and allow the key to be absent. if not force: - return self.api_get("users/%s/api_key/inputs" % self.get_user_id())["inputs"][0]["value"] + return self.api_get(f"users/{self.get_user_id()}/api_key/inputs")["inputs"][0]["value"] else: - return self.api_post("users/%s/api_key" % self.get_user_id()) + return self.api_post(f"users/{self.get_user_id()}/api_key") def get_user_id(self): user = self.get_logged_in_user() @@ -491,7 +491,7 @@ class NavigatesGalaxy(HasDriver): except self.TimeoutException as e: menu_items = user_menu.find_elements_by_css_selector("li a") menu_text = [mi.text for mi in menu_items] - message = "Failed to find logged in message in menu items %s" % ", ".join(menu_text) + message = f"Failed to find logged in message in menu items {', '.join(menu_text)}" raise self.prepend_timeout_message(e, message) text = user_email_element.text @@ -610,14 +610,14 @@ class NavigatesGalaxy(HasDriver): @retry_during_transitions def upload_set_footer_extension(self, ext, tab_id="regular"): if ext is not None: - selector = 'div#%s .upload-footer-extension' % tab_id + selector = f'div#{tab_id} .upload-footer-extension' self.wait_for_selector_visible(selector) self.select2_set_value(selector, ext) @retry_during_transitions def upload_set_footer_genome(self, genome, tab_id="regular"): if genome is not None: - selector = 'div#%s .upload-footer-genome' % tab_id + selector = f'div#{tab_id} .upload-footer-genome' self.wait_for_selector_visible(selector) self.select2_set_value(selector, genome) @@ -627,11 +627,11 @@ class NavigatesGalaxy(HasDriver): self.select2_set_value(".upload-footer-collection-type", collection_type) def upload_start(self, tab_id="regular"): - self.wait_for_and_click_selector("div#%s button#btn-start" % tab_id) + self.wait_for_and_click_selector(f"div#{tab_id} button#btn-start") @retry_during_transitions def upload_build(self, tab="collection"): - build_selector = "div#%s button#btn-build" % tab + build_selector = f"div#{tab} button#btn-build" # Pause a bit to let the callback on the build button be registered. time.sleep(.5) # Click the Build button and make sure it disappears. @@ -646,9 +646,9 @@ class NavigatesGalaxy(HasDriver): self.wait_for_selector_absent_or_hidden(build_selector) def upload_queue_local_file(self, test_path, tab_id="regular"): - self.wait_for_and_click_selector("div#%s button#btn-local" % tab_id) + self.wait_for_and_click_selector(f"div#{tab_id} button#btn-local") - file_upload = self.wait_for_selector('div#%s input[type="file"]' % tab_id) + file_upload = self.wait_for_selector(f'div#{tab_id} input[type="file"]') file_upload.send_keys(test_path) def upload_paste_data(self, pasted_content, tab_id="regular"): @@ -695,7 +695,7 @@ class NavigatesGalaxy(HasDriver): with self.rule_builder_rule_editor("add-filter-count") as editor_element: filter_input = editor_element.find_element_by_css_selector("input[type='number']") filter_input.clear() - filter_input.send_keys("%s" % count) + filter_input.send_keys(f"{count}") def rule_builder_sort(self, column_label, screenshot_name=None): rule_builder = self.components.rule_builder @@ -723,7 +723,7 @@ class NavigatesGalaxy(HasDriver): filter_input = editor_element.find_element_by_css_selector("input[type='number']") filter_input.clear() - filter_input.send_keys("%s" % group_count) + filter_input.send_keys(f"{group_count}") if screenshot_name: self.screenshot(screenshot_name) @@ -745,7 +745,7 @@ class NavigatesGalaxy(HasDriver): filter_input = editor_element.find_element_by_css_selector("input.rule-replacement") filter_input.clear() - filter_input.send_keys("%s" % replacement) + filter_input.send_keys(f"{replacement}") if screenshot_name: self.screenshot(screenshot_name) @@ -874,7 +874,7 @@ class NavigatesGalaxy(HasDriver): break if not found_option: - raise Exception("Failed to find workflow editor option with label [%s]" % option_label) + raise Exception(f"Failed to find workflow editor option with label [{option_label}]") def workflow_editor_click_options(self): return self.wait_for_and_click_selector("#workflow-options-button") @@ -999,7 +999,7 @@ class NavigatesGalaxy(HasDriver): break if not found: - raise Exception("Failed to find history item [%s] to select" % to_select_item) + raise Exception(f"Failed to find history item [{to_select_item}] to select") def libraries_dataset_import_from_history_click_ok(self, wait=True): self.wait_for_and_click(self.navigation.libraries.folder.selectors.import_datasets_ok_button) @@ -1091,7 +1091,7 @@ class NavigatesGalaxy(HasDriver): def workflow_index_click_option(self, option_title, workflow_index=0): self.workflow_click_option(".workflow-dropdown", workflow_index) if not self.select_dropdown_item(option_title): - raise AssertionError("Failed to find workflow action option with title [%s]" % option_title) + raise AssertionError(f"Failed to find workflow action option with title [{option_title}]") def workflow_index_click_tag_display(self, workflow_index=0): workflow_row_element = self.workflow_index_table_row(workflow_index) @@ -1152,7 +1152,7 @@ class NavigatesGalaxy(HasDriver): div_element = self.tool_parameter_div(expanded_parameter_id) assert div_element if expected_type in ["select", "data", "data_collection"]: - div_selector = "div.ui-form-element[tour_id$='%s']" % expanded_parameter_id + div_selector = f"div.ui-form-element[tour_id$='{expanded_parameter_id}']" self.select2_set_value(div_selector, value) else: input_element = div_element.find_element_by_css_selector("input") @@ -1182,7 +1182,7 @@ class NavigatesGalaxy(HasDriver): def wait_for_sizzle_selector_clickable(self, selector): element = self._wait_on( sizzle.sizzle_selector_clickable(selector), - "sizzle/jQuery selector [%s] to become clickable" % selector, + f"sizzle/jQuery selector [{selector}] to become clickable", ) return element @@ -1196,7 +1196,7 @@ class NavigatesGalaxy(HasDriver): # Click labelled option self.wait_for_visible(self.navigation.history_panel.options_menu) - menu_item_sizzle_selector = "#history-options-button-menu > a:contains('%s')" % option_label + menu_item_sizzle_selector = f"#history-options-button-menu > a:contains('{option_label}')" menu_selection_element = self.wait_for_sizzle_selector_clickable(menu_item_sizzle_selector) menu_selection_element.click() @@ -1255,7 +1255,7 @@ class NavigatesGalaxy(HasDriver): def history_panel_muli_operation_select_hid(self, hid): item_selector = self.history_panel_item_selector(hid, wait=True) - operation_radio_selector = "%s .selector" % item_selector + operation_radio_selector = f"{item_selector} .selector" self.wait_for_and_click_selector(operation_radio_selector) def history_panel_multi_operation_action_click(self, action): @@ -1284,13 +1284,13 @@ class NavigatesGalaxy(HasDriver): self.wait_for_and_click(dataset_selector) def history_panel_item_click_visualization_menu(self, hid): - viz_button_selector = "{} {}".format(self.history_panel_item_selector(hid), ".visualizations-dropdown") + viz_button_selector = f"{self.history_panel_item_selector(hid)} .visualizations-dropdown" self.wait_for_and_click_selector(viz_button_selector) - self.wait_for_selector_visible("{} {}".format(viz_button_selector, ".dropdown-menu")) + self.wait_for_selector_visible(f"{viz_button_selector} .dropdown-menu") def history_panel_item_available_visualizations_elements(self, hid): # Precondition: viz menu has been opened with history_panel_item_click_visualization_menu - viz_menu_selectors = "{} {}".format(self.history_panel_item_selector(hid), "a.visualization-link") + viz_menu_selectors = f"{self.history_panel_item_selector(hid)} a.visualization-link" return self.driver.find_elements_by_css_selector(viz_menu_selectors) def history_panel_item_get_nametags(self, hid): @@ -1314,12 +1314,12 @@ class NavigatesGalaxy(HasDriver): def history_panel_item_selector(self, hid, wait=False): current_history_id = self.current_history_id() - contents = self.api_get("histories/%s/contents" % current_history_id) + contents = self.api_get(f"histories/{current_history_id}/contents") try: history_item = [d for d in contents if d["hid"] == hid][0] except IndexError: raise Exception(f"Could not find history item with hid [{hid}] in contents [{contents}]") - history_item_selector = "#{}-{}".format(history_item["history_content_type"], history_item["id"]) + history_item_selector = f"#{history_item['history_content_type']}-{history_item['id']}" if wait: self.wait_for_selector_visible(history_item_selector) return history_item_selector @@ -1336,7 +1336,7 @@ class NavigatesGalaxy(HasDriver): def hda_click_primary_action_button(self, hid, button_key): item_component = self.history_panel_click_item_title(hid=hid, wait=True) item_component.primary_action_buttons.wait_for_visible() - button_component = item_component["%s_button" % button_key] + button_component = item_component[f"{button_key}_button"] button_component.wait_for_and_click() def history_panel_click_item_title(self, hid, **kwds): @@ -1375,7 +1375,7 @@ class NavigatesGalaxy(HasDriver): def collection_builder_click_paired_item(self, forward_or_reverse, item): assert forward_or_reverse in ["forward", "reverse"] - forward_column = self.wait_for_selector_visible(".%s-column .column-datasets" % forward_or_reverse) + forward_column = self.wait_for_selector_visible(f".{forward_or_reverse}-column .column-datasets") first_datset_forward = forward_column.find_elements_by_css_selector("li")[item] first_datset_forward.click() @@ -1425,7 +1425,7 @@ class NavigatesGalaxy(HasDriver): def tour_wait_for_clickable_element(self, selector): timeout = self.timeout_for(wait_type=WAIT_TYPES.JOB_COMPLETION) wait = self.wait(timeout=timeout) - timeout_message = self._timeout_message("sizzle (jQuery) selector [%s] to become clickable" % selector) + timeout_message = self._timeout_message(f"sizzle (jQuery) selector [{selector}] to become clickable") element = wait.until( sizzle.sizzle_selector_clickable(selector), timeout_message, @@ -1435,7 +1435,7 @@ class NavigatesGalaxy(HasDriver): def tour_wait_for_element_present(self, selector): timeout = self.timeout_for(wait_type=WAIT_TYPES.JOB_COMPLETION) wait = self.wait(timeout=timeout) - timeout_message = self._timeout_message("sizzle (jQuery) selector [%s] to become present" % selector) + timeout_message = self._timeout_message(f"sizzle (jQuery) selector [{selector}] to become present") element = wait.until( sizzle.sizzle_presence_of_selector(selector), timeout_message, @@ -1508,12 +1508,12 @@ class NavigatesGalaxy(HasDriver): def run_tour_step(self, step, step_index, tour_callback): preclick = step.get("preclick", []) for preclick_selector in preclick: - print("(Pre)Clicking %s" % preclick_selector) + print(f"(Pre)Clicking {preclick_selector}") self._tour_wait_for_and_click_element(preclick_selector) element_str = step.get("element", None) if element_str is not None: - print("Waiting for element %s" % element_str) + print(f"Waiting for element {element_str}") element = self.tour_wait_for_element_present(element_str) assert element is not None @@ -1525,7 +1525,7 @@ class NavigatesGalaxy(HasDriver): postclick = step.get("postclick", []) for postclick_selector in postclick: - print("(Post)Clicking %s" % postclick_selector) + print(f"(Post)Clicking {postclick_selector}") self._tour_wait_for_and_click_element(postclick_selector) @retry_during_transitions diff --git a/lib/galaxy/tool_shed/galaxy_install/install_manager.py b/lib/galaxy/tool_shed/galaxy_install/install_manager.py index cdc3afe7152..73bf0067af8 100644 --- a/lib/galaxy/tool_shed/galaxy_install/install_manager.py +++ b/lib/galaxy/tool_shed/galaxy_install/install_manager.py @@ -128,7 +128,7 @@ class InstallToolDependencyManager: log.exception('Error installing tool dependency %s version %s.', tool_dependency.name, tool_dependency.version) # Since there was an installation error, update the tool dependency status to Error. The remove_installation_path option must # be left False here. - error_message = '{}\n{}'.format(self.format_traceback(), util.unicodify(e)) + error_message = f'{self.format_traceback()}\n{util.unicodify(e)}' tool_dependency = tool_dependency_util.set_tool_dependency_attributes(self.app, tool_dependency=tool_dependency, status=self.app.install_model.ToolDependency.installation_status.ERROR, @@ -152,7 +152,7 @@ class InstallToolDependencyManager: # Parse the tool_dependencies.xml config. tree, error_message = xml_util.parse_xml(tool_dependencies_config) if tree is None: - log.debug("The received tool_dependencies.xml file is likely invalid: %s" % str(error_message)) + log.debug(f"The received tool_dependencies.xml file is likely invalid: {str(error_message)}") return installed_packages root = tree.getroot() elems = [] @@ -483,10 +483,10 @@ class InstallRepositoryManager: if not repository_revision_dict or not repo_info_dict: invalid_parameter_message = "No information is available for the requested repository revision.\n" invalid_parameter_message += "One or more of the following parameter values is likely invalid:\n" - invalid_parameter_message += "tool_shed_url: %s\n" % tool_shed_url - invalid_parameter_message += "name: %s\n" % name - invalid_parameter_message += "owner: %s\n" % owner - invalid_parameter_message += "changeset_revision: %s\n" % changeset_revision + invalid_parameter_message += f"tool_shed_url: {tool_shed_url}\n" + invalid_parameter_message += f"name: {name}\n" + invalid_parameter_message += f"owner: {owner}\n" + invalid_parameter_message += f"changeset_revision: {changeset_revision}\n" raise exceptions.RequestParameterInvalidException(invalid_parameter_message) repo_info_dicts = [repo_info_dict] return repository_revision_dict, repo_info_dicts diff --git a/lib/galaxy/tool_shed/galaxy_install/installed_repository_manager.py b/lib/galaxy/tool_shed/galaxy_install/installed_repository_manager.py index 68ef4616c1e..26b379d2573 100644 --- a/lib/galaxy/tool_shed/galaxy_install/installed_repository_manager.py +++ b/lib/galaxy/tool_shed/galaxy_install/installed_repository_manager.py @@ -638,10 +638,10 @@ class InstalledRepositoryManager: try: # Remove the repository from disk. shutil.rmtree(repository_install_dir) - log.debug("Removed repository installation directory: %s" % str(repository_install_dir)) + log.debug(f"Removed repository installation directory: {str(repository_install_dir)}") removed = True except Exception as e: - log.debug("Error removing repository installation directory {}: {}".format(str(repository_install_dir), str(e))) + log.debug(f"Error removing repository installation directory {str(repository_install_dir)}: {str(e)}") if isinstance(e, OSError) and not os.path.exists(repository_install_dir): removed = True log.debug("Repository directory does not exist on disk, marking as uninstalled.") @@ -777,7 +777,7 @@ class InstalledRepositoryManager: else: status = 'error' message = 'A repository must have the status New in order to be purged. This repository has ' - message += ' the status %s.' % str(repository.status) + message += f' the status {str(repository.status)}.' return status, message def remove_entry_from_installed_repository_dependencies_of_installed_repositories(self, repository): diff --git a/lib/galaxy/tool_shed/galaxy_install/metadata/installed_repository_metadata_manager.py b/lib/galaxy/tool_shed/galaxy_install/metadata/installed_repository_metadata_manager.py index 1df4969711a..6619ef98773 100644 --- a/lib/galaxy/tool_shed/galaxy_install/metadata/installed_repository_metadata_manager.py +++ b/lib/galaxy/tool_shed/galaxy_install/metadata/installed_repository_metadata_manager.py @@ -39,8 +39,8 @@ class InstalledRepositoryMetadataManager(MetadataGenerator): query = self.get_query_for_setting_metadata_on_repositories(order=True) for repository in query: owner = str(repository.owner) - option_label = '{} ({})'.format(str(repository.name), owner) - option_value = '%s' % self.app.security.encode_id(repository.id) + option_label = f'{str(repository.name)} ({owner})' + option_value = f'{self.app.security.encode_id(repository.id)}' repositories_select_field.add_option(option_label, option_value) return repositories_select_field @@ -95,11 +95,11 @@ class InstalledRepositoryMetadataManager(MetadataGenerator): self.app.install_model.context.add(self.repository) self.app.install_model.context.flush() self.app.tool_shed_repository_cache.rebuild() - log.debug('Metadata has been reset on repository %s.' % self.repository.name) + log.debug(f'Metadata has been reset on repository {self.repository.name}.') else: - log.debug('Metadata did not need to be reset on repository %s.' % self.repository.name) + log.debug(f'Metadata did not need to be reset on repository {self.repository.name}.') else: - log.debug('Error locating installation directory for repository %s.' % self.repository.name) + log.debug(f'Error locating installation directory for repository {self.repository.name}.') def reset_metadata_on_selected_repositories(self, user, **kwd): """ diff --git a/lib/galaxy/tool_shed/galaxy_install/migrate/check.py b/lib/galaxy/tool_shed/galaxy_install/migrate/check.py index f07ab310b45..4bef367d7b5 100644 --- a/lib/galaxy/tool_shed/galaxy_install/migrate/check.py +++ b/lib/galaxy/tool_shed/galaxy_install/migrate/check.py @@ -64,7 +64,7 @@ def verify_tools(app, url, galaxy_config_file=None, engine_options=None): return_code = proc.wait() output = proc.stdout.read(32768) if return_code != 0: - raise Exception("Error attempting to update the value of migrate_tools.version: %s" % output) + raise Exception(f"Error attempting to update the value of migrate_tools.version: {output}") elif missing_tool_configs_dict: if len(tool_panel_configs) == 1: plural = '' @@ -106,13 +106,13 @@ def verify_tools(app, url, galaxy_config_file=None, engine_options=None): tool_dependencies_tup[2]) if len(tool_dependencies_tup) >= 4: msg += "Requirements and installation information:\n" - msg += "%s\n" % tool_dependencies_tup[3] + msg += f"{tool_dependencies_tup[3]}\n" else: msg += "\n" msg += "------------------------------------\n" processed_tool_dependencies.append(tool_dependencies_tup) msg += "\n" - msg += "%s" % output.replace('done', '') + msg += f"{output.replace('done', '')}" msg += "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" msg += "sh ./scripts/migrate_tools/%04d_tools.sh\n" % latest_tool_migration_script_number msg += "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n" @@ -128,11 +128,11 @@ def verify_tools(app, url, galaxy_config_file=None, engine_options=None): msg += "tools will continue to be loaded into your tool panel. Because of this, existing entries for these tools have been\n" msg += f"removed from your file{plural} named {tool_panel_config_file_names}.\n\n" for missing_tool_config in missing_tool_configs_dict.keys(): - msg += "%s\n" % missing_tool_config + msg += f"{missing_tool_config}\n" msg += "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n" raise Exception(msg) else: - log.debug("The main Galaxy tool shed is not currently available, so skipped tool migration %s until next server startup" % db_schema.version) + log.debug(f"The main Galaxy tool shed is not currently available, so skipped tool migration {db_schema.version} until next server startup") else: log.info("At migrate_tools version %d" % db_schema.version) diff --git a/lib/galaxy/tool_shed/galaxy_install/migrate/common.py b/lib/galaxy/tool_shed/galaxy_install/migrate/common.py index 96946914ab3..42a7aa56374 100644 --- a/lib/galaxy/tool_shed/galaxy_install/migrate/common.py +++ b/lib/galaxy/tool_shed/galaxy_install/migrate/common.py @@ -21,7 +21,7 @@ class MigrateToolsApplication(galaxy.config.ConfiguresGalaxyMixin): sys.argv.pop(pos) galaxy_config_file = sys.argv.pop(pos) if not os.path.exists(galaxy_config_file): - print("Galaxy config file does not exist (hint: use '-c config.ini' for non-standard locations): %s" % galaxy_config_file) + print(f"Galaxy config file does not exist (hint: use '-c config.ini' for non-standard locations): {galaxy_config_file}") sys.exit(1) config_parser = configparser.ConfigParser({'here': os.getcwd()}) config_parser.read(galaxy_config_file) diff --git a/lib/galaxy/tool_shed/galaxy_install/migrate/scripts/migrate_tools.py b/lib/galaxy/tool_shed/galaxy_install/migrate/scripts/migrate_tools.py index 06e492d0568..28a4b154e0e 100644 --- a/lib/galaxy/tool_shed/galaxy_install/migrate/scripts/migrate_tools.py +++ b/lib/galaxy/tool_shed/galaxy_install/migrate/scripts/migrate_tools.py @@ -25,8 +25,8 @@ def main(): else: plural = 's' file_names = ', '.join(non_shed_tool_confs) - msg = "\nThe installation process is finished. All tools associated with this migration that were defined in your file%s named\n" % plural - msg += "%s, have been removed. You may now start your Galaxy server.\n" % file_names + msg = f"\nThe installation process is finished. All tools associated with this migration that were defined in your file{plural} named\n" + msg += f"{file_names}, have been removed. You may now start your Galaxy server.\n" print(msg) app.shutdown() sys.exit(0) diff --git a/lib/galaxy/tool_shed/galaxy_install/repository_dependencies/repository_dependency_manager.py b/lib/galaxy/tool_shed/galaxy_install/repository_dependencies/repository_dependency_manager.py index 0a45b6d6fd5..36e9674e0cb 100644 --- a/lib/galaxy/tool_shed/galaxy_install/repository_dependencies/repository_dependency_manager.py +++ b/lib/galaxy/tool_shed/galaxy_install/repository_dependencies/repository_dependency_manager.py @@ -214,7 +214,7 @@ class RepositoryDependencyInstallManager: elif repository_db_record.status in [install_model.ToolShedRepository.installation_status.DEACTIVATED]: # The current tool shed repository is deactivated, so updating its database record # is not necessary - just activate it. - log.info("Reactivating deactivated tool_shed_repository '%s'." % str(repository_db_record.name)) + log.info(f"Reactivating deactivated tool_shed_repository '{str(repository_db_record.name)}'.") self.app.installed_repository_manager.activate_repository(repository_db_record) # No additional updates to the database record are necessary. can_update_db_record = False @@ -482,13 +482,13 @@ class RepositoryDependencyInstallManager: will be set to the default NEW state. This will enable the repository to be freshly installed. """ - debug_msg = "Resetting tool_shed_repository '%s' for installation.\n" % repository.name + debug_msg = f"Resetting tool_shed_repository '{repository.name}' for installation.\n" debug_msg += "The current state of the tool_shed_repository is:\n" - debug_msg += "deleted: %s\n" % repository.deleted - debug_msg += "tool_shed_status: %s\n" % repository.tool_shed_status - debug_msg += "uninstalled: %s\n" % repository.uninstalled - debug_msg += "status: %s\n" % repository.status - debug_msg += "error_message: %s\n" % repository.error_message + debug_msg += f"deleted: {repository.deleted}\n" + debug_msg += f"tool_shed_status: {repository.tool_shed_status}\n" + debug_msg += f"uninstalled: {repository.uninstalled}\n" + debug_msg += f"status: {repository.status}\n" + debug_msg += f"error_message: {repository.error_message}\n" log.debug(debug_msg) repository.deleted = False repository.tool_shed_status = None @@ -501,7 +501,7 @@ class RepositoryDependencyInstallManager: def _urlopen(url, data=None): scheme = urlparse(url).scheme - assert scheme in ('http', 'https', 'ftp'), 'Invalid URL scheme: %s' % scheme + assert scheme in ('http', 'https', 'ftp'), f'Invalid URL scheme: {scheme}' if data is not None: data = smart_str(data) return urlopen(Request(url, data)) diff --git a/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/env_file_builder.py b/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/env_file_builder.py index 4b75b66e20d..96618935da9 100644 --- a/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/env_file_builder.py +++ b/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/env_file_builder.py @@ -28,14 +28,14 @@ class EnvFileBuilder: if env_var_action == 'prepend_to': changed_value = f'{env_var_value}:${env_var_name}' elif env_var_action == 'set_to': - changed_value = '%s' % env_var_value + changed_value = f'{env_var_value}' elif env_var_action == 'append_to': changed_value = f'${env_var_name}:{env_var_value}' line = f"{env_var_name}={changed_value}; export {env_var_name}" elif env_var_action == "source": line = f"if [ -f {env_var_value} ] ; then . {env_var_value} ; fi" else: - raise Exception("Unknown shell file action %s" % env_var_action) + raise Exception(f"Unknown shell file action {env_var_action}") env_shell_file_path = os.path.join(install_dir, 'env.sh') return line, env_shell_file_path diff --git a/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/install_environment.py b/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/install_environment.py index 626be903c31..8f7dccc76ad 100644 --- a/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/install_environment.py +++ b/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/install_environment.py @@ -65,11 +65,11 @@ class InstallEnvironment: break except OSError as e: # Undoubtedly close() was called during a concurrent operation on the same file object. - log.debug('Error closing file descriptor: %s' % str(e)) + log.debug(f'Error closing file descriptor: {str(e)}') time.sleep(.5) current_wait_time = time.time() - start_timer if current_wait_time >= 600: - error = 'Error closing file descriptor: %s' % str(e) + error = f'Error closing file descriptor: {str(e)}' break return error @@ -100,7 +100,7 @@ class InstallEnvironment: for env_setting in open(env_shell_file_path): cmds.append(env_setting.strip('\n')) else: - log.debug('Invalid file {} specified, ignoring {} action.'.format(str(env_shell_file_path), str(action_type))) + log.debug(f'Invalid file {str(env_shell_file_path)} specified, ignoring {str(action_type)} action.') return cmds def environment_dict(self, action_type='template_command'): @@ -112,7 +112,7 @@ class InstallEnvironment: env_name, env_path = env_string.split('=') env_vars[env_name] = env_path else: - log.debug('Invalid file %s specified, ignoring template_command action.' % str(env_shell_file_path)) + log.debug(f'Invalid file {str(env_shell_file_path)} specified, ignoring template_command action.') return env_vars def handle_command(self, tool_dependency, cmd, return_output=False, job_name=""): @@ -123,10 +123,10 @@ class InstallEnvironment: stdout = output.stdout stderr = output.stderr if len(stdout) > DATABASE_MAX_STRING_SIZE: - log.warning("Length of stdout > %s, so only a portion will be saved in the database." % str(DATABASE_MAX_STRING_SIZE_PRETTY)) + log.warning(f"Length of stdout > {str(DATABASE_MAX_STRING_SIZE_PRETTY)}, so only a portion will be saved in the database.") stdout = shrink_string_by_size(stdout, DATABASE_MAX_STRING_SIZE, join_by="\n..\n", left_larger=True, beginning_on_size_error=True) if len(stderr) > DATABASE_MAX_STRING_SIZE: - log.warning("Length of stderr > %s, so only a portion will be saved in the database." % str(DATABASE_MAX_STRING_SIZE_PRETTY)) + log.warning(f"Length of stderr > {str(DATABASE_MAX_STRING_SIZE_PRETTY)}, so only a portion will be saved in the database.") stderr = shrink_string_by_size(stderr, DATABASE_MAX_STRING_SIZE, join_by="\n..\n", left_larger=True, beginning_on_size_error=True) if output.return_code not in [0]: status = self.app.install_model.ToolDependency.installation_status.ERROR diff --git a/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py b/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py index c14bd1cfbe7..ad04c547ac8 100644 --- a/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py +++ b/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py @@ -49,7 +49,7 @@ class Download: try: download_to_file(download_url, file_path, chunk_size=basic_util.CHUNK_SIZE) except Exception as e: - err_msg = 'Error downloading from URL {} : {}'.format(str(download_url), str(e)) + err_msg = f'Error downloading from URL {str(download_url)} : {str(e)}' raise Exception(err_msg) if 'sha256sum' in checksums or '#sha256#' in download_url: @@ -144,7 +144,7 @@ class AssertDirectoryExecutable(RecipeStep): full_path = os.path.join(current_dir, action_dict['full_path']) if not self.assert_directory_executable(full_path=full_path): status = self.app.install_model.ToolDependency.installation_status.ERROR - error_message = 'The path %s is not a directory or is not executable by the owner.' % str(full_path) + error_message = f'The path {str(full_path)} is not a directory or is not executable by the owner.' tool_dependency = tool_dependency_util.set_tool_dependency_attributes(self.app, tool_dependency, status=status, @@ -190,7 +190,7 @@ class AssertDirectoryExists(RecipeStep): full_path = os.path.join(current_dir, action_dict['full_path']) if not self.assert_directory_exists(full_path=full_path): status = self.app.install_model.ToolDependency.installation_status.ERROR - error_message = 'The path %s is not a directory or does not exist.' % str(full_path) + error_message = f'The path {str(full_path)} is not a directory or does not exist.' tool_dependency = tool_dependency_util.set_tool_dependency_attributes(self.app, tool_dependency, status=status, @@ -239,7 +239,7 @@ class AssertFileExecutable(RecipeStep): full_path = os.path.join(current_dir, action_dict['full_path']) if not self.assert_file_executable(full_path=full_path): status = self.app.install_model.ToolDependency.installation_status.ERROR - error_message = 'The path %s is not a file or is not executable by the owner.' % str(full_path) + error_message = f'The path {str(full_path)} is not a file or is not executable by the owner.' tool_dependency = tool_dependency_util.set_tool_dependency_attributes(self.app, tool_dependency, status=status, @@ -285,7 +285,7 @@ class AssertFileExists(RecipeStep): full_path = os.path.join(current_dir, action_dict['full_path']) if not self.assert_file_exists(full_path=full_path): status = self.app.install_model.ToolDependency.installation_status.ERROR - error_message = 'The path %s is not a file or does not exist.' % str(full_path) + error_message = f'The path {str(full_path)} is not a file or does not exist.' tool_dependency = tool_dependency_util.set_tool_dependency_attributes(self.app, tool_dependency, status=status, @@ -315,9 +315,9 @@ class Autoconf(RecipeStep): with settings(warn_only=True): configure_opts = action_dict.get('configure_opts', '') if 'prefix=' in configure_opts: - pre_cmd = './configure %s && make && make install' % configure_opts + pre_cmd = f'./configure {configure_opts} && make && make install' else: - pre_cmd = './configure --prefix=$INSTALL_DIR %s && make && make install' % configure_opts + pre_cmd = f'./configure --prefix=$INSTALL_DIR {configure_opts} && make && make install' cmd = install_environment.build_command(basic_util.evaluate_template(pre_cmd, install_environment)) install_environment.handle_command(tool_dependency=tool_dependency, cmd=cmd, @@ -557,9 +557,9 @@ class DownloadByUrl(Download, RecipeStep): logfile = open(log_file, 'a') else: logfile = open(log_file, 'w') - logfile.write('Successfully downloaded from url: %s\n' % action_dict['url']) + logfile.write(f"Successfully downloaded from url: {action_dict['url']}\n") logfile.close() - log.debug('Successfully downloaded from url: %s' % action_dict['url']) + log.debug(f"Successfully downloaded from url: {action_dict['url']}") if initial_download: return tool_dependency, filtered_actions, dir return tool_dependency, None, None @@ -676,7 +676,7 @@ class MakeInstall(RecipeStep): # make; make install; allow providing make options with settings(warn_only=True): make_opts = action_dict.get('make_opts', '') - cmd = install_environment.build_command('make %s && make install' % make_opts) + cmd = install_environment.build_command(f'make {make_opts} && make install') install_environment.handle_command(tool_dependency=tool_dependency, cmd=cmd, return_output=False, @@ -854,7 +854,7 @@ class SetEnvironment(RecipeStep): cmds = install_environment.environment_commands('set_environment') env_var_dicts = action_dict.get('environment_variable', []) root_dir_dict = dict(action='set_to', - name='%s_ROOT_DIR' % re.sub(r"[^A-Z0-9_]", "_", tool_dependency.name.upper()), + name=f"{re.sub('[^A-Z0-9_]', '_', tool_dependency.name.upper())}_ROOT_DIR", value=install_environment.install_dir) env_var_dicts.append(root_dir_dict) for env_var_dict in env_var_dicts: @@ -944,7 +944,7 @@ class SetEnvironment(RecipeStep): if '$ENV[' in env_var_value and ']' in env_var_value: # Pull out the name of the environment variable to populate. inherited_env_var_name = env_var_value.split('[')[1].split(']')[0] - to_replace = '$ENV[%s]' % inherited_env_var_name + to_replace = f'$ENV[{inherited_env_var_name}]' found = False for env_cmd in set_prior_environment_commands: # LD_LIBRARY_PATH=//; export LD_LIBRARY_PATH @@ -960,7 +960,7 @@ class SetEnvironment(RecipeStep): if not found: # Replace the original $ENV[] with nothing, to avoid any shell misparsings later on. log.debug('Environment variable %s not found, removing from set_environment.', inherited_env_var_name) - env_var_value = env_var_value.replace(to_replace, '$%s' % inherited_env_var_name) + env_var_value = env_var_value.replace(to_replace, f'${inherited_env_var_name}') env_var_dict['value'] = env_var_value return env_var_dict @@ -1080,7 +1080,7 @@ class SetupPerlEnvironment(Download, RecipeStep): # If set to a true value then MakeMaker's prompt function will always # return the default without waiting for user input. cmd = '''PERL_MM_USE_DEFAULT=1; export PERL_MM_USE_DEFAULT; ''' - cmd += 'HOME=%s; export HOME; ' % work_dir + cmd += f'HOME={work_dir}; export HOME; ' cmd += 'export PERL5LIB=$INSTALL_DIR/lib/perl5:$PERL5LIB;' cmd += 'export PATH=$INSTALL_DIR/bin:$PATH;' if perl_package.find('://') != -1: @@ -1114,7 +1114,7 @@ class SetupPerlEnvironment(Download, RecipeStep): else: # perl package from CPAN without version number. # cpanm should be installed with the parent perl distribution, otherwise this will not work. - cmd += '''cpanm --local-lib=$INSTALL_DIR %s''' % (perl_package) + cmd += f'''cpanm --local-lib=$INSTALL_DIR {perl_package}''' cmd = install_environment.build_command(basic_util.evaluate_template(cmd, install_environment)) return_code = install_environment.handle_command(tool_dependency=tool_dependency, cmd=cmd, @@ -1328,7 +1328,7 @@ class SetupRubyEnvironment(Download, RecipeStep): ruby_package_tup = ruby_package_tup_dict['package'] gem, gem_version, gem_parameters = ruby_package_tup if gem_parameters: - gem_parameters = '-- %s' % gem_parameters + gem_parameters = f'-- {gem_parameters}' else: gem_parameters = '' if os.path.isfile(gem): @@ -1600,7 +1600,7 @@ class SetupVirtualEnv(Download, RecipeStep): setup_command = f"{python_cmd} {venv_src_directory}/virtualenv.py --no-site-packages '{venv_directory}'" # POSIXLY_CORRECT forces shell commands . and source to have the same # and well defined behavior in bash/zsh. - activate_command = "POSIXLY_CORRECT=1; . %s" % os.path.join(venv_directory, "bin", "activate") + activate_command = f"POSIXLY_CORRECT=1; . {os.path.join(venv_directory, 'bin', 'activate')}" if action_dict['use_requirements_file']: install_command = "python '%s' install -r '%s' --log '%s'" % \ (os.path.join(venv_directory, "bin", "pip"), @@ -1771,7 +1771,7 @@ class TemplateCommand(RecipeStep): with settings(warn_only=True, **env_vars): if language == 'cheetah': # We need to import fabric.api.env so that we can access all collected environment variables. - cmd = fill_template('#from fabric.api import env\n%s' % action_dict['command'], context=env_vars) + cmd = fill_template(f"#from fabric.api import env\n{action_dict['command']}", context=env_vars) # The caller should check the status of the returned tool_dependency since this function # does nothing with return_code. install_environment.handle_command(tool_dependency=tool_dependency, @@ -1795,6 +1795,6 @@ class TemplateCommand(RecipeStep): action_dict['language'] = language action_dict['command'] = action_elem_text else: - log.debug("Unsupported template language '%s'. Not proceeding." % str(language)) - raise Exception("Unsupported template language '%s' in tool dependency definition." % str(language)) + log.debug(f"Unsupported template language '{str(language)}'. Not proceeding.") + raise Exception(f"Unsupported template language '{str(language)}' in tool dependency definition.") return action_dict diff --git a/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/tag_handler.py b/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/tag_handler.py index b8ebfcdf53f..31a3e7e09c9 100644 --- a/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/tag_handler.py +++ b/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/tag_handler.py @@ -173,7 +173,7 @@ class Install(RecipeTag, SyncDatabase): include_after_install_actions=True) if not actions_elem_tuples: proceed_with_install = False - error_message = 'Version {} of the {} package cannot be installed because '.format(str(package_version), str(package_name)) + error_message = f'Version {str(package_version)} of the {str(package_name)} package cannot be installed because ' error_message += 'the recipe for installing the package is missing either an <actions> tag set or an <actions_group> ' error_message += 'tag set.' # Since there was an installation error, update the tool dependency status to Error. @@ -262,7 +262,7 @@ class Repository(RecipeTag, SyncDatabase): return tmp_filename else: message = "Unable to retrieve required tool_dependencies.xml file from the Tool Shed for revision " - message += "{} of installed repository {} owned by {}.".format(str(changeset_revision), str(name), str(owner)) + message += f"{str(changeset_revision)} of installed repository {str(name)} owned by {str(owner)}." raise Exception(message) def create_tool_dependency_with_initialized_env_sh_file(self, dependent_install_dir, tool_shed_repository, @@ -430,7 +430,7 @@ class Repository(RecipeTag, SyncDatabase): # required_repository. if required_repository.is_deactivated_or_installed: if not os.path.exists(required_repository_package_install_dir): - log.error('Missing required tool dependency directory %s' % str(required_repository_package_install_dir)) + log.error(f'Missing required tool dependency directory {str(required_repository_package_install_dir)}') repo_files_dir = required_repository.repo_files_directory(self.app) if not repo_files_dir: message = "Unable to locate the repository directory for revision %s of installed repository %s owned by %s." % \ @@ -488,7 +488,7 @@ class Repository(RecipeTag, SyncDatabase): for rd_tool_dependency in rd_tool_dependencies: if rd_tool_dependency.status == self.app.install_model.ToolDependency.installation_status.ERROR: # We'll log the error here, but continue installing packages since some may not require this dependency. - log.error("Error installing tool dependency for required repository: %s" % str(rd_tool_dependency.error_message)) + log.error(f"Error installing tool dependency for required repository: {str(rd_tool_dependency.error_message)}") return tool_dependency, proceed_with_install, action_elem_tuples def remove_file(self, file_name): @@ -524,7 +524,7 @@ class SetEnvironment(RecipeTag): try: self.set_environment(package_elem, tool_shed_repository, attr_tups_of_dependencies_for_install) except Exception as e: - error_message = "Error setting environment for tool dependency: %s" % str(e) + error_message = f"Error setting environment for tool dependency: {str(e)}" log.debug(error_message) return tool_dependency, proceed_with_install, action_elem_tuples diff --git a/lib/galaxy/tool_shed/galaxy_install/tools/data_manager.py b/lib/galaxy/tool_shed/galaxy_install/tools/data_manager.py index 2a6552eea31..343b2fb081d 100644 --- a/lib/galaxy/tool_shed/galaxy_install/tools/data_manager.py +++ b/lib/galaxy/tool_shed/galaxy_install/tools/data_manager.py @@ -40,7 +40,7 @@ class DataManagerHandler: """ data_managers_path = self.data_managers_path if data_managers_path: - root_str = '' % data_managers_path + root_str = f'' else: root_str = '' root = parse_xml_string(root_str) @@ -93,7 +93,7 @@ class DataManagerHandler: continue data_manager_dict = metadata_dict['data_manager'].get('data_managers', {}).get(data_manager_id, None) if data_manager_dict is None: - log.error("Data manager metadata is not defined properly for '%s'." % (data_manager_id)) + log.error(f"Data manager metadata is not defined properly for '{data_manager_id}'.") continue guid = data_manager_dict.get('guid', None) if guid is None: @@ -116,7 +116,7 @@ class DataManagerHandler: continue tool_config_filename = tool_dict.get('tool_config_filename', None) if tool_config_filename is None: - log.error("Data manager metadata is missing 'tool_config_file' for '%s'." % (data_manager_id)) + log.error(f"Data manager metadata is missing 'tool_config_file' for '{data_manager_id}'.") continue elem.set('shed_conf_file', shed_config_dict['config_filename']) if elem.get('tool_file', None) is not None: @@ -137,7 +137,7 @@ class DataManagerHandler: elif elem.tag is etree.Comment: pass else: - log.warning("Encountered unexpected element '{}':\n{}".format(elem.tag, xml_to_string(elem))) + log.warning(f"Encountered unexpected element '{elem.tag}':\n{xml_to_string(elem)}") config_elems.append(elem) data_manager_config_has_changes = True # Persist the altered shed_data_manager_config file. @@ -155,7 +155,7 @@ class DataManagerHandler: tree, error_message = parse_xml(shed_data_manager_conf_filename) if tree: root = tree.getroot() - assert root.tag == 'data_managers', 'The file provided (%s) for removing data managers from is not a valid data manager xml file.' % (shed_data_manager_conf_filename) + assert root.tag == 'data_managers', f'The file provided ({shed_data_manager_conf_filename}) for removing data managers from is not a valid data manager xml file.' guids = [data_manager_dict.get('guid') for data_manager_dict in metadata_dict.get('data_manager', {}).get('data_managers', {}).values() if 'guid' in data_manager_dict] load_old_data_managers_by_guid = {} data_manager_config_has_changes = False diff --git a/lib/galaxy/tool_shed/galaxy_install/tools/tool_panel_manager.py b/lib/galaxy/tool_shed/galaxy_install/tools/tool_panel_manager.py index ccc933a7044..ba50383aa64 100644 --- a/lib/galaxy/tool_shed/galaxy_install/tools/tool_panel_manager.py +++ b/lib/galaxy/tool_shed/galaxy_install/tools/tool_panel_manager.py @@ -354,7 +354,7 @@ class ToolPanelManager: file_name = strip_path(shed_tool_conf_dict['config_filename']) if shed_tool_conf == file_name: return shed_tool_conf_dict - raise RequestParameterInvalidException("Requested shed_tool_conf '%s' is not an active shed_tool_config_file" % shed_tool_conf) + raise RequestParameterInvalidException(f"Requested shed_tool_conf '{shed_tool_conf}' is not an active shed_tool_config_file") def handle_tool_panel_section(self, toolbox, tool_panel_section_id=None, new_tool_panel_section_label=None): """Return a ToolSection object retrieved from the current in-memory tool_panel.""" diff --git a/lib/galaxy/tool_shed/galaxy_install/update_repository_manager.py b/lib/galaxy/tool_shed/galaxy_install/update_repository_manager.py index 3e6f2796421..d780853de85 100644 --- a/lib/galaxy/tool_shed/galaxy_install/update_repository_manager.py +++ b/lib/galaxy/tool_shed/galaxy_install/update_repository_manager.py @@ -62,7 +62,7 @@ class UpdateRepositoryManager: changeset_revision_dict['changeset_revision'] = changeset_revision changeset_revision_dict['ctx_rev'] = ctx_rev except Exception as e: - log.debug("Error getting change set revision for update from the tool shed for repository '{}': {}".format(repository.name, str(e))) + log.debug(f"Error getting change set revision for update from the tool shed for repository '{repository.name}': {str(e)}") changeset_revision_dict['includes_data_managers'] = False changeset_revision_dict['includes_datatypes'] = False changeset_revision_dict['includes_tools'] = False diff --git a/lib/galaxy/tool_shed/metadata/metadata_generator.py b/lib/galaxy/tool_shed/metadata/metadata_generator.py index dcdc2009204..98e18c10971 100644 --- a/lib/galaxy/tool_shed/metadata/metadata_generator.py +++ b/lib/galaxy/tool_shed/metadata/metadata_generator.py @@ -153,7 +153,7 @@ class MetadataGenerator: tool_file = data_manager_elem.get('tool_file', None) data_manager_id = data_manager_elem.get('id', None) if data_manager_id is None: - log.error('Data Manager entry is missing id attribute in "%s".' % (data_manager_config_filename)) + log.error(f'Data Manager entry is missing id attribute in "{data_manager_config_filename}".') invalid_data_managers.append({'index': i, 'error_message': 'Data Manager entry is missing id attribute'}) continue @@ -163,7 +163,7 @@ class MetadataGenerator: guid = self.generate_guid_for_object(DataManager.GUID_TYPE, data_manager_id, version) data_tables = [] if tool_file is None: - log.error('Data Manager entry is missing tool_file attribute in "%s".' % (data_manager_config_filename)) + log.error(f'Data Manager entry is missing tool_file attribute in "{data_manager_config_filename}".') invalid_data_managers.append({'index': i, 'error_message': 'Data Manager entry is missing tool_file attribute'}) continue @@ -172,7 +172,7 @@ class MetadataGenerator: for data_table_elem in data_manager_elem.findall('data_table'): data_table_name = data_table_elem.get('name', None) if data_table_name is None: - log.error('Data Manager data_table entry is missing name attribute in "%s".' % (data_manager_config_filename)) + log.error(f'Data Manager data_table entry is missing name attribute in "{data_manager_config_filename}".') invalid_data_managers.append({'index': i, 'error_message': 'Data Manager entry is missing name attribute'}) bad_data_table = True @@ -185,7 +185,7 @@ class MetadataGenerator: tool_metadata_tool_file = os.path.join(repo_files_directory, data_manager_metadata_tool_file) tool = tools.get(tool_metadata_tool_file, None) if tool is None: - log.error("Unable to determine tools metadata for '%s'." % (data_manager_metadata_tool_file)) + log.error(f"Unable to determine tools metadata for '{data_manager_metadata_tool_file}'.") invalid_data_managers.append({'index': i, 'error_message': 'Unable to determine tools metadata'}) continue @@ -196,7 +196,7 @@ class MetadataGenerator: 'tool_config_file': data_manager_metadata_tool_file, 'data_tables': data_tables, 'tool_guid': tool['guid']} - log.debug('Loaded Data Manager tool_files: %s' % (tool_file)) + log.debug(f'Loaded Data Manager tool_files: {tool_file}') return metadata_dict def generate_datatypes_metadata(self, tv, repository_files_dir, datatypes_config, metadata_dict): @@ -663,7 +663,7 @@ class MetadataGenerator: # Nested required files are being populated correctly, # not sure we need the value here to be anything else? collection_type = values.collection_type - metadata_display_value = "%s collection" % collection_type + metadata_display_value = f"{collection_type} collection" inputs.append((param_name, metadata_display_value)) else: try: @@ -956,7 +956,7 @@ class MetadataGenerator: # installed tool shed repository. error_message = "Ignoring invalid repository dependency definition for tool shed %s, name %s, owner %s, " % \ (toolshed, name, owner) - error_message += "changeset revision %s." % changeset_revision + error_message += f"changeset revision {changeset_revision}." log.debug(error_message) is_valid = False return repository_dependency_tup, is_valid, error_message @@ -970,7 +970,7 @@ class MetadataGenerator: except Exception: error_message = "Ignoring repository dependency definition for tool shed %s, name %s, owner %s, " % \ (toolshed, name, owner) - error_message += "changeset revision %s because the owner is invalid." % changeset_revision + error_message += f"changeset revision {changeset_revision} because the owner is invalid." log.debug(error_message) is_valid = False return repository_dependency_tup, is_valid, error_message @@ -982,7 +982,7 @@ class MetadataGenerator: except Exception: error_message = "Ignoring repository dependency definition for tool shed %s, name %s, owner %s, " % \ (toolshed, name, owner) - error_message += "changeset revision %s because the name is invalid. " % changeset_revision + error_message += f"changeset revision {changeset_revision} because the name is invalid. " log.debug(error_message) is_valid = False return repository_dependency_tup, is_valid, error_message @@ -1013,7 +1013,7 @@ class MetadataGenerator: if not found: error_message = "Ignoring repository dependency definition for tool shed %s, name %s, owner %s, " % \ (toolshed, name, owner) - error_message += "changeset revision %s because the changeset revision is invalid. " % changeset_revision + error_message += f"changeset revision {changeset_revision} because the changeset revision is invalid. " log.debug(error_message) is_valid = False return repository_dependency_tup, is_valid, error_message @@ -1121,9 +1121,9 @@ class MetadataGenerator: def _get_readme_file_names(repository_name): """Return a list of file names that will be categorized as README files for the received repository_name.""" readme_files = ['readme', 'read_me', 'install'] - valid_filenames = ['%s.txt' % f for f in readme_files] - valid_filenames.extend(['%s.rst' % f for f in readme_files]) + valid_filenames = [f'{f}.txt' for f in readme_files] + valid_filenames.extend([f'{f}.rst' for f in readme_files]) valid_filenames.extend(readme_files) - valid_filenames.append('%s.txt' % repository_name) - valid_filenames.append('%s.rst' % repository_name) + valid_filenames.append(f'{repository_name}.txt') + valid_filenames.append(f'{repository_name}.rst') return valid_filenames diff --git a/lib/galaxy/tool_shed/tool_shed_registry.py b/lib/galaxy/tool_shed/tool_shed_registry.py index aecc4319e4b..3d927dc49c3 100644 --- a/lib/galaxy/tool_shed/tool_shed_registry.py +++ b/lib/galaxy/tool_shed/tool_shed_registry.py @@ -28,13 +28,13 @@ class Registry: # Parse tool_sheds_conf.xml tree, error_message = parse_xml(config) if tree is None: - log.warning("Unable to load references to tool sheds defined in file %s" % str(config)) + log.warning(f"Unable to load references to tool sheds defined in file {str(config)}") return root = tree.getroot() else: root = parse_xml_string(DEFAULT_TOOL_SHEDS_CONF_XML) config = "internal default config" - log.debug('Loading references to tool sheds from %s' % config) + log.debug(f'Loading references to tool sheds from {config}') for elem in root.findall('tool_shed'): try: name = elem.get('name', None) @@ -44,11 +44,11 @@ class Registry: if name and url: self.tool_sheds[name] = url self.tool_sheds_auth[name] = None - log.debug('Loaded reference to tool shed: %s' % name) + log.debug(f'Loaded reference to tool shed: {name}') if name and url and username and password: self.tool_sheds_auth[name] = AUTH_TUPLE(username, password) except Exception as e: - log.warning('Error loading reference to tool shed "{}", problem: {}'.format(name, str(e))) + log.warning(f'Error loading reference to tool shed "{name}", problem: {str(e)}') def url_auth(self, url): """ @@ -64,5 +64,5 @@ class Registry: shed_url_sans_protocol = remove_protocol_from_tool_shed_url(shed_url) if url_sans_protocol.startswith(shed_url_sans_protocol): return self.tool_sheds_auth[shed_name] - log.debug("Invalid url '%s' received by tool shed registry's url_auth method." % str(url)) + log.debug(f"Invalid url '{str(url)}' received by tool shed registry's url_auth method.") return None diff --git a/lib/galaxy/tool_shed/tools/data_table_manager.py b/lib/galaxy/tool_shed/tools/data_table_manager.py index c5baf9512d6..8914325650b 100644 --- a/lib/galaxy/tool_shed/tools/data_table_manager.py +++ b/lib/galaxy/tool_shed/tools/data_table_manager.py @@ -118,7 +118,7 @@ class ShedToolDataTableManager: def install_tool_data_tables(self, tool_shed_repository, tool_index_sample_files): TOOL_DATA_TABLE_FILE_NAME = 'tool_data_table_conf.xml' - TOOL_DATA_TABLE_FILE_SAMPLE_NAME = '%s.sample' % (TOOL_DATA_TABLE_FILE_NAME) + TOOL_DATA_TABLE_FILE_SAMPLE_NAME = f'{TOOL_DATA_TABLE_FILE_NAME}.sample' SAMPLE_SUFFIX = '.sample' SAMPLE_SUFFIX_OFFSET = -len(SAMPLE_SUFFIX) target_dir, tool_path, relative_target_dir = self.get_target_install_dir(tool_shed_repository) diff --git a/lib/galaxy/tool_shed/tools/tool_validator.py b/lib/galaxy/tool_shed/tools/tool_validator.py index 1d99b6ea774..276de9b1919 100644 --- a/lib/galaxy/tool_shed/tools/tool_validator.py +++ b/lib/galaxy/tool_shed/tools/tool_validator.py @@ -57,14 +57,14 @@ class ToolValidator: sample_found = False for sample_file in sample_files: sample_file_name = basic_util.strip_path(sample_file) - if sample_file_name == '%s.sample' % index_file_name: + if sample_file_name == f'{index_file_name}.sample': options.index_file = index_file_name if options.tool_data_table: options.tool_data_table.missing_index_file = None sample_found = True break if not sample_found: - correction_msg = "This file refers to a file named %s. " % str(index_file_name) + correction_msg = f"This file refers to a file named {str(index_file_name)}. " correction_msg += "Upload a file named %s.sample to the repository to correct this error." % \ str(index_file_name) invalid_files_and_errors_tups.append((tool_config_name, correction_msg)) @@ -84,7 +84,7 @@ class ToolValidator: except KeyError as e: tool = None valid = False - error_message = 'This file requires an entry for "%s" in the tool_data_table_conf.xml file. Upload a file ' % str(e) + error_message = f'This file requires an entry for "{str(e)}" in the tool_data_table_conf.xml file. Upload a file ' error_message += 'named tool_data_table_conf.xml.sample to the repository that includes the required entry to correct ' error_message += 'this error. ' log.exception(error_message) diff --git a/lib/galaxy/tool_shed/util/basic_util.py b/lib/galaxy/tool_shed/util/basic_util.py index 226723ca5f2..b3037315050 100644 --- a/lib/galaxy/tool_shed/util/basic_util.py +++ b/lib/galaxy/tool_shed/util/basic_util.py @@ -77,11 +77,11 @@ def get_env_var_values(install_environment): def get_file_type_str(changeset_revision, file_type): if file_type == 'zip': - file_type_str = '%s.zip' % changeset_revision + file_type_str = f'{changeset_revision}.zip' elif file_type == 'bz2': - file_type_str = '%s.tar.bz2' % changeset_revision + file_type_str = f'{changeset_revision}.tar.bz2' elif file_type == 'gz': - file_type_str = '%s.tar.gz' % changeset_revision + file_type_str = f'{changeset_revision}.tar.gz' else: file_type_str = '' return file_type_str @@ -113,8 +113,8 @@ def remove_dir(dir): def size_string(raw_text, size=MAX_DISPLAY_SIZE): """Return a subset of a string (up to MAX_DISPLAY_SIZE) translated to a safe string for display in a browser.""" if raw_text and len(raw_text) >= size: - large_str = '\nFile contents truncated because file size is larger than maximum viewing size of %s\n' % nice_size(size) - raw_text = '{}{}'.format(raw_text[0:size], large_str) + large_str = f'\nFile contents truncated because file size is larger than maximum viewing size of {nice_size(size)}\n' + raw_text = f'{raw_text[0:size]}{large_str}' return raw_text or '' @@ -141,7 +141,7 @@ def to_html_string(text): try: text = unicodify(text) except UnicodeDecodeError as e: - return "Error decoding string: %s" % str(e) + return f"Error decoding string: {str(e)}" text = str(markupsafe.escape(text)) text = text.replace('\n', '
    ') text = text.replace(' ', '    ') diff --git a/lib/galaxy/tool_shed/util/hg_util.py b/lib/galaxy/tool_shed/util/hg_util.py index 9eef66ab22f..0e0218146ed 100644 --- a/lib/galaxy/tool_shed/util/hg_util.py +++ b/lib/galaxy/tool_shed/util/hg_util.py @@ -26,9 +26,9 @@ def clone_repository(repository_clone_url, repository_file_dir, ctx_rev=None): subprocess.check_output(cmd, stderr=subprocess.STDOUT, stdin=subprocess.DEVNULL) return True, None except Exception as e: - error_message = 'Error cloning repository: %s' % unicodify(e) + error_message = f'Error cloning repository: {unicodify(e)}' if isinstance(e, subprocess.CalledProcessError): - error_message += "\nOutput was:\n%s" % unicodify(e.output) + error_message += f"\nOutput was:\n{unicodify(e.output)}" log.error(error_message) return False, error_message @@ -112,9 +112,9 @@ def pull_repository(repo_path, repository_clone_url, ctx_rev): try: subprocess.check_output(['hg', 'pull', '-r', ctx_rev, repository_clone_url], stderr=subprocess.STDOUT, cwd=repo_path) except Exception as e: - error_message = "Error pulling revision '{}': {}".format(ctx_rev, unicodify(e)) + error_message = f"Error pulling revision '{ctx_rev}': {unicodify(e)}" if isinstance(e, subprocess.CalledProcessError): - error_message += "\nOutput was:\n%s" % unicodify(e.output) + error_message += f"\nOutput was:\n{unicodify(e.output)}" raise Exception(error_message) @@ -174,9 +174,9 @@ def update_repository(repo_path, ctx_rev=None): try: subprocess.check_output(cmd, stderr=subprocess.STDOUT, cwd=repo_path) except Exception as e: - error_message = 'Error updating repository: %s' % unicodify(e) + error_message = f'Error updating repository: {unicodify(e)}' if isinstance(e, subprocess.CalledProcessError): - error_message += "\nOutput was:\n%s" % unicodify(e.output) + error_message += f"\nOutput was:\n{unicodify(e.output)}" raise Exception(error_message) diff --git a/lib/galaxy/tool_shed/util/repository_util.py b/lib/galaxy/tool_shed/util/repository_util.py index 905a4778cc0..dcad79e1ce0 100644 --- a/lib/galaxy/tool_shed/util/repository_util.py +++ b/lib/galaxy/tool_shed/util/repository_util.py @@ -36,7 +36,7 @@ def check_for_updates(app, model, repository_id=None): if ok: success_count += 1 else: - repository_names_not_updated.append('%s' % escape(str(repository.name))) + repository_names_not_updated.append(f'{escape(str(repository.name))}') if updated: updated_count += 1 message = "Checked the status in the tool shed for %d repositories. " % success_count @@ -50,11 +50,11 @@ def check_for_updates(app, model, repository_id=None): check_or_update_tool_shed_status_for_installed_repository(app, repository) if ok: if updated: - message = "The tool shed status for repository %s has been updated." % escape(str(repository.name)) + message = f"The tool shed status for repository {escape(str(repository.name))} has been updated." else: - message = "The status has not changed in the tool shed for repository %s." % escape(str(repository.name)) + message = f"The status has not changed in the tool shed for repository {escape(str(repository.name))}." else: - message = "Unable to retrieve status from the tool shed for repository %s." % escape(str(repository.name)) + message = f"Unable to retrieve status from the tool shed for repository {escape(str(repository.name))}." status = 'error' return message, status @@ -284,7 +284,7 @@ def get_repo_info_tuple_contents(repo_info_tuple): def get_repository_admin_role_name(repository_name, repository_owner): - return '{}_{}_admin'.format(str(repository_name), str(repository_owner)) + return f'{str(repository_name)}_{str(repository_owner)}_admin' def get_repository_and_repository_dependencies_from_repo_info_dict(app, repo_info_dict): diff --git a/lib/galaxy/tool_shed/util/shed_util_common.py b/lib/galaxy/tool_shed/util/shed_util_common.py index 42647404eb4..bbd5d2e45a3 100644 --- a/lib/galaxy/tool_shed/util/shed_util_common.py +++ b/lib/galaxy/tool_shed/util/shed_util_common.py @@ -174,10 +174,10 @@ def set_image_paths(app, text, encoded_repository_id=None, tool_shed_repository= """ if text: if repository_util.is_tool_shed_client(app) and encoded_repository_id: - route_to_images = 'admin_toolshed/static/images/%s' % encoded_repository_id + route_to_images = f'admin_toolshed/static/images/{encoded_repository_id}' elif encoded_repository_id: # We're in the tool shed. - route_to_images = '/repository/static/images/%s' % encoded_repository_id + route_to_images = f'/repository/static/images/{encoded_repository_id}' elif tool_shed_repository and tool_id and tool_version: route_to_images = 'shed_tool_static/{shed}/{owner}/{repo}/{tool}/{version}'.format( shed=tool_shed_repository.tool_shed, diff --git a/lib/galaxy/tool_shed/util/tool_dependency_util.py b/lib/galaxy/tool_shed/util/tool_dependency_util.py index 9de35558110..7105bb92f16 100644 --- a/lib/galaxy/tool_shed/util/tool_dependency_util.py +++ b/lib/galaxy/tool_shed/util/tool_dependency_util.py @@ -28,7 +28,7 @@ def build_tool_dependencies_select_field(app, tool_shed_repository, name, multip if tool_dependency.status in [app.install_model.ToolDependency.installation_status.NEVER_INSTALLED, app.install_model.ToolDependency.installation_status.UNINSTALLED]: continue - option_label = '{} version {}'.format(str(tool_dependency.name), str(tool_dependency.version)) + option_label = f'{str(tool_dependency.name)} version {str(tool_dependency.version)}' option_value = app.security.encode_id(tool_dependency.id) tool_dependencies_select_field.add_option(option_label, option_value) return tool_dependencies_select_field @@ -53,7 +53,7 @@ def create_or_update_tool_dependency(app, tool_shed_repository, name, version, t # Create a new tool_dependency record for the tool_shed_repository. debug_msg = 'Creating a new record for version %s of tool dependency %s for revision %s of repository %s. ' % \ (str(version), str(name), str(tool_shed_repository.changeset_revision), str(tool_shed_repository.name)) - debug_msg += 'The status is being set to %s.' % str(status) + debug_msg += f'The status is being set to {str(status)}.' log.debug(debug_msg) tool_dependency = app.install_model.ToolDependency(tool_shed_repository.id, name, version, type, status) context.add(tool_dependency) @@ -362,10 +362,10 @@ def remove_tool_dependency_installation_directory(dependency_install_dir): shutil.rmtree(dependency_install_dir) removed = True error_message = '' - log.debug("Removed tool dependency installation directory: %s" % str(dependency_install_dir)) + log.debug(f"Removed tool dependency installation directory: {str(dependency_install_dir)}") except Exception as e: removed = False - error_message = "Error removing tool dependency installation directory {}: {}".format(str(dependency_install_dir), str(e)) + error_message = f"Error removing tool dependency installation directory {str(dependency_install_dir)}: {str(e)}" log.warning(error_message) else: removed = True @@ -383,7 +383,7 @@ def set_tool_dependency_attributes(app, tool_dependency, status, error_message=N tool_shed_repository = tool_dependency.tool_shed_repository debug_msg = 'Updating an existing record for version %s of tool dependency %s for revision %s of repository %s ' % \ (str(tool_dependency.version), str(tool_dependency.name), str(tool_shed_repository.changeset_revision), str(tool_shed_repository.name)) - debug_msg += 'by updating the status from {} to {}.'.format(str(tool_dependency.status), str(status)) + debug_msg += f'by updating the status from {str(tool_dependency.status)} to {str(status)}.' log.debug(debug_msg) tool_dependency.status = status sa_session.add(tool_dependency) diff --git a/lib/galaxy/tool_shed/util/tool_util.py b/lib/galaxy/tool_shed/util/tool_util.py index 6614883447c..eb0091cf662 100644 --- a/lib/galaxy/tool_shed/util/tool_util.py +++ b/lib/galaxy/tool_shed/util/tool_util.py @@ -100,11 +100,11 @@ def generate_message_for_invalid_tools(app, invalid_file_tups, repository, metad tip_rev = str(repository.tip()) if not displaying_invalid_tool: if metadata_dict: - message += "Metadata may have been defined for some items in revision '%s'. " % tip_rev - message += "Correct the following problems if necessary and reset metadata.%s" % new_line + message += f"Metadata may have been defined for some items in revision '{tip_rev}'. " + message += f"Correct the following problems if necessary and reset metadata.{new_line}" else: - message += "Metadata cannot be defined for revision '%s' so this revision cannot be automatically " % tip_rev - message += "installed into a local Galaxy instance. Correct the following problems and reset metadata.%s" % new_line + message += f"Metadata cannot be defined for revision '{tip_rev}' so this revision cannot be automatically " + message += f"installed into a local Galaxy instance. Correct the following problems and reset metadata.{new_line}" for itc_tup in invalid_file_tups: tool_file, exception_msg = itc_tup if exception_msg.find('No such file or directory') >= 0: @@ -112,7 +112,7 @@ def generate_message_for_invalid_tools(app, invalid_file_tups, repository, metad missing_file_items = exception_items[7].split('/') missing_file = missing_file_items[-1].rstrip('\'') if missing_file.endswith('.loc'): - sample_ext = '%s.sample' % missing_file + sample_ext = f'{missing_file}.sample' else: sample_ext = missing_file correction_msg = "This file refers to a missing file %s%s%s. " % \ @@ -161,7 +161,7 @@ def handle_missing_index_file(app, tool_path, sample_files, repository_tools_tup # The repository must contain the required xxx.loc.sample file. for sample_file in sample_files: sample_file_name = basic_util.strip_path(sample_file) - if sample_file_name == '%s.sample' % missing_file_name: + if sample_file_name == f'{missing_file_name}.sample': target_path = copy_sample_file(app, os.path.join(tool_path, sample_file)) if options.tool_data_table and options.tool_data_table.missing_index_file: options.tool_data_table.handle_found_index_file(target_path) diff --git a/lib/galaxy/tool_util/client/staging.py b/lib/galaxy/tool_util/client/staging.py index 09494087eb9..51e0df336db 100644 --- a/lib/galaxy/tool_util/client/staging.py +++ b/lib/galaxy/tool_util/client/staging.py @@ -70,7 +70,7 @@ class StagingInterace(metaclass=abc.ABCMeta): else: files_attached[0] = True path = uri[len("file://"):] - upload_payload["__files"]["files_%s|file_data" % index] = self._attach_file(path) + upload_payload["__files"][f"files_{index}|file_data"] = self._attach_file(path) return {"src": "files"} fetch_payload = None @@ -171,10 +171,10 @@ class StagingInterace(metaclass=abc.ABCMeta): if upload_target.composite_data: for i, composite_data in enumerate(upload_target.composite_data): - upload_payload["inputs"]["files_%s|type" % i] = "upload_dataset" + upload_payload["inputs"][f"files_{i}|type"] = "upload_dataset" _attach_file(upload_payload, composite_data, index=i) - self._log("upload_payload is %s" % upload_payload) + self._log(f"upload_payload is {upload_payload}") return self._tools_post(upload_payload, files_attached=files_attached[0]) elif isinstance(upload_target, FileLiteralTarget): # For file literals - take them as is - never convert line endings. diff --git a/lib/galaxy/tool_util/cwl/parser.py b/lib/galaxy/tool_util/cwl/parser.py index 70661aa3bf0..9339a83a2d7 100644 --- a/lib/galaxy/tool_util/cwl/parser.py +++ b/lib/galaxy/tool_util/cwl/parser.py @@ -226,7 +226,7 @@ def check_requirements(rec, tool=True): else: possible = SUPPORTED_WORKFLOW_REQUIREMENTS if r["class"] not in possible: - raise Exception("Unsupported requirement %s" % r["class"]) + raise Exception(f"Unsupported requirement {r['class']}") for d in rec: check_requirements(rec[d], tool=tool) if isinstance(rec, list): @@ -596,7 +596,7 @@ class JobProxy: else: cwl_job.run() if not self._ok: - raise Exception("Final process state not ok, [%s]" % self._process_status) + raise Exception(f"Final process state not ok, [{self._process_status}]") return self._final_output else: return self.cwl_job().collect_outputs(tool_working_directory, rcode) @@ -613,7 +613,7 @@ class JobProxy: def _output_extra_files_dir(self, output_name): output_id = self.output_id(output_name) - return os.path.join(self._job_directory, "outputs", "dataset_%s_files" % output_id) + return os.path.join(self._job_directory, "outputs", f"dataset_{output_id}_files") def output_id(self, output_name): output_id = self._output_dict[output_name]["id"] @@ -797,7 +797,7 @@ class WorkflowProxy: if self.jsonld_id_to_label(input["id"]) == label: return i - raise Exception("Failed to find index for label %s" % label) + raise Exception(f"Failed to find index for label {label}") def jsonld_id_to_label(self, id): if "#" in self.cwl_id: @@ -972,7 +972,7 @@ class InputProxy: cwl_source_id = cwl_input.get("source", None) if cwl_source_id is None: if "valueFrom" not in cwl_input and "default" not in cwl_input: - msg = "Workflow step input must define a source, a valueFrom, or a default value. Obtained [%s]." % cwl_input + msg = f"Workflow step input must define a source, a valueFrom, or a default value. Obtained [{cwl_input}]." raise MessageException(msg) assert cwl_input_id @@ -1118,7 +1118,7 @@ def _outer_field_to_input_instance(field): name, label, description = _field_metadata(field) case_name = "_cwl__type_" - case_label = "Specify Parameter %s As" % label + case_label = f"Specify Parameter {label} As" def value_input(type_description): value_name = "_cwl__value_" @@ -1258,8 +1258,8 @@ class InputInstance: if itemwise and self.array: as_dict = dict( type="repeat", - name="%s_repeat" % self.name, - title="%s" % self.name, + name=f"{self.name}_repeat", + title=f"{self.name}", blocks=[ self.to_dict(itemwise=False) ] diff --git a/lib/galaxy/tool_util/cwl/representation.py b/lib/galaxy/tool_util/cwl/representation.py index 222511983be..8fba8442d75 100644 --- a/lib/galaxy/tool_util/cwl/representation.py +++ b/lib/galaxy/tool_util/cwl/representation.py @@ -126,9 +126,9 @@ def type_descriptions_for_field_types(field_types): try: type_representation_names_for_field_type = CWL_TYPE_TO_REPRESENTATIONS.get(field_type) except TypeError: - raise Exception("Failed to convert field_type %s" % field_type) + raise Exception(f"Failed to convert field_type {field_type}") if type_representation_names_for_field_type is None: - raise Exception("Failed to convert type %s" % field_type) + raise Exception(f"Failed to convert type {field_type}") type_representation_names.update(type_representation_names_for_field_type) type_representations = [] for type_representation in TYPE_REPRESENTATIONS: @@ -316,7 +316,7 @@ def to_cwl_job(tool, param_dict, local_working_directory): type_description_name = type_descriptions[0].name input_json[input_name] = simple_value(input, param_dict[input_name], type_description_name) - log.debug("Galaxy Tool State is CWL State is %s" % input_json) + log.debug(f"Galaxy Tool State is CWL State is {input_json}") return input_json @@ -384,20 +384,20 @@ def to_galaxy_parameters(tool, as_dict): as_dict_value, type(as_dict_value), case_strings ) ) - galaxy_request["%s|_cwl__type_" % input_name] = type_representation_name + galaxy_request[f"{input_name}|_cwl__type_"] = type_representation_name if type_representation_name != "null": current_case_index = input.get_current_case(type_representation_name) current_case_inputs = input.cases[current_case_index].inputs current_case_input = current_case_inputs["_cwl__value_"] galaxy_value = from_simple_value(current_case_input, as_dict_value, type_representation_name) - galaxy_request["%s|_cwl__value_" % input_name] = galaxy_value + galaxy_request[f"{input_name}|_cwl__value_"] = galaxy_value elif as_dict_value is NOT_PRESENT: continue else: galaxy_value = from_simple_value(input, as_dict_value) galaxy_request[input_name] = galaxy_value - log.info("Converted galaxy_request is %s" % galaxy_request) + log.info(f"Converted galaxy_request is {galaxy_request}") return galaxy_request diff --git a/lib/galaxy/tool_util/cwl/runtime_actions.py b/lib/galaxy/tool_util/cwl/runtime_actions.py index 6e37ab204a3..db20529a048 100644 --- a/lib/galaxy/tool_util/cwl/runtime_actions.py +++ b/lib/galaxy/tool_util/cwl/runtime_actions.py @@ -79,7 +79,7 @@ def handle_outputs(job_directory=None): with open(metadata_params_path) as f: metadata_params = json.load(f) except OSError: - raise Exception("Failed to find params.json from metadata directory [%s]" % metadata_directory) + raise Exception(f"Failed to find params.json from metadata directory [{metadata_directory}]") cwl_job_file = os.path.join(job_directory, JOB_JSON_FILE) if not os.path.exists(cwl_job_file): @@ -147,7 +147,7 @@ def handle_outputs(job_directory=None): if secondary_file_basename.startswith(output_basename): secondary_file_name = prefix + secondary_file_basename[len(output_basename):] break - prefix = "^%s" % prefix + prefix = f"^{prefix}" if "." not in output_basename: secondary_file_name = prefix + secondary_file_name break @@ -183,7 +183,7 @@ def handle_outputs(job_directory=None): target_path = job_proxy.output_directory_contents_dir(output_name) file_metadata = move_directory(output, target_path, output_name=output_name) else: - raise Exception("Unknown output type [%s] encountered" % output) + raise Exception(f"Unknown output type [{output}] encountered") provided_metadata[output_name] = file_metadata def handle_known_output_json(output, output_name): @@ -200,7 +200,7 @@ def handle_outputs(job_directory=None): if isinstance(output, dict) and "location" in output: handle_known_output(output, output_name, output_name) elif isinstance(output, dict): - prefix = "%s|__part__|" % output_name + prefix = f"{output_name}|__part__|" for record_key, record_value in output.items(): record_value_output_key = f"{prefix}{record_key}" if isinstance(record_value, dict) and "class" in record_value: @@ -216,7 +216,7 @@ def handle_outputs(job_directory=None): output_path = _possible_uri_to_path(el["location"]) elements.append({"name": str(index), "filename": output_path, "created_from_basename": el["basename"]}) else: - target_path = "{}____{}".format(output_name, str(index)) + target_path = f"{output_name}____{str(index)}" with open(target_path, "w") as f: f.write(json.dumps(el)) elements.append({"name": str(index), "filename": target_path, "ext": "expression.json"}) diff --git a/lib/galaxy/tool_util/cwl/util.py b/lib/galaxy/tool_util/cwl/util.py index c79beb8b1d4..c45bc15fa96 100644 --- a/lib/galaxy/tool_util/cwl/util.py +++ b/lib/galaxy/tool_util/cwl/util.py @@ -45,7 +45,7 @@ def output_properties(path=None, content=None, basename=None, pseduo_location=Fa contents = f.read(1024 * 1024) finally: f.close() - properties["checksum"] = "sha1$%s" % checksum.hexdigest() + properties["checksum"] = f"sha1${checksum.hexdigest()}" properties["size"] = filesize set_basename_and_derived_properties(properties, basename) _handle_pseudo_location(properties, pseduo_location) @@ -78,7 +78,7 @@ def abs_path(path_or_uri, relative_to): def path_or_uri_to_uri(path_or_uri): if "://" not in path_or_uri: - return "file://%s" % path_or_uri + return f"file://{path_or_uri}" else: return path_or_uri @@ -212,7 +212,7 @@ def galactic_job_json( } for secondary_file in secondary_files: secondary_file_path = secondary_file.get("location", None) or secondary_file.get("path", None) - assert secondary_file_path, "Invalid secondaryFile entry found [%s]" % secondary_file + assert secondary_file_path, f"Invalid secondaryFile entry found [{secondary_file}]" full_secondary_file_path = os.path.join(test_data_directory, secondary_file_path) basename = secondary_file.get("basename") or os.path.basename(secondary_file_path) order.append(unicodify(basename)) @@ -371,7 +371,7 @@ class DirectoryUploadTarget: self.tar_path = tar_path def __str__(self): - return "DirectoryUploadTarget[tar_path=%s]" % self.tar_path + return f"DirectoryUploadTarget[tar_path={self.tar_path}]" GalaxyOutput = namedtuple("GalaxyOutput", ["history_id", "history_content_type", "history_content_id", "metadata"]) @@ -386,7 +386,7 @@ def tool_response_to_output(tool_response, history_id, output_id): if output_collection["output_name"] == output_id: return GalaxyOutput(history_id, "dataset_collection", output_collection["id"], None) - raise Exception("Failed to find output with label [%s]" % output_id) + raise Exception(f"Failed to find output with label [{output_id}]") def invocation_to_output(invocation, history_id, output_id): diff --git a/lib/galaxy/tool_util/deps/__init__.py b/lib/galaxy/tool_util/deps/__init__.py index 753ea0cf2a5..8dd0729e0c3 100644 --- a/lib/galaxy/tool_util/deps/__init__.py +++ b/lib/galaxy/tool_util/deps/__init__.py @@ -362,7 +362,7 @@ class CachedDependencyManager(DependencyManager): try: shutil.rmtree(hashed_dependencies_dir) except Exception: - log.warning("Could not delete cached dependencies directory '%s'" % hashed_dependencies_dir) + log.warning(f"Could not delete cached dependencies directory '{hashed_dependencies_dir}'") raise else: log.debug("Cached dependencies directory '%s' already exists, skipping build", hashed_dependencies_dir) diff --git a/lib/galaxy/tool_util/deps/brew_exts.py b/lib/galaxy/tool_util/deps/brew_exts.py index 89ccb84b0ea..1f0c68afb6f 100755 --- a/lib/galaxy/tool_util/deps/brew_exts.py +++ b/lib/galaxy/tool_util/deps/brew_exts.py @@ -96,7 +96,7 @@ class RecipeContext: assert len(parts) == 3 parts = recipe.split("/") username = parts[0] - repository = "homebrew-%s" % parts[1] + repository = f"homebrew-{parts[1]}" path = os.path.join(username, repository) return path @@ -247,7 +247,7 @@ def commit_for_version(recipe_context, package, version): if mapping[0] == version: commit = mapping[1] if commit is None: - raise Exception("Failed to find commit for version %s" % version) + raise Exception(f"Failed to find commit for version {version}") return commit @@ -256,7 +256,7 @@ def print_versioned_deps(recipe_context, recipe, version): for dep in deps: val = dep['name'] if dep['versioned']: - val += "@%s" % dep['version'] + val += f"@{dep['version']}" print(val) @@ -394,7 +394,7 @@ class EnvAction: template = '''${variable}="$$${variable}:${value}"''' return [ self.__eval(template), - "export %s" % self.variable + f"export {self.variable}" ] @@ -477,9 +477,9 @@ def extended_brew_info(recipe): if line.startswith("From: "): extra_info["from_url"] = line[len("From: "):].strip() for dep_type in ["Build", "Required", "Recommended", "Optional"]: - if line.startswith("%s: " % dep_type): - key = "%s_dependencies" % dep_type.lower() - raw_val = line[len("%s: " % dep_type):] + if line.startswith(f"{dep_type}: "): + key = f"{dep_type.lower()}_dependencies" + raw_val = line[len(f"{dep_type}: "):] extra_info[key].extend(raw_val.split(", ")) return extra_info @@ -530,7 +530,7 @@ def ensure_brew_on_path(args): def ensure_on_path(brew): if brew != brew_on_path: - os.environ["PATH"] = "{}:{}".format(os.path.dirname(brew), os.environ["PATH"]) + os.environ["PATH"] = f"{os.path.dirname(brew)}:{os.environ['PATH']}" default_brew_path = os.path.join(DEFAULT_HOMEBREW_ROOT, "bin", "brew") if args and args.brew: diff --git a/lib/galaxy/tool_util/deps/conda_util.py b/lib/galaxy/tool_util/deps/conda_util.py index 573cc43f5f8..bce8668c09d 100644 --- a/lib/galaxy/tool_util/deps/conda_util.py +++ b/lib/galaxy/tool_util/deps/conda_util.py @@ -231,7 +231,7 @@ class CondaContext(installable.InstallableContext): try: if stdout_path: kwds['stdout'] = open(stdout_path, 'w') - cmd_string += " > '%s'" % stdout_path + cmd_string += f" > '{stdout_path}'" conda_exec_home = env['HOME'] = tempfile.mkdtemp(prefix='conda_exec_home_') # We don't want to pollute ~/.conda, which may not even be writable log.debug("Executing command: %s", cmd_string) return self.shell_exec(cmd, env=env, **kwds) @@ -360,26 +360,26 @@ class CondaTarget: def __init__(self, package, version=None, channel=None): if SHELL_UNSAFE_PATTERN.search(package) is not None: - raise ValueError("Invalid package [%s] encountered." % package) + raise ValueError(f"Invalid package [{package}] encountered.") self.package = package if version and SHELL_UNSAFE_PATTERN.search(version) is not None: - raise ValueError("Invalid version [%s] encountered." % version) + raise ValueError(f"Invalid version [{version}] encountered.") self.version = version if channel and SHELL_UNSAFE_PATTERN.search(channel) is not None: - raise ValueError("Invalid version [%s] encountered." % channel) + raise ValueError(f"Invalid version [{channel}] encountered.") self.channel = channel def __str__(self): - attributes = "package=%s" % self.package + attributes = f"package={self.package}" if self.version is not None: attributes = f"{self.package},version={self.version}" else: - attributes = "%s,unversioned" % self.package + attributes = f"{self.package},unversioned" if self.channel: attributes = "%s,channel=%s" % self.channel - return "CondaTarget[%s]" % attributes + return f"CondaTarget[{attributes}]" __repr__ = __str__ @@ -401,7 +401,7 @@ class CondaTarget: if self.version: return f"__{self.package}@{self.version}" else: - return "__%s@_uv_" % (self.package) + return f"__{self.package}@_uv_" def __hash__(self): return hash((self.package, self.version, self.channel)) @@ -433,10 +433,10 @@ def install_conda(conda_context, force_conda_build=False): download_cmd = commands.download_command(conda_link(), to=script_path) install_cmd = ['bash', script_path, '-b', '-p', conda_context.conda_prefix] package_targets = [ - "conda=%s" % CONDA_VERSION, + f"conda={CONDA_VERSION}", ] if force_conda_build or conda_context.use_local: - package_targets.append("conda-build=%s" % CONDA_BUILD_VERSION) + package_targets.append(f"conda-build={CONDA_BUILD_VERSION}") log.info("Installing conda, this may take several minutes.") try: exit_code = conda_context.shell_exec(download_cmd) diff --git a/lib/galaxy/tool_util/deps/container_classes.py b/lib/galaxy/tool_util/deps/container_classes.py index e9cc48803ec..30e2364d853 100644 --- a/lib/galaxy/tool_util/deps/container_classes.py +++ b/lib/galaxy/tool_util/deps/container_classes.py @@ -138,11 +138,11 @@ def preprocess_volumes(volumes_raw_str, container_type): for volume_raw_str in volumes_raw_strs: volume_parts = volume_raw_str.split(":") if len(volume_parts) > 3: - raise Exception("Unparsable volumes string in configuration [%s]" % volumes_raw_str) + raise Exception(f"Unparsable volumes string in configuration [{volumes_raw_str}]") if len(volume_parts) == 3: - volume_parts = ["{}:{}".format(volume_parts[0], volume_parts[1]), volume_parts[2]] + volume_parts = [f"{volume_parts[0]}:{volume_parts[1]}", volume_parts[2]] if len(volume_parts) == 2 and volume_parts[1] not in ("rw", "ro", "default_ro"): - volume_parts = ["{}:{}".format(volume_parts[0], volume_parts[1]), "rw"] + volume_parts = [f"{volume_parts[0]}:{volume_parts[1]}", "rw"] if len(volume_parts) == 1: volume_parts.append("rw") volumes.append(volume_parts) @@ -294,7 +294,7 @@ class DockerContainer(Container, HasDockerLikeVolumes): working_directory = self.job_info.working_directory if not working_directory: - raise Exception("Cannot containerize command [%s] without defined working directory." % working_directory) + raise Exception(f"Cannot containerize command [{working_directory}] without defined working directory.") volumes_raw = self._expand_volume_str(self.destination_info.get("docker_volumes", "$defaults")) preprocessed_volumes_list = preprocess_volumes(volumes_raw, self.container_type) @@ -332,12 +332,13 @@ class DockerContainer(Container, HasDockerLikeVolumes): # https://stackoverflow.com/questions/34228864/stop-and-delete-docker-container-if-its-running # Standard error is: # Error response from daemon: Cannot kill container: 2b0b961527574ebc873256b481bbe72e: No such container: 2b0b961527574ebc873256b481bbe72e - return """ + return f""" _on_exit() {{ - {} &> /dev/null + {kill_command} &> /dev/null }} trap _on_exit 0 -{}\n{}""".format(kill_command, cache_command, run_command) +{cache_command} +{run_command}""" def __cache_from_file_command(self, cached_image_file, docker_host_props): images_cmd = docker_util.build_docker_images_command(truncate=False, **docker_host_props) @@ -356,7 +357,7 @@ trap _on_exit 0 return cache_path if os.path.exists(cache_path) else None def __get_destination_overridable_property(self, name): - prop_name = "docker_%s" % name + prop_name = f"docker_{name}" if prop_name in self.destination_info: return self.destination_info[prop_name] else: @@ -365,7 +366,7 @@ trap _on_exit 0 def docker_cache_path(cache_directory, container_id): file_container_id = container_id.replace("/", "_slash_") - cache_file_name = "docker_%s.tar" % file_container_id + cache_file_name = f"docker_{file_container_id}.tar" return os.path.join(cache_directory, cache_file_name) @@ -396,7 +397,7 @@ class SingularityContainer(Container, HasDockerLikeVolumes): env = [] for pass_through_var in self.tool_info.env_pass_through: - env.append((pass_through_var, "$%s" % pass_through_var)) + env.append((pass_through_var, f"${pass_through_var}")) # Allow destinations to explicitly set environment variables just for # docker container. Better approach is to set for destination and then @@ -408,7 +409,7 @@ class SingularityContainer(Container, HasDockerLikeVolumes): working_directory = self.job_info.working_directory if not working_directory: - raise Exception("Cannot containerize command [%s] without defined working directory." % working_directory) + raise Exception(f"Cannot containerize command [{working_directory}] without defined working directory.") volumes_raw = self._expand_volume_str(self.destination_info.get("singularity_volumes", "$defaults")) preprocessed_volumes_list = preprocess_volumes(volumes_raw, self.container_type) diff --git a/lib/galaxy/tool_util/deps/container_resolvers/__init__.py b/lib/galaxy/tool_util/deps/container_resolvers/__init__.py index ed609dfc15a..654f6b9d994 100644 --- a/lib/galaxy/tool_util/deps/container_resolvers/__init__.py +++ b/lib/galaxy/tool_util/deps/container_resolvers/__init__.py @@ -58,4 +58,4 @@ class ContainerResolver(Dictifiable, metaclass=ABCMeta): return container_description.type in enabled_container_types def __str__(self): - return "%s[]" % self.__class__.__name__ + return f"{self.__class__.__name__}[]" diff --git a/lib/galaxy/tool_util/deps/container_resolvers/explicit.py b/lib/galaxy/tool_util/deps/container_resolvers/explicit.py index 516093701a6..61450baf67a 100644 --- a/lib/galaxy/tool_util/deps/container_resolvers/explicit.py +++ b/lib/galaxy/tool_util/deps/container_resolvers/explicit.py @@ -46,7 +46,7 @@ class ExplicitSingularityContainerResolver(ExplicitContainerResolver): if container_description.type == 'docker': desc_dict = container_description.to_dict() desc_dict['type'] = self.container_type - desc_dict['identifier'] = "docker://%s" % container_description.identifier + desc_dict['identifier'] = f"docker://{container_description.identifier}" container_description = container_description.from_dict(desc_dict) if self._container_type_enabled(container_description, enabled_container_types): return container_description diff --git a/lib/galaxy/tool_util/deps/container_resolvers/mulled.py b/lib/galaxy/tool_util/deps/container_resolvers/mulled.py index dce5f6eb60d..a6d698b4702 100644 --- a/lib/galaxy/tool_util/deps/container_resolvers/mulled.py +++ b/lib/galaxy/tool_util/deps/container_resolvers/mulled.py @@ -113,7 +113,7 @@ def identifier_to_cached_target(identifier, hash_func, namespace=None): image = None prefix = "" if namespace is not None: - prefix = "quay.io/%s/" % namespace + prefix = f"quay.io/{namespace}/" if image_name.startswith(prefix + "mulled-v1-"): if hash_func == "v2": return None @@ -135,7 +135,7 @@ def identifier_to_cached_target(identifier, hash_func, namespace=None): elif version.isdigit(): version_hash, build = None, version elif version: - log.debug("Unparsable mulled image tag encountered [%s]" % version) + log.debug(f"Unparsable mulled image tag encountered [{version}]") image = CachedV2MulledImageMultiTarget(image_name, version_hash, build, identifier) else: @@ -156,7 +156,7 @@ def list_cached_mulled_images_from_path(directory, hash_func="v2"): def get_filter(namespace): - prefix = "quay.io/" if namespace is None else "quay.io/%s" % namespace + prefix = "quay.io/" if namespace is None else f"quay.io/{namespace}" return lambda name: name.startswith(prefix) and name.count("/") == 2 @@ -306,7 +306,7 @@ def targets_to_mulled_name(targets, hash_func, namespace, resolution_cache=None, elif hash_func == "v1": base_image_name = v1_image_name(targets) else: - raise Exception("Unimplemented mulled hash_func [%s]" % hash_func) + raise Exception(f"Unimplemented mulled hash_func [{hash_func}]") cache_key = f"ns[{namespace}]__{hash_func}__{base_image_name}" if cache_key in unresolved_cache: @@ -321,7 +321,7 @@ def targets_to_mulled_name(targets, hash_func, namespace, resolution_cache=None, assert hash_func != "v1" # base_image_name of form :, expand tag # to include build number in tag. - name = "{}:{}".format(base_image_name.split(":")[0], tag) + name = f"{base_image_name.split(':')[0]}:{tag}" else: # base_image_name of form , simply add build number # as tag to fully qualify image. @@ -352,7 +352,7 @@ class CliContainerResolver(ContainerResolver): @cli_available.setter def cli_available(self, value): if not value: - log.info('{} CLI not available, cannot list or pull images in Galaxy process. Does not impact kubernetes.'.format(self.cli)) + log.info(f'{self.cli} CLI not available, cannot list or pull images in Galaxy process. Does not impact kubernetes.') self._cli_available = value @@ -386,7 +386,7 @@ class CachedMulledDockerContainerResolver(CliContainerResolver): return docker_cached_container_description(targets, self.namespace, hash_func=self.hash_func, shell=self.shell, resolution_cache=resolution_cache) def __str__(self): - return "CachedMulledDockerContainerResolver[namespace=%s]" % self.namespace + return f"CachedMulledDockerContainerResolver[namespace={self.namespace}]" class CachedMulledSingularityContainerResolver(SingularityCliContainerResolver): @@ -406,7 +406,7 @@ class CachedMulledSingularityContainerResolver(SingularityCliContainerResolver): return singularity_cached_container_description(targets, self.cache_directory, hash_func=self.hash_func, shell=self.shell) def __str__(self): - return "CachedMulledSingularityContainerResolver[cache_directory=%s]" % self.cache_directory + return f"CachedMulledSingularityContainerResolver[cache_directory={self.cache_directory}]" class MulledDockerContainerResolver(CliContainerResolver): @@ -487,7 +487,7 @@ class MulledDockerContainerResolver(CliContainerResolver): return container_description def __str__(self): - return "MulledDockerContainerResolver[namespace=%s]" % self.namespace + return f"MulledDockerContainerResolver[namespace={self.namespace}]" class MulledSingularityContainerResolver(SingularityCliContainerResolver, MulledDockerContainerResolver): @@ -517,7 +517,7 @@ class MulledSingularityContainerResolver(SingularityCliContainerResolver, Mulled shell(cmds=cmds) def __str__(self): - return "MulledSingularityContainerResolver[namespace=%s]" % self.namespace + return f"MulledSingularityContainerResolver[namespace={self.namespace}]" class BuildMulledDockerContainerResolver(CliContainerResolver): @@ -564,7 +564,7 @@ class BuildMulledDockerContainerResolver(CliContainerResolver): return involucro_context def __str__(self): - return "BuildDockerContainerResolver[namespace=%s]" % self.namespace + return f"BuildDockerContainerResolver[namespace={self.namespace}]" class BuildMulledSingularityContainerResolver(SingularityCliContainerResolver): @@ -612,7 +612,7 @@ class BuildMulledSingularityContainerResolver(SingularityCliContainerResolver): return involucro_context def __str__(self): - return "BuildSingularityContainerResolver[cache_directory=%s]" % self.cache_directory + return f"BuildSingularityContainerResolver[cache_directory={self.cache_directory}]" def mulled_targets(tool_info): diff --git a/lib/galaxy/tool_util/deps/containers.py b/lib/galaxy/tool_util/deps/containers.py index 63b06f385f8..7c5d1032177 100644 --- a/lib/galaxy/tool_util/deps/containers.py +++ b/lib/galaxy/tool_util/deps/containers.py @@ -129,9 +129,9 @@ class ContainerFinder: def __overridden_container_id(self, container_type, destination_info): if not self.__container_type_enabled(container_type, destination_info): return None - if "%s_container_id_override" % container_type in destination_info: - return destination_info.get("%s_container_id_override" % container_type) - if "%s_image_override" % container_type in destination_info: + if f"{container_type}_container_id_override" in destination_info: + return destination_info.get(f"{container_type}_container_id_override") + if f"{container_type}_image_override" in destination_info: return self.__build_container_id_from_parts(container_type, destination_info, mode="override") def __build_container_id_from_parts(self, container_type, destination_info, mode): @@ -152,13 +152,13 @@ class ContainerFinder: def __default_container_id(self, container_type, destination_info): if not self.__container_type_enabled(container_type, destination_info): return None - key = "%s_default_container_id" % container_type + key = f"{container_type}_default_container_id" # Also allow docker_image... if key not in destination_info: - key = "%s_image" % container_type + key = f"{container_type}_image" if key in destination_info: return destination_info.get(key) - elif "%s_image_default" % container_type in destination_info: + elif f"{container_type}_image_default" in destination_info: return self.__build_container_id_from_parts(container_type, destination_info, mode="default") return None @@ -174,7 +174,7 @@ class ContainerFinder: return CONTAINER_CLASSES[container_type](container_id, self.app_info, tool_info, destination_info, job_info, container_description) def __container_type_enabled(self, container_type, destination_info): - return asbool(destination_info.get("%s_enabled" % container_type, False)) + return asbool(destination_info.get(f"{container_type}_enabled", False)) class NullContainerFinder: diff --git a/lib/galaxy/tool_util/deps/docker_util.py b/lib/galaxy/tool_util/deps/docker_util.py index be78daf3afd..b9b572aa199 100644 --- a/lib/galaxy/tool_util/deps/docker_util.py +++ b/lib/galaxy/tool_util/deps/docker_util.py @@ -234,7 +234,7 @@ def parse_port_text(port_text): ports = {} for line in port_text.strip().split('\n'): if " -> " not in line: - raise Exception("Cannot parse host and port from line [%s]" % line) + raise Exception(f"Cannot parse host and port from line [{line}]") tool, host = line.split(" -> ", 1) hostname, port = host.rsplit(':', 1) if hostname == '::': diff --git a/lib/galaxy/tool_util/deps/installable.py b/lib/galaxy/tool_util/deps/installable.py index 85367a6bbc5..c03503a4ee5 100644 --- a/lib/galaxy/tool_util/deps/installable.py +++ b/lib/galaxy/tool_util/deps/installable.py @@ -48,11 +48,11 @@ def ensure_installed(installable_context, install_func, auto_init): if installable_context.can_install(): if install_func(installable_context): installed = False - log.warning("%s installation requested and failed." % desc) + log.warning(f"{desc} installation requested and failed.") else: installed = installable_context.is_installed() if not installed: - log.warning("%s installation requested, seemed to succeed, but not found." % desc) + log.warning(f"{desc} installation requested, seemed to succeed, but not found.") else: installed = False else: @@ -72,4 +72,4 @@ def ensure_installed(installable_context, install_func, auto_init): else: return _check() except FileLockException: - raise Exception("Failed to get file lock for %s" % os.path.join(parent_path, desc.lower())) + raise Exception(f"Failed to get file lock for {os.path.join(parent_path, desc.lower())}") diff --git a/lib/galaxy/tool_util/deps/mulled/get_tests.py b/lib/galaxy/tool_util/deps/mulled/get_tests.py index a0cf52e5e51..ae6bc383f3a 100644 --- a/lib/galaxy/tool_util/deps/mulled/get_tests.py +++ b/lib/galaxy/tool_util/deps/mulled/get_tests.py @@ -87,14 +87,14 @@ def get_anaconda_url(container, anaconda_channel='bioconda'): Download tarball from anaconda for test """ name = split_container_name(container) # list consisting of [name, version, (build, if present)] - return "https://anaconda.org/{}/{}/{}/download/linux-64/{}.tar.bz2".format(anaconda_channel, name[0], name[1], '-'.join(name)) + return f"https://anaconda.org/{anaconda_channel}/{name[0]}/{name[1]}/download/linux-64/{'-'.join(name)}.tar.bz2" def prepend_anaconda_url(url): """ Take a partial url and prepend 'https://anaconda.org' """ - return 'https://anaconda.org%s' % url + return f'https://anaconda.org{url}' def get_test_from_anaconda(url): @@ -165,14 +165,14 @@ def get_alternative_versions(filepath, filename, recipes_path=None, github_repo= Return files that match ``filepath/*/filename`` in the bioconda-recipes repository """ if recipes_path: - return [n.replace('%s/' % recipes_path, '') for n in glob(f'{recipes_path}/{filepath}/*/{filename}')] + return [n.replace(f'{recipes_path}/', '') for n in glob(f'{recipes_path}/{filepath}/*/{filename}')] # else use the GitHub API: versions = [] r = json.loads(requests.get(f'https://api.github.com/repos/{github_repo}/contents/{filepath}').text) for subfile in r: if subfile['type'] == 'dir': - if requests.get('https://raw.githubusercontent.com/{}/master/{}/{}'.format(github_repo, subfile['path'], filename)).status_code == 200: - versions.append('{}/{}'.format(subfile['path'], filename)) + if requests.get(f"https://raw.githubusercontent.com/{github_repo}/master/{subfile['path']}/{filename}").status_code == 200: + versions.append(f"{subfile['path']}/{filename}") return versions @@ -195,23 +195,23 @@ def deep_test_search(container, recipes_path=None, anaconda_channel='bioconda', """ name = split_container_name(container) for f in [ - (get_commands_from_yaml, open_recipe_file, ('recipes/{}/{}/meta.yaml'.format(name[0], name[1]), recipes_path, github_repo), container), - (get_run_test, open_recipe_file, ('recipes/{}/{}/run_test.sh'.format(name[0], name[1]), recipes_path, github_repo), container), - (get_commands_from_yaml, open_recipe_file, ('recipes/%s/meta.yaml' % name[0], recipes_path, github_repo), container), - (get_run_test, open_recipe_file, ('recipes/%s/run_test.sh' % name[0], recipes_path, github_repo), container), + (get_commands_from_yaml, open_recipe_file, (f'recipes/{name[0]}/{name[1]}/meta.yaml', recipes_path, github_repo), container), + (get_run_test, open_recipe_file, (f'recipes/{name[0]}/{name[1]}/run_test.sh', recipes_path, github_repo), container), + (get_commands_from_yaml, open_recipe_file, (f'recipes/{name[0]}/meta.yaml', recipes_path, github_repo), container), + (get_run_test, open_recipe_file, (f'recipes/{name[0]}/run_test.sh', recipes_path, github_repo), container), (get_test_from_anaconda, get_anaconda_url, (container, anaconda_channel), container), ]: result = try_a_func(*f) if result: return result - versions = get_alternative_versions('recipes/%s' % name[0], 'meta.yaml', recipes_path, github_repo) + versions = get_alternative_versions(f'recipes/{name[0]}', 'meta.yaml', recipes_path, github_repo) for version in versions: result = try_a_func(get_commands_from_yaml, open_recipe_file, (version, recipes_path, github_repo), container) if result: return result - versions = get_alternative_versions('recipes/%s' % name[0], 'run_test.sh', recipes_path, github_repo) + versions = get_alternative_versions(f'recipes/{name[0]}', 'run_test.sh', recipes_path, github_repo) for version in versions: result = try_a_func(get_run_test, open_recipe_file, (version, recipes_path, github_repo), container) if result: @@ -246,7 +246,7 @@ def hashed_test_search(container, recipes_path=None, deep=False, anaconda_channe """ package_tests = {'commands': [], 'imports': [], 'container': container, 'import_lang': 'python -c'} - githubpage = requests.get('https://raw.githubusercontent.com/BioContainers/multi-package-containers/master/combinations/%s.tsv' % container) + githubpage = requests.get(f'https://raw.githubusercontent.com/BioContainers/multi-package-containers/master/combinations/{container}.tsv') if githubpage.status_code == 200: packages = githubpage.text.split(',') # get names of packages from github packages = [package.split('=') for package in packages] @@ -255,22 +255,21 @@ def hashed_test_search(container, recipes_path=None, deep=False, anaconda_channe containers = [] for package in packages: - r = requests.get("https://anaconda.org/bioconda/%s/files" % package[0]) + r = requests.get(f"https://anaconda.org/bioconda/{package[0]}/files") p = '-'.join(package) for line in r.text.split('\n'): if p in line: build = line.split(p)[1].split('.tar.bz2')[0] if build == "": - containers.append('{}:{}'.format(package[0], package[1])) + containers.append(f'{package[0]}:{package[1]}') else: - containers.append('%s:%s-%s' % - (package[0], package[1], build)) + containers.append(f'{package[0]}:{package[1]}-{build}') break for container in containers: tests = main_test_search(container, recipes_path, deep, anaconda_channel, github_repo) package_tests['commands'] += tests.get('commands', []) # not a very nice solution but probably the simplest for imp in tests.get('imports', []): - package_tests['imports'].append("{} 'import {}'".format(tests['import_lang'], imp)) + package_tests['imports'].append(f"{tests['import_lang']} 'import {imp}'") return package_tests diff --git a/lib/galaxy/tool_util/deps/mulled/mulled_build.py b/lib/galaxy/tool_util/deps/mulled/mulled_build.py index e5e1f21e40f..9ebedecb172 100644 --- a/lib/galaxy/tool_util/deps/mulled/mulled_build.py +++ b/lib/galaxy/tool_util/deps/mulled/mulled_build.py @@ -78,9 +78,9 @@ From: %(base_image)s def involucro_link(): if IS_OS_X: - url = "https://github.com/mvdbeek/involucro/releases/download/v%s/involucro.darwin" % INVOLUCRO_VERSION + url = f"https://github.com/mvdbeek/involucro/releases/download/v{INVOLUCRO_VERSION}/involucro.darwin" else: - url = "https://github.com/involucro/involucro/releases/download/v%s/involucro" % INVOLUCRO_VERSION + url = f"https://github.com/involucro/involucro/releases/download/v{INVOLUCRO_VERSION}/involucro" return url @@ -125,7 +125,7 @@ def get_affected_packages(args): """ recipes_dir = args.recipes_dir hours = args.diff_hours - cmd = ['git', 'log', '--diff-filter=ACMRTUXB', '--name-only', '--pretty=""', '--since="%s hours ago"' % hours] + cmd = ['git', 'log', '--diff-filter=ACMRTUXB', '--name-only', '--pretty=""', f'--since="{hours} hours ago"'] changed_files = unicodify(subprocess.check_output(cmd, cwd=recipes_dir)).splitlines() pkg_list = {x for x in changed_files if x.startswith('recipes/') and x.endswith('meta.yaml')} for pkg in pkg_list: @@ -139,7 +139,7 @@ def conda_versions(pkg_name, file_name): ret = list() for pkg in j['packages'].values(): if pkg['name'] == pkg_name: - ret.append('{}--{}'.format(pkg['version'], pkg['build'])) + ret.append(f"{pkg['version']}--{pkg['build']}") return ret @@ -206,7 +206,7 @@ def mull_targets( target_tag = None if ":" in repo_template_kwds["image"]: image_name_parts = repo_template_kwds["image"].split(":") - assert len(image_name_parts) == 2, ": not allowed in image name [%s]" % repo_template_kwds["image"] + assert len(image_name_parts) == 2, f": not allowed in image name [{repo_template_kwds['image']}]" target_tag = image_name_parts[1] if tags and (target_tag is None or target_tag in tags): @@ -224,11 +224,11 @@ def mull_targets( target_str = ",".join(map(conda_build_target_str, targets)) bind_str = ",".join(binds) involucro_args = [ - '-f', '%s/invfile.lua' % DIRNAME, - '-set', "CHANNELS=%s" % channels, - '-set', "TARGETS=%s" % target_str, - '-set', "REPO=%s" % repo, - '-set', "BINDS=%s" % bind_str, + '-f', f'{DIRNAME}/invfile.lua', + '-set', f"CHANNELS={channels}", + '-set', f"TARGETS={target_str}", + '-set', f"REPO={repo}", + '-set', f"BINDS={bind_str}", ] dest_base_image = None if base_image: @@ -239,19 +239,19 @@ def mull_targets( dest_base_image = base_image_for_targets(targets) if dest_base_image: - involucro_args.extend(["-set", "DEST_BASE_IMAGE=%s" % dest_base_image]) + involucro_args.extend(["-set", f"DEST_BASE_IMAGE={dest_base_image}"]) if CONDA_IMAGE: - involucro_args.extend(["-set", "CONDA_IMAGE=%s" % CONDA_IMAGE]) + involucro_args.extend(["-set", f"CONDA_IMAGE={CONDA_IMAGE}"]) if verbose: involucro_args.extend(["-set", "VERBOSE=1"]) if singularity: singularity_image_name = repo_template_kwds['image'] involucro_args.extend(["-set", "SINGULARITY=1"]) - involucro_args.extend(["-set", "SINGULARITY_IMAGE_NAME=%s" % singularity_image_name]) - involucro_args.extend(["-set", "SINGULARITY_IMAGE_DIR=%s" % singularity_image_dir]) + involucro_args.extend(["-set", f"SINGULARITY_IMAGE_NAME={singularity_image_name}"]) + involucro_args.extend(["-set", f"SINGULARITY_IMAGE_DIR={singularity_image_dir}"]) involucro_args.extend(["-set", f"USER_ID={os.getuid()}:{os.getgid()}"]) if test: - involucro_args.extend(["-set", "TEST=%s" % test]) + involucro_args.extend(["-set", f"TEST={test}"]) if conda_version is not None: verbose = "--verbose" if verbose else "--quiet" involucro_args.extend(["-set", f"PREINSTALL=conda install {verbose} --yes conda={conda_version}"]) @@ -267,7 +267,7 @@ def mull_targets( test_bind.append(test_file) if test_bind: involucro_args.insert(6, '-set') - involucro_args.insert(7, "TEST_BINDS=%s" % ",".join(test_bind)) + involucro_args.insert(7, f"TEST_BINDS={','.join(test_bind)}") cmd = involucro_context.build_command(involucro_args) print('Executing: ' + ' '.join(shlex.quote(_) for _ in cmd)) if dry_run: @@ -324,7 +324,7 @@ class InvolucroContext(installable.InstallableContext): self.verbose = verbose def build_command(self, involucro_args): - return [self.involucro_bin, "-v=%s" % self.verbose] + involucro_args + return [self.involucro_bin, f"-v={self.verbose}"] + involucro_args def exec_command(self, involucro_args): cmd = self.build_command(involucro_args) diff --git a/lib/galaxy/tool_util/deps/mulled/mulled_build_channel.py b/lib/galaxy/tool_util/deps/mulled/mulled_build_channel.py index 2651e32f071..f610567feab 100644 --- a/lib/galaxy/tool_util/deps/mulled/mulled_build_channel.py +++ b/lib/galaxy/tool_util/deps/mulled/mulled_build_channel.py @@ -43,10 +43,10 @@ def _fetch_repo_data(args): platform_tag = 'osx-64' if sys.platform == 'darwin' else 'linux-64' subprocess.check_call([ 'wget', '--quiet', f'https://conda.anaconda.org/{channel}/{platform_tag}/repodata.json.bz2', - '-O', '%s.bz2' % repo_data + '-O', f'{repo_data}.bz2' ]) subprocess.check_call([ - 'bzip2', '-d', '%s.bz2' % repo_data + 'bzip2', '-d', f'{repo_data}.bz2' ]) return repo_data diff --git a/lib/galaxy/tool_util/deps/mulled/mulled_build_files.py b/lib/galaxy/tool_util/deps/mulled/mulled_build_files.py index 489c87d10f0..f21afeea3a9 100644 --- a/lib/galaxy/tool_util/deps/mulled/mulled_build_files.py +++ b/lib/galaxy/tool_util/deps/mulled/mulled_build_files.py @@ -84,7 +84,7 @@ def tuple_from_header(header): for field in KNOWN_FIELDS: if field not in fields: fields.append(field) - return collections.namedtuple("_Line", "%s" % " ".join(fields)) + return collections.namedtuple("_Line", f"{' '.join(fields)}") def line_to_targets(line_str, line_tuple): diff --git a/lib/galaxy/tool_util/deps/mulled/mulled_list.py b/lib/galaxy/tool_util/deps/mulled/mulled_list.py index 0a87698b9a1..54fb54c851e 100644 --- a/lib/galaxy/tool_util/deps/mulled/mulled_list.py +++ b/lib/galaxy/tool_util/deps/mulled/mulled_list.py @@ -26,10 +26,10 @@ def get_quay_containers(repository='biocontainers'): for repo in repos: logging.info(repo) tags_response = requests.get( - "{}/{}/{}".format(QUAY_API_ENDPOINT, repository, repo['name'])) + f"{QUAY_API_ENDPOINT}/{repository}/{repo['name']}") tags = tags_response.json()['tags'] for tag in tags: - containers.append('{}:{}'.format(repo['name'], tag)) + containers.append(f"{repo['name']}:{tag}") return containers @@ -61,7 +61,7 @@ def get_conda_envs(filepath): """ Get list of already existing envs """ - return [n.split('__')[-1].replace('@', ':') for n in glob('%s/*' % filepath)] + return [n.split('__')[-1].replace('@', ':') for n in glob(f'{filepath}/*')] def get_missing_containers(quay_list, singularity_list, blocklist_file=None): @@ -124,7 +124,7 @@ def main(): if args.output: with open(args.output, 'a') as f: for container in containers: - f.write('%s\n' % container) + f.write(f'{container}\n') else: print(containers) diff --git a/lib/galaxy/tool_util/deps/mulled/mulled_search.py b/lib/galaxy/tool_util/deps/mulled/mulled_search.py index cf83a945235..b72d8f11ffe 100755 --- a/lib/galaxy/tool_util/deps/mulled/mulled_search.py +++ b/lib/galaxy/tool_util/deps/mulled/mulled_search.py @@ -77,7 +77,7 @@ class QuaySearch(): # get all repositories with suggested keywords for suggestion in suggestions: - search_string = "*%s*" % suggestion + search_string = f"*{suggestion}*" query = QueryParser( "title", self.index.schema).parse(search_string) results_tmp = searcher.search(query) @@ -126,7 +126,7 @@ class CondaSearch(): search_string, use_exception_handler=True) if exit_code != 0: - logging.info('Search failed with: %s' % err) + logging.info(f'Search failed with: {err}') return [] return [{'package': n.split()[0], 'version': n.split()[1], 'build': n.split()[2]} for n in raw_out.split('\n')[2:-1]] @@ -141,7 +141,7 @@ class GitHubSearch(): Takes search_string variable and return results from the bioconda-recipes github repository in JSON format """ response = requests.get( - "https://api.github.com/search/code?q=%s+in:path+repo:bioconda/bioconda-recipes+path:recipes" % search_string).json() + f"https://api.github.com/search/code?q={search_string}+in:path+repo:bioconda/bioconda-recipes+path:recipes").json() return response def process_json(self, json, search_string): @@ -160,7 +160,7 @@ class GitHubSearch(): """ Check if a recipe exists in bioconda-recipes which matches search_string exactly """ - if requests.get("https://api.github.com/repos/bioconda/bioconda-recipes/contents/recipes/%s" % search_string).status_code == 200: + if requests.get(f"https://api.github.com/repos/bioconda/bioconda-recipes/contents/recipes/{search_string}").status_code == 200: return True else: return False @@ -184,7 +184,7 @@ def get_package_hash(packages, versions): if versions: hash_results['version_hash'] = package_hash.split(':')[1] - r = requests.get("https://quay.io/api/v1/repository/biocontainers/%s" % hash_results['package_hash']) + r = requests.get(f"https://quay.io/api/v1/repository/biocontainers/{hash_results['package_hash']}") if r.status_code == 200: hash_results['container_present'] = True if versions: # now test if the version hash is listed in the repository tags @@ -234,12 +234,12 @@ def readable_output(json, organization='biocontainers', channel='bioconda'): (organization, result['package'], result['version'])]) # NOT a real solution for results in json.get('conda', {}).values(): for result in results: - lines.append(['conda', result['package'], '{}--{}'.format(result['version'], result['build']), - 'conda install -c {} {}={}={}\n'.format(channel, result['package'], result['version'], result['build'])]) + lines.append(['conda', result['package'], f"{result['version']}--{result['build']}", + f"conda install -c {channel} {result['package']}={result['version']}={result['build']}\n"]) for results in json.get('singularity', {}).values(): for result in results: lines.append(['singularity', result['package'], result['version'], - 'wget https://depot.galaxyproject.org/singularity/{}:{}\n'.format(result['package'], result['version'])]) + f"wget https://depot.galaxyproject.org/singularity/{result['package']}:{result['version']}\n"]) col_width0, col_width1, col_width2 = (max(len( line[n]) for line in lines) + 2 for n in (0, 1, 2)) # def max col widths for the output @@ -256,7 +256,7 @@ def readable_output(json, organization='biocontainers', channel='bioconda'): lines = [['QUERY', 'LOCATION\n']] for recipe in json['github_recipe_present']['recipes']: lines.append( - [recipe, "https://api.github.com/repos/bioconda/bioconda-recipes/contents/recipes/%s\n" % recipe]) + [recipe, f"https://api.github.com/repos/bioconda/bioconda-recipes/contents/recipes/{recipe}\n"]) col_width0 = max(len(line[0]) for line in lines) + 2 @@ -272,7 +272,7 @@ def readable_output(json, organization='biocontainers', channel='bioconda'): for search_string, results in json.get('github', {}).items(): for result in results: lines.append([search_string, result['name'], - 'https://github.com/bioconda/bioconda-recipes/tree/master/%s\n' % result['path']]) + f"https://github.com/bioconda/bioconda-recipes/tree/master/{result['path']}\n"]) # def max col widths for the output col_width0, col_width1 = ( @@ -284,7 +284,7 @@ def readable_output(json, organization='biocontainers', channel='bioconda'): def deps_error_message(package): - return "Required dependency [%s] is not installed. Run 'pip install galaxy-tool-util[mulled]'." % package + return f"Required dependency [{package}] is not installed. Run 'pip install galaxy-tool-util[mulled]'." def main(argv=None): diff --git a/lib/galaxy/tool_util/deps/mulled/mulled_update_singularity_containers.py b/lib/galaxy/tool_util/deps/mulled/mulled_update_singularity_containers.py index 484a5a00565..cc52d529e27 100644 --- a/lib/galaxy/tool_util/deps/mulled/mulled_update_singularity_containers.py +++ b/lib/galaxy/tool_util/deps/mulled/mulled_update_singularity_containers.py @@ -30,7 +30,7 @@ def docker_to_singularity(container, installation, filepath, no_sudo=False): check_output(cmd.insert(0, 'sudo'), stderr=subprocess.STDOUT) check_output(['sudo', 'rm', '-rf', '/root/.singularity/docker/'], stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: - raise Exception("Docker to Singularity conversion failed.\nOutput was:\n%s" % unicodify(e.output)) + raise Exception(f"Docker to Singularity conversion failed.\nOutput was:\n{unicodify(e.output)}") def singularity_container_test(tests, installation, filepath): @@ -145,7 +145,7 @@ def container_testing(args=None): containers = get_list_from_file(args['container_list']) else: # if no containers are specified, test everything in the filepath containers = [n.split(args['filepath'])[1] - for n in glob('%s*' % args['filepath'])] + for n in glob(f"{args['filepath']}*")] with open(args['logfile'], 'w') as f: f.write("SINGULARITY CONTAINERS GENERATED:") @@ -162,16 +162,16 @@ def container_testing(args=None): f.write('\n\tTEST PASSED:') for container in test_results['passed']: - f.write('\n\t\t%s' % container) + f.write(f'\n\t\t{container}') f.write('\n\tTEST FAILED:') for container in test_results['failed']: - f.write('\n\t\t%s' % container['container']) + f.write(f"\n\t\t{container['container']}") for error in container['errors']: f.write('\n\t\t\tCOMMAND: {}\n\t\t\t\tERROR:{}'.format(error.get( 'command', 'import' + error.get('import', 'nothing found')), error['output'])) f.write('\n\tNO TEST AVAILABLE:') for container in test_results['notest']: - f.write('\n\t\t%s' % container) + f.write(f'\n\t\t{container}') if __name__ == "__main__": diff --git a/lib/galaxy/tool_util/deps/mulled/util.py b/lib/galaxy/tool_util/deps/mulled/util.py index 59c3c14cfa1..d73fac28065 100644 --- a/lib/galaxy/tool_util/deps/mulled/util.py +++ b/lib/galaxy/tool_util/deps/mulled/util.py @@ -22,7 +22,7 @@ QUAY_IO_TIMEOUT = 10 def create_repository(namespace, repo_name, oauth_token): assert oauth_token - headers = {'Authorization': 'Bearer %s' % oauth_token} + headers = {'Authorization': f'Bearer {oauth_token}'} data = { "repository": repo_name, "namespace": namespace, @@ -40,7 +40,7 @@ def quay_versions(namespace, pkg_name, session=None): return [] if 'tags' not in data: - raise Exception("Unexpected response from quay.io - no tags description found [%s]" % data) + raise Exception(f"Unexpected response from quay.io - no tags description found [{data}]") return [tag for tag in data['tags'].keys() if tag != 'latest'] @@ -85,7 +85,7 @@ def mulled_tags_for(namespace, image, tag_prefix=None, resolution_cache=None, se # Following check is pretty expensive against biocontainers... don't even bother doing it # if can't cache the response. if not _namespace_has_repo_name(namespace, image, resolution_cache): - log.info("skipping mulled_tags_for [%s] no repository" % image) + log.info(f"skipping mulled_tags_for [{image}] no repository") return [] cache_key = "galaxy.tool_util.deps.container_resolvers.mulled.util:tag_cache" @@ -167,10 +167,10 @@ def build_target(package_name, version=None, build=None, tag=None): def conda_build_target_str(target): rval = target.package_name if target.version: - rval += "=%s" % target.version + rval += f"={target.version}" if target.build: - rval += "=%s" % target.build + rval += f"={target.build}" return rval @@ -184,9 +184,9 @@ def _simple_image_name(targets, image_build=None): # Special case image_build == "0", which has been built without a suffix print("WARNING: Hard-coding image build instead of using Conda build - this is not recommended.") build = image_build - suffix += ":%s" % target.version + suffix += f":{target.version}" if build is not None: - suffix += "--%s" % build + suffix += f"--{build}" return f"{target.package_name}{suffix}" @@ -223,7 +223,7 @@ def v1_image_name(targets, image_build=None, name_override=None): requirements_buffer = "\n".join(map(conda_build_target_str, targets_order)) m = hashlib.sha1() m.update(requirements_buffer.encode()) - suffix = "" if not image_build else ":%s" % image_build + suffix = "" if not image_build else f":{image_build}" return f"mulled-v1-{m.hexdigest()}{suffix}" @@ -284,7 +284,7 @@ def v2_image_name(targets, image_build=None, name_override=None): build_suffix = "" elif version_hash_str: # tagged verson is - - build_suffix = "-%s" % image_build + build_suffix = f"-{image_build}" else: # tagged version is simply the build build_suffix = image_build diff --git a/lib/galaxy/tool_util/deps/resolvers/__init__.py b/lib/galaxy/tool_util/deps/resolvers/__init__.py index 4b83b644213..1553e577f76 100644 --- a/lib/galaxy/tool_util/deps/resolvers/__init__.py +++ b/lib/galaxy/tool_util/deps/resolvers/__init__.py @@ -319,7 +319,7 @@ class NullDependency(Dependency): """ Return a message describing this dependency """ - return "Dependency %s not found." % self.name + return f"Dependency {self.name} not found." def shell_commands(self): return None diff --git a/lib/galaxy/tool_util/deps/resolvers/brewed_tool_shed_packages.py b/lib/galaxy/tool_util/deps/resolvers/brewed_tool_shed_packages.py index 7b0d7d1e316..b4316894b08 100644 --- a/lib/galaxy/tool_util/deps/resolvers/brewed_tool_shed_packages.py +++ b/lib/galaxy/tool_util/deps/resolvers/brewed_tool_shed_packages.py @@ -68,7 +68,7 @@ class HomebrewToolShedDependencyResolver( try: raw_dependencies = RawDependencies(tool_dependencies_path) except Exception: - log.debug("Failed to parse dependencies in file %s" % tool_dependencies_path) + log.debug(f"Failed to parse dependencies in file {tool_dependencies_path}") return NullDependency(version=version, name=name) raw_dependency = raw_dependencies.find(name, version) diff --git a/lib/galaxy/tool_util/deps/resolvers/conda.py b/lib/galaxy/tool_util/deps/resolvers/conda.py index 98e9be264ac..3c035648adb 100644 --- a/lib/galaxy/tool_util/deps/resolvers/conda.py +++ b/lib/galaxy/tool_util/deps/resolvers/conda.py @@ -160,9 +160,9 @@ class CondaDependencyResolver(DependencyResolver, MultipleDependencyResolver, Li final_return_code = 0 for env, return_code in zip(environments, return_codes): if return_code == 0: - log.debug("Conda environment '%s' successfully removed." % env) + log.debug(f"Conda environment '{env}' successfully removed.") else: - log.debug("Conda environment '%s' could not be removed." % env) + log.debug(f"Conda environment '{env}' could not be removed.") final_return_code = return_code return final_return_code @@ -179,7 +179,7 @@ class CondaDependencyResolver(DependencyResolver, MultipleDependencyResolver, Li is_installed = self.conda_context.has_env(env) if not is_installed: - log.debug("Removing failed conda install of {}".format(str(conda_targets))) + log.debug(f"Removing failed conda install of {str(conda_targets)}") cleanup_failed_install_of_environment(env, conda_context=self.conda_context) return is_installed @@ -251,7 +251,7 @@ class CondaDependencyResolver(DependencyResolver, MultipleDependencyResolver, Li def merged_environment_name(self, conda_targets): if len(conda_targets) > 1: # For continuity with mulled containers this is kind of nice. - return "mulled-v1-%s" % hash_conda_packages(conda_targets) + return f"mulled-v1-{hash_conda_packages(conda_targets)}" else: assert len(conda_targets) == 1 return conda_targets[0].install_environment @@ -344,7 +344,7 @@ class CondaDependencyResolver(DependencyResolver, MultipleDependencyResolver, Li assert not self.read_only if type != "package": - log.warning("Cannot install dependencies of type '%s'" % type) + log.warning(f"Cannot install dependencies of type '{type}'") return False if self.versionless: @@ -410,9 +410,7 @@ class MergedCondaDependency(Dependency): # On explicit testing the only such requirement I am aware of is samtools - and it seems to work # fine with just appending the PATH as done below. Other tools may require additional # variables in the future. - return """export PATH=$PATH:'{}/bin' """.format( - self.environment_path, - ) + return f"""export PATH=$PATH:'{self.environment_path}/bin' """ else: return CONDA_SOURCE_CMD.format( activate_path=self.activate, @@ -479,9 +477,7 @@ class CondaDependency(Dependency): # On explicit testing the only such requirement I am aware of is samtools - and it seems to work # fine with just appending the PATH as done below. Other tools may require additional # variables in the future. - return """export PATH=$PATH:'{}/bin' """.format( - self.environment_path, - ) + return f"""export PATH=$PATH:'{self.environment_path}/bin' """ else: return CONDA_SOURCE_CMD.format( activate_path=self.activate, diff --git a/lib/galaxy/tool_util/deps/resolvers/lmod.py b/lib/galaxy/tool_util/deps/resolvers/lmod.py index 7c545f31a8b..6779bfb84d3 100644 --- a/lib/galaxy/tool_util/deps/resolvers/lmod.py +++ b/lib/galaxy/tool_util/deps/resolvers/lmod.py @@ -168,13 +168,13 @@ class LmodDependency(Dependency): # Build the list of command to add to run script # Note that since "module" is actually a bash function, we are directy executing the underlying executable instead # - Set the MODULEPATH environment variable - command = 'MODULEPATH=%s; ' % (self.lmod_dependency_resolver.modulepath) + command = f'MODULEPATH={self.lmod_dependency_resolver.modulepath}; ' command += 'export MODULEPATH; ' # - Execute the "module load" command (or rather the "/path/to/lmod load" command) command += f'eval `{self.lmod_dependency_resolver.lmodexec} load {module_to_load}` ' # - Execute the "settarg" command in addition if needed if self.lmod_dependency_resolver.settargexec is not None: - command += '&& eval `%s -s sh`' % (self.lmod_dependency_resolver.settargexec) + command += f'&& eval `{self.lmod_dependency_resolver.settargexec} -s sh`' return command diff --git a/lib/galaxy/tool_util/deps/resolvers/resolver_mixins.py b/lib/galaxy/tool_util/deps/resolvers/resolver_mixins.py index dd594fbdec8..2f3d9b8d126 100644 --- a/lib/galaxy/tool_util/deps/resolvers/resolver_mixins.py +++ b/lib/galaxy/tool_util/deps/resolvers/resolver_mixins.py @@ -79,4 +79,4 @@ class HomebrewDependency(Dependency): return raw_commands def __repr__(self): - return "PlatformBrewDependency[commands=%s]" % self.commands + return f"PlatformBrewDependency[commands={self.commands}]" diff --git a/lib/galaxy/tool_util/deps/singularity_util.py b/lib/galaxy/tool_util/deps/singularity_util.py index 3de0282045f..d8d1e8a004b 100644 --- a/lib/galaxy/tool_util/deps/singularity_util.py +++ b/lib/galaxy/tool_util/deps/singularity_util.py @@ -22,7 +22,7 @@ def pull_mulled_singularity_command(docker_image_identifier, ) save_path = docker_image_identifier if namespace: - prefix = "docker://quay.io/%s/" % namespace + prefix = f"docker://quay.io/{namespace}/" if docker_image_identifier.startswith(prefix): save_path = docker_image_identifier[len(prefix):] command_parts.extend(["build", os.path.join(cache_directory, save_path), docker_image_identifier]) diff --git a/lib/galaxy/tool_util/lint.py b/lib/galaxy/tool_util/lint.py index 552666175f5..7fb2e108a07 100644 --- a/lib/galaxy/tool_util/lint.py +++ b/lib/galaxy/tool_util/lint.py @@ -103,21 +103,21 @@ class LintContext: for message in self.error_messages: self.found_errors = True print_linter_info() - print(".. ERROR: %s" % message) + print(f".. ERROR: {message}") if self.level != LEVEL_ERROR: for message in self.warn_messages: self.found_warns = True print_linter_info() - print(".. WARNING: %s" % message) + print(f".. WARNING: {message}") if self.level == LEVEL_ALL: for message in self.info_messages: print_linter_info() - print(".. INFO: %s" % message) + print(f".. INFO: {message}") for message in self.valid_messages: print_linter_info() - print(".. CHECK: %s" % message) + print(f".. CHECK: {message}") def __handle_message(self, message_list, message, *args): if args: diff --git a/lib/galaxy/tool_util/linters/citations.py b/lib/galaxy/tool_util/linters/citations.py index 23d8b63cdcb..c038b4fdd0e 100644 --- a/lib/galaxy/tool_util/linters/citations.py +++ b/lib/galaxy/tool_util/linters/citations.py @@ -20,14 +20,14 @@ def lint_citations(tool_xml, lint_ctx): valid_citations = 0 for citation in citations[0]: if citation.tag != "citation": - lint_ctx.warn("Unknown tag discovered in citations block [%s], will be ignored." % citation.tag) + lint_ctx.warn(f"Unknown tag discovered in citations block [{citation.tag}], will be ignored.") continue citation_type = citation.attrib.get("type") if citation_type not in ('bibtex', 'doi'): lint_ctx.warn("Unknown citation type discovered [%s], will be ignored.", citation_type) continue if citation.text is None or not citation.text.strip(): - lint_ctx.error('Empty %s citation.' % citation_type) + lint_ctx.error(f'Empty {citation_type} citation.') continue valid_citations += 1 diff --git a/lib/galaxy/tool_util/linters/command.py b/lib/galaxy/tool_util/linters/command.py index 919cc9aebce..e675f92cc4a 100644 --- a/lib/galaxy/tool_util/linters/command.py +++ b/lib/galaxy/tool_util/linters/command.py @@ -29,14 +29,14 @@ def lint_command(tool_xml, lint_ctx): elif key == "detect_errors": detect_errors = value if detect_errors not in ["default", "exit_code", "aggressive"]: - lint_ctx.warn("Unknown detect_errors attribute [%s]" % detect_errors) + lint_ctx.warn(f"Unknown detect_errors attribute [{detect_errors}]") interpreter_info = "" if interpreter_type: - interpreter_info = " with interpreter of type [%s]" % interpreter_type + interpreter_info = f" with interpreter of type [{interpreter_type}]" if interpreter_type: lint_ctx.info("Command uses deprecated 'interpreter' attribute.") - lint_ctx.info("Tool contains a command%s." % interpreter_info) + lint_ctx.info(f"Tool contains a command{interpreter_info}.") def get_command(tool_xml): diff --git a/lib/galaxy/tool_util/linters/cwl.py b/lib/galaxy/tool_util/linters/cwl.py index 58390b5ddd4..69ddd9efd8b 100644 --- a/lib/galaxy/tool_util/linters/cwl.py +++ b/lib/galaxy/tool_util/linters/cwl.py @@ -26,7 +26,7 @@ def lint_new_draft(tool_source, lint_ctx): if cwl_version is None: lint_ctx.error("CWL file does not contain a 'cwlVersion'") if cwl_version not in ["v1.0"]: - lint_ctx.warn("CWL version [%s] is unknown, we recommend the v1.0 the stable release." % cwl_version) + lint_ctx.warn(f"CWL version [{cwl_version}] is unknown, we recommend the v1.0 the stable release.") else: lint_ctx.info("Modern CWL version [%s]", cwl_version) @@ -37,7 +37,7 @@ def lint_docker_image(tool_source, lint_ctx): lint_ctx.warn("Tool does not specify a DockerPull source.") else: identifier = containers[0].identifier - lint_ctx.info("Tool will run in Docker image [%s]." % identifier) + lint_ctx.info(f"Tool will run in Docker image [{identifier}].") def lint_description(tool_source, lint_ctx): diff --git a/lib/galaxy/tool_util/linters/help.py b/lib/galaxy/tool_util/linters/help.py index e5717ca9805..df0a3f9b801 100644 --- a/lib/galaxy/tool_util/linters/help.py +++ b/lib/galaxy/tool_util/linters/help.py @@ -29,7 +29,7 @@ def lint_help(tool_xml, lint_ctx): lint_ctx.warn("Help contains TODO text.") if invalid_rst: - lint_ctx.warn("Invalid reStructuredText found in help - [%s]." % invalid_rst) + lint_ctx.warn(f"Invalid reStructuredText found in help - [{invalid_rst}].") else: lint_ctx.valid("Help contains valid reStructuredText.") diff --git a/lib/galaxy/tool_util/linters/inputs.py b/lib/galaxy/tool_util/linters/inputs.py index aedf4923e2b..2dde74cab8c 100644 --- a/lib/galaxy/tool_util/linters/inputs.py +++ b/lib/galaxy/tool_util/linters/inputs.py @@ -195,7 +195,7 @@ def lint_repeats(tool_xml, lint_ctx): def _find_with_attribute(element, tag, attribute, test_value=None): rval = [] - for el in (element.findall('./%s' % tag) or []): + for el in (element.findall(f'./{tag}') or []): if attribute not in el.attrib: continue value = el.attrib[attribute] diff --git a/lib/galaxy/tool_util/linters/outputs.py b/lib/galaxy/tool_util/linters/outputs.py index 5ae74d50207..42e5ca68ea8 100644 --- a/lib/galaxy/tool_util/linters/outputs.py +++ b/lib/galaxy/tool_util/linters/outputs.py @@ -17,7 +17,7 @@ def lint_output(tool_xml, lint_ctx): for output in list(outputs[0]): if output.tag not in ["data", "collection"]: - lint_ctx.warn("Unknown element found in outputs [%s]" % output.tag) + lint_ctx.warn(f"Unknown element found in outputs [{output.tag}]") continue num_outputs += 1 if "name" not in output.attrib: @@ -47,7 +47,7 @@ def lint_output(tool_xml, lint_ctx): format_set = True if not format_set: - lint_ctx.warn("Tool {} output {} doesn't define an output format.".format(output.tag, output.attrib.get("name", "with missing name"))) + lint_ctx.warn(f"Tool {output.tag} output {output.attrib.get('name', 'with missing name')} doesn't define an output format.") lint_ctx.info("%d outputs found.", num_outputs) @@ -65,7 +65,7 @@ def __check_format(node, lint_ctx, allow_ext=False): if fmt is None: fmt = node.attrib.get("format") if fmt == "input": - lint_ctx.warn("Using format='input' on %s, format_source attribute is less ambiguous and should be used instead." % node.tag) + lint_ctx.warn(f"Using format='input' on {node.tag}, format_source attribute is less ambiguous and should be used instead.") return fmt is not None diff --git a/lib/galaxy/tool_util/linters/stdio.py b/lib/galaxy/tool_util/linters/stdio.py index 10f712d37f8..1c5268267d7 100644 --- a/lib/galaxy/tool_util/linters/stdio.py +++ b/lib/galaxy/tool_util/linters/stdio.py @@ -34,10 +34,10 @@ def lint_stdio(tool_source, lint_ctx): def _lint_exit_code(child, lint_ctx): for key in child.attrib.keys(): if key not in ["description", "level", "range"]: - lint_ctx.warn("Unknown attribute [%s] encountered on exit_code tag." % key) + lint_ctx.warn(f"Unknown attribute [{key}] encountered on exit_code tag.") def _lint_regex(child, lint_ctx): for key in child.attrib.keys(): if key not in ["description", "level", "match", "source"]: - lint_ctx.warn("Unknown attribute [%s] encountered on regex tag." % key) + lint_ctx.warn(f"Unknown attribute [{key}] encountered on regex tag.") diff --git a/lib/galaxy/tool_util/linters/xml_order.py b/lib/galaxy/tool_util/linters/xml_order.py index 786c9f0e8b1..3e34f6d111d 100644 --- a/lib/galaxy/tool_util/linters/xml_order.py +++ b/lib/galaxy/tool_util/linters/xml_order.py @@ -62,4 +62,4 @@ def _validate_for_tags(root, lint_ctx, tag_ordering): last_tag = tag last_key = key else: - lint_ctx.info("Unknown tag [%s] encountered, this may result in a warning in the future." % tag) + lint_ctx.info(f"Unknown tag [{tag}] encountered, this may result in a warning in the future.") diff --git a/lib/galaxy/tool_util/locations/dockstore.py b/lib/galaxy/tool_util/locations/dockstore.py index 42dd5f5d204..4076a71aab6 100644 --- a/lib/galaxy/tool_util/locations/dockstore.py +++ b/lib/galaxy/tool_util/locations/dockstore.py @@ -32,23 +32,23 @@ class _Ga4ghToolClient: self.base_url = base_url def get_tools(self): - return self._requests.get("%s/ga4gh/v1/tools" % self.base_url) + return self._requests.get(f"{self.base_url}/ga4gh/v1/tools") def get_tool(self, tool_id): - url = "{}/ga4gh/v1/tools/{}".format(self.base_url, quote(tool_id, safe='')) + url = f"{self.base_url}/ga4gh/v1/tools/{quote(tool_id, safe='')}" return self._requests.get(url) def get_tool_version(self, tool_id, version="latest"): - url = "{}/ga4gh/v1/tools/{}/versions/{}".format(self.base_url, quote(tool_id, safe=''), version) + url = f"{self.base_url}/ga4gh/v1/tools/{quote(tool_id, safe='')}/versions/{version}" return self._requests.get(url) def get_tool_descriptor(self, tool_id, version="latest", tool_type="CWL"): - url = "{}/ga4gh/v1/tools/{}/versions/{}/{}/descriptor".format(self.base_url, quote(tool_id, safe=''), version, tool_type) + url = f"{self.base_url}/ga4gh/v1/tools/{quote(tool_id, safe='')}/versions/{version}/{tool_type}/descriptor" return self._requests.get(url) def get_tool_cwl(self, tool_id, version="latest", as_string=False): tool_type = "CWL" - url = "{}/ga4gh/v1/tools/{}/versions/{}/{}/descriptor".format(self.base_url, quote(tool_id, safe=''), version, tool_type) + url = f"{self.base_url}/ga4gh/v1/tools/{quote(tool_id, safe='')}/versions/{version}/{tool_type}/descriptor" descriptor_response = self._requests.get(url) descriptor_str = descriptor_response.json()["descriptor"] if as_string: diff --git a/lib/galaxy/tool_util/output_checker.py b/lib/galaxy/tool_util/output_checker.py index 7cdbc2681ed..697c075f1a2 100644 --- a/lib/galaxy/tool_util/output_checker.py +++ b/lib/galaxy/tool_util/output_checker.py @@ -175,7 +175,7 @@ def __regex_err_msg(match, stream, regex): if regex.desc is not None: desc += regex.desc else: - desc += "Matched on %s" % match_str + desc += f"Matched on {match_str}" return { "type": "regex", "stream": stream, diff --git a/lib/galaxy/tool_util/parser/factory.py b/lib/galaxy/tool_util/parser/factory.py index 9acd3a7758b..29175178c70 100644 --- a/lib/galaxy/tool_util/parser/factory.py +++ b/lib/galaxy/tool_util/parser/factory.py @@ -53,7 +53,7 @@ def get_tool_source_from_representation(tool_format, tool_representation): tool_representation["version"] = "1.0.0" # Don't require version for embedded tools. return YamlToolSource(tool_representation) else: - raise Exception("Unknown tool representation format [%s]." % tool_format) + raise Exception(f"Unknown tool representation format [{tool_format}].") def get_input_source(content): diff --git a/lib/galaxy/tool_util/parser/interface.py b/lib/galaxy/tool_util/parser/interface.py index 8c549f3aa4a..faf4f79b12c 100644 --- a/lib/galaxy/tool_util/parser/interface.py +++ b/lib/galaxy/tool_util/parser/interface.py @@ -259,7 +259,7 @@ class ToolSource(metaclass=ABCMeta): if source_path: as_str = f'{self.__class__.__name__}[{source_path}]' else: - as_str = '%s[In-memory]' % (self.__class__.__name__) + as_str = f'{self.__class__.__name__}[In-memory]' return as_str @@ -426,7 +426,7 @@ class TestCollectionDef: def element_from_dict(element_dict): if "element_definition" not in element_dict: - raise Exception("Invalid element_dict %s" % element_dict) + raise Exception(f"Invalid element_dict {element_dict}") element_def = element_dict["element_definition"] if element_def.get("model_class", None) == "TestCollectionDef": element_def = TestCollectionDef.from_dict(element_def) diff --git a/lib/galaxy/tool_util/parser/output_actions.py b/lib/galaxy/tool_util/parser/output_actions.py index 621eedcf7c3..b83042a14d3 100644 --- a/lib/galaxy/tool_util/parser/output_actions.py +++ b/lib/galaxy/tool_util/parser/output_actions.py @@ -27,7 +27,7 @@ class ToolOutputActionGroup: elif elem.tag == "action": self.actions.append(ToolOutputAction.from_elem(self, elem)) else: - log.debug("Unknown ToolOutputAction tag specified: %s" % elem.tag) + log.debug(f"Unknown ToolOutputAction tag specified: {elem.tag}") def apply_action(self, output_dataset, other_values): for action in self.actions: @@ -66,7 +66,7 @@ class ToolOutputActionConditionalWhen(ToolOutputActionGroup): def get_ref(self, output_dataset, other_values): ref = other_values for ref_name in self.parent.name: - assert ref_name in ref, "Required dependency '%s' not found in incoming values" % ref_name + assert ref_name in ref, f"Required dependency '{ref_name}' not found in incoming values" ref = ref.get(ref_name) return ref @@ -203,7 +203,7 @@ class FromFileToolOutputActionOption(ToolOutputActionOption): if options: return str(options[self.offset][self.column]) except Exception as e: - log.debug("Error in FromFileToolOutputActionOption get_value: %s" % e) + log.debug(f"Error in FromFileToolOutputActionOption get_value: {e}") return None @@ -226,7 +226,7 @@ class FromParamToolOutputActionOption(ToolOutputActionOption): def get_value(self, other_values): value = other_values for ref_name in self.name: - assert ref_name in value, "Required dependency '%s' not found in incoming values" % ref_name + assert ref_name in value, f"Required dependency '{ref_name}' not found in incoming values" value = value.get(ref_name) for attr_name in self.param_attribute: # if the value is a list from a repeat tag you can access the first element of the repeat with @@ -252,7 +252,7 @@ class FromParamToolOutputActionOption(ToolOutputActionOption): if options: return str(options[self.offset][self.column]) except Exception as e: - log.debug("Error in FromParamToolOutputActionOption get_value: %s" % e) + log.debug(f"Error in FromParamToolOutputActionOption get_value: {e}") return None @@ -287,7 +287,7 @@ class FromDataTableOutputActionOption(ToolOutputActionOption): if options: return str(options[self.offset][self.column]) except Exception as e: - log.debug("Error in FromDataTableOutputActionOption get_value: %s" % e) + log.debug(f"Error in FromDataTableOutputActionOption get_value: {e}") return None @@ -368,7 +368,7 @@ class ParamValueToolOutputActionOptionFilter(ToolOutputActionOptionFilter): # find ref value value = other_values for ref_name in self.ref: - assert ref_name in value, "Required dependency '%s' not found in incoming values" % ref_name + assert ref_name in value, f"Required dependency '{ref_name}' not found in incoming values" value = value.get(ref_name) for attr_name in self.param_attribute: value = getattr(value, attr_name) @@ -407,7 +407,7 @@ class InsertColumnToolOutputActionOptionFilter(ToolOutputActionOptionFilter): # find ref value value = other_values for ref_name in self.ref: - assert ref_name in value, "Required dependency '%s' not found in incoming values" % ref_name + assert ref_name in value, f"Required dependency '{ref_name}' not found in incoming values" value = value.get(ref_name) value = str(value) else: @@ -514,7 +514,7 @@ class MetadataValueFilter(ToolOutputActionOptionFilter): def filter_options(self, options, other_values): ref = other_values for ref_name in self.ref: - assert ref_name in ref, "Required dependency '%s' not found in incoming values" % ref_name + assert ref_name in ref, f"Required dependency '{ref_name}' not found in incoming values" ref = ref.get(ref_name) value = str(getattr(ref.metadata, self.name)) rval = [] @@ -601,7 +601,7 @@ def parse_cast_attribute(cast): def parse_compare_type(compare): if compare is None: compare = 'eq' - assert compare in compare_types, "Invalid compare type specified: %s" % compare + assert compare in compare_types, f"Invalid compare type specified: {compare}" return compare_types[compare] diff --git a/lib/galaxy/tool_util/parser/output_collection_def.py b/lib/galaxy/tool_util/parser/output_collection_def.py index a6c05ed1e13..17d5f7130b9 100644 --- a/lib/galaxy/tool_util/parser/output_collection_def.py +++ b/lib/galaxy/tool_util/parser/output_collection_def.py @@ -63,7 +63,7 @@ def dataset_collection_description(**kwargs): if discover_via == "tool_provided_metadata": for key in ["pattern", "sort_by"]: if kwargs.get(key): - raise Exception("Cannot specify attribute [%s] if from_provided_metadata is True" % key) + raise Exception(f"Cannot specify attribute [{key}] if from_provided_metadata is True") return ToolProvidedMetadataDatasetCollection(**kwargs) else: return FilePatternDatasetCollectionDescription(**kwargs) diff --git a/lib/galaxy/tool_util/parser/xml.py b/lib/galaxy/tool_util/parser/xml.py index 0355946ab27..3af561ca65c 100644 --- a/lib/galaxy/tool_util/parser/xml.py +++ b/lib/galaxy/tool_util/parser/xml.py @@ -136,7 +136,7 @@ class XmlToolSource(ToolSource): if expression_el is not None: expression_type = expression_el.get("type") if expression_type != "ecma5.1": - raise Exception("Unknown expression type [%s] encountered" % expression_type) + raise Exception(f"Unknown expression type [{expression_type}] encountered") return expression_el.text return None @@ -382,7 +382,7 @@ class XmlToolSource(ToolSource): else: _parse_expression(out_child) else: - log.warning("Unknown output tag encountered [%s]" % out_child.tag) + log.warning(f"Unknown output tag encountered [{out_child.tag}]") for output_def in data_dict.values(): outputs[output_def.name] = output_def @@ -470,7 +470,7 @@ class XmlToolSource(ToolSource): elif detect_errors == "aggressive": exit_codes, regexes = aggressive_error_checks() else: - raise ValueError("Unknown detect_errors value encountered [%s]" % detect_errors) + raise ValueError(f"Unknown detect_errors value encountered [{detect_errors}]") elif len(self.root.findall('stdio')) == 0 and not self.legacy_defaults: exit_codes, regexes = error_on_exit_code() else: @@ -727,7 +727,7 @@ def __parse_extra_files_elem(extra): extra_type = attrib.pop('type', 'file') extra_name = attrib.pop('name', None) assert extra_type == 'directory' or extra_name is not None, \ - 'extra_files type (%s) requires a name attribute' % extra_type + f'extra_files type ({extra_type}) requires a name attribute' extra_value, extra_attributes = __parse_test_attributes(extra, attrib) return { "value": extra_value, @@ -914,8 +914,7 @@ class StdioParser: exit_code.range_end = int(code_ranges[1]) # If we got more than one colon, then ignore the exit code. elif (len(code_ranges) > 2): - log.warning("Invalid tool exit_code range %s - ignored" - % code_range) + log.warning(f"Invalid tool exit_code range {code_range} - ignored") continue # Else we have a singular value. If it's not an integer, then # we'll just write a log message and skip this exit_code. @@ -924,7 +923,7 @@ class StdioParser: exit_code.range_start = int(code_range) except Exception: log.error(code_range) - log.warning("Invalid range start for tool's exit_code %s: exit_code ignored" % code_range) + log.warning(f"Invalid range start for tool's exit_code {code_range}: exit_code ignored") continue exit_code.range_end = exit_code.range_start # TODO: Check if we got ">", ">=", "<", or "<=": @@ -933,7 +932,7 @@ class StdioParser: # the start must be -inf and the end must be +inf. # So at least warn about this situation: if isinf(exit_code.range_start) and isinf(exit_code.range_end): - log.warning("Tool exit_code range %s will match on all exit codes" % code_range) + log.warning(f"Tool exit_code range {code_range} will match on all exit codes") self.stdio_exit_codes.append(exit_code) except Exception: log.exception("Exception in parse_stdio_exit_codes!") diff --git a/lib/galaxy/tool_util/parser/yaml.py b/lib/galaxy/tool_util/parser/yaml.py index 5baec304acd..cbada5a9a8f 100644 --- a/lib/galaxy/tool_util/parser/yaml.py +++ b/lib/galaxy/tool_util/parser/yaml.py @@ -113,7 +113,7 @@ class YamlToolSource(ToolSource): elif output_type == "collection": output_collection_defs.append(self._parse_output_collection(tool, name, output_dict)) else: - message = "Unknown output_type [%s] encountered." % output_type + message = f"Unknown output_type [{output_type}] encountered." raise Exception(message) outputs = {} for output in output_defs: diff --git a/lib/galaxy/tool_util/provided_metadata.py b/lib/galaxy/tool_util/provided_metadata.py index 97aa5817234..abf3135f2aa 100644 --- a/lib/galaxy/tool_util/provided_metadata.py +++ b/lib/galaxy/tool_util/provided_metadata.py @@ -110,8 +110,8 @@ class LegacyToolProvidedMetadata(BaseToolProvidedMetadata): line = stringify_dictionary_keys(json.loads(line)) assert 'type' in line except Exception: - log.exception('(%s) Got JSON data from tool, but data is improperly formatted or no "type" key in data' % getattr(job_wrapper, "job_id", None)) - log.debug('Offending data was: %s' % line) + log.exception(f"({getattr(job_wrapper, 'job_id', None)}) Got JSON data from tool, but data is improperly formatted or no \"type\" key in data") + log.debug(f'Offending data was: {line}') continue # Set the dataset id if it's a dataset entry and isn't set. # This isn't insecure. We loop the job's output datasets in @@ -124,12 +124,12 @@ class LegacyToolProvidedMetadata(BaseToolProvidedMetadata): try: line['dataset_id'] = job_wrapper.get_output_file_id(dataset_basename) except KeyError: - log.warning('(%s) Tool provided job dataset-specific metadata without specifying a dataset' % job_wrapper.job_id) + log.warning(f'({job_wrapper.job_id}) Tool provided job dataset-specific metadata without specifying a dataset') continue else: match = re.match(r'(galaxy_)?dataset_(.*)\.dat', dataset_basename) if match is None: - raise Exception("processing tool_provided_metadata (e.g. galaxy.json) entry with invalid dataset name [%s]" % dataset_basename) + raise Exception(f"processing tool_provided_metadata (e.g. galaxy.json) entry with invalid dataset name [{dataset_basename}]") dataset_id = match.group(2) if dataset_id.isdigit(): line['dataset_id'] = dataset_id @@ -159,7 +159,7 @@ class LegacyToolProvidedMetadata(BaseToolProvidedMetadata): found_failed = False for meta in self.tool_provided_job_metadata: if meta.get("failed", False): - log.info("One or more tool outputs is marked as failed (%s)." % meta) + log.info(f"One or more tool outputs is marked as failed ({meta}).") found_failed = True return found_failed @@ -170,7 +170,7 @@ class LegacyToolProvidedMetadata(BaseToolProvidedMetadata): def rewrite(self): with open(self.meta_file, 'wt') as job_metadata_fh: for meta in self.tool_provided_job_metadata: - job_metadata_fh.write("%s\n" % (json.dumps(meta))) + job_metadata_fh.write(f"{json.dumps(meta)}\n") def get_new_datasets_for_metadata_collection(self): for meta in self.tool_provided_job_metadata: @@ -222,13 +222,13 @@ class ToolProvidedMetadata(BaseToolProvidedMetadata): continue if meta.get("failed", False): - log.info("One or more tool outputs is marked as failed (%s)." % meta) + log.info(f"One or more tool outputs is marked as failed ({meta}).") found_failed = True return found_failed def get_unnamed_outputs(self): - log.debug("unnamed outputs [%s]" % self.tool_provided_job_metadata) + log.debug(f"unnamed outputs [{self.tool_provided_job_metadata}]") return self.tool_provided_job_metadata.get("__unnamed_outputs", []) def rewrite(self): diff --git a/lib/galaxy/tool_util/verify/__init__.py b/lib/galaxy/tool_util/verify/__init__.py index 8b21fb430c2..66846a8df04 100644 --- a/lib/galaxy/tool_util/verify/__init__.py +++ b/lib/galaxy/tool_util/verify/__init__.py @@ -62,7 +62,7 @@ def verify( try: verify_assertions(output_content, attributes["assert_list"]) except AssertionError as err: - errmsg = '%s different than expected\n' % (item_label) + errmsg = f'{item_label} different than expected\n' errmsg += unicodify(err) raise AssertionError(errmsg) @@ -82,7 +82,7 @@ def verify( try: _verify_checksum(output_content, expected_checksum_type, expected_checksum) except AssertionError as err: - errmsg = '%s different than expected\n' % (item_label) + errmsg = f'{item_label} different than expected\n' errmsg += unicodify(err) raise AssertionError(errmsg) @@ -157,7 +157,7 @@ def verify( elif compare == "contains": files_contains(local_name, temp_name, attributes=attributes) else: - raise Exception('Unimplemented Compare type: %s' % compare) + raise Exception(f'Unimplemented Compare type: {compare}') except AssertionError as err: errmsg = f'{item_label} different than expected, difference (using {compare}):\n' errmsg += f"( {local_name} v. {temp_name} )\n" @@ -184,14 +184,14 @@ def _bam_to_sam(local_name, temp_name): temp_local = tempfile.NamedTemporaryFile(suffix='.sam', prefix='local_bam_converted_to_sam_') with tempfile.NamedTemporaryFile(suffix='.sam', prefix='history_bam_converted_to_sam_', delete=False) as temp: try: - pysam.view('-h', '-o%s' % temp_local.name, local_name) + pysam.view('-h', f'-o{temp_local.name}', local_name) except Exception as e: - msg = "Converting local (test-data) BAM to SAM failed: %s" % unicodify(e) + msg = f"Converting local (test-data) BAM to SAM failed: {unicodify(e)}" raise Exception(msg) try: - pysam.view('-h', '-o%s' % temp.name, temp_name) + pysam.view('-h', f'-o{temp.name}', temp_name) except Exception as e: - msg = "Converting history BAM to SAM failed: %s" % unicodify(e) + msg = f"Converting history BAM to SAM failed: {unicodify(e)}" raise Exception(msg) os.remove(temp_name) return temp_local, temp.name @@ -199,7 +199,7 @@ def _bam_to_sam(local_name, temp_name): def _verify_checksum(data, checksum_type, expected_checksum_value): if checksum_type not in ["md5", "sha1", "sha256", "sha512"]: - raise Exception("Unimplemented hash algorithm [%s] encountered." % checksum_type) + raise Exception(f"Unimplemented hash algorithm [{checksum_type}] encountered.") h = hashlib.new(checksum_type) h.update(data) diff --git a/lib/galaxy/tool_util/verify/asserts/__init__.py b/lib/galaxy/tool_util/verify/asserts/__init__.py index 75e8536e1ae..2dd433e324b 100644 --- a/lib/galaxy/tool_util/verify/asserts/__init__.py +++ b/lib/galaxy/tool_util/verify/asserts/__init__.py @@ -40,7 +40,7 @@ def verify_assertion(data, assertion_description): assert_function = getattr(assertion_module, assert_function_name) if assert_function is None: - errmsg = "Unable to find test function associated with XML tag '%s'. Check your tool file syntax." % tag + errmsg = f"Unable to find test function associated with XML tag '{tag}'. Check your tool file syntax." raise AssertionError(errmsg) assert_function_args = getfullargspec(assert_function).args diff --git a/lib/galaxy/tool_util/verify/asserts/text.py b/lib/galaxy/tool_util/verify/asserts/text.py index e16e51057c1..d501c0e1149 100644 --- a/lib/galaxy/tool_util/verify/asserts/text.py +++ b/lib/galaxy/tool_util/verify/asserts/text.py @@ -10,7 +10,7 @@ def assert_has_text(output, text, n=None): assert output.find(text) >= 0, f"Output file did not contain expected text '{text}' (output '{output}')" else: matches = re.findall(re.escape(text), output) - assert len(matches) == int(n), "Expected {} matches for '{}' in output file (output '{}'); found {}".format(n, text, output, len(matches)) + assert len(matches) == int(n), f"Expected {n} matches for '{text}' in output file (output '{output}'); found {len(matches)}" def assert_not_has_text(output, text): @@ -26,11 +26,11 @@ def assert_has_line(output, line, n=None): specified by the argument n.""" assert output is not None, "Checking has_line assertion on empty output (None)" if n is None: - match = re.search("^%s$" % re.escape(line), output, flags=re.MULTILINE) + match = re.search(f"^{re.escape(line)}$", output, flags=re.MULTILINE) assert match is not None, f"No line of output file was '{line}' (output was '{output}') " else: - matches = re.findall("^%s$" % re.escape(line), output, flags=re.MULTILINE) - assert len(matches) == int(n), "Expected {} lines matching '{}' in output file (output was '{}'); found {}".format(n, line, output, len(matches)) + matches = re.findall(f"^{re.escape(line)}$", output, flags=re.MULTILINE) + assert len(matches) == int(n), f"Expected {n} lines matching '{line}' in output file (output was '{output}'); found {len(matches)}" def assert_has_n_lines(output, n): @@ -44,11 +44,11 @@ def assert_has_text_matching(output, expression): """ Asserts the specified output contains text matching the regular expression specified by the argument expression.""" match = re.search(expression, output) - assert match is not None, "No text matching expression '%s' was found in output file." % expression + assert match is not None, f"No text matching expression '{expression}' was found in output file." def assert_has_line_matching(output, expression): """ Asserts the specified output contains a line matching the regular expression specified by the argument expression.""" - match = re.search("^%s$" % expression, output, flags=re.MULTILINE) - assert match is not None, "No line matching expression '%s' was found in output file." % expression + match = re.search(f"^{expression}$", output, flags=re.MULTILINE) + assert match is not None, f"No line matching expression '{expression}' was found in output file." diff --git a/lib/galaxy/tool_util/verify/asserts/xml.py b/lib/galaxy/tool_util/verify/asserts/xml.py index b0d283ea0b5..7835a2dd29e 100644 --- a/lib/galaxy/tool_util/verify/asserts/xml.py +++ b/lib/galaxy/tool_util/verify/asserts/xml.py @@ -29,7 +29,7 @@ def assert_is_valid_xml(output): to_xml(output) except Exception as e: # TODO: Narrow caught exception to just parsing failure - raise AssertionError("Expected valid XML, but could not parse output. %s" % unicodify(e)) + raise AssertionError(f"Expected valid XML, but could not parse output. {unicodify(e)}") def assert_has_element_with_path(output, path): @@ -38,7 +38,7 @@ def assert_has_element_with_path(output, path): simplified subsets of XPath implemented by lxml.etree; http://effbot.org/zone/element-xpath.htm for more information.""" if xml_find(output, path) is None: - errmsg = "Expected to find XML element matching expression %s, not such match was found." % path + errmsg = f"Expected to find XML element matching expression {path}, not such match was found." raise AssertionError(errmsg) diff --git a/lib/galaxy/tool_util/verify/interactor.py b/lib/galaxy/tool_util/verify/interactor.py index 3f5c1f44231..e4965b0bc67 100644 --- a/lib/galaxy/tool_util/verify/interactor.py +++ b/lib/galaxy/tool_util/verify/interactor.py @@ -87,7 +87,7 @@ def stage_data_in_history(galaxy_interactor, tool_id, all_test_data, history=Non class GalaxyInteractorApi: def __init__(self, **kwds): - self.api_url = "%s/api" % kwds["galaxy_url"].rstrip("/") + self.api_url = f"{kwds['galaxy_url'].rstrip('/')}/api" self.master_api_key = kwds["master_api_key"] self.api_key = self.__get_user_key(kwds.get("api_key"), kwds.get("master_api_key"), test_user=kwds.get("test_user")) if kwds.get('user_api_key_is_admin_key', False): @@ -118,7 +118,7 @@ class GalaxyInteractorApi: if user_key: return user_key test_user = self.ensure_user_with_email(test_user) - return self._post("users/%s/api_key" % test_user['id'], key=admin_key).json() + return self._post(f"users/{test_user['id']}/api_key", key=admin_key).json() # def get_tools(self): # response = self._get("tools?in_panel=false") @@ -127,7 +127,7 @@ class GalaxyInteractorApi: def get_tests_summary(self): response = self._get("tools/tests_summary") - assert response.status_code == 200, "Non 200 response from tool tests available API. [%s]" % response.content + assert response.status_code == 200, f"Non 200 response from tool tests available API. [{response.content}]" return response.json() def get_tool_tests(self, tool_id, tool_version=None): @@ -138,7 +138,7 @@ class GalaxyInteractorApi: return response.json() def verify_output_collection(self, output_collection_def, output_collection_id, history, tool_id): - data_collection = self._get("dataset_collections/%s" % output_collection_id, data={"instance_type": "history"}).json() + data_collection = self._get(f"dataset_collections/{output_collection_id}", data={"instance_type": "history"}).json() def verify_dataset(element, element_attrib, element_outfile): hda = element["object"] @@ -163,12 +163,12 @@ class GalaxyInteractorApi: try: self.verify_output_dataset(history_id=history_id, hda_id=hid, outfile=outfile, attributes=attributes, tool_id=tool_id) except AssertionError as e: - raise AssertionError("Output {}: {}".format(name, str(e))) + raise AssertionError(f"Output {name}: {str(e)}") primary_datasets = attributes.get('primary_datasets', {}) if primary_datasets: job_id = self._dataset_provenance(history_id, hid)["job_id"] - outputs = self._get("jobs/%s/outputs" % (job_id)).json() + outputs = self._get(f"jobs/{job_id}/outputs").json() for designation, (primary_outfile, primary_attributes) in primary_datasets.items(): primary_output = None @@ -186,7 +186,7 @@ class GalaxyInteractorApi: try: self.verify_output_dataset(history_id, primary_hda_id, primary_outfile, primary_attributes, tool_id=tool_id) except AssertionError as e: - raise AssertionError("Primary output {}: {}".format(name, str(e))) + raise AssertionError(f"Primary output {name}: {str(e)}") def wait_for_jobs(self, history_id, jobs, maxseconds): for job in jobs: @@ -215,7 +215,7 @@ class GalaxyInteractorApi: metadata = attributes.get('metadata', {}).copy() for key in metadata.copy().keys(): if key not in ['name', 'info', 'tags', 'created_from_basename']: - new_key = "metadata_%s" % key + new_key = f"metadata_{key}" metadata[new_key] = metadata[key] del metadata[key] elif key == "info": @@ -251,7 +251,7 @@ class GalaxyInteractorApi: else: compare(dataset_value, value) except KeyError: - msg = "Failed to verify dataset metadata, metadata key [%s] was not found." % key + msg = f"Failed to verify dataset metadata, metadata key [{key}] was not found." raise Exception(msg) def wait_for_job(self, job_id, history_id=None, maxseconds=DEFAULT_TOOL_TEST_WAIT): @@ -266,10 +266,10 @@ class GalaxyInteractorApi: return job_stdio def __get_job(self, job_id): - return self._get('jobs/%s' % job_id) + return self._get(f'jobs/{job_id}') def __get_job_stdio(self, job_id): - return self._get('jobs/%s?full=true' % job_id) + return self._get(f'jobs/{job_id}?full=true') def new_history(self, history_name='test_history', publish_history=False): create_response = self._post("histories", {"name": history_name}) @@ -360,7 +360,7 @@ class GalaxyInteractorApi: if not hasattr(metadata, "items"): raise Exception(f"Invalid metadata description found for input [{fname}] - [{metadata}]") for name, value in test_data.get('metadata', {}).items(): - tool_input["files_metadata|%s" % name] = value + tool_input[f"files_metadata|{name}"] = value composite_data = test_data['composite_data'] if composite_data: @@ -373,7 +373,7 @@ class GalaxyInteractorApi: }) else: file_content = self.test_data_download(tool_id, file_name, is_output=False) - files["files_%s|file_data" % i] = file_content + files[f"files_{i}|file_data"] = file_content tool_input.update({ "files_%d|type" % i: "upload_dataset", }) @@ -396,16 +396,16 @@ class GalaxyInteractorApi: "files_0|file_data": file_content } submit_response_object = self.__submit_tool(history_id, "upload1", tool_input, extra_data={"type": "upload_dataset"}, files=files) - submit_response = ensure_tool_run_response_okay(submit_response_object, "upload dataset %s" % name) - assert "outputs" in submit_response, "Invalid response from server [%s], expecting outputs in response." % submit_response + submit_response = ensure_tool_run_response_okay(submit_response_object, f"upload dataset {name}") + assert "outputs" in submit_response, f"Invalid response from server [{submit_response}], expecting outputs in response." outputs = submit_response["outputs"] - assert len(outputs) > 0, "Invalid response from server [%s], expecting an output dataset." % submit_response + assert len(outputs) > 0, f"Invalid response from server [{submit_response}], expecting an output dataset." dataset = outputs[0] hid = dataset['id'] self.uploads[os.path.basename(fname)] = self.uploads[fname] = self.uploads[name] = {"src": "hda", "id": hid} - assert "jobs" in submit_response, "Invalid response from server [%s], expecting jobs in response." % submit_response + assert "jobs" in submit_response, f"Invalid response from server [{submit_response}], expecting jobs in response." jobs = submit_response["jobs"] - assert len(jobs) > 0, "Invalid response from server [%s], expecting a job." % submit_response + assert len(jobs) > 0, f"Invalid response from server [{submit_response}], expecting a job." return lambda: self.wait_for_job(jobs[0]["id"], history_id, maxseconds=maxseconds) def run_tool(self, testdef, history_id, resource_parameters=None): @@ -429,7 +429,7 @@ class GalaxyInteractorApi: if resource_parameters: inputs_tree["__job_resource|__job_resource__select"] = "yes" for key, value in resource_parameters.items(): - inputs_tree["__job_resource|%s" % key] = value + inputs_tree[f"__job_resource|{key}"] = value # HACK: Flatten single-value lists. Required when using expand_grouping for key, value in inputs_tree.items(): @@ -455,7 +455,7 @@ class GalaxyInteractorApi: jobs=submit_response_object['jobs'], ) except KeyError: - message = "Error creating a job for these tool inputs - %s" % submit_response_object['err_msg'] + message = f"Error creating a job for these tool inputs - {submit_response_object['err_msg']}" raise RunToolException(message, inputs_tree) def _create_collection(self, history_id, collection_def): @@ -524,7 +524,7 @@ class GalaxyInteractorApi: def _summarize_history(self, history_id): if history_id is None: raise ValueError("_summarize_history passed empty history_id") - print("Problem in history with id %s - summary of history's datasets and jobs below." % history_id) + print(f"Problem in history with id {history_id} - summary of history's datasets and jobs below.") try: history_contents = self.__contents(history_id) except Exception: @@ -539,8 +539,8 @@ class GalaxyInteractorApi: dataset_id = dataset.get('id', None) print("| %d - %s (HID - NAME) " % (int(dataset['hid']), dataset['name'])) if history_content['history_content_type'] == 'dataset_collection': - history_contents_json = self._get("histories/{}/contents/dataset_collections/{}".format(history_id, history_content["id"])).json() - print("| Dataset Collection: %s" % history_contents_json) + history_contents_json = self._get(f"histories/{history_id}/contents/dataset_collections/{history_content['id']}").json() + print(f"| Dataset Collection: {history_contents_json}") print("|") continue @@ -566,10 +566,10 @@ class GalaxyInteractorApi: print("| *TEST FRAMEWORK ERROR FETCHING JOB DETAILS*") print("|") try: - jobs_json = self._get("jobs?history_id=%s" % history_id).json() + jobs_json = self._get(f"jobs?history_id={history_id}").json() for job_json in jobs_json: print(ERROR_MESSAGE_DATASET_SEP) - print("| Job %s" % job_json["id"]) + print(f"| Job {job_json['id']}") print("| State: ") print(self.format_for_summary(job_json.get("state", ""), "Job state is unknown.")) print("| Update Time:") @@ -596,7 +596,7 @@ class GalaxyInteractorApi: return dataset_json def __contents(self, history_id): - history_contents_response = self._get("histories/%s/contents" % history_id) + history_contents_response = self._get(f"histories/{history_id}/contents") history_contents_response.raise_for_status() return history_contents_response.json() @@ -653,7 +653,7 @@ class GalaxyInteractorApi: def fetcher(hda_id, base_name=None): url = f"histories/{history_id}/contents/{hda_id}/display?raw=true" if base_name: - url += "&filename=%s" % base_name + url += f"&filename={base_name}" response = None for _ in range(self.download_attempts): response = self._get(url) @@ -717,7 +717,7 @@ def ensure_tool_run_response_okay(submit_response_object, request_desc, inputs=N if "dbkey" in param_errors: dbkey_err_obj = param_errors["dbkey"] dbkey_val = dbkey_err_obj.get("parameter_value") - message = "Invalid dbkey specified [%s]" % dbkey_val + message = f"Invalid dbkey specified [{dbkey_val}]" for value in param_errors.values(): if isinstance(value, dict) and value.get("is_dynamic"): dynamic_param_error = True @@ -845,7 +845,7 @@ def _verify_composite_datatype_file_content(file_name, hda_id, base_name=None, a assert dataset_fetcher is not None data = dataset_fetcher(hda_id, base_name) - item_label = "History item %s" % hda_id + item_label = f"History item {hda_id}" try: verify( item_label, @@ -882,7 +882,7 @@ def _verify_extra_files_content(extra_files, hda_id, dataset_fetcher, test_data_ filename = os.path.relpath(filename, extracted_path) files_list.append((filename, os.path.join(extracted_path, filename), extra_file_attributes, extra_file_type)) else: - raise ValueError('unknown extra_files type: %s' % extra_file_type) + raise ValueError(f'unknown extra_files type: {extra_file_type}') try: for filename, filepath, attributes, extra_file_type in files_list: _verify_composite_datatype_file_content(filepath, hda_id, base_name=filename, attributes=attributes, dataset_fetcher=dataset_fetcher, test_data_downloader=test_data_downloader, keep_outputs_dir=keep_outputs_dir, mode=extra_file_type) @@ -1068,7 +1068,7 @@ def verify_tool(tool_id, job_data["dynamic_param_error"] = dynamic_param_error status = "error" if not skip_on_dynamic_param_errors or not dynamic_param_error else "skip" if input_staging_exception: - job_data["execution_problem"] = "Input staging problem: %s" % util.unicodify(input_staging_exception) + job_data["execution_problem"] = f"Input staging problem: {util.unicodify(input_staging_exception)}" status = "error" job_data["status"] = status register_job_data(job_data) @@ -1196,7 +1196,7 @@ def _verify_outputs(testdef, history, jobs, tool_id, data_list, data_collection_ data = raw_data verify_assertions(data, assertions) except AssertionError as err: - errmsg = '%s different than expected\n' % description + errmsg = f'{description} different than expected\n' errmsg += util.unicodify(err) register_exception(AssertionError(errmsg)) @@ -1225,9 +1225,9 @@ def _verify_outputs(testdef, history, jobs, tool_id, data_list, data_collection_ def _format_stream(output, stream, format): output = output or '' if format: - msg = "---------------------- >> begin tool %s << -----------------------\n" % stream + msg = f"---------------------- >> begin tool {stream} << -----------------------\n" msg += output + "\n" - msg += "----------------------- >> end tool %s << ------------------------\n" % stream + msg += f"----------------------- >> end tool {stream} << ------------------------\n" else: msg = output return msg @@ -1346,7 +1346,7 @@ def test_data_iter(required_files): assert new_name, 'You must supply the new dataset name as the value tag of the edit_attributes tag' data_dict['name'] = new_name else: - raise Exception('edit_attributes type (%s) is unimplemented' % edit_att.get('type', None)) + raise Exception(f"edit_attributes type ({edit_att.get('type', None)}) is unimplemented") yield data_dict diff --git a/lib/galaxy/tool_util/verify/script.py b/lib/galaxy/tool_util/verify/script.py index 2aa07d0a030..6d4102768f2 100644 --- a/lib/galaxy/tool_util/verify/script.py +++ b/lib/galaxy/tool_util/verify/script.py @@ -222,7 +222,7 @@ def test_tools( destination = os.path.abspath(results.test_json) log.info(f"Report written to '{destination}'") log.info(results.info_message()) - log.info("Total tool test time: {}".format(dt.datetime.now() - tool_test_start)) + log.info(f"Total tool test time: {dt.datetime.now() - tool_test_start}") if history_created and not no_history_cleanup: galaxy_interactor.delete_history(test_history) diff --git a/lib/galaxy/tool_util/verify/test_data.py b/lib/galaxy/tool_util/verify/test_data.py index e2f814e66fc..de303814d80 100644 --- a/lib/galaxy/tool_util/verify/test_data.py +++ b/lib/galaxy/tool_util/verify/test_data.py @@ -110,7 +110,7 @@ class GitDataResolver(FileDataResolver): stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) - print("Executing %s" % cmd) + print(f"Executing {cmd}") p = subprocess.Popen(cmd, **subprocess_kwds) stdout, stderr = p.communicate() if p.returncode != 0: diff --git a/lib/galaxy/tools/__init__.py b/lib/galaxy/tools/__init__.py index 39357284d9a..6d753030472 100644 --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -424,9 +424,9 @@ class ToolBox(BaseGalaxyToolBox): for option_tup in options: selected = set_selected and option_tup[1] == tool_id if selected: - select_field.add_option('version %s' % option_tup[0], option_tup[1], selected=True) + select_field.add_option(f'version {option_tup[0]}', option_tup[1], selected=True) else: - select_field.add_option('version %s' % option_tup[0], option_tup[1]) + select_field.add_option(f'version {option_tup[0]}', option_tup[1]) return select_field @@ -777,7 +777,7 @@ class Tool(Dictifiable): self.id = guid if not dynamic and not self.id: - raise Exception("Missing tool 'id' for tool at '%s'" % tool_source) + raise Exception(f"Missing tool 'id' for tool at '{tool_source}'") profile = packaging.version.parse(str(self.profile)) if profile >= packaging.version.parse("16.04") and packaging.version.parse(VERSION_MAJOR) < profile: @@ -986,7 +986,7 @@ class Tool(Dictifiable): if refactoring_tool and self.python_template_version.release[0] < 3: # Could be a code file that uses python 2 syntax translated_code = str(refactoring_tool.refactor_string(code_string, name='auto_translated_code_file')) - compiled_code = compile(translated_code, "futurized_%s" % code_path, 'exec') + compiled_code = compile(translated_code, f"futurized_{code_path}", 'exec') exec(compiled_code, self.code_namespace) else: raise @@ -1066,7 +1066,7 @@ class Tool(Dictifiable): if repo_dir.name == self.repository_name: return str(repo_dir) else: - log.error("Problem finding repository dir for tool '%s'" % self.id) + log.error(f"Problem finding repository dir for tool '{self.id}'") return repository_base_dir @@ -1174,7 +1174,7 @@ class Tool(Dictifiable): elif len(enctypes) == 1: self.enctype = enctypes.pop() else: - raise Exception("Conflicting required enctypes: %s" % str(enctypes)) + raise Exception(f"Conflicting required enctypes: {str(enctypes)}") # Check if the tool either has no parameters or only hidden (and # thus hardcoded) FIXME: hidden parameters aren't # parameters at all really, and should be passed in a different @@ -1259,7 +1259,7 @@ class Tool(Dictifiable): group.min = int(input_source.get("min", 0)) # Use float instead of int so that 'inf' can be used for no max group.max = float(input_source.get("max", "inf")) - assert group.min <= group.max, ValueError("Tool with id '%s': min repeat count must be less-than-or-equal to the max." % self.id) + assert group.min <= group.max, ValueError(f"Tool with id '{self.id}': min repeat count must be less-than-or-equal to the max.") # Force default to be within min-max range group.default = min(max(group.default, group.min), group.max) rval[group.name] = group @@ -1280,7 +1280,7 @@ class Tool(Dictifiable): case = ConditionalWhen() case.value = case_value if case_inputs: - page_source = XmlPageSource(XML("%s" % case_inputs)) + page_source = XmlPageSource(XML(f"{case_inputs}")) case.inputs = self.parse_input_elem(page_source, enctypes, context) else: case.inputs = {} @@ -1290,7 +1290,7 @@ class Tool(Dictifiable): test_param_input_source = input_source.parse_test_input_source() group.test_param = self.parse_param_elem(test_param_input_source, enctypes, context) if group.test_param.optional: - log.debug("Tool with id '%s': declares a conditional test parameter as optional, this is invalid and will be ignored." % self.id) + log.debug(f"Tool with id '{self.id}': declares a conditional test parameter as optional, this is invalid and will be ignored.") group.test_param.optional = False possible_cases = list(group.test_param.legal_values) # store possible cases, undefined whens will have no inputs # Must refresh when test_param changes @@ -1677,7 +1677,7 @@ class Tool(Dictifiable): return False, e except Exception as e: 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)) + message = f"Error executing tool with id '{self.id}': {unicodify(e)}" return False, message if isinstance(out_data, dict): return job, list(out_data.items()) @@ -1685,7 +1685,7 @@ class Tool(Dictifiable): if isinstance(out_data, str): message = out_data else: - message = "Failure executing tool with id '%s' (invalid data returned from tool execution)" % self.id + message = f"Failure executing tool with id '{self.id}' (invalid data returned from tool execution)" return False, message def find_fieldstorage(self, x): @@ -1884,17 +1884,17 @@ class Tool(Dictifiable): rup_dict[p_name] = p_val DATA_URL = param_dict.get('DATA_URL', None) assert DATA_URL is not None, "DATA_URL parameter missing in tool config." - DATA_URL += "/%s/display" % str(data.id) - redirect_url += "?DATA_URL=%s" % DATA_URL + DATA_URL += f"/{str(data.id)}/display" + redirect_url += f"?DATA_URL={DATA_URL}" # Add the redirect_url_params to redirect_url for p_name in rup_dict: - redirect_url += "&{}={}".format(p_name, rup_dict[p_name]) + redirect_url += f"&{p_name}={rup_dict[p_name]}" # Add the current user email to redirect_url if data.history.user: USERNAME = str(data.history.user.email) else: USERNAME = 'Anonymous' - redirect_url += "&USERNAME=%s" % USERNAME + redirect_url += f"&USERNAME={USERNAME}" return redirect_url def call_hook(self, hook_name, *args, **kwargs): @@ -2330,7 +2330,7 @@ class Tool(Dictifiable): if (self.id != tool_id and self.old_id != tool_id) or self.version != tool_version: if self.id == tool_id: if tool_version: - message = 'This job was run with tool version "%s", which is not available. ' % tool_version + message = f'This job was run with tool version "{tool_version}", which is not available. ' if len(tools) > 1: message += 'You can re-run the job with the selected tool or choose another version of the tool. ' else: @@ -2433,7 +2433,7 @@ class ExpressionTool(Tool): EXPRESSION_INPUTS_NAME = "_expression_inputs_.json" def parse_command(self, tool_source): - self.command = "cd ../; %s" % expressions.EXPRESSION_SCRIPT_CALL + self.command = f"cd ../; {expressions.EXPRESSION_SCRIPT_CALL}" self.interpreter = None self._expression = tool_source.parse_expression().strip() @@ -2522,7 +2522,7 @@ class DataSourceTool(OutputParameterJSONTool): default_tool_action = DataSourceToolAction def _build_GALAXY_URL_parameter(self): - return ToolParameter.build(self, XML('' % self.id)) + return ToolParameter.build(self, XML(f'')) def parse_inputs(self, tool_source): super().parse_inputs(tool_source) @@ -2549,7 +2549,7 @@ class DataSourceTool(OutputParameterJSONTool): # use wrapped dataset to access certain values wrapped_data = param_dict.get(out_name) # allow multiple files to be created - cur_base_param_name = 'GALAXY|%s|' % out_name + cur_base_param_name = f'GALAXY|{out_name}|' cur_name = param_dict.get(cur_base_param_name + 'name', name) cur_dbkey = param_dict.get(cur_base_param_name + 'dkey', dbkey) cur_info = param_dict.get(cur_base_param_name + 'info', info) @@ -2581,7 +2581,7 @@ class AsyncDataSourceTool(DataSourceTool): tool_type = 'data_source_async' def _build_GALAXY_URL_parameter(self): - return ToolParameter.build(self, XML('' % self.id)) + return ToolParameter.build(self, XML(f'')) class DataDestinationTool(Tool): @@ -2712,7 +2712,7 @@ class DataManagerTool(OutputParameterJSONTool): # process results of tool data_manager_id = job.data_manager_association.data_manager_id data_manager = self.app.data_managers.get_manager(data_manager_id, None) - assert data_manager is not None, "Invalid data manager (%s) requested. It may have been removed before the job completed." % (data_manager_id) + assert data_manager is not None, f"Invalid data manager ({data_manager_id}) requested. It may have been removed before the job completed." data_manager.process_result(out_data) def get_default_history_by_trans(self, trans, create=False): @@ -2929,7 +2929,7 @@ class MergeCollectionTool(DatabaseOperationTool): if element_identifier not in identifiers_map: identifiers_map[element_identifier] = [] elif dupl_actions == "fail": - raise Exception("Duplicate collection element identifiers found for [%s]" % element_identifier) + raise Exception(f"Duplicate collection element identifiers found for [{element_identifier}]") identifiers_map[element_identifier].append(input_num) for copy, input_list in enumerate(input_lists): @@ -3105,7 +3105,7 @@ class SortTool(DatabaseOperationTool): sorted_elements = [old_elements_dict[line.strip()] for line in fh] except KeyError: hdca_history_name = f"{hdca.hid}: {hdca.name}" - message = "List of element identifiers does not match element identifiers in collection '%s'" % hdca_history_name + message = f"List of element identifiers does not match element identifiers in collection '{hdca_history_name}'" raise Exception(message) else: message = "Number of lines must match number of list elements (%i), but file has %i lines" @@ -3135,7 +3135,7 @@ class RelabelFromFileTool(DatabaseOperationTool): def add_copied_value_to_new_elements(new_label, dce_object): new_label = new_label.strip() if new_label in new_elements: - raise Exception("New identifier [%s] appears twice in resulting collection, these values must be unique." % new_label) + raise Exception(f"New identifier [{new_label}] appears twice in resulting collection, these values must be unique.") if getattr(dce_object, "history_content_type", None) == "dataset": copied_value = dce_object.copy(flush=False) else: @@ -3158,7 +3158,7 @@ class RelabelFromFileTool(DatabaseOperationTool): default = None if strict else element_identifier new_label = new_labels_dict.get(element_identifier, default) if not new_label: - raise Exception("Failed to find new label for identifier [%s]" % element_identifier) + raise Exception(f"Failed to find new label for identifier [{element_identifier}]") add_copied_value_to_new_elements(new_label, dce_object) else: # If new_labels_dataset_assoc is not a two-column tabular dataset we label with the current line of the dataset @@ -3167,7 +3167,7 @@ class RelabelFromFileTool(DatabaseOperationTool): add_copied_value_to_new_elements(new_labels[i], dce_object) for key in new_elements.keys(): if not re.match(r"^[\w\- \.,]+$", key): - raise Exception("Invalid new colleciton identifier [%s]" % key) + raise Exception(f"Invalid new colleciton identifier [{key}]") self._add_datasets_to_history(history, new_elements.values()) output_collections.create_collection( next(iter(self.outputs.values())), "output", elements=new_elements diff --git a/lib/galaxy/tools/actions/__init__.py b/lib/galaxy/tools/actions/__init__.py index 977a9da76e9..018565e36aa 100644 --- a/lib/galaxy/tools/actions/__init__.py +++ b/lib/galaxy/tools/actions/__init__.py @@ -104,7 +104,7 @@ class DefaultToolAction: record_permission(action, role_id) else: if not trans.app.security_agent.can_access_dataset(current_user_roles, data.dataset): - raise ItemAccessibilityException("User does not have permission to use a dataset (%s) provided for input." % data.id) + raise ItemAccessibilityException(f"User does not have permission to use a dataset ({data.id}) provided for input.") permissions = trans.app.security_agent.get_permissions(data.dataset) for action, roles in permissions.items(): for role in roles: @@ -127,7 +127,7 @@ class DefaultToolAction: input_datasets[prefix + conversion_name + str(i + 1)] = new_data conversions.append((conversion_name, new_data)) else: - raise Exception('A path for explicit datatype conversion has not been found: {} --/--> {}'.format(input_datasets[prefix + input.name + str(i + 1)].extension, conversion_extensions)) + raise Exception(f'A path for explicit datatype conversion has not been found: {input_datasets[prefix + input.name + str(i + 1)].extension} --/--> {conversion_extensions}') if parent: parent[input.name][i] = input_datasets[prefix + input.name + str(i + 1)] for conversion_name, conversion_data in conversions: @@ -147,7 +147,7 @@ class DefaultToolAction: input_datasets[prefix + conversion_name] = new_data conversions.append((conversion_name, new_data)) else: - raise Exception('A path for explicit datatype conversion has not been found: {} --/--> {}'.format(input_datasets[prefix + input.name].extension, conversion_extensions)) + raise Exception(f'A path for explicit datatype conversion has not been found: {input_datasets[prefix + input.name].extension} --/--> {conversion_extensions}') target_dict = parent if not target_dict: target_dict = param_values @@ -246,7 +246,7 @@ class DefaultToolAction: return input_dataset_collections def _check_access(self, tool, trans): - assert tool.allow_user_access(trans.user), "User (%s) is not allowed to access this tool." % (trans.user) + assert tool.allow_user_access(trans.user), f"User ({trans.user}) is not allowed to access this tool." def _collect_inputs(self, tool, trans, incoming, history, current_user_roles, collection_info): """ Collect history as well as input datasets and collections. """ @@ -333,7 +333,7 @@ class DefaultToolAction: identifier = getattr(data, "element_identifier", None) if identifier is not None: - incoming["%s|__identifier__" % name] = identifier + incoming[f"{name}|__identifier__"] = identifier # Collect chromInfo dataset and add as parameters to incoming (chrom_info, db_dataset) = execution_cache.get_chrom_info(tool.id, input_dbkey) @@ -585,10 +585,10 @@ class DefaultToolAction: # to send back to the current Galaxy instance GALAXY_URL = incoming.get('GALAXY_URL', None) assert GALAXY_URL is not None, "GALAXY_URL parameter missing in tool config." - redirect_url += "&GALAXY_URL=%s" % GALAXY_URL + redirect_url += f"&GALAXY_URL={GALAXY_URL}" # Job should not be queued, so set state to ok job.set_state(app.model.Job.states.OK) - job.info = "Redirected to: %s" % redirect_url + job.info = f"Redirected to: {redirect_url}" trans.sa_session.add(job) trans.sa_session.flush() trans.response.send_redirect(url_for(controller='tool_runner', action='redirect', redirect_url=redirect_url)) @@ -602,7 +602,7 @@ class DefaultToolAction: # Dispatch to a job handler. enqueue() is responsible for flushing the job 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) + trans.log_event(f"Added job to the job queue, id: {str(job.id)}", tool_id=job.tool_id) return job, out_data, history def _remap_job_on_rerun(self, trans, galaxy_session, rerun_remap_job_id, current_job, out_data): @@ -688,7 +688,7 @@ class DefaultToolAction: input_names = [] for data in reversed(list(inp_data.values())): if getattr(data, "hid", None): - input_names.append('data %s' % data.hid) + input_names.append(f'data {data.hid}') return on_text_for_names(input_names) @@ -839,7 +839,7 @@ class OutputCollections: # sooner. raise Exception("Could not determine collection type to create.") if collection_type_source not in input_collections: - raise Exception("Could not find collection type source with name [%s]." % collection_type_source) + raise Exception(f"Could not find collection type source with name [{collection_type_source}].") # Using the collection_type_source string we get the DataCollectionToolParameter data_param = self.tool.inputs @@ -949,7 +949,7 @@ def filter_output(tool, output, incoming): if not eval(filter.text.strip(), globals(), incoming): return True # do not create this dataset except Exception as e: - log.debug('Tool %s output %s: dataset output filter (%s) failed: %s' % (tool.id, output.name, filter.text, e)) + log.debug(f'Tool {tool.id} output {output.name}: dataset output filter ({filter.text}) failed: {e}') return False diff --git a/lib/galaxy/tools/actions/data_manager.py b/lib/galaxy/tools/actions/data_manager.py index b4d8aa3d8cd..03ded8baa12 100644 --- a/lib/galaxy/tools/actions/data_manager.py +++ b/lib/galaxy/tools/actions/data_manager.py @@ -15,5 +15,5 @@ class DataManagerToolAction(DefaultToolAction): trans.sa_session.add(assoc) trans.sa_session.flush() else: - log.error("Got bad return value from DefaultToolAction.execute(): %s" % (rval)) + log.error(f"Got bad return value from DefaultToolAction.execute(): {rval}") return rval diff --git a/lib/galaxy/tools/actions/history_imp_exp.py b/lib/galaxy/tools/actions/history_imp_exp.py index 8e265ae1092..d6f31f07756 100644 --- a/lib/galaxy/tools/actions/history_imp_exp.py +++ b/lib/galaxy/tools/actions/history_imp_exp.py @@ -70,7 +70,7 @@ class ImportHistoryToolAction(ToolAction): # Queue the job for execution 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) + trans.log_event(f"Added import history job to the job queue, id: {str(job.id)}", tool_id=job.tool_id) return job, {} diff --git a/lib/galaxy/tools/actions/metadata.py b/lib/galaxy/tools/actions/metadata.py index 33647c5104c..28cb79de8f1 100644 --- a/lib/galaxy/tools/actions/metadata.py +++ b/lib/galaxy/tools/actions/metadata.py @@ -27,7 +27,7 @@ class SetMetadataToolAction(ToolAction): history_id, trans.user, incoming, set_output_hid, overwrite, history, job_params) # FIXME: can remove this when logging in execute_via_app method. - trans.log_event("Added set external metadata job to the job queue, id: %s" % str(job.id), tool_id=job.tool_id) + trans.log_event(f"Added set external metadata job to the job queue, id: {str(job.id)}", tool_id=job.tool_id) return job, odict def execute_via_app(self, tool, app, session_id, history_id, user=None, diff --git a/lib/galaxy/tools/actions/model_operations.py b/lib/galaxy/tools/actions/model_operations.py index c152bb81e1c..91474a35ae5 100644 --- a/lib/galaxy/tools/actions/model_operations.py +++ b/lib/galaxy/tools/actions/model_operations.py @@ -68,7 +68,7 @@ class ModelOperationToolAction(DefaultToolAction): # Queue the job for execution # trans.app.job_manager.job_queue.put( job.id, tool.id ) # trans.log_event( "Added database job action to the job queue, id: %s" % str(job.id), tool_id=job.tool_id ) - log.info("Calling produce_outputs, tool is %s" % tool) + log.info(f"Calling produce_outputs, tool is {tool}") return job, out_data, history def _produce_outputs(self, trans, tool, out_data, output_collections, incoming, history, tags): diff --git a/lib/galaxy/tools/actions/upload.py b/lib/galaxy/tools/actions/upload.py index 6ad5ff4665d..919d23e9742 100644 --- a/lib/galaxy/tools/actions/upload.py +++ b/lib/galaxy/tools/actions/upload.py @@ -26,7 +26,7 @@ class BaseUploadToolAction(ToolAction): persisting_uploads_timer = ExecutionTimer() incoming = upload_common.persist_uploads(incoming, trans) - log.debug("Persisted uploads %s" % persisting_uploads_timer) + log.debug(f"Persisted uploads {persisting_uploads_timer}") rval = self._setup_job(tool, trans, incoming, dataset_upload_inputs, history) return rval @@ -37,7 +37,7 @@ class BaseUploadToolAction(ToolAction): """Wrapper around upload_common.create_job with a timer.""" create_job_timer = ExecutionTimer() rval = upload_common.create_job(*args, **kwds) - log.debug("Created upload job %s" % create_job_timer) + log.debug(f"Created upload job {create_job_timer}") return rval @@ -52,7 +52,7 @@ class UploadToolAction(BaseUploadToolAction): json_file_path = upload_common.create_paramfile(trans, uploaded_datasets) data_list = [ud.data for ud in uploaded_datasets] - log.debug("Checked uploads %s" % check_timer) + log.debug(f"Checked uploads {check_timer}") return self._create_job( trans, incoming, tool, json_file_path, data_list, history=history ) diff --git a/lib/galaxy/tools/actions/upload_common.py b/lib/galaxy/tools/actions/upload_common.py index 9abb79fa14a..d4fb3a2fc5f 100644 --- a/lib/galaxy/tools/actions/upload_common.py +++ b/lib/galaxy/tools/actions/upload_common.py @@ -27,7 +27,7 @@ log = logging.getLogger(__name__) def validate_datatype_extension(datatypes_registry, ext): if ext and ext not in ('auto', 'data') and not datatypes_registry.get_datatype_by_extension(ext): - raise RequestParameterInvalidException("Requested extension '%s' unknown, cannot upload dataset." % ext) + raise RequestParameterInvalidException(f"Requested extension '{ext}' unknown, cannot upload dataset.") def validate_url(url, ip_allowlist): @@ -443,7 +443,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) + trans.log_event(f"Added job to the job queue, id: {str(job.id)}", tool_id=job.tool_id) output = {} for i, v in enumerate(outputs): if not hasattr(output_object, "collection_type"): diff --git a/lib/galaxy/tools/cache.py b/lib/galaxy/tools/cache.py index 351e654ba67..068fc7cc66f 100644 --- a/lib/galaxy/tools/cache.py +++ b/lib/galaxy/tools/cache.py @@ -194,7 +194,7 @@ class ToolCache: # If by chance the file is being removed while calculating the hash or modtime # we don't want the thread to die. if removed_tool_ids: - log.debug("Removed the following tools from cache: %s" % removed_tool_ids) + log.debug(f"Removed the following tools from cache: {removed_tool_ids}") return removed_tool_ids def _should_cleanup(self, config_filename): diff --git a/lib/galaxy/tools/data/__init__.py b/lib/galaxy/tools/data/__init__.py index c3b922f2c48..612df1bd591 100644 --- a/lib/galaxy/tools/data/__init__.py +++ b/lib/galaxy/tools/data/__init__.py @@ -159,7 +159,7 @@ class ToolDataTableManager: tool_data_path=tool_data_path, from_shed_config=True) except Exception as e: - error_message = 'Error attempting to parse file {}: {}'.format(str(os.path.split(config_filename)[1]), util.unicodify(e)) + error_message = f'Error attempting to parse file {str(os.path.split(config_filename)[1])}: {util.unicodify(e)}' log.debug(error_message, exc_info=True) table_elems = [] if persist: @@ -245,7 +245,7 @@ class ToolDataTable: @classmethod def from_elem(cls, table_elem, tool_data_path, from_shed_config, filename, tool_data_path_files, other_config_dict=None): table_type = table_elem.get('type', 'tabular') - assert table_type in tool_data_table_types, "Unknown data table type '%s'" % table_type + assert table_type in tool_data_table_types, f"Unknown data table type '{table_type}'" return tool_data_table_types[table_type](table_elem, tool_data_path, from_shed_config=from_shed_config, filename=filename, tool_data_path_files=tool_data_path_files, other_config_dict=other_config_dict) def __init__(self, config_element, tool_data_path, from_shed_config=False, filename=None, tool_data_path_files=None, other_config_dict=None): @@ -359,7 +359,7 @@ class TabularToolDataTable(ToolDataTable, Dictifiable): # Handle URLs as files filename = file_element.get('url', None) if filename: - tmp_file = NamedTemporaryFile(prefix='TTDT_URL_%s-' % self.name, mode='w') + tmp_file = NamedTemporaryFile(prefix=f'TTDT_URL_{self.name}-', mode='w') try: tmp_file.write(requests.get(filename, timeout=url_timeout).text) except Exception as e: @@ -405,9 +405,9 @@ class TabularToolDataTable(ToolDataTable, Dictifiable): if self.tool_data_path_files.exists(corrected_filename): filename = corrected_filename found = True - elif not from_shed_config and self.tool_data_path_files.exists("%s.sample" % corrected_filename): - log.info("Could not find tool data %s, reading sample" % corrected_filename) - filename = "%s.sample" % corrected_filename + elif not from_shed_config and self.tool_data_path_files.exists(f"{corrected_filename}.sample"): + log.info(f"Could not find tool data {corrected_filename}, reading sample") + filename = f"{corrected_filename}.sample" found = True errors = [] @@ -661,7 +661,7 @@ class TabularToolDataTable(ToolDataTable, Dictifiable): last_char = data_table_fh.read(1) if last_char not in [b'\n', b'\r']: data_table_fh.write(b'\n') - fields = "%s\n" % self.separator.join(fields) + fields = f"{self.separator.join(fields)}\n" data_table_fh.write(fields.encode('utf-8')) return not is_error diff --git a/lib/galaxy/tools/data_fetch.py b/lib/galaxy/tools/data_fetch.py index 2a571be51ce..9c800d4aa6e 100644 --- a/lib/galaxy/tools/data_fetch.py +++ b/lib/galaxy/tools/data_fetch.py @@ -77,7 +77,7 @@ def _fetch_target(upload_config, target): _, elements_from_path = _has_src_to_path(upload_config, target_or_item, is_dataset=False) items = _directory_to_items(elements_from_path) else: - raise Exception("Unknown elements from type encountered [%s]" % elements_from) + raise Exception(f"Unknown elements from type encountered [{elements_from}]") if items: del target_or_item["elements_from"] @@ -87,11 +87,11 @@ def _fetch_target(upload_config, target): try: _for_each_src(expand_elements_from, target) except Exception as e: - expansion_error = "Error expanding elements/items for upload destination. %s" % str(e) + expansion_error = f"Error expanding elements/items for upload destination. {str(e)}" if expansion_error is None: items = target.get("elements", None) - assert items is not None, "No element definition found for destination [%s]" % destination + assert items is not None, f"No element definition found for destination [{destination}]" else: items = [] @@ -188,7 +188,7 @@ def _fetch_target(upload_config, target): return rval else: if composite: - raise Exception("Non-composite datatype [%s] attempting to be created with composite data." % datatype) + raise Exception(f"Non-composite datatype [{datatype}] attempting to be created with composite data.") return _resolve_item_with_primary(item) def _resolve_item_with_primary(item): @@ -314,7 +314,7 @@ def _fetch_target(upload_config, target): if is_collection and not upload_config.allow_failed_collections and len(failed_elements) > 0: element_error = "Failed to fetch collection element(s):\n" for failed_element in failed_elements: - element_error += "\n- %s" % failed_element["error_message"] + element_error += f"\n- {failed_element['error_message']}" fetched_target["error_message"] = element_error fetched_target["elements"] = None else: @@ -384,7 +384,7 @@ def _has_src_to_path(upload_config, item, is_dataset=False): try: path = sniff.stream_url_to_file(url, file_sources=get_file_sources(upload_config.working_directory)) except Exception as e: - raise Exception("Failed to fetch url {}. {}".format(url, str(e))) + raise Exception(f"Failed to fetch url {url}. {str(e)}") if not is_dataset: # Actual target dataset will validate and put results in dict diff --git a/lib/galaxy/tools/data_manager/manager.py b/lib/galaxy/tools/data_manager/manager.py index dd823b2e925..25f9f89214b 100644 --- a/lib/galaxy/tools/data_manager/manager.py +++ b/lib/galaxy/tools/data_manager/manager.py @@ -50,7 +50,7 @@ class DataManagers: return # we are not able to load any data managers root = tree.getroot() if root.tag != 'data_managers': - log.error('A data managers configuration must have a "data_managers" tag as the root. "%s" is present' % (root.tag)) + log.error(f'A data managers configuration must have a "data_managers" tag as the root. "{root.tag}" is present') return if store_tool_path: tool_path = root.get('tool_path', None) @@ -78,12 +78,12 @@ class DataManagers: return None if add_manager: self.add_manager(data_manager) - log.debug('Loaded Data Manager: %s' % (data_manager.id)) + log.debug(f'Loaded Data Manager: {data_manager.id}') return data_manager def add_manager(self, data_manager): if data_manager.id in self.data_managers: - log.warning("A data manager has been defined twice: %s " % (data_manager.id)) + log.warning(f"A data manager has been defined twice: {data_manager.id} ") self.data_managers[data_manager.id] = data_manager for data_table_name in data_manager.data_tables.keys(): if data_table_name not in self.managed_data_tables: @@ -136,7 +136,7 @@ class DataManager: self.load_from_element(elem, tool_path or self.data_managers.tool_path) def load_from_element(self, elem, tool_path): - assert elem.tag == 'data_manager', 'A data manager configuration must have a "data_manager" tag as the root. "%s" is present' % (elem.tag) + assert elem.tag == 'data_manager', f'A data manager configuration must have a "data_manager" tag as the root. "{elem.tag}" is present' self.declared_id = elem.get('id') self.guid = elem.get('guid') path = elem.get('tool_file') @@ -146,7 +146,7 @@ class DataManager: if path is None: tool_elem = elem.find('tool') - assert tool_elem is not None, "Error loading tool for data manager. Make sure that a tool_file attribute or a tool tag set has been defined:\n%s" % (util.xml_to_string(elem)) + assert tool_elem is not None, f"Error loading tool for data manager. Make sure that a tool_file attribute or a tool tag set has been defined:\n{util.xml_to_string(elem)}" path = tool_elem.get("file") tool_guid = tool_elem.get("guid") # need to determine repository info so that dependencies will work correctly @@ -161,7 +161,7 @@ class DataManager: shed_conf = self.data_managers.app.toolbox.get_shed_config_dict_by_filename(shed_conf_file) if shed_conf: tool_path = shed_conf.get("tool_path", tool_path) - assert path is not None, "A tool file path could not be determined:\n%s" % (util.xml_to_string(elem)) + assert path is not None, f"A tool file path could not be determined:\n{util.xml_to_string(elem)}" self.load_tool(os.path.join(tool_path, path), guid=tool_guid, data_manager_id=self.id, @@ -201,9 +201,9 @@ class DataManager: if value_translation in VALUE_TRANSLATION_FUNCTIONS: value_translation = VALUE_TRANSLATION_FUNCTIONS[value_translation] else: - raise ValueError("Unsupported value translation function: '%s'" % (value_translation)) + raise ValueError(f"Unsupported value translation function: '{value_translation}'") else: - assert value_translation_type == DEFAULT_VALUE_TRANSLATION_TYPE, ValueError("Unsupported value translation type: '%s'" % (value_translation_type)) + assert value_translation_type == DEFAULT_VALUE_TRANSLATION_TYPE, ValueError(f"Unsupported value translation type: '{value_translation_type}'") self.value_translation_by_data_table_column[data_table_name][data_table_coumn_name].append(value_translation) for move_elem in column_elem.findall('move'): @@ -282,10 +282,10 @@ class DataManager: data_table = self.data_managers.app.tool_data_tables.get(data_table_name, None) if data_table is None: - log.error('The data manager "{}" returned an unknown data table "{}" with new entries "{}". These entries will not be created. Please confirm that an entry for "{}" exists in your "{}" file.'.format(self.id, data_table_name, data_table_values, data_table_name, 'tool_data_table_conf.xml')) + log.error(f"The data manager \"{self.id}\" returned an unknown data table \"{data_table_name}\" with new entries \"{data_table_values}\". These entries will not be created. Please confirm that an entry for \"{data_table_name}\" exists in your \"tool_data_table_conf.xml\" file.") continue # next table name if not isinstance(data_table, SUPPORTED_DATA_TABLE_TYPES): - log.error('The data manager "{}" returned an unsupported data table "{}" with type "{}" with new entries "{}". These entries will not be created. Please confirm that the data table is of a supported type ({}).'.format(self.id, data_table_name, type(data_table), data_table_values, SUPPORTED_DATA_TABLE_TYPES)) + log.error(f'The data manager "{self.id}" returned an unsupported data table "{data_table_name}" with type "{type(data_table)}" with new entries "{data_table_values}". These entries will not be created. Please confirm that the data table is of a supported type ({SUPPORTED_DATA_TABLE_TYPES}).') continue # next table name output_ref_values = {} if data_table_name in self.output_ref_by_data_table: diff --git a/lib/galaxy/tools/error_reports/plugins/email.py b/lib/galaxy/tools/error_reports/plugins/email.py index 7a31bbf613e..f1debbf93d7 100644 --- a/lib/galaxy/tools/error_reports/plugins/email.py +++ b/lib/galaxy/tools/error_reports/plugins/email.py @@ -31,7 +31,7 @@ class EmailPlugin(ErrorPlugin): error_reporter.send_report(user=job.get_user(), email=kwargs.get('email', None), message=kwargs.get('message', None), redact_user_details_in_bugreport=self.redact_user_details_in_bugreport) return ("Your error report has been sent", "success") except Exception as e: - return ("An error occurred sending the report by email: %s" % unicodify(e), "danger") + return (f"An error occurred sending the report by email: {unicodify(e)}", "danger") __all__ = ('EmailPlugin', ) diff --git a/lib/galaxy/tools/error_reports/plugins/github.py b/lib/galaxy/tools/error_reports/plugins/github.py index b7b649edc99..c7711a6fbce 100644 --- a/lib/galaxy/tools/error_reports/plugins/github.py +++ b/lib/galaxy/tools/error_reports/plugins/github.py @@ -76,7 +76,7 @@ class GithubPlugin(BaseGitPlugin): # Connect to the repo if github_projecturl not in self.git_project_cache: - self.git_project_cache[github_projecturl] = self.github.get_repo('%s' % github_projecturl) + self.git_project_cache[github_projecturl] = self.github.get_repo(f'{github_projecturl}') gh_project = self.git_project_cache[github_projecturl] # Make sure we keep a cache of the issues, per tool in this case @@ -84,7 +84,7 @@ class GithubPlugin(BaseGitPlugin): self._fill_issue_cache(gh_project, issue_cache_key) # Retrieve label - label = self.get_label('{}/{}'.format(unicodify(job.tool_id), unicodify(job.tool_version)), gh_project, issue_cache_key) + label = self.get_label(f'{unicodify(job.tool_id)}/{unicodify(job.tool_version)}', gh_project, issue_cache_key) # Generate information for the tool error_title = self._generate_error_title(job) diff --git a/lib/galaxy/tools/error_reports/plugins/gitlab.py b/lib/galaxy/tools/error_reports/plugins/gitlab.py index 136b272438f..ada1ff7462a 100644 --- a/lib/galaxy/tools/error_reports/plugins/gitlab.py +++ b/lib/galaxy/tools/error_reports/plugins/gitlab.py @@ -124,7 +124,7 @@ class GitLabPlugin(BaseGitPlugin): self.git_project_cache[gitlab_projecturl] = self.gitlab.projects.get(gitlab_urlencodedpath) except gitlab.GitlabGetError: # Handle scenario where the repository doesn't exist so we can still continue - log.warning("GitLab error reporting - Repository '%s' doesn't exist, using default repository." % gitlab_urlencodedpath) + log.warning(f"GitLab error reporting - Repository '{gitlab_urlencodedpath}' doesn't exist, using default repository.") # Redo some of the previous steps to recover from such an issue but continue issue creation gitlab_projecturl = "/".join((self.git_default_repo_owner, self.git_default_repo_name)) gitlab_urlencodedpath = urllib.quote_plus(gitlab_projecturl) @@ -147,10 +147,10 @@ class GitLabPlugin(BaseGitPlugin): if len(gl_project.commits.list()) > 0: gl_useremail = gl_project.commits.list()[0].attributes['author_email'] if not self.redact_user_details_in_bugreport: - log.debug("GitLab error reporting - Last author email: %s" % gl_useremail) + log.debug(f"GitLab error reporting - Last author email: {gl_useremail}") if gl_useremail not in self.git_username_id_cache: gl_emailquery = self.gitlab.users.list(search=gl_useremail) - log.debug("GitLab error reporting - User list: %s" % gl_emailquery) + log.debug(f"GitLab error reporting - User list: {gl_emailquery}") if len(gl_emailquery) > 0: log.debug("GitLab error reporting - Last Committer user ID: %d" % gl_emailquery[0].get_id()) @@ -166,12 +166,12 @@ class GitLabPlugin(BaseGitPlugin): # Check if issue is closed, otherwise reopen it issue_id = self.issue_cache[issue_cache_key][error_title] issue = gl_project.issues.get(issue_id) - log.info("GitLab error reporting - Issue state is %s" % issue.state) + log.info(f"GitLab error reporting - Issue state is {issue.state}") if issue.state == 'closed': # Reopen issue issue.state_event = 'reopen' issue.save() - log.info("GitLab error reporting - Reopened issue %s" % issue_id) + log.info(f"GitLab error reporting - Reopened issue {issue_id}") # Add a comment to an issue... self._append_issue(issue_cache_key, error_title, error_message, diff --git a/lib/galaxy/tools/error_reports/plugins/json.py b/lib/galaxy/tools/error_reports/plugins/json.py index d9b4c1f9061..5cf959c721c 100644 --- a/lib/galaxy/tools/error_reports/plugins/json.py +++ b/lib/galaxy/tools/error_reports/plugins/json.py @@ -56,7 +56,7 @@ class JsonPlugin(ErrorPlugin): data['message'] = kwargs['message'] json.dump(data, handle, indent=2) - return ('Wrote error report to %s' % path, 'success') + return (f'Wrote error report to {path}', 'success') __all__ = ('JsonPlugin', ) diff --git a/lib/galaxy/tools/error_reports/plugins/sentry.py b/lib/galaxy/tools/error_reports/plugins/sentry.py index 3415e831a65..b14ed7a42a2 100644 --- a/lib/galaxy/tools/error_reports/plugins/sentry.py +++ b/lib/galaxy/tools/error_reports/plugins/sentry.py @@ -119,7 +119,7 @@ class SentryPlugin(ErrorPlugin): extra=extra, message=unicodify(error_message), ) - return ('Submitted bug report to Sentry. Your guru meditation number is %s' % response, 'success') + return (f'Submitted bug report to Sentry. Your guru meditation number is {response}', 'success') __all__ = ('SentryPlugin', ) diff --git a/lib/galaxy/tools/errors.py b/lib/galaxy/tools/errors.py index 4e63dab16ee..fadb9a9bebe 100644 --- a/lib/galaxy/tools/errors.py +++ b/lib/galaxy/tools/errors.py @@ -141,7 +141,7 @@ class ErrorReporter: assert hda is not None, ValueError("No HDA yet") except Exception: hda = sa_session.query(model.HistoryDatasetAssociation).get(app.security.decode_id(hda_id)) - assert isinstance(hda, model.HistoryDatasetAssociation), ValueError("Bad value provided for HDA (%s)." % (hda)) + assert isinstance(hda, model.HistoryDatasetAssociation), ValueError(f"Bad value provided for HDA ({hda}).") self.hda = hda # Get the associated job self.job = hda.creating_job @@ -181,12 +181,12 @@ class ErrorReporter: # user.) email_str = 'redacted' if user: - email_str += ' (user: %s)' % user.id + email_str += f' (user: {user.id})' else: if user: - email_str = "'%s'" % user.email + email_str = f"'{user.email}'" if email and user.email != email: - email_str += " (providing preferred contact email '%s')" % email + email_str += f" (providing preferred contact email '{email}')" else: email_str = "'%s'" % (email or 'anonymous') @@ -245,7 +245,7 @@ class EmailErrorReporter(ErrorReporter): error_msg = validate_email_str(email) if not error_msg and self._can_access_dataset(user): to += ', ' + email.strip() - subject = "Galaxy tool error report from %s" % email + subject = f"Galaxy tool error report from {email}" try: subject = "{} ({})".format( subject, self.app.toolbox.get_tool(self.job.tool_id, self.job.tool_version).old_id) diff --git a/lib/galaxy/tools/evaluation.py b/lib/galaxy/tools/evaluation.py index 9de9998c145..dd7a62d12d8 100644 --- a/lib/galaxy/tools/evaluation.py +++ b/lib/galaxy/tools/evaluation.py @@ -545,7 +545,7 @@ class ToolEvaluator: self.__write_workdir_file(config_filename, environment_variable_template, param_dict, is_template=is_template, strip=environment_variable_def.get("strip", False)) config_file_basename = os.path.basename(config_filename) # environment setup in job file template happens before `cd $working_directory` - environment_variable["value"] = '`cat "%s/%s"`' % (self.compute_environment.env_config_directory(), config_file_basename) + environment_variable["value"] = f'`cat "{self.compute_environment.env_config_directory()}/{config_file_basename}"`' environment_variable["raw"] = True environment_variable["job_directory_path"] = config_filename environment_variables.append(environment_variable) @@ -553,11 +553,11 @@ class ToolEvaluator: home_dir = self.compute_environment.home_directory() tmp_dir = self.compute_environment.tmp_directory() if home_dir: - environment_variable = dict(name="HOME", value='"%s"' % home_dir, raw=True) + environment_variable = dict(name="HOME", value=f'"{home_dir}"', raw=True) environment_variables.append(environment_variable) if tmp_dir: for tmp_directory_var in self.tool.tmp_directory_vars: - environment_variable = dict(name=tmp_directory_var, value='"%s"' % tmp_dir, raw=True) + environment_variable = dict(name=tmp_directory_var, value=f'"{tmp_dir}"', raw=True) environment_variables.append(environment_variable) self.environment_variables = environment_variables return environment_variables @@ -600,7 +600,7 @@ class ToolEvaluator: rval = json.dumps(file_sources_dict) return rval, False else: - raise Exception("Unknown config file type %s" % config_type) + raise Exception(f"Unknown config file type {config_type}") return json.dumps(wrapped_json.json_wrap(self.tool.inputs, self.param_dict, diff --git a/lib/galaxy/tools/execute.py b/lib/galaxy/tools/execute.py index 48ac8c23884..dda052a93cf 100644 --- a/lib/galaxy/tools/execute.py +++ b/lib/galaxy/tools/execute.py @@ -127,7 +127,7 @@ def execute(trans, tool, mapping_params, history, rerun_remap_job_id=None, colle for job in execution_tracker.successful_jobs: # Put the job in the queue if tracking in memory tool.app.job_manager.enqueue(job, tool=tool, flush=False) - trans.log_event("Added job to the job queue, id: %s" % str(job.id), tool_id=tool_id) + trans.log_event(f"Added job to the job queue, id: {str(job.id)}", tool_id=tool_id) trans.sa_session.flush() if has_remaining_jobs: diff --git a/lib/galaxy/tools/expressions/script.py b/lib/galaxy/tools/expressions/script.py index 0cb18ae7464..f19bd697b6e 100644 --- a/lib/galaxy/tools/expressions/script.py +++ b/lib/galaxy/tools/expressions/script.py @@ -1,7 +1,7 @@ import os EXPRESSION_SCRIPT_NAME = "_evaluate_expression_.py" -EXPRESSION_SCRIPT_CALL = "python %s" % EXPRESSION_SCRIPT_NAME +EXPRESSION_SCRIPT_CALL = f"python {EXPRESSION_SCRIPT_NAME}" def write_evalute_script(in_directory): diff --git a/lib/galaxy/tools/imp_exp/__init__.py b/lib/galaxy/tools/imp_exp/__init__.py index 1989a2afc18..e836ba325b1 100644 --- a/lib/galaxy/tools/imp_exp/__init__.py +++ b/lib/galaxy/tools/imp_exp/__init__.py @@ -73,7 +73,7 @@ class JobImportHistoryArchiveWrapper: shutil.rmtree(archive_dir) except Exception as e: - jiha.job.tool_stderr += "Error cleaning up history import job: %s" % e + jiha.job.tool_stderr += f"Error cleaning up history import job: {e}" self.sa_session.flush() raise diff --git a/lib/galaxy/tools/imp_exp/export_history.py b/lib/galaxy/tools/imp_exp/export_history.py index 856fc741057..7cd45abf0a7 100644 --- a/lib/galaxy/tools/imp_exp/export_history.py +++ b/lib/galaxy/tools/imp_exp/export_history.py @@ -24,7 +24,7 @@ def create_archive(export_directory, out_file, gzip=False): print('Created history archive.') return 0 except Exception as e: - print('Error creating history archive: %s' % unicodify(e), file=sys.stderr) + print(f'Error creating history archive: {unicodify(e)}', file=sys.stderr) return 1 finally: shutil.rmtree(export_directory, ignore_errors=True) @@ -69,7 +69,7 @@ def _write_to_destination(file_sources_path, out_file, destination_uri): def get_file_sources(file_sources_path): - assert os.path.exists(file_sources_path), "file sources path [%s] does not exist" % file_sources_path + assert os.path.exists(file_sources_path), f"file sources path [{file_sources_path}] does not exist" from galaxy.files import ConfiguredFileSources with open(file_sources_path) as f: file_sources_as_dict = json.load(f) diff --git a/lib/galaxy/tools/imp_exp/unpack_tar_gz_archive.py b/lib/galaxy/tools/imp_exp/unpack_tar_gz_archive.py index 83deca60fb5..e39fd240f91 100644 --- a/lib/galaxy/tools/imp_exp/unpack_tar_gz_archive.py +++ b/lib/galaxy/tools/imp_exp/unpack_tar_gz_archive.py @@ -21,7 +21,7 @@ MAX_SIZE = 100 * math.pow(2, 30) def get_file_sources(file_sources_path): - assert os.path.exists(file_sources_path), "file sources path [%s] does not exist" % file_sources_path + assert os.path.exists(file_sources_path), f"file sources path [{file_sources_path}] does not exist" from galaxy.files import ConfiguredFileSources with open(file_sources_path) as f: file_sources_as_dict = json.load(f) @@ -41,7 +41,7 @@ def check_archive(archive_file, dest_dir): dest_dir, arc_path )).startswith(dest_dir.rstrip(os.sep) + os.sep), \ - "Archive member would extract outside target directory: %s" % arc_path + f"Archive member would extract outside target directory: {arc_path}" return True diff --git a/lib/galaxy/tools/parameters/__init__.py b/lib/galaxy/tools/parameters/__init__.py index d01a61cf884..f18c554d4a6 100644 --- a/lib/galaxy/tools/parameters/__init__.py +++ b/lib/galaxy/tools/parameters/__init__.py @@ -127,13 +127,13 @@ def visit_input_values(inputs, input_values, callback, name_prefix='', label_pre 'parent': input_values, 'value': value, 'prefixed_name': f'{name_prefix}{input.name}', - 'prefixed_label': '{}{}'.format(label_prefix, input.label or input.name), + 'prefixed_label': f'{label_prefix}{input.label or input.name}', 'prefix': parent_prefix, 'context': context, 'error': error } if input.name not in input_values: - args['error'] = 'No value found for \'%s\'.' % args.get('prefixed_label') + args['error'] = f"No value found for '{args.get('prefixed_label')}'." new_value = callback(**args) if no_replacement_value is REPLACE_ON_TRUTHY: replace = bool(new_value) @@ -408,7 +408,7 @@ def _populate_state_legacy(request_context, inputs, incoming, state, errors, pre state[input.name] = input.get_initial_value(request_context, context) key = prefix + input.name group_state = state[input.name] - group_prefix = '%s|' % (key) + group_prefix = f'{key}|' if input.type == 'repeat': rep_index = 0 del group_state[:] diff --git a/lib/galaxy/tools/parameters/basic.py b/lib/galaxy/tools/parameters/basic.py index 673d89aeb86..14c2994ae7a 100644 --- a/lib/galaxy/tools/parameters/basic.py +++ b/lib/galaxy/tools/parameters/basic.py @@ -292,7 +292,7 @@ class ToolParameter(Dictifiable): param_name = cls.parse_name(input_source) param_type = input_source.get('type') if not param_type: - raise ValueError("parameter '%s' requires a 'type'" % (param_name)) + raise ValueError(f"parameter '{param_name}' requires a 'type'") elif param_type not in parameter_types: raise ValueError(f"parameter '{param_name}' uses an unknown type '{param_type}'") else: @@ -658,7 +658,7 @@ class FTPFileToolParameter(ToolParameter): def get_initial_value(self, trans, other_values): if trans is not None: if trans.user is not None: - self.user_ftp_dir = "%s/" % trans.user_ftp_dir + self.user_ftp_dir = f"{trans.user_ftp_dir}/" return None @property @@ -769,7 +769,7 @@ class ColorToolParameter(ToolParameter): try: return str(tuple(int(value.lstrip('#')[i: i + 2], 16) for i in (0, 2, 4))) except Exception: - raise ParameterValueError("Failed to convert \'%s\' to RGB." % value, self.name) + raise ParameterValueError(f"Failed to convert '{value}' to RGB.", self.name) return str(value) @@ -940,7 +940,7 @@ class SelectToolParameter(ToolParameter): elif set(value).issubset(set(fallback_values.keys())): return [fallback_values[v] for v in value] else: - raise ParameterValueError("invalid options ({!r}) were selected (valid options: {})".format(",".join(set(value) - set(legal_values)), ",".join(legal_values)), self.name, is_dynamic=self.is_dynamic) + raise ParameterValueError(f"invalid options ({','.join(set(value) - set(legal_values))!r}) were selected (valid options: {','.join(legal_values)})", self.name, is_dynamic=self.is_dynamic) else: value_is_none = (value == "None" and "None" not in legal_values) if value_is_none or not value: @@ -958,7 +958,7 @@ class SelectToolParameter(ToolParameter): elif not require_legal_value: return value else: - raise ParameterValueError("an invalid option ({!r}) was selected (valid options: {})".format(value, ",".join(legal_values)), self.name, value, is_dynamic=self.is_dynamic) + raise ParameterValueError(f"an invalid option ({value!r}) was selected (valid options: {','.join(legal_values)})", self.name, value, is_dynamic=self.is_dynamic) def to_param_dict_string(self, value, other_values=None): if value in (None, []): @@ -1456,7 +1456,7 @@ class DrillDownSelectToolParameter(SelectToolParameter): if from_file: if not os.path.isabs(from_file): from_file = os.path.join(tool.app.config.tool_data_path, from_file) - elem = XML("%s" % open(from_file).read()) + elem = XML(f"{open(from_file).read()}") self.dynamic_options = elem.get('dynamic_options', None) if self.dynamic_options: self.is_dynamic = True @@ -1540,7 +1540,7 @@ class DrillDownSelectToolParameter(SelectToolParameter): rval = [] for val in value: if val not in legal_values: - raise ParameterValueError("an invalid option ({!r}) was selected (valid options: {})".format(val, ",".join(legal_values)), self.name, val) + raise ParameterValueError(f"an invalid option ({val!r}) was selected (valid options: {','.join(legal_values)})", self.name, val) rval.append(val) return rval @@ -1898,7 +1898,7 @@ class DataToolParameter(BaseDataToolParameter): decoded_id = trans.security.decode_id(single_value['id']) rval.append(trans.sa_session.query(trans.app.model.LibraryDatasetDatasetAssociation).get(decoded_id)) else: - raise ValueError("Unknown input source %s passed to job submission API." % single_value['src']) + raise ValueError(f"Unknown input source {single_value['src']} passed to job submission API.") elif isinstance(single_value, trans.app.model.HistoryDatasetCollectionAssociation): rval.append(single_value) elif isinstance(single_value, trans.app.model.DatasetCollectionElement): @@ -1928,7 +1928,7 @@ class DataToolParameter(BaseDataToolParameter): decoded_id = trans.security.decode_id(value['id']) rval = trans.sa_session.query(trans.app.model.HistoryDatasetCollectionAssociation).get(decoded_id) else: - raise ValueError("Unknown input source %s passed to job submission API." % value['src']) + raise ValueError(f"Unknown input source {value['src']} passed to job submission API.") elif str(value).startswith("__collection_reduce__|"): encoded_ids = [v[len("__collection_reduce__|"):] for v in str(value).split(",")] decoded_ids = map(trans.security.decode_id, encoded_ids) @@ -2097,7 +2097,7 @@ class DataToolParameter(BaseDataToolParameter): name = hdca.name if match.implicit_conversion: - name = "%s (with implicit datatype conversion)" % name + name = f"{name} (with implicit datatype conversion)" append(d['options']['hdca'], hdca, name, 'hdca', subcollection_type=subcollection_type) continue @@ -2244,7 +2244,7 @@ class DataCollectionToolParameter(BaseDataToolParameter): for hdca, implicit_conversion in self.match_collections(trans, history, dataset_collection_matcher): name = hdca.name if implicit_conversion: - name = "%s (with implicit datatype conversion)" % name + name = f"{name} (with implicit datatype conversion)" d['options']['hdca'].append({ 'id': trans.security.encode_id(hdca.id), 'hid': hdca.hid, @@ -2258,7 +2258,7 @@ class DataCollectionToolParameter(BaseDataToolParameter): subcollection_type = self._history_query(trans).can_map_over(hdca).collection_type name = hdca.name if implicit_conversion: - name = "%s (with implicit datatype conversion)" % name + name = f"{name} (with implicit datatype conversion)" d['options']['hdca'].append({ 'id': trans.security.encode_id(hdca.id), 'hid': hdca.hid, diff --git a/lib/galaxy/tools/parameters/dynamic_options.py b/lib/galaxy/tools/parameters/dynamic_options.py index 249a24f49de..a0614a47f5a 100644 --- a/lib/galaxy/tools/parameters/dynamic_options.py +++ b/lib/galaxy/tools/parameters/dynamic_options.py @@ -190,10 +190,10 @@ class DataMetaFilter(Filter): try: ref = _get_ref_data(other_values, self.ref_name) except KeyError: # no such dataset - log.warning("could not filter by metadata: %s unknown" % self.ref_name) + log.warning(f"could not filter by metadata: {self.ref_name} unknown") return [] except ValueError: # not a valid dataset - log.warning("could not filter by metadata: %s not a data or collection parameter" % self.ref_name) + log.warning(f"could not filter by metadata: {self.ref_name} not a data or collection parameter") return [] # get the metadata value. # - for lists: (of data sets) and collections the meta data values of all @@ -603,7 +603,7 @@ class DynamicOptions: @property def missing_tool_data_table_name(self): if not self.tool_data_table: - log.warning("Data table named '%s' is required by tool but not configured" % self.tool_data_table_name) + log.warning(f"Data table named '{self.tool_data_table_name}' is required by tool but not configured") return self.tool_data_table_name return None @@ -663,10 +663,10 @@ class DynamicOptions: try: datasets = _get_ref_data(other_values, self.dataset_ref_name) except KeyError: # no such dataset - log.warning("could not create dynamic options from_dataset: %s unknown" % self.dataset_ref_name) + log.warning(f"could not create dynamic options from_dataset: {self.dataset_ref_name} unknown") return [] except ValueError: # not a valid dataset - log.warning("could not create dynamic options from_dataset: %s not a data or collection parameter" % self.dataset_ref_name) + log.warning(f"could not create dynamic options from_dataset: {self.dataset_ref_name} not a data or collection parameter") return [] options = [] @@ -722,7 +722,7 @@ class DynamicOptions: if isinstance(field_name, int): field_index = field_name else: - assert field_name in self.columns, "Requested '%s' column missing from column def" % field_name + assert field_name in self.columns, f"Requested '{field_name}' column missing from column def" field_index = self.columns[field_name] if not isinstance(value, list): value = [value] diff --git a/lib/galaxy/tools/parameters/grouping.py b/lib/galaxy/tools/parameters/grouping.py index 037a71e285b..483f361c803 100644 --- a/lib/galaxy/tools/parameters/grouping.py +++ b/lib/galaxy/tools/parameters/grouping.py @@ -22,7 +22,7 @@ from galaxy.util.dictifiable import Dictifiable from galaxy.util.expressions import ExpressionContext log = logging.getLogger(__name__) -URI_PREFIXES = ["%s://" % x for x in ["http", "https", "ftp", "file", "gxfiles", "gximport", "gxuserimport", "gxftp"]] +URI_PREFIXES = [f"{x}://" for x in ["http", "https", "ftp", "file", "gxfiles", "gximport", "gxuserimport", "gxftp"]] class Group(Dictifiable): @@ -88,7 +88,7 @@ class Repeat(Group): return inflector.pluralize(self.title) def label(self): - return "Repeat (%s)" % self.title + return f"Repeat ({self.title})" def value_to_basic(self, value, app, use_security=False): rval = [] @@ -162,7 +162,7 @@ class Section(Group): return inflector.pluralize(self.title) def label(self): - return "Section (%s)" % self.title + return f"Section ({self.title})" def value_to_basic(self, value, app, use_security=False): rval = {} @@ -228,7 +228,7 @@ class UploadDataset(Group): filenames.append(composite_file.get('ftp_files', [])[0]) dataset_name = os.path.commonprefix(filenames).rstrip('.') or None if dataset_name is None: - dataset_name = 'Uploaded Composite Dataset (%s)' % self.get_file_type(context) + dataset_name = f'Uploaded Composite Dataset ({self.get_file_type(context)})' return dataset_name def get_file_base_name(self, context): @@ -266,7 +266,7 @@ class UploadDataset(Group): return inflector.pluralize(self.title) def group_title(self, context): - return "{} ({})".format(self.title, context.get(self.file_type_name, self.default_file_type)) + return f"{self.title} ({context.get(self.file_type_name, self.default_file_type)})" def title_by_index(self, trans, index, context): d_type = self.get_datatype(trans, context) @@ -276,7 +276,7 @@ class UploadDataset(Group): if composite_file.description: rval = f"{rval} ({composite_file.description})" if composite_file.optional: - rval = "%s [optional]" % rval + rval = f"{rval} [optional]" return rval if index < self.get_file_count(trans, context): return "Extra primary file" @@ -507,7 +507,7 @@ class UploadDataset(Group): # This allows for comparison when the filesystem uses a different encoding than the browser. ftp_files = [unicodedata.normalize('NFC', f) for f in ftp_files if isinstance(f, str)] if trans.user is None: - log.warning('Anonymous user passed values in ftp_files: %s' % ftp_files) + log.warning(f'Anonymous user passed values in ftp_files: {ftp_files}') ftp_files = [] # TODO: warning to the user (could happen if session has become invalid) else: @@ -527,7 +527,7 @@ class UploadDataset(Group): ftp_files = [] for ftp_file in ftp_files: if ftp_file not in valid_files: - log.warning('User passed an invalid file path in ftp_files: %s' % ftp_file) + log.warning(f'User passed an invalid file path in ftp_files: {ftp_file}') continue # TODO: warning to the user (could happen if file is already imported) ftp_data_file = {'local_filename': os.path.abspath(os.path.join(user_ftp_dir, ftp_file)), @@ -610,7 +610,7 @@ class UploadDataset(Group): for i, group_incoming in enumerate(groups_incoming[writable_files_offset:]): key = keys[i + writable_files_offset] if not force_composite and group_incoming is None and not writable_files[list(writable_files.keys())[keys.index(key)]].optional: - dataset.warnings.append("A required composite file (%s) was not specified." % (key)) + dataset.warnings.append(f"A required composite file ({key}) was not specified.") dataset.composite_files[key] = None else: file_bunch, warnings = get_one_filename(group_incoming) @@ -622,7 +622,7 @@ class UploadDataset(Group): elif not force_composite: dataset.composite_files[key] = None if not writable_files[list(writable_files.keys())[keys.index(key)]].optional: - dataset.warnings.append("A required composite file (%s) was not specified." % (key)) + dataset.warnings.append(f"A required composite file ({key}) was not specified.") return [dataset] else: rval = [] @@ -653,7 +653,7 @@ class Conditional(Group): @property def label(self): - return "Conditional (%s)" % self.name + return f"Conditional ({self.name})" def get_current_case(self, value): # Convert value to user representation diff --git a/lib/galaxy/tools/parameters/meta.py b/lib/galaxy/tools/parameters/meta.py index da6566ecc5c..ab030009b70 100644 --- a/lib/galaxy/tools/parameters/meta.py +++ b/lib/galaxy/tools/parameters/meta.py @@ -233,7 +233,7 @@ def __expand_collection_parameter(trans, input_key, incoming_val, collections_to try: src = incoming_val["src"] if src != "hdca": - raise exceptions.ToolMetaParameterException("Invalid dataset collection source type %s" % src) + raise exceptions.ToolMetaParameterException(f"Invalid dataset collection source type {src}") encoded_hdc_id = incoming_val["id"] subcollection_type = incoming_val.get('map_over_type', None) except TypeError: diff --git a/lib/galaxy/tools/parameters/sanitize.py b/lib/galaxy/tools/parameters/sanitize.py index 815ad05988d..080837155ba 100644 --- a/lib/galaxy/tools/parameters/sanitize.py +++ b/lib/galaxy/tools/parameters/sanitize.py @@ -69,7 +69,7 @@ class ToolParameterSanitizer: while val in rval._valid_chars: rval._valid_chars.remove(val) else: - log.debug('Invalid action tag in valid: %s' % action_elem.tag) + log.debug(f'Invalid action tag in valid: {action_elem.tag}') for mapping_elem in elem.findall('mapping'): rval._mapped_chars = rval.get_mapping_by_name(mapping_elem.get('initial', 'default')) for action_elem in mapping_elem: @@ -87,7 +87,7 @@ class ToolParameterSanitizer: if map_source is not None and map_key in rval._mapped_chars: del rval._mapped_chars[map_key] else: - log.debug('Invalid action tag in mapping: %s' % action_elem.tag) + log.debug(f'Invalid action tag in mapping: {action_elem.tag}') return rval @classmethod @@ -105,11 +105,11 @@ class ToolParameterSanitizer: try: value = eval(split_name) except NameError as e: - log.debug('Invalid string preset specified: %s' % e) + log.debug(f'Invalid string preset specified: {e}') elif split_name in cls.VALID_PRESET: value = cls.VALID_PRESET[split_name] else: - log.debug('Invalid preset name specified: %s' % split_name) + log.debug(f'Invalid preset name specified: {split_name}') rval.extend([val for val in value if val not in rval]) return rval @@ -121,7 +121,7 @@ class ToolParameterSanitizer: if split_name in cls.MAPPING_PRESET: rval.update(cls.MAPPING_PRESET[split_name]) else: - log.debug('Invalid preset name specified: %s' % split_name) + log.debug(f'Invalid preset name specified: {split_name}') return rval # end class methods @@ -161,4 +161,4 @@ class ToolParameterSanitizer: elif isinstance(value, list): return list(map(self.sanitize_text, value)) else: - raise Exception('Unknown parameter type ({}:{})'.format(type(value), value)) + raise Exception(f'Unknown parameter type ({type(value)}:{value})') diff --git a/lib/galaxy/tools/parameters/validation.py b/lib/galaxy/tools/parameters/validation.py index bb6206c6fbb..de5184205f3 100644 --- a/lib/galaxy/tools/parameters/validation.py +++ b/lib/galaxy/tools/parameters/validation.py @@ -126,7 +126,7 @@ class ExpressionValidator(Validator): try: evalresult = eval(self.expression, dict(value=value)) except Exception: - log.debug("Validator {} could not be evaluated on {}".format(self.expression, str(value)), exc_info=True) + log.debug(f"Validator {self.expression} could not be evaluated on {str(value)}", exc_info=True) raise ValueError(message) if not(evalresult): raise ValueError(message) @@ -439,7 +439,7 @@ class ValueInDataTableColumnValidator(Validator): column = int(column) except ValueError: pass - message = elem.get("message", "Value was not found in %s." % (table_name)) + message = elem.get("message", f"Value was not found in {table_name}.") line_startswith = elem.get("line_startswith", None) if line_startswith: line_startswith = line_startswith.strip() diff --git a/lib/galaxy/tools/parameters/wrapped_json.py b/lib/galaxy/tools/parameters/wrapped_json.py index d397783e082..3ddf7ffafd1 100644 --- a/lib/galaxy/tools/parameters/wrapped_json.py +++ b/lib/galaxy/tools/parameters/wrapped_json.py @@ -114,7 +114,7 @@ def _json_wrap_input(input, value_wrapper, profile, handle_files="skip"): else: json_value = [_cast_if_not_none(value_wrapper.value, int)] else: - raise NotImplementedError("input_type [%s] not implemented" % input_type) + raise NotImplementedError(f"input_type [{input_type}] not implemented") return json_value diff --git a/lib/galaxy/tools/recommendations.py b/lib/galaxy/tools/recommendations.py index 0687f2d0aec..5986f2ed69a 100644 --- a/lib/galaxy/tools/recommendations.py +++ b/lib/galaxy/tools/recommendations.py @@ -271,7 +271,7 @@ class ToolRecommendations(): try: sample[idx] = int(self.model_data_dictionary[tool_name]) except Exception: - log.exception("Failed to find tool %s in model" % (tool_name)) + log.exception(f"Failed to find tool {tool_name} in model") return prediction_data sample = np.reshape(sample, (1, self.max_seq_len)) # boost the predicted scores using tools' usage diff --git a/lib/galaxy/tools/test.py b/lib/galaxy/tools/test.py index 0d405ebcdf9..4da1352086f 100644 --- a/lib/galaxy/tools/test.py +++ b/lib/galaxy/tools/test.py @@ -233,7 +233,7 @@ def _matching_case_for_value(tool, cond, declared_value): # No explicit value for this param and cannot determine a # default - give up. Previously this would just result in a key # error exception. - msg = "Failed to find test parameter value specification required for conditional %s" % cond.name + msg = f"Failed to find test parameter value specification required for conditional {cond.name}" raise Exception(msg) # Check the tool's defined cases against predicate to determine @@ -249,7 +249,7 @@ def _matching_case_for_value(tool, cond, declared_value): def _add_uploaded_dataset(name, value, extra, input_parameter, required_files): if value is None: - assert input_parameter.optional, '%s is not optional. You must provide a valid filename.' % name + assert input_parameter.optional, f'{name} is not optional. You must provide a valid filename.' return value return require_file(name, value, extra, required_files) @@ -311,7 +311,7 @@ class ParamContext: return name def __str__(self): - return "Context[for_state=%s]" % self.for_state() + return f"Context[for_state={self.for_state()}]" def param_names(self): for parent_context_param in self.parent_context.param_names(): diff --git a/lib/galaxy/tools/toolbox/base.py b/lib/galaxy/tools/toolbox/base.py index 6ab39d1f6b8..a82222d6230 100644 --- a/lib/galaxy/tools/toolbox/base.py +++ b/lib/galaxy/tools/toolbox/base.py @@ -230,7 +230,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): """ - log.info("Parsing the tool configuration %s" % config_filename) + log.info(f"Parsing the tool configuration {config_filename}") try: tool_conf_source = get_toolbox_parser(config_filename) except OSError as exc: @@ -343,7 +343,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): if tool_panel_section_key in self._tool_panel: # Appending a tool to an existing section in toolbox._tool_panel tool_section = self._tool_panel[tool_panel_section_key] - log.debug("Appending to tool panel section: %s" % str(tool_section.name)) + log.debug(f"Appending to tool panel section: {str(tool_section.name)}") elif new_label and self._tool_panel.get_label(new_label): tool_section = self._tool_panel.get_label(new_label) tool_panel_section_key = tool_section.id @@ -367,7 +367,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): def create_section(self, section_dict): tool_section = ToolSection(section_dict) self._tool_panel.append_section(tool_section.id, tool_section) - log.debug("Loading new tool panel section: %s" % str(tool_section.name)) + log.debug(f"Loading new tool panel section: {str(tool_section.name)}") return tool_section def get_integrated_section_for_tool(self, tool): @@ -614,7 +614,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): 'version': val.version or '', } section = ToolSection(section_dict) - log.debug("Loading section: %s" % section_dict.get('name')) + log.debug(f"Loading section: {section_dict.get('name')}") for section_key, section_item_type, section_val in val.panel_items_iter(): if section_item_type == panel_item_types.TOOL: tool_id = section_key.replace('tool_', '', 1) @@ -630,7 +630,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): elif section_item_type == panel_item_types.LABEL: if section_val: section.elems[section_key] = section_val - log.debug("Loaded label: %s" % (section_val.text)) + log.debug(f"Loaded label: {section_val.text}") self._tool_panel[key] = section log.debug("Loading tool panel finished %s", execution_timer) @@ -675,7 +675,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): if tool_uuid is not None: tool_from_uuid = self._get_tool_by_uuid(tool_uuid) if tool_from_uuid is None: - raise ObjectNotFound("Failed to find a tool with uuid [%s]" % tool_uuid) + raise ObjectNotFound(f"Failed to find a tool with uuid [{tool_uuid}]") tool_id = tool_from_uuid.id if tool_id is None: raise AssertionError("get_tool called with tool_id as None") @@ -861,7 +861,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): tool = self.load_tool(concrete_path, use_cached=False, tool_cache_data_dir=tool_cache_data_dir) if string_as_bool(item.get('hidden', False)): tool.hidden = True - key = 'tool_%s' % str(tool.id) + key = f'tool_{str(tool.id)}' if can_load_into_panel_dict: if guid and not from_cache: tool.tool_shed = tool_shed_repository.tool_shed @@ -1018,7 +1018,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): tool = self.load_tool(tool_file, tool_cache_data_dir) self.__add_tool(tool, load_panel_dict, elems) # Always load the tool into the integrated_panel_dict, or it will not be included in the integrated_tool_panel.xml file. - key = 'tool_%s' % str(tool.id) + key = f'tool_{str(tool.id)}' integrated_elems[key] = tool if async_load: @@ -1062,7 +1062,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): # If the tool is broken but still exists we can load it from the cache tool = self.load_tool_from_cache(config_file, recover_tool=True) if tool: - log.exception("Tool '%s' is not valid:" % config_file) + log.exception(f"Tool '{config_file}' is not valid:") tool.tool_errors = 'Current on-disk tool is not valid' else: raise @@ -1130,7 +1130,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): """ # Make sure the tool is actually loaded. if tool_id not in self._tools_by_id: - raise ObjectNotFound("No tool found with id '%s'." % escape(tool_id)) + raise ObjectNotFound(f"No tool found with id '{escape(tool_id)}'.") else: tool = self._tools_by_id[tool_id] return tool.to_archive() @@ -1141,7 +1141,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): replace the old tool. """ if tool_id not in self._tools_by_id: - message = "No tool with id '%s'." % escape(tool_id) + message = f"No tool with id '{escape(tool_id)}'." status = 'error' else: old_tool = self._tools_by_id[tool_id] @@ -1181,7 +1181,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): if needed. """ if tool_id not in self._tools_by_id: - message = "No tool with id %s" % escape(tool_id) + message = f"No tool with id {escape(tool_id)}" status = 'error' else: tool = self._tools_by_id[tool_id] @@ -1203,9 +1203,9 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): del self.data_manager_tools[tool_id] # TODO: do we need to manually remove from the integrated panel here? message = "Removed the tool:
    " - message += "name: %s
    " % escape(tool.name) - message += "id: %s
    " % escape(tool.id) - message += "version: %s" % escape(tool.version) + message += f"name: {escape(tool.name)}
    " + message += f"id: {escape(tool.id)}
    " + message += f"version: {escape(tool.version)}" status = 'done' return message, status @@ -1225,7 +1225,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): if tool_panel_section_id not in self._tool_panel: # Hack introduced without comment in a29d54619813d5da992b897557162a360b8d610c- # not sure why it is needed. - fixed_tool_panel_section_id = 'section_%s' % tool_panel_section_id + fixed_tool_panel_section_id = f'section_{tool_panel_section_id}' if fixed_tool_panel_section_id in self._tool_panel: tool_panel_section_id = fixed_tool_panel_section_id else: @@ -1343,7 +1343,7 @@ def _filter_for_panel(item, item_type, filters, context): if not filter_method(context, filter_item): return False except Exception as e: - raise MessageException("Toolbox filter exception from '{}': {}.".format(filter_method.__name__, unicodify(e))) + raise MessageException(f"Toolbox filter exception from '{filter_method.__name__}': {unicodify(e)}.") return True if item_type == panel_item_types.TOOL: if _apply_filter(item, filters['tool']): diff --git a/lib/galaxy/tools/toolbox/filters/__init__.py b/lib/galaxy/tools/toolbox/filters/__init__.py index acbb64ea797..87bb8d696a2 100644 --- a/lib/galaxy/tools/toolbox/filters/__init__.py +++ b/lib/galaxy/tools/toolbox/filters/__init__.py @@ -44,7 +44,7 @@ class FilterFactory: elif name == 'toolbox_label_filters': category = "label" if category: - validate = getattr(trans.app.config, 'user_tool_%s_filters' % category, []) + validate = getattr(trans.app.config, f'user_tool_{category}_filters', []) self.__init_filters(category, user_filters, filters, validate=validate) if kwds.get("trackster", False): filters["tool"].append(_has_trackster_conf) diff --git a/lib/galaxy/tools/toolbox/integrated_panel.py b/lib/galaxy/tools/toolbox/integrated_panel.py index 5edcbcb1a0a..e3bcd078cac 100644 --- a/lib/galaxy/tools/toolbox/integrated_panel.py +++ b/lib/galaxy/tools/toolbox/integrated_panel.py @@ -61,7 +61,7 @@ class ManagesIntegratedToolPanelMixin: if tracking_directory: if not os.path.exists(tracking_directory): os.makedirs(tracking_directory) - name = "integrated_tool_panel_%.10f.xml" % time.time() + name = f"integrated_tool_panel_{time.time():.10f}.xml" filename = os.path.join(tracking_directory, name) else: filename = destination @@ -77,9 +77,9 @@ $INTEGRATED_TOOL_PANEL for _, item_type, item in self._integrated_tool_panel.panel_items_iter(): if item: if item_type == panel_item_types.TOOL: - integrated_tool_panel.append(' \n' % item.id) + integrated_tool_panel.append(f' \n') elif item_type == panel_item_types.WORKFLOW: - integrated_tool_panel.append(' \n' % item.id) + integrated_tool_panel.append(f' \n') elif item_type == panel_item_types.LABEL: label_id = item.id or '' label_text = item.text or '' @@ -89,14 +89,14 @@ $INTEGRATED_TOOL_PANEL section_id = item.id or '' section_name = item.name or '' section_version = item.version or '' - integrated_tool_panel.append('
    \n'.format(escape(section_id), escape(section_name), section_version)) + integrated_tool_panel.append(f'
    \n') for _section_key, section_item_type, section_item in item.panel_items_iter(): if section_item_type == panel_item_types.TOOL: if section_item: - integrated_tool_panel.append(' \n' % section_item.id) + integrated_tool_panel.append(f' \n') elif section_item_type == panel_item_types.WORKFLOW: if section_item: - integrated_tool_panel.append(' \n' % section_item.id) + integrated_tool_panel.append(f' \n') elif section_item_type == panel_item_types.LABEL: if section_item: label_id = section_item.id or '' diff --git a/lib/galaxy/tools/toolbox/panel.py b/lib/galaxy/tools/toolbox/panel.py index e94ce23ddc2..71d67a78c5e 100644 --- a/lib/galaxy/tools/toolbox/panel.py +++ b/lib/galaxy/tools/toolbox/panel.py @@ -128,45 +128,45 @@ class ToolPanelElements(odict, HasPanelItems): return element def has_tool_with_id(self, tool_id): - key = 'tool_%s' % tool_id + key = f'tool_{tool_id}' return key in self def replace_tool(self, previous_tool_id, new_tool_id, tool): - previous_key = 'tool_%s' % previous_tool_id - new_key = 'tool_%s' % new_tool_id + previous_key = f'tool_{previous_tool_id}' + new_key = f'tool_{new_tool_id}' index = self.keys().index(previous_key) del self[previous_key] self.insert(index, new_key, tool) def index_of_tool_id(self, tool_id): - query_key = 'tool_%s' % tool_id + query_key = f'tool_{tool_id}' for index, target_key in enumerate(self.keys()): if query_key == target_key: return index return None def insert_tool(self, index, tool): - key = "tool_%s" % tool.id + key = f"tool_{tool.id}" self.insert(index, key, tool) def get_tool_with_id(self, tool_id): - key = "tool_%s" % tool_id + key = f"tool_{tool_id}" return self[key] def append_tool(self, tool): - key = "tool_%s" % tool.id + key = f"tool_{tool.id}" self[key] = tool def stub_tool(self, key): - key = "tool_%s" % key + key = f"tool_{key}" self[key] = None def stub_workflow(self, key): - key = 'workflow_%s' % key + key = f'workflow_{key}' self[key] = None def stub_label(self, key): - key = 'label_%s' % key + key = f'label_{key}' self[key] = None def append_section(self, key, section_elems): diff --git a/lib/galaxy/tools/util/galaxyops/__init__.py b/lib/galaxy/tools/util/galaxyops/__init__.py index a5894ba5347..70839468ab2 100644 --- a/lib/galaxy/tools/util/galaxyops/__init__.py +++ b/lib/galaxy/tools/util/galaxyops/__init__.py @@ -36,7 +36,7 @@ def parse_cols_arg(cols): def default_printer(stream, exc, obj): print("%d: %s" % (obj.linenum, obj.current_line), file=stream) - print("\tError: %s" % unicodify(exc), file=stream) + print(f"\tError: {unicodify(exc)}", file=stream) def skipped(reader, filedesc=""): diff --git a/lib/galaxy/tools/wrappers.py b/lib/galaxy/tools/wrappers.py index 3427f77732b..843458d3172 100644 --- a/lib/galaxy/tools/wrappers.py +++ b/lib/galaxy/tools/wrappers.py @@ -312,7 +312,7 @@ class DatasetFilenameWrapper(ToolParameterValueWrapper): if datatype is not None: datatypes.append(datatype) else: - log.warning("Datatype class not found for extension '%s', which is used as parameter of 'is_of_type()' method" % (e)) + log.warning(f"Datatype class not found for extension '{e}', which is used as parameter of 'is_of_type()' method") return self.dataset.datatype.matches_any(datatypes) def __str__(self): @@ -530,7 +530,7 @@ class ElementIdentifierMapper: def __init__(self, input_datasets=None): if input_datasets is not None: - self.identifier_key_dict = {v: "%s|__identifier__" % k for k, v in input_datasets.items()} + self.identifier_key_dict = {v: f"{k}|__identifier__" for k, v in input_datasets.items()} else: self.identifier_key_dict = {} diff --git a/lib/galaxy/tours/_impl.py b/lib/galaxy/tours/_impl.py index be413f9d498..68f4b692c83 100644 --- a/lib/galaxy/tours/_impl.py +++ b/lib/galaxy/tours/_impl.py @@ -93,9 +93,9 @@ class ToursRegistryImpl: tour = yaml.safe_load(f) load_tour_steps(tour) self.tours[tour_id] = tour - log.info("Loaded tour '%s'" % tour_id) + log.info(f"Loaded tour '{tour_id}'") except OSError: - log.exception("Tour '%s' could not be loaded, error reading file." % tour_id) + log.exception(f"Tour '{tour_id}' could not be loaded, error reading file.") except yaml.error.YAMLError: log.exception("Tour '%s' could not be loaded, error within file." " Please check your yaml syntax." % tour_id) diff --git a/lib/galaxy/util/__init__.py b/lib/galaxy/util/__init__.py index 892d9da46a7..fece589be7d 100644 --- a/lib/galaxy/util/__init__.py +++ b/lib/galaxy/util/__init__.py @@ -297,7 +297,7 @@ def xml_to_string(elem, pretty=False): except TypeError as e: # we assume this is a comment if hasattr(elem, 'text'): - return "\n" % elem.text + return f"\n" else: raise e if xml_str and pretty: @@ -340,7 +340,7 @@ def xml_element_to_dict(elem): rval[elem.tag][key] = value if elem.attrib: for key, value in elem.attrib.items(): - rval[elem.tag]["@%s" % key] = value + rval[elem.tag][f"@{key}"] = value if elem.text: text = elem.text.strip() @@ -460,7 +460,7 @@ def shrink_string_by_size(value, size, join_by="..", left_larger=True, beginning left_index += 1 else: right_index += 1 - value = "{}{}{}".format(value[:left_index], join_by, value[-right_index:]) + value = f"{value[:left_index]}{join_by}{value[-right_index:]}" return value @@ -612,7 +612,7 @@ def sanitize_param(value, valid_characters=valid_chars, character_map=mapped_cha elif isinstance(value, list): return [sanitize_text(x, valid_characters=valid_characters, character_map=character_map, invalid_character=invalid_character) for x in value] else: - raise Exception('Unknown parameter type (%s)' % (type(value))) + raise Exception(f'Unknown parameter type ({type(value)})') valid_filename_chars = set(string.ascii_letters + string.digits + '_.') @@ -683,7 +683,7 @@ def mask_password_from_url(url): # This can manipulate the input other than just masking password, # so the previous string replace method is preferred when the # password doesn't appear twice in the url - split = split._replace(netloc=split.netloc.replace(f"{split.username}:{split.password}", '%s:********' % split.username)) + split = split._replace(netloc=split.netloc.replace(f"{split.username}:{split.password}", f'{split.username}:********')) url = urlunsplit(split) return url @@ -746,7 +746,7 @@ def in_directory(file, directory, local_path_module=os.path): False """ if local_path_module != os.path: - _safe_contains = importlib.import_module('galaxy.util.path.%s' % local_path_module.__name__).safe_contains + _safe_contains = importlib.import_module(f'galaxy.util.path.{local_path_module.__name__}').safe_contains else: directory = os.path.realpath(directory) _safe_contains = safe_contains @@ -836,7 +836,7 @@ class Params: # changed to not require this and NEVER_SANITIZE should be # removed. if (value is not None and key not in self.NEVER_SANITIZE - and True not in [key.endswith("|%s" % nonsanitize_parameter) for + and True not in [key.endswith(f"|{nonsanitize_parameter}") for nonsanitize_parameter in self.NEVER_SANITIZE]): self.__dict__[key] = sanitize_param(value) else: @@ -865,7 +865,7 @@ class Params: return self.__dict__.get(key, default) def __str__(self): - return '%s' % self.__dict__ + return f'{self.__dict__}' def __len__(self): return len(self.__dict__) @@ -951,7 +951,7 @@ def asbool(obj): elif obj in falsy: return False else: - raise ValueError("String is not true/false: %r" % obj) + raise ValueError(f"String is not true/false: {obj!r}") return bool(obj) @@ -1059,7 +1059,7 @@ def unicodify(value, encoding=DEFAULT_ENCODING, error='replace', strip_null=Fals value = str(value, encoding, error) except Exception as e: if log_exception: - msg = "Value '{}' could not be coerced to Unicode: {}('{}')".format(repr(value), type(e).__name__, e) + msg = f"Value '{repr(value)}' could not be coerced to Unicode: {type(e).__name__}('{e}')" log.exception(msg) raise if strip_null: @@ -1367,7 +1367,7 @@ def size_to_bytes(size): size_re = re.compile(r'(?P(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)\s*(?P[eptgmk]?(b|bytes?)?)?$') size_match = size_re.match(size.lower()) if size_match is None: - raise ValueError("Could not parse string '%s'" % size) + raise ValueError(f"Could not parse string '{size}'") number = float(size_match.group("number")) multiple = size_match.group("multiple") if multiple == "" or multiple.startswith('b'): @@ -1600,19 +1600,19 @@ def build_url(base_url, port=80, scheme='http', pathspec=None, params=None, dose parsed_url = urlparse(base_url) if scheme != 'http': parsed_url.scheme = scheme - assert parsed_url.scheme in ('http', 'https', 'ftp'), 'Invalid URL scheme: %s' % scheme + assert parsed_url.scheme in ('http', 'https', 'ftp'), f'Invalid URL scheme: {scheme}' if port != 80: url = '%s://%s:%d/%s' % (parsed_url.scheme, parsed_url.netloc.rstrip('/'), int(port), parsed_url.path) else: - url = '{}://{}/{}'.format(parsed_url.scheme, parsed_url.netloc.rstrip('/'), parsed_url.path.lstrip('/')) + url = f"{parsed_url.scheme}://{parsed_url.netloc.rstrip('/')}/{parsed_url.path.lstrip('/')}" if len(pathspec) > 0: - url = '{}/{}'.format(url.rstrip('/'), '/'.join(pathspec)) + url = f"{url.rstrip('/')}/{'/'.join(pathspec)}" if parsed_url.query: for query_parameter in parsed_url.query.split('&'): key, value = query_parameter.split('=') params[key] = value if params: - url += '?%s' % urlencode(params, doseq=doseq) + url += f'?{urlencode(params, doseq=doseq)}' return url @@ -1687,7 +1687,7 @@ class ExecutionTimer: self.begin = time.time() def __str__(self): - return "(%0.3f ms)" % (self.elapsed * 1000) + return f"({self.elapsed * 1000:0.3f} ms)" @property def elapsed(self): @@ -1710,7 +1710,7 @@ class StructuredExecutionTimer: message = string.Template(self.template).safe_substitute(kwd) else: message = self.template - log_message = message + " (%0.3f ms)" % (self.elapsed * 1000) + log_message = message + f" ({self.elapsed * 1000:0.3f} ms)" return log_message @property diff --git a/lib/galaxy/util/bunch.py b/lib/galaxy/util/bunch.py index daf1fbf0af3..06987622015 100644 --- a/lib/galaxy/util/bunch.py +++ b/lib/galaxy/util/bunch.py @@ -28,7 +28,7 @@ class Bunch: return self.__dict__.values() def __str__(self): - return '%s' % self.__dict__ + return f'{self.__dict__}' def __bool__(self): return bool(self.__dict__) diff --git a/lib/galaxy/util/compression_utils.py b/lib/galaxy/util/compression_utils.py index 9de41e1a1dd..fefd5692a97 100644 --- a/lib/galaxy/util/compression_utils.py +++ b/lib/galaxy/util/compression_utils.py @@ -94,11 +94,11 @@ class CompressedFile: if self.file_name.endswith('.tar'): self.file_name = os.path.splitext(self.file_name)[0] self.type = self.file_type - method = 'open_%s' % self.file_type + method = f'open_{self.file_type}' if hasattr(self, method): self.archive = getattr(self, method)(file_path, mode) else: - raise NameError('File type %s specified, no open method found.' % self.file_type) + raise NameError(f'File type {self.file_type} specified, no open method found.') @property def common_prefix_dir(self): @@ -152,7 +152,7 @@ class CompressedFile: if os.path.exists(absolute_filepath): os.chmod(absolute_filepath, unix_permissions) else: - log.warning("Unable to change permission on extracted file '%s' as it does not exist" % absolute_filepath) + log.warning(f"Unable to change permission on extracted file '{absolute_filepath}' as it does not exist") return os.path.abspath(os.path.join(extraction_path, common_prefix_dir)) def safemembers(self): @@ -161,7 +161,7 @@ class CompressedFile: if self.file_type == "tar": for finfo in members: if not safe_relpath(finfo.name): - raise Exception("Path '%s' is blocked (illegal path)." % finfo.name) + raise Exception(f"Path '{finfo.name}' is blocked (illegal path).") if finfo.issym() or finfo.islnk(): link_target = os.path.join(os.path.dirname(finfo.name), finfo.linkname) if not safe_relpath(link_target) or not os.path.normpath(link_target).startswith(common_prefix_dir): @@ -191,13 +191,13 @@ class CompressedFile: return member def getmembers(self): - return getattr(self, 'getmembers_%s' % self.type)() + return getattr(self, f'getmembers_{self.type}')() def getname(self, member): - return getattr(self, 'getname_%s' % self.type)(member) + return getattr(self, f'getname_{self.type}')(member) def isdir(self, member): - return getattr(self, 'isdir_%s' % self.type)(member) + return getattr(self, f'isdir_{self.type}')(member) def isdir_tar(self, member): return member.isdir() diff --git a/lib/galaxy/util/dbkeys.py b/lib/galaxy/util/dbkeys.py index 27b4b1d4fcc..c29daf574c3 100644 --- a/lib/galaxy/util/dbkeys.py +++ b/lib/galaxy/util/dbkeys.py @@ -101,7 +101,7 @@ class GenomeBuilds: if user and hasattr(user, 'preferences') and 'dbkeys' in user.preferences: user_keys = loads(user.preferences['dbkeys']) for key, chrom_dict in user_keys.items(): - rval.append((key, "{} ({}) [Custom]".format(chrom_dict['name'], key))) + rval.append((key, f"{chrom_dict['name']} ({key}) [Custom]")) # Load old builds.txt static keys rval.extend(self._static_dbkeys) # load dbkeys from dbkey data table @@ -146,6 +146,6 @@ class GenomeBuilds: if not chrom_info: # Default to built-in build. # Since we are using an unverified dbkey, we will sanitize the dbkey before use - chrom_info = os.path.join(self._static_chrom_info_path, "%s.len" % sanitize_lists_to_string(dbkey)) + chrom_info = os.path.join(self._static_chrom_info_path, f"{sanitize_lists_to_string(dbkey)}.len") chrom_info = os.path.abspath(chrom_info) return (chrom_info, db_dataset) diff --git a/lib/galaxy/util/dictifiable.py b/lib/galaxy/util/dictifiable.py index be844653910..162d0bf3acd 100644 --- a/lib/galaxy/util/dictifiable.py +++ b/lib/galaxy/util/dictifiable.py @@ -52,7 +52,7 @@ class Dictifiable: try: visible_keys = self.__getattribute__('dict_' + view + '_visible_keys') except AttributeError: - raise Exception('Unknown Dictifiable view: %s' % view) + raise Exception(f'Unknown Dictifiable view: {view}') for key in visible_keys: try: item = self.__getattribute__(key) diff --git a/lib/galaxy/util/filelock.py b/lib/galaxy/util/filelock.py index 9369f612ac1..03d0261735e 100644 --- a/lib/galaxy/util/filelock.py +++ b/lib/galaxy/util/filelock.py @@ -26,7 +26,7 @@ class FileLock: """ self.is_locked = False full_path = os.path.abspath(file_name) - self.lockfile = "%s.lock" % full_path + self.lockfile = f"{full_path}.lock" self.file_name = full_path self.timeout = timeout self.delay = delay diff --git a/lib/galaxy/util/form_builder.py b/lib/galaxy/util/form_builder.py index 758af3c3599..c2478beb6dd 100644 --- a/lib/galaxy/util/form_builder.py +++ b/lib/galaxy/util/form_builder.py @@ -98,7 +98,7 @@ class SelectField(BaseField): elif display == "radio": assert not(multiple), "Radio display only supported for single select" elif display is not None: - raise Exception("Unknown display type: %s" % display) + raise Exception(f"Unknown display type: {display}") self.display = display def add_option(self, text, value, selected=False): diff --git a/lib/galaxy/util/heartbeat.py b/lib/galaxy/util/heartbeat.py index 29ed342e23b..7da6de5282d 100644 --- a/lib/galaxy/util/heartbeat.py +++ b/lib/galaxy/util/heartbeat.py @@ -80,7 +80,7 @@ class Heartbeat(threading.Thread): self.open_logs() try: # Print separator with timestamp - self.file.write("Traceback dump for all threads at %s:\n\n" % time.asctime()) + self.file.write(f"Traceback dump for all threads at {time.asctime()}:\n\n") # Print the thread states threads = get_current_thread_object_dict() for thread_id, frame in sys._current_frames().items(): @@ -157,7 +157,7 @@ class Heartbeat(threading.Thread): return stack_frames[-1] def print_nonsleeping(self, threads_object_dict): - self.file_nonsleeping.write("Non-Sleeping threads at %s:\n\n" % time.asctime()) + self.file_nonsleeping.write(f"Non-Sleeping threads at {time.asctime()}:\n\n") all_threads_are_sleeping = True threads = get_current_thread_object_dict() for thread_id, frame in sys._current_frames().items(): diff --git a/lib/galaxy/util/json.py b/lib/galaxy/util/json.py index 245da0858fe..6ef84d34aab 100644 --- a/lib/galaxy/util/json.py +++ b/lib/galaxy/util/json.py @@ -102,7 +102,7 @@ def validate_jsonrpc_request(request, regular_methods, notification_methods): assert 'jsonrpc' in request, \ 'This server requires JSON-RPC 2.0 and no "jsonrpc" member was sent with the Request object as per the JSON-RPC 2.0 Specification.' assert request['jsonrpc'] == '2.0', \ - 'Requested JSON-RPC version "%s" != required version "2.0".' % request['jsonrpc'] + f"Requested JSON-RPC version \"{request['jsonrpc']}\" != required version \"2.0\"." assert 'method' in request, 'No "method" member was sent with the Request object' except AssertionError as e: return False, request, jsonrpc_response(request=request, @@ -118,7 +118,7 @@ def validate_jsonrpc_request(request, regular_methods, notification_methods): data='Valid methods are: %s' % ', '.join(regular_methods + notification_methods))) try: if request['method'] in regular_methods: - assert 'id' in request, 'No "id" member was sent with the Request object and the requested method "%s" is not a notification method' % request['method'] + assert 'id' in request, f"No \"id\" member was sent with the Request object and the requested method \"{request['method']}\" is not a notification method" except AssertionError as e: return False, request, jsonrpc_response(request=request, error=dict(code=-32600, @@ -146,13 +146,13 @@ def validate_jsonrpc_response(response, id=None): 'The "message" member of the "error" object in the Response is missing.' except Exception: log.exception('Response was not valid JSON-RPC') - log.debug('Response was: %s' % response) + log.debug(f'Response was: {response}') return False, response if id is not None: try: assert 'id' in response and response['id'] == id except Exception: - log.error('The response id "{}" does not match the request id "{}"'.format(response['id'], id)) + log.error(f"The response id \"{response['id']}\" does not match the request id \"{id}\"") return False, response return True, response diff --git a/lib/galaxy/util/jstree.py b/lib/galaxy/util/jstree.py index d18ff164a69..2dfb1869522 100644 --- a/lib/galaxy/util/jstree.py +++ b/lib/galaxy/util/jstree.py @@ -62,7 +62,7 @@ class Node(dictobj.DictionaryObject): children = kwargs.get('children', {}) if len([key for key in children if not isinstance(children[key], Node)]): raise TypeError( - "One or more children were not instances of '%s'" % Node.__name__) + f"One or more children were not instances of '{Node.__name__}'") if 'children' in kwargs: del kwargs['children'] self._items['children'] = dictobj.MutableDictionaryObject(children) @@ -108,7 +108,7 @@ class JSTree(dictobj.DictionaryObject): """ if len([p for p in paths if not isinstance(p, Path)]): raise TypeError( - "All paths must be instances of '%s'" % Path.__name__) + f"All paths must be instances of '{Path.__name__}'") super().__init__() @@ -141,7 +141,7 @@ class JSTree(dictobj.DictionaryObject): s = fmt % (" " * depth * spacing, root.text) for child in root.children: child = root.children[child] - s += "\n%s" % self.pretty(child, depth + 1, spacing) + s += f"\n{self.pretty(child, depth + 1, spacing)}" return s def jsonData(self): diff --git a/lib/galaxy/util/object_wrapper.py b/lib/galaxy/util/object_wrapper.py index ada091e9bef..101a202fd36 100644 --- a/lib/galaxy/util/object_wrapper.py +++ b/lib/galaxy/util/object_wrapper.py @@ -128,7 +128,7 @@ def wrap_with_safe_string(value, no_wrap_classes=None): value_mod = inspect.getmodule(value) if value_mod: wrapped_class_name = f"{value_mod.__name__}.{wrapped_class_name}" - wrapped_class_name = "SafeStringWrapper({}:{})".format(wrapped_class_name, ",".join(sorted(map(str, no_wrap_classes)))) + wrapped_class_name = f"SafeStringWrapper({wrapped_class_name}:{','.join(sorted(map(str, no_wrap_classes)))})" do_wrap_func_name = f"__do_wrap_{wrapped_class_name}" do_wrap_func = __do_wrap global_dict = globals() @@ -206,7 +206,7 @@ class SafeStringWrapper: return sanitize_lists_to_string(self.unsanitized, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP) def __repr__(self): - return "{} object at {:x} on: {}".format(sanitize_lists_to_string(self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP), id(self), sanitize_lists_to_string(repr(self.unsanitized), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP)) + return f"{sanitize_lists_to_string(self.__class__.__name__, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP)} object at {id(self):x} on: {sanitize_lists_to_string(repr(self.unsanitized), valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP)}" def __lt__(self, other): while isinstance(other, SafeStringWrapper): diff --git a/lib/galaxy/util/oset.py b/lib/galaxy/util/oset.py index b209a98eb5b..c3e3c873267 100644 --- a/lib/galaxy/util/oset.py +++ b/lib/galaxy/util/oset.py @@ -54,7 +54,7 @@ class OrderedSet(MutableSet): def __repr__(self): if not self: return f'{self.__class__.__name__}()' - return '{}({!r})'.format(self.__class__.__name__, list(self)) + return f'{self.__class__.__name__}({list(self)!r})' def __eq__(self, other): if isinstance(other, OrderedSet): diff --git a/lib/galaxy/util/pastescript/loadwsgi.py b/lib/galaxy/util/pastescript/loadwsgi.py index f7a7226864c..323fe2d2788 100644 --- a/lib/galaxy/util/pastescript/loadwsgi.py +++ b/lib/galaxy/util/pastescript/loadwsgi.py @@ -66,8 +66,8 @@ def fix_type_error(exc_info, callable, varargs, kwargs): if kwargs: kwargs = sorted(kwargs.keys()) args += ', '.join('%s=...' % n for n in kwargs) - gotspec = '(%s)' % args - msg = '{}; got {}, wanted {}'.format(exc_info[1], gotspec, argspec) + gotspec = f'({args})' + msg = f'{exc_info[1]}; got {gotspec}, wanted {argspec}' exc_info[1].args = (msg,) return exc_info @@ -183,7 +183,7 @@ class _App(_ObjectType): elif context.protocol == 'paste.app_factory': return fix_call(context.object, context.global_conf, **context.local_conf) else: - assert 0, "Protocol %r unknown" % context.protocol + assert 0, f"Protocol {context.protocol!r} unknown" APP = _App() @@ -206,7 +206,7 @@ class _Filter(_ObjectType): **context.local_conf) return filter_wrapper else: - assert 0, "Protocol %r unknown" % context.protocol + assert 0, f"Protocol {context.protocol!r} unknown" FILTER = _Filter() @@ -229,7 +229,7 @@ class _Server(_ObjectType): **context.local_conf) return server_wrapper else: - assert 0, "Protocol %r unknown" % context.protocol + assert 0, f"Protocol {context.protocol!r} unknown" SERVER = _Server() @@ -327,13 +327,12 @@ def loadcontext(object_type, uri, name=None, relative_to=None, if name is None: name = 'main' if ':' not in uri: - raise LookupError("URI has no scheme: %r" % uri) + raise LookupError(f"URI has no scheme: {uri!r}") scheme, path = uri.split(':', 1) scheme = scheme.lower() if scheme not in _loaders: raise LookupError( - "URI scheme not known: %r (from %s)" - % (scheme, ', '.join(_loaders.keys()))) + f"URI scheme not known: {scheme!r} (from {', '.join(_loaders.keys())})") return _loaders[scheme]( object_type, uri, path, name=name, relative_to=relative_to, @@ -540,7 +539,7 @@ class ConfigLoader(_Loader): # This will work with 'server' and 'filter', otherwise it # could fail but there is an error message already for # bad protocols - context.protocol = 'paste.%s_factory' % section_protocol + context.protocol = f'paste.{section_protocol}_factory' return context @@ -554,11 +553,10 @@ class ConfigLoader(_Loader): break if len(possible) > 1: raise LookupError( - "Multiple protocols given in section %r: %s" - % (section, possible)) + f"Multiple protocols given in section {section!r}: {possible}") if not possible: raise LookupError( - "No loader given in section %r" % section) + f"No loader given in section {section!r}") found_protocol, found_expr = possible[0] del local_conf[found_protocol] value = import_string(found_expr) diff --git a/lib/galaxy/util/pastescript/serve.py b/lib/galaxy/util/pastescript/serve.py index a30fca3f032..73c96963754 100644 --- a/lib/galaxy/util/pastescript/serve.py +++ b/lib/galaxy/util/pastescript/serve.py @@ -202,8 +202,7 @@ class Command: self.args.append(filename) else: assert 0, ( - "Value takes_config_file must be None, 1, or -1 (not %r)" - % take) + f"Value takes_config_file must be None, 1, or -1 (not {take!r})") if os.environ.get('PASTE_DEFAULT_QUIET'): self.verbose = 0 @@ -220,7 +219,7 @@ class Command: for var_name, option_name in self.required_args: if not getattr(self.options, var_name, None): raise BadCommand( - 'You must provide the option %s' % option_name) + f'You must provide the option {option_name}') result = self.command() if result is None: return self.return_code @@ -232,8 +231,7 @@ class Command: usage = ' ' + self.usage else: usage = '' - self.parser.usage = "%prog [options]{}\n{}".format( - usage, self.summary) + self.parser.usage = f"%prog [options]{usage}\n{self.summary}" self.parser.prog = self._prog_name() if self.description: desc = self.description @@ -242,7 +240,7 @@ class Command: self.options, self.args = self.parser.parse_args(args) def _prog_name(self): - return '{} {}'.format(os.path.basename(sys.argv[0]), self.command_name) + return f'{os.path.basename(sys.argv[0])} {self.command_name}' ######################################## # Utility methods @@ -337,8 +335,7 @@ class Command: for arg in args: if '=' not in arg: raise BadCommand( - 'Variable assignment %r invalid (no "=")' - % arg) + f'Variable assignment {arg!r} invalid (no "=")') name, value = arg.split('=', 1) result[name] = value return result @@ -374,8 +371,7 @@ class NotFoundCommand(Command): print('Known commands:') longest = max([len(n) for n, c in commands]) for name, command in commands: - print(' {} {}'.format(self.pad(name, length=longest), - command.load().summary)) + print(f' {self.pad(name, length=longest)} {command.load().summary}') return 2 @@ -548,7 +544,7 @@ class ServeCommand(Command): if cmd not in (None, 'start', 'stop', 'restart', 'status'): raise BadCommand( - 'Error: must give start|stop|restart (not %s)' % cmd) + f'Error: must give start|stop|restart (not {cmd})') if cmd == 'status' or self.options.show_status: return self.show_status() @@ -592,7 +588,7 @@ class ServeCommand(Command): try: writeable_log_file = open(self.options.log_file, 'a') except OSError as ioe: - msg = 'Error: Unable to write to log file: %s' % ioe + msg = f'Error: Unable to write to log file: {ioe}' raise BadCommand(msg) writeable_log_file.close() @@ -601,7 +597,7 @@ class ServeCommand(Command): try: writeable_pid_file = open(self.options.pid_file, 'a') except OSError as ioe: - msg = 'Error: Unable to write to pid file: %s' % ioe + msg = f'Error: Unable to write to pid file: {ioe}' raise BadCommand(msg) writeable_pid_file.close() @@ -656,7 +652,7 @@ class ServeCommand(Command): msg = ' ' + str(e) else: msg = '' - print('Exiting%s (-v to see traceback)' % msg) + print(f'Exiting{msg} (-v to see traceback)') except AttributeError as e: # Capturing bad error response from paste if str(e) == "'WSGIThreadPoolServer' object has no attribute 'thread_pool'": @@ -727,19 +723,19 @@ class ServeCommand(Command): def stop_daemon(self): pid_file = self.options.pid_file or 'paster.pid' if not os.path.exists(pid_file): - print('No PID file exists in %s' % pid_file) + print(f'No PID file exists in {pid_file}') return 1 pid = read_pidfile(pid_file) if not pid: - print("Not a valid PID file in %s" % pid_file) + print(f"Not a valid PID file in {pid_file}") return 1 pid = live_pidfile(pid_file) if not pid: - print("PID in %s is not valid (deleting)" % pid_file) + print(f"PID in {pid_file} is not valid (deleting)") try: os.unlink(pid_file) except OSError as e: - print("Could not delete: %s" % e) + print(f"Could not delete: {e}") return 2 return 1 for _i in range(10): @@ -748,7 +744,7 @@ class ServeCommand(Command): os.kill(pid, signal.SIGTERM) time.sleep(1) else: - print("failed to kill web process %s" % pid) + print(f"failed to kill web process {pid}") return 3 if os.path.exists(pid_file): os.unlink(pid_file) @@ -757,17 +753,17 @@ class ServeCommand(Command): def show_status(self): pid_file = self.options.pid_file or 'paster.pid' if not os.path.exists(pid_file): - print('No PID file %s' % pid_file) + print(f'No PID file {pid_file}') return 1 pid = read_pidfile(pid_file) if not pid: - print('No PID in file %s' % pid_file) + print(f'No PID in file {pid_file}') return 1 pid = live_pidfile(pid_file) if not pid: print(f'PID {pid} in {pid_file} is not running') return 1 - print('Server running in PID %s' % pid) + print(f'Server running in PID {pid}') return 0 def restart_with_reloader(self): @@ -826,7 +822,7 @@ class ServeCommand(Command): entry = grp.getgrnam(group) except KeyError: raise BadCommand( - "Bad group: %r; no such group exists" % group) + f"Bad group: {group!r}; no such group exists") gid = entry.gr_gid try: uid = int(user) @@ -836,7 +832,7 @@ class ServeCommand(Command): entry = pwd.getpwnam(user) except KeyError: raise BadCommand( - "Bad username: %r; no such user exists" % user) + f"Bad username: {user!r}; no such user exists") if not gid: gid = entry.pw_gid uid = entry.pw_uid @@ -942,13 +938,13 @@ def _remove_pid_file(written_pid, filename, verbosity): filename, pid_in_file, current_pid)) return if verbosity > 0: - print("Removing PID file %s" % filename) + print(f"Removing PID file {filename}") try: os.unlink(filename) return except OSError as e: # Record, but don't give traceback - print("Cannot remove PID file: %s" % e) + print(f"Cannot remove PID file: {e}") # well, at least lets not leave the invalid PID around... try: f = open(filename, 'w') @@ -1036,7 +1032,7 @@ def run(args=None): if options.do_help: args = ['help'] + args if not args: - print('Usage: %s COMMAND' % sys.argv[0]) + print(f'Usage: {sys.argv[0]} COMMAND') args = ['help'] command_name = args[0] if command_name not in commands: diff --git a/lib/galaxy/util/path/__init__.py b/lib/galaxy/util/path/__init__.py index a6bd071ce40..980a1575d95 100644 --- a/lib/galaxy/util/path/__init__.py +++ b/lib/galaxy/util/path/__init__.py @@ -358,11 +358,11 @@ def external_chown(path, pwent, external_chown_script, description="file"): cmd = shlex.split(external_chown_script) cmd.extend([path, pwent[0], str(pwent[3])]) - log.debug('Changing ownership of {} with: {}'.format(path, ' '.join(map(shlex.quote, cmd)))) + log.debug(f"Changing ownership of {path} with: {' '.join(map(shlex.quote, cmd))}") galaxy.util.commands.execute(cmd) return True except galaxy.util.commands.CommandLineException as e: - log.warning('Changing ownership of {} {} failed: {}'.format(description, path, galaxy.util.unicodify(e))) + log.warning(f'Changing ownership of {description} {path} failed: {galaxy.util.unicodify(e)}') return False diff --git a/lib/galaxy/util/plugin_config.py b/lib/galaxy/util/plugin_config.py index 276344498a9..66deafe4bcb 100644 --- a/lib/galaxy/util/plugin_config.py +++ b/lib/galaxy/util/plugin_config.py @@ -87,7 +87,7 @@ def __load_plugins_from_dicts(plugins_dict, configs, extra_kwds, plugin_type_key if plugin_type_key in config: plugin_type = config[plugin_type_key] break - assert plugin_type is not None, "Could not determine plugin type for [%s]" % config + assert plugin_type is not None, f"Could not determine plugin type for [{config}]" plugin_kwds = config plugin_kwds.update(extra_kwds) plugin = plugins_dict[plugin_type](**plugin_kwds) diff --git a/lib/galaxy/util/properties.py b/lib/galaxy/util/properties.py index 535426872b5..64638a46199 100644 --- a/lib/galaxy/util/properties.py +++ b/lib/galaxy/util/properties.py @@ -85,7 +85,7 @@ def load_app_properties( properties.update(kwds) # update from env - override_prefix = "%sOVERRIDE_" % config_prefix + override_prefix = f"{config_prefix}OVERRIDE_" for key in os.environ: if key.startswith(override_prefix): config_key = key[len(override_prefix):].lower() @@ -116,7 +116,7 @@ def read_properties_from_file(config_file, config_section=None): else: properties.update(parser.defaults()) else: - raise InvalidFileFormatError("File '%s' doesn't have a supported extension" % config_file) + raise InvalidFileFormatError(f"File '{config_file}' doesn't have a supported extension") return properties diff --git a/lib/galaxy/util/rules_dsl.py b/lib/galaxy/util/rules_dsl.py index d946d0d7333..0b79ec2e80f 100644 --- a/lib/galaxy/util/rules_dsl.py +++ b/lib/galaxy/util/rules_dsl.py @@ -14,10 +14,10 @@ def get_rules_specification(): def _ensure_rule_contains_keys(rule, keys): for key, instance_class in keys.items(): if key not in rule: - raise ValueError("Rule of type [{}] does not contain key [{}].".format(rule["type"], key)) + raise ValueError(f"Rule of type [{rule['type']}] does not contain key [{key}].") value = rule[key] if not isinstance(value, instance_class): - raise ValueError("Rule of type [{}] does not contain correct value type for key [{}].".format(rule["type"], key)) + raise ValueError(f"Rule of type [{rule['type']}] does not contain correct value type for key [{key}].") def _ensure_key_value_in(rule, key, values): @@ -107,7 +107,7 @@ class AddColumnGroupTagValueRuleDefinition(BaseRuleDefinition): def apply(self, rule, data, sources): rule_value = rule["value"] - tag_prefix = "group:%s:" % rule_value + tag_prefix = f"group:{rule_value}:" new_rows = [] for index, row in enumerate(data): diff --git a/lib/galaxy/util/submodules.py b/lib/galaxy/util/submodules.py index 068113295af..068050a23d3 100644 --- a/lib/galaxy/util/submodules.py +++ b/lib/galaxy/util/submodules.py @@ -46,7 +46,7 @@ def __import_submodules_impl(module, recursive=False): if recursive and is_pkg: submodules.update(__import_submodules_impl(submodule, recursive=True)) except BaseException: - message = "%s dynamic module could not be loaded (traceback follows):" % (full_name) + message = f"{full_name} dynamic module could not be loaded (traceback follows):" log.exception(message) continue return submodules diff --git a/lib/galaxy/util/template.py b/lib/galaxy/util/template.py index 13cd2951fec..25890fe572b 100644 --- a/lib/galaxy/util/template.py +++ b/lib/galaxy/util/template.py @@ -91,7 +91,7 @@ def fill_template(template_text, # list comprehensions, as this has never worked for dict or set comprehensions or # generator expressions in Cheetah. var_not_found = e.args[0].split("'")[1] - replace_str = 'VFFSL(SL,"%s",True)' % var_not_found + replace_str = f'VFFSL(SL,"{var_not_found}",True)' lineno = last_stack.lineno - 1 module_code = t._CHEETAH_generatedModuleCode.splitlines() module_code[lineno] = module_code[lineno].replace(replace_str, var_not_found) diff --git a/lib/galaxy/util/tool_shed/common_util.py b/lib/galaxy/util/tool_shed/common_util.py index ceeb94894bd..2188ae76302 100644 --- a/lib/galaxy/util/tool_shed/common_util.py +++ b/lib/galaxy/util/tool_shed/common_util.py @@ -129,7 +129,7 @@ def generate_clone_url_for_repository_in_tool_shed(user, repository): base_url = url_for('/', qualified=True).rstrip('/') if user: protocol, base = base_url.split('://') - username = '%s@' % user.username + username = f'{user.username}@' return f'{protocol}://{username}{base}/repos/{repository.user.username}/{repository.name}' else: return f'{base_url}/repos/{repository.user.username}/{repository.name}' @@ -264,7 +264,7 @@ def get_tool_shed_repository_url(app, tool_shed, owner, name): if tool_shed_url: # Append a slash to the tool shed URL, because urlparse.urljoin will eliminate # the last part of a URL if it does not end with a forward slash. - tool_shed_url = '%s/' % tool_shed_url + tool_shed_url = f'{tool_shed_url}/' return urljoin(tool_shed_url, f'view/{owner}/{name}') return tool_shed_url diff --git a/lib/galaxy/util/tool_shed/xml_util.py b/lib/galaxy/util/tool_shed/xml_util.py index 01e38fcdd74..699d7cf34cf 100644 --- a/lib/galaxy/util/tool_shed/xml_util.py +++ b/lib/galaxy/util/tool_shed/xml_util.py @@ -69,13 +69,13 @@ def parse_xml(file_name, check_exists=True): """Returns a parsed xml tree with comments intact.""" error_message = '' if check_exists and not os.path.exists(file_name): - return None, "File does not exist %s" % str(file_name) + return None, f"File does not exist {str(file_name)}" try: tree = galaxy_parse_xml(file_name, remove_comments=False, strip_whitespace=False) except OSError: raise except Exception as e: - error_message = "Exception attempting to parse {}: {}".format(str(file_name), unicodify(e)) + error_message = f"Exception attempting to parse {str(file_name)}: {unicodify(e)}" log.exception(error_message) return None, error_message return tree, error_message diff --git a/lib/galaxy/util/watcher.py b/lib/galaxy/util/watcher.py index b0960e11eb3..4c3de5ef198 100644 --- a/lib/galaxy/util/watcher.py +++ b/lib/galaxy/util/watcher.py @@ -42,7 +42,7 @@ def get_observer_class(config_name, config_value, default, monitor_what_str): raise Exception(message) if expect_observer and observer_class is None: - message = "Watchdog library unavailable, cannot monitor %s." % monitor_what_str + message = f"Watchdog library unavailable, cannot monitor {monitor_what_str}." if config_value == "auto": log.info(message) else: diff --git a/lib/galaxy/util/xml_macros.py b/lib/galaxy/util/xml_macros.py index 65879aee84d..5354be8c718 100644 --- a/lib/galaxy/util/xml_macros.py +++ b/lib/galaxy/util/xml_macros.py @@ -92,7 +92,7 @@ def expand_nested_tokens(tokens): for current_token_name, current_token_value in tokens.items(): if token_name in current_token_value: if token_name == current_token_name: - raise Exception("Token '%s' cannot contain itself" % token_name) + raise Exception(f"Token '{token_name}' cannot contain itself") tokens[current_token_name] = current_token_value.replace(token_name, tokens[token_name]) return tokens diff --git a/lib/galaxy/util/yaml_util.py b/lib/galaxy/util/yaml_util.py index 2fae2ed6936..3a6fa8039fd 100644 --- a/lib/galaxy/util/yaml_util.py +++ b/lib/galaxy/util/yaml_util.py @@ -46,7 +46,7 @@ def ordered_load(stream, merge_duplicate_keys=False): if key in mapping: if not merge_duplicate_keys: raise ConstructorError("while constructing a mapping", node.start_mark, - "found duplicated key (%s)" % key, key_node.start_mark) + f"found duplicated key ({key})", key_node.start_mark) log.debug("Merging values for duplicate key '%s' into a list", key) if merged_duplicate.get(key): mapping[key].append(value) diff --git a/lib/galaxy/visualization/data_providers/genome.py b/lib/galaxy/visualization/data_providers/genome.py index 3393db81073..48316860922 100644 --- a/lib/galaxy/visualization/data_providers/genome.py +++ b/lib/galaxy/visualization/data_providers/genome.py @@ -355,7 +355,7 @@ class TabixDataProvider(GenomeDataProvider, FilterableMixin): # Write data in region. iterator = self.get_iterator(data_file, region.chrom, region.start, region.end) for line in iterator: - out.write("%s\n" % line) + out.write(f"{line}\n") # # -- Interval data providers -- @@ -532,7 +532,7 @@ class BedDataProvider(GenomeDataProvider): with self.open_data_file() as data_file: iterator = self.get_iterator(data_file, chrom, start, end) for line in iterator: - out.write("%s\n" % line) + out.write(f"{line}\n") class BedTabixDataProvider(TabixDataProvider, BedDataProvider): @@ -731,7 +731,7 @@ class VcfDataProvider(GenomeDataProvider): # Write data in region. iterator = self.get_iterator(data_file, region.chrom, region.start, region.end) for line in iterator: - out.write("%s\n" % line) + out.write(f"{line}\n") class VcfTabixDataProvider(TabixDataProvider, VcfDataProvider): diff --git a/lib/galaxy/visualization/plugins/config_parser.py b/lib/galaxy/visualization/plugins/config_parser.py index 21a1beb10bb..1e62b9767fb 100644 --- a/lib/galaxy/visualization/plugins/config_parser.py +++ b/lib/galaxy/visualization/plugins/config_parser.py @@ -255,7 +255,7 @@ class DataSourceParser: if xml_tree.text not in self.ALLOWED_MODEL_CLASSES: # log.debug( 'available data_source model_classes: %s' %( str( self.ALLOWED_MODEL_CLASSES ) ) ) - raise ParsingException('Invalid data_source model_class: %s' % (xml_tree.text)) + raise ParsingException(f'Invalid data_source model_class: {xml_tree.text}') # look up the model from the model module returning an empty data_source if not found model_class = getattr(galaxy.model, xml_tree.text, None) diff --git a/lib/galaxy/visualization/plugins/interactive_environments.py b/lib/galaxy/visualization/plugins/interactive_environments.py index da160d94b19..37bf2d54d2e 100644 --- a/lib/galaxy/visualization/plugins/interactive_environments.py +++ b/lib/galaxy/visualization/plugins/interactive_environments.py @@ -82,7 +82,7 @@ class InteractiveEnvironmentRequest: try: os.chmod(self.temp_dir, os.stat(self.temp_dir).st_mode | stat.S_IXOTH) except Exception: - log.error("Could not change permissions of tmpdir %s" % self.temp_dir) + log.error(f"Could not change permissions of tmpdir {self.temp_dir}") # continue anyway # This duplicates the logic in the proxy manager @@ -148,7 +148,7 @@ class InteractiveEnvironmentRequest: viz_config = configparser.ConfigParser(default_dict) conf_path = os.path.join(self.attr.our_config_dir, self.attr.viz_id + ".ini") if not os.path.exists(conf_path): - conf_path = "%s.sample" % conf_path + conf_path = f"{conf_path}.sample" viz_config.read(conf_path) self.attr.viz_config = viz_config @@ -313,7 +313,7 @@ class InteractiveEnvironmentRequest: command_inject = _check_uid_and_gid(command_inject) # --name should really not be set, but we'll try to honor it anyway - name = ['--name=%s' % self._get_name_for_run()] if '--name' not in command_inject else [] + name = [f'--name={self._get_name_for_run()}'] if '--name' not in command_inject else [] env = self._get_env_for_run(env_override) import_volume_def = self._get_import_volume_for_run() if volumes is None: @@ -441,7 +441,7 @@ class InteractiveEnvironmentRequest: return None else: container_id = stdout.strip() - log.debug("Container id: %s" % container_id) + log.debug(f"Container id: {container_id}") inspect_data = self.inspect_container(container_id) port_mappings = self.get_container_port_mapping(inspect_data) self.attr.docker_hostname = self.get_container_host(inspect_data) diff --git a/lib/galaxy/visualization/plugins/plugin.py b/lib/galaxy/visualization/plugins/plugin.py index aeda3ffeabe..1ca8c217a82 100644 --- a/lib/galaxy/visualization/plugins/plugin.py +++ b/lib/galaxy/visualization/plugins/plugin.py @@ -132,7 +132,7 @@ class VisualizationPlugin(ServesTemplatesPluginMixin): match = path.split('/config/')[-1] return os.path.join('./static', match, 'static') else: - log.debug('Visualization has no static path: %s.' % path) + log.debug(f'Visualization has no static path: {path}.') def _get_saved_visualization_config(self, visualization, revision=None, **kwargs): """ @@ -305,7 +305,7 @@ class ScriptVisualizationPlugin(VisualizationPlugin): template. """ render_vars['embedded'] = self._parse_embedded(embedded) - render_vars['static_url'] = url_for('/%s/' % self.static_path) + render_vars['static_url'] = url_for(f'/{self.static_path}/') render_vars.update(vars={}) render_vars.update({ "script_attributes": self.config['entry_point']['attr'] diff --git a/lib/galaxy/visualization/plugins/registry.py b/lib/galaxy/visualization/plugins/registry.py index 47b337a43a7..3b5c23b915a 100644 --- a/lib/galaxy/visualization/plugins/registry.py +++ b/lib/galaxy/visualization/plugins/registry.py @@ -163,7 +163,7 @@ class VisualizationsRegistry: return False if 'config' not in os.listdir(plugin_path): return False - expected_config_filename = '%s.xml' % (os.path.split(plugin_path)[1]) + expected_config_filename = f'{os.path.split(plugin_path)[1]}.xml' if not os.path.isfile(os.path.join(plugin_path, 'config', expected_config_filename)): return False return True @@ -188,7 +188,7 @@ class VisualizationsRegistry: plugin = self._build_plugin(plugin_name, plugin_path, config) return plugin else: - raise ObjectNotFound('Visualization XML not found: %s.' % config_file) + raise ObjectNotFound(f'Visualization XML not found: {config_file}.') def _build_plugin(self, plugin_name, plugin_path, config): # TODO: as builder not factory diff --git a/lib/galaxy/visualization/plugins/resource_parser.py b/lib/galaxy/visualization/plugins/resource_parser.py index 0b6576479a2..8f583b06122 100644 --- a/lib/galaxy/visualization/plugins/resource_parser.py +++ b/lib/galaxy/visualization/plugins/resource_parser.py @@ -88,7 +88,7 @@ class ResourceParser: # so: error if required, otherwise get a default (which itself defaults to None) if resource is None: if param_config['required']: - raise KeyError('required param %s not found in URL' % (param_name)) + raise KeyError(f'required param {param_name} not found in URL') resource = self.parse_parameter_default(trans, param_config) resources[var_name_in_template] = resource @@ -112,7 +112,7 @@ class ResourceParser: except Exception as exception: log.warning('Exception parsing visualization param from query: ' - + '{}, {}, ({}) {}'.format(param_name, config_val, str(type(exception)), str(exception))) + + f'{param_name}, {config_val}, ({str(type(exception))}) {str(exception)}') config_val = None # here - we've either had no value in the query_params or there was a failure to parse diff --git a/lib/galaxy/web/framework/base.py b/lib/galaxy/web/framework/base.py index 44482d9bb69..078a426932d 100644 --- a/lib/galaxy/web/framework/base.py +++ b/lib/galaxy/web/framework/base.py @@ -207,7 +207,7 @@ class WebApplication: raise trans.controller = controller_name trans.action = action - environ['controller_action_key'] = "{}.{}.{}".format('api' if environ['is_api_request'] else 'web', controller_name, action or 'default') + environ['controller_action_key'] = f"{'api' if environ['is_api_request'] else 'web'}.{controller_name}.{action or 'default'}" # Combine mapper args and query string / form args and call kwargs = trans.request.params.mixed() kwargs.update(map_match) diff --git a/lib/galaxy/web/framework/decorators.py b/lib/galaxy/web/framework/decorators.py index 75388fc0892..bd8c261a4c7 100644 --- a/lib/galaxy/web/framework/decorators.py +++ b/lib/galaxy/web/framework/decorators.py @@ -173,7 +173,7 @@ def legacy_expose_api(func, to_json=True, user_required=True): decoded_user_id = trans.security.decode_id(kwargs['payload']['run_as']) except TypeError: trans.response.status = 400 - return "Malformed user id ( %s ) specified, unable to decode." % str(kwargs['payload']['run_as']) + return f"Malformed user id ( {str(kwargs['payload']['run_as'])} ) specified, unable to decode." try: user = trans.sa_session.query(trans.app.model.User).get(decoded_user_id) trans.set_user(user) @@ -298,7 +298,7 @@ def expose_api(func, to_json=True, user_required=True, user_or_session_required= try: decoded_user_id = trans.security.decode_id(kwargs['payload']['run_as']) except (TypeError, ValueError): - error_message = "Malformed user id ( %s ) specified, unable to decode." % str(kwargs['payload']['run_as']) + error_message = f"Malformed user id ( {str(kwargs['payload']['run_as'])} ) specified, unable to decode." error_code = error_codes.USER_INVALID_RUN_AS return __api_error_response(trans, err_code=error_code, err_msg=error_message, status_code=400) try: diff --git a/lib/galaxy/web/framework/helpers/grids.py b/lib/galaxy/web/framework/helpers/grids.py index 4568987d3ac..349528c967c 100644 --- a/lib/galaxy/web/framework/helpers/grids.py +++ b/lib/galaxy/web/framework/helpers/grids.py @@ -203,7 +203,7 @@ class CommunityRatingColumn(GridColumn, UsesItemRatings): def sort(self, trans, query, ascending, column_name=None): # Get the columns that connect item's table and item's rating association table. - item_rating_assoc_class = getattr(trans.model, '%sRatingAssociation' % self.model_class.__name__) + item_rating_assoc_class = getattr(trans.model, f'{self.model_class.__name__}RatingAssociation') foreign_key = get_foreign_key(item_rating_assoc_class, self.model_class) fk_col = foreign_key.parent referent_col = foreign_key.get_referent(self.model_class.table) @@ -639,10 +639,10 @@ class Grid: if use_default_filter: if self.default_filter: column_filter = self.default_filter.get(column.key) - elif "f-" + column.model_class.__name__ + ".%s" % column.key in kwargs: + elif "f-" + column.model_class.__name__ + f".{column.key}" in kwargs: # Queries that include table joins cannot guarantee unique column names. This problem is # handled by setting the column_filter value to .. - column_filter = kwargs.get("f-" + column.model_class.__name__ + ".%s" % column.key) + column_filter = kwargs.get("f-" + column.model_class.__name__ + f".{column.key}") elif "f-" + column.key in kwargs: column_filter = kwargs.get("f-" + column.key) elif column.key in base_filter: diff --git a/lib/galaxy/web/framework/helpers/tags.py b/lib/galaxy/web/framework/helpers/tags.py index b837c5d84ff..255460bba8f 100644 --- a/lib/galaxy/web/framework/helpers/tags.py +++ b/lib/galaxy/web/framework/helpers/tags.py @@ -22,7 +22,7 @@ def format_attrs(**attrs): >>> format_attrs(p=None) == u'' True """ - strings = [' {}="{}"'.format(attr, escape_silent(value)) + strings = [f' {attr}="{escape_silent(value)}"' for attr, value in sorted(attrs.items()) if value is not None] return ''.join(strings) diff --git a/lib/galaxy/web/framework/middleware/error.py b/lib/galaxy/web/framework/middleware/error.py index 455b28982c0..e34b380079d 100644 --- a/lib/galaxy/web/framework/middleware/error.py +++ b/lib/galaxy/web/framework/middleware/error.py @@ -252,8 +252,7 @@ class CatchingIter: exc_info, self.environ) if close_response is not None: response += ( - '
    Error in .close():
    %s' - % close_response) + f'
    Error in .close():
    {close_response}') if not self.start_checker.response_started: self.start_checker('500 Internal Server Error', diff --git a/lib/galaxy/web/framework/middleware/profile.py b/lib/galaxy/web/framework/middleware/profile.py index 1c0da981c23..fc30f22cff0 100644 --- a/lib/galaxy/web/framework/middleware/profile.py +++ b/lib/galaxy/web/framework/middleware/profile.py @@ -93,9 +93,9 @@ def pstats_as_html(stats, *sel_list): funcs, order_message, select_message = get_func_list(stats, sel_list) # Deal with any ordering or selection messages if order_message: - rval.append("
    %s
    " % markupsafe.escape(order_message)) + rval.append(f"
    {markupsafe.escape(order_message)}
    ") if select_message: - rval.append("
    %s
    " % markupsafe.escape(select_message)) + rval.append(f"
    {markupsafe.escape(select_message)}
    ") # Build a table for the functions if list: rval.append("") @@ -114,25 +114,25 @@ def pstats_as_html(stats, *sel_list): ncalls = str(nc) if nc != cc: ncalls = ncalls + '/' + str(cc) - rval.append("" % markupsafe.escape(ncalls)) + rval.append(f"") # tottime - rval.append("" % tt) + rval.append(f"") # percall if nc == 0: percall = "" else: - percall = "%0.8f" % (tt / nc) - rval.append("" % markupsafe.escape(percall)) + percall = f"{tt / nc:0.8f}" + rval.append(f"") # cumtime - rval.append("" % ct) + rval.append(f"") # ctpercall if cc == 0: ctpercall = "" else: - ctpercall = "%0.8f" % (ct / cc) - rval.append("" % markupsafe.escape(ctpercall)) + ctpercall = f"{ct / cc:0.8f}" + rval.append(f"") # location - rval.append("" % markupsafe.escape(func_std_string(func))) + rval.append(f"") # row complete rval.append("") rval.append("
    %s{markupsafe.escape(ncalls)}%0.8f{tt:0.8f}%s{markupsafe.escape(percall)}%0.8f{ct:0.8f}%s{markupsafe.escape(ctpercall)}%s{markupsafe.escape(func_std_string(func))}
    ") diff --git a/lib/galaxy/web/framework/middleware/remoteuser.py b/lib/galaxy/web/framework/middleware/remoteuser.py index 1fc9c2e4dad..c2527a9afa4 100644 --- a/lib/galaxy/web/framework/middleware/remoteuser.py +++ b/lib/galaxy/web/framework/middleware/remoteuser.py @@ -82,7 +82,7 @@ class RemoteUser: if self.normalize_remote_user_email: environ[self.remote_user_header] = environ[self.remote_user_header].lower() if self.maildomain and '@' not in environ[self.remote_user_header]: - environ[self.remote_user_header] = "{}@{}".format(environ[self.remote_user_header], self.maildomain) + environ[self.remote_user_header] = f"{environ[self.remote_user_header]}@{self.maildomain}" path_info = environ.get('PATH_INFO', '') @@ -190,7 +190,7 @@ class RemoteUser: return self.error(start_response, title, message) return self.app(environ, start_response) else: - log.debug("Unable to identify user. %s not found" % self.remote_user_header) + log.debug(f"Unable to identify user. {self.remote_user_header} not found") for k, v in environ.items(): log.debug("%s = %s", k, v) diff --git a/lib/galaxy/web/framework/middleware/sentry.py b/lib/galaxy/web/framework/middleware/sentry.py index 494a1675d59..254190a4322 100644 --- a/lib/galaxy/web/framework/middleware/sentry.py +++ b/lib/galaxy/web/framework/middleware/sentry.py @@ -70,7 +70,7 @@ class Sentry: headers['Cookie'] = 'redacted' cak = environ.get('controller_action_key', None) or environ.get('PATH_INFO', "NOPATH").strip('/').replace('/', '.') event_id = self.client.captureMessage( - "SLOREQ: %s" % cak, + f"SLOREQ: {cak}", data={ 'sentry.interfaces.Http': { 'method': environ.get('REQUEST_METHOD'), diff --git a/lib/galaxy/web/legacy_framework/grids.py b/lib/galaxy/web/legacy_framework/grids.py index 2b2507d06d6..c7e479f474e 100644 --- a/lib/galaxy/web/legacy_framework/grids.py +++ b/lib/galaxy/web/legacy_framework/grids.py @@ -195,7 +195,7 @@ class CommunityRatingColumn(GridColumn, UsesItemRatings): def sort(self, trans, query, ascending, column_name=None): # Get the columns that connect item's table and item's rating association table. - item_rating_assoc_class = getattr(trans.model, '%sRatingAssociation' % self.model_class.__name__) + item_rating_assoc_class = getattr(trans.model, f'{self.model_class.__name__}RatingAssociation') foreign_key = get_foreign_key(item_rating_assoc_class, self.model_class) fk_col = foreign_key.parent referent_col = foreign_key.get_referent(self.model_class.table) @@ -605,10 +605,10 @@ class Grid: if use_default_filter: if self.default_filter: column_filter = self.default_filter.get(column.key) - elif "f-" + column.model_class.__name__ + ".%s" % column.key in kwargs: + elif "f-" + column.model_class.__name__ + f".{column.key}" in kwargs: # Queries that include table joins cannot guarantee unique column names. This problem is # handled by setting the column_filter value to .. - column_filter = kwargs.get("f-" + column.model_class.__name__ + ".%s" % column.key) + column_filter = kwargs.get("f-" + column.model_class.__name__ + f".{column.key}") elif "f-" + column.key in kwargs: column_filter = kwargs.get("f-" + column.key) elif column.key in base_filter: diff --git a/lib/galaxy/web/proxy/__init__.py b/lib/galaxy/web/proxy/__init__.py index ef798ae8d80..93d19d10993 100644 --- a/lib/galaxy/web/proxy/__init__.py +++ b/lib/galaxy/web/proxy/__init__.py @@ -70,7 +70,7 @@ class ProxyManager: self.proxy_ipc.handle_requests( authentication, proxy_requests, - '/%s' % route_name, + f'/{route_name}', container_ids, container_interface, ) @@ -94,7 +94,7 @@ class ProxyManager: authentication = AuthenticationToken(trans) for k in kwargs.keys(): if k not in self.valid_update_keys: - raise Exception("Invalid proxy request update key: %s" % k) + raise Exception(f"Invalid proxy request update key: {k}") return self.proxy_ipc.update_requests(authentication, **kwargs) def query_proxy(self, trans): @@ -347,7 +347,7 @@ class RestGolangProxyIpc: except requests.exceptions.ConnectionError as err: log.exception(err) if sleep > 5: - excp = "Could not contact proxy after %s seconds" % sum(range(sleep + 1)) + excp = f"Could not contact proxy after {sum(range(sleep + 1))} seconds" raise Exception(excp) time.sleep(sleep) self.handle_requests(authentication, proxy_requests, route_name, container_ids, container_interface, sleep=sleep + 1) diff --git a/lib/galaxy/web_stack/__init__.py b/lib/galaxy/web_stack/__init__.py index 94853086770..3d420b8d592 100644 --- a/lib/galaxy/web_stack/__init__.py +++ b/lib/galaxy/web_stack/__init__.py @@ -157,7 +157,7 @@ class ApplicationStack: pass def log_startup(self): - log.info("Galaxy server instance '%s' is running" % self.config.server_name) + log.info(f"Galaxy server instance '{self.config.server_name}' is running") def start(self): # TODO: with a stack config the pools could be parsed here @@ -498,7 +498,7 @@ class UWSGIApplicationStack(MessageApplicationStack): return instance_id def log_startup(self): - msg = ["Galaxy server instance '%s' is running" % self.config.server_name] + msg = [f"Galaxy server instance '{self.config.server_name}' is running"] # Log the next messages when the first worker finishes starting. This # may not be the first to finish (so Galaxy could be serving already), # but it's a good approximation and gives the correct root_pid below diff --git a/lib/galaxy/web_stack/handlers.py b/lib/galaxy/web_stack/handlers.py index 14a14a5428d..04077b36f55 100644 --- a/lib/galaxy/web_stack/handlers.py +++ b/lib/galaxy/web_stack/handlers.py @@ -191,10 +191,10 @@ class ConfiguresHandlers: if rval is not None: # If the parent element has a 'default' attribute, use the id or tag in that attribute if required and rval not in names: - raise Exception("default attribute '%s' does not match a defined id or tag in a child element" % (rval)) - log.debug("default set to child with id or tag '%s'" % (rval)) + raise Exception(f"default attribute '{rval}' does not match a defined id or tag in a child element") + log.debug(f"default set to child with id or tag '{rval}'") elif auto and len(names) == 1: - log.info("Setting default to child with id '%s'" % (names[0])) + log.info(f"Setting default to child with id '{names[0]}'") rval = names[0] elif required: raise Exception("No default specified, please specify a valid id or tag with the 'default' attribute") @@ -322,7 +322,7 @@ class ConfiguresHandlers: :returns: str -- This process's server name (handler ID). """ assert queue_callback is not None, \ - "Cannot perform '%s' handler assignment: `queue_callback` is None" % HANDLER_ASSIGNMENT_METHODS.MEM_SELF + f"Cannot perform '{HANDLER_ASSIGNMENT_METHODS.MEM_SELF}' handler assignment: `queue_callback` is None" if configured: log.warning("(%s) Ignoring handler assignment to '%s' because configured handler assignment method" " '' overrides per-tool handler assignment", obj.log_str(), diff --git a/lib/galaxy/web_stack/message.py b/lib/galaxy/web_stack/message.py index 80c11553a8f..f57a6d40229 100644 --- a/lib/galaxy/web_stack/message.py +++ b/lib/galaxy/web_stack/message.py @@ -90,7 +90,7 @@ class ApplicationStackMessage(dict): This could also be implemented as a mixin class. """ - assert self.default_handler is not None, '%s has no default handler method, cannot bind' % self.__class__.__name__ + assert self.default_handler is not None, f'{self.__class__.__name__} has no default handler method, cannot bind' setattr(obj, name, types.MethodType(self.default_handler, obj)) log.debug("Bound default message handler '%s.%s' to %s", self.__class__.__name__, self.default_handler.__name__, getattr(obj, name)) @@ -144,7 +144,7 @@ class TaskMessage(ParamMessage): cls=self.__class__.__name__, task=msg.task, msg=msg) - getattr(self, '_handle_%s_msg' % msg.task)(**msg.params) + getattr(self, f'_handle_{msg.task}_msg')(**msg.params) @property def task(self): diff --git a/lib/galaxy/web_stack/transport.py b/lib/galaxy/web_stack/transport.py index eb99bbef357..18eb1ebea95 100644 --- a/lib/galaxy/web_stack/transport.py +++ b/lib/galaxy/web_stack/transport.py @@ -139,7 +139,7 @@ class UWSGIFarmMessageTransport(ApplicationStackTransport): % (uwsgi.mule_id(), ','.join(map(str, range(1, len([x for x in self.stack._configured_mules if x.endswith('galaxy/main.py')]) + 1))))) elif len(self.stack._farms) > 1: - raise RuntimeError('Mule %s is in multiple farms! This configuration is not supported due to locking issues' % uwsgi.mule_id()) + raise RuntimeError(f'Mule {uwsgi.mule_id()} is in multiple farms! This configuration is not supported due to locking issues') # only mules receive messages so don't bother starting the dispatcher if we're not a mule (although # currently it doesn't have any registered handlers and so wouldn't start anyway) super().start() diff --git a/lib/galaxy/webapps/base/controller.py b/lib/galaxy/webapps/base/controller.py index 13a2be6c2df..2d343e6c8c4 100644 --- a/lib/galaxy/webapps/base/controller.py +++ b/lib/galaxy/webapps/base/controller.py @@ -168,7 +168,7 @@ class BaseUIController(BaseController): raise # handled in the caller except Exception: log.exception("Exception in get_object check for %s %s:", class_name, str(id)) - raise Exception('Server error retrieving {} id ( {} ).'.format(class_name, str(id))) + raise Exception(f'Server error retrieving {class_name} id ( {str(id)} ).') def message_exception(self, trans, message, sanitize=True): trans.response.status = 400 @@ -183,7 +183,7 @@ class BaseAPIController(BaseController): check_ownership=check_ownership, check_accessible=check_accessible, deleted=deleted) except exceptions.ItemDeletionException as e: - raise HTTPBadRequest(detail="Invalid {} id ( {} ) specified: {}".format(class_name, str(id), util.unicodify(e))) + raise HTTPBadRequest(detail=f"Invalid {class_name} id ( {str(id)} ) specified: {util.unicodify(e)}") except exceptions.MessageException as e: raise HTTPBadRequest(detail=e.err_msg) except Exception as e: @@ -215,7 +215,7 @@ class BaseAPIController(BaseController): except Exception: invalid.append(item) if invalid: - msg = "The following value(s) for associated users and/or groups could not be parsed: %s." % ', '.join(invalid) + msg = f"The following value(s) for associated users and/or groups could not be parsed: {', '.join(invalid)}." msg += " Valid values are email addresses of users, names of groups, or IDs of both." raise Exception(msg) payload['in_users'] = list(map(str, new_in_users)) @@ -406,7 +406,7 @@ class ExportsHistoryMixin: trans.response.set_content_type('application/x-gzip') else: trans.response.set_content_type('application/x-tar') - disposition = 'attachment; filename="%s"' % jeha.export_name + disposition = f'attachment; filename="{jeha.export_name}"' trans.response.headers["Content-Disposition"] = disposition archive = trans.app.object_store.get_filename(jeha.dataset) return open(archive, mode='rb') @@ -526,7 +526,7 @@ class UsesLibraryMixinItems(SharableItemSecurityMixin): ``library_contents.create`` will branch to this if called with 'from_hda_id' in its payload. """ - log.debug('_copy_hda_to_library_folder: %s' % (str((from_hda_id, folder_id, ldda_message)))) + log.debug(f'_copy_hda_to_library_folder: {str((from_hda_id, folder_id, ldda_message))}') # PRECONDITION: folder_id has already been altered to remove the folder prefix ('F') # TODO: allow name and other, editable ldda attrs? if ldda_message: @@ -1080,15 +1080,15 @@ class UsesVisualizationMixin(UsesLibraryMixinItems): try: dataset_id = trans.security.decode_id(dataset_id) except (AttributeError, TypeError): - raise HTTPBadRequest("Invalid dataset id: %s." % str(dataset_id)) + raise HTTPBadRequest(f"Invalid dataset id: {str(dataset_id)}.") try: data = trans.sa_session.query(trans.app.model.HistoryDatasetAssociation).get(int(dataset_id)) except Exception: - raise HTTPBadRequest("Invalid dataset id: %s." % str(dataset_id)) + raise HTTPBadRequest(f"Invalid dataset id: {str(dataset_id)}.") if not data: - raise HTTPBadRequest("Invalid dataset id: %s." % str(dataset_id)) + raise HTTPBadRequest(f"Invalid dataset id: {str(dataset_id)}.") if check_ownership: # Verify ownership. @@ -1096,7 +1096,7 @@ class UsesVisualizationMixin(UsesLibraryMixinItems): if not user: error("Must be logged in to manage Galaxy items") if data.history.user != user: - error("%s is not owned by current user" % data.__class__.__name__) + error(f"{data.__class__.__name__} is not owned by current user") if check_accessible: current_user_roles = trans.get_current_user_roles() @@ -1292,15 +1292,15 @@ class UsesFormDefinitionsMixin: # Save a form_builder field object params = util.Params(kwd) if isinstance(field_obj, trans.model.UserAddress): - field_obj.desc = util.restore_text(params.get('%s_short_desc' % widget_name, '')) - field_obj.name = util.restore_text(params.get('%s_name' % widget_name, '')) - field_obj.institution = util.restore_text(params.get('%s_institution' % widget_name, '')) - field_obj.address = util.restore_text(params.get('%s_address' % widget_name, '')) - field_obj.city = util.restore_text(params.get('%s_city' % widget_name, '')) - field_obj.state = util.restore_text(params.get('%s_state' % widget_name, '')) - field_obj.postal_code = util.restore_text(params.get('%s_postal_code' % widget_name, '')) - field_obj.country = util.restore_text(params.get('%s_country' % widget_name, '')) - field_obj.phone = util.restore_text(params.get('%s_phone' % widget_name, '')) + field_obj.desc = util.restore_text(params.get(f'{widget_name}_short_desc', '')) + field_obj.name = util.restore_text(params.get(f'{widget_name}_name', '')) + field_obj.institution = util.restore_text(params.get(f'{widget_name}_institution', '')) + field_obj.address = util.restore_text(params.get(f'{widget_name}_address', '')) + field_obj.city = util.restore_text(params.get(f'{widget_name}_city', '')) + field_obj.state = util.restore_text(params.get(f'{widget_name}_state', '')) + field_obj.postal_code = util.restore_text(params.get(f'{widget_name}_postal_code', '')) + field_obj.country = util.restore_text(params.get(f'{widget_name}_country', '')) + field_obj.phone = util.restore_text(params.get(f'{widget_name}_phone', '')) trans.sa_session.add(field_obj) trans.sa_session.flush() @@ -1436,7 +1436,7 @@ class UsesTagsMixin(SharableItemSecurityMixin): def _get_item_tag_assoc(self, trans, item_class_name, id, tag_name): user = trans.user tagged_item = self._get_tagged_item(trans, item_class_name, id) - log.debug("In get_item_tag_assoc with tagged_item %s" % tagged_item) + log.debug(f"In get_item_tag_assoc with tagged_item {tagged_item}") return self.get_tag_handler(trans)._get_item_tag_assoc(user, tagged_item, tag_name) def set_tags_from_list(self, trans, item, new_tags_list, user=None): @@ -1559,7 +1559,7 @@ class UsesExtendedMetadataMixin(SharableItemSecurityMixin): else: # BUG: Everything is cast to string, which can lead to false positives # for cross type comparisions, ie "True" == True - yield prefix, ("%s" % (meta)).encode("utf8", errors='replace') + yield prefix, (f"{meta}").encode("utf8", errors='replace') def sort_by_attr(seq, attr): diff --git a/lib/galaxy/webapps/base/webapp.py b/lib/galaxy/webapps/base/webapp.py index 33b26c2dd1f..4e265a3a040 100644 --- a/lib/galaxy/webapps/base/webapp.py +++ b/lib/galaxy/webapps/base/webapp.py @@ -488,7 +488,7 @@ class GalaxyWebTransaction(base.DefaultWebTransaction, context.ProvidesHistoryCo galaxy_session.user.email) elif galaxy_session is not None and galaxy_session.user is not None and galaxy_session.user.deleted: invalidate_existing_session = True - log.warning("User '%s' is marked deleted, invalidating session" % galaxy_session.user.email) + log.warning(f"User '{galaxy_session.user.email}' is marked deleted, invalidating session") # Do we need to invalidate the session for some reason? if invalidate_existing_session: prev_galaxy_session = galaxy_session diff --git a/lib/galaxy/webapps/galaxy/api/_fetch_util.py b/lib/galaxy/webapps/galaxy/api/_fetch_util.py index 53ed15e3978..9135e8cab4c 100644 --- a/lib/galaxy/webapps/galaxy/api/_fetch_util.py +++ b/lib/galaxy/webapps/galaxy/api/_fetch_util.py @@ -171,7 +171,7 @@ def validate_and_normalize_targets(trans, payload): looks_like_url = True if not looks_like_url: - raise RequestParameterInvalidException("Invalid URL [%s] found in src definition." % url) + raise RequestParameterInvalidException(f"Invalid URL [{url}] found in src definition.") validate_url(url, trans.app.config.fetch_url_allowlist_ips) item["in_place"] = run_as_real_user @@ -191,13 +191,13 @@ def validate_and_normalize_targets(trans, payload): def _handle_invalid_link_data_only_type(item): link_data_only = item.get("link_data_only", False) if link_data_only: - raise RequestParameterInvalidException("link_data_only is invalid for src type [%s]" % item.get("src")) + raise RequestParameterInvalidException(f"link_data_only is invalid for src type [{item.get('src')}]") def _handle_invalid_link_data_only_elements_type(item): link_data_only = item.get("link_data_only", False) if link_data_only and item.get("elements_from", False) in ELEMENTS_FROM_TRANSIENT_TYPES: - raise RequestParameterInvalidException("link_data_only is invalid for derived elements from [%s]" % item.get("elements_from")) + raise RequestParameterInvalidException(f"link_data_only is invalid for derived elements from [{item.get('elements_from')}]") def _for_each_src(f, obj): diff --git a/lib/galaxy/webapps/galaxy/api/cloudauthz.py b/lib/galaxy/webapps/galaxy/api/cloudauthz.py index 3617de5fb2b..1fa76c2e53f 100644 --- a/lib/galaxy/webapps/galaxy/api/cloudauthz.py +++ b/lib/galaxy/webapps/galaxy/api/cloudauthz.py @@ -117,7 +117,7 @@ class CloudAuthzController(BaseGalaxyAPIController): description = payload.get("description", "") if not isinstance(config, dict): - log.debug(msg_template.format("invalid config type `{}`, expect `dict`".format(type(config)))) + log.debug(msg_template.format(f"invalid config type `{type(config)}`, expect `dict`")) raise RequestParameterInvalidException('Invalid type for the required `config` variable; expect `dict` ' 'but received `{}`.'.format(type(config))) if authn_id: @@ -149,7 +149,7 @@ class CloudAuthzController(BaseGalaxyAPIController): description=description ) view = self.cloudauthz_serializer.serialize_to_view(new_cloudauthz, trans=trans, **self._parse_serialization_params(kwargs, 'summary')) - log.debug('Created a new cloudauthz record for the user id `{}` '.format(str(trans.user.id))) + log.debug(f'Created a new cloudauthz record for the user id `{str(trans.user.id)}` ') return view except Exception as e: log.exception(msg_template.format("exception while creating the new cloudauthz record")) @@ -183,7 +183,7 @@ class CloudAuthzController(BaseGalaxyAPIController): cloudauthz = trans.app.authnz_manager.try_get_authz_config(trans.sa_session, trans.user.id, authz_id) trans.sa_session.delete(cloudauthz) trans.sa_session.flush() - log.debug('Deleted a cloudauthz record with id `{}` for the user id `{}` '.format(authz_id, str(trans.user.id))) + log.debug(f'Deleted a cloudauthz record with id `{authz_id}` for the user id `{str(trans.user.id)}` ') view = self.cloudauthz_serializer.serialize_to_view(cloudauthz, trans=trans, **self._parse_serialization_params(kwargs, 'summary')) trans.response.status = '200' return view diff --git a/lib/galaxy/webapps/galaxy/api/datasets.py b/lib/galaxy/webapps/galaxy/api/datasets.py index d0539848c98..55f178a6841 100644 --- a/lib/galaxy/webapps/galaxy/api/datasets.py +++ b/lib/galaxy/webapps/galaxy/api/datasets.py @@ -495,7 +495,7 @@ class DatasetsController(BaseGalaxyAPIController, UsesVisualizationMixin): log.exception("Error getting metadata_file (%s) for dataset (%s) from history (%s)", metadata_file, history_content_id, history_id) trans.response.status = 500 - rval = "Could not get metadata for dataset: %s" % util.unicodify(e) + rval = f"Could not get metadata for dataset: {util.unicodify(e)}" return rval @web.expose_api_anonymous diff --git a/lib/galaxy/webapps/galaxy/api/forms.py b/lib/galaxy/webapps/galaxy/api/forms.py index 1ca8588d08f..a105d86642f 100644 --- a/lib/galaxy/webapps/galaxy/api/forms.py +++ b/lib/galaxy/webapps/galaxy/api/forms.py @@ -41,14 +41,14 @@ class FormDefinitionAPIController(BaseGalaxyAPIController): decoded_form_definition_id = trans.security.decode_id(form_definition_id) except TypeError: trans.response.status = 400 - return "Malformed form definition id ( %s ) specified, unable to decode." % str(form_definition_id) + return f"Malformed form definition id ( {str(form_definition_id)} ) specified, unable to decode." try: form_definition = trans.sa_session.query(trans.app.model.FormDefinition).get(decoded_form_definition_id) except Exception: form_definition = None if not form_definition or not trans.user_is_admin: trans.response.status = 400 - return "Invalid form definition id ( %s ) specified." % str(form_definition_id) + return f"Invalid form definition id ( {str(form_definition_id)} ) specified." item = form_definition.to_dict(view='element', value_mapper={'id': trans.security.encode_id, 'form_definition_current_id': trans.security.encode_id}) item['url'] = url_for('form', id=form_definition_id) return item diff --git a/lib/galaxy/webapps/galaxy/api/histories.py b/lib/galaxy/webapps/galaxy/api/histories.py index 6b57e569686..6c14cadb69d 100644 --- a/lib/galaxy/webapps/galaxy/api/histories.py +++ b/lib/galaxy/webapps/galaxy/api/histories.py @@ -355,7 +355,7 @@ class HistoriesController(BaseGalaxyAPIController, ExportsHistoryMixin, ImportsH raise exceptions.MessageException("Please provide a url or file.") job = self.queue_history_import(trans, archive_type=archive_type, archive_source=archive_source) job_dict = job.to_dict() - job_dict["message"] = "Importing history from source '%s'. This history will be visible when the import is complete." % archive_source + job_dict["message"] = f"Importing history from source '{archive_source}'. This history will be visible when the import is complete." return trans.security.encode_all_ids(job_dict) new_history = None @@ -363,7 +363,7 @@ class HistoriesController(BaseGalaxyAPIController, ExportsHistoryMixin, ImportsH if copy_this_history_id: decoded_id = self.decode_id(copy_this_history_id) original_history = self.manager.get_accessible(decoded_id, trans.user, current_history=trans.history) - hist_name = hist_name or ("Copy of '%s'" % original_history.name) + hist_name = hist_name or (f"Copy of '{original_history.name}'") new_history = original_history.copy(name=hist_name, target_user=trans.user, all_datasets=all_datasets) # otherwise, create a new empty history diff --git a/lib/galaxy/webapps/galaxy/api/history_contents.py b/lib/galaxy/webapps/galaxy/api/history_contents.py index 5bff0f937d4..57bc80a5e1b 100644 --- a/lib/galaxy/webapps/galaxy/api/history_contents.py +++ b/lib/galaxy/webapps/galaxy/api/history_contents.py @@ -403,7 +403,7 @@ class HistoryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, source = payload.get('source', None) if source not in ('library', 'hda'): raise exceptions.RequestParameterInvalidException( - "'source' must be either 'library' or 'hda': %s" % (source)) + f"'source' must be either 'library' or 'hda': {source}") content = payload.get('content', None) if content is None: raise exceptions.RequestParameterMissingException("'content' id of lda or hda is missing") @@ -431,7 +431,7 @@ class HistoryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, ld = self.get_library_dataset(trans, content) if type(ld) is not trans.app.model.LibraryDataset: raise exceptions.RequestParameterInvalidException( - "Library content id ( %s ) is not a dataset" % content) + f"Library content id ( {content} ) is not a dataset") hda = ld.library_dataset_dataset_association.to_history_dataset_association(history, add_to_history=True) return hda @@ -473,7 +473,7 @@ class HistoryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, user=trans.user, trans=trans, **self._parse_serialization_params(kwd, 'detailed')) rval.append(hda_dict) else: - message = "Invalid 'source' parameter in request %s" % source + message = f"Invalid 'source' parameter in request {source}" raise exceptions.RequestParameterInvalidException(message) trans.sa_session.flush() @@ -548,7 +548,7 @@ class HistoryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, dataset_instance_attributes=dataset_instance_attributes, ) else: - message = "Invalid 'source' parameter in request %s" % source + message = f"Invalid 'source' parameter in request {source}" raise exceptions.RequestParameterInvalidException(message) # if the consumer specified keys or view, use the secondary serializer @@ -818,7 +818,7 @@ class HistoryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, user=trans.user, trans=trans, **self._parse_serialization_params(kwd, 'detailed')) def __handle_unknown_contents_type(self, trans, contents_type): - raise exceptions.UnknownContentsType('Unknown contents type: %s' % type) + raise exceptions.UnknownContentsType(f'Unknown contents type: {type}') def __index_v2(self, trans, history_id, **kwd): """ diff --git a/lib/galaxy/webapps/galaxy/api/job_files.py b/lib/galaxy/webapps/galaxy/api/job_files.py index 282af0249b2..1376de16918 100644 --- a/lib/galaxy/webapps/galaxy/api/job_files.py +++ b/lib/galaxy/webapps/galaxy/api/job_files.py @@ -116,7 +116,7 @@ class JobFilesAPIController(BaseGalaxyAPIController): def __authorize_job_access(self, trans, encoded_job_id, **kwargs): for key in ["path", "job_key"]: if key not in kwargs: - error_message = "Job files action requires a valid '%s'." % key + error_message = f"Job files action requires a valid '{key}'." raise exceptions.ObjectAttributeMissingException(error_message) job_id = trans.security.decode_id(encoded_job_id) diff --git a/lib/galaxy/webapps/galaxy/api/jobs.py b/lib/galaxy/webapps/galaxy/api/jobs.py index c05740b122e..e856a16450b 100644 --- a/lib/galaxy/webapps/galaxy/api/jobs.py +++ b/lib/galaxy/webapps/galaxy/api/jobs.py @@ -324,11 +324,11 @@ class JobController(BaseGalaxyAPIController, UsesVisualizationMixin): """ job = self.__get_job(trans, id) if not job: - raise exceptions.ObjectNotFound("Could not access job with id '%s'" % id) + raise exceptions.ObjectNotFound(f"Could not access job with id '{id}'") if job.state == job.states.PAUSED: job.resume() else: - exceptions.RequestParameterInvalidException("Job with id '%s' is not paused" % (job.tool_id)) + exceptions.RequestParameterInvalidException(f"Job with id '{job.tool_id}' is not paused") return self.__dictify_associations(trans, job.output_datasets, job.output_library_datasets) @expose_api_anonymous @@ -419,12 +419,12 @@ class JobController(BaseGalaxyAPIController, UsesVisualizationMixin): job = self.__get_job(trans, id) if not job: - raise exceptions.ObjectNotFound("Could not access job with id '%s'" % id) + raise exceptions.ObjectNotFound(f"Could not access job with id '{id}'") tool = self.app.toolbox.get_tool(job.tool_id, kwd.get('tool_version') or job.tool_version) if tool is None: raise exceptions.ObjectNotFound("Requested tool not found") if not tool.is_workflow_compatible: - raise exceptions.ConfigDoesNotAllowException("Tool '%s' cannot be rerun." % (job.tool_id)) + raise exceptions.ConfigDoesNotAllowException(f"Tool '{job.tool_id}' cannot be rerun.") return tool.to_json(trans, {}, job=job) def __dictify_associations(self, trans, *association_lists): diff --git a/lib/galaxy/webapps/galaxy/api/library_contents.py b/lib/galaxy/webapps/galaxy/api/library_contents.py index d2c8c4f871d..d0d25f135ab 100644 --- a/lib/galaxy/webapps/galaxy/api/library_contents.py +++ b/lib/galaxy/webapps/galaxy/api/library_contents.py @@ -221,7 +221,7 @@ class LibraryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, create_type = payload.pop('create_type') if create_type not in ('file', 'folder', 'collection'): trans.response.status = 400 - return "Invalid value for 'create_type' parameter ( %s ) specified." % create_type + return f"Invalid value for 'create_type' parameter ( {create_type} ) specified." if 'folder_id' not in payload: trans.response.status = 400 @@ -375,7 +375,7 @@ class LibraryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, else: # BUG: Everything is cast to string, which can lead to false positives # for cross type comparisions, ie "True" == True - yield prefix, ("%s" % (meta)).encode("utf8", errors='replace') + yield prefix, (f"{meta}").encode("utf8", errors='replace') @expose_api def update(self, trans, id, library_id, payload, **kwd): @@ -414,7 +414,7 @@ class LibraryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, elif content_id.startswith('F'): return 'LibraryFolder', content_id[1:] else: - raise HTTPBadRequest('Malformed library content id ( %s ) specified, unable to decode.' % str(content_id)) + raise HTTPBadRequest(f'Malformed library content id ( {str(content_id)} ) specified, unable to decode.') @expose_api def delete(self, trans, library_id, id, **kwd): diff --git a/lib/galaxy/webapps/galaxy/api/library_datasets.py b/lib/galaxy/webapps/galaxy/api/library_datasets.py index 624b9744614..e99b1ab5581 100644 --- a/lib/galaxy/webapps/galaxy/api/library_datasets.py +++ b/lib/galaxy/webapps/galaxy/api/library_datasets.py @@ -633,7 +633,7 @@ class LibraryDatasetsController(BaseGalaxyAPIController, UsesVisualizationMixin, if is_composite: # need to add all the components from the extra_files_path to the zip if zpathext == '': - zpath = '%s.html' % zpath # fake the real nature of the html file + zpath = f'{zpath}.html' # fake the real nature of the html file try: if archive_format == 'zip': archive.write(ldda.dataset.file_name, zpath) # add the primary of a composite set @@ -691,7 +691,7 @@ class LibraryDatasetsController(BaseGalaxyAPIController, UsesVisualizationMixin, trans.response.headers['Content-Length'] = str(fStat.st_size) fname = f"{ldda.name}.{ldda.extension}" fname = ''.join(c in util.FILENAME_VALID_CHARS and c or '_' for c in fname)[0:150] - trans.response.headers["Content-Disposition"] = 'attachment; filename="%s"' % fname + trans.response.headers["Content-Disposition"] = f'attachment; filename="{fname}"' try: return open(dataset.file_name, 'rb') except Exception: diff --git a/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py b/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py index aed41af1b72..b9434eae382 100644 --- a/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py +++ b/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py @@ -288,13 +288,13 @@ class ToolShedRepositoriesController(BaseGalaxyAPIController): try: repository = get_tool_shed_repository_by_id(self.app, id) except ValueError: - raise HTTPBadRequest(detail="No repository with id '%s' found" % id) + raise HTTPBadRequest(detail=f"No repository with id '{id}' found") else: tsr_arguments = ['name', 'owner', 'changeset_revision', 'tool_shed_url'] try: tsr_arguments = {key: kwd[key] for key in tsr_arguments} except KeyError as e: - raise HTTPBadRequest(detail="Missing required parameter '%s'" % e.args[0]) + raise HTTPBadRequest(detail=f"Missing required parameter '{e.args[0]}'") repository = get_installed_repository(app=self.app, tool_shed=tsr_arguments['tool_shed_url'], name=tsr_arguments['name'], @@ -363,11 +363,11 @@ class ToolShedRepositoriesController(BaseGalaxyAPIController): except Exception: failed.append(repository_id) if successful: - message = "Successful reset of metadata for %s." % len(successful) + message = f"Successful reset of metadata for {len(successful)}." if failed: - message += " Failed for %s." % len(failed) + message += f" Failed for {len(failed)}." elif failed: - message = "Failed to reset metadata for %s." % len(failed) + message = f"Failed to reset metadata for {len(failed)}." return dict(message=message, successful=successful, failed=failed) else: raise exceptions.MessageException("Please specify repository ids [repository_ids].") @@ -453,7 +453,7 @@ class ToolShedRepositoriesController(BaseGalaxyAPIController): # Example URL: http://localhost:8763/api/tool_shed_repositories/df7a1f0c02a5b08e tool_shed_repository = get_tool_shed_repository_by_id(self.app, id) if tool_shed_repository is None: - log.debug("Unable to locate tool_shed_repository record for id %s." % (str(id))) + log.debug(f"Unable to locate tool_shed_repository record for id {str(id)}.") return {} tool_shed_repository_dict = tool_shed_repository.as_dict(value_mapper=self.__get_value_mapper(trans, tool_shed_repository)) tool_shed_repository_dict['url'] = url_for(controller='tool_shed_repositories', diff --git a/lib/galaxy/webapps/galaxy/api/tools.py b/lib/galaxy/webapps/galaxy/api/tools.py index fa0ba60e8ad..5b65f247666 100644 --- a/lib/galaxy/webapps/galaxy/api/tools.py +++ b/lib/galaxy/webapps/galaxy/api/tools.py @@ -215,7 +215,7 @@ class ToolsController(BaseGalaxyAPIController, UsesVisualizationMixin): tools = self.app.toolbox.get_tool(id, get_all_versions=True) for tool in tools: if not tool.allow_user_access(trans.user): - raise exceptions.AuthenticationFailed("Access denied, please login for tool with id '%s'." % id) + raise exceptions.AuthenticationFailed(f"Access denied, please login for tool with id '{id}'.") else: tools = [self._get_tool(id, tool_version=tool_version, user=trans.user)] @@ -433,7 +433,7 @@ class ToolsController(BaseGalaxyAPIController, UsesVisualizationMixin): tool_tarball = trans.app.toolbox.package_tool(trans, id) trans.response.set_content_type('application/x-gzip') download_file = open(tool_tarball, "rb") - trans.response.headers["Content-Disposition"] = 'attachment; filename="%s.tgz"' % (id) + trans.response.headers["Content-Disposition"] = f'attachment; filename="{id}.tgz"' return download_file @expose_api_anonymous @@ -493,7 +493,7 @@ class ToolsController(BaseGalaxyAPIController, UsesVisualizationMixin): tool_id = payload.get("tool_id") tool_uuid = payload.get("tool_uuid") if tool_id in PROTECTED_TOOLS: - raise exceptions.RequestParameterInvalidException("Cannot execute tool [%s] directly, must use alternative endpoint." % tool_id) + raise exceptions.RequestParameterInvalidException(f"Cannot execute tool [{tool_id}] directly, must use alternative endpoint.") if tool_id is None and tool_uuid is None: raise exceptions.RequestParameterInvalidException("Must specify a valid tool_id to use this endpoint.") return self._create(trans, payload, **kwd) @@ -525,7 +525,7 @@ class ToolsController(BaseGalaxyAPIController, UsesVisualizationMixin): if not trans.user: log.warning("Anonymous user attempts to execute tool, but account activation is turned on.") elif not trans.user.active: - log.warning("User \"%s\" attempts to execute tool, but account activation is turned on and user account is not active." % trans.user.email) + log.warning(f"User \"{trans.user.email}\" attempts to execute tool, but account activation is turned on and user account is not active.") # Set running history from payload parameters. # History not set correctly as part of this API call for @@ -540,7 +540,7 @@ class ToolsController(BaseGalaxyAPIController, UsesVisualizationMixin): # Set up inputs. inputs = payload.get('inputs', {}) if not isinstance(inputs, dict): - raise exceptions.RequestParameterInvalidException("inputs invalid %s" % inputs) + raise exceptions.RequestParameterInvalidException(f"inputs invalid {inputs}") # Find files coming in as multipart file data and add to inputs. for k, v in payload.items(): @@ -640,9 +640,9 @@ class ToolsController(BaseGalaxyAPIController, UsesVisualizationMixin): def _get_tool(self, id, tool_version=None, user=None): tool = self.app.toolbox.get_tool(id, tool_version) if not tool: - raise exceptions.ObjectNotFound("Could not find tool with id '%s'." % id) + raise exceptions.ObjectNotFound(f"Could not find tool with id '{id}'.") if not tool.allow_user_access(user): - raise exceptions.AuthenticationFailed("Access denied, please login for tool with id '%s'." % id) + raise exceptions.AuthenticationFailed(f"Access denied, please login for tool with id '{id}'.") return tool diff --git a/lib/galaxy/webapps/galaxy/api/toolshed.py b/lib/galaxy/webapps/galaxy/api/toolshed.py index e2d1d798773..6a0fec3ad88 100644 --- a/lib/galaxy/webapps/galaxy/api/toolshed.py +++ b/lib/galaxy/webapps/galaxy/api/toolshed.py @@ -46,6 +46,6 @@ class ToolShedController(BaseGalaxyAPIController): try: return json.loads(url_get(tool_shed_url, params=dict(params), pathspec=pathspec)) except Exception as e: - raise MessageException("Invalid server response. %s." % str(e)) + raise MessageException(f"Invalid server response. {str(e)}.") else: raise MessageException("Invalid toolshed url.") diff --git a/lib/galaxy/webapps/galaxy/api/users.py b/lib/galaxy/webapps/galaxy/api/users.py index 75f19224f03..b240563ee2e 100644 --- a/lib/galaxy/webapps/galaxy/api/users.py +++ b/lib/galaxy/webapps/galaxy/api/users.py @@ -88,27 +88,27 @@ class UserAPIController(BaseGalaxyAPIController, UsesTagsMixin, BaseUIController deleted = util.string_as_bool(deleted) if f_email and (trans.user_is_admin or trans.app.config.expose_user_email): - query = query.filter(User.email.like("%%%s%%" % f_email)) + query = query.filter(User.email.like(f"%{f_email}%")) if f_name and (trans.user_is_admin or trans.app.config.expose_user_name): - query = query.filter(User.username.like("%%%s%%" % f_name)) + query = query.filter(User.username.like(f"%{f_name}%")) if f_any: if trans.user_is_admin: query = query.filter(or_( - User.email.like("%%%s%%" % f_any), - User.username.like("%%%s%%" % f_any) + User.email.like(f"%{f_any}%"), + User.username.like(f"%{f_any}%") )) else: if trans.app.config.expose_user_email and trans.app.config.expose_user_name: query = query.filter(or_( - User.email.like("%%%s%%" % f_any), - User.username.like("%%%s%%" % f_any) + User.email.like(f"%{f_any}%"), + User.username.like(f"%{f_any}%") )) elif trans.app.config.expose_user_email: - query = query.filter(User.email.like("%%%s%%" % f_any)) + query = query.filter(User.email.like(f"%{f_any}%")) elif trans.app.config.expose_user_name: - query = query.filter(User.username.like("%%%s%%" % f_any)) + query = query.filter(User.username.like(f"%{f_any}%")) if deleted: # only admins can see deleted users @@ -434,7 +434,7 @@ class UserAPIController(BaseGalaxyAPIController, UsesTagsMixin, BaseUIController else: message = 'Unable to send activation email, please contact your local Galaxy administrator.' if trans.app.config.error_email_to is not None: - message += ' Contact: %s' % trans.app.config.error_email_to + message += f' Contact: {trans.app.config.error_email_to}' raise exceptions.InternalServerError(message) # Update public name if 'username' in payload: @@ -495,13 +495,13 @@ class UserAPIController(BaseGalaxyAPIController, UsesTagsMixin, BaseUIController try: user_address = trans.sa_session.query(UserAddress).get(trans.security.decode_id(d['id'])) except Exception as e: - raise exceptions.ObjectNotFound('Failed to access user address ({}). {}'.format(d['id'], e)) + raise exceptions.ObjectNotFound(f"Failed to access user address ({d['id']}). {e}") else: user_address = UserAddress() trans.log_event('User address added') for field in AddressField.fields(): if str(field[2]).lower() == 'required' and not d.get(field[0]): - raise exceptions.ObjectAttributeMissingException('Address {}: {} ({}) required.'.format(index + 1, field[1], field[0])) + raise exceptions.ObjectAttributeMissingException(f'Address {index + 1}: {field[1]} ({field[0]}) required.') setattr(user_address, field[0], str(d.get(field[0], ''))) user_address.user = user user.addresses.append(user_address) @@ -531,9 +531,9 @@ class UserAPIController(BaseGalaxyAPIController, UsesTagsMixin, BaseUIController tool_id = payload.get('object_id') tool = self.app.toolbox.get_tool(tool_id) if not tool: - raise exceptions.ObjectNotFound("Could not find tool with id '%s'." % tool_id) + raise exceptions.ObjectNotFound(f"Could not find tool with id '{tool_id}'.") if not tool.allow_user_access(user): - raise exceptions.AuthenticationFailed("Access denied for tool with id '%s'." % tool_id) + raise exceptions.AuthenticationFailed(f"Access denied for tool with id '{tool_id}'.") if 'tools' in favorites: favorite_tools = favorites['tools'] else: @@ -577,7 +577,7 @@ class UserAPIController(BaseGalaxyAPIController, UsesTagsMixin, BaseUIController if object_type in ['tools']: pass else: - raise exceptions.ObjectAttributeInvalidException("This type is not supported. Given object_type: %s" % object_type) + raise exceptions.ObjectAttributeInvalidException(f"This type is not supported. Given object_type: {object_type}") @expose_api def get_password(self, trans, id, payload=None, **kwd): @@ -695,7 +695,7 @@ class UserAPIController(BaseGalaxyAPIController, UsesTagsMixin, BaseUIController if len(split) > 1: description = split[1] else: - log.warning('No description specified in the __doc__ string for %s.' % filter_name) + log.warning(f'No description specified in the __doc__ string for {filter_name}.') filter_inputs.append({ 'type': 'boolean', @@ -895,14 +895,14 @@ class UserAPIController(BaseGalaxyAPIController, UsesTagsMixin, BaseUIController del dbkeys[key] user.preferences['dbkeys'] = json.dumps(dbkeys) trans.sa_session.flush() - return {'message': 'Deleted %s.' % key} + return {'message': f'Deleted {key}.'} else: - raise exceptions.ObjectNotFound('Could not find and delete build (%s).' % key) + raise exceptions.ObjectNotFound(f'Could not find and delete build ({key}).') def _get_user(self, trans, id): user = self.get_user(trans, id) if not user: - raise exceptions.RequestParameterInvalidException('Invalid user (%s).' % id) + raise exceptions.RequestParameterInvalidException(f'Invalid user ({id}).') if user != trans.user and not trans.user_is_admin: raise exceptions.InsufficientPermissionsException('Access denied.') return user diff --git a/lib/galaxy/webapps/galaxy/api/visualizations.py b/lib/galaxy/webapps/galaxy/api/visualizations.py index 2eb158df9f3..7782081310a 100644 --- a/lib/galaxy/webapps/galaxy/api/visualizations.py +++ b/lib/galaxy/webapps/galaxy/api/visualizations.py @@ -187,30 +187,30 @@ class VisualizationsController(BaseGalaxyAPIController, UsesVisualizationMixin, # TODO: validate types in VALID_TYPES/registry names at the mixin/model level? if key == 'type': if not isinstance(val, str): - raise ValidationError('{} must be a string or unicode: {}'.format(key, str(type(val)))) + raise ValidationError(f'{key} must be a string or unicode: {str(type(val))}') val = util.sanitize_html.sanitize_html(val) elif key == 'config': if not isinstance(val, dict): - raise ValidationError('{} must be a dictionary: {}'.format(key, str(type(val)))) + raise ValidationError(f'{key} must be a dictionary: {str(type(val))}') elif key == 'annotation': if not isinstance(val, str): - raise ValidationError('{} must be a string or unicode: {}'.format(key, str(type(val)))) + raise ValidationError(f'{key} must be a string or unicode: {str(type(val))}') val = util.sanitize_html.sanitize_html(val) # these are keys that actually only be *updated* at the revision level and not here # (they are still valid for create, tho) elif key == 'title': if not isinstance(val, str): - raise ValidationError('{} must be a string or unicode: {}'.format(key, str(type(val)))) + raise ValidationError(f'{key} must be a string or unicode: {str(type(val))}') val = util.sanitize_html.sanitize_html(val) elif key == 'slug': if not isinstance(val, str): - raise ValidationError('{} must be a string: {}'.format(key, str(type(val)))) + raise ValidationError(f'{key} must be a string: {str(type(val))}') val = util.sanitize_html.sanitize_html(val) elif key == 'dbkey': if not isinstance(val, str): - raise ValidationError('{} must be a string or unicode: {}'.format(key, str(type(val)))) + raise ValidationError(f'{key} must be a string or unicode: {str(type(val))}') val = util.sanitize_html.sanitize_html(val) elif key not in valid_but_uneditable_keys: diff --git a/lib/galaxy/webapps/galaxy/api/workflows.py b/lib/galaxy/webapps/galaxy/api/workflows.py index 0684ded7496..4614d07d88c 100644 --- a/lib/galaxy/webapps/galaxy/api/workflows.py +++ b/lib/galaxy/webapps/galaxy/api/workflows.py @@ -326,11 +326,11 @@ class WorkflowsAPIController(BaseGalaxyAPIController, UsesStoredWorkflowMixin, U } if payload is None or len(ways_to_create.intersection(payload)) == 0: - message = "One parameter among - %s - must be specified" % ", ".join(ways_to_create) + message = f"One parameter among - {', '.join(ways_to_create)} - must be specified" raise exceptions.RequestParameterMissingException(message) if len(ways_to_create.intersection(payload)) > 1: - message = "Only one parameter among - %s - must be specified" % ", ".join(ways_to_create) + message = f"Only one parameter among - {', '.join(ways_to_create)} - must be specified" raise exceptions.RequestParameterInvalidException(message) if 'installed_repository_file' in payload: @@ -338,7 +338,7 @@ class WorkflowsAPIController(BaseGalaxyAPIController, UsesStoredWorkflowMixin, U raise exceptions.AdminRequiredException() installed_repository_file = payload.get('installed_repository_file', '') if not os.path.exists(installed_repository_file): - raise exceptions.RequestParameterInvalidException("Workflow file '%s' not found" % installed_repository_file) + raise exceptions.RequestParameterInvalidException(f"Workflow file '{installed_repository_file}' not found") elif os.path.getsize(os.path.abspath(installed_repository_file)) > 0: with open(installed_repository_file, encoding='utf-8') as f: workflow_data = f.read() @@ -366,7 +366,7 @@ class WorkflowsAPIController(BaseGalaxyAPIController, UsesStoredWorkflowMixin, U try: archive_data = requests.get(archive_source).text except Exception: - raise exceptions.MessageException("Failed to open URL '%s'." % escape(archive_source)) + raise exceptions.MessageException(f"Failed to open URL '{escape(archive_source)}'.") elif hasattr(archive_file, 'file'): uploaded_file = archive_file.file uploaded_file_name = uploaded_file.name @@ -524,7 +524,7 @@ class WorkflowsAPIController(BaseGalaxyAPIController, UsesStoredWorkflowMixin, U trans.sa_session.flush() # TODO: Unsure of response message to let api know that a workflow was successfully deleted - return ("Workflow '%s' successfully deleted" % stored_workflow.name) + return (f"Workflow '{stored_workflow.name}' successfully deleted") @expose_api def import_new_workflow_deprecated(self, trans: GalaxyWebTransaction, payload, **kwd): @@ -746,7 +746,7 @@ class WorkflowsAPIController(BaseGalaxyAPIController, UsesStoredWorkflowMixin, U workflow_id = workflow.id workflow = workflow.latest_workflow - response = {"message": "Workflow '%s' imported successfully." % escape(workflow.name), "status": "success", + response = {"message": f"Workflow '{escape(workflow.name)}' imported successfully.", "status": "success", "id": trans.security.encode_id(workflow_id)} if workflow.has_errors: response["message"] = "Imported, but some steps in this workflow have validation errors." @@ -803,7 +803,7 @@ class WorkflowsAPIController(BaseGalaxyAPIController, UsesStoredWorkflowMixin, U try: stored_workflow = self.get_stored_workflow(trans, workflow_id, check_ownership=False) except Exception: - raise exceptions.ObjectNotFound("Malformed workflow id ( %s ) specified." % workflow_id) + raise exceptions.ObjectNotFound(f"Malformed workflow id ( {workflow_id} ) specified.") if stored_workflow.importable is False: raise exceptions.ItemAccessibilityException('The owner of this workflow has disabled imports via this link.') elif stored_workflow.deleted: @@ -1240,7 +1240,7 @@ class WorkflowsAPIController(BaseGalaxyAPIController, UsesStoredWorkflowMixin, U # specified in https://github.com/biocompute-objects/BCO_Specification/blob/main/docs/top-level.md#203-etag-etag etag = hashlib.sha256(json.dumps(bco_dict, sort_keys=True).encode()).hexdigest() bco_dict.update({ - 'object_id': url_for(controller="api/invocations/%s" % invocation_id, action='biocompute', qualified=True), + 'object_id': url_for(controller=f"api/invocations/{invocation_id}", action='biocompute', qualified=True), 'spec_version': spec_version, 'etag': etag, }) @@ -1274,7 +1274,7 @@ class WorkflowsAPIController(BaseGalaxyAPIController, UsesStoredWorkflowMixin, U generated will very likely change in important ways over time. """ ret_dict = self._generate_invocation_bco(trans, invocation_id, **kwd) - trans.response.headers["Content-Disposition"] = 'attachment; filename="bco_%s.json"' % invocation_id + trans.response.headers["Content-Disposition"] = f'attachment; filename="bco_{invocation_id}.json"' trans.response.set_content_type("application/json") return format_return_as_json(ret_dict, pretty=True) diff --git a/lib/galaxy/webapps/galaxy/buildapp.py b/lib/galaxy/webapps/galaxy/buildapp.py index 66c89f0eff7..aab62951408 100644 --- a/lib/galaxy/webapps/galaxy/buildapp.py +++ b/lib/galaxy/webapps/galaxy/buildapp.py @@ -662,14 +662,14 @@ def populate_api_routes(webapp, app): for noun, suffix in invoke_names.items(): name = f"{noun}{suffix}" webapp.mapper.connect( - 'list_workflow_%s' % name, + f'list_workflow_{name}', '/api/workflows/{workflow_id}/%s' % noun, controller='workflows', action='index_invocations', conditions=dict(method=['GET']) ) webapp.mapper.connect( - 'workflow_%s' % name, + f'workflow_{name}', '/api/workflows/{workflow_id}/%s' % noun, controller='workflows', action='invoke', @@ -682,21 +682,21 @@ def populate_api_routes(webapp, app): # /api/workflows//usage/ (deprecated) conditions = conditions or dict(method=['GET']) webapp.mapper.connect( - 'workflow_invocation_%s' % endpoint_name, + f'workflow_invocation_{endpoint_name}', '/api/workflows/{workflow_id}/invocations/{invocation_id}' + endpoint_suffix, controller='workflows', action=action, conditions=conditions, ) webapp.mapper.connect( - 'workflow_usage_%s' % endpoint_name, + f'workflow_usage_{endpoint_name}', '/api/workflows/{workflow_id}/usage/{invocation_id}' + endpoint_suffix, controller='workflows', action=action, conditions=conditions, ) webapp.mapper.connect( - 'invocation_%s' % endpoint_name, + f'invocation_{endpoint_name}', '/api/invocations/{invocation_id}' + endpoint_suffix, controller='workflows', action=action, @@ -1224,47 +1224,47 @@ def populate_api_routes(webapp, app): def _add_item_tags_controller(webapp, name_prefix, path_prefix, **kwd): # Not just using map.resources because actions should be based on name not id - controller = "%stags" % name_prefix - name = "%stag" % name_prefix - path = "%s/tags" % path_prefix + controller = f"{name_prefix}tags" + name = f"{name_prefix}tag" + path = f"{path_prefix}/tags" map = webapp.mapper # Allow view items' tags. map.connect(name, path, controller=controller, action="index", conditions=dict(method=["GET"])) # Allow remove tag from item - map.connect("%s_delete" % name, "%s/tags/{tag_name}" % path_prefix, + map.connect(f"{name}_delete", "%s/tags/{tag_name}" % path_prefix, controller=controller, action="delete", conditions=dict(method=["DELETE"])) # Allow create a new tag with from name - map.connect("%s_create" % name, "%s/tags/{tag_name}" % path_prefix, + map.connect(f"{name}_create", "%s/tags/{tag_name}" % path_prefix, controller=controller, action="create", conditions=dict(method=["POST"])) # Allow update tag value - map.connect("%s_update" % name, "%s/tags/{tag_name}" % path_prefix, + map.connect(f"{name}_update", "%s/tags/{tag_name}" % path_prefix, controller=controller, action="update", conditions=dict(method=["PUT"])) # Allow show tag by name - map.connect("%s_show" % name, "%s/tags/{tag_name}" % path_prefix, + map.connect(f"{name}_show", "%s/tags/{tag_name}" % path_prefix, controller=controller, action="show", conditions=dict(method=["GET"])) def _add_item_extended_metadata_controller(webapp, name_prefix, path_prefix, **kwd): - controller = "%sextended_metadata" % name_prefix - name = "%sextended_metadata" % name_prefix + controller = f"{name_prefix}extended_metadata" + name = f"{name_prefix}extended_metadata" webapp.mapper.resource(name, "extended_metadata", path_prefix=path_prefix, controller=controller) def _add_item_annotation_controller(webapp, name_prefix, path_prefix, **kwd): - controller = "%sannotations" % name_prefix - name = "%sannotation" % name_prefix + controller = f"{name_prefix}annotations" + name = f"{name_prefix}annotation" webapp.mapper.resource(name, "annotation", path_prefix=path_prefix, controller=controller) def _add_item_provenance_controller(webapp, name_prefix, path_prefix, **kwd): - controller = "%sprovenance" % name_prefix - name = "%sprovenance" % name_prefix + controller = f"{name_prefix}provenance" + name = f"{name_prefix}provenance" webapp.mapper.resource(name, "provenance", path_prefix=path_prefix, controller=controller) diff --git a/lib/galaxy/webapps/galaxy/controllers/_create_history_template.py b/lib/galaxy/webapps/galaxy/controllers/_create_history_template.py index c6fefe5998f..9be9c2c77d5 100644 --- a/lib/galaxy/webapps/galaxy/controllers/_create_history_template.py +++ b/lib/galaxy/webapps/galaxy/controllers/_create_history_template.py @@ -90,7 +90,7 @@ def render_item_job(trans, job, children): tool_name = tool.name tool_desc = tool.description else: - tool_name = "Unknown tool with id: %s" % job.tool_id + tool_name = f"Unknown tool with id: {job.tool_id}" tool_desc = '' params_object = None try: diff --git a/lib/galaxy/webapps/galaxy/controllers/admin.py b/lib/galaxy/webapps/galaxy/controllers/admin.py index b18af172e6f..d6d8fa6b221 100644 --- a/lib/galaxy/webapps/galaxy/controllers/admin.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin.py @@ -362,7 +362,7 @@ class QuotaListGrid(grids.Grid): if quota.deleted: return "deleted" elif quota.default: - return "default for %s users" % quota.default[0].type + return f"default for {quota.default[0].type} users" return "" class UsersColumn(grids.GridColumn): @@ -460,7 +460,7 @@ class ToolVersionListGrid(grids.Grid): toolbox = trans.app.toolbox if toolbox.has_tool(tool_version.tool_id, exact=True): link = url_for(controller='tool_runner', tool_id=tool_version.tool_id) - link_str = '' % link + link_str = f'' return f'' return tool_version.tool_id @@ -473,12 +473,12 @@ class ToolVersionListGrid(grids.Grid): for tool_id in tool.lineage.tool_ids: if toolbox.has_tool(tool_id, exact=True): link = url_for(controller='tool_runner', tool_id=tool_id) - link_str = '' % link + link_str = f'' tool_ids_str += f'
    ' else: - tool_ids_str += '%s
    ' % tool_version.tool_id + tool_ids_str += f'{tool_version.tool_id}
    ' else: - tool_ids_str += '%s
    ' % tool_version.tool_id + tool_ids_str += f'{tool_version.tool_id}
    ' return tool_ids_str # Grid definition @@ -592,7 +592,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP if 'operation' in kwd: id = kwd.get('id') if not id: - message, status = ('Invalid user id (%s) received.' % str(id), 'error') + message, status = (f'Invalid user id ({str(id)}) received.', 'error') ids = util.listify(id) operation = kwd['operation'].lower() if operation == 'delete': @@ -636,7 +636,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP if 'operation' in kwargs: id = kwargs.get('id') if not id: - return self.message_exception(trans, 'Invalid quota id (%s) received.' % str(id)) + return self.message_exception(trans, f'Invalid quota id ({str(id)}) received.') quotas = [] for quota_id in util.listify(id): try: @@ -739,7 +739,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP def manage_users_and_groups_for_quota(self, trans, payload=None, **kwd): quota_id = kwd.get('id') if not quota_id: - return self.message_exception(trans, 'Invalid quota id (%s) received' % str(quota_id)) + return self.message_exception(trans, f'Invalid quota id ({str(quota_id)}) received') quota = get_quota(trans, quota_id) if trans.request.method == 'GET': in_users = [] @@ -839,7 +839,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP if user: trans.handle_user_logout() trans.handle_user_login(user) - return trans.show_message('You are now logged in as {}, return to the home page'.format(user.email, url_for(controller='root')), use_panels=True) + return trans.show_message(f"You are now logged in as {user.email}, return to the home page", use_panels=True) except Exception: log.exception("Error fetching user for impersonation") return trans.response.send_redirect(web.url_for(controller='admin', @@ -916,7 +916,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP if 'operation' in kwargs: id = kwargs.get('id', None) if not id: - message, status = ('Invalid role id (%s) received.' % str(id), 'error') + message, status = (f'Invalid role id ({str(id)}) received.', 'error') ids = util.listify(id) operation = kwargs['operation'].lower().replace('+', ' ') if operation == 'delete': @@ -1045,7 +1045,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP def manage_users_and_groups_for_role(self, trans, payload=None, **kwd): role_id = kwd.get('id') if not role_id: - return self.message_exception(trans, 'Invalid role id (%s) received' % str(role_id)) + return self.message_exception(trans, f'Invalid role id ({str(role_id)}) received') role = get_role(trans, role_id) if trans.request.method == 'GET': in_users = [] @@ -1099,7 +1099,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP role.deleted = True trans.sa_session.add(role) trans.sa_session.flush() - message += ' %s ' % role.name + message += f' {role.name} ' return (message, 'done') def _undelete_role(self, trans, ids): @@ -1108,12 +1108,12 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP for role_id in ids: role = get_role(trans, role_id) if not role.deleted: - return ("Role '%s' has not been deleted, so it cannot be undeleted." % role.name, "error") + return (f"Role '{role.name}' has not been deleted, so it cannot be undeleted.", "error") role.deleted = False trans.sa_session.add(role) trans.sa_session.flush() count += 1 - undeleted_roles += " %s" % role.name + undeleted_roles += f" {role.name}" return ("Undeleted %d roles: %s" % (count, undeleted_roles), "done") def _purge_role(self, trans, ids): @@ -1128,7 +1128,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP for role_id in ids: role = get_role(trans, role_id) if not role.deleted: - return ("Role '%s' has not been deleted, so it cannot be purged." % role.name, "error") + return (f"Role '{role.name}' has not been deleted, so it cannot be purged.", "error") # Delete UserRoleAssociations for ura in role.users: user = trans.sa_session.query(trans.app.model.User).get(ura.user_id) @@ -1149,7 +1149,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP for dp in role.dataset_actions: trans.sa_session.delete(dp) trans.sa_session.flush() - message += " %s " % role.name + message += f" {role.name} " return (message, "done") @web.legacy_expose_api @@ -1160,7 +1160,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP if 'operation' in kwargs: id = kwargs.get('id') if not id: - return self.message_exception(trans, 'Invalid group id (%s) received.' % str(id)) + return self.message_exception(trans, f'Invalid group id ({str(id)}) received.') ids = util.listify(id) operation = kwargs['operation'].lower().replace('+', ' ') if operation == 'delete': @@ -1211,7 +1211,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP def manage_users_and_roles_for_group(self, trans, payload=None, **kwd): group_id = kwd.get('id') if not group_id: - return self.message_exception(trans, 'Invalid group id (%s) received' % str(group_id)) + return self.message_exception(trans, f'Invalid group id ({str(group_id)}) received') group = get_group(trans, group_id) if trans.request.method == 'GET': in_users = [] @@ -1301,7 +1301,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP if trans.sa_session.query(trans.app.model.Role).filter(trans.app.model.Role.table.c.name == name).first(): return self.message_exception(trans, 'A role with that name already exists, so choose another name or disable role creation.') # Create the role - role = trans.app.model.Role(name=name, description='Role for group %s' % name) + role = trans.app.model.Role(name=name, description=f'Role for group {name}') trans.sa_session.add(role) # Associate the group with the role gra = trans.model.GroupRoleAssociation(group, role) @@ -1322,7 +1322,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP group.deleted = True trans.sa_session.add(group) trans.sa_session.flush() - message += ' %s ' % group.name + message += f' {group.name} ' return (message, 'done') def _undelete_group(self, trans, ids): @@ -1331,12 +1331,12 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP for group_id in ids: group = get_group(trans, group_id) if not group.deleted: - return ("Group '%s' has not been deleted, so it cannot be undeleted." % group.name, "error") + return (f"Group '{group.name}' has not been deleted, so it cannot be undeleted.", "error") group.deleted = False trans.sa_session.add(group) trans.sa_session.flush() count += 1 - undeleted_groups += " %s" % group.name + undeleted_groups += f" {group.name}" return ("Undeleted %d groups: %s" % (count, undeleted_groups), "done") def _purge_group(self, trans, ids): @@ -1344,7 +1344,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP for group_id in ids: group = get_group(trans, group_id) if not group.deleted: - return ("Group '%s' has not been deleted, so it cannot be purged." % group.name, "error") + return (f"Group '{group.name}' has not been deleted, so it cannot be purged.", "error") # Delete UserGroupAssociations for uga in group.users: trans.sa_session.delete(uga) @@ -1352,7 +1352,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP for gra in group.roles: trans.sa_session.delete(gra) trans.sa_session.flush() - message += " %s " % group.name + message += f" {group.name} " return (message, "done") @web.expose @@ -1395,7 +1395,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP # Actually do the delete self.user_manager.delete(user) # Accumulate messages for the return message - message += ' %s ' % user.email + message += f' {user.email} ' return (message, 'done') def _undelete_user(self, trans, ids): @@ -1407,7 +1407,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP self.user_manager.undelete(user) # Count and accumulate messages to return to the admin panel count += 1 - undeleted_users += ' %s' % user.email + undeleted_users += f' {user.email}' message = 'Undeleted %d users: %s' % (count, undeleted_users) return (message, 'done') @@ -1427,26 +1427,26 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP for user_id in ids: user = get_user(trans, user_id) self.user_manager.purge(user) - message += '\t%s\n ' % user.email + message += f'\t{user.email}\n ' return (message, 'done') def _recalculate_user(self, trans, user_id): user = trans.sa_session.query(trans.model.User).get(trans.security.decode_id(user_id)) if not user: - return ('User not found for id (%s)' % sanitize_text(str(user_id)), 'error') + return (f'User not found for id ({sanitize_text(str(user_id))})', 'error') current = user.get_disk_usage() user.calculate_and_set_disk_usage() new = user.get_disk_usage() if new in (current, None): - message = 'Usage is unchanged at %s.' % nice_size(current) + message = f'Usage is unchanged at {nice_size(current)}.' else: - message = 'Usage has changed by {} to {}.'.format(nice_size(new - current), nice_size(new)) + message = f'Usage has changed by {nice_size(new - current)} to {nice_size(new)}.' return (message, 'done') def _new_user_apikey(self, trans, user_id): user = trans.sa_session.query(trans.model.User).get(trans.security.decode_id(user_id)) if not user: - return ('User not found for id (%s)' % sanitize_text(str(user_id)), 'error') + return (f'User not found for id ({sanitize_text(str(user_id))})', 'error') new_key = trans.app.model.APIKeys( user_id=trans.security.decode_id(user_id), key=trans.app.security.get_new_guid() @@ -1458,25 +1458,25 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP def _activate_user(self, trans, user_id): user = trans.sa_session.query(trans.model.User).get(trans.security.decode_id(user_id)) if not user: - return ('User not found for id (%s)' % sanitize_text(str(user_id)), 'error') + return (f'User not found for id ({sanitize_text(str(user_id))})', 'error') self.user_manager.activate(user) - return ('Activated user: %s.' % user.email, 'done') + return (f'Activated user: {user.email}.', 'done') def _resend_activation_email(self, trans, user_id): user = trans.sa_session.query(trans.model.User).get(trans.security.decode_id(user_id)) if not user: - return ('User not found for id (%s)' % sanitize_text(str(user_id)), 'error') + return (f'User not found for id ({sanitize_text(str(user_id))})', 'error') if self.user_manager.send_activation_email(trans, user.email, user.username): - return ('Activation email has been sent to user: %s.' % user.email, 'done') + return (f'Activation email has been sent to user: {user.email}.', 'done') else: - return ('Unable to send activation email to user: %s.' % user.email, 'error') + return (f'Unable to send activation email to user: {user.email}.', 'error') @web.legacy_expose_api @web.require_admin def manage_roles_and_groups_for_user(self, trans, payload=None, **kwd): user_id = kwd.get('id') if not user_id: - return self.message_exception(trans, 'Invalid user id (%s) received' % str(user_id)) + return self.message_exception(trans, f'Invalid user id ({str(user_id)}) received') user = get_user(trans, user_id) if trans.request.method == 'GET': in_roles = [] @@ -1591,7 +1591,7 @@ def get_user(trans, user_id): """Get a User from the database by id.""" user = trans.sa_session.query(trans.model.User).get(trans.security.decode_id(user_id)) if not user: - return trans.show_error_message("User not found for id (%s)" % str(user_id)) + return trans.show_error_message(f"User not found for id ({str(user_id)})") return user @@ -1601,7 +1601,7 @@ def get_role(trans, id): id = trans.security.decode_id(id) role = trans.sa_session.query(trans.model.Role).get(id) if not role: - return trans.show_error_message("Role not found for id (%s)" % str(id)) + return trans.show_error_message(f"Role not found for id ({str(id)})") return role @@ -1611,7 +1611,7 @@ def get_group(trans, id): id = trans.security.decode_id(id) group = trans.sa_session.query(trans.model.Group).get(id) if not group: - return trans.show_error_message("Group not found for id (%s)" % str(id)) + return trans.show_error_message(f"Group not found for id ({str(id)})") return group diff --git a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py index b5f91cb58ad..7e92798353c 100644 --- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py @@ -56,10 +56,10 @@ class AdminToolshed(AdminGalaxy): repository = repository_util.get_installed_tool_shed_repository(trans.app, repository_id) try: trans.app.installed_repository_manager.activate_repository(repository) - message = 'The %s repository has been activated.' % escape(repository.name) + message = f'The {escape(repository.name)} repository has been activated.' status = 'done' except Exception as e: - error_message = "Error activating repository {}: {}".format(escape(repository.name), unicodify(e)) + error_message = f"Error activating repository {escape(repository.name)}: {unicodify(e)}" log.exception(error_message) message = '%s.
    You may be able to resolve this by uninstalling and then reinstalling the repository. Click here to uninstall the repository.' \ % (error_message, web.url_for(controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id(repository.id))) @@ -123,7 +123,7 @@ class AdminToolshed(AdminGalaxy): action='reselect_tool_panel_section', **kwd)) else: - message = "Unable to get latest revision for repository %s from " % escape(str(repository.name)) + message = f"Unable to get latest revision for repository {escape(str(repository.name))} from " message += "the Tool Shed, so repository re-installation is not possible at this time." status = "error" return trans.response.send_redirect(web.url_for(controller='admin_toolshed', @@ -291,11 +291,11 @@ class AdminToolshed(AdminGalaxy): if installed_tool_dependency.status == trans.app.install_model.ToolDependency.installation_status.ERROR: text = unicodify(installed_tool_dependency.error_message) if text is not None: - err_msg += ' %s' % text + err_msg += f' {text}' if err_msg: message += err_msg status = 'error' - message += "Installed tool dependencies: %s" % ', '.join(td.name for td in installed_tool_dependencies) + message += f"Installed tool dependencies: {', '.join(td.name for td in installed_tool_dependencies)}" td_ids = [trans.security.encode_id(td.id) for td in tool_shed_repository.tool_dependencies] return trans.response.send_redirect(web.url_for(controller='admin_toolshed', action='manage_tool_dependencies', @@ -323,7 +323,7 @@ class AdminToolshed(AdminGalaxy): url = util.build_url(tool_shed_url, pathspec=pathspec, params=params) latest_downloadable_revision = json.loads(raw_text) if latest_downloadable_revision == hg_util.INITIAL_CHANGELOG_HASH: - return trans.show_error_message('Error retrieving the latest downloadable revision for this repository via the url %s.' % url) + return trans.show_error_message(f'Error retrieving the latest downloadable revision for this repository via the url {url}.') else: # Make sure the latest changeset_revision of the repository has not already been installed. # Updates to installed repository revisions may have occurred, so make sure to locate the @@ -339,7 +339,7 @@ class AdminToolshed(AdminGalaxy): message = 'Revision %s of repository %s owned by %s has already been installed.' % \ (latest_downloadable_revision, name, owner) if current_changeset_revision != latest_downloadable_revision: - message += ' The current changeset revision is %s.' % current_changeset_revision + message += f' The current changeset revision is {current_changeset_revision}.' return trans.show_error_message(message) else: # Install the latest downloadable revision of the repository. @@ -351,7 +351,7 @@ class AdminToolshed(AdminGalaxy): url = util.build_url(tool_shed_url, pathspec=pathspec, params=params) return trans.response.send_redirect(url) else: - return trans.show_error_message('Cannot locate installed tool shed repository with encoded id %s.' % str(repository_id)) + return trans.show_error_message(f'Cannot locate installed tool shed repository with encoded id {str(repository_id)}.') else: return trans.show_error_message('The request parameters did not include the required encoded id of installed repository.') @@ -619,10 +619,10 @@ class AdminToolshed(AdminGalaxy): # The Tool Shed cannot handle the get_repository_id request, so the code must be older than the # 04/2014 Galaxy release when it was introduced. It will be safest to error out and let the # Tool Shed admin update the Tool Shed to a later release. - message = 'The updates available for the repository %s ' % escape(str(repository.name)) + message = f'The updates available for the repository {escape(str(repository.name))} ' message += 'include newly defined repository or tool dependency definitions, and attempting ' message += 'to update the repository resulted in the following error. Contact the Tool Shed ' - message += 'administrator if necessary.
    %s' % unicodify(e) + message += f'administrator if necessary.
    {unicodify(e)}' return trans.show_error_message(message) changeset_revisions = updating_to_changeset_revision else: @@ -1116,7 +1116,7 @@ class AdminToolshed(AdminGalaxy): message += "different section in the tool panel. " status = 'warning' else: - message += "The tools contained in your %s repository were last loaded into the tool panel outside of any sections. " % escape(tool_shed_repository.name) + message += f"The tools contained in your {escape(tool_shed_repository.name)} repository were last loaded into the tool panel outside of any sections. " message += "Uncheck the No changes check box and select a tool panel section to load the tools into that section. " status = 'warning' else: @@ -1204,7 +1204,7 @@ class AdminToolshed(AdminGalaxy): errors = True message = f'{message} {error_message}' if errors: - message = "Error attempting to uninstall tool dependencies: %s" % message + message = f"Error attempting to uninstall tool dependencies: {message}" status = 'error' else: message = "These tool dependencies have been uninstalled: %s" % \ @@ -1245,7 +1245,7 @@ class AdminToolshed(AdminGalaxy): refresh=True) if changeset_revision and latest_changeset_revision and latest_ctx_rev: if changeset_revision == latest_changeset_revision: - message = "The installed repository named '%s' is current, there are no updates available. " % name + message = f"The installed repository named '{name}' is current, there are no updates available. " else: irm = install_manager.InstallRepositoryManager(trans.app) install_dependencies, irmm_metadata_dict = irm.update_tool_shed_repository( @@ -1285,7 +1285,7 @@ class AdminToolshed(AdminGalaxy): message = "The installed repository named '%s' has been updated to change set revision '%s'. " % \ (name, latest_changeset_revision) else: - message = "The latest changeset revision could not be retrieved for the installed repository named '%s'. " % name + message = f"The latest changeset revision could not be retrieved for the installed repository named '{name}'. " status = 'error' return trans.response.send_redirect(web.url_for(controller='admin_toolshed', action='manage_repository', diff --git a/lib/galaxy/webapps/galaxy/controllers/async.py b/lib/galaxy/webapps/galaxy/controllers/async.py index 2dacb566990..dfc68373f1d 100644 --- a/lib/galaxy/webapps/galaxy/controllers/async.py +++ b/lib/galaxy/webapps/galaxy/controllers/async.py @@ -42,34 +42,34 @@ class ASync(BaseUIController): URL = params.URL data_id = params.data_id - log.debug('async dataid -> %s' % data_id) - trans.log_event('Async dataid -> %s' % str(data_id)) + log.debug(f'async dataid -> {data_id}') + trans.log_event(f'Async dataid -> {str(data_id)}') # initialize the tool toolbox = self.get_toolbox() tool = toolbox.get_tool(tool_id) if not tool: - return "Tool with id %s not found" % tool_id + return f"Tool with id {tool_id} not found" # # we have an incoming data_id # if data_id: if not URL: - return "No URL parameter was submitted for data %s" % data_id + return f"No URL parameter was submitted for data {data_id}" data = trans.sa_session.query(trans.model.HistoryDatasetAssociation).get(data_id) if not data: - return "Data %s does not exist or has already been deleted" % data_id + return f"Data {data_id} does not exist or has already been deleted" if STATUS == 'OK': key = hmac_new(trans.app.config.tool_secret, "%d:%d" % (data.id, data.history_id)) if key != data_secret: - return "You do not have permission to alter data %s." % data_id + return f"You do not have permission to alter data {data_id}." # push the job into the queue data.state = data.blurb = data.states.RUNNING - log.debug('executing tool %s' % tool.id) - trans.log_event('Async executing tool %s' % tool.id, tool_id=tool.id) + log.debug(f'executing tool {tool.id}') + trans.log_event(f'Async executing tool {tool.id}', tool_id=tool.id) galaxy_url = trans.request.base + f'/async/{tool_id}/{data.id}/{key}' galaxy_url = params.get("GALAXY_URL", galaxy_url) params = dict(URL=URL, GALAXY_URL=galaxy_url, name=data.name, info=data.info, dbkey=data.dbkey, data_type=data.ext) @@ -90,10 +90,10 @@ class ASync(BaseUIController): original_history = trans.sa_session.query(trans.app.model.History).get(data.history_id) tool.execute(trans, incoming=params, history=original_history) else: - log.debug('async error -> %s' % STATUS) - trans.log_event('Async error -> %s' % STATUS) + log.debug(f'async error -> {STATUS}') + trans.log_event(f'Async error -> {STATUS}') data.state = data.blurb = "error" - data.info = "Error -> %s" % STATUS + data.info = f"Error -> {STATUS}" trans.sa_session.flush() @@ -126,7 +126,7 @@ class ASync(BaseUIController): if GALAXY_TYPE is None: raise Exception("Error: ToolOutput object not found") - GALAXY_NAME = params.name or params.GALAXY_NAME or '%s query' % tool.name + GALAXY_NAME = params.name or params.GALAXY_NAME or f'{tool.name} query' GALAXY_INFO = params.info or params.GALAXY_INFO or params.galaxyDescription or '' GALAXY_BUILD = params.dbkey or params.GALAXY_BUILD or params.galaxyFreeze or '?' @@ -165,9 +165,9 @@ class ASync(BaseUIController): url_join_char = '&' else: url_join_char = '?' - url = "{}{}{}".format(url, url_join_char, urlencode(params.flatten())) - log.debug("connecting to -> %s" % url) - trans.log_event("Async connecting to -> %s" % url) + url = f"{url}{url_join_char}{urlencode(params.flatten())}" + log.debug(f"connecting to -> {url}") + trans.log_event(f"Async connecting to -> {url}") text = requests.get(url).text.strip() if not text.endswith('OK'): raise Exception(text) diff --git a/lib/galaxy/webapps/galaxy/controllers/authnz.py b/lib/galaxy/webapps/galaxy/controllers/authnz.py index f2feabd4eb1..c74b338a038 100644 --- a/lib/galaxy/webapps/galaxy/controllers/authnz.py +++ b/lib/galaxy/webapps/galaxy/controllers/authnz.py @@ -182,7 +182,7 @@ class OIDC(JSAppLauncher): try: cilogon_idps = json.loads(url_get('https://cilogon.org/idplist/', params=dict(kwargs))) except Exception as e: - raise Exception("Invalid server response. %s." % str(e)) + raise Exception(f"Invalid server response. {str(e)}.") if (allowed_idps): validated_idps = list(filter(lambda idp: idp['EntityID'] in allowed_idps, cilogon_idps)) diff --git a/lib/galaxy/webapps/galaxy/controllers/data_manager.py b/lib/galaxy/webapps/galaxy/controllers/data_manager.py index 8d686b74df1..2a79e154056 100644 --- a/lib/galaxy/webapps/galaxy/controllers/data_manager.py +++ b/lib/galaxy/webapps/galaxy/controllers/data_manager.py @@ -51,7 +51,7 @@ class DataManager(BaseUIController): data_manager_id = kwd.get('id', None) data_manager = trans.app.data_managers.get_manager(data_manager_id) if data_manager is None: - return {'message': "Invalid Data Manager (%s) was requested" % data_manager_id, + return {'message': f"Invalid Data Manager ({data_manager_id}) was requested", 'status': "error"} jobs = [] for assoc in trans.sa_session.query(trans.app.model.DataManagerJobAssociation).filter_by(data_manager_id=data_manager_id): @@ -93,7 +93,7 @@ class DataManager(BaseUIController): job = None log.error(f"Bad job id ({job_id}) passed to job_info: {e}") if not job: - return {'message': "Invalid job (%s) was requested" % job_id, + return {'message': f"Invalid job ({job_id}) was requested", 'status': "error"} data_manager_id = job.data_manager_association.data_manager_id data_manager = trans.app.data_managers.get_manager(data_manager_id) @@ -155,7 +155,7 @@ class DataManager(BaseUIController): 'status': "error"} data_table = trans.app.tool_data_tables.get(data_table_name, None) if data_table is None: - return {'message': "Invalid data table '%s' was requested." % data_table_name, + return {'message': f"Invalid data table '{data_table_name}' was requested.", 'status': "error"} return {'dataTable': {'name': data_table.name, 'columns': data_table.get_column_name_list(), @@ -211,7 +211,7 @@ class DataManager(BaseUIController): if data_table is None: return { 'data': data, - 'message': 'Invalid Data table (%s) was requested' % table_name, + 'message': f'Invalid Data table ({table_name}) was requested', 'status': 'error' } @@ -238,7 +238,7 @@ class DataManager(BaseUIController): controller='data_manager', action='tool_data_table_items', table_name=table_name, - message='The data table "%s" has been reloaded.' % table_name, + message=f'The data table "{table_name}" has been reloaded.', status='done', ) diff --git a/lib/galaxy/webapps/galaxy/controllers/dataset.py b/lib/galaxy/webapps/galaxy/controllers/dataset.py index 39d1c39da65..4017de1ad5e 100644 --- a/lib/galaxy/webapps/galaxy/controllers/dataset.py +++ b/lib/galaxy/webapps/galaxy/controllers/dataset.py @@ -132,14 +132,14 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE try: data = trans.sa_session.query(trans.app.model.HistoryDatasetAssociation).get(self.decode_id(hda_id)) if data is None: - raise ValueError('Invalid reference dataset id: %s.' % hda_id) + raise ValueError(f'Invalid reference dataset id: {hda_id}.') except Exception: try: data = trans.sa_session.query(trans.app.model.HistoryDatasetAssociation).get(int(hda_id)) except Exception: data = None if not data: - raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable("Invalid reference dataset id: %s." % str(hda_id)) + raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable(f"Invalid reference dataset id: {str(hda_id)}.") if not self._can_access_dataset(trans, data): return trans.show_error_message("You are not allowed to access this dataset") if data.purged: @@ -158,7 +158,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE data = self._check_dataset(trans, dataset_id) if isinstance(data, str): return data - log.debug("Checking transfer status for dataset %s..." % data.dataset.id) + log.debug(f"Checking transfer status for dataset {data.dataset.id}...") # Pulling files in extra_files_path into cache is not handled via this # method but that's primarily because those files are typically linked to @@ -355,7 +355,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE # if setting metadata previously failed and all required elements have now been set, clear the failed state. if data._state == trans.model.Dataset.states.FAILED_METADATA and not data.missing_meta(): data._state = None - message = 'Attributes updated. %s' % message if message else 'Attributes updated.' + message = f'Attributes updated. {message}' if message else 'Attributes updated.' else: message = 'Attributes updated, but metadata could not be changed because this dataset is currently being used as input or output. You must cancel or wait for these jobs to complete before changing metadata.' status = 'warning' @@ -364,7 +364,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE # The user clicked the Save button on the 'Change data type' form datatype = payload.get('datatype') self.hda_deserializer.deserialize(data, {'datatype': datatype}, trans=trans) - message = 'Changed the type to %s.' % datatype + message = f'Changed the type to {datatype}.' elif operation == 'datatype_detect': # The user clicked the 'Detect datatype' button on the 'Change data type' form if data.datatype.is_datatype_change_allowed(): @@ -380,9 +380,9 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE trans.app.datatypes_registry.set_external_metadata_tool.tool_action.execute( trans.app.datatypes_registry.set_external_metadata_tool, trans, incoming={'input1': data}, overwrite=False) # overwrite is False as per existing behavior - message = 'Detection was finished and changed the datatype to %s.' % datatype + message = f'Detection was finished and changed the datatype to {datatype}.' else: - return self.message_exception(trans, 'Changing datatype "%s" is not allowed.' % (data.extension)) + return self.message_exception(trans, f'Changing datatype "{data.extension}" is not allowed.') elif operation == 'autodetect': # The user clicked the Auto-detect button on the 'Edit Attributes' form self.hda_manager.set_metadata(trans, data, overwrite=True) @@ -405,7 +405,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE ) message = 'Your changes completed successfully.' else: - return self.message_exception(trans, 'Invalid operation identifier (%s).' % operation) + return self.message_exception(trans, f'Invalid operation identifier ({operation}).') return {'status': status, 'message': sanitize_text(message)} def _get_dataset_for_edit(self, trans, dataset_id): @@ -416,7 +416,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE trans.log_event("dataset_id is None, cannot load a dataset to edit.") return None, self.message_exception(trans, 'You must provide a dataset id to edit attributes.') if data is None: - trans.log_event("Problem retrieving dataset id (%s)." % dataset_id) + trans.log_event(f"Problem retrieving dataset id ({dataset_id}).") return None, self.message_exception(trans, 'The dataset id is invalid.') if dataset_id is not None and data.history.user is not None and data.history.user != trans.user: trans.log_event(f"User attempted to edit a dataset they do not own (encoded: {dataset_id}, decoded: {id}).") @@ -436,16 +436,16 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE # Set referer message. referer = trans.request.referer if referer: - referer_message = "return to the previous page" % escape(referer) + referer_message = f"return to the previous page" else: - referer_message = "go to Galaxy's start page" % url_for('/') + referer_message = f"go to Galaxy's start page" # Error checking. if not dataset_id: - return trans.show_error_message("You must specify a dataset to import. You can %s." % referer_message, use_panels=True) + return trans.show_error_message(f"You must specify a dataset to import. You can {referer_message}.", use_panels=True) # Do import. cur_history = trans.get_history(create=True) status, message = self._copy_datasets(trans, [dataset_id], [cur_history], imported=True) - message = "Dataset imported.
    You can start using the dataset or {}.".format(url_for('/'), referer_message) + message = f"Dataset imported.
    You can start using the dataset or {referer_message}." return trans.show_message(message, type=status, use_panels=True) @web.expose @@ -466,7 +466,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE dataset = self.hda_manager.get_accessible(decoded_id, trans.user) dataset = self.hda_manager.error_if_uploading(dataset) if dataset: - return "Embedded Dataset '%s'" % dataset.name + return f"Embedded Dataset '{dataset.name}'" @web.expose @web.require_login("use Galaxy datasets") @@ -583,7 +583,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE site = filename data = trans.sa_session.query(trans.app.model.HistoryDatasetAssociation).get(dataset_id) if not data: - raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable("Invalid reference dataset id: %s." % str(dataset_id)) + raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable(f"Invalid reference dataset id: {str(dataset_id)}.") if 'display_url' not in kwd or 'redirect_url' not in kwd: return trans.show_error_message('Invalid parameters specified for "display at" link, please contact a Galaxy administrator') try: @@ -609,11 +609,11 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE app_kwds[name[len("app_"):]] = value del kwds[name] if kwds: - log.debug("Unexpected Keywords passed to display_application: %s" % kwds) # route memory? + log.debug(f"Unexpected Keywords passed to display_application: {kwds}") # route memory? # decode ids data, user = decode_dataset_user(trans, dataset_id, user_id) if not data: - raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable("Invalid reference dataset id: %s." % str(dataset_id)) + raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable(f"Invalid reference dataset id: {str(dataset_id)}.") if user is None: user = trans.user if user: @@ -632,17 +632,17 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE display_app = trans.app.datatypes_registry.display_applications.get(app_name) if not display_app: log.debug("Unknown display application has been requested: %s", app_name) - return paste.httpexceptions.HTTPNotFound("The requested display application (%s) is not available." % (app_name)) + return paste.httpexceptions.HTTPNotFound(f"The requested display application ({app_name}) is not available.") dataset_hash, user_hash = encode_dataset_user(trans, data, user) try: display_link = display_app.get_link(link_name, data, dataset_hash, user_hash, trans, app_kwds) except Exception as e: log.debug("Error generating display_link: %s", e) # User can sometimes recover from, e.g. conversion errors by fixing input metadata, so use conflict - return paste.httpexceptions.HTTPConflict("Error generating display_link: %s" % e) + return paste.httpexceptions.HTTPConflict(f"Error generating display_link: {e}") if not display_link: log.debug("Unknown display link has been requested: %s", link_name) - return paste.httpexceptions.HTTPNotFound("Unknown display link has been requested: %s" % link_name) + return paste.httpexceptions.HTTPNotFound(f"Unknown display link has been requested: {link_name}") if data.state == data.states.ERROR: msg.append(('This dataset is in an error state, you cannot view it at an external display application.', 'error')) elif data.deleted: @@ -665,12 +665,12 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE log.debug(e) return paste.httpexceptions.HTTPNotFound(util.unicodify(e)) value = display_link.get_param_value(action_param) - assert value, "An invalid parameter name was provided: %s" % action_param + assert value, f"An invalid parameter name was provided: {action_param}" assert value.parameter.viewable, "This parameter is not viewable." if value.parameter.type == 'data': try: if action_param_extra: - assert value.parameter.allow_extra_files_access, "Extra file content requested (%s), but allow_extra_files_access is False." % (action_param_extra) + assert value.parameter.allow_extra_files_access, f"Extra file content requested ({action_param_extra}), but allow_extra_files_access is False." file_name = os.path.join(value.extra_files_path, action_param_extra) else: file_name = value.file_name @@ -693,7 +693,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE # redirect user to url generated by display link return trans.response.send_redirect(display_link.display_url()) else: - msg.append(('Invalid action provided: %s' % app_action, 'error')) + msg.append((f'Invalid action provided: {app_action}', 'error')) else: if app_action is None: if trans.history != data.history: @@ -705,7 +705,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE display_link.prepare_display() preparable_steps = display_link.get_prepare_steps() else: - raise Exception('Attempted a view action (%s) on a non-ready display application' % app_action) + raise Exception(f'Attempted a view action ({app_action}) on a non-ready display application') return trans.fill_template_mako("dataset/display_application/display.mako", msg=msg, display_app=display_app, @@ -721,7 +721,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE try: id = self.decode_id(dataset_id) hda = trans.sa_session.query(self.app.model.HistoryDatasetAssociation).get(id) - assert hda, 'Invalid HDA: %s' % id + assert hda, f'Invalid HDA: {id}' # Walk up parent datasets to find the containing history topmost_parent = hda while topmost_parent.parent: @@ -730,7 +730,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE # Mark deleted and cleanup hda.mark_deleted() hda.clear_associated_files() - trans.log_event("Dataset id %s marked as deleted" % str(id)) + trans.log_event(f"Dataset id {str(id)} marked as deleted") self.hda_manager.stop_creating_job(hda) trans.sa_session.flush() except Exception: @@ -749,7 +749,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE id = self.decode_id(dataset_id) history = trans.get_history() hda = trans.sa_session.query(self.app.model.HistoryDatasetAssociation).get(id) - assert hda and hda.undeletable, 'Invalid HDA: %s' % id + assert hda and hda.undeletable, f'Invalid HDA: {id}' # Walk up parent datasets to find the containing history topmost_parent = hda while topmost_parent.parent: @@ -758,7 +758,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE # Mark undeleted hda.mark_undeleted() trans.sa_session.flush() - trans.log_event("Dataset id %s has been undeleted" % str(id)) + trans.log_event(f"Dataset id {str(id)} has been undeleted") except Exception: msg = f'HDA undeletion failed (encoded: {dataset_id}, decoded: {id})' log.exception(msg) @@ -783,7 +783,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE # Mark undeleted hda.mark_unhidden() trans.sa_session.flush() - trans.log_event("Dataset id %s has been unhidden" % str(id)) + trans.log_event(f"Dataset id {str(id)} has been unhidden") return True return False @@ -813,7 +813,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE # Mark purged hda.purged = True trans.sa_session.add(hda) - trans.log_event("HDA id %s has been purged" % hda.id) + trans.log_event(f"HDA id {hda.id} has been purged") trans.sa_session.flush() # Don't delete anything if there are active HDAs or any LDDAs, even if # the LDDAs are deleted. Let the cleanup scripts get it in the latter @@ -897,7 +897,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE except ValueError: hda = None if not hda: - raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable("Invalid reference dataset id: %s." % escape(str(dataset_id))) + raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable(f"Invalid reference dataset id: {escape(str(dataset_id))}.") if not self._can_access_dataset(trans, hda): return trans.show_error_message("You are not allowed to access this dataset") diff --git a/lib/galaxy/webapps/galaxy/controllers/forms.py b/lib/galaxy/webapps/galaxy/controllers/forms.py index d157687a69d..79364892f5b 100644 --- a/lib/galaxy/webapps/galaxy/controllers/forms.py +++ b/lib/galaxy/webapps/galaxy/controllers/forms.py @@ -87,7 +87,7 @@ class Forms(BaseUIController): if 'operation' in kwd: id = kwd.get('id') if not id: - return self.message_exception(trans, 'Invalid form id (%s) received.' % str(id)) + return self.message_exception(trans, f'Invalid form id ({str(id)}) received.') ids = util.listify(id) operation = kwd['operation'].lower() if operation == 'delete': @@ -135,19 +135,19 @@ class Forms(BaseUIController): row = line.split(',') if len(row) >= 6: prefix = 'fields_%i|' % index - payload['{}{}'.format(prefix, 'name')] = '%i_imported_field' % (index + 1) - payload['{}{}'.format(prefix, 'label')] = row[0] - payload['{}{}'.format(prefix, 'helptext')] = row[1] - payload['{}{}'.format(prefix, 'type')] = row[2] - payload['{}{}'.format(prefix, 'default')] = row[3] - payload['{}{}'.format(prefix, 'selectlist')] = row[4].split(',') - payload['{}{}'.format(prefix, 'required')] = row[5].lower() == 'true' + payload[f"{prefix}name"] = '%i_imported_field' % (index + 1) + payload[f"{prefix}label"] = row[0] + payload[f"{prefix}helptext"] = row[1] + payload[f"{prefix}type"] = row[2] + payload[f"{prefix}default"] = row[3] + payload[f"{prefix}selectlist"] = row[4].split(',') + payload[f"{prefix}required"] = row[5].lower() == 'true' index = index + 1 new_form, message = self.save_form_definition(trans, None, payload) if new_form is None: return self.message_exception(trans, message) imported = (' with %i imported fields' % index) if index > 0 else '' - message = 'The form \'{}\' has been created{}.'.format(payload.get('name'), imported) + message = f"The form '{payload.get('name')}' has been created{imported}." return {'message': util.sanitize_text(message)} @web.legacy_expose_api @@ -230,7 +230,7 @@ class Forms(BaseUIController): new_form, message = self.save_form_definition(trans, id, payload) if new_form is None: return self.message_exception(trans, message) - message = 'The form \'%s\' has been updated.' % payload.get('name') + message = f"The form '{payload.get('name')}' has been updated." return {'message': util.sanitize_text(message)} def get_current_form(self, trans, payload=None, **kwd): @@ -245,7 +245,7 @@ class Forms(BaseUIController): index = 0 while True: prefix = 'fields_%i|' % index - if '{}{}'.format(prefix, 'label') in payload: + if f"{prefix}label" in payload: field_attributes = ['name', 'label', 'helptext', 'required', 'type', 'selectlist', 'default'] field_dict = {attr: payload.get(f'{prefix}{attr}') for attr in field_attributes} field_dict['visible'] = True @@ -279,9 +279,9 @@ class Forms(BaseUIController): if not field['label']: return None, 'All the field labels must be completed.' if not VALID_FIELDNAME_RE.match(field['name']): - return None, '%s is not a valid field name.' % field['name'] + return None, f"{field['name']} is not a valid field name." if field['name'] in field_names_dict: - return None, 'Each field name must be unique in the form definition. %s is not unique.' % field['name'] + return None, f"Each field name must be unique in the form definition. {field['name']} is not unique." else: field_names_dict[field['name']] = 1 # create a new form definition @@ -295,7 +295,7 @@ class Forms(BaseUIController): if form_id: form_definition_current = trans.sa_session.query(trans.app.model.FormDefinitionCurrent).get(trans.security.decode_id(form_id)) if form_definition_current is None: - return None, 'Invalid form id (%s) provided. Cannot save form.' % form_id + return None, f'Invalid form id ({form_id}) provided. Cannot save form.' else: form_definition_current = trans.app.model.FormDefinitionCurrent() # create corresponding row in the form_definition_current table @@ -332,5 +332,5 @@ def get_form(trans, form_id): """Get a FormDefinition from the database by id.""" form = trans.sa_session.query(trans.app.model.FormDefinitionCurrent).get(trans.security.decode_id(form_id)) if not form: - return trans.show_error_message("Form not found for id (%s)" % str(form_id)) + return trans.show_error_message(f"Form not found for id ({str(form_id)})") return form diff --git a/lib/galaxy/webapps/galaxy/controllers/history.py b/lib/galaxy/webapps/galaxy/controllers/history.py index 96dba4ba74f..ebfc530981b 100644 --- a/lib/galaxy/webapps/galaxy/controllers/history.py +++ b/lib/galaxy/webapps/galaxy/controllers/history.py @@ -329,7 +329,7 @@ class HistoryController(BaseUIController, SharableMixin, UsesAnnotations, UsesIt try: if history.users_shared_with: raise exceptions.ObjectAttributeInvalidException( - "History (%s) has been shared with others, unshare it before deleting it." % history.name + f"History ({history.name}) has been shared with others, unshare it before deleting it." ) if purge: self.history_manager.purge(history) @@ -341,16 +341,16 @@ class HistoryController(BaseUIController, SharableMixin, UsesAnnotations, UsesIt message_parts.append(unicodify(e)) status = ERROR else: - trans.log_event("History (%s) marked as deleted" % history.name) + trans.log_event(f"History ({history.name}) marked as deleted") n_deleted += 1 if n_deleted: part = "Deleted %d %s" % (n_deleted, iff(n_deleted != 1, "histories", "history")) if purge and trans.app.config.allow_user_dataset_purge: - part += " and removed {} dataset{} from disk".format(iff(n_deleted != 1, "their", "its"), iff(n_deleted != 1, 's', '')) + part += f" and removed {iff(n_deleted != 1, 'their', 'its')} dataset{iff(n_deleted != 1, 's', '')} from disk" elif purge: part += " but the datasets were not removed from disk because that feature is not enabled in this Galaxy instance" - message_parts.append("%s. " % part) + message_parts.append(f"{part}. ") if deleted_current: # if this history is the current history for this session, # - attempt to find the most recently used, undeleted history and switch to it. @@ -653,7 +653,7 @@ class HistoryController(BaseUIController, SharableMixin, UsesAnnotations, UsesIt """ history_id = kwd.get('id') if not history_id: - return self.message_exception(trans, 'Invalid history id (%s) received' % str(history_id)) + return self.message_exception(trans, f'Invalid history id ({str(history_id)}) received') history = self.history_manager.get_owned(self.decode_id(history_id), trans.user, current_history=trans.history) if trans.request.method == 'GET': inputs = [] @@ -718,7 +718,7 @@ class HistoryController(BaseUIController, SharableMixin, UsesAnnotations, UsesIt trans.app.security_agent.set_all_dataset_permissions(hda.dataset, private_permissions) if not trans.app.security_agent.dataset_is_private_to_user(trans, hda.dataset): raise exceptions.InternalServerError('An error occurred and the dataset is NOT private.') - return {'message': 'Success, requested permissions have been changed in %s.' % ("all histories" if all_histories else history.name)} + return {'message': f"Success, requested permissions have been changed in {'all histories' if all_histories else history.name}."} @web.expose @web.require_login("share histories with other users") @@ -909,7 +909,7 @@ class HistoryController(BaseUIController, SharableMixin, UsesAnnotations, UsesIt send_to_user = None if not send_to_user: - send_to_err += "%s is not a valid Galaxy user. " % string + send_to_err += f"{string} is not a valid Galaxy user. " elif send_to_user == user: send_to_err += "You cannot send histories to yourself. " else: @@ -1033,7 +1033,7 @@ class HistoryController(BaseUIController, SharableMixin, UsesAnnotations, UsesIt histories = histories or {} if not histories: send_to_err += "No users have been specified or no histories can be sent without changing permissions or associating a sharing role. " - return trans.response.send_redirect(web.url_for("/histories/list?status=error&message=%s" % send_to_err)) + return trans.response.send_redirect(web.url_for(f"/histories/list?status=error&message={send_to_err}")) else: shared_histories = [] for send_to_user, send_to_user_histories in histories.items(): @@ -1046,7 +1046,7 @@ class HistoryController(BaseUIController, SharableMixin, UsesAnnotations, UsesIt trans.sa_session.flush() if history not in shared_histories: shared_histories.append(history) - return trans.response.send_redirect(web.url_for("/histories/sharing?id=%s" % trans.security.encode_id(shared_histories[0].id))) + return trans.response.send_redirect(web.url_for(f"/histories/sharing?id={trans.security.encode_id(shared_histories[0].id)}")) # ......................................................................... actions/orig. async @web.expose @@ -1059,7 +1059,7 @@ class HistoryController(BaseUIController, SharableMixin, UsesAnnotations, UsesIt hda.purge_usage_from_quota(trans.user) hda.purged = True trans.sa_session.add(hda) - trans.log_event("HDA id %s has been purged" % hda.id) + trans.log_event(f"HDA id {hda.id} has been purged") trans.sa_session.flush() if hda.dataset.user_can_purge: try: @@ -1158,7 +1158,7 @@ class HistoryController(BaseUIController, SharableMixin, UsesAnnotations, UsesIt 'title': 'Change history name(s)', 'inputs': [{ 'name': 'name_%i' % i, - 'label': 'Current: %s' % h.name, + 'label': f'Current: {h.name}', 'value': h.name } for i, h in enumerate(histories)] } @@ -1178,7 +1178,7 @@ class HistoryController(BaseUIController, SharableMixin, UsesAnnotations, UsesIt h.name = new_name trans.sa_session.add(h) trans.sa_session.flush() - trans.log_event('History renamed: id: {}, renamed to: {}'.format(str(h.id), new_name)) + trans.log_event(f'History renamed: id: {str(h.id)}, renamed to: {new_name}') messages.append('History \'' + cur_name + '\' renamed to \'' + new_name + '\'.') message = sanitize_text(' '.join(messages)) if messages else 'History names remain unchanged.' return {'message': message, 'status': 'success'} diff --git a/lib/galaxy/webapps/galaxy/controllers/openid.py b/lib/galaxy/webapps/galaxy/controllers/openid.py index d7872f275f4..865b4d794b4 100644 --- a/lib/galaxy/webapps/galaxy/controllers/openid.py +++ b/lib/galaxy/webapps/galaxy/controllers/openid.py @@ -41,9 +41,9 @@ class OpenID(BaseUIController): try: request = consumer.begin(openid_provider_obj.op_endpoint_url) if request is None: - return trans.show_error_message("No OpenID services are available at %s." % openid_provider_obj.op_endpoint_url) + return trans.show_error_message(f"No OpenID services are available at {openid_provider_obj.op_endpoint_url}.") except Exception as e: - return trans.show_error_message("Failed to begin OpenID authentication: %s." % unicodify(e)) + return trans.show_error_message(f"Failed to begin OpenID authentication: {unicodify(e)}.") if request is not None: self.openid_manager.add_sreg(trans, request, required=openid_provider_obj.sreg_required, optional=openid_provider_obj.sreg_optional) if request.shouldSendRedirect(): @@ -60,15 +60,15 @@ class OpenID(BaseUIController): @web.expose def openid_process(self, trans, **kwd): '''Handle's response from OpenID Providers''' - return_link = "Click here to return." % url_for("/") + return_link = f"Click here to return." if not trans.app.config.enable_openid: - return trans.show_error_message("OpenID authentication is not enabled in this instance of Galaxy. %s" % return_link) + return trans.show_error_message(f"OpenID authentication is not enabled in this instance of Galaxy. {return_link}") consumer = self.openid_manager.get_consumer(trans) info = consumer.complete(kwd, trans.request.url) openid_provider = kwd.get('openid_provider', None) if info.status == self.openid_manager.SUCCESS: openid_provider_obj = self.openid_providers.get(openid_provider) openid_provider_obj.post_authentication(trans, self.openid_manager, info) - return trans.show_message("Processed OpenID authentication. %s" % return_link) + return trans.show_message(f"Processed OpenID authentication. {return_link}") else: return trans.show_error_message(f"Authentication via OpenID failed: {info.message}. {return_link}") diff --git a/lib/galaxy/webapps/galaxy/controllers/page.py b/lib/galaxy/webapps/galaxy/controllers/page.py index a04113bcc01..d39ce3d2fa3 100644 --- a/lib/galaxy/webapps/galaxy/controllers/page.py +++ b/lib/galaxy/webapps/galaxy/controllers/page.py @@ -458,14 +458,14 @@ class PageController(BaseUIController, SharableMixin, .first() if not other: mtype = "error" - msg = ("User '%s' does not exist" % escape(email)) + msg = f"User '{escape(email)}' does not exist" elif other == trans.get_user(): mtype = "error" msg = ("You cannot share a page with yourself") elif trans.sa_session.query(model.PageUserShareAssociation) \ .filter_by(user=other, page=page).count() > 0: mtype = "error" - msg = ("Page already shared with '%s'" % escape(email)) + msg = f"Page already shared with '{escape(email)}'" else: share = model.PageUserShareAssociation() share.page = page @@ -477,7 +477,7 @@ class PageController(BaseUIController, SharableMixin, page_title = escape(page.title) other_email = escape(other.email) trans.set_message(f"Page '{page_title}' shared with user '{other_email}'") - return trans.response.send_redirect(url_for("/pages/sharing?id=%s" % id)) + return trans.response.send_redirect(url_for(f"/pages/sharing?id={id}")) return trans.fill_template("/ind_share_base.mako", message=msg, messagetype=mtype, @@ -574,7 +574,7 @@ class PageController(BaseUIController, SharableMixin, # TODO: user should be able to embed any item he has access to. see display_by_username_and_slug for security code. page = self.get_page(trans, id) if page: - return "Embedded Page '%s'" % page.title + return f"Embedded Page '{page.title}'" @web.expose @web.json diff --git a/lib/galaxy/webapps/galaxy/controllers/root.py b/lib/galaxy/webapps/galaxy/controllers/root.py index 1d7feaf2c7c..81a89d156bc 100644 --- a/lib/galaxy/webapps/galaxy/controllers/root.py +++ b/lib/galaxy/webapps/galaxy/controllers/root.py @@ -146,7 +146,7 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): elif tool.help: yield tool.help else: - yield "No additional help available for tool '%s'" % tool.name + yield f"No additional help available for tool '{tool.name}'" yield "" # ---- Dataset display / editing ---------------------------------------- @@ -166,7 +166,7 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): try: hid = int(hid) except ValueError: - return "hid '%s' is invalid" % str(hid) + return f"hid '{str(hid)}' is invalid" history = trans.get_history() for dataset in history.datasets: if dataset.hid == hid: @@ -180,7 +180,7 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): try: data = trans.sa_session.query(self.app.model.HistoryDatasetAssociation).get(id) except Exception: - return "Dataset id '%s' is invalid" % str(id) + return f"Dataset id '{str(id)}' is invalid" if data: current_user_roles = trans.get_current_user_roles() if trans.app.security_agent.can_access_dataset(current_user_roles, data.dataset): @@ -193,7 +193,7 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): fname = data.name fname = ''.join(c in FILENAME_VALID_CHARS and c or '_' for c in fname)[0:150] trans.response.headers["Content-Disposition"] = f'attachment; filename="GalaxyHistoryItem-{data.hid}-[{fname}]{toext}"' - trans.log_event("Display dataset id: %s" % str(id)) + trans.log_event(f"Display dataset id: {str(id)}") try: return open(data.file_name, 'rb') except Exception: @@ -201,7 +201,7 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): else: return "You are not allowed to access this dataset" else: - return "No dataset with id '%s'" % str(id) + return f"No dataset with id '{str(id)}'" @web.expose def display_as(self, trans, id=None, display_app=None, **kwd): @@ -216,7 +216,7 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): current_user_roles = trans.get_current_user_roles() if authz_method == 'rbac' and trans.app.security_agent.can_access_dataset(current_user_roles, data): trans.response.set_content_type(data.get_mime()) - trans.log_event("Formatted dataset id {} for display at {}".format(str(id), display_app)) + trans.log_event(f"Formatted dataset id {str(id)} for display at {display_app}") return data.as_display_type(display_app, **kwd) elif authz_method == 'display_at' and trans.app.host_security_agent.allow_action(trans.request.remote_addr, data.permitted_actions.DATASET_ACCESS, @@ -246,7 +246,7 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): dataset.deleted = True dataset.clear_associated_files() trans.sa_session.flush() - trans.log_event("History id %s cleared" % (str(history.id))) + trans.log_event(f"History id {str(history.id)} cleared") trans.response.send_redirect(web.url_for("/index")) @web.expose @@ -278,7 +278,7 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): trans.sa_session.flush() if not user_history.datasets: trans.set_history(new_history) - trans.log_event("History imported, id: {}, name: '{}': ".format(str(new_history.id), new_history.name)) + trans.log_event(f"History imported, id: {str(new_history.id)}, name: '{new_history.name}': ") return trans.show_ok_message(""" History "{}" has been imported. Click here to begin.""".format(new_history.name, web.url_for('/'))) @@ -297,7 +297,7 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): trans.sa_session.add(new_history) trans.sa_session.flush() trans.set_history(new_history) - trans.log_event("History imported, id: {}, name: '{}': ".format(str(new_history.id), new_history.name)) + trans.log_event(f"History imported, id: {str(new_history.id)}, name: '{new_history.name}': ") return trans.show_ok_message(""" History "{}" has been imported. Click here to begin.""".format(new_history.name, web.url_for('/'))) @@ -312,7 +312,7 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): and refresh the history panel. """ trans.new_history(name=name) - trans.log_event("Created new History, id: %s." % str(trans.history.id)) + trans.log_event(f"Created new History, id: {str(trans.history.id)}.") return trans.show_message("New history created", refresh_frames=['history']) @web.expose @@ -353,7 +353,7 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): trans.log_event("Added dataset %d to history %d" % (data.id, trans.history.id)) return trans.show_ok_message("Dataset " + str(data.hid) + " added to history " + str(history_id) + ".") except Exception as e: - msg = "Failed to add dataset to history: %s" % unicodify(e) + msg = f"Failed to add dataset to history: {unicodify(e)}" log.error(msg) trans.log_event(msg) return trans.show_error_message("Adding File to History has Failed") @@ -385,7 +385,7 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): def bucket_proxy(self, trans, bucket=None, **kwd): if bucket: trans.response.set_content_type('text/xml') - b_list_xml = requests.get('http://s3.amazonaws.com/%s/' % bucket) + b_list_xml = requests.get(f'http://s3.amazonaws.com/{bucket}/') return b_list_xml.text raise Exception("You must specify a bucket") @@ -396,11 +396,11 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): """ rval = "" for k in trans.request.headers: - rval += "{}: {}
    ".format(k, trans.request.headers[k]) + rval += f"{k}: {trans.request.headers[k]}
    " for k in kwd: - rval += "{}: {}
    ".format(k, kwd[k]) + rval += f"{k}: {kwd[k]}
    " if isinstance(kwd[k], cgi_FieldStorage): - rval += "-> %s" % kwd[k].file.read() + rval += f"-> {kwd[k].file.read()}" return rval @web.json diff --git a/lib/galaxy/webapps/galaxy/controllers/tag.py b/lib/galaxy/webapps/galaxy/controllers/tag.py index 9b0f9e0cfe0..f10e38cd6b0 100644 --- a/lib/galaxy/webapps/galaxy/controllers/tag.py +++ b/lib/galaxy/webapps/galaxy/controllers/tag.py @@ -169,7 +169,7 @@ class TagsController(BaseUIController, UsesTagsMixin): limit=limit) result_set = trans.sa_session.execute(query) # Create and return autocomplete data. - ac_data = "#Header|Your Values for '%s'\n" % (tag_name) + ac_data = f"#Header|Your Values for '{tag_name}'\n" tag_uname = self._get_usernames_for_tag(trans, trans.user, tag, item_class, item_tag_assoc_class)[0] for row in result_set: ac_data += tag_uname + ":" + row[0] + "|" + row[0] + "\n" diff --git a/lib/galaxy/webapps/galaxy/controllers/tool_runner.py b/lib/galaxy/webapps/galaxy/controllers/tool_runner.py index d7df059f86e..1085c558825 100644 --- a/lib/galaxy/webapps/galaxy/controllers/tool_runner.py +++ b/lib/galaxy/webapps/galaxy/controllers/tool_runner.py @@ -80,7 +80,7 @@ class ToolRunner(BaseUIController): except Exception as e: error(galaxy.util.unicodify(e)) if len(params) > 0: - trans.log_event('Tool params: %s' % (str(params)), tool_id=tool_id) + trans.log_event(f'Tool params: {str(params)}', tool_id=tool_id) return trans.fill_template('root/tool_runner.mako', **vars) @web.expose @@ -130,9 +130,9 @@ class ToolRunner(BaseUIController): # No tool matching the tool id, display an error (shouldn't happen) if not tool: log.error("data_source_redirect called with tool id '%s' but no such tool exists", tool_id) - trans.log_event("Tool id '%s' does not exist" % tool_id) + trans.log_event(f"Tool id '{tool_id}' does not exist") trans.response.status = 404 - return trans.show_error_message("Tool '%s' does not exist." % (escape(tool_id))) + return trans.show_error_message(f"Tool '{escape(tool_id)}' does not exist.") if isinstance(tool, DataSourceTool): link = url_for(tool.action, **tool.get_static_param_values(trans)) @@ -144,5 +144,5 @@ class ToolRunner(BaseUIController): def redirect(self, trans, redirect_url=None, **kwd): if not redirect_url: return trans.show_error_message("Required URL for redirection missing") - trans.log_event("Redirecting to: %s" % redirect_url) + trans.log_event(f"Redirecting to: {redirect_url}") return trans.fill_template('root/redirect.mako', redirect_url=redirect_url) diff --git a/lib/galaxy/webapps/galaxy/controllers/user.py b/lib/galaxy/webapps/galaxy/controllers/user.py index ffba90b02ab..840857353fe 100644 --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -110,7 +110,7 @@ class User(BaseUIController, UsesFormDefinitionsMixin, CreatesApiKeysMixin): auto_create_roles=autoreg["auto_create_roles"], auto_assign_roles_to_groups_only=autoreg["auto_assign_roles_to_groups_only"]) else: - message = "Auto-registration failed, contact your local Galaxy administrator. %s" % message + message = f"Auto-registration failed, contact your local Galaxy administrator. {message}" else: message = "No such user or invalid password." return message, user @@ -134,7 +134,7 @@ class User(BaseUIController, UsesFormDefinitionsMixin, CreatesApiKeysMixin): if not login or not password: return self.message_exception(trans, "Please specify a username and password.") user = self.user_manager.get_user_by_identity(login) - log.debug("trans.app.config.auth_config_file: %s" % trans.app.config.auth_config_file) + log.debug(f"trans.app.config.auth_config_file: {trans.app.config.auth_config_file}") if user is None: message, user = self.__autoregistration(trans, login, password) if message: @@ -142,12 +142,12 @@ class User(BaseUIController, UsesFormDefinitionsMixin, CreatesApiKeysMixin): elif user.deleted: message = "This account has been marked deleted, contact your local Galaxy administrator to restore the account." if trans.app.config.error_email_to is not None: - message += " Contact: %s." % trans.app.config.error_email_to + message += f" Contact: {trans.app.config.error_email_to}." return self.message_exception(trans, message, sanitize=False) elif user.external: message = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it." if trans.app.config.error_email_to is not None: - message += " Contact: %s." % trans.app.config.error_email_to + message += f" Contact: {trans.app.config.error_email_to}." return self.message_exception(trans, message, sanitize=False) elif not trans.app.auth_manager.check_password(user, password): return self.message_exception(trans, "Invalid password.") @@ -172,7 +172,7 @@ class User(BaseUIController, UsesFormDefinitionsMixin, CreatesApiKeysMixin): if pw_expires and user.last_password_change < datetime.today() - timedelta(days=pw_expires.days / 10): # If password is about to expire, modify message to state that. expiredate = datetime.today() - user.last_password_change + pw_expires - return {"message": "Your password will expire in %s day(s)." % expiredate.days, "status": "warning"} + return {"message": f"Your password will expire in {expiredate.days} day(s).", "status": "warning"} return {"message": "Success.", "redirect": self.__get_redirect_url(redirect)} @web.expose @@ -198,11 +198,11 @@ class User(BaseUIController, UsesFormDefinitionsMixin, CreatesApiKeysMixin): username = trans.user.username is_activation_sent = self.user_manager.send_activation_email(trans, email, username) if is_activation_sent: - message = 'This account has not been activated yet. The activation link has been sent again. Please check your email address {} including the spam/trash folder. Return to the home page.'.format(escape(email), url_for('/')) + message = f"This account has not been activated yet. The activation link has been sent again. Please check your email address {escape(email)} including the spam/trash folder. Return to the home page." else: - message = 'This account has not been activated yet but we are unable to send the activation link. Please contact your local Galaxy administrator. Return to the home page.' % url_for('/') + message = f"This account has not been activated yet but we are unable to send the activation link. Please contact your local Galaxy administrator. Return to the home page." if trans.app.config.error_email_to is not None: - message += ' Error contact: %s.' % trans.app.config.error_email_to + message += f' Error contact: {trans.app.config.error_email_to}.' return message, is_activation_sent def is_outside_grace_period(self, trans, create_time): diff --git a/lib/galaxy/webapps/galaxy/controllers/visualization.py b/lib/galaxy/webapps/galaxy/controllers/visualization.py index 0a558709a33..44aea3e5515 100644 --- a/lib/galaxy/webapps/galaxy/controllers/visualization.py +++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py @@ -52,8 +52,8 @@ class HistoryDatasetsSelectionGrid(grids.Grid): """ Filter by dbkey through a raw SQL b/c metadata is a BLOB. """ dbkey_user, dbkey = decode_dbkey(dbkey) dbkey = dbkey.replace("'", "\\'") - return query.filter(or_(text("metadata like '%%\"dbkey\": [\"%s\"]%%'" % dbkey, - "metadata like '%%\"dbkey\": \"%s\"%%'" % dbkey))) + return query.filter(or_(text(f"metadata like '%\"dbkey\": [\"{dbkey}\"]%'", + f"metadata like '%\"dbkey\": \"{dbkey}\"%'"))) class HistoryColumn(grids.GridColumn): def get_value(self, trans, grid, hda): @@ -333,9 +333,9 @@ class VisualizationController(BaseUIController, SharableMixin, UsesVisualization visualization = self.get_visualization(trans, id, check_ownership=False) user = trans.get_user() owner = (visualization.user == user) - new_title = "Copy of '%s'" % visualization.title + new_title = f"Copy of '{visualization.title}'" if not owner: - new_title += " shared by %s" % visualization.user.email + new_title += f" shared by {visualization.user.email}" copied_viz = visualization.copy(user=trans.user, title=new_title) @@ -345,7 +345,7 @@ class VisualizationController(BaseUIController, SharableMixin, UsesVisualization session.flush() # Display the management page - trans.set_message('Created new visualization with name "%s"' % copied_viz.title) + trans.set_message(f'Created new visualization with name "{copied_viz.title}"') return @web.expose @@ -387,17 +387,17 @@ class VisualizationController(BaseUIController, SharableMixin, UsesVisualization # Set referer message. referer = trans.request.referer if referer: - referer_message = "return to the previous page" % escape(referer) + referer_message = f"return to the previous page" else: - referer_message = "go to Galaxy's start page" % web.url_for('/') + referer_message = f"go to Galaxy's start page" # Do import. session = trans.sa_session visualization = self.get_visualization(trans, id, check_ownership=False) if visualization.importable is False: - return trans.show_error_message("The owner of this visualization has disabled imports via this link.
    You can %s" % referer_message, use_panels=True) + return trans.show_error_message(f"The owner of this visualization has disabled imports via this link.
    You can {referer_message}", use_panels=True) elif visualization.deleted: - return trans.show_error_message("You can't import this visualization because it has been deleted.
    You can %s" % referer_message, use_panels=True) + return trans.show_error_message(f"You can't import this visualization because it has been deleted.
    You can {referer_message}", use_panels=True) else: # Create imported visualization via copy. # TODO: need to handle custom db keys. @@ -427,14 +427,14 @@ class VisualizationController(BaseUIController, SharableMixin, UsesVisualization .first() if not other: mtype = "error" - msg = ("User '%s' does not exist" % escape(email)) + msg = f"User '{escape(email)}' does not exist" elif other == trans.get_user(): mtype = "error" msg = ("You cannot share a visualization with yourself") elif trans.sa_session.query(model.VisualizationUserShareAssociation) \ .filter_by(user=other, visualization=visualization).count() > 0: mtype = "error" - msg = ("Visualization already shared with '%s'" % escape(email)) + msg = f"Visualization already shared with '{escape(email)}'" else: share = model.VisualizationUserShareAssociation() share.visualization = visualization @@ -446,7 +446,7 @@ class VisualizationController(BaseUIController, SharableMixin, UsesVisualization viz_title = escape(visualization.title) other_email = escape(other.email) trans.set_message(f"Visualization '{viz_title}' shared with user '{other_email}'") - return trans.response.send_redirect(web.url_for("/visualizations/sharing?id=%s" % id)) + return trans.response.send_redirect(web.url_for(f"/visualizations/sharing?id={id}")) return trans.fill_template("/ind_share_base.mako", message=msg, messagetype=mtype, @@ -938,7 +938,7 @@ class VisualizationController(BaseUIController, SharableMixin, UsesVisualization if (i > 500): break fields = line.split() - location = name = "{}:{}-{}".format(fields[0], fields[1], fields[2]) + location = name = f"{fields[0]}:{fields[1]}-{fields[2]}" if len(fields) > 3: name = fields[4] rows.append([location, name]) diff --git a/lib/galaxy/webapps/galaxy/controllers/workflow.py b/lib/galaxy/webapps/galaxy/controllers/workflow.py index 6c2d5bf06bb..390c408a512 100644 --- a/lib/galaxy/webapps/galaxy/controllers/workflow.py +++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py @@ -304,14 +304,14 @@ class WorkflowController(BaseUIController, SharableMixin, UsesStoredWorkflowMixi .first() if not other: mtype = "error" - msg = ("User '%s' does not exist" % escape(email)) + msg = f"User '{escape(email)}' does not exist" elif other == trans.get_user(): mtype = "error" msg = ("You cannot share a workflow with yourself") elif trans.sa_session.query(model.StoredWorkflowUserShareAssociation) \ .filter_by(user=other, stored_workflow=stored).count() > 0: mtype = "error" - msg = ("Workflow already shared with '%s'" % escape(email)) + msg = f"Workflow already shared with '{escape(email)}'" else: share = model.StoredWorkflowUserShareAssociation() share.stored_workflow = stored @@ -319,7 +319,7 @@ class WorkflowController(BaseUIController, SharableMixin, UsesStoredWorkflowMixi session = trans.sa_session session.add(share) session.flush() - trans.set_message("Workflow '{}' shared with user '{}'".format(escape(stored.name), escape(other.email))) + trans.set_message(f"Workflow '{escape(stored.name)}' shared with user '{escape(other.email)}'") return trans.response.send_redirect(url_for(controller='workflow', action='sharing', id=id)) return trans.fill_template("/ind_share_base.mako", message=msg, @@ -396,16 +396,16 @@ class WorkflowController(BaseUIController, SharableMixin, UsesStoredWorkflowMixi # Set referer message. referer = trans.request.referer if referer: - referer_message = "return to the previous page" % escape(referer) + referer_message = f"return to the previous page" else: - referer_message = "go to Galaxy's start page" % url_for('/') + referer_message = f"go to Galaxy's start page" # Do import. stored = self.get_stored_workflow(trans, id, check_ownership=False) if stored.importable is False: - return trans.show_error_message("The owner of this workflow has disabled imports via this link.
    You can %s" % referer_message, use_panels=True) + return trans.show_error_message(f"The owner of this workflow has disabled imports via this link.
    You can {referer_message}", use_panels=True) elif stored.deleted: - return trans.show_error_message("You can't import this workflow because it has been deleted.
    You can %s" % referer_message, use_panels=True) + return trans.show_error_message(f"You can't import this workflow because it has been deleted.
    You can {referer_message}", use_panels=True) self._import_shared_workflow(trans, stored) # Redirect to load galaxy frames. @@ -473,7 +473,7 @@ class WorkflowController(BaseUIController, SharableMixin, UsesStoredWorkflowMixi # TODO: user should be able to embed any item he has access to. see display_by_username_and_slug for security code. stored = self.get_stored_workflow(trans, id) if stored: - return "Embedded Workflow '%s'" % stored.name + return f"Embedded Workflow '{stored.name}'" @web.expose @web.json @@ -520,9 +520,9 @@ class WorkflowController(BaseUIController, SharableMixin, UsesStoredWorkflowMixi # Copy. new_stored = model.StoredWorkflow() if (save_as_name): - new_stored.name = '%s' % save_as_name + new_stored.name = f'{save_as_name}' else: - new_stored.name = "Copy of %s" % stored.name + new_stored.name = f"Copy of {stored.name}" new_stored.latest_workflow = stored.latest_workflow # Copy annotation. annotation_obj = self.get_item_annotation_obj(trans.sa_session, stored.user, stored) @@ -530,16 +530,16 @@ class WorkflowController(BaseUIController, SharableMixin, UsesStoredWorkflowMixi self.add_item_annotation(trans.sa_session, trans.get_user(), new_stored, annotation_obj.annotation) new_stored.copy_tags_from(trans.user, stored) if not owner: - new_stored.name += " shared by %s" % stored.user.email + new_stored.name += f" shared by {stored.user.email}" new_stored.user = user # Persist session = trans.sa_session session.add(new_stored) session.flush() # Display the management page - message = 'Created new workflow with name: %s' % escape(new_stored.name) + message = f'Created new workflow with name: {escape(new_stored.name)}' trans.set_message(message) - return_url = url_for('/') + 'workflow?status=done&message=%s' % escape(message) + return_url = url_for('/') + f'workflow?status=done&message={escape(message)}' trans.response.send_redirect(return_url) @web.legacy_expose_api @@ -579,7 +579,7 @@ class WorkflowController(BaseUIController, SharableMixin, UsesStoredWorkflowMixi session = trans.sa_session session.add(stored_workflow) session.flush() - return {'id': trans.security.encode_id(stored_workflow.id), 'message': 'Workflow %s has been created.' % workflow_name} + return {'id': trans.security.encode_id(stored_workflow.id), 'message': f'Workflow {workflow_name} has been created.'} @web.json def save_workflow_as(self, trans, workflow_name, workflow_data, workflow_annotation="", from_tool_form=False): @@ -642,9 +642,9 @@ class WorkflowController(BaseUIController, SharableMixin, UsesStoredWorkflowMixi trans.sa_session.add(stored) trans.sa_session.flush() # Display the management page - message = "Workflow deleted: %s" % escape(stored.name) + message = f"Workflow deleted: {escape(stored.name)}" trans.set_message(message) - return trans.response.send_redirect(url_for('/') + 'workflow?status=done&message=%s' % escape(message)) + return trans.response.send_redirect(url_for('/') + f'workflow?status=done&message={escape(message)}') @web.expose @web.require_login("edit workflows") @@ -777,7 +777,7 @@ class WorkflowController(BaseUIController, SharableMixin, UsesStoredWorkflowMixi # Do request and get result. auth_header = base64.b64encode(f'{myexp_username}:{myexp_password}') - headers = {"Content-type": "text/xml", "Accept": "text/xml", "Authorization": "Basic %s" % auth_header} + headers = {"Content-type": "text/xml", "Accept": "text/xml", "Authorization": f"Basic {auth_header}"} myexp_url = trans.app.config.myexperiment_target_url conn = HTTPConnection(myexp_url) # NOTE: blocks web thread. @@ -790,7 +790,7 @@ class WorkflowController(BaseUIController, SharableMixin, UsesStoredWorkflowMixi parser = SingleTagContentsParser('id') parser.feed(response_data) myexp_workflow_id = parser.tag_content - workflow_list_str = "
    Return to workflow list." % url_for(controller='workflows', action='list') + workflow_list_str = f"
    Return to
    workflow list." if myexp_workflow_id: return trans.show_message( """Workflow '{}' successfully exported to myExperiment.
    @@ -837,7 +837,7 @@ class WorkflowController(BaseUIController, SharableMixin, UsesStoredWorkflowMixi return "Workflow cannot be exported due to missing tools." sname = stored.name sname = ''.join(c in FILENAME_VALID_CHARS and c or '_' for c in sname)[0:150] - trans.response.headers["Content-Disposition"] = 'attachment; filename="Galaxy-Workflow-%s.ga"' % (sname) + trans.response.headers["Content-Disposition"] = f'attachment; filename="Galaxy-Workflow-{sname}.ga"' trans.response.set_content_type('application/galaxy-archive') return stored_dict @@ -906,9 +906,9 @@ def _build_workflow_on_str(instance_ds_names): if num_multi_inputs == 0: return "" elif num_multi_inputs == 1: - return " on %s" % instance_ds_names[0] + return f" on {instance_ds_names[0]}" else: - return " on {} and {}".format(", ".join(instance_ds_names[0:-1]), instance_ds_names[-1]) + return f" on {', '.join(instance_ds_names[0:-1])} and {instance_ds_names[-1]}" def _expand_multiple_inputs(kwargs): @@ -981,7 +981,7 @@ def _split_inputs(kwargs): input_val = kwargs[input_key] if isinstance(input_val, list): input_base = input_key[:-len("|input")] - mode_key = "%s|multi_mode" % input_base + mode_key = f"{input_base}|multi_mode" mode = kwargs.get(mode_key, "matched") if mode == "matched": matched_multi_inputs[input_key] = input_val diff --git a/lib/galaxy/webapps/reports/app.py b/lib/galaxy/webapps/reports/app.py index 71fcfcbbf88..371b7852150 100644 --- a/lib/galaxy/webapps/reports/app.py +++ b/lib/galaxy/webapps/reports/app.py @@ -30,7 +30,7 @@ class UniverseApplication(BasicApp): if self.config.database_connection: db_url = self.config.database_connection else: - db_url = "sqlite:///%s?isolation_level=IMMEDIATE" % self.config.database + db_url = f"sqlite:///{self.config.database}?isolation_level=IMMEDIATE" # Setup the database engine and ORM self.model = galaxy.model.mapping.init(self.config.file_path, db_url, diff --git a/lib/galaxy/webapps/reports/config.py b/lib/galaxy/webapps/reports/config.py index 670e57d618d..e8e4213900c 100644 --- a/lib/galaxy/webapps/reports/config.py +++ b/lib/galaxy/webapps/reports/config.py @@ -68,7 +68,7 @@ class Configuration: # Check that required directories exist for path in self.root, self.template_path: if not os.path.isdir(path): - raise ConfigurationError("Directory does not exist: %s" % path) + raise ConfigurationError(f"Directory does not exist: {path}") @property def sentry_dsn_public(self): diff --git a/lib/galaxy/webapps/reports/controllers/history.py b/lib/galaxy/webapps/reports/controllers/history.py index f5ff791061c..81f0a784c17 100644 --- a/lib/galaxy/webapps/reports/controllers/history.py +++ b/lib/galaxy/webapps/reports/controllers/history.py @@ -26,9 +26,9 @@ def int_to_octet(size): size /= 1000. no_unit += 1 try: - return "{:.2f} {}".format(size, units[no_unit]) + return f"{size:.2f} {units[no_unit]}" except IndexError: - return "{:.0f} {}".format(size * ((no_unit - len(units) + 1) * 1000.), units[-1]) + return f"{size * ((no_unit - len(units) + 1) * 1000.0):.0f} {units[-1]}" class History(BaseUIController): diff --git a/lib/galaxy/webapps/reports/controllers/system.py b/lib/galaxy/webapps/reports/controllers/system.py index b31a1123d3b..80427710ba2 100644 --- a/lib/galaxy/webapps/reports/controllers/system.py +++ b/lib/galaxy/webapps/reports/controllers/system.py @@ -168,7 +168,7 @@ class System(BaseUIController): def nice_size(size, include_bytes=False): """Returns a readably formatted string with the size""" niced = False - nice_string = "%s bytes" % size + nice_string = f"{size} bytes" try: nsize = Decimal(size) for x in ['bytes', 'KB', 'MB', 'GB']: @@ -178,7 +178,7 @@ def nice_size(size, include_bytes=False): break nsize /= Decimal("1024.0") if not niced: - nice_string = "{:3.1f} {}".format(nsize, 'TB') + nice_string = f"{nsize:3.1f} TB" niced = True if include_bytes and x != 'bytes': nice_string = f"{nice_string} ({size} bytes)" diff --git a/lib/galaxy/webapps/reports/controllers/tools.py b/lib/galaxy/webapps/reports/controllers/tools.py index b18cd351049..159d5bfe3ea 100644 --- a/lib/galaxy/webapps/reports/controllers/tools.py +++ b/lib/galaxy/webapps/reports/controllers/tools.py @@ -31,9 +31,9 @@ def int_to_octet(size): size /= 1000. no_unit += 1 try: - return "{:.2f} {}".format(size, units[no_unit]) + return f"{size:.2f} {units[no_unit]}" except IndexError: - return "{:.0f} {}".format(size * ((no_unit - len(units) + 1) * 1000.), units[-1]) + return f"{size * ((no_unit - len(units) + 1) * 1000.0):.0f} {units[-1]}" class Tools(BaseUIController): @@ -60,7 +60,7 @@ class Tools(BaseUIController): return returned if splited[1]: return "%d min. %d sec." % splited[1:3] - return "%.1f sec." % splited[2] + return f"{splited[2]:.1f} sec." @web.expose def tools_and_job_state(self, trans, **kwd): diff --git a/lib/galaxy/workflow/extract.py b/lib/galaxy/workflow/extract.py index 351bbcb48b9..a240731671f 100644 --- a/lib/galaxy/workflow/extract.py +++ b/lib/galaxy/workflow/extract.py @@ -87,7 +87,7 @@ def extract_steps(trans, history=None, job_ids=None, dataset_ids=None, dataset_c step = model.WorkflowStep() step.type = 'data_collection_input' if hid not in summary.collection_types: - raise exceptions.RequestParameterInvalidException("hid %s does not appear to be a collection" % hid) + raise exceptions.RequestParameterInvalidException(f"hid {hid} does not appear to be a collection") collection_type = summary.collection_types[hid] if dataset_collection_names: name = dataset_collection_names[i] @@ -121,7 +121,7 @@ def extract_steps(trans, history=None, job_ids=None, dataset_ids=None, dataset_c if input_collection: other_hid = input_collection.hid else: - log.info("Cannot find implicit input collection for %s" % input_name) + log.info(f"Cannot find implicit input collection for {input_name}") if other_hid in hid_to_output_pair: step_input = step.get_or_add_input(input_name) other_step, other_name = hid_to_output_pair[other_hid] @@ -142,7 +142,7 @@ def extract_steps(trans, history=None, job_ids=None, dataset_ids=None, dataset_c hid = None for implicit_pair in jobs[job]: query_assoc_name, dataset_collection = implicit_pair - if query_assoc_name == assoc_name or assoc_name.startswith("__new_primary_file_%s|" % query_assoc_name): + if query_assoc_name == assoc_name or assoc_name.startswith(f"__new_primary_file_{query_assoc_name}|"): hid = summary.hid(dataset_collection) if hid is None: template = "Failed to find matching implicit job - job id is %s, implicit pairs are %s, assoc_name is %s." @@ -156,7 +156,7 @@ def extract_steps(trans, history=None, job_ids=None, dataset_ids=None, dataset_c has_hid = assoc.dataset_collection_instance hid = summary.hid(has_hid) if hid in hid_to_output_pair: - log.warning("duplicate hid found in extract_steps [%s]" % hid) + log.warning(f"duplicate hid found in extract_steps [{hid}]") hid_to_output_pair[hid] = (step, assoc.name) return steps @@ -185,7 +185,7 @@ class DatasetCollectionCreationJob: def __init__(self, dataset_collection): self.is_fake = True - self.id = "fake_%s" % dataset_collection.id + self.id = f"fake_{dataset_collection.id}" self.from_jobs = None self.name = "Dataset Collection Creation" self.disabled_why = "Dataset collection created in a way not compatible with workflows" diff --git a/lib/galaxy/workflow/modules.py b/lib/galaxy/workflow/modules.py index 8400f42114b..81f8b8935ff 100644 --- a/lib/galaxy/workflow/modules.py +++ b/lib/galaxy/workflow/modules.py @@ -480,7 +480,7 @@ class SubWorkflowModule(WorkflowModule): for workflow_output in step['workflow_outputs']: label = workflow_output['label'] if not label: - label = "{}:{}".format(order_index, workflow_output['output_name']) + label = f"{order_index}:{workflow_output['output_name']}" workflow_output_uuid = workflow_output.get('uuid') or object() for data_output in data_outputs: data_output_uuid = data_output.get('uuid') or object() @@ -492,7 +492,7 @@ class SubWorkflowModule(WorkflowModule): # This can happen when importing workflows with missing tools. # We can't raise an exception here, as that would prevent loading # the workflow. - log.error("Workflow output '%s' defined, but not listed among data outputs" % workflow_output['output_name']) + log.error(f"Workflow output '{workflow_output['output_name']}' defined, but not listed among data outputs") continue outputs.append(data_output) return outputs @@ -1282,7 +1282,7 @@ class ToolModule(WorkflowModule): ) tool_uuid = dynamic_tool.uuid if tool_id is None and tool_uuid is None: - raise exceptions.RequestParameterInvalidException("No content id could be located for for step [%s]" % d) + raise exceptions.RequestParameterInvalidException(f"No content id could be located for for step [{d}]") module = super().from_dict(trans, d, tool_id=tool_id, tool_version=tool_version, tool_uuid=tool_uuid, **kwds) module.post_job_actions = d.get('post_job_actions', {}) module.workflow_outputs = d.get('workflow_outputs', []) @@ -1291,7 +1291,7 @@ class ToolModule(WorkflowModule): if tool_id != module.tool_id: message += f"The tool (id '{tool_id}') specified in this step is not available. Using the tool with id {module.tool_id} instead." if d.get('tool_version', 'Unspecified') != module.get_version(): - message += "{}: using version '{}' instead of version '{}' specified in this workflow.".format(tool_id, module.get_version(), d.get('tool_version', 'Unspecified')) + message += f"{tool_id}: using version '{module.get_version()}' instead of version '{d.get('tool_version', 'Unspecified')}' specified in this workflow." if message: log.debug(message) module.version_changes.append(message) @@ -1319,7 +1319,7 @@ class ToolModule(WorkflowModule): if not old_tool_shed_url: # a tool from a different tool_shed has been found, but the original tool shed has been deactivated old_tool_shed_url = "http://" + old_tool_shed # let's just assume it's either http, or a http is forwarded to https. old_url = old_tool_shed_url + f"/view/{module.tool.repository_owner}/{module.tool.repository_name}/" - new_url = module.tool.sharable_url + '/%s/' % module.tool.changeset_revision + new_url = module.tool.sharable_url + f'/{module.tool.changeset_revision}/' new_tool_shed_url = new_url.split("/view")[0] message += f"The tool \'{module.tool.name}\', version {tool_version} by the owner {module.tool.repository_owner} installed from
    {old_tool_shed_url} is not available. " message += f"A derivation of this tool installed from {new_tool_shed_url} will be used instead. " @@ -1329,7 +1329,7 @@ class ToolModule(WorkflowModule): log.debug(message) module.version_changes.append(message) else: - log.warning("The tool '%s' is missing. Cannot build workflow module." % tool_id) + log.warning(f"The tool '{tool_id}' is missing. Cannot build workflow module.") return module # ---- Saving in various forms ------------------------------------------ @@ -1369,7 +1369,7 @@ class ToolModule(WorkflowModule): def get_errors(self, include_tool_id=False, **kwargs): if not self.tool: if include_tool_id: - return "%s is not installed" % self.tool_id + return f"{self.tool_id} is not installed" else: return "Tool is not installed" @@ -1522,7 +1522,7 @@ class ToolModule(WorkflowModule): return ConnectedValue() visit_input_values(self.tool.inputs, self.state.inputs, callback) else: - raise ToolMissingException("Tool %s missing. Cannot add dummy datasets." % self.tool_id, + raise ToolMissingException(f"Tool {self.tool_id} missing. Cannot add dummy datasets.", tool_id=self.tool_id) def get_post_job_actions(self, incoming): @@ -1623,7 +1623,7 @@ class ToolModule(WorkflowModule): state.inputs[RUNTIME_STEP_META_STATE_KEY] = step_metadata_runtime_state return state, step_errors else: - raise ToolMissingException("Tool %s missing. Cannot compute runtime state." % self.tool_id, + raise ToolMissingException(f"Tool {self.tool_id} missing. Cannot compute runtime state.", tool_id=self.tool_id) def decode_runtime_state(self, runtime_state): @@ -1636,7 +1636,7 @@ class ToolModule(WorkflowModule): self.__restore_step_meta_runtime_state(json.loads(runtime_state[RUNTIME_STEP_META_STATE_KEY])) return state else: - raise ToolMissingException("Tool %s missing. Cannot recover runtime state." % self.tool_id, + raise ToolMissingException(f"Tool {self.tool_id} missing. Cannot recover runtime state.", tool_id=self.tool_id) def execute(self, trans, progress, invocation_step, use_cached_job=False): @@ -1644,7 +1644,7 @@ class ToolModule(WorkflowModule): step = invocation_step.workflow_step tool = trans.app.toolbox.get_tool(step.tool_id, tool_version=step.tool_version, tool_uuid=step.tool_uuid) if not tool.is_workflow_compatible: - message = "Specified tool [%s] in workflow is not workflow-compatible." % tool.id + message = f"Specified tool [{tool.id}] in workflow is not workflow-compatible." raise Exception(message) tool_state = step.state # Not strictly needed - but keep Tool state clean by stripping runtime @@ -1714,7 +1714,7 @@ class ToolModule(WorkflowModule): unmatched_input_connections = expected_replacement_keys - found_replacement_keys if unmatched_input_connections: - log.warning("Failed to use input connections for inputs [%s]" % unmatched_input_connections) + log.warning(f"Failed to use input connections for inputs [{unmatched_input_connections}]") param_combinations.append(execution_state.inputs) @@ -1760,7 +1760,7 @@ class ToolModule(WorkflowModule): execution_tracker = pje.execution_tracker except ToolInputsNotReadyException: - delayed_why = "tool [%s] inputs are not ready, this special tool requires inputs to be ready" % tool.id + delayed_why = f"tool [{tool.id}] inputs are not ready, this special tool requires inputs to be ready" raise DelayedWorkflowEvaluation(why=delayed_why) progress.record_executed_job_count(len(execution_tracker.successful_jobs)) diff --git a/lib/galaxy/workflow/refactor/execute.py b/lib/galaxy/workflow/refactor/execute.py index 1f5b9b66521..3a6a76a99ea 100644 --- a/lib/galaxy/workflow/refactor/execute.py +++ b/lib/galaxy/workflow/refactor/execute.py @@ -67,7 +67,7 @@ class WorkflowRefactorExecutor: # the workflow state out of sync. It is fine if you're just executing one # action at a time or just performing actions that use raw_workflow_description. action_type = action.action_type - refactor_method_name = "_apply_%s" % action_type + refactor_method_name = f"_apply_{action_type}" refactor_method = getattr(self, refactor_method_name, None) if refactor_method is None: raise RequestParameterInvalidException( diff --git a/lib/galaxy/workflow/reports/__init__.py b/lib/galaxy/workflow/reports/__init__.py index 15c068e40ca..a1340e31bc8 100644 --- a/lib/galaxy/workflow/reports/__init__.py +++ b/lib/galaxy/workflow/reports/__init__.py @@ -14,4 +14,4 @@ def generate_report(trans, invocation, runtime_report_config_json=None, plugin_t elif target_format == "pdf": return plugin.generate_report_pdf(trans, invocation, runtime_report_config_json=runtime_report_config_json) else: - raise RequestParameterInvalidException("Unknown report format [%s]" % target_format) + raise RequestParameterInvalidException(f"Unknown report format [{target_format}]") diff --git a/lib/galaxy/workflow/reports/generators/markdown.py b/lib/galaxy/workflow/reports/generators/markdown.py index 4f735274d43..95f8b8a7483 100644 --- a/lib/galaxy/workflow/reports/generators/markdown.py +++ b/lib/galaxy/workflow/reports/generators/markdown.py @@ -34,7 +34,7 @@ class MarkdownWorkflowMarkdownReportGeneratorPlugin(WorkflowMarkdownGeneratorPlu reports_config = (invocation.workflow.reports_config or {}).copy() # TODO: more intelligent merge here. reports_config.update(runtime_report_config_json or {}) - title = reports_config.get("title", "Workflow Execution Summary of %s" % invocation.workflow.stored_workflow.name) + title = reports_config.get("title", f"Workflow Execution Summary of {invocation.workflow.stored_workflow.name}") markdown = reports_config.get("markdown") if markdown is None: template_kwds = {"title": title} diff --git a/lib/galaxy/workflow/resources/__init__.py b/lib/galaxy/workflow/resources/__init__.py index 282fa596d74..01445a4a45d 100644 --- a/lib/galaxy/workflow/resources/__init__.py +++ b/lib/galaxy/workflow/resources/__init__.py @@ -46,7 +46,7 @@ def _read_defined_parameter_definitions(config): params_file = getattr(config, "job_resource_params_file", None) if not params_file or not os.path.exists(params_file): params_file = None - log.debug("Loading workflow resource parameter definitions from %s" % params_file) + log.debug(f"Loading workflow resource parameter definitions from {params_file}") if params_file: return galaxy.util.parse_resource_parameters(params_file) else: @@ -162,7 +162,7 @@ def _import_resource_mapping_function(qualified_function_path): try: __import__(full_module_name) except ImportError: - raise Exception("Failed to find workflow resource mapper module %s" % full_module_name) + raise Exception(f"Failed to find workflow resource mapper module {full_module_name}") module = sys.modules[full_module_name] if hasattr(module, function_name): diff --git a/lib/galaxy/workflow/run.py b/lib/galaxy/workflow/run.py index 5a600d8d6d7..f43a748d27c 100644 --- a/lib/galaxy/workflow/run.py +++ b/lib/galaxy/workflow/run.py @@ -241,11 +241,11 @@ class WorkflowInvoker: # No steps created yet - have to delay evaluation. if not step_invocation: - delayed_why = "depends on step [%s] but that step has not been invoked yet" % output_id + delayed_why = f"depends on step [{output_id}] but that step has not been invoked yet" raise modules.DelayedWorkflowEvaluation(why=delayed_why) if step_invocation.state != 'scheduled': - delayed_why = "depends on step [%s] job has not finished scheduling yet" % output_id + delayed_why = f"depends on step [{output_id}] job has not finished scheduling yet" raise modules.DelayedWorkflowEvaluation(delayed_why) for job_assoc in step_invocation.jobs: @@ -253,7 +253,7 @@ class WorkflowInvoker: if job: # At least one job in incomplete. if not job.finished: - delayed_why = "depends on step [%s] but one or more jobs created from that step have not finished yet" % output_id + delayed_why = f"depends on step [{output_id}] but one or more jobs created from that step have not finished yet" raise modules.DelayedWorkflowEvaluation(why=delayed_why) if job.state != job.states.OK: @@ -351,7 +351,7 @@ class WorkflowProgress: raise Exception(message) step_outputs = self.outputs[output_step_id] if step_outputs is STEP_OUTPUT_DELAYED: - delayed_why = "dependent step [%s] delayed, so this step must be delayed" % output_step_id + delayed_why = f"dependent step [{output_step_id}] delayed, so this step must be delayed" raise modules.DelayedWorkflowEvaluation(why=delayed_why) output_name = connection.output_name try: @@ -370,7 +370,7 @@ class WorkflowProgress: # TODO: consider distinguish between cancelled and failed? raise modules.CancelWorkflowEvaluation() - delayed_why = "dependent collection [%s] not yet populated with datasets" % replacement.id + delayed_why = f"dependent collection [{replacement.id}] not yet populated with datasets" raise modules.DelayedWorkflowEvaluation(why=delayed_why) data_inputs = (model.HistoryDatasetAssociation, model.HistoryDatasetCollectionAssociation, model.DatasetCollection) @@ -399,7 +399,7 @@ class WorkflowProgress: output_name = workflow_output.output_name step_outputs = self.outputs[step.id] if step_outputs is STEP_OUTPUT_DELAYED: - delayed_why = "depends on workflow output [%s] but that output has not been created yet" % output_name + delayed_why = f"depends on workflow output [{output_name}] but that output has not been created yet" raise modules.DelayedWorkflowEvaluation(why=delayed_why) else: return step_outputs[output_name] @@ -474,7 +474,7 @@ class WorkflowProgress: workflow_invocation = self.workflow_invocation subworkflow_invocation = workflow_invocation.get_subworkflow_invocation_for_step(step) if subworkflow_invocation is None: - raise Exception("Failed to find persisted workflow invocation for step [%s]" % step.id) + raise Exception(f"Failed to find persisted workflow invocation for step [{step.id}]") return subworkflow_invocation def subworkflow_invoker(self, trans, step, use_cached_job=False): diff --git a/lib/galaxy/workflow/run_request.py b/lib/galaxy/workflow/run_request.py index 8dd6f7fc920..206a1b1e826 100644 --- a/lib/galaxy/workflow/run_request.py +++ b/lib/galaxy/workflow/run_request.py @@ -207,15 +207,15 @@ def _get_target_history(trans, workflow, payload, param_keys=None, index=0): if history_name: nh_name = history_name else: - nh_name = 'History from %s workflow' % workflow.name + nh_name = f'History from {workflow.name} workflow' if len(param_keys) <= index: raise exceptions.MessageException("Incorrect expansion of workflow batch parameters.") ids = param_keys[index] nids = len(ids) if nids == 1: - nh_name = '{} on {}'.format(nh_name, ids[0]) + nh_name = f'{nh_name} on {ids[0]}' elif nids > 1: - nh_name = '{} on {} and {}'.format(nh_name, ', '.join(ids[0:-1]), ids[-1]) + nh_name = f"{nh_name} on {', '.join(ids[0:-1])} and {ids[-1]}" new_history = trans.app.model.History(user=trans.user, name=nh_name) trans.sa_session.add(new_history) target_history = new_history @@ -293,11 +293,11 @@ def build_workflow_run_configs(trans, workflow, payload): if step.type == 'parameter_input': continue if 'src' not in input_dict: - raise exceptions.RequestParameterInvalidException("Not input source type defined for input '%s'." % input_dict) + raise exceptions.RequestParameterInvalidException(f"Not input source type defined for input '{input_dict}'.") if 'id' not in input_dict: - raise exceptions.RequestParameterInvalidException("Not input id defined for input '%s'." % input_dict) + raise exceptions.RequestParameterInvalidException(f"Not input id defined for input '{input_dict}'.") if 'content' in input_dict: - raise exceptions.RequestParameterInvalidException("Input cannot specify explicit 'content' attribute %s'." % input_dict) + raise exceptions.RequestParameterInvalidException(f"Input cannot specify explicit 'content' attribute {input_dict}'.") input_source = input_dict['src'] input_id = input_dict['id'] try: @@ -318,13 +318,13 @@ def build_workflow_run_configs(trans, workflow, payload): if dataset is None: # this will need to be changed later. If federation code is avalible, then a missing UUID # could be found amoung fereration partners - raise exceptions.RequestParameterInvalidException("Input cannot find UUID: %s." % input_id) + raise exceptions.RequestParameterInvalidException(f"Input cannot find UUID: {input_id}.") assert trans.user_is_admin or trans.app.security_agent.can_access_dataset(trans.get_current_user_roles(), dataset) content = history.add_dataset(dataset) elif input_source == 'hdca': content = app.dataset_collections_service.get_dataset_collection_instance(trans, 'history', input_id) else: - raise exceptions.RequestParameterInvalidException("Unknown workflow input source '%s' specified." % input_source) + raise exceptions.RequestParameterInvalidException(f"Unknown workflow input source '{input_source}' specified.") if add_to_history and content.history != history: content = content.copy() if isinstance(content, app.model.HistoryDatasetAssociation): @@ -333,7 +333,7 @@ def build_workflow_run_configs(trans, workflow, payload): history.add_dataset_collection(content) input_dict['content'] = content except AssertionError: - raise exceptions.ItemAccessibilityException("Invalid workflow input '%s' specified" % input_id) + raise exceptions.ItemAccessibilityException(f"Invalid workflow input '{input_id}' specified") for key in set(normalized_inputs.keys()): value = normalized_inputs[key] if isinstance(value, dict) and 'content' in value: @@ -367,7 +367,7 @@ def build_workflow_run_configs(trans, workflow, payload): if value == option_value: valid_option = True if not valid_option: - raise exceptions.RequestParameterInvalidException("Invalid value for parameter '%s' found." % name) + raise exceptions.RequestParameterInvalidException(f"Invalid value for parameter '{name}' found.") run_configs.append(WorkflowRunConfig( target_history=history, @@ -404,7 +404,7 @@ def workflow_run_config_to_request(trans, run_config, workflow): step_state = model.WorkflowRequestStepState() step_state.workflow_step = step - log.info("Creating a step_state for step.id %s" % step.id) + log.info(f"Creating a step_state for step.id {step.id}") step_state.value = serializable_runtime_state workflow_invocation.step_states.append(step_state) diff --git a/lib/galaxy/workflow/scheduling_manager.py b/lib/galaxy/workflow/scheduling_manager.py index 1bd9a479d3a..867f7e1f9a2 100644 --- a/lib/galaxy/workflow/scheduling_manager.py +++ b/lib/galaxy/workflow/scheduling_manager.py @@ -157,7 +157,7 @@ class WorkflowSchedulingManager(ConfiguresHandlers): try: self._assign_handler(workflow_invocation, flush=flush) except HandlerAssignmentError: - raise RuntimeError("Unable to set a handler for workflow invocation '%s'" % workflow_invocation.id) + raise RuntimeError(f"Unable to set a handler for workflow invocation '{workflow_invocation.id}'") return workflow_invocation @@ -181,7 +181,7 @@ class WorkflowSchedulingManager(ConfiguresHandlers): log.info("No workflow schedulers plugin config file defined, using default scheduler.") use_default_scheduler = True elif not os.path.exists(config_file): - log.info("Cannot find workflow schedulers plugin config file '%s', using default scheduler." % config_file) + log.info(f"Cannot find workflow schedulers plugin config file '{config_file}', using default scheduler.") use_default_scheduler = True if use_default_scheduler: diff --git a/lib/galaxy/workflow/trs_proxy.py b/lib/galaxy/workflow/trs_proxy.py index 57873e308e3..d1fa5fb85fb 100644 --- a/lib/galaxy/workflow/trs_proxy.py +++ b/lib/galaxy/workflow/trs_proxy.py @@ -83,7 +83,7 @@ class TrsProxy: return self._get(trs_api_url) def get_version_descriptor(self, trs_server, tool_id, version_id, **kwd): - trs_api_url = self._get_tool_api_endpoint(trs_server, tool_id, **kwd) + "/versions/" + version_id + "/%s/descriptor" % GA4GH_GALAXY_DESCRIPTOR + trs_api_url = self._get_tool_api_endpoint(trs_server, tool_id, **kwd) + "/versions/" + version_id + f"/{GA4GH_GALAXY_DESCRIPTOR}/descriptor" return self._get(trs_api_url)["content"] def _quote(self, tool_id, **kwd): diff --git a/lib/galaxy_ext/container_monitor/monitor.py b/lib/galaxy_ext/container_monitor/monitor.py index 0f1969b6428..15ce8e9d2b8 100644 --- a/lib/galaxy_ext/container_monitor/monitor.py +++ b/lib/galaxy_ext/container_monitor/monitor.py @@ -42,7 +42,7 @@ def main(): callback_url = container_config.get("callback_url") connection_configuration = container_config["connection_configuration"] if container_type != "docker": - raise Exception("Monitoring container type [%s], not yet implemented." % container_type) + raise Exception(f"Monitoring container type [{container_type}], not yet implemented.") ports_raw = None exc_traceback = "" diff --git a/lib/galaxy_test/api/conftest.py b/lib/galaxy_test/api/conftest.py index 0f36a325933..56121a75d29 100644 --- a/lib/galaxy_test/api/conftest.py +++ b/lib/galaxy_test/api/conftest.py @@ -14,11 +14,11 @@ def get_timings(test_uuid): # ts = datetime.datetime.fromtimestamp(to_timestamp).strftime('%Y-%m-%dT%H:%M:%S.%fZ') params = { "db": "telegraf", - "q": "select * from galaxy_ where test='%s'" % (test_uuid,), + "q": f"select * from galaxy_ where test='{test_uuid}'", } query = urlencode(params) headers = {"content-type": "application/json"} - url = "http://localhost:8086/query?%s" % query + url = f"http://localhost:8086/query?{query}" response = requests.get(url, headers=headers) if response.ok: return response.json() diff --git a/lib/galaxy_test/api/test_api_batch.py b/lib/galaxy_test/api/test_api_batch.py index 18bcdabc99a..5f192e4bbdf 100644 --- a/lib/galaxy_test/api/test_api_batch.py +++ b/lib/galaxy_test/api/test_api_batch.py @@ -16,7 +16,7 @@ class ApiBatchTestCase(ApiTestCase): def _post_batch(self, batch): data = json.dumps({"batch": batch}) - return post("%s/batch" % (self.galaxy_interactor.api_url), data=data) + return post(f"{self.galaxy_interactor.api_url}/batch", data=data) # ---- tests def test_simple_array(self): diff --git a/lib/galaxy_test/api/test_dataset_collections.py b/lib/galaxy_test/api/test_dataset_collections.py index 39577f41d58..ec63e8a6e8f 100644 --- a/lib/galaxy_test/api/test_dataset_collections.py +++ b/lib/galaxy_test/api/test_dataset_collections.py @@ -101,7 +101,7 @@ class DatasetCollectionApiTestCase(ApiTestCase): self._assert_status_code_is(create_response, 200) archive = zipfile.ZipFile(BytesIO(create_response.content)) namelist = archive.namelist() - assert len(namelist) == 3, "Expected 3 elements in [%s]" % namelist + assert len(namelist) == 3, f"Expected 3 elements in [{namelist}]" collection_name = dataset_collection['name'] for element, zip_path in zip(returned_dce, namelist): assert f"{collection_name}/{element['element_identifier']}.{element['object']['file_ext']}" == zip_path @@ -116,10 +116,10 @@ class DatasetCollectionApiTestCase(ApiTestCase): self._assert_status_code_is(create_response, 200) archive = zipfile.ZipFile(BytesIO(create_response.content)) namelist = archive.namelist() - assert len(namelist) == 2, "Expected 2 elements in [%s]" % namelist + assert len(namelist) == 2, f"Expected 2 elements in [{namelist}]" collection_name = dataset_collection['name'] for element, zip_path in zip(returned_dce, namelist): - assert "{}/{}.{}".format(collection_name, element['element_identifier'], element['object']['file_ext']) == zip_path + assert f"{collection_name}/{element['element_identifier']}.{element['object']['file_ext']}" == zip_path def test_list_pair_download(self): fetch_response = self.dataset_collection_populator.create_list_of_pairs_in_history(self.history_id).json() @@ -132,10 +132,10 @@ class DatasetCollectionApiTestCase(ApiTestCase): self._assert_status_code_is(create_response, 200) archive = zipfile.ZipFile(BytesIO(create_response.content)) namelist = archive.namelist() - assert len(namelist) == 2, "Expected 2 elements in [%s]" % namelist + assert len(namelist) == 2, f"Expected 2 elements in [{namelist}]" pair_collection_name = pair['element_identifier'] for element, zip_path in zip(pair['object']['elements'], namelist): - assert "{}/{}/{}.{}".format(list_collection_name, pair_collection_name, element['element_identifier'], element['object']['file_ext']) == zip_path + assert f"{list_collection_name}/{pair_collection_name}/{element['element_identifier']}.{element['object']['file_ext']}" == zip_path def test_list_list_download(self): dataset_collection = self.dataset_collection_populator.create_list_of_list_in_history(self.history_id).json() @@ -146,7 +146,7 @@ class DatasetCollectionApiTestCase(ApiTestCase): self._assert_status_code_is(create_response, 200) archive = zipfile.ZipFile(BytesIO(create_response.content)) namelist = archive.namelist() - assert len(namelist) == 3, "Expected 3 elements in [%s]" % namelist + assert len(namelist) == 3, f"Expected 3 elements in [{namelist}]" def test_list_list_list_download(self): dataset_collection = self.dataset_collection_populator.create_list_of_list_in_history(self.history_id, collection_type='list:list:list').json() @@ -157,7 +157,7 @@ class DatasetCollectionApiTestCase(ApiTestCase): self._assert_status_code_is(create_response, 200) archive = zipfile.ZipFile(BytesIO(create_response.content)) namelist = archive.namelist() - assert len(namelist) == 3, "Expected 3 elements in [%s]" % namelist + assert len(namelist) == 3, f"Expected 3 elements in [{namelist}]" def test_hda_security(self): element_identifiers = self.dataset_collection_populator.pair_identifiers(self.history_id) @@ -274,7 +274,7 @@ class DatasetCollectionApiTestCase(ApiTestCase): assert "bagit.txt" in hdca["populated_state_message"], hdca def _assert_one_collection_created_in_history(self): - contents_response = self._get("histories/%s/contents/dataset_collections" % self.history_id) + contents_response = self._get(f"histories/{self.history_id}/contents/dataset_collections") self._assert_status_code_is(contents_response, 200) contents = contents_response.json() assert len(contents) == 1 @@ -307,7 +307,7 @@ class DatasetCollectionApiTestCase(ApiTestCase): response = self._get(contents_url) self._assert_status_code_is(response, 200) fake_collection_id = '5d7db0757a2eb7ef' - fake_contents_url = '/api/dataset_collections/{}/contents/{}'.format(hdca['id'], fake_collection_id) + fake_contents_url = f"/api/dataset_collections/{hdca['id']}/contents/{fake_collection_id}" error_response = self._get(fake_contents_url) assert_object_id_error(error_response) @@ -373,7 +373,7 @@ class DatasetCollectionApiTestCase(ApiTestCase): def _get_contents_url_for_hdca(self, hdca): # look up the history contents using optional serialization key - history_contents_url = "histories/%s/contents?v=dev&view=summary&keys=contents_url" % (self.history_id) + history_contents_url = f"histories/{self.history_id}/contents?v=dev&view=summary&keys=contents_url" json = self._get(history_contents_url).json() # filter out the collection we just made id = hdca.id diff --git a/lib/galaxy_test/api/test_datasets.py b/lib/galaxy_test/api/test_datasets.py index 38755e66ba3..514b2981ab2 100644 --- a/lib/galaxy_test/api/test_datasets.py +++ b/lib/galaxy_test/api/test_datasets.py @@ -98,7 +98,7 @@ class DatasetsApiTestCase(ApiTestCase): def test_show(self): hda1 = self.dataset_populator.new_dataset(self.history_id) - show_response = self._get("datasets/%s" % (hda1["id"])) + show_response = self._get(f"datasets/{hda1['id']}") self._assert_status_code_is(show_response, 200) self.__assert_matches_hda(hda1, show_response.json()) @@ -115,7 +115,7 @@ class DatasetsApiTestCase(ApiTestCase): """) hda1 = self.dataset_populator.new_dataset(self.history_id, content=contents) self.dataset_populator.wait_for_history(self.history_id) - display_response = self._get("histories/{}/contents/{}/display".format(self.history_id, hda1["id"]), { + display_response = self._get(f"histories/{self.history_id}/contents/{hda1['id']}/display", { 'raw': 'True' }) self._assert_status_code_is(display_response, 200) diff --git a/lib/galaxy_test/api/test_histories.py b/lib/galaxy_test/api/test_histories.py index d3e9b776302..bdc92baf468 100644 --- a/lib/galaxy_test/api/test_histories.py +++ b/lib/galaxy_test/api/test_histories.py @@ -17,10 +17,10 @@ from ._framework import ApiTestCase class BaseHistories: def _show(self, history_id): - return self._get("histories/%s" % history_id).json() + return self._get(f"histories/{history_id}").json() def _update(self, history_id, data): - update_url = self._api_url("histories/%s" % history_id, use_key=True) + update_url = self._api_url(f"histories/{history_id}", use_key=True) put_response = put(update_url, json=data) return put_response @@ -92,7 +92,7 @@ class HistoriesApiTestCase(ApiTestCase, BaseHistories, SharingApiTests): assert not show_response["deleted"] # Delete the history - self._delete("histories/%s" % history_id) + self._delete(f"histories/{history_id}") # Check can view it - but it is deleted show_response = self._show(history_id) @@ -109,15 +109,15 @@ class HistoriesApiTestCase(ApiTestCase, BaseHistories, SharingApiTests): def test_purge(self): history_id = self._create_history("TestHistoryForPurge")["id"] data = {'purge': True} - self._delete("histories/%s" % history_id, data=data) + self._delete(f"histories/{history_id}", data=data) show_response = self._show(history_id) assert show_response["deleted"] assert show_response["purged"] def test_undelete(self): history_id = self._create_history("TestHistoryForDeleteAndUndelete")["id"] - self._delete("histories/%s" % history_id) - self._post("histories/deleted/%s/undelete" % history_id) + self._delete(f"histories/{history_id}") + self._post(f"histories/deleted/{history_id}/undelete") show_response = self._show(history_id) assert not show_response["deleted"] @@ -185,10 +185,10 @@ class HistoriesApiTestCase(ApiTestCase, BaseHistories, SharingApiTests): def test_invalid_keys(self): invalid_history_id = "1234123412341234" - assert self._get("histories/%s" % invalid_history_id).status_code == 400 + assert self._get(f"histories/{invalid_history_id}").status_code == 400 assert self._update(invalid_history_id, {"name": "new name"}).status_code == 400 - assert self._delete("histories/%s" % invalid_history_id).status_code == 400 - assert self._post("histories/deleted/%s/undelete" % invalid_history_id).status_code == 400 + assert self._delete(f"histories/{invalid_history_id}").status_code == 400 + assert self._post(f"histories/deleted/{invalid_history_id}/undelete").status_code == 400 def test_create_anonymous_fails(self): post_data = dict(name="CannotCreate") @@ -207,7 +207,7 @@ class HistoriesApiTestCase(ApiTestCase, BaseHistories, SharingApiTests): post_data = dict(name="TestHistoryForTag") history_id = self._post("histories", data=post_data).json()["id"] tag_data = dict(value="awesometagvalue") - tag_url = "histories/%s/tags/awesometagname" % history_id + tag_url = f"histories/{history_id}/tags/awesometagname" tag_create_response = self._post(tag_url, data=tag_data) self._assert_status_code_is(tag_create_response, 200) @@ -380,7 +380,7 @@ class ImportExportHistoryTestCase(ApiTestCase, BaseHistories): return imported_history_id def _assert_history_length(self, history_id, n): - contents_response = self._get("histories/%s/contents" % history_id) + contents_response = self._get(f"histories/{history_id}/contents") self._assert_status_code_is(contents_response, 200) contents = contents_response.json() assert len(contents) == n, contents diff --git a/lib/galaxy_test/api/test_history_contents.py b/lib/galaxy_test/api/test_history_contents.py index 27b2ee07003..7f349dd7f74 100644 --- a/lib/galaxy_test/api/test_history_contents.py +++ b/lib/galaxy_test/api/test_history_contents.py @@ -25,13 +25,13 @@ class HistoryContentsApiTestCase(ApiTestCase): def test_index_hda_summary(self): hda1 = self.dataset_populator.new_dataset(self.history_id) - contents_response = self._get("histories/%s/contents" % self.history_id) + contents_response = self._get(f"histories/{self.history_id}/contents") hda_summary = self.__check_for_hda(contents_response, hda1) assert "display_types" not in hda_summary # Quick summary, not full details def test_make_private_and_public(self): hda1 = self._wait_for_new_hda() - update_url = "histories/{}/contents/{}/permissions".format(self.history_id, hda1["id"]) + update_url = f"histories/{self.history_id}/contents/{hda1['id']}/permissions" role_id = self.dataset_populator.user_private_role_id() # Give manage permission to the user. @@ -70,7 +70,7 @@ class HistoryContentsApiTestCase(ApiTestCase): if api_endpoint == "history_contents": update_url = f"histories/{self.history_id}/contents/{hda_id}/permissions" else: - update_url = "datasets/%s/permissions" % hda_id + update_url = f"datasets/{hda_id}/permissions" role_id = self.dataset_populator.user_private_role_id() @@ -144,13 +144,13 @@ class HistoryContentsApiTestCase(ApiTestCase): def test_index_hda_all_details(self): hda1 = self.dataset_populator.new_dataset(self.history_id) - contents_response = self._get("histories/%s/contents?details=all" % self.history_id) + contents_response = self._get(f"histories/{self.history_id}/contents?details=all") hda_details = self.__check_for_hda(contents_response, hda1) self.__assert_hda_has_full_details(hda_details) def test_index_hda_detail_by_id(self): hda1 = self.dataset_populator.new_dataset(self.history_id) - contents_response = self._get("histories/{}/contents?details={}".format(self.history_id, hda1["id"])) + contents_response = self._get(f"histories/{self.history_id}/contents?details={hda1['id']}") hda_details = self.__check_for_hda(contents_response, hda1) self.__assert_hda_has_full_details(hda_details) @@ -168,7 +168,7 @@ class HistoryContentsApiTestCase(ApiTestCase): ) second_history_id = self.dataset_populator.new_history() assert self.__count_contents(second_history_id) == 0 - create_response = self._post("histories/%s/contents" % second_history_id, create_data) + create_response = self._post(f"histories/{second_history_id}/contents", create_data) self._assert_status_code_is(create_response, 200) assert self.__count_contents(second_history_id) == 1 @@ -179,7 +179,7 @@ class HistoryContentsApiTestCase(ApiTestCase): content=ld["id"], ) assert self.__count_contents(self.history_id) == 0 - create_response = self._post("histories/%s/contents" % self.history_id, create_data) + create_response = self._post(f"histories/{self.history_id}/contents", create_data) self._assert_status_code_is(create_response, 200) assert self.__count_contents(self.history_id) == 1 @@ -241,7 +241,7 @@ class HistoryContentsApiTestCase(ApiTestCase): return hda1 def _set_edit_update(self, json): - set_edit_url = "%s/dataset/set_edit" % self.url + set_edit_url = f"{self.url}/dataset/set_edit" update_response = put(set_edit_url, json=json) return update_response @@ -259,7 +259,7 @@ class HistoryContentsApiTestCase(ApiTestCase): return update_response def _raw_update_batch(self, data): - update_url = self._api_url("histories/%s/contents" % (self.history_id), use_key=True) + update_url = self._api_url(f"histories/{self.history_id}/contents", use_key=True) update_response = put(update_url, json=data) return update_response @@ -267,7 +267,7 @@ class HistoryContentsApiTestCase(ApiTestCase): hda1 = self.dataset_populator.new_dataset(self.history_id) self.dataset_populator.wait_for_history(self.history_id) assert str(self.__show(hda1).json()["deleted"]).lower() == "false" - delete_response = self._delete("histories/{}/contents/{}".format(self.history_id, hda1["id"])) + delete_response = self._delete(f"histories/{self.history_id}/contents/{hda1['id']}") assert delete_response.status_code < 300 # Something in the 200s :). assert str(self.__show(hda1).json()["deleted"]).lower() == "true" @@ -277,7 +277,7 @@ class HistoryContentsApiTestCase(ApiTestCase): assert str(self.__show(hda1).json()["deleted"]).lower() == "false" assert str(self.__show(hda1).json()["purged"]).lower() == "false" data = {'purge': True} - delete_response = self._delete("histories/{}/contents/{}".format(self.history_id, hda1["id"]), data=data) + delete_response = self._delete(f"histories/{self.history_id}/contents/{hda1['id']}", data=data) assert delete_response.status_code < 300 # Something in the 200s :). assert str(self.__show(hda1).json()["deleted"]).lower() == "true" assert str(self.__show(hda1).json()["purged"]).lower() == "true" @@ -287,14 +287,14 @@ class HistoryContentsApiTestCase(ApiTestCase): self.history_id, type="dataset_collection" ) - endpoint = "histories/%s/contents" % self.history_id + endpoint = f"histories/{self.history_id}/contents" self._check_pair_creation(endpoint, payload) def test_dataset_collection_creation_on_typed_contents(self): payload = self.dataset_collection_populator.create_pair_payload( self.history_id, ) - endpoint = "histories/%s/contents/dataset_collections" % self.history_id + endpoint = f"histories/{self.history_id}/contents/dataset_collections" self._check_pair_creation(endpoint, payload) def test_dataset_collection_create_from_exisiting_datasets_with_new_tags(self): @@ -316,7 +316,7 @@ class HistoryContentsApiTestCase(ApiTestCase): ]), 'type': 'dataset_collection', 'copy_elements': True} - r = self._post("histories/%s/contents" % self.history_id, creation_payload).json() + r = self._post(f"histories/{self.history_id}/contents", creation_payload).json() assert r['elements'][0]['object']['id'] != hda_id, "HDA has not been copied" assert len(r['elements'][0]['object']['tags']) == 1 assert r['elements'][0]['object']['tags'][0] == 'my_new_tag' @@ -345,7 +345,7 @@ class HistoryContentsApiTestCase(ApiTestCase): assert pre_dataset_count == post_dataset_count # Test show dataset colleciton. - collection_url = "histories/{}/contents/dataset_collections/{}".format(self.history_id, dataset_collection["id"]) + collection_url = f"histories/{self.history_id}/contents/dataset_collections/{dataset_collection['id']}" show_response = self._get(collection_url) self._assert_status_code_is(show_response, 200) dataset_collection = show_response.json() @@ -367,7 +367,7 @@ class HistoryContentsApiTestCase(ApiTestCase): run = self.dataset_populator.run_collection_creates_list(self.history_id, hdca_id) collections = run['output_collections'] collection = collections[0] - jobs_summary_url = "histories/{}/contents/dataset_collections/{}/jobs_summary".format(self.history_id, collection["id"]) + jobs_summary_url = f"histories/{self.history_id}/contents/dataset_collections/{collection['id']}/jobs_summary" jobs_summary_response = self._get(jobs_summary_url) self._assert_status_code_is(jobs_summary_response, 200) jobs_summary = jobs_summary_response.json() @@ -384,7 +384,7 @@ class HistoryContentsApiTestCase(ApiTestCase): self.dataset_populator.wait_for_history_jobs(self.history_id) collections = run['implicit_collections'] collection = collections[0] - jobs_summary_url = "histories/{}/contents/dataset_collections/{}/jobs_summary".format(self.history_id, collection["id"]) + jobs_summary_url = f"histories/{self.history_id}/contents/dataset_collections/{collection['id']}/jobs_summary" jobs_summary_response = self._get(jobs_summary_url) self._assert_status_code_is(jobs_summary_response, 200) jobs_summary = jobs_summary_response.json() @@ -399,10 +399,10 @@ class HistoryContentsApiTestCase(ApiTestCase): ) payload["hide_source_items"] = True - dataset_collection_response = self._post("histories/%s/contents" % self.history_id, payload) + dataset_collection_response = self._post(f"histories/{self.history_id}/contents", payload) self.__check_create_collection_response(dataset_collection_response) - contents_response = self._get("histories/%s/contents" % self.history_id) + contents_response = self._get(f"histories/{self.history_id}/contents") datasets = [d for d in contents_response.json() if d["history_content_type"] == "dataset" and d["hid"] in [1, 2]] # Assert two datasets in source were hidden. assert len(datasets) == 2 @@ -414,10 +414,10 @@ class HistoryContentsApiTestCase(ApiTestCase): self.history_id, type="dataset_collection" ) - dataset_collection_response = self._post("histories/%s/contents" % self.history_id, payload) + dataset_collection_response = self._post(f"histories/{self.history_id}/contents", payload) self._assert_status_code_is(dataset_collection_response, 200) hdca = dataset_collection_response.json() - update_url = self._api_url("histories/{}/contents/dataset_collections/{}".format(self.history_id, hdca["id"]), use_key=True) + update_url = self._api_url(f"histories/{self.history_id}/contents/dataset_collections/{hdca['id']}", use_key=True) # Awkward json.dumps required here because of https://trello.com/c/CQwmCeG6 body = json.dumps(dict(name="newnameforpair")) update_response = put(update_url, data=body) @@ -433,10 +433,10 @@ class HistoryContentsApiTestCase(ApiTestCase): source='hdca', content=hdca_id, ) - assert len(self._get("histories/%s/contents/dataset_collections" % second_history_id).json()) == 0 - create_response = self._post("histories/%s/contents/dataset_collections" % second_history_id, create_data) + assert len(self._get(f"histories/{second_history_id}/contents/dataset_collections").json()) == 0 + create_response = self._post(f"histories/{second_history_id}/contents/dataset_collections", create_data) self.__check_create_collection_response(create_response) - contents = self._get("histories/%s/contents/dataset_collections" % second_history_id).json() + contents = self._get(f"histories/{second_history_id}/contents/dataset_collections").json() assert len(contents) == 1 new_forward, _ = self.__get_paired_response_elements(contents[0]) self._assert_has_keys(new_forward, "history_id") @@ -463,11 +463,11 @@ class HistoryContentsApiTestCase(ApiTestCase): content=hdca_id, copy_elements=True, ) - assert len(self._get("histories/%s/contents/dataset_collections" % second_history_id).json()) == 0 - create_response = self._post("histories/%s/contents/dataset_collections" % second_history_id, create_data) + assert len(self._get(f"histories/{second_history_id}/contents/dataset_collections").json()) == 0 + create_response = self._post(f"histories/{second_history_id}/contents/dataset_collections", create_data) self.__check_create_collection_response(create_response) - contents = self._get("histories/%s/contents/dataset_collections" % second_history_id).json() + contents = self._get(f"histories/{second_history_id}/contents/dataset_collections").json() assert len(contents) == 1 new_forward, _ = self.__get_paired_response_elements(contents[0]) self._assert_has_keys(new_forward, "history_id") @@ -497,7 +497,7 @@ class HistoryContentsApiTestCase(ApiTestCase): element_identifiers=json.dumps(element_identifiers), collection_type="list", ) - create_response = self._post("histories/%s/contents/dataset_collections" % history_id, create_data) + create_response = self._post(f"histories/{history_id}/contents/dataset_collections", create_data) hdca = self.__check_create_collection_response(create_response) elements = hdca["elements"] assert len(elements) == 1 @@ -520,7 +520,7 @@ class HistoryContentsApiTestCase(ApiTestCase): ) with self._different_user(): second_history_id = self.dataset_populator.new_history() - create_response = self._post("histories/%s/contents/dataset_collections" % second_history_id, create_data) + create_response = self._post(f"histories/{second_history_id}/contents/dataset_collections", create_data) self._assert_status_code_is(create_response, 403) def __check_create_collection_response(self, response): @@ -530,13 +530,13 @@ class HistoryContentsApiTestCase(ApiTestCase): return dataset_collection def __show(self, contents): - show_response = self._get("histories/{}/contents/{}s/{}".format(self.history_id, contents["history_content_type"], contents["id"])) + show_response = self._get(f"histories/{self.history_id}/contents/{contents['history_content_type']}s/{contents['id']}") return show_response def __count_contents(self, history_id=None, **kwds): if history_id is None: history_id = self.history_id - contents_response = self._get("histories/%s/contents" % history_id, kwds) + contents_response = self._get(f"histories/{history_id}/contents", kwds) return len(contents_response.json()) def __assert_hda_has_full_details(self, hda_details): @@ -558,7 +558,7 @@ class HistoryContentsApiTestCase(ApiTestCase): def test_job_state_summary_field(self): create_response = self.dataset_collection_populator.create_pair_in_history(self.history_id, contents=["123", "456"]) self._assert_status_code_is(create_response, 200) - contents_response = self._get("histories/%s/contents?v=dev&keys=job_state_summary&view=summary" % self.history_id) + contents_response = self._get(f"histories/{self.history_id}/contents?v=dev&keys=job_state_summary&view=summary") self._assert_status_code_is(contents_response, 200) contents = contents_response.json() for c in filter(lambda c: c['history_content_type'] == 'dataset_collection', contents): diff --git a/lib/galaxy_test/api/test_history_contents_provenance.py b/lib/galaxy_test/api/test_history_contents_provenance.py index 9c9fd2eec51..2951116b040 100644 --- a/lib/galaxy_test/api/test_history_contents_provenance.py +++ b/lib/galaxy_test/api/test_history_contents_provenance.py @@ -11,6 +11,6 @@ class TestProvenance(ApiTestCase): def test_show_prov(self): history_id = self.dataset_populator.new_history() new_dataset1 = self.dataset_populator.new_dataset(history_id, content='for prov') - prov_response = self._get("histories/{}/contents/{}/provenance".format(history_id, new_dataset1["id"])) + prov_response = self._get(f"histories/{history_id}/contents/{new_dataset1['id']}/provenance") self._assert_status_code_is(prov_response, 200) self._assert_has_keys(prov_response.json(), "job_id", "id", "stdout", "stderr", "parameters", "tool_id") diff --git a/lib/galaxy_test/api/test_jobs.py b/lib/galaxy_test/api/test_jobs.py index 20977320897..6b6263fadaf 100644 --- a/lib/galaxy_test/api/test_jobs.py +++ b/lib/galaxy_test/api/test_jobs.py @@ -213,13 +213,13 @@ steps: self._assert_has_key(first_job, 'id', 'state', 'exit_code', 'update_time', 'create_time') job_id = first_job["id"] - show_jobs_response = self._get("jobs/%s" % job_id) + show_jobs_response = self._get(f"jobs/{job_id}") self._assert_status_code_is(show_jobs_response, 200) job_details = show_jobs_response.json() self._assert_has_key(job_details, 'id', 'state', 'exit_code', 'update_time', 'create_time') - show_jobs_response = self._get("jobs/%s" % job_id, {"full": True}) + show_jobs_response = self._get(f"jobs/{job_id}", {"full": True}) self._assert_status_code_is(show_jobs_response, 200) job_details = show_jobs_response.json() @@ -244,7 +244,7 @@ steps: # show_jobs_response = self._get( "jobs/%s" % job_id, admin=False ) # self._assert_status_code_is( show_jobs_response, 200 ) - show_jobs_response = self._get("jobs/%s" % job_id, admin=True) + show_jobs_response = self._get(f"jobs/{job_id}", admin=True) self._assert_has_keys(show_jobs_response.json(), "command_line", "external_id") def _run_detect_errors(self, history_id, inputs): @@ -309,8 +309,8 @@ steps: ) empty_output_job = empty_run_response["jobs"][0] cat_empty_job = cat_empty_twice_run_response["jobs"][0] - empty_output_common_problems_response = self._get('jobs/%s/common_problems' % empty_output_job["id"]).json() - cat_empty_common_problems_response = self._get('jobs/%s/common_problems' % cat_empty_job["id"]).json() + empty_output_common_problems_response = self._get(f"jobs/{empty_output_job['id']}/common_problems").json() + cat_empty_common_problems_response = self._get(f"jobs/{cat_empty_job['id']}/common_problems").json() self._assert_has_keys(empty_output_common_problems_response, "has_empty_inputs", "has_duplicate_inputs") self._assert_has_keys(cat_empty_common_problems_response, "has_empty_inputs", "has_duplicate_inputs") assert not empty_output_common_problems_response["has_empty_inputs"] @@ -330,7 +330,7 @@ steps: job_id = run_response['jobs'][0]["id"] self.dataset_populator.wait_for_job(job_id) dataset_id = run_response['outputs'][0]['id'] - response = self._post('jobs/%s/error' % job_id, + response = self._post(f'jobs/{job_id}/error', data={'dataset_id': dataset_id}) assert response.status_code == 200, response.text @@ -340,7 +340,7 @@ steps: cookies = requests.get(self.url).cookies payload = json.dumps({"tool_id": "detect_errors_aggressive", "inputs": {"error_bool": "true"}}) - run_response = requests.post("%s/tools" % self.galaxy_interactor.api_url, data=payload, cookies=cookies).json() + run_response = requests.post(f"{self.galaxy_interactor.api_url}/tools", data=payload, cookies=cookies).json() job_id = run_response['jobs'][0]["id"] dataset_id = run_response['outputs'][0]['id'] response = requests.post(f'{self.galaxy_interactor.api_url}/jobs/{job_id}/error', @@ -466,7 +466,7 @@ steps: assert len(jobs) == 1 def job_state(): - jobs_response = self._get("jobs/%s" % jobs[0]["id"]) + jobs_response = self._get(f"jobs/{jobs[0]['id']}") return jobs_response # Give job some time to get up and running. @@ -475,7 +475,7 @@ steps: assert running_state == "running", running_state def job_state(): - jobs_response = self._get("jobs/%s" % jobs[0]["id"]) + jobs_response = self._get(f"jobs/{jobs[0]['id']}") return jobs_response return job_state, outputs @@ -516,19 +516,19 @@ steps: job_id = run_response['jobs'][0]['id'] output = run_response["outputs"][0] # Delete second jobs input while second job is waiting for first job - delete_response = self._delete("histories/{}/contents/{}".format(history_id, hda1['id'])) + delete_response = self._delete(f"histories/{history_id}/contents/{hda1['id']}") self._assert_status_code_is(delete_response, 200) self.dataset_populator.wait_for_history_jobs(history_id, assert_ok=False) - dataset_details = self._get("histories/{}/contents/{}".format(history_id, output['id'])).json() + dataset_details = self._get(f"histories/{history_id}/contents/{output['id']}").json() assert dataset_details['state'] == 'paused' # Undelete input dataset - undelete_response = self._put("histories/{}/contents/{}".format(history_id, hda1['id']), + undelete_response = self._put(f"histories/{history_id}/contents/{hda1['id']}", data=json.dumps({'deleted': False})) self._assert_status_code_is(undelete_response, 200) - resume_response = self._put("jobs/%s/resume" % job_id) + resume_response = self._put(f"jobs/{job_id}/resume") self._assert_status_code_is(resume_response, 200) self.dataset_populator.wait_for_history_jobs(history_id, assert_ok=True) - dataset_details = self._get("histories/{}/contents/{}".format(history_id, output['id'])).json() + dataset_details = self._get(f"histories/{history_id}/contents/{output['id']}").json() assert dataset_details['state'] == 'ok' def _get_history_item_as_admin(self, history_id, item_id): @@ -542,7 +542,7 @@ steps: # We first copy the datasets, so that the update time is lower than the job creation time new_history_id = self.dataset_populator.new_history() copy_payload = {"content": dataset_id, "source": "hda", "type": "dataset"} - copy_response = self._post("histories/%s/contents" % new_history_id, data=copy_payload) + copy_response = self._post(f"histories/{new_history_id}/contents", data=copy_payload) self._assert_status_code_is(copy_response, 200) inputs = json.dumps({ 'input1': {'src': 'hda', 'id': dataset_id} @@ -649,7 +649,7 @@ steps: # We test that a job can be found even if the collection has been copied to another history new_history_id = self.dataset_populator.new_history() copy_payload = {"content": list_id_a, "source": "hdca", "type": "dataset_collection"} - copy_response = self._post("histories/%s/contents" % new_history_id, data=copy_payload) + copy_response = self._post(f"histories/{new_history_id}/contents", data=copy_payload) self._assert_status_code_is(copy_response, 200) new_list_a = copy_response.json()['id'] copied_inputs = json.dumps({ @@ -694,7 +694,7 @@ steps: wait_for_job=True, assert_ok=True, ) - rerun_params = self._get("jobs/%s/build_for_rerun" % run_response['jobs'][0]['id']).json() + rerun_params = self._get(f"jobs/{run_response['jobs'][0]['id']}/build_for_rerun").json() # Since we call rerun on the first (and only) job we should get the expanded input # which is a dataset collection element (and not the list:pair hdca that was used as input to the original # job). @@ -756,7 +756,7 @@ steps: assert_ok=True, ) assert len(run_response['jobs']) == 2 - rerun_params = self._get("jobs/%s/build_for_rerun" % run_response['jobs'][0]['id']).json() + rerun_params = self._get(f"jobs/{run_response['jobs'][0]['id']}/build_for_rerun").json() # Since we call rerun on the first (and only) job we should get the expanded input # which is a dataset collection element (and not the list:list hdca that was used as input to the original # job). diff --git a/lib/galaxy_test/api/test_libraries.py b/lib/galaxy_test/api/test_libraries.py index 9955eb82419..fa3dca15d6f 100644 --- a/lib/galaxy_test/api/test_libraries.py +++ b/lib/galaxy_test/api/test_libraries.py @@ -31,14 +31,14 @@ class LibrariesApiTestCase(ApiTestCase): def test_delete(self): library = self.library_populator.new_library("DeleteTestLibrary") - create_response = self._delete("libraries/%s" % library["id"], admin=True) + create_response = self._delete(f"libraries/{library['id']}", admin=True) self._assert_status_code_is(create_response, 200) library = create_response.json() self._assert_has_keys(library, "deleted") assert library["deleted"] is True # Test undeleting data = dict(undelete=True) - create_response = self._delete("libraries/%s" % library["id"], data=data, admin=True) + create_response = self._delete(f"libraries/{library['id']}", data=data, admin=True) library = create_response.json() self._assert_status_code_is(create_response, 200) assert library["deleted"] is False @@ -50,17 +50,17 @@ class LibrariesApiTestCase(ApiTestCase): self._assert_status_code_is(create_response, 403) # Anons can't delete libs library = self.library_populator.new_library("AnonDeleteTestLibrary") - create_response = self._delete("libraries/%s" % library["id"], admin=False, anon=True) + create_response = self._delete(f"libraries/{library['id']}", admin=False, anon=True) self._assert_status_code_is(create_response, 403) # Anons can't update libs data = dict(name="ChangedName", description="ChangedDescription", synopsis='ChangedSynopsis') - create_response = self._patch("libraries/%s" % library["id"], data=data, admin=False, anon=True) + create_response = self._patch(f"libraries/{library['id']}", data=data, admin=False, anon=True) self._assert_status_code_is(create_response, 403) def test_update(self): library = self.library_populator.new_library("UpdateTestLibrary") data = dict(name='ChangedName', description='ChangedDescription', synopsis='ChangedSynopsis') - create_response = self._patch("libraries/%s" % library["id"], data=data, admin=True) + create_response = self._patch(f"libraries/{library['id']}", data=data, admin=True) self._assert_status_code_is(create_response, 200) library = create_response.json() self._assert_has_keys(library, 'name', 'description', 'synopsis') @@ -85,7 +85,7 @@ class LibrariesApiTestCase(ApiTestCase): hda_id = self.dataset_populator.new_dataset(history_id, content="1 2 3")['id'] with self._different_user(): payload = {'from_hda_id': hda_id} - create_response = self._post("folders/%s/contents" % folder_id, payload) + create_response = self._post(f"folders/{folder_id}/contents", payload) self._assert_status_code_is(create_response, 403) def test_show_private_dataset_permissions(self): @@ -178,7 +178,7 @@ class LibrariesApiTestCase(ApiTestCase): 'upload_option': 'upload_file', 'files_0|url_paste': FILE_URL, } - create_response = self._post("libraries/%s/contents" % library['id'], payload) + create_response = self._post(f"libraries/{library['id']}/contents", payload) self._assert_status_code_is(create_response, 400) assert create_response.json() == "Requested extension 'xxx' unknown, cannot upload dataset." @@ -259,7 +259,7 @@ class LibrariesApiTestCase(ApiTestCase): history_id = self.dataset_populator.new_history() hda_id = self.dataset_populator.new_dataset(history_id, content="1 2 3")['id'] payload = {'from_hda_id': hda_id} - create_response = self._post("folders/%s/contents" % folder_id, payload) + create_response = self._post(f"folders/{folder_id}/contents", payload) self._assert_status_code_is(create_response, 200) self._assert_has_keys(create_response.json(), "name", "id") @@ -275,25 +275,25 @@ class LibrariesApiTestCase(ApiTestCase): history_id = self.dataset_populator.new_history() hda_id = self.dataset_populator.new_dataset(history_id, content="1 2 3 sub")['id'] payload = {'from_hda_id': hda_id} - create_response = self._post("folders/%s/contents" % subfolder_id, payload) + create_response = self._post(f"folders/{subfolder_id}/contents", payload) self._assert_status_code_is(create_response, 200) self._assert_has_keys(create_response.json(), "name", "id") dataset_update_time = create_response.json()['update_time'] - container_fetch_response = self.galaxy_interactor.get("folders/%s/contents" % folder_id) + container_fetch_response = self.galaxy_interactor.get(f"folders/{folder_id}/contents") container_update_time = container_fetch_response.json()['folder_contents'][0]['update_time'] assert dataset_update_time == container_update_time, container_fetch_response def test_update_dataset_in_folder(self): ld = self._create_dataset_in_folder_in_library("ForUpdateDataset", wait=True) data = {'name': 'updated_name', 'file_ext': 'fastq', 'misc_info': 'updated_info', 'genome_build': 'updated_genome_build'} - create_response = self._patch("libraries/datasets/%s" % ld.json()["id"], data=data) + create_response = self._patch(f"libraries/datasets/{ld.json()['id']}", data=data) self._assert_status_code_is(create_response, 200) self._assert_has_keys(create_response.json(), "name", "file_ext", "misc_info", "genome_build") def test_update_dataset_tags(self): ld = self._create_dataset_in_folder_in_library("ForTagtestDataset") data = {"tags": ["#Lancelot", "name:Holy Grail", "blue"]} - create_response = self._patch("libraries/datasets/%s" % ld.json()["id"], data=data) + create_response = self._patch(f"libraries/datasets/{ld.json()['id']}", data=data) self._assert_status_code_is(create_response, 200) self._assert_has_keys(create_response.json(), "tags") assert create_response.json()["tags"] == "name:Lancelot, name:HolyGrail, blue" @@ -301,7 +301,7 @@ class LibrariesApiTestCase(ApiTestCase): def test_invalid_update_dataset_in_folder(self): ld = self._create_dataset_in_folder_in_library("ForInvalidUpdateDataset") data = {'file_ext': 'nonexisting_type'} - create_response = self._patch("libraries/datasets/%s" % ld.json()["id"], data=data) + create_response = self._patch(f"libraries/datasets/{ld.json()['id']}", data=data) self._assert_status_code_is(create_response, 400) assert 'This Galaxy does not recognize the datatype of:' in create_response.json()['err_msg'] @@ -310,14 +310,14 @@ class LibrariesApiTestCase(ApiTestCase): # Wait for metadata job to finish. time.sleep(2) data = {'file_ext': 'data'} - create_response = self._patch("libraries/datasets/%s" % ld.json()["id"], data=data) + create_response = self._patch(f"libraries/datasets/{ld.json()['id']}", data=data) self._assert_status_code_is(create_response, 200) self._assert_has_keys(create_response.json(), "file_ext") assert create_response.json()["file_ext"] == "data" # Wait for metadata job to finish. time.sleep(2) data = {'file_ext': 'auto'} - create_response = self._patch("libraries/datasets/%s" % ld.json()["id"], data=data) + create_response = self._patch(f"libraries/datasets/{ld.json()['id']}", data=data) self._assert_status_code_is(create_response, 200) self._assert_has_keys(create_response.json(), "file_ext") assert create_response.json()["file_ext"] == "txt" @@ -331,7 +331,7 @@ class LibrariesApiTestCase(ApiTestCase): def test_import_paired_collection(self): ld = self._create_dataset_in_folder_in_library("ForHistoryImport").json() history_id = self.dataset_populator.new_history() - url = "histories/%s/contents" % history_id + url = f"histories/{history_id}/contents" collection_name = 'Paired-end data (from library)' payload = { 'name': collection_name, @@ -356,7 +356,7 @@ class LibrariesApiTestCase(ApiTestCase): def _import_to_history(self, visible=True): ld = self._create_dataset_in_folder_in_library("ForHistoryImport").json() history_id = self.dataset_populator.new_history() - url = "histories/%s/contents" % history_id + url = f"histories/{history_id}/contents" collection_name = 'new_collection_name' element_identifer = 'new_element_identifier' payload = { @@ -388,7 +388,7 @@ class LibrariesApiTestCase(ApiTestCase): history_id = self.dataset_populator.new_history() hdca_id = self.dataset_collection_populator.create_list_in_history(history_id, contents=["xxx", "yyy"], direct_upload=True).json()["outputs"][0]["id"] payload = {'from_hdca_id': hdca_id, 'create_type': 'file', 'folder_id': folder_id} - create_response = self._post("libraries/%s/contents" % library['id'], payload) + create_response = self._post(f"libraries/{library['id']}/contents", payload) self._assert_status_code_is(create_response, 200) def test_create_datasets_in_folder_from_collection(self): @@ -399,14 +399,14 @@ class LibrariesApiTestCase(ApiTestCase): self._assert_status_code_is(folder_response, 200) folder_id = folder_response.json()[0]['id'] payload = {'from_hdca_id': hdca_id} - create_response = self._post("folders/%s/contents" % folder_id, payload) + create_response = self._post(f"folders/{folder_id}/contents", payload) self._assert_status_code_is(create_response, 200) assert len(create_response.json()) == 2 # Also test that anything different from a flat dataset collection list # is refused hdca_pair_id = self.dataset_collection_populator.create_list_of_pairs_in_history(history_id).json()["outputs"][0]['id'] payload = {'from_hdca_id': hdca_pair_id} - create_response = self._post("folders/%s/contents" % folder_id, payload) + create_response = self._post(f"folders/{folder_id}/contents", payload) self._assert_status_code_is(create_response, 501) assert create_response.json()['err_msg'] == 'Cannot add nested collections to library. Please flatten your collection first.' @@ -416,14 +416,14 @@ class LibrariesApiTestCase(ApiTestCase): create_type="folder", name="New Folder", ) - return self._post("libraries/%s/contents" % library["id"], data=create_data) + return self._post(f"libraries/{library['id']}/contents", data=create_data) def _create_subfolder(self, containing_folder_id): create_data = dict( description="new subfolder desc", name="New Subfolder", ) - return self._post("folders/%s" % containing_folder_id, data=create_data) + return self._post(f"folders/{containing_folder_id}", data=create_data) def _create_dataset_in_folder_in_library(self, library_name, wait=False): library = self.library_populator.new_private_library(library_name) @@ -433,5 +433,5 @@ class LibrariesApiTestCase(ApiTestCase): history_id = self.dataset_populator.new_history() hda_id = self.dataset_populator.new_dataset(history_id, content="1 2 3", wait=wait)['id'] payload = {'from_hda_id': hda_id, 'create_type': 'file', 'folder_id': folder_id} - ld = self._post("libraries/%s/contents" % folder_id, payload) + ld = self._post(f"libraries/{folder_id}/contents", payload) return ld diff --git a/lib/galaxy_test/api/test_page_revisions.py b/lib/galaxy_test/api/test_page_revisions.py index fb89c90d680..3506bb2e0be 100644 --- a/lib/galaxy_test/api/test_page_revisions.py +++ b/lib/galaxy_test/api/test_page_revisions.py @@ -7,7 +7,7 @@ class PageRevisionsApiTestCase(BasePageApiTestCase): def test_create(self): page_json = self._create_valid_page_with_slug("pr1") revision_data = dict(content="

    NewContent!

    ") - page_revision_response = self._post("pages/%s/revisions" % page_json['id'], data=revision_data) + page_revision_response = self._post(f"pages/{page_json['id']}/revisions", data=revision_data) self._assert_status_code_is(page_revision_response, 200) page_revision_json = page_revision_response.json() self._assert_has_keys(page_revision_json, 'id', 'content') @@ -15,13 +15,13 @@ class PageRevisionsApiTestCase(BasePageApiTestCase): def test_403_if_create_revision_on_unowned_page(self): page_json = self._create_valid_page_as("pr2@bx.psu.edu", "pr2") revision_data = dict(content="

    NewContent!

    ") - page_revision_response = self._post("pages/%s/revisions" % page_json['id'], data=revision_data) + page_revision_response = self._post(f"pages/{page_json['id']}/revisions", data=revision_data) self._assert_status_code_is(page_revision_response, 403) def test_revision_index(self): page_json = self._create_valid_page_with_slug("pr3") revision_data = dict(content="

    NewContent!

    ") - revisions_url = "pages/%s/revisions" % page_json['id'] + revisions_url = f"pages/{page_json['id']}/revisions" self._post(revisions_url, data=revision_data) revisions_response = self._get(revisions_url) self._assert_status_code_is(revisions_response, 200) @@ -29,7 +29,7 @@ class PageRevisionsApiTestCase(BasePageApiTestCase): assert len(revisions_json) == 2 # Original revision and new one def test_malformed_id_if_index_unknown_page(self): - revisions_url = "pages/%s/revisions" % self._random_key() + revisions_url = f"pages/{self._random_key()}/revisions" revisions_response = self._get(revisions_url) self._assert_status_code_is(revisions_response, 400) self._assert_error_code_is(revisions_response, error_codes.MALFORMED_ID) diff --git a/lib/galaxy_test/api/test_pages.py b/lib/galaxy_test/api/test_pages.py index 7e570a4833f..7b04017cf49 100644 --- a/lib/galaxy_test/api/test_pages.py +++ b/lib/galaxy_test/api/test_pages.py @@ -88,7 +88,7 @@ steps: page_response = self._post("pages", page_request, json=True) self._assert_status_code_is(page_response, 200) page_response = page_response.json() - show_response = self._get("pages/%s" % page_response['id']) + show_response = self._get(f"pages/{page_response['id']}") self._assert_status_code_is(show_response, 200) show_json = show_response.json() self._assert_has_keys(show_json, "slug", "title", "id") @@ -143,17 +143,17 @@ steps: def test_delete(self): response_json = self._create_valid_page_with_slug("testdelete") - delete_response = delete(self._api_url("pages/%s" % response_json['id'], use_key=True)) + delete_response = delete(self._api_url(f"pages/{response_json['id']}", use_key=True)) self._assert_status_code_is(delete_response, 204) def test_400_on_delete_invalid_page_id(self): - delete_response = delete(self._api_url("pages/%s" % self._random_key(), use_key=True)) + delete_response = delete(self._api_url(f"pages/{self._random_key()}", use_key=True)) self._assert_status_code_is(delete_response, 400) self._assert_error_code_is(delete_response, error_codes.MALFORMED_ID) def test_403_on_delete_unowned_page(self): page_response = self._create_valid_page_as("others_page@bx.psu.edu", "otherspage") - delete_response = delete(self._api_url("pages/%s" % page_response["id"], use_key=True)) + delete_response = delete(self._api_url(f"pages/{page_response['id']}", use_key=True)) self._assert_status_code_is(delete_response, 403) self._assert_error_code_is(delete_response, error_codes.USER_DOES_NOT_OWN_ITEM) @@ -175,7 +175,7 @@ steps: dataset_populator = DatasetPopulator(self.galaxy_interactor) valid_id = dataset_populator.new_history() page_request = self._test_page_payload(slug="invalid-embed-content") - page_request["content"] = '''

    Page!

    ''' % valid_id + page_request["content"] = f'''

    Page!

    ''' page_response = self._post("pages", page_request, json=True) self._assert_status_code_is(page_response, 400) self._assert_error_code_is(page_response, error_codes.USER_REQUEST_INVALID_PARAMETER) @@ -190,7 +190,7 @@ steps: def test_show(self): response_json = self._create_valid_page_with_slug("pagetoshow") - show_response = self._get("pages/%s" % response_json['id']) + show_response = self._get(f"pages/{response_json['id']}") self._assert_status_code_is(show_response, 200) show_json = show_response.json() self._assert_has_keys(show_json, "slug", "title", "id") @@ -201,7 +201,7 @@ steps: def test_403_on_unowner_show(self): response_json = self._create_valid_page_as("others_page_show@bx.psu.edu", "otherspageshow") - show_response = self._get("pages/%s" % response_json['id']) + show_response = self._get(f"pages/{response_json['id']}") self._assert_status_code_is(show_response, 403) self._assert_error_code_is(show_response, error_codes.USER_CANNOT_ACCESS_ITEM) diff --git a/lib/galaxy_test/api/test_roles.py b/lib/galaxy_test/api/test_roles.py index 987141dea6b..aa414a242f7 100644 --- a/lib/galaxy_test/api/test_roles.py +++ b/lib/galaxy_test/api/test_roles.py @@ -47,7 +47,7 @@ class RolesApiTestCase(ApiTestCase): assert different_user_role_id in admin_roles_response_ids # Check showing a valid, role. - role_response = self._get("roles/%s" % user_role_id) + role_response = self._get(f"roles/{user_role_id}") assert_status_code_is(role_response, 200) role = role_response.json() RolesApiTestCase.check_role_dict(role, assert_id=user_role_id) @@ -128,7 +128,7 @@ class RolesApiTestCase(ApiTestCase): # Trying to access roles are errors - should probably be 403 not 400 though? with self._different_user(): different_user_role_id = self.dataset_populator.user_private_role_id() - response = self._get("roles/%s" % different_user_role_id) + response = self._get(f"roles/{different_user_role_id}") assert_status_code_is(response, 400) def test_create_only_admin(self): diff --git a/lib/galaxy_test/api/test_search.py b/lib/galaxy_test/api/test_search.py index a6f75fc4462..a44d866e8e4 100644 --- a/lib/galaxy_test/api/test_search.py +++ b/lib/galaxy_test/api/test_search.py @@ -13,7 +13,7 @@ class SearchApiTestCase(ApiTestCase): assert self.__has_result_with_name(search_response, "test_for_search"), search_response.text # Deleted - delete_url = self._api_url("workflows/%s" % workflow_id, use_key=True) + delete_url = self._api_url(f"workflows/{workflow_id}", use_key=True) delete(delete_url) search_response = self.__search("select * from workflow where deleted = False") diff --git a/lib/galaxy_test/api/test_tool_data.py b/lib/galaxy_test/api/test_tool_data.py index 2b767c998fb..0c9b4843c51 100644 --- a/lib/galaxy_test/api/test_tool_data.py +++ b/lib/galaxy_test/api/test_tool_data.py @@ -40,7 +40,7 @@ class ToolDataApiTestCase(ApiTestCase): field = show_field_response.json() self._assert_has_keys(field, "files", "name", "fields", "fingerprint", "base_dir") files = field["files"] - assert len(files) == 2, "Length of files [%s] was not 2." % files + assert len(files) == 2, f"Length of files [{files}] was not 2." def test_download_field_file(self): show_field_response = self._get("tool_data/testalpha/fields/data1/files/entry.txt", admin=True) diff --git a/lib/galaxy_test/api/test_tools.py b/lib/galaxy_test/api/test_tools.py index 05fae94da18..bc3ea2c1abe 100644 --- a/lib/galaxy_test/api/test_tools.py +++ b/lib/galaxy_test/api/test_tools.py @@ -140,7 +140,7 @@ class ToolsTestCase(ApiTestCase, TestsTools): @skip_without_tool("test_sam_to_bam_conversions") def test_requirements(self): - requirements_response = self._get("tools/%s/requirements" % "test_sam_to_bam_conversions", admin=True) + requirements_response = self._get(f"tools/{'test_sam_to_bam_conversions'}/requirements", admin=True) self._assert_status_code_is_ok(requirements_response) requirements = requirements_response.json() assert len(requirements) == 1, requirements @@ -151,7 +151,7 @@ class ToolsTestCase(ApiTestCase, TestsTools): def test_show_repeat(self): tool_info = self._show_valid_tool("cat1") parameters = tool_info["inputs"] - assert len(parameters) == 2, "Expected two inputs - got [%s]" % parameters + assert len(parameters) == 2, f"Expected two inputs - got [{parameters}]" assert parameters[0]["name"] == "input1" assert parameters[1]["name"] == "queries" @@ -268,7 +268,7 @@ class ToolsTestCase(ApiTestCase, TestsTools): payload = self.dataset_populator.run_tool_payload( tool_id="test_data_source", inputs={ - "URL": "file://%s" % os.path.join(os.getcwd(), "README.rst"), + "URL": f"file://{os.path.join(os.getcwd(), 'README.rst')}", "URL_method": "get", "data_type": "bed", }, @@ -290,7 +290,7 @@ class ToolsTestCase(ApiTestCase, TestsTools): data = dict(io_details=True) if tool_version: data['tool_version'] = tool_version - tool_show_response = self._get("tools/%s" % tool_id, data=data) + tool_show_response = self._get(f"tools/{tool_id}", data=data) self._assert_status_code_is(tool_show_response, 200) tool_info = tool_show_response.json() self._assert_has_keys(tool_info, "inputs", "outputs", "panel_section_id") @@ -298,17 +298,17 @@ class ToolsTestCase(ApiTestCase, TestsTools): @skip_without_tool("composite_output") def test_test_data_filepath_security(self): - test_data_response = self._get("tools/%s/test_data_path?filename=../CONTRIBUTORS.md" % "composite_output", admin=True) + test_data_response = self._get(f"tools/{'composite_output'}/test_data_path?filename=../CONTRIBUTORS.md", admin=True) assert test_data_response.status_code == 404, test_data_response.text @skip_without_tool("composite_output") def test_test_data_admin_security(self): - test_data_response = self._get("tools/%s/test_data_path?filename=../CONTRIBUTORS.md" % "composite_output") + test_data_response = self._get(f"tools/{'composite_output'}/test_data_path?filename=../CONTRIBUTORS.md") assert test_data_response.status_code == 403, test_data_response.text @skip_without_tool("dbkey_filter_multi_input") def test_data_table_requirement_annotated(self): - test_data_response = self._get("tools/%s/test_data" % "dbkey_filter_multi_input") + test_data_response = self._get(f"tools/{'dbkey_filter_multi_input'}/test_data") assert test_data_response.status_code == 200 test_case = test_data_response.json()[0] assert test_case['required_data_tables'][0] == 'test_fasta_indexes' @@ -316,7 +316,7 @@ class ToolsTestCase(ApiTestCase, TestsTools): @skip_without_tool("composite_output") def test_test_data_composite_output(self): - test_data_response = self._get("tools/%s/test_data" % "composite_output") + test_data_response = self._get(f"tools/{'composite_output'}/test_data") assert test_data_response.status_code == 200 test_data = test_data_response.json() assert len(test_data) == 1 @@ -327,7 +327,7 @@ class ToolsTestCase(ApiTestCase, TestsTools): @skip_without_tool("collection_two_paired") def test_test_data_collection_two_paired(self): - test_data_response = self._get("tools/%s/test_data" % "collection_two_paired") + test_data_response = self._get(f"tools/{'collection_two_paired'}/test_data") assert test_data_response.status_code == 200 test_data = test_data_response.json() assert len(test_data) == 2 @@ -339,7 +339,7 @@ class ToolsTestCase(ApiTestCase, TestsTools): @skip_without_tool("collection_nested_test") def test_test_data_collection_nested(self): - test_data_response = self._get("tools/%s/test_data" % "collection_nested_test") + test_data_response = self._get(f"tools/{'collection_nested_test'}/test_data") assert test_data_response.status_code == 200 test_data = test_data_response.json() assert len(test_data) == 2 @@ -349,7 +349,7 @@ class ToolsTestCase(ApiTestCase, TestsTools): @skip_without_tool("expression_null_handling_1") def test_test_data_null_boolean_inputs(self): - test_data_response = self._get("tools/%s/test_data" % "expression_null_handling_1") + test_data_response = self._get(f"tools/{'expression_null_handling_1'}/test_data") assert test_data_response.status_code == 200 test_data = test_data_response.json() assert len(test_data) == 3 @@ -362,24 +362,24 @@ class ToolsTestCase(ApiTestCase, TestsTools): @skip_without_tool("simple_constructs_y") def test_test_data_yaml_tools(self): - test_data_response = self._get("tools/%s/test_data" % "simple_constructs_y") + test_data_response = self._get(f"tools/{'simple_constructs_y'}/test_data") assert test_data_response.status_code == 200 test_data = test_data_response.json() assert len(test_data) == 3 @skip_without_tool("cat1") def test_test_data_download(self): - test_data_response = self._get("tools/%s/test_data_download?filename=1.bed" % "cat1") + test_data_response = self._get(f"tools/{'cat1'}/test_data_download?filename=1.bed") assert test_data_response.status_code == 200, test_data_response.text.startswith('chr') @skip_without_tool("composite_output") def test_test_data_downloads_security(self): - test_data_response = self._get("tools/%s/test_data_download?filename=../CONTRIBUTORS.md" % "composite_output") + test_data_response = self._get(f"tools/{'composite_output'}/test_data_download?filename=../CONTRIBUTORS.md") assert test_data_response.status_code == 404, test_data_response.text @skip_without_tool("composite_output") def test_test_data_download_composite(self): - test_data_response = self._get("tools/%s/test_data_download?filename=velveth_test1" % "composite_output") + test_data_response = self._get(f"tools/{'composite_output'}/test_data_download?filename=velveth_test1") assert test_data_response.status_code == 200 with zipfile.ZipFile(BytesIO(test_data_response.content)) as contents: namelist = contents.namelist() @@ -691,7 +691,7 @@ class ToolsTestCase(ApiTestCase, TestsTools): dataset_details = [] for output in [outputs_one, outputs_two, outputs_three]: output_id = output['outputs'][0]['id'] - dataset_details.append(self._get("datasets/%s" % output_id).json()) + dataset_details.append(self._get(f"datasets/{output_id}").json()) filenames = [dd['file_name'] for dd in dataset_details] assert len(filenames) == 3, filenames assert len(set(filenames)) <= 2, filenames @@ -725,13 +725,13 @@ class ToolsTestCase(ApiTestCase, TestsTools): @skip_without_tool("multiple_versions") @uses_test_history(require_new=False) def test_test_by_versions(self, history_id): - test_data_response = self._get("tools/%s/test_data" % "multiple_versions") + test_data_response = self._get(f"tools/{'multiple_versions'}/test_data") test_data_response.raise_for_status() test_data_dicts = test_data_response.json() assert len(test_data_dicts) == 1 assert test_data_dicts[0]["tool_version"] == "0.2" - test_data_response = self._get("tools/%s/test_data?tool_version=*" % "multiple_versions") + test_data_response = self._get(f"tools/{'multiple_versions'}/test_data?tool_version=*") test_data_response.raise_for_status() test_data_dicts = test_data_response.json() assert len(test_data_dicts) == 3 @@ -968,7 +968,7 @@ class ToolsTestCase(ApiTestCase, TestsTools): self.assertEqual(output_collection["name"], "Table split on first column") self.dataset_populator.wait_for_job(create["jobs"][0]["id"], assert_ok=True) - get_collection_response = self._get("dataset_collections/%s" % output_collection["id"], data={"instance_type": "history"}) + get_collection_response = self._get(f"dataset_collections/{output_collection['id']}", data={"instance_type": "history"}) self._assert_status_code_is(get_collection_response, 200) output_collection = get_collection_response.json() @@ -991,7 +991,7 @@ class ToolsTestCase(ApiTestCase, TestsTools): } create = self._run("collection_creates_dynamic_nested", history_id, inputs, assert_ok=False, wait_for_job=True) self._assert_status_code_is(create, 200) - collection = self._get("dataset_collections/%s" % create.json()["output_collections"][0]["id"], data={"instance_type": "history"}).json() + collection = self._get(f"dataset_collections/{create.json()['output_collections'][0]['id']}", data={"instance_type": "history"}).json() assert collection['element_count'] == 3 for nested_collection in collection['elements']: nested_collection = nested_collection['object'] @@ -1527,7 +1527,7 @@ class ToolsTestCase(ApiTestCase, TestsTools): self.assertEqual(implicit_collections[0]['collection_type'], 'list:list:paired') self.assertEqual(implicit_collections[0]['elements'][0]['object']['element_count'], None) self.dataset_populator.wait_for_job(create["jobs"][0]["id"], assert_ok=True) - hdca = self._get("histories/{}/contents/dataset_collections/{}".format(history_id, implicit_collections[0]['id'])).json() + hdca = self._get(f"histories/{history_id}/contents/dataset_collections/{implicit_collections[0]['id']}").json() self.assertEqual(hdca['elements'][0]['object']['elements'][0]['object']['elements'][0]['element_identifier'], 'forward') def _bed_list(self, history_id): @@ -2164,8 +2164,8 @@ class ToolsTestCase(ApiTestCase, TestsTools): hdca1_id = self._build_pair(history_id, ["123\n", "456\n"]) hdca2_id = self.dataset_collection_populator.create_list_in_history(history_id).json()["id"] inputs = { - "f1": "__collection_reduce__|%s" % hdca1_id, - "f2": "__collection_reduce__|%s" % hdca2_id, + "f1": f"__collection_reduce__|{hdca1_id}", + "f2": f"__collection_reduce__|{hdca2_id}", } self._check_simple_reduce_job(history_id, inputs) @@ -2259,7 +2259,7 @@ class ToolsTestCase(ApiTestCase, TestsTools): with self.dataset_populator.test_history() as history_id: hdca1_id = self._build_pair(history_id, ["123\n", "456\n"]) inputs = { - "outer_repeat_0|f1": "__collection_reduce__|%s" % hdca1_id, + "outer_repeat_0|f1": f"__collection_reduce__|{hdca1_id}", } create = self._run("multi_data_repeat", history_id, inputs, assert_ok=True) outputs = create['outputs'] diff --git a/lib/galaxy_test/api/test_tools_upload.py b/lib/galaxy_test/api/test_tools_upload.py index 4c3cc7dcb0a..d94c318aa9d 100644 --- a/lib/galaxy_test/api/test_tools_upload.py +++ b/lib/galaxy_test/api/test_tools_upload.py @@ -770,7 +770,7 @@ class ToolsUploadTestCase(ApiTestCase): def test_upload_from_404_url(self): history_id, new_dataset = self._upload('https://usegalaxy.org/bla123', assert_ok=False) dataset_details = self.dataset_populator.get_history_dataset_details(history_id, dataset_id=new_dataset["id"], assert_ok=False) - assert dataset_details['state'] == 'error', "expected dataset state to be 'error', but got '%s'" % dataset_details['state'] + assert dataset_details['state'] == 'error', f"expected dataset state to be 'error', but got '{dataset_details['state']}'" @skip_if_site_down("https://usegalaxy.org") def test_upload_from_valid_url(self): diff --git a/lib/galaxy_test/api/test_users.py b/lib/galaxy_test/api/test_users.py index ca1796e74d6..e6fbfec6ee4 100644 --- a/lib/galaxy_test/api/test_users.py +++ b/lib/galaxy_test/api/test_users.py @@ -65,14 +65,14 @@ class UsersApiTestCase(ApiTestCase): # non-existent no_user_id = '5d7db0757a2eb7ef' - update_url = self._api_url("users/%s" % (no_user_id), use_key=True) + update_url = self._api_url(f"users/{no_user_id}", use_key=True) update_response = put(update_url, data=json.dumps(dict(username=new_name))) assert_object_id_error(update_response) def test_admin_update(self): new_name = 'flexo' user = self._setup_user(TEST_USER_EMAIL) - update_url = self._api_url("users/%s" % (user["id"]), params=dict(key=self.master_api_key)) + update_url = self._api_url(f"users/{user['id']}", params=dict(key=self.master_api_key)) update_response = put(update_url, data=json.dumps(dict(username=new_name))) self._assert_status_code_is(update_response, 200) update_json = update_response.json() @@ -80,32 +80,32 @@ class UsersApiTestCase(ApiTestCase): def test_delete_user(self): user = self._setup_user(TEST_USER_EMAIL_DELETE) - self._delete("users/%s" % user["id"], admin=True) - updated_user = self._get("users/deleted/%s" % user['id'], admin=True).json() + self._delete(f"users/{user['id']}", admin=True) + updated_user = self._get(f"users/deleted/{user['id']}", admin=True).json() assert updated_user['deleted'] is True, updated_user def test_purge_user(self): """Delete user and then purge them.""" user = self._setup_user(TEST_USER_EMAIL_PURGE) - response = self._delete("users/%s" % user["id"], admin=True) + response = self._delete(f"users/{user['id']}", admin=True) self._assert_status_code_is_ok(response) data = dict(purge="True") - response = self._delete("users/%s" % user["id"], data=data, admin=True) + response = self._delete(f"users/{user['id']}", data=data, admin=True) self._assert_status_code_is_ok(response) payload = {'deleted': "True"} - purged_user = self._get("users/%s" % user['id'], payload, admin=True).json() + purged_user = self._get(f"users/{user['id']}", payload, admin=True).json() assert purged_user['deleted'] is True, purged_user assert purged_user['purged'] is True, purged_user def test_undelete_user(self): """Delete user and then undelete them.""" user = self._setup_user(TEST_USER_EMAIL_UNDELETE) - self._delete("users/%s" % user["id"], admin=True) + self._delete(f"users/{user['id']}", admin=True) payload = {'deleted': "True"} - deleted_user = self._get("users/%s" % user['id'], payload, admin=True).json() + deleted_user = self._get(f"users/{user['id']}", payload, admin=True).json() assert deleted_user['deleted'] is True, deleted_user - self._post("users/deleted/%s/undelete" % user["id"], admin=True) - undeleted_user = self._get("users/%s" % user['id'], admin=True).json() + self._post(f"users/deleted/{user['id']}/undelete", admin=True) + undeleted_user = self._get(f"users/{user['id']}", admin=True).json() assert undeleted_user['deleted'] is False, undeleted_user def test_information(self): @@ -138,32 +138,32 @@ class UsersApiTestCase(ApiTestCase): def test_favorites(self): user = self._setup_user(TEST_USER_EMAIL) # adding a tool to favorites - url = self._api_url("users/%s/favorites/tools" % user["id"], params=dict(key=self.master_api_key)) + url = self._api_url(f"users/{user['id']}/favorites/tools", params=dict(key=self.master_api_key)) put_response = put(url, data=json.dumps({"object_id": "cat1"})) self._assert_status_code_is_ok(put_response) self.assertEqual(put_response.json()["tools"][0], "cat1") # not implemented for workflows yet - url = self._api_url("users/%s/favorites/workflows" % user["id"], params=dict(key=self.master_api_key)) + url = self._api_url(f"users/{user['id']}/favorites/workflows", params=dict(key=self.master_api_key)) put_response = put(url, data=json.dumps({"object_id": "14ds68f4sda68gf46dsag4"})) self._assert_status_code_is(put_response, 400) # delete existing tool favorite - url = self._api_url("users/%s/favorites/tools/cat1" % user["id"], params=dict(key=self.master_api_key)) + url = self._api_url(f"users/{user['id']}/favorites/tools/cat1", params=dict(key=self.master_api_key)) delete_response = delete(url) self._assert_status_code_is_ok(delete_response) self.assertEqual(delete_response.json()["tools"], []) # delete non-existing tool favorite - url = self._api_url("users/%s/favorites/tools/madeuptoolthatdoes/not/exist/in/favs" % user["id"], params=dict(key=self.master_api_key)) + url = self._api_url(f"users/{user['id']}/favorites/tools/madeuptoolthatdoes/not/exist/in/favs", params=dict(key=self.master_api_key)) delete_response = delete(url) self._assert_status_code_is(delete_response, 404) # delete non existing workflow favorite - url = self._api_url("users/%s/favorites/workflows/1as5das5das56d465" % user["id"], params=dict(key=self.master_api_key)) + url = self._api_url(f"users/{user['id']}/favorites/workflows/1as5das5das56d465", params=dict(key=self.master_api_key)) delete_response = delete(url) self._assert_status_code_is(delete_response, 400) @skip_without_tool("cat1") def test_search_favorites(self): user, user_key = self._setup_user_get_key(TEST_USER_EMAIL) - url = self._api_url("users/%s/favorites/tools" % user["id"], params=dict(key=user_key)) + url = self._api_url(f"users/{user['id']}/favorites/tools", params=dict(key=user_key)) fav_response = put(url, data=json.dumps({"object_id": "cat1"})) self._assert_status_code_is_ok(fav_response) assert "cat1" in fav_response.json()["tools"] @@ -172,13 +172,13 @@ class UsersApiTestCase(ApiTestCase): assert "cat1" in search_response def __url(self, action, user): - return self._api_url("users/{}/{}".format(user["id"], action), params=dict(key=self.master_api_key)) + return self._api_url(f"users/{user['id']}/{action}", params=dict(key=self.master_api_key)) def __show(self, user): - return self._get("users/%s" % (user['id'])) + return self._get(f"users/{user['id']}") def __update(self, user, **new_data): - update_url = self._api_url("users/%s" % (user["id"]), use_key=True) + update_url = self._api_url(f"users/{user['id']}", use_key=True) return put(update_url, data=new_data) def __assert_matches_user(self, userA, userB): diff --git a/lib/galaxy_test/api/test_visualizations.py b/lib/galaxy_test/api/test_visualizations.py index 8f25f1049a9..6fc8848346d 100644 --- a/lib/galaxy_test/api/test_visualizations.py +++ b/lib/galaxy_test/api/test_visualizations.py @@ -61,14 +61,14 @@ class VisualizationsApiTestCase(ApiTestCase, SharingApiTests): def test_update_title(self): viz_id, viz = self._create_viz() - update_url = self._api_url("visualizations/%s" % viz_id, use_key=True) + update_url = self._api_url(f"visualizations/{viz_id}", use_key=True) response = put(update_url, {"title": "New Name"}) self._assert_status_code_is(response, 200) updated_viz = self._show_viz(viz_id) assert updated_viz["title"] == "New Name" def _show_viz(self, viz_id, assert_ok=True): - show_response = self._get("visualizations/%s" % viz_id) + show_response = self._get(f"visualizations/{viz_id}") if assert_ok: self._assert_status_code_is(show_response, 200) @@ -83,7 +83,7 @@ class VisualizationsApiTestCase(ApiTestCase, SharingApiTests): uuid_str = str(uuid.uuid4()) title = title if title is not None else 'Test Visualization' - slug = slug if slug is not None else 'test-visualization-%s' % uuid_str + slug = slug if slug is not None else f'test-visualization-{uuid_str}' config = config if config is not None else json.dumps({ "x": 10, "y": 12, diff --git a/lib/galaxy_test/api/test_workflow_extraction.py b/lib/galaxy_test/api/test_workflow_extraction.py index 76946ef3405..7fc6528fc78 100644 --- a/lib/galaxy_test/api/test_workflow_extraction.py +++ b/lib/galaxy_test/api/test_workflow_extraction.py @@ -445,7 +445,7 @@ test_data: def _history_contents(self, history_id=None): if history_id is None: history_id = self.history_id - return self._get("histories/%s/contents" % history_id).json() + return self._get(f"histories/{history_id}/contents").json() def __copy_content_to_history(self, history_id, content): if content["history_content_type"] == "dataset": @@ -453,14 +453,14 @@ test_data: source="hda", content=content["id"] ) - response = self._post("histories/%s/contents/datasets" % history_id, payload) + response = self._post(f"histories/{history_id}/contents/datasets", payload) else: payload = dict( source="hdca", content=content["id"] ) - response = self._post("histories/%s/contents/dataset_collections" % history_id, payload) + response = self._post(f"histories/{history_id}/contents/dataset_collections", payload) self._assert_status_code_is(response, 200) return response.json() @@ -546,7 +546,7 @@ test_data: self._assert_status_code_is(create_workflow_response, 200) new_workflow_id = create_workflow_response.json()["id"] - download_response = self._get("workflows/%s/download" % new_workflow_id) + download_response = self._get(f"workflows/{new_workflow_id}/download") self._assert_status_code_is(download_response, 200) downloaded_workflow = download_response.json() return downloaded_workflow diff --git a/lib/galaxy_test/api/test_workflows.py b/lib/galaxy_test/api/test_workflows.py index 271d41966d1..a45856c5745 100644 --- a/lib/galaxy_test/api/test_workflows.py +++ b/lib/galaxy_test/api/test_workflows.py @@ -127,7 +127,7 @@ class BaseWorkflowsApiTestCase(ApiTestCase): hda1 = self.dataset_populator.new_dataset(history_id, content="1 2 3") hda2 = self.dataset_populator.new_dataset(history_id, content="4 5 6") workflow_request = dict( - history="hist_id=%s" % history_id, + history=f"hist_id={history_id}", workflow_id=workflow_id, ) label_map = { @@ -171,7 +171,7 @@ class BaseWorkflowsApiTestCase(ApiTestCase): return self.dataset_populator.ds_entry(history_content) def _workflow_inputs(self, uploaded_workflow_id): - workflow_show_resposne = self._get("workflows/%s" % uploaded_workflow_id) + workflow_show_resposne = self._get(f"workflows/{uploaded_workflow_id}") self._assert_status_code_is(workflow_show_resposne, 200) workflow_inputs = workflow_show_resposne.json()["inputs"] return workflow_inputs @@ -257,13 +257,13 @@ class WorkflowsApiTestCase(BaseWorkflowsApiTestCase, ChangeDatatypeTestCase): def test_show_valid(self): workflow_id = self.workflow_populator.simple_workflow("dummy") workflow_id = self.workflow_populator.simple_workflow("test_regular") - show_response = self._get("workflows/%s" % workflow_id, {"style": "instance"}) + show_response = self._get(f"workflows/{workflow_id}", {"style": "instance"}) workflow = show_response.json() self._assert_looks_like_instance_workflow_representation(workflow) assert len(workflow["steps"]) == 3 self.assertEqual(sorted(step["id"] for step in workflow["steps"].values()), [0, 1, 2]) - show_response = self._get("workflows/%s" % workflow_id, {"legacy": True}) + show_response = self._get(f"workflows/{workflow_id}", {"legacy": True}) workflow = show_response.json() self._assert_looks_like_instance_workflow_representation(workflow) assert len(workflow["steps"]) == 3 @@ -272,17 +272,17 @@ class WorkflowsApiTestCase(BaseWorkflowsApiTestCase, ChangeDatatypeTestCase): self.assertNotEqual(sorted(step["id"] for step in workflow["steps"].values()), [0, 1, 2]) def test_show_invalid_key_is_400(self): - show_response = self._get("workflows/%s" % self._random_key()) + show_response = self._get(f"workflows/{self._random_key()}") self._assert_status_code_is(show_response, 400) def test_cannot_show_private_workflow(self): workflow_id = self.workflow_populator.simple_workflow("test_not_importable") with self._different_user(): - show_response = self._get("workflows/%s" % workflow_id) + show_response = self._get(f"workflows/{workflow_id}") self._assert_status_code_is(show_response, 403) # Try as anonymous user - workflows_url = self._api_url("workflows/%s" % workflow_id) + workflows_url = self._api_url(f"workflows/{workflow_id}") assert get(workflows_url).status_code == 403 def test_cannot_download_private_workflow(self): @@ -291,12 +291,12 @@ class WorkflowsApiTestCase(BaseWorkflowsApiTestCase, ChangeDatatypeTestCase): with pytest.raises(AssertionError) as excinfo: self._download_workflow(workflow_id) assert '403' in str(excinfo.value) - workflows_url = self._api_url("workflows/%s/download" % workflow_id) + workflows_url = self._api_url(f"workflows/{workflow_id}/download") assert get(workflows_url).status_code == 403 def test_anon_can_download_public_workflow(self): workflow_id = self.workflow_populator.simple_workflow("test_downloadable", publish=True) - workflows_url = self._api_url("workflows/%s/download" % workflow_id) + workflows_url = self._api_url(f"workflows/{workflow_id}/download") response = get(workflows_url) response.raise_for_status() assert response.json()['a_galaxy_workflow'] == 'true' @@ -305,7 +305,7 @@ class WorkflowsApiTestCase(BaseWorkflowsApiTestCase, ChangeDatatypeTestCase): workflow_id = self.workflow_populator.simple_workflow("test_delete") workflow_name = "test_delete" self._assert_user_has_workflow_with_name(workflow_name) - workflow_url = self._api_url("workflows/%s" % workflow_id, use_key=True) + workflow_url = self._api_url(f"workflows/{workflow_id}", use_key=True) delete_response = delete(workflow_url) self._assert_status_code_is(delete_response, 200) # Make sure workflow is no longer in index by default. @@ -314,7 +314,7 @@ class WorkflowsApiTestCase(BaseWorkflowsApiTestCase, ChangeDatatypeTestCase): def test_other_cannot_delete(self): workflow_id = self.workflow_populator.simple_workflow("test_other_delete") with self._different_user(): - workflow_url = self._api_url("workflows/%s" % workflow_id, use_key=True) + workflow_url = self._api_url(f"workflows/{workflow_id}", use_key=True) delete_response = delete(workflow_url) self._assert_status_code_is(delete_response, 403) @@ -327,7 +327,7 @@ class WorkflowsApiTestCase(BaseWorkflowsApiTestCase, ChangeDatatypeTestCase): workflow_id = self.workflow_populator.simple_workflow("test_delete") workflow_index = self._get("workflows").json() assert [w for w in workflow_index if w['id'] == workflow_id] - workflow_url = self._api_url("workflows/%s" % workflow_id, use_key=True) + workflow_url = self._api_url(f"workflows/{workflow_id}", use_key=True) delete_response = delete(workflow_url) self._assert_status_code_is(delete_response, 200) workflow_index = self._get("workflows").json() @@ -408,7 +408,7 @@ class WorkflowsApiTestCase(BaseWorkflowsApiTestCase, ChangeDatatypeTestCase): uuid = str(uuid4()) step_dict["uuid"] = uuid uuids[order_index] = uuid - label = "label_%s" % order_index + label = f"label_{order_index}" step_dict["label"] = label labels[order_index] = label @@ -621,7 +621,7 @@ test_data: workflow_id = self._upload_yaml_workflow(WORKFLOW_NESTED_SIMPLE, publish=True) subworkflow_content_id = get_subworkflow_content_id(workflow_id) - instance_response = self._get("workflows/%s?instance=true" % subworkflow_content_id) + instance_response = self._get(f"workflows/{subworkflow_content_id}?instance=true") self._assert_status_code_is(instance_response, 200) subworkflow = instance_response.json() assert subworkflow['inputs']['0']['label'] == 'inner_input' @@ -1141,7 +1141,7 @@ steps: self._run_jobs(WORKFLOW_WITH_DYNAMIC_OUTPUT_COLLECTION, history_id=history_id, assert_ok=True, wait=True) details = self.dataset_populator.get_history_dataset_details(history_id, hid=0) last_item_hid = details["hid"] - assert last_item_hid == 7, "Expected 7 history items, got %s" % last_item_hid + assert last_item_hid == 7, f"Expected 7 history items, got {last_item_hid}" content = self.dataset_populator.get_history_dataset_content(history_id, hid=0) self.assertEqual("10.0\n30.0\n20.0\n40.0\n", content) @@ -1430,7 +1430,7 @@ test_data: @skip_without_tool("random_lines1") def test_run_runtime_parameters_after_pause(self): with self.dataset_populator.test_history() as history_id: - workflow_run_description = """%s + workflow_run_description = f"""{WORKFLOW_RUNTIME_PARAMETER_AFTER_PAUSE} test_data: step_parameters: @@ -1439,7 +1439,7 @@ test_data: input1: value: 1.bed type: File -""" % WORKFLOW_RUNTIME_PARAMETER_AFTER_PAUSE +""" job_summary = self._run_jobs(workflow_run_description, history_id=history_id, wait=False) uploaded_workflow_id, invocation_id = job_summary.workflow_id, job_summary.invocation_id @@ -1568,7 +1568,7 @@ test_data: - identifier: samp1 content: "0\n1" """, history_id=history_id) - history = self._get('histories/%s/contents' % history_id).json() + history = self._get(f'histories/{history_id}/contents').json() flattened_collection = history[-1] assert flattened_collection['history_content_type'] == 'dataset_collection' assert flattened_collection['collection_type'] == 'list' @@ -1626,7 +1626,7 @@ steps: report_config = downloaded_workflow["report"] assert "markdown" in report_config report_json = self.workflow_populator.workflow_report_json(workflow_id, invocation_id) - assert "markdown" in report_json, "markdown not in report json %s" % report_json + assert "markdown" in report_json, f"markdown not in report json {report_json}" self._assert_has_keys(report_json, "markdown", "render_format") assert report_json["render_format"] == "markdown" markdown_content = report_json["markdown"] @@ -1699,7 +1699,7 @@ input_c: def test_workflow_request(self): workflow = self.workflow_populator.load_workflow(name="test_for_queue") workflow_request, history_id = self._setup_workflow_run(workflow) - url = "workflows/%s/usage" % (workflow_request["workflow_id"]) + url = f"workflows/{workflow_request['workflow_id']}/usage" del workflow_request["workflow_id"] run_workflow_response = self._post(url, data=workflow_request) @@ -2272,7 +2272,7 @@ input1: # is not complete. self._assert_invocation_non_terminal(uploaded_workflow_id, invocation_id) - self._delete("histories/%s" % history_id) + self._delete(f"histories/{history_id}") invocation_cancelled = self._wait_for_invocation_state(uploaded_workflow_id, invocation_id, 'cancelled') assert invocation_cancelled, "Workflow state is not cancelled..." @@ -2292,7 +2292,7 @@ input1: # is not complete. self._assert_invocation_non_terminal(uploaded_workflow_id, invocation_id) - self._delete("histories/%s" % history_id) + self._delete(f"histories/{history_id}") invocation_cancelled = self._wait_for_invocation_state(uploaded_workflow_id, invocation_id, 'cancelled') assert invocation_cancelled, "Workflow state is not cancelled..." @@ -2434,7 +2434,7 @@ steps: r = self._delete(f"histories/{history_id}/contents/{deleted_id}?purge={purge}") label_map = {"input1": self._ds_entry(hdca1)} workflow_request = dict( - history="hist_id=%s" % history_id, + history=f"hist_id={history_id}", workflow_id=workflow_id, ds_map=self._build_ds_map(workflow_id, label_map), ) @@ -2815,15 +2815,15 @@ steps: new_ds_map = json.loads(new_workflow_request['ds_map']) for key, input_values in run_workflow_response['inputs'].items(): copy_payload = {"content": input_values['id'], "source": "hda", "type": "dataset"} - copy_response = self._post("histories/%s/contents" % history_id_two, data=copy_payload).json() + copy_response = self._post(f"histories/{history_id_two}/contents", data=copy_payload).json() new_ds_map[key]['id'] = copy_response['id'] new_workflow_request['ds_map'] = json.dumps(new_ds_map, sort_keys=True) - new_workflow_request['history'] = "hist_id=%s" % history_id_two + new_workflow_request['history'] = f"hist_id={history_id_two}" new_workflow_request['use_cached_job'] = True # We run the workflow again, it should not produce any new outputs new_workflow_response = self._post("workflows", data=new_workflow_request).json() - first_wf_output = self._get("datasets/%s" % run_workflow_response['outputs'][0]).json() - second_wf_output = self._get("datasets/%s" % new_workflow_response['outputs'][0]).json() + first_wf_output = self._get(f"datasets/{run_workflow_response['outputs'][0]}").json() + second_wf_output = self._get(f"datasets/{new_workflow_response['outputs'][0]}").json() assert first_wf_output['file_name'] == second_wf_output['file_name'], \ f"first output:\n{first_wf_output}\nsecond output:\n{second_wf_output}" @@ -2842,7 +2842,7 @@ outer_input: dataset_type = inputs['outer_input']['src'] dataset_id = inputs['outer_input']['id'] copy_payload = {"content": dataset_id, "source": dataset_type, "type": "dataset"} - copy_response = self._post("histories/%s/contents" % history_id_two, data=copy_payload) + copy_response = self._post(f"histories/{history_id_two}/contents", data=copy_payload) self._assert_status_code_is(copy_response, 200) new_dataset_id = copy_response.json()['id'] inputs['outer_input']['id'] = new_dataset_id @@ -2883,7 +2883,7 @@ outer_input: workflow_request, history_id = self._setup_workflow_run(workflow) with self._different_user(): other_history_id = self.dataset_populator.new_history() - workflow_request["history"] = "hist_id=%s" % other_history_id + workflow_request["history"] = f"hist_id={other_history_id}" run_workflow_response = self._post("workflows", data=workflow_request) self._assert_status_code_is(run_workflow_response, 403) @@ -2898,7 +2898,7 @@ outer_input: self.dataset_populator.wait_for_history(history_id, assert_ok=True) label_map = {"list1": self._ds_entry(hdca1), "list2": self._ds_entry(hdca2)} workflow_request = dict( - history="hist_id=%s" % history_id, + history=f"hist_id={history_id}", workflow_id=workflow_id, ds_map=self._build_ds_map(workflow_id, label_map), ) @@ -3311,7 +3311,7 @@ input1: assert_ok=True) unpaused_dataset = self.dataset_populator.get_history_dataset_details(history_id, wait=True, assert_ok=False) assert unpaused_dataset['state'] == 'ok' - assert unpaused_dataset['name'] == "%s suffix" % name + assert unpaused_dataset['name'] == f"{name} suffix" @skip_without_tool("cat") def test_run_rename_based_on_input_recursive(self): @@ -3904,7 +3904,7 @@ steps: "parameters_normalized": True, "parameters": dumps(parameters), } - invocation_response = self._post("workflows/%s/usage" % workflow_id, data=workflow_request) + invocation_response = self._post(f"workflows/{workflow_id}/usage", data=workflow_request) self._assert_status_code_is(invocation_response, 200) time.sleep(5) self.dataset_populator.wait_for_history(history_id, assert_ok=True) @@ -3948,7 +3948,7 @@ steps: "parameters_normalized": True, "parameters": dumps(parameters), } - invocation_response = self._post("workflows/%s/usage" % workflow_id, data=workflow_request) + invocation_response = self._post(f"workflows/{workflow_id}/usage", data=workflow_request) self._assert_status_code_is(invocation_response, 200) time.sleep(5) self.dataset_populator.wait_for_history(history_id, assert_ok=True) @@ -3986,10 +3986,10 @@ steps: - text: "abd" """) workflow_request = dict( - history="hist_id=%s" % history_id, + history=f"hist_id={history_id}", parameters=dumps(dict(validation_repeat={"r2_0|text": ""})) ) - url = "workflows/%s/invocations" % workflow_id + url = f"workflows/{workflow_id}/invocations" invocation_response = self._post(url, data=workflow_request) # Take a valid stat and make it invalid, assert workflow won't run. self._assert_status_code_is(invocation_response, 400) @@ -4019,7 +4019,7 @@ steps: uploaded_workflow_id = self.workflow_populator.create_workflow(workflow) history_id = self.dataset_populator.new_history() workflow_request = dict( - history="hist_id=%s" % history_id, + history=f"hist_id={history_id}", workflow_id=uploaded_workflow_id, parameters=dumps(dict(validation_default=substitions)) ) @@ -4147,9 +4147,9 @@ input: def test_only_own_invocations_indexed_and_accessible(self): workflow_id, usage = self._run_workflow_once_get_invocation("test_usage") with self._different_user(): - usage_details_response = self._get("workflows/{}/usage/{}".format(workflow_id, usage["id"])) + usage_details_response = self._get(f"workflows/{workflow_id}/usage/{usage['id']}") self._assert_status_code_is(usage_details_response, 403) - index_response = self._get("workflows/%s/invocations" % workflow_id) + index_response = self._get(f"workflows/{workflow_id}/invocations") self._assert_status_code_is(index_response, 200) assert len(index_response.json()) == 0 @@ -4282,7 +4282,7 @@ input_c: self._assert_status_code_is(other_import_response, 200) other_id = other_import_response.json()["id"] workflow_request, history_id = self._setup_workflow_run(workflow_id=other_id) - response = self._get("workflows/%s/usage" % other_id) + response = self._get(f"workflows/{other_id}/usage") self._assert_status_code_is(response, 200) assert len(response.json()) == 0 run_workflow_response = self._post("workflows", data=workflow_request) @@ -4298,7 +4298,7 @@ input_c: with self._different_user(): workflow_request, history_id = self._setup_workflow_run(workflow_id=workflow_id) workflow_request['workflow_id'] = workflow_request.pop('workflow_id') - response = self._get("workflows/%s/usage" % workflow_id) + response = self._get(f"workflows/{workflow_id}/usage") self._assert_status_code_is(response, 200) assert len(response.json()) == 0 run_workflow_response = self._post("workflows", data=workflow_request) @@ -4313,7 +4313,7 @@ input_c: workflow_id = self.workflow_populator.simple_workflow("test_usage", publish=True) workflow_request, history_id = self._setup_workflow_run(workflow_id=workflow_id) workflow_request['workflow_id'] = workflow_request.pop('workflow_id') - response = self._get("workflows/%s/usage" % workflow_id) + response = self._get(f"workflows/{workflow_id}/usage") self._assert_status_code_is(response, 200) assert len(response.json()) == 0 run_workflow_response = self._post("workflows", data=workflow_request) @@ -4397,13 +4397,13 @@ input_c: workflow = self.workflow_populator.load_workflow(name=name) workflow_request, history_id = self._setup_workflow_run(workflow) workflow_id = workflow_request["workflow_id"] - response = self._get("workflows/%s/usage" % workflow_id) + response = self._get(f"workflows/{workflow_id}/usage") self._assert_status_code_is(response, 200) assert len(response.json()) == 0 run_workflow_response = self._post("workflows", data=workflow_request) self._assert_status_code_is(run_workflow_response, 200) - response = self._get("workflows/%s/usage" % workflow_id) + response = self._get(f"workflows/{workflow_id}/usage") self._assert_status_code_is(response, 200) usages = response.json() assert len(usages) == 1 @@ -4415,7 +4415,7 @@ input_c: return workflow_request, history_id, random_line_steps def _random_lines_steps(self, workflow_request): - workflow_summary_response = self._get("workflows/%s" % workflow_request["workflow_id"]) + workflow_summary_response = self._get(f"workflows/{workflow_request['workflow_id']}") self._assert_status_code_is(workflow_summary_response, 200) steps = workflow_summary_response.json()["steps"] return sorted((step for step in steps.values() if step["tool_id"] == "random_lines1"), key=lambda step: step["id"]) @@ -4429,7 +4429,7 @@ input_c: ten_lines = "\n".join(str(_) for _ in range(10)) hda1 = self.dataset_populator.new_dataset(history_id, content=ten_lines) workflow_request = dict( - history="hist_id=%s" % history_id, + history=f"hist_id={history_id}", workflow_id=uploaded_workflow_id, ds_map=dumps({ key: self._ds_entry(hda1), @@ -4447,15 +4447,15 @@ input_c: self._execute_invocation_step_action(uploaded_workflow_id, invocation_id, pause_step_id, action=action) def __assert_lines_hid_line_count_is(self, history, hid, lines): - contents_url = "histories/%s/contents" % history + contents_url = f"histories/{history}/contents" history_contents = self.__history_contents(history) hda_summary = next(hc for hc in history_contents if hc["hid"] == hid) - hda_info_response = self._get("{}/{}".format(contents_url, hda_summary["id"])) + hda_info_response = self._get(f"{contents_url}/{hda_summary['id']}") self._assert_status_code_is(hda_info_response, 200) self.assertEqual(hda_info_response.json()["metadata_data_lines"], lines) def __history_contents(self, history_id): - contents_url = "histories/%s/contents" % history_id + contents_url = f"histories/{history_id}/contents" history_contents_response = self._get(contents_url) self._assert_status_code_is(history_contents_response, 200) return history_contents_response.json() @@ -4477,7 +4477,7 @@ input_c: return self._post(route, import_data) def _show_workflow(self, workflow_id): - show_response = self._get("workflows/%s" % workflow_id) + show_response = self._get(f"workflows/{workflow_id}") self._assert_status_code_is(show_response, 200) return show_response.json() diff --git a/lib/galaxy_test/api/test_workflows_from_yaml.py b/lib/galaxy_test/api/test_workflows_from_yaml.py index 28a4453bc45..c5c3a3ed404 100644 --- a/lib/galaxy_test/api/test_workflows_from_yaml.py +++ b/lib/galaxy_test/api/test_workflows_from_yaml.py @@ -72,7 +72,7 @@ input1: "hello world" def test_outputs(self): workflow_id = self._upload_yaml_workflow(WORKFLOW_WITH_OUTPUTS, round_trip_format_conversion=True) - workflow = self._get("workflows/%s/download" % workflow_id).json() + workflow = self._get(f"workflows/{workflow_id}/download").json() self.assertEqual(workflow["steps"]["1"]["workflow_outputs"][0]["output_name"], "out_file1") self.assertEqual(workflow["steps"]["1"]["workflow_outputs"][0]["label"], "wf_output_1") workflow = self.workflow_populator.download_workflow(workflow_id, style="format2") @@ -135,7 +135,7 @@ steps: assert subworkflow_connection["input_subworkflow_step_id"] == 0 workflow_reupload_id = self.import_workflow(workflow)["id"] - workflow_reupload = self._get("workflows/%s/download" % workflow_reupload_id).json() + workflow_reupload = self._get(f"workflows/{workflow_reupload_id}/download").json() by_label = self._steps_by_label(workflow_reupload) subworkflow_step = by_label["nested_workflow"] assert subworkflow_step["type"] == "subworkflow" diff --git a/lib/galaxy_test/base/api.py b/lib/galaxy_test/base/api.py index f7a3ec5565b..0bc30bc2604 100644 --- a/lib/galaxy_test/base/api.py +++ b/lib/galaxy_test/base/api.py @@ -25,7 +25,7 @@ class UsesApiTestCaseMixin: if os.environ.get('GALAXY_TEST_EXTERNAL') is None: # Only kill running jobs after test for managed test instances for job in self.galaxy_interactor.get('jobs?state=running&?user_details=true').json(): - self._delete("jobs/%s" % job['id']) + self._delete(f"jobs/{job['id']}") def _api_url(self, path, params=None, use_key=None, use_admin_key=None): if not params: @@ -56,7 +56,7 @@ class UsesApiTestCaseMixin: def _setup_user_get_key(self, email, password=None, is_admin=True): user = self._setup_user(email, password, is_admin) - return user, self._post("users/%s/api_key" % user["id"], admin=True).json() + return user, self._post(f"users/{user['id']}/api_key", admin=True).json() @contextmanager def _different_user(self, email=OTHER_USER): diff --git a/lib/galaxy_test/base/populators.py b/lib/galaxy_test/base/populators.py index 2aeaa4f57e5..601404508ad 100644 --- a/lib/galaxy_test/base/populators.py +++ b/lib/galaxy_test/base/populators.py @@ -239,7 +239,7 @@ class BaseDatasetPopulator(BasePopulator): :returns: the HDA id of the new object """ run_response = self.new_dataset_request(history_id, content=content, wait=wait, **kwds) - assert run_response.status_code == 200, "Failed to create new dataset with response: %s" % run_response.text + assert run_response.status_code == 200, f"Failed to create new dataset with response: {run_response.text}" return run_response.json()["outputs"][0] def new_dataset_request(self, history_id: str, content=None, wait: bool = False, **kwds) -> requests.Response: @@ -281,7 +281,7 @@ class BaseDatasetPopulator(BasePopulator): def wait_for_history(self, history_id: str, assert_ok: bool = False, timeout: timeout_type = DEFAULT_TIMEOUT) -> str: try: - return wait_on_state(lambda: self._get("histories/%s" % history_id), desc="history state", assert_ok=assert_ok, timeout=timeout) + return wait_on_state(lambda: self._get(f"histories/{history_id}"), desc="history state", assert_ok=assert_ok, timeout=timeout) except AssertionError: self._summarize_history(history_id) raise @@ -328,7 +328,7 @@ class BaseDatasetPopulator(BasePopulator): return active_jobs def cancel_job(self, job_id: str) -> Response: - return self._delete("jobs/%s" % job_id) + return self._delete(f"jobs/{job_id}") def delete_history(self, history_id: str) -> None: delete_response = self._delete(f"histories/{history_id}") @@ -370,12 +370,12 @@ class BaseDatasetPopulator(BasePopulator): return list_response.json() def show_dynamic_tool(self, uuid) -> dict: - show_response = self._get("dynamic_tools/%s" % uuid, admin=True) + show_response = self._get(f"dynamic_tools/{uuid}", admin=True) assert show_response.status_code == 200, show_response return show_response.json() def deactivate_dynamic_tool(self, uuid) -> dict: - delete_response = self._delete("dynamic_tools/%s" % uuid, admin=True) + delete_response = self._delete(f"dynamic_tools/{uuid}", admin=True) return delete_response.json() def _summarize_history(self, history_id: str) -> None: @@ -488,7 +488,7 @@ class BaseDatasetPopulator(BasePopulator): data["filename"] = filename if raw: data['raw'] = True - display_response = self._get_contents_request(history_id, "/%s/display" % dataset_id, data=data) + display_response = self._get_contents_request(history_id, f"/{dataset_id}/display", data=data) assert display_response.status_code == 200, display_response.text if type == 'text': return display_response.text @@ -507,13 +507,13 @@ class BaseDatasetPopulator(BasePopulator): def get_history_dataset_extra_files(self, history_id: str, **kwds) -> list: dataset_id = self.__history_content_id(history_id, **kwds) - details_response = self._get_contents_request(history_id, "/%s/extra_files" % dataset_id) + details_response = self._get_contents_request(history_id, f"/{dataset_id}/extra_files") assert details_response.status_code == 200, details_response.content return details_response.json() def get_history_collection_details(self, history_id: str, **kwds) -> dict: hdca_id = self.__history_content_id(history_id, **kwds) - details_response = self._get_contents_request(history_id, "/dataset_collections/%s" % hdca_id) + details_response = self._get_contents_request(history_id, f"/dataset_collections/{hdca_id}") assert details_response.status_code == 200, details_response.content return details_response.json() @@ -562,7 +562,7 @@ class BaseDatasetPopulator(BasePopulator): def _get_contents_request(self, history_id: str, suffix: str = "", data=None) -> Response: if data is None: data = {} - url = "histories/%s/contents" % history_id + url = f"histories/{history_id}/contents" if suffix: url = f"{url}{suffix}" return self._get(url, data=data) @@ -668,7 +668,7 @@ class BaseDatasetPopulator(BasePopulator): return history_id def prepare_export(self, history_id, data): - url = "histories/%s/exports" % history_id + url = f"histories/{history_id}/exports" put_response = self._put(url, data) put_response.raise_for_status() @@ -716,7 +716,7 @@ class BaseDatasetPopulator(BasePopulator): def history_names(): return {h["name"]: h for h in self.get_histories()} - import_name = "imported from archive: %s" % history_name + import_name = f"imported from archive: {history_name}" assert import_name not in history_names() self.import_history(import_data) @@ -731,7 +731,7 @@ class BaseDatasetPopulator(BasePopulator): return imported_history_id def rename_history(self, history_id, new_name): - update_url = "histories/%s" % history_id + update_url = f"histories/{history_id}" put_response = self._put(update_url, {"name": new_name}) return put_response @@ -749,7 +749,7 @@ class BaseDatasetPopulator(BasePopulator): wait_on(history_has_length, desc="import history population") def history_length(self, history_id): - contents_response = self._get("histories/%s/contents" % history_id) + contents_response = self._get(f"histories/{history_id}/contents") api_asserts.assert_status_code_is(contents_response, 200) contents = contents_response.json() return len(contents) @@ -836,7 +836,7 @@ class BaseWorkflowPopulator(BasePopulator): def load_workflow_from_resource(self, name: str, filename: Optional[str] = None) -> dict: if filename is None: - filename = "data/%s.ga" % name + filename = f"data/{name}.ga" content = unicodify(resource_string(__name__, filename)) return self.load_workflow(name, content=content) @@ -899,7 +899,7 @@ class BaseWorkflowPopulator(BasePopulator): if len(invocations) == expected_invocation_count: return True - wait_on(invocation_count, "%s history invocations" % expected_invocation_count) + wait_on(invocation_count, f"{expected_invocation_count} history invocations") for invocation in self.history_invocations(history_id): workflow_id = invocation["workflow_id"] invocation_id = invocation["id"] @@ -912,12 +912,12 @@ class BaseWorkflowPopulator(BasePopulator): self.dataset_populator.wait_for_history_jobs(history_id, assert_ok=assert_ok, timeout=timeout) def get_invocation(self, invocation_id): - r = self._get("invocations/%s" % invocation_id) + r = self._get(f"invocations/{invocation_id}") r.raise_for_status() return r.json() def get_biocompute_object(self, invocation_id): - bco_response = self._get("invocations/%s/biocompute" % invocation_id) + bco_response = self._get(f"invocations/{invocation_id}/biocompute") bco_response.raise_for_status() return bco_response.json() @@ -932,7 +932,7 @@ class BaseWorkflowPopulator(BasePopulator): api_asserts.assert_has_keys(bco['io_domain'], "input_subdomain", "output_subdomain") def invoke_workflow_raw(self, workflow_id, request: dict) -> Response: - url = "workflows/%s/usage" % (workflow_id) + url = f"workflows/{workflow_id}/usage" invocation_response = self._post(url, data=request) return invocation_response @@ -943,7 +943,7 @@ class BaseWorkflowPopulator(BasePopulator): if request is None: request = {} - request["history"] = "hist_id=%s" % history_id, + request["history"] = f"hist_id={history_id}", if inputs: request["inputs"] = json.dumps(inputs) request["inputs_by"] = 'step_index' @@ -966,7 +966,7 @@ class BaseWorkflowPopulator(BasePopulator): params["style"] = style if history_id is not None: params['history_id'] = history_id - response = self._get("workflows/%s/download" % workflow_id, data=params) + response = self._get(f"workflows/{workflow_id}/download", data=params) api_asserts.assert_status_code_is(response, 200) if style != "format2": return response.json() @@ -977,7 +977,7 @@ class BaseWorkflowPopulator(BasePopulator): data = dict( workflow=workflow_object ) - raw_url = 'workflows/%s' % workflow_id + raw_url = f'workflows/{workflow_id}' put_response = self._put(raw_url, json.dumps(data)) return put_response @@ -989,7 +989,7 @@ class BaseWorkflowPopulator(BasePopulator): data["style"] = style if dry_run is not None: data["dry_run"] = dry_run - raw_url = 'workflows/%s/refactor' % workflow_id + raw_url = f'workflows/{workflow_id}/refactor' put_response = self._put(raw_url, json.dumps(data)) return put_response @@ -1030,7 +1030,7 @@ class BaseWorkflowPopulator(BasePopulator): history_id = self.dataset_populator.new_history() inputs, label_map, has_uploads = load_data_dict(history_id, test_data, self.dataset_populator, self.dataset_collection_populator) workflow_request = dict( - history="hist_id=%s" % history_id, + history=f"hist_id={history_id}", workflow_id=workflow_id, ) workflow_request["inputs"] = json.dumps(label_map) @@ -1180,10 +1180,10 @@ class WorkflowPopulator(GalaxyInteractorHttpMixin, BaseWorkflowPopulator, Import for i in range(workflow_depth): step = i + 2 if step % 2 == 1: - step_dict = {"tool_id": "cat_list", "state": {"input1": self._link("step_%s" % (step - 1), "output")}} + step_dict = {"tool_id": "cat_list", "state": {"input1": self._link(f"step_{step - 1}", "output")}} else: - step_dict = {"tool_id": "split", "state": {"input1": self._link("step_%s" % (step - 1), "out_file1")}} - step_dict["label"] = "step_%s" % (step,) + step_dict = {"tool_id": "split", "state": {"input1": self._link(f"step_{step - 1}", "out_file1")}} + step_dict["label"] = f"step_{step}" scale_workflow_steps.append(step_dict) workflow_dict = { @@ -1235,7 +1235,7 @@ class LibraryPopulator: LIBRARY_ADD_in=perm_list, LIBRARY_MANAGE_in=perm_list, ) - response = self.galaxy_interactor.post("libraries/%s/permissions" % library_id, data=permissions, admin=True) + response = self.galaxy_interactor.post(f"libraries/{library_id}/permissions", data=permissions, admin=True) api_asserts.assert_status_code_is(response, 200) def user_email(self): @@ -1280,7 +1280,7 @@ class LibraryPopulator: def wait_on_library_dataset(self, library, dataset): def show(): - return self.galaxy_interactor.get("libraries/{}/contents/{}".format(library["id"], dataset["id"])) + return self.galaxy_interactor.get(f"libraries/{library['id']}/contents/{dataset['id']}") wait_on_state(show, assert_ok=True, timeout=DEFAULT_TIMEOUT) return show().json() @@ -1289,7 +1289,7 @@ class LibraryPopulator: if files is None: files = {} - url_rel = "libraries/%s/contents" % library_id + url_rel = f"libraries/{library_id}/contents" return self.galaxy_interactor.post(url_rel, payload, files=files) def show_ldda(self, library_id, library_dataset_id): @@ -1298,7 +1298,7 @@ class LibraryPopulator: def new_library_dataset_in_private_library(self, library_name="private_dataset", wait=True): library = self.new_private_library(library_name) payload, files = self.create_dataset_request(library, file_type="txt", contents="create_test") - create_response = self.galaxy_interactor.post("libraries/%s/contents" % library["id"], payload, files=files) + create_response = self.galaxy_interactor.post(f"libraries/{library['id']}/contents", payload, files=files) api_asserts.assert_status_code_is(create_response, 200) library_datasets = create_response.json() assert len(library_datasets) == 1 @@ -1313,7 +1313,7 @@ class LibraryPopulator: return library, library_dataset def get_library_contents_with_path(self, library_id, path): - all_contents_response = self.galaxy_interactor.get("libraries/%s/contents" % library_id) + all_contents_response = self.galaxy_interactor.get(f"libraries/{library_id}/contents") api_asserts.assert_status_code_is(all_contents_response, 200) all_contents = all_contents_response.json() matching = [c for c in all_contents if c["name"] == path] @@ -1363,7 +1363,7 @@ class BaseDatasetCollectionPopulator: def create_nested_collection(self, history_id, collection_type, name=None, collection=None, element_identifiers=None): """Create a nested collection either from collection or using collection_type).""" assert collection_type is not None - name = name or "Test %s" % collection_type + name = name or f"Test {collection_type}" if collection is not None: assert element_identifiers is None element_identifiers = [] @@ -1459,7 +1459,7 @@ class BaseDatasetCollectionPopulator: elif collection_type == "list": contents = ["TestData123", "TestData123", "TestData123"] else: - raise Exception("Unknown collection_type %s" % collection_type) + raise Exception(f"Unknown collection_type {collection_type}") if isinstance(contents, list): for i, contents_level in enumerate(contents): @@ -1676,7 +1676,7 @@ def load_data_dict(history_id, test_data, dataset_populator, dataset_collection_ label_map[key] = dataset_populator.ds_entry(hda) inputs[key] = hda else: - raise ValueError("Invalid test_data def %s" % test_data) + raise ValueError(f"Invalid test_data def {test_data}") return inputs, label_map, has_uploads @@ -1701,13 +1701,13 @@ def stage_rules_example(galaxy_interactor, history_id, example): def wait_on_state(state_func: Callable, desc="state", skip_states=None, ok_states=None, assert_ok=False, timeout=DEFAULT_TIMEOUT) -> str: def get_state(): response = state_func() - assert response.status_code == 200, "Failed to fetch state update while waiting. [%s]" % response.content + assert response.status_code == 200, f"Failed to fetch state update while waiting. [{response.content}]" state = response.json()["state"] if state in skip_states: return None else: if assert_ok: - assert state in ok_states, "Final state - %s - not okay." % state + assert state in ok_states, f"Final state - {state} - not okay." return state if skip_states is None: diff --git a/lib/galaxy_test/driver/driver_util.py b/lib/galaxy_test/driver/driver_util.py index 573a9c6a1e7..86156f838b9 100644 --- a/lib/galaxy_test/driver/driver_util.py +++ b/lib/galaxy_test/driver/driver_util.py @@ -261,7 +261,7 @@ def setup_galaxy_config( if default_shed_tool_data_table_config: config["shed_tool_data_table_config"] = default_shed_tool_data_table_config if not use_shared_connection_for_amqp: - config["amqp_internal_connection"] = "sqlalchemy+sqlite:///%s?isolation_level=IMMEDIATE" % os.path.join(tmpdir, "control.sqlite") + config["amqp_internal_connection"] = f"sqlalchemy+sqlite:///{os.path.join(tmpdir, 'control.sqlite')}?isolation_level=IMMEDIATE" config.update(database_conf(tmpdir, prefer_template_database=prefer_template_database)) config.update(install_database_conf(tmpdir, default_merged=default_install_db_merged)) @@ -381,14 +381,14 @@ def copy_database_template(source, db_path): # do all migration steps instead of downloading a template. log.exception(e) else: - raise Exception("Failed to copy database template from source %s" % source) + raise Exception(f"Failed to copy database template from source {source}") def database_conf(db_path, prefix="GALAXY", prefer_template_database=False): """Find (and populate if needed) Galaxy database connection.""" database_auto_migrate = False check_migrate_databases = True - dburi_var = "%s_TEST_DBURI" % prefix + dburi_var = f"{prefix}_TEST_DBURI" template_name = None if dburi_var in os.environ: database_connection = os.environ[dburi_var] @@ -398,7 +398,7 @@ def database_conf(db_path, prefix="GALAXY", prefer_template_database=False): database_template_parsed = urlparse(database_connection) template_name = database_template_parsed.path[1:] # drop / from /galaxy actual_db = "gxtest" + ''.join(random.choice(string.ascii_uppercase) for _ in range(10)) - actual_database_parsed = database_template_parsed._replace(path="/%s" % actual_db) + actual_database_parsed = database_template_parsed._replace(path=f"/{actual_db}") database_connection = actual_database_parsed.geturl() if not database_exists(database_connection): # We pass by migrations and instantiate the current table @@ -407,8 +407,8 @@ def database_conf(db_path, prefix="GALAXY", prefer_template_database=False): toolshed_mapping.init(database_connection, create_tables=True) check_migrate_databases = False else: - default_db_filename = "%s.sqlite" % prefix.lower() - template_var = "%s_TEST_DB_TEMPLATE" % prefix + default_db_filename = f"{prefix.lower()}.sqlite" + template_var = f"{prefix}_TEST_DB_TEMPLATE" db_path = os.path.join(db_path, default_db_filename) if template_var in os.environ: # Middle ground between recreating a completely new @@ -418,7 +418,7 @@ def database_conf(db_path, prefix="GALAXY", prefer_template_database=False): # cases (namely tool shed tests expecting clean database). copy_database_template(os.environ[template_var], db_path) database_auto_migrate = True - database_connection = 'sqlite:///%s' % db_path + database_connection = f'sqlite:///{db_path}' config = { "check_migrate_databases": check_migrate_databases, "database_connection": database_connection, @@ -439,7 +439,7 @@ def install_database_conf(db_path, default_merged=False): install_galaxy_database_connection = None else: install_galaxy_db_path = os.path.join(db_path, 'install.sqlite') - install_galaxy_database_connection = 'sqlite:///%s' % install_galaxy_db_path + install_galaxy_database_connection = f'sqlite:///{install_galaxy_db_path}' conf = {} if install_galaxy_database_connection is not None: conf["install_database_connection"] = install_galaxy_database_connection @@ -452,7 +452,7 @@ def database_files_path(test_tmpdir, prefix="GALAXY"): Use prefix to default this if TOOL_SHED_TEST_DBPATH or GALAXY_TEST_DBPATH is set in the environment. """ - environ_var = "%s_TEST_DBPATH" % prefix + environ_var = f"{prefix}_TEST_DBPATH" if environ_var in os.environ: db_path = os.environ[environ_var] else: @@ -528,7 +528,7 @@ def attempt_ports(port): if port is not None: return port - raise Exception("An existing process seems bound to specified test server port [%s]" % port) + raise Exception(f"An existing process seems bound to specified test server port [{port}]") else: random.seed() for _ in range(0, 9): @@ -538,7 +538,7 @@ def attempt_ports(port): os.environ['GALAXY_WEB_PORT'] = port return port - raise Exception("Unable to open a port between {} and {} to start Galaxy server".format(8000, 10000)) + raise Exception(f"Unable to open a port between {8000} and {10000} to start Galaxy server") def serve_webapp(webapp, port=None, host=None): @@ -586,7 +586,7 @@ def cleanup_directory(tempdir): """ skip_cleanup = "GALAXY_TEST_NO_CLEANUP" in os.environ or "TOOL_SHED_TEST_NO_CLEANUP" in os.environ if skip_cleanup: - log.info("GALAXY_TEST_NO_CLEANUP is on. Temporary files in %s" % tempdir) + log.info(f"GALAXY_TEST_NO_CLEANUP is on. Temporary files in {tempdir}") return try: if os.path.exists(tempdir) and not skip_cleanup: @@ -669,9 +669,9 @@ def build_shed_app(simple_kwargs): def explicitly_configured_host_and_port(prefix, config_object): - host_env_key = "%s_TEST_HOST" % prefix - port_env_key = "%s_TEST_PORT" % prefix - port_random_env_key = "%s_TEST_PORT_RANDOM" % prefix + host_env_key = f"{prefix}_TEST_HOST" + port_env_key = f"{prefix}_TEST_PORT" + port_random_env_key = f"{prefix}_TEST_PORT_RANDOM" default_web_host = getattr(config_object, "default_web_host", DEFAULT_WEB_HOST) host = os.environ.get(host_env_key, default_web_host) @@ -693,8 +693,8 @@ def explicitly_configured_host_and_port(prefix, config_object): def set_and_wait_for_http_target(prefix, host, port, sleep_amount=0.1, sleep_tries=150): - host_env_key = "%s_TEST_HOST" % prefix - port_env_key = "%s_TEST_PORT" % prefix + host_env_key = f"{prefix}_TEST_HOST" + port_env_key = f"{prefix}_TEST_PORT" os.environ[host_env_key] = host os.environ[port_env_key] = port wait_for_http_server(host, port, sleep_amount=sleep_amount, sleep_tries=sleep_tries) @@ -728,19 +728,19 @@ class EmbeddedServerWrapper(ServerWrapper): def stop(self): if self._server is not None and hasattr(self._server, "server_close"): - log.info("Shutting down embedded %s Paste server" % self.name) + log.info(f"Shutting down embedded {self.name} Paste server") self._server.server_close() - log.info("Embedded web server %s stopped" % self.name) + log.info(f"Embedded web server {self.name} stopped") if self._server is not None and hasattr(self._server, "shutdown"): - log.info("Shutting down embedded %s uvicorn server" % self.name) + log.info(f"Shutting down embedded {self.name} uvicorn server") self._server.should_exit = True - log.info("Embedded web server %s stopped" % self.name) + log.info(f"Embedded web server {self.name} stopped") if self._app is not None: - log.info("Stopping application %s" % self.name) + log.info(f"Stopping application {self.name}") self._app.shutdown() - log.info("Application %s stopped." % self.name) + log.info(f"Application {self.name} stopped.") class UwsgiServerWrapper(ServerWrapper): @@ -1091,7 +1091,7 @@ class GalaxyTestDriver(TestDriver): log.info(f"Functional tests will be run against external Galaxy server {server_wrapper.host}:{server_wrapper.port}") self.server_wrappers.append(server_wrapper) else: - log.info("Functional tests will be run against test managed Galaxy server %s" % self.external_galaxy) + log.info(f"Functional tests will be run against test managed Galaxy server {self.external_galaxy}") # Ensure test file directory setup even though galaxy config isn't built. ensure_test_file_dir_set() diff --git a/lib/galaxy_test/driver/integration_util.py b/lib/galaxy_test/driver/integration_util.py index b22d72b5855..376e20274af 100644 --- a/lib/galaxy_test/driver/integration_util.py +++ b/lib/galaxy_test/driver/integration_util.py @@ -46,7 +46,7 @@ def skip_unless_postgres(): def skip_unless_executable(executable): if which(executable): return _identity - return pytest.mark.skip("PATH doesn't contain executable %s" % executable) + return pytest.mark.skip(f"PATH doesn't contain executable {executable}") def skip_unless_docker(): diff --git a/lib/galaxy_test/selenium/framework.py b/lib/galaxy_test/selenium/framework.py index 9afda2e3853..5a4d5dfda42 100644 --- a/lib/galaxy_test/selenium/framework.py +++ b/lib/galaxy_test/selenium/framework.py @@ -94,7 +94,7 @@ def managed_history(f): try: current_history_id = self.current_history_id() self.dataset_populator.cancel_history_jobs(current_history_id) - self.api_delete("histories/%s" % current_history_id) + self.api_delete(f"histories/{current_history_id}") except Exception: print("Faild to cleanup managed history, selenium connection corrupted somehow?") return func_wrapper @@ -130,8 +130,8 @@ def dump_test_information(self, name_prefix): try: full_log = self.driver.get_log(log_type) trimmed_log = [entry for entry in full_log if entry["level"] not in ["DEBUG", "INFO"]] - write_file("%s.log.json" % log_type, json.dumps(trimmed_log, indent=True)) - write_file("%s.log.verbose.json" % log_type, json.dumps(full_log, indent=True)) + write_file(f"{log_type}.log.json", json.dumps(trimmed_log, indent=True)) + write_file(f"{log_type}.log.verbose.json", json.dumps(full_log, indent=True)) except Exception: continue @@ -177,9 +177,9 @@ class TestSnapshot: def write_to_error_directory(self, write_file_func): prefix = "%d-%s" % (self.index, self.description) - write_file_func("%s-screenshot.png" % prefix, self.screenshot_binary, raw=True) - write_file_func("%s-traceback.txt" % prefix, self.exc) - write_file_func("%s-stack.txt" % prefix, str(self.stack)) + write_file_func(f"{prefix}-screenshot.png", self.screenshot_binary, raw=True) + write_file_func(f"{prefix}-traceback.txt", self.exc) + write_file_func(f"{prefix}-stack.txt", str(self.stack)) class GalaxyTestSeleniumContext(GalaxySeleniumContext): @@ -327,7 +327,7 @@ class TestWithSeleniumMixin(GalaxyTestSeleniumContext, UsesApiTestCaseMixin): self.driver.close() except Exception as e: if "cannot kill Chrome" in str(e): - print("Ignoring likely harmless error in Selenium shutdown %s" % e) + print(f"Ignoring likely harmless error in Selenium shutdown {e}") else: exception = e @@ -385,7 +385,7 @@ class TestWithSeleniumMixin(GalaxyTestSeleniumContext, UsesApiTestCaseMixin): """ visualization_names = self.history_panel_item_available_visualizations(hid) if visualization_name not in visualization_names: - raise unittest.SkipTest("Skipping test, visualization [%s] doesn't appear to be configured." % visualization_name) + raise unittest.SkipTest(f"Skipping test, visualization [{visualization_name}] doesn't appear to be configured.") class SeleniumTestCase(FunctionalTestCase, TestWithSeleniumMixin): diff --git a/lib/galaxy_test/selenium/test_admin_app.py b/lib/galaxy_test/selenium/test_admin_app.py index b9471709398..6dace7b4899 100644 --- a/lib/galaxy_test/selenium/test_admin_app.py +++ b/lib/galaxy_test/selenium/test_admin_app.py @@ -58,7 +58,7 @@ class AdminAppTestCase(SeleniumTestCase): # This serves as a check for the presence of the upgrade notification. admin_component.toolshed.upgrade_notification.wait_for_visible() self.screenshot('admin_toolshed_repo_installed') - repository_row = self.driver.find_element_by_xpath("//div[contains(text(), '%s')]/.." % repository_name) + repository_row = self.driver.find_element_by_xpath(f"//div[contains(text(), '{repository_name}')]/..") repository_row.click() self.sleep_for(self.wait_types.UX_TRANSITION) self.screenshot('admin_toolshed_installed_only') diff --git a/lib/galaxy_test/selenium/test_custom_builds.py b/lib/galaxy_test/selenium/test_custom_builds.py index 8cdd994417a..83096309266 100644 --- a/lib/galaxy_test/selenium/test_custom_builds.py +++ b/lib/galaxy_test/selenium/test_custom_builds.py @@ -69,7 +69,7 @@ class CustomBuildsTestcase(SharedStateSeleniumTestCase): break if delete_button is None: - raise AssertionError('Failed to find custom build with name [%s]' % build_name) + raise AssertionError(f'Failed to find custom build with name [{build_name}]') delete_button.click() diff --git a/lib/galaxy_test/selenium/test_histories_list.py b/lib/galaxy_test/selenium/test_histories_list.py index 0cd9848c8ce..ee276a4fa89 100644 --- a/lib/galaxy_test/selenium/test_histories_list.py +++ b/lib/galaxy_test/selenium/test_histories_list.py @@ -286,8 +286,7 @@ class SavedHistoriesTestCase(SharedStateSeleniumTestCase): self.history_panel_create_new_with_name(name) def select_filter(self, filter_key, filter_value): - filter_selector = 'a[filter_key="%s"][filter_val="%s"]' % \ - (filter_key, filter_value) + filter_selector = f'a[filter_key="{filter_key}"][filter_val="{filter_value}"]' self.wait_for_and_click_selector(filter_selector) def get_history_tags_cell(self, history_name): @@ -300,7 +299,7 @@ class SavedHistoriesTestCase(SharedStateSeleniumTestCase): break if tags_cell is None: - raise AssertionError('Failed to find history with name [%s]' % history_name) + raise AssertionError(f'Failed to find history with name [{history_name}]') return tags_cell diff --git a/lib/galaxy_test/selenium/test_history_dataset_state.py b/lib/galaxy_test/selenium/test_history_dataset_state.py index af1b38f56e7..40ee3ee8900 100644 --- a/lib/galaxy_test/selenium/test_history_dataset_state.py +++ b/lib/galaxy_test/selenium/test_history_dataset_state.py @@ -80,10 +80,10 @@ class HistoryDatasetStateTestCase(SeleniumTestCase, UsesHistoryItemAssertions): # ensure old tooltip expired, # no tooltip appeared before the 1st element if i > 0: - previous_button = item_button["%s_button" % expected_buttons[i - 1]].wait_for_visible() + previous_button = item_button[f"{expected_buttons[i - 1]}_button"].wait_for_visible() if previous_button.get_attribute("aria-describedby") is not None: # wait for tooltip to disappear self.components._.tooltip_balloon.wait_for_absent() - button = item_button["%s_button" % expected_button] + button = item_button[f"{expected_button}_button"] self.assert_tooltip_text(button.wait_for_visible(), BUTTON_TOOLTIPS[expected_button]) diff --git a/lib/galaxy_test/selenium/test_history_sharing.py b/lib/galaxy_test/selenium/test_history_sharing.py index bcd784b746e..07498f6cfc2 100644 --- a/lib/galaxy_test/selenium/test_history_sharing.py +++ b/lib/galaxy_test/selenium/test_history_sharing.py @@ -13,14 +13,14 @@ class HistorySharingTestCase(SeleniumTestCase): def test_sharing_valid(self): user1_email, user2_email, history_id = self.setup_two_users_with_one_shared_history() self.submit_login(user2_email, retries=VALID_LOGIN_RETRIES) - response = self.api_get("histories/%s" % history_id, raw=True) + response = self.api_get(f"histories/{history_id}", raw=True) assert response.status_code == 200, response.text @selenium_test def test_sharing_valid_by_id(self): user1_email, user2_email, history_id = self.setup_two_users_with_one_shared_history(share_by_id=True) self.submit_login(user2_email, retries=VALID_LOGIN_RETRIES) - response = self.api_get("histories/%s" % history_id, raw=True) + response = self.api_get(f"histories/{history_id}", raw=True) assert response.status_code == 200, response.text @selenium_test @@ -37,7 +37,7 @@ class HistorySharingTestCase(SeleniumTestCase): self.logout_if_needed() self.submit_login(user2_email, retries=VALID_LOGIN_RETRIES) - response = self.api_get("histories/%s" % history_id, raw=True) + response = self.api_get(f"histories/{history_id}", raw=True) assert response.status_code == 403 @selenium_test @@ -51,7 +51,7 @@ class HistorySharingTestCase(SeleniumTestCase): self.logout_if_needed() self.register(user2_email) - response = self.api_get("histories/%s" % history_id, raw=True) + response = self.api_get(f"histories/{history_id}", raw=True) assert response.status_code == 403 @selenium_test @@ -120,5 +120,5 @@ class HistorySharingTestCase(SeleniumTestCase): if assert_valid: self.assert_no_error_message() - xpath = '//td[contains(text(), "%s")]' % user_email + xpath = f'//td[contains(text(), "{user_email}")]' self.wait_for_xpath_visible(xpath) diff --git a/lib/galaxy_test/selenium/test_jupyter.py b/lib/galaxy_test/selenium/test_jupyter.py index 5d1e0d7ae42..b0d12c1312a 100644 --- a/lib/galaxy_test/selenium/test_jupyter.py +++ b/lib/galaxy_test/selenium/test_jupyter.py @@ -50,7 +50,7 @@ class JupyterTestCase(SeleniumTestCase): cell_li = li_link break if cell_li is None: - raise Exception("Failed to find 'Cell' drop down menu, found menu options %s" % found_li_texts) + raise Exception(f"Failed to find 'Cell' drop down menu, found menu options {found_li_texts}") cell_li.click() self.wait_for_and_click_selector("ul#cell_menu li#run_all_cells") finally: diff --git a/lib/galaxy_test/selenium/test_library_contents.py b/lib/galaxy_test/selenium/test_library_contents.py index a9d5251f588..f908412353d 100644 --- a/lib/galaxy_test/selenium/test_library_contents.py +++ b/lib/galaxy_test/selenium/test_library_contents.py @@ -33,7 +33,7 @@ class LibraryContentsTestCase(SeleniumTestCase, UsesLibraryAssertions): self.assert_num_displayed_items_is(1) # check empty folder - new_folder_link = self.wait_for_xpath_visible('//a[contains(text(), "%s")]' % sub_folder_name) + new_folder_link = self.wait_for_xpath_visible(f'//a[contains(text(), "{sub_folder_name}")]') new_folder_link.click() # assert that 'empty folder message' is present diff --git a/lib/galaxy_test/selenium/test_published_histories_grid.py b/lib/galaxy_test/selenium/test_published_histories_grid.py index b191c52cde5..b59d00f385e 100644 --- a/lib/galaxy_test/selenium/test_published_histories_grid.py +++ b/lib/galaxy_test/selenium/test_published_histories_grid.py @@ -93,7 +93,7 @@ class HistoryGridTestCase(SharedStateSeleniumTestCase): break if tags is None: - raise AssertionError('Failed to find history with name [%s]' % self.history1_name) + raise AssertionError(f'Failed to find history with name [{self.history1_name}]') tag_button_selector = 'div.tag-name' tag_buttons = tags.find_elements_by_css_selector(tag_button_selector) diff --git a/lib/galaxy_test/selenium/test_tool_form.py b/lib/galaxy_test/selenium/test_tool_form.py index e9bbcf16976..fd851bbf9c0 100644 --- a/lib/galaxy_test/selenium/test_tool_form.py +++ b/lib/galaxy_test/selenium/test_tool_form.py @@ -366,7 +366,7 @@ https://raw.githubusercontent.com/jmchilton/galaxy/apply_rules_tutorials/test-da def _tool_apply_with_source(self, rules_json, hid=None, landing_screenshot=None, rule_init_screenshot=None, rule_complete_screenshot=None): self._tool_open_apply_rules() if hid: - self.tool_set_value("input", "%s:" % hid, expected_type="data_collection") + self.tool_set_value("input", f"{hid}:", expected_type="data_collection") if landing_screenshot: self.screenshot(landing_screenshot) rule_builder = self.components.rule_builder diff --git a/lib/galaxy_test/selenium/test_workflow_run.py b/lib/galaxy_test/selenium/test_workflow_run.py index cb4b22d8cec..8ba08357afc 100644 --- a/lib/galaxy_test/selenium/test_workflow_run.py +++ b/lib/galaxy_test/selenium/test_workflow_run.py @@ -195,7 +195,7 @@ steps: self.workflow_populator.wait_for_history_workflows(history_id, expected_invocation_count=1) invocation_0 = self.workflow_populator.history_invocations(history_id)[0] - self.get("workflows/invocations/report?id=%s" % invocation_0["id"]) + self.get(f"workflows/invocations/report?id={invocation_0['id']}") self.wait_for_selector_visible(".embedded-dataset") self.screenshot("workflow_report_custom_1") diff --git a/lib/tool_shed/dependencies/attribute_handlers.py b/lib/tool_shed/dependencies/attribute_handlers.py index a8deaaf6f60..871534746a9 100644 --- a/lib/tool_shed/dependencies/attribute_handlers.py +++ b/lib/tool_shed/dependencies/attribute_handlers.py @@ -41,7 +41,7 @@ class RepositoryDependencyAttributeHandler: # altered, new_elem, error_message = self.handle_elem(elem) if error_message: - error_message += ' The %s file contains an invalid tag.' % TOOL_DEPENDENCY_DEFINITION_FILENAME + error_message += f' The {TOOL_DEPENDENCY_DEFINITION_FILENAME} file contains an invalid tag.' return altered, new_elem, error_message def handle_elem(self, elem): @@ -116,9 +116,9 @@ class RepositoryDependencyAttributeHandler: else: error_message = 'Invalid latest installable changeset_revision %s ' % \ str(lastest_installable_changeset_revision) - error_message += 'retrieved for repository {} owned by {}. '.format(str(name), str(owner)) + error_message += f'retrieved for repository {str(name)} owned by {str(owner)}. ' else: - error_message = 'Unable to locate repository with name {} and owner {}. '.format(str(name), str(owner)) + error_message = f'Unable to locate repository with name {str(name)} and owner {str(owner)}. ' return altered, elem, error_message def handle_sub_elem(self, parent_elem, elem_index, elem): diff --git a/lib/tool_shed/dependencies/repository/relation_builder.py b/lib/tool_shed/dependencies/repository/relation_builder.py index 4411d8612d5..46ba3d6677b 100644 --- a/lib/tool_shed/dependencies/repository/relation_builder.py +++ b/lib/tool_shed/dependencies/repository/relation_builder.py @@ -225,7 +225,7 @@ class RelationBuilder: rd_only_if_compiling_contained_td = 'False' message = "The revision %s defined for repository %s owned by %s is invalid, so repository " % \ (str(rd_changeset_revision), str(rd_name), str(rd_owner)) - message += "dependencies defined for repository %s will be ignored." % str(repository_name) + message += f"dependencies defined for repository {str(repository_name)} will be ignored." log.debug(message) else: repository_components_tuple = container_util.get_components_from_key(key) @@ -233,7 +233,7 @@ class RelationBuilder: toolshed, repository_name, repository_owner, repository_changeset_revision = components_list[0:4] message = "The revision %s defined for repository %s owned by %s is invalid, so repository " % \ (str(rd_changeset_revision), str(rd_name), str(rd_owner)) - message += "dependencies defined for repository %s will be ignored." % str(repository_name) + message += f"dependencies defined for repository {str(repository_name)} will be ignored." log.debug(message) return updated_key_rd_dicts diff --git a/lib/tool_shed/galaxy_install/dependency_display.py b/lib/tool_shed/galaxy_install/dependency_display.py index 46139ee1350..b7b610cb6de 100644 --- a/lib/tool_shed/galaxy_install/dependency_display.py +++ b/lib/tool_shed/galaxy_install/dependency_display.py @@ -70,7 +70,7 @@ class DependencyDisplayer: only_if_compiling_contained_td, error = \ common_util.parse_repository_dependency_tuple(repository_dependency_tup, contains_error=True) if error: - message += '%s ' % str(error) + message += f'{str(error)} ' else: # The complete dependency hierarchy could not be determined for a repository being installed into # Galaxy. This is likely due to invalid repository dependency definitions, so we'll get them from @@ -113,7 +113,7 @@ class DependencyDisplayer: for requirement_dict in invalid_tool_dependencies.values(): error = requirement_dict.get('error', None) if error: - message = '%s ' % str(error) + message = f'{str(error)} ' return message def generate_message_for_orphan_tool_dependencies(self, repository, metadata_dict): @@ -322,7 +322,7 @@ class DependencyDisplayer: tool_dependencies_root_folder.folders.append(tool_dependencies_folder) new_containers_dict['tool_dependencies'] = tool_dependencies_root_folder except Exception as e: - log.debug("Exception in merge_containers_dicts_for_new_install: %s" % str(e)) + log.debug(f"Exception in merge_containers_dicts_for_new_install: {str(e)}") finally: lock.release() return new_containers_dict diff --git a/lib/tool_shed/galaxy_install/grids/admin_toolshed_grids.py b/lib/tool_shed/galaxy_install/grids/admin_toolshed_grids.py index c0af8ad72c1..d080a795921 100644 --- a/lib/tool_shed/galaxy_install/grids/admin_toolshed_grids.py +++ b/lib/tool_shed/galaxy_install/grids/admin_toolshed_grids.py @@ -14,7 +14,7 @@ def generate_deprecated_repository_img_str(include_mouse_over=False): deprecated_tip_str = 'class="icon-button" title="This repository is deprecated in the Tool Shed"' else: deprecated_tip_str = '' - return ''.format(url_for('/static'), deprecated_tip_str) + return f"" def generate_includes_workflows_img_str(include_mouse_over=False): @@ -22,7 +22,7 @@ def generate_includes_workflows_img_str(include_mouse_over=False): deprecated_tip_str = 'class="icon-button" title="This repository contains exported workflows"' else: deprecated_tip_str = '' - return ''.format(url_for('/static'), deprecated_tip_str) + return f"" def generate_latest_revision_img_str(include_mouse_over=False): @@ -30,7 +30,7 @@ def generate_latest_revision_img_str(include_mouse_over=False): latest_revision_tip_str = 'class="icon-button" title="This is the latest installable revision of this repository"' else: latest_revision_tip_str = '' - return ''.format(url_for('/static'), latest_revision_tip_str) + return f"" def generate_revision_updates_img_str(include_mouse_over=False): @@ -38,7 +38,7 @@ def generate_revision_updates_img_str(include_mouse_over=False): revision_updates_tip_str = 'class="icon-button" title="Updates are available in the Tool Shed for this revision"' else: revision_updates_tip_str = '' - return ''.format(url_for('/static'), revision_updates_tip_str) + return f"" def generate_revision_upgrades_img_str(include_mouse_over=False): @@ -46,7 +46,7 @@ def generate_revision_upgrades_img_str(include_mouse_over=False): revision_upgrades_tip_str = 'class="icon-button" title="A newer installable revision is available for this repository"' else: revision_upgrades_tip_str = '' - return ''.format(url_for('/static'), revision_upgrades_tip_str) + return f"" def generate_unknown_img_str(include_mouse_over=False): @@ -54,7 +54,7 @@ def generate_unknown_img_str(include_mouse_over=False): unknown_tip_str = 'class="icon-button" title="Unable to get information from the Tool Shed"' else: unknown_tip_str = '' - return ''.format(url_for('/static'), unknown_tip_str) + return f"" class InstalledRepositoryGrid(grids.Grid): @@ -211,10 +211,10 @@ class InstalledRepositoryGrid(grids.Grid): @property def legend(self): - legend_str = '%s  Updates are available in the Tool Shed for this revision
    ' % generate_revision_updates_img_str() - legend_str += '%s  A newer installable revision is available for this repository
    ' % generate_revision_upgrades_img_str() - legend_str += '%s  This is the latest installable revision of this repository
    ' % generate_latest_revision_img_str() - legend_str += '%s  This repository is deprecated in the Tool Shed
    ' % generate_deprecated_repository_img_str() - legend_str += '%s  This repository contains exported workflows
    ' % generate_includes_workflows_img_str() - legend_str += '%s  Unable to get information from the Tool Shed
    ' % generate_unknown_img_str() + legend_str = f'{generate_revision_updates_img_str()}  Updates are available in the Tool Shed for this revision
    ' + legend_str += f'{generate_revision_upgrades_img_str()}  A newer installable revision is available for this repository
    ' + legend_str += f'{generate_latest_revision_img_str()}  This is the latest installable revision of this repository
    ' + legend_str += f'{generate_deprecated_repository_img_str()}  This repository is deprecated in the Tool Shed
    ' + legend_str += f'{generate_includes_workflows_img_str()}  This repository contains exported workflows
    ' + legend_str += f'{generate_unknown_img_str()}  Unable to get information from the Tool Shed
    ' return legend_str diff --git a/lib/tool_shed/galaxy_install/utility_containers/__init__.py b/lib/tool_shed/galaxy_install/utility_containers/__init__.py index 745503ed71c..da1547cdd80 100644 --- a/lib/tool_shed/galaxy_install/utility_containers/__init__.py +++ b/lib/tool_shed/galaxy_install/utility_containers/__init__.py @@ -138,7 +138,7 @@ class GalaxyUtilityContainerManager(utility_container_manager.UtilityContainerMa label='Invalid Data Managers') containers_dict['invalid_data_managers'] = invalid_data_managers_root_folder except Exception as e: - log.debug("Exception in build_repository_containers: %s" % str(e)) + log.debug(f"Exception in build_repository_containers: {str(e)}") finally: lock.release() return containers_dict diff --git a/lib/tool_shed/grids/repository_grid_filter_manager.py b/lib/tool_shed/grids/repository_grid_filter_manager.py index 4c3caae5fdc..5b07feb863e 100644 --- a/lib/tool_shed/grids/repository_grid_filter_manager.py +++ b/lib/tool_shed/grids/repository_grid_filter_manager.py @@ -17,15 +17,15 @@ class RepositoryGridFilterManager: def get_grid_title(self, trans, trailing_string='', default=''): filter = self.get_filter(trans) if filter == self.filters.CERTIFIED_LEVEL_ONE: - return "Certified 1 Repositories %s" % trailing_string + return f"Certified 1 Repositories {trailing_string}" if filter == self.filters.CERTIFIED_LEVEL_TWO: - return "Certified 2 Repositories %s" % trailing_string + return f"Certified 2 Repositories {trailing_string}" if filter == self.filters.CERTIFIED_LEVEL_ONE_SUITES: - return "Certified 1 Repository Suites %s" % trailing_string + return f"Certified 1 Repository Suites {trailing_string}" if filter == self.filters.CERTIFIED_LEVEL_TWO_SUITES: - return "Certified 2 Repository Suites %s" % trailing_string + return f"Certified 2 Repository Suites {trailing_string}" if filter == self.filters.SUITES: - return "Repository Suites %s" % trailing_string + return f"Repository Suites {trailing_string}" return f"{default} {trailing_string}" def get_filter(self, trans): diff --git a/lib/tool_shed/grids/repository_grids.py b/lib/tool_shed/grids/repository_grids.py index 9c5573d67fb..501e6e8cb33 100644 --- a/lib/tool_shed/grids/repository_grids.py +++ b/lib/tool_shed/grids/repository_grids.py @@ -88,7 +88,7 @@ class RepositoryGrid(grids.Grid): else: heads_str = '' for ctx in heads: - heads_str += '%s
    ' % hg_util.get_revision_label_from_ctx(ctx, include_date=True) + heads_str += f'{hg_util.get_revision_label_from_ctx(ctx, include_date=True)}
    ' heads_str.rstrip('
    ') if multiple_heads: heads_str += '' @@ -104,15 +104,15 @@ class RepositoryGrid(grids.Grid): # A repository's metadata revisions may not all be installable, as some may contain only invalid tools. select_field = grids_util.build_changeset_revision_select_field(trans, repository, downloadable=False) if len(select_field.options) > 1: - tmpl = "" for o in select_field.options: - tmpl += "".format(o[1], o[0]) + tmpl += f"" tmpl += "" return tmpl elif len(select_field.options) == 1: option_items = select_field.options[0][0] rev_label, rev_date = option_items.split(' ') - rev_date = '%s' % rev_date + rev_date = f'{rev_date}' return f'{rev_label} {rev_date}' return '' @@ -986,8 +986,8 @@ class RepositoryDependenciesGrid(RepositoryMetadataGrid): required_repository_id, updated_changeset_revision) required_repository_metadata_id = trans.security.encode_id(required_repository_metadata.id) - rd_line += '' % (required_repository_metadata_id) - rd_line += 'Repository {} revision {} owned by {}'.format(escape_html(name), escape_html(owner), escape_html(changeset_revision)) + rd_line += f'' + rd_line += f'Repository {escape_html(name)} revision {escape_html(owner)} owned by {escape_html(changeset_revision)}' if required_repository: rd_line += '' rd_str.append(rd_line) @@ -1048,8 +1048,8 @@ class DatatypesGrid(RepositoryMetadataGrid): sorted_datatype_tups = sorted(datatype_tups, key=lambda datatype_tup: datatype_tup[0]) for datatype_tup in sorted_datatype_tups: extension, datatype = datatype_tup[:2] - datatype_str = '' % trans.security.encode_id(repository_metadata.id) - datatype_str += '{}: {}'.format(escape_html(extension), escape_html(datatype)) + datatype_str = f'' + datatype_str += f'{escape_html(extension)}: {escape_html(datatype)}' datatype_str += '' datatype_list.append(datatype_str) return '
    '.join(datatype_list) @@ -1106,7 +1106,7 @@ class ToolDependenciesGrid(RepositoryMetadataGrid): env_dicts = tds_dict['set_environment'] num_env_dicts = len(env_dicts) if num_env_dicts > 0: - td_str += '' % trans.security.encode_id(repository_metadata.id) + td_str += f'' td_str += 'environment: ' td_str += ', '.join(escape_html(env_dict['name']) for env_dict in env_dicts) td_str += '
    ' @@ -1117,8 +1117,8 @@ class ToolDependenciesGrid(RepositoryMetadataGrid): # Example: {"name": "bwa", "type": "package", "version": "0.5.9"} name = td_dict['name'] version = td_dict['version'] - td_str += '' % trans.security.encode_id(repository_metadata.id) - td_str += '{} version {}'.format(escape_html(name), escape_html(version)) + td_str += f'' + td_str += f'{escape_html(name)} version {escape_html(version)}' td_str += '' if index < num_keys - 1: td_str += '
    ' @@ -1178,8 +1178,8 @@ class ToolsGrid(RepositoryMetadataGrid): sorted_tool_tups = sorted(tool_tups, key=lambda tool_tup: tool_tup[0]) for tool_tup in sorted_tool_tups: tool_id, version = tool_tup[:2] - tool_str = '' % trans.security.encode_id(repository_metadata.id) - tool_str += '{}: {}'.format(escape_html(tool_id), escape_html(version)) + tool_str = f'' + tool_str += f'{escape_html(tool_id)}: {escape_html(version)}' tool_str += '' tool_line.append(tool_str) return '
    '.join(tool_line) @@ -1287,9 +1287,9 @@ class ValidRepositoryGrid(RepositoryGrid): """Display a SelectField whose options are the changeset_revision strings of all download-able revisions of this repository.""" select_field = grids_util.build_changeset_revision_select_field(trans, repository, downloadable=True) if len(select_field.options) > 1: - tmpl = "" for o in select_field.options: - tmpl += "".format(o[1], o[0]) + tmpl += f"" tmpl += "" return tmpl elif len(select_field.options) == 1: diff --git a/lib/tool_shed/grids/repository_review_grids.py b/lib/tool_shed/grids/repository_review_grids.py index 419ce91b560..ecac55216b5 100644 --- a/lib/tool_shed/grids/repository_review_grids.py +++ b/lib/tool_shed/grids/repository_review_grids.py @@ -86,8 +86,8 @@ class RepositoriesWithReviewsGrid(RepositoryGrid): rval = '' if repository.reviewers: for user in repository.reviewers: - rval += '' % trans.security.encode_id(user.id) - rval += '%s | ' % user.username + rval += f'' + rval += f'{user.username} | ' if rval[-3:] == ' | ': rval = rval[:-3] return rval @@ -100,11 +100,11 @@ class RepositoriesWithReviewsGrid(RepositoryGrid): if review.rating: for index in range(1, 6): rval += ' (index - 0.5) and review.rating < (index + 0.5): rval += 'checked="checked" ' rval += '/>' @@ -117,7 +117,7 @@ class RepositoriesWithReviewsGrid(RepositoryGrid): rval = '' for review in repository.reviews: if review.approved: - rval += '%s
    ' % review.approved + rval += f'{review.approved}
    ' return rval title = "All reviewed repositories" @@ -305,11 +305,11 @@ class RepositoryReviewsByUserGrid(grids.Grid): if review.rating: for index in range(1, 6): rval = ' (index - 0.5) and review.rating < (index + 0.5): rval += 'checked="checked" ' rval += '/>' diff --git a/lib/tool_shed/metadata/repository_metadata_manager.py b/lib/tool_shed/metadata/repository_metadata_manager.py index 585de4e1401..935e38f2c2e 100644 --- a/lib/tool_shed/metadata/repository_metadata_manager.py +++ b/lib/tool_shed/metadata/repository_metadata_manager.py @@ -60,8 +60,8 @@ class RepositoryMetadataManager(metadata_generator.MetadataGenerator): query = self.get_query_for_setting_metadata_on_repositories(my_writable=my_writable, order=True) for repository in query: owner = str(repository.user.username) - option_label = '{} ({})'.format(str(repository.name), owner) - option_value = '%s' % self.app.security.encode_id(repository.id) + option_label = f'{str(repository.name)} ({owner})' + option_value = f'{self.app.security.encode_id(repository.id)}' repositories_select_field.add_option(option_label, option_value) return repositories_select_field @@ -734,7 +734,7 @@ class RepositoryMetadataManager(metadata_generator.MetadataGenerator): def reset_all_metadata_on_repository_in_tool_shed(self): """Reset all metadata on a single repository in a tool shed.""" - log.debug("Resetting all metadata on repository: %s" % self.repository.name) + log.debug(f"Resetting all metadata on repository: {self.repository.name}") repo = self.repository.hg_repo # The list of changeset_revisions refers to repository_metadata records that have been created # or updated. When the following loop completes, we'll delete all repository_metadata records diff --git a/lib/tool_shed/test/base/test_db_util.py b/lib/tool_shed/test/base/test_db_util.py index 82cf6caaa14..c128444126e 100644 --- a/lib/tool_shed/test/base/test_db_util.py +++ b/lib/tool_shed/test/base/test_db_util.py @@ -88,9 +88,9 @@ def get_installed_repository_by_name_owner(repository_name, owner, return_multip def get_private_role(user): for role in user.all_roles(): - if role.name == user.email and role.description == 'Private Role for %s' % user.email: + if role.name == user.email and role.description == f'Private Role for {user.email}': return role - raise AssertionError("Private role not found for user '%s'" % user.email) + raise AssertionError(f"Private role not found for user '{user.email}'") def get_role(user, role_name): @@ -205,9 +205,9 @@ def ga_refresh(obj): def get_galaxy_private_role(user): for role in user.all_roles(): - if role.name == user.email and role.description == 'Private Role for %s' % user.email: + if role.name == user.email and role.description == f'Private Role for {user.email}': return role - raise AssertionError("Private role not found for user '%s'" % user.email) + raise AssertionError(f"Private role not found for user '{user.email}'") def get_galaxy_user(email): diff --git a/lib/tool_shed/test/base/twilltestcase.py b/lib/tool_shed/test/base/twilltestcase.py index 35008207c3d..b4ed4e816ba 100644 --- a/lib/tool_shed/test/base/twilltestcase.py +++ b/lib/tool_shed/test/base/twilltestcase.py @@ -120,7 +120,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): except AssertionError: try: # May have created the account in a previous test run... - self.check_page_for_string("User with email '%s' already exists." % email) + self.check_page_for_string(f"User with email '{email}' already exists.") previously_created = True except AssertionError: try: @@ -212,7 +212,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): key, value = query_parameter.split('=') params[key] = value if params: - url += '?%s' % urlencode(params, doseq=doseq) + url += f'?{urlencode(params, doseq=doseq)}' new_url = tc.go(url) return_code = tc.browser.code assert return_code in allowed_codes, 'Invalid HTTP return code %s, allowed codes: %s' % \ @@ -318,7 +318,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): def check_galaxy_repository_tool_panel_section(self, repository, expected_tool_panel_section): metadata = repository.metadata - assert 'tools' in metadata, 'Tools not found in repository metadata: %s' % metadata + assert 'tools' in metadata, f'Tools not found in repository metadata: {metadata}' # If integrated_tool_panel.xml is to be tested, this test method will need to be enhanced to handle tools # from the same repository in different tool panel sections. Getting the first tool guid is ok, because # currently all tools contained in a single repository will be loaded into the same tool panel section. @@ -401,7 +401,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): '''Load the invalid tool page for each invalid tool associated with this changeset revision and verify the received error messages.''' repository_metadata = self.get_repository_metadata_by_changeset_revision(repository, changeset_revision) metadata = repository_metadata.metadata - assert 'invalid_tools' in metadata, 'Metadata for changeset revision %s does not define invalid tools' % changeset_revision + assert 'invalid_tools' in metadata, f'Metadata for changeset revision {changeset_revision} does not define invalid tools' for tool_xml in metadata['invalid_tools']: self.load_invalid_tool_page(repository, tool_xml=tool_xml, @@ -473,7 +473,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): else: for _, name, _, _ in repository_tuples: repository_names.append(name) - dependency_description = '{} depends on {}.'.format(repository.name, ', '.join(repository_names)) + dependency_description = f"{repository.name} depends on {', '.join(repository_names)}." filename = 'repository_dependencies.xml' self.generate_simple_dependency_xml(repository_tuples=repository_tuples, filename=filename, @@ -572,7 +572,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): if not isinstance(data_manager_names, list): data_manager_names = [data_manager_names] for data_manager_name in data_manager_names: - assert data_manager_name in data_managers, "The requested Data Manager '%s' was not found in repository metadata." % data_manager_name + assert data_manager_name in data_managers, f"The requested Data Manager '{data_manager_name}' was not found in repository metadata." else: data_manager_name = list(data_managers.keys()) for data_manager_name in data_manager_names: @@ -647,22 +647,22 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): strings_displayed = [] strings_not_displayed = [] for category in categories_to_add: - tc.fv("2", "category_id", '+%s' % category) - strings_displayed.append("selected>%s" % category) + tc.fv("2", "category_id", f'+{category}') + strings_displayed.append(f"selected>{category}") for category in categories_to_remove: - tc.fv("2", "category_id", '-%s' % category) - strings_not_displayed.append("selected>%s" % category) + tc.fv("2", "category_id", f'-{category}') + strings_not_displayed.append(f"selected>{category}") tc.submit("manage_categories_button") self.check_for_strings(strings_displayed, strings_not_displayed) if restore_original: strings_displayed = [] strings_not_displayed = [] for category in categories_to_remove: - tc.fv("2", "category_id", '+%s' % category) - strings_displayed.append("selected>%s" % category) + tc.fv("2", "category_id", f'+{category}') + strings_displayed.append(f"selected>{category}") for category in categories_to_add: - tc.fv("2", "category_id", '-%s' % category) - strings_not_displayed.append("selected>%s" % category) + tc.fv("2", "category_id", f'-{category}') + strings_not_displayed.append(f"selected>{category}") tc.submit("manage_categories_button") self.check_for_strings(strings_displayed, strings_not_displayed) @@ -704,12 +704,12 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): def expect_repo_created_strings(self, name): return [ - 'Repository %s' % name, - 'Repository %s has been created' % name, + f'Repository {name}', + f'Repository {name} has been created', ] def fetch_repository_metadata(self, repository, strings_displayed=None, strings_not_displayed=None): - url = '/api/repositories/%s/metadata' % self.security.encode_id(repository.id) + url = f'/api/repositories/{self.security.encode_id(repository.id)}/metadata' self.visit_url(url) self.check_for_strings(strings_displayed, strings_not_displayed) @@ -719,13 +719,13 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): for label, contents in review_contents_dict.items(): if contents: changed = True - kwd['%s__ESEP__comment' % label] = contents['comment'] - kwd['%s__ESEP__rating' % label] = contents['rating'] + kwd[f'{label}__ESEP__comment'] = contents['comment'] + kwd[f'{label}__ESEP__rating'] = contents['rating'] if 'private' in contents: - kwd['%s__ESEP__private' % label] = contents['private'] - kwd['%s__ESEP__approved' % label] = contents['approved'] + kwd[f'{label}__ESEP__private'] = contents['private'] + kwd[f'{label}__ESEP__approved'] = contents['approved'] else: - kwd['%s__ESEP__approved' % label] = 'not_applicable' + kwd[f'{label}__ESEP__approved'] = 'not_applicable' self.check_for_strings(strings_displayed, strings_not_displayed) self.submit_form(button='Workflows__ESEP__review_button', **kwd) if changed: @@ -797,7 +797,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): changeset_revision=changeset_revision, prior_installation_required=prior_installation_value)) if dependency_description: - description = ' description="%s"' % dependency_description + description = f' description="{dependency_description}"' else: description = dependency_description template_parser = string.Template(common.new_repository_dependencies_xml) @@ -848,7 +848,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): def get_repositories_category_api(self, categories, strings_displayed=None, strings_not_displayed=None): for category in categories: - url = '/api/categories/%s/repositories' % self.security.encode_id(category.id) + url = f'/api/categories/{self.security.encode_id(category.id)}/repositories' self.visit_url(url) self.check_for_strings(strings_displayed, strings_not_displayed) @@ -965,7 +965,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): def get_tool_panel_section_from_api(self, metadata): tool_metadata = metadata['tools'] tool_guid = quote_plus(tool_metadata[0]['guid'], safe='') - api_url = '/api/tools/%s' % tool_guid + api_url = f'/api/tools/{tool_guid}' self.visit_galaxy_url(api_url) tool_dict = loads(self.last_page()) tool_panel_section = tool_dict['panel_section_name'] @@ -974,7 +974,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): def get_tool_panel_section_from_repository_metadata(self, metadata): tool_metadata = metadata['tools'] tool_guid = tool_metadata[0]['guid'] - assert 'tool_panel_section' in metadata, 'Tool panel section not found in metadata: %s' % metadata + assert 'tool_panel_section' in metadata, f'Tool panel section not found in metadata: {metadata}' tool_panel_section_metadata = metadata['tool_panel_section'] # tool_section_dict = dict( tool_config=guids_and_configs[ guid ], # id=section_id, @@ -1002,7 +1002,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): role_members_edit_button='Save') url = '/admin/manage_users_and_groups_for_role' self.visit_url(url, params) - strings_displayed = ["Role '%s' has been updated" % role.name] + strings_displayed = [f"Role '{role.name}' has been updated"] self.check_for_strings(strings_displayed, strings_not_displayed) def grant_write_access(self, @@ -1016,7 +1016,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): self.display_manage_repository_page(repository) self.check_for_strings(strings_displayed, strings_not_displayed) for username in usernames: - tc.fv("user_access", "allow_push", '+%s' % username) + tc.fv("user_access", "allow_push", f'+{username}') tc.submit('user_access_button') self.check_for_strings(post_submit_strings_displayed, post_submit_strings_not_displayed) @@ -1093,12 +1093,12 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): ) tc.browser.result = ResultWrapper(r) else: - assert len(submit_button) == 1, 'Expected to find a single submit button, found {} ({})'.format(len(submit_button), ','.join(submit_button)) + assert len(submit_button) == 1, f"Expected to find a single submit button, found {len(submit_button)} ({','.join(submit_button)})" submit_button = submit_button[0] self.submit_form(form=form, button=submit_button, **kwds) self.check_for_strings(post_submit_strings_displayed, strings_not_displayed) repository_ids = self.initiate_installation_process(new_tool_panel_section_label=new_tool_panel_section_label) - log.debug('Waiting for the installation of repository IDs: %s' % str(repository_ids)) + log.debug(f'Waiting for the installation of repository IDs: {str(repository_ids)}') self.wait_for_repository_installation(repository_ids) def load_citable_url(self, @@ -1116,11 +1116,11 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): url = f'{self.url}/view/{username}' # If repository name is passed in, append that to the url. if repository_name: - url += '/%s' % repository_name + url += f'/{repository_name}' if changeset_revision: # Changeset revision should never be provided unless repository name also is. assert repository_name is not None, 'Changeset revision is present, but repository name is not - aborting.' - url += '/%s' % changeset_revision + url += f'/{changeset_revision}' self.visit_url(url) self.check_for_strings(strings_displayed, strings_not_displayed) # Now load the page that should be displayed inside the iframe and check for strings. @@ -1336,7 +1336,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): form_id = form.attrib.get('id') controls = [control for control in form.inputs if str(control.name) == field_name] if len(controls) > 0: - log.debug('Setting field {} of form {} to {}.'.format(field_name, form_id, str(field_value))) + log.debug(f'Setting field {field_name} of form {form_id} to {str(field_value)}.') tc.formvalue(form_id, field_name, str(field_value)) kwd[field_name] = str(field_value) else: @@ -1499,12 +1499,12 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): metadata = installed_repository.metadata self.reset_installed_repository_metadata(installed_repository) new_metadata = installed_repository.metadata - assert metadata == new_metadata, 'Metadata for installed repository %s differs after metadata reset.' % name + assert metadata == new_metadata, f'Metadata for installed repository {name} differs after metadata reset.' def verify_installed_repository_no_tool_panel_section(self, repository): '''Verify that there is no 'tool_panel_section' entry in the repository metadata.''' metadata = repository.metadata - assert 'tool_panel_section' not in metadata, 'Tool panel section incorrectly found in metadata: %s' % metadata + assert 'tool_panel_section' not in metadata, f'Tool panel section incorrectly found in metadata: {metadata}' def verify_installed_repository_data_table_entries(self, required_data_table_entries): # The value of the received required_data_table_entries will be something like: [ 'sam_fa_indexes' ] @@ -1543,14 +1543,14 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): # rather than allowing the location to be a configurable setting like the tool shed requires. file_path = file_elem.get('path', None) # The value of file_path will be something like: "tool-data/all_fasta.loc" - assert file_path is not None, 'The "path" attribute is missing for the %s entry.' % required_data_table_entry + assert file_path is not None, f'The "path" attribute is missing for the {required_data_table_entry} entry.' # The following test is probably not necesary, but the tool-data directory should exist! galaxy_tool_data_dir, loc_file_name = os.path.split(file_path) - assert galaxy_tool_data_dir is not None, 'The hard-coded Galaxy tool-data directory is missing for the %s entry.' % required_data_table_entry + assert galaxy_tool_data_dir is not None, f'The hard-coded Galaxy tool-data directory is missing for the {required_data_table_entry} entry.' assert os.path.exists(galaxy_tool_data_dir), 'The Galaxy tool-data directory does not exist.' # Make sure the loc_file_name was correctly copied into the configured directory location. configured_file_location = os.path.join(self.tool_data_path, loc_file_name) - assert os.path.isfile(configured_file_location), 'The expected copied file "%s" is missing.' % configured_file_location + assert os.path.isfile(configured_file_location), f'The expected copied file "{configured_file_location}" is missing.' # We've found the value of the required_data_table_entry in data_tables, which is the parsed # shed_tool_data_table_conf.xml, so all is well! break @@ -1596,7 +1596,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): new_metadata[metadata.changeset_revision] = metadata.metadata # Python's dict comparison recursively compares sorted key => value pairs and returns true if any key or value differs, # or if the number of keys differs. - assert old_metadata == new_metadata, 'Metadata changed after reset on repository %s.' % repository.name + assert old_metadata == new_metadata, f'Metadata changed after reset on repository {repository.name}.' def visit_galaxy_url(self, url, params=None, doseq=False, allowed_codes=None): if allowed_codes is None: diff --git a/lib/tool_shed/test/functional/test_0000_basic_repository_features.py b/lib/tool_shed/test/functional/test_0000_basic_repository_features.py index 5cbaa005a18..5c43c0cde50 100644 --- a/lib/tool_shed/test/functional/test_0000_basic_repository_features.py +++ b/lib/tool_shed/test/functional/test_0000_basic_repository_features.py @@ -16,15 +16,15 @@ class TestBasicRepositoryFeatures(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.test_user_2_email, username=common.test_user_2_name) test_user_2 = self.test_db_util.get_user(common.test_user_2_email) - assert test_user_2 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_2_email + assert test_user_2 is not None, f'Problem retrieving user with email {common.test_user_2_email} from the database' self.test_db_util.get_private_role(test_user_2) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_repository_without_categories(self): @@ -91,7 +91,7 @@ class TestBasicRepositoryFeatures(ShedTwillTestCase): self.check_for_valid_tools(repository, strings_displayed=['Filter1']) self.check_count_of_metadata_revisions_associated_with_repository(repository, metadata_count=1) tip = self.get_repository_tip(repository) - tool_guid = '%s/repos/user1/filtering_0000/Filter1/1.1.0' % self.url.replace('http://', '').rstrip('/') + tool_guid = f"{self.url.replace('http://', '').rstrip('/')}/repos/user1/filtering_0000/Filter1/1.1.0" tool_metadata_strings_displayed = [tool_guid, '1.1.0', # The tool version. 'Filter1', # The tool ID. @@ -103,7 +103,7 @@ class TestBasicRepositoryFeatures(ShedTwillTestCase): tool_metadata_strings_displayed=tool_metadata_strings_displayed, tool_page_strings_displayed=tool_page_strings_displayed) self.check_repository_metadata(repository, tip_only=False) - self.browse_repository(repository, strings_displayed=["Repository '%s' revision" % repository.name, '(repository tip)']) + self.browse_repository(repository, strings_displayed=[f"Repository '{repository.name}' revision", '(repository tip)']) self.display_repository_clone_page(common.test_user_1_name, repository_name, strings_displayed=['Uploaded filtering 1.1.0', latest_changeset_revision]) @@ -195,7 +195,7 @@ class TestBasicRepositoryFeatures(ShedTwillTestCase): strings_displayed = ['Select a revision'] self.display_manage_repository_page(repository, strings_displayed=strings_displayed) self.check_count_of_metadata_revisions_associated_with_repository(repository, metadata_count=2) - tool_guid = '%s/repos/user1/filtering_0000/Filter1/2.2.0' % self.url.replace('http://', '').rstrip('/') + tool_guid = f"{self.url.replace('http://', '').rstrip('/')}/repos/user1/filtering_0000/Filter1/2.2.0" tool_metadata_strings_displayed = [tool_guid, '2.2.0', # The tool version. 'Filter1', # The tool ID. @@ -362,5 +362,5 @@ class TestBasicRepositoryFeatures(ShedTwillTestCase): repository = self.test_db_util.get_repository_by_name_and_owner(repository_name, common.test_user_1_name) encoded_repository_id = self.security.encode_id(repository.id) strings_displayed = ['Invalid+changeset+revision'] - self.visit_url('/repository/view_repository?id={}&changeset_revision={}'.format(encoded_repository_id, 'nonsensical_changeset')) + self.visit_url(f"/repository/view_repository?id={encoded_repository_id}&changeset_revision=nonsensical_changeset") self.check_for_strings(strings_displayed=strings_displayed, strings_not_displayed=[]) diff --git a/lib/tool_shed/test/functional/test_0010_repository_with_tool_dependencies.py b/lib/tool_shed/test/functional/test_0010_repository_with_tool_dependencies.py index 0f2ce89ad34..3a9e1af3bde 100644 --- a/lib/tool_shed/test/functional/test_0010_repository_with_tool_dependencies.py +++ b/lib/tool_shed/test/functional/test_0010_repository_with_tool_dependencies.py @@ -24,11 +24,11 @@ class TestFreebayesRepository(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_category(self): diff --git a/lib/tool_shed/test/functional/test_0020_basic_repository_dependencies.py b/lib/tool_shed/test/functional/test_0020_basic_repository_dependencies.py index 2d1c5a91f96..ba85dc69018 100644 --- a/lib/tool_shed/test/functional/test_0020_basic_repository_dependencies.py +++ b/lib/tool_shed/test/functional/test_0020_basic_repository_dependencies.py @@ -16,11 +16,11 @@ class TestBasicRepositoryDependencies(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_category(self): diff --git a/lib/tool_shed/test/functional/test_0030_repository_dependency_revisions.py b/lib/tool_shed/test/functional/test_0030_repository_dependency_revisions.py index 2b80d6175a7..053a2ac0ea0 100644 --- a/lib/tool_shed/test/functional/test_0030_repository_dependency_revisions.py +++ b/lib/tool_shed/test/functional/test_0030_repository_dependency_revisions.py @@ -18,11 +18,11 @@ class TestRepositoryDependencyRevisions(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_category(self): diff --git a/lib/tool_shed/test/functional/test_0040_repository_circular_dependencies.py b/lib/tool_shed/test/functional/test_0040_repository_circular_dependencies.py index bbfc34bf38e..6c6c48c7fd4 100644 --- a/lib/tool_shed/test/functional/test_0040_repository_circular_dependencies.py +++ b/lib/tool_shed/test/functional/test_0040_repository_circular_dependencies.py @@ -16,11 +16,11 @@ class TestRepositoryCircularDependencies(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_category(self): diff --git a/lib/tool_shed/test/functional/test_0050_circular_dependencies_4_levels.py b/lib/tool_shed/test/functional/test_0050_circular_dependencies_4_levels.py index 1224d69372c..79e016d9a8f 100644 --- a/lib/tool_shed/test/functional/test_0050_circular_dependencies_4_levels.py +++ b/lib/tool_shed/test/functional/test_0050_circular_dependencies_4_levels.py @@ -39,11 +39,11 @@ class TestRepositoryCircularDependenciesToNLevels(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_convert_repository(self): diff --git a/lib/tool_shed/test/functional/test_0070_invalid_tool.py b/lib/tool_shed/test/functional/test_0070_invalid_tool.py index dc5f3e1256f..5ca2fc18690 100644 --- a/lib/tool_shed/test/functional/test_0070_invalid_tool.py +++ b/lib/tool_shed/test/functional/test_0070_invalid_tool.py @@ -14,11 +14,11 @@ class TestBismarkRepository(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_category_and_repository(self): @@ -53,7 +53,7 @@ class TestBismarkRepository(ShedTwillTestCase): strings_not_displayed=[]) valid_revision = self.get_repository_tip(repository) self.test_db_util.refresh(repository) - tool_guid = '%s/repos/user1/bismark_0070/bismark_methylation_extractor/0.7.7.3' % self.url.replace('http://', '').rstrip('/') + tool_guid = f"{self.url.replace('http://', '').rstrip('/')}/repos/user1/bismark_0070/bismark_methylation_extractor/0.7.7.3" tool_metadata_strings_displayed = [tool_guid, '0.7.7.3', # The tool version. 'bismark_methylation_extractor', # The tool ID. diff --git a/lib/tool_shed/test/functional/test_0080_advanced_circular_dependencies.py b/lib/tool_shed/test/functional/test_0080_advanced_circular_dependencies.py index b38acdb1c77..b2ed893bab2 100644 --- a/lib/tool_shed/test/functional/test_0080_advanced_circular_dependencies.py +++ b/lib/tool_shed/test/functional/test_0080_advanced_circular_dependencies.py @@ -19,11 +19,11 @@ class TestRepositoryCircularDependencies(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_column_repository(self): diff --git a/lib/tool_shed/test/functional/test_0090_tool_search.py b/lib/tool_shed/test/functional/test_0090_tool_search.py index b7b43891ee0..a890170135f 100644 --- a/lib/tool_shed/test/functional/test_0090_tool_search.py +++ b/lib/tool_shed/test/functional/test_0090_tool_search.py @@ -35,11 +35,11 @@ class TestRepositoryCircularDependenciesAgain(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_bwa_base_repository(self): diff --git a/lib/tool_shed/test/functional/test_0100_complex_repository_dependencies.py b/lib/tool_shed/test/functional/test_0100_complex_repository_dependencies.py index 16eeeb90279..e5fa15d2ee2 100644 --- a/lib/tool_shed/test/functional/test_0100_complex_repository_dependencies.py +++ b/lib/tool_shed/test/functional/test_0100_complex_repository_dependencies.py @@ -24,11 +24,11 @@ class TestComplexRepositoryDependencies(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_bwa_package_repository(self): diff --git a/lib/tool_shed/test/functional/test_0110_invalid_simple_repository_dependencies.py b/lib/tool_shed/test/functional/test_0110_invalid_simple_repository_dependencies.py index 482679ea2d6..1b18851e4e5 100644 --- a/lib/tool_shed/test/functional/test_0110_invalid_simple_repository_dependencies.py +++ b/lib/tool_shed/test/functional/test_0110_invalid_simple_repository_dependencies.py @@ -19,11 +19,11 @@ class TestBasicRepositoryDependencies(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_category(self): diff --git a/lib/tool_shed/test/functional/test_0120_simple_repository_dependency_multiple_owners.py b/lib/tool_shed/test/functional/test_0120_simple_repository_dependency_multiple_owners.py index cf51bbd2df5..b12867605fe 100644 --- a/lib/tool_shed/test/functional/test_0120_simple_repository_dependency_multiple_owners.py +++ b/lib/tool_shed/test/functional/test_0120_simple_repository_dependency_multiple_owners.py @@ -33,15 +33,15 @@ class TestRepositoryMultipleOwners(ShedTwillTestCase): """ self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.test_user_2_email, username=common.test_user_2_name) test_user_2 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_2 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_2_email + assert test_user_2 is not None, f'Problem retrieving user with email {common.test_user_2_email} from the database' self.test_db_util.get_private_role(test_user_2) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_datatypes_repository(self): diff --git a/lib/tool_shed/test/functional/test_0130_datatype_converters.py b/lib/tool_shed/test/functional/test_0130_datatype_converters.py index baf3cc2c626..c9ef03e39de 100644 --- a/lib/tool_shed/test/functional/test_0130_datatype_converters.py +++ b/lib/tool_shed/test/functional/test_0130_datatype_converters.py @@ -21,11 +21,11 @@ class TestDatatypeConverters(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_bed_to_gff_repository(self): diff --git a/lib/tool_shed/test/functional/test_0140_tool_help_images.py b/lib/tool_shed/test/functional/test_0140_tool_help_images.py index f99cee4e87a..83845244882 100644 --- a/lib/tool_shed/test/functional/test_0140_tool_help_images.py +++ b/lib/tool_shed/test/functional/test_0140_tool_help_images.py @@ -28,11 +28,11 @@ class TestToolHelpImages(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_htseq_count_repository(self): @@ -75,7 +75,7 @@ class TestToolHelpImages(ShedTwillTestCase): changeset_revision = self.get_repository_tip(repository) self.display_manage_repository_page(repository) # Generate the image path. - image_path = 'src="/repository/static/images/%s/count_modes.png"' % self.security.encode_id(repository.id) + image_path = f'src="/repository/static/images/{self.security.encode_id(repository.id)}/count_modes.png"' # The repository uploaded in this test should only have one metadata revision, with one tool defined, which # should be the tool that contains a link to the image. repository_metadata = repository.metadata_revisions[0].metadata diff --git a/lib/tool_shed/test/functional/test_0150_prior_installation_required.py b/lib/tool_shed/test/functional/test_0150_prior_installation_required.py index e3cb0fcf993..968b2186429 100644 --- a/lib/tool_shed/test/functional/test_0150_prior_installation_required.py +++ b/lib/tool_shed/test/functional/test_0150_prior_installation_required.py @@ -33,11 +33,11 @@ class TestSimplePriorInstallation(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_convert_repository(self): diff --git a/lib/tool_shed/test/functional/test_0160_circular_prior_installation_required.py b/lib/tool_shed/test/functional/test_0160_circular_prior_installation_required.py index 78b71a85202..b0032671e9d 100644 --- a/lib/tool_shed/test/functional/test_0160_circular_prior_installation_required.py +++ b/lib/tool_shed/test/functional/test_0160_circular_prior_installation_required.py @@ -32,11 +32,11 @@ class TestSimplePriorInstallation(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_convert_repository(self): diff --git a/lib/tool_shed/test/functional/test_0170_complex_prior_installation_required.py b/lib/tool_shed/test/functional/test_0170_complex_prior_installation_required.py index f3345a91737..2335ce3527b 100644 --- a/lib/tool_shed/test/functional/test_0170_complex_prior_installation_required.py +++ b/lib/tool_shed/test/functional/test_0170_complex_prior_installation_required.py @@ -27,11 +27,11 @@ class TestComplexPriorInstallation(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_matplotlib_repository(self): diff --git a/lib/tool_shed/test/functional/test_0300_reset_all_metadata.py b/lib/tool_shed/test/functional/test_0300_reset_all_metadata.py index ab54b414711..212f07a11b8 100644 --- a/lib/tool_shed/test/functional/test_0300_reset_all_metadata.py +++ b/lib/tool_shed/test/functional/test_0300_reset_all_metadata.py @@ -50,11 +50,11 @@ class TestResetAllRepositoryMetadata(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_filtering_repository(self): @@ -600,4 +600,4 @@ class TestResetAllRepositoryMetadata(ShedTwillTestCase): for metadata in self.get_repository_metadata(repository): new_metadata[self.security.encode_id(repository.id)][metadata.changeset_revision] = metadata.metadata if old_metadata[self.security.encode_id(repository.id)] != new_metadata[self.security.encode_id(repository.id)]: - raise AssertionError('Metadata changed after reset for repository %s.' % repository.name) + raise AssertionError(f'Metadata changed after reset for repository {repository.name}.') diff --git a/lib/tool_shed/test/functional/test_0310_hg_api_features.py b/lib/tool_shed/test/functional/test_0310_hg_api_features.py index d101d308a83..a8741740b69 100644 --- a/lib/tool_shed/test/functional/test_0310_hg_api_features.py +++ b/lib/tool_shed/test/functional/test_0310_hg_api_features.py @@ -25,15 +25,15 @@ class TestHgWebFeatures(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.test_user_2_email, username=common.test_user_2_name) test_user_2 = self.test_db_util.get_user(common.test_user_2_email) - assert test_user_2 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_2_email + assert test_user_2 is not None, f'Problem retrieving user with email {common.test_user_2_email} from the database' self.test_db_util.get_private_role(test_user_2) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_filtering_repository(self): diff --git a/lib/tool_shed/test/functional/test_0400_repository_component_reviews.py b/lib/tool_shed/test/functional/test_0400_repository_component_reviews.py index 6d3910a6f3d..a2409f521a4 100644 --- a/lib/tool_shed/test/functional/test_0400_repository_component_reviews.py +++ b/lib/tool_shed/test/functional/test_0400_repository_component_reviews.py @@ -47,15 +47,15 @@ class TestRepositoryComponentReviews(ShedTwillTestCase): """ self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.test_user_2_email, username=common.test_user_2_name) test_user_2 = self.test_db_util.get_user(common.test_user_2_email) - assert test_user_2 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_2_email + assert test_user_2 is not None, f'Problem retrieving user with email {common.test_user_2_email} from the database' self.test_db_util.get_private_role(test_user_2) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_grant_reviewer_role(self): diff --git a/lib/tool_shed/test/functional/test_0410_repository_component_review_access_control.py b/lib/tool_shed/test/functional/test_0410_repository_component_review_access_control.py index 606e04516ec..ee584bf25d5 100644 --- a/lib/tool_shed/test/functional/test_0410_repository_component_review_access_control.py +++ b/lib/tool_shed/test/functional/test_0410_repository_component_review_access_control.py @@ -26,19 +26,19 @@ class TestRepositoryComponentReviews(ShedTwillTestCase): """ self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.test_user_2_email, username=common.test_user_2_name) test_user_2 = self.test_db_util.get_user(common.test_user_2_email) - assert test_user_2 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_2_email + assert test_user_2 is not None, f'Problem retrieving user with email {common.test_user_2_email} from the database' self.test_db_util.get_private_role(test_user_2) self.login(email=common.test_user_3_email, username=common.test_user_3_name) test_user_3 = self.test_db_util.get_user(common.test_user_3_email) - assert test_user_3 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_3_email + assert test_user_3 is not None, f'Problem retrieving user with email {common.test_user_3_email} from the database' self.test_db_util.get_private_role(test_user_3) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_grant_reviewer_role(self): diff --git a/lib/tool_shed/test/functional/test_0420_citable_urls_for_repositories.py b/lib/tool_shed/test/functional/test_0420_citable_urls_for_repositories.py index 36d17aa71a5..09e77b0fd8f 100644 --- a/lib/tool_shed/test/functional/test_0420_citable_urls_for_repositories.py +++ b/lib/tool_shed/test/functional/test_0420_citable_urls_for_repositories.py @@ -35,11 +35,11 @@ class TestRepositoryCitableURLs(ShedTwillTestCase): """ self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_repository(self): @@ -129,7 +129,7 @@ class TestRepositoryCitableURLs(ShedTwillTestCase): strings_displayed_in_iframe = ['user1', 'filtering_0420', 'Galaxy filtering tool for test 0420'] strings_displayed_in_iframe.append(self.get_repository_tip(repository)) strings_displayed_in_iframe.append('Link to this repository:') - strings_displayed_in_iframe.append('%s/view/user1/filtering_0420' % self.url) + strings_displayed_in_iframe.append(f'{self.url}/view/user1/filtering_0420') self.load_citable_url(username='user1', repository_name='filtering_0420', changeset_revision=None, diff --git a/lib/tool_shed/test/functional/test_0430_browse_utilities.py b/lib/tool_shed/test/functional/test_0430_browse_utilities.py index 77171a37af6..57e2c37b1ba 100644 --- a/lib/tool_shed/test/functional/test_0430_browse_utilities.py +++ b/lib/tool_shed/test/functional/test_0430_browse_utilities.py @@ -35,11 +35,11 @@ class TestToolShedBrowseUtilities(ShedTwillTestCase): """ self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_datatypes_repository(self): diff --git a/lib/tool_shed/test/functional/test_0440_deleting_dependency_definitions.py b/lib/tool_shed/test/functional/test_0440_deleting_dependency_definitions.py index 411512cf60f..214911acac4 100644 --- a/lib/tool_shed/test/functional/test_0440_deleting_dependency_definitions.py +++ b/lib/tool_shed/test/functional/test_0440_deleting_dependency_definitions.py @@ -59,11 +59,11 @@ class TestDeletedDependencies(ShedTwillTestCase): """ self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_column_maker_repository(self): @@ -323,7 +323,7 @@ class TestDeletedDependencies(ShedTwillTestCase): # Check that the new tip does not have a metadata revision. metadata_record = self.get_repository_metadata_by_changeset_revision(repository, new_changeset_revision) # If a changeset revision does not have metadata, the above method will return None. - assert metadata_record is None, 'The tip revision of %s should not have metadata, but metadata was found.' % repository.name + assert metadata_record is None, f'The tip revision of {repository.name} should not have metadata, but metadata was found.' # Verify that the new changeset revision is not downloadable. assert len(repository.downloadable_revisions) == 1, 'Repository %s has %d downloadable revisions, expected 1.' % \ (repository.name, len(repository.downloadable_revisions)) diff --git a/lib/tool_shed/test/functional/test_0460_upload_to_repository.py b/lib/tool_shed/test/functional/test_0460_upload_to_repository.py index 417dae4c652..846c5ab40c2 100644 --- a/lib/tool_shed/test/functional/test_0460_upload_to_repository.py +++ b/lib/tool_shed/test/functional/test_0460_upload_to_repository.py @@ -61,15 +61,15 @@ class TestAutomaticDependencyRevision(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.test_user_2_email, username=common.test_user_2_name) test_user_2 = self.test_db_util.get_user(common.test_user_2_email) - assert test_user_2 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_2_email + assert test_user_2 is not None, f'Problem retrieving user with email {common.test_user_2_email} from the database' self.test_db_util.get_private_role(test_user_2) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_datatypes_repository(self): diff --git a/lib/tool_shed/test/functional/test_0470_tool_dependency_repository_type.py b/lib/tool_shed/test/functional/test_0470_tool_dependency_repository_type.py index a3addd0b132..ca98a48d679 100644 --- a/lib/tool_shed/test/functional/test_0470_tool_dependency_repository_type.py +++ b/lib/tool_shed/test/functional/test_0470_tool_dependency_repository_type.py @@ -58,16 +58,16 @@ class TestEnvironmentInheritance(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) self.create_category(name=category_name, description=category_description) self.login(email=common.test_user_2_email, username=common.test_user_2_name) test_user_2 = self.test_db_util.get_user(common.test_user_2_email) - assert test_user_2 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_2_email + assert test_user_2 is not None, f'Problem retrieving user with email {common.test_user_2_email} from the database' self.test_db_util.get_private_role(test_user_2) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) def test_0005_create_libx11_repository(self): diff --git a/lib/tool_shed/test/functional/test_0480_tool_dependency_xml_verification.py b/lib/tool_shed/test/functional/test_0480_tool_dependency_xml_verification.py index 864257ccc64..aae1bd73d66 100644 --- a/lib/tool_shed/test/functional/test_0480_tool_dependency_xml_verification.py +++ b/lib/tool_shed/test/functional/test_0480_tool_dependency_xml_verification.py @@ -26,16 +26,16 @@ class TestDependencyDefinitionValidation(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) self.create_category(name=category_name, description=category_description) self.login(email=common.test_user_2_email, username=common.test_user_2_name) test_user_2 = self.test_db_util.get_user(common.test_user_2_email) - assert test_user_2 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_2_email + assert test_user_2 is not None, f'Problem retrieving user with email {common.test_user_2_email} from the database' self.test_db_util.get_private_role(test_user_2) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) def test_0005_create_tool_dependency_repository(self): diff --git a/lib/tool_shed/test/functional/test_0530_repository_admin_feature.py b/lib/tool_shed/test/functional/test_0530_repository_admin_feature.py index abd2349d8a1..504b90938ba 100644 --- a/lib/tool_shed/test/functional/test_0530_repository_admin_feature.py +++ b/lib/tool_shed/test/functional/test_0530_repository_admin_feature.py @@ -37,15 +37,15 @@ class TestRepositoryAdminRole(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.test_user_2_email, username=common.test_user_2_name) test_user_2 = self.test_db_util.get_user(common.test_user_2_email) - assert test_user_2 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_2_email + assert test_user_2 is not None, f'Problem retrieving user with email {common.test_user_2_email} from the database' self.test_db_util.get_private_role(test_user_2) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_filtering_repository(self): @@ -110,9 +110,9 @@ class TestRepositoryAdminRole(ShedTwillTestCase): new repository name from Step 4. ''' test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - old_repository_admin_role = self.test_db_util.get_role(test_user_1, 'filtering_0530_%s_admin' % test_user_1.username) + old_repository_admin_role = self.test_db_util.get_role(test_user_1, f'filtering_0530_{test_user_1.username}_admin') assert old_repository_admin_role is None, 'Admin role filtering_0530_user1_admin incorrectly exists.' - new_repository_admin_role = self.test_db_util.get_role(test_user_1, 'renamed_filtering_0530_%s_admin' % test_user_1.username) + new_repository_admin_role = self.test_db_util.get_role(test_user_1, f'renamed_filtering_0530_{test_user_1.username}_admin') assert new_repository_admin_role is not None, 'Admin role renamed_filtering_0530_user1_admin does not exist.' def test_0030_verify_access_denied(self): diff --git a/lib/tool_shed/test/functional/test_0540_get_all_metadata_from_api.py b/lib/tool_shed/test/functional/test_0540_get_all_metadata_from_api.py index 5e1dd02d201..ac11d04af23 100644 --- a/lib/tool_shed/test/functional/test_0540_get_all_metadata_from_api.py +++ b/lib/tool_shed/test/functional/test_0540_get_all_metadata_from_api.py @@ -37,11 +37,11 @@ class TestGetAllMetadata(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_bwa_package_repository(self): @@ -55,7 +55,7 @@ class TestGetAllMetadata(ShedTwillTestCase): owner=common.test_user_1_name, category_id=self.security.encode_id(category.id), strings_displayed=[]) - assert repository is not None, 'Error creating repository %s' % repositories['bwa']['name'] + assert repository is not None, f"Error creating repository {repositories['bwa']['name']}" self.upload_file(repository, filename='0540_files/package_bwa/tool_dependencies.xml', filepath=None, @@ -77,7 +77,7 @@ class TestGetAllMetadata(ShedTwillTestCase): owner=common.test_user_1_name, category_id=self.security.encode_id(category.id), strings_displayed=[]) - assert repository is not None, 'Error creating repository %s' % repositories['convert']['name'] + assert repository is not None, f"Error creating repository {repositories['convert']['name']}" self.upload_file(repository, filename='0540_files/convert_chars/convert_chars.tar', filepath=None, @@ -109,7 +109,7 @@ class TestGetAllMetadata(ShedTwillTestCase): owner=common.test_user_1_name, category_id=self.security.encode_id(category.id), strings_displayed=[]) - assert repository is not None, 'Error creating repository %s' % repositories['column']['name'] + assert repository is not None, f"Error creating repository {repositories['column']['name']}" self.upload_file(repository, filename='0540_files/column_maker/column_maker.tar', filepath=None, diff --git a/lib/tool_shed/test/functional/test_0550_metadata_updated_dependencies.py b/lib/tool_shed/test/functional/test_0550_metadata_updated_dependencies.py index be1e8943840..1c19427eb61 100644 --- a/lib/tool_shed/test/functional/test_0550_metadata_updated_dependencies.py +++ b/lib/tool_shed/test/functional/test_0550_metadata_updated_dependencies.py @@ -41,11 +41,11 @@ class TestGetUpdatedMetadata(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_freebayes_repository(self): @@ -59,7 +59,7 @@ class TestGetUpdatedMetadata(ShedTwillTestCase): owner=common.test_user_1_name, category_id=self.security.encode_id(category.id), strings_displayed=[]) - assert freebayes is not None, 'Error creating freebayes %s' % repositories['freebayes']['name'] + assert freebayes is not None, f"Error creating freebayes {repositories['freebayes']['name']}" self.upload_file(freebayes, filename='0550_files/package_freebayes_1_0550.tgz', filepath=None, @@ -81,7 +81,7 @@ class TestGetUpdatedMetadata(ShedTwillTestCase): owner=common.test_user_1_name, category_id=self.security.encode_id(category.id), strings_displayed=[]) - assert samtools is not None, 'Error creating samtools %s' % repositories['samtools']['name'] + assert samtools is not None, f"Error creating samtools {repositories['samtools']['name']}" self.upload_file(samtools, filename='0550_files/package_samtools_1_0550.tgz', filepath=None, @@ -101,7 +101,7 @@ class TestGetUpdatedMetadata(ShedTwillTestCase): owner=common.test_user_1_name, category_id=self.security.encode_id(category.id), strings_displayed=[]) - assert repository is not None, 'Error creating repository %s' % repositories['filtering']['name'] + assert repository is not None, f"Error creating repository {repositories['filtering']['name']}" self.upload_file(repository, filename='0550_files/filtering_1.0.tgz', filepath=None, diff --git a/lib/tool_shed/test/functional/test_1000_install_basic_repository.py b/lib/tool_shed/test/functional/test_1000_install_basic_repository.py index 17ce8fdf9f0..030ca40f332 100644 --- a/lib/tool_shed/test/functional/test_1000_install_basic_repository.py +++ b/lib/tool_shed/test/functional/test_1000_install_basic_repository.py @@ -8,15 +8,15 @@ class BasicToolShedFeatures(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) self.galaxy_login(email=common.admin_email, username=common.admin_username) galaxy_admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert galaxy_admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert galaxy_admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(galaxy_admin_user) def test_0005_ensure_repositories_and_categories_exist(self): diff --git a/lib/tool_shed/test/functional/test_1010_install_repository_with_tool_dependencies.py b/lib/tool_shed/test/functional/test_1010_install_repository_with_tool_dependencies.py index 7c480d46c87..60d879a9bbb 100644 --- a/lib/tool_shed/test/functional/test_1010_install_repository_with_tool_dependencies.py +++ b/lib/tool_shed/test/functional/test_1010_install_repository_with_tool_dependencies.py @@ -17,15 +17,15 @@ class ToolWithToolDependencies(ShedTwillTestCase): """Create necessary user accounts.""" self.galaxy_login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(admin_user) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_ensure_repositories_and_categories_exist(self): diff --git a/lib/tool_shed/test/functional/test_1020_install_repository_with_repository_dependencies.py b/lib/tool_shed/test/functional/test_1020_install_repository_with_repository_dependencies.py index a502a73442c..645ac0aff74 100644 --- a/lib/tool_shed/test/functional/test_1020_install_repository_with_repository_dependencies.py +++ b/lib/tool_shed/test/functional/test_1020_install_repository_with_repository_dependencies.py @@ -19,15 +19,15 @@ class ToolWithRepositoryDependencies(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) self.galaxy_login(email=common.admin_email, username=common.admin_username) galaxy_admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert galaxy_admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert galaxy_admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(galaxy_admin_user) def test_0005_ensure_repositories_and_categories_exist(self): diff --git a/lib/tool_shed/test/functional/test_1030_install_repository_with_dependency_revisions.py b/lib/tool_shed/test/functional/test_1030_install_repository_with_dependency_revisions.py index 1d0894b0786..214beef0c07 100644 --- a/lib/tool_shed/test/functional/test_1030_install_repository_with_dependency_revisions.py +++ b/lib/tool_shed/test/functional/test_1030_install_repository_with_dependency_revisions.py @@ -22,15 +22,15 @@ class RepositoryWithDependencyRevisions(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) self.galaxy_login(email=common.admin_email, username=common.admin_username) galaxy_admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert galaxy_admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert galaxy_admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(galaxy_admin_user) def test_0005_ensure_repositories_and_categories_exist(self): diff --git a/lib/tool_shed/test/functional/test_1040_install_repository_basic_circular_dependencies.py b/lib/tool_shed/test/functional/test_1040_install_repository_basic_circular_dependencies.py index f390f1a42b5..e2296c7a44f 100644 --- a/lib/tool_shed/test/functional/test_1040_install_repository_basic_circular_dependencies.py +++ b/lib/tool_shed/test/functional/test_1040_install_repository_basic_circular_dependencies.py @@ -20,11 +20,11 @@ class TestInstallingCircularDependencies(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_freebayes_repository(self): diff --git a/lib/tool_shed/test/functional/test_1050_circular_dependencies_4_levels.py b/lib/tool_shed/test/functional/test_1050_circular_dependencies_4_levels.py index e3d64b82073..25f5c5dd4ec 100644 --- a/lib/tool_shed/test/functional/test_1050_circular_dependencies_4_levels.py +++ b/lib/tool_shed/test/functional/test_1050_circular_dependencies_4_levels.py @@ -41,11 +41,11 @@ class TestInstallRepositoryCircularDependencies(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_convert_repository(self): @@ -258,7 +258,7 @@ class TestInstallRepositoryCircularDependencies(ShedTwillTestCase): for repository in [emboss_datatypes_repository, emboss_repository, column_repository]: self.check_repository_dependency(freebayes_repository, repository) freebayes_dependencies = [freebayes_repository, emboss_datatypes_repository, emboss_repository, column_repository] - strings_displayed = ['{} depends on {}.'.format(freebayes_repository.name, ', '.join(repo.name for repo in freebayes_dependencies))] + strings_displayed = [f"{freebayes_repository.name} depends on {', '.join(repo.name for repo in freebayes_dependencies)}."] self.display_manage_repository_page(freebayes_repository, strings_displayed=strings_displayed) def test_0050_verify_tool_dependencies(self): diff --git a/lib/tool_shed/test/functional/test_1070_invalid_tool.py b/lib/tool_shed/test/functional/test_1070_invalid_tool.py index cf224d01976..3cc9ecf68da 100644 --- a/lib/tool_shed/test/functional/test_1070_invalid_tool.py +++ b/lib/tool_shed/test/functional/test_1070_invalid_tool.py @@ -14,15 +14,15 @@ class TestFreebayesRepository(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.galaxy_login(email=common.admin_email, username=common.admin_username) galaxy_admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert galaxy_admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert galaxy_admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(galaxy_admin_user) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_ensure_existence_of_repository_and_category(self): diff --git a/lib/tool_shed/test/functional/test_1080_advanced_circular_dependency_installation.py b/lib/tool_shed/test/functional/test_1080_advanced_circular_dependency_installation.py index f0d5133fa56..86836956f43 100644 --- a/lib/tool_shed/test/functional/test_1080_advanced_circular_dependency_installation.py +++ b/lib/tool_shed/test/functional/test_1080_advanced_circular_dependency_installation.py @@ -25,15 +25,15 @@ class TestRepositoryDependencies(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.galaxy_login(email=common.admin_email, username=common.admin_username) galaxy_admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert galaxy_admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert galaxy_admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(galaxy_admin_user) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_and_populate_column_repository(self): diff --git a/lib/tool_shed/test/functional/test_1090_repository_dependency_handling.py b/lib/tool_shed/test/functional/test_1090_repository_dependency_handling.py index a8ddffb3935..5f30d4a8eed 100644 --- a/lib/tool_shed/test/functional/test_1090_repository_dependency_handling.py +++ b/lib/tool_shed/test/functional/test_1090_repository_dependency_handling.py @@ -23,15 +23,15 @@ class TestRepositoryDependencies(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.galaxy_login(email=common.admin_email, username=common.admin_username) galaxy_admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert galaxy_admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert galaxy_admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(galaxy_admin_user) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_and_populate_column_repository(self): diff --git a/lib/tool_shed/test/functional/test_1100_install_updated_repository_dependencies.py b/lib/tool_shed/test/functional/test_1100_install_updated_repository_dependencies.py index 7af2ef499e1..825604d7134 100644 --- a/lib/tool_shed/test/functional/test_1100_install_updated_repository_dependencies.py +++ b/lib/tool_shed/test/functional/test_1100_install_updated_repository_dependencies.py @@ -19,15 +19,15 @@ class TestRepositoryDependencies(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.galaxy_login(email=common.admin_email, username=common.admin_username) galaxy_admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert galaxy_admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert galaxy_admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(galaxy_admin_user) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_and_populate_column_repository(self): diff --git a/lib/tool_shed/test/functional/test_1120_install_repository_with_complex_dependencies.py b/lib/tool_shed/test/functional/test_1120_install_repository_with_complex_dependencies.py index fc68c4b0efa..85f70894bb0 100644 --- a/lib/tool_shed/test/functional/test_1120_install_repository_with_complex_dependencies.py +++ b/lib/tool_shed/test/functional/test_1120_install_repository_with_complex_dependencies.py @@ -22,11 +22,11 @@ class TestInstallingComplexRepositoryDependencies(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_bwa_package_repository(self): @@ -256,13 +256,13 @@ class TestInstallingComplexRepositoryDependencies(ShedTwillTestCase): env_sh_path = self.get_env_sh_path(tool_dependency_name='bwa', tool_dependency_version='0.5.9', repository=base_repository) - assert os.path.exists(env_sh_path), 'env.sh was not generated in %s for this dependency.' % env_sh_path + assert os.path.exists(env_sh_path), f'env.sh was not generated in {env_sh_path} for this dependency.' contents = open(env_sh_path).read() if tool_repository.installed_changeset_revision not in contents: raise AssertionError('Installed changeset revision %s not found in env.sh.\nContents of env.sh: %s' % (tool_repository.installed_changeset_revision, contents)) if 'package_bwa_0_5_9_0100' not in contents: - raise AssertionError('Repository name package_bwa_0_5_9_0100 not found in env.sh.\nContents of env.sh: %s' % contents) + raise AssertionError(f'Repository name package_bwa_0_5_9_0100 not found in env.sh.\nContents of env.sh: {contents}') def test_0060_verify_tool_dependency_uninstallation(self): '''Uninstall the package_bwa_0_5_9_0100 repository.''' @@ -279,4 +279,4 @@ class TestInstallingComplexRepositoryDependencies(ShedTwillTestCase): tool_repository.name, tool_repository.installed_changeset_revision, 'env.sh') - assert os.path.exists(env_sh_path), 'Path %s does not exist after deactivating the repository that generated it.' % env_sh_path + assert os.path.exists(env_sh_path), f'Path {env_sh_path} does not exist after deactivating the repository that generated it.' diff --git a/lib/tool_shed/test/functional/test_1130_install_repository_with_invalid_repository_dependency.py b/lib/tool_shed/test/functional/test_1130_install_repository_with_invalid_repository_dependency.py index 5eab6c6bfe0..91ab86e48ad 100644 --- a/lib/tool_shed/test/functional/test_1130_install_repository_with_invalid_repository_dependency.py +++ b/lib/tool_shed/test/functional/test_1130_install_repository_with_invalid_repository_dependency.py @@ -20,11 +20,11 @@ class TestBasicRepositoryDependencies(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_category(self): diff --git a/lib/tool_shed/test/functional/test_1140_simple_repository_dependency_multiple_owners.py b/lib/tool_shed/test/functional/test_1140_simple_repository_dependency_multiple_owners.py index 08af8f2c51a..f8020f5156e 100644 --- a/lib/tool_shed/test/functional/test_1140_simple_repository_dependency_multiple_owners.py +++ b/lib/tool_shed/test/functional/test_1140_simple_repository_dependency_multiple_owners.py @@ -38,15 +38,15 @@ class TestInstallRepositoryMultipleOwners(ShedTwillTestCase): """ self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.test_user_2_email, username=common.test_user_2_name) test_user_2 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_2 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_2_email + assert test_user_2 is not None, f'Problem retrieving user with email {common.test_user_2_email} from the database' self.test_db_util.get_private_role(test_user_2) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_datatypes_repository(self): diff --git a/lib/tool_shed/test/functional/test_1150_datatype_converters.py b/lib/tool_shed/test/functional/test_1150_datatype_converters.py index 2810bef4471..0244b1cdddf 100644 --- a/lib/tool_shed/test/functional/test_1150_datatype_converters.py +++ b/lib/tool_shed/test/functional/test_1150_datatype_converters.py @@ -21,15 +21,15 @@ class TestDatatypeConverters(ShedTwillTestCase): """Create necessary user accounts.""" self.galaxy_login(email=common.admin_email, username=common.admin_username) galaxy_admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert galaxy_admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert galaxy_admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(galaxy_admin_user) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_bed_to_gff_repository(self): diff --git a/lib/tool_shed/test/functional/test_1160_tool_help_images.py b/lib/tool_shed/test/functional/test_1160_tool_help_images.py index 754cba287b8..191d809238b 100644 --- a/lib/tool_shed/test/functional/test_1160_tool_help_images.py +++ b/lib/tool_shed/test/functional/test_1160_tool_help_images.py @@ -24,11 +24,11 @@ class TestToolHelpImages(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_htseq_count_repository(self): @@ -68,7 +68,7 @@ class TestToolHelpImages(ShedTwillTestCase): changeset_revision = self.get_repository_tip(repository) self.display_manage_repository_page(repository) # Generate the image path. - image_path = 'src="/repository/static/images/%s/count_modes.png"' % self.security.encode_id(repository.id) + image_path = f'src="/repository/static/images/{self.security.encode_id(repository.id)}/count_modes.png"' # The repository uploaded in this test should only have one metadata revision, with one tool defined, which # should be the tool that contains a link to the image. repository_metadata = repository.metadata_revisions[0].metadata diff --git a/lib/tool_shed/test/functional/test_1170_prior_installation_required.py b/lib/tool_shed/test/functional/test_1170_prior_installation_required.py index 0fa3ed5d710..cd9eb41372d 100644 --- a/lib/tool_shed/test/functional/test_1170_prior_installation_required.py +++ b/lib/tool_shed/test/functional/test_1170_prior_installation_required.py @@ -39,15 +39,15 @@ class TestSimplePriorInstallation(ShedTwillTestCase): """Create necessary user accounts.""" self.galaxy_login(email=common.admin_email, username=common.admin_username) galaxy_admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert galaxy_admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert galaxy_admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(galaxy_admin_user) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_convert_repository(self): diff --git a/lib/tool_shed/test/functional/test_1180_circular_prior_installation_required.py b/lib/tool_shed/test/functional/test_1180_circular_prior_installation_required.py index 74fad0b9dbb..f6a2e367d91 100644 --- a/lib/tool_shed/test/functional/test_1180_circular_prior_installation_required.py +++ b/lib/tool_shed/test/functional/test_1180_circular_prior_installation_required.py @@ -52,15 +52,15 @@ class TestSimplePriorInstallation(ShedTwillTestCase): """Create necessary user accounts.""" self.galaxy_login(email=common.admin_email, username=common.admin_username) galaxy_admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert galaxy_admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert galaxy_admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(galaxy_admin_user) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_convert_repository(self): diff --git a/lib/tool_shed/test/functional/test_1190_complex_prior_installation_required.py b/lib/tool_shed/test/functional/test_1190_complex_prior_installation_required.py index 1c828395efc..45a0c106464 100644 --- a/lib/tool_shed/test/functional/test_1190_complex_prior_installation_required.py +++ b/lib/tool_shed/test/functional/test_1190_complex_prior_installation_required.py @@ -31,11 +31,11 @@ class TestComplexPriorInstallation(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_matplotlib_repository(self): diff --git a/lib/tool_shed/test/functional/test_1200_uninstall_and_reinstall_basic_repository.py b/lib/tool_shed/test/functional/test_1200_uninstall_and_reinstall_basic_repository.py index cf50b847800..931a342cbd3 100644 --- a/lib/tool_shed/test/functional/test_1200_uninstall_and_reinstall_basic_repository.py +++ b/lib/tool_shed/test/functional/test_1200_uninstall_and_reinstall_basic_repository.py @@ -8,15 +8,15 @@ class UninstallingAndReinstallingRepositories(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) self.galaxy_login(email=common.admin_email, username=common.admin_username) galaxy_admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert galaxy_admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert galaxy_admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(galaxy_admin_user) def test_0005_ensure_repositories_and_categories_exist(self): diff --git a/lib/tool_shed/test/functional/test_1210_uninstall_reinstall_repository_with_tool_dependencies.py b/lib/tool_shed/test/functional/test_1210_uninstall_reinstall_repository_with_tool_dependencies.py index 7111255c494..46e0d75e814 100644 --- a/lib/tool_shed/test/functional/test_1210_uninstall_reinstall_repository_with_tool_dependencies.py +++ b/lib/tool_shed/test/functional/test_1210_uninstall_reinstall_repository_with_tool_dependencies.py @@ -10,15 +10,15 @@ class UninstallingAndReinstallingRepositories(ShedTwillTestCase): """Create necessary user accounts.""" self.galaxy_login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(admin_user) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_ensure_repositories_and_categories_exist(self): diff --git a/lib/tool_shed/test/functional/test_1220_uninstall_reinstall_repository_with_repository_dependencies.py b/lib/tool_shed/test/functional/test_1220_uninstall_reinstall_repository_with_repository_dependencies.py index 84637dbc3ee..da514480d1b 100644 --- a/lib/tool_shed/test/functional/test_1220_uninstall_reinstall_repository_with_repository_dependencies.py +++ b/lib/tool_shed/test/functional/test_1220_uninstall_reinstall_repository_with_repository_dependencies.py @@ -20,15 +20,15 @@ class UninstallingAndReinstallingRepositories(ShedTwillTestCase): """Create necessary user accounts.""" self.galaxy_login(email=common.admin_email, username=common.admin_username) galaxy_admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert galaxy_admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert galaxy_admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(galaxy_admin_user) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_ensure_repositories_and_categories_exist(self): diff --git a/lib/tool_shed/test/functional/test_1230_uninstall_reinstall_repository_with_dependency_revisions.py b/lib/tool_shed/test/functional/test_1230_uninstall_reinstall_repository_with_dependency_revisions.py index a2f3b21436e..8c8756d95b8 100644 --- a/lib/tool_shed/test/functional/test_1230_uninstall_reinstall_repository_with_dependency_revisions.py +++ b/lib/tool_shed/test/functional/test_1230_uninstall_reinstall_repository_with_dependency_revisions.py @@ -22,15 +22,15 @@ class UninstallingAndReinstallingRepositories(ShedTwillTestCase): """Create necessary user accounts.""" self.galaxy_login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(admin_user) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_ensure_repositories_and_categories_exist(self): diff --git a/lib/tool_shed/test/functional/test_1300_reset_all_metadata.py b/lib/tool_shed/test/functional/test_1300_reset_all_metadata.py index 6dd5829ffc5..89f994a3ee4 100644 --- a/lib/tool_shed/test/functional/test_1300_reset_all_metadata.py +++ b/lib/tool_shed/test/functional/test_1300_reset_all_metadata.py @@ -44,11 +44,11 @@ class TestResetInstalledRepositoryMetadata(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_categories(self): diff --git a/lib/tool_shed/test/functional/test_1410_update_manager.py b/lib/tool_shed/test/functional/test_1410_update_manager.py index 1de705e407f..ca5cb31d5c1 100644 --- a/lib/tool_shed/test/functional/test_1410_update_manager.py +++ b/lib/tool_shed/test/functional/test_1410_update_manager.py @@ -31,15 +31,15 @@ class TestUpdateManager(ShedTwillTestCase): """ self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) self.galaxy_login(email=common.admin_email, username=common.admin_username) galaxy_admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert galaxy_admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert galaxy_admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(galaxy_admin_user) def test_0005_create_filtering_repository(self): diff --git a/lib/tool_shed/test/functional/test_1420_tool_dependency_environment_inheritance.py b/lib/tool_shed/test/functional/test_1420_tool_dependency_environment_inheritance.py index 1a8cc08fd95..ba3061defdb 100644 --- a/lib/tool_shed/test/functional/test_1420_tool_dependency_environment_inheritance.py +++ b/lib/tool_shed/test/functional/test_1420_tool_dependency_environment_inheritance.py @@ -59,16 +59,16 @@ class TestEnvironmentInheritance(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) self.create_category(name=category_name, description=category_description) self.login(email=common.test_user_2_email, username=common.test_user_2_name) test_user_2 = self.test_db_util.get_user(common.test_user_2_email) - assert test_user_2 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_2_email + assert test_user_2 is not None, f'Problem retrieving user with email {common.test_user_2_email} from the database' self.test_db_util.get_private_role(test_user_2) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) def test_0005_create_lapack_repository(self): diff --git a/lib/tool_shed/test/functional/test_1430_repair_installed_repository.py b/lib/tool_shed/test/functional/test_1430_repair_installed_repository.py index 4b429523965..0d60dfb6362 100644 --- a/lib/tool_shed/test/functional/test_1430_repair_installed_repository.py +++ b/lib/tool_shed/test/functional/test_1430_repair_installed_repository.py @@ -38,16 +38,16 @@ class TestRepairRepository(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) self.create_category(name=category_name, description=category_description) self.login(email=common.test_user_2_email, username=common.test_user_2_name) test_user_2 = self.test_db_util.get_user(common.test_user_2_email) - assert test_user_2 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_2_email + assert test_user_2 is not None, f'Problem retrieving user with email {common.test_user_2_email} from the database' self.test_db_util.get_private_role(test_user_2) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) def test_0005_create_filter_repository(self): diff --git a/lib/tool_shed/test/functional/test_1440_missing_env_sh_files.py b/lib/tool_shed/test/functional/test_1440_missing_env_sh_files.py index db98db7aad7..7447b40f335 100644 --- a/lib/tool_shed/test/functional/test_1440_missing_env_sh_files.py +++ b/lib/tool_shed/test/functional/test_1440_missing_env_sh_files.py @@ -32,16 +32,16 @@ class TestMissingEnvSh(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) self.create_category(name=category_name, description=category_description) self.login(email=common.test_user_2_email, username=common.test_user_2_name) test_user_2 = self.test_db_util.get_user(common.test_user_2_email) - assert test_user_2 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_2_email + assert test_user_2 is not None, f'Problem retrieving user with email {common.test_user_2_email} from the database' self.test_db_util.get_private_role(test_user_2) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) def test_0005_create_package_repository(self): diff --git a/lib/tool_shed/test/functional/test_1450_installing_datatypes_sniffers.py b/lib/tool_shed/test/functional/test_1450_installing_datatypes_sniffers.py index d4655ca486a..f8c720b68a4 100644 --- a/lib/tool_shed/test/functional/test_1450_installing_datatypes_sniffers.py +++ b/lib/tool_shed/test/functional/test_1450_installing_datatypes_sniffers.py @@ -28,15 +28,15 @@ class TestInstallDatatypesSniffers(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) self.galaxy_login(email=common.admin_email, username=common.admin_username) galaxy_admin_user = self.test_db_util.get_galaxy_user(common.admin_email) - assert galaxy_admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert galaxy_admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_galaxy_private_role(galaxy_admin_user) def test_0005_ensure_repositories_and_categories_exist(self): diff --git a/lib/tool_shed/test/functional/test_1460_data_managers.py b/lib/tool_shed/test/functional/test_1460_data_managers.py index dac5908b103..98a8d6c20d7 100644 --- a/lib/tool_shed/test/functional/test_1460_data_managers.py +++ b/lib/tool_shed/test/functional/test_1460_data_managers.py @@ -31,16 +31,16 @@ class TestDataManagers(ShedTwillTestCase): """Create necessary user accounts and login as an admin user.""" self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) self.create_category(name=category_name, description=category_description) self.login(email=common.test_user_2_email, username=common.test_user_2_name) test_user_2 = self.test_db_util.get_user(common.test_user_2_email) - assert test_user_2 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_2_email + assert test_user_2 is not None, f'Problem retrieving user with email {common.test_user_2_email} from the database' self.test_db_util.get_private_role(test_user_2) self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) def test_0010_create_data_manager_repository(self): @@ -64,7 +64,7 @@ class TestDataManagers(ShedTwillTestCase): valid_tools_only=True, uncompress_file=True, remove_repo_files_not_in_tar=False, - commit_message='Populate %s with a data manager configuration.' % data_manager_repository_name, + commit_message=f'Populate {data_manager_repository_name} with a data manager configuration.', strings_displayed=[], strings_not_displayed=[]) diff --git a/lib/tool_shed/test/functional/test_1470_updating_installed_repositories.py b/lib/tool_shed/test/functional/test_1470_updating_installed_repositories.py index c52c779861f..53914d4ff0c 100644 --- a/lib/tool_shed/test/functional/test_1470_updating_installed_repositories.py +++ b/lib/tool_shed/test/functional/test_1470_updating_installed_repositories.py @@ -28,11 +28,11 @@ class TestUpdateInstalledRepository(ShedTwillTestCase): """Create necessary user accounts.""" self.login(email=common.test_user_1_email, username=common.test_user_1_name) test_user_1 = self.test_db_util.get_user(common.test_user_1_email) - assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + assert test_user_1 is not None, f'Problem retrieving user with email {common.test_user_1_email} from the database' self.test_db_util.get_private_role(test_user_1) self.login(email=common.admin_email, username=common.admin_username) admin_user = self.test_db_util.get_user(common.admin_email) - assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + assert admin_user is not None, f'Problem retrieving user with email {common.admin_email} from the database' self.test_db_util.get_private_role(admin_user) def test_0005_create_filtering_repository(self): diff --git a/lib/tool_shed/util/admin_util.py b/lib/tool_shed/util/admin_util.py index a20c65c48d3..dea466e101e 100644 --- a/lib/tool_shed/util/admin_util.py +++ b/lib/tool_shed/util/admin_util.py @@ -298,7 +298,7 @@ class Admin: role.deleted = True trans.sa_session.add(role) trans.sa_session.flush() - message += " %s " % role.name + message += f" {role.name} " trans.response.send_redirect(web.url_for(controller='admin', action='roles', message=util.sanitize_text(message), @@ -320,7 +320,7 @@ class Admin: for role_id in ids: role = get_role(trans, role_id) if not role.deleted: - message = "Role '%s' has not been deleted, so it cannot be undeleted." % role.name + message = f"Role '{role.name}' has not been deleted, so it cannot be undeleted." trans.response.send_redirect(web.url_for(controller='admin', action='roles', message=util.sanitize_text(message), @@ -329,7 +329,7 @@ class Admin: trans.sa_session.add(role) trans.sa_session.flush() count += 1 - undeleted_roles += " %s" % role.name + undeleted_roles += f" {role.name}" message = "Undeleted %d roles: %s" % (count, undeleted_roles) trans.response.send_redirect(web.url_for(controller='admin', action='roles', @@ -358,7 +358,7 @@ class Admin: for role_id in ids: role = get_role(trans, role_id) if not role.deleted: - message = "Role '%s' has not been deleted, so it cannot be purged." % role.name + message = f"Role '{role.name}' has not been deleted, so it cannot be purged." trans.response.send_redirect(web.url_for(controller='admin', action='roles', message=util.sanitize_text(message), @@ -383,7 +383,7 @@ class Admin: for dp in role.dataset_actions: trans.sa_session.delete(dp) trans.sa_session.flush() - message += " %s " % role.name + message += f" {role.name} " trans.response.send_redirect(web.url_for(controller='admin', action='roles', message=util.sanitize_text(message), @@ -534,7 +534,7 @@ class Admin: trans.sa_session.add(gra) if create_role_for_group_checked: # Create the role - role = trans.app.model.Role(name=name, description='Role for group %s' % name) + role = trans.app.model.Role(name=name, description=f'Role for group {name}') trans.sa_session.add(role) # Associate the role with the group gra = trans.model.GroupRoleAssociation(group, role) @@ -588,7 +588,7 @@ class Admin: group.deleted = True trans.sa_session.add(group) trans.sa_session.flush() - message += " %s " % group.name + message += f" {group.name} " trans.response.send_redirect(web.url_for(controller='admin', action='groups', message=util.sanitize_text(message), @@ -610,7 +610,7 @@ class Admin: for group_id in ids: group = get_group(trans, group_id) if not group.deleted: - message = "Group '%s' has not been deleted, so it cannot be undeleted." % group.name + message = f"Group '{group.name}' has not been deleted, so it cannot be undeleted." trans.response.send_redirect(web.url_for(controller='admin', action='groups', message=util.sanitize_text(message), @@ -619,7 +619,7 @@ class Admin: trans.sa_session.add(group) trans.sa_session.flush() count += 1 - undeleted_groups += " %s" % group.name + undeleted_groups += f" {group.name}" message = "Undeleted %d groups: %s" % (count, undeleted_groups) trans.response.send_redirect(web.url_for(controller='admin', action='groups', @@ -644,7 +644,7 @@ class Admin: group = get_group(trans, group_id) if not group.deleted: # We should never reach here, but just in case there is a bug somewhere... - message = "Group '%s' has not been deleted, so it cannot be purged." % group.name + message = f"Group '{group.name}' has not been deleted, so it cannot be purged." trans.response.send_redirect(web.url_for(controller='admin', action='groups', message=util.sanitize_text(message), @@ -656,7 +656,7 @@ class Admin: for gra in group.roles: trans.sa_session.delete(gra) trans.sa_session.flush() - message += " %s " % group.name + message += f" {group.name} " trans.response.send_redirect(web.url_for(controller='admin', action='groups', message=util.sanitize_text(message), @@ -727,7 +727,7 @@ class Admin: user = get_user(trans, user_id) user.deleted = True - compliance_log.info('delete-user-event: %s' % user_id) + compliance_log.info(f'delete-user-event: {user_id}') # See lib/galaxy/webapps/tool_shed/controllers/admin.py pseudorandom_value = str(int(time.time())) email_hash = new_secure_hash(user.email + pseudorandom_value) @@ -749,7 +749,7 @@ class Admin: trans.sa_session.add(user) trans.sa_session.flush() - message += " %s " % user.email + message += f" {user.email} " trans.response.send_redirect(web.url_for(controller='admin', action='users', message=util.sanitize_text(message), @@ -771,7 +771,7 @@ class Admin: for user_id in ids: user = get_user(trans, user_id) if not user.deleted: - message = "User '%s' has not been deleted, so it cannot be undeleted." % user.email + message = f"User '{user.email}' has not been deleted, so it cannot be undeleted." trans.response.send_redirect(web.url_for(controller='admin', action='users', message=util.sanitize_text(message), @@ -780,7 +780,7 @@ class Admin: trans.sa_session.add(user) trans.sa_session.flush() count += 1 - undeleted_users += " %s" % user.email + undeleted_users += f" {user.email}" message = "Undeleted %d users: %s" % (count, undeleted_users) trans.response.send_redirect(web.url_for(controller='admin', action='users', @@ -815,7 +815,7 @@ class Admin: user = get_user(trans, user_id) if not user.deleted: # We should never reach here, but just in case there is a bug somewhere... - message = "User '%s' has not been deleted, so it cannot be purged." % user.email + message = f"User '{user.email}' has not been deleted, so it cannot be purged." trans.response.send_redirect(web.url_for(controller='admin', action='users', message=util.sanitize_text(message), @@ -849,7 +849,7 @@ class Admin: user.purged = True trans.sa_session.add(user) trans.sa_session.flush() - message += "%s " % user.email + message += f"{user.email} " trans.response.send_redirect(web.url_for(controller='admin', action='users', message=util.sanitize_text(message), @@ -901,7 +901,7 @@ class Admin: message = '' status = '' if not user_id: - message += "Invalid user id (%s) received" % str(user_id) + message += f"Invalid user id ({str(user_id)}) received" trans.response.send_redirect(web.url_for(controller='admin', action='users', message=util.sanitize_text(message), @@ -975,7 +975,7 @@ def get_user(trans, user_id): """Get a User from the database by id.""" user = trans.sa_session.query(trans.model.User).get(trans.security.decode_id(user_id)) if not user: - return trans.show_error_message("User not found for id (%s)" % str(user_id)) + return trans.show_error_message(f"User not found for id ({str(user_id)})") return user @@ -985,7 +985,7 @@ def get_role(trans, id): id = trans.security.decode_id(id) role = trans.sa_session.query(trans.model.Role).get(id) if not role: - return trans.show_error_message("Role not found for id (%s)" % str(id)) + return trans.show_error_message(f"Role not found for id ({str(id)})") return role @@ -995,5 +995,5 @@ def get_group(trans, id): id = trans.security.decode_id(id) group = trans.sa_session.query(trans.model.Group).get(id) if not group: - return trans.show_error_message("Group not found for id (%s)" % str(id)) + return trans.show_error_message(f"Group not found for id ({str(id)})") return group diff --git a/lib/tool_shed/util/commit_util.py b/lib/tool_shed/util/commit_util.py index 995e30d1ceb..845d52c441d 100644 --- a/lib/tool_shed/util/commit_util.py +++ b/lib/tool_shed/util/commit_util.py @@ -82,9 +82,9 @@ def check_file_contents_for_email_alerts(app): def check_file_content_for_html_and_images(file_path): message = '' if checkers.check_html(file_path): - message = 'The file "%s" contains HTML content.\n' % str(file_path) + message = f'The file "{str(file_path)}" contains HTML content.\n' elif checkers.check_image(file_path): - message = 'The file "%s" contains image content.\n' % str(file_path) + message = f'The file "{str(file_path)}" contains image content.\n' return message @@ -179,7 +179,7 @@ def handle_directory_changes(app, host, username, repository, full_path, filenam try: hg_util.remove_file(repo_path, repo_file, force=True) except Exception as e: - log.debug("Error removing files using the mercurial API, so trying a different approach, the error was: %s" % str(e)) + log.debug(f"Error removing files using the mercurial API, so trying a different approach, the error was: {str(e)}") relative_selected_file = repo_file.split('repo_%d' % repository.id)[1].lstrip('/') repo.dirstate.remove(relative_selected_file) repo.dirstate.write() diff --git a/lib/tool_shed/util/hg_util.py b/lib/tool_shed/util/hg_util.py index 78d1a49d4ab..f7de9b28884 100644 --- a/lib/tool_shed/util/hg_util.py +++ b/lib/tool_shed/util/hg_util.py @@ -29,9 +29,9 @@ def add_changeset(repo_path, path_to_filename_in_archive): try: subprocess.check_output(['hg', 'add', path_to_filename_in_archive], stderr=subprocess.STDOUT, cwd=repo_path) except Exception as e: - error_message = "Error adding '{}' to repository: {}".format(path_to_filename_in_archive, unicodify(e)) + error_message = f"Error adding '{path_to_filename_in_archive}' to repository: {unicodify(e)}" if isinstance(e, subprocess.CalledProcessError): - error_message += "\nOutput was:\n%s" % unicodify(e.output) + error_message += f"\nOutput was:\n{unicodify(e.output)}" raise Exception(error_message) @@ -41,9 +41,9 @@ def archive_repository_revision(app, repository, archive_dir, changeset_revision try: subprocess.check_output(['hg', 'archive', '-r', changeset_revision, archive_dir], stderr=subprocess.STDOUT, cwd=repo_path) except Exception as e: - error_message = "Error attempting to archive revision '{}' of repository '{}': {}".format(changeset_revision, repository.name, unicodify(e)) + error_message = f"Error attempting to archive revision '{changeset_revision}' of repository '{repository.name}': {unicodify(e)}" if isinstance(e, subprocess.CalledProcessError): - error_message += "\nOutput was:\n%s" % unicodify(e.output) + error_message += f"\nOutput was:\n{unicodify(e.output)}" log.exception(error_message) raise Exception(error_message) @@ -52,11 +52,11 @@ def commit_changeset(repo_path, full_path_to_changeset, username, message): try: subprocess.check_output(['hg', 'commit', '-u', username, '-m', message, full_path_to_changeset], stderr=subprocess.STDOUT, cwd=repo_path) except Exception as e: - error_message = "Error committing '{}' to repository: {}".format(full_path_to_changeset, unicodify(e)) + error_message = f"Error committing '{full_path_to_changeset}' to repository: {unicodify(e)}" if isinstance(e, subprocess.CalledProcessError): if e.returncode == 1 and 'nothing changed' in unicodify(e.output): return - error_message += "\nOutput was:\n%s" % unicodify(e.output) + error_message += f"\nOutput was:\n{unicodify(e.output)}" raise Exception(error_message) @@ -78,8 +78,8 @@ def create_hgrc_file(app, repository): fp.write('default = .\n') fp.write('default-push = .\n') fp.write('[web]\n') - fp.write('allow_push = %s\n' % repository.user.username) - fp.write('name = %s\n' % repository.name) + fp.write(f'allow_push = {repository.user.username}\n') + fp.write(f'name = {repository.name}\n') fp.write('push_ssl = false\n') fp.write('[extensions]\n') fp.write('hgext.purge=') @@ -145,7 +145,7 @@ def get_revision_label(app, repository, changeset_revision, include_date=True, i return get_revision_label_from_ctx(ctx, include_date=include_date, include_hash=include_hash) else: if include_hash: - return "-1:%s" % changeset_revision + return f"-1:{changeset_revision}" else: return "-1" @@ -162,18 +162,18 @@ def get_rev_label_changeset_revision_from_repository_metadata(app, repository_me if include_date: changeset_revision_date = get_readable_ctx_date(ctx) if include_hash: - label = "{}:{} ({})".format(str(ctx.rev()), changeset_revision, changeset_revision_date) + label = f"{str(ctx.rev())}:{changeset_revision} ({changeset_revision_date})" else: - label = "{} ({})".format(str(ctx.rev()), changeset_revision_date) + label = f"{str(ctx.rev())} ({changeset_revision_date})" else: if include_hash: - label = "{}:{}".format(str(ctx.rev()), changeset_revision) + label = f"{str(ctx.rev())}:{changeset_revision}" else: - label = "%s" % str(ctx.rev()) + label = f"{str(ctx.rev())}" else: rev = '-1' if include_hash: - label = "-1:%s" % changeset_revision + label = f"-1:{changeset_revision}" else: label = "-1" return rev, label, changeset_revision @@ -189,7 +189,7 @@ def get_revision_label_from_ctx(ctx, include_date=True, include_hash=True): (str(ctx.rev()), str(get_readable_ctx_date(ctx))) else: if include_hash: - return '{}:{}'.format(str(ctx.rev()), str(ctx)) + return f'{str(ctx.rev())}:{str(ctx)}' else: return str(ctx.rev()) @@ -205,7 +205,7 @@ def get_rev_label_from_changeset_revision(repo, changeset_revision, include_date label = get_revision_label_from_ctx(ctx, include_date=include_date) else: rev = '-1' - label = "-1:%s" % changeset_revision + label = f"-1:{changeset_revision}" return rev, label @@ -217,9 +217,9 @@ def remove_file(repo_path, selected_file, force=True): try: subprocess.check_output(cmd, stderr=subprocess.STDOUT, cwd=repo_path) except Exception as e: - error_message = "Error removing file '{}': {}".format(selected_file, unicodify(e)) + error_message = f"Error removing file '{selected_file}': {unicodify(e)}" if isinstance(e, subprocess.CalledProcessError): - error_message += "\nOutput was:\n%s" % unicodify(e.output) + error_message += f"\nOutput was:\n{unicodify(e.output)}" raise Exception(error_message) @@ -230,9 +230,9 @@ def init_repository(repo_path): try: subprocess.check_output(['hg', 'init'], stderr=subprocess.STDOUT, cwd=repo_path) except Exception as e: - error_message = 'Error initializing repository: %s' % unicodify(e) + error_message = f'Error initializing repository: {unicodify(e)}' if isinstance(e, subprocess.CalledProcessError): - error_message += "\nOutput was:\n%s" % unicodify(e.output) + error_message += f"\nOutput was:\n{unicodify(e.output)}" raise Exception(error_message) @@ -243,9 +243,9 @@ def changeset2rev(repo_path, changeset_revision): try: rev = subprocess.check_output(['hg', 'id', '-r', changeset_revision, '-n'], stderr=subprocess.STDOUT, cwd=repo_path) except Exception as e: - error_message = "Error looking for changeset '{}': {}".format(changeset_revision, unicodify(e)) + error_message = f"Error looking for changeset '{changeset_revision}': {unicodify(e)}" if isinstance(e, subprocess.CalledProcessError): - error_message += "\nOutput was:\n%s" % unicodify(e.output) + error_message += f"\nOutput was:\n{unicodify(e.output)}" raise Exception(error_message) return int(rev.strip()) diff --git a/lib/tool_shed/util/hgweb_config.py b/lib/tool_shed/util/hgweb_config.py index b3444fd3825..870dadf7ae7 100644 --- a/lib/tool_shed/util/hgweb_config.py +++ b/lib/tool_shed/util/hgweb_config.py @@ -78,7 +78,7 @@ class HgWebConfigManager: # We used to raise an exception here... # raise Exception( "Required file %s does not exist - check config setting for hgweb_config_dir." % hgweb_config ) # ...but now we just log the missing file and create a new empty one. - log.debug("Required file %s does not exist, so creating a new, empty file. Check your config setting for hgweb_config_dir." % hgweb_config) + log.debug(f"Required file {hgweb_config} does not exist, so creating a new, empty file. Check your config setting for hgweb_config_dir.") with open(hgweb_config, 'w') as hgweb_config_file: hgweb_config_file.write(new_hgweb_config_template) return os.path.abspath(hgweb_config) @@ -87,7 +87,7 @@ class HgWebConfigManager: # Make a backup of the hgweb.config file. today = date.today() backup_date = today.strftime("%Y_%m_%d") - hgweb_config_backup_filename = 'hgweb.config_%s_backup' % backup_date + hgweb_config_backup_filename = f'hgweb.config_{backup_date}_backup' hgweb_config_copy = os.path.join(self.hgweb_config_dir, hgweb_config_backup_filename) shutil.copy(os.path.abspath(self.hgweb_config), os.path.abspath(hgweb_config_copy)) diff --git a/lib/tool_shed/util/repository_util.py b/lib/tool_shed/util/repository_util.py index 6a569b56357..2b0418e389a 100644 --- a/lib/tool_shed/util/repository_util.py +++ b/lib/tool_shed/util/repository_util.py @@ -192,7 +192,7 @@ def create_repository(app, name, type, description, long_description, user_id, c sa_session.flush() # Update the repository registry. app.repository_registry.add_entry(repository) - message = "Repository %s has been created." % escape(str(repository.name)) + message = f"Repository {escape(str(repository.name))} has been created." return repository, message @@ -201,7 +201,7 @@ def generate_sharable_link_for_repository_in_tool_shed(repository, changeset_rev base_url = web.url_for('/', qualified=True).rstrip('/') sharable_url = f'{base_url}/view/{repository.user.username}/{repository.name}' if changeset_revision: - sharable_url += '/%s' % changeset_revision + sharable_url += f'/{changeset_revision}' return sharable_url @@ -330,14 +330,14 @@ def get_tool_shed_repository_status_label(app, tool_shed_repository=None, name=N app.install_model.ToolShedRepository.installation_status.INSTALLING_REPOSITORY_DEPENDENCIES) elif tool_shed_repository.missing_repository_dependencies: bgcolor = app.install_model.ToolShedRepository.states.WARNING - status_label = '%s, missing repository dependencies' % status_label + status_label = f'{status_label}, missing repository dependencies' elif tool_shed_repository.tool_dependencies_being_installed: bgcolor = app.install_model.ToolShedRepository.states.WARNING status_label = '{}, {}'.format(status_label, app.install_model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES) elif tool_shed_repository.missing_tool_dependencies: bgcolor = app.install_model.ToolShedRepository.states.WARNING - status_label = '%s, missing tool dependencies' % status_label + status_label = f'{status_label}, missing tool dependencies' else: bgcolor = app.install_model.ToolShedRepository.states.OK else: @@ -463,7 +463,7 @@ def update_repository(app, trans, id, **kwds): repo_dir = repository.repo_path(app) # Change the entry in the hgweb.config file for the repository. old_lhs = f"repos/{repository.user.username}/{repository.name}" - new_lhs = "repos/{}/{}".format(repository.user.username, kwds['name']) + new_lhs = f"repos/{repository.user.username}/{kwds['name']}" trans.app.hgweb_config_manager.change_entry(old_lhs, new_lhs, repo_dir) # Change the entry in the repository's hgrc file. @@ -495,13 +495,13 @@ def validate_repository_name(app, name, user): if name in ['None', None, '']: return 'Enter the required repository name.' if name in ['repos']: - return "The term '%s' is a reserved word in the Tool Shed, so it cannot be used as a repository name." % name + return f"The term '{name}' is a reserved word in the Tool Shed, so it cannot be used as a repository name." check_existing = get_repository_by_name_and_owner(app, name, user.username) if check_existing is not None: if check_existing.deleted: - return 'You own a deleted repository named %s, please choose a different name.' % escape(name) + return f'You own a deleted repository named {escape(name)}, please choose a different name.' else: - return "You already own a repository named %s, please choose a different name." % escape(name) + return f"You already own a repository named {escape(name)}, please choose a different name." if len(name) < 2: return "Repository names must be at least 2 characters in length." if len(name) > 80: diff --git a/lib/tool_shed/util/shed_index.py b/lib/tool_shed/util/shed_index.py index f9e5a3d2d6f..efe33007f3c 100644 --- a/lib/tool_shed/util/shed_index.py +++ b/lib/tool_shed/util/shed_index.py @@ -157,7 +157,7 @@ def debug_handler(path, exc_info): By default the underlying tool parsing logs warnings for each exception. This is very chatty hence this metod changes it to debug level. """ - log.debug("Failed to load tool with path %s." % path, exc_info=exc_info) + log.debug(f"Failed to load tool with path {path}.", exc_info=exc_info) def load_one_dir(path): diff --git a/lib/tool_shed/util/shed_util_common.py b/lib/tool_shed/util/shed_util_common.py index aeea59f8b97..87c5f60cc69 100644 --- a/lib/tool_shed/util/shed_util_common.py +++ b/lib/tool_shed/util/shed_util_common.py @@ -205,7 +205,7 @@ def get_repository_file_contents(app, file_path, repository_id, is_admin=False): return '
    Binary file
    ' else: for line in open(file_path): - safe_str = '{}{}'.format(safe_str, basic_util.to_html_string(line)) + safe_str = f'{safe_str}{basic_util.to_html_string(line)}' # Stop reading after string is larger than MAX_CONTENT_SIZE. if len(safe_str) > MAX_CONTENT_SIZE: large_str = \ @@ -372,7 +372,7 @@ def handle_email_alerts(app, host, repository, content_alert_str='', new_repo_al admin_users = app.config.get("admin_users", "").split(",") frm = email_from if new_repo_alert: - subject = "Galaxy tool shed alert for new repository named %s" % str(repository.name) + subject = f"Galaxy tool shed alert for new repository named {str(repository.name)}" subject = subject[:80] email_alerts = [] for user in sa_session.query(app.model.User) \ @@ -458,8 +458,8 @@ def open_repository_files_folder(app, folder_path, repository_id, is_admin=False if filename: if os.path.isdir(full_path) and path_is_browsable: # Append a '/' character so that our jquery dynatree will function properly. - filename = '%s/' % filename - full_path = '%s/' % full_path + filename = f'{filename}/' + full_path = f'{full_path}/' is_folder = True node = {"title": filename, "isFolder": is_folder, diff --git a/lib/tool_shed/utility_containers/__init__.py b/lib/tool_shed/utility_containers/__init__.py index 8d75cdd1e62..13327535656 100644 --- a/lib/tool_shed/utility_containers/__init__.py +++ b/lib/tool_shed/utility_containers/__init__.py @@ -357,4 +357,4 @@ class ToolShedUtilityContainerManager(utility_container_manager.UtilityContainer return containers_dict def generate_tool_dependencies_key(self, name, version, type): - return '{}{}{}{}{}'.format(str(name), container_util.STRSEP, str(version), container_util.STRSEP, str(type)) + return f'{str(name)}{container_util.STRSEP}{str(version)}{container_util.STRSEP}{str(type)}' diff --git a/lib/tool_shed/utility_containers/utility_container_manager.py b/lib/tool_shed/utility_containers/utility_container_manager.py index 1b147b4aefd..df0a75c52f9 100644 --- a/lib/tool_shed/utility_containers/utility_container_manager.py +++ b/lib/tool_shed/utility_containers/utility_container_manager.py @@ -709,9 +709,9 @@ class UtilityContainerManager: self.app.security.encode_id(tool_shed_repository_id)) if tool_shed_repository: if tool_shed_repository.missing_repository_dependencies: - installation_status = '%s, missing repository dependencies' % installation_status + installation_status = f'{installation_status}, missing repository dependencies' elif tool_shed_repository.missing_tool_dependencies: - installation_status = '%s, missing tool dependencies' % installation_status + installation_status = f'{installation_status}, missing tool dependencies' return tool_shed_repository_id, installation_status, repository_dependency def get_folder(self, folder, key): diff --git a/lib/tool_shed/webapp/api/categories.py b/lib/tool_shed/webapp/api/categories.py index 414a679ed64..707dc967b89 100644 --- a/lib/tool_shed/webapp/api/categories.py +++ b/lib/tool_shed/webapp/api/categories.py @@ -58,7 +58,7 @@ class CategoriesController(BaseAPIController): trans.sa_session.flush() category_dict = category.to_dict(view='element', value_mapper=self.__get_value_mapper(trans)) - category_dict['message'] = "Category '%s' has been created" % str(category.name) + category_dict['message'] = f"Category '{str(category.name)}' has been created" category_dict['url'] = web.url_for(controller='categories', action='show', id=trans.security.encode_id(category.id)) @@ -85,7 +85,7 @@ class CategoriesController(BaseAPIController): page = kwd.get('page', None) category = suc.get_category(self.app, category_id) if category is None: - category_dict = dict(message='Unable to locate category record for id %s.' % (str(id)), + category_dict = dict(message=f'Unable to locate category record for id {str(id)}.', status='error') return category_dict category_dict = category.to_dict(view='element', @@ -141,7 +141,7 @@ class CategoriesController(BaseAPIController): """ category = suc.get_category(self.app, id) if category is None: - category_dict = dict(message='Unable to locate category record for id %s.' % (str(id)), + category_dict = dict(message=f'Unable to locate category record for id {str(id)}.', status='error') return category_dict category_dict = category.to_dict(view='element', diff --git a/lib/tool_shed/webapp/api/groups.py b/lib/tool_shed/webapp/api/groups.py index ff38ed6c81d..a7479ca93a6 100644 --- a/lib/tool_shed/webapp/api/groups.py +++ b/lib/tool_shed/webapp/api/groups.py @@ -91,7 +91,7 @@ class GroupsController(BaseAPIController): decoded_id = trans.security.decode_id(encoded_id) group = self.group_manager.get(trans, decoded_id) if group is None: - raise ObjectNotFound('Unable to locate group record for id %s.' % (str(encoded_id))) + raise ObjectNotFound(f'Unable to locate group record for id {str(encoded_id)}.') return self._populate(trans, group) def _populate(self, trans, group): diff --git a/lib/tool_shed/webapp/api/repositories.py b/lib/tool_shed/webapp/api/repositories.py index 82a24d2e22d..40a49689664 100644 --- a/lib/tool_shed/webapp/api/repositories.py +++ b/lib/tool_shed/webapp/api/repositories.py @@ -81,7 +81,7 @@ class RepositoriesController(BaseAPIController): raise HTTPBadRequest(detail="Missing required parameter 'owner'.") repository = repository_util.get_repository_by_name_and_owner(self.app, name, owner) if repository is None: - error_message = 'Cannot locate repository with name {} and owner {},'.format(str(name), str(owner)) + error_message = f'Cannot locate repository with name {str(name)} and owner {str(owner)},' log.debug(error_message) response_dict['status'] = 'error' response_dict['message'] = error_message @@ -206,7 +206,7 @@ class RepositoriesController(BaseAPIController): # Get the repository information. repository = repository_util.get_repository_by_name_and_owner(self.app, name, owner, eagerload_columns=['downloadable_revisions']) if repository is None: - log.debug('Cannot locate repository {} owned by {}'.format(str(name), str(owner))) + log.debug(f'Cannot locate repository {str(name)} owned by {str(owner)}') return {}, {}, {} encoded_repository_id = trans.security.encode_id(repository.id) repository_dict = repository.to_dict(view='element', @@ -339,7 +339,7 @@ class RepositoriesController(BaseAPIController): callback = kwd.get('callback', 'callback') search_results = self._search(trans, q, page, page_size) if return_jsonp: - response = str('{}({});'.format(callback, json.dumps(search_results))) + response = str(f'{callback}({json.dumps(search_results)});') else: response = json.dumps(search_results) return response @@ -378,7 +378,7 @@ class RepositoriesController(BaseAPIController): metadata_dict['tool_dependencies'] = {} if metadata.includes_tools: metadata_dict['tools'] = metadata.metadata['tools'] - all_metadata['{}:{}'.format(int(changeset), changehash)] = metadata_dict + all_metadata[f'{int(changeset)}:{changehash}'] = metadata_dict if repository_found is not None: all_metadata['current_changeset'] = repository_found[0] # all_metadata[ 'found_changesets' ] = repository_found @@ -474,7 +474,7 @@ class RepositoriesController(BaseAPIController): raise HTTPBadRequest(detail="Missing required parameter 'owner'.") repository = repository_util.get_repository_by_name_and_owner(self.app, name, owner) if repository is None: - error_message = 'Cannot locate repository with name {} and owner {},'.format(str(name), str(owner)) + error_message = f'Cannot locate repository with name {str(name)} and owner {str(owner)},' log.debug(error_message) response_dict['status'] = 'error' response_dict['message'] = error_message @@ -543,7 +543,7 @@ class RepositoriesController(BaseAPIController): """ def handle_repository(trans, rmm, repository, results): - log.debug("Resetting metadata on repository %s" % str(repository.name)) + log.debug(f"Resetting metadata on repository {str(repository.name)}") try: rmm.set_repository(repository) rmm.reset_all_metadata_on_repository_in_tool_shed() @@ -563,7 +563,7 @@ class RepositoriesController(BaseAPIController): message = "Error resetting metadata on repository %s owned by %s: %s" % \ (str(repository.name), str(repository.user.username), util.unicodify(e)) results['unsuccessful_count'] += 1 - status = '{} : {}'.format(str(repository.name), message) + status = f'{str(repository.name)} : {message}' results['repository_status'].append(status) return results rmm = repository_metadata_manager.RepositoryMetadataManager(app=self.app, @@ -653,7 +653,7 @@ class RepositoriesController(BaseAPIController): message = "Error resetting metadata on repository %s owned by %s: %s" % \ (str(repository.name), str(repository.user.username), util.unicodify(e)) results['status'] = 'error' - status = '{} : {}'.format(str(repository.name), message) + status = f'{str(repository.name)} : {message}' results['repository_status'].append(status) return results @@ -661,7 +661,7 @@ class RepositoriesController(BaseAPIController): if repository_id is not None: repository = repository_util.get_repository_in_tool_shed(self.app, repository_id) start_time = strftime("%Y-%m-%d %H:%M:%S") - log.debug("{}...resetting metadata on repository {}".format(start_time, str(repository.name))) + log.debug(f"{start_time}...resetting metadata on repository {str(repository.name)}") results = handle_repository(trans, start_time, repository) stop_time = strftime("%Y-%m-%d %H:%M:%S") results['stop_time'] = stop_time @@ -819,7 +819,7 @@ class RepositoriesController(BaseAPIController): metadata_dict['tool_dependencies'] = {} if metadata.includes_tools: metadata_dict['tools'] = metadata.metadata['tools'] - all_metadata['{}:{}'.format(int(changeset), changehash)] = metadata_dict + all_metadata[f'{int(changeset)}:{changehash}'] = metadata_dict return all_metadata @expose_api diff --git a/lib/tool_shed/webapp/api/repository_revisions.py b/lib/tool_shed/webapp/api/repository_revisions.py index 100a48a8b0b..9ba52661d2d 100644 --- a/lib/tool_shed/webapp/api/repository_revisions.py +++ b/lib/tool_shed/webapp/api/repository_revisions.py @@ -74,11 +74,11 @@ class RepositoryRevisionsController(BaseAPIController): repository_dependencies_dicts = [] repository_metadata = metadata_util.get_repository_metadata_by_id(trans.app, id) if repository_metadata is None: - log.debug('Invalid repository_metadata id received: %s' % str(id)) + log.debug(f'Invalid repository_metadata id received: {str(id)}') return repository_dependencies_dicts metadata = repository_metadata.metadata if metadata is None: - log.debug('The repository_metadata record with id %s has no metadata.' % str(id)) + log.debug(f'The repository_metadata record with id {str(id)} has no metadata.') return repository_dependencies_dicts if 'repository_dependencies' in metadata: rd_tups = metadata['repository_dependencies']['repository_dependencies'] @@ -140,7 +140,7 @@ class RepositoryRevisionsController(BaseAPIController): # Example URL: http://localhost:9009/api/repository_revisions/bb125606ff9ea620 repository_metadata = metadata_util.get_repository_metadata_by_id(trans.app, id) if repository_metadata is None: - log.debug('Cannot locate repository_metadata with id %s' % str(id)) + log.debug(f'Cannot locate repository_metadata with id {str(id)}') return {} encoded_repository_id = trans.security.encode_id(repository_metadata.repository_id) repository_metadata_dict = repository_metadata.to_dict(view='element', @@ -164,7 +164,7 @@ class RepositoryRevisionsController(BaseAPIController): repository_metadata = metadata_util.get_repository_metadata_by_id(trans.app, repository_metadata_id) if repository_metadata is None: decoded_repository_metadata_id = trans.security.decode_id(repository_metadata_id) - log.debug('Cannot locate repository_metadata with id %s' % str(decoded_repository_metadata_id)) + log.debug(f'Cannot locate repository_metadata with id {str(decoded_repository_metadata_id)}') return {} else: decoded_repository_metadata_id = repository_metadata.id diff --git a/lib/tool_shed/webapp/api/tools.py b/lib/tool_shed/webapp/api/tools.py index 794eaecb023..e0097ab4cd2 100644 --- a/lib/tool_shed/webapp/api/tools.py +++ b/lib/tool_shed/webapp/api/tools.py @@ -71,7 +71,7 @@ class ToolsController(BaseAPIController): callback = kwd.get('callback', 'callback') search_results = self._search(trans, q, page, page_size) if return_jsonp: - response = str('{}({});'.format(callback, json.dumps(search_results))) + response = str(f'{callback}({json.dumps(search_results)});') else: response = json.dumps(search_results) return response diff --git a/lib/tool_shed/webapp/api/users.py b/lib/tool_shed/webapp/api/users.py index 748ff5b487b..556aee34dfa 100644 --- a/lib/tool_shed/webapp/api/users.py +++ b/lib/tool_shed/webapp/api/users.py @@ -52,7 +52,7 @@ class UsersController(BaseAPIController): user = self.__create_user(trans, email, username, password) user_dict = user.to_dict(view='element', value_mapper=self.__get_value_mapper(trans)) - user_dict['message'] = "User '%s' has been created." % str(user.username) + user_dict['message'] = f"User '{str(user.username)}' has been created." user_dict['url'] = web.url_for(controller='users', action='show', id=trans.security.encode_id(user.id)) @@ -108,7 +108,7 @@ class UsersController(BaseAPIController): # user is requesting data about themselves user = trans.user if id == 'current' else suc.get_user(trans.app, id) if user is None: - user_dict = dict(message='Unable to locate user record for id %s.' % (str(id)), + user_dict = dict(message=f'Unable to locate user record for id {str(id)}.', status='error') return user_dict user_dict = user.to_dict(view='element', @@ -120,7 +120,7 @@ class UsersController(BaseAPIController): def __validate(self, trans, email, password, confirm, username): if username in ['repos']: - return "The term '%s' is a reserved word in the Tool Shed, so it cannot be used as a public user name." % username + return f"The term '{username}' is a reserved word in the Tool Shed, so it cannot be used as a public user name." message = "\n".join((validate_email(trans, email), validate_password(trans, password, confirm), validate_publicname(trans, username))).rstrip() diff --git a/lib/tool_shed/webapp/app.py b/lib/tool_shed/webapp/app.py index 3457f9e9f13..e7531115e6e 100644 --- a/lib/tool_shed/webapp/app.py +++ b/lib/tool_shed/webapp/app.py @@ -54,7 +54,7 @@ class UniverseApplication(BasicApp): if self.config.database_connection: db_url = self.config.database_connection else: - db_url = "sqlite:///%s?isolation_level=IMMEDIATE" % self.config.database + db_url = f"sqlite:///{self.config.database}?isolation_level=IMMEDIATE" # Initialize the Tool Shed database and check for appropriate schema version. from tool_shed.webapp.model.migrate.check import create_or_verify_database create_or_verify_database(db_url, self.config.database_engine_options) diff --git a/lib/tool_shed/webapp/config.py b/lib/tool_shed/webapp/config.py index c4890f8ab64..866017b1a51 100644 --- a/lib/tool_shed/webapp/config.py +++ b/lib/tool_shed/webapp/config.py @@ -57,7 +57,7 @@ class ToolShedAppConfiguration(BaseAppConfiguration, CommonConfigurationMixin): self._ensure_directory(path) # Check that required files exist. if not os.path.isfile(self.datatypes_config): - raise ConfigurationError('File not found: %s' % self.datatypes_config) + raise ConfigurationError(f'File not found: {self.datatypes_config}') def _process_config(self, kwargs): # Backwards compatibility for names used in too many places to fix @@ -70,7 +70,7 @@ class ToolShedAppConfiguration(BaseAppConfiguration, CommonConfigurationMixin): self.version = VERSION # Database related configuration if not self.database_connection: # Provide default if not supplied by user - self.database_connection = 'sqlite:///%s?isolation_level=IMMEDIATE' % self._in_data_dir('community.sqlite') + self.database_connection = f"sqlite:///{self._in_data_dir('community.sqlite')}?isolation_level=IMMEDIATE" self.database_engine_options = get_database_engine_options(kwargs) self.database_create_tables = string_as_bool(kwargs.get('database_create_tables', 'True')) # Where dataset files are stored diff --git a/lib/tool_shed/webapp/controllers/admin.py b/lib/tool_shed/webapp/controllers/admin.py index 20ecf733721..71d79df638b 100644 --- a/lib/tool_shed/webapp/controllers/admin.py +++ b/lib/tool_shed/webapp/controllers/admin.py @@ -146,7 +146,7 @@ class AdminController(BaseUIController, Admin): trans.sa_session.flush() # Update the Tool Shed's repository registry. trans.app.repository_registry.add_category_entry(category) - message = "Category '%s' has been created" % escape(category.name) + message = f"Category '{escape(category.name)}' has been created" status = 'done' trans.response.send_redirect(web.url_for(controller='admin', action='manage_categories', @@ -188,7 +188,7 @@ class AdminController(BaseUIController, Admin): # Update the repository registry. trans.app.repository_registry.remove_entry(repository) count += 1 - deleted_repositories += " %s " % repository.name + deleted_repositories += f" {repository.name} " if count: message = "Deleted %d %s: %s" % (count, inflector.cond_plural(len(ids), "repository"), escape(deleted_repositories)) else: @@ -265,7 +265,7 @@ class AdminController(BaseUIController, Admin): if original_category_name != new_name: # Update the Tool Shed's repository registry. trans.app.repository_registry.edit_category_entry(original_category_name, new_name) - message = "The information has been saved for category '%s'" % escape(category.name) + message = f"The information has been saved for category '{escape(category.name)}'" status = 'done' return trans.response.send_redirect(web.url_for(controller='admin', action='manage_categories', @@ -405,7 +405,7 @@ class AdminController(BaseUIController, Admin): # Update the repository registry. trans.app.repository_registry.add_entry(repository) count += 1 - undeleted_repositories += " %s" % repository.name + undeleted_repositories += f" {repository.name}" if count: message = "Undeleted %d %s: %s" % (count, inflector.cond_plural(count, "repository"), undeleted_repositories) else: @@ -435,7 +435,7 @@ class AdminController(BaseUIController, Admin): trans.sa_session.flush() # Update the Tool Shed's repository registry. trans.app.repository_registry.remove_category_entry(category) - message += " %s " % escape(category.name) + message += f" {escape(category.name)} " else: message = "No category ids received for deleting." trans.response.send_redirect(web.url_for(controller='admin', @@ -463,7 +463,7 @@ class AdminController(BaseUIController, Admin): for rca in category.repositories: trans.sa_session.delete(rca) trans.sa_session.flush() - purged_categories += " %s " % category.name + purged_categories += f" {category.name} " message = "Purged %d categories: %s" % (count, escape(purged_categories)) else: message = "No category ids received for purging." @@ -490,7 +490,7 @@ class AdminController(BaseUIController, Admin): # Update the Tool Shed's repository registry. trans.app.repository_registry.add_category_entry(category) count += 1 - undeleted_categories += " %s" % category.name + undeleted_categories += f" {category.name}" message = "Undeleted %d categories: %s" % (count, escape(undeleted_categories)) else: message = "No category ids received for undeleting." diff --git a/lib/tool_shed/webapp/controllers/repository.py b/lib/tool_shed/webapp/controllers/repository.py index aad5dadda05..b0eb5c21372 100644 --- a/lib/tool_shed/webapp/controllers/repository.py +++ b/lib/tool_shed/webapp/controllers/repository.py @@ -60,7 +60,7 @@ def get_mercurial_default_options_dict(command): if type(possible) is tuple: possible = possible[0] if len(possible) != 1: - raise Exception('unable to find mercurial command "%s"' % command) + raise Exception(f'unable to find mercurial command "{command}"') return {r[1].replace(b'-', b'_'): r[2] for r in next(iter(possible.values()))[1][1]} @@ -314,7 +314,7 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings): if user_id: user = suc.get_user(trans.app, user_id) trailing_string = '' - default = 'Repositories Owned by %s' % str(user.username) + default = f'Repositories Owned by {str(user.username)}' else: trailing_string = '' default = 'Repositories' @@ -371,7 +371,7 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings): repository = repository_util.get_repository_in_tool_shed(trans.app, repository_id) user_id = trans.security.encode_id(repository.user.id) user = suc.get_user(trans.app, user_id) - self.repositories_by_user_grid.title = "Repositories owned by %s" % user.username + self.repositories_by_user_grid.title = f"Repositories owned by {user.username}" kwd['user_id'] = user_id return self.repositories_by_user_grid(trans, **kwd) selected_changeset_revision, repository = suc.get_repository_from_refresh_on_change(trans.app, **kwd) @@ -385,7 +385,7 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings): if category_id: category = suc.get_category(trans.app, category_id) if category: - trailing_string = 'in Category %s' % str(category.name) + trailing_string = f'in Category {str(category.name)}' else: trailing_string = 'in Category' else: @@ -623,7 +623,7 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings): changeset_revision=changeset_revision) pathspec = ['admin_toolshed', 'update_to_changeset_revision'] else: - message = 'Unable to check for updates due to an invalid Galaxy URL: %s. ' % galaxy_url + message = f'Unable to check for updates due to an invalid Galaxy URL: {galaxy_url}. ' message += 'You may need to enable third-party cookies in your browser. ' return trans.show_error_message(message) if changeset_revision == repository.tip(): @@ -741,7 +741,7 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings): string.Template(template).safe_substitute(selected_repositories=repository_string) docker_image_string = docker_image_template trans.response.set_content_type('application/text/plain') - trans.response.headers["Content-Disposition"] = 'attachment; filename="%s"' % docker_file_name + trans.response.headers["Content-Disposition"] = f'attachment; filename="{docker_file_name}"' opened_file = open(docker_file_path, "w") opened_file.write(docker_image_string) opened_file.close() @@ -829,11 +829,11 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings): if mark_deprecated: # Update the repository registry. trans.app.repository_registry.remove_entry(repository) - message = 'The repository %s has been marked as deprecated.' % escape(repository.name) + message = f'The repository {escape(repository.name)} has been marked as deprecated.' else: # Update the repository registry. trans.app.repository_registry.add_entry(repository) - message = 'The repository %s has been marked as not deprecated.' % escape(repository.name) + message = f'The repository {escape(repository.name)} has been marked as not deprecated.' trans.response.send_redirect(web.url_for(controller='repository', action='browse_repositories', operation='repositories_i_own', @@ -899,7 +899,7 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings): message=message, status=status) except Exception as e: - message = "Error displaying tool, probably due to a problem in the tool config. The exception is: %s." % util.unicodify(e) + message = f"Error displaying tool, probably due to a problem in the tool config. The exception is: {util.unicodify(e)}." if trans.webapp.name == 'galaxy' or render_repository_actions_for == 'galaxy': return trans.response.send_redirect(web.url_for(controller='repository', action='preview_tools_in_changeset', @@ -1546,7 +1546,7 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings): url = util.build_url(galaxy_url, pathspec=pathspec, params=params) return trans.response.send_redirect(url) else: - message = 'Repository installation is not possible due to an invalid Galaxy URL: %s. ' % galaxy_url + message = f'Repository installation is not possible due to an invalid Galaxy URL: {galaxy_url}. ' message += 'You may need to enable third-party cookies in your browser. ' status = 'error' return trans.response.send_redirect(web.url_for(controller='repository', @@ -1590,7 +1590,7 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings): message=message, status='error') except Exception as e: - message = "Exception thrown attempting to display tool: %s." % util.unicodify(e) + message = f"Exception thrown attempting to display tool: {util.unicodify(e)}." if trans.webapp.name == 'galaxy': return trans.response.send_redirect(web.url_for(controller='repository', action='preview_tools_in_changeset', @@ -2241,14 +2241,14 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings): email=trans.user.email, message=message, host=host) - subject = "Regarding your tool shed repository named %s" % repository.name + subject = f"Regarding your tool shed repository named {repository.name}" # Send it try: util.send_mail(from_address, to_address, subject, body, trans.app.config) message = "Your message has been sent" status = "done" except Exception as e: - message = "An error occurred sending your message by email: %s" % util.unicodify(e) + message = f"An error occurred sending your message by email: {util.unicodify(e)}" status = "error" else: # Do all we can to eliminate spam. @@ -2358,7 +2358,7 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings): user = None if user: user_id = trans.security.encode_id(user.id) - message = "This list of repositories owned by {}, does not include one named {}.".format(str(owner), str(name)) + message = f"This list of repositories owned by {str(owner)}, does not include one named {str(name)}." return trans.response.send_redirect(web.url_for(controller='repository', action='index', user_id=user_id, @@ -2468,7 +2468,7 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings): repo = repository.hg_repo ctx = hg_util.get_changectx_for_changeset(repo, ctx_str) if ctx is None: - message = "Repository does not include changeset revision '%s'." % str(ctx_str) + message = f"Repository does not include changeset revision '{str(ctx_str)}'." status = 'error' return trans.response.send_redirect(web.url_for(controller='repository', action='view_changelog', @@ -2551,7 +2551,7 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings): return trans.response.send_redirect(web.url_for(controller='repository', action='view_repository', **kwd)) - return trans.show_error_message("Invalid repository id '%s' received." % repository_id) + return trans.show_error_message(f"Invalid repository id '{repository_id}' received.") return trans.show_error_message("The repository id was not received.") @web.expose diff --git a/lib/tool_shed/webapp/controllers/repository_review.py b/lib/tool_shed/webapp/controllers/repository_review.py index 2c22865f997..91ee640985f 100644 --- a/lib/tool_shed/webapp/controllers/repository_review.py +++ b/lib/tool_shed/webapp/controllers/repository_review.py @@ -53,7 +53,7 @@ class RepositoryReviewController(BaseUIController, ratings_util.ItemRatings): review.approved = approved_select_field_value trans.sa_session.add(review) trans.sa_session.flush() - message = 'Approved value %s saved for this revision.' % escape(approved_select_field_value) + message = f'Approved value {escape(approved_select_field_value)} saved for this revision.' repository_id = trans.security.encode_id(review.repository_id) changeset_revision = review.changeset_revision return trans.response.send_redirect(web.url_for(controller='repository_review', @@ -123,7 +123,7 @@ class RepositoryReviewController(BaseUIController, ratings_util.ItemRatings): component = trans.app.model.Component(name=name, description=description) trans.sa_session.add(component) trans.sa_session.flush() - message = "Component '%s' has been created" % escape(component.name) + message = f"Component '{escape(component.name)}' has been created" status = 'done' trans.response.send_redirect(web.url_for(controller='repository_review', action='manage_components', @@ -153,7 +153,7 @@ class RepositoryReviewController(BaseUIController, ratings_util.ItemRatings): repository_id=repository_id, changeset_revision=changeset_revision, user_id=trans.security.encode_id(trans.user.id)): - message = "You have already created a review for revision {} of repository {}.".format(changeset_revision, escape(repository.name)) + message = f"You have already created a review for revision {changeset_revision} of repository {escape(repository.name)}." status = "error" else: # See if there are any reviews for previous changeset revisions that the user can copy. @@ -220,7 +220,7 @@ class RepositoryReviewController(BaseUIController, ratings_util.ItemRatings): component.description = new_description trans.sa_session.add(component) trans.sa_session.flush() - message = "The information has been saved for the component named %s" % escape(component.name) + message = f"The information has been saved for the component named {escape(component.name)}" status = 'done' return trans.response.send_redirect(web.url_for(controller='repository_review', action='manage_components', @@ -339,7 +339,7 @@ class RepositoryReviewController(BaseUIController, ratings_util.ItemRatings): component_review_dict['component_review'] = component_review components_dict[component_name] = component_review_dict if revision_approved_setting_changed: - message += 'Approved value %s saved for this revision.
    ' % review.approved + message += f'Approved value {review.approved} saved for this revision.
    ' if saved_component_names: message += 'Reviews were saved for components: %s' % ', '.join(saved_component_names) if not revision_approved_setting_changed and not saved_component_names: @@ -567,7 +567,7 @@ class RepositoryReviewController(BaseUIController, ratings_util.ItemRatings): **kwd)) # The user may not be the current user. The value of the received id is the encoded user id. user = suc.get_user(trans.app, kwd['id']) - self.repository_reviews_by_user_grid.title = "All repository revision reviews for user '%s'" % user.username + self.repository_reviews_by_user_grid.title = f"All repository revision reviews for user '{user.username}'" return self.repository_reviews_by_user_grid(trans, **kwd) @web.expose diff --git a/lib/tool_shed/webapp/controllers/upload.py b/lib/tool_shed/webapp/controllers/upload.py index 4670c9c4efc..6aea13d08c7 100644 --- a/lib/tool_shed/webapp/controllers/upload.py +++ b/lib/tool_shed/webapp/controllers/upload.py @@ -62,10 +62,10 @@ class UploadController(BaseUIController): elif url and url.startswith('hg'): # Use mercurial clone to fetch repository, contents will then be copied over. uploaded_directory = tempfile.mkdtemp() - repo_url = 'http%s' % url[len('hg'):] + repo_url = f"http{url[len('hg'):]}" cloned_ok, error_message = hg_util.clone_repository(repo_url, uploaded_directory) if not cloned_ok: - message = 'Error uploading via mercurial clone: %s' % error_message + message = f'Error uploading via mercurial clone: {error_message}' status = 'error' basic_util.remove_dir(uploaded_directory) uploaded_directory = None @@ -75,7 +75,7 @@ class UploadController(BaseUIController): stream = requests.get(url, stream=True) except Exception as e: valid_url = False - message = 'Error uploading file via http: %s' % util.unicodify(e) + message = f'Error uploading file via http: {util.unicodify(e)}' status = 'error' uploaded_file = None if valid_url: diff --git a/lib/tool_shed/webapp/controllers/user.py b/lib/tool_shed/webapp/controllers/user.py index 454bb2830e5..8a0a64dd592 100644 --- a/lib/tool_shed/webapp/controllers/user.py +++ b/lib/tool_shed/webapp/controllers/user.py @@ -72,7 +72,7 @@ class User(BaseUser): status = "error" elif response.get("expired_user"): change_password_url = url_for(controller='user', action='change_password', id=response.get("expired_user")) - message = "{}
    Click here to change your password.".format(response.get("message"), change_password_url) + message = f"{response.get('message')}
    Click here to change your password." status = "warning" else: success = True @@ -125,7 +125,7 @@ class User(BaseUser): if not trans.app.config.allow_user_creation and not trans.user_is_admin: message = 'User registration is disabled. Please contact your local Galaxy administrator for an account.' if trans.app.config.error_email_to is not None: - message += ' Contact: %s' % trans.app.config.error_email_to + message += f' Contact: {trans.app.config.error_email_to}' status = 'error' else: # check user is allowed to register @@ -200,15 +200,15 @@ class User(BaseUser): if trans.app.config.user_activation_on: is_activation_sent = self.user_manager.send_activation_email(trans, email, username) if is_activation_sent: - message = 'Now logged in as {}.
    Verification email has been sent to your email address. Please verify it by clicking the activation link in the email.
    Please check your spam/trash folder in case you cannot find the message.
    Return to the home page.'.format(escape(user.email), url_for('/')) + message = f"Now logged in as {escape(user.email)}.
    Verification email has been sent to your email address. Please verify it by clicking the activation link in the email.
    Please check your spam/trash folder in case you cannot find the message.
    Return to the home page." else: status = "error" message = 'Unable to send activation email, please contact your local Galaxy administrator.' if trans.app.config.error_email_to is not None: - message += ' Contact: %s' % trans.app.config.error_email_to + message += f' Contact: {trans.app.config.error_email_to}' else: # User activation is OFF, proceed without sending the activation email. - message = 'Now logged in as {}.
    Return to the home page.'.format(escape(user.email), url_for('/')) + message = f"Now logged in as {escape(user.email)}.
    Return to the home page." return message, status, user, status is None @web.expose @@ -249,7 +249,7 @@ class User(BaseUser): util.send_mail(frm, email, subject, body, trans.app.config) trans.sa_session.add(reset_user) trans.sa_session.flush() - trans.log_event("User reset password: %s" % email) + trans.log_event(f"User reset password: {email}") except Exception: log.exception('Unable to reset password.') return trans.fill_template('/webapps/tool_shed/user/reset_password.mako', @@ -266,7 +266,7 @@ class User(BaseUser): else: user = trans.user if not user: - raise AssertionError("The user id (%s) is not valid" % str(user_id)) + raise AssertionError(f"The user id ({str(user_id)}) is not valid") email = util.restore_text(params.get('email', user.email)) username = util.restore_text(params.get('username', '')) if not username: @@ -377,7 +377,7 @@ class User(BaseUser): else: message = 'Unable to send activation email, please contact your local Galaxy administrator.' if trans.app.config.error_email_to is not None: - message += ' Contact: %s' % trans.app.config.error_email_to + message += f' Contact: {trans.app.config.error_email_to}' if (user.username != username): user.username = username trans.sa_session.add(user) @@ -457,7 +457,7 @@ class User(BaseUser): def __validate(self, trans, email, password, confirm, username): if username in ['repos']: - return "The term '%s' is a reserved word in the Tool Shed, so it cannot be used as a public user name." % username + return f"The term '{username}' is a reserved word in the Tool Shed, so it cannot be used as a public user name." message = "\n".join((validate_email(trans, email), validate_password(trans, password, confirm), validate_publicname(trans, username))).rstrip() diff --git a/lib/tool_shed/webapp/model/__init__.py b/lib/tool_shed/webapp/model/__init__.py index b7f3b99f260..9dffc522f03 100644 --- a/lib/tool_shed/webapp/model/__init__.py +++ b/lib/tool_shed/webapp/model/__init__.py @@ -80,7 +80,7 @@ class User(Dictifiable, _HasTable): def set_password_cleartext(self, cleartext): message = validate_password_str(cleartext) if message: - raise Exception("Invalid password: %s" % message) + raise Exception(f"Invalid password: {message}") """Set 'self.password' to the digest of 'cleartext'.""" self.password = new_secure_hash(text_type=cleartext) @@ -221,7 +221,7 @@ class Repository(Dictifiable, _HasTable): @property def admin_role(self): - admin_role_name = '{}_{}_admin'.format(str(self.name), str(self.user.username)) + admin_role_name = f'{str(self.name)}_{str(self.user.username)}_admin' for rra in self.roles: role = rra.role if str(role.name) == admin_role_name: @@ -303,7 +303,7 @@ class Repository(Dictifiable, _HasTable): def revision(self): repo = self.hg_repo tip_ctx = repo[repo.changelog.tip()] - return "{}:{}".format(str(tip_ctx.rev()), str(tip_ctx)) + return f"{str(tip_ctx.rev())}:{str(tip_ctx)}" def set_allow_push(self, usernames, remove_auth=''): allow_push = util.listify(self.allow_push()) @@ -323,7 +323,7 @@ class Repository(Dictifiable, _HasTable): with open(hgrc_file, 'w') as fh: for line in lines: if line.startswith('allow_push'): - fh.write('allow_push = %s' % allow_push) + fh.write(f'allow_push = {allow_push}') else: fh.write(line) diff --git a/lib/tool_shed/webapp/model/migrate/check.py b/lib/tool_shed/webapp/model/migrate/check.py index 2e37c4840b1..ccb65ec6038 100644 --- a/lib/tool_shed/webapp/model/migrate/check.py +++ b/lib/tool_shed/webapp/model/migrate/check.py @@ -30,7 +30,7 @@ def create_or_verify_database(url, engine_options=None): engine_options = engine_options or {} # Create engine and metadata if not database_exists(url): - message = "Creating database for URI [%s]" % url + message = f"Creating database for URI [{url}]" log.info(message) create_database(url) diff --git a/lib/tool_shed/webapp/model/migrate/versions/0002_add_tool_suite_column.py b/lib/tool_shed/webapp/model/migrate/versions/0002_add_tool_suite_column.py index 1724b6dcafd..9223379e520 100644 --- a/lib/tool_shed/webapp/model/migrate/versions/0002_add_tool_suite_column.py +++ b/lib/tool_shed/webapp/model/migrate/versions/0002_add_tool_suite_column.py @@ -34,7 +34,7 @@ def upgrade(migrate_engine): default_false = "0" elif migrate_engine.name in ['postgresql', 'postgres']: default_false = "false" - migrate_engine.execute("UPDATE tool SET suite=%s" % default_false) + migrate_engine.execute(f"UPDATE tool SET suite={default_false}") except Exception: log.exception("Adding suite column to the tool table failed.") diff --git a/lib/tool_shed/webapp/model/migrate/versions/0009_add_malicious_column.py b/lib/tool_shed/webapp/model/migrate/versions/0009_add_malicious_column.py index f1b9838b4d3..9ee235260ee 100644 --- a/lib/tool_shed/webapp/model/migrate/versions/0009_add_malicious_column.py +++ b/lib/tool_shed/webapp/model/migrate/versions/0009_add_malicious_column.py @@ -34,7 +34,7 @@ def upgrade(migrate_engine): default_false = "0" elif migrate_engine.name in ['postgresql', 'postgres']: default_false = "false" - migrate_engine.execute("UPDATE repository_metadata SET malicious=%s" % default_false) + migrate_engine.execute(f"UPDATE repository_metadata SET malicious={default_false}") except Exception: log.exception("Adding malicious column to the repository_metadata table failed.") diff --git a/lib/tool_shed/webapp/model/migrate/versions/0010_add_new_repo_alert_column.py b/lib/tool_shed/webapp/model/migrate/versions/0010_add_new_repo_alert_column.py index 4dac6edc244..73ee33252ab 100644 --- a/lib/tool_shed/webapp/model/migrate/versions/0010_add_new_repo_alert_column.py +++ b/lib/tool_shed/webapp/model/migrate/versions/0010_add_new_repo_alert_column.py @@ -36,7 +36,7 @@ def upgrade(migrate_engine): default_false = "false" else: log.debug("unknown migrate_engine dialect") - migrate_engine.execute("UPDATE galaxy_user SET new_repo_alert=%s" % default_false) + migrate_engine.execute(f"UPDATE galaxy_user SET new_repo_alert={default_false}") except Exception: log.exception("Adding new_repo_alert column to the galaxy_user table failed.") diff --git a/lib/tool_shed/webapp/model/migrate/versions/0012_add_downloadable_column.py b/lib/tool_shed/webapp/model/migrate/versions/0012_add_downloadable_column.py index 62c24ee145d..f84f236d567 100644 --- a/lib/tool_shed/webapp/model/migrate/versions/0012_add_downloadable_column.py +++ b/lib/tool_shed/webapp/model/migrate/versions/0012_add_downloadable_column.py @@ -34,7 +34,7 @@ def upgrade(migrate_engine): default_true = "1" elif migrate_engine.name in ['postgresql', 'postgres']: default_true = "true" - migrate_engine.execute("UPDATE repository_metadata SET downloadable=%s" % default_true) + migrate_engine.execute(f"UPDATE repository_metadata SET downloadable={default_true}") except Exception: log.exception("Adding downloadable column to the repository_metadata table failed.") diff --git a/lib/tool_shed/webapp/model/migrate/versions/0013_add_review_tables.py b/lib/tool_shed/webapp/model/migrate/versions/0013_add_review_tables.py index aa82faaac3c..5d8a8fcef8f 100644 --- a/lib/tool_shed/webapp/model/migrate/versions/0013_add_review_tables.py +++ b/lib/tool_shed/webapp/model/migrate/versions/0013_add_review_tables.py @@ -33,7 +33,7 @@ def nextval(migrate_engine, table, col='id'): elif migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite': return "null" else: - raise Exception('Unable to convert data for unknown database type: %s' % migrate_engine.name) + raise Exception(f'Unable to convert data for unknown database type: {migrate_engine.name}') def localtimestamp(migrate_engine): @@ -42,7 +42,7 @@ def localtimestamp(migrate_engine): elif migrate_engine.name == 'sqlite': return "current_date || ' ' || current_time" else: - raise Exception('Unable to convert data for unknown database type: %s' % migrate_engine.name) + raise Exception(f'Unable to convert data for unknown database type: {migrate_engine.name}') def boolean_false(migrate_engine): @@ -51,7 +51,7 @@ def boolean_false(migrate_engine): elif migrate_engine.name == 'sqlite': return 0 else: - raise Exception('Unable to convert data for unknown database type: %s' % migrate_engine.name) + raise Exception(f'Unable to convert data for unknown database type: {migrate_engine.name}') RepositoryReview_table = Table("repository_review", metadata, @@ -111,20 +111,20 @@ def upgrade(migrate_engine): for tup in zip(names, descriptions): name, description = tup cmd = "INSERT INTO component VALUES (" - cmd += "%s, " % nextval(migrate_engine, 'component') - cmd += "'%s', " % name - cmd += "'%s' " % description + cmd += f"{nextval(migrate_engine, 'component')}, " + cmd += f"'{name}', " + cmd += f"'{description}' " cmd += ");" migrate_engine.execute(cmd) # Insert a REVIEWER role into the role table. cmd = "INSERT INTO role VALUES (" - cmd += "%s, " % nextval(migrate_engine, 'role') - cmd += "%s, " % localtimestamp(migrate_engine) - cmd += "%s, " % localtimestamp(migrate_engine) - cmd += "'%s', " % REVIEWER + cmd += f"{nextval(migrate_engine, 'role')}, " + cmd += f"{localtimestamp(migrate_engine)}, " + cmd += f"{localtimestamp(migrate_engine)}, " + cmd += f"'{REVIEWER}', " cmd += "'A user or group member with this role can review repositories.', " - cmd += "'%s', " % ROLE_TYPE - cmd += "%s" % boolean_false(migrate_engine) + cmd += f"'{ROLE_TYPE}', " + cmd += f"{boolean_false(migrate_engine)}" cmd += ");" migrate_engine.execute(cmd) # Get the id of the REVIEWER role. @@ -136,15 +136,15 @@ def upgrade(migrate_engine): role_id = None # Insert an IUC group into the galaxy_group table. cmd = "INSERT INTO galaxy_group VALUES (" - cmd += "%s, " % nextval(migrate_engine, 'galaxy_group') - cmd += "%s, " % localtimestamp(migrate_engine) - cmd += "%s, " % localtimestamp(migrate_engine) - cmd += "'%s', " % IUC - cmd += "%s" % boolean_false(migrate_engine) + cmd += f"{nextval(migrate_engine, 'galaxy_group')}, " + cmd += f"{localtimestamp(migrate_engine)}, " + cmd += f"{localtimestamp(migrate_engine)}, " + cmd += f"'{IUC}', " + cmd += f"{boolean_false(migrate_engine)}" cmd += ");" migrate_engine.execute(cmd) # Get the id of the IUC group. - cmd = "SELECT id FROM galaxy_group WHERE name = '%s';" % (IUC) + cmd = f"SELECT id FROM galaxy_group WHERE name = '{IUC}';" row = migrate_engine.execute(cmd).fetchone() if row: group_id = row[0] @@ -153,11 +153,11 @@ def upgrade(migrate_engine): if group_id and role_id: # Insert a group_role_association for the IUC group and the REVIEWER role. cmd = "INSERT INTO group_role_association VALUES (" - cmd += "%s, " % nextval(migrate_engine, 'group_role_association') + cmd += f"{nextval(migrate_engine, 'group_role_association')}, " cmd += "%d, " % int(group_id) cmd += "%d, " % int(role_id) - cmd += "%s, " % localtimestamp(migrate_engine) - cmd += "%s " % localtimestamp(migrate_engine) + cmd += f"{localtimestamp(migrate_engine)}, " + cmd += f"{localtimestamp(migrate_engine)} " cmd += ");" migrate_engine.execute(cmd) @@ -179,7 +179,7 @@ def downgrade(migrate_engine): except Exception: log.exception("Dropping component table failed.") # Get the id of the REVIEWER group. - cmd = "SELECT id FROM galaxy_group WHERE name = '%s';" % (IUC) + cmd = f"SELECT id FROM galaxy_group WHERE name = '{IUC}';" row = migrate_engine.execute(cmd).fetchone() if row: group_id = row[0] diff --git a/lib/tool_shed/webapp/model/migrate/versions/0014_add_deprecated_column.py b/lib/tool_shed/webapp/model/migrate/versions/0014_add_deprecated_column.py index 4ab4534d4da..e9db03e1d31 100644 --- a/lib/tool_shed/webapp/model/migrate/versions/0014_add_deprecated_column.py +++ b/lib/tool_shed/webapp/model/migrate/versions/0014_add_deprecated_column.py @@ -34,7 +34,7 @@ def upgrade(migrate_engine): default_false = "0" elif migrate_engine.name in ['postgresql', 'postgres']: default_false = "false" - migrate_engine.execute("UPDATE repository SET deprecated=%s" % default_false) + migrate_engine.execute(f"UPDATE repository SET deprecated={default_false}") except Exception: log.exception("Adding deprecated column to the repository table failed.") diff --git a/lib/tool_shed/webapp/model/migrate/versions/0016_add_do_not_test_tools_functionally_correct_errors_columns.py b/lib/tool_shed/webapp/model/migrate/versions/0016_add_do_not_test_tools_functionally_correct_errors_columns.py index 0c0f2c40582..7610c58a0cc 100644 --- a/lib/tool_shed/webapp/model/migrate/versions/0016_add_do_not_test_tools_functionally_correct_errors_columns.py +++ b/lib/tool_shed/webapp/model/migrate/versions/0016_add_do_not_test_tools_functionally_correct_errors_columns.py @@ -37,7 +37,7 @@ def upgrade(migrate_engine): default_false = "0" elif migrate_engine.name in ['postgresql', 'postgres']: default_false = "false" - migrate_engine.execute("UPDATE repository_metadata SET tools_functionally_correct=%s" % default_false) + migrate_engine.execute(f"UPDATE repository_metadata SET tools_functionally_correct={default_false}") except Exception: log.exception("Adding tools_functionally_correct column to the repository_metadata table failed.") c = Column("do_not_test", Boolean, default=False, index=True) @@ -50,7 +50,7 @@ def upgrade(migrate_engine): default_false = "0" elif migrate_engine.name in ['postgresql', 'postgres']: default_false = "false" - migrate_engine.execute("UPDATE repository_metadata SET do_not_test=%s" % default_false) + migrate_engine.execute(f"UPDATE repository_metadata SET do_not_test={default_false}") except Exception: log.exception("Adding do_not_test column to the repository_metadata table failed.") c = Column("time_last_tested", DateTime, default=None, nullable=True) diff --git a/lib/tool_shed/webapp/model/migrate/versions/0017_add_galaxy_utility_columns_to_repository_metadata_table.py b/lib/tool_shed/webapp/model/migrate/versions/0017_add_galaxy_utility_columns_to_repository_metadata_table.py index 4f661c53feb..e2252df0ccf 100644 --- a/lib/tool_shed/webapp/model/migrate/versions/0017_add_galaxy_utility_columns_to_repository_metadata_table.py +++ b/lib/tool_shed/webapp/model/migrate/versions/0017_add_galaxy_utility_columns_to_repository_metadata_table.py @@ -36,7 +36,7 @@ def upgrade(migrate_engine): try: c.create(RepositoryMetadata_table, index_name="ix_repository_metadata_inc_datatypes") assert c is RepositoryMetadata_table.c.includes_datatypes - migrate_engine.execute("UPDATE repository_metadata SET includes_datatypes=%s" % default_false) + migrate_engine.execute(f"UPDATE repository_metadata SET includes_datatypes={default_false}") except Exception: log.exception("Adding includes_datatypes column to the repository_metadata table failed.") @@ -45,7 +45,7 @@ def upgrade(migrate_engine): try: c.create(RepositoryMetadata_table, index_name="ix_repository_metadata_has_repo_deps") assert c is RepositoryMetadata_table.c.has_repository_dependencies - migrate_engine.execute("UPDATE repository_metadata SET has_repository_dependencies=%s" % default_false) + migrate_engine.execute(f"UPDATE repository_metadata SET has_repository_dependencies={default_false}") except Exception: log.exception("Adding has_repository_dependencies column to the repository_metadata table failed.") @@ -54,7 +54,7 @@ def upgrade(migrate_engine): try: c.create(RepositoryMetadata_table, index_name="ix_repository_metadata_inc_tools") assert c is RepositoryMetadata_table.c.includes_tools - migrate_engine.execute("UPDATE repository_metadata SET includes_tools=%s" % default_false) + migrate_engine.execute(f"UPDATE repository_metadata SET includes_tools={default_false}") except Exception: log.exception("Adding includes_tools column to the repository_metadata table failed.") @@ -63,7 +63,7 @@ def upgrade(migrate_engine): try: c.create(RepositoryMetadata_table, index_name="ix_repository_metadata_inc_tool_deps") assert c is RepositoryMetadata_table.c.includes_tool_dependencies - migrate_engine.execute("UPDATE repository_metadata SET includes_tool_dependencies=%s" % default_false) + migrate_engine.execute(f"UPDATE repository_metadata SET includes_tool_dependencies={default_false}") except Exception: log.exception("Adding includes_tool_dependencies column to the repository_metadata table failed.") @@ -72,7 +72,7 @@ def upgrade(migrate_engine): try: c.create(RepositoryMetadata_table, index_name="ix_repository_metadata_inc_workflows") assert c is RepositoryMetadata_table.c.includes_workflows - migrate_engine.execute("UPDATE repository_metadata SET includes_workflows=%s" % default_false) + migrate_engine.execute(f"UPDATE repository_metadata SET includes_workflows={default_false}") except Exception: log.exception("Adding includes_workflows column to the repository_metadata table failed.") diff --git a/lib/tool_shed/webapp/model/migrate/versions/0018_add_repository_metadata_flag_columns.py b/lib/tool_shed/webapp/model/migrate/versions/0018_add_repository_metadata_flag_columns.py index ad44714bece..78c1839cce7 100644 --- a/lib/tool_shed/webapp/model/migrate/versions/0018_add_repository_metadata_flag_columns.py +++ b/lib/tool_shed/webapp/model/migrate/versions/0018_add_repository_metadata_flag_columns.py @@ -61,7 +61,7 @@ def upgrade(migrate_engine): try: c.create(RepositoryMetadata_table, index_name="ix_repository_metadata_mtc") assert c is RepositoryMetadata_table.c.missing_test_components - migrate_engine.execute("UPDATE repository_metadata SET missing_test_components=%s" % default_false) + migrate_engine.execute(f"UPDATE repository_metadata SET missing_test_components={default_false}") except Exception: log.exception("Adding missing_test_components column to the repository_metadata table failed.") diff --git a/lib/tool_shed/webapp/model/migrate/versions/0019_add_skip_tool_test_table_and_test_install_error_column.py b/lib/tool_shed/webapp/model/migrate/versions/0019_add_skip_tool_test_table_and_test_install_error_column.py index 13602365f56..5b4bdea2509 100644 --- a/lib/tool_shed/webapp/model/migrate/versions/0019_add_skip_tool_test_table_and_test_install_error_column.py +++ b/lib/tool_shed/webapp/model/migrate/versions/0019_add_skip_tool_test_table_and_test_install_error_column.py @@ -55,7 +55,7 @@ def upgrade(migrate_engine): try: c.create(RepositoryMetadata_table, index_name="ix_repository_metadata_ttie") assert c is RepositoryMetadata_table.c.test_install_error - migrate_engine.execute("UPDATE repository_metadata SET test_install_error=%s" % default_false) + migrate_engine.execute(f"UPDATE repository_metadata SET test_install_error={default_false}") except Exception: log.exception("Adding test_install_error column to the repository_metadata table failed.") diff --git a/lib/tool_shed/webapp/model/migrate/versions/0022_add_repository_admin_roles.py b/lib/tool_shed/webapp/model/migrate/versions/0022_add_repository_admin_roles.py index 60531bbff85..edc5ac493aa 100644 --- a/lib/tool_shed/webapp/model/migrate/versions/0022_add_repository_admin_roles.py +++ b/lib/tool_shed/webapp/model/migrate/versions/0022_add_repository_admin_roles.py @@ -38,7 +38,7 @@ def nextval(migrate_engine, table, col='id'): elif migrate_engine.name in ['mysql', 'sqlite']: return "null" else: - raise Exception('Unable to convert data for unknown database type: %s' % migrate_engine.name) + raise Exception(f'Unable to convert data for unknown database type: {migrate_engine.name}') def localtimestamp(migrate_engine): @@ -47,7 +47,7 @@ def localtimestamp(migrate_engine): elif migrate_engine.name == 'sqlite': return "current_date || ' ' || current_time" else: - raise Exception('Unable to convert data for unknown database type: %s' % migrate_engine.name) + raise Exception(f'Unable to convert data for unknown database type: {migrate_engine.name}') def boolean_false(migrate_engine): @@ -56,7 +56,7 @@ def boolean_false(migrate_engine): elif migrate_engine.name == 'sqlite': return 0 else: - raise Exception('Unable to convert data for unknown database type: %s' % migrate_engine.name) + raise Exception(f'Unable to convert data for unknown database type: {migrate_engine.name}') def upgrade(migrate_engine): @@ -79,19 +79,19 @@ def upgrade(migrate_engine): user_id = row[2] username = row[3] repository_ids.append(int(repository_id)) - role_names.append('{}_{}_admin'.format(str(name), str(username))) + role_names.append(f'{str(name)}_{str(username)}_admin') user_ids.append(int(user_id)) # Insert a new record into the role table for each new role. for tup in zip(repository_ids, user_ids, role_names): repository_id, user_id, role_name = tup cmd = "INSERT INTO role VALUES (" - cmd += "%s, " % nextval(migrate_engine, 'role') - cmd += "%s, " % localtimestamp(migrate_engine) - cmd += "%s, " % localtimestamp(migrate_engine) - cmd += "'%s', " % role_name + cmd += f"{nextval(migrate_engine, 'role')}, " + cmd += f"{localtimestamp(migrate_engine)}, " + cmd += f"{localtimestamp(migrate_engine)}, " + cmd += f"'{role_name}', " cmd += "'A user or group member with this role can administer this repository.', " - cmd += "'%s', " % ROLE_TYPE - cmd += "%s" % boolean_false(migrate_engine) + cmd += f"'{ROLE_TYPE}', " + cmd += f"{boolean_false(migrate_engine)}" cmd += ");" migrate_engine.execute(cmd) # Get the id of the new role. @@ -104,20 +104,20 @@ def upgrade(migrate_engine): if role_id: # Create a repository_role_association record to associate the repository with the new role. cmd = "INSERT INTO repository_role_association VALUES (" - cmd += "%s, " % nextval(migrate_engine, 'repository_role_association') + cmd += f"{nextval(migrate_engine, 'repository_role_association')}, " cmd += "%d, " % int(repository_id) cmd += "%d, " % int(role_id) - cmd += "%s, " % localtimestamp(migrate_engine) - cmd += "%s " % localtimestamp(migrate_engine) + cmd += f"{localtimestamp(migrate_engine)}, " + cmd += f"{localtimestamp(migrate_engine)} " cmd += ");" migrate_engine.execute(cmd) # Create a user_role_association record to associate the repository owner with the new role. cmd = "INSERT INTO user_role_association VALUES (" - cmd += "%s, " % nextval(migrate_engine, 'user_role_association') + cmd += f"{nextval(migrate_engine, 'user_role_association')}, " cmd += "%d, " % int(user_id) cmd += "%d, " % int(role_id) - cmd += "%s, " % localtimestamp(migrate_engine) - cmd += "%s " % localtimestamp(migrate_engine) + cmd += f"{localtimestamp(migrate_engine)}, " + cmd += f"{localtimestamp(migrate_engine)} " cmd += ");" migrate_engine.execute(cmd) @@ -132,11 +132,11 @@ def downgrade(migrate_engine): for row in migrate_engine.execute(cmd): name = row[0] username = row[1] - role_names.append('{}_{}_admin'.format(str(name), str(username))) + role_names.append(f'{str(name)}_{str(username)}_admin') # Delete each role as well as all users associated with each role. for role_name in role_names: # Select the id of the record associated with the current role_name from the role table. - cmd = "SELECT id, name FROM role WHERE name = '%s';" % role_name + cmd = f"SELECT id, name FROM role WHERE name = '{role_name}';" row = migrate_engine.execute(cmd).fetchone() if row: role_id = row[0] diff --git a/lib/tool_shed/webapp/security/__init__.py b/lib/tool_shed/webapp/security/__init__.py index 4563788cbbc..96e3be5780c 100644 --- a/lib/tool_shed/webapp/security/__init__.py +++ b/lib/tool_shed/webapp/security/__init__.py @@ -22,7 +22,7 @@ class RBACAgent: permitted_actions = Bunch() def associate_components(self, **kwd): - raise Exception('No valid method of associating provided components: %s' % kwd) + raise Exception(f'No valid method of associating provided components: {kwd}') def associate_user_role(self, user, role): raise Exception('No valid method of associating a user with a role') @@ -96,7 +96,7 @@ class CommunityRBACAgent(RBACAgent): return self.associate_group_role(kwd['group'], kwd['role']) elif 'repository' in kwd: return self.associate_repository_category(kwd['repository'], kwd['category']) - raise Exception('No valid method of associating provided components: %s' % kwd) + raise Exception(f'No valid method of associating provided components: {kwd}') def associate_group_role(self, group, role): assoc = self.model.GroupRoleAssociation(group, role) diff --git a/scripts/galaxy_main.py b/scripts/galaxy_main.py index c6a49f20bcc..cb0595baa19 100755 --- a/scripts/galaxy_main.py +++ b/scripts/galaxy_main.py @@ -129,7 +129,7 @@ def handle_signal(signum, frame): def register_signals(): for name in ('TERM', 'INT', 'HUP'): - sig = getattr(signal, 'SIG%s' % name) + sig = getattr(signal, f'SIG{name}') signal.signal(sig, handle_signal) @@ -179,7 +179,7 @@ class GalaxyConfigBuilder: self.config_file = unicodify(config_file) # FIXME: this won't work for non-Paste ini configs if self.config_is_ini: - self.config_section = "app:%s" % unicodify(kwds.get("app") or (args and args.app) or DEFAULT_INI_APP) + self.config_section = f"app:{unicodify(kwds.get('app') or args and args.app or DEFAULT_INI_APP)}" else: self.config_section = self.app_name self.log_file = (args and args.log_file) @@ -192,7 +192,7 @@ class GalaxyConfigBuilder: arg_parser.add_argument("-d", "--daemonize", default=False, help="Daemonize process", action="store_true") arg_parser.add_argument("--daemon-log-file", default=None, help="log file for daemon script ") arg_parser.add_argument("--log-file", default=None, help="Galaxy log file (overrides log configuration in config_file if set)") - arg_parser.add_argument("--pid-file", default=DEFAULT_PID, help="pid file (default is %s)" % DEFAULT_PID) + arg_parser.add_argument("--pid-file", default=DEFAULT_PID, help=f"pid file (default is {DEFAULT_PID})") arg_parser.add_argument("--server-name", default=None, help="set a galaxy server name") arg_parser.add_argument("--attach-to-pool", action="append", default=None, help="attach to asynchronous worker pool (specify multiple times for multiple pools)") From f1ff658cb7ddf47e2de4ecea684a59b1019ec02c Mon Sep 17 00:00:00 2001 From: Dannon Baker Date: Tue, 2 Mar 2021 15:32:49 -0500 Subject: [PATCH 2/7] Concatenation pass, fstring conversion --- lib/galaxy/actions/admin.py | 6 +- lib/galaxy/authnz/custos_authnz.py | 8 +- lib/galaxy/authnz/psa_authnz.py | 2 +- lib/galaxy/config/__init__.py | 2 +- lib/galaxy/containers/__init__.py | 4 +- lib/galaxy/containers/docker.py | 6 +- lib/galaxy/containers/docker_model.py | 6 +- lib/galaxy/containers/docker_swarm.py | 4 +- lib/galaxy/datatypes/assembly.py | 6 +- lib/galaxy/datatypes/binary.py | 4 +- .../datatypes/converters/interval_to_fli.py | 4 +- lib/galaxy/datatypes/dataproviders/dataset.py | 4 +- .../datatypes/dataproviders/external.py | 2 +- lib/galaxy/datatypes/genetics.py | 2 +- lib/galaxy/datatypes/isa.py | 2 +- lib/galaxy/datatypes/tabular.py | 6 +- lib/galaxy/datatypes/triples.py | 2 +- lib/galaxy/datatypes/util/gff_util.py | 2 +- lib/galaxy/dependencies/__init__.py | 2 +- lib/galaxy/files/sources/__init__.py | 2 +- lib/galaxy/job_metrics/instrumenters/core.py | 2 +- lib/galaxy/jobs/__init__.py | 8 +- lib/galaxy/jobs/actions/post.py | 6 +- lib/galaxy/jobs/dynamic_tool_destination.py | 136 +++++++++--------- lib/galaxy/jobs/handler.py | 2 +- lib/galaxy/jobs/runners/__init__.py | 2 +- lib/galaxy/jobs/runners/chronos.py | 8 +- lib/galaxy/jobs/runners/cli.py | 4 +- lib/galaxy/jobs/runners/drmaa.py | 12 +- lib/galaxy/jobs/runners/godocker.py | 34 ++--- lib/galaxy/jobs/runners/kubernetes.py | 12 +- lib/galaxy/jobs/runners/pbs.py | 8 +- lib/galaxy/jobs/runners/slurm.py | 2 +- lib/galaxy/jobs/runners/util/cli/job/lsf.py | 4 +- lib/galaxy/jobs/runners/util/cli/job/slurm.py | 2 +- .../jobs/runners/util/condor/__init__.py | 18 +-- lib/galaxy/jobs/runners/util/pykube_util.py | 4 +- lib/galaxy/jobs/splitters/multi.py | 8 +- lib/galaxy/managers/base.py | 10 +- lib/galaxy/managers/citations.py | 2 +- lib/galaxy/managers/containers.py | 4 +- lib/galaxy/managers/datasets.py | 4 +- lib/galaxy/managers/executables.py | 2 +- lib/galaxy/managers/folders.py | 4 +- lib/galaxy/managers/lddas.py | 6 +- lib/galaxy/managers/libraries.py | 12 +- lib/galaxy/managers/library_datasets.py | 8 +- lib/galaxy/managers/markdown_parse.py | 2 +- lib/galaxy/managers/markdown_util.py | 6 +- lib/galaxy/managers/pages.py | 4 +- lib/galaxy/managers/rbac_secured.py | 2 +- lib/galaxy/managers/roles.py | 2 +- lib/galaxy/managers/taggable.py | 4 +- lib/galaxy/managers/users.py | 8 +- lib/galaxy/managers/workflows.py | 6 +- lib/galaxy/metadata/set_metadata.py | 4 +- lib/galaxy/model/__init__.py | 20 +-- lib/galaxy/model/search.py | 2 +- lib/galaxy/model/security.py | 8 +- lib/galaxy/model/store/__init__.py | 6 +- lib/galaxy/model/tags.py | 6 +- .../model/tool_shed_install/__init__.py | 2 +- lib/galaxy/objectstore/__init__.py | 2 +- lib/galaxy/objectstore/irods.py | 30 ++-- lib/galaxy/queue_worker.py | 2 +- lib/galaxy/security/idencoding.py | 2 +- lib/galaxy/selenium/components.py | 2 +- lib/galaxy/selenium/driver_factory.py | 4 +- lib/galaxy/selenium/navigates_galaxy.py | 12 +- .../recipe/install_environment.py | 4 +- lib/galaxy/tool_util/cwl/parser.py | 2 +- lib/galaxy/tool_util/cwl/schema.py | 2 +- lib/galaxy/tool_util/deps/brew_exts.py | 6 +- .../deps/container_resolvers/mulled.py | 4 +- lib/galaxy/tool_util/deps/containers.py | 6 +- .../tool_util/deps/mulled/mulled_build.py | 2 +- .../deps/mulled/mulled_build_files.py | 2 +- .../tool_util/deps/mulled/mulled_search.py | 2 +- .../mulled_update_singularity_containers.py | 6 +- .../resolvers/unlinked_tool_shed_packages.py | 4 +- lib/galaxy/tool_util/loader_directory.py | 4 +- lib/galaxy/tool_util/locations/dockstore.py | 2 +- lib/galaxy/tool_util/output_checker.py | 4 +- .../tool_util/verify/asserts/__init__.py | 4 +- lib/galaxy/tool_util/verify/interactor.py | 12 +- lib/galaxy/tool_util/verify/script.py | 12 +- lib/galaxy/tools/__init__.py | 14 +- lib/galaxy/tools/actions/__init__.py | 2 +- lib/galaxy/tools/data/__init__.py | 4 +- lib/galaxy/tools/data_fetch.py | 6 +- .../tools/error_reports/plugins/base_git.py | 2 +- lib/galaxy/tools/errors.py | 2 +- lib/galaxy/tools/expressions/evaluation.py | 2 +- lib/galaxy/tools/parameters/__init__.py | 16 +-- lib/galaxy/tools/parameters/basic.py | 4 +- lib/galaxy/tools/parameters/sanitize.py | 4 +- lib/galaxy/tools/recommendations.py | 2 +- lib/galaxy/tools/search/__init__.py | 4 +- lib/galaxy/tools/toolbox/base.py | 18 +-- lib/galaxy/tools/toolbox/integrated_panel.py | 6 +- lib/galaxy/tools/toolbox/tags.py | 2 +- lib/galaxy/util/compression_utils.py | 2 +- lib/galaxy/util/dictifiable.py | 2 +- lib/galaxy/util/facts.py | 2 +- lib/galaxy/util/heartbeat.py | 2 +- lib/galaxy/util/inflection.py | 4 +- lib/galaxy/util/object_wrapper.py | 2 +- lib/galaxy/util/pastescript/loadwsgi.py | 8 +- lib/galaxy/util/pastescript/serve.py | 6 +- lib/galaxy/util/submodules.py | 2 +- .../data_providers/phyloviz/baseparser.py | 2 +- .../data_providers/phyloviz/newickparser.py | 2 +- lib/galaxy/visualization/genomes.py | 2 +- .../visualization/plugins/config_parser.py | 2 +- .../plugins/interactive_environments.py | 12 +- lib/galaxy/visualization/plugins/plugin.py | 2 +- lib/galaxy/visualization/plugins/registry.py | 4 +- lib/galaxy/web/framework/base.py | 26 ++-- lib/galaxy/web/framework/helpers/grids.py | 26 ++-- lib/galaxy/web/framework/middleware/error.py | 4 +- .../web/framework/middleware/profile.py | 4 +- .../web/framework/middleware/remoteuser.py | 2 +- lib/galaxy/web/framework/middleware/statsd.py | 4 +- .../web/framework/middleware/translogger.py | 2 +- lib/galaxy/web/legacy_framework/grids.py | 26 ++-- lib/galaxy/web/proxy/__init__.py | 2 +- lib/galaxy/web/statsd_client.py | 2 +- lib/galaxy/web_stack/__init__.py | 16 +-- lib/galaxy/web_stack/transport.py | 6 +- lib/galaxy/webapps/base/controller.py | 8 +- lib/galaxy/webapps/base/webapp.py | 6 +- lib/galaxy/webapps/galaxy/api/cloudauthz.py | 6 +- .../webapps/galaxy/api/history_contents.py | 6 +- .../webapps/galaxy/api/library_contents.py | 20 +-- .../webapps/galaxy/api/library_datasets.py | 18 +-- lib/galaxy/webapps/galaxy/api/users.py | 8 +- lib/galaxy/webapps/galaxy/api/workflows.py | 2 +- lib/galaxy/webapps/galaxy/buildapp.py | 6 +- .../controllers/_create_history_template.py | 42 +++--- .../webapps/galaxy/controllers/admin.py | 4 +- .../webapps/galaxy/controllers/async.py | 4 +- .../webapps/galaxy/controllers/authnz.py | 4 +- .../webapps/galaxy/controllers/dataset.py | 10 +- .../webapps/galaxy/controllers/history.py | 2 +- lib/galaxy/webapps/galaxy/controllers/page.py | 4 +- lib/galaxy/webapps/galaxy/controllers/root.py | 8 +- lib/galaxy/webapps/galaxy/controllers/tag.py | 8 +- .../galaxy/controllers/visualization.py | 2 +- .../webapps/galaxy/controllers/workflow.py | 6 +- lib/galaxy/webapps/reports/buildapp.py | 2 +- .../webapps/reports/controllers/tools.py | 12 +- lib/galaxy/workflow/extract.py | 2 +- lib/galaxy/workflow/modules.py | 6 +- lib/galaxy/workflow/trs_proxy.py | 10 +- lib/galaxy_test/api/test_api_batch.py | 8 +- .../api/test_dataset_collections.py | 4 +- lib/galaxy_test/api/test_tools.py | 2 +- lib/galaxy_test/base/populators.py | 12 +- lib/galaxy_test/driver/driver_util.py | 2 +- lib/galaxy_test/selenium/framework.py | 10 +- .../selenium/test_history_multi_view.py | 2 +- .../selenium/test_library_landing.py | 6 +- .../selenium/test_workflow_editor.py | 4 +- lib/tool_shed/managers/groups.py | 2 +- lib/tool_shed/test/base/twilltestcase.py | 10 +- ...test_0420_citable_urls_for_repositories.py | 4 +- lib/tool_shed/util/admin_util.py | 4 +- lib/tool_shed/util/shed_index.py | 2 +- lib/tool_shed/util/shed_util_common.py | 8 +- lib/tool_shed/webapp/buildapp.py | 2 +- lib/tool_shed/webapp/controllers/user.py | 8 +- .../webapp/framework/middleware/remoteuser.py | 2 +- lib/tool_shed/webapp/search/repo_search.py | 12 +- lib/tool_shed/webapp/search/tool_search.py | 8 +- lib/tool_shed/webapp/security/__init__.py | 2 +- 175 files changed, 599 insertions(+), 599 deletions(-) diff --git a/lib/galaxy/actions/admin.py b/lib/galaxy/actions/admin.py index 6a54762b98e..1eb65a6b778 100644 --- a/lib/galaxy/actions/admin.py +++ b/lib/galaxy/actions/admin.py @@ -152,7 +152,7 @@ class AdminActions: if len(names) == 1: raise ActionInputError(f"Quota '{names[0]}' is a default, please unset it as a default before deleting it.") elif len(names) > 1: - raise ActionInputError("Quotas are defaults, please unset them as defaults before deleting them: " + ', '.join(names)) + raise ActionInputError(f"Quotas are defaults, please unset them as defaults before deleting them: {', '.join(names)}") message = "Deleted %d quotas: " % len(quotas) for q in quotas: q.deleted = True @@ -171,7 +171,7 @@ class AdminActions: if len(names) == 1: raise ActionInputError(f"Quota '{names[0]}' has not been deleted, so it cannot be undeleted.") elif len(names) > 1: - raise ActionInputError("Quotas have not been deleted so they cannot be undeleted: " + ', '.join(names)) + raise ActionInputError(f"Quotas have not been deleted so they cannot be undeleted: {', '.join(names)}") message = "Undeleted %d quotas: " % len(quotas) for q in quotas: q.deleted = False @@ -196,7 +196,7 @@ class AdminActions: if len(names) == 1: raise ActionInputError(f"Quota '{names[0]}' has not been deleted, so it cannot be purged.") elif len(names) > 1: - raise ActionInputError("Quotas have not been deleted so they cannot be undeleted: " + ', '.join(names)) + raise ActionInputError(f"Quotas have not been deleted so they cannot be undeleted: {', '.join(names)}") message = "Purged %d quotas: " % len(quotas) for q in quotas: # Delete UserQuotaAssociations diff --git a/lib/galaxy/authnz/custos_authnz.py b/lib/galaxy/authnz/custos_authnz.py index 4fa2fc5c4ea..33b035bbf50 100644 --- a/lib/galaxy/authnz/custos_authnz.py +++ b/lib/galaxy/authnz/custos_authnz.py @@ -114,7 +114,7 @@ class CustosAuthnz(IdentityProvider): log.exception(message) raise exceptions.AuthenticationFailed(message) else: - login_redirect_url = login_redirect_url + 'root/login?confirm=true&custos_token=' + json.dumps(token) + login_redirect_url = f"{login_redirect_url}root/login?confirm=true&custos_token={json.dumps(token)}" return login_redirect_url, None custos_authnz_token = CustosAuthnzToken(user=user, @@ -224,7 +224,7 @@ class CustosAuthnz(IdentityProvider): else: client_secret = self.config['client_secret'] token_endpoint = self.config['token_endpoint'] - clientIdAndSec = self.config['client_id'] + ":" + self.config['client_secret'] # for custos + clientIdAndSec = f"{self.config['client_id']}:{self.config['client_secret']}" # for custos return oauth2_session.fetch_token( token_endpoint, client_secret=client_secret, @@ -263,7 +263,7 @@ class CustosAuthnz(IdentityProvider): self.config['credential_url'] = '/'.join([self.config['url'].rstrip('/'), 'credentials']) self._get_custos_credentials() # Set custos endpoints - clientIdAndSec = self.config['client_id'] + ":" + self.config['client_secret'] + clientIdAndSec = f"{self.config['client_id']}:{self.config['client_secret']}" eps = requests.get(self.config['well_known_oidc_config_uri'], headers={"Authorization": f"Basic {util.unicodify(base64.b64encode(util.smart_str(clientIdAndSec)))}"}, verify=False, params={'client_id': self.config['client_id']}) @@ -276,7 +276,7 @@ class CustosAuthnz(IdentityProvider): self._load_well_known_oidc_config(well_known_oidc_config) def _get_custos_credentials(self): - clientIdAndSec = self.config['client_id'] + ":" + self.config['client_secret'] + clientIdAndSec = f"{self.config['client_id']}:{self.config['client_secret']}" creds = requests.get(self.config['credential_url'], headers={"Authorization": f"Basic {util.unicodify(base64.b64encode(util.smart_str(clientIdAndSec)))}"}, verify=False, params={'client_id': self.config['client_id']}) diff --git a/lib/galaxy/authnz/psa_authnz.py b/lib/galaxy/authnz/psa_authnz.py index f42dbe2b6cf..a8827168e1c 100644 --- a/lib/galaxy/authnz/psa_authnz.py +++ b/lib/galaxy/authnz/psa_authnz.py @@ -165,7 +165,7 @@ class PSAAuthnz(IdentityProvider): on_the_fly_config(trans.sa_session) self.config[setting_name('LOGIN_REDIRECT_URL')] = login_redirect_url strategy = Strategy(trans.request, trans.session, Storage, self.config) - strategy.session_set(BACKENDS_NAME[self.config['provider']] + '_state', state_token) + strategy.session_set(f"{BACKENDS_NAME[self.config['provider']]}_state", state_token) backend = self._load_backend(strategy, self.config['redirect_uri']) redirect_url = do_complete( backend, diff --git a/lib/galaxy/config/__init__.py b/lib/galaxy/config/__init__.py index 8d0dd87117f..25e714ff7d6 100644 --- a/lib/galaxy/config/__init__.py +++ b/lib/galaxy/config/__init__.py @@ -815,7 +815,7 @@ class GalaxyAppConfiguration(BaseAppConfiguration, CommonConfigurationMixin): self.amqp_internal_connection = kwargs.get('amqp_internal_connection') # TODO Get extra amqp args as necessary for ssl elif 'database_connection' in kwargs: - self.amqp_internal_connection = "sqlalchemy+" + self.database_connection + self.amqp_internal_connection = f"sqlalchemy+{self.database_connection}" else: self.amqp_internal_connection = f"sqlalchemy+sqlite:///{self._in_data_dir('control.sqlite')}?isolation_level=IMMEDIATE" self.pretty_datetime_format = expand_pretty_datetime_format(self.pretty_datetime_format) diff --git a/lib/galaxy/containers/__init__.py b/lib/galaxy/containers/__init__.py index 97cf6e6cec1..5bf9a3c1a35 100644 --- a/lib/galaxy/containers/__init__.py +++ b/lib/galaxy/containers/__init__.py @@ -219,7 +219,7 @@ class ContainerInterface(metaclass=ABCMeta): } log.warning("option '%s' not in %s.option_map, guessing flag '%s' type '%s'", opt, self.__class__.__name__, optdef['flag'], optdef['type']) - opts.append(getattr(self, '_stringify_kwopt_' + optdef['type'])(optdef['flag'], val)) + opts.append(getattr(self, f"_stringify_kwopt_{optdef['type']}")(optdef['flag'], val)) return ' '.join(opts) def _stringify_kwopt_boolean(self, flag, val): @@ -272,7 +272,7 @@ class ContainerInterface(metaclass=ABCMeta): return stdout.strip() else: msg = f"Command '{command}' returned non-zero exit status {p.returncode}" - log.error(msg + ': ' + stderr.strip()) + log.error(f"{msg}: {stderr.strip()}") raise ContainerCLIError( msg, stdout=stdout.strip(), diff --git a/lib/galaxy/containers/docker.py b/lib/galaxy/containers/docker.py index aaf2c9cde4d..9a41889bcec 100644 --- a/lib/galaxy/containers/docker.py +++ b/lib/galaxy/containers/docker.py @@ -168,7 +168,7 @@ class DockerCLIInterface(DockerInterface): kwopt_list.append('{vol}:{bind}{mode}'.format( vol=hostvol, bind=guestopts['bind'], - mode=':' + mode if mode else '' + mode=f":{mode}" if mode else '' )) return self._stringify_kwopt_list(flag, kwopt_list) @@ -234,7 +234,7 @@ class DockerAPIClient: if isinstance(f, partial): f = f.func try: - return getattr(f, '__qualname__', f.im_class.__name__ + '.' + f.__name__) + return getattr(f, '__qualname__', f"{f.im_class.__name__}.{f.__name__}") except AttributeError: return f.__name__ @@ -489,7 +489,7 @@ class DockerAPIInterface(DockerInterface): # keyword arguments spec_kwopts = {} # retrieve the option map for the docker-py object we're creating - option_map = getattr(self, option_map_name + '_option_map') + option_map = getattr(self, f"{option_map_name}_option_map") # set defaults for key in filter(lambda k: option_map[k].get('default'), option_map.keys()): map_spec = option_map[key] diff --git a/lib/galaxy/containers/docker_model.py b/lib/galaxy/containers/docker_model.py index ebb62a016b9..7d368688f0f 100644 --- a/lib/galaxy/containers/docker_model.py +++ b/lib/galaxy/containers/docker_model.py @@ -24,8 +24,8 @@ from galaxy.util import ( CPUS_LABEL = '_galaxy_cpus' IMAGE_LABEL = '_galaxy_image' -CPUS_CONSTRAINT = 'node.labels.' + CPUS_LABEL -IMAGE_CONSTRAINT = 'node.labels.' + IMAGE_LABEL +CPUS_CONSTRAINT = f"node.labels.{CPUS_LABEL}" +IMAGE_CONSTRAINT = f"node.labels.{IMAGE_LABEL}" log = logging.getLogger(__name__) @@ -676,7 +676,7 @@ class DockerTask: service = service or interface.service(id=t.get('ServiceID')) node = node or interface.node(id=t.get('NodeID')) if service: - name = service.name + '.' + str(t['Slot']) + name = f"{service.name}.{str(t['Slot'])}" else: name = t['ID'] image = t['Spec']['ContainerSpec']['Image'].split('@', 1)[0], # remove pin diff --git a/lib/galaxy/containers/docker_swarm.py b/lib/galaxy/containers/docker_swarm.py index 8cc14768b0a..6ac26c547df 100644 --- a/lib/galaxy/containers/docker_swarm.py +++ b/lib/galaxy/containers/docker_swarm.py @@ -426,10 +426,10 @@ class DockerSwarmAPIInterface(DockerSwarmInterface, DockerAPIInterface): # service constraints kwopts['constraint'] = kwopts.get('constraint', []) if self._conf.service_create_image_constraint: - kwopts['constraint'].append(IMAGE_CONSTRAINT + '==' + image) + kwopts['constraint'].append(f"{IMAGE_CONSTRAINT}=={image}") if self._conf.service_create_cpus_constraint: cpus = kwopts.get('reserve_cpus', kwopts.get('limit_cpus', '1')) - kwopts['constraint'].append(CPUS_CONSTRAINT + '==' + cpus) + kwopts['constraint'].append(f"{CPUS_CONSTRAINT}=={cpus}") # ports if 'publish_port_random' in kwopts: kwopts['ports'] = [DockerSwarmAPIInterface.create_random_port_spec(kwopts.pop('publish_port_random'))] diff --git a/lib/galaxy/datatypes/assembly.py b/lib/galaxy/datatypes/assembly.py index d975251f5d4..b3be0ff1f9b 100644 --- a/lib/galaxy/datatypes/assembly.py +++ b/lib/galaxy/datatypes/assembly.py @@ -182,11 +182,11 @@ class Velvet(Html): dataset.metadata.short2_reads = short2_reads dataset.info = re.sub(r'.*velveth \S+', 'hash_length', re.sub(r'\n', ' ', log_msg)) if paired_end_reads: - gen_msg = gen_msg + ' Paired-End Reads' + gen_msg = f"{gen_msg} Paired-End Reads" if long_reads: - gen_msg = gen_msg + ' Long Reads' + gen_msg = f"{gen_msg} Long Reads" if len(gen_msg) > 0: - gen_msg = 'Uses: ' + gen_msg + gen_msg = f"Uses: {gen_msg}" except Exception: log.debug(f"Velveth could not read Log file in {efp}") log.debug(f"Velveth log info {gen_msg}") diff --git a/lib/galaxy/datatypes/binary.py b/lib/galaxy/datatypes/binary.py index 21329f8cdef..be2afb495ea 100644 --- a/lib/galaxy/datatypes/binary.py +++ b/lib/galaxy/datatypes/binary.py @@ -708,7 +708,7 @@ class CRAM(Binary): def set_meta(self, dataset, overwrite=True, **kwd): major_version, minor_version = self.get_cram_version(dataset.file_name) if major_version != -1: - dataset.metadata.cram_version = str(major_version) + "." + str(minor_version) + dataset.metadata.cram_version = f"{str(major_version)}.{str(minor_version)}" if not dataset.metadata.cram_index: index_file = dataset.metadata.spec['cram_index'].param.new_file(dataset=dataset) @@ -788,7 +788,7 @@ class Bcf(BaseBcf): try: cmd = ['python', '-c', f"import pysam.bcftools; pysam.bcftools.index('{dataset_symlink}')"] subprocess.check_call(cmd) - shutil.move(dataset_symlink + '.csi', index_file.file_name) + shutil.move(f"{dataset_symlink}.csi", index_file.file_name) except Exception as e: raise Exception(f'Error setting BCF metadata: {util.unicodify(e)}') finally: diff --git a/lib/galaxy/datatypes/converters/interval_to_fli.py b/lib/galaxy/datatypes/converters/interval_to_fli.py index 201a7d507d5..16dcf4f88d3 100644 --- a/lib/galaxy/datatypes/converters/interval_to_fli.py +++ b/lib/galaxy/datatypes/converters/interval_to_fli.py @@ -97,9 +97,9 @@ def main(): # Write padded entries. with open(out_fname, 'w') as out: - out.write(str(max_len + 1).ljust(max_len) + '\n') + out.write(f"{str(max_len + 1).ljust(max_len)}\n") for entry in entries: - out.write(entry.ljust(max_len) + '\n') + out.write(f"{entry.ljust(max_len)}\n") if __name__ == '__main__': diff --git a/lib/galaxy/datatypes/dataproviders/dataset.py b/lib/galaxy/datatypes/dataproviders/dataset.py index ccded5a6575..7d856ad847a 100644 --- a/lib/galaxy/datatypes/dataproviders/dataset.py +++ b/lib/galaxy/datatypes/dataproviders/dataset.py @@ -664,11 +664,11 @@ class SamtoolsDataProvider(line.RegexLineDataProvider): validated_flag_list.append('S') if validated_flag_list: - opt_list.append('-' + ''.join(validated_flag_list)) + opt_list.append(f"-{''.join(validated_flag_list)}") for flag, arg in options_dict.items(): if flag in self.FLAGS_W_ARGS: - opt_list.extend(['-' + flag, str(arg)]) + opt_list.extend([f"-{flag}", str(arg)]) return opt_list diff --git a/lib/galaxy/datatypes/dataproviders/external.py b/lib/galaxy/datatypes/dataproviders/external.py index 58790a5041d..7a3f9fb34f2 100644 --- a/lib/galaxy/datatypes/dataproviders/external.py +++ b/lib/galaxy/datatypes/dataproviders/external.py @@ -172,4 +172,4 @@ class TempfileDataProvider(base.DataProvider): parent_gen = super().__iter__() with open(self.tmp_file, 'w') as open_file: for datum in parent_gen: - open_file.write(datum + '\n') + open_file.write(f"{datum}\n") diff --git a/lib/galaxy/datatypes/genetics.py b/lib/galaxy/datatypes/genetics.py index 79742505f71..75c5281783b 100644 --- a/lib/galaxy/datatypes/genetics.py +++ b/lib/galaxy/datatypes/genetics.py @@ -102,7 +102,7 @@ class GenomeGraphs(Tabular): internal_url = "%s" % app.url_for(controller='dataset', dataset_id=dataset.id, action='display_at', - filename='ucsc_' + site_name) + filename=f"ucsc_{site_name}") display_url = "%s%s/display_as?id=%i&display_app=%s&authz_method=display_at" % (base_url, app.url_for(controller='root'), dataset.id, type) display_url = quote_plus(display_url) # was display_url = quote_plus( "%s/display_as?id=%i&display_app=%s" % (base_url, dataset.id, type) ) diff --git a/lib/galaxy/datatypes/isa.py b/lib/galaxy/datatypes/isa.py index 1511023ca84..4afb5b14e99 100644 --- a/lib/galaxy/datatypes/isa.py +++ b/lib/galaxy/datatypes/isa.py @@ -288,7 +288,7 @@ class _Isa(data.Data): html += '
      ' for data_file in assay.data_files: if data_file.filename != '': - html += '
    • ' + escape(util.unicodify(str(data_file.filename), 'utf-8')) + ' - ' + escape(util.unicodify(str(data_file.label), 'utf-8')) + '
    • ' + html += f"
    • {escape(util.unicodify(str(data_file.filename), 'utf-8'))} - {escape(util.unicodify(str(data_file.label), 'utf-8'))}
    • " html += '
    ' html += '' diff --git a/lib/galaxy/datatypes/tabular.py b/lib/galaxy/datatypes/tabular.py index 95d1fbf28e7..5d82a9a858b 100644 --- a/lib/galaxy/datatypes/tabular.py +++ b/lib/galaxy/datatypes/tabular.py @@ -1132,8 +1132,8 @@ class ConnectivityTable(Tabular): edam_format = "format_3309" file_ext = "ct" - header_regexp = re.compile("^[0-9]+" + "(?:\t|[ ]+)" + ".*?" + "(?:ENERGY|energy|dG)" + "[ \t].*?=") - structure_regexp = re.compile("^[0-9]+" + "(?:\t|[ ]+)" + "[ACGTURYKMSWBDHVN]+" + "(?:\t|[ ]+)" + "[^\t]+" + "(?:\t|[ ]+)" + "[^\t]+" + "(?:\t|[ ]+)" + "[^\t]+" + "(?:\t|[ ]+)" + "[^\t]+") + header_regexp = re.compile(f"^[0-9]+(?: |[ ]+).*?(?:ENERGY|energy|dG)[ ].*?=") + structure_regexp = re.compile(f"^[0-9]+(?: |[ ]+)[ACGTURYKMSWBDHVN]+(?: |[ ]+)[^ ]+(?: |[ ]+)[^ ]+(?: |[ ]+)[^ ]+(?: |[ ]+)[^ ]+") def __init__(self, **kwd): super().__init__(**kwd) @@ -1230,7 +1230,7 @@ class ConnectivityTable(Tabular): ck_data_body = re.sub('\n[ \t]+', '\n', ck_data_body) ck_data_body = re.sub('[ ]+', '\t', ck_data_body) - return dumps({'ck_data': util.unicodify(ck_data_header + "\n" + ck_data_body), 'ck_index': ck_index + 1}) + return dumps({'ck_data': util.unicodify(f"{ck_data_header}\n{ck_data_body}"), 'ck_index': ck_index + 1}) @build_sniff_from_prefix diff --git a/lib/galaxy/datatypes/triples.py b/lib/galaxy/datatypes/triples.py index 7ee143a9a8f..c7ef1e4c2b9 100644 --- a/lib/galaxy/datatypes/triples.py +++ b/lib/galaxy/datatypes/triples.py @@ -130,7 +130,7 @@ class Rdf(xml.GenericXml, Triples): def sniff_prefix(self, file_prefix): # ' + path + return f"date +\"%s\" > {path}" def __read_seconds_since_epoch(self, job_directory, name): path = self._instrument_file_path(job_directory, f"epoch_{name}") diff --git a/lib/galaxy/jobs/__init__.py b/lib/galaxy/jobs/__init__.py index 78666c1e2b2..bdef16cf9b3 100644 --- a/lib/galaxy/jobs/__init__.py +++ b/lib/galaxy/jobs/__init__.py @@ -785,7 +785,7 @@ class JobConfiguration(ConfiguresHandlers): # Name to load was specified as '' if '.' not in load: # For legacy reasons, try from galaxy.jobs.runners first if there's no '.' in the name - module_name = 'galaxy.jobs.runners.' + load + module_name = f"galaxy.jobs.runners.{load}" try: module = __import__(module_name) except ImportError: @@ -1521,10 +1521,10 @@ class JobWrapper(HasResourceParameters): dataset.info = (dataset.info or '') if context['stdout'].strip(): # Ensure white space between entries - dataset.info = dataset.info.rstrip() + "\n" + context['stdout'].strip() + dataset.info = f"{dataset.info.rstrip()}\n{context['stdout'].strip()}" if context['stderr'].strip(): # Ensure white space between entries - dataset.info = dataset.info.rstrip() + "\n" + context['stderr'].strip() + dataset.info = f"{dataset.info.rstrip()}\n{context['stderr'].strip()}" dataset.tool_version = self.version_string dataset.set_size() if 'uuid' in context: @@ -2204,7 +2204,7 @@ class JobWrapper(HasResourceParameters): elif job.history is not None and job.history.user is not None: return job.history.user.email elif job.galaxy_session is not None: - return 'anonymous@' + job.galaxy_session.remote_addr.split()[-1] + return f"anonymous@{job.galaxy_session.remote_addr.split()[-1]}" else: return 'anonymous@unknown' diff --git a/lib/galaxy/jobs/actions/post.py b/lib/galaxy/jobs/actions/post.py index 7387500f609..afc7f6565a1 100644 --- a/lib/galaxy/jobs/actions/post.py +++ b/lib/galaxy/jobs/actions/post.py @@ -47,7 +47,7 @@ class EmailAction(DefaultJobAction): try: frm = app.config.email_from history_id_encoded = app.security.encode_id(job.history_id) - link = app.config.galaxy_infrastructure_url + "/histories/view?id=" + history_id_encoded + link = f"{app.config.galaxy_infrastructure_url}/histories/view?id={history_id_encoded}" if frm is None: if action.action_arguments and 'host' in action.action_arguments: host = action.action_arguments['host'] @@ -191,7 +191,7 @@ class RenameDatasetAction(DefaultJobAction): if len(fields) > 1: temp = "" for i in range(1, len(fields) - 1): - temp += "." + fields[i] + temp += f".{fields[i]}" replacement += temp elif operation == "upper": replacement = replacement.upper() @@ -313,7 +313,7 @@ class ColumnSetAction(DefaultJobAction): @classmethod def get_short_str(cls, pja): - return "Set the following metadata values:
    " + "
    ".join('{} : {}'.format(escape(k), escape(v)) for k, v in pja.action_arguments.items()) + return f"Set the following metadata values:
    {'
    '.join('{} : {}'.format(escape(k), escape(v)) for k, v in pja.action_arguments.items())}" class SetMetadataAction(DefaultJobAction): diff --git a/lib/galaxy/jobs/dynamic_tool_destination.py b/lib/galaxy/jobs/dynamic_tool_destination.py index ad725a87e5b..046003b23af 100755 --- a/lib/galaxy/jobs/dynamic_tool_destination.py +++ b/lib/galaxy/jobs/dynamic_tool_destination.py @@ -352,9 +352,9 @@ class RuleValidator: if "nice_value" in rule: if rule["nice_value"] < -20 or rule["nice_value"] > 20: - error = "nice_value goes from -20 to 20; rule " + str(counter) - error += " in '" + str(tool) + "' has a nice_value of '" - error += str(rule["nice_value"]) + "'." + error = f"nice_value goes from -20 to 20; rule {str(counter)}" + error += f" in '{str(tool)}' has a nice_value of '" + error += f"{str(rule['nice_value'])}'." if not return_bool: error += " Setting nice_value to 0." rule["nice_value"] = 0 @@ -364,8 +364,8 @@ class RuleValidator: valid_rule = False else: - error = "No nice_value found for rule " + str(counter) + " in '" - error += str(tool) + "'." + error = f"No nice_value found for rule {str(counter)} in '" + error += f"{str(tool)}'." if not return_bool: error += " Setting nice_value to 0." rule["nice_value"] = 0 @@ -394,8 +394,8 @@ class RuleValidator: if "fail_message" in rule: if "destination" not in rule or rule['destination'] != "fail": - error = "Found a fail_message for rule " + str(counter) - error += " in '" + str(tool) + "', but destination is not 'fail'!" + error = f"Found a fail_message for rule {str(counter)}" + error += f" in '{str(tool)}', but destination is not 'fail'!" if not return_bool: error += " Setting destination to 'fail'." if verbose: @@ -409,12 +409,12 @@ class RuleValidator: suggestion = None if isinstance(rule["destination"], str): if rule["destination"] == "fail" and "fail_message" not in rule: - error = "Missing a fail_message for rule " + str(counter) - error += " in '" + str(tool) + "'." + error = f"Missing a fail_message for rule {str(counter)}" + error += f" in '{str(tool)}'." if not return_bool: error += " Adding generic fail_message." - message = "Invalid parameters for rule " + str(counter) - message += " in '" + str(tool) + "'." + message = f"Invalid parameters for rule {str(counter)}" + message += f" in '{str(tool)}'." rule["fail_message"] = message if verbose: log.debug(error) @@ -432,12 +432,12 @@ class RuleValidator: for priority in rule["destination"]["priority"]: if priority not in priority_list: error = "Invalid priority '" - error += str(priority) + "' for rule " - error += str(counter) + " in '" + str(tool) + "'." + error += f"{str(priority)}' for rule " + error += f"{str(counter)} in '{str(tool)}'." suggestion = get_typo_correction(priority, priority_list, max_edit_dist) if suggestion: - error += " Did you mean '" + str(suggestion) + "'?" + error += f" Did you mean '{str(suggestion)}'?" if not return_bool: error += " Ignoring..." if verbose: @@ -447,8 +447,8 @@ class RuleValidator: elif not isinstance(rule["destination"]["priority"][priority], str): error = "Cannot parse tool destination '" error += str(rule["destination"]["priority"][priority]) - error += "' for rule " + str(counter) - error += " in '" + str(tool) + "'." + error += f"' for rule {str(counter)}" + error += f" in '{str(tool)}'." if not return_bool: error += " Ignoring..." if verbose: @@ -463,24 +463,24 @@ class RuleValidator: if not is_valid: valid_rule = False else: - error = "No destination specified for rule " + str(counter) - error += " in '" + str(tool) + "'." + error = f"No destination specified for rule {str(counter)}" + error += f" in '{str(tool)}'." if not return_bool: error += " Ignoring..." if verbose: log.debug(error) valid_rule = False else: - error = "No destination specified for rule " + str(counter) - error += " in '" + str(tool) + "'." + error = f"No destination specified for rule {str(counter)}" + error += f" in '{str(tool)}'." if not return_bool: error += " Ignoring..." if verbose: log.debug(error) valid_rule = False else: - error = "No destination specified for rule " + str(counter) - error += " in '" + str(tool) + "'." + error = f"No destination specified for rule {str(counter)}" + error += f" in '{str(tool)}'." if not return_bool: error += " Ignoring..." if verbose: @@ -542,8 +542,8 @@ class RuleValidator: if upper_bound != -1 and lower_bound > upper_bound: - error = "lower_bound exceeds upper_bound for rule " + str(counter) - error += " in '" + str(tool) + "'." + error = f"lower_bound exceeds upper_bound for rule {str(counter)}" + error += f" in '{str(tool)}'." if not return_bool: error += " Reversing bounds." temp_upper_bound = rule["upper_bound"] @@ -555,8 +555,8 @@ class RuleValidator: valid_rule = False else: - error = "Missing bounds for rule " + str(counter) - error += " in '" + str(tool) + "'." + error = f"Missing bounds for rule {str(counter)}" + error += f" in '{str(tool)}'." if not return_bool: error += " Ignoring rule." rule = None @@ -594,8 +594,8 @@ class RuleValidator: """ if "arguments" not in rule or not isinstance(rule["arguments"], dict): - error = "No arguments found for rule " + str(counter) + " in '" - error += str(tool) + "' despite being of type arguments." + error = f"No arguments found for rule {str(counter)} in '" + error += f"{str(tool)}' despite being of type arguments." if not return_bool: error += " Ignoring rule." rule = None @@ -638,9 +638,9 @@ class RuleValidator: if isinstance(rule["users"], list): for user in reversed(rule["users"]): if not isinstance(user, str): - error = "Entry '" + str(user) + "' in users for rule " - error += str(counter) + " in tool '" + str(tool) - error += "' is in an " + "invalid format!" + error = f"Entry '{str(user)}' in users for rule " + error += f"{str(counter)} in tool '{str(tool)}" + error += f"' is in an invalid format!" if not return_bool: error += " Ignoring entry." if verbose: @@ -650,9 +650,9 @@ class RuleValidator: else: if re.match(emailregex, user) is None: - error = "Supplied email '" + str(user) - error += "' for rule " + str(counter) + " in tool '" - error += str(tool) + "' is in " + "an invalid format!" + error = f"Supplied email '{str(user)}" + error += f"' for rule {str(counter)} in tool '" + error += f"{str(tool)}' is in an invalid format!" if not return_bool: error += " Ignoring email." if verbose: @@ -672,8 +672,8 @@ class RuleValidator: # post-processing checking to make sure we didn't just remove all the users # if we did, we should ignore the rule if rule is not None and rule["users"] is not None and len(rule["users"]) == 0: - error = "No valid user emails were specified for rule " + str(counter) - error += " in tool '" + str(tool) + "'!" + error = f"No valid user emails were specified for rule {str(counter)}" + error += f" in tool '{str(tool)}'!" if not return_bool: error += " Ignoring rule." rule = None @@ -786,7 +786,7 @@ def validate_destination(app, destination: str, err_message: str, err_message_co if not valid_destination: error = err_message % err_message_contents if suggestion: - error += " Did you mean '" + suggestion + "'?" + error += f" Did you mean '{suggestion}'?" if not return_bool: error += " Ignoring..." if verbose: @@ -828,7 +828,7 @@ def validate_config(obj: dict, app=None, return_bool: bool = False): else: valid_config = False if obj: - log.debug("Verbose value '" + str(obj['verbose']) + "' is not True or False! Falling back to verbose...") + log.debug(f"Verbose value '{str(obj['verbose'])}' is not True or False! Falling back to verbose...") verbose = True if not return_bool and verbose: @@ -891,7 +891,7 @@ def validate_config(obj: dict, app=None, return_bool: bool = False): suggestion = get_typo_correction(obj['default_priority'], priority_list, max_edit_dist) if suggestion: - error += " Did you mean '" + str(suggestion) + "'?" + error += f" Did you mean '{str(suggestion)}'?" if verbose: log.debug(error) else: @@ -946,17 +946,17 @@ def validate_config(obj: dict, app=None, return_bool: bool = False): suggestion = get_typo_correction(curr['priority'], priority_list, max_edit_dist) if suggestion: - error += " Did you mean '" + str(suggestion) + "'?" + error += f" Did you mean '{str(suggestion)}'?" if verbose: log.debug(error) valid_config = False else: - error = "User '" + user + "' is missing a priority!" + error = f"User '{user}' is missing a priority!" if verbose: log.debug(error) valid_config = False else: - error = "User '" + user + "' is missing a priority!" + error = f"User '{user}' is missing a priority!" if verbose: log.debug(error) valid_config = False @@ -1027,13 +1027,13 @@ def validate_config(obj: dict, app=None, return_bool: bool = False): suggestion = get_typo_correction(priority, priority_list, max_edit_dist) if suggestion: - error += " Did you mean '" + str(suggestion) + "'?" + error += f" Did you mean '{str(suggestion)}'?" if verbose: log.debug(error) valid_config = False else: error = "No default priority destinations specified" - error += " for " + str(tool) + " in config!" + error += f" for {str(tool)} in config!" if verbose: log.debug(error) valid_config = False @@ -1081,8 +1081,8 @@ def validate_config(obj: dict, app=None, return_bool: bool = False): # if rule['rule_type'] in available_rule_types else: error = "Unrecognized rule_type '" - error += rule['rule_type'] + "' " - error += "found in '" + str(tool) + "'. " + error += f"{rule['rule_type']}' " + error += f"found in '{str(tool)}'. " if not return_bool: error += "Ignoring..." if verbose: @@ -1094,7 +1094,7 @@ def validate_config(obj: dict, app=None, return_bool: bool = False): counter += 1 error = "No rule_type found for rule " error += str(counter) - error += " in '" + str(tool) + "'." + error += f" in '{str(tool)}'." if verbose: log.debug(error) valid_config = False @@ -1102,7 +1102,7 @@ def validate_config(obj: dict, app=None, return_bool: bool = False): # if "rules" in curr and isinstance(curr['rules'], list): elif not tool_has_default: valid_config = False - error = "Tool '" + str(tool) + "' does not have" + error = f"Tool '{str(tool)}' does not have" error += " rules nor a default_destination!" if verbose: log.debug(error) @@ -1110,7 +1110,7 @@ def validate_config(obj: dict, app=None, return_bool: bool = False): # if obj['tools'][tool] is not None: else: valid_config = False - error = "Config section for tool '" + str(tool) + "' is blank!" + error = f"Config section for tool '{str(tool)}' is blank!" if verbose: log.debug(error) @@ -1128,7 +1128,7 @@ def validate_config(obj: dict, app=None, return_bool: bool = False): # quickly run through categories to detect unrecognized types for category in obj.keys(): if category not in valid_categories: - error = "Unrecognized category '" + category + error = f"Unrecognized category '{category}" error += "' found in config file!" if verbose: log.debug(error) @@ -1225,7 +1225,7 @@ def str_to_bytes(size): try: curr_size = float(curr_size) except ValueError: - error = "Unable to convert size " + str(size) + error = f"Unable to convert size {str(size)}" raise MalformedYMLException(error) # Get the unit and convert to bytes @@ -1234,7 +1234,7 @@ def str_to_bytes(size): for _ in range(pos, 1, -1): curr_size *= 1024 except ValueError: - error = "Unable to convert size " + str(size) + error = f"Unable to convert size {str(size)}" raise MalformedYMLException(error) except NameError: pass @@ -1343,7 +1343,7 @@ def map_tool_to_destination( if inp_data[da] is not None and os.path.isfile(inp_data[da].file_name): num_input_datasets += 1 if verbose: - message = "Loading file: " + str(da) + message = f"Loading file: {str(da)}" message += str(inp_data[da].file_name) log.debug(message) @@ -1367,15 +1367,15 @@ def map_tool_to_destination( except AttributeError: # Otherwise, say that input isn't a file if verbose: - log.debug("Not a file: " + str(inp_data[da])) + log.debug(f"Not a file: {str(inp_data[da])}") if verbose: if filesize_rule_present: - log.debug("Total size: " + bytes_to_str(file_size)) + log.debug(f"Total size: {bytes_to_str(file_size)}") if records_rule_present: - log.debug("Total amount of records: " + str(records)) + log.debug(f"Total amount of records: {str(records)}") if num_input_datasets_rule_present: - log.debug("Total number of files: " + str(num_input_datasets)) + log.debug(f"Total number of files: {str(num_input_datasets)}") matched_rule = None user_authorized = None @@ -1516,7 +1516,7 @@ def map_tool_to_destination( except KeyError: matched = False if verbose: - error = "Argument '" + str(arg) + error = f"Argument '{str(arg)}" error += "' not recognized!" log.debug(error) @@ -1528,15 +1528,15 @@ def map_tool_to_destination( # if user_authorized else: if verbose: - error = "User email '" + str(user_email) + "' not " + error = f"User email '{str(user_email)}' not " error += "specified in list of authorized users for " - error += "rule " + str(rule_counter) + " in tool '" - error += str(tool.old_id) + "'! Ignoring rule." + error += f"rule {str(rule_counter)} in tool '" + error += f"{str(tool.old_id)}'! Ignoring rule." log.debug(error) # if str(tool.old_id) in config else: - error = "Tool '" + str(tool.old_id) + "' not specified in config. " + error = f"Tool '{str(tool.old_id)}' not specified in config. " error += "Using default destination." if verbose: log.debug(error) @@ -1565,7 +1565,7 @@ def map_tool_to_destination( # if "default_destination" in config else: destination = "fail" - fail_message = "Job '" + str(tool.old_id) + "' failed; " + fail_message = f"Job '{str(tool.old_id)}' failed; " fail_message += "no global default destination specified in config!" # if fail_message is not None @@ -1582,11 +1582,11 @@ def map_tool_to_destination( if config is not None: if destination == "fail": - output = "An error occurred: " + fail_message + output = f"An error occurred: {fail_message}" log.debug(output) else: - output = "Running '" + str(tool.old_id) + "' with '" - output += destination + "'." + output = f"Running '{str(tool.old_id)}' with '" + output += f"{destination}'." log.debug(output) return destination @@ -1650,7 +1650,7 @@ def get_destination_list_from_job_config(job_config_location) -> set: destination_list.add(destination.get("id")) else: - error = "Destination ID '" + str(destination) + error = f"Destination ID '{str(destination)}" error += "' in job configuration file cannot be" error += " parsed. Things may not work as expected!" log.debug(error) @@ -1783,7 +1783,7 @@ if __name__ == '__main__': '-j', '--job-config', dest='job_config') parser.add_argument( - '-V', '--version', action='version', version="%(prog)s " + __version__) + '-V', '--version', action='version', version=f"%(prog)s {__version__}") args = parser.parse_args() diff --git a/lib/galaxy/jobs/handler.py b/lib/galaxy/jobs/handler.py index 5116e5662e8..af91fa1c2e2 100644 --- a/lib/galaxy/jobs/handler.py +++ b/lib/galaxy/jobs/handler.py @@ -1022,7 +1022,7 @@ class DefaultJobDispatcher: # URLs can have their URL params converted to the destination's param # dict by the plugin. self.app.job_config.convert_legacy_destinations(self.job_runners) - log.debug("Loaded job runners plugins: " + ':'.join(self.job_runners.keys())) + log.debug(f"Loaded job runners plugins: {':'.join(self.job_runners.keys())}") def __get_runner_name(self, job_wrapper): if job_wrapper.can_split(): diff --git a/lib/galaxy/jobs/runners/__init__.py b/lib/galaxy/jobs/runners/__init__.py index 9c2267090d3..cffed06346e 100644 --- a/lib/galaxy/jobs/runners/__init__.py +++ b/lib/galaxy/jobs/runners/__init__.py @@ -574,7 +574,7 @@ class JobState: job_name += f'_{self.job_wrapper.tool.old_id}' if not self.redact_email_in_job_name and self.job_wrapper.user: job_name += f'_{self.job_wrapper.user}' - self.job_name = ''.join(x if x in (string.ascii_letters + string.digits + '_') else '_' for x in job_name) + self.job_name = ''.join(x if x in (f"{string.ascii_letters + string.digits}_") else '_' for x in job_name) @staticmethod def default_job_file(files_dir, id_tag): diff --git a/lib/galaxy/jobs/runners/chronos.py b/lib/galaxy/jobs/runners/chronos.py index 5d3a42df1d4..d500ce3a5e8 100644 --- a/lib/galaxy/jobs/runners/chronos.py +++ b/lib/galaxy/jobs/runners/chronos.py @@ -147,10 +147,10 @@ class ChronosJobRunner(AsynchronousJobRunner): @handle_exception_call def queue_job(self, job_wrapper): - LOGGER.debug("Starting queue_job for job " + job_wrapper.get_id_tag()) + LOGGER.debug(f"Starting queue_job for job {job_wrapper.get_id_tag()}") if not self.prepare_job(job_wrapper, include_metadata=False, modify_command_for_container=False): - LOGGER.debug("Not ready " + job_wrapper.get_id_tag()) + LOGGER.debug(f"Not ready {job_wrapper.get_id_tag()}") return job_destination = job_wrapper.job_destination chronos_job_spec = self._get_job_spec(job_wrapper) @@ -279,7 +279,7 @@ class ChronosJobRunner(AsynchronousJobRunner): if not os.path.exists(job_wrapper.working_directory): LOGGER.error("No working directory found") - path = job_wrapper.working_directory + '/chronos_' + job_wrapper.get_id_tag() + '.sh' + path = f"{job_wrapper.working_directory}/chronos_{job_wrapper.get_id_tag()}.sh" mode = 0o755 with open(path, 'w', encoding='utf-8') as f: @@ -295,7 +295,7 @@ class ChronosJobRunner(AsynchronousJobRunner): template = { 'async': False, # 'command': job_wrapper.runner_command_line, - 'command': '$SHELL ' + command_script_path, + 'command': f"$SHELL {command_script_path}", 'owner': self.runner_params['owner'], 'disabled': False, 'schedule': 'R1//PT1S', diff --git a/lib/galaxy/jobs/runners/cli.py b/lib/galaxy/jobs/runners/cli.py index 629220ca664..0896619c8d4 100644 --- a/lib/galaxy/jobs/runners/cli.py +++ b/lib/galaxy/jobs/runners/cli.py @@ -43,8 +43,8 @@ class ShellJobRunner(AsynchronousJobRunner): params = {} shell_params, job_params = url.split('/')[2:4] # split 'foo=bar&baz=quux' into { 'foo' : 'bar', 'baz' : 'quux' } - shell_params = {'shell_' + k: v for k, v in [kv.split('=', 1) for kv in shell_params.split('&')]} - job_params = {'job_' + k: v for k, v in [kv.split('=', 1) for kv in job_params.split('&')]} + shell_params = {f"shell_{k}": v for k, v in [kv.split('=', 1) for kv in shell_params.split('&')]} + job_params = {f"job_{k}": v for k, v in [kv.split('=', 1) for kv in job_params.split('&')]} params.update(shell_params) params.update(job_params) log.debug(f"Converted URL '{url}' to destination runner=cli, params={params}") diff --git a/lib/galaxy/jobs/runners/drmaa.py b/lib/galaxy/jobs/runners/drmaa.py index 1e196031dec..dfab38465c6 100644 --- a/lib/galaxy/jobs/runners/drmaa.py +++ b/lib/galaxy/jobs/runners/drmaa.py @@ -45,8 +45,8 @@ class DRMAAJobRunner(AsynchronousJobRunner): runner_param_specs = { 'drmaa_library_path': dict(map=str, default=os.environ.get('DRMAA_LIBRARY_PATH', None))} for retry_exception in RETRY_EXCEPTIONS_LOWER: - runner_param_specs[retry_exception + '_state'] = dict(map=str, valid=lambda x: x in (model.Job.states.OK, model.Job.states.ERROR), default=model.Job.states.OK) - runner_param_specs[retry_exception + '_retries'] = dict(map=int, valid=lambda x: int(x) >= 0, default=0) + runner_param_specs[f"{retry_exception}_state"] = dict(map=str, valid=lambda x: x in (model.Job.states.OK, model.Job.states.ERROR), default=model.Job.states.OK) + runner_param_specs[f"{retry_exception}_retries"] = dict(map=int, valid=lambda x: int(x) >= 0, default=0) if 'runner_param_specs' not in kwargs: kwargs['runner_param_specs'] = dict() @@ -283,11 +283,11 @@ class DRMAAJobRunner(AsynchronousJobRunner): state = self.ds.job_status(external_job_id) # Reset exception retries for retry_exception in RETRY_EXCEPTIONS_LOWER: - setattr(ajs, retry_exception + '_retries', 0) + setattr(ajs, f"{retry_exception}_retries", 0) except (drmaa.InternalException, drmaa.InvalidJobException) as e: ecn = type(e).__name__ - retry_param = ecn.lower() + '_retries' - state_param = ecn.lower() + '_state' + retry_param = f"{ecn.lower()}_retries" + state_param = f"{ecn.lower()}_state" retries = getattr(ajs, retry_param, 0) log.warning("(%s/%s) unable to check job status because of %s exception for %d consecutive tries: %s", galaxy_id_tag, external_job_id, ecn, retries + 1, e) if self.runner_params[retry_param] > 0: @@ -436,7 +436,7 @@ class DRMAAJobRunner(AsynchronousJobRunner): job_name += f'_{job_wrapper.tool.old_id}' if not self.redact_email_in_job_name and external_runjob_script is None: job_name += f'_{job_wrapper.user}' - job_name = ''.join(x if x in (string.ascii_letters + string.digits + '_') else '_' for x in job_name) + job_name = ''.join(x if x in (f"{string.ascii_letters + string.digits}_") else '_' for x in job_name) if self.restrict_job_name_length: job_name = job_name[:self.restrict_job_name_length] return job_name diff --git a/lib/galaxy/jobs/runners/godocker.py b/lib/galaxy/jobs/runners/godocker.py index 9f9399497e6..6b689ca4984 100644 --- a/lib/galaxy/jobs/runners/godocker.py +++ b/lib/galaxy/jobs/runners/godocker.py @@ -157,7 +157,7 @@ class GodockerJobRunner(AsynchronousJobRunner): log.error("Job creation failure. No Response from GoDocker") job_wrapper.fail("Not submitted") else: - log.debug("Starting queue_job for job " + job_id) + log.debug(f"Starting queue_job for job {job_id}") # Create an object of AsynchronousJobState and add it to the monitor queue. ajs = AsynchronousJobState(files_dir=job_wrapper.working_directory, job_wrapper=job_wrapper, job_id=job_id, job_destination=job_destination) self.monitor_queue.put(ajs) @@ -180,7 +180,7 @@ class GodockerJobRunner(AsynchronousJobRunner): """ Get task from GoDocker """ job_persisted_state = job_state.job_wrapper.get_state() job_status_god = self.get_task(job_state.job_id) - log.debug("Job ID: " + str(job_state.job_id) + " Job Status: " + str(job_status_god['status']['primary'])) + log.debug(f"Job ID: {str(job_state.job_id)} Job Status: {str(job_status_god['status']['primary'])}") if job_status_god['status']['primary'] == "over" or job_persisted_state == model.Job.states.STOPPED: job_state.running = False @@ -234,7 +234,7 @@ class GodockerJobRunner(AsynchronousJobRunner): No Return data expected ''' job_id = job_wrapper.job_id - log.debug("STOP JOB EXECUTION OF JOB ID: " + str(job_id)) + log.debug(f"STOP JOB EXECUTION OF JOB ID: {str(job_id)}") # Get task status from GoDocker. job_status_god = self.get_task_status(job_id) if job_status_god['status']['primary'] != "over": @@ -276,8 +276,8 @@ class GodockerJobRunner(AsynchronousJobRunner): if vol['name'] == "go-docker": path = str(vol['path']) if path: - god_output_file = path + "/god.log" - god_error_file = path + "/god.err" + god_output_file = f"{path}/god.log" + god_error_file = f"{path}/god.err" try: # Read from GoDocker output_file and write it into galaxy output_file. f = open(god_output_file) @@ -299,9 +299,9 @@ class GodockerJobRunner(AsynchronousJobRunner): log_file.write(out_log) log_file.close() f.close() - log.debug("CREATE OUTPUT FILE: " + job_state.output_file) - log.debug("CREATE ERROR FILE: " + job_state.error_file) - log.debug("CREATE EXIT CODE FILE: " + job_state.exit_code_file) + log.debug(f"CREATE OUTPUT FILE: {job_state.output_file}") + log.debug(f"CREATE ERROR FILE: {job_state.error_file}") + log.debug(f"CREATE EXIT CODE FILE: {job_state.exit_code_file}") except OSError as e: log.error('Could not access task log file: %s', unicodify(e)) log.debug("IO Error occurred when accessing the files.") @@ -315,7 +315,7 @@ class GodockerJobRunner(AsynchronousJobRunner): Create Login model schema of GoDocker and call the http_post_request method. """ log.debug("LOGIN TASK TO BE EXECUTED \n") - log.debug("GODOCKER LOGIN: " + str(login)) + log.debug(f"GODOCKER LOGIN: {str(login)}") data = json.dumps({'user': login, 'apikey': apikey}) # Create object of Godocker class g_auth = Godocker(server, login, apikey, noCert) @@ -378,11 +378,11 @@ class GodockerJobRunner(AsynchronousJobRunner): if(job_destination.params["virtualenv"] == "true"): GALAXY_VENV_TEMPLATE = """GALAXY_VIRTUAL_ENV="%s"; if [ "$GALAXY_VIRTUAL_ENV" != "None" -a -z "$VIRTUAL_ENV" -a -f "$GALAXY_VIRTUAL_ENV/bin/activate" ]; then . "$GALAXY_VIRTUAL_ENV/bin/activate"; fi;""" venv = GALAXY_VENV_TEMPLATE % job_wrapper.galaxy_virtual_env - command = "#!/bin/bash\n" + "cd " + job_wrapper.working_directory + "\n" + venv + "\n" + job_wrapper.runner_command_line + command = f"#!/bin/bash\ncd {job_wrapper.working_directory}\n{venv}\n{job_wrapper.runner_command_line}" else: - command = "#!/bin/bash\n" + "cd " + job_wrapper.working_directory + "\n" + job_wrapper.runner_command_line + command = f"#!/bin/bash\ncd {job_wrapper.working_directory}\n{job_wrapper.runner_command_line}" except Exception: - command = "#!/bin/bash\n" + "cd " + job_wrapper.working_directory + "\n" + job_wrapper.runner_command_line + command = f"#!/bin/bash\ncd {job_wrapper.working_directory}\n{job_wrapper.runner_command_line}" # GoDocker Job model schema job = { @@ -424,7 +424,7 @@ class GodockerJobRunner(AsynchronousJobRunner): result = self.auth.http_post_request( "/api/1.0/task", json.dumps(job), - {'Authorization': 'Bearer ' + self.auth.token, 'Content-type': 'application/json', 'Accept': 'application/json'} + {'Authorization': f"Bearer {self.auth.token}", 'Content-type': 'application/json', 'Accept': 'application/json'} ) # Return job_id return str(result.json()['id']) @@ -435,7 +435,7 @@ class GodockerJobRunner(AsynchronousJobRunner): """ job = False if self.auth.token: - result = self.auth.http_get_request("/api/1.0/task/" + str(job_id), {'Authorization': 'Bearer ' + self.auth.token}) + result = self.auth.http_get_request(f"/api/1.0/task/{str(job_id)}", {'Authorization': f"Bearer {self.auth.token}"}) job = result.json() # Return the job return job @@ -446,7 +446,7 @@ class GodockerJobRunner(AsynchronousJobRunner): """ job = False if self.auth.token: - result = self.auth.http_get_request("/api/1.0/task/" + str(job_id) + "/suspend", {'Authorization': 'Bearer ' + self.auth.token}) + result = self.auth.http_get_request(f"/api/1.0/task/{str(job_id)}/suspend", {'Authorization': f"Bearer {self.auth.token}"}) job = result.json() # Return the job return job @@ -457,7 +457,7 @@ class GodockerJobRunner(AsynchronousJobRunner): """ job = False if self.auth.token: - result = self.auth.http_get_request("/api/1.0/task/" + str(job_id) + "/status", {'Authorization': 'Bearer ' + self.auth.token}) + result = self.auth.http_get_request(f"/api/1.0/task/{str(job_id)}/status", {'Authorization': f"Bearer {self.auth.token}"}) job = result.json() # Return task status return job @@ -468,7 +468,7 @@ class GodockerJobRunner(AsynchronousJobRunner): """ job = False if self.auth.token: - result = self.auth.http_delete_request("/api/1.0/task/" + str(job_id), {'Authorization': 'Bearer ' + self.auth.token}) + result = self.auth.http_delete_request(f"/api/1.0/task/{str(job_id)}", {'Authorization': f"Bearer {self.auth.token}"}) job = result.json() # Return the job return job diff --git a/lib/galaxy/jobs/runners/kubernetes.py b/lib/galaxy/jobs/runners/kubernetes.py index aaf33c98ed5..da158f48bf7 100644 --- a/lib/galaxy/jobs/runners/kubernetes.py +++ b/lib/galaxy/jobs/runners/kubernetes.py @@ -127,7 +127,7 @@ class KubernetesJobRunner(AsynchronousJobRunner): # prepare the job # We currently don't need to include_metadata or include_work_dir_outputs, as working directory is the same # where galaxy will expect results. - log.debug("Starting queue_job for job " + job_wrapper.get_id_tag()) + log.debug(f"Starting queue_job for job {job_wrapper.get_id_tag()}") ajs = AsynchronousJobState(files_dir=job_wrapper.working_directory, job_wrapper=job_wrapper, job_destination=job_wrapper.job_destination) @@ -240,7 +240,7 @@ class KubernetesJobRunner(AsynchronousJobRunner): """ label_val = self.LABEL_REGEX.sub("_", value) if not self.LABEL_START.search(label_val): - label_val = 'x' + label_val + label_val = f"x{label_val}" if not self.LABEL_END.search(label_val): label_val += 'x' return label_val @@ -521,14 +521,14 @@ class KubernetesJobRunner(AsynchronousJobRunner): repo = "" owner = "" if 'repo' in job_destination.params: - repo = job_destination.params['repo'] + "/" + repo = f"{job_destination.params['repo']}/" if 'owner' in job_destination.params: - owner = job_destination.params['owner'] + "/" + owner = f"{job_destination.params['owner']}/" k8s_cont_image = repo + owner + job_destination.params['image'] if 'tag' in job_destination.params: - k8s_cont_image += ":" + job_destination.params['tag'] + k8s_cont_image += f":{job_destination.params['tag']}" return k8s_cont_image @@ -788,7 +788,7 @@ class KubernetesJobRunner(AsynchronousJobRunner): def recover(self, job, job_wrapper): """Recovers jobs stuck in the queued/running state when Galaxy started""" job_id = job.get_job_runner_external_id() - log.debug("k8s trying to recover job: " + job_id) + log.debug(f"k8s trying to recover job: {job_id}") if job_id is None: self.put(job_wrapper) return diff --git a/lib/galaxy/jobs/runners/pbs.py b/lib/galaxy/jobs/runners/pbs.py index 8e235c44872..7088007a6f7 100644 --- a/lib/galaxy/jobs/runners/pbs.py +++ b/lib/galaxy/jobs/runners/pbs.py @@ -140,7 +140,7 @@ class PBSJobRunner(AsynchronousJobRunner): assert opts != [''] # stripping the - comes later (in parse_destination_params) for i, opt in enumerate(opts): - opts[i] = '-' + opt + opts[i] = f"-{opt}" except Exception: opts = [] for opt in opts: @@ -184,7 +184,7 @@ class PBSJobRunner(AsynchronousJobRunner): rval.append(dict(name=pbs.ATTR_l, value=val, resource=res)) else: try: - rval.append(dict(name=getattr(pbs, 'ATTR_' + arg), value=value)) + rval.append(dict(name=getattr(pbs, f"ATTR_{arg}"), value=value)) except AttributeError as e: raise Exception(f"Invalid parameter '{arg}': {e}") return rval @@ -242,8 +242,8 @@ class PBSJobRunner(AsynchronousJobRunner): # If an application server is set, we're staging if self.app.config.pbs_application_server: - pbs_ofile = self.app.config.pbs_application_server + ':' + ofile - pbs_efile = self.app.config.pbs_application_server + ':' + efile + pbs_ofile = f"{self.app.config.pbs_application_server}:{ofile}" + pbs_efile = f"{self.app.config.pbs_application_server}:{efile}" output_files = [str(o) for o in output_fnames] output_files.append(ecfile) stagein = self.get_stage_in_out(job_wrapper.get_input_fnames() + output_files, symlink=True) diff --git a/lib/galaxy/jobs/runners/slurm.py b/lib/galaxy/jobs/runners/slurm.py index f05dcd00658..794d9bde7ae 100644 --- a/lib/galaxy/jobs/runners/slurm.py +++ b/lib/galaxy/jobs/runners/slurm.py @@ -85,7 +85,7 @@ class SlurmJobRunner(DRMAAJobRunner): job_info_values.append(v) except ValueError: # Some value may contain spaces (e.g. `Comment=** time_limit (60m) min_nodes (1) **`) - job_info_values[-1] += ' ' + job_info + job_info_values[-1] += f" {job_info}" job_info_dict = dict(zip(job_info_keys, job_info_values)) return job_info_dict['JobState'] diff --git a/lib/galaxy/jobs/runners/util/cli/job/lsf.py b/lib/galaxy/jobs/runners/util/cli/job/lsf.py index bce64d4120e..a3ad27e123c 100644 --- a/lib/galaxy/jobs/runners/util/cli/job/lsf.py +++ b/lib/galaxy/jobs/runners/util/cli/job/lsf.py @@ -66,7 +66,7 @@ class LSF(BaseJobExec): return "bjobs -a -o \"id stat\" -noheader" # check this def get_single_status(self, job_id): - return "bjobs -o stat -noheader " + job_id + return f"bjobs -o stat -noheader {job_id}" def parse_status(self, status, job_ids): # Get status for each job, skipping header. @@ -91,7 +91,7 @@ class LSF(BaseJobExec): return self._get_job_state(status) def get_failure_reason(self, job_id): - return "bjobs -l " + job_id + return f"bjobs -l {job_id}" def parse_failure_reason(self, reason, job_id): # LSF will produce the following in the job output file: diff --git a/lib/galaxy/jobs/runners/util/cli/job/slurm.py b/lib/galaxy/jobs/runners/util/cli/job/slurm.py index ff8a6ba46d9..d87479b513d 100644 --- a/lib/galaxy/jobs/runners/util/cli/job/slurm.py +++ b/lib/galaxy/jobs/runners/util/cli/job/slurm.py @@ -52,7 +52,7 @@ class Slurm(BaseJobExec): return "squeue -a -o '%A %t'" def get_single_status(self, job_id): - return "squeue -a -o '%A %t' -j " + job_id + return f"squeue -a -o '%A %t' -j {job_id}" def parse_status(self, status, job_ids): # Get status for each job, skipping header. diff --git a/lib/galaxy/jobs/runners/util/condor/__init__.py b/lib/galaxy/jobs/runners/util/condor/__init__.py index 2fbead6c80f..93b2c5cdf5b 100644 --- a/lib/galaxy/jobs/runners/util/condor/__init__.py +++ b/lib/galaxy/jobs/runners/util/condor/__init__.py @@ -60,10 +60,10 @@ def build_submit_description(executable, output, error, user_log, query_params): submit_description = [] for key, value in all_query_params.items(): submit_description.append(f'{key} = {value}') - submit_description.append('executable = ' + executable) - submit_description.append('output = ' + output) - submit_description.append('error = ' + error) - submit_description.append('log = ' + user_log) + submit_description.append(f"executable = {executable}") + submit_description.append(f"output = {output}") + submit_description.append(f"error = {error}") + submit_description.append(f"log = {user_log}") submit_description.append('queue') return '\n'.join(submit_description) @@ -109,15 +109,15 @@ def summarize_condor_log(log_file, external_id): s1 = s4 = s7 = s5 = s9 = False with open(log_file) as log_handle: for line in log_handle: - if '001 (' + log_job_id + '.' in line: + if f"001 ({log_job_id}." in line: s1 = True - if '004 (' + log_job_id + '.' in line: + if f"004 ({log_job_id}." in line: s4 = True - if '007 (' + log_job_id + '.' in line: + if f"007 ({log_job_id}." in line: s7 = True - if '005 (' + log_job_id + '.' in line: + if f"005 ({log_job_id}." in line: s5 = True - if '009 (' + log_job_id + '.' in line: + if f"009 ({log_job_id}." in line: s9 = True file_size = log_handle.tell() return s1, s4, s7, s5, s9, file_size diff --git a/lib/galaxy/jobs/runners/util/pykube_util.py b/lib/galaxy/jobs/runners/util/pykube_util.py index 7b57c7f9e52..87abfe59cbe 100644 --- a/lib/galaxy/jobs/runners/util/pykube_util.py +++ b/lib/galaxy/jobs/runners/util/pykube_util.py @@ -83,7 +83,7 @@ def find_job_object_by_name(pykube_api, job_name, namespace=None): def find_pod_object_by_name(pykube_api, job_name, namespace=None): - return Pod.objects(pykube_api).filter(selector="job-name=" + job_name, namespace=namespace) + return Pod.objects(pykube_api).filter(selector=f"job-name={job_name}", namespace=namespace) def is_pod_unschedulable(pykube_api, pod, namespace=None): @@ -145,7 +145,7 @@ def job_object_dict(params, job_prefix, spec): "apiVersion": params.get('k8s_job_api_version', DEFAULT_JOB_API_VERSION), "kind": "Job", "metadata": { - "generateName": job_prefix + "-", + "generateName": f"{job_prefix}-", "namespace": params.get('k8s_namespace', DEFAULT_NAMESPACE), }, "spec": spec, diff --git a/lib/galaxy/jobs/splitters/multi.py b/lib/galaxy/jobs/splitters/multi.py index 3866ee90c2a..0fc3fe95a17 100644 --- a/lib/galaxy/jobs/splitters/multi.py +++ b/lib/galaxy/jobs/splitters/multi.py @@ -101,7 +101,7 @@ def do_split(job_wrapper): for file in names: os.symlink(file, os.path.join(dir, os.path.basename(file))) tasks = [] - prepare_files = os.path.join(util.galaxy_directory(), 'extract_dataset_parts.sh') + ' %s' + prepare_files = f"{os.path.join(util.galaxy_directory(), 'extract_dataset_parts.sh')} %s" for dir in task_dirs: task = model.Task(parent_job, dir, prepare_files % dir) tasks.append(task) @@ -167,7 +167,7 @@ def do_merge(job_wrapper, task_wrappers): msg = 'nothing to merge for %s (expected %i files)' \ % (output_file_name, len(task_dirs)) log.debug(msg) - stderr += msg + "\n" + stderr += f"{msg}\n" elif output in pickone_outputs: # just pick one of them if output not in pickone_done: @@ -189,7 +189,7 @@ def do_merge(job_wrapper, task_wrappers): out = tw.get_task().stdout.strip() err = tw.get_task().stderr.strip() if len(out) > 0: - stdout += "\n" + tw.working_directory + ':\n' + out + stdout += f"\n{tw.working_directory}:\n{out}" if len(err) > 0: - stderr += "\n" + tw.working_directory + ':\n' + err + stderr += f"\n{tw.working_directory}:\n{err}" return (stdout, stderr) diff --git a/lib/galaxy/managers/base.py b/lib/galaxy/managers/base.py index a5d4f3327b7..928dcc64b75 100644 --- a/lib/galaxy/managers/base.py +++ b/lib/galaxy/managers/base.py @@ -267,9 +267,9 @@ class ModelManager: try: return query.one() except sqlalchemy.orm.exc.NoResultFound: - raise exceptions.ObjectNotFound(self.model_class.__name__ + ' not found') + raise exceptions.ObjectNotFound(f"{self.model_class.__name__} not found") except sqlalchemy.orm.exc.MultipleResultsFound: - raise exceptions.InconsistentDatabase('found more than one ' + self.model_class.__name__) + raise exceptions.InconsistentDatabase(f"found more than one {self.model_class.__name__}") def _one_or_none(self, query): """ @@ -622,7 +622,7 @@ class ModelSerializer(HasAModelManager): return self.serializers[original_key] if original_key in self.serializable_keyset: return lambda i, k, **c: self.default_serializer(i, original_key, **c) - raise KeyError('serializer not found for remap: ' + original_key) + raise KeyError(f"serializer not found for remap: {original_key}") def default_serializer(self, item, key, **context): """ @@ -1053,7 +1053,7 @@ class ModelFilterParser(HasAModelManager): # correct op_string to usable function key fn_name = op_string if op_string in self.UNDERSCORED_OPS: - fn_name = '__' + op_string + '__' + fn_name = f"__{op_string}__" elif op_string == 'in': fn_name = 'in_' @@ -1084,7 +1084,7 @@ class ModelFilterParser(HasAModelManager): return True if bool_string in ('False', False): return False - raise ValueError('invalid boolean: ' + str(bool_string)) + raise ValueError(f"invalid boolean: {str(bool_string)}") def parse_id_list(self, id_list_string, sep=','): """ diff --git a/lib/galaxy/managers/citations.py b/lib/galaxy/managers/citations.py index a0a8dcd1818..174bdca10a3 100644 --- a/lib/galaxy/managers/citations.py +++ b/lib/galaxy/managers/citations.py @@ -46,7 +46,7 @@ class DoiCache: self._cache = CacheManager(**parse_cache_config_options(cache_opts)).get_cache('doi') def _raw_get_bibtex(self, doi): - doi_url = "https://doi.org/" + doi + doi_url = f"https://doi.org/{doi}" headers = {'Accept': 'application/x-bibtex'} req = requests.get(doi_url, headers=headers) req.encoding = req.apparent_encoding diff --git a/lib/galaxy/managers/containers.py b/lib/galaxy/managers/containers.py index e8ef05bdd57..3c105da8bd9 100644 --- a/lib/galaxy/managers/containers.py +++ b/lib/galaxy/managers/containers.py @@ -92,7 +92,7 @@ class LibraryFolderAsContainerManagerMixin(ContainerManagerMixin): return self.lda_manager elif isinstance(content, model.LibraryFolder): return self.folder_manager - raise TypeError('Unknown contents class: ' + str(content)) + raise TypeError(f"Unknown contents class: {str(content)}") class DatasetCollectionAsContainerManagerMixin(ContainerManagerMixin): @@ -111,4 +111,4 @@ class DatasetCollectionAsContainerManagerMixin(ContainerManagerMixin): return self.collection_manager elif isinstance(content, model.DatasetCollection): return self.collection_manager - raise TypeError('Unknown contents class: ' + str(content)) + raise TypeError(f"Unknown contents class: {str(content)}") diff --git a/lib/galaxy/managers/datasets.py b/lib/galaxy/managers/datasets.py index 8036962c52b..84f08e1f5af 100644 --- a/lib/galaxy/managers/datasets.py +++ b/lib/galaxy/managers/datasets.py @@ -489,7 +489,7 @@ class _UnflattenedMetadataDatasetAssociationSerializer(base.ModelSerializer, 'genome_build': lambda i, k, **c: i.dbkey, # derived (not mapped) attributes - 'data_type': lambda i, k, **c: i.datatype.__class__.__module__ + '.' + i.datatype.__class__.__name__, + 'data_type': lambda i, k, **c: f"{i.datatype.__class__.__module__}.{i.datatype.__class__.__name__}", 'converted': self.serialize_converted_datasets, # TODO: metadata/extra files @@ -636,7 +636,7 @@ class DatasetAssociationSerializer(_UnflattenedMetadataDatasetAssociationSeriali # prefix each key within and return prefixed = {} for key, val in metadata.items(): - prefixed_key = 'metadata_' + key + prefixed_key = f"metadata_{key}" prefixed[prefixed_key] = val return prefixed diff --git a/lib/galaxy/managers/executables.py b/lib/galaxy/managers/executables.py index d4250691c21..776f7299367 100644 --- a/lib/galaxy/managers/executables.py +++ b/lib/galaxy/managers/executables.py @@ -25,7 +25,7 @@ def artifact_class(trans, as_dict): else: for item in graph: found_id = item.get("id") - if found_id == object_id or found_id == "#" + object_id: + if found_id == object_id or found_id == f"#{object_id}": target_object = item if target_object and target_object.get("class"): diff --git a/lib/galaxy/managers/folders.py b/lib/galaxy/managers/folders.py index d3c0c305f23..96d071ccffe 100644 --- a/lib/galaxy/managers/folders.py +++ b/lib/galaxy/managers/folders.py @@ -135,9 +135,9 @@ class FolderManager: """ folder_dict = folder.to_dict(view='element') folder_dict = trans.security.encode_all_ids(folder_dict, True) - folder_dict['id'] = 'F' + folder_dict['id'] + folder_dict['id'] = f"F{folder_dict['id']}" if folder_dict['parent_id'] is not None: - folder_dict['parent_id'] = 'F' + folder_dict['parent_id'] + folder_dict['parent_id'] = f"F{folder_dict['parent_id']}" folder_dict['update_time'] = folder.update_time.strftime("%Y-%m-%d %I:%M %p") return folder_dict diff --git a/lib/galaxy/managers/lddas.py b/lib/galaxy/managers/lddas.py index 5f088b32078..c4dcdf6d3f4 100644 --- a/lib/galaxy/managers/lddas.py +++ b/lib/galaxy/managers/lddas.py @@ -45,7 +45,7 @@ class LDDAManager(DatasetAssociationManager): else: invalid_access_roles_ids.append(role_id) if len(invalid_access_roles_ids) > 0: - log.warning("The following roles could not be added to the dataset access permission: " + str(invalid_access_roles_ids)) + log.warning(f"The following roles could not be added to the dataset access permission: {str(invalid_access_roles_ids)}") access_permission = dict(access=valid_access_roles) trans.app.security_agent.set_dataset_permission(dataset, access_permission) @@ -61,7 +61,7 @@ class LDDAManager(DatasetAssociationManager): else: invalid_manage_roles_ids.append(role_id) if len(invalid_manage_roles_ids) > 0: - log.warning("The following roles could not be added to the dataset manage permission: " + str(invalid_manage_roles_ids)) + log.warning(f"The following roles could not be added to the dataset manage permission: {str(invalid_manage_roles_ids)}") manage_permission = {trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS: valid_manage_roles} trans.app.security_agent.set_dataset_permission(dataset, manage_permission) @@ -76,6 +76,6 @@ class LDDAManager(DatasetAssociationManager): else: invalid_modify_roles_ids.append(role_id) if len(invalid_modify_roles_ids) > 0: - log.warning("The following roles could not be added to the dataset modify permission: " + str(invalid_modify_roles_ids)) + log.warning(f"The following roles could not be added to the dataset modify permission: {str(invalid_modify_roles_ids)}") modify_permission = {trans.app.security_agent.permitted_actions.LIBRARY_MODIFY: valid_modify_roles} trans.app.security_agent.set_library_item_permission(library_dataset, modify_permission) diff --git a/lib/galaxy/managers/libraries.py b/lib/galaxy/managers/libraries.py index 49bbd341d18..639cac2f518 100644 --- a/lib/galaxy/managers/libraries.py +++ b/lib/galaxy/managers/libraries.py @@ -56,7 +56,7 @@ class LibraryManager: except NoResultFound: raise exceptions.RequestParameterInvalidException('No library found with the id provided.') except Exception as e: - raise exceptions.InternalServerError('Error loading from the database.' + unicodify(e)) + raise exceptions.InternalServerError(f"Error loading from the database.{unicodify(e)}") library = self.secure(trans, library, check_accessible) return library @@ -558,7 +558,7 @@ class LibrariesManager: else: invalid_access_roles_names.append(role_id) if len(invalid_access_roles_names) > 0: - log.warning("The following roles could not be added to the library access permission: " + str(invalid_access_roles_names)) + log.warning(f"The following roles could not be added to the library access permission: {str(invalid_access_roles_names)}") # ADD TO LIBRARY ROLES valid_add_roles = [] @@ -571,7 +571,7 @@ class LibrariesManager: else: invalid_add_roles_names.append(role_id) if len(invalid_add_roles_names) > 0: - log.warning("The following roles could not be added to the add library item permission: " + str(invalid_add_roles_names)) + log.warning(f"The following roles could not be added to the add library item permission: {str(invalid_add_roles_names)}") # MANAGE LIBRARY ROLES valid_manage_roles = [] @@ -584,7 +584,7 @@ class LibrariesManager: else: invalid_manage_roles_names.append(role_id) if len(invalid_manage_roles_names) > 0: - log.warning("The following roles could not be added to the manage library permission: " + str(invalid_manage_roles_names)) + log.warning(f"The following roles could not be added to the manage library permission: {str(invalid_manage_roles_names)}") # MODIFY LIBRARY ROLES valid_modify_roles = [] @@ -597,7 +597,7 @@ class LibrariesManager: else: invalid_modify_roles_names.append(role_id) if len(invalid_modify_roles_names) > 0: - log.warning("The following roles could not be added to the modify library permission: " + str(invalid_modify_roles_names)) + log.warning(f"The following roles could not be added to the modify library permission: {str(invalid_modify_roles_names)}") permissions = {trans.app.security_agent.permitted_actions.LIBRARY_ACCESS: valid_access_roles} permissions.update({trans.app.security_agent.permitted_actions.LIBRARY_ADD: valid_add_roles}) @@ -623,7 +623,7 @@ class LibrariesManager: params = util.Params(payload) permissions = {} for k, v in trans.app.model.Library.permitted_actions.items(): - role_params = params.get(k + '_in', []) + role_params = params.get(f"{k}_in", []) in_roles = [trans.sa_session.query(trans.app.model.Role).get(trans.security.decode_id(x)) for x in util.listify(role_params)] permissions[trans.app.security_agent.get_action(v.action)] = in_roles trans.app.security_agent.set_all_library_permissions(trans, library, permissions) diff --git a/lib/galaxy/managers/library_datasets.py b/lib/galaxy/managers/library_datasets.py index 8c761458987..7bb2f55ecf2 100644 --- a/lib/galaxy/managers/library_datasets.py +++ b/lib/galaxy/managers/library_datasets.py @@ -43,7 +43,7 @@ class LibraryDatasetsManager(datasets.DatasetAssociationManager): try: ld = trans.sa_session.query(trans.app.model.LibraryDataset).filter(trans.app.model.LibraryDataset.table.c.id == decoded_library_dataset_id).one() except Exception as e: - raise InternalServerError('Error loading from the database.' + util.unicodify(e)) + raise InternalServerError(f"Error loading from the database.{util.unicodify(e)}") ld = self.secure(trans, ld, check_accessible) return ld @@ -232,7 +232,7 @@ class LibraryDatasetsManager(datasets.DatasetAssociationManager): if ldda.dataset.uuid: rval['uuid'] = str(ldda.dataset.uuid) rval['deleted'] = ld.deleted - rval['folder_id'] = 'F' + rval['folder_id'] + rval['folder_id'] = f"F{rval['folder_id']}" rval['full_path'] = full_path rval['file_size'] = util.nice_size(int(ldda.get_size())) rval['date_uploaded'] = ldda.create_time.strftime("%Y-%m-%d %I:%M %p") @@ -259,10 +259,10 @@ class LibraryDatasetsManager(datasets.DatasetAssociationManager): path_to_root = [] if folder.parent_id is None: # We are almost in root - path_to_root.append(('F' + trans.security.encode_id(folder.id), folder.name)) + path_to_root.append((f"F{trans.security.encode_id(folder.id)}", folder.name)) else: # We add the current folder and traverse up one folder. - path_to_root.append(('F' + trans.security.encode_id(folder.id), folder.name)) + path_to_root.append((f"F{trans.security.encode_id(folder.id)}", folder.name)) upper_folder = trans.sa_session.query(trans.app.model.LibraryFolder).get(folder.parent_id) path_to_root.extend(self._build_path(trans, upper_folder)) return path_to_root diff --git a/lib/galaxy/managers/markdown_parse.py b/lib/galaxy/managers/markdown_parse.py index 3c4effd7f9a..f4f658c878c 100644 --- a/lib/galaxy/managers/markdown_parse.py +++ b/lib/galaxy/managers/markdown_parse.py @@ -47,7 +47,7 @@ FUNCTION_ARG = r'\s*[\w\|]+\s*=\s*(?:%s)\s*' % ARG_VAL_REGEX # embed commas between arguments FUNCTION_MULTIPLE_ARGS = fr'(?P{FUNCTION_ARG})(?P(?:,{FUNCTION_ARG})*)' FUNCTION_MULTIPLE_ARGS_PATTERN = re.compile(FUNCTION_MULTIPLE_ARGS) -FUNCTION_CALL_LINE_TEMPLATE = r'\s*%s\s*\((?:' + FUNCTION_MULTIPLE_ARGS + r')?\)\s*' +FUNCTION_CALL_LINE_TEMPLATE = f"\\s*%s\\s*\\((?:{FUNCTION_MULTIPLE_ARGS})?\\)\\s*" GALAXY_MARKDOWN_FUNCTION_CALL_LINE = re.compile(FUNCTION_CALL_LINE_TEMPLATE % GALAXY_FLAVORED_MARKDOWN_CONTAINER_REGEX) WHITE_SPACE_ONLY_PATTERN = re.compile(r"^[\s]+$") diff --git a/lib/galaxy/managers/markdown_util.py b/lib/galaxy/managers/markdown_util.py index 53b0f5a1d0a..bf198d1a815 100644 --- a/lib/galaxy/managers/markdown_util.py +++ b/lib/galaxy/managers/markdown_util.py @@ -452,7 +452,7 @@ class ToBasicMarkdownDirectiveHandler(GalaxyInternalMarkdownDirectiveHandler): def walk_elements(collection, element_prefix=""): if ":" in collection.collection_type: for element in collection.elements: - walk_elements(element.child_collection, element_prefix + element.element_identifier + ":") + walk_elements(element.child_collection, f"{element_prefix + element.element_identifier}:") else: for element in collection.elements: markdown_wrapper[0] += f"**Element:** {element_prefix}{element.element_identifier}\n\n" @@ -495,7 +495,7 @@ class ToBasicMarkdownDirectiveHandler(GalaxyInternalMarkdownDirectiveHandler): markdown += "| " depth = parameter["depth"] if depth > 1: - markdown += ">" * (parameter["depth"] - 1) + " " + markdown += f"{'>' * (parameter['depth'] - 1)} " markdown += parameter["text"] markdown += " | " value = parameter["value"] @@ -767,7 +767,7 @@ def _remap_galaxy_markdown_calls(func, markdown): if matching_line: match = GALAXY_MARKDOWN_FUNCTION_CALL_LINE.match(line) - return func(match.group(1), matching_line + "\n") + return func(match.group(1), f"{matching_line}\n") else: return (container, True) diff --git a/lib/galaxy/managers/pages.py b/lib/galaxy/managers/pages.py index 292a7b351ad..7fb35b5f01e 100644 --- a/lib/galaxy/managers/pages.py +++ b/lib/galaxy/managers/pages.py @@ -485,9 +485,9 @@ class PageContentProcessor(HTMLParser): def _shorttag_replace(self, match): tag = match.group(1) if tag in self.elements_no_end_tag: - return '<' + tag + ' />' + return f"<{tag} />" else: - return '<' + tag + '>' + return f"<{tag}>" def feed(self, data): data = re.compile(r' 0: - llog_name += ':' + job_name + llog_name += f":{job_name}" llog = logging.getLogger(llog_name) # Print the command we're about to execute, ``set -x`` style. - llog.debug('+ ' + str(command)) + llog.debug(f"+ {str(command)}") # Launch the command as subprocess. A bufsize of 1 means line buffered. process_handle = subprocess.Popen(str(command), stdout=subprocess.PIPE, diff --git a/lib/galaxy/tool_util/cwl/parser.py b/lib/galaxy/tool_util/cwl/parser.py index 9339a83a2d7..1d3db7da6a5 100644 --- a/lib/galaxy/tool_util/cwl/parser.py +++ b/lib/galaxy/tool_util/cwl/parser.py @@ -148,7 +148,7 @@ def _to_cwl_tool_object(tool_path=None, tool_object=None, cwl_tool_object=None, path = tool_directory if path is None: path = os.getcwd() - uri = ref_resolver.file_uri(path) + "/" + uri = f"{ref_resolver.file_uri(path)}/" sourceline.add_lc_filename(tool_object, uri) raw_process_reference = schema_loader.raw_process_reference_for_object( tool_object, diff --git a/lib/galaxy/tool_util/cwl/schema.py b/lib/galaxy/tool_util/cwl/schema.py index 2059d016fe7..6de0dc4aac7 100644 --- a/lib/galaxy/tool_util/cwl/schema.py +++ b/lib/galaxy/tool_util/cwl/schema.py @@ -51,7 +51,7 @@ class SchemaLoader: """) processed_path = os.path.join(output_dir, os.path.basename(path)) path = os.path.abspath(path) - uri = "file://" + path + uri = f"file://{path}" loading_context = loading_context or self.loading_context() if REWRITE_EXPRESSIONS: from cwl_utils import cwl_v1_0_expression_refactor diff --git a/lib/galaxy/tool_util/deps/brew_exts.py b/lib/galaxy/tool_util/deps/brew_exts.py index 1f0c68afb6f..82a275c7cdc 100755 --- a/lib/galaxy/tool_util/deps/brew_exts.py +++ b/lib/galaxy/tool_util/deps/brew_exts.py @@ -513,7 +513,7 @@ def __action(sys): def recipe_cellar_path(cellar_path, recipe, version): recipe_base = recipe.split("/")[-1] recipe_base_path = os.path.join(cellar_path, recipe_base, version) - revision_paths = glob.glob(recipe_base_path + "_*") + revision_paths = glob.glob(f"{recipe_base_path}_*") if revision_paths: revisions = map(lambda x: int(x.rsplit("_", 1)[-1]), revision_paths) max_revision = max(revisions) @@ -547,8 +547,8 @@ def ensure_brew_on_path(args): def which(file): # http://stackoverflow.com/questions/5226958/which-equivalent-function-in-python for path in os.environ["PATH"].split(":"): - if os.path.exists(path + "/" + file): - return path + "/" + file + if os.path.exists(f"{path}/{file}"): + return f"{path}/{file}" return None diff --git a/lib/galaxy/tool_util/deps/container_resolvers/mulled.py b/lib/galaxy/tool_util/deps/container_resolvers/mulled.py index a6d698b4702..e2136dfb081 100644 --- a/lib/galaxy/tool_util/deps/container_resolvers/mulled.py +++ b/lib/galaxy/tool_util/deps/container_resolvers/mulled.py @@ -114,7 +114,7 @@ def identifier_to_cached_target(identifier, hash_func, namespace=None): prefix = "" if namespace is not None: prefix = f"quay.io/{namespace}/" - if image_name.startswith(prefix + "mulled-v1-"): + if image_name.startswith(f"{prefix}mulled-v1-"): if hash_func == "v2": return None @@ -123,7 +123,7 @@ def identifier_to_cached_target(identifier, hash_func, namespace=None): if version and version.isdigit(): build = version image = CachedV1MulledImageMultiTarget(hash, build, identifier) - elif image_name.startswith(prefix + "mulled-v2-"): + elif image_name.startswith(f"{prefix}mulled-v2-"): if hash_func == "v1": return None diff --git a/lib/galaxy/tool_util/deps/containers.py b/lib/galaxy/tool_util/deps/containers.py index 7c5d1032177..af49c501556 100644 --- a/lib/galaxy/tool_util/deps/containers.py +++ b/lib/galaxy/tool_util/deps/containers.py @@ -140,13 +140,13 @@ class ContainerFinder: repo_key = f"{container_type}_repo_{mode}" owner_key = f"{container_type}_owner_{mode}" if repo_key in destination_info: - repo = destination_info[repo_key] + "/" + repo = f"{destination_info[repo_key]}/" if owner_key in destination_info: - owner = destination_info[owner_key] + "/" + owner = f"{destination_info[owner_key]}/" cont_id = repo + owner + destination_info[f"{container_type}_image_{mode}"] tag_key = f"{container_type}_tag_{mode}" if tag_key in destination_info: - cont_id += ":" + destination_info[tag_key] + cont_id += f":{destination_info[tag_key]}" return cont_id def __default_container_id(self, container_type, destination_info): diff --git a/lib/galaxy/tool_util/deps/mulled/mulled_build.py b/lib/galaxy/tool_util/deps/mulled/mulled_build.py index 9ebedecb172..5fa69a497e1 100644 --- a/lib/galaxy/tool_util/deps/mulled/mulled_build.py +++ b/lib/galaxy/tool_util/deps/mulled/mulled_build.py @@ -269,7 +269,7 @@ def mull_targets( involucro_args.insert(6, '-set') involucro_args.insert(7, f"TEST_BINDS={','.join(test_bind)}") cmd = involucro_context.build_command(involucro_args) - print('Executing: ' + ' '.join(shlex.quote(_) for _ in cmd)) + print(f"Executing: {' '.join(shlex.quote(_) for _ in cmd)}") if dry_run: return 0 ensure_installed(involucro_context, True) diff --git a/lib/galaxy/tool_util/deps/mulled/mulled_build_files.py b/lib/galaxy/tool_util/deps/mulled/mulled_build_files.py index f21afeea3a9..8f436503f3a 100644 --- a/lib/galaxy/tool_util/deps/mulled/mulled_build_files.py +++ b/lib/galaxy/tool_util/deps/mulled/mulled_build_files.py @@ -57,7 +57,7 @@ def generate_targets(target_source): """Generate all targets from TSV files in specified file or directory.""" target_source = os.path.abspath(target_source) if os.path.isdir(target_source): - target_source_files = glob.glob(target_source + "/*.tsv") + target_source_files = glob.glob(f"{target_source}/*.tsv") else: target_source_files = [target_source] diff --git a/lib/galaxy/tool_util/deps/mulled/mulled_search.py b/lib/galaxy/tool_util/deps/mulled/mulled_search.py index b72d8f11ffe..249d09c9141 100755 --- a/lib/galaxy/tool_util/deps/mulled/mulled_search.py +++ b/lib/galaxy/tool_util/deps/mulled/mulled_search.py @@ -119,7 +119,7 @@ class CondaSearch(): """ if run_command is None: - raise Exception("Invalid search destination. " + deps_error_message("conda")) + raise Exception(f"Invalid search destination. {deps_error_message('conda')}") raw_out, err, exit_code = run_command( 'search', '-c', self.channel, diff --git a/lib/galaxy/tool_util/deps/mulled/mulled_update_singularity_containers.py b/lib/galaxy/tool_util/deps/mulled/mulled_update_singularity_containers.py index cc52d529e27..35ac039a60c 100644 --- a/lib/galaxy/tool_util/deps/mulled/mulled_update_singularity_containers.py +++ b/lib/galaxy/tool_util/deps/mulled/mulled_update_singularity_containers.py @@ -22,7 +22,7 @@ def docker_to_singularity(container, installation, filepath, no_sudo=False): """ Convert docker to singularity container. """ - cmd = [installation, 'build', '/'.join((filepath, container)), 'docker://quay.io/biocontainers/' + container] + cmd = [installation, 'build', '/'.join((filepath, container)), f"docker://quay.io/biocontainers/{container}"] try: if no_sudo: check_output(cmd, stderr=subprocess.STDOUT) @@ -68,7 +68,7 @@ def singularity_container_test(tests, installation, filepath): if test.get('imports', False): for imp in test['imports']: try: - check_output(exec_command.extend([test['import_lang'], 'import ' + imp]), stderr=subprocess.STDOUT) + check_output(exec_command.extend([test['import_lang'], f"import {imp}"]), stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: errors.append({'import': imp, 'output': unicodify(e.output)}) test_passed = False @@ -168,7 +168,7 @@ def container_testing(args=None): f.write(f"\n\t\t{container['container']}") for error in container['errors']: f.write('\n\t\t\tCOMMAND: {}\n\t\t\t\tERROR:{}'.format(error.get( - 'command', 'import' + error.get('import', 'nothing found')), error['output'])) + 'command', f"import{error.get('import', 'nothing found')}"), error['output'])) f.write('\n\tNO TEST AVAILABLE:') for container in test_results['notest']: f.write(f'\n\t\t{container}') diff --git a/lib/galaxy/tool_util/deps/resolvers/unlinked_tool_shed_packages.py b/lib/galaxy/tool_util/deps/resolvers/unlinked_tool_shed_packages.py index eafa3b685ad..9c3ac107003 100644 --- a/lib/galaxy/tool_util/deps/resolvers/unlinked_tool_shed_packages.py +++ b/lib/galaxy/tool_util/deps/resolvers/unlinked_tool_shed_packages.py @@ -37,7 +37,7 @@ from .galaxy_packages import BaseGalaxyPackageDependencyResolver log = logging.getLogger(__name__) MANUAL = "manual" -PREFERRED_OWNERS = MANUAL + ",iuc,devteam" +PREFERRED_OWNERS = f"{MANUAL},iuc,devteam" class UnlinkedToolShedPackageDependencyResolver(BaseGalaxyPackageDependencyResolver): @@ -84,7 +84,7 @@ class UnlinkedToolShedPackageDependencyResolver(BaseGalaxyPackageDependencyResol for owner in listdir(path): owner_path = join(path, owner) for package_name in listdir(owner_path): - if package_name.lower().startswith("package_" + name.lower()): + if package_name.lower().startswith(f"package_{name.lower()}"): package_path = join(owner_path, package_name) for revision in listdir(package_path): revision_path = join(package_path, revision) diff --git a/lib/galaxy/tool_util/loader_directory.py b/lib/galaxy/tool_util/loader_directory.py index 056ec577447..93cca0916a6 100644 --- a/lib/galaxy/tool_util/loader_directory.py +++ b/lib/galaxy/tool_util/loader_directory.py @@ -258,12 +258,12 @@ def _find_tool_files(path_or_uri_like, recursive, enable_beta_formats): else: if enable_beta_formats: if not recursive: - files = glob.glob(path + "/*") + files = glob.glob(f"{path}/*") else: files = _find_files(path, "*") else: if not recursive: - files = glob.glob(path + "/*.xml") + files = glob.glob(f"{path}/*.xml") else: files = _find_files(path, "*.xml") return [os.path.abspath(_) for _ in files] diff --git a/lib/galaxy/tool_util/locations/dockstore.py b/lib/galaxy/tool_util/locations/dockstore.py index 4076a71aab6..00a6aed23d2 100644 --- a/lib/galaxy/tool_util/locations/dockstore.py +++ b/lib/galaxy/tool_util/locations/dockstore.py @@ -19,7 +19,7 @@ class DockStoreResolver(ToolLocationResolver): tool_id, version = tool_id.split(":", 1) else: tool_id, version = tool_id, "latest" - tmp_path = self._temp_path(uri_like + ".cwl") + tmp_path = self._temp_path(f"{uri_like}.cwl") cwl_str = _Ga4ghToolClient().get_tool_cwl(tool_id, version=version, as_string=True) with open(tmp_path, "wb") as f: f.write(cwl_str) diff --git a/lib/galaxy/tool_util/output_checker.py b/lib/galaxy/tool_util/output_checker.py index 697c075f1a2..89e1b0bef29 100644 --- a/lib/galaxy/tool_util/output_checker.py +++ b/lib/galaxy/tool_util/output_checker.py @@ -162,11 +162,11 @@ def __regex_err_msg(match, stream, regex): that will contain the string matched on. """ # Get the description for the error level: - desc = StdioErrorLevel.desc(regex.error_level) + ": " + desc = f"{StdioErrorLevel.desc(regex.error_level)}: " mstart = match.start() mend = match.end() if mend - mstart > 256: - match_str = match.string[mstart:mstart + 256] + "..." + match_str = f"{match.string[mstart:mstart + 256]}..." else: match_str = match.string[mstart:mend] diff --git a/lib/galaxy/tool_util/verify/asserts/__init__.py b/lib/galaxy/tool_util/verify/asserts/__init__.py index 2dd433e324b..5eaff1f7d00 100644 --- a/lib/galaxy/tool_util/verify/asserts/__init__.py +++ b/lib/galaxy/tool_util/verify/asserts/__init__.py @@ -14,7 +14,7 @@ assertion_module_names = ['text', 'tabular', 'xml', 'hdf5', 'archive', 'size'] # to the list of assertion module names defined above. assertion_modules = [] for assertion_module_name in assertion_module_names: - full_assertion_module_name = 'galaxy.tool_util.verify.asserts.' + assertion_module_name + full_assertion_module_name = f"galaxy.tool_util.verify.asserts.{assertion_module_name}" try: # Dynamically import module __import__(full_assertion_module_name) @@ -33,7 +33,7 @@ def verify_assertions(data, assertion_description_list): def verify_assertion(data, assertion_description): tag = assertion_description["tag"] - assert_function_name = "assert_" + tag + assert_function_name = f"assert_{tag}" assert_function = None for assertion_module in assertion_modules: if hasattr(assertion_module, assert_function_name): diff --git a/lib/galaxy/tool_util/verify/interactor.py b/lib/galaxy/tool_util/verify/interactor.py index e4965b0bc67..f3c4f727834 100644 --- a/lib/galaxy/tool_util/verify/interactor.py +++ b/lib/galaxy/tool_util/verify/interactor.py @@ -369,7 +369,7 @@ class GalaxyInteractorApi: if force_path_paste: file_path = self.test_data_path(tool_id, file_name) tool_input.update({ - "files_%d|url_paste" % i: "file://" + file_path + "files_%d|url_paste" % i: f"file://{file_path}" }) else: file_content = self.test_data_download(tool_id, file_name, is_output=False) @@ -388,7 +388,7 @@ class GalaxyInteractorApi: if force_path_paste: file_name = self.test_data_path(tool_id, fname) tool_input.update({ - "files_0|url_paste": "file://" + file_name + "files_0|url_paste": f"file://{file_name}" }) else: file_content = self.test_data_download(tool_id, fname, is_output=False) @@ -1175,11 +1175,11 @@ def _verify_outputs(testdef, history, jobs, tool_id, data_list, data_collection_ for job_message in job_messages: message_type = job_message.get("type") if message_type == "regex" and job_message.get("stream") == "stderr": - stderr_prefix += (job_message.get("desc") or '') + "\n" + stderr_prefix += f"{job_message.get('desc') or ''}\n" elif message_type == "regex" and job_message.get("stream") == "stdout": - stdout_prefix += (job_message.get("desc") or '') + "\n" + stdout_prefix += f"{job_message.get('desc') or ''}\n" elif message_type == "exit_code": - stderr_prefix += (job_message.get("desc") or '') + "\n" + stderr_prefix += f"{job_message.get('desc') or ''}\n" else: raise Exception(f"Unknown job message type [{message_type}] in [{job_message}]") @@ -1226,7 +1226,7 @@ def _format_stream(output, stream, format): output = output or '' if format: msg = f"---------------------- >> begin tool {stream} << -----------------------\n" - msg += output + "\n" + msg += f"{output}\n" msg += f"----------------------- >> end tool {stream} << ------------------------\n" else: msg = output diff --git a/lib/galaxy/tool_util/verify/script.py b/lib/galaxy/tool_util/verify/script.py index 6d4102768f2..49551db2864 100644 --- a/lib/galaxy/tool_util/verify/script.py +++ b/lib/galaxy/tool_util/verify/script.py @@ -232,14 +232,14 @@ def _test_id_for_reference(test_reference): tool_version = test_reference.tool_version test_index = test_reference.test_index - if tool_version and tool_id.endswith("/" + tool_version): - tool_id = tool_id[:-len("/" + tool_version)] + if tool_version and tool_id.endswith(f"/{tool_version}"): + tool_id = tool_id[:-len(f"/{tool_version}")] label_base = tool_id if tool_version: - label_base += "/" + str(tool_version) + label_base += f"/{str(tool_version)}" - test_id = label_base + "-" + str(test_index) + test_id = f"{label_base}-{str(test_index)}" return test_id @@ -258,8 +258,8 @@ def _test_tool( test_index = test_reference.test_index # If given a tool_id with a version suffix, strip it off so we can treat tool_version # correctly at least in client_test_config. - if tool_version and tool_id.endswith("/" + tool_version): - tool_id = tool_id[:-len("/" + tool_version)] + if tool_version and tool_id.endswith(f"/{tool_version}"): + tool_id = tool_id[:-len(f"/{tool_version}")] test_id = _test_id_for_reference(test_reference) diff --git a/lib/galaxy/tools/__init__.py b/lib/galaxy/tools/__init__.py index 6d753030472..782084339a5 100644 --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -876,7 +876,7 @@ class Tool(Dictifiable): executable = self.version_string_cmd.split()[0] abs_executable = os.path.abspath(os.path.join(self.tool_dir, executable)) command_line = self.version_string_cmd.replace(executable, abs_executable, 1) - self.version_string_cmd = version_cmd_interpreter + " " + command_line + self.version_string_cmd = f"{version_cmd_interpreter} {command_line}" # Parallelism for tasks, read from tool config. self.parallelism = tool_source.parse_parallelism() @@ -1149,7 +1149,7 @@ class Tool(Dictifiable): raise Exception('URL parameters in a non-default tool action can not be used ' 'in conjunction with nginx upload. Please convert them to ' 'hidden POST parameters') - self.action = (self.app.config.nginx_upload_path + '?nginx_redir=', + self.action = (f"{self.app.config.nginx_upload_path}?nginx_redir=", unquote_plus(self.action)) self.target = input_elem.get("target", self.target) self.method = input_elem.get("method", self.method) @@ -2032,7 +2032,7 @@ class Tool(Dictifiable): for data_table_filename in data_table.filenames: # FIXME: from_shed_config seems to always be False. if not data_table.filenames[data_table_filename]['from_shed_config']: - tar_file = data_table.filenames[data_table_filename]['filename'] + '.sample' + tar_file = f"{data_table.filenames[data_table_filename]['filename']}.sample" sample_file = os.path.join(data_table.filenames[data_table_filename]['tool_data_path'], tar_file) # Use the .sample file, if one exists. If not, skip this data table. @@ -2550,10 +2550,10 @@ class DataSourceTool(OutputParameterJSONTool): wrapped_data = param_dict.get(out_name) # allow multiple files to be created cur_base_param_name = f'GALAXY|{out_name}|' - cur_name = param_dict.get(cur_base_param_name + 'name', name) - cur_dbkey = param_dict.get(cur_base_param_name + 'dkey', dbkey) - cur_info = param_dict.get(cur_base_param_name + 'info', info) - cur_data_type = param_dict.get(cur_base_param_name + 'data_type', data_type) + cur_name = param_dict.get(f"{cur_base_param_name}name", name) + cur_dbkey = param_dict.get(f"{cur_base_param_name}dkey", dbkey) + cur_info = param_dict.get(f"{cur_base_param_name}info", info) + cur_data_type = param_dict.get(f"{cur_base_param_name}data_type", data_type) if cur_name: data.name = cur_name if not data.info and cur_info: diff --git a/lib/galaxy/tools/actions/__init__.py b/lib/galaxy/tools/actions/__init__.py index 018565e36aa..1ce4dcafe56 100644 --- a/lib/galaxy/tools/actions/__init__.py +++ b/lib/galaxy/tools/actions/__init__.py @@ -801,7 +801,7 @@ class DefaultToolAction: def _get_default_data_name(self, dataset, tool, on_text=None, trans=None, incoming=None, history=None, params=None, job_params=None, **kwd): name = tool.name if on_text: - name += (" on " + on_text) + name += f" on {on_text}" return name diff --git a/lib/galaxy/tools/data/__init__.py b/lib/galaxy/tools/data/__init__.py index 612df1bd591..f5e42b70001 100644 --- a/lib/galaxy/tools/data/__init__.py +++ b/lib/galaxy/tools/data/__init__.py @@ -764,10 +764,10 @@ class TabularToolDataField(Dictifiable): return path def clean_base_dir(self, path): - return re.sub("^" + self.get_base_dir() + r"/*", "", path) + return re.sub(f"^{self.get_base_dir()}/*", "", path) def get_files(self): - return glob(self.get_base_path() + "*") + return glob(f"{self.get_base_path()}*") def get_filesize_map(self, rm_base_dir=False): out = {} diff --git a/lib/galaxy/tools/data_fetch.py b/lib/galaxy/tools/data_fetch.py index 9c800d4aa6e..c0fa8227fe9 100644 --- a/lib/galaxy/tools/data_fetch.py +++ b/lib/galaxy/tools/data_fetch.py @@ -142,7 +142,7 @@ def _fetch_target(upload_config, target): name = item.get("name") or 'Composite Dataset' dataset_bunch.name = name primary_file = sniff.stream_to_file(StringIO(datatype.generate_primary_file(dataset_bunch)), prefix='upload_auto_primary_file', dir=".") - extra_files_path = primary_file + "_extra" + extra_files_path = f"{primary_file}_extra" os.mkdir(extra_files_path) rval = { "name": name, @@ -172,7 +172,7 @@ def _fetch_target(upload_config, target): key, writable_file.is_binary, ".", - os.path.basename(extra_files_path) + "_", + f"{os.path.basename(extra_files_path)}_", composite_item, ) composite_item_idx += 1 @@ -262,7 +262,7 @@ def _fetch_target(upload_config, target): if extra_files: # TODO: optimize to just copy the whole directory to extra files instead. assert not upload_config.link_data_only, "linking composite dataset files not yet implemented" - extra_files_path = path + "_extra" + extra_files_path = f"{path}_extra" staged_extra_files = extra_files_path os.mkdir(extra_files_path) diff --git a/lib/galaxy/tools/error_reports/plugins/base_git.py b/lib/galaxy/tools/error_reports/plugins/base_git.py index 0a9b63994fb..361398f6ea4 100644 --- a/lib/galaxy/tools/error_reports/plugins/base_git.py +++ b/lib/galaxy/tools/error_reports/plugins/base_git.py @@ -56,7 +56,7 @@ class BaseGitPlugin(ErrorPlugin, metaclass=ABCMeta): return None try: if job.tool_id not in self.ts_repo_cache: - ts_repo_request_data = requests.get(ts_url + "/api/repositories?tool_ids=" + str(job.tool_id)).json() + ts_repo_request_data = requests.get(f"{ts_url}/api/repositories?tool_ids={str(job.tool_id)}").json() for repoinfo in ts_repo_request_data.values(): if isinstance(repoinfo, dict): diff --git a/lib/galaxy/tools/errors.py b/lib/galaxy/tools/errors.py index fadb9a9bebe..2c2d4c11269 100644 --- a/lib/galaxy/tools/errors.py +++ b/lib/galaxy/tools/errors.py @@ -244,7 +244,7 @@ class EmailErrorReporter(ErrorReporter): frm = self.app.config.email_from error_msg = validate_email_str(email) if not error_msg and self._can_access_dataset(user): - to += ', ' + email.strip() + to += f", {email.strip()}" subject = f"Galaxy tool error report from {email}" try: subject = "{} ({})".format( diff --git a/lib/galaxy/tools/expressions/evaluation.py b/lib/galaxy/tools/expressions/evaluation.py index c14332d9d3c..204e771ca60 100644 --- a/lib/galaxy/tools/expressions/evaluation.py +++ b/lib/galaxy/tools/expressions/evaluation.py @@ -27,7 +27,7 @@ def evaluate(config, input): close_fds=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE) - input_str = json.dumps(new_input) + "\n\n" + input_str = f"{json.dumps(new_input)}\n\n" input_bytes = input_str.encode("utf-8") (stdoutdata, stderrdata) = sp.communicate(input_bytes) if sp.returncode != 0: diff --git a/lib/galaxy/tools/parameters/__init__.py b/lib/galaxy/tools/parameters/__init__.py index f18c554d4a6..03fd992ad40 100644 --- a/lib/galaxy/tools/parameters/__init__.py +++ b/lib/galaxy/tools/parameters/__init__.py @@ -162,7 +162,7 @@ def visit_input_values(inputs, input_values, callback, name_prefix='', label_pre visit_input_values(input.inputs, d, callback, new_name_prefix, new_label_prefix, parent_prefix=new_name_prefix, **payload) elif isinstance(input, Conditional): values = input_values[input.name] = input_values.get(input.name, {}) - new_name_prefix = name_prefix + input.name + '|' + new_name_prefix = f"{name_prefix + input.name}|" case_error = None if get_current_case(input, values) >= 0 else 'The selected case is unavailable/invalid.' callback_helper(input.test_param, values, new_name_prefix, label_prefix, parent_prefix=name_prefix, context=context, error=case_error) values['__current_case__'] = get_current_case(input, values) @@ -170,7 +170,7 @@ def visit_input_values(inputs, input_values, callback, name_prefix='', label_pre visit_input_values(input.cases[values['__current_case__']].inputs, values, callback, new_name_prefix, label_prefix, parent_prefix=name_prefix, **payload) elif isinstance(input, Section): values = input_values[input.name] = input_values.get(input.name, {}) - new_name_prefix = name_prefix + input.name + '|' + new_name_prefix = f"{name_prefix + input.name}|" visit_input_values(input.inputs, values, callback, new_name_prefix, label_prefix, parent_prefix=name_prefix, **payload) else: callback_helper(input, input_values, name_prefix, label_prefix, parent_prefix=parent_prefix, context=context) @@ -260,12 +260,12 @@ def params_to_incoming(incoming, inputs, input_values, app, name_prefix=""): elif isinstance(input, Conditional): values = input_values[input.name] current = values['__current_case__'] - new_name_prefix = name_prefix + input.name + '|' + new_name_prefix = f"{name_prefix + input.name}|" incoming[new_name_prefix + input.test_param.name] = values[input.test_param.name] params_to_incoming(incoming, input.cases[current].inputs, values, app, new_name_prefix) elif isinstance(input, Section): values = input_values[input.name] - new_name_prefix = name_prefix + input.name + '|' + new_name_prefix = f"{name_prefix + input.name}|" params_to_incoming(incoming, input.inputs, values, app, new_name_prefix) else: value = input_values.get(input.name) @@ -419,7 +419,7 @@ def _populate_state_legacy(request_context, inputs, incoming, state, errors, pre if rep_index < input.max: new_state = {'__index__': rep_index} group_state.append(new_state) - _populate_state_legacy(request_context, input.inputs, incoming, new_state, errors, prefix=rep_prefix + '|', context=context, check=check, simple_errors=simple_errors) + _populate_state_legacy(request_context, input.inputs, incoming, new_state, errors, prefix=f"{rep_prefix}|", context=context, check=check, simple_errors=simple_errors) rep_index += 1 elif input.type == 'conditional': if input.value_ref and not input.value_ref_in_group: @@ -467,11 +467,11 @@ def _get_incoming_value(incoming, key, default): Fetch value from incoming dict directly or check special nginx upload created variants of this key. """ - if '__' + key + '__is_composite' in incoming: - composite_keys = incoming['__' + key + '__keys'].split() + if f"__{key}__is_composite" in incoming: + composite_keys = incoming[f"__{key}__keys"].split() value = dict() for composite_key in composite_keys: - value[composite_key] = incoming[key + '_' + composite_key] + value[composite_key] = incoming[f"{key}_{composite_key}"] return value else: return incoming.get(key, default) diff --git a/lib/galaxy/tools/parameters/basic.py b/lib/galaxy/tools/parameters/basic.py index 14c2994ae7a..ffe7b593a35 100644 --- a/lib/galaxy/tools/parameters/basic.py +++ b/lib/galaxy/tools/parameters/basic.py @@ -1177,7 +1177,7 @@ class SelectTagParameter(SelectToolParameter): """ options = [] for tag in self.get_tag_list(other_values): - options.append(('Tags: ' + tag, tag, False)) + options.append((f"Tags: {tag}", tag, False)) return options def get_initial_value(self, trans, other_values): @@ -1350,7 +1350,7 @@ class ColumnListParameter(SelectToolParameter): if isinstance(col, tuple) and len(col) == 2: options.append((col[1], col[0], False)) else: - options.append(('Column: ' + col, col, False)) + options.append((f"Column: {col}", col, False)) return options def get_initial_value(self, trans, other_values): diff --git a/lib/galaxy/tools/parameters/sanitize.py b/lib/galaxy/tools/parameters/sanitize.py index 080837155ba..79c498db340 100644 --- a/lib/galaxy/tools/parameters/sanitize.py +++ b/lib/galaxy/tools/parameters/sanitize.py @@ -43,7 +43,7 @@ class ToolParameterSanitizer: True """ - VALID_PRESET = {'default': (string.ascii_letters + string.digits + " -=_.()/+*^,:?!"), 'none': ''} + VALID_PRESET = {'default': (f"{string.ascii_letters + string.digits} -=_.()/+*^,:?!"), 'none': ''} MAPPING_PRESET = {'default': galaxy.util.mapped_chars, 'none': {}} DEFAULT_INVALID_CHAR = 'X' @@ -101,7 +101,7 @@ class ToolParameterSanitizer: if split_name.startswith('string.'): string_constant = split_name[7:] if string_constant in ('letters', 'lowercase', 'uppercase'): - split_name = 'string.ascii_' + string_constant + split_name = f"string.ascii_{string_constant}" try: value = eval(split_name) except NameError as e: diff --git a/lib/galaxy/tools/recommendations.py b/lib/galaxy/tools/recommendations.py index 5986f2ed69a..26ee9151f9a 100644 --- a/lib/galaxy/tools/recommendations.py +++ b/lib/galaxy/tools/recommendations.py @@ -79,7 +79,7 @@ class ToolRecommendations(): # iterate through all the attributes of the model to find weights of neural network layers for item in trained_model.keys(): if "weight_" in item: - weight = trained_model["weight_" + str(counter_layer_weights)][()] + weight = trained_model[f"weight_{str(counter_layer_weights)}"][()] model_weights.append(weight) counter_layer_weights += 1 self.loaded_model = tf.keras.models.model_from_json(model_config) diff --git a/lib/galaxy/tools/search/__init__.py b/lib/galaxy/tools/search/__init__.py index ac695b5d114..e5b8d28594d 100644 --- a/lib/galaxy/tools/search/__init__.py +++ b/lib/galaxy/tools/search/__init__.py @@ -190,7 +190,7 @@ class ToolBoxSearch: else: cleaned_query = ' '.join(token.text for token in self.rex(cleaned_query)) # Use asterisk Whoosh wildcard so e.g. 'bow' easily matches 'bowtie' - parsed_query = self.parser.parse('*' + cleaned_query + '*') + parsed_query = self.parser.parse(f"*{cleaned_query}*") hits = self.searcher.search(parsed_query, limit=float(tool_search_limit), sortedby='') return [hit['id'] for hit in hits] @@ -205,7 +205,7 @@ class ToolBoxSearch: ngrams = [token.text for token in token_analyzer(cleaned_query)] for query in ngrams: # Get the tool list with respective scores for each qgram - curr_hits = self.searcher.search(self.parser.parse('*' + query + '*'), limit=float(tool_search_limit)) + curr_hits = self.searcher.search(self.parser.parse(f"*{query}*"), limit=float(tool_search_limit)) for i, curr_hit in enumerate(curr_hits): is_present = False for prev_hit in hits_with_score: diff --git a/lib/galaxy/tools/toolbox/base.py b/lib/galaxy/tools/toolbox/base.py index a82222d6230..6634b83c5e9 100644 --- a/lib/galaxy/tools/toolbox/base.py +++ b/lib/galaxy/tools/toolbox/base.py @@ -558,7 +558,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): elem = etree.Element('label') elem.attrib['text'] = self.edam[term]['label'] elem.attrib['id'] = term - self._tool_panel['label_' + term] = ToolSectionLabel(elem) + self._tool_panel[f"label_{term}"] = ToolSectionLabel(elem) for (term, tool_id, key, val, val_name) in operations[term].values(): section = self._get_section(term, self.edam[term]['label']) @@ -572,7 +572,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): elem = etree.Element('label') elem.attrib['text'] = self.edam[term]['label'] elem.attrib['id'] = term - self._tool_panel['label_' + term] = ToolSectionLabel(elem) + self._tool_panel[f"label_{term}"] = ToolSectionLabel(elem) for (term, tool_id, key, val, val_name) in topics[term].values(): section = self._get_section(term, self.edam[term]['label']) @@ -587,7 +587,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): def _sort_edam_key(self, x): if x in ('operation_0004', 'topic_0003'): - return '!' + x + return f"!{x}" else: return self.edam[x]['label'] @@ -683,8 +683,8 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): if "/repos/" in tool_id: # test if tool came from a toolshed tool_id_without_tool_shed = tool_id.split("/repos/")[1] available_tool_sheds = [urlparse(_) for _ in self.app.tool_shed_registry.tool_sheds.values()] - available_tool_sheds = [url.geturl().replace(url.scheme + "://", '', 1) for url in available_tool_sheds] - tool_ids = [tool_shed + "repos/" + tool_id_without_tool_shed for tool_shed in available_tool_sheds] + available_tool_sheds = [url.geturl().replace(f"{url.scheme}://", '', 1) for url in available_tool_sheds] + tool_ids = [f"{tool_shed}repos/{tool_id_without_tool_shed}" for tool_shed in available_tool_sheds] if tool_id in tool_ids: # move original tool_id to the top of tool_ids tool_ids.remove(tool_id) tool_ids.insert(0, tool_id) @@ -953,7 +953,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): workflow_id = item.get('id') workflow = self._load_workflow(workflow_id) self._workflows_by_id[workflow_id] = workflow - key = 'workflow_' + workflow_id + key = f"workflow_{workflow_id}" if load_panel_dict: panel_dict[key] = workflow # Always load workflows into the integrated_panel_dict. @@ -963,7 +963,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): def _load_label_tag_set(self, item, panel_dict, integrated_panel_dict, load_panel_dict, index=None): label = ToolSectionLabel(item) - key = 'label_' + label.id + key = f"label_{label.id}" if load_panel_dict: panel_dict[key] = label integrated_panel_dict.update_or_append(index, key, label) @@ -1156,7 +1156,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): new_tool.installed_changeset_revision = old_tool.installed_changeset_revision new_tool.old_id = old_tool.old_id # Replace old_tool with new_tool in self._tool_panel - tool_key = 'tool_' + tool_id + tool_key = f"tool_{tool_id}" for key, val in self._tool_panel.items(): if key == tool_key: self._tool_panel[key] = new_tool @@ -1190,7 +1190,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): if tool_cache: tool_cache.expire_tool(tool_id) if remove_from_panel: - tool_key = 'tool_' + tool_id + tool_key = f"tool_{tool_id}" for key, val in self._tool_panel.items(): if key == tool_key: del self._tool_panel[key] diff --git a/lib/galaxy/tools/toolbox/integrated_panel.py b/lib/galaxy/tools/toolbox/integrated_panel.py index e3bcd078cac..4646896cbb8 100644 --- a/lib/galaxy/tools/toolbox/integrated_panel.py +++ b/lib/galaxy/tools/toolbox/integrated_panel.py @@ -110,10 +110,10 @@ $INTEGRATED_TOOL_PANEL with RenamedTemporaryFile(filename, mode='w') as f: f.write(tp_string) if tracking_directory: - with open(filename + ".stack", "w") as f: + with open(f"{filename}.stack", "w") as f: f.write(''.join(traceback.format_stack())) - shutil.copy(filename, filename + ".copy") - shutil.move(filename + ".copy", destination) + shutil.copy(filename, f"{filename}.copy") + shutil.move(f"{filename}.copy", destination) try: os.chmod(destination, RW_R__R__) except OSError: diff --git a/lib/galaxy/tools/toolbox/tags.py b/lib/galaxy/tools/toolbox/tags.py index ba0033a9454..88f25557543 100644 --- a/lib/galaxy/tools/toolbox/tags.py +++ b/lib/galaxy/tools/toolbox/tags.py @@ -49,7 +49,7 @@ class PersistentToolTagManager(AbstractToolTagManager): self.sa_session = app.model.context def reset_tags(self): - log.info("removing all tool tag associations (" + str(self.sa_session.query(self.app.model.ToolTagAssociation).count()) + ")") + log.info(f"removing all tool tag associations ({str(self.sa_session.query(self.app.model.ToolTagAssociation).count())})") self.sa_session.query(self.app.model.ToolTagAssociation).delete() self.sa_session.flush() diff --git a/lib/galaxy/util/compression_utils.py b/lib/galaxy/util/compression_utils.py index fefd5692a97..4a22807dd6a 100644 --- a/lib/galaxy/util/compression_utils.py +++ b/lib/galaxy/util/compression_utils.py @@ -170,7 +170,7 @@ class CompressedFile: elif self.file_type == "zip": for name in members.namelist(): if not safe_relpath(name): - raise Exception(name + " is blocked (illegal path).") + raise Exception(f"{name} is blocked (illegal path).") yield name def getmembers_tar(self): diff --git a/lib/galaxy/util/dictifiable.py b/lib/galaxy/util/dictifiable.py index 162d0bf3acd..acd6a5eaefb 100644 --- a/lib/galaxy/util/dictifiable.py +++ b/lib/galaxy/util/dictifiable.py @@ -50,7 +50,7 @@ class Dictifiable: # Fill item dict with visible keys. try: - visible_keys = self.__getattribute__('dict_' + view + '_visible_keys') + visible_keys = self.__getattribute__(f"dict_{view}_visible_keys") except AttributeError: raise Exception(f'Unknown Dictifiable view: {view}') for key in visible_keys: diff --git a/lib/galaxy/util/facts.py b/lib/galaxy/util/facts.py index 519b6936d4a..a00f597c11f 100644 --- a/lib/galaxy/util/facts.py +++ b/lib/galaxy/util/facts.py @@ -30,7 +30,7 @@ class Facts(MutableMapping): if config is not None: for name in dir(config): if not name.startswith('_') and isinstance(getattr(config, name), str): - self.__dict__['config_' + name] = lambda name=name: getattr(config, name) + self.__dict__[f"config_{name}"] = lambda name=name: getattr(config, name) def __getitem__(self, key): item = self.__dict__.__getitem__(key) diff --git a/lib/galaxy/util/heartbeat.py b/lib/galaxy/util/heartbeat.py index 7da6de5282d..baf8623486c 100644 --- a/lib/galaxy/util/heartbeat.py +++ b/lib/galaxy/util/heartbeat.py @@ -53,7 +53,7 @@ class Heartbeat(threading.Thread): pid=self.pid ) fname, ext = os.path.splitext(self.fname) - self.fname_nonsleeping = fname + '.nonsleeping' + ext + self.fname_nonsleeping = f"{fname}.nonsleeping{ext}" wait = self.period if self.period <= 0: wait = 60 diff --git a/lib/galaxy/util/inflection.py b/lib/galaxy/util/inflection.py index 84840aad6c0..3f5a5ca7b01 100644 --- a/lib/galaxy/util/inflection.py +++ b/lib/galaxy/util/inflection.py @@ -109,9 +109,9 @@ class Inflector: for form_a, form_b in self.IRREGULAR_WORDS.items(): if not pluralize: form_a, form_b = form_b, form_a - match = re.search('(' + form_a + ')$', word, re.IGNORECASE) + match = re.search(f"({form_a})$", word, re.IGNORECASE) if match: - return re.sub('(?i)' + form_a + '$', match.expand('\\1')[0] + form_b[1:], word) + return re.sub(f"(?i){form_a}$", match.expand('\\1')[0] + form_b[1:], word) def _apply_rules(self, rules, word): for pattern, replacement in rules: diff --git a/lib/galaxy/util/object_wrapper.py b/lib/galaxy/util/object_wrapper.py index 101a202fd36..16b71f599f3 100644 --- a/lib/galaxy/util/object_wrapper.py +++ b/lib/galaxy/util/object_wrapper.py @@ -60,7 +60,7 @@ __WRAP_MAPPINGS__ = (dict, UserDict, ) # Define the set of characters that are not sanitized, and define a set of mappings for those that are. # characters that are valid -VALID_CHARACTERS = set(string.ascii_letters + string.digits + " -=_.()/+*^,:?!@") +VALID_CHARACTERS = set(f"{string.ascii_letters + string.digits} -=_.()/+*^,:?!@") # characters that are allowed but need to be escaped CHARACTER_MAP = {'>': '__gt__', diff --git a/lib/galaxy/util/pastescript/loadwsgi.py b/lib/galaxy/util/pastescript/loadwsgi.py index 323fe2d2788..6e84867de35 100644 --- a/lib/galaxy/util/pastescript/loadwsgi.py +++ b/lib/galaxy/util/pastescript/loadwsgi.py @@ -75,7 +75,7 @@ def fix_type_error(exc_info, callable, varargs, kwargs): def _short_repr(v): v = repr(v) if len(v) > 12: - v = v[:8] + '...' + v[-4:] + v = f"{v[:8]}...{v[-4:]}" return v @@ -112,7 +112,7 @@ def lookup_object(spec): def import_string(s): - return pkg_resources.EntryPoint.parse("x=" + s).load(False) + return pkg_resources.EntryPoint.parse(f"x={s}").load(False) def _aslist(obj): @@ -353,7 +353,7 @@ def _loadconfig(object_type, uri, path, name, relative_to, if relative_to.endswith('/'): path = relative_to + path else: - path = relative_to + '/' + path + path = f"{relative_to}/{path}" if path.startswith('///'): path = path[2:] path = unquote(path) @@ -646,7 +646,7 @@ class ConfigLoader(_Loader): found.append(name_prefix) name = 'main' for section in sections: - if section.startswith(name_prefix + ':'): + if section.startswith(f"{name_prefix}:"): if section[len(name_prefix) + 1:].strip() == name: found.append(section) return found diff --git a/lib/galaxy/util/pastescript/serve.py b/lib/galaxy/util/pastescript/serve.py index 73c96963754..49b0ad8182e 100644 --- a/lib/galaxy/util/pastescript/serve.py +++ b/lib/galaxy/util/pastescript/serve.py @@ -228,7 +228,7 @@ class Command: def parse_args(self, args): if self.usage: - usage = ' ' + self.usage + usage = f" {self.usage}" else: usage = '' self.parser.usage = f"%prog [options]{usage}\n{self.summary}" @@ -567,7 +567,7 @@ class ServeCommand(Command): app_name = self.options.app_name vars = self.parse_vars(restvars) if not self._scheme_re.search(app_spec): - app_spec = 'config:' + app_spec + app_spec = f"config:{app_spec}" server_name = self.options.server_name if self.options.server: server_spec = 'egg:PasteScript' @@ -649,7 +649,7 @@ class ServeCommand(Command): if self.verbose > 1: raise if str(e): - msg = ' ' + str(e) + msg = f" {str(e)}" else: msg = '' print(f'Exiting{msg} (-v to see traceback)') diff --git a/lib/galaxy/util/submodules.py b/lib/galaxy/util/submodules.py index 068050a23d3..d0544e7489a 100644 --- a/lib/galaxy/util/submodules.py +++ b/lib/galaxy/util/submodules.py @@ -39,7 +39,7 @@ def __import_submodules_impl(module, recursive=False): module = importlib.import_module(module) submodules = [] for _, name, is_pkg in pkgutil.walk_packages(module.__path__): - full_name = module.__name__ + '.' + name + full_name = f"{module.__name__}.{name}" try: submodule = importlib.import_module(full_name) submodules.append(submodule) diff --git a/lib/galaxy/visualization/data_providers/phyloviz/baseparser.py b/lib/galaxy/visualization/data_providers/phyloviz/baseparser.py index a7c499bc231..45d9e1f6ae6 100644 --- a/lib/galaxy/visualization/data_providers/phyloviz/baseparser.py +++ b/lib/galaxy/visualization/data_providers/phyloviz/baseparser.py @@ -26,7 +26,7 @@ class Node: self.children += child def __str__(self): - return self.name + " id:" + str(self.id) + ", depth: " + str(self.depth) + return f"{self.name} id:{str(self.id)}, depth: {str(self.depth)}" def toJson(self): """Converts the data in the node to a dict representation of json""" diff --git a/lib/galaxy/visualization/data_providers/phyloviz/newickparser.py b/lib/galaxy/visualization/data_providers/phyloviz/newickparser.py index 4144b612344..e329d7cb8ec 100644 --- a/lib/galaxy/visualization/data_providers/phyloviz/newickparser.py +++ b/lib/galaxy/visualization/data_providers/phyloviz/newickparser.py @@ -43,7 +43,7 @@ class Newick_Parser(Base_Parser): """elements separated by comma could be empty""" if string.find("(") != -1: - raise Exception("Tree is not well form, location: " + string) + raise Exception(f"Tree is not well form, location: {string}") childrenString = string.split(",") childrenNodes = [] diff --git a/lib/galaxy/visualization/genomes.py b/lib/galaxy/visualization/genomes.py index 3869a5178ec..f9c3f62efac 100644 --- a/lib/galaxy/visualization/genomes.py +++ b/lib/galaxy/visualization/genomes.py @@ -50,7 +50,7 @@ class GenomeRegion: self.sequence = sequence def __str__(self): - return self.chrom + ":" + str(self.start) + "-" + str(self.end) + return f"{self.chrom}:{str(self.start)}-{str(self.end)}" @staticmethod def from_dict(obj_dict): diff --git a/lib/galaxy/visualization/plugins/config_parser.py b/lib/galaxy/visualization/plugins/config_parser.py index 1e62b9767fb..ca2c2f7972f 100644 --- a/lib/galaxy/visualization/plugins/config_parser.py +++ b/lib/galaxy/visualization/plugins/config_parser.py @@ -186,7 +186,7 @@ class VisualizationsConfigParser: entry_point_attrib = dict(entry_point.attrib) entry_point_type = entry_point_attrib.pop('entry_point_type', 'mako') if entry_point_type not in self.ALLOWED_ENTRY_POINT_TYPES: - raise ParsingException('Unknown entry_point type: ' + entry_point_type) + raise ParsingException(f"Unknown entry_point type: {entry_point_type}") return { 'type': entry_point_type, 'file': entry_point.text, diff --git a/lib/galaxy/visualization/plugins/interactive_environments.py b/lib/galaxy/visualization/plugins/interactive_environments.py index 37bf2d54d2e..713d679ac2f 100644 --- a/lib/galaxy/visualization/plugins/interactive_environments.py +++ b/lib/galaxy/visualization/plugins/interactive_environments.py @@ -51,7 +51,7 @@ class InteractiveEnvironmentRequest: self.attr.redact_username_in_logs = trans.app.config.redact_username_in_logs self.attr.galaxy_root_dir = os.path.abspath(self.attr.galaxy_config.root) self.attr.root = web.url_for("/") - self.attr.app_root = self.attr.root + "static/plugins/interactive_environments/" + self.attr.viz_id + "/static/" + self.attr.app_root = f"{self.attr.root}static/plugins/interactive_environments/{self.attr.viz_id}/static/" self.attr.import_volume = True plugin_path = os.path.abspath(plugin.path) @@ -101,7 +101,7 @@ class InteractiveEnvironmentRequest: # multiple leading '/' characters, which will cause the client to # request resources from http://dynamic_proxy_prefix if self.attr.proxy_prefix.startswith('/'): - self.attr.proxy_prefix = '/' + self.attr.proxy_prefix.lstrip('/') + self.attr.proxy_prefix = f"/{self.attr.proxy_prefix.lstrip('/')}" assert not self.attr.container_interface \ or not self.attr.container_interface.publish_port_list_required \ @@ -127,7 +127,7 @@ class InteractiveEnvironmentRequest: self.allowed_images = [x['image'] for x in yaml.safe_load(handle)] if len(self.allowed_images) == 0: - raise Exception("No allowed images specified for " + self.attr.viz_id) + raise Exception(f"No allowed images specified for {self.attr.viz_id}") self.default_image = self.allowed_images[0] @@ -146,7 +146,7 @@ class InteractiveEnvironmentRequest: 'docker_connect_port': None, } viz_config = configparser.ConfigParser(default_dict) - conf_path = os.path.join(self.attr.our_config_dir, self.attr.viz_id + ".ini") + conf_path = os.path.join(self.attr.our_config_dir, f"{self.attr.viz_id}.ini") if not os.path.exists(conf_path): conf_path = f"{conf_path}.sample" viz_config.read(conf_path) @@ -203,9 +203,9 @@ class InteractiveEnvironmentRequest: if self.attr.viz_config.has_option("docker", "galaxy_url"): conf_file['galaxy_url'] = self.attr.viz_config.get("docker", "galaxy_url") elif self.attr.galaxy_config.galaxy_infrastructure_url_set: - conf_file['galaxy_url'] = self.attr.galaxy_config.galaxy_infrastructure_url.rstrip('/') + '/' + conf_file['galaxy_url'] = f"{self.attr.galaxy_config.galaxy_infrastructure_url.rstrip('/')}/" else: - conf_file['galaxy_url'] = request.application_url.rstrip('/') + '/' + conf_file['galaxy_url'] = f"{request.application_url.rstrip('/')}/" # Galaxy paster port is deprecated conf_file['galaxy_paster_port'] = conf_file['galaxy_web_port'] diff --git a/lib/galaxy/visualization/plugins/plugin.py b/lib/galaxy/visualization/plugins/plugin.py index 1ca8c217a82..26466b286da 100644 --- a/lib/galaxy/visualization/plugins/plugin.py +++ b/lib/galaxy/visualization/plugins/plugin.py @@ -74,7 +74,7 @@ class VisualizationPlugin(ServesTemplatesPluginMixin): self.base_url = '/'.join((base_url, self.name)) if base_url else self.name self.static_path = self._get_static_path(self.path) if self.static_path and os.path.exists(os.path.join(self.static_path, 'logo.png')): - self.config['logo'] = self.static_path + '/logo.png' + self.config['logo'] = f"{self.static_path}/logo.png" template_cache_dir = context.get('template_cache_dir', None) additional_template_paths = context.get('additional_template_paths', []) self._set_up_template_plugin(template_cache_dir, additional_template_paths=additional_template_paths) diff --git a/lib/galaxy/visualization/plugins/registry.py b/lib/galaxy/visualization/plugins/registry.py index 3b5c23b915a..be1112778a5 100644 --- a/lib/galaxy/visualization/plugins/registry.py +++ b/lib/galaxy/visualization/plugins/registry.py @@ -180,7 +180,7 @@ class VisualizationsRegistry: """ plugin_name = os.path.split(plugin_path)[1] # TODO: this is the standard/older way to config - config_file = os.path.join(plugin_path, 'config', (plugin_name + '.xml')) + config_file = os.path.join(plugin_path, 'config', (f"{plugin_name}.xml")) if os.path.exists(config_file): config = self.config_parser.parse_file(config_file) if config is not None: @@ -218,7 +218,7 @@ class VisualizationsRegistry: Wrap to throw error if plugin not in registry. """ if key not in self.plugins: - raise ObjectNotFound('Unknown or invalid visualization: ' + key) + raise ObjectNotFound(f"Unknown or invalid visualization: {key}") return self.plugins[key] def get_plugins(self, embeddable=None): diff --git a/lib/galaxy/web/framework/base.py b/lib/galaxy/web/framework/base.py index 078a426932d..b64f5a76aef 100644 --- a/lib/galaxy/web/framework/base.py +++ b/lib/galaxy/web/framework/base.py @@ -34,11 +34,11 @@ def __resource_with_deleted(self, member_name, collection_name, **kwargs): as resource() with the addition of standardized routes for handling elements in Galaxy's "deleted but not really deleted" fashion. """ - collection_path = kwargs.get('path_prefix', '') + '/' + collection_name + '/deleted' - member_path = collection_path + '/{id}' - self.connect('deleted_' + collection_name, collection_path, controller=collection_name, action='index', deleted=True, conditions=dict(method=['GET'])) - self.connect('deleted_' + member_name, member_path, controller=collection_name, action='show', deleted=True, conditions=dict(method=['GET'])) - self.connect('undelete_deleted_' + member_name, member_path + '/undelete', controller=collection_name, action='undelete', + collection_path = f"{kwargs.get('path_prefix', '')}/{collection_name}/deleted" + member_path = f"{collection_path}/{{id}}" + self.connect(f"deleted_{collection_name}", collection_path, controller=collection_name, action='index', deleted=True, conditions=dict(method=['GET'])) + self.connect(f"deleted_{member_name}", member_path, controller=collection_name, action='show', deleted=True, conditions=dict(method=['GET'])) + self.connect(f"undelete_deleted_{member_name}", f"{member_path}/undelete", controller=collection_name, action='undelete', conditions=dict(method=['POST'])) self.resource(member_name, collection_name, **kwargs) @@ -146,7 +146,7 @@ class WebApplication: controller_name = map_match.pop('controller', None) controller = controllers.get(controller_name, None) if controller is None: - raise webob.exc.HTTPNotFound("No controller for " + path_info) + raise webob.exc.HTTPNotFound(f"No controller for {path_info}") # Resolve action method on controller # This is the easiest way to make the controller/action accessible for # url_for invocations. Specifically, grids. @@ -155,18 +155,18 @@ class WebApplication: if method is None and not use_default: # Skip default, we do this, for example, when we want to fail # through to another mapper. - raise webob.exc.HTTPNotFound("No action for " + path_info) + raise webob.exc.HTTPNotFound(f"No action for {path_info}") if method is None: # no matching method, we try for a default method = getattr(controller, 'default', None) if method is None: - raise webob.exc.HTTPNotFound("No action for " + path_info) + raise webob.exc.HTTPNotFound(f"No action for {path_info}") # Is the method exposed if not getattr(method, 'exposed', False): - raise webob.exc.HTTPNotFound("Action not exposed for " + path_info) + raise webob.exc.HTTPNotFound(f"Action not exposed for {path_info}") # Is the method callable if not callable(method): - raise webob.exc.HTTPNotFound("Action not callable for " + path_info) + raise webob.exc.HTTPNotFound(f"Action not callable for {path_info}") return (controller_name, controller, action, method) def handle_request(self, environ, start_response, body_renderer=None): @@ -183,7 +183,7 @@ class WebApplication: environ['is_api_request'] = False controllers = self.controllers if map_match is None: - raise webob.exc.HTTPNotFound("No route for " + path_info) + raise webob.exc.HTTPNotFound(f"No route for {path_info}") self.trace(path_info=path_info, map_match=map_match) # Setup routes rc = routes.request_config() @@ -395,7 +395,7 @@ class Request(webob.Request): @lazy_property def base(self): - return (self.scheme + "://" + self.host) + return (f"{self.scheme}://{self.host}") # @lazy_property # def params( self ): @@ -531,6 +531,6 @@ def walk_controller_modules(package_name): for fname in os.listdir(controller_dir): if not(fname.startswith("_")) and fname.endswith(".py"): name = fname[:-3] - module_name = package_name + "." + name + module_name = f"{package_name}.{name}" module = import_module(module_name) yield name, module diff --git a/lib/galaxy/web/framework/helpers/grids.py b/lib/galaxy/web/framework/helpers/grids.py index 349528c967c..0b101232428 100644 --- a/lib/galaxy/web/framework/helpers/grids.py +++ b/lib/galaxy/web/framework/helpers/grids.py @@ -123,7 +123,7 @@ class TextColumn(GridColumn): else: a_key = self.key model_class_key_field = getattr(self.model_class, a_key) - return func.lower(model_class_key_field).like("%" + a_filter.lower() + "%") + return func.lower(model_class_key_field).like(f"%{a_filter.lower()}%") def sort(self, trans, query, ascending, column_name=None): """Sort column using case-insensitive alphabetical sorting.""" @@ -245,7 +245,7 @@ class OwnerAnnotationColumn(TextColumn, UsesAnnotations): def get_single_filter(self, user, a_filter): """ Filter by annotation and annotation owner. """ return self.model_class.annotations.any( - and_(func.lower(self.model_annotation_association_class.annotation).like("%" + a_filter.lower() + "%"), + and_(func.lower(self.model_annotation_association_class.annotation).like(f"%{a_filter.lower()}%"), # TODO: not sure why, to filter by owner's annotations, we have to do this rather than # 'self.model_class.user==self.model_annotation_association_class.user' self.model_annotation_association_class.table.c.user_id == self.model_class.table.c.user_id)) @@ -282,10 +282,10 @@ class CommunityTagsColumn(TextColumn): for name, value in raw_tags: if name: # Filter by all tags. - clause_list.append(self.model_class.tags.any(func.lower(self.model_tag_association_class.user_tname).like("%" + name.lower() + "%"))) + clause_list.append(self.model_class.tags.any(func.lower(self.model_tag_association_class.user_tname).like(f"%{name.lower()}%"))) if value: # Filter by all values. - clause_list.append(self.model_class.tags.any(func.lower(self.model_tag_association_class.user_value).like("%" + value.lower() + "%"))) + clause_list.append(self.model_class.tags.any(func.lower(self.model_tag_association_class.user_value).like(f"%{value.lower()}%"))) return and_(*clause_list) @@ -311,10 +311,10 @@ class IndividualTagsColumn(CommunityTagsColumn): for name, value in raw_tags: if name: # Filter by individual's tag names. - clause_list.append(self.model_class.tags.any(and_(func.lower(self.model_tag_association_class.user_tname).like("%" + name.lower() + "%"), self.model_tag_association_class.user == user))) + clause_list.append(self.model_class.tags.any(and_(func.lower(self.model_tag_association_class.user_tname).like(f"%{name.lower()}%"), self.model_tag_association_class.user == user))) if value: # Filter by individual's tag values. - clause_list.append(self.model_class.tags.any(and_(func.lower(self.model_tag_association_class.user_value).like("%" + value.lower() + "%"), self.model_tag_association_class.user == user))) + clause_list.append(self.model_class.tags.any(and_(func.lower(self.model_tag_association_class.user_value).like(f"%{value.lower()}%"), self.model_tag_association_class.user == user))) return and_(*clause_list) @@ -564,7 +564,7 @@ class GridColumnFilter: def get_url_args(self): rval = {} for k, v in self.args.items(): - rval["f-" + k] = v + rval[f"f-{k}"] = v return rval @@ -639,12 +639,12 @@ class Grid: if use_default_filter: if self.default_filter: column_filter = self.default_filter.get(column.key) - elif "f-" + column.model_class.__name__ + f".{column.key}" in kwargs: + elif f"f-{column.model_class.__name__}.{column.key}" in kwargs: # Queries that include table joins cannot guarantee unique column names. This problem is # handled by setting the column_filter value to .. - column_filter = kwargs.get("f-" + column.model_class.__name__ + f".{column.key}") - elif "f-" + column.key in kwargs: - column_filter = kwargs.get("f-" + column.key) + column_filter = kwargs.get(f"f-{column.model_class.__name__}.{column.key}") + elif f"f-{column.key}" in kwargs: + column_filter = kwargs.get(f"f-{column.key}") elif column.key in base_filter: column_filter = base_filter.get(column.key) @@ -697,10 +697,10 @@ class Grid: # that we can encode to UTF-8 and thus handle user input to filters. if isinstance(column_filter, list): # Filter is a list; process each item. - extra_url_args["f-" + column.key] = dumps(column_filter) + extra_url_args[f"f-{column.key}"] = dumps(column_filter) else: # Process singleton filter. - extra_url_args["f-" + column.key] = column_filter + extra_url_args[f"f-{column.key}"] = column_filter # Process sort arguments. sort_key = None if 'sort' in kwargs: diff --git a/lib/galaxy/web/framework/middleware/error.py b/lib/galaxy/web/framework/middleware/error.py index e34b380079d..f50a0a2a158 100644 --- a/lib/galaxy/web/framework/middleware/error.py +++ b/lib/galaxy/web/framework/middleware/error.py @@ -422,14 +422,14 @@ def handle_exception(exc_info, error_stream, html=True, extra = "

    The error has been logged to our team." if 'sentry_event_id' in environ: extra += " If you want to contact us about this error, please reference the following

    " - extra += "GURU MEDITATION: #" + environ['sentry_event_id'] + "" + extra += f"GURU MEDITATION: #{environ['sentry_event_id']}" extra += "

    " return_error = error_template('', msg, extra) else: return_error = None if not reported and error_stream: err_report = formatter.format_text(exc_data, show_hidden_frames=True) - err_report += '\n' + '-' * 60 + '\n' + err_report += f"\n{'-' * 60}\n" error_stream.write(err_report) if extra_data: error_stream.write(extra_data) diff --git a/lib/galaxy/web/framework/middleware/profile.py b/lib/galaxy/web/framework/middleware/profile.py index fc30f22cff0..f3cfd09bc47 100644 --- a/lib/galaxy/web/framework/middleware/profile.py +++ b/lib/galaxy/web/framework/middleware/profile.py @@ -113,7 +113,7 @@ def pstats_as_html(stats, *sel_list): # ncalls ncalls = str(nc) if nc != cc: - ncalls = ncalls + '/' + str(cc) + ncalls = f"{ncalls}/{str(cc)}" rval.append(f"{markupsafe.escape(ncalls)}") # tottime rval.append(f"{tt:0.8f}") @@ -147,7 +147,7 @@ def get_func_list(stats, sel_list): # Determine if an ordering was applied if stats.fcn_list: list = stats.fcn_list[:] - order_message = "Ordered by: " + stats.sort_type + order_message = f"Ordered by: {stats.sort_type}" else: list = list(stats.stats.keys()) order_message = "Random listing order was used" diff --git a/lib/galaxy/web/framework/middleware/remoteuser.py b/lib/galaxy/web/framework/middleware/remoteuser.py index c2527a9afa4..3b6d1a0c2e4 100644 --- a/lib/galaxy/web/framework/middleware/remoteuser.py +++ b/lib/galaxy/web/framework/middleware/remoteuser.py @@ -134,7 +134,7 @@ class RemoteUser: if environ.get(self.remote_user_header, None): if not environ[self.remote_user_header].count('@'): if self.maildomain is not None: - environ[self.remote_user_header] += '@' + self.maildomain + environ[self.remote_user_header] += f"@{self.maildomain}" else: title = "Access to Galaxy is denied" message = """ diff --git a/lib/galaxy/web/framework/middleware/statsd.py b/lib/galaxy/web/framework/middleware/statsd.py index e08cb382fac..40814988ca3 100644 --- a/lib/galaxy/web/framework/middleware/statsd.py +++ b/lib/galaxy/web/framework/middleware/statsd.py @@ -38,8 +38,8 @@ class StatsdMiddleware: self.galaxy_stasd_client.timing(page, dt) try: times = QUERY_COUNT_LOCAL.times - self.galaxy_stasd_client.timing("sql." + page, sum(times) * 1000.) - self.galaxy_stasd_client.incr("sqlqueries." + page, len(times)) + self.galaxy_stasd_client.timing(f"sql.{page}", sum(times) * 1000.) + self.galaxy_stasd_client.incr(f"sqlqueries.{page}", len(times)) except AttributeError: # Not logging query counts, skip pass diff --git a/lib/galaxy/web/framework/middleware/translogger.py b/lib/galaxy/web/framework/middleware/translogger.py index e11a0709d80..b567b2c9d1f 100644 --- a/lib/galaxy/web/framework/middleware/translogger.py +++ b/lib/galaxy/web/framework/middleware/translogger.py @@ -53,7 +53,7 @@ class TransLogger: req_uri = quote(environ.get('SCRIPT_NAME', '') + environ.get('PATH_INFO', '')) if environ.get('QUERY_STRING'): - req_uri += '?' + environ['QUERY_STRING'] + req_uri += f"?{environ['QUERY_STRING']}" method = environ['REQUEST_METHOD'] def replacement_start_response(status, headers, exc_info=None): diff --git a/lib/galaxy/web/legacy_framework/grids.py b/lib/galaxy/web/legacy_framework/grids.py index c7e479f474e..15e3522a13f 100644 --- a/lib/galaxy/web/legacy_framework/grids.py +++ b/lib/galaxy/web/legacy_framework/grids.py @@ -122,7 +122,7 @@ class TextColumn(GridColumn): else: a_key = self.key model_class_key_field = getattr(self.model_class, a_key) - return func.lower(model_class_key_field).like("%" + a_filter.lower() + "%") + return func.lower(model_class_key_field).like(f"%{a_filter.lower()}%") def sort(self, trans, query, ascending, column_name=None): """Sort column using case-insensitive alphabetical sorting.""" @@ -237,7 +237,7 @@ class OwnerAnnotationColumn(TextColumn, UsesAnnotations): def get_single_filter(self, user, a_filter): """ Filter by annotation and annotation owner. """ return self.model_class.annotations.any( - and_(func.lower(self.model_annotation_association_class.annotation).like("%" + a_filter.lower() + "%"), + and_(func.lower(self.model_annotation_association_class.annotation).like(f"%{a_filter.lower()}%"), # TODO: not sure why, to filter by owner's annotations, we have to do this rather than # 'self.model_class.user==self.model_annotation_association_class.user' self.model_annotation_association_class.table.c.user_id == self.model_class.table.c.user_id)) @@ -274,10 +274,10 @@ class CommunityTagsColumn(TextColumn): for name, value in raw_tags: if name: # Filter by all tags. - clause_list.append(self.model_class.tags.any(func.lower(self.model_tag_association_class.user_tname).like("%" + name.lower() + "%"))) + clause_list.append(self.model_class.tags.any(func.lower(self.model_tag_association_class.user_tname).like(f"%{name.lower()}%"))) if value: # Filter by all values. - clause_list.append(self.model_class.tags.any(func.lower(self.model_tag_association_class.user_value).like("%" + value.lower() + "%"))) + clause_list.append(self.model_class.tags.any(func.lower(self.model_tag_association_class.user_value).like(f"%{value.lower()}%"))) return and_(*clause_list) @@ -303,10 +303,10 @@ class IndividualTagsColumn(CommunityTagsColumn): for name, value in raw_tags: if name: # Filter by individual's tag names. - clause_list.append(self.model_class.tags.any(and_(func.lower(self.model_tag_association_class.user_tname).like("%" + name.lower() + "%"), self.model_tag_association_class.user == user))) + clause_list.append(self.model_class.tags.any(and_(func.lower(self.model_tag_association_class.user_tname).like(f"%{name.lower()}%"), self.model_tag_association_class.user == user))) if value: # Filter by individual's tag values. - clause_list.append(self.model_class.tags.any(and_(func.lower(self.model_tag_association_class.user_value).like("%" + value.lower() + "%"), self.model_tag_association_class.user == user))) + clause_list.append(self.model_class.tags.any(and_(func.lower(self.model_tag_association_class.user_value).like(f"%{value.lower()}%"), self.model_tag_association_class.user == user))) return and_(*clause_list) @@ -526,7 +526,7 @@ class GridColumnFilter: def get_url_args(self): rval = {} for k, v in self.args.items(): - rval["f-" + k] = v + rval[f"f-{k}"] = v return rval @@ -605,12 +605,12 @@ class Grid: if use_default_filter: if self.default_filter: column_filter = self.default_filter.get(column.key) - elif "f-" + column.model_class.__name__ + f".{column.key}" in kwargs: + elif f"f-{column.model_class.__name__}.{column.key}" in kwargs: # Queries that include table joins cannot guarantee unique column names. This problem is # handled by setting the column_filter value to .. - column_filter = kwargs.get("f-" + column.model_class.__name__ + f".{column.key}") - elif "f-" + column.key in kwargs: - column_filter = kwargs.get("f-" + column.key) + column_filter = kwargs.get(f"f-{column.model_class.__name__}.{column.key}") + elif f"f-{column.key}" in kwargs: + column_filter = kwargs.get(f"f-{column.key}") elif column.key in base_filter: column_filter = base_filter.get(column.key) @@ -664,12 +664,12 @@ class Grid: if isinstance(column_filter, list): # Filter is a list; process each item. column_filter = [str(_).encode('utf-8') if not isinstance(_, str) else _ for _ in column_filter] - extra_url_args["f-" + column.key] = dumps(column_filter) + extra_url_args[f"f-{column.key}"] = dumps(column_filter) else: # Process singleton filter. if not isinstance(column_filter, str): column_filter = str(column_filter) - extra_url_args["f-" + column.key] = column_filter.encode("utf-8") + extra_url_args[f"f-{column.key}"] = column_filter.encode("utf-8") # Process sort arguments. sort_key = None if 'sort' in kwargs: diff --git a/lib/galaxy/web/proxy/__init__.py b/lib/galaxy/web/proxy/__init__.py index 93d19d10993..9d15b550f1d 100644 --- a/lib/galaxy/web/proxy/__init__.py +++ b/lib/galaxy/web/proxy/__init__.py @@ -59,7 +59,7 @@ class ProxyManager: def setup_proxy(self, trans, host=DEFAULT_PROXY_TO_HOST, port=None, proxy_prefix="", route_name="", container_ids=None, container_interface=None): if self.manage_dynamic_proxy: log.info("Attempting to start dynamic proxy process") - log.debug("Cmd: " + ' '.join(self.lazy_process.command_and_args)) + log.debug(f"Cmd: {' '.join(self.lazy_process.command_and_args)}") self.lazy_process.start_process() if container_ids is None: diff --git a/lib/galaxy/web/statsd_client.py b/lib/galaxy/web/statsd_client.py index 7936213088e..b6c88ad73f0 100644 --- a/lib/galaxy/web/statsd_client.py +++ b/lib/galaxy/web/statsd_client.py @@ -42,7 +42,7 @@ class VanillaGalaxyStatsdClient: def _effective_infix(self, path, tags): tags = tags or {} if self.statsd_influxdb and tags: - return ',' + ",".join(f"{k}={v}" for (k, v) in tags.items()) + ",path=" + return f",{','.join(f'{k}={v}' for k, v in tags.items())}" + ',path=' if self.statsd_influxdb: return ',path=' else: diff --git a/lib/galaxy/web_stack/__init__.py b/lib/galaxy/web_stack/__init__.py index 3d420b8d592..3008347efc5 100644 --- a/lib/galaxy/web_stack/__init__.py +++ b/lib/galaxy/web_stack/__init__.py @@ -124,8 +124,8 @@ class ApplicationStack: for pool_name in self.configured_pools: if pool_name == base_pool: tag = job_config.DEFAULT_HANDLER_TAG - elif pool_name.startswith(base_pool + '.'): - tag = pool_name.replace(base_pool + '.', '', 1) + elif pool_name.startswith(f"{base_pool}."): + tag = pool_name.replace(f"{base_pool}.", '', 1) else: continue # Pools are hierarchical (so that you can have e.g. workflow schedulers use the job handlers pool if no @@ -181,7 +181,7 @@ class ApplicationStack: return {} def has_base_pool(self, pool_name): - return self.has_pool(pool_name) or any([pool.startswith(pool_name + '.') for pool in self.configured_pools]) + return self.has_pool(pool_name) or any([pool.startswith(f"{pool_name}.") for pool in self.configured_pools]) def has_pool(self, pool_name): return pool_name in self.configured_pools @@ -306,11 +306,11 @@ class UWSGIApplicationStack(MessageApplicationStack): val = unicodify(uwsgi.opt.get('shared-socket', [])[int(val.split('=')[1])]) proto = opt if opt != 'socket' else 'uwsgi' if proto == 'uwsgi' and ':' not in val: - return 'uwsgi://' + val + return f"uwsgi://{val}" else: - proto = proto + '://' + proto = f"{proto}://" host, port = val.rsplit(':', 1) - port = ':' + port.split(',', 1)[0] + port = f":{port.split(',', 1)[0]}" if host in UWSGIApplicationStack.bind_all_addrs: host = UWSGIApplicationStack.localhost_addrs[0] return proto + host + port @@ -421,7 +421,7 @@ class UWSGIApplicationStack(MessageApplicationStack): # Count the required number of uWSGI locks if job_config.use_messaging: for pool_name in self.configured_pools: - if (pool_name == base_pool or pool_name.startswith(base_pool + '.')): + if (pool_name == base_pool or pool_name.startswith(f"{base_pool}.")): self._lock_farms.add(pool_name) @property @@ -510,7 +510,7 @@ class UWSGIApplicationStack(MessageApplicationStack): root_pid = uwsgi.masterpid() or os.getpid() msg.append('Starting server in PID %d.' % root_pid) for s in UWSGIApplicationStack._serving_on(): - msg.append('serving on ' + s) + msg.append(f"serving on {s}") if len(msg) == 1: msg.append('serving on unknown URL') log.info('\n'.join(msg)) diff --git a/lib/galaxy/web_stack/transport.py b/lib/galaxy/web_stack/transport.py index 18eb1ebea95..95d8ecf93ac 100644 --- a/lib/galaxy/web_stack/transport.py +++ b/lib/galaxy/web_stack/transport.py @@ -39,7 +39,7 @@ class ApplicationStackTransport: # Don't unnecessarily start a thread that we don't need. if self.can_run and not self.running and not self.dispatcher_thread and self.dispatcher and self.dispatcher.handler_count: self.running = True - self.dispatcher_thread = threading.Thread(name=self.__class__.__name__ + ".dispatcher_thread", target=self._dispatch_messages) + self.dispatcher_thread = threading.Thread(name=f"{self.__class__.__name__}.dispatcher_thread", target=self._dispatch_messages) self.dispatcher_thread.start() log.info('%s dispatcher started', self.__class__.__name__) @@ -78,7 +78,7 @@ class UWSGIFarmMessageTransport(ApplicationStackTransport): need = len(self.stack._lock_farms) if num < need: raise RuntimeError('Need %i uWSGI locks but only %i exist(s): Set `locks = %i` in uWSGI configuration' % (need, num, need - 1)) - self._locks.extend(['RECV_MSG_FARM_' + x for x in sorted(self.stack._lock_farms)]) + self._locks.extend([f"RECV_MSG_FARM_{x}" for x in sorted(self.stack._lock_farms)]) # this would be nice, but in my 2.0.15 uWSGI, the uwsgi module has no set_option function, and I don't know if it'd work even if the function existed as documented # if len(self.lock_map) > 1: # uwsgi.set_option('locks', len(self.lock_map)) @@ -100,7 +100,7 @@ class UWSGIFarmMessageTransport(ApplicationStackTransport): uwsgi.unlock(self._locks.index(name_or_id)) def _farm_recv_msg_lock_num(self): - return self._locks.index('RECV_MSG_FARM_' + self.stack._farm_name) + return self._locks.index(f"RECV_MSG_FARM_{self.stack._farm_name}") def _dispatch_messages(self): # this could be moved to the base class if locking was abstracted and a get_message method was added diff --git a/lib/galaxy/webapps/base/controller.py b/lib/galaxy/webapps/base/controller.py index 2d343e6c8c4..d7bbbdc2950 100644 --- a/lib/galaxy/webapps/base/controller.py +++ b/lib/galaxy/webapps/base/controller.py @@ -800,7 +800,7 @@ class UsesVisualizationMixin(UsesLibraryMixinItems): # copy vis and alter title # TODO: need to handle custom db keys. - imported_visualization = visualization.copy(user=user, title="imported: " + visualization.title) + imported_visualization = visualization.copy(user=user, title=f"imported: {visualization.title}") trans.sa_session.add(imported_visualization) trans.sa_session.flush() return imported_visualization @@ -1238,7 +1238,7 @@ class UsesStoredWorkflowMixin(SharableItemSecurityMixin, UsesAnnotations): """ Imports a shared workflow """ # Copy workflow. imported_stored = model.StoredWorkflow() - imported_stored.name = "imported: " + stored.name + imported_stored.name = f"imported: {stored.name}" workflow = stored.latest_workflow.copy(user=trans.user) workflow.stored_workflow = imported_stored imported_stored.latest_workflow = workflow @@ -1471,7 +1471,7 @@ class UsesTagsMixin(SharableItemSecurityMixin): # boil the tag tuples down into a sorted list of DISTINCT name:val strings tags = all_tags_query.distinct().all() - tags = [((name + ':' + val) if val else name) for name, val in tags] + tags = [(f"{name}:{val}" if val else name) for name, val in tags] return sorted(tags) @@ -1552,7 +1552,7 @@ class UsesExtendedMetadataMixin(SharableItemSecurityMixin): """ if isinstance(meta, dict): for a in meta: - yield from self._scan_json_block(meta[a], prefix + "/" + a) + yield from self._scan_json_block(meta[a], f"{prefix}/{a}") elif isinstance(meta, list): for i, a in enumerate(meta): yield from self._scan_json_block(a, prefix + "[%d]" % (i)) diff --git a/lib/galaxy/webapps/base/webapp.py b/lib/galaxy/webapps/base/webapp.py index 4e265a3a040..867ed69b501 100644 --- a/lib/galaxy/webapps/base/webapp.py +++ b/lib/galaxy/webapps/base/webapp.py @@ -620,14 +620,14 @@ class GalaxyWebTransaction(base.DefaultWebTransaction, context.ProvidesHistoryCo user.set_random_password(length=12) user.external = True # Replace invalid characters in the username - for char in [x for x in username if x not in string.ascii_lowercase + string.digits + '-' + '.']: + for char in [x for x in username if x not in f"{string.ascii_lowercase + string.digits}-."]: username = username.replace(char, '-') # Find a unique username - user can change it later if self.sa_session.query(self.app.model.User).filter_by(username=username).first(): i = 1 - while self.sa_session.query(self.app.model.User).filter_by(username=(username + '-' + str(i))).first(): + while self.sa_session.query(self.app.model.User).filter_by(username=f"{username}-{str(i)}").first(): i += 1 - username += '-' + str(i) + username += f"-{str(i)}" user.username = username self.sa_session.add(user) self.sa_session.flush() diff --git a/lib/galaxy/webapps/galaxy/api/cloudauthz.py b/lib/galaxy/webapps/galaxy/api/cloudauthz.py index 1fa76c2e53f..8b4e7e9c7dc 100644 --- a/lib/galaxy/webapps/galaxy/api/cloudauthz.py +++ b/lib/galaxy/webapps/galaxy/api/cloudauthz.py @@ -91,7 +91,7 @@ class CloudAuthzController(BaseGalaxyAPIController): * status: HTTP response code * message: A message complementary to the response code. """ - msg_template = "Rejected user `" + str(trans.user.id) + "`'s request to create cloudauthz config because of {}." + msg_template = f"Rejected user `{str(trans.user.id)}`'s request to create cloudauthz config because of {{}}." if not isinstance(payload, dict): raise ActionInputError('Invalid payload data type. The payload is expected to be a dictionary, but ' 'received data of type `{}`.'.format(str(type(payload)))) @@ -172,7 +172,7 @@ class CloudAuthzController(BaseGalaxyAPIController): :return The cloudauthz record marked as deleted, serialized as a JSON object. """ - msg_template = "Rejected user `" + str(trans.user.id) + "`'s request to delete cloudauthz config because of {}." + msg_template = f"Rejected user `{str(trans.user.id)}`'s request to delete cloudauthz config because of {{}}." try: authz_id = self.decode_id(encoded_authz_id) except MalformedId as e: @@ -236,7 +236,7 @@ class CloudAuthzController(BaseGalaxyAPIController): """ - msg_template = "Rejected user `" + str(trans.user.id) + "`'s request to delete cloudauthz config because of {}." + msg_template = f"Rejected user `{str(trans.user.id)}`'s request to delete cloudauthz config because of {{}}." try: authz_id = self.decode_id(encoded_authz_id) except MalformedId as e: diff --git a/lib/galaxy/webapps/galaxy/api/history_contents.py b/lib/galaxy/webapps/galaxy/api/history_contents.py index 57bc80a5e1b..62dd596d87f 100644 --- a/lib/galaxy/webapps/galaxy/api/history_contents.py +++ b/lib/galaxy/webapps/galaxy/api/history_contents.py @@ -1023,7 +1023,7 @@ class HistoryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, # ---- for composite files, we use id and name for a directory and, inside that, ... if self.hda_manager.is_composite(content): # ...save the 'main' composite file (gen. html) - paths_and_files.append((content.file_name, os.path.join(archive_path, content.name + '.html'))) + paths_and_files.append((content.file_name, os.path.join(archive_path, f"{content.name}.html"))) for extra_file in self.hda_manager.extra_files(content): extra_file_basename = os.path.basename(extra_file) archive_extra_file_path = os.path.join(archive_path, extra_file_basename) @@ -1033,8 +1033,8 @@ class HistoryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, # ---- for single files, we add the true extension to id and name and store that single filename else: # some dataset names can contain their original file extensions, don't repeat - if not archive_path.endswith('.' + content.extension): - archive_path += '.' + content.extension + if not archive_path.endswith(f".{content.extension}"): + archive_path += f".{content.extension}" paths_and_files.append((content.file_name, archive_path)) # filter the contents that contain datasets using any filters possible from index above and map the datasets diff --git a/lib/galaxy/webapps/galaxy/api/library_contents.py b/lib/galaxy/webapps/galaxy/api/library_contents.py index d0d25f135ab..355dbb8df95 100644 --- a/lib/galaxy/webapps/galaxy/api/library_contents.py +++ b/lib/galaxy/webapps/galaxy/api/library_contents.py @@ -77,7 +77,7 @@ class LibraryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, if not admin: can_access, folder_ids = trans.app.security_agent.check_folder_contents(trans.user, current_user_roles, subfolder) if (admin or can_access) and not subfolder.deleted: - subfolder.api_path = folder.api_path + '/' + subfolder.name + subfolder.api_path = f"{folder.api_path}/{subfolder.name}" subfolder.api_type = 'folder' rval.append(subfolder) rval.extend(traverse(subfolder)) @@ -88,7 +88,7 @@ class LibraryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, ld.library_dataset_dataset_association.dataset ) if (admin or can_access) and not ld.deleted: - ld.api_path = folder.api_path + '/' + ld.name + ld.api_path = f"{folder.api_path}/{ld.name}" ld.api_type = 'file' rval.append(ld) return rval @@ -101,10 +101,10 @@ class LibraryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, except NoResultFound: raise exceptions.RequestParameterInvalidException('No library found with the id provided.') except Exception as e: - raise exceptions.InternalServerError('Error loading from the database.' + util.unicodify(e)) + raise exceptions.InternalServerError(f"Error loading from the database.{util.unicodify(e)}") if not (trans.user_is_admin or trans.app.security_agent.can_access_library(current_user_roles, library)): raise exceptions.RequestParameterInvalidException('No library found with the id provided.') - encoded_id = 'F' + trans.security.encode_id(library.root_folder.id) + encoded_id = f"F{trans.security.encode_id(library.root_folder.id)}" # appending root folder rval.append(dict(id=encoded_id, type='folder', @@ -115,7 +115,7 @@ class LibraryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, for content in traverse(library.root_folder): encoded_id = trans.security.encode_id(content.id) if content.api_type == 'folder': - encoded_id = 'F' + encoded_id + encoded_id = f"F{encoded_id}" rval.append(dict(id=encoded_id, type=content.api_type, name=content.api_path, @@ -146,16 +146,16 @@ class LibraryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, if class_name == 'LibraryFolder': content = self.get_library_folder(trans, content_id, check_ownership=False, check_accessible=True) rval = content.to_dict(view='element', value_mapper={'id': trans.security.encode_id}) - rval['id'] = 'F' + str(rval['id']) + rval['id'] = f"F{str(rval['id'])}" if rval['parent_id'] is not None: # This can happen for root folders. - rval['parent_id'] = 'F' + str(trans.security.encode_id(rval['parent_id'])) + rval['parent_id'] = f"F{str(trans.security.encode_id(rval['parent_id']))}" rval['parent_library_id'] = trans.security.encode_id(rval['parent_library_id']) else: content = self.get_library_dataset(trans, content_id, check_ownership=False, check_accessible=True) rval = content.to_dict(view='element') rval['id'] = trans.security.encode_id(rval['id']) rval['ldda_id'] = trans.security.encode_id(rval['ldda_id']) - rval['folder_id'] = 'F' + str(trans.security.encode_id(rval['folder_id'])) + rval['folder_id'] = f"F{str(trans.security.encode_id(rval['folder_id']))}" rval['parent_library_id'] = trans.security.encode_id(rval['parent_library_id']) tag_manager = tags.GalaxyTagHandler(trans.sa_session) @@ -288,7 +288,7 @@ class LibraryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, v = v.library_dataset encoded_id = trans.security.encode_id(v.id) if create_type == 'folder': - encoded_id = 'F' + encoded_id + encoded_id = f"F{encoded_id}" rval.append(dict(id=encoded_id, name=v.name, url=url_for('library_content', library_id=library_id, id=encoded_id))) @@ -368,7 +368,7 @@ class LibraryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems, """ if isinstance(meta, dict): for a in meta: - yield from self._scan_json_block(meta[a], prefix + "/" + a) + yield from self._scan_json_block(meta[a], f"{prefix}/{a}") elif isinstance(meta, list): for i, a in enumerate(meta): yield from self._scan_json_block(a, prefix + "[%d]" % (i)) diff --git a/lib/galaxy/webapps/galaxy/api/library_datasets.py b/lib/galaxy/webapps/galaxy/api/library_datasets.py index e99b1ab5581..108a28dbbec 100644 --- a/lib/galaxy/webapps/galaxy/api/library_datasets.py +++ b/lib/galaxy/webapps/galaxy/api/library_datasets.py @@ -94,7 +94,7 @@ class LibraryDatasetsController(BaseGalaxyAPIController, UsesVisualizationMixin, try: ldda = self.get_library_dataset_dataset_association(trans, id=encoded_ldda_id, check_ownership=False, check_accessible=False) except Exception as e: - raise exceptions.ObjectNotFound('Requested version of library dataset was not found.' + util.unicodify(e)) + raise exceptions.ObjectNotFound(f"Requested version of library dataset was not found.{util.unicodify(e)}") if ldda not in library_dataset.expired_datasets: raise exceptions.ObjectNotFound('Given library dataset does not have the requested version.') @@ -268,7 +268,7 @@ class LibraryDatasetsController(BaseGalaxyAPIController, UsesVisualizationMixin, else: invalid_access_roles_ids.append(role_id) if len(invalid_access_roles_ids) > 0: - log.warning("The following roles could not be added to the dataset access permission: " + str(invalid_access_roles_ids)) + log.warning(f"The following roles could not be added to the dataset access permission: {str(invalid_access_roles_ids)}") access_permission = dict(access=valid_access_roles) trans.app.security_agent.set_dataset_permission(dataset, access_permission) @@ -284,7 +284,7 @@ class LibraryDatasetsController(BaseGalaxyAPIController, UsesVisualizationMixin, else: invalid_manage_roles_ids.append(role_id) if len(invalid_manage_roles_ids) > 0: - log.warning("The following roles could not be added to the dataset manage permission: " + str(invalid_manage_roles_ids)) + log.warning(f"The following roles could not be added to the dataset manage permission: {str(invalid_manage_roles_ids)}") manage_permission = {trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS: valid_manage_roles} trans.app.security_agent.set_dataset_permission(dataset, manage_permission) @@ -299,7 +299,7 @@ class LibraryDatasetsController(BaseGalaxyAPIController, UsesVisualizationMixin, else: invalid_modify_roles_ids.append(role_id) if len(invalid_modify_roles_ids) > 0: - log.warning("The following roles could not be added to the dataset modify permission: " + str(invalid_modify_roles_ids)) + log.warning(f"The following roles could not be added to the dataset modify permission: {str(invalid_modify_roles_ids)}") modify_permission = {trans.app.security_agent.permitted_actions.LIBRARY_MODIFY: valid_modify_roles} trans.app.security_agent.set_library_item_permission(library_dataset, modify_permission) return self._get_current_roles(trans, library_dataset) @@ -339,7 +339,7 @@ class LibraryDatasetsController(BaseGalaxyAPIController, UsesVisualizationMixin, rval['file_size'] = nice_size rval['update_time'] = library_dataset.update_time.strftime("%Y-%m-%d %I:%M %p") rval['deleted'] = library_dataset.deleted - rval['folder_id'] = 'F' + rval['folder_id'] + rval['folder_id'] = f"F{rval['folder_id']}" return rval @expose_api @@ -565,7 +565,7 @@ class LibraryDatasetsController(BaseGalaxyAPIController, UsesVisualizationMixin, except HTTPInternalServerError: raise exceptions.InternalServerError('Internal error.') except Exception as e: - raise exceptions.InternalServerError('Unknown error.' + util.unicodify(e)) + raise exceptions.InternalServerError(f"Unknown error.{util.unicodify(e)}") folders_to_download = kwd.get('folder_ids%5B%5D', None) if folders_to_download is None: @@ -647,7 +647,7 @@ class LibraryDatasetsController(BaseGalaxyAPIController, UsesVisualizationMixin, raise exceptions.ObjectNotFound("Requested dataset not found. ") except Exception as e: log.exception("Unable to add composite parent %s to temporary library download archive", ldda.dataset.file_name) - raise exceptions.InternalServerError("Unable to add composite parent to temporary library download archive. " + util.unicodify(e)) + raise exceptions.InternalServerError(f"Unable to add composite parent to temporary library download archive. {util.unicodify(e)}") flist = glob.glob(os.path.join(ldda.dataset.extra_files_path, '*.*')) # glob returns full paths for fpath in flist: @@ -664,7 +664,7 @@ class LibraryDatasetsController(BaseGalaxyAPIController, UsesVisualizationMixin, raise exceptions.ObjectNotFound("Requested dataset not found.") except Exception as e: log.exception("Unable to add %s to temporary library download archive %s", fname, outfname) - raise exceptions.InternalServerError("Unable to add dataset to temporary library download archive . " + util.unicodify(e)) + raise exceptions.InternalServerError(f"Unable to add dataset to temporary library download archive . {util.unicodify(e)}") else: try: archive.write(ldda.dataset.file_name, path) @@ -676,7 +676,7 @@ class LibraryDatasetsController(BaseGalaxyAPIController, UsesVisualizationMixin, raise exceptions.ObjectNotFound("Requested dataset not found.") except Exception as e: log.exception("Unable to add %s to temporary library download archive %s", ldda.dataset.file_name, outfname) - raise exceptions.InternalServerError("Unknown error. " + util.unicodify(e)) + raise exceptions.InternalServerError(f"Unknown error. {util.unicodify(e)}") trans.response.headers.update(archive.get_headers()) return archive.response() elif archive_format == 'uncompressed': diff --git a/lib/galaxy/webapps/galaxy/api/users.py b/lib/galaxy/webapps/galaxy/api/users.py index b240563ee2e..25233326d73 100644 --- a/lib/galaxy/webapps/galaxy/api/users.py +++ b/lib/galaxy/webapps/galaxy/api/users.py @@ -307,7 +307,7 @@ class UserAPIController(BaseGalaxyAPIController, UsesTagsMixin, BaseUIController input['help'] = f"{help} {required}" else: input['help'] = required - field = item + '|' + input['name'] + field = f"{item}|{input['name']}" for data_item in user.extra_preferences: if field in data_item: input['value'] = user.extra_preferences[data_item] @@ -421,7 +421,7 @@ class UserAPIController(BaseGalaxyAPIController, UsesTagsMixin, BaseUIController # Update user email and user's private role name which must match private_role = trans.app.security_agent.get_private_user_role(user) private_role.name = email - private_role.description = 'Private role for ' + email + private_role.description = f"Private role for {email}" user.email = email trans.sa_session.add(user) trans.sa_session.add(private_role) @@ -462,7 +462,7 @@ class UserAPIController(BaseGalaxyAPIController, UsesTagsMixin, BaseUIController extra_pref_keys = self._get_extra_user_preferences(trans) if extra_pref_keys is not None: for key in extra_pref_keys: - key_prefix = key + '|' + key_prefix = f"{key}|" for item in payload: if item.startswith(key_prefix): # Show error message if the required field is empty @@ -670,7 +670,7 @@ class UserAPIController(BaseGalaxyAPIController, UsesTagsMixin, BaseUIController new_filters = [] for prefixed_name in payload: if payload.get(prefixed_name) == 'true' and prefixed_name.startswith(filter_type): - prefix = filter_type + '|' + prefix = f"{filter_type}|" new_filters.append(prefixed_name[len(prefix):]) user.preferences[filter_type] = ','.join(new_filters) trans.sa_session.add(user) diff --git a/lib/galaxy/webapps/galaxy/api/workflows.py b/lib/galaxy/webapps/galaxy/api/workflows.py index 4614d07d88c..bb86e56b533 100644 --- a/lib/galaxy/webapps/galaxy/api/workflows.py +++ b/lib/galaxy/webapps/galaxy/api/workflows.py @@ -1431,7 +1431,7 @@ class WorkflowsAPIController(BaseGalaxyAPIController, UsesStoredWorkflowMixin, U install_options = workflow_create_options.install_options for k in tools: item = tools[k] - tool_shed_url = 'https://' + item['tool_shed'] + '/' + tool_shed_url = f"https://{item['tool_shed']}/" name = item['name'] owner = item['owner'] changeset_revision = item['changeset_revision'] diff --git a/lib/galaxy/webapps/galaxy/buildapp.py b/lib/galaxy/webapps/galaxy/buildapp.py index aab62951408..7fbe248c66d 100644 --- a/lib/galaxy/webapps/galaxy/buildapp.py +++ b/lib/galaxy/webapps/galaxy/buildapp.py @@ -683,21 +683,21 @@ def populate_api_routes(webapp, app): conditions = conditions or dict(method=['GET']) webapp.mapper.connect( f'workflow_invocation_{endpoint_name}', - '/api/workflows/{workflow_id}/invocations/{invocation_id}' + endpoint_suffix, + f"/api/workflows/{{workflow_id}}/invocations/{{invocation_id}}{endpoint_suffix}", controller='workflows', action=action, conditions=conditions, ) webapp.mapper.connect( f'workflow_usage_{endpoint_name}', - '/api/workflows/{workflow_id}/usage/{invocation_id}' + endpoint_suffix, + f"/api/workflows/{{workflow_id}}/usage/{{invocation_id}}{endpoint_suffix}", controller='workflows', action=action, conditions=conditions, ) webapp.mapper.connect( f'invocation_{endpoint_name}', - '/api/invocations/{invocation_id}' + endpoint_suffix, + f"/api/invocations/{{invocation_id}}{endpoint_suffix}", controller='workflows', action=action, conditions=conditions, diff --git a/lib/galaxy/webapps/galaxy/controllers/_create_history_template.py b/lib/galaxy/webapps/galaxy/controllers/_create_history_template.py index 9be9c2c77d5..e9d83587aec 100644 --- a/lib/galaxy/webapps/galaxy/controllers/_create_history_template.py +++ b/lib/galaxy/webapps/galaxy/controllers/_create_history_template.py @@ -32,7 +32,7 @@ def render_item_hda(trans, hda, children): elif hda.copied_from_library_dataset_dataset_association: template = render_hda_copied_from_library(trans, hda, children) else: - template = '
    ' + template = f"
    " return template @@ -43,16 +43,16 @@ def render_hda_copied_from_history(trans, hda, children): template = '' id = trans.security.encode_id(hda.id) history_id = trans.security.encode_id(hda.copied_from_history_dataset_association.history_id) - url = url_for('/histories/view?id=' + history_id) + url = url_for(f"/histories/view?id={history_id}") template = '
    ' template += ' Copied from history dataset: ' - template += '' + hda.copied_from_history_dataset_association.name + '' + template += f"{hda.copied_from_history_dataset_association.name}" template += '
    ' template += 'History: ' template += '' - template += '' + hda.copied_from_history_dataset_association.history.name + '' + template += f"{hda.copied_from_history_dataset_association.history.name}" template += '
    ' - template += '
    ' + template += f"
    " return template @@ -63,19 +63,19 @@ def render_hda_copied_from_library(trans, hda, children): template = '' id = trans.security.encode_id(hda.id) folder = hda.copied_from_library_dataset_dataset_association.library_dataset.folder - folder_id = 'F' + trans.security.encode_id(folder.id) - url = url_for('/library/list#folders/' + folder_id) + folder_id = f"F{trans.security.encode_id(folder.id)}" + url = url_for(f"/library/list#folders/{folder_id}") template = '
    ' template += '
    ' template += '
    ' template += 'Copied from library dataset:' - template += '' + hda.copied_from_library_dataset_dataset_association.name + '' + template += f"{hda.copied_from_library_dataset_dataset_association.name}" template += '
    ' template += '
    ' template += 'Library: ' template += '' - template += '' + folder.name + '
    ' - template += '
    ' + template += f"{folder.name}" + template += f"
    " return template @@ -97,8 +97,8 @@ def render_item_job(trans, job, children): params_object = job.get_param_values(trans.app, ignore_errors=True) except Exception: pass - template += '
    ' + tool_name + '' - template += ' - ' + tool_desc + '
    ' + template += f"
    {tool_name}" + template += f" - {tool_desc}
    " if tool and params_object: template += '' template += inputs_recursive(trans, tool.inputs, params_object, depth=1) @@ -119,7 +119,7 @@ def render_item_wf(trans, wf, children): """ Render a workflow and its children (jobs) """ - template = '
    ' + wf.workflow.name + '' + template = f"
    {wf.workflow.name}" template += '- Workflow
    ' for e, c in reversed(children): template += render_item(trans, e, c) @@ -131,7 +131,7 @@ def inputs_recursive_indent(text, depth): """ Add an indentation depending on the depth in a
    """ - return '' + return f"" def inputs_recursive(trans, input_params, param_values, depth=1, upgrade_messages=None): @@ -162,7 +162,7 @@ def inputs_recursive(trans, input_params, param_values, depth=1, upgrade_message if is_valid: tool_parameter_template += '' tool_parameter_template += inputs_recursive_indent(text=input.test_param.label, depth=depth) - tool_parameter_template += '' + tool_parameter_template += f"" inputs_recursive(trans, input.cases[current_case].inputs, param_values[input.name], depth=depth + 1, upgrade_messages=upgrade_messages.get(input.name)) else: tool_parameter_template += '' @@ -171,7 +171,7 @@ def inputs_recursive(trans, input_params, param_values, depth=1, upgrade_message elif input.type == "upload_dataset": tool_parameter_template += '' tool_parameter_template += inputs_recursive_indent(text=input.group_title(param_values), depth=depth) - tool_parameter_template += '' + tool_parameter_template += f"" elif input.type == "data": tool_parameter_template += '' tool_parameter_template += inputs_recursive_indent(text=input.label, depth=depth) @@ -183,17 +183,17 @@ def inputs_recursive(trans, input_params, param_values, depth=1, upgrade_message hda = element encoded_id = trans.security.encode_id(hda.id) dataset_info_url = url_for(controller="dataset", action="show_params", dataset_id=encoded_id) - tool_parameter_template += '' + str(hda.hid) + ':' + hda.name + '' + tool_parameter_template += f"{str(hda.hid)}:{hda.name}" else: - tool_parameter_template += str(element.hid) + ':' + element.name + tool_parameter_template += f"{str(element.hid)}:{element.name}" tool_parameter_template += '' elif input.visible: label = input.label if (hasattr(input, "label") and input.label) else input.name tool_parameter_template += '' tool_parameter_template += inputs_recursive_indent(text=label, depth=depth) - tool_parameter_template += '' - tool_parameter_template += '' + tool_parameter_template += f"" + tool_parameter_template += f"" else: tool_parameter_template += '' if input.type == "conditional": diff --git a/lib/galaxy/webapps/galaxy/controllers/admin.py b/lib/galaxy/webapps/galaxy/controllers/admin.py index d6d8fa6b221..d1eb6168f87 100644 --- a/lib/galaxy/webapps/galaxy/controllers/admin.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin.py @@ -676,7 +676,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP all_groups.append((group.name, trans.security.encode_id(group.id))) default_options = [('No', 'no')] for type_ in trans.app.model.DefaultQuotaAssociation.types: - default_options.append(('Yes, ' + type_, type_)) + default_options.append((f"Yes, {type_}", type_)) return {'title': 'Create Quota', 'inputs': [ { @@ -809,7 +809,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP default_value = quota.default[0].type if quota.default else 'no' default_options = [('No', 'no')] for typ in trans.app.model.DefaultQuotaAssociation.types.__members__.values(): - default_options.append(('Yes, ' + typ, typ)) + default_options.append((f"Yes, {typ}", typ)) return { 'title': 'Set quota default for \'%s\'' % util.sanitize_text(quota.name), 'inputs': [{ diff --git a/lib/galaxy/webapps/galaxy/controllers/async.py b/lib/galaxy/webapps/galaxy/controllers/async.py index dfc68373f1d..789abdd564b 100644 --- a/lib/galaxy/webapps/galaxy/controllers/async.py +++ b/lib/galaxy/webapps/galaxy/controllers/async.py @@ -70,7 +70,7 @@ class ASync(BaseUIController): data.state = data.blurb = data.states.RUNNING log.debug(f'executing tool {tool.id}') trans.log_event(f'Async executing tool {tool.id}', tool_id=tool.id) - galaxy_url = trans.request.base + f'/async/{tool_id}/{data.id}/{key}' + galaxy_url = f"{trans.request.base}/async/{tool_id}/{data.id}/{key}" galaxy_url = params.get("GALAXY_URL", galaxy_url) params = dict(URL=URL, GALAXY_URL=galaxy_url, name=data.name, info=data.info, dbkey=data.dbkey, data_type=data.ext) @@ -154,7 +154,7 @@ class ASync(BaseUIController): try: key = hmac_new(trans.app.config.tool_secret, "%d:%d" % (data.id, data.history_id)) - galaxy_url = trans.request.base + f'/async/{tool_id}/{data.id}/{key}' + galaxy_url = f"{trans.request.base}/async/{tool_id}/{data.id}/{key}" params.update({'GALAXY_URL': galaxy_url}) params.update({'data_id': data.id}) diff --git a/lib/galaxy/webapps/galaxy/controllers/authnz.py b/lib/galaxy/webapps/galaxy/controllers/authnz.py index c74b338a038..c7a8abe007f 100644 --- a/lib/galaxy/webapps/galaxy/controllers/authnz.py +++ b/lib/galaxy/webapps/galaxy/controllers/authnz.py @@ -125,7 +125,7 @@ class OIDC(JSAppLauncher): trans=trans, login_redirect_url=url_for('/')) except exceptions.AuthenticationFailed as e: - return trans.response.send_redirect(trans.request.base + url_for('/') + 'root/login?message=' + (str(e) or "Duplicate Email")) + return trans.response.send_redirect(f"{trans.request.base + url_for('/')}root/login?message={str(e) or 'Duplicate Email'}") if success is False: return trans.show_error_message(message) @@ -160,7 +160,7 @@ class OIDC(JSAppLauncher): @web.json @web.expose def logout(self, trans, provider, **kwargs): - post_logout_redirect_url = trans.request.base + url_for('/') + 'root/login?is_logout_redirect=true' + post_logout_redirect_url = f"{trans.request.base + url_for('/')}root/login?is_logout_redirect=true" success, message, redirect_uri = trans.app.authnz_manager.logout(provider, trans, post_logout_redirect_url=post_logout_redirect_url) diff --git a/lib/galaxy/webapps/galaxy/controllers/dataset.py b/lib/galaxy/webapps/galaxy/controllers/dataset.py index 4017de1ad5e..d14a47aa2ef 100644 --- a/lib/galaxy/webapps/galaxy/controllers/dataset.py +++ b/lib/galaxy/webapps/galaxy/controllers/dataset.py @@ -283,7 +283,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE in_roles[action.action] = [trans.security.encode_id(role.id) for role in roles] for index, action in trans.app.model.Dataset.permitted_actions.items(): if action == trans.app.security_agent.permitted_actions.DATASET_ACCESS: - help_text = action.description + '
    NOTE: Users must have every role associated with this dataset in order to access it.' + help_text = f"{action.description}
    NOTE: Users must have every role associated with this dataset in order to access it." else: help_text = action.description permission_inputs.append({ @@ -1003,10 +1003,10 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE source_contents.sort(key=lambda content: content.hid) for content in source_contents: if content is None: - error_msg = error_msg + "You tried to copy a dataset that does not exist. " + error_msg = f"{error_msg}You tried to copy a dataset that does not exist. " invalid_contents += 1 elif content.history != history: - error_msg = error_msg + "You tried to copy a dataset which is not in your current history. " + error_msg = f"{error_msg}You tried to copy a dataset which is not in your current history. " invalid_contents += 1 else: for hist in target_histories: @@ -1066,13 +1066,13 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE data = self.hda_manager.error_if_uploading(data) if data is None: - error_msg = error_msg + "You tried to copy a dataset that does not exist or that you do not have access to. " + error_msg = f"{error_msg}You tried to copy a dataset that does not exist or that you do not have access to. " invalid_datasets += 1 else: for hist in target_histories: dataset_copy = data.copy() if imported: - dataset_copy.name = "imported: " + dataset_copy.name + dataset_copy.name = f"imported: {dataset_copy.name}" hist.add_dataset(dataset_copy) trans.sa_session.flush() num_datasets_copied = len(dataset_ids) - invalid_datasets diff --git a/lib/galaxy/webapps/galaxy/controllers/history.py b/lib/galaxy/webapps/galaxy/controllers/history.py index ebfc530981b..d363d2790db 100644 --- a/lib/galaxy/webapps/galaxy/controllers/history.py +++ b/lib/galaxy/webapps/galaxy/controllers/history.py @@ -1179,7 +1179,7 @@ class HistoryController(BaseUIController, SharableMixin, UsesAnnotations, UsesIt trans.sa_session.add(h) trans.sa_session.flush() trans.log_event(f'History renamed: id: {str(h.id)}, renamed to: {new_name}') - messages.append('History \'' + cur_name + '\' renamed to \'' + new_name + '\'.') + messages.append(f"History '{cur_name}' renamed to '{new_name}'.") message = sanitize_text(' '.join(messages)) if messages else 'History names remain unchanged.' return {'message': message, 'status': 'success'} diff --git a/lib/galaxy/webapps/galaxy/controllers/page.py b/lib/galaxy/webapps/galaxy/controllers/page.py index d39ce3d2fa3..1754e4be236 100644 --- a/lib/galaxy/webapps/galaxy/controllers/page.py +++ b/lib/galaxy/webapps/galaxy/controllers/page.py @@ -338,8 +338,8 @@ class PageController(BaseUIController, SharableMixin, content_hide = True if "invocation_id" in kwd: invocation_id = kwd.get("invocation_id") - form_title = form_title + " from Invocation Report" - slug = "invocation-report-" + invocation_id + form_title = f"{form_title} from Invocation Report" + slug = f"invocation-report-{invocation_id}" invocation_report = self.workflow_manager.get_invocation_report(trans, invocation_id) title = invocation_report.get("title") content = invocation_report.get("markdown") diff --git a/lib/galaxy/webapps/galaxy/controllers/root.py b/lib/galaxy/webapps/galaxy/controllers/root.py index 81a89d156bc..22174cd8985 100644 --- a/lib/galaxy/webapps/galaxy/controllers/root.py +++ b/lib/galaxy/webapps/galaxy/controllers/root.py @@ -189,7 +189,7 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): fStat = os.stat(data.file_name) trans.response.headers['Content-Length'] = str(fStat.st_size) if toext[0:1] != ".": - toext = "." + toext + toext = f".{toext}" fname = data.name fname = ''.join(c in FILENAME_VALID_CHARS and c or '_' for c in fname)[0:150] trans.response.headers["Content-Disposition"] = f'attachment; filename="GalaxyHistoryItem-{data.hid}-[{fname}]{toext}"' @@ -264,7 +264,7 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): if import_history.user_id == user.id: return trans.show_error_message("You cannot import your own history.") new_history = import_history.copy(target_user=trans.user) - new_history.name = "imported: " + new_history.name + new_history.name = f"imported: {new_history.name}" new_history.user_id = user.id galaxy_session = trans.get_galaxy_session() try: @@ -284,7 +284,7 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): to begin.""".format(new_history.name, web.url_for('/'))) elif not user_history.datasets or confirm: new_history = import_history.copy() - new_history.name = "imported: " + new_history.name + new_history.name = f"imported: {new_history.name}" new_history.user_id = None galaxy_session = trans.get_galaxy_session() try: @@ -351,7 +351,7 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): data.set_peek() trans.sa_session.flush() trans.log_event("Added dataset %d to history %d" % (data.id, trans.history.id)) - return trans.show_ok_message("Dataset " + str(data.hid) + " added to history " + str(history_id) + ".") + return trans.show_ok_message(f"Dataset {str(data.hid)} added to history {str(history_id)}.") except Exception as e: msg = f"Failed to add dataset to history: {unicodify(e)}" log.error(msg) diff --git a/lib/galaxy/webapps/galaxy/controllers/tag.py b/lib/galaxy/webapps/galaxy/controllers/tag.py index f10e38cd6b0..5db26c4c4a0 100644 --- a/lib/galaxy/webapps/galaxy/controllers/tag.py +++ b/lib/galaxy/webapps/galaxy/controllers/tag.py @@ -109,7 +109,7 @@ class TagsController(BaseUIController, UsesTagsMixin): # Build select statement. cols_to_select = [item_tag_assoc_class.table.c.tag_id, func.count('*')] from_obj = item_tag_assoc_class.table.join(item_class.table).join(trans.app.model.Tag.table) - where_clause = and_(trans.app.model.Tag.table.c.name.like(q + "%"), + where_clause = and_(trans.app.model.Tag.table.c.name.like(f"{q}%"), item_tag_assoc_class.table.c.user_id == user.id) order_by = [func.count("*").desc()] group_by = item_tag_assoc_class.table.c.tag_id @@ -131,7 +131,7 @@ class TagsController(BaseUIController, UsesTagsMixin): # Add tag to autocomplete data. Use the most frequent name that user # has employed for the tag. tag_names = self._get_usernames_for_tag(trans, trans.user, tag, item_class, item_tag_assoc_class) - ac_data += tag_names[0] + "|" + tag_names[0] + "\n" + ac_data += f"{tag_names[0]}|{tag_names[0]}\n" return ac_data def _get_tag_autocomplete_values(self, trans, q, limit, timestamp, user=None, item=None, item_class=None): @@ -157,7 +157,7 @@ class TagsController(BaseUIController, UsesTagsMixin): from_obj = item_tag_assoc_class.table.join(item_class.table).join(trans.app.model.Tag.table) where_clause = and_(item_tag_assoc_class.table.c.user_id == user.id, trans.app.model.Tag.table.c.id == tag.id, - item_tag_assoc_class.table.c.value.like(tag_value + "%")) + item_tag_assoc_class.table.c.value.like(f"{tag_value}%")) order_by = [func.count("*").desc(), item_tag_assoc_class.table.c.value] group_by = item_tag_assoc_class.table.c.value # Do query and get result set. @@ -172,7 +172,7 @@ class TagsController(BaseUIController, UsesTagsMixin): ac_data = f"#Header|Your Values for '{tag_name}'\n" tag_uname = self._get_usernames_for_tag(trans, trans.user, tag, item_class, item_tag_assoc_class)[0] for row in result_set: - ac_data += tag_uname + ":" + row[0] + "|" + row[0] + "\n" + ac_data += f"{tag_uname}:{row[0]}|{row[0]}\n" return ac_data def _get_usernames_for_tag(self, trans, user, tag, item_class, item_tag_assoc_class): diff --git a/lib/galaxy/webapps/galaxy/controllers/visualization.py b/lib/galaxy/webapps/galaxy/controllers/visualization.py index 44aea3e5515..9b4d56dd6b8 100644 --- a/lib/galaxy/webapps/galaxy/controllers/visualization.py +++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py @@ -402,7 +402,7 @@ class VisualizationController(BaseUIController, SharableMixin, UsesVisualization # Create imported visualization via copy. # TODO: need to handle custom db keys. - imported_visualization = visualization.copy(user=trans.user, title="imported: " + visualization.title) + imported_visualization = visualization.copy(user=trans.user, title=f"imported: {visualization.title}") # Persist session = trans.sa_session diff --git a/lib/galaxy/webapps/galaxy/controllers/workflow.py b/lib/galaxy/webapps/galaxy/controllers/workflow.py index 390c408a512..80870f8d1c0 100644 --- a/lib/galaxy/webapps/galaxy/controllers/workflow.py +++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py @@ -205,7 +205,7 @@ class WorkflowController(BaseUIController, SharableMixin, UsesStoredWorkflowMixi Render workflow main page (management of existing workflows) """ # Take care of proxy prefix in url as well - redirect_url = url_for('/') + 'workflow' + redirect_url = f"{url_for('/')}workflow" return trans.response.send_redirect(redirect_url) @web.expose @@ -539,7 +539,7 @@ class WorkflowController(BaseUIController, SharableMixin, UsesStoredWorkflowMixi # Display the management page message = f'Created new workflow with name: {escape(new_stored.name)}' trans.set_message(message) - return_url = url_for('/') + f'workflow?status=done&message={escape(message)}' + return_url = f"{url_for('/')}workflow?status=done&message={escape(message)}" trans.response.send_redirect(return_url) @web.legacy_expose_api @@ -644,7 +644,7 @@ class WorkflowController(BaseUIController, SharableMixin, UsesStoredWorkflowMixi # Display the management page message = f"Workflow deleted: {escape(stored.name)}" trans.set_message(message) - return trans.response.send_redirect(url_for('/') + f'workflow?status=done&message={escape(message)}') + return trans.response.send_redirect(f"{url_for('/')}workflow?status=done&message={escape(message)}") @web.expose @web.require_login("edit workflows") diff --git a/lib/galaxy/webapps/reports/buildapp.py b/lib/galaxy/webapps/reports/buildapp.py index 0ec39bf28e8..224b4de2f45 100644 --- a/lib/galaxy/webapps/reports/buildapp.py +++ b/lib/galaxy/webapps/reports/buildapp.py @@ -33,7 +33,7 @@ def add_ui_controllers(webapp, app): for fname in os.listdir(controller_dir): if not fname.startswith("_") and fname.endswith(".py"): name = fname[:-3] - module_name = "galaxy.webapps.reports.controllers." + name + module_name = f"galaxy.webapps.reports.controllers.{name}" module = __import__(module_name) for comp in module_name.split(".")[1:]: module = getattr(module, comp) diff --git a/lib/galaxy/webapps/reports/controllers/tools.py b/lib/galaxy/webapps/reports/controllers/tools.py index 159d5bfe3ea..492dd9ce1a8 100644 --- a/lib/galaxy/webapps/reports/controllers/tools.py +++ b/lib/galaxy/webapps/reports/controllers/tools.py @@ -49,14 +49,14 @@ class Tools(BaseUIController): if len(splited) == 2: returned = "%s %dH" % (splited[0], int(splited[1].split(':')[0])) if colored: - return '' + returned + '' + return f"{returned}" return returned else: splited = tuple([float(_) for _ in str(date).split(':')]) if splited[0]: returned = '%d h. %d min.' % splited[:2] if colored: - return '' + returned + '' + return f"{returned}" return returned if splited[1]: return "%d min. %d sec." % splited[1:3] @@ -331,13 +331,13 @@ class Tools(BaseUIController): if words.count(word) > 1: to_replace.append(word) for word in to_replace: - sentence = ("
    " + word) * 2 + sentence = f"
    {word}" * 2 count = 2 - while sentence + "
    " + word in new_key: - sentence += "
    " + word + while f"{sentence}
    {word}" in new_key: + sentence += f"
    {word}" count += 1 if sentence in new_key: - new_key = new_key.replace(sentence, '
    ' + word + " [this line in %d times]" % (count)) + new_key = new_key.replace(sentence, f"
    {word}{' [this line in %d times]' % count}") data[new_key] = counter[key] return trans.fill_template("/webapps/reports/tool_error_messages.mako", diff --git a/lib/galaxy/workflow/extract.py b/lib/galaxy/workflow/extract.py index a240731671f..1aacc814cf4 100644 --- a/lib/galaxy/workflow/extract.py +++ b/lib/galaxy/workflow/extract.py @@ -381,7 +381,7 @@ def __cleanup_param_values(inputs, values): # Cleanup the other deprecated crap associated with datasets # as well. Worse, for nested datasets all the metadata is # being pushed into the root. FIXME: MUST REMOVE SOON - key = prefix + key + "_" + key = f"{prefix + key}_" for k in root_values.keys(): if k not in root_input_keys and k.startswith(key): del root_values[k] diff --git a/lib/galaxy/workflow/modules.py b/lib/galaxy/workflow/modules.py index 81f8b8935ff..e57bed5f79c 100644 --- a/lib/galaxy/workflow/modules.py +++ b/lib/galaxy/workflow/modules.py @@ -1317,9 +1317,9 @@ class ToolModule(WorkflowModule): if old_tool_shed not in tool_id: # Only display the following warning if the tool comes from a different tool shed old_tool_shed_url = get_tool_shed_url_from_tool_shed_registry(trans.app, old_tool_shed) if not old_tool_shed_url: # a tool from a different tool_shed has been found, but the original tool shed has been deactivated - old_tool_shed_url = "http://" + old_tool_shed # let's just assume it's either http, or a http is forwarded to https. - old_url = old_tool_shed_url + f"/view/{module.tool.repository_owner}/{module.tool.repository_name}/" - new_url = module.tool.sharable_url + f'/{module.tool.changeset_revision}/' + old_tool_shed_url = f"http://{old_tool_shed}" # let's just assume it's either http, or a http is forwarded to https. + old_url = f"{old_tool_shed_url}/view/{module.tool.repository_owner}/{module.tool.repository_name}/" + new_url = f"{module.tool.sharable_url}/{module.tool.changeset_revision}/" new_tool_shed_url = new_url.split("/view")[0] message += f"The tool \'{module.tool.name}\', version {tool_version} by the owner {module.tool.repository_owner} installed from {old_tool_shed_url} is not available. " message += f"A derivation of this tool installed from {new_tool_shed_url} will be used instead. " diff --git a/lib/galaxy/workflow/trs_proxy.py b/lib/galaxy/workflow/trs_proxy.py index d1fa5fb85fb..6b4c396e9df 100644 --- a/lib/galaxy/workflow/trs_proxy.py +++ b/lib/galaxy/workflow/trs_proxy.py @@ -75,15 +75,15 @@ class TrsProxy: return self._get(trs_api_url) def get_versions(self, trs_server, tool_id, **kwd): - trs_api_url = self._get_tool_api_endpoint(trs_server, tool_id, **kwd) + "/versions" + trs_api_url = f"{self._get_tool_api_endpoint(trs_server, tool_id, **kwd)}/versions" return self._get(trs_api_url) def get_version(self, trs_server, tool_id, version_id, **kwd): - trs_api_url = self._get_tool_api_endpoint(trs_server, tool_id, **kwd) + "/versions/" + version_id + trs_api_url = f"{self._get_tool_api_endpoint(trs_server, tool_id, **kwd)}/versions/{version_id}" return self._get(trs_api_url) def get_version_descriptor(self, trs_server, tool_id, version_id, **kwd): - trs_api_url = self._get_tool_api_endpoint(trs_server, tool_id, **kwd) + "/versions/" + version_id + f"/{GA4GH_GALAXY_DESCRIPTOR}/descriptor" + trs_api_url = f"{self._get_tool_api_endpoint(trs_server, tool_id, **kwd)}/versions/{version_id}/{GA4GH_GALAXY_DESCRIPTOR}/descriptor" return self._get(trs_api_url)["content"] def _quote(self, tool_id, **kwd): @@ -110,10 +110,10 @@ class TrsProxy: def _get_api_endpoint(self, trs_server, **kwd): trs_url = self._server_dict[trs_server]["api_url"] - trs_api_endpoint = trs_url + "/" + "ga4gh/trs/v2/tools" + trs_api_endpoint = f"{trs_url}/ga4gh/trs/v2/tools" return trs_api_endpoint def _get_tool_api_endpoint(self, trs_server, tool_id, **kwd): tool_id = self._quote(tool_id, **kwd) - trs_api_url = self._get_api_endpoint(trs_server, **kwd) + "/" + tool_id + trs_api_url = f"{self._get_api_endpoint(trs_server, **kwd)}/{tool_id}" return trs_api_url diff --git a/lib/galaxy_test/api/test_api_batch.py b/lib/galaxy_test/api/test_api_batch.py index 5f192e4bbdf..cbdbd11139f 100644 --- a/lib/galaxy_test/api/test_api_batch.py +++ b/lib/galaxy_test/api/test_api_batch.py @@ -12,7 +12,7 @@ class ApiBatchTestCase(ApiTestCase): def _with_key(self, url, admin=False): sep = '&' if '?' in url else '?' - return url + sep + 'key=' + self._get_api_key(admin=admin) + return f"{url + sep}key={self._get_api_key(admin=admin)}" def _post_batch(self, batch): data = json.dumps({"batch": batch}) @@ -65,9 +65,9 @@ class ApiBatchTestCase(ApiTestCase): post_data = dict(name='test') create_response = self._post('histories', data=post_data).json() - history_url = '/api/histories/' + create_response['id'] - history_url_with_keys = history_url + '?v=dev&keys=size,non_ready_jobs' - contents_url_with_filters = history_url + '/contents?v=dev&q=deleted&qv=True' + history_url = f"/api/histories/{create_response['id']}" + history_url_with_keys = f"{history_url}?v=dev&keys=size,non_ready_jobs" + contents_url_with_filters = f"{history_url}/contents?v=dev&q=deleted&qv=True" batch = [ dict(url=self._with_key(history_url_with_keys)), dict(url=self._with_key(contents_url_with_filters)), diff --git a/lib/galaxy_test/api/test_dataset_collections.py b/lib/galaxy_test/api/test_dataset_collections.py index ec63e8a6e8f..1356dbf9bd7 100644 --- a/lib/galaxy_test/api/test_dataset_collections.py +++ b/lib/galaxy_test/api/test_dataset_collections.py @@ -347,12 +347,12 @@ class DatasetCollectionApiTestCase(ApiTestCase): hdca, root_contents_url = self._create_collection_contents_pair() # check limit - limited_contents = self._get(root_contents_url + '?limit=1').json() + limited_contents = self._get(f"{root_contents_url}?limit=1").json() assert len(limited_contents) == 1 assert limited_contents[0]['element_index'] == 0 # check offset - offset_contents = self._get(root_contents_url + '?offset=1').json() + offset_contents = self._get(f"{root_contents_url}?offset=1").json() assert len(offset_contents) == 1 assert offset_contents[0]['element_index'] == 1 diff --git a/lib/galaxy_test/api/test_tools.py b/lib/galaxy_test/api/test_tools.py index bc3ea2c1abe..d09df663f74 100644 --- a/lib/galaxy_test/api/test_tools.py +++ b/lib/galaxy_test/api/test_tools.py @@ -720,7 +720,7 @@ class ToolsTestCase(ApiTestCase, TestsTools): self.assertEqual(len(outputs), 1) output1 = outputs[0] output1_content = self.dataset_populator.get_history_dataset_content(history_id, dataset=output1) - self.assertEqual(output1_content.strip(), "Version " + version) + self.assertEqual(output1_content.strip(), f"Version {version}") @skip_without_tool("multiple_versions") @uses_test_history(require_new=False) diff --git a/lib/galaxy_test/base/populators.py b/lib/galaxy_test/base/populators.py index 601404508ad..29ad58e2392 100644 --- a/lib/galaxy_test/base/populators.py +++ b/lib/galaxy_test/base/populators.py @@ -1134,9 +1134,9 @@ class WorkflowPopulator(GalaxyInteractorHttpMixin, BaseWorkflowPopulator, Import ] for i in range(workflow_depth): - link = "cat_" + str(i) + "/out_file1" + link = f"cat_{str(i)}/out_file1" scale_workflow_steps.append( - {"tool_id": "cat", "state": {"input1": self._link(link)}, "label": "cat_" + str(i + 1)} + {"tool_id": "cat", "state": {"input1": self._link(link)}, "label": f"cat_{str(i + 1)}"} ) workflow_dict = { @@ -1156,8 +1156,8 @@ class WorkflowPopulator(GalaxyInteractorHttpMixin, BaseWorkflowPopulator, Import ] for i in range(workflow_depth): - link1 = "cat_" + str(i) + "#out_file1" - link2 = "cat_" + str(i) + "#out_file2" + link1 = f"cat_{str(i)}#out_file1" + link2 = f"cat_{str(i)}#out_file2" scale_workflow_steps.append( {"tool_id": "cat", "state": {"input1": self._link(link1), "input2": self._link(link2)}} ) @@ -1196,7 +1196,7 @@ class WorkflowPopulator(GalaxyInteractorHttpMixin, BaseWorkflowPopulator, Import @staticmethod def _link(link, output_name=None): if output_name is not None: - link = str(link) + "/" + output_name + link = f"{str(link)}/{output_name}" return {"$link": link} @@ -1762,7 +1762,7 @@ class GiHttpMixin: if route.startswith("/api/"): route = route[len("/api/"):] - return self._api_url() + "/" + route + return f"{self._api_url()}/{route}" class GiDatasetPopulator(BaseDatasetPopulator, GiHttpMixin): diff --git a/lib/galaxy_test/driver/driver_util.py b/lib/galaxy_test/driver/driver_util.py index 86156f838b9..c0c6cb71576 100644 --- a/lib/galaxy_test/driver/driver_util.py +++ b/lib/galaxy_test/driver/driver_util.py @@ -397,7 +397,7 @@ def database_conf(db_path, prefix="GALAXY", prefer_template_database=False): if do_template: database_template_parsed = urlparse(database_connection) template_name = database_template_parsed.path[1:] # drop / from /galaxy - actual_db = "gxtest" + ''.join(random.choice(string.ascii_uppercase) for _ in range(10)) + actual_db = f"gxtest{''.join(random.choice(string.ascii_uppercase) for _ in range(10))}" actual_database_parsed = database_template_parsed._replace(path=f"/{actual_db}") database_connection = actual_database_parsed.geturl() if not database_exists(database_connection): diff --git a/lib/galaxy_test/selenium/framework.py b/lib/galaxy_test/selenium/framework.py index 5a4d5dfda42..8c4348422ad 100644 --- a/lib/galaxy_test/selenium/framework.py +++ b/lib/galaxy_test/selenium/framework.py @@ -240,7 +240,7 @@ class TestWithSeleniumMixin(GalaxyTestSeleniumContext, UsesApiTestCaseMixin): try: self.setup_with_driver() except Exception: - dump_test_information(self, self.__class__.__name__ + "_setup") + dump_test_information(self, f"{self.__class__.__name__}_setup") raise def setup_with_driver(self): @@ -544,7 +544,7 @@ class SeleniumSessionGetPostMixin: def _get(self, route, data=None, headers=None, admin=False) -> Response: data = data or {} - full_url = self.selenium_context.build_url("api/" + route, for_selenium=False) + full_url = self.selenium_context.build_url(f"api/{route}", for_selenium=False) cookies = None if admin: full_url = f"{full_url}?key={self._mixin_admin_api_key}" @@ -554,7 +554,7 @@ class SeleniumSessionGetPostMixin: return response def _post(self, route, data=None, files=None, headers=None, admin=False, json: bool = False) -> Response: - full_url = self.selenium_context.build_url("api/" + route, for_selenium=False) + full_url = self.selenium_context.build_url(f"api/{route}", for_selenium=False) if data is None: data = {} @@ -573,7 +573,7 @@ class SeleniumSessionGetPostMixin: def _delete(self, route, data=None, headers=None, admin=False) -> Response: data = data or {} - full_url = self.selenium_context.build_url("api/" + route, for_selenium=False) + full_url = self.selenium_context.build_url(f"api/{route}", for_selenium=False) cookies = None if admin: full_url = f"{full_url}?key={self._mixin_admin_api_key}" @@ -584,7 +584,7 @@ class SeleniumSessionGetPostMixin: def _put(self, route, data=None, headers=None, admin=False) -> Response: data = data or {} - full_url = self.selenium_context.build_url("api/" + route, for_selenium=False) + full_url = self.selenium_context.build_url(f"api/{route}", for_selenium=False) cookies = None if admin: full_url = f"{full_url}?key={self._mixin_admin_api_key}" diff --git a/lib/galaxy_test/selenium/test_history_multi_view.py b/lib/galaxy_test/selenium/test_history_multi_view.py index c5cc1c9a3a7..b5886453c97 100644 --- a/lib/galaxy_test/selenium/test_history_multi_view.py +++ b/lib/galaxy_test/selenium/test_history_multi_view.py @@ -129,7 +129,7 @@ class HistoryMultiViewTestCase(SeleniumTestCase): histories = self.components.multi_history_view.histories.all() assert len(histories) == histories_number # search for history with history_id - assert should_exist == any(history.get_attribute("id") == "history-column-" + history_id for history in histories) + assert should_exist == any(history.get_attribute("id") == f"history-column-{history_id}" for history in histories) def copy_history(self, history_id): self.components.multi_history_view.history_dropdown_btn(history_id=history_id).wait_for_and_click() diff --git a/lib/galaxy_test/selenium/test_library_landing.py b/lib/galaxy_test/selenium/test_library_landing.py index 7d7ef25f783..2b0902db5b7 100644 --- a/lib/galaxy_test/selenium/test_library_landing.py +++ b/lib/galaxy_test/selenium/test_library_landing.py @@ -61,11 +61,11 @@ class LibraryLandingTestCase(SeleniumTestCase): self.wait_for_overlays_cleared() namebase = self._get_random_name(prefix="testsort") - self.libraries_index_create(namebase + " b") + self.libraries_index_create(f"{namebase} b") self.wait_for_overlays_cleared() - self.libraries_index_create(namebase + " a") + self.libraries_index_create(f"{namebase} a") self.wait_for_overlays_cleared() - self.libraries_index_create(namebase + " c") + self.libraries_index_create(f"{namebase} c") self.screenshot("libraries_index") diff --git a/lib/galaxy_test/selenium/test_workflow_editor.py b/lib/galaxy_test/selenium/test_workflow_editor.py index 6e476032a25..70ef7192b10 100644 --- a/lib/galaxy_test/selenium/test_workflow_editor.py +++ b/lib/galaxy_test/selenium/test_workflow_editor.py @@ -549,8 +549,8 @@ steps: def workflow_editor_connect(self, source, sink, screenshot_partial=None): source_id, sink_id = self.workflow_editor_source_sink_terminal_ids(source, sink) - source_element = self.driver.find_element_by_css_selector("#" + source_id) - sink_element = self.driver.find_element_by_css_selector("#" + sink_id) + source_element = self.driver.find_element_by_css_selector(f"#{source_id}") + sink_element = self.driver.find_element_by_css_selector(f"#{sink_id}") ac = self.action_chains() ac = ac.move_to_element(source_element).click_and_hold() diff --git a/lib/tool_shed/managers/groups.py b/lib/tool_shed/managers/groups.py index 45b3104e2f1..d3a5338bbc1 100644 --- a/lib/tool_shed/managers/groups.py +++ b/lib/tool_shed/managers/groups.py @@ -60,7 +60,7 @@ class GroupManager: raise ItemAccessibilityException('Only administrators can create groups.') else: if self.get(trans, name=name): - raise Conflict('Group with the given name already exists. Name: ' + str(name)) + raise Conflict(f"Group with the given name already exists. Name: {str(name)}") # TODO add description field to the model group = trans.app.model.Group(name=name) trans.sa_session.add(group) diff --git a/lib/tool_shed/test/base/twilltestcase.py b/lib/tool_shed/test/base/twilltestcase.py index b4ed4e816ba..ad4916aabcd 100644 --- a/lib/tool_shed/test/base/twilltestcase.py +++ b/lib/tool_shed/test/base/twilltestcase.py @@ -530,7 +530,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): def deactivate_repository(self, installed_repository, strings_displayed=None, strings_not_displayed=None): encoded_id = self.security.encode_id(installed_repository.id) api_key = get_admin_api_key() - response = requests.delete(self.galaxy_url + "/api/tool_shed_repositories/" + encoded_id, data={'remove_from_disk': False, 'key': api_key}) + response = requests.delete(f"{self.galaxy_url}/api/tool_shed_repositories/{encoded_id}", data={'remove_from_disk': False, 'key': api_key}) assert response.status_code != 403, response.content def delete_files_from_repository(self, repository, filenames=None, strings_displayed=None, strings_not_displayed=None): @@ -1259,7 +1259,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): def reset_installed_repository_metadata(self, repository): encoded_id = self.security.encode_id(repository.id) api_key = get_admin_api_key() - response = requests.post(self.galaxy_url + "/api/tool_shed_repositories/reset_metadata_on_selected_installed_repositories", data={'repository_ids': [encoded_id], 'key': api_key}) + response = requests.post(f"{self.galaxy_url}/api/tool_shed_repositories/reset_metadata_on_selected_installed_repositories", data={'repository_ids': [encoded_id], 'key': api_key}) assert response.status_code != 403, response.content def reset_metadata_on_selected_repositories(self, repository_ids): @@ -1269,7 +1269,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): def reset_metadata_on_selected_installed_repositories(self, repository_ids): api_key = get_admin_api_key() - response = requests.post(self.galaxy_url + "/api/tool_shed_repositories/reset_metadata_on_selected_installed_repositories", data={'repository_ids': repository_ids, 'key': api_key}) + response = requests.post(f"{self.galaxy_url}/api/tool_shed_repositories/reset_metadata_on_selected_installed_repositories", data={'repository_ids': repository_ids, 'key': api_key}) assert response.status_code != 403, response.content def reset_repository_metadata(self, repository): @@ -1376,7 +1376,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): def uninstall_repository(self, installed_repository, strings_displayed=None, strings_not_displayed=None): encoded_id = self.security.encode_id(installed_repository.id) api_key = get_admin_api_key() - response = requests.delete(self.galaxy_url + "/api/tool_shed_repositories/" + encoded_id, data={'remove_from_disk': True, 'key': api_key}) + response = requests.delete(f"{self.galaxy_url}/api/tool_shed_repositories/{encoded_id}", data={'remove_from_disk': True, 'key': api_key}) assert response.status_code != 403, response.content def update_installed_repository(self, installed_repository, strings_displayed=None, strings_not_displayed=None): @@ -1391,7 +1391,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): def update_tool_shed_status(self): api_key = get_admin_api_key() - response = requests.get(self.galaxy_url + "/api/tool_shed_repositories/check_for_updates?key=" + api_key) + response = requests.get(f"{self.galaxy_url}/api/tool_shed_repositories/check_for_updates?key={api_key}") assert response.status_code != 403, response.content def upload_file(self, diff --git a/lib/tool_shed/test/functional/test_0420_citable_urls_for_repositories.py b/lib/tool_shed/test/functional/test_0420_citable_urls_for_repositories.py index 09e77b0fd8f..b9debaf3cd9 100644 --- a/lib/tool_shed/test/functional/test_0420_citable_urls_for_repositories.py +++ b/lib/tool_shed/test/functional/test_0420_citable_urls_for_repositories.py @@ -153,7 +153,7 @@ class TestRepositoryCitableURLs(ShedTwillTestCase): # Since twill does not load the contents of an iframe, we need to check that the iframe has been generated correctly, # then directly load the url that the iframe should be loading and check for the expected strings. # The iframe should point to /repository/view_repository?id= - strings_displayed = ['/repository', 'view_repository', 'id=' + encoded_repository_id] + strings_displayed = ['/repository', 'view_repository', f"id={encoded_repository_id}"] strings_displayed_in_iframe = ['user1', 'filtering_0420', 'Galaxy filtering tool for test 0420', first_changeset_hash] strings_displayed_in_iframe.append('Link to this repository revision:') strings_displayed_in_iframe.append(f'{self.url}/view/user1/filtering_0420/{first_changeset_hash}') @@ -177,7 +177,7 @@ class TestRepositoryCitableURLs(ShedTwillTestCase): # Since twill does not load the contents of an iframe, we need to check that the iframe has been generated correctly, # then directly load the url that the iframe should be loading and check for the expected strings. # The iframe should point to /repository/view_repository?id=&status=error - strings_displayed = ['/repository', 'view_repository', 'id=' + encoded_repository_id] + strings_displayed = ['/repository', 'view_repository', f"id={encoded_repository_id}"] strings_displayed.extend(['The+change+log', 'does+not+include+revision', invalid_changeset_hash, 'status=error']) self.load_citable_url(username='user1', repository_name='filtering_0420', diff --git a/lib/tool_shed/util/admin_util.py b/lib/tool_shed/util/admin_util.py index dea466e101e..79adee0339b 100644 --- a/lib/tool_shed/util/admin_util.py +++ b/lib/tool_shed/util/admin_util.py @@ -890,8 +890,8 @@ class Admin: def name_autocomplete_data(self, trans, q=None, limit=None, timestamp=None): """Return autocomplete data for user emails""" ac_data = "" - for user in trans.sa_session.query(trans.app.model.User).filter_by(deleted=False).filter(func.lower(trans.app.model.User.email).like(q.lower() + "%")): - ac_data = ac_data + user.email + "\n" + for user in trans.sa_session.query(trans.app.model.User).filter_by(deleted=False).filter(func.lower(trans.app.model.User.email).like(f"{q.lower()}%")): + ac_data = f"{ac_data + user.email}\n" return ac_data @web.expose diff --git a/lib/tool_shed/util/shed_index.py b/lib/tool_shed/util/shed_index.py index efe33007f3c..26afd1bc18c 100644 --- a/lib/tool_shed/util/shed_index.py +++ b/lib/tool_shed/util/shed_index.py @@ -120,7 +120,7 @@ def get_repos(sa_session, file_path, hgweb_config_dir, **kwargs): hg_repo = hg.repository(ui.ui(), repo_path.encode('utf-8')) lineage = [] for changeset in hg_repo.changelog: - lineage.append(unicodify(changeset) + ":" + unicodify(hg_repo[changeset])) + lineage.append(f"{unicodify(changeset)}:{unicodify(hg_repo[changeset])}") repo_lineage = str(lineage) # Parse all the tools within repo for a separate index. diff --git a/lib/tool_shed/util/shed_util_common.py b/lib/tool_shed/util/shed_util_common.py index 87c5f60cc69..01487d15831 100644 --- a/lib/tool_shed/util/shed_util_common.py +++ b/lib/tool_shed/util/shed_util_common.py @@ -193,7 +193,7 @@ def get_repository_file_contents(app, file_path, repository_id, is_admin=False): return 'Invalid file path' # Symlink targets are checked by is_path_browsable if os.path.islink(file_path): - safe_str = 'link to: ' + basic_util.to_html_string(os.readlink(file_path)) + safe_str = f"link to: {basic_util.to_html_string(os.readlink(file_path))}" return safe_str elif checkers.is_gzip(file_path): return '
    gzip compressed file
    ' @@ -335,9 +335,9 @@ def handle_email_alerts(app, host, repository, content_alert_str='', new_repo_al if app.config.email_from is not None: email_from = app.config.email_from elif host.split(':')[0] in ['localhost', '127.0.0.1', '0.0.0.0']: - email_from = 'galaxy-no-reply@' + socket.getfqdn() + email_from = f"galaxy-no-reply@{socket.getfqdn()}" else: - email_from = 'galaxy-no-reply@' + host.split(':')[0] + email_from = f"galaxy-no-reply@{host.split(':')[0]}" ctx = repo[repo.changelog.tip()] username = unicodify(ctx.user()) try: @@ -454,7 +454,7 @@ def open_repository_files_folder(app, folder_path, repository_id, is_admin=False is_link = os.path.islink(full_path) path_is_browsable = is_path_browsable(app, full_path, repository_id) if is_link and not path_is_browsable: - log.warning('Valid folder contains a symlink outside of the repository location. Link found in: ' + str(full_path)) + log.warning(f"Valid folder contains a symlink outside of the repository location. Link found in: {str(full_path)}") if filename: if os.path.isdir(full_path) and path_is_browsable: # Append a '/' character so that our jquery dynatree will function properly. diff --git a/lib/tool_shed/webapp/buildapp.py b/lib/tool_shed/webapp/buildapp.py index 9abff46545c..bf176432d68 100644 --- a/lib/tool_shed/webapp/buildapp.py +++ b/lib/tool_shed/webapp/buildapp.py @@ -37,7 +37,7 @@ def add_ui_controllers(webapp, app): for fname in os.listdir(controller_dir): if not fname.startswith("_") and fname.endswith(".py"): name = fname[:-3] - module_name = "tool_shed.webapp.controllers." + name + module_name = f"tool_shed.webapp.controllers.{name}" module = __import__(module_name) for comp in module_name.split(".")[1:]: module = getattr(module, comp) diff --git a/lib/tool_shed/webapp/controllers/user.py b/lib/tool_shed/webapp/controllers/user.py index 8a0a64dd592..df2321ffc00 100644 --- a/lib/tool_shed/webapp/controllers/user.py +++ b/lib/tool_shed/webapp/controllers/user.py @@ -178,7 +178,7 @@ class User(BaseUser): # subscribe user to email list if trans.app.config.smtp_server is None: status = "error" - message = "Now logged in as " + user.email + ". However, subscribing to the mailing list has failed because mail is not configured for this Galaxy instance.
    Please contact your local Galaxy administrator." + message = f"Now logged in as {user.email}. However, subscribing to the mailing list has failed because mail is not configured for this Galaxy instance.
    Please contact your local Galaxy administrator." else: body = 'Join Mailing list.\n' to = trans.app.config.mailing_join_addr @@ -189,7 +189,7 @@ class User(BaseUser): except Exception: log.exception('Subscribing to the mailing list has failed.') status = "warning" - message = "Now logged in as " + user.email + ". However, subscribing to the mailing list has failed." + message = f"Now logged in as {user.email}. However, subscribing to the mailing list has failed." if status != "error": if not is_admin: # The handle_user_login() method has a call to the history_set_default_permissions() method @@ -243,7 +243,7 @@ class User(BaseUser): token=prt.token, qualified=True) body = PASSWORD_RESET_TEMPLATE % (host, prt.expiration_time.strftime(trans.app.config.pretty_datetime_format), reset_url) - frm = trans.app.config.email_from or 'galaxy-no-reply@' + host + frm = trans.app.config.email_from or f"galaxy-no-reply@{host}" subject = 'Galaxy Password Reset' try: util.send_mail(frm, email, subject, body, trans.app.config) @@ -362,7 +362,7 @@ class User(BaseUser): # The user's private role name must match the user's login ( email ) private_role = trans.app.security_agent.get_private_user_role(user) private_role.name = email - private_role.description = 'Private role for ' + email + private_role.description = f"Private role for {email}" # Change the email itself user.email = email trans.sa_session.add_all((user, private_role)) diff --git a/lib/tool_shed/webapp/framework/middleware/remoteuser.py b/lib/tool_shed/webapp/framework/middleware/remoteuser.py index dd4e35e7626..f0f9db25d36 100644 --- a/lib/tool_shed/webapp/framework/middleware/remoteuser.py +++ b/lib/tool_shed/webapp/framework/middleware/remoteuser.py @@ -91,7 +91,7 @@ class RemoteUser: if 'HTTP_REMOTE_USER' in environ and environ['HTTP_REMOTE_USER'] != '(null)': if not environ['HTTP_REMOTE_USER'].count('@'): if self.maildomain is not None: - environ['HTTP_REMOTE_USER'] += '@' + self.maildomain + environ['HTTP_REMOTE_USER'] += f"@{self.maildomain}" else: title = "Access to this Galaxy tool shed is denied" message = """ diff --git a/lib/tool_shed/webapp/search/repo_search.py b/lib/tool_shed/webapp/search/repo_search.py index d78160df649..fcfb01a3947 100644 --- a/lib/tool_shed/webapp/search/repo_search.py +++ b/lib/tool_shed/webapp/search/repo_search.py @@ -71,10 +71,10 @@ class RepoSearch: :returns results: dictionary containing hits themselves and the hits summary """ - log.debug('raw search query: #' + str(search_term)) + log.debug(f"raw search query: #{str(search_term)}") lower_search_term = search_term.lower() allow_query, search_term_without_filters = self._parse_reserved_filters(lower_search_term) - log.debug('term without filters: #' + str(search_term_without_filters)) + log.debug(f"term without filters: #{str(search_term_without_filters)}") whoosh_index_dir = trans.app.config.whoosh_index_dir index_exists = whoosh.index.exists_in(whoosh_index_dir) @@ -107,12 +107,12 @@ class RepoSearch: user_query = Every('name') sortedby = 'name' else: - user_query = parser.parse('*' + search_term_without_filters + '*') + user_query = parser.parse(f"*{search_term_without_filters}*") sortedby = '' try: hits = searcher.search_page(user_query, page, pagelen=page_size, filter=allow_query, terms=True, sortedby=sortedby) - log.debug('total hits: ' + str(len(hits))) - log.debug('scored hits: ' + str(hits.scored_length())) + log.debug(f"total hits: {str(len(hits))}") + log.debug(f"scored hits: {str(hits.scored_length())}") except ValueError: raise ObjectNotFound('The requested page does not exist.') results = {} @@ -121,7 +121,7 @@ class RepoSearch: results['page_size'] = str(page_size) results['hits'] = [] for hit in hits: - log.debug('matched terms: ' + str(hit.matched_terms())) + log.debug(f"matched terms: {str(hit.matched_terms())}") hit_dict = {} hit_dict['id'] = trans.security.encode_id(hit.get('id')) hit_dict['repo_owner_username'] = hit.get('repo_owner_username') diff --git a/lib/tool_shed/webapp/search/tool_search.py b/lib/tool_shed/webapp/search/tool_search.py index 4df4a19cba4..f325b022683 100644 --- a/lib/tool_shed/webapp/search/tool_search.py +++ b/lib/tool_shed/webapp/search/tool_search.py @@ -61,16 +61,16 @@ class ToolSearch: 'help', 'repo_owner_username'], schema=schema) - user_query = parser.parse('*' + search_term + '*') + user_query = parser.parse(f"*{search_term}*") try: hits = searcher.search_page(user_query, page, pagelen=page_size, terms=True) except ValueError: raise ObjectNotFound('The requested page does not exist.') - log.debug('searching tools for: #' + str(search_term)) - log.debug('total hits: ' + str(len(hits))) - log.debug('scored hits: ' + str(hits.scored_length())) + log.debug(f"searching tools for: #{str(search_term)}") + log.debug(f"total hits: {str(len(hits))}") + log.debug(f"scored hits: {str(hits.scored_length())}") results = {} results['total_results'] = str(len(hits)) results['page'] = str(page) diff --git a/lib/tool_shed/webapp/security/__init__.py b/lib/tool_shed/webapp/security/__init__.py index 96e3be5780c..f794ffad19b 100644 --- a/lib/tool_shed/webapp/security/__init__.py +++ b/lib/tool_shed/webapp/security/__init__.py @@ -124,7 +124,7 @@ class CommunityRBACAgent(RBACAgent): def create_private_user_role(self, user): # Create private role - role = self.model.Role(name=user.email, description='Private Role for ' + user.email, type=self.model.Role.types.PRIVATE) + role = self.model.Role(name=user.email, description=f"Private Role for {user.email}", type=self.model.Role.types.PRIVATE) self.sa_session.add(role) self.sa_session.flush() # Add user to role From 64025b767bf8b2bffc2f6ddfa557d04be456ba85 Mon Sep 17 00:00:00 2001 From: Dannon Baker Date: Wed, 10 Feb 2021 08:30:05 -0500 Subject: [PATCH 3/7] Typo fix --- lib/galaxy/datatypes/tabular.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/galaxy/datatypes/tabular.py b/lib/galaxy/datatypes/tabular.py index 5d82a9a858b..e50bdec84ae 100644 --- a/lib/galaxy/datatypes/tabular.py +++ b/lib/galaxy/datatypes/tabular.py @@ -1201,7 +1201,7 @@ class ConnectivityTable(Tabular): else: if j != int(re.split(r'\W+', line, 1)[0]): return False - elif j == length: # Last line of first sequence has been recheached + elif j == length: # Last line of first sequence has been reached return True else: j += 1 From ace65206e298ddb8ffdf0c72399eec4d049cf951 Mon Sep 17 00:00:00 2001 From: Dannon Baker Date: Wed, 10 Feb 2021 08:28:04 -0500 Subject: [PATCH 4/7] fstring fixup --- lib/galaxy/datatypes/tabular.py | 4 ++-- lib/galaxy/jobs/dynamic_tool_destination.py | 2 +- lib/galaxy/managers/rbac_secured.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/galaxy/datatypes/tabular.py b/lib/galaxy/datatypes/tabular.py index e50bdec84ae..3be8c1244fc 100644 --- a/lib/galaxy/datatypes/tabular.py +++ b/lib/galaxy/datatypes/tabular.py @@ -1132,8 +1132,8 @@ class ConnectivityTable(Tabular): edam_format = "format_3309" file_ext = "ct" - header_regexp = re.compile(f"^[0-9]+(?: |[ ]+).*?(?:ENERGY|energy|dG)[ ].*?=") - structure_regexp = re.compile(f"^[0-9]+(?: |[ ]+)[ACGTURYKMSWBDHVN]+(?: |[ ]+)[^ ]+(?: |[ ]+)[^ ]+(?: |[ ]+)[^ ]+(?: |[ ]+)[^ ]+") + header_regexp = re.compile("^[0-9]+(?: |[ ]+).*?(?:ENERGY|energy|dG)[ ].*?=") + structure_regexp = re.compile("^[0-9]+(?: |[ ]+)[ACGTURYKMSWBDHVN]+(?: |[ ]+)[^ ]+(?: |[ ]+)[^ ]+(?: |[ ]+)[^ ]+(?: |[ ]+)[^ ]+") def __init__(self, **kwd): super().__init__(**kwd) diff --git a/lib/galaxy/jobs/dynamic_tool_destination.py b/lib/galaxy/jobs/dynamic_tool_destination.py index 046003b23af..905d4f65693 100755 --- a/lib/galaxy/jobs/dynamic_tool_destination.py +++ b/lib/galaxy/jobs/dynamic_tool_destination.py @@ -640,7 +640,7 @@ class RuleValidator: if not isinstance(user, str): error = f"Entry '{str(user)}' in users for rule " error += f"{str(counter)} in tool '{str(tool)}" - error += f"' is in an invalid format!" + error += "' is in an invalid format!" if not return_bool: error += " Ignoring entry." if verbose: diff --git a/lib/galaxy/managers/rbac_secured.py b/lib/galaxy/managers/rbac_secured.py index 53fec615f5f..3587089b6b4 100644 --- a/lib/galaxy/managers/rbac_secured.py +++ b/lib/galaxy/managers/rbac_secured.py @@ -81,7 +81,7 @@ class DatasetRBACPermission(RBACPermission): # ---- double secrect probation def __assert_action(self): if not self.action_name: - raise NotImplementedError(f"abstract parent class needs action_name") + raise NotImplementedError("abstract parent class needs action_name") # ---- interface def by_dataset(self, dataset): From c2b2d52c4c9cbd4e9f2adf54b6651bd596bd3584 Mon Sep 17 00:00:00 2001 From: Dannon Baker Date: Tue, 11 May 2021 13:56:10 -0400 Subject: [PATCH 5/7] Another pass post-rebase --- lib/galaxy/celery/tasks.py | 2 +- lib/galaxy/containers/__init__.py | 2 +- lib/galaxy/datatypes/converters/lped_to_fped_converter.py | 2 +- lib/galaxy/datatypes/genetics.py | 2 +- lib/galaxy/datatypes/isa.py | 2 +- lib/galaxy/datatypes/tabular.py | 2 +- lib/galaxy/jobs/runners/kubernetes.py | 8 ++++---- lib/galaxy/managers/folders.py | 8 ++++---- lib/galaxy/managers/interactivetool.py | 2 +- lib/galaxy/managers/markdown_util.py | 8 ++++---- lib/galaxy/managers/sharable.py | 6 +++--- lib/galaxy/managers/workflows.py | 2 +- lib/galaxy/model/orm/scripts.py | 2 +- lib/galaxy/objectstore/irods.py | 2 +- lib/galaxy/selenium/components.py | 2 +- .../tool_dependencies/recipe/install_environment.py | 2 +- lib/galaxy/tool_util/deps/mulled/mulled_build.py | 4 ++-- lib/galaxy/tool_util/verify/asserts/text.py | 2 +- lib/galaxy/tool_util/verify/interactor.py | 4 ++-- lib/galaxy/tools/toolbox/base.py | 2 +- lib/galaxy/util/bool_expressions.py | 2 +- lib/galaxy/util/json.py | 2 +- lib/galaxy/util/pastescript/loadwsgi.py | 2 +- lib/galaxy/util/rules_dsl.py | 4 ++-- lib/galaxy/version.py | 2 +- lib/galaxy/webapps/galaxy/api/folder_contents.py | 2 +- lib/galaxy/webapps/galaxy/controllers/admin.py | 2 +- lib/galaxy/workflow/modules.py | 2 +- lib/galaxy_test/api/test_jobs.py | 2 +- lib/galaxy_test/selenium/test_library_landing.py | 4 ++-- lib/galaxy_test/selenium/test_personal_information.py | 2 +- lib/tool_shed/test/base/twilltestcase.py | 2 +- lib/tool_shed/util/shed_util_common.py | 2 +- lib/tool_shed/webapp/controllers/repository_review.py | 2 +- lib/tool_shed/webapp/model/__init__.py | 2 +- 35 files changed, 50 insertions(+), 50 deletions(-) diff --git a/lib/galaxy/celery/tasks.py b/lib/galaxy/celery/tasks.py index 878c080f64b..a70a27d641b 100644 --- a/lib/galaxy/celery/tasks.py +++ b/lib/galaxy/celery/tasks.py @@ -33,7 +33,7 @@ def recalculate_user_disk_usage(session: scoped_session, user_id=None): user.calculate_and_set_disk_usage() log.info(f"New user disk usage is {user.disk_usage}") else: - log.error("Recalculate user disk usage task failed, user %s not found" % user_id) + log.error(f"Recalculate user disk usage task failed, user {user_id} not found") else: log.error("Recalculate user disk usage task received without user_id.") diff --git a/lib/galaxy/containers/__init__.py b/lib/galaxy/containers/__init__.py index 5bf9a3c1a35..ffb9c9e25c8 100644 --- a/lib/galaxy/containers/__init__.py +++ b/lib/galaxy/containers/__init__.py @@ -237,7 +237,7 @@ class ContainerInterface(metaclass=ABCMeta): """ if isinstance(val, str): return self._stringify_kwopt_string(flag, val) - return ' '.join('{flag} {value}'.format(flag=flag, value=shlex.quote(str(v))) for v in val) + return ' '.join(f'{flag} {shlex.quote(str(v))}' for v in val) def _stringify_kwopt_list_of_kvpairs(self, flag, val): """ diff --git a/lib/galaxy/datatypes/converters/lped_to_fped_converter.py b/lib/galaxy/datatypes/converters/lped_to_fped_converter.py index c94b431264a..9ba6c738e1c 100644 --- a/lib/galaxy/datatypes/converters/lped_to_fped_converter.py +++ b/lib/galaxy/datatypes/converters/lped_to_fped_converter.py @@ -68,7 +68,7 @@ def rgConv(inpedfilepath, outhtmlname, outfilepath): g = lrow[6:] gc = [recode.get(z, '0') for z in g] lrow = p + gc - row = '%s\n' % ' '.join(lrow) + row = f"{' '.join(lrow)}\n" o.write(row) diff --git a/lib/galaxy/datatypes/genetics.py b/lib/galaxy/datatypes/genetics.py index 75c5281783b..ad603755819 100644 --- a/lib/galaxy/datatypes/genetics.py +++ b/lib/galaxy/datatypes/genetics.py @@ -146,7 +146,7 @@ class GenomeGraphs(Tabular): out.append('
    ') for row in d: out.append('') - out.append(''.join('' % x for x in row.split())) + out.append(''.join(f'' for x in row.split())) out.append('') out.append('
    ' + text + '{text}
    ' + input.cases[current_case].value + '
    {input.cases[current_case].value}
    ' + str(len(param_values[input.name])) + ' uploaded datasets
    {str(len(param_values[input.name]))} uploaded datasets
    ' + input.value_to_display_text(param_values[input.name]) + '' + upgrade_messages.get(input.name, '') + '
    {input.value_to_display_text(param_values[input.name])}{upgrade_messages.get(input.name, '')}
    %s{x}
    ') out = "".join(out) diff --git a/lib/galaxy/datatypes/isa.py b/lib/galaxy/datatypes/isa.py index 4afb5b14e99..033ef544741 100644 --- a/lib/galaxy/datatypes/isa.py +++ b/lib/galaxy/datatypes/isa.py @@ -275,7 +275,7 @@ class _Isa(data.Data): html += f'

    Submitted the {study.submission_date}

    ' html += f'

    Released on {study.public_release_date}

    ' - html += '

    Experimental factors used: %s

    ' % ', '.join(x.name for x in study.factors) + html += f"

    Experimental factors used: {', '.join(x.name for x in study.factors)}

    " # Loop on all assays of this study for assay in study.assays: diff --git a/lib/galaxy/datatypes/tabular.py b/lib/galaxy/datatypes/tabular.py index 3be8c1244fc..552c8d0e80c 100644 --- a/lib/galaxy/datatypes/tabular.py +++ b/lib/galaxy/datatypes/tabular.py @@ -869,7 +869,7 @@ class Eland(Tabular): # This data type requires at least 11 columns in the data if dataset.metadata.columns - len(self.column_names) > 0: for i in range(len(self.column_names), max(dataset.metadata.columns, self.max_peek_columns)): - out.append('%s' % str(i + 1)) + out.append(f'{str(i + 1)}') out.append('') out.append(self.make_html_peek_rows(dataset, skipchars=skipchars, peek=peek)) out.append('') diff --git a/lib/galaxy/jobs/runners/kubernetes.py b/lib/galaxy/jobs/runners/kubernetes.py index da158f48bf7..2df7d58c302 100644 --- a/lib/galaxy/jobs/runners/kubernetes.py +++ b/lib/galaxy/jobs/runners/kubernetes.py @@ -308,7 +308,7 @@ class KubernetesJobRunner(AsynchronousJobRunner): } }, "spec": { - "ports": [{"name": "job-{}-{}".format(self.__force_label_conformity(ajs.job_wrapper.get_id_tag()), p), + "ports": [{"name": f"job-{self.__force_label_conformity(ajs.job_wrapper.get_id_tag())}-{p}", "port": int(p), "protocol": "TCP", "targetPort": int(p)} for p in guest_ports], @@ -543,7 +543,7 @@ class KubernetesJobRunner(AsynchronousJobRunner): return "job-container" def __get_k8s_job_name(self, prefix, job_wrapper): - return "{}-{}".format(prefix, self.__force_label_conformity(job_wrapper.get_id_tag())) + return f"{prefix}-{self.__force_label_conformity(job_wrapper.get_id_tag())}" def __get_destination_params(self, job_wrapper): """Obtains allowable runner param overrides from the destination""" @@ -719,7 +719,7 @@ class KubernetesJobRunner(AsynchronousJobRunner): return any(True for c in conditions if c['type'] == 'Failed' and c['reason'] == 'DeadlineExceeded') def _get_pod_for_job(self, job_state): - pods = Pod.objects(self._pykube_api).filter(selector="app=%s" % job_state.job_id, + pods = Pod.objects(self._pykube_api).filter(selector=f"app={job_state.job_id}", namespace=self.runner_params['k8s_namespace']) if not pods.response['items']: return None @@ -764,7 +764,7 @@ class KubernetesJobRunner(AsynchronousJobRunner): k8s_job = Job(self._pykube_api, job_to_delete.response['items'][0]) if job_wrapper.guest_ports: k8s_job_prefix = self.__produce_k8s_job_prefix() - k8s_job_name = "{}-{}".format(k8s_job_prefix, self.__force_label_conformity(job_wrapper.get_id_tag())) + k8s_job_name = f"{k8s_job_prefix}-{self.__force_label_conformity(job_wrapper.get_id_tag())}" log.debug(f'Deleting service/ingress for job with ID {job_wrapper.get_id_tag()}') job_failed = (k8s_job.obj['status']['failed'] > 0 if 'failed' in k8s_job.obj['status'] else False) diff --git a/lib/galaxy/managers/folders.py b/lib/galaxy/managers/folders.py index 96d071ccffe..e5a14e7b8e8 100644 --- a/lib/galaxy/managers/folders.py +++ b/lib/galaxy/managers/folders.py @@ -54,7 +54,7 @@ class FolderManager: except NoResultFound: raise RequestParameterInvalidException('No folder found with the id provided.') except Exception as e: - raise InternalServerError('Error loading from the database.' + util.unicodify(e)) + raise InternalServerError(f"Error loading from the database.{util.unicodify(e)}") folder = self.secure(trans, folder, check_manageable, check_accessible) return folder @@ -458,7 +458,7 @@ class FoldersService: else: invalid_add_roles_names.append(role_id) if len(invalid_add_roles_names) > 0: - log.warning("The following roles could not be added to the add library item permission: " + str(invalid_add_roles_names)) + log.warning(f"The following roles could not be added to the add library item permission: {str(invalid_add_roles_names)}") # MANAGE FOLDER ROLES valid_manage_roles = [] @@ -472,7 +472,7 @@ class FoldersService: else: invalid_manage_roles_names.append(role_id) if len(invalid_manage_roles_names) > 0: - log.warning("The following roles could not be added to the manage folder permission: " + str(invalid_manage_roles_names)) + log.warning(f"The following roles could not be added to the manage folder permission: {str(invalid_manage_roles_names)}") # MODIFY FOLDER ROLES valid_modify_roles = [] @@ -486,7 +486,7 @@ class FoldersService: else: invalid_modify_roles_names.append(role_id) if len(invalid_modify_roles_names) > 0: - log.warning("The following roles could not be added to the modify folder permission: " + str(invalid_modify_roles_names)) + log.warning(f"The following roles could not be added to the modify folder permission: {str(invalid_modify_roles_names)}") permissions = {trans.app.security_agent.permitted_actions.LIBRARY_ADD: valid_add_roles} permissions.update({trans.app.security_agent.permitted_actions.LIBRARY_MANAGE: valid_manage_roles}) diff --git a/lib/galaxy/managers/interactivetool.py b/lib/galaxy/managers/interactivetool.py index 595d5db4d8d..46268ed9514 100644 --- a/lib/galaxy/managers/interactivetool.py +++ b/lib/galaxy/managers/interactivetool.py @@ -280,7 +280,7 @@ class InteractiveToolManager: if not entry_point.requires_domain: rval = self.app.url_for(f'/{entry_point_prefix}/access/{entry_point_class}/{entry_point_encoded_id}/{entry_point.token}/') if entry_point.entry_url: - rval = '{}/{}'.format(rval.rstrip('/'), entry_point.entry_url.lstrip('/')) + rval = f"{rval.rstrip('/')}/{entry_point.entry_url.lstrip('/')}" if rval[0] != "/": rval = f'/{rval}' return rval diff --git a/lib/galaxy/managers/markdown_util.py b/lib/galaxy/managers/markdown_util.py index bf198d1a815..839263418e9 100644 --- a/lib/galaxy/managers/markdown_util.py +++ b/lib/galaxy/managers/markdown_util.py @@ -96,7 +96,7 @@ class GalaxyInternalMarkdownDirectiveHandler(metaclass=abc.ABCMeta): if id_match: object_id = int(id_match.group(2)) encoded_id = trans.security.encode_id(object_id) - line = line.replace(id_match.group(), "{}={}".format(id_match.group(1), encoded_id)) + line = line.replace(id_match.group(), f"{id_match.group(1)}={encoded_id}") if container == "history_link": _check_object(object_id, line) history = history_manager.get_accessible(object_id, trans.user) @@ -500,7 +500,7 @@ class ToBasicMarkdownDirectiveHandler(GalaxyInternalMarkdownDirectiveHandler): markdown += " | " value = parameter["value"] if isinstance(value, list): - markdown += ", ".join("{}: {}".format(p["hid"], p["name"]) for p in value) + markdown += ", ".join(f"{p['hid']}: {p['name']}" for p in value) else: markdown += value markdown += " |\n" @@ -682,9 +682,9 @@ history_dataset_collection_display(input={}) if container == "workflow_display": # TODO: this really should be workflow id not stored workflow id but the API # it consumes wants the stored id. - return ("workflow_display(workflow_id=%s)\n" % invocation.workflow.stored_workflow.id, False) + return (f"workflow_display(workflow_id={invocation.workflow.stored_workflow.id})\n", False) if container == "history_link": - return ("history_link(history_id=%s)\n" % invocation.history.id, False) + return (f"history_link(history_id={invocation.history.id})\n", False) if container == "invocation_date": return (f"invocation_date(invocation_id={invocation.id})\n", False) ref_object_type = None diff --git a/lib/galaxy/managers/sharable.py b/lib/galaxy/managers/sharable.py index 5782895eae8..d52c4888689 100644 --- a/lib/galaxy/managers/sharable.py +++ b/lib/galaxy/managers/sharable.py @@ -631,7 +631,7 @@ class ShareableService: if hasattr(item, "has_possible_members") and item.has_possible_members: skipped = self._make_members_public(trans, item) else: - raise exceptions.MessageException("%s not importable." % class_name) + raise exceptions.MessageException(f"{class_name} not importable.") elif action == "disable_link_access": item.importable = False elif action == "unpublish": @@ -643,10 +643,10 @@ class ShareableService: raise exceptions.MessageException(f"Missing required user_id to perform {action}") user = trans.sa_session.query(trans.app.model.User).get(trans.app.security.decode_id(payload.user_id)) class_name_lc = class_name.lower() - ShareAssociation = getattr(trans.app.model, "%sUserShareAssociation" % class_name) + ShareAssociation = getattr(trans.app.model, f"{class_name}UserShareAssociation") usas = trans.sa_session.query(ShareAssociation).filter_by(**{"user": user, class_name_lc: item}).all() if not usas: - raise exceptions.MessageException("%s was not shared with user." % class_name) + raise exceptions.MessageException(f"{class_name} was not shared with user.") for usa in usas: trans.sa_session.delete(usa) trans.sa_session.add(item) diff --git a/lib/galaxy/managers/workflows.py b/lib/galaxy/managers/workflows.py index e4cf2b4e9d2..f7b176ea512 100644 --- a/lib/galaxy/managers/workflows.py +++ b/lib/galaxy/managers/workflows.py @@ -625,7 +625,7 @@ class WorkflowContentsManager(UsesAnnotations): errors[step.id] = step_errors if missing_tools: workflow.annotation = self.get_item_annotation_str(trans.sa_session, trans.user, workflow) - raise exceptions.MessageException('Following tools missing: %s' % ', '.join(missing_tools)) + raise exceptions.MessageException(f"Following tools missing: {', '.join(missing_tools)}") workflow.annotation = self.get_item_annotation_str(trans.sa_session, trans.user, workflow) step_order_indices = {} for step in workflow.steps: diff --git a/lib/galaxy/model/orm/scripts.py b/lib/galaxy/model/orm/scripts.py index 2b0da1a5986..86ce5c03195 100644 --- a/lib/galaxy/model/orm/scripts.py +++ b/lib/galaxy/model/orm/scripts.py @@ -135,7 +135,7 @@ def get_config(argv, use_argparse=True, cwd=None): if (f"{config_prefix}database_connection") in properties: db_url = properties[f"{config_prefix}database_connection"] else: - db_url = "sqlite:///%s?isolation_level=IMMEDIATE" % os.path.join(get_data_dir(properties), default_sqlite_file) + db_url = f"sqlite:///{os.path.join(get_data_dir(properties), default_sqlite_file)}?isolation_level=IMMEDIATE" install_database_connection = properties.get('install_database_connection') return dict(db_url=db_url, repo=repo, config_file=config_file, database=database, install_database_connection=install_database_connection) diff --git a/lib/galaxy/objectstore/irods.py b/lib/galaxy/objectstore/irods.py index 824a5a73151..8c8da670a47 100644 --- a/lib/galaxy/objectstore/irods.py +++ b/lib/galaxy/objectstore/irods.py @@ -432,7 +432,7 @@ class IRODSObjectStore(DiskObjectStore, CloudConfigMixin): # Add file containing 'from_string' to the irods collection, since # put() expects a file as input. Get file name from data object's 'desc' field - self.session.data_objects.put(data_obj.desc, collection_path + "/", **options) + self.session.data_objects.put(data_obj.desc, f"{collection_path}/", **options) log.debug("Pushed data from string '%s' to collection '%s'", from_string, data_object_path) else: diff --git a/lib/galaxy/selenium/components.py b/lib/galaxy/selenium/components.py index 6db9d0783e4..44bc3a9b8a9 100644 --- a/lib/galaxy/selenium/components.py +++ b/lib/galaxy/selenium/components.py @@ -71,7 +71,7 @@ class SelectorTemplate(Target): selector = self._selector if self.__kwds is not None: selector = string.Template(selector).substitute(self.__kwds) - selector = selector + "".join(".%s" % c for c in self.with_classes) + selector = selector + "".join(f".{c}" for c in self.with_classes) return selector @property diff --git a/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/install_environment.py b/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/install_environment.py index 4181ed23767..03f1baebf64 100644 --- a/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/install_environment.py +++ b/lib/galaxy/tool_shed/galaxy_install/tool_dependencies/recipe/install_environment.py @@ -272,7 +272,7 @@ class InstallEnvironment: log.exception(str(e)) def __setup_environment(self): - return "&&".join(". %s" % _ for _ in self.__valid_env_shell_file_paths()) + return "&&".join(f". {_}" for _ in self.__valid_env_shell_file_paths()) def __valid_env_shell_file_paths(self): return [_ for _ in self.env_shell_file_paths if os.path.exists(_)] diff --git a/lib/galaxy/tool_util/deps/mulled/mulled_build.py b/lib/galaxy/tool_util/deps/mulled/mulled_build.py index 5fa69a497e1..3198f1b6353 100644 --- a/lib/galaxy/tool_util/deps/mulled/mulled_build.py +++ b/lib/galaxy/tool_util/deps/mulled/mulled_build.py @@ -100,9 +100,9 @@ def get_tests(args, pkg_path): if tests_commands: tests.append(' && '.join(tests_commands)) if tests_imports and 'python' in requirements: - tests.append(' && '.join('python -c "import %s"' % imp for imp in tests_imports)) + tests.append(' && '.join(f'python -c "import {imp}"' for imp in tests_imports)) elif tests_imports and ('perl' in requirements or 'perl-threaded' in requirements): - tests.append(' && '.join('''perl -e "use %s;"''' % imp for imp in tests_imports)) + tests.append(' && '.join(f'''perl -e "use {imp};\"''' for imp in tests_imports)) tests = ' && '.join(tests) tests = tests.replace('$R ', 'Rscript ') diff --git a/lib/galaxy/tool_util/verify/asserts/text.py b/lib/galaxy/tool_util/verify/asserts/text.py index d501c0e1149..003fd48bde9 100644 --- a/lib/galaxy/tool_util/verify/asserts/text.py +++ b/lib/galaxy/tool_util/verify/asserts/text.py @@ -17,7 +17,7 @@ def assert_not_has_text(output, text): """ Asserts specified output does not contain the substring specified by the argument text.""" assert output is not None, "Checking not_has_text assertion on empty output (None)" - assert output.find(text) < 0, "Output file contains unexpected text '%s'" % text + assert output.find(text) < 0, f"Output file contains unexpected text '{text}'" def assert_has_line(output, line, n=None): diff --git a/lib/galaxy/tool_util/verify/interactor.py b/lib/galaxy/tool_util/verify/interactor.py index f3c4f727834..646ae8bd2a1 100644 --- a/lib/galaxy/tool_util/verify/interactor.py +++ b/lib/galaxy/tool_util/verify/interactor.py @@ -131,10 +131,10 @@ class GalaxyInteractorApi: return response.json() def get_tool_tests(self, tool_id, tool_version=None): - url = "tools/%s/test_data" % tool_id + url = f"tools/{tool_id}/test_data" params = {'tool_version': tool_version} if tool_version else None response = self._get(url, data=params) - assert response.status_code == 200, "Non 200 response from tool test API. [%s]" % response.content + assert response.status_code == 200, f"Non 200 response from tool test API. [{response.content}]" return response.json() def verify_output_collection(self, output_collection_def, output_collection_id, history, tool_id): diff --git a/lib/galaxy/tools/toolbox/base.py b/lib/galaxy/tools/toolbox/base.py index 6634b83c5e9..cd3cfa0a833 100644 --- a/lib/galaxy/tools/toolbox/base.py +++ b/lib/galaxy/tools/toolbox/base.py @@ -325,7 +325,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin): dynamic_tool_conf_paths.append(dynamic_tool_conf_path) if dynamic_tool_conf_path == filename: return shed_config_dict - log.warning("'{}' not among installable tool config files ({})".format(filename, ', '.join(dynamic_tool_conf_paths))) + log.warning(f"'{filename}' not among installable tool config files ({', '.join(dynamic_tool_conf_paths)})") return None def update_shed_config(self, shed_conf): diff --git a/lib/galaxy/util/bool_expressions.py b/lib/galaxy/util/bool_expressions.py index cd93cb2ec89..ca65c175344 100644 --- a/lib/galaxy/util/bool_expressions.py +++ b/lib/galaxy/util/bool_expressions.py @@ -29,7 +29,7 @@ ParserElement.enablePackrat() # Defines the allowed characters that form a valid token. # Tokens that don't match this format will raise an exception when found. -DEFAULT_TOKEN_FORMAT = alphanums + "_-@." +DEFAULT_TOKEN_FORMAT = f"{alphanums}_-@." TRUE = Keyword("True") FALSE = Keyword("False") diff --git a/lib/galaxy/util/json.py b/lib/galaxy/util/json.py index 6ef84d34aab..b33f7c3d29c 100644 --- a/lib/galaxy/util/json.py +++ b/lib/galaxy/util/json.py @@ -115,7 +115,7 @@ def validate_jsonrpc_request(request, regular_methods, notification_methods): return False, request, jsonrpc_response(request=request, error=dict(code=-32601, message='Method not found', - data='Valid methods are: %s' % ', '.join(regular_methods + notification_methods))) + data=f"Valid methods are: {', '.join(regular_methods + notification_methods)}")) try: if request['method'] in regular_methods: assert 'id' in request, f"No \"id\" member was sent with the Request object and the requested method \"{request['method']}\" is not a notification method" diff --git a/lib/galaxy/util/pastescript/loadwsgi.py b/lib/galaxy/util/pastescript/loadwsgi.py index 6e84867de35..2bb816d0e4d 100644 --- a/lib/galaxy/util/pastescript/loadwsgi.py +++ b/lib/galaxy/util/pastescript/loadwsgi.py @@ -65,7 +65,7 @@ def fix_type_error(exc_info, callable, varargs, kwargs): args += ', ' if kwargs: kwargs = sorted(kwargs.keys()) - args += ', '.join('%s=...' % n for n in kwargs) + args += ', '.join(f'{n}=...' for n in kwargs) gotspec = f'({args})' msg = f'{exc_info[1]}; got {gotspec}, wanted {argspec}' exc_info[1].args = (msg,) diff --git a/lib/galaxy/util/rules_dsl.py b/lib/galaxy/util/rules_dsl.py index 0b79ec2e80f..47a94a759da 100644 --- a/lib/galaxy/util/rules_dsl.py +++ b/lib/galaxy/util/rules_dsl.py @@ -560,9 +560,9 @@ class RuleSet: @property def display(self): message = "Rules:\n" - message += "".join("- %s\n" % r for r in self.raw_rules) + message += "".join(f"- {r}\n" for r in self.raw_rules) message += "Column Definitions:\n" - message += "".join("- %s\n" % m for m in self.raw_mapping) + message += "".join(f"- {m}\n" for m in self.raw_mapping) return message diff --git a/lib/galaxy/version.py b/lib/galaxy/version.py index 008e7824155..323bec2c155 100644 --- a/lib/galaxy/version.py +++ b/lib/galaxy/version.py @@ -1,3 +1,3 @@ VERSION_MAJOR = "21.09" VERSION_MINOR = "dev0" -VERSION = VERSION_MAJOR + ('.' + VERSION_MINOR if VERSION_MINOR else '') +VERSION = VERSION_MAJOR + (f".{VERSION_MINOR}" if VERSION_MINOR else '') diff --git a/lib/galaxy/webapps/galaxy/api/folder_contents.py b/lib/galaxy/webapps/galaxy/api/folder_contents.py index 0fff9bb3c79..0eec9573261 100644 --- a/lib/galaxy/webapps/galaxy/api/folder_contents.py +++ b/lib/galaxy/webapps/galaxy/api/folder_contents.py @@ -239,7 +239,7 @@ class FolderContentsAPIView(UsesLibraryMixinItems): if ((len(encoded_folder_id) % 16 == 1) and encoded_folder_id.startswith('F')): return encoded_folder_id[1:] else: - raise exceptions.MalformedId('Malformed folder id ( %s ) specified, unable to decode.' % str(encoded_folder_id)) + raise exceptions.MalformedId(f'Malformed folder id ( {str(encoded_folder_id)} ) specified, unable to decode.') def _build_path(self, trans, folder): """ diff --git a/lib/galaxy/webapps/galaxy/controllers/admin.py b/lib/galaxy/webapps/galaxy/controllers/admin.py index d1eb6168f87..e0de451988b 100644 --- a/lib/galaxy/webapps/galaxy/controllers/admin.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin.py @@ -1369,7 +1369,7 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP if users: if trans.request.method == 'GET': return { - 'message': 'Changes password(s) for: %s.' % ', '.join(user.email for user in users.values()), + 'message': f"Changes password(s) for: {', '.join(user.email for user in users.values())}.", 'status': 'info', 'inputs': [{'name': 'password', 'label': 'New password', 'type': 'password'}, {'name': 'confirm', 'label': 'Confirm password', 'type': 'password'}] diff --git a/lib/galaxy/workflow/modules.py b/lib/galaxy/workflow/modules.py index e57bed5f79c..2c3751821a8 100644 --- a/lib/galaxy/workflow/modules.py +++ b/lib/galaxy/workflow/modules.py @@ -1122,7 +1122,7 @@ class InputParameterModule(WorkflowModule): return state def _parameter_option_def_to_tool_form_str(self, parameter_def): - return ",".join("{}:{}".format(o["value"], o["label"]) if isinstance(o, dict) else o for o in parameter_def) + return ",".join(f"{o['value']}:{o['label']}" if isinstance(o, dict) else o for o in parameter_def) def get_export_state(self): export_state = self._parse_state_into_dict() diff --git a/lib/galaxy_test/api/test_jobs.py b/lib/galaxy_test/api/test_jobs.py index 6b6263fadaf..0dcbad044c1 100644 --- a/lib/galaxy_test/api/test_jobs.py +++ b/lib/galaxy_test/api/test_jobs.py @@ -236,7 +236,7 @@ steps: job_lock_response.raise_for_status() assert not job_lock_response.json()["active"] - show_jobs_response = self._get("jobs/%s" % job_id, admin=False) + show_jobs_response = self._get(f"jobs/{job_id}", admin=False) self._assert_not_has_keys(show_jobs_response.json(), "external_id") # TODO: Re-activate test case when API accepts privacy settings diff --git a/lib/galaxy_test/selenium/test_library_landing.py b/lib/galaxy_test/selenium/test_library_landing.py index 2b0902db5b7..2f47e920e1d 100644 --- a/lib/galaxy_test/selenium/test_library_landing.py +++ b/lib/galaxy_test/selenium/test_library_landing.py @@ -75,10 +75,10 @@ class LibraryLandingTestCase(SeleniumTestCase): self.screenshot("libraries_index_search") # sort ascending self.libraries_index_sort_click() - self._assert_names_are([namebase + " a", namebase + " b", namebase + " c"]) + self._assert_names_are([f"{namebase} a", f"{namebase} b", f"{namebase} c"]) # sort descending self.libraries_index_sort_click() - self._assert_names_are([namebase + " c", namebase + " b", namebase + " a"]) + self._assert_names_are([f"{namebase} c", f"{namebase} b", f"{namebase} a"]) def _search_for_only_with_name(self, name): self.libraries_index_search_for(name) diff --git a/lib/galaxy_test/selenium/test_personal_information.py b/lib/galaxy_test/selenium/test_personal_information.py index 6d52dcb39d9..ebdaae2cc1d 100644 --- a/lib/galaxy_test/selenium/test_personal_information.py +++ b/lib/galaxy_test/selenium/test_personal_information.py @@ -127,7 +127,7 @@ class ManageInformationTestCase(SeleniumTestCase): element.send_keys(new_input_text) def get_address_input_field(self, address_form, input_field_label): - return address_form.find_element_by_css_selector("[data-label='" + input_field_label + "'] > input") + return address_form.find_element_by_css_selector(f"[data-label='{input_field_label}'] > input") class DeleteCurrentAccountTestCase(SeleniumTestCase): diff --git a/lib/tool_shed/test/base/twilltestcase.py b/lib/tool_shed/test/base/twilltestcase.py index ad4916aabcd..47cf5b8380a 100644 --- a/lib/tool_shed/test/base/twilltestcase.py +++ b/lib/tool_shed/test/base/twilltestcase.py @@ -486,7 +486,7 @@ class ShedTwillTestCase(DrivenFunctionalTestCase): valid_tools_only=False, uncompress_file=False, remove_repo_files_not_in_tar=False, - commit_message='Uploaded dependency on %s.' % ', '.join(repository_names), + commit_message=f"Uploaded dependency on {', '.join(repository_names)}.", strings_displayed=None, strings_not_displayed=None) diff --git a/lib/tool_shed/util/shed_util_common.py b/lib/tool_shed/util/shed_util_common.py index 01487d15831..cdfa1c727d1 100644 --- a/lib/tool_shed/util/shed_util_common.py +++ b/lib/tool_shed/util/shed_util_common.py @@ -384,7 +384,7 @@ def handle_email_alerts(app, host, repository, content_alert_str='', new_repo_al else: email_alerts.append(user.email) else: - subject = "Galaxy tool shed update alert for repository named %s" % str(repository.name) + subject = f"Galaxy tool shed update alert for repository named {str(repository.name)}" email_alerts = json.loads(repository.email_alerts) for email in email_alerts: to = email.strip() diff --git a/lib/tool_shed/webapp/controllers/repository_review.py b/lib/tool_shed/webapp/controllers/repository_review.py index 91ee640985f..339d948e020 100644 --- a/lib/tool_shed/webapp/controllers/repository_review.py +++ b/lib/tool_shed/webapp/controllers/repository_review.py @@ -341,7 +341,7 @@ class RepositoryReviewController(BaseUIController, ratings_util.ItemRatings): if revision_approved_setting_changed: message += f'Approved value {review.approved} saved for this revision.
    ' if saved_component_names: - message += 'Reviews were saved for components: %s' % ', '.join(saved_component_names) + message += f"Reviews were saved for components: {', '.join(saved_component_names)}" if not revision_approved_setting_changed and not saved_component_names: message += 'No changes were made to this review, so nothing was saved.' if review and review.approved: diff --git a/lib/tool_shed/webapp/model/__init__.py b/lib/tool_shed/webapp/model/__init__.py index 9dffc522f03..328d42ea322 100644 --- a/lib/tool_shed/webapp/model/__init__.py +++ b/lib/tool_shed/webapp/model/__init__.py @@ -313,7 +313,7 @@ class Repository(Dictifiable, _HasTable): for username in util.listify(usernames): if username not in allow_push: allow_push.append(username) - allow_push = '%s\n' % ','.join(allow_push) + allow_push = f"{','.join(allow_push)}\n" # Why doesn't the following work? # repo.ui.setconfig('web', 'allow_push', allow_push) repo_dir = self.repo_path() From e7d48d8f9a33632418969c9cac2adb78e08a2600 Mon Sep 17 00:00:00 2001 From: Dannon Baker Date: Tue, 11 May 2021 21:02:39 -0400 Subject: [PATCH 6/7] Fix old (minor) typo --- lib/galaxy/managers/taggable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/galaxy/managers/taggable.py b/lib/galaxy/managers/taggable.py index 4d63385f9fd..eb9baef9172 100644 --- a/lib/galaxy/managers/taggable.py +++ b/lib/galaxy/managers/taggable.py @@ -107,7 +107,7 @@ class TaggableFilterMixin: return True class_name = model_class.__name__ if class_name == 'HistoryDatasetCollectionAssociation': - # Unfortunately we were a little inconsistent with out naming scheme + # Unfortunately we were a little inconsistent with our naming scheme class_name = 'HistoryDatasetCollection' target_model = getattr(model, f"{class_name}TagAssociation") id_column = f"{target_model.table.name.rsplit('_tag_association')[0]}_id" From 35c35faa436ccd7b952292dfee46739dc559bb24 Mon Sep 17 00:00:00 2001 From: Dannon Baker Date: Tue, 11 May 2021 21:09:52 -0400 Subject: [PATCH 7/7] Fix sqlalchemy column handling -- this is so unintuitive :/ --- lib/galaxy/managers/taggable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/galaxy/managers/taggable.py b/lib/galaxy/managers/taggable.py index eb9baef9172..c4b8e0f1509 100644 --- a/lib/galaxy/managers/taggable.py +++ b/lib/galaxy/managers/taggable.py @@ -111,7 +111,7 @@ class TaggableFilterMixin: class_name = 'HistoryDatasetCollection' target_model = getattr(model, f"{class_name}TagAssociation") id_column = f"{target_model.table.name.rsplit('_tag_association')[0]}_id" - column = f"{target_model.table.c.user_tname}:{target_model.table.c.user_value}" + column = target_model.table.c.user_tname + ":" + target_model.table.c.user_value if op == 'eq': if ':' not in val: # We require an exact match and the tag to look for has no user_value,