dxpy 0.392.0__tar.gz → 0.394.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dxpy-0.392.0 → dxpy-0.394.0}/PKG-INFO +1 -1
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/__init__.py +9 -9
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/dxfile.py +20 -42
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/nextflow/nextflow_builder.py +2 -1
- dxpy-0.394.0/dxpy/toolkit_version.py +1 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy.egg-info/PKG-INFO +1 -1
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_dxclient.py +19 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_dxpy.py +43 -21
- dxpy-0.392.0/dxpy/toolkit_version.py +0 -1
- {dxpy-0.392.0 → dxpy-0.394.0}/MANIFEST.in +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/Readme.md +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/api.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/app_builder.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/app_categories.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/asset_builder.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/__init__.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/apollo/__init__.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/apollo/cmd_line_options_validator.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/apollo/data_transformations.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/apollo/dataset.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/apollo/json_validation_by_schema.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/apollo/schemas/__init__.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/apollo/schemas/assay_filtering_conditions.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/apollo/schemas/assay_filtering_json_schemas.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/apollo/schemas/input_arguments_validation_schemas.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/apollo/vizclient.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/apollo/vizserver_filters_from_json_parser.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/apollo/vizserver_payload_builder.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/auth.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/download_all_inputs.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/dxanalysis.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/dxapp.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/dxapp_container_functions.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/dxapplet.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/dxdatabase.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/dxdatabase_functions.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/dxdataobject_functions.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/dxfile_functions.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/dxglobalworkflow.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/dxjob.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/dxproject.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/dxrecord.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/dxworkflow.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/mount_all_inputs.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/search.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/cli/__init__.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/cli/cp.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/cli/dataset_utilities.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/cli/download.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/cli/exec_io.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/cli/help_messages.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/cli/org.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/cli/output_handling.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/cli/parsers.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/cli/workflow.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/compat.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/Homo_sapiens_genes_manifest.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/Homo_sapiens_genes_manifest_staging.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/Homo_sapiens_genes_manifest_staging_vep.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/Homo_sapiens_genes_manifest_vep.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/__init__.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/cohort_filter_payload.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/column_conditions.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/column_conversion.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/filter_to_payload.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/germline_utils.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/input_validation.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/input_validation_somatic.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/retrieve_allele_schema.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/retrieve_annotation_schema.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/retrieve_bins.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/retrieve_genotype_schema.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/return_columns_allele.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/return_columns_annotation.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/return_columns_genotype.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/return_columns_genotype_only.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/somatic_filter_payload.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dxlog.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/exceptions.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/executable_builder.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/nextflow/ImageRef.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/nextflow/ImageRefFactory.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/nextflow/__init__.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/nextflow/awscli_assets.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/nextflow/awscli_assets.staging.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/nextflow/collect_images.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/nextflow/nextaur_assets.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/nextflow/nextaur_assets.staging.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/nextflow/nextflow_assets.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/nextflow/nextflow_assets.staging.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/nextflow/nextflow_templates.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/nextflow/nextflow_utils.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/packages/__init__.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/scripts/__init__.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/scripts/dx.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/scripts/dx_app_wizard.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/scripts/dx_build_app.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/scripts/dx_build_applet.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/ssh_tunnel_app_support.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/system_requirements.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/__init__.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/bash.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/python.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/Readme.md +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/bash/basic/dxapp.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/bash/basic/src/code.sh +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/bash/parallelized/dxapp.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/bash/parallelized/src/code.sh +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/bash/scatter-process-gather/dxapp.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/bash/scatter-process-gather/src/code.sh +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/nextflow/dxapp.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/nextflow/src/nextflow.sh +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/python/basic/dxapp.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/python/basic/src/code.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/python/basic/test/test.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/python/parallelized/dxapp.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/python/parallelized/src/code.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/python/parallelized/test/test.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/python/scatter-process-gather/dxapp.json +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/python/scatter-process-gather/src/code.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/python/scatter-process-gather/test/test.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/utils.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/__init__.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/batch_utils.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/completer.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/config.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/describe.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/exec_utils.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/executable_unbuilder.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/file_handle.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/file_load_utils.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/genomic_utils.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/job_log_client.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/local_exec_utils.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/pathmatch.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/pretty_print.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/printing.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/resolver.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/spelling_corrector.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/utils/version.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy/workflow_builder.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy.egg-info/SOURCES.txt +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy.egg-info/dependency_links.txt +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy.egg-info/entry_points.txt +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy.egg-info/not-zip-safe +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy.egg-info/requires.txt +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/dxpy.egg-info/top_level.txt +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/requirements.txt +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/requirements_setuptools.txt +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/requirements_test.txt +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/scripts/dx-clone-asset +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/scripts/dx-docker +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/scripts/dx-download-all-inputs +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/scripts/dx-fetch-bundled-depends +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/scripts/dx-generate-dxapp +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/scripts/dx-jobutil-add-output +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/scripts/dx-jobutil-dxlink +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/scripts/dx-jobutil-get-identity-token +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/scripts/dx-jobutil-new-job +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/scripts/dx-jobutil-parse-link +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/scripts/dx-jobutil-report-error +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/scripts/dx-log-stream +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/scripts/dx-mount-all-inputs +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/scripts/dx-notebook-reconnect +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/scripts/dx-print-bash-vars +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/scripts/dx-upload-all-outputs +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/setup.cfg +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/setup.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_batch.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_create_cohort.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_describe.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_dx-docker.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_dx_app_wizard.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_dx_bash_helpers.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_dx_completion.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_dx_symlink.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_dxabs.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_dxasset.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_dxpy_utils.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_dxunpack.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_extract_assay.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_extract_dataset.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_extract_expression.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_extract_somatic.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_nextflow.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_nextflow_ImageRef.py +0 -0
- {dxpy-0.392.0 → dxpy-0.394.0}/test/test_nextflow_ImageRefFactory.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dxpy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.394.0
|
|
4
4
|
Summary: DNAnexus Platform API bindings for Python
|
|
5
5
|
Home-page: https://github.com/dnanexus/dx-toolkit
|
|
6
6
|
Author: Aleksandra Zalcman, Andrey Kislyuk, Anurag Biyani, Geet Duggal, Katherine Lai, Kurt Jensen, Marek Hrvol, Ohad Rodeh, Phil Sung
|
|
@@ -351,7 +351,7 @@ def _calculate_retry_delay(response, num_attempts):
|
|
|
351
351
|
resource, including the most recent failed one
|
|
352
352
|
:type num_attempts: int
|
|
353
353
|
'''
|
|
354
|
-
if response is not None and response.status
|
|
354
|
+
if response is not None and response.status in (503, 429) and 'retry-after' in response.headers:
|
|
355
355
|
try:
|
|
356
356
|
return int(response.headers['retry-after'])
|
|
357
357
|
except ValueError:
|
|
@@ -553,10 +553,10 @@ def DXHTTPRequest(resource, data, method='POST', headers=None, auth=True,
|
|
|
553
553
|
|
|
554
554
|
# Maintain two separate counters for the number of tries...
|
|
555
555
|
|
|
556
|
-
try_index = 0 # excluding 503 errors. The number of tries as given here
|
|
556
|
+
try_index = 0 # excluding 503/429 errors. The number of tries as given here
|
|
557
557
|
# cannot exceed (max_retries + 1).
|
|
558
|
-
|
|
559
|
-
|
|
558
|
+
try_index_including_throttled = 0 # including 503/429 errors. This number is used to
|
|
559
|
+
# do exponential backoff.
|
|
560
560
|
|
|
561
561
|
retried_responses = []
|
|
562
562
|
_url = None
|
|
@@ -730,7 +730,7 @@ def DXHTTPRequest(resource, data, method='POST', headers=None, auth=True,
|
|
|
730
730
|
or isinstance(e, _RETRYABLE_WITH_RESPONSE)):
|
|
731
731
|
ok_to_retry = is_retryable
|
|
732
732
|
else:
|
|
733
|
-
ok_to_retry = 500 <= response.status < 600
|
|
733
|
+
ok_to_retry = response.status == 429 or 500 <= response.status < 600
|
|
734
734
|
|
|
735
735
|
# The server has closed the connection prematurely
|
|
736
736
|
if (response is not None
|
|
@@ -753,10 +753,10 @@ def DXHTTPRequest(resource, data, method='POST', headers=None, auth=True,
|
|
|
753
753
|
if rewind_input_buffer_offset is not None:
|
|
754
754
|
data.seek(rewind_input_buffer_offset)
|
|
755
755
|
|
|
756
|
-
delay = _calculate_retry_delay(response,
|
|
756
|
+
delay = _calculate_retry_delay(response, try_index_including_throttled + 1)
|
|
757
757
|
|
|
758
758
|
range_str = (' (range=%s)' % (headers['Range'],)) if 'Range' in headers else ''
|
|
759
|
-
if response is not None and response.status
|
|
759
|
+
if response is not None and response.status in (503, 429):
|
|
760
760
|
waiting_msg = 'Waiting %d seconds before retry...' % (delay,)
|
|
761
761
|
else:
|
|
762
762
|
waiting_msg = 'Waiting %d seconds before retry %d of %d...' % (
|
|
@@ -768,8 +768,8 @@ def DXHTTPRequest(resource, data, method='POST', headers=None, auth=True,
|
|
|
768
768
|
|
|
769
769
|
logger.warning(log_msg)
|
|
770
770
|
time.sleep(delay)
|
|
771
|
-
|
|
772
|
-
if response is None or response.status
|
|
771
|
+
try_index_including_throttled += 1
|
|
772
|
+
if response is None or response.status not in (503, 429):
|
|
773
773
|
try_index += 1
|
|
774
774
|
continue
|
|
775
775
|
|
|
@@ -253,6 +253,8 @@ class DXFile(DXDataObject):
|
|
|
253
253
|
self._file_length = None
|
|
254
254
|
self._cur_part = 1
|
|
255
255
|
self._num_uploaded_parts = 0
|
|
256
|
+
# Cache for object existence in project
|
|
257
|
+
self._exists_in_proj = None
|
|
256
258
|
|
|
257
259
|
def _new(self, dx_hash, media_type=None, **kwargs):
|
|
258
260
|
"""
|
|
@@ -314,39 +316,19 @@ class DXFile(DXDataObject):
|
|
|
314
316
|
raise
|
|
315
317
|
|
|
316
318
|
def __iter__(self):
|
|
317
|
-
_buffer =
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
else:
|
|
331
|
-
_buffer = _buffer + more
|
|
332
|
-
else:
|
|
333
|
-
if self._binary_mode:
|
|
334
|
-
raise DXFileError("Cannot read lines when file opened in binary mode")
|
|
335
|
-
# python3 is much stricter about distinguishing
|
|
336
|
-
# 'bytes' from 'str'.
|
|
337
|
-
while not done:
|
|
338
|
-
if "\n" in _buffer:
|
|
339
|
-
lines = _buffer.splitlines()
|
|
340
|
-
for i in range(len(lines) - 1):
|
|
341
|
-
yield lines[i]
|
|
342
|
-
_buffer = lines[len(lines) - 1]
|
|
343
|
-
else:
|
|
344
|
-
more = self.read(self._read_bufsize)
|
|
345
|
-
if more == "":
|
|
346
|
-
done = True
|
|
347
|
-
else:
|
|
348
|
-
_buffer = _buffer + more
|
|
349
|
-
|
|
319
|
+
_buffer = ""
|
|
320
|
+
if self._binary_mode:
|
|
321
|
+
raise DXFileError("Cannot read lines when file opened in binary mode")
|
|
322
|
+
while True:
|
|
323
|
+
more = self.read(self._read_bufsize)
|
|
324
|
+
if not more:
|
|
325
|
+
break
|
|
326
|
+
_buffer += more
|
|
327
|
+
parts = _buffer.split("\n")
|
|
328
|
+
for i in range(len(parts) - 1):
|
|
329
|
+
yield parts[i]
|
|
330
|
+
# The final piece may be incomplete, so keep it in the buffer
|
|
331
|
+
_buffer = parts[-1]
|
|
350
332
|
if _buffer:
|
|
351
333
|
yield _buffer
|
|
352
334
|
|
|
@@ -954,18 +936,14 @@ class DXFile(DXDataObject):
|
|
|
954
936
|
buf.seek(orig_buf_pos)
|
|
955
937
|
return buf.read()
|
|
956
938
|
|
|
957
|
-
# Debug fallback
|
|
958
|
-
# import urllib2
|
|
959
|
-
# req = urllib2.Request(url, headers=headers)
|
|
960
|
-
# response = urllib2.urlopen(req)
|
|
961
|
-
# return response.read()
|
|
962
|
-
|
|
963
939
|
def read(self, length=None, use_compression=None, project=None, **kwargs):
|
|
964
|
-
if
|
|
940
|
+
# Check if the file is present in dxfile project attribute if the project arg not specified
|
|
941
|
+
if project is None and self._exists_in_proj is None and self.get_proj_id() is not None:
|
|
942
|
+
self._exists_in_proj = object_exists_in_project(self.get_id(), self.get_proj_id())
|
|
943
|
+
# Use the DXFile attribute if the project arg is not provided
|
|
944
|
+
if project is None and self._exists_in_proj:
|
|
965
945
|
project = self.get_proj_id()
|
|
966
946
|
data = self._read2(length=length, use_compression=use_compression, project=project, **kwargs)
|
|
967
|
-
if USING_PYTHON2:
|
|
968
|
-
return data
|
|
969
947
|
# In python3, the underlying system methods use the 'bytes' type, not 'string'
|
|
970
948
|
if self._binary_mode is True:
|
|
971
949
|
return data
|
|
@@ -182,7 +182,8 @@ def prepare_custom_inputs(schema_file="./nextflow_schema.json"):
|
|
|
182
182
|
|
|
183
183
|
with open(schema_file, "r") as fh:
|
|
184
184
|
schema = json.load(fh)
|
|
185
|
-
|
|
185
|
+
defs_key = "definitions" if "definitions" in schema else "$defs" if "$defs" in schema else {}
|
|
186
|
+
for d_key, d_schema in schema.get(defs_key).items():
|
|
186
187
|
required_inputs = d_schema.get("required", [])
|
|
187
188
|
for property_key, property in d_schema.get("properties", {}).items():
|
|
188
189
|
dx_input = {}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
version = '0.394.0'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dxpy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.394.0
|
|
4
4
|
Summary: DNAnexus Platform API bindings for Python
|
|
5
5
|
Home-page: https://github.com/dnanexus/dx-toolkit
|
|
6
6
|
Author: Aleksandra Zalcman, Andrey Kislyuk, Anurag Biyani, Geet Duggal, Katherine Lai, Kurt Jensen, Marek Hrvol, Ohad Rodeh, Phil Sung
|
|
@@ -1964,6 +1964,25 @@ dxpy.run()
|
|
|
1964
1964
|
run("cd {wd}; rm test; touch test".format(wd=wd))
|
|
1965
1965
|
run("cd {wd}; dx download -f test".format(wd=wd))
|
|
1966
1966
|
assert_md5_checksum(os.path.join(wd, "test"), hashlib.md5(part1 + part2))
|
|
1967
|
+
|
|
1968
|
+
def test_dx_download_api_call_count(self):
|
|
1969
|
+
"""
|
|
1970
|
+
Ensure that dx download does not make more than 4 API calls as observed in _DX_DEBUG output.
|
|
1971
|
+
"""
|
|
1972
|
+
with chdir(tempfile.mkdtemp()):
|
|
1973
|
+
# Create a test file and upload it
|
|
1974
|
+
test_file = dxpy.upload_string("test content", name="test_file", project=self.project, wait_on_close=True)
|
|
1975
|
+
test_file_id = test_file.get_id()
|
|
1976
|
+
|
|
1977
|
+
# Run dx download with _DX_DEBUG enabled
|
|
1978
|
+
(stdout, stderr) = run(f"_DX_DEBUG=1 dx download {test_file_id}", also_return_stderr=True)
|
|
1979
|
+
|
|
1980
|
+
# Count the number of API calls in the debug output
|
|
1981
|
+
api_call_count = len([line for line in stderr.splitlines() if line.startswith(">") and dxpy.APISERVER in line])
|
|
1982
|
+
|
|
1983
|
+
# Assert that no more than 4 API calls were made
|
|
1984
|
+
self.assertLessEqual(api_call_count, 4, f"dx download made {api_call_count} API calls, exceeding the limit of 4.\n_DX_DEBUG:\n{stderr}")
|
|
1985
|
+
|
|
1967
1986
|
|
|
1968
1987
|
|
|
1969
1988
|
class TestDXClientDownloadDataEgressBilling(DXTestCase):
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
from __future__ import print_function, unicode_literals, division, absolute_import
|
|
21
21
|
|
|
22
|
-
import os, unittest, tempfile, filecmp, time, json, sys
|
|
22
|
+
import os, unittest, tempfile, filecmp, time, json, sys, random
|
|
23
23
|
import shutil
|
|
24
24
|
import string
|
|
25
25
|
import subprocess
|
|
@@ -27,6 +27,7 @@ import platform
|
|
|
27
27
|
import pytest
|
|
28
28
|
import re
|
|
29
29
|
import certifi
|
|
30
|
+
from mock import patch
|
|
30
31
|
|
|
31
32
|
from urllib3.exceptions import SSLError, NewConnectionError
|
|
32
33
|
|
|
@@ -859,6 +860,47 @@ class TestDXFile(testutil.DXTestCaseCompat):
|
|
|
859
860
|
dxpy.WORKSPACE_ID = workspace_id
|
|
860
861
|
|
|
861
862
|
del os.environ['DX_JOB_ID']
|
|
863
|
+
|
|
864
|
+
def test_dxfile_read_api_call_count(self):
|
|
865
|
+
"""
|
|
866
|
+
Ensure that dxfile.read() does not make more than 4 API calls by counting DXHTTPRequest invocations
|
|
867
|
+
"""
|
|
868
|
+
print(sys.version)
|
|
869
|
+
with testutil.temporary_project() as project:
|
|
870
|
+
# Create a random 1KiB upload string
|
|
871
|
+
upload_string = ''.join(random.choices(string.ascii_lowercase + string.digits, k=1024))
|
|
872
|
+
dxfile = dxpy.upload_string(upload_string, project=project.get_id(), wait_on_close=True)
|
|
873
|
+
|
|
874
|
+
# Patch DXHTTPRequest to count its invocations
|
|
875
|
+
with patch("dxpy.DXHTTPRequest", wraps=dxpy.DXHTTPRequest) as mock_request:
|
|
876
|
+
# DXFile instantiated with project-id
|
|
877
|
+
dxfile.read()
|
|
878
|
+
# Count the number of DXHTTPRequest calls
|
|
879
|
+
api_call_count = mock_request.call_count
|
|
880
|
+
print(f"dxfile.read() made {api_call_count} API calls")
|
|
881
|
+
self.assertLessEqual(api_call_count, 4, f"dxfile.read() made {api_call_count} API calls, exceeding the limit.")
|
|
882
|
+
mock_request.reset_mock()
|
|
883
|
+
|
|
884
|
+
# DXFile instantiated without project-id
|
|
885
|
+
dxfile = dxpy.DXFile(dxfile.get_id(), project=None)
|
|
886
|
+
dxfile.read()
|
|
887
|
+
api_call_count = mock_request.call_count
|
|
888
|
+
print(f"dxfile.read() made {api_call_count} API calls")
|
|
889
|
+
self.assertLessEqual(api_call_count, 4, f"dxfile.read() made {api_call_count} API calls, exceeding the limit.")
|
|
890
|
+
mock_request.reset_mock()
|
|
891
|
+
|
|
892
|
+
# Call DXFile.read() 1024 times
|
|
893
|
+
dxfile = dxpy.DXFile(dxfile.get_id(), project=project.get_id())
|
|
894
|
+
while True:
|
|
895
|
+
data = dxfile.read(1)
|
|
896
|
+
if not data:
|
|
897
|
+
break
|
|
898
|
+
api_call_count = mock_request.call_count
|
|
899
|
+
print(f"dxfile.read() made {api_call_count} API calls")
|
|
900
|
+
self.assertLessEqual(api_call_count, 4, f"dxfile.read() made {api_call_count} API calls, exceeding the limit.")
|
|
901
|
+
mock_request.reset_mock()
|
|
902
|
+
|
|
903
|
+
|
|
862
904
|
|
|
863
905
|
|
|
864
906
|
class TestFolder(unittest.TestCase):
|
|
@@ -2551,26 +2593,6 @@ class TestHTTPResponses(testutil.DXTestCaseCompat):
|
|
|
2551
2593
|
with self.assertRaisesRegex((SSLError, IOError, OpenSSL.SSL.Error), "file"):
|
|
2552
2594
|
dxpy.DXHTTPRequest("/system/whoami", {}, cert_file="nonexistent")
|
|
2553
2595
|
|
|
2554
|
-
def test_fake_errors(self):
|
|
2555
|
-
dxpy.DXHTTPRequest('/system/fakeError', {'errorType': 'Valid JSON'}, always_retry=True)
|
|
2556
|
-
|
|
2557
|
-
# Minimal latency with retries, in seconds. This makes sure we actually did a retry.
|
|
2558
|
-
min_sec_with_retries = 1
|
|
2559
|
-
max_num_retries = 2
|
|
2560
|
-
start_time = time.time()
|
|
2561
|
-
with self.assertRaises(ValueError):
|
|
2562
|
-
dxpy.DXHTTPRequest('/system/fakeError', {'errorType': 'Invalid JSON'},
|
|
2563
|
-
max_retries=max_num_retries, always_retry=True)
|
|
2564
|
-
end_time = time.time()
|
|
2565
|
-
self.assertGreater(end_time - start_time, min_sec_with_retries)
|
|
2566
|
-
|
|
2567
|
-
start_time = time.time()
|
|
2568
|
-
with self.assertRaises(ValueError):
|
|
2569
|
-
dxpy.DXHTTPRequest('/system/fakeError', {'errorType': 'Error not decodeable'},
|
|
2570
|
-
max_retries=max_num_retries, always_retry=True)
|
|
2571
|
-
end_time = time.time()
|
|
2572
|
-
self.assertGreater(end_time - start_time, min_sec_with_retries)
|
|
2573
|
-
|
|
2574
2596
|
def test_system_headers_user_agent(self):
|
|
2575
2597
|
headers = dxpy.api.system_headers()
|
|
2576
2598
|
self.assertTrue('user-agent' in headers)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
version = '0.392.0'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dxpy-0.392.0 → dxpy-0.394.0}/dxpy/bindings/apollo/schemas/input_arguments_validation_schemas.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/Homo_sapiens_genes_manifest_staging.json
RENAMED
|
File without changes
|
{dxpy-0.392.0 → dxpy-0.394.0}/dxpy/dx_extract_utils/Homo_sapiens_genes_manifest_staging_vep.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/bash/scatter-process-gather/dxapp.json
RENAMED
|
File without changes
|
{dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/bash/scatter-process-gather/src/code.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/python/scatter-process-gather/dxapp.json
RENAMED
|
File without changes
|
{dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/python/scatter-process-gather/src/code.py
RENAMED
|
File without changes
|
{dxpy-0.392.0 → dxpy-0.394.0}/dxpy/templating/templates/python/scatter-process-gather/test/test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|