From d1060855a92285a598af159935fc81e6adf3eef0 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Tue, 16 Feb 2021 11:09:09 -0500 Subject: [PATCH 01/35] Experiment with updated settings. --- poetry.lock | 1394 ++++++++++++++++++++++++++---------------------- pyproject.toml | 105 ++-- 2 files changed, 809 insertions(+), 690 deletions(-) diff --git a/poetry.lock b/poetry.lock index cc1c7dfbd8..e93d1ca4f7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -6,6 +6,14 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "1.5" +[[package]] +category = "dev" +description = "Atomic file writes." +name = "atomicwrites" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.4.0" + [[package]] category = "main" description = "Classes Without Boilerplate" @@ -49,22 +57,16 @@ category = "main" description = "Universal Command Line Environment for AWS." name = "awscli" optional = false -python-versions = "*" -version = "1.16.314" +python-versions = ">= 2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +version = "1.19.8" [package.dependencies] -botocore = "1.13.50" +PyYAML = ">=3.10,<5.4" +botocore = "1.20.8" +colorama = ">=0.2.5,<0.4.4" docutils = ">=0.10,<0.16" -rsa = ">=3.1.2,<=3.5.0" -s3transfer = ">=0.2.0,<0.3.0" - -[package.dependencies.PyYAML] -python = "<2.6.0 || >=2.7.0,<3.3.0 || >=3.4.0" -version = ">=3.10,<5.3" - -[package.dependencies.colorama] -python = "<2.6.0 || >=2.7.0,<3.3.0 || >=3.4.0" -version = ">=0.2.5,<0.4.2" +rsa = ">=3.1.2,<=4.5.0" +s3transfer = ">=0.3.0,<0.4.0" [[package]] category = "main" @@ -104,21 +106,21 @@ category = "main" description = "The AWS SDK for Python" name = "boto3" optional = false -python-versions = "*" -version = "1.10.50" +python-versions = ">= 2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +version = "1.17.8" [package.dependencies] -botocore = ">=1.13.50,<1.14.0" +botocore = ">=1.20.8,<1.21.0" jmespath = ">=0.7.1,<1.0.0" -s3transfer = ">=0.2.0,<0.3.0" +s3transfer = ">=0.3.0,<0.4.0" [[package]] category = "dev" -description = "Type annotations for boto3 1.16.36, generated by mypy-boto3-buider 4.2.0" +description = "Type annotations for boto3 1.17.8, generated by mypy-boto3-buider 4.4.0" name = "boto3-stubs" optional = false python-versions = ">=3.6" -version = "1.16.36.0" +version = "1.17.8.0" [package.dependencies] [package.dependencies.typing-extensions] @@ -126,277 +128,279 @@ python = "<3.8" version = "*" [package.extras] -accessanalyzer = ["mypy-boto3-accessanalyzer (1.16.36.0)"] -acm = ["mypy-boto3-acm (1.16.36.0)"] -acm-pca = ["mypy-boto3-acm-pca (1.16.36.0)"] -alexaforbusiness = ["mypy-boto3-alexaforbusiness (1.16.36.0)"] -all = ["mypy-boto3-accessanalyzer (1.16.36.0)", "mypy-boto3-acm (1.16.36.0)", "mypy-boto3-acm-pca (1.16.36.0)", "mypy-boto3-alexaforbusiness (1.16.36.0)", "mypy-boto3-amplify (1.16.36.0)", "mypy-boto3-amplifybackend (1.16.36.0)", "mypy-boto3-apigateway (1.16.36.0)", "mypy-boto3-apigatewaymanagementapi (1.16.36.0)", "mypy-boto3-apigatewayv2 (1.16.36.0)", "mypy-boto3-appconfig (1.16.36.0)", "mypy-boto3-appflow (1.16.36.0)", "mypy-boto3-appintegrations (1.16.36.0)", "mypy-boto3-application-autoscaling (1.16.36.0)", "mypy-boto3-application-insights (1.16.36.0)", "mypy-boto3-appmesh (1.16.36.0)", "mypy-boto3-appstream (1.16.36.0)", "mypy-boto3-appsync (1.16.36.0)", "mypy-boto3-athena (1.16.36.0)", "mypy-boto3-auditmanager (1.16.36.0)", "mypy-boto3-autoscaling (1.16.36.0)", "mypy-boto3-autoscaling-plans (1.16.36.0)", "mypy-boto3-backup (1.16.36.0)", "mypy-boto3-batch (1.16.36.0)", "mypy-boto3-braket (1.16.36.0)", "mypy-boto3-budgets (1.16.36.0)", "mypy-boto3-ce (1.16.36.0)", "mypy-boto3-chime (1.16.36.0)", "mypy-boto3-cloud9 (1.16.36.0)", "mypy-boto3-clouddirectory (1.16.36.0)", "mypy-boto3-cloudformation (1.16.36.0)", "mypy-boto3-cloudfront (1.16.36.0)", "mypy-boto3-cloudhsm (1.16.36.0)", "mypy-boto3-cloudhsmv2 (1.16.36.0)", "mypy-boto3-cloudsearch (1.16.36.0)", "mypy-boto3-cloudsearchdomain (1.16.36.0)", "mypy-boto3-cloudtrail (1.16.36.0)", "mypy-boto3-cloudwatch (1.16.36.0)", "mypy-boto3-codeartifact (1.16.36.0)", "mypy-boto3-codebuild (1.16.36.0)", "mypy-boto3-codecommit (1.16.36.0)", "mypy-boto3-codedeploy (1.16.36.0)", "mypy-boto3-codeguru-reviewer (1.16.36.0)", "mypy-boto3-codeguruprofiler (1.16.36.0)", "mypy-boto3-codepipeline (1.16.36.0)", "mypy-boto3-codestar (1.16.36.0)", "mypy-boto3-codestar-connections (1.16.36.0)", "mypy-boto3-codestar-notifications (1.16.36.0)", "mypy-boto3-cognito-identity (1.16.36.0)", "mypy-boto3-cognito-idp (1.16.36.0)", "mypy-boto3-cognito-sync (1.16.36.0)", "mypy-boto3-comprehend (1.16.36.0)", "mypy-boto3-comprehendmedical (1.16.36.0)", "mypy-boto3-compute-optimizer (1.16.36.0)", "mypy-boto3-config (1.16.36.0)", "mypy-boto3-connect (1.16.36.0)", "mypy-boto3-connect-contact-lens (1.16.36.0)", "mypy-boto3-connectparticipant (1.16.36.0)", "mypy-boto3-cur (1.16.36.0)", "mypy-boto3-customer-profiles (1.16.36.0)", "mypy-boto3-databrew (1.16.36.0)", "mypy-boto3-dataexchange (1.16.36.0)", "mypy-boto3-datapipeline (1.16.36.0)", "mypy-boto3-datasync (1.16.36.0)", "mypy-boto3-dax (1.16.36.0)", "mypy-boto3-detective (1.16.36.0)", "mypy-boto3-devicefarm (1.16.36.0)", "mypy-boto3-devops-guru (1.16.36.0)", "mypy-boto3-directconnect (1.16.36.0)", "mypy-boto3-discovery (1.16.36.0)", "mypy-boto3-dlm (1.16.36.0)", "mypy-boto3-dms (1.16.36.0)", "mypy-boto3-docdb (1.16.36.0)", "mypy-boto3-ds (1.16.36.0)", "mypy-boto3-dynamodb (1.16.36.0)", "mypy-boto3-dynamodbstreams (1.16.36.0)", "mypy-boto3-ebs (1.16.36.0)", "mypy-boto3-ec2 (1.16.36.0)", "mypy-boto3-ec2-instance-connect (1.16.36.0)", "mypy-boto3-ecr (1.16.36.0)", "mypy-boto3-ecr-public (1.16.36.0)", "mypy-boto3-ecs (1.16.36.0)", "mypy-boto3-efs (1.16.36.0)", "mypy-boto3-eks (1.16.36.0)", "mypy-boto3-elastic-inference (1.16.36.0)", "mypy-boto3-elasticache (1.16.36.0)", "mypy-boto3-elasticbeanstalk (1.16.36.0)", "mypy-boto3-elastictranscoder (1.16.36.0)", "mypy-boto3-elb (1.16.36.0)", "mypy-boto3-elbv2 (1.16.36.0)", "mypy-boto3-emr (1.16.36.0)", "mypy-boto3-emr-containers (1.16.36.0)", "mypy-boto3-es (1.16.36.0)", "mypy-boto3-events (1.16.36.0)", "mypy-boto3-firehose (1.16.36.0)", "mypy-boto3-fms (1.16.36.0)", "mypy-boto3-forecast (1.16.36.0)", "mypy-boto3-forecastquery (1.16.36.0)", "mypy-boto3-frauddetector (1.16.36.0)", "mypy-boto3-fsx (1.16.36.0)", "mypy-boto3-gamelift (1.16.36.0)", "mypy-boto3-glacier (1.16.36.0)", "mypy-boto3-globalaccelerator (1.16.36.0)", "mypy-boto3-glue (1.16.36.0)", "mypy-boto3-greengrass (1.16.36.0)", "mypy-boto3-groundstation (1.16.36.0)", "mypy-boto3-guardduty (1.16.36.0)", "mypy-boto3-health (1.16.36.0)", "mypy-boto3-healthlake (1.16.36.0)", "mypy-boto3-honeycode (1.16.36.0)", "mypy-boto3-iam (1.16.36.0)", "mypy-boto3-identitystore (1.16.36.0)", "mypy-boto3-imagebuilder (1.16.36.0)", "mypy-boto3-importexport (1.16.36.0)", "mypy-boto3-inspector (1.16.36.0)", "mypy-boto3-iot (1.16.36.0)", "mypy-boto3-iot-data (1.16.36.0)", "mypy-boto3-iot-jobs-data (1.16.36.0)", "mypy-boto3-iot1click-devices (1.16.36.0)", "mypy-boto3-iot1click-projects (1.16.36.0)", "mypy-boto3-iotanalytics (1.16.36.0)", "mypy-boto3-iotevents (1.16.36.0)", "mypy-boto3-iotevents-data (1.16.36.0)", "mypy-boto3-iotsecuretunneling (1.16.36.0)", "mypy-boto3-iotsitewise (1.16.36.0)", "mypy-boto3-iotthingsgraph (1.16.36.0)", "mypy-boto3-ivs (1.16.36.0)", "mypy-boto3-kafka (1.16.36.0)", "mypy-boto3-kendra (1.16.36.0)", "mypy-boto3-kinesis (1.16.36.0)", "mypy-boto3-kinesis-video-archived-media (1.16.36.0)", "mypy-boto3-kinesis-video-media (1.16.36.0)", "mypy-boto3-kinesis-video-signaling (1.16.36.0)", "mypy-boto3-kinesisanalytics (1.16.36.0)", "mypy-boto3-kinesisanalyticsv2 (1.16.36.0)", "mypy-boto3-kinesisvideo (1.16.36.0)", "mypy-boto3-kms (1.16.36.0)", "mypy-boto3-lakeformation (1.16.36.0)", "mypy-boto3-lambda (1.16.36.0)", "mypy-boto3-lex-models (1.16.36.0)", "mypy-boto3-lex-runtime (1.16.36.0)", "mypy-boto3-license-manager (1.16.36.0)", "mypy-boto3-lightsail (1.16.36.0)", "mypy-boto3-logs (1.16.36.0)", "mypy-boto3-lookoutvision (1.16.36.0)", "mypy-boto3-machinelearning (1.16.36.0)", "mypy-boto3-macie (1.16.36.0)", "mypy-boto3-macie2 (1.16.36.0)", "mypy-boto3-managedblockchain (1.16.36.0)", "mypy-boto3-marketplace-catalog (1.16.36.0)", "mypy-boto3-marketplace-entitlement (1.16.36.0)", "mypy-boto3-marketplacecommerceanalytics (1.16.36.0)", "mypy-boto3-mediaconnect (1.16.36.0)", "mypy-boto3-mediaconvert (1.16.36.0)", "mypy-boto3-medialive (1.16.36.0)", "mypy-boto3-mediapackage (1.16.36.0)", "mypy-boto3-mediapackage-vod (1.16.36.0)", "mypy-boto3-mediastore (1.16.36.0)", "mypy-boto3-mediastore-data (1.16.36.0)", "mypy-boto3-mediatailor (1.16.36.0)", "mypy-boto3-meteringmarketplace (1.16.36.0)", "mypy-boto3-mgh (1.16.36.0)", "mypy-boto3-migrationhub-config (1.16.36.0)", "mypy-boto3-mobile (1.16.36.0)", "mypy-boto3-mq (1.16.36.0)", "mypy-boto3-mturk (1.16.36.0)", "mypy-boto3-mwaa (1.16.36.0)", "mypy-boto3-neptune (1.16.36.0)", "mypy-boto3-network-firewall (1.16.36.0)", "mypy-boto3-networkmanager (1.16.36.0)", "mypy-boto3-opsworks (1.16.36.0)", "mypy-boto3-opsworkscm (1.16.36.0)", "mypy-boto3-organizations (1.16.36.0)", "mypy-boto3-outposts (1.16.36.0)", "mypy-boto3-personalize (1.16.36.0)", "mypy-boto3-personalize-events (1.16.36.0)", "mypy-boto3-personalize-runtime (1.16.36.0)", "mypy-boto3-pi (1.16.36.0)", "mypy-boto3-pinpoint (1.16.36.0)", "mypy-boto3-pinpoint-email (1.16.36.0)", "mypy-boto3-pinpoint-sms-voice (1.16.36.0)", "mypy-boto3-polly (1.16.36.0)", "mypy-boto3-pricing (1.16.36.0)", "mypy-boto3-qldb (1.16.36.0)", "mypy-boto3-qldb-session (1.16.36.0)", "mypy-boto3-quicksight (1.16.36.0)", "mypy-boto3-ram (1.16.36.0)", "mypy-boto3-rds (1.16.36.0)", "mypy-boto3-rds-data (1.16.36.0)", "mypy-boto3-redshift (1.16.36.0)", "mypy-boto3-redshift-data (1.16.36.0)", "mypy-boto3-rekognition (1.16.36.0)", "mypy-boto3-resource-groups (1.16.36.0)", "mypy-boto3-resourcegroupstaggingapi (1.16.36.0)", "mypy-boto3-robomaker (1.16.36.0)", "mypy-boto3-route53 (1.16.36.0)", "mypy-boto3-route53domains (1.16.36.0)", "mypy-boto3-route53resolver (1.16.36.0)", "mypy-boto3-s3 (1.16.36.0)", "mypy-boto3-s3control (1.16.36.0)", "mypy-boto3-s3outposts (1.16.36.0)", "mypy-boto3-sagemaker (1.16.36.0)", "mypy-boto3-sagemaker-a2i-runtime (1.16.36.0)", "mypy-boto3-sagemaker-edge (1.16.36.0)", "mypy-boto3-sagemaker-featurestore-runtime (1.16.36.0)", "mypy-boto3-sagemaker-runtime (1.16.36.0)", "mypy-boto3-savingsplans (1.16.36.0)", "mypy-boto3-schemas (1.16.36.0)", "mypy-boto3-sdb (1.16.36.0)", "mypy-boto3-secretsmanager (1.16.36.0)", "mypy-boto3-securityhub (1.16.36.0)", "mypy-boto3-serverlessrepo (1.16.36.0)", "mypy-boto3-service-quotas (1.16.36.0)", "mypy-boto3-servicecatalog (1.16.36.0)", "mypy-boto3-servicecatalog-appregistry (1.16.36.0)", "mypy-boto3-servicediscovery (1.16.36.0)", "mypy-boto3-ses (1.16.36.0)", "mypy-boto3-sesv2 (1.16.36.0)", "mypy-boto3-shield (1.16.36.0)", "mypy-boto3-signer (1.16.36.0)", "mypy-boto3-sms (1.16.36.0)", "mypy-boto3-sms-voice (1.16.36.0)", "mypy-boto3-snowball (1.16.36.0)", "mypy-boto3-sns (1.16.36.0)", "mypy-boto3-sqs (1.16.36.0)", "mypy-boto3-ssm (1.16.36.0)", "mypy-boto3-sso (1.16.36.0)", "mypy-boto3-sso-admin (1.16.36.0)", "mypy-boto3-sso-oidc (1.16.36.0)", "mypy-boto3-stepfunctions (1.16.36.0)", "mypy-boto3-storagegateway (1.16.36.0)", "mypy-boto3-sts (1.16.36.0)", "mypy-boto3-support (1.16.36.0)", "mypy-boto3-swf (1.16.36.0)", "mypy-boto3-synthetics (1.16.36.0)", "mypy-boto3-textract (1.16.36.0)", "mypy-boto3-timestream-query (1.16.36.0)", "mypy-boto3-timestream-write (1.16.36.0)", "mypy-boto3-transcribe (1.16.36.0)", "mypy-boto3-transfer (1.16.36.0)", "mypy-boto3-translate (1.16.36.0)", "mypy-boto3-waf (1.16.36.0)", "mypy-boto3-waf-regional (1.16.36.0)", "mypy-boto3-wafv2 (1.16.36.0)", "mypy-boto3-workdocs (1.16.36.0)", "mypy-boto3-worklink (1.16.36.0)", "mypy-boto3-workmail (1.16.36.0)", "mypy-boto3-workmailmessageflow (1.16.36.0)", "mypy-boto3-workspaces (1.16.36.0)", "mypy-boto3-xray (1.16.36.0)"] -amplify = ["mypy-boto3-amplify (1.16.36.0)"] -amplifybackend = ["mypy-boto3-amplifybackend (1.16.36.0)"] -apigateway = ["mypy-boto3-apigateway (1.16.36.0)"] -apigatewaymanagementapi = ["mypy-boto3-apigatewaymanagementapi (1.16.36.0)"] -apigatewayv2 = ["mypy-boto3-apigatewayv2 (1.16.36.0)"] -appconfig = ["mypy-boto3-appconfig (1.16.36.0)"] -appflow = ["mypy-boto3-appflow (1.16.36.0)"] -appintegrations = ["mypy-boto3-appintegrations (1.16.36.0)"] -application-autoscaling = ["mypy-boto3-application-autoscaling (1.16.36.0)"] -application-insights = ["mypy-boto3-application-insights (1.16.36.0)"] -appmesh = ["mypy-boto3-appmesh (1.16.36.0)"] -appstream = ["mypy-boto3-appstream (1.16.36.0)"] -appsync = ["mypy-boto3-appsync (1.16.36.0)"] -athena = ["mypy-boto3-athena (1.16.36.0)"] -auditmanager = ["mypy-boto3-auditmanager (1.16.36.0)"] -autoscaling = ["mypy-boto3-autoscaling (1.16.36.0)"] -autoscaling-plans = ["mypy-boto3-autoscaling-plans (1.16.36.0)"] -backup = ["mypy-boto3-backup (1.16.36.0)"] -batch = ["mypy-boto3-batch (1.16.36.0)"] -braket = ["mypy-boto3-braket (1.16.36.0)"] -budgets = ["mypy-boto3-budgets (1.16.36.0)"] -ce = ["mypy-boto3-ce (1.16.36.0)"] -chime = ["mypy-boto3-chime (1.16.36.0)"] -cloud9 = ["mypy-boto3-cloud9 (1.16.36.0)"] -clouddirectory = ["mypy-boto3-clouddirectory (1.16.36.0)"] -cloudformation = ["mypy-boto3-cloudformation (1.16.36.0)"] -cloudfront = ["mypy-boto3-cloudfront (1.16.36.0)"] -cloudhsm = ["mypy-boto3-cloudhsm (1.16.36.0)"] -cloudhsmv2 = ["mypy-boto3-cloudhsmv2 (1.16.36.0)"] -cloudsearch = ["mypy-boto3-cloudsearch (1.16.36.0)"] -cloudsearchdomain = ["mypy-boto3-cloudsearchdomain (1.16.36.0)"] -cloudtrail = ["mypy-boto3-cloudtrail (1.16.36.0)"] -cloudwatch = ["mypy-boto3-cloudwatch (1.16.36.0)"] -codeartifact = ["mypy-boto3-codeartifact (1.16.36.0)"] -codebuild = ["mypy-boto3-codebuild (1.16.36.0)"] -codecommit = ["mypy-boto3-codecommit (1.16.36.0)"] -codedeploy = ["mypy-boto3-codedeploy (1.16.36.0)"] -codeguru-reviewer = ["mypy-boto3-codeguru-reviewer (1.16.36.0)"] -codeguruprofiler = ["mypy-boto3-codeguruprofiler (1.16.36.0)"] -codepipeline = ["mypy-boto3-codepipeline (1.16.36.0)"] -codestar = ["mypy-boto3-codestar (1.16.36.0)"] -codestar-connections = ["mypy-boto3-codestar-connections (1.16.36.0)"] -codestar-notifications = ["mypy-boto3-codestar-notifications (1.16.36.0)"] -cognito-identity = ["mypy-boto3-cognito-identity (1.16.36.0)"] -cognito-idp = ["mypy-boto3-cognito-idp (1.16.36.0)"] -cognito-sync = ["mypy-boto3-cognito-sync (1.16.36.0)"] -comprehend = ["mypy-boto3-comprehend (1.16.36.0)"] -comprehendmedical = ["mypy-boto3-comprehendmedical (1.16.36.0)"] -compute-optimizer = ["mypy-boto3-compute-optimizer (1.16.36.0)"] -config = ["mypy-boto3-config (1.16.36.0)"] -connect = ["mypy-boto3-connect (1.16.36.0)"] -connect-contact-lens = ["mypy-boto3-connect-contact-lens (1.16.36.0)"] -connectparticipant = ["mypy-boto3-connectparticipant (1.16.36.0)"] -cur = ["mypy-boto3-cur (1.16.36.0)"] -customer-profiles = ["mypy-boto3-customer-profiles (1.16.36.0)"] -databrew = ["mypy-boto3-databrew (1.16.36.0)"] -dataexchange = ["mypy-boto3-dataexchange (1.16.36.0)"] -datapipeline = ["mypy-boto3-datapipeline (1.16.36.0)"] -datasync = ["mypy-boto3-datasync (1.16.36.0)"] -dax = ["mypy-boto3-dax (1.16.36.0)"] -detective = ["mypy-boto3-detective (1.16.36.0)"] -devicefarm = ["mypy-boto3-devicefarm (1.16.36.0)"] -devops-guru = ["mypy-boto3-devops-guru (1.16.36.0)"] -directconnect = ["mypy-boto3-directconnect (1.16.36.0)"] -discovery = ["mypy-boto3-discovery (1.16.36.0)"] -dlm = ["mypy-boto3-dlm (1.16.36.0)"] -dms = ["mypy-boto3-dms (1.16.36.0)"] -docdb = ["mypy-boto3-docdb (1.16.36.0)"] -ds = ["mypy-boto3-ds (1.16.36.0)"] -dynamodb = ["mypy-boto3-dynamodb (1.16.36.0)"] -dynamodbstreams = ["mypy-boto3-dynamodbstreams (1.16.36.0)"] -ebs = ["mypy-boto3-ebs (1.16.36.0)"] -ec2 = ["mypy-boto3-ec2 (1.16.36.0)"] -ec2-instance-connect = ["mypy-boto3-ec2-instance-connect (1.16.36.0)"] -ecr = ["mypy-boto3-ecr (1.16.36.0)"] -ecr-public = ["mypy-boto3-ecr-public (1.16.36.0)"] -ecs = ["mypy-boto3-ecs (1.16.36.0)"] -efs = ["mypy-boto3-efs (1.16.36.0)"] -eks = ["mypy-boto3-eks (1.16.36.0)"] -elastic-inference = ["mypy-boto3-elastic-inference (1.16.36.0)"] -elasticache = ["mypy-boto3-elasticache (1.16.36.0)"] -elasticbeanstalk = ["mypy-boto3-elasticbeanstalk (1.16.36.0)"] -elastictranscoder = ["mypy-boto3-elastictranscoder (1.16.36.0)"] -elb = ["mypy-boto3-elb (1.16.36.0)"] -elbv2 = ["mypy-boto3-elbv2 (1.16.36.0)"] -emr = ["mypy-boto3-emr (1.16.36.0)"] -emr-containers = ["mypy-boto3-emr-containers (1.16.36.0)"] -es = ["mypy-boto3-es (1.16.36.0)"] -essential = ["mypy-boto3-cloudformation (1.16.36.0)", "mypy-boto3-dynamodb (1.16.36.0)", "mypy-boto3-ec2 (1.16.36.0)", "mypy-boto3-lambda (1.16.36.0)", "mypy-boto3-rds (1.16.36.0)", "mypy-boto3-s3 (1.16.36.0)", "mypy-boto3-sqs (1.16.36.0)"] -events = ["mypy-boto3-events (1.16.36.0)"] -firehose = ["mypy-boto3-firehose (1.16.36.0)"] -fms = ["mypy-boto3-fms (1.16.36.0)"] -forecast = ["mypy-boto3-forecast (1.16.36.0)"] -forecastquery = ["mypy-boto3-forecastquery (1.16.36.0)"] -frauddetector = ["mypy-boto3-frauddetector (1.16.36.0)"] -fsx = ["mypy-boto3-fsx (1.16.36.0)"] -gamelift = ["mypy-boto3-gamelift (1.16.36.0)"] -glacier = ["mypy-boto3-glacier (1.16.36.0)"] -globalaccelerator = ["mypy-boto3-globalaccelerator (1.16.36.0)"] -glue = ["mypy-boto3-glue (1.16.36.0)"] -greengrass = ["mypy-boto3-greengrass (1.16.36.0)"] -groundstation = ["mypy-boto3-groundstation (1.16.36.0)"] -guardduty = ["mypy-boto3-guardduty (1.16.36.0)"] -health = ["mypy-boto3-health (1.16.36.0)"] -healthlake = ["mypy-boto3-healthlake (1.16.36.0)"] -honeycode = ["mypy-boto3-honeycode (1.16.36.0)"] -iam = ["mypy-boto3-iam (1.16.36.0)"] -identitystore = ["mypy-boto3-identitystore (1.16.36.0)"] -imagebuilder = ["mypy-boto3-imagebuilder (1.16.36.0)"] -importexport = ["mypy-boto3-importexport (1.16.36.0)"] -inspector = ["mypy-boto3-inspector (1.16.36.0)"] -iot = ["mypy-boto3-iot (1.16.36.0)"] -iot-data = ["mypy-boto3-iot-data (1.16.36.0)"] -iot-jobs-data = ["mypy-boto3-iot-jobs-data (1.16.36.0)"] -iot1click-devices = ["mypy-boto3-iot1click-devices (1.16.36.0)"] -iot1click-projects = ["mypy-boto3-iot1click-projects (1.16.36.0)"] -iotanalytics = ["mypy-boto3-iotanalytics (1.16.36.0)"] -iotevents = ["mypy-boto3-iotevents (1.16.36.0)"] -iotevents-data = ["mypy-boto3-iotevents-data (1.16.36.0)"] -iotsecuretunneling = ["mypy-boto3-iotsecuretunneling (1.16.36.0)"] -iotsitewise = ["mypy-boto3-iotsitewise (1.16.36.0)"] -iotthingsgraph = ["mypy-boto3-iotthingsgraph (1.16.36.0)"] -ivs = ["mypy-boto3-ivs (1.16.36.0)"] -kafka = ["mypy-boto3-kafka (1.16.36.0)"] -kendra = ["mypy-boto3-kendra (1.16.36.0)"] -kinesis = ["mypy-boto3-kinesis (1.16.36.0)"] -kinesis-video-archived-media = ["mypy-boto3-kinesis-video-archived-media (1.16.36.0)"] -kinesis-video-media = ["mypy-boto3-kinesis-video-media (1.16.36.0)"] -kinesis-video-signaling = ["mypy-boto3-kinesis-video-signaling (1.16.36.0)"] -kinesisanalytics = ["mypy-boto3-kinesisanalytics (1.16.36.0)"] -kinesisanalyticsv2 = ["mypy-boto3-kinesisanalyticsv2 (1.16.36.0)"] -kinesisvideo = ["mypy-boto3-kinesisvideo (1.16.36.0)"] -kms = ["mypy-boto3-kms (1.16.36.0)"] -lakeformation = ["mypy-boto3-lakeformation (1.16.36.0)"] -lambda = ["mypy-boto3-lambda (1.16.36.0)"] -lex-models = ["mypy-boto3-lex-models (1.16.36.0)"] -lex-runtime = ["mypy-boto3-lex-runtime (1.16.36.0)"] -license-manager = ["mypy-boto3-license-manager (1.16.36.0)"] -lightsail = ["mypy-boto3-lightsail (1.16.36.0)"] -logs = ["mypy-boto3-logs (1.16.36.0)"] -lookoutvision = ["mypy-boto3-lookoutvision (1.16.36.0)"] -machinelearning = ["mypy-boto3-machinelearning (1.16.36.0)"] -macie = ["mypy-boto3-macie (1.16.36.0)"] -macie2 = ["mypy-boto3-macie2 (1.16.36.0)"] -managedblockchain = ["mypy-boto3-managedblockchain (1.16.36.0)"] -marketplace-catalog = ["mypy-boto3-marketplace-catalog (1.16.36.0)"] -marketplace-entitlement = ["mypy-boto3-marketplace-entitlement (1.16.36.0)"] -marketplacecommerceanalytics = ["mypy-boto3-marketplacecommerceanalytics (1.16.36.0)"] -mediaconnect = ["mypy-boto3-mediaconnect (1.16.36.0)"] -mediaconvert = ["mypy-boto3-mediaconvert (1.16.36.0)"] -medialive = ["mypy-boto3-medialive (1.16.36.0)"] -mediapackage = ["mypy-boto3-mediapackage (1.16.36.0)"] -mediapackage-vod = ["mypy-boto3-mediapackage-vod (1.16.36.0)"] -mediastore = ["mypy-boto3-mediastore (1.16.36.0)"] -mediastore-data = ["mypy-boto3-mediastore-data (1.16.36.0)"] -mediatailor = ["mypy-boto3-mediatailor (1.16.36.0)"] -meteringmarketplace = ["mypy-boto3-meteringmarketplace (1.16.36.0)"] -mgh = ["mypy-boto3-mgh (1.16.36.0)"] -migrationhub-config = ["mypy-boto3-migrationhub-config (1.16.36.0)"] -mobile = ["mypy-boto3-mobile (1.16.36.0)"] -mq = ["mypy-boto3-mq (1.16.36.0)"] -mturk = ["mypy-boto3-mturk (1.16.36.0)"] -mwaa = ["mypy-boto3-mwaa (1.16.36.0)"] -neptune = ["mypy-boto3-neptune (1.16.36.0)"] -network-firewall = ["mypy-boto3-network-firewall (1.16.36.0)"] -networkmanager = ["mypy-boto3-networkmanager (1.16.36.0)"] -opsworks = ["mypy-boto3-opsworks (1.16.36.0)"] -opsworkscm = ["mypy-boto3-opsworkscm (1.16.36.0)"] -organizations = ["mypy-boto3-organizations (1.16.36.0)"] -outposts = ["mypy-boto3-outposts (1.16.36.0)"] -personalize = ["mypy-boto3-personalize (1.16.36.0)"] -personalize-events = ["mypy-boto3-personalize-events (1.16.36.0)"] -personalize-runtime = ["mypy-boto3-personalize-runtime (1.16.36.0)"] -pi = ["mypy-boto3-pi (1.16.36.0)"] -pinpoint = ["mypy-boto3-pinpoint (1.16.36.0)"] -pinpoint-email = ["mypy-boto3-pinpoint-email (1.16.36.0)"] -pinpoint-sms-voice = ["mypy-boto3-pinpoint-sms-voice (1.16.36.0)"] -polly = ["mypy-boto3-polly (1.16.36.0)"] -pricing = ["mypy-boto3-pricing (1.16.36.0)"] -qldb = ["mypy-boto3-qldb (1.16.36.0)"] -qldb-session = ["mypy-boto3-qldb-session (1.16.36.0)"] -quicksight = ["mypy-boto3-quicksight (1.16.36.0)"] -ram = ["mypy-boto3-ram (1.16.36.0)"] -rds = ["mypy-boto3-rds (1.16.36.0)"] -rds-data = ["mypy-boto3-rds-data (1.16.36.0)"] -redshift = ["mypy-boto3-redshift (1.16.36.0)"] -redshift-data = ["mypy-boto3-redshift-data (1.16.36.0)"] -rekognition = ["mypy-boto3-rekognition (1.16.36.0)"] -resource-groups = ["mypy-boto3-resource-groups (1.16.36.0)"] -resourcegroupstaggingapi = ["mypy-boto3-resourcegroupstaggingapi (1.16.36.0)"] -robomaker = ["mypy-boto3-robomaker (1.16.36.0)"] -route53 = ["mypy-boto3-route53 (1.16.36.0)"] -route53domains = ["mypy-boto3-route53domains (1.16.36.0)"] -route53resolver = ["mypy-boto3-route53resolver (1.16.36.0)"] -s3 = ["mypy-boto3-s3 (1.16.36.0)"] -s3control = ["mypy-boto3-s3control (1.16.36.0)"] -s3outposts = ["mypy-boto3-s3outposts (1.16.36.0)"] -sagemaker = ["mypy-boto3-sagemaker (1.16.36.0)"] -sagemaker-a2i-runtime = ["mypy-boto3-sagemaker-a2i-runtime (1.16.36.0)"] -sagemaker-edge = ["mypy-boto3-sagemaker-edge (1.16.36.0)"] -sagemaker-featurestore-runtime = ["mypy-boto3-sagemaker-featurestore-runtime (1.16.36.0)"] -sagemaker-runtime = ["mypy-boto3-sagemaker-runtime (1.16.36.0)"] -savingsplans = ["mypy-boto3-savingsplans (1.16.36.0)"] -schemas = ["mypy-boto3-schemas (1.16.36.0)"] -sdb = ["mypy-boto3-sdb (1.16.36.0)"] -secretsmanager = ["mypy-boto3-secretsmanager (1.16.36.0)"] -securityhub = ["mypy-boto3-securityhub (1.16.36.0)"] -serverlessrepo = ["mypy-boto3-serverlessrepo (1.16.36.0)"] -service-quotas = ["mypy-boto3-service-quotas (1.16.36.0)"] -servicecatalog = ["mypy-boto3-servicecatalog (1.16.36.0)"] -servicecatalog-appregistry = ["mypy-boto3-servicecatalog-appregistry (1.16.36.0)"] -servicediscovery = ["mypy-boto3-servicediscovery (1.16.36.0)"] -ses = ["mypy-boto3-ses (1.16.36.0)"] -sesv2 = ["mypy-boto3-sesv2 (1.16.36.0)"] -shield = ["mypy-boto3-shield (1.16.36.0)"] -signer = ["mypy-boto3-signer (1.16.36.0)"] -sms = ["mypy-boto3-sms (1.16.36.0)"] -sms-voice = ["mypy-boto3-sms-voice (1.16.36.0)"] -snowball = ["mypy-boto3-snowball (1.16.36.0)"] -sns = ["mypy-boto3-sns (1.16.36.0)"] -sqs = ["mypy-boto3-sqs (1.16.36.0)"] -ssm = ["mypy-boto3-ssm (1.16.36.0)"] -sso = ["mypy-boto3-sso (1.16.36.0)"] -sso-admin = ["mypy-boto3-sso-admin (1.16.36.0)"] -sso-oidc = ["mypy-boto3-sso-oidc (1.16.36.0)"] -stepfunctions = ["mypy-boto3-stepfunctions (1.16.36.0)"] -storagegateway = ["mypy-boto3-storagegateway (1.16.36.0)"] -sts = ["mypy-boto3-sts (1.16.36.0)"] -support = ["mypy-boto3-support (1.16.36.0)"] -swf = ["mypy-boto3-swf (1.16.36.0)"] -synthetics = ["mypy-boto3-synthetics (1.16.36.0)"] -textract = ["mypy-boto3-textract (1.16.36.0)"] -timestream-query = ["mypy-boto3-timestream-query (1.16.36.0)"] -timestream-write = ["mypy-boto3-timestream-write (1.16.36.0)"] -transcribe = ["mypy-boto3-transcribe (1.16.36.0)"] -transfer = ["mypy-boto3-transfer (1.16.36.0)"] -translate = ["mypy-boto3-translate (1.16.36.0)"] -waf = ["mypy-boto3-waf (1.16.36.0)"] -waf-regional = ["mypy-boto3-waf-regional (1.16.36.0)"] -wafv2 = ["mypy-boto3-wafv2 (1.16.36.0)"] -workdocs = ["mypy-boto3-workdocs (1.16.36.0)"] -worklink = ["mypy-boto3-worklink (1.16.36.0)"] -workmail = ["mypy-boto3-workmail (1.16.36.0)"] -workmailmessageflow = ["mypy-boto3-workmailmessageflow (1.16.36.0)"] -workspaces = ["mypy-boto3-workspaces (1.16.36.0)"] -xray = ["mypy-boto3-xray (1.16.36.0)"] +accessanalyzer = ["mypy-boto3-accessanalyzer (1.17.8.0)"] +acm = ["mypy-boto3-acm (1.17.8.0)"] +acm-pca = ["mypy-boto3-acm-pca (1.17.8.0)"] +alexaforbusiness = ["mypy-boto3-alexaforbusiness (1.17.8.0)"] +all = ["mypy-boto3-accessanalyzer (1.17.8.0)", "mypy-boto3-acm (1.17.8.0)", "mypy-boto3-acm-pca (1.17.8.0)", "mypy-boto3-alexaforbusiness (1.17.8.0)", "mypy-boto3-amp (1.17.8.0)", "mypy-boto3-amplify (1.17.8.0)", "mypy-boto3-amplifybackend (1.17.8.0)", "mypy-boto3-apigateway (1.17.8.0)", "mypy-boto3-apigatewaymanagementapi (1.17.8.0)", "mypy-boto3-apigatewayv2 (1.17.8.0)", "mypy-boto3-appconfig (1.17.8.0)", "mypy-boto3-appflow (1.17.8.0)", "mypy-boto3-appintegrations (1.17.8.0)", "mypy-boto3-application-autoscaling (1.17.8.0)", "mypy-boto3-application-insights (1.17.8.0)", "mypy-boto3-appmesh (1.17.8.0)", "mypy-boto3-appstream (1.17.8.0)", "mypy-boto3-appsync (1.17.8.0)", "mypy-boto3-athena (1.17.8.0)", "mypy-boto3-auditmanager (1.17.8.0)", "mypy-boto3-autoscaling (1.17.8.0)", "mypy-boto3-autoscaling-plans (1.17.8.0)", "mypy-boto3-backup (1.17.8.0)", "mypy-boto3-batch (1.17.8.0)", "mypy-boto3-braket (1.17.8.0)", "mypy-boto3-budgets (1.17.8.0)", "mypy-boto3-ce (1.17.8.0)", "mypy-boto3-chime (1.17.8.0)", "mypy-boto3-cloud9 (1.17.8.0)", "mypy-boto3-clouddirectory (1.17.8.0)", "mypy-boto3-cloudformation (1.17.8.0)", "mypy-boto3-cloudfront (1.17.8.0)", "mypy-boto3-cloudhsm (1.17.8.0)", "mypy-boto3-cloudhsmv2 (1.17.8.0)", "mypy-boto3-cloudsearch (1.17.8.0)", "mypy-boto3-cloudsearchdomain (1.17.8.0)", "mypy-boto3-cloudtrail (1.17.8.0)", "mypy-boto3-cloudwatch (1.17.8.0)", "mypy-boto3-codeartifact (1.17.8.0)", "mypy-boto3-codebuild (1.17.8.0)", "mypy-boto3-codecommit (1.17.8.0)", "mypy-boto3-codedeploy (1.17.8.0)", "mypy-boto3-codeguru-reviewer (1.17.8.0)", "mypy-boto3-codeguruprofiler (1.17.8.0)", "mypy-boto3-codepipeline (1.17.8.0)", "mypy-boto3-codestar (1.17.8.0)", "mypy-boto3-codestar-connections (1.17.8.0)", "mypy-boto3-codestar-notifications (1.17.8.0)", "mypy-boto3-cognito-identity (1.17.8.0)", "mypy-boto3-cognito-idp (1.17.8.0)", "mypy-boto3-cognito-sync (1.17.8.0)", "mypy-boto3-comprehend (1.17.8.0)", "mypy-boto3-comprehendmedical (1.17.8.0)", "mypy-boto3-compute-optimizer (1.17.8.0)", "mypy-boto3-config (1.17.8.0)", "mypy-boto3-connect (1.17.8.0)", "mypy-boto3-connect-contact-lens (1.17.8.0)", "mypy-boto3-connectparticipant (1.17.8.0)", "mypy-boto3-cur (1.17.8.0)", "mypy-boto3-customer-profiles (1.17.8.0)", "mypy-boto3-databrew (1.17.8.0)", "mypy-boto3-dataexchange (1.17.8.0)", "mypy-boto3-datapipeline (1.17.8.0)", "mypy-boto3-datasync (1.17.8.0)", "mypy-boto3-dax (1.17.8.0)", "mypy-boto3-detective (1.17.8.0)", "mypy-boto3-devicefarm (1.17.8.0)", "mypy-boto3-devops-guru (1.17.8.0)", "mypy-boto3-directconnect (1.17.8.0)", "mypy-boto3-discovery (1.17.8.0)", "mypy-boto3-dlm (1.17.8.0)", "mypy-boto3-dms (1.17.8.0)", "mypy-boto3-docdb (1.17.8.0)", "mypy-boto3-ds (1.17.8.0)", "mypy-boto3-dynamodb (1.17.8.0)", "mypy-boto3-dynamodbstreams (1.17.8.0)", "mypy-boto3-ebs (1.17.8.0)", "mypy-boto3-ec2 (1.17.8.0)", "mypy-boto3-ec2-instance-connect (1.17.8.0)", "mypy-boto3-ecr (1.17.8.0)", "mypy-boto3-ecr-public (1.17.8.0)", "mypy-boto3-ecs (1.17.8.0)", "mypy-boto3-efs (1.17.8.0)", "mypy-boto3-eks (1.17.8.0)", "mypy-boto3-elastic-inference (1.17.8.0)", "mypy-boto3-elasticache (1.17.8.0)", "mypy-boto3-elasticbeanstalk (1.17.8.0)", "mypy-boto3-elastictranscoder (1.17.8.0)", "mypy-boto3-elb (1.17.8.0)", "mypy-boto3-elbv2 (1.17.8.0)", "mypy-boto3-emr (1.17.8.0)", "mypy-boto3-emr-containers (1.17.8.0)", "mypy-boto3-es (1.17.8.0)", "mypy-boto3-events (1.17.8.0)", "mypy-boto3-firehose (1.17.8.0)", "mypy-boto3-fms (1.17.8.0)", "mypy-boto3-forecast (1.17.8.0)", "mypy-boto3-forecastquery (1.17.8.0)", "mypy-boto3-frauddetector (1.17.8.0)", "mypy-boto3-fsx (1.17.8.0)", "mypy-boto3-gamelift (1.17.8.0)", "mypy-boto3-glacier (1.17.8.0)", "mypy-boto3-globalaccelerator (1.17.8.0)", "mypy-boto3-glue (1.17.8.0)", "mypy-boto3-greengrass (1.17.8.0)", "mypy-boto3-greengrassv2 (1.17.8.0)", "mypy-boto3-groundstation (1.17.8.0)", "mypy-boto3-guardduty (1.17.8.0)", "mypy-boto3-health (1.17.8.0)", "mypy-boto3-healthlake (1.17.8.0)", "mypy-boto3-honeycode (1.17.8.0)", "mypy-boto3-iam (1.17.8.0)", "mypy-boto3-identitystore (1.17.8.0)", "mypy-boto3-imagebuilder (1.17.8.0)", "mypy-boto3-importexport (1.17.8.0)", "mypy-boto3-inspector (1.17.8.0)", "mypy-boto3-iot (1.17.8.0)", "mypy-boto3-iot-data (1.17.8.0)", "mypy-boto3-iot-jobs-data (1.17.8.0)", "mypy-boto3-iot1click-devices (1.17.8.0)", "mypy-boto3-iot1click-projects (1.17.8.0)", "mypy-boto3-iotanalytics (1.17.8.0)", "mypy-boto3-iotdeviceadvisor (1.17.8.0)", "mypy-boto3-iotevents (1.17.8.0)", "mypy-boto3-iotevents-data (1.17.8.0)", "mypy-boto3-iotfleethub (1.17.8.0)", "mypy-boto3-iotsecuretunneling (1.17.8.0)", "mypy-boto3-iotsitewise (1.17.8.0)", "mypy-boto3-iotthingsgraph (1.17.8.0)", "mypy-boto3-iotwireless (1.17.8.0)", "mypy-boto3-ivs (1.17.8.0)", "mypy-boto3-kafka (1.17.8.0)", "mypy-boto3-kendra (1.17.8.0)", "mypy-boto3-kinesis (1.17.8.0)", "mypy-boto3-kinesis-video-archived-media (1.17.8.0)", "mypy-boto3-kinesis-video-media (1.17.8.0)", "mypy-boto3-kinesis-video-signaling (1.17.8.0)", "mypy-boto3-kinesisanalytics (1.17.8.0)", "mypy-boto3-kinesisanalyticsv2 (1.17.8.0)", "mypy-boto3-kinesisvideo (1.17.8.0)", "mypy-boto3-kms (1.17.8.0)", "mypy-boto3-lakeformation (1.17.8.0)", "mypy-boto3-lambda (1.17.8.0)", "mypy-boto3-lex-models (1.17.8.0)", "mypy-boto3-lex-runtime (1.17.8.0)", "mypy-boto3-lexv2-models (1.17.8.0)", "mypy-boto3-lexv2-runtime (1.17.8.0)", "mypy-boto3-license-manager (1.17.8.0)", "mypy-boto3-lightsail (1.17.8.0)", "mypy-boto3-location (1.17.8.0)", "mypy-boto3-logs (1.17.8.0)", "mypy-boto3-lookoutvision (1.17.8.0)", "mypy-boto3-machinelearning (1.17.8.0)", "mypy-boto3-macie (1.17.8.0)", "mypy-boto3-macie2 (1.17.8.0)", "mypy-boto3-managedblockchain (1.17.8.0)", "mypy-boto3-marketplace-catalog (1.17.8.0)", "mypy-boto3-marketplace-entitlement (1.17.8.0)", "mypy-boto3-marketplacecommerceanalytics (1.17.8.0)", "mypy-boto3-mediaconnect (1.17.8.0)", "mypy-boto3-mediaconvert (1.17.8.0)", "mypy-boto3-medialive (1.17.8.0)", "mypy-boto3-mediapackage (1.17.8.0)", "mypy-boto3-mediapackage-vod (1.17.8.0)", "mypy-boto3-mediastore (1.17.8.0)", "mypy-boto3-mediastore-data (1.17.8.0)", "mypy-boto3-mediatailor (1.17.8.0)", "mypy-boto3-meteringmarketplace (1.17.8.0)", "mypy-boto3-mgh (1.17.8.0)", "mypy-boto3-migrationhub-config (1.17.8.0)", "mypy-boto3-mobile (1.17.8.0)", "mypy-boto3-mq (1.17.8.0)", "mypy-boto3-mturk (1.17.8.0)", "mypy-boto3-mwaa (1.17.8.0)", "mypy-boto3-neptune (1.17.8.0)", "mypy-boto3-network-firewall (1.17.8.0)", "mypy-boto3-networkmanager (1.17.8.0)", "mypy-boto3-opsworks (1.17.8.0)", "mypy-boto3-opsworkscm (1.17.8.0)", "mypy-boto3-organizations (1.17.8.0)", "mypy-boto3-outposts (1.17.8.0)", "mypy-boto3-personalize (1.17.8.0)", "mypy-boto3-personalize-events (1.17.8.0)", "mypy-boto3-personalize-runtime (1.17.8.0)", "mypy-boto3-pi (1.17.8.0)", "mypy-boto3-pinpoint (1.17.8.0)", "mypy-boto3-pinpoint-email (1.17.8.0)", "mypy-boto3-pinpoint-sms-voice (1.17.8.0)", "mypy-boto3-polly (1.17.8.0)", "mypy-boto3-pricing (1.17.8.0)", "mypy-boto3-qldb (1.17.8.0)", "mypy-boto3-qldb-session (1.17.8.0)", "mypy-boto3-quicksight (1.17.8.0)", "mypy-boto3-ram (1.17.8.0)", "mypy-boto3-rds (1.17.8.0)", "mypy-boto3-rds-data (1.17.8.0)", "mypy-boto3-redshift (1.17.8.0)", "mypy-boto3-redshift-data (1.17.8.0)", "mypy-boto3-rekognition (1.17.8.0)", "mypy-boto3-resource-groups (1.17.8.0)", "mypy-boto3-resourcegroupstaggingapi (1.17.8.0)", "mypy-boto3-robomaker (1.17.8.0)", "mypy-boto3-route53 (1.17.8.0)", "mypy-boto3-route53domains (1.17.8.0)", "mypy-boto3-route53resolver (1.17.8.0)", "mypy-boto3-s3 (1.17.8.0)", "mypy-boto3-s3control (1.17.8.0)", "mypy-boto3-s3outposts (1.17.8.0)", "mypy-boto3-sagemaker (1.17.8.0)", "mypy-boto3-sagemaker-a2i-runtime (1.17.8.0)", "mypy-boto3-sagemaker-edge (1.17.8.0)", "mypy-boto3-sagemaker-featurestore-runtime (1.17.8.0)", "mypy-boto3-sagemaker-runtime (1.17.8.0)", "mypy-boto3-savingsplans (1.17.8.0)", "mypy-boto3-schemas (1.17.8.0)", "mypy-boto3-sdb (1.17.8.0)", "mypy-boto3-secretsmanager (1.17.8.0)", "mypy-boto3-securityhub (1.17.8.0)", "mypy-boto3-serverlessrepo (1.17.8.0)", "mypy-boto3-service-quotas (1.17.8.0)", "mypy-boto3-servicecatalog (1.17.8.0)", "mypy-boto3-servicecatalog-appregistry (1.17.8.0)", "mypy-boto3-servicediscovery (1.17.8.0)", "mypy-boto3-ses (1.17.8.0)", "mypy-boto3-sesv2 (1.17.8.0)", "mypy-boto3-shield (1.17.8.0)", "mypy-boto3-signer (1.17.8.0)", "mypy-boto3-sms (1.17.8.0)", "mypy-boto3-sms-voice (1.17.8.0)", "mypy-boto3-snowball (1.17.8.0)", "mypy-boto3-sns (1.17.8.0)", "mypy-boto3-sqs (1.17.8.0)", "mypy-boto3-ssm (1.17.8.0)", "mypy-boto3-sso (1.17.8.0)", "mypy-boto3-sso-admin (1.17.8.0)", "mypy-boto3-sso-oidc (1.17.8.0)", "mypy-boto3-stepfunctions (1.17.8.0)", "mypy-boto3-storagegateway (1.17.8.0)", "mypy-boto3-sts (1.17.8.0)", "mypy-boto3-support (1.17.8.0)", "mypy-boto3-swf (1.17.8.0)", "mypy-boto3-synthetics (1.17.8.0)", "mypy-boto3-textract (1.17.8.0)", "mypy-boto3-timestream-query (1.17.8.0)", "mypy-boto3-timestream-write (1.17.8.0)", "mypy-boto3-transcribe (1.17.8.0)", "mypy-boto3-transfer (1.17.8.0)", "mypy-boto3-translate (1.17.8.0)", "mypy-boto3-waf (1.17.8.0)", "mypy-boto3-waf-regional (1.17.8.0)", "mypy-boto3-wafv2 (1.17.8.0)", "mypy-boto3-wellarchitected (1.17.8.0)", "mypy-boto3-workdocs (1.17.8.0)", "mypy-boto3-worklink (1.17.8.0)", "mypy-boto3-workmail (1.17.8.0)", "mypy-boto3-workmailmessageflow (1.17.8.0)", "mypy-boto3-workspaces (1.17.8.0)", "mypy-boto3-xray (1.17.8.0)"] +amp = ["mypy-boto3-amp (1.17.8.0)"] +amplify = ["mypy-boto3-amplify (1.17.8.0)"] +amplifybackend = ["mypy-boto3-amplifybackend (1.17.8.0)"] +apigateway = ["mypy-boto3-apigateway (1.17.8.0)"] +apigatewaymanagementapi = ["mypy-boto3-apigatewaymanagementapi (1.17.8.0)"] +apigatewayv2 = ["mypy-boto3-apigatewayv2 (1.17.8.0)"] +appconfig = ["mypy-boto3-appconfig (1.17.8.0)"] +appflow = ["mypy-boto3-appflow (1.17.8.0)"] +appintegrations = ["mypy-boto3-appintegrations (1.17.8.0)"] +application-autoscaling = ["mypy-boto3-application-autoscaling (1.17.8.0)"] +application-insights = ["mypy-boto3-application-insights (1.17.8.0)"] +appmesh = ["mypy-boto3-appmesh (1.17.8.0)"] +appstream = ["mypy-boto3-appstream (1.17.8.0)"] +appsync = ["mypy-boto3-appsync (1.17.8.0)"] +athena = ["mypy-boto3-athena (1.17.8.0)"] +auditmanager = ["mypy-boto3-auditmanager (1.17.8.0)"] +autoscaling = ["mypy-boto3-autoscaling (1.17.8.0)"] +autoscaling-plans = ["mypy-boto3-autoscaling-plans (1.17.8.0)"] +backup = ["mypy-boto3-backup (1.17.8.0)"] +batch = ["mypy-boto3-batch (1.17.8.0)"] +braket = ["mypy-boto3-braket (1.17.8.0)"] +budgets = ["mypy-boto3-budgets (1.17.8.0)"] +ce = ["mypy-boto3-ce (1.17.8.0)"] +chime = ["mypy-boto3-chime (1.17.8.0)"] +cloud9 = ["mypy-boto3-cloud9 (1.17.8.0)"] +clouddirectory = ["mypy-boto3-clouddirectory (1.17.8.0)"] +cloudformation = ["mypy-boto3-cloudformation (1.17.8.0)"] +cloudfront = ["mypy-boto3-cloudfront (1.17.8.0)"] +cloudhsm = ["mypy-boto3-cloudhsm (1.17.8.0)"] +cloudhsmv2 = ["mypy-boto3-cloudhsmv2 (1.17.8.0)"] +cloudsearch = ["mypy-boto3-cloudsearch (1.17.8.0)"] +cloudsearchdomain = ["mypy-boto3-cloudsearchdomain (1.17.8.0)"] +cloudtrail = ["mypy-boto3-cloudtrail (1.17.8.0)"] +cloudwatch = ["mypy-boto3-cloudwatch (1.17.8.0)"] +codeartifact = ["mypy-boto3-codeartifact (1.17.8.0)"] +codebuild = ["mypy-boto3-codebuild (1.17.8.0)"] +codecommit = ["mypy-boto3-codecommit (1.17.8.0)"] +codedeploy = ["mypy-boto3-codedeploy (1.17.8.0)"] +codeguru-reviewer = ["mypy-boto3-codeguru-reviewer (1.17.8.0)"] +codeguruprofiler = ["mypy-boto3-codeguruprofiler (1.17.8.0)"] +codepipeline = ["mypy-boto3-codepipeline (1.17.8.0)"] +codestar = ["mypy-boto3-codestar (1.17.8.0)"] +codestar-connections = ["mypy-boto3-codestar-connections (1.17.8.0)"] +codestar-notifications = ["mypy-boto3-codestar-notifications (1.17.8.0)"] +cognito-identity = ["mypy-boto3-cognito-identity (1.17.8.0)"] +cognito-idp = ["mypy-boto3-cognito-idp (1.17.8.0)"] +cognito-sync = ["mypy-boto3-cognito-sync (1.17.8.0)"] +comprehend = ["mypy-boto3-comprehend (1.17.8.0)"] +comprehendmedical = ["mypy-boto3-comprehendmedical (1.17.8.0)"] +compute-optimizer = ["mypy-boto3-compute-optimizer (1.17.8.0)"] +config = ["mypy-boto3-config (1.17.8.0)"] +connect = ["mypy-boto3-connect (1.17.8.0)"] +connect-contact-lens = ["mypy-boto3-connect-contact-lens (1.17.8.0)"] +connectparticipant = ["mypy-boto3-connectparticipant (1.17.8.0)"] +cur = ["mypy-boto3-cur (1.17.8.0)"] +customer-profiles = ["mypy-boto3-customer-profiles (1.17.8.0)"] +databrew = ["mypy-boto3-databrew (1.17.8.0)"] +dataexchange = ["mypy-boto3-dataexchange (1.17.8.0)"] +datapipeline = ["mypy-boto3-datapipeline (1.17.8.0)"] +datasync = ["mypy-boto3-datasync (1.17.8.0)"] +dax = ["mypy-boto3-dax (1.17.8.0)"] +detective = ["mypy-boto3-detective (1.17.8.0)"] +devicefarm = ["mypy-boto3-devicefarm (1.17.8.0)"] +devops-guru = ["mypy-boto3-devops-guru (1.17.8.0)"] +directconnect = ["mypy-boto3-directconnect (1.17.8.0)"] +discovery = ["mypy-boto3-discovery (1.17.8.0)"] +dlm = ["mypy-boto3-dlm (1.17.8.0)"] +dms = ["mypy-boto3-dms (1.17.8.0)"] +docdb = ["mypy-boto3-docdb (1.17.8.0)"] +ds = ["mypy-boto3-ds (1.17.8.0)"] +dynamodb = ["mypy-boto3-dynamodb (1.17.8.0)"] +dynamodbstreams = ["mypy-boto3-dynamodbstreams (1.17.8.0)"] +ebs = ["mypy-boto3-ebs (1.17.8.0)"] +ec2 = ["mypy-boto3-ec2 (1.17.8.0)"] +ec2-instance-connect = ["mypy-boto3-ec2-instance-connect (1.17.8.0)"] +ecr = ["mypy-boto3-ecr (1.17.8.0)"] +ecr-public = ["mypy-boto3-ecr-public (1.17.8.0)"] +ecs = ["mypy-boto3-ecs (1.17.8.0)"] +efs = ["mypy-boto3-efs (1.17.8.0)"] +eks = ["mypy-boto3-eks (1.17.8.0)"] +elastic-inference = ["mypy-boto3-elastic-inference (1.17.8.0)"] +elasticache = ["mypy-boto3-elasticache (1.17.8.0)"] +elasticbeanstalk = ["mypy-boto3-elasticbeanstalk (1.17.8.0)"] +elastictranscoder = ["mypy-boto3-elastictranscoder (1.17.8.0)"] +elb = ["mypy-boto3-elb (1.17.8.0)"] +elbv2 = ["mypy-boto3-elbv2 (1.17.8.0)"] +emr = ["mypy-boto3-emr (1.17.8.0)"] +emr-containers = ["mypy-boto3-emr-containers (1.17.8.0)"] +es = ["mypy-boto3-es (1.17.8.0)"] +essential = ["mypy-boto3-cloudformation (1.17.8.0)", "mypy-boto3-dynamodb (1.17.8.0)", "mypy-boto3-ec2 (1.17.8.0)", "mypy-boto3-lambda (1.17.8.0)", "mypy-boto3-rds (1.17.8.0)", "mypy-boto3-s3 (1.17.8.0)", "mypy-boto3-sqs (1.17.8.0)"] +events = ["mypy-boto3-events (1.17.8.0)"] +firehose = ["mypy-boto3-firehose (1.17.8.0)"] +fms = ["mypy-boto3-fms (1.17.8.0)"] +forecast = ["mypy-boto3-forecast (1.17.8.0)"] +forecastquery = ["mypy-boto3-forecastquery (1.17.8.0)"] +frauddetector = ["mypy-boto3-frauddetector (1.17.8.0)"] +fsx = ["mypy-boto3-fsx (1.17.8.0)"] +gamelift = ["mypy-boto3-gamelift (1.17.8.0)"] +glacier = ["mypy-boto3-glacier (1.17.8.0)"] +globalaccelerator = ["mypy-boto3-globalaccelerator (1.17.8.0)"] +glue = ["mypy-boto3-glue (1.17.8.0)"] +greengrass = ["mypy-boto3-greengrass (1.17.8.0)"] +greengrassv2 = ["mypy-boto3-greengrassv2 (1.17.8.0)"] +groundstation = ["mypy-boto3-groundstation (1.17.8.0)"] +guardduty = ["mypy-boto3-guardduty (1.17.8.0)"] +health = ["mypy-boto3-health (1.17.8.0)"] +healthlake = ["mypy-boto3-healthlake (1.17.8.0)"] +honeycode = ["mypy-boto3-honeycode (1.17.8.0)"] +iam = ["mypy-boto3-iam (1.17.8.0)"] +identitystore = ["mypy-boto3-identitystore (1.17.8.0)"] +imagebuilder = ["mypy-boto3-imagebuilder (1.17.8.0)"] +importexport = ["mypy-boto3-importexport (1.17.8.0)"] +inspector = ["mypy-boto3-inspector (1.17.8.0)"] +iot = ["mypy-boto3-iot (1.17.8.0)"] +iot-data = ["mypy-boto3-iot-data (1.17.8.0)"] +iot-jobs-data = ["mypy-boto3-iot-jobs-data (1.17.8.0)"] +iot1click-devices = ["mypy-boto3-iot1click-devices (1.17.8.0)"] +iot1click-projects = ["mypy-boto3-iot1click-projects (1.17.8.0)"] +iotanalytics = ["mypy-boto3-iotanalytics (1.17.8.0)"] +iotdeviceadvisor = ["mypy-boto3-iotdeviceadvisor (1.17.8.0)"] +iotevents = ["mypy-boto3-iotevents (1.17.8.0)"] +iotevents-data = ["mypy-boto3-iotevents-data (1.17.8.0)"] +iotfleethub = ["mypy-boto3-iotfleethub (1.17.8.0)"] +iotsecuretunneling = ["mypy-boto3-iotsecuretunneling (1.17.8.0)"] +iotsitewise = ["mypy-boto3-iotsitewise (1.17.8.0)"] +iotthingsgraph = ["mypy-boto3-iotthingsgraph (1.17.8.0)"] +iotwireless = ["mypy-boto3-iotwireless (1.17.8.0)"] +ivs = ["mypy-boto3-ivs (1.17.8.0)"] +kafka = ["mypy-boto3-kafka (1.17.8.0)"] +kendra = ["mypy-boto3-kendra (1.17.8.0)"] +kinesis = ["mypy-boto3-kinesis (1.17.8.0)"] +kinesis-video-archived-media = ["mypy-boto3-kinesis-video-archived-media (1.17.8.0)"] +kinesis-video-media = ["mypy-boto3-kinesis-video-media (1.17.8.0)"] +kinesis-video-signaling = ["mypy-boto3-kinesis-video-signaling (1.17.8.0)"] +kinesisanalytics = ["mypy-boto3-kinesisanalytics (1.17.8.0)"] +kinesisanalyticsv2 = ["mypy-boto3-kinesisanalyticsv2 (1.17.8.0)"] +kinesisvideo = ["mypy-boto3-kinesisvideo (1.17.8.0)"] +kms = ["mypy-boto3-kms (1.17.8.0)"] +lakeformation = ["mypy-boto3-lakeformation (1.17.8.0)"] +lambda = ["mypy-boto3-lambda (1.17.8.0)"] +lex-models = ["mypy-boto3-lex-models (1.17.8.0)"] +lex-runtime = ["mypy-boto3-lex-runtime (1.17.8.0)"] +lexv2-models = ["mypy-boto3-lexv2-models (1.17.8.0)"] +lexv2-runtime = ["mypy-boto3-lexv2-runtime (1.17.8.0)"] +license-manager = ["mypy-boto3-license-manager (1.17.8.0)"] +lightsail = ["mypy-boto3-lightsail (1.17.8.0)"] +location = ["mypy-boto3-location (1.17.8.0)"] +logs = ["mypy-boto3-logs (1.17.8.0)"] +lookoutvision = ["mypy-boto3-lookoutvision (1.17.8.0)"] +machinelearning = ["mypy-boto3-machinelearning (1.17.8.0)"] +macie = ["mypy-boto3-macie (1.17.8.0)"] +macie2 = ["mypy-boto3-macie2 (1.17.8.0)"] +managedblockchain = ["mypy-boto3-managedblockchain (1.17.8.0)"] +marketplace-catalog = ["mypy-boto3-marketplace-catalog (1.17.8.0)"] +marketplace-entitlement = ["mypy-boto3-marketplace-entitlement (1.17.8.0)"] +marketplacecommerceanalytics = ["mypy-boto3-marketplacecommerceanalytics (1.17.8.0)"] +mediaconnect = ["mypy-boto3-mediaconnect (1.17.8.0)"] +mediaconvert = ["mypy-boto3-mediaconvert (1.17.8.0)"] +medialive = ["mypy-boto3-medialive (1.17.8.0)"] +mediapackage = ["mypy-boto3-mediapackage (1.17.8.0)"] +mediapackage-vod = ["mypy-boto3-mediapackage-vod (1.17.8.0)"] +mediastore = ["mypy-boto3-mediastore (1.17.8.0)"] +mediastore-data = ["mypy-boto3-mediastore-data (1.17.8.0)"] +mediatailor = ["mypy-boto3-mediatailor (1.17.8.0)"] +meteringmarketplace = ["mypy-boto3-meteringmarketplace (1.17.8.0)"] +mgh = ["mypy-boto3-mgh (1.17.8.0)"] +migrationhub-config = ["mypy-boto3-migrationhub-config (1.17.8.0)"] +mobile = ["mypy-boto3-mobile (1.17.8.0)"] +mq = ["mypy-boto3-mq (1.17.8.0)"] +mturk = ["mypy-boto3-mturk (1.17.8.0)"] +mwaa = ["mypy-boto3-mwaa (1.17.8.0)"] +neptune = ["mypy-boto3-neptune (1.17.8.0)"] +network-firewall = ["mypy-boto3-network-firewall (1.17.8.0)"] +networkmanager = ["mypy-boto3-networkmanager (1.17.8.0)"] +opsworks = ["mypy-boto3-opsworks (1.17.8.0)"] +opsworkscm = ["mypy-boto3-opsworkscm (1.17.8.0)"] +organizations = ["mypy-boto3-organizations (1.17.8.0)"] +outposts = ["mypy-boto3-outposts (1.17.8.0)"] +personalize = ["mypy-boto3-personalize (1.17.8.0)"] +personalize-events = ["mypy-boto3-personalize-events (1.17.8.0)"] +personalize-runtime = ["mypy-boto3-personalize-runtime (1.17.8.0)"] +pi = ["mypy-boto3-pi (1.17.8.0)"] +pinpoint = ["mypy-boto3-pinpoint (1.17.8.0)"] +pinpoint-email = ["mypy-boto3-pinpoint-email (1.17.8.0)"] +pinpoint-sms-voice = ["mypy-boto3-pinpoint-sms-voice (1.17.8.0)"] +polly = ["mypy-boto3-polly (1.17.8.0)"] +pricing = ["mypy-boto3-pricing (1.17.8.0)"] +qldb = ["mypy-boto3-qldb (1.17.8.0)"] +qldb-session = ["mypy-boto3-qldb-session (1.17.8.0)"] +quicksight = ["mypy-boto3-quicksight (1.17.8.0)"] +ram = ["mypy-boto3-ram (1.17.8.0)"] +rds = ["mypy-boto3-rds (1.17.8.0)"] +rds-data = ["mypy-boto3-rds-data (1.17.8.0)"] +redshift = ["mypy-boto3-redshift (1.17.8.0)"] +redshift-data = ["mypy-boto3-redshift-data (1.17.8.0)"] +rekognition = ["mypy-boto3-rekognition (1.17.8.0)"] +resource-groups = ["mypy-boto3-resource-groups (1.17.8.0)"] +resourcegroupstaggingapi = ["mypy-boto3-resourcegroupstaggingapi (1.17.8.0)"] +robomaker = ["mypy-boto3-robomaker (1.17.8.0)"] +route53 = ["mypy-boto3-route53 (1.17.8.0)"] +route53domains = ["mypy-boto3-route53domains (1.17.8.0)"] +route53resolver = ["mypy-boto3-route53resolver (1.17.8.0)"] +s3 = ["mypy-boto3-s3 (1.17.8.0)"] +s3control = ["mypy-boto3-s3control (1.17.8.0)"] +s3outposts = ["mypy-boto3-s3outposts (1.17.8.0)"] +sagemaker = ["mypy-boto3-sagemaker (1.17.8.0)"] +sagemaker-a2i-runtime = ["mypy-boto3-sagemaker-a2i-runtime (1.17.8.0)"] +sagemaker-edge = ["mypy-boto3-sagemaker-edge (1.17.8.0)"] +sagemaker-featurestore-runtime = ["mypy-boto3-sagemaker-featurestore-runtime (1.17.8.0)"] +sagemaker-runtime = ["mypy-boto3-sagemaker-runtime (1.17.8.0)"] +savingsplans = ["mypy-boto3-savingsplans (1.17.8.0)"] +schemas = ["mypy-boto3-schemas (1.17.8.0)"] +sdb = ["mypy-boto3-sdb (1.17.8.0)"] +secretsmanager = ["mypy-boto3-secretsmanager (1.17.8.0)"] +securityhub = ["mypy-boto3-securityhub (1.17.8.0)"] +serverlessrepo = ["mypy-boto3-serverlessrepo (1.17.8.0)"] +service-quotas = ["mypy-boto3-service-quotas (1.17.8.0)"] +servicecatalog = ["mypy-boto3-servicecatalog (1.17.8.0)"] +servicecatalog-appregistry = ["mypy-boto3-servicecatalog-appregistry (1.17.8.0)"] +servicediscovery = ["mypy-boto3-servicediscovery (1.17.8.0)"] +ses = ["mypy-boto3-ses (1.17.8.0)"] +sesv2 = ["mypy-boto3-sesv2 (1.17.8.0)"] +shield = ["mypy-boto3-shield (1.17.8.0)"] +signer = ["mypy-boto3-signer (1.17.8.0)"] +sms = ["mypy-boto3-sms (1.17.8.0)"] +sms-voice = ["mypy-boto3-sms-voice (1.17.8.0)"] +snowball = ["mypy-boto3-snowball (1.17.8.0)"] +sns = ["mypy-boto3-sns (1.17.8.0)"] +sqs = ["mypy-boto3-sqs (1.17.8.0)"] +ssm = ["mypy-boto3-ssm (1.17.8.0)"] +sso = ["mypy-boto3-sso (1.17.8.0)"] +sso-admin = ["mypy-boto3-sso-admin (1.17.8.0)"] +sso-oidc = ["mypy-boto3-sso-oidc (1.17.8.0)"] +stepfunctions = ["mypy-boto3-stepfunctions (1.17.8.0)"] +storagegateway = ["mypy-boto3-storagegateway (1.17.8.0)"] +sts = ["mypy-boto3-sts (1.17.8.0)"] +support = ["mypy-boto3-support (1.17.8.0)"] +swf = ["mypy-boto3-swf (1.17.8.0)"] +synthetics = ["mypy-boto3-synthetics (1.17.8.0)"] +textract = ["mypy-boto3-textract (1.17.8.0)"] +timestream-query = ["mypy-boto3-timestream-query (1.17.8.0)"] +timestream-write = ["mypy-boto3-timestream-write (1.17.8.0)"] +transcribe = ["mypy-boto3-transcribe (1.17.8.0)"] +transfer = ["mypy-boto3-transfer (1.17.8.0)"] +translate = ["mypy-boto3-translate (1.17.8.0)"] +waf = ["mypy-boto3-waf (1.17.8.0)"] +waf-regional = ["mypy-boto3-waf-regional (1.17.8.0)"] +wafv2 = ["mypy-boto3-wafv2 (1.17.8.0)"] +wellarchitected = ["mypy-boto3-wellarchitected (1.17.8.0)"] +workdocs = ["mypy-boto3-workdocs (1.17.8.0)"] +worklink = ["mypy-boto3-worklink (1.17.8.0)"] +workmail = ["mypy-boto3-workmail (1.17.8.0)"] +workmailmessageflow = ["mypy-boto3-workmailmessageflow (1.17.8.0)"] +workspaces = ["mypy-boto3-workspaces (1.17.8.0)"] +xray = ["mypy-boto3-xray (1.17.8.0)"] [[package]] category = "main" description = "Low-level, data-driven core of boto 3." name = "botocore" optional = false -python-versions = "*" -version = "1.13.50" +python-versions = ">= 2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +version = "1.20.8" [package.dependencies] -docutils = ">=0.10,<0.16" jmespath = ">=0.7.1,<1.0.0" - -[package.dependencies.python-dateutil] -python = ">=2.7" -version = ">=2.1,<3.0.0" - -[package.dependencies.urllib3] -python = ">=3.4" -version = ">=1.20,<1.26" +python-dateutil = ">=2.1,<3.0.0" +urllib3 = ">=1.25.4,<1.27" [[package]] category = "main" @@ -412,7 +416,7 @@ description = "Foreign Function Interface for Python calling C code." name = "cffi" optional = false python-versions = "*" -version = "1.14.4" +version = "1.14.5" [package.dependencies] pycparser = "*" @@ -462,7 +466,7 @@ description = "Code coverage measurement for Python" name = "coverage" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "5.3" +version = "5.4" [package.extras] toml = ["toml"] @@ -473,7 +477,7 @@ description = "Show coverage stats online via coveralls.io" name = "coveralls" optional = false python-versions = ">= 3.5" -version = "2.2.0" +version = "3.0.0" [package.dependencies] coverage = ">=4.1,<6.0" @@ -488,19 +492,19 @@ category = "dev" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." name = "cryptography" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*" -version = "3.3.1" +python-versions = ">=3.6" +version = "3.4.5" [package.dependencies] cffi = ">=1.12" -six = ">=1.4.1" [package.extras] docs = ["sphinx (>=1.6.5,<1.8.0 || >1.8.0,<3.1.0 || >3.1.0,<3.1.1 || >3.1.1)", "sphinx-rtd-theme"] docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"] +sdist = ["setuptools-rust (>=0.11.4)"] ssh = ["bcrypt (>=3.1.5)"] -test = ["pytest (>=3.6.0,<3.9.0 || >3.9.0,<3.9.1 || >3.9.1,<3.9.2 || >3.9.2)", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,<3.79.2 || >3.79.2)"] +test = ["pytest (>=6.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,<3.79.2 || >3.79.2)"] [[package]] category = "main" @@ -508,7 +512,7 @@ description = "Storage support for 4DN Data Portals." name = "dcicsnovault" optional = false python-versions = ">=3.6,<3.7" -version = "4.1.0" +version = "4.3.1" [package.dependencies] MarkupSafe = ">=0.23,<1" @@ -524,8 +528,8 @@ aws_requests_auth = ">=0.4.1,<0.5.0" awscli = ">=1.15.42,<2.0.0" "backports.statistics" = "0.1.0" boto3 = ">=1.7.42,<2.0.0" -dcicutils = "1.5.0" -elasticsearch_dsl = "6.4.0" +dcicutils = ">=1.8.3,<2.0.0" +elasticsearch_dsl = ">=6.4.0,<7.0.0" future = ">=0.15.2,<0.16.0" futures = ">=3.1.1,<4.0.0" html5lib = "0.9999999" @@ -567,13 +571,13 @@ description = "Utility package for interacting with the 4DN Data Portal and othe name = "dcicutils" optional = false python-versions = ">=3.4,<3.8" -version = "1.5.0" +version = "1.10.0" [package.dependencies] aws-requests-auth = ">=0.4.2,<1" boto3 = ">=1.10.46,<2.0.0" botocore = ">=1.13.46,<2.0.0" -elasticsearch = "6.4.0" +elasticsearch = "6.8.1" gitpython = ">=3.1.2,<4.0.0" pytz = ">=2016.4" requests = ">=2.21.0,<3.0.0" @@ -588,7 +592,7 @@ description = "A Python library for the Docker Engine API." name = "docker" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "4.4.0" +version = "4.4.2" [package.dependencies] pywin32 = "227" @@ -636,14 +640,14 @@ category = "main" description = "Python client for Elasticsearch" name = "elasticsearch" optional = false -python-versions = "*" -version = "6.4.0" +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4" +version = "6.8.1" [package.dependencies] urllib3 = ">=1.21.1" [package.extras] -develop = ["requests (>=2.0.0,<3.0.0)", "nose", "coverage", "mock", "pyaml", "nosexcover", "sphinx", "sphinx-rtd-theme"] +develop = ["requests (>=2.0.0,<3.0.0)", "nose", "coverage", "mock", "pyyaml", "nosexcover", "numpy", "pandas", "sphinx (<1.7)", "sphinx-rtd-theme"] requests = ["requests (>=2.4.0,<3.0.0)"] [[package]] @@ -696,7 +700,7 @@ description = "Plugin for nose or pytest that automatically reruns flaky tests." name = "flaky" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.6.1" +version = "3.7.0" [[package]] category = "dev" @@ -750,7 +754,7 @@ description = "Python Git Library" name = "gitpython" optional = false python-versions = ">=3.4" -version = "3.1.11" +version = "3.1.13" [package.dependencies] gitdb = ">=4.0.1,<5" @@ -772,7 +776,7 @@ description = "Human friendly output for text interfaces using Python" name = "humanfriendly" optional = false python-versions = "*" -version = "1.44.5" +version = "1.44.9" [[package]] category = "main" @@ -791,8 +795,8 @@ category = "main" description = "Internationalized Domain Names in Applications (IDNA)" name = "idna" optional = false -python-versions = "*" -version = "2.7" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.10" [[package]] category = "dev" @@ -801,7 +805,7 @@ marker = "python_version < \"3.8\"" name = "importlib-metadata" optional = false python-versions = ">=3.6" -version = "3.3.0" +version = "3.4.0" [package.dependencies] zipp = ">=0.5" @@ -811,8 +815,8 @@ python = "<3.8" version = ">=3.6.4" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "jaraco.test (>=3.2.0)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] +docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] +testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] [[package]] category = "main" @@ -820,8 +824,8 @@ description = "Read resources from Python packages" marker = "python_version < \"3.7\"" name = "importlib-resources" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -version = "3.3.0" +python-versions = ">=3.6" +version = "5.1.0" [package.dependencies] [package.dependencies.zipp] @@ -829,7 +833,8 @@ python = "<3.8" version = ">=0.4" [package.extras] -docs = ["sphinx", "rst.linker", "jaraco.packaging"] +docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] +testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "pytest-black (>=0.3.7)", "pytest-mypy"] [[package]] category = "main" @@ -853,7 +858,7 @@ description = "A very fast and expressive template engine." name = "jinja2" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.11.2" +version = "2.11.3" [package.dependencies] MarkupSafe = ">=0.23" @@ -883,7 +888,7 @@ description = "Python library for serializing any arbitrary object graph into JS name = "jsonpickle" optional = false python-versions = ">=2.7" -version = "1.4.2" +version = "2.0.0" [package.dependencies] [package.dependencies.importlib-metadata] @@ -892,7 +897,7 @@ version = "*" [package.extras] docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] -testing = ["coverage (<5)", "pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-black-multipy", "pytest-cov", "ecdsa", "feedparser", "numpy", "pandas", "pymongo", "sqlalchemy", "enum34", "jsonlib"] +testing = ["coverage (<5)", "pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-black-multipy", "pytest-cov", "ecdsa", "feedparser", "numpy", "pandas", "pymongo", "sklearn", "sqlalchemy", "enum34", "jsonlib"] "testing.libs" = ["demjson", "simplejson", "ujson", "yajl"] [[package]] @@ -948,6 +953,14 @@ build = ["twine", "wheel", "blurb"] docs = ["sphinx"] test = ["pytest (<5.4)", "pytest-cov"] +[[package]] +category = "dev" +description = "More routines for operating on iterables, beyond itertools" +name = "more-itertools" +optional = false +python-versions = ">=3.5" +version = "8.7.0" + [[package]] category = "dev" description = "A library that allows your python tests to easily mock out the boto library" @@ -998,7 +1011,13 @@ description = "comprehensive password hashing framework supporting over 30 schem name = "passlib" optional = false python-versions = "*" -version = "1.6.5" +version = "1.7.4" + +[package.extras] +argon2 = ["argon2-cffi (>=18.2.0)"] +bcrypt = ["bcrypt (>=3.1.0)"] +build_docs = ["sphinx (>=1.6)", "sphinxcontrib-fulltoc (>=1.2.0)", "cloud-sptheme (>=1.10.1)"] +totp = ["cryptography"] [[package]] category = "main" @@ -1057,13 +1076,29 @@ plaster = ">=0.5" [package.extras] testing = ["pytest", "pytest-cov"] +[[package]] +category = "dev" +description = "plugin and hook calling mechanisms for python" +name = "pluggy" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "0.13.1" + +[package.dependencies] +[package.dependencies.importlib-metadata] +python = "<3.8" +version = ">=0.12" + +[package.extras] +dev = ["pre-commit", "tox"] + [[package]] category = "main" description = "Cross-platform lib for process and system monitoring in Python." name = "psutil" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "5.7.3" +version = "5.8.0" [package.extras] test = ["ipaddress", "mock", "unittest2", "enum34", "pywin32", "wmi"] @@ -1081,16 +1116,16 @@ category = "main" description = "psycopg2 - Python-PostgreSQL Database Adapter" name = "psycopg2-binary" optional = false -python-versions = "*" -version = "2.7.7" +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" +version = "2.8.6" [[package]] category = "main" description = "library with cross-python path, ini-parsing, io, code, log facilities" name = "py" optional = false -python-versions = "*" -version = "1.4.31" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.10.0" [[package]] category = "dev" @@ -1143,8 +1178,8 @@ category = "dev" description = "Cryptographic library for Python" name = "pycryptodome" optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.9.9" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "3.10.1" [[package]] category = "dev" @@ -1172,8 +1207,8 @@ category = "main" description = "Python parsing module" name = "pyparsing" optional = false -python-versions = "*" -version = "2.1.1" +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +version = "2.4.7" [[package]] category = "main" @@ -1215,7 +1250,7 @@ description = "pyramid_multiauth" name = "pyramid-multiauth" optional = false python-versions = "*" -version = "0.8.0" +version = "0.9.0" [package.dependencies] pyramid = "*" @@ -1242,7 +1277,7 @@ description = "A package which allows Pyramid requests to join the active transa name = "pyramid-tm" optional = false python-versions = "*" -version = "2.2.1" +version = "2.4" [package.dependencies] pyramid = ">=1.5" @@ -1268,24 +1303,33 @@ category = "dev" description = "pytest: simple powerful testing with Python" name = "pytest" optional = false -python-versions = "*" -version = "2.9.2" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "3.10.1" [package.dependencies] +atomicwrites = ">=1.0" +attrs = ">=17.4.0" colorama = "*" -py = ">=1.4.29" +more-itertools = ">=4.0.0" +pluggy = ">=0.7" +py = ">=1.5.0" +setuptools = "*" +six = ">=1.10.0" [[package]] category = "dev" description = "Pytest plugin for measuring coverage." name = "pytest-cov" optional = false -python-versions = "*" -version = "2.2.1" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "2.9.0" [package.dependencies] -coverage = ">=3.7.1" -pytest = ">=2.6.0" +coverage = ">=4.4" +pytest = ">=3.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests (2.0.2)", "six", "pytest-xdist", "virtualenv"] [[package]] category = "dev" @@ -1293,61 +1337,80 @@ description = "Parse queries in Lucene and Elasticsearch syntaxes" name = "pytest-exact-fixtures" optional = false python-versions = "*" -version = "0.1" +version = "0.3" + +[package.dependencies] +pytest = ">=3.3.0" + +[[package]] +category = "dev" +description = "run tests in isolated forked subprocesses" +name = "pytest-forked" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "1.3.0" + +[package.dependencies] +py = "*" +pytest = ">=3.10" [[package]] category = "dev" -description = "py.test plugin to show failures instantly" +description = "pytest plugin to show failures instantly" name = "pytest-instafail" optional = false -python-versions = "*" -version = "0.3.0" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.4.2" [package.dependencies] -pytest = ">=2.3" +pytest = ">=2.9" [[package]] category = "dev" -description = "Thin-wrapper around the mock package for easier use with py.test" +description = "Thin-wrapper around the mock package for easier use with pytest" name = "pytest-mock" optional = false -python-versions = "*" -version = "0.11.0" +python-versions = ">=3.5" +version = "3.2.0" [package.dependencies] pytest = ">=2.7" +[package.extras] +dev = ["pre-commit", "tox", "pytest-asyncio"] + [[package]] category = "dev" description = "py.test plugin to abort hanging tests" name = "pytest-timeout" optional = false python-versions = "*" -version = "1.0.0" +version = "1.4.2" [package.dependencies] -pytest = ">=2.8.0" +pytest = ">=3.6.0" [[package]] category = "dev" -description = "py.test xdist plugin for distributed testing and loop-on-failing modes" +description = "pytest xdist plugin for distributed testing and loop-on-failing modes" name = "pytest-xdist" optional = false -python-versions = "*" -version = "1.14" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.27.0" [package.dependencies] execnet = ">=1.1" -py = ">=1.4.22" -pytest = ">=2.4.2" +pytest = ">=3.6.0" +pytest-forked = "*" +six = "*" [[package]] category = "main" description = "Extensions to the standard Python datetime module" name = "python-dateutil" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -version = "2.7.3" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +version = "2.8.1" [package.dependencies] six = ">=1.5" @@ -1384,7 +1447,7 @@ description = "World timezone definitions, modern and historical" name = "pytz" optional = false python-versions = "*" -version = "2020.4" +version = "2021.1" [[package]] category = "dev" @@ -1425,10 +1488,10 @@ description = "rdflib extension adding JSON-LD parser and serializer" name = "rdflib-jsonld" optional = false python-versions = "*" -version = "0.3" +version = "0.5.0" [package.dependencies] -rdflib = ">=4.2" +rdflib = ">=4.2.2" [[package]] category = "dev" @@ -1436,14 +1499,14 @@ description = "Forensic debugging WSGI middleware" name = "repoze.debug" optional = false python-versions = "*" -version = "1.0.2" +version = "1.1" [package.dependencies] WebOb = "*" [package.extras] -docs = ["webob", "sphinx"] -testing = ["webob", "nose", "coverage"] +docs = ["sphinx", "webob"] +testing = ["webob", "coverage", "nose"] [[package]] category = "main" @@ -1451,11 +1514,11 @@ description = "Python HTTP for Humans." name = "requests" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.25.0" +version = "2.25.1" [package.dependencies] certifi = ">=2017.4.17" -chardet = ">=3.0.2,<4" +chardet = ">=3.0.2,<5" idna = ">=2.5,<3" urllib3 = ">=1.21.1,<1.27" @@ -1518,10 +1581,10 @@ description = "An Amazon S3 Transfer Manager" name = "s3transfer" optional = false python-versions = "*" -version = "0.2.1" +version = "0.3.4" [package.dependencies] -botocore = ">=1.12.36,<2.0.0" +botocore = ">=1.12.36,<2.0a.0" [[package]] category = "main" @@ -1572,7 +1635,7 @@ description = "A pure Python implementation of a sliding window memory map manag name = "smmap" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.0.4" +version = "3.0.5" [[package]] category = "main" @@ -1580,8 +1643,8 @@ description = "A modern CSS selector implementation for Beautiful Soup." marker = "python_version >= \"3.0\"" name = "soupsieve" optional = false -python-versions = ">=3.5" -version = "2.1" +python-versions = ">=3.6" +version = "2.2" [[package]] category = "main" @@ -1589,12 +1652,14 @@ description = "SPARQL Endpoint interface to Python" name = "sparqlwrapper" optional = false python-versions = "*" -version = "1.7.6" +version = "1.8.5" [package.dependencies] -keepalive = ">=0.5" rdflib = ">=4.0" +[package.extras] +keepalive = ["keepalive (>=0.5)"] + [[package]] category = "main" description = "Database Abstraction Library" @@ -1732,7 +1797,7 @@ description = "HTTP library with thread-safe connection pooling, file post, and name = "urllib3" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "1.25.11" +version = "1.26.3" [package.extras] brotli = ["brotlipy (>=0.6.0)"] @@ -1769,7 +1834,7 @@ description = "WSGI request and response object" name = "webob" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*" -version = "1.8.5" +version = "1.8.6" [package.extras] docs = ["Sphinx (>=1.7.5)", "pylons-sphinx-themes"] @@ -1905,8 +1970,8 @@ category = "main" description = "Interfaces for Python" name = "zope.interface" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "4.6.0" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "4.7.2" [package.dependencies] setuptools = "*" @@ -1934,7 +1999,7 @@ transaction = ">=1.6.0" test = ["zope.testing"] [metadata] -content-hash = "96939759c2b7f322d4e5719b41339f1295be79b055ec2836b03a1d2449719b3d" +content-hash = "86b27c4ede18c241ab46a6e320f74c9ed7b54d549b783b7142b2e3fade326b2f" lock-version = "1.0" python-versions = ">=3.6.1,<3.7" @@ -1943,6 +2008,10 @@ apipkg = [ {file = "apipkg-1.5-py2.py3-none-any.whl", hash = "sha256:58587dd4dc3daefad0487f6d9ae32b4542b185e1c36db6993290e7c41ca2b47c"}, {file = "apipkg-1.5.tar.gz", hash = "sha256:37228cda29411948b422fae072f57e31d3396d2ee1c9783775980ee9c9990af6"}, ] +atomicwrites = [ + {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, + {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, +] attrs = [ {file = "attrs-20.3.0-py2.py3-none-any.whl", hash = "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6"}, {file = "attrs-20.3.0.tar.gz", hash = "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"}, @@ -1956,8 +2025,8 @@ aws-xray-sdk = [ {file = "aws_xray_sdk-0.95-py2.py3-none-any.whl", hash = "sha256:72791618feb22eaff2e628462b0d58f398ce8c1bacfa989b7679817ab1fad60c"}, ] awscli = [ - {file = "awscli-1.16.314-py2.py3-none-any.whl", hash = "sha256:8ea6dd9a3538c35e5d1596a4409c7501e12457e93889487351fe52f55b54cac3"}, - {file = "awscli-1.16.314.tar.gz", hash = "sha256:258d1d56707a299f77efc822a56ae1437ddb7080904ec5960a88fcf2d4d0fe38"}, + {file = "awscli-1.19.8-py2.py3-none-any.whl", hash = "sha256:a2893a97ba30ef9c6a9c41b9c9d3bbecc03f71ee335aa92f162a003e69a4074c"}, + {file = "awscli-1.19.8.tar.gz", hash = "sha256:ae426af1dac71b5c9474344bb3a045f8a68f009db6559fa06f9849b19761b4f0"}, ] "backports.statistics" = [ {file = "backports.statistics-0.1.0-py2.py3-none-any.whl", hash = "sha256:2732e003151620762ba3ea25b881b5ca0debe2fcbf41b32b6eaff5842a8b99d7"}, @@ -1973,58 +2042,59 @@ boto = [ {file = "boto-2.49.0.tar.gz", hash = "sha256:ea0d3b40a2d852767be77ca343b58a9e3a4b00d9db440efb8da74b4e58025e5a"}, ] boto3 = [ - {file = "boto3-1.10.50-py2.py3-none-any.whl", hash = "sha256:aa58c8de6aed36211e0897598de2a3d89122ad8cd1450165679720180ab880ef"}, - {file = "boto3-1.10.50.tar.gz", hash = "sha256:5c00d51101d6a7ddf2207ae8a738e5c815c5fcffbee76121f38bd41d83c936a5"}, + {file = "boto3-1.17.8-py2.py3-none-any.whl", hash = "sha256:c294eb103db0ab6c55a53f68cc87761ff7e564733e7b23e51dac475a18c0a12b"}, + {file = "boto3-1.17.8.tar.gz", hash = "sha256:819890e92268d730bdef1d8bac08fb069b148bec21f2172a1a99380798224e1b"}, ] boto3-stubs = [ - {file = "boto3-stubs-1.16.36.0.tar.gz", hash = "sha256:ad9f1b7da0608a2677c4464274ba230f0364b029619b5a8e47e43ed8d5f0249a"}, - {file = "boto3_stubs-1.16.36.0-py3-none-any.whl", hash = "sha256:ad382c647c0cf1ebef431f458e649add6e1097ac7d57dfd10006f6d1f9296902"}, + {file = "boto3-stubs-1.17.8.0.tar.gz", hash = "sha256:749a93f17b2bae4f75c829acdffa5073c29c0f9e6d4e2936c825f183bbbed07a"}, + {file = "boto3_stubs-1.17.8.0-py3-none-any.whl", hash = "sha256:ef030363419e979b7f1e2eecbc62c63387ca8e72ee2e7aa71a483b24fd152e2e"}, ] botocore = [ - {file = "botocore-1.13.50-py2.py3-none-any.whl", hash = "sha256:adb4cb188cd0866e7337f9a049fc68db042b0340fd496d40bca349c8dbfc6a2d"}, - {file = "botocore-1.13.50.tar.gz", hash = "sha256:765a5c637ff792239727c327b221ed5a4d851e9f176ce8b8b9eca536425c74d4"}, + {file = "botocore-1.20.8-py2.py3-none-any.whl", hash = "sha256:65e2fb81f941dfefa8cc3ef72d46a62d4b6219b8eb6550062b644b36935f6e4f"}, + {file = "botocore-1.20.8.tar.gz", hash = "sha256:cd621cdd14a81d2c3c5276516066d9e6ea20a515cf3113a80ad74f3f8b04a093"}, ] certifi = [ {file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"}, {file = "certifi-2020.12.5.tar.gz", hash = "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c"}, ] cffi = [ - {file = "cffi-1.14.4-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775"}, - {file = "cffi-1.14.4-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06"}, - {file = "cffi-1.14.4-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26"}, - {file = "cffi-1.14.4-cp27-cp27m-win32.whl", hash = "sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c"}, - {file = "cffi-1.14.4-cp27-cp27m-win_amd64.whl", hash = "sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b"}, - {file = "cffi-1.14.4-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d"}, - {file = "cffi-1.14.4-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca"}, - {file = "cffi-1.14.4-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698"}, - {file = "cffi-1.14.4-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b"}, - {file = "cffi-1.14.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293"}, - {file = "cffi-1.14.4-cp35-cp35m-win32.whl", hash = "sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2"}, - {file = "cffi-1.14.4-cp35-cp35m-win_amd64.whl", hash = "sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7"}, - {file = "cffi-1.14.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f"}, - {file = "cffi-1.14.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362"}, - {file = "cffi-1.14.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec"}, - {file = "cffi-1.14.4-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b"}, - {file = "cffi-1.14.4-cp36-cp36m-win32.whl", hash = "sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668"}, - {file = "cffi-1.14.4-cp36-cp36m-win_amd64.whl", hash = "sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009"}, - {file = "cffi-1.14.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb"}, - {file = "cffi-1.14.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d"}, - {file = "cffi-1.14.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03"}, - {file = "cffi-1.14.4-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01"}, - {file = "cffi-1.14.4-cp37-cp37m-win32.whl", hash = "sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e"}, - {file = "cffi-1.14.4-cp37-cp37m-win_amd64.whl", hash = "sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35"}, - {file = "cffi-1.14.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d"}, - {file = "cffi-1.14.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b"}, - {file = "cffi-1.14.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53"}, - {file = "cffi-1.14.4-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e"}, - {file = "cffi-1.14.4-cp38-cp38-win32.whl", hash = "sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d"}, - {file = "cffi-1.14.4-cp38-cp38-win_amd64.whl", hash = "sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375"}, - {file = "cffi-1.14.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909"}, - {file = "cffi-1.14.4-cp39-cp39-manylinux1_i686.whl", hash = "sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd"}, - {file = "cffi-1.14.4-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a"}, - {file = "cffi-1.14.4-cp39-cp39-win32.whl", hash = "sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3"}, - {file = "cffi-1.14.4-cp39-cp39-win_amd64.whl", hash = "sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b"}, - {file = "cffi-1.14.4.tar.gz", hash = "sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c"}, + {file = "cffi-1.14.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991"}, + {file = "cffi-1.14.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1"}, + {file = "cffi-1.14.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa"}, + {file = "cffi-1.14.5-cp27-cp27m-win32.whl", hash = "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3"}, + {file = "cffi-1.14.5-cp27-cp27m-win_amd64.whl", hash = "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5"}, + {file = "cffi-1.14.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482"}, + {file = "cffi-1.14.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6"}, + {file = "cffi-1.14.5-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045"}, + {file = "cffi-1.14.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa"}, + {file = "cffi-1.14.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406"}, + {file = "cffi-1.14.5-cp35-cp35m-win32.whl", hash = "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369"}, + {file = "cffi-1.14.5-cp35-cp35m-win_amd64.whl", hash = "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315"}, + {file = "cffi-1.14.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892"}, + {file = "cffi-1.14.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058"}, + {file = "cffi-1.14.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5"}, + {file = "cffi-1.14.5-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132"}, + {file = "cffi-1.14.5-cp36-cp36m-win32.whl", hash = "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53"}, + {file = "cffi-1.14.5-cp36-cp36m-win_amd64.whl", hash = "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813"}, + {file = "cffi-1.14.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73"}, + {file = "cffi-1.14.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06"}, + {file = "cffi-1.14.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1"}, + {file = "cffi-1.14.5-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49"}, + {file = "cffi-1.14.5-cp37-cp37m-win32.whl", hash = "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62"}, + {file = "cffi-1.14.5-cp37-cp37m-win_amd64.whl", hash = "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4"}, + {file = "cffi-1.14.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053"}, + {file = "cffi-1.14.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0"}, + {file = "cffi-1.14.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e"}, + {file = "cffi-1.14.5-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827"}, + {file = "cffi-1.14.5-cp38-cp38-win32.whl", hash = "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e"}, + {file = "cffi-1.14.5-cp38-cp38-win_amd64.whl", hash = "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396"}, + {file = "cffi-1.14.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea"}, + {file = "cffi-1.14.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322"}, + {file = "cffi-1.14.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c"}, + {file = "cffi-1.14.5-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee"}, + {file = "cffi-1.14.5-cp39-cp39-win32.whl", hash = "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396"}, + {file = "cffi-1.14.5-cp39-cp39-win_amd64.whl", hash = "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d"}, + {file = "cffi-1.14.5.tar.gz", hash = "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"}, ] chardet = [ {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, @@ -2042,72 +2112,80 @@ colorama = [ {file = "colorama-0.3.3.tar.gz", hash = "sha256:eb21f2ba718fbf357afdfdf6f641ab393901c7ca8d9f37edd0bee4806ffa269c"}, ] coverage = [ - {file = "coverage-5.3-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:bd3166bb3b111e76a4f8e2980fa1addf2920a4ca9b2b8ca36a3bc3dedc618270"}, - {file = "coverage-5.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:9342dd70a1e151684727c9c91ea003b2fb33523bf19385d4554f7897ca0141d4"}, - {file = "coverage-5.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:63808c30b41f3bbf65e29f7280bf793c79f54fb807057de7e5238ffc7cc4d7b9"}, - {file = "coverage-5.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4d6a42744139a7fa5b46a264874a781e8694bb32f1d76d8137b68138686f1729"}, - {file = "coverage-5.3-cp27-cp27m-win32.whl", hash = "sha256:86e9f8cd4b0cdd57b4ae71a9c186717daa4c5a99f3238a8723f416256e0b064d"}, - {file = "coverage-5.3-cp27-cp27m-win_amd64.whl", hash = "sha256:7858847f2d84bf6e64c7f66498e851c54de8ea06a6f96a32a1d192d846734418"}, - {file = "coverage-5.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:530cc8aaf11cc2ac7430f3614b04645662ef20c348dce4167c22d99bec3480e9"}, - {file = "coverage-5.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:381ead10b9b9af5f64646cd27107fb27b614ee7040bb1226f9c07ba96625cbb5"}, - {file = "coverage-5.3-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:71b69bd716698fa62cd97137d6f2fdf49f534decb23a2c6fc80813e8b7be6822"}, - {file = "coverage-5.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:1d44bb3a652fed01f1f2c10d5477956116e9b391320c94d36c6bf13b088a1097"}, - {file = "coverage-5.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:1c6703094c81fa55b816f5ae542c6ffc625fec769f22b053adb42ad712d086c9"}, - {file = "coverage-5.3-cp35-cp35m-win32.whl", hash = "sha256:cedb2f9e1f990918ea061f28a0f0077a07702e3819602d3507e2ff98c8d20636"}, - {file = "coverage-5.3-cp35-cp35m-win_amd64.whl", hash = "sha256:7f43286f13d91a34fadf61ae252a51a130223c52bfefb50310d5b2deb062cf0f"}, - {file = "coverage-5.3-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:c851b35fc078389bc16b915a0a7c1d5923e12e2c5aeec58c52f4aa8085ac8237"}, - {file = "coverage-5.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:aac1ba0a253e17889550ddb1b60a2063f7474155465577caa2a3b131224cfd54"}, - {file = "coverage-5.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2b31f46bf7b31e6aa690d4c7a3d51bb262438c6dcb0d528adde446531d0d3bb7"}, - {file = "coverage-5.3-cp36-cp36m-win32.whl", hash = "sha256:c5f17ad25d2c1286436761b462e22b5020d83316f8e8fcb5deb2b3151f8f1d3a"}, - {file = "coverage-5.3-cp36-cp36m-win_amd64.whl", hash = "sha256:aef72eae10b5e3116bac6957de1df4d75909fc76d1499a53fb6387434b6bcd8d"}, - {file = "coverage-5.3-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:e8caf961e1b1a945db76f1b5fa9c91498d15f545ac0ababbe575cfab185d3bd8"}, - {file = "coverage-5.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:29a6272fec10623fcbe158fdf9abc7a5fa032048ac1d8631f14b50fbfc10d17f"}, - {file = "coverage-5.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2d43af2be93ffbad25dd959899b5b809618a496926146ce98ee0b23683f8c51c"}, - {file = "coverage-5.3-cp37-cp37m-win32.whl", hash = "sha256:c3888a051226e676e383de03bf49eb633cd39fc829516e5334e69b8d81aae751"}, - {file = "coverage-5.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9669179786254a2e7e57f0ecf224e978471491d660aaca833f845b72a2df3709"}, - {file = "coverage-5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0203acd33d2298e19b57451ebb0bed0ab0c602e5cf5a818591b4918b1f97d516"}, - {file = "coverage-5.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:582ddfbe712025448206a5bc45855d16c2e491c2dd102ee9a2841418ac1c629f"}, - {file = "coverage-5.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0f313707cdecd5cd3e217fc68c78a960b616604b559e9ea60cc16795c4304259"}, - {file = "coverage-5.3-cp38-cp38-win32.whl", hash = "sha256:78e93cc3571fd928a39c0b26767c986188a4118edc67bc0695bc7a284da22e82"}, - {file = "coverage-5.3-cp38-cp38-win_amd64.whl", hash = "sha256:8f264ba2701b8c9f815b272ad568d555ef98dfe1576802ab3149c3629a9f2221"}, - {file = "coverage-5.3-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:50691e744714856f03a86df3e2bff847c2acede4c191f9a1da38f088df342978"}, - {file = "coverage-5.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:9361de40701666b034c59ad9e317bae95c973b9ff92513dd0eced11c6adf2e21"}, - {file = "coverage-5.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:c1b78fb9700fc961f53386ad2fd86d87091e06ede5d118b8a50dea285a071c24"}, - {file = "coverage-5.3-cp39-cp39-win32.whl", hash = "sha256:cb7df71de0af56000115eafd000b867d1261f786b5eebd88a0ca6360cccfaca7"}, - {file = "coverage-5.3-cp39-cp39-win_amd64.whl", hash = "sha256:47a11bdbd8ada9b7ee628596f9d97fbd3851bd9999d398e9436bd67376dbece7"}, - {file = "coverage-5.3.tar.gz", hash = "sha256:280baa8ec489c4f542f8940f9c4c2181f0306a8ee1a54eceba071a449fb870a0"}, + {file = "coverage-5.4-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:6d9c88b787638a451f41f97446a1c9fd416e669b4d9717ae4615bd29de1ac135"}, + {file = "coverage-5.4-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:66a5aae8233d766a877c5ef293ec5ab9520929c2578fd2069308a98b7374ea8c"}, + {file = "coverage-5.4-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9754a5c265f991317de2bac0c70a746efc2b695cf4d49f5d2cddeac36544fb44"}, + {file = "coverage-5.4-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:fbb17c0d0822684b7d6c09915677a32319f16ff1115df5ec05bdcaaee40b35f3"}, + {file = "coverage-5.4-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:b7f7421841f8db443855d2854e25914a79a1ff48ae92f70d0a5c2f8907ab98c9"}, + {file = "coverage-5.4-cp27-cp27m-win32.whl", hash = "sha256:4a780807e80479f281d47ee4af2eb2df3e4ccf4723484f77da0bb49d027e40a1"}, + {file = "coverage-5.4-cp27-cp27m-win_amd64.whl", hash = "sha256:87c4b38288f71acd2106f5d94f575bc2136ea2887fdb5dfe18003c881fa6b370"}, + {file = "coverage-5.4-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:c6809ebcbf6c1049002b9ac09c127ae43929042ec1f1dbd8bb1615f7cd9f70a0"}, + {file = "coverage-5.4-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ba7ca81b6d60a9f7a0b4b4e175dcc38e8fef4992673d9d6e6879fd6de00dd9b8"}, + {file = "coverage-5.4-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:89fc12c6371bf963809abc46cced4a01ca4f99cba17be5e7d416ed7ef1245d19"}, + {file = "coverage-5.4-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:4a8eb7785bd23565b542b01fb39115a975fefb4a82f23d407503eee2c0106247"}, + {file = "coverage-5.4-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:7e40d3f8eb472c1509b12ac2a7e24158ec352fc8567b77ab02c0db053927e339"}, + {file = "coverage-5.4-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:1ccae21a076d3d5f471700f6d30eb486da1626c380b23c70ae32ab823e453337"}, + {file = "coverage-5.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:755c56beeacac6a24c8e1074f89f34f4373abce8b662470d3aa719ae304931f3"}, + {file = "coverage-5.4-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:322549b880b2d746a7672bf6ff9ed3f895e9c9f108b714e7360292aa5c5d7cf4"}, + {file = "coverage-5.4-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:60a3307a84ec60578accd35d7f0c71a3a971430ed7eca6567399d2b50ef37b8c"}, + {file = "coverage-5.4-cp35-cp35m-win32.whl", hash = "sha256:1375bb8b88cb050a2d4e0da901001347a44302aeadb8ceb4b6e5aa373b8ea68f"}, + {file = "coverage-5.4-cp35-cp35m-win_amd64.whl", hash = "sha256:16baa799ec09cc0dcb43a10680573269d407c159325972dd7114ee7649e56c66"}, + {file = "coverage-5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2f2cf7a42d4b7654c9a67b9d091ec24374f7c58794858bff632a2039cb15984d"}, + {file = "coverage-5.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:b62046592b44263fa7570f1117d372ae3f310222af1fc1407416f037fb3af21b"}, + {file = "coverage-5.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:812eaf4939ef2284d29653bcfee9665f11f013724f07258928f849a2306ea9f9"}, + {file = "coverage-5.4-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:859f0add98707b182b4867359e12bde806b82483fb12a9ae868a77880fc3b7af"}, + {file = "coverage-5.4-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:04b14e45d6a8e159c9767ae57ecb34563ad93440fc1b26516a89ceb5b33c1ad5"}, + {file = "coverage-5.4-cp36-cp36m-win32.whl", hash = "sha256:ebfa374067af240d079ef97b8064478f3bf71038b78b017eb6ec93ede1b6bcec"}, + {file = "coverage-5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:84df004223fd0550d0ea7a37882e5c889f3c6d45535c639ce9802293b39cd5c9"}, + {file = "coverage-5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:1b811662ecf72eb2d08872731636aee6559cae21862c36f74703be727b45df90"}, + {file = "coverage-5.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6b588b5cf51dc0fd1c9e19f622457cc74b7d26fe295432e434525f1c0fae02bc"}, + {file = "coverage-5.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3fe50f1cac369b02d34ad904dfe0771acc483f82a1b54c5e93632916ba847b37"}, + {file = "coverage-5.4-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:32ab83016c24c5cf3db2943286b85b0a172dae08c58d0f53875235219b676409"}, + {file = "coverage-5.4-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:68fb816a5dd901c6aff352ce49e2a0ffadacdf9b6fae282a69e7a16a02dad5fb"}, + {file = "coverage-5.4-cp37-cp37m-win32.whl", hash = "sha256:a636160680c6e526b84f85d304e2f0bb4e94f8284dd765a1911de9a40450b10a"}, + {file = "coverage-5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:bb32ca14b4d04e172c541c69eec5f385f9a075b38fb22d765d8b0ce3af3a0c22"}, + {file = "coverage-5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4d7165a4e8f41eca6b990c12ee7f44fef3932fac48ca32cecb3a1b2223c21f"}, + {file = "coverage-5.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a565f48c4aae72d1d3d3f8e8fb7218f5609c964e9c6f68604608e5958b9c60c3"}, + {file = "coverage-5.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:fff1f3a586246110f34dc762098b5afd2de88de507559e63553d7da643053786"}, + {file = "coverage-5.4-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:a839e25f07e428a87d17d857d9935dd743130e77ff46524abb992b962eb2076c"}, + {file = "coverage-5.4-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:6625e52b6f346a283c3d563d1fd8bae8956daafc64bb5bbd2b8f8a07608e3994"}, + {file = "coverage-5.4-cp38-cp38-win32.whl", hash = "sha256:5bee3970617b3d74759b2d2df2f6a327d372f9732f9ccbf03fa591b5f7581e39"}, + {file = "coverage-5.4-cp38-cp38-win_amd64.whl", hash = "sha256:03ed2a641e412e42cc35c244508cf186015c217f0e4d496bf6d7078ebe837ae7"}, + {file = "coverage-5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:14a9f1887591684fb59fdba8feef7123a0da2424b0652e1b58dd5b9a7bb1188c"}, + {file = "coverage-5.4-cp39-cp39-manylinux1_i686.whl", hash = "sha256:9564ac7eb1652c3701ac691ca72934dd3009997c81266807aef924012df2f4b3"}, + {file = "coverage-5.4-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:0f48fc7dc82ee14aeaedb986e175a429d24129b7eada1b7e94a864e4f0644dde"}, + {file = "coverage-5.4-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:107d327071061fd4f4a2587d14c389a27e4e5c93c7cba5f1f59987181903902f"}, + {file = "coverage-5.4-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:0cdde51bfcf6b6bd862ee9be324521ec619b20590787d1655d005c3fb175005f"}, + {file = "coverage-5.4-cp39-cp39-win32.whl", hash = "sha256:c67734cff78383a1f23ceba3b3239c7deefc62ac2b05fa6a47bcd565771e5880"}, + {file = "coverage-5.4-cp39-cp39-win_amd64.whl", hash = "sha256:c669b440ce46ae3abe9b2d44a913b5fd86bb19eb14a8701e88e3918902ecd345"}, + {file = "coverage-5.4-pp36-none-any.whl", hash = "sha256:c0ff1c1b4d13e2240821ef23c1efb1f009207cb3f56e16986f713c2b0e7cd37f"}, + {file = "coverage-5.4-pp37-none-any.whl", hash = "sha256:cd601187476c6bed26a0398353212684c427e10a903aeafa6da40c63309d438b"}, + {file = "coverage-5.4.tar.gz", hash = "sha256:6d2e262e5e8da6fa56e774fb8e2643417351427604c2b177f8e8c5f75fc928ca"}, ] coveralls = [ - {file = "coveralls-2.2.0-py2.py3-none-any.whl", hash = "sha256:2301a19500b06649d2ec4f2858f9c69638d7699a4c63027c5d53daba666147cc"}, - {file = "coveralls-2.2.0.tar.gz", hash = "sha256:b990ba1f7bc4288e63340be0433698c1efe8217f78c689d254c2540af3d38617"}, + {file = "coveralls-3.0.0-py2.py3-none-any.whl", hash = "sha256:f8384968c57dee4b7133ae701ecdad88e85e30597d496dcba0d7fbb470dca41f"}, + {file = "coveralls-3.0.0.tar.gz", hash = "sha256:5399c0565ab822a70a477f7031f6c88a9dd196b3de2877b3facb43b51bd13434"}, ] cryptography = [ - {file = "cryptography-3.3.1-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:c366df0401d1ec4e548bebe8f91d55ebcc0ec3137900d214dd7aac8427ef3030"}, - {file = "cryptography-3.3.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9f6b0492d111b43de5f70052e24c1f0951cb9e6022188ebcb1cc3a3d301469b0"}, - {file = "cryptography-3.3.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:a69bd3c68b98298f490e84519b954335154917eaab52cf582fa2c5c7efc6e812"}, - {file = "cryptography-3.3.1-cp27-cp27m-win32.whl", hash = "sha256:84ef7a0c10c24a7773163f917f1cb6b4444597efd505a8aed0a22e8c4780f27e"}, - {file = "cryptography-3.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:594a1db4511bc4d960571536abe21b4e5c3003e8750ab8365fafce71c5d86901"}, - {file = "cryptography-3.3.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:0003a52a123602e1acee177dc90dd201f9bb1e73f24a070db7d36c588e8f5c7d"}, - {file = "cryptography-3.3.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:83d9d2dfec70364a74f4e7c70ad04d3ca2e6a08b703606993407bf46b97868c5"}, - {file = "cryptography-3.3.1-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:dc42f645f8f3a489c3dd416730a514e7a91a59510ddaadc09d04224c098d3302"}, - {file = "cryptography-3.3.1-cp36-abi3-manylinux1_x86_64.whl", hash = "sha256:788a3c9942df5e4371c199d10383f44a105d67d401fb4304178020142f020244"}, - {file = "cryptography-3.3.1-cp36-abi3-manylinux2010_x86_64.whl", hash = "sha256:69e836c9e5ff4373ce6d3ab311c1a2eed274793083858d3cd4c7d12ce20d5f9c"}, - {file = "cryptography-3.3.1-cp36-abi3-manylinux2014_aarch64.whl", hash = "sha256:9e21301f7a1e7c03dbea73e8602905a4ebba641547a462b26dd03451e5769e7c"}, - {file = "cryptography-3.3.1-cp36-abi3-win32.whl", hash = "sha256:b4890d5fb9b7a23e3bf8abf5a8a7da8e228f1e97dc96b30b95685df840b6914a"}, - {file = "cryptography-3.3.1-cp36-abi3-win_amd64.whl", hash = "sha256:0e85aaae861d0485eb5a79d33226dd6248d2a9f133b81532c8f5aae37de10ff7"}, - {file = "cryptography-3.3.1.tar.gz", hash = "sha256:7e177e4bea2de937a584b13645cab32f25e3d96fc0bc4a4cf99c27dc77682be6"}, + {file = "cryptography-3.4.5-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:18d6f3ac1da14a01c95f4590ee58e96aa6628d231ce738e9eca330b9997127b6"}, + {file = "cryptography-3.4.5-cp36-abi3-manylinux2010_x86_64.whl", hash = "sha256:c8dc9859c5a046e1ca22da360dfd609c09064a4f974881cb5cba977c581088ec"}, + {file = "cryptography-3.4.5-cp36-abi3-manylinux2014_aarch64.whl", hash = "sha256:0bf49d5b38e4f3745a0eab0597fa97720dd49b30d65f534b49a82e303f149deb"}, + {file = "cryptography-3.4.5-cp36-abi3-manylinux2014_x86_64.whl", hash = "sha256:9c6f7552d4f2130542d488b9d9e5b1546204b5d1aa90c823d50cce8eed421363"}, + {file = "cryptography-3.4.5-cp36-abi3-win32.whl", hash = "sha256:b0873ac0c0e6bc6882cd285930cc382ec4e78786be71bdc113c06246eea61294"}, + {file = "cryptography-3.4.5-cp36-abi3-win_amd64.whl", hash = "sha256:8b3b79af57e12aabbc3db81e563eaa07870293a1ffdcc891d107035ce9a0dbff"}, + {file = "cryptography-3.4.5.tar.gz", hash = "sha256:4f6761a82b51fe02cda8f45af1c2f698a10f50003dc9c2572d8a49eda2e6d35b"}, ] dcicsnovault = [ - {file = "dcicsnovault-4.1.0-py3-none-any.whl", hash = "sha256:61aec2c36bb3605bddc704487279e3db89c820d53226e4f66c21d57f50de620b"}, - {file = "dcicsnovault-4.1.0.tar.gz", hash = "sha256:7328be4cb77a4c79c42ccaf36abd488b0724afaa32b312b95b7b9d7ae066b865"}, + {file = "dcicsnovault-4.3.1-py3-none-any.whl", hash = "sha256:bf83b07f439d959d531e5cfdad9f1a8d5971b2ea6f3a01cd73f6e67647e65f52"}, + {file = "dcicsnovault-4.3.1.tar.gz", hash = "sha256:e002036a00bb81b6f6de4aadc586e52eae12fcd9736f2b561a2ea873e48cc3d2"}, ] dcicutils = [ - {file = "dcicutils-1.5.0-py3-none-any.whl", hash = "sha256:9da439e853707f391fd6ff38b04985deb541b76cc62807694fa59a6c21779b6a"}, - {file = "dcicutils-1.5.0.tar.gz", hash = "sha256:5543e3b5c1fc3bce5018fc7043df6ec13a54e03f226fa09500ec4abb3e267ad7"}, + {file = "dcicutils-1.10.0-py3-none-any.whl", hash = "sha256:79757f6ae722c6d17c4cedc1f1742782c51ec927de5add7539eaa220adc7e545"}, + {file = "dcicutils-1.10.0.tar.gz", hash = "sha256:655e2041e0bbdf089a66942c3af2bc985fea347f890cea5b5681570a28424445"}, ] docker = [ - {file = "docker-4.4.0-py2.py3-none-any.whl", hash = "sha256:317e95a48c32de8c1aac92a48066a5b73e218ed096e03758bcdd799a7130a1a1"}, - {file = "docker-4.4.0.tar.gz", hash = "sha256:cffc771d4ea1389fc66bc95cb72d304aa41d1a1563482a9a000fba3a84ed5071"}, + {file = "docker-4.4.2-py2.py3-none-any.whl", hash = "sha256:20d71afc593486f2297bb7fb7406b03876f31894337e914a5062050c65085cab"}, + {file = "docker-4.4.2.tar.gz", hash = "sha256:67f33d4cf95182db631a17eef7d666d2c91f624c1d3fbc4df6009cb2f2a4c604"}, ] docopt = [ {file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"}, @@ -2121,8 +2199,8 @@ ecdsa = [ {file = "ecdsa-0.16.1.tar.gz", hash = "sha256:cfc046a2ddd425adbd1a78b3c46f0d1325c657811c0f45ecc3a0a6236c1e50ff"}, ] elasticsearch = [ - {file = "elasticsearch-6.4.0-py2.py3-none-any.whl", hash = "sha256:1f0f633e3b500d5042424f75a505badf8c4b9962c1b4734cdfb3087fb67920be"}, - {file = "elasticsearch-6.4.0.tar.gz", hash = "sha256:fb5ab15ee283f104b5a7a5695c7e879cb2927e4eb5aed9c530811590b41259ad"}, + {file = "elasticsearch-6.8.1-py2.py3-none-any.whl", hash = "sha256:540d633afcc0a32972e4b489c4559c9a96e294850853238f7a18b1cbd267c2ed"}, + {file = "elasticsearch-6.8.1.tar.gz", hash = "sha256:a8062a00b61bc7babeea028530667583a68ecb1a9f59ab0b22ff7feaf70d3564"}, ] elasticsearch-dsl = [ {file = "elasticsearch-dsl-6.4.0.tar.gz", hash = "sha256:26416f4dd46ceca43d62ef74970d9de4bdd6f4b0f163316f0b432c9e61a08bec"}, @@ -2137,8 +2215,8 @@ flake8 = [ {file = "flake8-3.8.4.tar.gz", hash = "sha256:aadae8761ec651813c24be05c6f7b4680857ef6afaae4651a4eccaef97ce6c3b"}, ] flaky = [ - {file = "flaky-3.6.1-py2.py3-none-any.whl", hash = "sha256:5471615b32b0f8086573de924475b1f0d31e0e8655a089eb9c38a0fbff3f11aa"}, - {file = "flaky-3.6.1.tar.gz", hash = "sha256:8cd5455bb00c677f787da424eaf8c4a58a922d0e97126d3085db5b279a98b698"}, + {file = "flaky-3.7.0-py2.py3-none-any.whl", hash = "sha256:d6eda73cab5ae7364504b7c44670f70abed9e75f77dd116352f662817592ec9c"}, + {file = "flaky-3.7.0.tar.gz", hash = "sha256:3ad100780721a1911f57a165809b7ea265a7863305acb66708220820caf8aa0d"}, ] flask = [ {file = "Flask-1.1.2-py2.py3-none-any.whl", hash = "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557"}, @@ -2157,30 +2235,31 @@ gitdb = [ {file = "gitdb-4.0.5.tar.gz", hash = "sha256:c9e1f2d0db7ddb9a704c2a0217be31214e91a4fe1dea1efad19ae42ba0c285c9"}, ] gitpython = [ - {file = "GitPython-3.1.11-py3-none-any.whl", hash = "sha256:6eea89b655917b500437e9668e4a12eabdcf00229a0df1762aabd692ef9b746b"}, - {file = "GitPython-3.1.11.tar.gz", hash = "sha256:befa4d101f91bad1b632df4308ec64555db684c360bd7d2130b4807d49ce86b8"}, + {file = "GitPython-3.1.13-py3-none-any.whl", hash = "sha256:c5347c81d232d9b8e7f47b68a83e5dc92e7952127133c5f2df9133f2c75a1b29"}, + {file = "GitPython-3.1.13.tar.gz", hash = "sha256:8621a7e777e276a5ec838b59280ba5272dd144a18169c36c903d8b38b99f750a"}, ] html5lib = [ {file = "html5lib-0.9999999.tar.gz", hash = "sha256:2612a191a8d5842bfa057e41ba50bbb9dcb722419d2408c78cff4758d0754868"}, ] humanfriendly = [ - {file = "humanfriendly-1.44.5.tar.gz", hash = "sha256:4465e94cdfac4659c485a680057eae8beadd94f480db8cfa71de8fc85ddc429c"}, + {file = "humanfriendly-1.44.9-py2.py3-none-any.whl", hash = "sha256:ed65dfd6172b579318eef1c6f73614a406db618e6c55fc8788de05a73ab88657"}, + {file = "humanfriendly-1.44.9.tar.gz", hash = "sha256:c87a120046cc6d05e86d69fd5bc7794e7f5229fc40f05544d0a6a8f9040b07f5"}, ] hupper = [ {file = "hupper-1.5-py2.py3-none-any.whl", hash = "sha256:626b77e3ce55dbfc11e670a0eeed413de6fdbf5cf0bb92458dd4e0d5fc462ab8"}, {file = "hupper-1.5.tar.gz", hash = "sha256:693a167badbe82177219fccf1a27c5a007498c843c21d0071795a9bbb3f0c60a"}, ] idna = [ - {file = "idna-2.7-py2.py3-none-any.whl", hash = "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e"}, - {file = "idna-2.7.tar.gz", hash = "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16"}, + {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, + {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, ] importlib-metadata = [ - {file = "importlib_metadata-3.3.0-py3-none-any.whl", hash = "sha256:bf792d480abbd5eda85794e4afb09dd538393f7d6e6ffef6e9f03d2014cf9450"}, - {file = "importlib_metadata-3.3.0.tar.gz", hash = "sha256:5c5a2720817414a6c41f0a49993908068243ae02c1635a228126519b509c8aed"}, + {file = "importlib_metadata-3.4.0-py3-none-any.whl", hash = "sha256:ace61d5fc652dc280e7b6b4ff732a9c2d40db2c0f92bc6cb74e07b73d53a1771"}, + {file = "importlib_metadata-3.4.0.tar.gz", hash = "sha256:fa5daa4477a7414ae34e95942e4dd07f62adf589143c875c133c1e53c4eff38d"}, ] importlib-resources = [ - {file = "importlib_resources-3.3.0-py2.py3-none-any.whl", hash = "sha256:a3d34a8464ce1d5d7c92b0ea4e921e696d86f2aa212e684451cb1482c8d84ed5"}, - {file = "importlib_resources-3.3.0.tar.gz", hash = "sha256:7b51f0106c8ec564b1bef3d9c588bc694ce2b92125bbb6278f4f2f5b54ec3592"}, + {file = "importlib_resources-5.1.0-py3-none-any.whl", hash = "sha256:885b8eae589179f661c909d699a546cf10d83692553e34dca1bf5eb06f7f6217"}, + {file = "importlib_resources-5.1.0.tar.gz", hash = "sha256:bfdad047bce441405a49cf8eb48ddce5e56c696e185f59147a8b79e75e9e6380"}, ] isodate = [ {file = "isodate-0.5.4.tar.gz", hash = "sha256:42105c41d037246dc1987e36d96f3752ffd5c0c24834dd12e4fdbe1e79544e31"}, @@ -2190,8 +2269,8 @@ itsdangerous = [ {file = "itsdangerous-1.1.0.tar.gz", hash = "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19"}, ] jinja2 = [ - {file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"}, - {file = "Jinja2-2.11.2.tar.gz", hash = "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0"}, + {file = "Jinja2-2.11.3-py2.py3-none-any.whl", hash = "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419"}, + {file = "Jinja2-2.11.3.tar.gz", hash = "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6"}, ] jmespath = [ {file = "jmespath-0.9.0-py2.py3-none-any.whl", hash = "sha256:ade5261b0d7d34b6f53accc91e6881b579b40161ed575e6ac465de5edad32815"}, @@ -2201,8 +2280,8 @@ jsondiff = [ {file = "jsondiff-1.1.1.tar.gz", hash = "sha256:2d0437782de9418efa34e694aa59f43d7adb1899bd9a793f063867ddba8f7893"}, ] jsonpickle = [ - {file = "jsonpickle-1.4.2-py2.py3-none-any.whl", hash = "sha256:2ac5863099864c63d7f0c367af5e512c94f3384977dd367f2eae5f2303f7b92c"}, - {file = "jsonpickle-1.4.2.tar.gz", hash = "sha256:c9b99b28a9e6a3043ec993552db79f4389da11afcb1d0246d93c79f4b5e64062"}, + {file = "jsonpickle-2.0.0-py2.py3-none-any.whl", hash = "sha256:c1010994c1fbda87a48f8a56698605b598cb0fc6bb7e7927559fc1100e69aeac"}, + {file = "jsonpickle-2.0.0.tar.gz", hash = "sha256:0be49cba80ea6f87a168aa8168d717d00c6ca07ba83df3cec32d3b30bfe6fb9a"}, ] jsonschema-serialize-fork = [ {file = "jsonschema_serialize_fork-2.1.1.tar.gz", hash = "sha256:49b502326ac408729f72c95db018bf0e4d47860e3cd76e944f368f41a5483ed5"}, @@ -2229,6 +2308,10 @@ mock = [ {file = "mock-4.0.3-py3-none-any.whl", hash = "sha256:122fcb64ee37cfad5b3f48d7a7d51875d7031aaf3d8be7c42e2bee25044eee62"}, {file = "mock-4.0.3.tar.gz", hash = "sha256:7d3fbbde18228f4ff2f1f119a45cdffa458b4c0dee32eb4d2bb2f82554bac7bc"}, ] +more-itertools = [ + {file = "more-itertools-8.7.0.tar.gz", hash = "sha256:c5d6da9ca3ff65220c3bfd2a8db06d698f05d4d2b9be57e1deb2be5a45019713"}, + {file = "more_itertools-8.7.0-py3-none-any.whl", hash = "sha256:5652a9ac72209ed7df8d9c15daf4e1aa0e3d2ccd3c87f8265a0673cd9cbc9ced"}, +] moto = [ {file = "moto-1.3.7-py2.py3-none-any.whl", hash = "sha256:4df37936ff8d6a4b8229aab347a7b412cd2ca4823ff47bd1362ddfbc6c5e4ecf"}, {file = "moto-1.3.7.tar.gz", hash = "sha256:129de2e04cb250d9f8b2c722ec152ed1b5426ef179b4ebb03e9ec36e6eb3fcc5"}, @@ -2238,8 +2321,8 @@ netaddr = [ {file = "netaddr-0.8.0.tar.gz", hash = "sha256:d6cc57c7a07b1d9d2e917aa8b36ae8ce61c35ba3fcd1b83ca31c5a0ee2b5a243"}, ] passlib = [ - {file = "passlib-1.6.5-py2.py3-none-any.whl", hash = "sha256:ad631a58dc8abeb0f48016c13f4b3b0f3a7b1045a8cb3c61dd15e2d95b45c472"}, - {file = "passlib-1.6.5.tar.gz", hash = "sha256:a83d34f53dc9b17aa42c9a35c3fbcc5120f3fcb07f7f8721ec45e6a27be347fc"}, + {file = "passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1"}, + {file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"}, ] pastedeploy = [ {file = "PasteDeploy-1.5.2-py2.py3-none-any.whl", hash = "sha256:39973e73f391335fac8bc8a8a95f7d34a9f42e2775600ce2dc518d93b37ef943"}, @@ -2288,18 +2371,39 @@ plaster-pastedeploy = [ {file = "plaster_pastedeploy-0.6-py2.py3-none-any.whl", hash = "sha256:71e29b0ab90df8343bca5f0debe4706f0f8147308a78922c8c26e8252809bce4"}, {file = "plaster_pastedeploy-0.6.tar.gz", hash = "sha256:c231130cb86ae414084008fe1d1797db7e61dc5eaafb5e755de21387c27c6fae"}, ] +pluggy = [ + {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, + {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, +] psutil = [ - {file = "psutil-5.7.3-cp27-none-win32.whl", hash = "sha256:1cd6a0c9fb35ece2ccf2d1dd733c1e165b342604c67454fd56a4c12e0a106787"}, - {file = "psutil-5.7.3-cp27-none-win_amd64.whl", hash = "sha256:e02c31b2990dcd2431f4524b93491941df39f99619b0d312dfe1d4d530b08b4b"}, - {file = "psutil-5.7.3-cp35-cp35m-win32.whl", hash = "sha256:56c85120fa173a5d2ad1d15a0c6e0ae62b388bfb956bb036ac231fbdaf9e4c22"}, - {file = "psutil-5.7.3-cp35-cp35m-win_amd64.whl", hash = "sha256:fa38ac15dbf161ab1e941ff4ce39abd64b53fec5ddf60c23290daed2bc7d1157"}, - {file = "psutil-5.7.3-cp36-cp36m-win32.whl", hash = "sha256:01bc82813fbc3ea304914581954979e637bcc7084e59ac904d870d6eb8bb2bc7"}, - {file = "psutil-5.7.3-cp36-cp36m-win_amd64.whl", hash = "sha256:6a3e1fd2800ca45083d976b5478a2402dd62afdfb719b30ca46cd28bb25a2eb4"}, - {file = "psutil-5.7.3-cp37-cp37m-win32.whl", hash = "sha256:fbcac492cb082fa38d88587d75feb90785d05d7e12d4565cbf1ecc727aff71b7"}, - {file = "psutil-5.7.3-cp37-cp37m-win_amd64.whl", hash = "sha256:5d9106ff5ec2712e2f659ebbd112967f44e7d33f40ba40530c485cc5904360b8"}, - {file = "psutil-5.7.3-cp38-cp38-win32.whl", hash = "sha256:ade6af32eb80a536eff162d799e31b7ef92ddcda707c27bbd077238065018df4"}, - {file = "psutil-5.7.3-cp38-cp38-win_amd64.whl", hash = "sha256:2cb55ef9591b03ef0104bedf67cc4edb38a3edf015cf8cf24007b99cb8497542"}, - {file = "psutil-5.7.3.tar.gz", hash = "sha256:af73f7bcebdc538eda9cc81d19db1db7bf26f103f91081d780bbacfcb620dee2"}, + {file = "psutil-5.8.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64"}, + {file = "psutil-5.8.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c"}, + {file = "psutil-5.8.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df"}, + {file = "psutil-5.8.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131"}, + {file = "psutil-5.8.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60"}, + {file = "psutil-5.8.0-cp27-none-win32.whl", hash = "sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876"}, + {file = "psutil-5.8.0-cp27-none-win_amd64.whl", hash = "sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65"}, + {file = "psutil-5.8.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8"}, + {file = "psutil-5.8.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6"}, + {file = "psutil-5.8.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac"}, + {file = "psutil-5.8.0-cp36-cp36m-win32.whl", hash = "sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2"}, + {file = "psutil-5.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d"}, + {file = "psutil-5.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935"}, + {file = "psutil-5.8.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d"}, + {file = "psutil-5.8.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023"}, + {file = "psutil-5.8.0-cp37-cp37m-win32.whl", hash = "sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394"}, + {file = "psutil-5.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563"}, + {file = "psutil-5.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef"}, + {file = "psutil-5.8.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28"}, + {file = "psutil-5.8.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b"}, + {file = "psutil-5.8.0-cp38-cp38-win32.whl", hash = "sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d"}, + {file = "psutil-5.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d"}, + {file = "psutil-5.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7"}, + {file = "psutil-5.8.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4"}, + {file = "psutil-5.8.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b"}, + {file = "psutil-5.8.0-cp39-cp39-win32.whl", hash = "sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0"}, + {file = "psutil-5.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3"}, + {file = "psutil-5.8.0.tar.gz", hash = "sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6"}, ] psycopg2 = [ {file = "psycopg2-2.8.6-cp27-cp27m-win32.whl", hash = "sha256:068115e13c70dc5982dfc00c5d70437fe37c014c808acce119b5448361c03725"}, @@ -2317,40 +2421,45 @@ psycopg2 = [ {file = "psycopg2-2.8.6.tar.gz", hash = "sha256:fb23f6c71107c37fd667cb4ea363ddeb936b348bbd6449278eb92c189699f543"}, ] psycopg2-binary = [ - {file = "psycopg2-binary-2.7.7.tar.gz", hash = "sha256:b19e9f1b85c5d6136f5a0549abdc55dcbd63aba18b4f10d0d063eb65ef2c68b4"}, - {file = "psycopg2_binary-2.7.7-cp27-cp27m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:ec43358c105794bc2b6fd34c68d27f92bea7102393c01889e93f4b6a70975728"}, - {file = "psycopg2_binary-2.7.7-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:9a7bccb1212e63f309eb9fab47b6eaef796f59850f169a25695b248ca1bf681b"}, - {file = "psycopg2_binary-2.7.7-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:2e952fa17ba48cbc2dc063ddeec37d7dc4ea0ef7db0ac1eda8906365a8543f31"}, - {file = "psycopg2_binary-2.7.7-cp27-cp27m-win32.whl", hash = "sha256:79cde4660de6f0bb523c229763bd8ad9a93ac6760b72c369cf1213955c430934"}, - {file = "psycopg2_binary-2.7.7-cp27-cp27m-win_amd64.whl", hash = "sha256:96b4e902cde37a7fc6ab306b3ac089a3949e6ce3d824eeca5b19dc0bedb9f6e2"}, - {file = "psycopg2_binary-2.7.7-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:19a2d1f3567b30f6c2bb3baea23f74f69d51f0c06c2e2082d0d9c28b0733a4c2"}, - {file = "psycopg2_binary-2.7.7-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:df6444f952ca849016902662e1a47abf4fa0678d75f92fd9dd27f20525f809cd"}, - {file = "psycopg2_binary-2.7.7-cp33-cp33m-win32.whl", hash = "sha256:7c8159352244e11bdd422226aa17651110b600d175220c451a9acf795e7414e0"}, - {file = "psycopg2_binary-2.7.7-cp33-cp33m-win_amd64.whl", hash = "sha256:d444b1545430ffc1e7a24ce5a9be122ccd3b135a7b7e695c5862c5aff0b11159"}, - {file = "psycopg2_binary-2.7.7-cp34-cp34m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:cb095a0657d792c8de9f7c9a0452385a309dfb1bbbb3357d6b1e216353ade6ca"}, - {file = "psycopg2_binary-2.7.7-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:bde7959ef012b628868d69c474ec4920252656d0800835ed999ba5e4f57e3e2e"}, - {file = "psycopg2_binary-2.7.7-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:f4c6926d9c03dadce7a3b378b40d2fea912c1344ef9b29869f984fb3d2a2420b"}, - {file = "psycopg2_binary-2.7.7-cp34-cp34m-win32.whl", hash = "sha256:2b69cf4b0fa2716fd977aa4e1fd39af6110eb47b2bb30b4e5a469d8fbecfc102"}, - {file = "psycopg2_binary-2.7.7-cp34-cp34m-win_amd64.whl", hash = "sha256:587098ca4fc46c95736459d171102336af12f0d415b3b865972a79c03f06259f"}, - {file = "psycopg2_binary-2.7.7-cp35-cp35m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:676d1a80b1eebc0cacae8dd09b2fde24213173bf65650d22b038c5ed4039f392"}, - {file = "psycopg2_binary-2.7.7-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4957452f7868f43f32c090dadb4188e9c74a4687323c87a882e943c2bd4780c3"}, - {file = "psycopg2_binary-2.7.7-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:5b79368bcdb1da4a05f931b62760bea0955ee2c81531d8e84625df2defd3f709"}, - {file = "psycopg2_binary-2.7.7-cp35-cp35m-win32.whl", hash = "sha256:6b0211ecda389101a7d1d3df2eba0cf7ffbdd2480ca6f1d2257c7bd739e84110"}, - {file = "psycopg2_binary-2.7.7-cp35-cp35m-win_amd64.whl", hash = "sha256:d16d42a1b9772152c1fe606f679b2316551f7e1a1ce273e7f808e82a136cdb3d"}, - {file = "psycopg2_binary-2.7.7-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:5138cec2ee1e53a671e11cc519505eb08aaaaf390c508f25b09605763d48de4b"}, - {file = "psycopg2_binary-2.7.7-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:7aba9786ac32c2a6d5fb446002ed936b47d5e1f10c466ef7e48f66eb9f9ebe3b"}, - {file = "psycopg2_binary-2.7.7-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:e63850d8c52ba2b502662bf3c02603175c2397a9acc756090e444ce49508d41e"}, - {file = "psycopg2_binary-2.7.7-cp36-cp36m-win32.whl", hash = "sha256:945f2eedf4fc6b2432697eb90bb98cc467de5147869e57405bfc31fa0b824741"}, - {file = "psycopg2_binary-2.7.7-cp36-cp36m-win_amd64.whl", hash = "sha256:d93ccc7bf409ec0a23f2ac70977507e0b8a8d8c54e5ee46109af2f0ec9e411f3"}, - {file = "psycopg2_binary-2.7.7-cp37-cp37m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:5cf43807392247d9bc99737160da32d3fa619e0bfd85ba24d1c78db205f472a4"}, - {file = "psycopg2_binary-2.7.7-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:b664011bb14ca1f2287c17185e222f2098f7b4c857961dbcf9badb28786dbbf4"}, - {file = "psycopg2_binary-2.7.7-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3d72a5fdc5f00ca85160915eb9a973cf9a0ab8148f6eda40708bf672c55ac1d1"}, - {file = "psycopg2_binary-2.7.7-cp37-cp37m-win32.whl", hash = "sha256:a3bfcac727538ec11af304b5eccadbac952d4cca1a551a29b8fe554e3ad535dc"}, - {file = "psycopg2_binary-2.7.7-cp37-cp37m-win_amd64.whl", hash = "sha256:348b49dd737ff74cfb5e663e18cb069b44c64f77ec0523b5794efafbfa7df0b8"}, + {file = "psycopg2-binary-2.8.6.tar.gz", hash = "sha256:11b9c0ebce097180129e422379b824ae21c8f2a6596b159c7659e2e5a00e1aa0"}, + {file = "psycopg2_binary-2.8.6-cp27-cp27m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:d14b140a4439d816e3b1229a4a525df917d6ea22a0771a2a78332273fd9528a4"}, + {file = "psycopg2_binary-2.8.6-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1fabed9ea2acc4efe4671b92c669a213db744d2af8a9fc5d69a8e9bc14b7a9db"}, + {file = "psycopg2_binary-2.8.6-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:f5ab93a2cb2d8338b1674be43b442a7f544a0971da062a5da774ed40587f18f5"}, + {file = "psycopg2_binary-2.8.6-cp27-cp27m-win32.whl", hash = "sha256:b4afc542c0ac0db720cf516dd20c0846f71c248d2b3d21013aa0d4ef9c71ca25"}, + {file = "psycopg2_binary-2.8.6-cp27-cp27m-win_amd64.whl", hash = "sha256:e74a55f6bad0e7d3968399deb50f61f4db1926acf4a6d83beaaa7df986f48b1c"}, + {file = "psycopg2_binary-2.8.6-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:0deac2af1a587ae12836aa07970f5cb91964f05a7c6cdb69d8425ff4c15d4e2c"}, + {file = "psycopg2_binary-2.8.6-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ad20d2eb875aaa1ea6d0f2916949f5c08a19c74d05b16ce6ebf6d24f2c9f75d1"}, + {file = "psycopg2_binary-2.8.6-cp34-cp34m-win32.whl", hash = "sha256:950bc22bb56ee6ff142a2cb9ee980b571dd0912b0334aa3fe0fe3788d860bea2"}, + {file = "psycopg2_binary-2.8.6-cp34-cp34m-win_amd64.whl", hash = "sha256:b8a3715b3c4e604bcc94c90a825cd7f5635417453b253499664f784fc4da0152"}, + {file = "psycopg2_binary-2.8.6-cp35-cp35m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:d1b4ab59e02d9008efe10ceabd0b31e79519da6fb67f7d8e8977118832d0f449"}, + {file = "psycopg2_binary-2.8.6-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:ac0c682111fbf404525dfc0f18a8b5f11be52657d4f96e9fcb75daf4f3984859"}, + {file = "psycopg2_binary-2.8.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7d92a09b788cbb1aec325af5fcba9fed7203897bbd9269d5691bb1e3bce29550"}, + {file = "psycopg2_binary-2.8.6-cp35-cp35m-win32.whl", hash = "sha256:aaa4213c862f0ef00022751161df35804127b78adf4a2755b9f991a507e425fd"}, + {file = "psycopg2_binary-2.8.6-cp35-cp35m-win_amd64.whl", hash = "sha256:c2507d796fca339c8fb03216364cca68d87e037c1f774977c8fc377627d01c71"}, + {file = "psycopg2_binary-2.8.6-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:ee69dad2c7155756ad114c02db06002f4cded41132cc51378e57aad79cc8e4f4"}, + {file = "psycopg2_binary-2.8.6-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:e82aba2188b9ba309fd8e271702bd0d0fc9148ae3150532bbb474f4590039ffb"}, + {file = "psycopg2_binary-2.8.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d5227b229005a696cc67676e24c214740efd90b148de5733419ac9aaba3773da"}, + {file = "psycopg2_binary-2.8.6-cp36-cp36m-win32.whl", hash = "sha256:a0eb43a07386c3f1f1ebb4dc7aafb13f67188eab896e7397aa1ee95a9c884eb2"}, + {file = "psycopg2_binary-2.8.6-cp36-cp36m-win_amd64.whl", hash = "sha256:e1f57aa70d3f7cc6947fd88636a481638263ba04a742b4a37dd25c373e41491a"}, + {file = "psycopg2_binary-2.8.6-cp37-cp37m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:833709a5c66ca52f1d21d41865a637223b368c0ee76ea54ca5bad6f2526c7679"}, + {file = "psycopg2_binary-2.8.6-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ba28584e6bca48c59eecbf7efb1576ca214b47f05194646b081717fa628dfddf"}, + {file = "psycopg2_binary-2.8.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:6a32f3a4cb2f6e1a0b15215f448e8ce2da192fd4ff35084d80d5e39da683e79b"}, + {file = "psycopg2_binary-2.8.6-cp37-cp37m-win32.whl", hash = "sha256:0e4dc3d5996760104746e6cfcdb519d9d2cd27c738296525d5867ea695774e67"}, + {file = "psycopg2_binary-2.8.6-cp37-cp37m-win_amd64.whl", hash = "sha256:cec7e622ebc545dbb4564e483dd20e4e404da17ae07e06f3e780b2dacd5cee66"}, + {file = "psycopg2_binary-2.8.6-cp38-cp38-macosx_10_9_x86_64.macosx_10_9_intel.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:ba381aec3a5dc29634f20692349d73f2d21f17653bda1decf0b52b11d694541f"}, + {file = "psycopg2_binary-2.8.6-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a0c50db33c32594305b0ef9abc0cb7db13de7621d2cadf8392a1d9b3c437ef77"}, + {file = "psycopg2_binary-2.8.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:2dac98e85565d5688e8ab7bdea5446674a83a3945a8f416ad0110018d1501b94"}, + {file = "psycopg2_binary-2.8.6-cp38-cp38-win32.whl", hash = "sha256:bd1be66dde2b82f80afb9459fc618216753f67109b859a361cf7def5c7968729"}, + {file = "psycopg2_binary-2.8.6-cp38-cp38-win_amd64.whl", hash = "sha256:8cd0fb36c7412996859cb4606a35969dd01f4ea34d9812a141cd920c3b18be77"}, + {file = "psycopg2_binary-2.8.6-cp39-cp39-macosx_10_9_x86_64.macosx_10_9_intel.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:89705f45ce07b2dfa806ee84439ec67c5d9a0ef20154e0e475e2b2ed392a5b83"}, + {file = "psycopg2_binary-2.8.6-cp39-cp39-manylinux1_i686.whl", hash = "sha256:42ec1035841b389e8cc3692277a0bd81cdfe0b65d575a2c8862cec7a80e62e52"}, + {file = "psycopg2_binary-2.8.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7312e931b90fe14f925729cde58022f5d034241918a5c4f9797cac62f6b3a9dd"}, + {file = "psycopg2_binary-2.8.6-cp39-cp39-win32.whl", hash = "sha256:6422f2ff0919fd720195f64ffd8f924c1395d30f9a495f31e2392c2efafb5056"}, + {file = "psycopg2_binary-2.8.6-cp39-cp39-win_amd64.whl", hash = "sha256:15978a1fbd225583dd8cdaf37e67ccc278b5abecb4caf6b2d6b8e2b948e953f6"}, ] py = [ - {file = "py-1.4.31-py2.py3-none-any.whl", hash = "sha256:4a3e4f3000c123835ac39cab5ccc510642153bc47bc1f13e2bbb53039540ae69"}, - {file = "py-1.4.31.tar.gz", hash = "sha256:a6501963c725fc2554dabfece8ae9a8fb5e149c0ac0a42fd2b02c5c1c57fc114"}, + {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"}, + {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"}, ] pyaml = [ {file = "pyaml-20.4.0-py2.py3-none-any.whl", hash = "sha256:67081749a82b72c45e5f7f812ee3a14a03b3f5c25ff36ec3b290514f8c4c4b99"}, @@ -2380,41 +2489,36 @@ pycparser = [ {file = "pycparser-2.14.tar.gz", hash = "sha256:7959b4a74abdc27b312fed1c21e6caf9309ce0b29ea86b591fd2e99ecdf27f73"}, ] pycryptodome = [ - {file = "pycryptodome-3.9.9-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:5598dc6c9dbfe882904e54584322893eff185b98960bbe2cdaaa20e8a437b6e5"}, - {file = "pycryptodome-3.9.9-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1cfdb92dca388e27e732caa72a1cc624520fe93752a665c3b6cd8f1a91b34916"}, - {file = "pycryptodome-3.9.9-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5f19e6ef750f677d924d9c7141f54bade3cd56695bbfd8a9ef15d0378557dfe4"}, - {file = "pycryptodome-3.9.9-cp27-cp27m-win32.whl", hash = "sha256:a3d8a9efa213be8232c59cdc6b65600276508e375e0a119d710826248fd18d37"}, - {file = "pycryptodome-3.9.9-cp27-cp27m-win_amd64.whl", hash = "sha256:50826b49fbca348a61529693b0031cdb782c39060fb9dca5ac5dff858159dc5a"}, - {file = "pycryptodome-3.9.9-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:19cb674df6c74a14b8b408aa30ba8a89bd1c01e23505100fb45f930fbf0ed0d9"}, - {file = "pycryptodome-3.9.9-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:28f75e58d02019a7edc7d4135203d2501dfc47256d175c72c9798f9a129a49a7"}, - {file = "pycryptodome-3.9.9-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:6d3baaf82681cfb1a842f1c8f77beac791ceedd99af911e4f5fabec32bae2259"}, - {file = "pycryptodome-3.9.9-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:946399d15eccebafc8ce0257fc4caffe383c75e6b0633509bd011e357368306c"}, - {file = "pycryptodome-3.9.9-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:eb01f9997e4d6a8ec8a1ad1f676ba5a362781ff64e8189fe2985258ba9cb9706"}, - {file = "pycryptodome-3.9.9-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:411745c6dce4eff918906eebcde78771d44795d747e194462abb120d2e537cd9"}, - {file = "pycryptodome-3.9.9-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:8f9f84059039b672a5a705b3c5aa21747867bacc30a72e28bf0d147cc8ef85ed"}, - {file = "pycryptodome-3.9.9-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:7798e73225a699651888489fbb1dbc565e03a509942a8ce6194bbe6fb582a41f"}, - {file = "pycryptodome-3.9.9-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:46e96aeb8a9ca8b1edf9b1fd0af4bf6afcf3f1ca7fa35529f5d60b98f3e4e959"}, - {file = "pycryptodome-3.9.9-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:843e5f10ecdf9d307032b8b91afe9da1d6ed5bb89d0bbec5c8dcb4ba44008e11"}, - {file = "pycryptodome-3.9.9-cp36-cp36m-win32.whl", hash = "sha256:b68794fba45bdb367eeb71249c26d23e61167510a1d0c3d6cf0f2f14636e62ee"}, - {file = "pycryptodome-3.9.9-cp36-cp36m-win_amd64.whl", hash = "sha256:60febcf5baf70c566d9d9351c47fbd8321da9a4edf2eff45c4c31c86164ca794"}, - {file = "pycryptodome-3.9.9-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:4ed27951b0a17afd287299e2206a339b5b6d12de9321e1a1575261ef9c4a851b"}, - {file = "pycryptodome-3.9.9-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:9000877383e2189dafd1b2fc68c6c726eca9a3cfb6d68148fbb72ccf651959b6"}, - {file = "pycryptodome-3.9.9-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:faa682c404c218e8788c3126c9a4b8fbcc54dc245b5b6e8ea5b46f3b63bd0c84"}, - {file = "pycryptodome-3.9.9-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:62c488a21c253dadc9f731a32f0ac61e4e436d81a1ea6f7d1d9146ed4d20d6bd"}, - {file = "pycryptodome-3.9.9-cp37-cp37m-win32.whl", hash = "sha256:834b790bbb6bd18956f625af4004d9c15eed12d5186d8e57851454ae76d52215"}, - {file = "pycryptodome-3.9.9-cp37-cp37m-win_amd64.whl", hash = "sha256:70d807d11d508433daf96244ec1c64e55039e8a35931fc5ea9eee94dbe3cb6b5"}, - {file = "pycryptodome-3.9.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:27397aee992af69d07502126561d851ba3845aa808f0e55c71ad0efa264dd7d4"}, - {file = "pycryptodome-3.9.9-cp38-cp38-manylinux1_i686.whl", hash = "sha256:d7ec2bd8f57c559dd24e71891c51c25266a8deb66fc5f02cc97c7fb593d1780a"}, - {file = "pycryptodome-3.9.9-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:e15bde67ccb7d4417f627dd16ffe2f5a4c2941ce5278444e884cb26d73ecbc61"}, - {file = "pycryptodome-3.9.9-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:5c3c4865730dfb0263f822b966d6d58429d8b1e560d1ddae37685fd9e7c63161"}, - {file = "pycryptodome-3.9.9-cp38-cp38-win32.whl", hash = "sha256:76b1a34d74bb2c91bce460cdc74d1347592045627a955e9a252554481c17c52f"}, - {file = "pycryptodome-3.9.9-cp38-cp38-win_amd64.whl", hash = "sha256:6e4227849e4231a3f5b35ea5bdedf9a82b3883500e5624f00a19156e9a9ef861"}, - {file = "pycryptodome-3.9.9-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2a68df525b387201a43b27b879ce8c08948a430e883a756d6c9e3acdaa7d7bd8"}, - {file = "pycryptodome-3.9.9-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:a4599c0ca0fc027c780c1c45ed996d5bef03e571470b7b1c7171ec1e1a90914c"}, - {file = "pycryptodome-3.9.9-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b4e6b269a8ddaede774e5c3adbef6bf452ee144e6db8a716d23694953348cd86"}, - {file = "pycryptodome-3.9.9-cp39-cp39-win32.whl", hash = "sha256:a199e9ca46fc6e999e5f47fce342af4b56c7de85fae893c69ab6aa17531fb1e1"}, - {file = "pycryptodome-3.9.9-cp39-cp39-win_amd64.whl", hash = "sha256:6e89bb3826e6f84501e8e3b205c22595d0c5492c2f271cbb9ee1c48eb1866645"}, - {file = "pycryptodome-3.9.9.tar.gz", hash = "sha256:910e202a557e1131b1c1b3f17a63914d57aac55cf9fb9b51644962841c3995c4"}, + {file = "pycryptodome-3.10.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1c5e1ca507de2ad93474be5cfe2bfa76b7cf039a1a32fc196f40935944871a06"}, + {file = "pycryptodome-3.10.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:6260e24d41149268122dd39d4ebd5941e9d107f49463f7e071fd397e29923b0c"}, + {file = "pycryptodome-3.10.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:3f840c49d38986f6e17dbc0673d37947c88bc9d2d9dba1c01b979b36f8447db1"}, + {file = "pycryptodome-3.10.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:2dea65df54349cdfa43d6b2e8edb83f5f8d6861e5cf7b1fbc3e34c5694c85e27"}, + {file = "pycryptodome-3.10.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:e61e363d9a5d7916f3a4ce984a929514c0df3daf3b1b2eb5e6edbb131ee771cf"}, + {file = "pycryptodome-3.10.1-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:2603c98ae04aac675fefcf71a6c87dc4bb74a75e9071ae3923bbc91a59f08d35"}, + {file = "pycryptodome-3.10.1-cp27-cp27m-win32.whl", hash = "sha256:38661348ecb71476037f1e1f553159b80d256c00f6c0b00502acac891f7116d9"}, + {file = "pycryptodome-3.10.1-cp27-cp27m-win_amd64.whl", hash = "sha256:1723ebee5561628ce96748501cdaa7afaa67329d753933296321f0be55358dce"}, + {file = "pycryptodome-3.10.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:77997519d8eb8a4adcd9a47b9cec18f9b323e296986528186c0e9a7a15d6a07e"}, + {file = "pycryptodome-3.10.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:99b2f3fc51d308286071d0953f92055504a6ffe829a832a9fc7a04318a7683dd"}, + {file = "pycryptodome-3.10.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:e0a4d5933a88a2c98bbe19c0c722f5483dc628d7a38338ac2cb64a7dbd34064b"}, + {file = "pycryptodome-3.10.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d3d6958d53ad307df5e8469cc44474a75393a434addf20ecd451f38a72fe29b8"}, + {file = "pycryptodome-3.10.1-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:a8eb8b6ea09ec1c2535bf39914377bc8abcab2c7d30fa9225eb4fe412024e427"}, + {file = "pycryptodome-3.10.1-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:31c1df17b3dc5f39600a4057d7db53ac372f492c955b9b75dd439f5d8b460129"}, + {file = "pycryptodome-3.10.1-cp35-abi3-manylinux1_i686.whl", hash = "sha256:a3105a0eb63eacf98c2ecb0eb4aa03f77f40fbac2bdde22020bb8a536b226bb8"}, + {file = "pycryptodome-3.10.1-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:a92d5c414e8ee1249e850789052608f582416e82422502dc0ac8c577808a9067"}, + {file = "pycryptodome-3.10.1-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:60386d1d4cfaad299803b45a5bc2089696eaf6cdd56f9fc17479a6f89595cfc8"}, + {file = "pycryptodome-3.10.1-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:501ab36aae360e31d0ec370cf5ce8ace6cb4112060d099b993bc02b36ac83fb6"}, + {file = "pycryptodome-3.10.1-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:fc7489a50323a0df02378bc2fff86eb69d94cc5639914346c736be981c6a02e7"}, + {file = "pycryptodome-3.10.1-cp35-abi3-win32.whl", hash = "sha256:9b6f711b25e01931f1c61ce0115245a23cdc8b80bf8539ac0363bdcf27d649b6"}, + {file = "pycryptodome-3.10.1-cp35-abi3-win_amd64.whl", hash = "sha256:7fd519b89585abf57bf47d90166903ec7b43af4fe23c92273ea09e6336af5c07"}, + {file = "pycryptodome-3.10.1-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:09c1555a3fa450e7eaca41ea11cd00afe7c91fef52353488e65663777d8524e0"}, + {file = "pycryptodome-3.10.1-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:758949ca62690b1540dfb24ad773c6da9cd0e425189e83e39c038bbd52b8e438"}, + {file = "pycryptodome-3.10.1-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:e3bf558c6aeb49afa9f0c06cee7fb5947ee5a1ff3bd794b653d39926b49077fa"}, + {file = "pycryptodome-3.10.1-pp27-pypy_73-win32.whl", hash = "sha256:f977cdf725b20f6b8229b0c87acb98c7717e742ef9f46b113985303ae12a99da"}, + {file = "pycryptodome-3.10.1-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6d2df5223b12437e644ce0a3be7809471ffa71de44ccd28b02180401982594a6"}, + {file = "pycryptodome-3.10.1-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:98213ac2b18dc1969a47bc65a79a8fca02a414249d0c8635abb081c7f38c91b6"}, + {file = "pycryptodome-3.10.1-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:12222a5edc9ca4a29de15fbd5339099c4c26c56e13c2ceddf0b920794f26165d"}, + {file = "pycryptodome-3.10.1-pp36-pypy36_pp73-win32.whl", hash = "sha256:6bbf7fee7b7948b29d7e71fcacf48bac0c57fb41332007061a933f2d996f9713"}, + {file = "pycryptodome-3.10.1.tar.gz", hash = "sha256:3e2e3a06580c5f190df843cdb90ea28d61099cf4924334d5297a995de68e4673"}, ] pyflakes = [ {file = "pyflakes-2.2.0-py2.py3-none-any.whl", hash = "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92"}, @@ -2425,14 +2529,8 @@ pyjwt = [ {file = "PyJWT-1.5.3.tar.gz", hash = "sha256:500be75b17a63f70072416843dc80c8821109030be824f4d14758f114978bae7"}, ] pyparsing = [ - {file = "pyparsing-2.1.1-py2.py3-none-any.whl", hash = "sha256:3a9743e0cba1df5ad7e5412d19a5ec1cd320c08852d5b5a4050aabe877d46c1f"}, - {file = "pyparsing-2.1.1.tar.gz", hash = "sha256:9bae5cd4cbee6da0d7d8d9a1647f5253a3b89652e707647eaf1961f4932ae6c6"}, - {file = "pyparsing-2.1.1.win32-py2.6.exe", hash = "sha256:f1a56b9e7c6a43ffe9a696cf3454b2c5774342d8493635da03d056d393591779"}, - {file = "pyparsing-2.1.1.win32-py2.7.exe", hash = "sha256:1302197acc1d5bbb206ca35dfae346cbb16d493e08d720ee4b15e97665d82026"}, - {file = "pyparsing-2.1.1.win32-py3.3.exe", hash = "sha256:be0d5736784b6100bf47a587b112e9a5b00d0803025407feb981836109c1acb8"}, - {file = "pyparsing-2.1.1.win32-py3.4.exe", hash = "sha256:26d293069c5208e132bdeef81d4f9e20dd0d35da2ed78eded4af1da148fdf130"}, - {file = "pyparsing-2.1.1.win32-py3.5.exe", hash = "sha256:900351d66d07f1338942074a4306c54d684d53a19df286e8679fdb69a0122dca"}, - {file = "pyparsing-2.1.1.zip", hash = "sha256:4bd04badfda39b1e2fd0d77cb78b488c881d88c31734791a0ae902979ae10575"}, + {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, + {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, ] pyramid = [ {file = "pyramid-1.10.4-py2.py3-none-any.whl", hash = "sha256:51bf64647345237c00d2fe558935e0e4938c156e29f17e203457fd8e1d757dc7"}, @@ -2442,49 +2540,55 @@ pyramid-localroles = [ {file = "pyramid_localroles-0.1.zip", hash = "sha256:4d297d06677d54471cbca9f2744e9224528204cf83045a2a19b6f84707d0ef1b"}, ] pyramid-multiauth = [ - {file = "pyramid_multiauth-0.8.0-py2.py3-none-any.whl", hash = "sha256:a460e43223e8fbdaa580ef9319fb2f1299bf6cea9c9496e68169c3a6e07ed523"}, - {file = "pyramid_multiauth-0.8.0.tar.gz", hash = "sha256:535770d3807421c11f891c786cec45407eee71432eaa4d628fa4e6a9b04802d3"}, + {file = "pyramid_multiauth-0.9.0-py2.py3-none-any.whl", hash = "sha256:6cad38c3613db10b45fe7dd5f4b81e43d7ed12c623cbceee7626d4d0dd8a0f52"}, + {file = "pyramid_multiauth-0.9.0.tar.gz", hash = "sha256:3eda2a01de867ce8e68e8f0f410a7b51be68891e34dc31808992fdf1bcc4f952"}, ] pyramid-retry = [ {file = "pyramid_retry-1.0-py2.py3-none-any.whl", hash = "sha256:7053f2345b2676f9b9031605a6764169963dad2f73e26873ce9331f86c78db46"}, {file = "pyramid_retry-1.0.tar.gz", hash = "sha256:7ad3b813df3c5c903bb1e2c4075266b52295ce32e614ba8c15c656c07c503923"}, ] pyramid-tm = [ - {file = "pyramid_tm-2.2.1-py2.py3-none-any.whl", hash = "sha256:7e374c0b774d4a5c83b04fe4c195a601c7219023cf4944a8e4251a86b7e288da"}, - {file = "pyramid_tm-2.2.1.tar.gz", hash = "sha256:fde97db9d92039a154ca6afffdd2485874c7d3e7a6432adb51b7a60810bad422"}, + {file = "pyramid_tm-2.4-py2.py3-none-any.whl", hash = "sha256:4a4e212cd239f06c496d074f5d294e88478b94059541448bc151d505f653be59"}, + {file = "pyramid_tm-2.4.tar.gz", hash = "sha256:5fd6d4ac9181a65ec54e5b280229ed6d8b3ed6a8f5a0bcff05c572751f086533"}, ] pyramid-translogger = [ {file = "pyramid_translogger-0.1.tar.gz", hash = "sha256:0bae9a98a7ba62316917272d06c553fbb9116cbc561592b6ebfabcb335724589"}, ] pytest = [ - {file = "pytest-2.9.2-py2.py3-none-any.whl", hash = "sha256:ccc23b4aab3ef3e19e731de9baca73f3b1a7e610d9ec65b28c36a5a3305f0349"}, - {file = "pytest-2.9.2.tar.gz", hash = "sha256:12c18abb9a09a5b2802dba75c7a2d7d6c8c0f1258abd8243e7688415d87ad1d8"}, + {file = "pytest-3.10.1-py2.py3-none-any.whl", hash = "sha256:3f193df1cfe1d1609d4c583838bea3d532b18d6160fd3f55c9447fdca30848ec"}, + {file = "pytest-3.10.1.tar.gz", hash = "sha256:e246cf173c01169b9617fc07264b7b1316e78d7a650055235d6d897bc80d9660"}, ] pytest-cov = [ - {file = "pytest-cov-2.2.1.tar.gz", hash = "sha256:a8b22e53e7f3b971454c35df99dffe21f4749f539491e935c55d3ff7e1b284fa"}, - {file = "pytest_cov-2.2.1-py2.py3-none-any.whl", hash = "sha256:40bfd01002ceaf9e6c5d371d3c4d541d378a4214ea03e45f934980766a809384"}, + {file = "pytest-cov-2.9.0.tar.gz", hash = "sha256:b6a814b8ed6247bd81ff47f038511b57fe1ce7f4cc25b9106f1a4b106f1d9322"}, + {file = "pytest_cov-2.9.0-py2.py3-none-any.whl", hash = "sha256:c87dfd8465d865655a8213859f1b4749b43448b5fae465cb981e16d52a811424"}, ] pytest-exact-fixtures = [ - {file = "pytest_exact_fixtures-0.1.tar.gz", hash = "sha256:9f20b98260346fa9e62c86df8e1efc5405ae6559edf824240ef4a8f50f7305fd"}, + {file = "pytest_exact_fixtures-0.3-py2.py3-none-any.whl", hash = "sha256:853436198b51026de937b06de60ab5276a6c924614e36193c60041140b66aec6"}, + {file = "pytest_exact_fixtures-0.3.tar.gz", hash = "sha256:f3e93bbea59f74f0beb5bf71cd18048e2b478ad665e71c37a4f8b33f4ec72718"}, +] +pytest-forked = [ + {file = "pytest-forked-1.3.0.tar.gz", hash = "sha256:6aa9ac7e00ad1a539c41bec6d21011332de671e938c7637378ec9710204e37ca"}, + {file = "pytest_forked-1.3.0-py2.py3-none-any.whl", hash = "sha256:dc4147784048e70ef5d437951728825a131b81714b398d5d52f17c7c144d8815"}, ] pytest-instafail = [ - {file = "pytest-instafail-0.3.0.tar.gz", hash = "sha256:b4d5fc3ca81e530a8d0e15a7771dc14b06fc9a0930c4b3909a7f4527040572c3"}, + {file = "pytest-instafail-0.4.2.tar.gz", hash = "sha256:19273fdf3f0f9a1cb4b7a0bc8aa1bdaaf6b0f62a681b693d5eca4626abc99782"}, + {file = "pytest_instafail-0.4.2-py2.py3-none-any.whl", hash = "sha256:1ec440a177be89a9ed2759dade8e1f7a2b95bac74ae81dc91318d309bf4ebd4f"}, ] pytest-mock = [ - {file = "pytest-mock-0.11.0.zip", hash = "sha256:a897c6283aa116c161f5f08b8f73301685f6b8abfcd0b9b0d000668bc0faaaa3"}, - {file = "pytest_mock-0.11.0-py2.py3-none-any.whl", hash = "sha256:5d109071ac1c6a5a883aece92c507b4562efce86054ab39c83a9f3554688289d"}, + {file = "pytest-mock-3.2.0.tar.gz", hash = "sha256:7122d55505d5ed5a6f3df940ad174b3f606ecae5e9bc379569cdcbd4cd9d2b83"}, + {file = "pytest_mock-3.2.0-py3-none-any.whl", hash = "sha256:5564c7cd2569b603f8451ec77928083054d8896046830ca763ed68f4112d17c7"}, ] pytest-timeout = [ - {file = "pytest-timeout-1.0.0.tar.gz", hash = "sha256:1465096be73e16df1e15d1b1453692428a7e15b997d756bc565aee0d12798ce1"}, - {file = "pytest_timeout-1.0.0-py2.py3-none-any.whl", hash = "sha256:d53665f3dad30de23b8377623a5ec9b6f489c4a70aa952c1860febc33dac3c88"}, + {file = "pytest-timeout-1.4.2.tar.gz", hash = "sha256:20b3113cf6e4e80ce2d403b6fb56e9e1b871b510259206d40ff8d609f48bda76"}, + {file = "pytest_timeout-1.4.2-py2.py3-none-any.whl", hash = "sha256:541d7aa19b9a6b4e475c759fd6073ef43d7cdc9a92d95644c260076eb257a063"}, ] pytest-xdist = [ - {file = "pytest-xdist-1.14.zip", hash = "sha256:4a5e1199122fa29e3017d8d189f59ccc5d82e841474ba2a1eec0e89606153623"}, - {file = "pytest_xdist-1.14-py2.py3-none-any.whl", hash = "sha256:052f95dea01ccfc752f9f4828908bc6e16d4130ffc420b6e131019554a9957db"}, + {file = "pytest-xdist-1.27.0.tar.gz", hash = "sha256:a96ed691705882560fa3fc95531fbd4c224896c827f4004817eb2dcac4ba41a2"}, + {file = "pytest_xdist-1.27.0-py2.py3-none-any.whl", hash = "sha256:a64915be2b23235d6cec0992b8f59b791d64083756fbf13cf574fa5757085bc7"}, ] python-dateutil = [ - {file = "python-dateutil-2.7.3.tar.gz", hash = "sha256:e27001de32f627c22380a688bcc43ce83504a7bc5da472209b4c70f02829f0b8"}, - {file = "python_dateutil-2.7.3-py2.py3-none-any.whl", hash = "sha256:1adb80e7a782c12e52ef9a8182bebeb73f1d7e24e374397af06fb4956c8dc5c0"}, + {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, + {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, ] python-jose = [ {file = "python-jose-2.0.2.tar.gz", hash = "sha256:391f860dbe274223d73dd87de25e4117bf09e8fe5f93a417663b1f2d7b591165"}, @@ -2495,8 +2599,8 @@ python-magic = [ {file = "python_magic-0.4.15-py2.py3-none-any.whl", hash = "sha256:f2674dcfad52ae6c49d4803fa027809540b130db1dec928cfbb9240316831375"}, ] pytz = [ - {file = "pytz-2020.4-py2.py3-none-any.whl", hash = "sha256:5c55e189b682d420be27c6995ba6edce0c0a77dd67bfbe2ae6607134d5851ffd"}, - {file = "pytz-2020.4.tar.gz", hash = "sha256:3e6b7dd2d1e0a59084bcee14a17af60c5c562cdc16d828e8eba2e683d3a7e268"}, + {file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"}, + {file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"}, ] pywin32 = [ {file = "pywin32-227-cp27-cp27m-win32.whl", hash = "sha256:371fcc39416d736401f0274dd64c2302728c9e034808e37381b5e1b22be4a6b0"}, @@ -2530,14 +2634,15 @@ rdflib = [ {file = "rdflib-4.2.2.tar.gz", hash = "sha256:da1df14552555c5c7715d8ce71c08f404c988c58a1ecd38552d0da4fc261280d"}, ] rdflib-jsonld = [ - {file = "rdflib-jsonld-0.3.tar.gz", hash = "sha256:944a1cf22a217bd78acacc183ea329848cba3f24d0cfb86541b42732cd412a88"}, + {file = "rdflib-jsonld-0.5.0.tar.gz", hash = "sha256:4f7d55326405071c7bce9acf5484643bcb984eadb84a6503053367da207105ed"}, ] "repoze.debug" = [ - {file = "repoze.debug-1.0.2.tar.gz", hash = "sha256:67a211638f7719977fda6d1442ef2f1aa14599e4da098db4fdfe23bdc98dde11"}, + {file = "repoze.debug-1.1-py2-none-any.whl", hash = "sha256:1d90e5b088b167bcde13bdedfe2e34f15fe8a1f53103e406e49b7c11be4d994d"}, + {file = "repoze.debug-1.1.tar.gz", hash = "sha256:f897fbb3a09499b0cee3fe2c5e4579ff04e5b0b87b1aad6098d242cbbf573000"}, ] requests = [ - {file = "requests-2.25.0-py2.py3-none-any.whl", hash = "sha256:e786fa28d8c9154e6a4de5d46a1d921b8749f8b74e28bde23768e5e16eece998"}, - {file = "requests-2.25.0.tar.gz", hash = "sha256:7f1a0b932f4a60a1a65caa4263921bb7d9ee911957e0ae4a23a6dd08185ad5f8"}, + {file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"}, + {file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"}, ] responses = [ {file = "responses-0.12.1-py2.py3-none-any.whl", hash = "sha256:ef265bd3200bdef5ec17912fc64a23570ba23597fd54ca75c18650fa1699213d"}, @@ -2556,8 +2661,8 @@ rutter = [ {file = "rutter-0.3.tar.gz", hash = "sha256:2607d3c3843f0e6094e62235b7a587b0603bf3985dd3522ee3f739648790bd5c"}, ] s3transfer = [ - {file = "s3transfer-0.2.1-py2.py3-none-any.whl", hash = "sha256:b780f2411b824cb541dbcd2c713d0cb61c7d1bcadae204cdddda2b35cef493ba"}, - {file = "s3transfer-0.2.1.tar.gz", hash = "sha256:6efc926738a3cd576c2a79725fed9afde92378aa5c6a957e3af010cb019fac9d"}, + {file = "s3transfer-0.3.4-py2.py3-none-any.whl", hash = "sha256:1e28620e5b444652ed752cf87c7e0cb15b0e578972568c6609f0f18212f259ed"}, + {file = "s3transfer-0.3.4.tar.gz", hash = "sha256:7fdddb4f22275cf1d32129e21f056337fd2a80b6ccef1664528145b72c49e6d2"}, ] sentry-sdk = [ {file = "sentry-sdk-0.16.5.tar.gz", hash = "sha256:e12eb1c2c01cd9e9cfe70608dbda4ef451f37ef0b7cbb92e5d43f87c341d6334"}, @@ -2598,18 +2703,19 @@ six = [ {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, ] smmap = [ - {file = "smmap-3.0.4-py2.py3-none-any.whl", hash = "sha256:54c44c197c819d5ef1991799a7e30b662d1e520f2ac75c9efbeb54a742214cf4"}, - {file = "smmap-3.0.4.tar.gz", hash = "sha256:9c98bbd1f9786d22f14b3d4126894d56befb835ec90cef151af566c7e19b5d24"}, + {file = "smmap-3.0.5-py2.py3-none-any.whl", hash = "sha256:7bfcf367828031dc893530a29cb35eb8c8f2d7c8f2d0989354d75d24c8573714"}, + {file = "smmap-3.0.5.tar.gz", hash = "sha256:84c2751ef3072d4f6b2785ec7ee40244c6f45eb934d9e543e2c51f1bd3d54c50"}, ] soupsieve = [ - {file = "soupsieve-2.1-py3-none-any.whl", hash = "sha256:4bb21a6ee4707bf43b61230e80740e71bfe56e55d1f1f50924b087bb2975c851"}, - {file = "soupsieve-2.1.tar.gz", hash = "sha256:6dc52924dc0bc710a5d16794e6b3480b2c7c08b07729505feab2b2c16661ff6e"}, + {file = "soupsieve-2.2-py3-none-any.whl", hash = "sha256:d3a5ea5b350423f47d07639f74475afedad48cf41c0ad7a82ca13a3928af34f6"}, + {file = "soupsieve-2.2.tar.gz", hash = "sha256:407fa1e8eb3458d1b5614df51d9651a1180ea5fedf07feb46e45d7e25e6d6cdd"}, ] sparqlwrapper = [ - {file = "SPARQLWrapper-1.7.6-py2.7.egg", hash = "sha256:0b9ee3070ca418585b752b48e5ef1d33aa2bf9d5431186ee30b6bcf212c52e78"}, - {file = "SPARQLWrapper-1.7.6-py3.4.egg", hash = "sha256:55b972ed27cf81243f3d8a837993a4b3f8ccc7392f9f847c86e5b6a8ebdfdcd1"}, - {file = "SPARQLWrapper-1.7.6.tar.gz", hash = "sha256:dccabec900eb9c97cb47834bd4b66ceaeb4d9ea11bae24a24fe734e9f48522f8"}, - {file = "SPARQLWrapper-1.7.6.zip", hash = "sha256:052c5b99ede756e227ff2db61a6664633a135d99fa4a8d728459480f5bc9a540"}, + {file = "SPARQLWrapper-1.8.5-py2-none-any.whl", hash = "sha256:357ee8a27bc910ea13d77836dbddd0b914991495b8cc1bf70676578155e962a8"}, + {file = "SPARQLWrapper-1.8.5-py2.7.egg", hash = "sha256:17ec44b08b8ae2888c801066249f74fe328eec25d90203ce7eadaf82e64484c7"}, + {file = "SPARQLWrapper-1.8.5-py3-none-any.whl", hash = "sha256:c7f9c9d8ebb13428771bc3b6dee54197422507dcc3dea34e30d5dcfc53478dec"}, + {file = "SPARQLWrapper-1.8.5-py3.4.egg", hash = "sha256:8cf6c21126ed76edc85c5c232fd6f77b9f61f8ad1db90a7147cdde2104aff145"}, + {file = "SPARQLWrapper-1.8.5.tar.gz", hash = "sha256:d6a66b5b8cda141660e07aeb00472db077a98d22cb588c973209c7336850fb3c"}, ] sqlalchemy = [ {file = "SQLAlchemy-1.3.16-cp27-cp27m-macosx_10_13_x86_64.whl", hash = "sha256:8d8c21e9d4efef01351bf28513648ceb988031be4159745a7ad1b3e28c8ff68a"}, @@ -2668,8 +2774,8 @@ uptime = [ {file = "uptime-3.0.1.tar.gz", hash = "sha256:7c300254775b807ce46e3dcbcda30aa3b9a204b9c57a7ac1e79ee6dbe3942973"}, ] urllib3 = [ - {file = "urllib3-1.25.11-py2.py3-none-any.whl", hash = "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e"}, - {file = "urllib3-1.25.11.tar.gz", hash = "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2"}, + {file = "urllib3-1.26.3-py2.py3-none-any.whl", hash = "sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80"}, + {file = "urllib3-1.26.3.tar.gz", hash = "sha256:de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73"}, ] venusian = [ {file = "venusian-1.2.0-py2.py3-none-any.whl", hash = "sha256:2f2d077a1eedc3fda40425f65687c8c494da7e83d7c23bc2c4d1a40eb3ca5b6d"}, @@ -2680,8 +2786,8 @@ waitress = [ {file = "waitress-1.2.0.tar.gz", hash = "sha256:e624c829656ffc99b33d661072b2814885ae92835cf835ee8ab283ddb7c915b9"}, ] webob = [ - {file = "WebOb-1.8.5-py2.py3-none-any.whl", hash = "sha256:36db8203c67023d68c1b00208a7bf55e3b10de2aa317555740add29c619de12b"}, - {file = "WebOb-1.8.5.tar.gz", hash = "sha256:05aaab7975e0ee8af2026325d656e5ce14a71f1883c52276181821d6d5bf7086"}, + {file = "WebOb-1.8.6-py2.py3-none-any.whl", hash = "sha256:a3c89a8e9ba0aeb17382836cdb73c516d0ecf6630ec40ec28288f3ed459ce87b"}, + {file = "WebOb-1.8.6.tar.gz", hash = "sha256:aa3a917ed752ba3e0b242234b2a373f9c4e2a75d35291dcbe977649bd21fd108"}, ] websocket-client = [ {file = "websocket_client-0.57.0-py2.py3-none-any.whl", hash = "sha256:0fc45c961324d79c781bab301359d5a1b00b13ad1b10415a4780229ef71a5549"}, @@ -2726,35 +2832,45 @@ zipp = [ {file = "zope.deprecation-4.4.0.tar.gz", hash = "sha256:0d453338f04bacf91bbfba545d8bcdf529aa829e67b705eac8c1a7fdce66e2df"}, ] "zope.interface" = [ - {file = "zope.interface-4.6.0-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:a15e75d284178afe529a536b0e8b28b7e107ef39626a7809b4ee64ff3abc9127"}, - {file = "zope.interface-4.6.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:bbcef00d09a30948756c5968863316c949d9cedbc7aabac5e8f0ffbdb632e5f1"}, - {file = "zope.interface-4.6.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9e998ba87df77a85c7bed53240a7257afe51a07ee6bc3445a0bf841886da0b97"}, - {file = "zope.interface-4.6.0-cp27-cp27m-win32.whl", hash = "sha256:20a12ab46a7e72b89ce0671e7d7a6c3c1ca2c2766ac98112f78c5bddaa6e4375"}, - {file = "zope.interface-4.6.0-cp27-cp27m-win_amd64.whl", hash = "sha256:d788a3999014ddf416f2dc454efa4a5dbeda657c6aba031cf363741273804c6b"}, - {file = "zope.interface-4.6.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7e5c9a5012b2b33e87980cee7d1c82412b2ebabcb5862d53413ba1a2cfde23aa"}, - {file = "zope.interface-4.6.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bad44274b151d46619a7567010f7cde23a908c6faa84b97598fd2f474a0c6891"}, - {file = "zope.interface-4.6.0-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:7040547e5b882349c0a2cc9b50674b1745db551f330746af434aad4f09fba2cc"}, - {file = "zope.interface-4.6.0-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:81295629128f929e73be4ccfdd943a0906e5fe3cdb0d43ff1e5144d16fbb52b1"}, - {file = "zope.interface-4.6.0-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:298f82c0ab1b182bd1f34f347ea97dde0fffb9ecf850ecf7f8904b8442a07487"}, - {file = "zope.interface-4.6.0-cp34-cp34m-win32.whl", hash = "sha256:7e099fde2cce8b29434684f82977db4e24f0efa8b0508179fce1602d103296a2"}, - {file = "zope.interface-4.6.0-cp34-cp34m-win_amd64.whl", hash = "sha256:f99451f3a579e73b5dd58b1b08d1179791d49084371d9a47baad3b22417f0317"}, - {file = "zope.interface-4.6.0-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:3b877de633a0f6d81b600624ff9137312d8b1d0f517064dfc39999352ab659f0"}, - {file = "zope.interface-4.6.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:b639f72b95389620c1f881d94739c614d385406ab1d6926a9ffe1c8abbea23fe"}, - {file = "zope.interface-4.6.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:11ebddf765bff3bbe8dbce10c86884d87f90ed66ee410a7e6c392086e2c63d02"}, - {file = "zope.interface-4.6.0-cp35-cp35m-win32.whl", hash = "sha256:1157b1ec2a1f5bf45668421e3955c60c610e31913cc695b407a574efdbae1f7b"}, - {file = "zope.interface-4.6.0-cp35-cp35m-win_amd64.whl", hash = "sha256:a6a6ff82f5f9b9702478035d8f6fb6903885653bff7ec3a1e011edc9b1a7168d"}, - {file = "zope.interface-4.6.0-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:4265681e77f5ac5bac0905812b828c9fe1ce80c6f3e3f8574acfb5643aeabc5b"}, - {file = "zope.interface-4.6.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:086707e0f413ff8800d9c4bc26e174f7ee4c9c8b0302fbad68d083071822316c"}, - {file = "zope.interface-4.6.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5f4d42baed3a14c290a078e2696c5f565501abde1b2f3f1a1c0a94fbf6fbcc39"}, - {file = "zope.interface-4.6.0-cp36-cp36m-win32.whl", hash = "sha256:a0c39e2535a7e9c195af956610dba5a1073071d2d85e9d2e5d789463f63e52ab"}, - {file = "zope.interface-4.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:968d5c5702da15c5bf8e4a6e4b67a4d92164e334e9c0b6acf080106678230b98"}, - {file = "zope.interface-4.6.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:14b242d53f6f35c2d07aa2c0e13ccb710392bcd203e1b82a1828d216f6f6b11f"}, - {file = "zope.interface-4.6.0-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:2f6175722da6f23dbfc76c26c241b67b020e1e83ec7fe93c9e5d3dd18667ada2"}, - {file = "zope.interface-4.6.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:eed88ae03e1ef3a75a0e96a55a99d7937ed03e53d0cffc2451c208db445a2966"}, - {file = "zope.interface-4.6.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:95cc574b0b83b85be9917d37cd2fad0ce5a0d21b024e1a5804d044aabea636fc"}, - {file = "zope.interface-4.6.0-cp37-cp37m-win32.whl", hash = "sha256:62dd71dbed8cc6a18379700701d959307823b3b2451bdc018594c48956ace745"}, - {file = "zope.interface-4.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:550695c4e7313555549aa1cdb978dc9413d61307531f123558e438871a883d63"}, - {file = "zope.interface-4.6.0.tar.gz", hash = "sha256:1b3d0dcabc7c90b470e59e38a9acaa361be43b3a6ea644c0063951964717f0e5"}, + {file = "zope.interface-4.7.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:34381fcecc6e6f57d72bc2fab6175976eeacdd61dbb34427a37b260238278199"}, + {file = "zope.interface-4.7.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:4d0830e1d544b2c303064ec01923de2b9d6f5b5d0d78608a91d758b0f469361c"}, + {file = "zope.interface-4.7.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:73a618e734803ded8b8d8f14f9a6371c6a1acc445840cf6ae57733041e796671"}, + {file = "zope.interface-4.7.2-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:a82d36ecc28e72904388f72f57f3c04aee7c43a019e302d61944b3886c261be3"}, + {file = "zope.interface-4.7.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:b0029f193d91a1e0085e4a99dd71e4c63a3e7826ec4a8d2ea457f02e1b6b0bb4"}, + {file = "zope.interface-4.7.2-cp27-cp27m-win32.whl", hash = "sha256:d8a0cb84de725ccd6abd9b5bd32cb94a11db336076fb6d459f1fed23d0719e0c"}, + {file = "zope.interface-4.7.2-cp27-cp27m-win_amd64.whl", hash = "sha256:a36e7e1972109504dfa0995a89b6c24a990113eb4cedef93d0eaf1452901b6ac"}, + {file = "zope.interface-4.7.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:2690fd5b042062d866017db11ce1e12d4862df28614cc2915dc57e52b46a8594"}, + {file = "zope.interface-4.7.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:0616040d5a18786aff5d25ef6e1fa0f875b7ba5b6f1a923c1153be81dd9c65ad"}, + {file = "zope.interface-4.7.2-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6f1e8914eee2e3a0bcf435d963ca5cf3a3df89a47cbd3e2b16343bc875194fed"}, + {file = "zope.interface-4.7.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:a41a34c55887743ee124e8f696217dec1a7eead1164d27ef27dfae528c396a23"}, + {file = "zope.interface-4.7.2-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:1033e7bb858c398580ca7cbb50f15b715e6031d5772f8a1bde4042c12300a52a"}, + {file = "zope.interface-4.7.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:ae6c4a1fa696c12c3b654fa0d160f3781271f0edbbb0ae50f285a91f2a272a09"}, + {file = "zope.interface-4.7.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:64446f9baa2c51f47b0e272939c583ffd220e67f5bcbc2f18dd244c5a46a7018"}, + {file = "zope.interface-4.7.2-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:a7b50fa86c1bd863ef3b3314da62928c015a732bb0aef220852b9606104f0df5"}, + {file = "zope.interface-4.7.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a9fce290a6ba88e5e6e81dd1e800c045212df69ab69d1de0d303b1af9cec692f"}, + {file = "zope.interface-4.7.2-cp35-cp35m-win32.whl", hash = "sha256:f044fec9c7e1b0ec6fdf0d3abc648c2f3b9128933051a9a73af52dbdd9e6d6e9"}, + {file = "zope.interface-4.7.2-cp35-cp35m-win_amd64.whl", hash = "sha256:23c4a70a9abb8faa35e2967e2e7cbd9225512b706b6eb96b01eb1ccbb2b632c3"}, + {file = "zope.interface-4.7.2-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:61b95dbfd03ce2a55c38da711cba7130605dbef4839ca12b53c46827826c5c5b"}, + {file = "zope.interface-4.7.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:98a21acc7d1e45fcb700831b66ec6c84a3c2a5a94868d72ef83565966adc474f"}, + {file = "zope.interface-4.7.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:6f2bf246ee9350f428860c37db6158cfb27a7e585d60b2bb3b88864810875835"}, + {file = "zope.interface-4.7.2-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:b12241fac561b635329c3275e911a53e104b43875b99d31332d006d52e180912"}, + {file = "zope.interface-4.7.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:7d3c4f10b7a8502a68a8eadcd57e86a35e3948af3edee7bd49a21b225361b0da"}, + {file = "zope.interface-4.7.2-cp36-cp36m-win32.whl", hash = "sha256:02339c53bbf7e438dec371af1f401e4843f9dc5765b3b032032b195dd72b47f2"}, + {file = "zope.interface-4.7.2-cp36-cp36m-win_amd64.whl", hash = "sha256:31fdcc9eaf2c379e8b416184a0749ce3f95fdaf206b092b63bdc065aecca6a95"}, + {file = "zope.interface-4.7.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9e67e9fa7dc43210ad766cd6eef133d9d256a530fe07e5585685cdc742170d10"}, + {file = "zope.interface-4.7.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:b906dda76ab70b6905ef3014260e7f1c861a0c4841e29826eb34a6187255504b"}, + {file = "zope.interface-4.7.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:07de051fac6dedc6c659034f80bc46623edc776c757fa26f3f467954b12d2403"}, + {file = "zope.interface-4.7.2-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:36e7438d2f71153cea6b119ddd2648bc010cec4368fd8e7170e50090c0d7ed19"}, + {file = "zope.interface-4.7.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:4855384c27fe7e31efbee32f74659421d64e5bfa8b7df2ec08d306d0f3d4cee6"}, + {file = "zope.interface-4.7.2-cp37-cp37m-win32.whl", hash = "sha256:3b6a2ef2c6b4e9786939bd9861e7b98bc01cb3024f87c8cf4b78872f2afcf584"}, + {file = "zope.interface-4.7.2-cp37-cp37m-win_amd64.whl", hash = "sha256:eb92c733be08c6e2b8dfd4613d1b3c2f345ca4f83219d40fda4680333d3a0dc4"}, + {file = "zope.interface-4.7.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:07a8bb9110854c0ab9329adbbec7050af242a78a62e226ab49e9c2182090f501"}, + {file = "zope.interface-4.7.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:11db683f49652b34aa87904b27d00f9032fa2db7f1f9676c05b13361a3c7547c"}, + {file = "zope.interface-4.7.2-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:65cef4766be4be9372621cd17773424302c21785dfaf6e9bd5b64b1f1264f9cc"}, + {file = "zope.interface-4.7.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:08ae0a88ac29b92faff069e0511ad27197b3274bdf67ebd8c75aaeb05823c7af"}, + {file = "zope.interface-4.7.2-cp38-cp38-win32.whl", hash = "sha256:993051db4278f9ec3b191ae823a7bb32b6a91fed6e960d43500fc4ce64cdb4e0"}, + {file = "zope.interface-4.7.2-cp38-cp38-win_amd64.whl", hash = "sha256:d79da12a15edd6d7c366766954c4b6de0247e85ba35ee2ad9f37f972e7080f8a"}, + {file = "zope.interface-4.7.2.tar.gz", hash = "sha256:fd1101bd3fcb4f4cf3485bb20d6cb0b56909b94d3bd2a53a6cb9d381c3da3365"}, ] "zope.sqlalchemy" = [ {file = "zope.sqlalchemy-1.3-py2.py3-none-any.whl", hash = "sha256:607d65c7974b2aa586f0608ca740b03ddb582ad84ceb3545b55ad5a402fd6dff"}, diff --git a/pyproject.toml b/pyproject.toml index 2f9ac0822b..5df7daa14c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,96 +36,92 @@ classifiers = [ [tool.poetry.dependencies] python = ">=3.6.1,<3.7" -boto3 = "^1.10.50" -botocore = "^1.13.50" +awscli = ">=1.18.219" +boto3 = "^1.16.59" +botocore = "^1.19.59" certifi = ">=2020.11.8" chardet = "3.0.4" -# TODO: These next three are not used in cgap. Are they really needed? -kmp 29-Apr-2020 -# I think .recipe is a buildout thing so I'm going to try commenting this out as a start. Delete later. -kmp 15-Dec-2020 -# "collective.recipe.cmd" = "0.11" -# "collective.recipe.modwsgi" = "2.1" -# "collective.recipe.template" = "1.13" colorama = "0.3.3" -dcicsnovault = "4.1.0" -dcicutils = "^1.4.0" +dcicsnovault = "4.3.1" +dcicutils = "^1.10.0" docutils = "0.12" -elasticsearch = "6.4.0" +elasticsearch = "6.8.1" elasticsearch-dsl = "^6.4.0" execnet = "1.4.1" future = "^0.15.2" -humanfriendly = "1.44.5" +humanfriendly = "^1.44.9" hupper = "1.5" -idna = "2.7" +idna = ">=2.7,<3" isodate = "0.5.4" jmespath = "0.9.0" -jsonschema-serialize-fork = "2.1.1" +jsonschema_serialize_fork = "^2.1.1" keepalive = "0.5" loremipsum = "1.0.5" netaddr = ">=0.7.18,<1" -passlib = "1.6.5" +passlib = "^1.7.4" PasteDeploy = "1.5.2" pbkdf2 = "1.3" Pillow = "^6.2.2" # 6.x.x should work for CGAP -Will 11/18/2020 plaster = "1.0" plaster-pastedeploy = "0.6" -psutil = "^5.6.6" -psycopg2-binary = "2.7.7" -py = "1.4.31" +psutil = "^5.8.0" +psycopg2-binary = "^2.8.6" +py = ">=1.8.1" # was "1.4.31" (used by pytest, not sure if elsewhere) pyasn1 = "0.1.9" PyBrowserID = "^0.10.0" pycparser = "2.14" PyJWT = "1.5.3" -pyparsing = "2.1.1" +pyparsing = "^2.4.7" pyramid = "1.10.4" -pyramid-localroles = ">=0.1,<1" -pyramid-multiauth = "0.8.0" -pyramid-retry = "1.0" -pyramid-tm = "2.2.1" -pyramid-translogger = "^0.1" -python-dateutil = "2.7.3" +pyramid_localroles = ">=0.1,<1" +pyramid_multiauth = ">=0.9.0,<1" +pyramid-retry = "^1.0" +pyramid-tm = "^2.4" +pyramid_translogger = "^0.1" +python-dateutil = "^2.8.1" # python-magic is presently pinned to 0.4.15 in lockstep with dcicsnovault's requirements. See explanation there. python-magic = "0.4.15" pytz = ">=2020.4" rdflib = "^4.2.2" -rdflib-jsonld = "0.3" +rdflib-jsonld = ">=0.5.0,<1.0.0" requests = "^2.23.0" -rfc3987 = "^1.3.6" +rfc3987 = "^1.3.8" rsa = "3.3" -rutter = ">=0.2,<1" -s3transfer = "^0.2.0" +rutter = ">=0.3,<1" +s3transfer = ">=0.3.0,<0.4.0" simplejson = "^3.17.0" -SPARQLWrapper = "1.7.6" +SPARQLWrapper = "^1.8.5" SQLAlchemy = "1.3.16" # Pinned because >=1.3.17 is broken for us (circular constraints prevent deletes) -structlog = ">=18.1.0,<20" +structlog = ">=19.2.0,<20" submit4dn = "0.9.7" -subprocess-middleware = ">=0.3,<1" +subprocess_middleware = ">=0.3,<1" # Useful for picking apart pyproject.toml toml = ">=0.10.1,<1" -transaction = "2.4.0" +transaction = "^2.4.0" translationstring = "1.3" uptime = ">=3.0.1,<4" urllib3 = "^1.24.3" venusian = "^1.2.0" waitress = "1.2.0" # 1.4.3 had lots of problems, so pin this -kmp 18-May-2020 -WebOb = "1.8.5" -WebTest = "^2.0.21" +WebOb = "^1.8.6" +WebTest = "^2.0.35" wheel = "0.29.0" WSGIProxy2 = "0.4.2" -xlrd = "^1.0.0" +xlrd = "^1.2.0" xlwt = "1.2.0" -"zope.deprecation" = "4.4.0" -"zope.interface" = "4.6.0" +"zope.deprecation" = "^4.4.0" +"zope.interface" = "^4.7.2" "zope.sqlalchemy" = "1.3" sentry-sdk = "^0.16.5" [tool.poetry.dev-dependencies] # PyCharm says boto3-stubs contains useful type hints -boto3-stubs = ">=1.16.15.0" -coverage = ">=5.2" +boto3-stubs = ">=1.16.59.0" +coverage = ">=5.3.1" codacy-coverage = ">=1.3.11" -coveralls = ">=2.1.1" -flake8 = "^3.7.8" -flaky = "3.6.1" +coveralls = ">=3.0.0" +flake8 = ">=3.8.4" +flaky = ">=3.7.0" # flask only for moto[server] flask = ">=1.1.1" # Here AND ELSEWHERE (related scripts), we pin use of moto 1.3.7. @@ -140,15 +136,22 @@ flask = ">=1.1.1" # If not, get a reference to an open bug report here so we can check back periodically. moto = "1.3.7" # TODO: Investigate whether a major version upgrade is allowable for 'pytest', which is several versions behind. -pytest = "2.9.2" -pytest-cov = "2.2.1" -pytest-exact-fixtures = "0.1" -pytest-instafail = "0.3.0" -pytest-mock = "0.11.0" -pytest-timeout = "1.0.0" -pytest-xdist = "1.14" -# responses = "^0" -"repoze.debug" = "1.0.2" +pytest = ">=3.10,<4" +pytest-cov = ">=2.2.1" +pytest-exact-fixtures = ">=0.1" +pytest-instafail = ">=0.3.0" +pytest-mock = ">=0.11.0" +pytest-timeout = ">=1.0.0" +pytest-xdist = ">=1.14" +"repoze.debug" = ">=1.0.2" + +# In pytest 6.0, we'll be able to use this instead of a separate pytest.ini configuration. +# -kmp 18-Jan-2021 +# +# [tool.pytest.ini_options] +# minversion = "6.0" +# ...etc. +# See details at https://pytest.org/en/stable/customize.html [tool.poetry.scripts] # snovault commands From 53ea8b81964e605a76c4e47aee1a96ac6e944a72 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 00:01:28 -0500 Subject: [PATCH 02/35] Add a few other files that don't need to go into git. --- .gitignore | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index a2316fae74..10d02188d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .coverage +*.srctr* coverage.xml beanstalk.cfg /coverage @@ -16,6 +17,7 @@ beanstalk.cfg /develop-eggs/ /downloads/ /eggs/ +/ped_files_data/ /.eggs/ /extends/ /jsconfig.json @@ -66,8 +68,17 @@ elasticsearch-*.deb # Emacs backup files *~ +# PyCharm metadata +.idea/ + # Virtual environments +# Conventions vary, including env, venv, or longer names like cgap_env, +# but typically they end in "env". *env/ -# PyCharm -.idea/ +# Saved configurations from Elastic beanstalk that have been downloaded. +.elasticbeanstalk/saved_configs/ +.elasticbeanstalk/app_versions/ + +# Used for some kinds of debugging in dcicutils, snovault, cgap & ff. +DEBUGLOG-* From 2ffb342f2d6f60211c042e20816f7dae81890ac8 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 00:02:25 -0500 Subject: [PATCH 03/35] Updates to psql-start and kibana-start migrated from cgap. --- scripts/kibana-start | 80 ++++++++++++++++++++++++++++++++++++++++---- scripts/psql-start | 70 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 6 deletions(-) create mode 100755 scripts/psql-start diff --git a/scripts/kibana-start b/scripts/kibana-start index 7f08948d19..3b311bf451 100755 --- a/scripts/kibana-start +++ b/scripts/kibana-start @@ -1,5 +1,60 @@ #!/bin/bash +docker_kibana_image=docker.elastic.co/kibana/kibana-oss:6.8.9 +docker_kibana_port=5601 +local_kibana_port=${docker_kibana_port} +default_es_port=9200 +local_es_port=${default_es_port} + +if [ "$1" = "test" ]; then + + # This deletes all the output that doesn't match our pattern and includes only what does. + # Ref: https://stackoverflow.com/questions/6011661/regexp-sed-suppress-no-match-output + port=`ps aux | sed -E '/.*elasticsearch.*-Ehttp[.]port=([0-9]+)[^0-9].*/!d;s//\1/'` + + if [ -z "${port}" ]; then + echo "Cannot find test port." + exit 1 + elif [ `echo "${port}" | wc -l` -gt 1 ]; then + echo "Found multiple test ports:" + echo "${port}" + exit 1 + fi + + if [[ "${port}" =~ ^[0-9]+$ ]]; then + local_es_port="${port}" + echo "Using local_es_port=${local_es_port}." + else + echo "Port format is wrong: ${port}" + exit 1 + fi + +elif [[ "$1" =~ ^[0-9]+$ ]]; then + + local_es_port=$1 + echo "Using local_es_port=${local_es_port}." + +elif [ $# -gt 0 -a "$1" != "dev" ]; then + + echo "Syntax: $0 [ | test | dev ]" + echo " Starts kibana. By default, or if 'dev' is given, uses the standard port ${default_es_port}." + echo " If es-port is an integer, that port is used." + echo " If es-port is the word 'test', a test port is found using 'ps aux'." + echo " Note that this will choose its own http port, which will be 5601 for es-port=9200," + echo " or else a generated port number 10000+( % 55536) otherwise." + exit 1 + +fi + +if [ "${local_es_port}" != "${default_es_port}" ]; then + # 0-1023 are reserved ports + # 1024-65535 are available for custom use, but usualy 1024-9999 are assigned manually + # we'll generate a port in the range 10000-65535. that might sometimes collide, but probably VERY rarely. + local_kibana_port=$(( $local_es_port % 55536 + 10000 )) +fi + +echo "Using local_kibana_port=${local_kibana_port}" + docker --version if [ $? -ne 0 ]; then @@ -11,25 +66,38 @@ fi existing_network=`docker network ls | grep localnet` if [ -z "${existing_network}" ]; then + echo "creating localnet --driver=bridge" docker network create localnet --driver=bridge else echo "docker localnet is already set up. From 'docker network':" - echo " ${existing_network}" + # echo " ${existing_network}" fi -existing_kibana=`docker ps | egrep 'kibana:[0-9]*.[0-9]+.*[ ].*'` +# This pattern is structured so that if we need to extract the container id (e.g., to kill it), it will be in \1. +# But I figured out a way not to have to kill the old one, so that part of the pattern isn't used any more. +# I retained the first group just for possible future use. At this point, this just detects whether we have a +# handler for $local_kibana_port at all. This pattern also anticipates kibana images named 'kibana' or 'kibana-oss'. +# I other image names come up, for example if aws creates its own naming convention, it will need adjusting. +# -kmp 31-Jan-2021 +kibana_docker_pattern="([0-9a-f]+) .*kibana(-oss)?:[0-9]+[.][0-9]+[.].*0[.]0[.]0[.]0[:]${local_kibana_port}-[>]" + +existing_kibana=`docker ps | egrep "${kibana_docker_pattern}"` if [ -z "${existing_kibana}" ]; then - docker run -d --network localnet -p 5601:5601 -e ELASTICSEARCH_URL=http://host.docker.internal:9200 kibana:5.6.16 + echo "Kibana is not already running for ES port ${local_es_port}" + docker_es_url="http://host.docker.internal:${local_es_port}" + docker run -d --network localnet -p ${local_kibana_port}:${docker_kibana_port} -e ELASTICSEARCH_URL=${docker_es_url} ${docker_kibana_image} + + echo "Waiting for kibana to start..." + sleep 5 else - echo "Kibana is already running. From 'docker ps':" + echo "Kibana is already listening on port ${local_kibana_port} for elasticsearch on port ${local_es_port}:" echo " ${existing_kibana}" fi -local_kibana_url="http://localhost:5601/app/kibana#/dev_tools/console?_g=()" +local_kibana_url="http://localhost:${local_kibana_port}/app/kibana#/dev_tools/console?_g=()" echo "Opening kibana in browser at '${local_kibana_url}'..." open "${local_kibana_url}" & - diff --git a/scripts/psql-start b/scripts/psql-start new file mode 100755 index 0000000000..8957093bf8 --- /dev/null +++ b/scripts/psql-start @@ -0,0 +1,70 @@ +#!/bin/bash + +port=$1 + +dev_url_line=`grep 'sqlalchemy[.]url =' development.ini` + +dev_url=`echo "${dev_url_line}" | sed -E 's/^.* = (.*)$/\1/'` +dev_port=`echo "${dev_url_line}" | sed -E 's|^.* = .*:([0-9]+)/postgres[?].*$|\1|'` + + +# echo "dev_url=${dev_url}" +# echo "dev_port=${dev_port}" + + +# There seem be two processes, one for postgres and one for postgres-engine. +# The relevant data can be obtained from either, but matching both +# the match for postgres[^-] excludes the matches on postgres-engine so we +# can assume the match is unique. + +if [ "$port" = 'test' ]; then + + test_process=`ps aux | grep '.*[p]ostgres -D.*/private[a-zA-Z0-9_/-]*/postgresql[^-]'` + + if [ -z "${test_process}" ]; then + + echo "No test process found." + exit 1 + + else + + test_url=`echo "$test_process" | sed -E 's|^.*postgres[ ]+-D[ ]+([/a-zA-Z0-9_-]+)[ ]+.*-p[ ]+([0-9]+)([^0-9].*)?$|postgresql://postgres@localhost:\2/postgres?host=\1|'` + psql "${test_url}" + + # psql `ps aux | grep '.*[p]ostgres -D.*/private[a-zA-Z0-9_/-]*/postgresql[^-]' | sed -E 's|^.*postgres[ ]+-D[ ]+([/a-zA-Z0-9_-]+)[ ]+.*-p[ ]+([0-9]+)([^0-9].*)?$|postgresql://postgres@localhost:\2/postgres?host=\1|'` + + fi + +elif [ "$port" = 'dev' -o "$port" = "$dev_port" ]; then + + dev_url=`grep 'sqlalchemy[.]url =' development.ini | sed -E 's/^.* = (.*)/\1/'` + psql "${dev_url}" + +elif [[ "${port}" =~ ^[0-9]+$ ]]; then + + port_process=`ps aux | grep ".*[p]ostgres -D.*/private[a-zA-Z0-9_/-]*/postgresql[^-].*-p[ ]+${port}.*"` + + if [ -z "${port_process}" ]; then + + echo "No postgres process found on port ${port}." + exit 1 + + else + + port_url=`echo "$test_process" | sed -E 's|^.*postgres[ ]+-D[ ]+([/a-zA-Z0-9_-]+)[ ]+.*-p[ ]+([0-9]+)([^0-9].*)?$|postgresql://postgres@localhost:\2/postgres?host=\1|'` + psql "${port_url}" + + # psql `ps aux | grep '.*[p]ostgres -D.*/private[a-zA-Z0-9_/-]*/postgresql[^-]' | sed -E 's|^.*postgres[ ]+-D[ ]+([/a-zA-Z0-9_-]+)[ ]+.*-p[ ]+([0-9]+)([^0-9].*)?$|postgresql://postgres@localhost:\2/postgres?host=\1|'` + + fi + +else + + echo "Syntax: $0 [ | test | dev ]" + echo "" + echo "Starts psql for debugging in a way that corresponds to the given port." + echo "The port can be an integer or one of the special tokens 'dev' or 'test'." + echo "If 'dev' is given, the port from development.ini (currently '${dev_port}') is used." + echo "If 'test' is given, the port will be found from data in 'ps aux'." + +fi From 70375ffe6b59a5f3a37fdf29ee45476380dbd909 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:07:12 -0500 Subject: [PATCH 04/35] Port various utilities from cgap's src/encoded/util.py just to have utilities level. (Many are unused but may back other code we want to port.) Rename src/encoded/utils.py to src/encoded/util.py so these filenames will align again. Adjust files that import the renamed file. Also adjust test_indexing.py to use meta = MetaData(...); meta.reflect() instead of meta = MetaData(..., reflect=True). --- src/encoded/__init__.py | 2 +- src/encoded/tests/test_aggregation.py | 2 +- src/encoded/tests/test_batch_download.py | 2 +- src/encoded/tests/test_indexing.py | 5 +- src/encoded/tests/test_search.py | 2 +- .../tests/test_types_init_collections.py | 2 +- src/encoded/tests/test_types_protocol.py | 2 +- src/encoded/tests/test_utils.py | 4 +- src/encoded/tests/test_validation_errors.py | 2 +- src/encoded/types/file.py | 2 +- src/encoded/util.py | 401 ++++++++++++++++++ 11 files changed, 414 insertions(+), 12 deletions(-) create mode 100644 src/encoded/util.py diff --git a/src/encoded/__init__.py b/src/encoded/__init__.py index 4bc4be72b4..ec425ca29a 100644 --- a/src/encoded/__init__.py +++ b/src/encoded/__init__.py @@ -34,7 +34,7 @@ # from webob.cookies import JSONSerializer from .loadxl import load_all -from .utils import find_other_in_pair +from .util import find_other_in_pair if sys.version_info.major < 3: diff --git a/src/encoded/tests/test_aggregation.py b/src/encoded/tests/test_aggregation.py index e35dce8240..9700b7b6a9 100644 --- a/src/encoded/tests/test_aggregation.py +++ b/src/encoded/tests/test_aggregation.py @@ -1,7 +1,7 @@ import pytest from dcicutils.qa_utils import notice_pytest_fixtures -from ..utils import delay_rerun +from ..util import delay_rerun from .workbook_fixtures import app_settings, app, workbook diff --git a/src/encoded/tests/test_batch_download.py b/src/encoded/tests/test_batch_download.py index cafd00a750..e26bac7ca1 100644 --- a/src/encoded/tests/test_batch_download.py +++ b/src/encoded/tests/test_batch_download.py @@ -1,7 +1,7 @@ import pytest from dcicutils.qa_utils import notice_pytest_fixtures -from ..utils import delay_rerun +from ..util import delay_rerun # Use workbook fixture from BDD tests (including elasticsearch) from .workbook_fixtures import app_settings, app, workbook diff --git a/src/encoded/tests/test_indexing.py b/src/encoded/tests/test_indexing.py index 50273e542c..c9cd50a5de 100644 --- a/src/encoded/tests/test_indexing.py +++ b/src/encoded/tests/test_indexing.py @@ -31,7 +31,7 @@ from unittest import mock from zope.sqlalchemy import mark_changed from .. import main -from ..utils import delay_rerun +from ..util import delay_rerun from ..verifier import verify_item from .workbook_fixtures import app_settings from .test_permissions import wrangler, wrangler_testapp @@ -88,7 +88,8 @@ def setup_and_teardown(app): # AFTER THE TEST session = app.registry[DBSESSION] connection = session.connection().connect() - meta = MetaData(bind=session.connection(), reflect=True) + meta = MetaData(bind=session.connection()) + meta.reflect() for table in meta.sorted_tables: print('Clear table %s' % table) print('Count before -->', str(connection.scalar("SELECT COUNT(*) FROM %s" % table))) diff --git a/src/encoded/tests/test_search.py b/src/encoded/tests/test_search.py index d3c6198deb..2b0a077b39 100644 --- a/src/encoded/tests/test_search.py +++ b/src/encoded/tests/test_search.py @@ -11,7 +11,7 @@ from ..commands.run_upgrader_on_inserts import get_inserts # Use workbook fixture from BDD tests (including elasticsearch) from .workbook_fixtures import app_settings, app, workbook -# from ..utils import customized_delay_rerun +# from ..util import customized_delay_rerun pytestmark = [ diff --git a/src/encoded/tests/test_types_init_collections.py b/src/encoded/tests/test_types_init_collections.py index 18e460973f..afd99d9d20 100644 --- a/src/encoded/tests/test_types_init_collections.py +++ b/src/encoded/tests/test_types_init_collections.py @@ -1,7 +1,7 @@ import pytest from ..types.image import Image -from ..utils import utc_today_str +from ..util import utc_today_str pytestmark = [pytest.mark.setone, pytest.mark.working, pytest.mark.schema] diff --git a/src/encoded/tests/test_types_protocol.py b/src/encoded/tests/test_types_protocol.py index 92569e1bfa..8a2febd9cc 100644 --- a/src/encoded/tests/test_types_protocol.py +++ b/src/encoded/tests/test_types_protocol.py @@ -1,7 +1,7 @@ import datetime import pytest -from ..utils import utc_today_str +from ..util import utc_today_str pytestmark = [pytest.mark.setone, pytest.mark.working, pytest.mark.schema] diff --git a/src/encoded/tests/test_utils.py b/src/encoded/tests/test_utils.py index cbd95cef3d..4c7fbca5da 100644 --- a/src/encoded/tests/test_utils.py +++ b/src/encoded/tests/test_utils.py @@ -3,8 +3,8 @@ import re from pyramid.httpexceptions import HTTPForbidden -from ..utils import (compute_set_difference_one, find_other_in_pair, delay_rerun, utc_today_str, - customized_delay_rerun, check_user_is_logged_in) +from ..util import (compute_set_difference_one, find_other_in_pair, delay_rerun, utc_today_str, + customized_delay_rerun, check_user_is_logged_in) pytestmark = pytest.mark.working diff --git a/src/encoded/tests/test_validation_errors.py b/src/encoded/tests/test_validation_errors.py index b48c4c4bc2..08280bf485 100644 --- a/src/encoded/tests/test_validation_errors.py +++ b/src/encoded/tests/test_validation_errors.py @@ -2,7 +2,7 @@ from dcicutils.qa_utils import notice_pytest_fixtures from .workbook_fixtures import app_settings, workbook -# from ..utils import delay_rerun +# from ..util import delay_rerun notice_pytest_fixtures(app_settings, workbook) diff --git a/src/encoded/types/file.py b/src/encoded/types/file.py index 603fd9e252..ed65705908 100644 --- a/src/encoded/types/file.py +++ b/src/encoded/types/file.py @@ -63,7 +63,7 @@ get_item_or_none, lab_award_attribution_embed_list ) -from ..utils import check_user_is_logged_in +from ..util import check_user_is_logged_in logging.getLogger('boto3').setLevel(logging.CRITICAL) diff --git a/src/encoded/util.py b/src/encoded/util.py new file mode 100644 index 0000000000..03fdf5d2f9 --- /dev/null +++ b/src/encoded/util.py @@ -0,0 +1,401 @@ +# utility functions + +import contextlib +import datetime +import gzip +import io +import os +import pyramid.request +import tempfile +import time + +from dcicutils.misc_utils import check_true +from io import BytesIO +from pyramid.httpexceptions import HTTPUnprocessableEntity, HTTPForbidden, HTTPServerError +from snovault import COLLECTIONS, Collection +from snovault.crud_views import collection_add as sno_collection_add +from snovault.embed import make_subrequest +from snovault.schema_utils import validate_request +from .types.base import get_item_or_none + + +ENCODED_ROOT_DIR = os.path.dirname(__file__) + + +def resolve_file_path(path, file_loc=None): + """ Takes a relative path from this file location and returns an absolute path to + the desired file, needed for WSGI to resolve embed files. + + :param path: relative path to be converted + :param file_loc: absolute path to location path is relative to, by default path/to/encoded/src/ + :return: absolute path to location specified by path + """ + if path.startswith("~"): + # Really this shouldn't happen, so we could instead raise an error, but at least this is semantically correct. + path = os.path.expanduser(path) + if file_loc: + if file_loc.startswith("~"): + file_loc = os.path.expanduser(file_loc) + path_to_this_file = os.path.abspath(os.path.dirname(file_loc)) + else: + path_to_this_file = os.path.abspath(ENCODED_ROOT_DIR) + return os.path.join(path_to_this_file, path) + + +def deduplicate_list(lst): + """ De-duplicates the given list by converting it to a set then back to a list. + + NOTES: + * The list must contain 'hashable' type elements that can be used in sets. + * The result list might not be ordered the same as the input list. + * This will also take tuples as input, though the result will be a list. + + :param lst: list to de-duplicate + :return: de-duplicated list + """ + return list(set(lst)) + + +def gunzip_content(content): + """ Helper that will gunzip content """ + f_in = BytesIO() + f_in.write(content) + f_in.seek(0) + with gzip.GzipFile(fileobj=f_in, mode='rb') as f: + gunzipped_content = f.read() + return gunzipped_content.decode('utf-8') + + +DEBUGLOG = os.environ.get('DEBUGLOG', "") + + +def debuglog(*args): + """ + As the name implies, this is a low-tech logging facility for temporary debugging info. + Prints info to a file in user's home directory. + + The debuglog facility allows simple debugging for temporary debugging of disparate parts of the system. + It takes arguments like print or one of the logging operations and outputs to ~/DEBUGLOG-yyyymmdd.txt. + Each line in the log is timestamped. + """ + if DEBUGLOG: + try: + nowstr = str(datetime.datetime.now()) + dateid = nowstr[:10].replace('-', '') + with io.open(os.path.expanduser(os.path.join(DEBUGLOG, "DEBUGLOG-%s.txt" % dateid)), "a+") as fp: + print(nowstr, *args, file=fp) + except Exception: + # There are many things that could go wrong, but none of them are important enough to fuss over. + # Maybe it was a bad pathname? Out of disk space? Network error? + # It doesn't really matter. Just continue... + pass + + +def subrequest_object(request, object_id): + subreq = make_subrequest(request, "/" + object_id) + subreq.headers['Accept'] = 'application/json' + # Tweens are suppressed here because this is an internal call and doesn't need things like HTML processing. + # -kmp 2-Feb-2021 + response = request.invoke_subrequest(subreq, use_tweens=False) + if response.status_code >= 300: # alas, the response from a pyramid subrequest has no .raise_for_status() + raise HTTPServerError("Error obtaining object: %s" % object_id) + object_json = response.json + return object_json + + +def subrequest_item_creation(request: pyramid.request.Request, item_type: str, json_body: dict = None) -> dict: + """ + Acting as proxy on behalf of request, this creates a new item of the given item_type with attributes per json_body. + + For example, + + subrequest_item_creation(request=request, item_type='NobelPrize', + json_body={'category': 'peace', 'year': 2016)) + + Args: + request: the request on behalf of which this subrequest is done + item_type: the name of the item item type to be created + json_body: a python dictionary representing JSON containing data to use in initializing the newly created item + + Returns: + a python dictionary (JSON description) of the item created + + """ + + if json_body is None: + json_body = {} + collection_path = '/' + item_type + method = 'POST' + # json_utf8 = json.dumps(json_body).encode('utf-8') # Unused, but here just in case + check_true(not request.remote_user, "request.remote_user has %s before we set it." % request.remote_user) + request.remote_user = 'EMBED' + subrequest = make_subrequest(request=request, path=collection_path, method=method, json_body=json_body) + subrequest.remote_user = 'EMBED' + subrequest.registry = request.registry + # Maybe... + # validated = json_body.copy() + # subrequest.validated = validated + collection: Collection = subrequest.registry[COLLECTIONS][item_type] + check_true(subrequest.json_body, "subrequest.json_body is not properly initialized.") + check_true(not subrequest.validated, "subrequest was unexpectedly validated already.") + check_true(not subrequest.errors, "subrequest.errors already has errors before trying to validate.") + check_true(subrequest.remote_user == request.remote_user, + "Mismatch: subrequest.remote_user=%r request.remote_user=%r" + % (subrequest.remote_user, request.remote_user)) + validate_request(schema=collection.type_info.schema, request=subrequest, data=json_body) + if not subrequest.validated: + return { + "@type": ["Exception"], + "errors": subrequest.errors + } + else: + json_result: dict = sno_collection_add(context=collection, request=subrequest, render=False) + return json_result + + +# These next few could be in dcicutils.s3_utils as part of s3Utils, but details of interfaces would have to change. +# For now, for expedience, they can live here and we can refactor later. -kmp 25-Jul-2020 + +@contextlib.contextmanager +def s3_output_stream(s3_client, bucket: str, key: str): + """ + This context manager allows one to write: + + with s3_output_stream(s3_client, bucket, key) as fp: + print("foo", file=fp) + + to do output to an s3 bucket. + + In fact, an intermediate local file is involved, so this function yields a file pointer (fp) to a + temporary local file that is open for write. That fp should be used to supply content to the file + during the dynamic scope of the context manager. Once the context manager's body executes, the + file will be closed, its contents will be copied to s3, and finally the temporary local file will + be deleted. + + Args: + s3_client: a client object that results from a boto3.client('s3', ...) call. + bucket: an S3 bucket name + key: the name of a key within the given S3 bucket + """ + + tempfile_name = tempfile.mktemp() + try: + with io.open(tempfile_name, 'w') as fp: + yield fp + s3_client.upload_file(Filename=tempfile_name, Bucket=bucket, Key=key) + finally: + try: + os.remove(tempfile_name) + except Exception: + pass + + +@contextlib.contextmanager +def s3_local_file(s3_client, bucket: str, key: str): + """ + This context manager allows one to write: + + with s3_local_file(s3_client, bucket, key) as file: + with io.open(local_file, 'r') as fp: + dictionary = json.load(fp) + + to do input from an s3 bucket. + + Args: + s3_client: a client object that results from a boto3.client('s3', ...) call. + bucket: an S3 bucket name + key: the name of a key within the given S3 bucket + """ + ext = os.path.splitext(key)[-1] + tempfile_name = tempfile.mktemp() + ext + try: + s3_client.download_file(Bucket=bucket, Key=key, Filename=tempfile_name) + yield tempfile_name + finally: + try: + os.remove(tempfile_name) + except Exception: + pass + + +@contextlib.contextmanager +def s3_input_stream(s3_client, bucket: str, key: str, mode: str = 'r'): + """ + This context manager allows one to write: + + with s3_input_stream(s3_client, bucket, key) as fp: + dictionary = json.load(fp) + + to do input from an s3 bucket. + + In fact, an intermediate local file is created, copied, and deleted. + + Args: + s3_client: a client object that results from a boto3.client('s3', ...) call. + bucket: an S3 bucket name + key: the name of a key within the given S3 bucket + mode: an input mode acceptable to io.open + """ + + with s3_local_file(s3_client, bucket, key) as file: + with io.open(file, mode=mode) as fp: + yield fp + + +def create_empty_s3_file(s3_client, bucket: str, key: str): + """ + Args: + s3_client: a client object that results from a boto3.client('s3', ...) call. + bucket: an S3 bucket name + key: the name of a key within the given S3 bucket + """ + empty_file = "/dev/null" + s3_client.upload_file(empty_file, Bucket=bucket, Key=key) + + +def get_trusted_email(request, context=None, raise_errors=True): + """ + Get an email address on behalf of which we can issue other requests. + + If auth0 has authenticated user info to offer, return that. + Otherwise, look for a userid.xxx among request.effective_principals and get the email from that. + + This will raise HTTPUnprocessableEntity if there's a problem obtaining the mail. + """ + try: + context = context or "Requirement" + email = getattr(request, '_auth0_authenticated', None) + if not email: + user_uuid = None + for principal in request.effective_principals: + if principal.startswith('userid.'): + user_uuid = principal[7:] + break + if not user_uuid: + raise HTTPUnprocessableEntity('%s: Must provide authentication' % context) + user_props = get_item_or_none(request, user_uuid) + if not user_props: + raise HTTPUnprocessableEntity('%s: User profile missing' % context) + if 'email' not in user_props: + raise HTTPUnprocessableEntity('%s: Entry for "email" missing in user profile.' % context) + email = user_props['email'] + return email + except Exception: + if raise_errors: + raise + return None + + +def beanstalk_env_from_request(request): + return beanstalk_env_from_registry(request.registry) + + +def beanstalk_env_from_registry(registry): + return registry.settings.get('env.name') + + +def compute_set_difference_one(s1, s2): + """ Computes the set difference between s1 and s2 (ie: in s1 but not in s2) + PRE: s1 and s2 differ by one element and thus their set + difference is a single element + + :arg s1 (set(T)): super set + :arg s2 (set(T)): subset + :returns (T): the single differing element between s1 and s2. + :raises: exception if more than on element is found + """ + res = s1 - s2 + if len(res) > 1: + raise RuntimeError('Got more than one result for set difference') + return next(iter(res)) + + +def find_other_in_pair(element, pair): + """ Wrapper for compute_set_difference_one + + :arg element (T): item to look for in pair + :arg pair (2-tuple of T): pair of things 'element' is in + :returns (T): item in pair that is not element + :raises: exception if types do not match or in compute_set_diferrence_one + """ + return compute_set_difference_one(set(pair), {element}) + + +def customized_delay_rerun(sleep_seconds=1): + def parameterized_delay_rerun(*args): + """ Rerun function for flaky """ + time.sleep(sleep_seconds) + return True + return parameterized_delay_rerun + + +delay_rerun = customized_delay_rerun(sleep_seconds=1) + + +def utc_today_str(): + return datetime.datetime.strftime(datetime.datetime.utcnow(), "%Y-%m-%d") + + +def check_user_is_logged_in(request): + """ Raises HTTPForbidden if the request did not come from a logged in user. """ + for principal in request.effective_principals: + if principal.startswith('userid.') or principal == 'group.admin': # allow if logged in OR has admin + break + else: + raise HTTPForbidden(title="Not logged in.") + + +# IMPLEMENTATION NOTE: +# +# We have middleware that overrides various details about content type that are declared in the view_config. +# It used to work by having a wired set of exceptions, but this facility allows us to do it in a more data-driven +# way. Really I think we should just rely on the information in the view_config, but I didn't have time to explore +# why we are not using that. +# +# See validate_request_tween_factory in renderers.py for where this is used. This declaration info is here +# rather than there to simplify the load order dependencies. +# +# -kmp 1-Sep-2020 + +CONTENT_TYPE_SPECIAL_CASES = { + 'application/x-www-form-urlencoded': [ + # Single legacy special case to allow us to POST to metadata TSV requests via form submission. + # All other special case values should be added using register_path_content_type. + '/metadata/' + ] +} + + +def register_path_content_type(*, path, content_type): + """ + Registers that endpoints that begin with the specified path use the indicated content_type. + + This is part of an inelegant workaround for an issue in renderers.py that maybe we can make go away in the future. + See the 'implementation note' in ingestion/common.py for more details. + """ + exceptions = CONTENT_TYPE_SPECIAL_CASES.get(content_type, None) + if exceptions is None: + CONTENT_TYPE_SPECIAL_CASES[content_type] = exceptions = [] + if path not in exceptions: + exceptions.append(path) + + +def content_type_allowed(request): + """ + Returns True if the current request allows the requested content type. + + This is part of an inelegant workaround for an issue in renderers.py that maybe we can make go away in the future. + See the 'implementation note' in ingestion/common.py for more details. + """ + if request.content_type == "application/json": + # For better or worse, we always allow this. + return True + + exceptions = CONTENT_TYPE_SPECIAL_CASES.get(request.content_type) + + if exceptions: + for text in exceptions: + if text in request.path: + return True + + return False From 340750788671e123379c87ebe07299f860c31d6d Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:10:43 -0500 Subject: [PATCH 05/35] Use new kibana-start and psql-start scripts to support psql-test and kibana-start-test and use poetry 1.1.4 in Makefile. --- Makefile | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index dc00733ead..05c1755b13 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +SHELL=/bin/bash + clean: # clear node modules, eggs, npm build stuff make clean-python-caches make clean-npm-caches @@ -38,7 +40,7 @@ macpoetry-install: # Same as 'poetry install' except that on OSX Catalina, an e configure: # does any pre-requisite installs pip install --upgrade pip - pip install poetry==1.0.10 # pinned to avoid build problems we cannot fix in pyproject.toml + pip install poetry==1.1.4 # poetry latest as of 1/25/2021 seemed to work but apparantly does not build: # builds make configure @@ -93,11 +95,17 @@ deploy2: # spins up waittress to serve the application pserve development.ini psql-dev: # starts psql with the url after 'sqlalchemy.url =' in development.ini - @psql `grep 'sqlalchemy[.]url =' development.ini | sed -E 's/^.* = (.*)/\1/'` + @scripts/psql-start dev + +psql-test: # starts psql with a url constructed from data in 'ps aux'. + @scripts/psql-start test -kibana-start: +kibana-start: # starts a dev version of kibana (default port) scripts/kibana-start +kibana-start-test: # starts a test version of kibana (port chosen for active tests) + scripts/kibana-start test + kibana-stop: scripts/kibana-stop @@ -140,11 +148,14 @@ info: $(info - Use 'make configure' to install poetry. You should not have to do this directly.) $(info - Use 'make deploy1' to spin up postgres/elasticsearch and load inserts.) $(info - Use 'make deploy2' to spin up the application server.) - $(info - Use 'make psql-dev' to start psql on data associated with an active 'make deploy1'.) - $(info - Use 'make kibana-start' to start kibana, and 'make kibana-stop' to stop it.) + $(info - Use 'make kibana-start' to start kibana on the default local ES port, and 'make kibana-stop' to stop it.) + $(info - Use 'make kibana-start-test' to start kibana on the port being used for active testing, and 'make kibana-stop' to stop it.) $(info - Use 'make kill' to kill postgres and elasticsearch proccesses. Please use with care.) $(info - Use 'make moto-setup' to install moto, for less flaky tests. Implied by 'make build'.) $(info - Use 'make npm-setup' to build the front-end. Implied by 'make build'.) + $(info - Use 'make psql-dev' to start psql on data associated with an active 'make deploy1'.) + $(info - Use 'make psql-test' to start psql on data associated with an active test.) + $(info - Use 'make retest' to run failing tests from the previous test run.) $(info - Use 'make test' to run tests with normal options we use on travis ('-m "working and not performance"').) $(info - Use 'make test-any' to run tests without marker constraints (i.e., with no '-m' option).) $(info - Use 'make update' to update dependencies (and the lock file).) From 39393e5eea32ccffcc819e9d58b507d00459f1e0 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:28:48 -0500 Subject: [PATCH 06/35] Add extra newline to 13_run_npm.config for parity with cgap-portal diff. --- .ebextensions/13_run_npm.config | 1 + 1 file changed, 1 insertion(+) diff --git a/.ebextensions/13_run_npm.config b/.ebextensions/13_run_npm.config index ac212b476b..041c390660 100644 --- a/.ebextensions/13_run_npm.config +++ b/.ebextensions/13_run_npm.config @@ -31,6 +31,7 @@ files: echo "Finished NPM build in 99_run_npm." >> /var/log/deploy.log echo "Finished NPM build in 99_run_npm." + echo "Restarting Apache" sudo service httpd restart From 56e25b4e73db53ad62c10866ec59b9344e2383a6 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:29:27 -0500 Subject: [PATCH 07/35] Confirm rename. --- src/encoded/utils.py | 56 -------------------------------------------- 1 file changed, 56 deletions(-) delete mode 100644 src/encoded/utils.py diff --git a/src/encoded/utils.py b/src/encoded/utils.py deleted file mode 100644 index 882b81c2e3..0000000000 --- a/src/encoded/utils.py +++ /dev/null @@ -1,56 +0,0 @@ -# utility functions - -import datetime -import time -from pyramid.httpexceptions import HTTPForbidden - - -def compute_set_difference_one(s1, s2): - """ Computes the set difference between s1 and s2 (ie: in s1 but not in s2) - PRE: s1 and s2 differ by one element and thus their set - difference is a single element - - :arg s1 (set(T)): super set - :arg s2 (set(T)): subset - :returns (T): the single differing element between s1 and s2. - :raises: exception if more than on element is found - """ - res = s1 - s2 - if len(res) > 1: - raise RuntimeError('Got more than one result for set difference') - return next(iter(res)) - - -def find_other_in_pair(element, pair): - """ Wrapper for compute_set_difference_one - - :arg element (T): item to look for in pair - :arg pair (2-tuple of T): pair of things 'element' is in - :returns (T): item in pair that is not element - :raises: exception if types do not match or in compute_set_diferrence_one - """ - return compute_set_difference_one(set(pair), {element}) - - -def customized_delay_rerun(sleep_seconds=1): - def parameterized_delay_rerun(*args): - """ Rerun function for flaky """ - time.sleep(sleep_seconds) - return True - return parameterized_delay_rerun - - -delay_rerun = customized_delay_rerun(sleep_seconds=1) - - -def utc_today_str(): - return datetime.datetime.strftime(datetime.datetime.utcnow(), "%Y-%m-%d") - - -def check_user_is_logged_in(request): - """ Raises HTTPForbidden if the request did not come from a logged in user. """ - for principal in request.effective_principals: - if principal.startswith('userid.') or principal == 'group.admin': # allow if logged in OR has admin - break - else: - raise HTTPForbidden(title="Not logged in.") From ec3c2cca8188a24e0868fe638296af14f94ccdc9 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:30:25 -0500 Subject: [PATCH 08/35] Port cgap handling of tilde in setup_eb.py into fourfront. --- setup_eb.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/setup_eb.py b/setup_eb.py index b1fb0fc58e..86cdfa45c5 100644 --- a/setup_eb.py +++ b/setup_eb.py @@ -10,14 +10,18 @@ PYPROJECT_TOML = toml.decoder.load(os.path.join(ROOT_DIR, 'pyproject.toml')) POETRY_DATA = PYPROJECT_TOML['tool']['poetry'] -_CARET_MATCH = re.compile(r"[\^]([0-9]+)([.].*)$") +_CARET_MATCH = re.compile(r"[\^]([0-9]+)([.].*)?$") +_TILDE_MATCH = re.compile(r"[~]([0-9]+[.])([0-9]+)([.].*)?$") def fix_requirement(requirement): m = _CARET_MATCH.match(requirement) if m: - return ">=%s%s,<%s" % (m.group(1), m.group(2), int(m.group(1))+1) - elif requirement[0].isdigit(): + return ">=%s%s,<%s" % (m.group(1), m.group(2), int(m.group(1)) + 1) + m = _TILDE_MATCH.match(requirement) + if m: + return ">=%s%s%s,<%s%s" % (m.group(1), m.group(2), m.group(3), m.group(1), int(m.group(2)) + 1) + if requirement[0].isdigit(): return "==" + requirement else: return requirement From 71870134321f9e7ac8eec61f459216cfbdb41543 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:32:27 -0500 Subject: [PATCH 09/35] Port some light refactoring and a bug fix (missing module prefix zipfile.ZipFile) from cgap-portal version of scr/encoded/xlreader.py --- src/encoded/xlreader.py | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/encoded/xlreader.py b/src/encoded/xlreader.py index 0b8728d758..ad7f8faf60 100644 --- a/src/encoded/xlreader.py +++ b/src/encoded/xlreader.py @@ -36,7 +36,6 @@ def cell_value(cell, datemode): raise ValueError(repr(cell), 'unknown cell type') - def reader(stream, sheetname=None): """ Read named sheet or first and only sheet from xlsx file """ @@ -67,8 +66,7 @@ def __init__(self, stream, fieldnames=None, restkey=None, restval=None, def __iter__(self): return self - @property - def fieldnames(self): + def _assure_fieldnames_encached(self): if self._fieldnames is None: try: self._fieldnames = next(self.reader) @@ -76,24 +74,40 @@ def fieldnames(self): pass else: self.line_num += 1 - #self.line_num = self.reader.line_num + + # Yes, we definitely do not want to re-sync to the underlying .reader stream's line number, + # since our line number is not counting the lines in that file. See comment in __next__() below. + # -kmp 18-Jan-2021 + # self.line_num = self.reader.line_num + + @property + def fieldnames(self): + self._assure_fieldnames_encached() return self._fieldnames @fieldnames.setter def fieldnames(self, value): self._fieldnames = value + # If we ever wanted to know the line number of the underlying .csv file, this would be how to do it, + # since our .line_num is not counting the actual line numbers in the file. + # + # @property + # def csv_line_num(self): + # return self.reader.line_num + def __next__(self): - if self._fieldnames is None: - # Used only for its side effect. - self.fieldnames + self._assure_fieldnames_encached() row = next(self.reader) + # For reasons of history, we apparently only increment the line number only once per __next__ call, + # even though we will skip blank lines in the file, so this line number does NOT represent the CSV + # line number when debugging. Rather, it is some more abstract quantity. -kmp 18-Jan-2021 self.line_num += 1 # unlike the basic reader, we prefer not to return blanks, # because we will typically wind up with a dict full of None # values - while row == []: + while row == []: # noQA - PyCharm thinks 'while not row:' is simpler, but this seems clearer. -kmp 18-Jan-2021 row = next(self.reader) d = dict(zip(self.fieldnames, row)) lf = len(self.fieldnames) @@ -109,7 +123,11 @@ def __next__(self): def zipfile_to_csv(zipfilename, outpath, ext='.csv', dialect='excel', **fmtparams): """ For Google Drive download zips """ - zf = ZipFile(zipfilename) + # TODO: This function is presumably untested because this file had an unused 'import zipfile' and this + # reference to ZipFile did not have a module qualifier on it, so PyCharm was asserting this was + # going to get an undefined variable reference. I've added the qualifier, and PyCharm assures me + # there is a function zipfile.ZipFile, but I assume nothing uses this. -kmp 18-Jan-2021 + zf = zipfile.ZipFile(zipfilename) for name in zf.namelist(): subpath, entry_ext = os.path.splitext(name) if entry_ext.lower() != '.xlsx': @@ -120,4 +138,3 @@ def zipfile_to_csv(zipfilename, outpath, ext='.csv', dialect='excel', **fmtparam csvfile = open(os.path.join(outpath, subpath + ext), 'w') wr = csv.writer(csvfile, dialect=dialect, **fmtparams) wr.writerows(list(reader(sheet))) - From 2cca870092a7e2b22f132342da9d37baabfbf4b9 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:33:44 -0500 Subject: [PATCH 10/35] Add test cases for setup_eb.fix_requirement to test_setup_eb.py --- test_setup_eb.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test_setup_eb.py b/test_setup_eb.py index e36588a9c1..d13408a184 100644 --- a/test_setup_eb.py +++ b/test_setup_eb.py @@ -43,6 +43,10 @@ def test_setup_eb(): assert isinstance(setup_eb.VERSION, str) assert setup_eb.VERSION[0].isdigit() + assert setup_eb.fix_requirement("1.3.5") == "==1.3.5" + assert setup_eb.fix_requirement("^1.3.5") == ">=1.3.5,<2" + assert setup_eb.fix_requirement("~1.3.5") == ">=1.3.5,<1.4" + if __name__ == '__main__': From effb1a19c05ee66589a86e86e673812d8fc2be10 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:37:19 -0500 Subject: [PATCH 11/35] Rearrange imports and light PEP8 in src/encoded/root.py --- src/encoded/root.py | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/encoded/root.py b/src/encoded/root.py index 4112534a16..847db97622 100644 --- a/src/encoded/root.py +++ b/src/encoded/root.py @@ -1,18 +1,13 @@ import uptime -from pyramid.decorator import reify -from snovault import Root, calculated_property, root, COLLECTIONS, STORAGE -from .schema_formats import is_accession + +from collections import OrderedDict from dcicutils import lang_utils from dcicutils.env_utils import is_stg_or_prd_env -from pyramid.security import ( - ALL_PERMISSIONS, - Allow, - Authenticated, - Deny, - Everyone, -) -from collections import OrderedDict from encoded import APP_VERSION_REGISTRY_KEY +from pyramid.decorator import reify +from pyramid.security import ALL_PERMISSIONS, Allow, Authenticated, Deny, Everyone +from snovault import Root, calculated_property, root, COLLECTIONS, STORAGE +from .schema_formats import is_accession def includeme(config): @@ -115,8 +110,8 @@ def health_page_view(request): "elasticsearch": settings.get('elasticsearch.server'), "file_upload_bucket": settings.get('file_upload_bucket'), "foursight": foursight_url, - "indexer": settings.get('indexer'), - "index_server": settings.get('index_server'), + "indexer": settings.get("indexer"), + "index_server": settings.get("index_server"), "load_data": settings.get('load_test_data'), "namespace": settings.get('indexer.namespace'), "processed_file_bucket": settings.get('file_wfout_bucket'), @@ -253,7 +248,7 @@ def content(self, request): user = request._auth0_authenticated if hasattr(request, '_auth0_authenticated') else True return_list = [] for section_name in sections_to_get: - try: # Can be caused by 404 / Not Found during indexing + try: # Can be caused by 404 / Not Found during indexing res = request.embed('/static-sections', section_name, '@@embedded', as_user=user) return_list.append(res) except KeyError: @@ -269,7 +264,7 @@ def carousel(self, request): user = request._auth0_authenticated if hasattr(request, '_auth0_authenticated') else True try: return request.embed('/search/?type=StaticSection§ion_type=Home+Page+Slide&sort=name', as_user=user).get('@graph', []) - except KeyError: # Can be caused by 404 / Not Found during indexing + except KeyError: # Can be caused by 404 / Not Found during indexing return [] @calculated_property(schema={ @@ -281,7 +276,7 @@ def announcements(self, request): user = request._auth0_authenticated if hasattr(request, '_auth0_authenticated') else True try: return request.embed('/search/?type=StaticSection§ion_type=Announcement&sort=-date_created', as_user=user).get('@graph', []) - except KeyError: # Can be caused by 404 / Not Found during indexing + except KeyError: # Can be caused by 404 / Not Found during indexing return [] @calculated_property(schema={ From 5f12ac0e02fbe83b842e646874c0d109b890d236 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:38:32 -0500 Subject: [PATCH 12/35] Suppress some noisy deprecation warnings in src/encoded/types/page.py beause they'd be complicated to fix right now. --- src/encoded/types/page.py | 60 ++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/src/encoded/types/page.py b/src/encoded/types/page.py index 2af193ffdd..913a004a74 100644 --- a/src/encoded/types/page.py +++ b/src/encoded/types/page.py @@ -1,34 +1,19 @@ """ The type file for the collection Pages. Which is used for static pages on the portal """ -from urllib.parse import ( - urlparse, - urlencode -) + +from dcicutils.misc_utils import filtered_warnings from pyramid.httpexceptions import ( # 301-307 redirect code response HTTPMovedPermanently, HTTPFound, HTTPSeeOther, HTTPTemporaryRedirect ) -from pyramid.view import ( - view_config, -) -from snovault import ( - collection, - load_schema, - COLLECTIONS, - CONNECTION -) -from ..search import get_iterable_search_results -from .base import ( - Item, - ALLOW_CURRENT, DELETED, ALLOW_LAB_SUBMITTER_EDIT, ALLOW_VIEWING_GROUP_VIEW, ONLY_ADMIN_VIEW -) -from .user_content import ( - StaticSection -) +from pyramid.view import view_config +from snovault import collection, load_schema, COLLECTIONS, CONNECTION +from snovault.crud_views import collection_add, item_edit from snovault.resource_views import item_view_page +from snovault.util import debug_log from snovault.validators import ( validate_item_content_post, validate_item_content_put, @@ -38,11 +23,9 @@ no_validate_item_content_put, no_validate_item_content_patch ) -from snovault.crud_views import ( - collection_add, - item_edit, -) -from snovault.util import debug_log +from ..search import get_iterable_search_results +from .base import Item, ALLOW_CURRENT, DELETED, ALLOW_LAB_SUBMITTER_EDIT, ALLOW_VIEWING_GROUP_VIEW, ONLY_ADMIN_VIEW +from .user_content import StaticSection def get_pyramid_http_exception_for_redirect_code(code): @@ -165,12 +148,24 @@ def is_static_page(info, request): def includeme(config): - config.add_route( - 'staticpage', - '/*subpath', - custom_predicates=[is_static_page], - request_method="GET" - ) + with filtered_warnings("ignore", category=DeprecationWarning): + config.add_route( + 'staticpage', + '/*subpath', + # TODO: Replace custom_predicates=[is_static_page] with something more modern. + # The custom_predicates needs to be rewritten. + # Although there is a complex rewrite using .add_route_predicate, + # the simpler case of just using .add_static_view may bypass a lot of complexity. + # But this needs more study to get right. For now this code will work and + # we're just going to suppress the warning. -kmp 16-May-2020 + # Refs: + # - https://stackoverflow.com/questions/30102767/custom-route-predicates-in-pyramid + # - https://docs.pylonsproject.org/projects/pyramid/en/latest/_modules/pyramid/config/routes.html + # - https://docs.pylonsproject.org/projects/pyramid/en/master/narr/hooks.html#view-and-route-predicates + # - https://docs.pylonsproject.org/projects/pyramid/en/latest/api/config.html + custom_predicates=[is_static_page], + request_method="GET" + ) config.add_view(static_page, route_name='staticpage') @@ -193,6 +188,7 @@ class Page(Item): class Collection(Item.Collection): pass + for field in ['display_title', 'name', 'description', 'content.name']: Page.embedded_list = Page.embedded_list + [ 'children.' + field, 'children.children.' + field, 'children.children.children.' + field From 4966b2d51463ab6966a2aa25fa27dfe3fdbf6901 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:41:51 -0500 Subject: [PATCH 13/35] Port the post_only= argument to load_all and load_all_gen in src/encoded/loadxl.py. --- src/encoded/loadxl.py | 102 +++++++++++++++++++++++++----------------- 1 file changed, 61 insertions(+), 41 deletions(-) diff --git a/src/encoded/loadxl.py b/src/encoded/loadxl.py index dde0562deb..c21cc534e3 100644 --- a/src/encoded/loadxl.py +++ b/src/encoded/loadxl.py @@ -101,6 +101,7 @@ def load_data_view(context, request): # this is a bit wierd but want to reuse load_data functionality so I'm rolling with it config_uri = request.json.get('config_uri', 'production.ini') patch_only = request.json.get('patch_only', False) + post_only = request.json.get('post_only', False) app = get_app(config_uri, 'app') environ = {'HTTP_ACCEPT': 'application/json', 'REMOTE_USER': 'TEST'} testapp = webtest.TestApp(app, environ) @@ -129,10 +130,10 @@ def load_data_view(context, request): # this directly calls load_all_gen, instead of load_all if iter_resp: return Response( - content_type = 'text/plain', - app_iter = LoadGenWrapper( - load_all_gen(testapp, inserts, None, overwrite=overwrite, - itype=itype, from_json=from_json, patch_only=patch_only) + content_type='text/plain', + app_iter=LoadGenWrapper( + load_all_gen(testapp, inserts, None, overwrite=overwrite, itype=itype, + from_json=from_json, patch_only=patch_only, post_only=post_only) ) ) # otherwise, it is a regular view and we can call load_all as usual @@ -264,7 +265,7 @@ def format_for_attachment(json_data, docsdir): # â–‘ """ -def load_all(testapp, inserts, docsdir, overwrite=True, itype=None, from_json=False, patch_only=False): +def load_all(testapp, inserts, docsdir, overwrite=True, itype=None, from_json=False, patch_only=False, post_only=False): """ Wrapper function for load_all_gen, which invokes the generator returned from that function. Takes all of the same args as load_all_gen, so @@ -276,18 +277,19 @@ def load_all(testapp, inserts, docsdir, overwrite=True, itype=None, from_json=Fa with the functionality of load_all_gen. """ gen = LoadGenWrapper( - load_all_gen(testapp, inserts, docsdir, overwrite, itype, from_json, patch_only) + load_all_gen(testapp, inserts, docsdir, overwrite, itype, from_json, patch_only, post_only) ) # run the generator; don't worry about the output for _ in gen: pass - # gen.caught will str error message on error, otherwise None on success - if gen.caught is not None: + # gen.caught is None for success and an error message on failure + if gen.caught is None: + return None + else: return Exception(gen.caught) - return gen.caught -def load_all_gen(testapp, inserts, docsdir, overwrite=True, itype=None, from_json=False, patch_only=False): +def load_all_gen(testapp, inserts, docsdir, overwrite=True, itype=None, from_json=False, patch_only=False, post_only=False): """ Generator function that yields bytes information about each item POSTed/PATCHed. Is the base functionality of load_all function. @@ -302,7 +304,8 @@ def load_all_gen(testapp, inserts, docsdir, overwrite=True, itype=None, from_jso overwrite (bool) : if the database contains the item already, skip or patch itype (list or str): limit selection to certain type/types from_json (bool) : if set to true, inserts should be dict instead of folder name - + patch_only (bool) : if set to true will only do second round patch - no posts + post_only (bool) : if set to true posts full item no second round or lookup - use with care - will not work if linkTos to items not in db yet Yields: Bytes with information on POSTed/PATCHed items @@ -329,9 +332,11 @@ def load_all_gen(testapp, inserts, docsdir, overwrite=True, itype=None, from_jso use_itype = True if (itype and isinstance(itype, basestring)) else False else: # cannot get the file err_msg = 'Failure loading inserts from %s. Could not find matching file or directory.' % inserts + # import pdb; pdb.set_trace() print(err_msg) yield str.encode('ERROR: %s\n' % err_msg) - raise StopIteration + return + # raise StopIteration # load from the directory/file for a_file in files: if use_itype: @@ -356,9 +361,11 @@ def load_all_gen(testapp, inserts, docsdir, overwrite=True, itype=None, from_jso err_msg = 'No items found in %s' % inserts if itype: err_msg += ' for item type(s) %s' % itype + # import pdb; pdb.set_trace() print(err_msg) yield str.encode('ERROR: %s' % err_msg) - raise StopIteration + return + # raise StopIteration # order Items all_types = list(store.keys()) for ref_item in reversed(ORDER): @@ -371,30 +378,34 @@ def load_all_gen(testapp, inserts, docsdir, overwrite=True, itype=None, from_jso second_round_items = {} if not patch_only: for a_type in all_types: - # this conversion of schema name to object type works for all existing schemas at the moment - obj_type = "".join([i.title() for i in a_type.split('_')]) - # minimal schema - schema_info = profiles[obj_type] - req_fields = schema_info.get('required', []) - ids = schema_info.get('identifyingProperties', []) - # some schemas did not include aliases - if 'aliases' not in ids: - ids.append('aliases') - # file format is required for files, but its usability depends this field - if a_type in ['file_format', 'experiment_type']: - req_fields.append('valid_item_types') - first_fields = list(set(req_fields+ids)) + first_fields = [] + if not post_only: + # this conversion of schema name to object type works for all existing schemas at the moment + obj_type = "".join([i.title() for i in a_type.split('_')]) + # minimal schema + schema_info = profiles[obj_type] + req_fields = schema_info.get('required', []) + ids = schema_info.get('identifyingProperties', []) + # some schemas did not include aliases + if 'aliases' not in ids: + ids.append('aliases') + # file format is required for files, but its usability depends this field + if a_type in ['file_format', 'experiment_type']: + req_fields.append('valid_item_types') + first_fields = list(set(req_fields+ids)) skip_existing_items = set() posted = 0 patched = 0 skip_exist = 0 for an_item in store[a_type]: - try: - # 301 because @id is the existing item path, not uuid - testapp.get('/'+an_item['uuid'], status=[200, 301]) - exists = True - except Exception: - exists = False + exists = False + if not post_only: + try: + # 301 because @id is the existing item path, not uuid + testapp.get('/'+an_item['uuid'], status=[200, 301]) + exists = True + except Exception: + pass # skip the items that exists # if overwrite=True, still include them in PATCH round if exists: @@ -403,10 +414,13 @@ def load_all_gen(testapp, inserts, docsdir, overwrite=True, itype=None, from_jso skip_existing_items.add(an_item['uuid']) yield str.encode('SKIP: %s\n' % an_item['uuid']) else: - post_first = {key: value for (key, value) in an_item.items() if key in first_fields} - post_first = format_for_attachment(post_first, docsdir) + if post_only: + to_post = an_item + else: + to_post = {key: value for (key, value) in an_item.items() if key in first_fields} + to_post = format_for_attachment(to_post, docsdir) try: - res = testapp.post_json('/'+a_type, post_first) + res = testapp.post_json('/'+a_type, to_post) assert res.status_code == 201 posted += 1 # yield bytes to work with Response.app_iter @@ -416,12 +430,15 @@ def load_all_gen(testapp, inserts, docsdir, overwrite=True, itype=None, from_jso ''.format(a_type, str(first_fields), str(e))) # remove newlines from error, since they mess with generator output e_str = str(e).replace('\n', '') + # import pdb; pdb.set_trace() yield str.encode('ERROR: %s\n' % e_str) - raise StopIteration - second_round_items[a_type] = [i for i in store[a_type] if i['uuid'] not in skip_existing_items] + return + # raise StopIteration + if not post_only: + second_round_items[a_type] = [i for i in store[a_type] if i['uuid'] not in skip_existing_items] logger.info('{} 1st: {} items posted, {} items exists.'.format(a_type, posted, skip_exist)) logger.info('{} 1st: {} items will be patched in second round'.format(a_type, str(len(second_round_items.get(a_type, []))))) - elif overwrite: + elif overwrite and not post_only: logger.info('Posting round skipped') for a_type in all_types: second_round_items[a_type] = [i for i in store[a_type]] @@ -431,7 +448,6 @@ def load_all_gen(testapp, inserts, docsdir, overwrite=True, itype=None, from_jso rnd = ' 2nd' if not patch_only else '' for a_type in all_types: patched = 0 - obj_type = "".join([i.title() for i in a_type.split('_')]) if not second_round_items[a_type]: logger.info('{}{}: no items to patch'.format(a_type, rnd)) continue @@ -448,8 +464,10 @@ def load_all_gen(testapp, inserts, docsdir, overwrite=True, itype=None, from_jso print('Patching {} failed. Patch body:\n{}\n\nError Message:\n{}'.format( a_type, str(an_item), str(e))) e_str = str(e).replace('\n', '') + # import pdb; pdb.set_trace() yield str.encode('ERROR: %s\n' % e_str) - raise StopIteration + return + # raise StopIteration logger.info('{}{}: {} items patched .'.format(a_type, rnd, patched)) # explicit return upon finish @@ -509,7 +527,9 @@ def load_test_data(app, overwrite=False): def load_local_data(app, overwrite=False): """ - Load temp-local-inserts. If not present, load inserts and master-inserts + Load inserts from temporary insert folders, if present and populated + with .json insert files. + If not present, load inserts and master-inserts. Returns: None if successful, otherwise Exception encountered From ba95e4ff8dcbe05c90115eb396303eee2d71b5cf Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:43:41 -0500 Subject: [PATCH 14/35] Use .hash instead of .encrypt in src/encoded/types/access_key.py and src/encoded/tests/test_access_key.py --- src/encoded/tests/test_access_key.py | 8 ++++---- src/encoded/types/access_key.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/encoded/tests/test_access_key.py b/src/encoded/tests/test_access_key.py index 218dc8055d..d2f17d2ddb 100644 --- a/src/encoded/tests/test_access_key.py +++ b/src/encoded/tests/test_access_key.py @@ -153,12 +153,12 @@ def test_access_key_user_disable_login(anontestapp, no_login_access_key): def test_access_key_edit(anontestapp, access_key): headers = {'Authorization': auth_header(access_key)} - NEW_DESCRIPTION = 'new description' - properties = {'description': NEW_DESCRIPTION} + new_description = 'new description' + properties = {'description': new_description} anontestapp.put_json(access_key['@id'], properties, headers=headers) res = anontestapp.get(access_key['@id'], properties, headers=headers) - assert res.json['description'] == NEW_DESCRIPTION + assert res.json['description'] == new_description @pytest.mark.parametrize('frame', ['', 'raw', 'object', 'embedded', 'page']) @@ -172,4 +172,4 @@ def test_access_key_uses_edw_hash(app, access_key): root = app.registry[COLLECTIONS] obj = root.by_item_type['access_key'][access_key['access_key_id']] pwhash = obj.properties['secret_access_key_hash'] - assert EDWHash.encrypt(access_key['secret_access_key']) == pwhash + assert EDWHash.hash(access_key['secret_access_key']) == pwhash diff --git a/src/encoded/types/access_key.py b/src/encoded/types/access_key.py index bda734d0dd..4f646ebd84 100644 --- a/src/encoded/types/access_key.py +++ b/src/encoded/types/access_key.py @@ -107,7 +107,7 @@ def access_key_add(context, request): password = None if 'secret_access_key_hash' not in request.validated: password = generate_password() - request.validated['secret_access_key_hash'] = crypt_context.encrypt(password) + request.validated['secret_access_key_hash'] = crypt_context.hash(password) result = collection_add(context, request) @@ -130,7 +130,7 @@ def access_key_reset_secret(context, request): request.validated = context.properties.copy() crypt_context = request.registry[CRYPT_CONTEXT] password = generate_password() - new_hash = crypt_context.encrypt(password) + new_hash = crypt_context.hash(password) request.validated['secret_access_key_hash'] = new_hash result = item_edit(context, request, render=False) result['access_key_id'] = request.validated['access_key_id'] From fad2e816633d9e55b36f20d4c57b628374de3fdf Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:44:26 -0500 Subject: [PATCH 15/35] Add a pytest_configure in conftest.py that sets tempfile.tempdir to '/tmp'. --- conftest.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/conftest.py b/conftest.py index 571f801334..8ff004ce07 100644 --- a/conftest.py +++ b/conftest.py @@ -1,4 +1,6 @@ import pytest +import tempfile + def pytest_addoption(parser): parser.addoption("--es", action="store", default="", dest='es', @@ -15,3 +17,10 @@ def remote_es(request): @pytest.fixture(scope='session') def aws_auth(request): return request.config.getoption("--aws-auth") + + +def pytest_configure(): + # This adjustment is important to set the default choice of temporary filenames to a nice short name + # because without it some of the filenames we generate end up being too long, and critical functionality + # ends up failing. Some socket-related filenames, for example, seem to have length limits. -kmp 5-Jun-2020 + tempfile.tempdir = '/tmp' From cf4a6c5a4330585e24759e76fb8bb55fcdfc8fcd Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:45:13 -0500 Subject: [PATCH 16/35] Also .hash instead of .encrypt in src/encoded/tests/test_edw_hash.py --- src/encoded/tests/test_edw_hash.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/encoded/tests/test_edw_hash.py b/src/encoded/tests/test_edw_hash.py index 41b598ea05..a26356ae0b 100644 --- a/src/encoded/tests/test_edw_hash.py +++ b/src/encoded/tests/test_edw_hash.py @@ -15,4 +15,4 @@ @pytest.mark.parametrize(('password', 'pwhash'), TEST_HASHES.items()) def test_edw_hash(password, pwhash): - assert EDWHash.encrypt(password) == pwhash + assert EDWHash.hash(password) == pwhash From 8dc4b70fb29e56f8eb8e2755f9d133c846a29fd6 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:45:59 -0500 Subject: [PATCH 17/35] Bump versions of awscli, boto3, botocore, netaddr, boto3-stubs. --- pyproject.toml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5df7daa14c..02ad154095 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,9 +36,9 @@ classifiers = [ [tool.poetry.dependencies] python = ">=3.6.1,<3.7" -awscli = ">=1.18.219" -boto3 = "^1.16.59" -botocore = "^1.19.59" +awscli = ">=1.19.9" +boto3 = "^1.17.9" +botocore = "^1.20.9" certifi = ">=2020.11.8" chardet = "3.0.4" colorama = "0.3.3" @@ -57,7 +57,7 @@ jmespath = "0.9.0" jsonschema_serialize_fork = "^2.1.1" keepalive = "0.5" loremipsum = "1.0.5" -netaddr = ">=0.7.18,<1" +netaddr = ">=0.8.0,<1" passlib = "^1.7.4" PasteDeploy = "1.5.2" pbkdf2 = "1.3" @@ -116,7 +116,7 @@ sentry-sdk = "^0.16.5" [tool.poetry.dev-dependencies] # PyCharm says boto3-stubs contains useful type hints -boto3-stubs = ">=1.16.59.0" +boto3-stubs = ">=1.17.8" coverage = ">=5.3.1" codacy-coverage = ">=1.3.11" coveralls = ">=3.0.0" From 6001cbf7a3dafc68c430dc9365a4a266bd249e08 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:46:36 -0500 Subject: [PATCH 18/35] Bump patch version. --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 02ad154095..f95ebb57b4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] # Note: Various modules refer to this system as "encoded", not "fourfront". name = "encoded" -version = "2.3.18" +version = "2.3.19" description = "4DN-DCIC Fourfront" authors = ["4DN-DCIC Team "] license = "MIT" From c0e93171377c917f55cdb7356c4bd94c032d683e Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:50:30 -0500 Subject: [PATCH 19/35] Make jwt algorithms explicit in src/encoded/authentication.py. Also don't special-case GET and HEAD methods. --- src/encoded/authentication.py | 55 +++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/src/encoded/authentication.py b/src/encoded/authentication.py index 67d7a65058..8ee4464661 100644 --- a/src/encoded/authentication.py +++ b/src/encoded/authentication.py @@ -6,6 +6,7 @@ import jwt from base64 import b64decode +from dcicutils.misc_utils import remove_element from passlib.context import CryptContext from urllib.parse import urlencode from pyramid.authentication import ( @@ -47,6 +48,27 @@ CRYPT_CONTEXT = __name__ + ':crypt_context' +JWT_ENCODING_ALGORITHM = 'HS256' + +# Might need to keep a list of previously used algorithms here, not just the one we use now. +# Decryption algorithm used to default to a long list, but more recent versions of jwt library +# say we should stop assuming that. +# +# In case it goes away, as far as I can tell, the default for decoding from their +# default_algorithms() method used to be what we've got in JWT_ALL_ALGORITHMS here. +# -kmp 15-May-2020 + +JWT_ALL_ALGORITHMS = ['ES512', 'RS384', 'HS512', 'ES256', 'none', + 'RS256', 'PS512', 'ES384', 'HS384', 'ES521', + 'PS384', 'HS256', 'PS256', 'RS512'] + +# Probably we could get away with fewer, but I think not as few as just our own encoding algorithm, +# so for now I believe the above list was the default, and this just rearranges it to prefer the one +# we use for encoding. -kmp 19-Jan-2021 + +JWT_DECODING_ALGORITHMS = [JWT_ENCODING_ALGORITHM] + remove_element(JWT_ENCODING_ALGORITHM, JWT_ALL_ALGORITHMS) + + def includeme(config): config.include('.edw_hash') setting_prefix = 'passlib.' @@ -205,6 +227,7 @@ def get_token_info(self, token, request): if auth0_client and auth0_secret: # leeway accounts for clock drift between us and auth0 payload = jwt.decode(token, b64decode(auth0_secret, '-_'), + algorithms=JWT_DECODING_ALGORITHMS, audience=auth0_client, leeway=30) if 'email' in payload and payload.get('email_verified') is True: request.set_property(lambda r: False, 'auth0_expired') @@ -229,21 +252,27 @@ def get_token_info(self, token, request): def get_jwt(request): + token = None + + # First try to obtain JWT from headers try: - # ensure this is a jwt token not basic auth: - auth_type = request.headers['Authorization'][:6] - if auth_type.strip().lower() == 'bearer': - token = request.headers['Authorization'][7:] - except (ValueError, TypeError, KeyError): + # Ensure this is a JWT token, not basic auth. + # Per https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication and + # https://tools.ietf.org/html/rfc6750, JWT is introduced by 'bearer', as in + # Authorization: Bearer something.something.something + # rather than, for example, the 'basic' key information, which as discussed in + # https://tools.ietf.org/html/rfc7617 is base64 encoded and looks like: + # Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== + # See also https://jwt.io/introduction/ for other info specific to JWT. + [auth_type, auth_data] = request.headers['Authorization'].strip().split(' ', 1) + if auth_type.lower() == 'bearer': + token = auth_data.strip() # The spec says exactly one space, but then a token, so spaces don't matter + except Exception: pass - if not token and request.method in ('GET', 'HEAD'): - # Only grab this if is a GET request, not a transactional request to help mitigate CSRF attacks. - # See: https://en.wikipedia.org/wiki/Cross-site_request_forgery#Cookie-to-header_token - # The way our JS grabs and sticks JWT into Authorization header is somewhat analogous to above approach. - # TODO: Ensure our `Access-Control-Allow-Origin` response headers are appropriate (more for CGAP). - # TODO: Get a security audit done. + # If the JWT is not in the headers, get it from cookies + if not token: token = request.cookies.get('jwtToken') return token @@ -410,7 +439,9 @@ def impersonate_user(context, request): 'aud': auth0_client, } - id_token = jwt.encode(jwt_contents, b64decode(auth0_secret, '-_'), algorithm='HS256') + id_token = jwt.encode(jwt_contents, b64decode(auth0_secret, '-_'), + algorithm=JWT_ENCODING_ALGORITHM + ) user_properties['id_token'] = id_token.decode('utf-8') return user_properties From c4bffdd8a02c56bdb5dbe3c229380582ab1873ab Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:51:08 -0500 Subject: [PATCH 20/35] PyCharm PEP8 hint in src/encoded/dev_servers.py --- src/encoded/dev_servers.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/encoded/dev_servers.py b/src/encoded/dev_servers.py index e7497bb027..4600888f55 100644 --- a/src/encoded/dev_servers.py +++ b/src/encoded/dev_servers.py @@ -1,8 +1,11 @@ """\ Examples For the development.ini you must supply the paster app name: + %(prog)s development.ini --app-name app --init --clear + """ + import argparse import atexit import logging @@ -47,7 +50,7 @@ def nginx_server_process(prefix='', echo=False): def main(): - parser = argparse.ArgumentParser( + parser = argparse.ArgumentParser( # noqa - PyCharm wrongly thinks the formatter_class is specified wrong here. description="Run development servers", epilog=EPILOG, formatter_class=argparse.RawDescriptionHelpFormatter, ) From 6410658382f48fd7826213c2cd0739ac2a293f52 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:54:03 -0500 Subject: [PATCH 21/35] Use new ACCESSION_PREFIX variable to minimize number of places code diverges. Add a TEST_PREFIX variable for symmetry. Compute the letter pairs needed for accession ids by looking at the schema files. --- src/encoded/schema_formats.py | 28 ++++++++++++++++++++++++++-- src/encoded/server_defaults.py | 14 +++++--------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/encoded/schema_formats.py b/src/encoded/schema_formats.py index 821b3c7c3c..f8fc1cad98 100644 --- a/src/encoded/schema_formats.py +++ b/src/encoded/schema_formats.py @@ -1,17 +1,41 @@ +import glob +import io +import json +import pkg_resources import re import rfc3987 + from jsonschema_serialize_fork import FormatChecker from pyramid.threadlocal import get_current_request from .server_defaults import ( ACCESSION_FACTORY, + ACCESSION_PREFIX, + TEST_PREFIX, test_accession, ) from uuid import UUID -accession_re = re.compile(r'^4DN(EX|ES|FI|FS|SR|BS|IN|WF)[1-9A-Z]{7}$') -test_accession_re = re.compile(r'^TST(EX|ES|FI|FS|SR|BS|IN|WF)[0-9]{4}([0-9][0-9][0-9]|[A-Z][A-Z][A-Z])$') + +def compute_accession_codes(): + letter_pairs = set() + for file in glob.glob(pkg_resources.resource_filename('encoded', 'schemas/*.json')): + with io.open(file) as fp: + schema = json.load(fp) + letter_pair = schema.get('properties', {}).get('accession', {}).get('accessionType') + if letter_pair: + if not isinstance(letter_pair, str) or len(letter_pair) != 2: + raise RuntimeError("accession_type in %s is not a 2-character string:", letter_pair) + letter_pairs.add(letter_pair) + return "|".join(sorted(letter_pairs)) + + +ACCESSION_CODES = compute_accession_codes() + +accession_re = re.compile(r'^%s(%s)[1-9A-Z]{7}$' % (ACCESSION_PREFIX, ACCESSION_CODES)) +test_accession_re = re.compile(r'^%s(%s)[0-9]{4}([0-9][0-9][0-9]|[A-Z][A-Z][A-Z])$' % (TEST_PREFIX, ACCESSION_CODES)) uuid_re = re.compile(r'(?i)\{?(?:[0-9a-f]{4}-?){8}\}?') + @FormatChecker.cls_checks("uuid") def is_uuid(instance): # Python's UUID ignores all dashes, whereas Postgres is more strict diff --git a/src/encoded/server_defaults.py b/src/encoded/server_defaults.py index 8a6f900d7e..cfbb427310 100644 --- a/src/encoded/server_defaults.py +++ b/src/encoded/server_defaults.py @@ -1,21 +1,17 @@ -from datetime import datetime import random import uuid -from string import ( - digits, - ascii_uppercase, - ) - +from datetime import datetime from jsonschema_serialize_fork import NO_DEFAULT - from pyramid.path import DottedNameResolver from pyramid.threadlocal import get_current_request - from snovault.schema_utils import server_default +from string import digits, ascii_uppercase ACCESSION_FACTORY = __name__ + ':accession_factory' +ACCESSION_PREFIX = '4DN' +TEST_PREFIX = 'TST' def includeme(config): @@ -114,7 +110,7 @@ def add_last_modified(properties, userid=None): def enc_accession(accession_type): random_part = ''.join(random.choice(s) for s in FDN_ACCESSION_FORMAT) - return '4DN' + accession_type + random_part + return ACCESSION_PREFIX + accession_type + random_part TEST_ACCESSION_FORMAT = (digits, ) * 7 From 86ec08c9adf9a9ac280222e791e4497f1822bd08 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:57:43 -0500 Subject: [PATCH 22/35] In conftest.py, change htmltestapp and anonhtmltestapp to pass HTTP_ACCEPT, which is more like what browsers would do and is needed for some ported changes from cgap-portal. Light PEP8. Remove pytest_plugins setting, which is deprecated; this info is now in pytest.ini. Change pytest.ini to have markers in line with cgap-portal, to use testpaths rather than a --pyargs setting, and to use -p to handle plugins. --- pytest.ini | 17 +++++++++++++---- src/encoded/tests/conftest.py | 15 ++++++--------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/pytest.ini b/pytest.ini index 233f25b85f..799207aa11 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,18 +1,27 @@ [pytest] addopts = - --pyargs encoded.tests deploy.tests - -p encoded.tests deploy.tests + -p encoded.tests.datafixtures + -p snovault.tests.serverfixtures --instafail markers = + action_fail: mark a test that fails consistently on GA (and thus skipped) broken: mark as a 'broken' test that does not run on Travis es: mark a test as an elastic search test (deselect with '-m "not es"') - indexing: mark a test as an indexing test (deselect with '-m "not indexing"') + file_operation: a test that utilizes files + indexing: mark a test as an indexing test, or really just not-workbook (deselect with '-m "not indexing"') ingestion: mark a test as an ingestion test (deselect with '-m "not ingestion"') + integrated: an integration test + integratedx: an excludable integration test, redundantly testing functionality also covered by a unit test + manual: a test that is only ever intended to be run manually performance: mark a test as a performance test (deselect with '-m "not performance"') schema: mark a test as a schema-related test (deselect with '-m "not schema"') + search: mark a test a search module test (deselect with '-m "not search"') setone: (deprecated) instead of '-m "setone"', please use '-m "not indexing"', TODO: refs and scripts to be rewritten slow: mark a test as slow (deselect with '-m "not slow"') storage: mark a test as about storage (deselect with '-m "not storage"') + unit: a proper unit test working: mark a test as working (deselect with '-m "not working"') - action_fail: known to fail on Github Action build norecursedirs = *env site-packages .cache .git .idea *.egg-info +testpaths = + src/encoded + deploy diff --git a/src/encoded/tests/conftest.py b/src/encoded/tests/conftest.py index 1501ef1c52..0dceeec019 100644 --- a/src/encoded/tests/conftest.py +++ b/src/encoded/tests/conftest.py @@ -19,12 +19,6 @@ from .conftest_settings import make_app_settings_dictionary -pytest_plugins = [ - 'encoded.tests.datafixtures', - 'snovault.tests.serverfixtures', -] - - @pytest.fixture(autouse=True) def autouse_external_tx(external_tx): pass @@ -125,8 +119,7 @@ def dummy_request(root, registry, app): @pytest.fixture(scope='session') def app(app_settings): - '''WSGI application level functional testing. - ''' + """ WSGI application level functional testing. """ return main({}, **app_settings) @@ -156,7 +149,10 @@ def root(registry): @pytest.fixture def anonhtmltestapp(app): - return webtest.TestApp(app) + environ = { + 'HTTP_ACCEPT': 'text/html', + } + return webtest.TestApp(app, environ) @pytest.fixture @@ -165,6 +161,7 @@ def htmltestapp(app): # TODO: Name may be misleading. If only for HTML testing, seems like it should be text/html. # Or if it spans CSS and other things, maybe call it page_content_testapp? -kmp 03-Feb-2020 environ = { + 'HTTP_ACCEPT': 'text/html', 'REMOTE_USER': 'TEST', } return webtest.TestApp(app, environ) From 22ae5f2326c51249308a01657468057414584109 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 05:59:28 -0500 Subject: [PATCH 23/35] Use dcicutils.misc_utils.TestApp in src/commands/add_date_created.py, import_data.py --- src/encoded/commands/add_date_created.py | 2 +- src/encoded/commands/import_data.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/encoded/commands/add_date_created.py b/src/encoded/commands/add_date_created.py index 065a89c22b..5220c0bad1 100644 --- a/src/encoded/commands/add_date_created.py +++ b/src/encoded/commands/add_date_created.py @@ -20,7 +20,7 @@ from future.utils import iteritems from pyramid import paster from pyramid.traversal import resource_path -from webtest import TestApp +from dcicutils.misc_utils import TestApp pacific = pytz.timezone('US/Pacific') diff --git a/src/encoded/commands/import_data.py b/src/encoded/commands/import_data.py index 9e4de995a4..f9a4fe31fb 100644 --- a/src/encoded/commands/import_data.py +++ b/src/encoded/commands/import_data.py @@ -27,7 +27,7 @@ from base64 import b64encode from pyramid.compat import ascii_native_ from pyramid import paster -from webtest import TestApp +from dcicutils.misc_utils import TestApp from wsgiproxy.proxies import ALLOWED_METHODS from urllib.parse import urlparse from .. import loadxl From aab5734ce54983e9fa38b4773f59db26d9ce5af9 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 06:00:05 -0500 Subject: [PATCH 24/35] Remove an internal import in src/encoded/commands/spreadsheet_to_json.py --- src/encoded/commands/spreadsheet_to_json.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/encoded/commands/spreadsheet_to_json.py b/src/encoded/commands/spreadsheet_to_json.py index 3455f2930d..5356c1d42e 100644 --- a/src/encoded/commands/spreadsheet_to_json.py +++ b/src/encoded/commands/spreadsheet_to_json.py @@ -5,10 +5,12 @@ """ -from .. import loadxl +import argparse import json import os.path +from .. import loadxl + EPILOG = __doc__ @@ -45,7 +47,6 @@ def convert(filename, sheetname=None, outputdir=None, skip_blanks=False): def main(): - import argparse parser = argparse.ArgumentParser( # noqa - PyCharm wrongly thinks the formatter_class is specified wrong here. description="Convert spreadsheet to json list", epilog=EPILOG, formatter_class=argparse.RawDescriptionHelpFormatter, From 05522937751362cdc34df1208598c584c210db8b Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 06:01:38 -0500 Subject: [PATCH 25/35] Unmark biosample_relation as a fixture. It is not a fixture. --- src/encoded/tests/test_types_biosample.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/encoded/tests/test_types_biosample.py b/src/encoded/tests/test_types_biosample.py index 3e8b979247..a8eb82c432 100644 --- a/src/encoded/tests/test_types_biosample.py +++ b/src/encoded/tests/test_types_biosample.py @@ -39,7 +39,6 @@ def biosample_w_treatment(testapp, biosample_1, rnai): return testapp.patch_json(biosample_1['@id'], {'treatments': [rnai['@id']]}).json['@graph'][0] -@pytest.fixture def biosample_relation(derived_from): return {"biosample_relation": [{"relationship_type": "derived from", "biosample": derived_from['@id']}]} From 22b6902890856954d12e9a235f12af852bcd9b73 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 06:04:27 -0500 Subject: [PATCH 26/35] Port recent tweens work related to mime type selection in src/encoded/renderers.py. Some PEP8. --- src/encoded/renderers.py | 188 +++++++++++++++++++++++++++++---------- 1 file changed, 139 insertions(+), 49 deletions(-) diff --git a/src/encoded/renderers.py b/src/encoded/renderers.py index 6ad6f35a6e..039ea1229d 100644 --- a/src/encoded/renderers.py +++ b/src/encoded/renderers.py @@ -4,35 +4,33 @@ import psutil import time -from pkg_resources import resource_filename -from urllib.parse import urlencode +from dcicutils.misc_utils import environ_bool, PRINT, ignored from functools import lru_cache +from pkg_resources import resource_filename from pyramid.events import BeforeRender, subscriber from pyramid.httpexceptions import ( HTTPMovedPermanently, HTTPPreconditionFailed, HTTPUnauthorized, - # HTTPForbidden, HTTPUnsupportedMediaType, HTTPNotAcceptable, HTTPServerError ) -# from pyramid.security import forget +from pyramid.response import Response from pyramid.settings import asbool from pyramid.threadlocal import manager -from pyramid.response import Response from pyramid.traversal import split_path_info, _join_path_tuple -# from snovault.validation import CSRFTokenError -# from subprocess_middleware.tween import SubprocessTween from subprocess_middleware.worker import TransformWorker +from urllib.parse import urlencode from webob.cookies import Cookie +from .util import content_type_allowed log = logging.getLogger(__name__) def includeme(config): - ''' + """ Can get tween ordering by executing the following on command-line from root dir: `bin/ptween development.ini` @@ -67,13 +65,15 @@ def includeme(config): This means that if handler(request) is called, then the downstream tweens are acted upon it, until response is returned. It's an ONION! - ''' + """ config.add_tween('.renderers.validate_request_tween_factory', under='snovault.stats.stats_tween_factory') - # DISABLED - .add_tween('.renderers.remove_expired_session_cookies_tween_factory', under='.renderers.validate_request_tween_factory') + # DISABLED - .add_tween('.renderers.remove_expired_session_cookies_tween_factory', + # under='.renderers.validate_request_tween_factory') config.add_tween('.renderers.render_page_html_tween_factory', under='.renderers.validate_request_tween_factory') - # The above tweens, when using response (= `handler(request)`) act on the _transformed_ response (containing HTML body). + # The above tweens, when using response (= `handler(request)`) act on the _transformed_ response + # (containing HTML body). # The below tweens run _before_ the JS rendering. Responses in these tweens have not been transformed to HTML yet. config.add_tween('.renderers.set_response_headers_tween_factory', under='.renderers.render_page_html_tween_factory') @@ -93,6 +93,7 @@ def validate_request_tween_factory(handler, registry): Apache config: SetEnvIf Request_Method HEAD X_REQUEST_METHOD=HEAD """ + ignored(registry) def validate_request_tween(request): @@ -107,19 +108,18 @@ def validate_request_tween(request): # Includes page text/html requests. return handler(request) - elif request.content_type != 'application/json': - if request.content_type == 'application/x-www-form-urlencoded' and request.path[0:10] == '/metadata/': - # Special case to allow us to POST to metadata TSV requests via form submission - return handler(request) + elif content_type_allowed(request): + return handler(request) + + else: detail = "Request content type %s is not 'application/json'" % request.content_type raise HTTPUnsupportedMediaType(detail) - return handler(request) - return validate_request_tween def security_tween_factory(handler, registry): + ignored(registry) def security_tween(request): """ @@ -132,7 +132,7 @@ def security_tween(request): """ expected_user = request.headers.get('X-If-Match-User') - if expected_user is not None: # Not sure when this is the case + if expected_user is not None: # Not sure when this is the case if request.authenticated_userid != 'mailto.' + expected_user: detail = 'X-If-Match-User does not match' raise HTTPPreconditionFailed(detail) @@ -147,15 +147,18 @@ def security_tween(request): raise HTTPUnauthorized( title="No Access", comment="Invalid Authorization header or Auth Challenge response.", - headers={'WWW-Authenticate': "Bearer realm=\"{}\"; Basic realm=\"{}\"".format(request.domain, request.domain) } + headers={ + 'WWW-Authenticate': ("Bearer realm=\"{}\"; Basic realm=\"{}\"" + .format(request.domain, request.domain)) + } ) - if hasattr(request, 'auth0_expired'): # Add some security-related headers on the up-swing response = handler(request) if request.auth0_expired: - #return response + # return response + # # If have the attribute and it is true, then our session has expired. # This is true for both AJAX requests (which have request.authorization) & browser page # requests (which have cookie); both cases handled in authentication.py @@ -166,9 +169,13 @@ def security_tween(request): # Especially for initial document requests by browser, but also desired for AJAX and other requests, # unset jwtToken cookie so initial client-side React render has App(instance).state.session = false # to be synced w/ server-side - response.set_cookie(name='jwtToken', value=None, max_age=0,path='/') # = Same as response.delete_cookie(..) + response.set_cookie(name='jwtToken', + value=None, max_age=0, path='/') # = Same as response.delete_cookie(..) response.status_code = 401 - response.headers['WWW-Authenticate'] = "Bearer realm=\"{}\", title=\"Session Expired\"; Basic realm=\"{}\"".format(request.domain, request.domain) + response.headers['WWW-Authenticate'] = ( + "Bearer realm=\"{}\", title=\"Session Expired\"; Basic realm=\"{}\"" + .format(request.domain, request.domain) + ) else: # We have JWT and it's not expired. Add 'X-Request-JWT' & 'X-User-Info' header. # For performance, only do it if should transform to HTML as is not needed on every request. @@ -180,8 +187,13 @@ def security_tween(request): # This header is parsed in renderer.js, or, more accurately, # by libs/react-middleware.js which is imported by server.js and compiled into # renderer.js. Is used to get access to User Info on initial web page render. - response.headers['X-Request-JWT'] = request.cookies.get('jwtToken','') - response.headers['X-User-Info'] = json.dumps(request.user_info) # Re-ified property set in authentication.py + response.headers['X-Request-JWT'] = request.cookies.get('jwtToken', '') + # TODO: Should user_info be copied before the del? If the user info is shared, + # we are modifying it for other uses. -kmp 24-Jan-2021 + user_info = request.user_info.copy() # Re-ified property set in authentication.py + # Redundant - don't need this in SSR nor browser as get from X-Request-JWT. + del user_info["id_token"] + response.headers['X-User-Info'] = json.dumps(user_info) else: response.headers['X-Request-JWT'] = "null" return response @@ -193,20 +205,20 @@ def security_tween(request): # requests from Authorization header which acts like a CSRF token. # See authentication.py - get_jwt() - #token = request.headers.get('X-CSRF-Token') - #if token is not None: - # # Avoid dirtying the session and adding a Set-Cookie header - # # XXX Should consider if this is a good idea or not and timeouts - # if token == dict.get(request.session, '_csrft_', None): - # return handler(request) - # raise CSRFTokenError('Incorrect CSRF token') + # token = request.headers.get('X-CSRF-Token') + # if token is not None: + # # Avoid dirtying the session and adding a Set-Cookie header + # # XXX Should consider if this is a good idea or not and timeouts + # if token == dict.get(request.session, '_csrft_', None): + # return handler(request) + # raise CSRFTokenError('Incorrect CSRF token') # raise CSRFTokenError('Missing CSRF token') return security_tween def remove_expired_session_cookies_tween_factory(handler, registry): - ''' + """ CURRENTLY DISABLED Original purpose of this was to remove expired (session?) cookies. See: https://github.com/ENCODE-DCC/encoded/commit/75854803c99e5044a6a33aedb3a79d750481b6cd#diff-bc19a9793a1b3b4870cff50e7c7c9bd1R135 @@ -214,7 +226,8 @@ def remove_expired_session_cookies_tween_factory(handler, registry): We disable it for now via removing from tween chain as are using JWT tokens and handling their removal in security_tween_factory & authentication.py as well as client-side (upon "Logout" action). If needed for some reason, can re-enable. - ''' + """ # noQA - not going to break the long URL line above + ignored(registry) ignore = { '/favicon.ico', @@ -225,8 +238,8 @@ def remove_expired_session_cookies_tween(request): return handler(request) session = request.session - #if session or session._cookie_name not in request.cookies: - # return handler(request) + # if session or session._cookie_name not in request.cookies: + # return handler(request) response = handler(request) # Below seems to be empty always; though we do have some in request.cookies @@ -250,7 +263,9 @@ def remove_expired_session_cookies_tween(request): def set_response_headers_tween_factory(handler, registry): - '''Add additional response headers here''' + """Add additional response headers here""" + ignored(registry) + def set_response_headers_tween(request): response = handler(request) response.headers['X-Request-URL'] = request.url @@ -306,15 +321,80 @@ def canonical_redirect(event): raise HTTPMovedPermanently(location=location, detail="Redirected from " + str(request.path_info)) +# Web browsers send an Accept request header for initial (e.g. non-AJAX) page requests +# which should contain 'text/html' +MIME_TYPE_HTML = 'text/html' +MIME_TYPE_JSON = 'application/json' +MIME_TYPE_LD_JSON = 'application/ld+json' + +MIME_TYPES_SUPPORTED = [MIME_TYPE_JSON, MIME_TYPE_HTML, MIME_TYPE_LD_JSON] +MIME_TYPE_DEFAULT = MIME_TYPES_SUPPORTED[0] +MIME_TYPE_TRIAGE_MODE = 'modern' # if this doesn't work, fall back to 'legacy' + +DEBUG_MIME_TYPES = environ_bool("DEBUG_MIME_TYPES", default=False) + + +def best_mime_type(request, mode=MIME_TYPE_TRIAGE_MODE): + # TODO: I think this function does nothing but return MIME_TYPES_SUPPORTED[0] -kmp 3-Feb-2021 + """ + Given a request, tries to figure out the best kind of MIME type to use in response + based on what kinds of responses we support and what was requested. + + In the case we can't comply, we just use application/json whether or not that's what was asked for. + """ + if mode == 'legacy': + # See: + # https://tedboy.github.io/flask/generated/generated/werkzeug.Accept.best_match.html#werkzeug-accept-best-match + # Note that this is now deprecated, or will be. The message is oddly worded ("will be deprecated") + # that presumably means "will be removed". Deprecation IS the warning of actual action, not the action itself. + # "This is currently maintained for backward compatibility, and will be deprecated in the future. + # AcceptValidHeader.best_match() uses its own algorithm (one not specified in RFC 7231) to determine + # what is a best match. The algorithm has many issues, and does not conform to RFC 7231." + # Anyway, we were getting this warning during testing: + # DeprecationWarning: The behavior of AcceptValidHeader.best_match is currently + # being maintained for backward compatibility, but it will be deprecated in the future, + # as it does not conform to the RFC. + # TODO: Once the modern replacement is shown to work, we should remove this conditional branch. + result = request.accept.best_match(MIME_TYPES_SUPPORTED, MIME_TYPE_DEFAULT) + else: + options = request.accept.acceptable_offers(MIME_TYPES_SUPPORTED) + if not options: + # TODO: Probably we should return a 406 response by raising HTTPNotAcceptable if + # no acceptable types are available. (Certainly returning JSON in this case is + # not some kind of friendly help toa naive user with an old browser.) + # Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status + result = MIME_TYPE_DEFAULT + else: + mime_type, score = options[0] + result = mime_type + if DEBUG_MIME_TYPES: + PRINT("Using mime type", result, "for", request.method, request.url) + for k, v in request.headers.items(): + PRINT("%s: %s" % (k, v)) + PRINT("----------") + return result + + @lru_cache(maxsize=16) def should_transform(request, response): - ''' + """ Determines whether to transform the response from JSON->HTML/JS depending on type of response - and what the request is looking for to be returned via e.g. request Accept, Authorization header. - In case of no Accept header, attempts to guess. - - Memoized via `lru_cache`. Cache size is set to be 16 (> 1) in case sub-requests fired off during handling. - ''' + and what the request is looking for to be returned via these criteria, which are tried in order + until one succeeds: + + * If the request method is other than GET or HEAD, returns False. + * If the response.content_type is other than 'application/json', returns False. + * If a 'frame=' query param is given and not 'page' (the default), returns False. + * If a 'format=json' query param is given explicitly, + * For 'format=html', returns True. + * For 'format=json', returns False. + This rule does not match if 'format=' is not given explicitly. + If 'format=' is given an explicit value of ther than 'html' or 'json', an HTTPNotAcceptable error will be raised. + * If the first element of MIME_TYPES_SUPPORTED[0] is 'text/html', returns True. + * Otherwise, in all remaining cases, returns False. + + NOTE: Memoized via `lru_cache`. Cache size is set to be 16 (> 1) in case sub-requests fired off during handling. + """ # We always return JSON in response to POST, PATCH, etc. if request.method not in ('GET', 'HEAD'): return False @@ -323,6 +403,12 @@ def should_transform(request, response): if response.content_type != 'application/json': return False + # If we have a 'frame' that is not None or page, force JSON, since our UI doesn't handle all various + # forms of the data, just embedded/page. + request_frame = request.params.get("frame", "page") + if request_frame != "page": + return False + # The `format` URI param allows us to override request's 'Accept' header. format = request.params.get('format') if format is not None: @@ -332,16 +418,18 @@ def should_transform(request, response): if format == 'html': return True else: - raise HTTPNotAcceptable("Improper format URI parameter", comment="The format URI parameter should be set to either html or json.") + raise HTTPNotAcceptable("Improper format URI parameter", + comment="The format URI parameter should be set to either html or json.") # Web browsers send an Accept request header for initial (e.g. non-AJAX) page requests # which should contain 'text/html' # See: https://tedboy.github.io/flask/generated/generated/werkzeug.Accept.best_match.html#werkzeug-accept-best-match - mime_type = request.accept.best_match(['text/html', 'application/json', 'application/ld+json'], 'application/json') - format = mime_type.split('/', 1)[1] # Will be 1 of 'html', 'json', 'json-ld' + mime_type = best_mime_type(request) + format = mime_type.split('/', 1)[1] # Will be 1 of 'html', 'json', 'json-ld' - # N.B. ld+json (JSON-LD) is likely more unique case and might be sent by search engines (?) which can parse JSON-LDs. - # At some point we could maybe have it to be same as making an `@@object` or `?frame=object` request (?) esp if fill + # N.B. ld+json (JSON-LD) is likely more unique case and might be sent by search engines (?) + # which can parse JSON-LDs. At some point we could maybe have it to be same as + # making an `@@object` or `?frame=object` request (?) esp if fill # out @context response w/ schema(s) (or link to schema) if format == 'html': @@ -368,7 +456,9 @@ class TransformErrorResponse(HTTPServerError): rss_limit = 256 * (1024 ** 2) # MB - reload_process = True if registry.settings.get('reload_templates', False) else lambda proc: psutil.Process(proc.pid).memory_info().rss > rss_limit + reload_process = (True + if registry.settings.get('reload_templates', False) + else lambda proc: psutil.Process(proc.pid).memory_info().rss > rss_limit) # TransformWorker inits and manages a subprocess # it re-uses the subprocess so interestingly data in JS global variables From d64a698db057e7ddeeed21d7aed0414c6452b906 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 06:09:13 -0500 Subject: [PATCH 27/35] Port test_renderers.py from cgap-portal. --- src/encoded/tests/test_renderers.py | 117 ++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 src/encoded/tests/test_renderers.py diff --git a/src/encoded/tests/test_renderers.py b/src/encoded/tests/test_renderers.py new file mode 100644 index 0000000000..baca692fb9 --- /dev/null +++ b/src/encoded/tests/test_renderers.py @@ -0,0 +1,117 @@ +from dcicutils.qa_utils import MockResponse +from unittest import mock +from pyramid.testing import DummyRequest +from .. import renderers +from ..renderers import ( + best_mime_type, should_transform, MIME_TYPES_SUPPORTED, MIME_TYPE_DEFAULT, + MIME_TYPE_JSON, MIME_TYPE_HTML, MIME_TYPE_LD_JSON, +) + + +DEFAULT_SHOULD_TRANSFORM = (MIME_TYPE_DEFAULT == MIME_TYPE_HTML) + + +class DummyResponse(MockResponse): + + def __init__(self, content_type=None, status_code: int = 200, json=None, content=None, url=None, + params=None): + self.params = {} if params is None else params + self.content_type = content_type + super().__init__(status_code=status_code, json=json, content=content, url=url) + + +def test_mime_variables(): + + # Really these don't need testing but it's useful visually to remind us of their values here. + assert MIME_TYPE_HTML == 'text/html' + assert MIME_TYPE_JSON == 'application/json' + assert MIME_TYPE_LD_JSON == 'application/ld+json' + assert MIME_TYPES_SUPPORTED == [MIME_TYPE_JSON, MIME_TYPE_HTML, MIME_TYPE_LD_JSON] + assert MIME_TYPE_DEFAULT == MIME_TYPE_JSON + + +VARIOUS_MIME_TYPES_TO_TEST = ['*/*', 'text/html', 'application/json', 'application/ld+json', 'text/xml', 'who/cares'] + + +def test_best_mime_type(the_constant_answer=MIME_TYPE_DEFAULT): + + for requested_mime_type in VARIOUS_MIME_TYPES_TO_TEST: + req = DummyRequest(headers={'Accept': requested_mime_type}) + assert best_mime_type(req, 'legacy') == the_constant_answer + assert best_mime_type(req, 'modern') == the_constant_answer + req = DummyRequest(headers={}) # The Accept header in the request just isn't being consulted + assert best_mime_type(req, 'modern') == the_constant_answer + assert best_mime_type(req, 'modern') == the_constant_answer + + +def test_best_mime_type_traditional(): + + test_best_mime_type('application/json') + + +TYPICAL_URLS = [ + 'http://whatever/foo', + 'http://whatever/foo/', + 'http://whatever/foo.json', + 'http://whatever/foo.html', +] + +ALLOWED_FRAMES_OR_NONE = ['raw', 'page', 'embedded', 'object', 'bad', None] + +SOME_HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD'] + +ALLOWED_FORMATS_OR_NONE = ['json', 'html', None] + + +def test_should_transform(): + + for method in SOME_HTTP_METHODS: + for _format in ALLOWED_FORMATS_OR_NONE: + for requested_mime_type in VARIOUS_MIME_TYPES_TO_TEST: + for response_content_type in VARIOUS_MIME_TYPES_TO_TEST: + for frame in [None] + ALLOWED_FRAMES_OR_NONE: + for url in TYPICAL_URLS: + + params = {} + if frame is not None: + params['frame'] = frame + if _format is not None: + params['format'] = _format + + req = DummyRequest(headers={'Accept': requested_mime_type}, + method=method, + url=url, + params=params) + resp = DummyResponse(content_type=response_content_type, url=url) + + print("method=", method, + "format=", _format, + "params=", params, + "requested=", requested_mime_type, + "response_content_type=", response_content_type, + "frame=", frame, + ) + + if req.method not in ('GET', 'HEAD'): + assert not should_transform(req, resp) + elif resp.content_type != 'application/json': + # If the response MIME type is not application/json, + # it just can't be transformed at all. + assert not should_transform(req, resp) + elif params.get("frame", "page") != 'page': + assert not should_transform(req, resp) + elif _format is not None: + assert should_transform(req, resp) is (_format == 'html') + else: + assert should_transform(req, resp) is DEFAULT_SHOULD_TRANSFORM + + +def test_should_transform_without_best_mime_type(): + + with mock.patch.object(renderers, "best_mime_type") as mock_best_mime_type: + + # Demonstrate that best_mime_type(...) could be replaced by MIME_TYPES_SUPPORTED[0] + mock_best_mime_type.return_value = MIME_TYPES_SUPPORTED[0] + + test_should_transform() + From d4e3e8382b82c9549cfcbe555ef95968508f894c Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 06:09:47 -0500 Subject: [PATCH 28/35] PEP8 --- src/encoded/authentication.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/encoded/authentication.py b/src/encoded/authentication.py index 8ee4464661..5d837383cb 100644 --- a/src/encoded/authentication.py +++ b/src/encoded/authentication.py @@ -440,8 +440,7 @@ def impersonate_user(context, request): } id_token = jwt.encode(jwt_contents, b64decode(auth0_secret, '-_'), - algorithm=JWT_ENCODING_ALGORITHM - ) + algorithm=JWT_ENCODING_ALGORITHM) user_properties['id_token'] = id_token.decode('utf-8') return user_properties From bff4eca82b90a7fcf840e58d753fd1393f53099d Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 06:10:44 -0500 Subject: [PATCH 29/35] Use dcicutils.misc_utils.TestApp in src/encoded/commands/load_access_keys.py --- src/encoded/commands/load_access_keys.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/encoded/commands/load_access_keys.py b/src/encoded/commands/load_access_keys.py index bd41c9e380..eced23c603 100644 --- a/src/encoded/commands/load_access_keys.py +++ b/src/encoded/commands/load_access_keys.py @@ -5,7 +5,8 @@ import os import boto3 from pyramid.paster import get_app -from webtest import TestApp, AppError +from webtest import AppError +from dcicutils.misc_utils import TestApp from dcicutils.beanstalk_utils import get_beanstalk_real_url log = structlog.getLogger(__name__) From c0c1d85578e7a3803efb06ada00a70b3ae00bb14 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 06:11:58 -0500 Subject: [PATCH 30/35] Add a use of set(...) in purge_item_type.py to remove duplicates. Change the way commits work to be more incremental. --- src/encoded/commands/purge_item_type.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/encoded/commands/purge_item_type.py b/src/encoded/commands/purge_item_type.py index 546737e9dc..0d6cb3a5d1 100644 --- a/src/encoded/commands/purge_item_type.py +++ b/src/encoded/commands/purge_item_type.py @@ -43,18 +43,19 @@ def purge_item_type_from_storage(app, item_types, prod=False): # purge uuids directly from PickStorage, ignoring status=deleted checks configure_dbsession(app) - uuids_to_purge = get_uuids_for_types(app.registry, item_types) + # The use of set(...) is to de-duplicate. -kmp 28-Jan-2021 + uuids_to_purge = set(get_uuids_for_types(app.registry, item_types)) pstorage = app.registry[STORAGE] for uuid in uuids_to_purge: try: pstorage.purge_uuid(uuid) + transaction.commit() except Exception as e: # XXX: handle recoverable exceptions? logger.error('Encountered exception purging an item type (uuid: %s) from the DB: %s' % (uuid, e)) transaction.abort() return False - transaction.commit() return True @@ -76,3 +77,7 @@ def main(): app = get_app(args.config_uri, args.app_name) sys.exit(purge_item_type_from_storage(app, [args.item_type], prod=args.prod)) + + +if __name__ == '__main__': + main() From 174e1910d28bc6e3086f6561be899195835f6ff0 Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 06:12:49 -0500 Subject: [PATCH 31/35] Backport a TODO comment about {'use_ssl': True} in src/encoded/commands/configure_kibana_index.py --- src/encoded/commands/configure_kibana_index.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/encoded/commands/configure_kibana_index.py b/src/encoded/commands/configure_kibana_index.py index 4ef6346949..69b75b5219 100644 --- a/src/encoded/commands/configure_kibana_index.py +++ b/src/encoded/commands/configure_kibana_index.py @@ -40,6 +40,8 @@ def main(): use_es = get_health_page(ff_env=args.env)['elasticsearch'] # create client and ensure kibana index exists + # TODO: CGAP does this differently. If port 443 is used, Will says use_ssl is implied and can be omitted here. + # Need to verify that and then make both systems agree here. -kmp 16-Feb-2021 es_options = {'use_ssl': True} client = create_es_client(use_es, use_aws_auth=True, **es_options) if not client.indices.exists(index='.kibana'): From 4ac2485b0e99ad404bcb5c8e18acddf293cf23bd Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 07:15:12 -0500 Subject: [PATCH 32/35] Rename test_utils.py to test_util.py --- src/encoded/tests/test_util.py | 94 ++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/encoded/tests/test_util.py diff --git a/src/encoded/tests/test_util.py b/src/encoded/tests/test_util.py new file mode 100644 index 0000000000..4c7fbca5da --- /dev/null +++ b/src/encoded/tests/test_util.py @@ -0,0 +1,94 @@ +import datetime +import pytest +import re +from pyramid.httpexceptions import HTTPForbidden + +from ..util import (compute_set_difference_one, find_other_in_pair, delay_rerun, utc_today_str, + customized_delay_rerun, check_user_is_logged_in) + + +pytestmark = pytest.mark.working + + +def test_compute_set_difference_one(): + """ Tests that our set difference utility function behaves correctly under various cases """ + s1 = {1, 2, 3, 4} + s2 = {1, 2, 3} + assert compute_set_difference_one(s1, s2) == 4 + s1 = {1, 2, 3, 4} + s2 = {1, 2, 3, 4} + with pytest.raises(StopIteration): + compute_set_difference_one(s1, s2) + with pytest.raises(StopIteration): + compute_set_difference_one(s2, s1) + s1 = {1, 2, 3, 4, 5, 6} + s2 = {1, 2, 3, 4} + with pytest.raises(RuntimeError): + compute_set_difference_one(s1, s2) + with pytest.raises(StopIteration): + compute_set_difference_one(s2, s1) + s1 = {1, 2} + s2 = {1} + assert compute_set_difference_one(s1, s2) == 2 + + +def test_find_other_in_pair(): + """ Tests the wrapper for the above function """ + assert find_other_in_pair(1, [1, 2]) == 2 + assert find_other_in_pair(2, [1, 2]) == 1 + lst = [1, 2, 3] + val = [1, 2] + with pytest.raises(TypeError): + find_other_in_pair(val, lst) # val is 'not single valued' + val = 1 + with pytest.raises(TypeError): + find_other_in_pair(val, None) # no pair to compare to + with pytest.raises(RuntimeError): # too many results + find_other_in_pair(None, lst) + + +DELAY_FUZZ_SECONDS = 0.1 + + +def test_delay_rerun(): + expected_delay = 1.0 + t0 = datetime.datetime.now() + delay_rerun() + t1 = datetime.datetime.now() + assert (t1 - t0).total_seconds() > expected_delay + assert (t1 - t0).total_seconds() < expected_delay + DELAY_FUZZ_SECONDS + + +def test_customize_delay_rerun(): + custom_delay = 0.5 + half_delay_rerun = customized_delay_rerun(sleep_seconds=custom_delay) + t0 = datetime.datetime.now() + half_delay_rerun() + t1 = datetime.datetime.now() + assert (t1 - t0).total_seconds() > custom_delay + assert (t1 - t0).total_seconds() < custom_delay + DELAY_FUZZ_SECONDS + + +def test_utc_today_str(): + pattern = "[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]" + actual = utc_today_str() + assert re.match(pattern, actual), "utc_today_str() result %s did not match format: %s" % (actual, pattern) + + +@pytest.mark.parametrize('principals, allow', [ + (['role1', 'role2'], False), + (['role1', 'userid.uuid'], True), + (['role1', 'group.admin'], True), + (['system.Everyone'], False) +]) +def test_check_user_is_logged_in(principals, allow): + """ Simple test that ensures the logged in check is working as expected """ + class MockRequest: + def __init__(self, principals): + self.effective_principals = principals + req = MockRequest(principals) + if allow: + check_user_is_logged_in(req) + else: + with pytest.raises(HTTPForbidden): + check_user_is_logged_in(req) From d667276b9e0e2942f284bb56355008f0df0ee69c Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 07:29:03 -0500 Subject: [PATCH 33/35] Delete test_utils.py because it was renamed to test_util.py --- src/encoded/tests/test_utils.py | 94 --------------------------------- 1 file changed, 94 deletions(-) delete mode 100644 src/encoded/tests/test_utils.py diff --git a/src/encoded/tests/test_utils.py b/src/encoded/tests/test_utils.py deleted file mode 100644 index 4c7fbca5da..0000000000 --- a/src/encoded/tests/test_utils.py +++ /dev/null @@ -1,94 +0,0 @@ -import datetime -import pytest -import re -from pyramid.httpexceptions import HTTPForbidden - -from ..util import (compute_set_difference_one, find_other_in_pair, delay_rerun, utc_today_str, - customized_delay_rerun, check_user_is_logged_in) - - -pytestmark = pytest.mark.working - - -def test_compute_set_difference_one(): - """ Tests that our set difference utility function behaves correctly under various cases """ - s1 = {1, 2, 3, 4} - s2 = {1, 2, 3} - assert compute_set_difference_one(s1, s2) == 4 - s1 = {1, 2, 3, 4} - s2 = {1, 2, 3, 4} - with pytest.raises(StopIteration): - compute_set_difference_one(s1, s2) - with pytest.raises(StopIteration): - compute_set_difference_one(s2, s1) - s1 = {1, 2, 3, 4, 5, 6} - s2 = {1, 2, 3, 4} - with pytest.raises(RuntimeError): - compute_set_difference_one(s1, s2) - with pytest.raises(StopIteration): - compute_set_difference_one(s2, s1) - s1 = {1, 2} - s2 = {1} - assert compute_set_difference_one(s1, s2) == 2 - - -def test_find_other_in_pair(): - """ Tests the wrapper for the above function """ - assert find_other_in_pair(1, [1, 2]) == 2 - assert find_other_in_pair(2, [1, 2]) == 1 - lst = [1, 2, 3] - val = [1, 2] - with pytest.raises(TypeError): - find_other_in_pair(val, lst) # val is 'not single valued' - val = 1 - with pytest.raises(TypeError): - find_other_in_pair(val, None) # no pair to compare to - with pytest.raises(RuntimeError): # too many results - find_other_in_pair(None, lst) - - -DELAY_FUZZ_SECONDS = 0.1 - - -def test_delay_rerun(): - expected_delay = 1.0 - t0 = datetime.datetime.now() - delay_rerun() - t1 = datetime.datetime.now() - assert (t1 - t0).total_seconds() > expected_delay - assert (t1 - t0).total_seconds() < expected_delay + DELAY_FUZZ_SECONDS - - -def test_customize_delay_rerun(): - custom_delay = 0.5 - half_delay_rerun = customized_delay_rerun(sleep_seconds=custom_delay) - t0 = datetime.datetime.now() - half_delay_rerun() - t1 = datetime.datetime.now() - assert (t1 - t0).total_seconds() > custom_delay - assert (t1 - t0).total_seconds() < custom_delay + DELAY_FUZZ_SECONDS - - -def test_utc_today_str(): - pattern = "[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]" - actual = utc_today_str() - assert re.match(pattern, actual), "utc_today_str() result %s did not match format: %s" % (actual, pattern) - - -@pytest.mark.parametrize('principals, allow', [ - (['role1', 'role2'], False), - (['role1', 'userid.uuid'], True), - (['role1', 'group.admin'], True), - (['system.Everyone'], False) -]) -def test_check_user_is_logged_in(principals, allow): - """ Simple test that ensures the logged in check is working as expected """ - class MockRequest: - def __init__(self, principals): - self.effective_principals = principals - req = MockRequest(principals) - if allow: - check_user_is_logged_in(req) - else: - with pytest.raises(HTTPForbidden): - check_user_is_logged_in(req) From 659ab9f870c0e9db82f7954574bdca38ebd2542e Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Wed, 17 Feb 2021 07:31:51 -0500 Subject: [PATCH 34/35] Update lock file. --- poetry.lock | 568 ++++++++++++++++++++++++++-------------------------- 1 file changed, 284 insertions(+), 284 deletions(-) diff --git a/poetry.lock b/poetry.lock index e93d1ca4f7..b236570abb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -58,11 +58,11 @@ description = "Universal Command Line Environment for AWS." name = "awscli" optional = false python-versions = ">= 2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -version = "1.19.8" +version = "1.19.9" [package.dependencies] PyYAML = ">=3.10,<5.4" -botocore = "1.20.8" +botocore = "1.20.9" colorama = ">=0.2.5,<0.4.4" docutils = ">=0.10,<0.16" rsa = ">=3.1.2,<=4.5.0" @@ -107,20 +107,20 @@ description = "The AWS SDK for Python" name = "boto3" optional = false python-versions = ">= 2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -version = "1.17.8" +version = "1.17.9" [package.dependencies] -botocore = ">=1.20.8,<1.21.0" +botocore = ">=1.20.9,<1.21.0" jmespath = ">=0.7.1,<1.0.0" s3transfer = ">=0.3.0,<0.4.0" [[package]] category = "dev" -description = "Type annotations for boto3 1.17.8, generated by mypy-boto3-buider 4.4.0" +description = "Type annotations for boto3 1.17.9, generated by mypy-boto3-buider 4.4.0" name = "boto3-stubs" optional = false python-versions = ">=3.6" -version = "1.17.8.0" +version = "1.17.9.0" [package.dependencies] [package.dependencies.typing-extensions] @@ -128,266 +128,266 @@ python = "<3.8" version = "*" [package.extras] -accessanalyzer = ["mypy-boto3-accessanalyzer (1.17.8.0)"] -acm = ["mypy-boto3-acm (1.17.8.0)"] -acm-pca = ["mypy-boto3-acm-pca (1.17.8.0)"] -alexaforbusiness = ["mypy-boto3-alexaforbusiness (1.17.8.0)"] -all = ["mypy-boto3-accessanalyzer (1.17.8.0)", "mypy-boto3-acm (1.17.8.0)", "mypy-boto3-acm-pca (1.17.8.0)", "mypy-boto3-alexaforbusiness (1.17.8.0)", "mypy-boto3-amp (1.17.8.0)", "mypy-boto3-amplify (1.17.8.0)", "mypy-boto3-amplifybackend (1.17.8.0)", "mypy-boto3-apigateway (1.17.8.0)", "mypy-boto3-apigatewaymanagementapi (1.17.8.0)", "mypy-boto3-apigatewayv2 (1.17.8.0)", "mypy-boto3-appconfig (1.17.8.0)", "mypy-boto3-appflow (1.17.8.0)", "mypy-boto3-appintegrations (1.17.8.0)", "mypy-boto3-application-autoscaling (1.17.8.0)", "mypy-boto3-application-insights (1.17.8.0)", "mypy-boto3-appmesh (1.17.8.0)", "mypy-boto3-appstream (1.17.8.0)", "mypy-boto3-appsync (1.17.8.0)", "mypy-boto3-athena (1.17.8.0)", "mypy-boto3-auditmanager (1.17.8.0)", "mypy-boto3-autoscaling (1.17.8.0)", "mypy-boto3-autoscaling-plans (1.17.8.0)", "mypy-boto3-backup (1.17.8.0)", "mypy-boto3-batch (1.17.8.0)", "mypy-boto3-braket (1.17.8.0)", "mypy-boto3-budgets (1.17.8.0)", "mypy-boto3-ce (1.17.8.0)", "mypy-boto3-chime (1.17.8.0)", "mypy-boto3-cloud9 (1.17.8.0)", "mypy-boto3-clouddirectory (1.17.8.0)", "mypy-boto3-cloudformation (1.17.8.0)", "mypy-boto3-cloudfront (1.17.8.0)", "mypy-boto3-cloudhsm (1.17.8.0)", "mypy-boto3-cloudhsmv2 (1.17.8.0)", "mypy-boto3-cloudsearch (1.17.8.0)", "mypy-boto3-cloudsearchdomain (1.17.8.0)", "mypy-boto3-cloudtrail (1.17.8.0)", "mypy-boto3-cloudwatch (1.17.8.0)", "mypy-boto3-codeartifact (1.17.8.0)", "mypy-boto3-codebuild (1.17.8.0)", "mypy-boto3-codecommit (1.17.8.0)", "mypy-boto3-codedeploy (1.17.8.0)", "mypy-boto3-codeguru-reviewer (1.17.8.0)", "mypy-boto3-codeguruprofiler (1.17.8.0)", "mypy-boto3-codepipeline (1.17.8.0)", "mypy-boto3-codestar (1.17.8.0)", "mypy-boto3-codestar-connections (1.17.8.0)", "mypy-boto3-codestar-notifications (1.17.8.0)", "mypy-boto3-cognito-identity (1.17.8.0)", "mypy-boto3-cognito-idp (1.17.8.0)", "mypy-boto3-cognito-sync (1.17.8.0)", "mypy-boto3-comprehend (1.17.8.0)", "mypy-boto3-comprehendmedical (1.17.8.0)", "mypy-boto3-compute-optimizer (1.17.8.0)", "mypy-boto3-config (1.17.8.0)", "mypy-boto3-connect (1.17.8.0)", "mypy-boto3-connect-contact-lens (1.17.8.0)", "mypy-boto3-connectparticipant (1.17.8.0)", "mypy-boto3-cur (1.17.8.0)", "mypy-boto3-customer-profiles (1.17.8.0)", "mypy-boto3-databrew (1.17.8.0)", "mypy-boto3-dataexchange (1.17.8.0)", "mypy-boto3-datapipeline (1.17.8.0)", "mypy-boto3-datasync (1.17.8.0)", "mypy-boto3-dax (1.17.8.0)", "mypy-boto3-detective (1.17.8.0)", "mypy-boto3-devicefarm (1.17.8.0)", "mypy-boto3-devops-guru (1.17.8.0)", "mypy-boto3-directconnect (1.17.8.0)", "mypy-boto3-discovery (1.17.8.0)", "mypy-boto3-dlm (1.17.8.0)", "mypy-boto3-dms (1.17.8.0)", "mypy-boto3-docdb (1.17.8.0)", "mypy-boto3-ds (1.17.8.0)", "mypy-boto3-dynamodb (1.17.8.0)", "mypy-boto3-dynamodbstreams (1.17.8.0)", "mypy-boto3-ebs (1.17.8.0)", "mypy-boto3-ec2 (1.17.8.0)", "mypy-boto3-ec2-instance-connect (1.17.8.0)", "mypy-boto3-ecr (1.17.8.0)", "mypy-boto3-ecr-public (1.17.8.0)", "mypy-boto3-ecs (1.17.8.0)", "mypy-boto3-efs (1.17.8.0)", "mypy-boto3-eks (1.17.8.0)", "mypy-boto3-elastic-inference (1.17.8.0)", "mypy-boto3-elasticache (1.17.8.0)", "mypy-boto3-elasticbeanstalk (1.17.8.0)", "mypy-boto3-elastictranscoder (1.17.8.0)", "mypy-boto3-elb (1.17.8.0)", "mypy-boto3-elbv2 (1.17.8.0)", "mypy-boto3-emr (1.17.8.0)", "mypy-boto3-emr-containers (1.17.8.0)", "mypy-boto3-es (1.17.8.0)", "mypy-boto3-events (1.17.8.0)", "mypy-boto3-firehose (1.17.8.0)", "mypy-boto3-fms (1.17.8.0)", "mypy-boto3-forecast (1.17.8.0)", "mypy-boto3-forecastquery (1.17.8.0)", "mypy-boto3-frauddetector (1.17.8.0)", "mypy-boto3-fsx (1.17.8.0)", "mypy-boto3-gamelift (1.17.8.0)", "mypy-boto3-glacier (1.17.8.0)", "mypy-boto3-globalaccelerator (1.17.8.0)", "mypy-boto3-glue (1.17.8.0)", "mypy-boto3-greengrass (1.17.8.0)", "mypy-boto3-greengrassv2 (1.17.8.0)", "mypy-boto3-groundstation (1.17.8.0)", "mypy-boto3-guardduty (1.17.8.0)", "mypy-boto3-health (1.17.8.0)", "mypy-boto3-healthlake (1.17.8.0)", "mypy-boto3-honeycode (1.17.8.0)", "mypy-boto3-iam (1.17.8.0)", "mypy-boto3-identitystore (1.17.8.0)", "mypy-boto3-imagebuilder (1.17.8.0)", "mypy-boto3-importexport (1.17.8.0)", "mypy-boto3-inspector (1.17.8.0)", "mypy-boto3-iot (1.17.8.0)", "mypy-boto3-iot-data (1.17.8.0)", "mypy-boto3-iot-jobs-data (1.17.8.0)", "mypy-boto3-iot1click-devices (1.17.8.0)", "mypy-boto3-iot1click-projects (1.17.8.0)", "mypy-boto3-iotanalytics (1.17.8.0)", "mypy-boto3-iotdeviceadvisor (1.17.8.0)", "mypy-boto3-iotevents (1.17.8.0)", "mypy-boto3-iotevents-data (1.17.8.0)", "mypy-boto3-iotfleethub (1.17.8.0)", "mypy-boto3-iotsecuretunneling (1.17.8.0)", "mypy-boto3-iotsitewise (1.17.8.0)", "mypy-boto3-iotthingsgraph (1.17.8.0)", "mypy-boto3-iotwireless (1.17.8.0)", "mypy-boto3-ivs (1.17.8.0)", "mypy-boto3-kafka (1.17.8.0)", "mypy-boto3-kendra (1.17.8.0)", "mypy-boto3-kinesis (1.17.8.0)", "mypy-boto3-kinesis-video-archived-media (1.17.8.0)", "mypy-boto3-kinesis-video-media (1.17.8.0)", "mypy-boto3-kinesis-video-signaling (1.17.8.0)", "mypy-boto3-kinesisanalytics (1.17.8.0)", "mypy-boto3-kinesisanalyticsv2 (1.17.8.0)", "mypy-boto3-kinesisvideo (1.17.8.0)", "mypy-boto3-kms (1.17.8.0)", "mypy-boto3-lakeformation (1.17.8.0)", "mypy-boto3-lambda (1.17.8.0)", "mypy-boto3-lex-models (1.17.8.0)", "mypy-boto3-lex-runtime (1.17.8.0)", "mypy-boto3-lexv2-models (1.17.8.0)", "mypy-boto3-lexv2-runtime (1.17.8.0)", "mypy-boto3-license-manager (1.17.8.0)", "mypy-boto3-lightsail (1.17.8.0)", "mypy-boto3-location (1.17.8.0)", "mypy-boto3-logs (1.17.8.0)", "mypy-boto3-lookoutvision (1.17.8.0)", "mypy-boto3-machinelearning (1.17.8.0)", "mypy-boto3-macie (1.17.8.0)", "mypy-boto3-macie2 (1.17.8.0)", "mypy-boto3-managedblockchain (1.17.8.0)", "mypy-boto3-marketplace-catalog (1.17.8.0)", "mypy-boto3-marketplace-entitlement (1.17.8.0)", "mypy-boto3-marketplacecommerceanalytics (1.17.8.0)", "mypy-boto3-mediaconnect (1.17.8.0)", "mypy-boto3-mediaconvert (1.17.8.0)", "mypy-boto3-medialive (1.17.8.0)", "mypy-boto3-mediapackage (1.17.8.0)", "mypy-boto3-mediapackage-vod (1.17.8.0)", "mypy-boto3-mediastore (1.17.8.0)", "mypy-boto3-mediastore-data (1.17.8.0)", "mypy-boto3-mediatailor (1.17.8.0)", "mypy-boto3-meteringmarketplace (1.17.8.0)", "mypy-boto3-mgh (1.17.8.0)", "mypy-boto3-migrationhub-config (1.17.8.0)", "mypy-boto3-mobile (1.17.8.0)", "mypy-boto3-mq (1.17.8.0)", "mypy-boto3-mturk (1.17.8.0)", "mypy-boto3-mwaa (1.17.8.0)", "mypy-boto3-neptune (1.17.8.0)", "mypy-boto3-network-firewall (1.17.8.0)", "mypy-boto3-networkmanager (1.17.8.0)", "mypy-boto3-opsworks (1.17.8.0)", "mypy-boto3-opsworkscm (1.17.8.0)", "mypy-boto3-organizations (1.17.8.0)", "mypy-boto3-outposts (1.17.8.0)", "mypy-boto3-personalize (1.17.8.0)", "mypy-boto3-personalize-events (1.17.8.0)", "mypy-boto3-personalize-runtime (1.17.8.0)", "mypy-boto3-pi (1.17.8.0)", "mypy-boto3-pinpoint (1.17.8.0)", "mypy-boto3-pinpoint-email (1.17.8.0)", "mypy-boto3-pinpoint-sms-voice (1.17.8.0)", "mypy-boto3-polly (1.17.8.0)", "mypy-boto3-pricing (1.17.8.0)", "mypy-boto3-qldb (1.17.8.0)", "mypy-boto3-qldb-session (1.17.8.0)", "mypy-boto3-quicksight (1.17.8.0)", "mypy-boto3-ram (1.17.8.0)", "mypy-boto3-rds (1.17.8.0)", "mypy-boto3-rds-data (1.17.8.0)", "mypy-boto3-redshift (1.17.8.0)", "mypy-boto3-redshift-data (1.17.8.0)", "mypy-boto3-rekognition (1.17.8.0)", "mypy-boto3-resource-groups (1.17.8.0)", "mypy-boto3-resourcegroupstaggingapi (1.17.8.0)", "mypy-boto3-robomaker (1.17.8.0)", "mypy-boto3-route53 (1.17.8.0)", "mypy-boto3-route53domains (1.17.8.0)", "mypy-boto3-route53resolver (1.17.8.0)", "mypy-boto3-s3 (1.17.8.0)", "mypy-boto3-s3control (1.17.8.0)", "mypy-boto3-s3outposts (1.17.8.0)", "mypy-boto3-sagemaker (1.17.8.0)", "mypy-boto3-sagemaker-a2i-runtime (1.17.8.0)", "mypy-boto3-sagemaker-edge (1.17.8.0)", "mypy-boto3-sagemaker-featurestore-runtime (1.17.8.0)", "mypy-boto3-sagemaker-runtime (1.17.8.0)", "mypy-boto3-savingsplans (1.17.8.0)", "mypy-boto3-schemas (1.17.8.0)", "mypy-boto3-sdb (1.17.8.0)", "mypy-boto3-secretsmanager (1.17.8.0)", "mypy-boto3-securityhub (1.17.8.0)", "mypy-boto3-serverlessrepo (1.17.8.0)", "mypy-boto3-service-quotas (1.17.8.0)", "mypy-boto3-servicecatalog (1.17.8.0)", "mypy-boto3-servicecatalog-appregistry (1.17.8.0)", "mypy-boto3-servicediscovery (1.17.8.0)", "mypy-boto3-ses (1.17.8.0)", "mypy-boto3-sesv2 (1.17.8.0)", "mypy-boto3-shield (1.17.8.0)", "mypy-boto3-signer (1.17.8.0)", "mypy-boto3-sms (1.17.8.0)", "mypy-boto3-sms-voice (1.17.8.0)", "mypy-boto3-snowball (1.17.8.0)", "mypy-boto3-sns (1.17.8.0)", "mypy-boto3-sqs (1.17.8.0)", "mypy-boto3-ssm (1.17.8.0)", "mypy-boto3-sso (1.17.8.0)", "mypy-boto3-sso-admin (1.17.8.0)", "mypy-boto3-sso-oidc (1.17.8.0)", "mypy-boto3-stepfunctions (1.17.8.0)", "mypy-boto3-storagegateway (1.17.8.0)", "mypy-boto3-sts (1.17.8.0)", "mypy-boto3-support (1.17.8.0)", "mypy-boto3-swf (1.17.8.0)", "mypy-boto3-synthetics (1.17.8.0)", "mypy-boto3-textract (1.17.8.0)", "mypy-boto3-timestream-query (1.17.8.0)", "mypy-boto3-timestream-write (1.17.8.0)", "mypy-boto3-transcribe (1.17.8.0)", "mypy-boto3-transfer (1.17.8.0)", "mypy-boto3-translate (1.17.8.0)", "mypy-boto3-waf (1.17.8.0)", "mypy-boto3-waf-regional (1.17.8.0)", "mypy-boto3-wafv2 (1.17.8.0)", "mypy-boto3-wellarchitected (1.17.8.0)", "mypy-boto3-workdocs (1.17.8.0)", "mypy-boto3-worklink (1.17.8.0)", "mypy-boto3-workmail (1.17.8.0)", "mypy-boto3-workmailmessageflow (1.17.8.0)", "mypy-boto3-workspaces (1.17.8.0)", "mypy-boto3-xray (1.17.8.0)"] -amp = ["mypy-boto3-amp (1.17.8.0)"] -amplify = ["mypy-boto3-amplify (1.17.8.0)"] -amplifybackend = ["mypy-boto3-amplifybackend (1.17.8.0)"] -apigateway = ["mypy-boto3-apigateway (1.17.8.0)"] -apigatewaymanagementapi = ["mypy-boto3-apigatewaymanagementapi (1.17.8.0)"] -apigatewayv2 = ["mypy-boto3-apigatewayv2 (1.17.8.0)"] -appconfig = ["mypy-boto3-appconfig (1.17.8.0)"] -appflow = ["mypy-boto3-appflow (1.17.8.0)"] -appintegrations = ["mypy-boto3-appintegrations (1.17.8.0)"] -application-autoscaling = ["mypy-boto3-application-autoscaling (1.17.8.0)"] -application-insights = ["mypy-boto3-application-insights (1.17.8.0)"] -appmesh = ["mypy-boto3-appmesh (1.17.8.0)"] -appstream = ["mypy-boto3-appstream (1.17.8.0)"] -appsync = ["mypy-boto3-appsync (1.17.8.0)"] -athena = ["mypy-boto3-athena (1.17.8.0)"] -auditmanager = ["mypy-boto3-auditmanager (1.17.8.0)"] -autoscaling = ["mypy-boto3-autoscaling (1.17.8.0)"] -autoscaling-plans = ["mypy-boto3-autoscaling-plans (1.17.8.0)"] -backup = ["mypy-boto3-backup (1.17.8.0)"] -batch = ["mypy-boto3-batch (1.17.8.0)"] -braket = ["mypy-boto3-braket (1.17.8.0)"] -budgets = ["mypy-boto3-budgets (1.17.8.0)"] -ce = ["mypy-boto3-ce (1.17.8.0)"] -chime = ["mypy-boto3-chime (1.17.8.0)"] -cloud9 = ["mypy-boto3-cloud9 (1.17.8.0)"] -clouddirectory = ["mypy-boto3-clouddirectory (1.17.8.0)"] -cloudformation = ["mypy-boto3-cloudformation (1.17.8.0)"] -cloudfront = ["mypy-boto3-cloudfront (1.17.8.0)"] -cloudhsm = ["mypy-boto3-cloudhsm (1.17.8.0)"] -cloudhsmv2 = ["mypy-boto3-cloudhsmv2 (1.17.8.0)"] -cloudsearch = ["mypy-boto3-cloudsearch (1.17.8.0)"] -cloudsearchdomain = ["mypy-boto3-cloudsearchdomain (1.17.8.0)"] -cloudtrail = ["mypy-boto3-cloudtrail (1.17.8.0)"] -cloudwatch = ["mypy-boto3-cloudwatch (1.17.8.0)"] -codeartifact = ["mypy-boto3-codeartifact (1.17.8.0)"] -codebuild = ["mypy-boto3-codebuild (1.17.8.0)"] -codecommit = ["mypy-boto3-codecommit (1.17.8.0)"] -codedeploy = ["mypy-boto3-codedeploy (1.17.8.0)"] -codeguru-reviewer = ["mypy-boto3-codeguru-reviewer (1.17.8.0)"] -codeguruprofiler = ["mypy-boto3-codeguruprofiler (1.17.8.0)"] -codepipeline = ["mypy-boto3-codepipeline (1.17.8.0)"] -codestar = ["mypy-boto3-codestar (1.17.8.0)"] -codestar-connections = ["mypy-boto3-codestar-connections (1.17.8.0)"] -codestar-notifications = ["mypy-boto3-codestar-notifications (1.17.8.0)"] -cognito-identity = ["mypy-boto3-cognito-identity (1.17.8.0)"] -cognito-idp = ["mypy-boto3-cognito-idp (1.17.8.0)"] -cognito-sync = ["mypy-boto3-cognito-sync (1.17.8.0)"] -comprehend = ["mypy-boto3-comprehend (1.17.8.0)"] -comprehendmedical = ["mypy-boto3-comprehendmedical (1.17.8.0)"] -compute-optimizer = ["mypy-boto3-compute-optimizer (1.17.8.0)"] -config = ["mypy-boto3-config (1.17.8.0)"] -connect = ["mypy-boto3-connect (1.17.8.0)"] -connect-contact-lens = ["mypy-boto3-connect-contact-lens (1.17.8.0)"] -connectparticipant = ["mypy-boto3-connectparticipant (1.17.8.0)"] -cur = ["mypy-boto3-cur (1.17.8.0)"] -customer-profiles = ["mypy-boto3-customer-profiles (1.17.8.0)"] -databrew = ["mypy-boto3-databrew (1.17.8.0)"] -dataexchange = ["mypy-boto3-dataexchange (1.17.8.0)"] -datapipeline = ["mypy-boto3-datapipeline (1.17.8.0)"] -datasync = ["mypy-boto3-datasync (1.17.8.0)"] -dax = ["mypy-boto3-dax (1.17.8.0)"] -detective = ["mypy-boto3-detective (1.17.8.0)"] -devicefarm = ["mypy-boto3-devicefarm (1.17.8.0)"] -devops-guru = ["mypy-boto3-devops-guru (1.17.8.0)"] -directconnect = ["mypy-boto3-directconnect (1.17.8.0)"] -discovery = ["mypy-boto3-discovery (1.17.8.0)"] -dlm = ["mypy-boto3-dlm (1.17.8.0)"] -dms = ["mypy-boto3-dms (1.17.8.0)"] -docdb = ["mypy-boto3-docdb (1.17.8.0)"] -ds = ["mypy-boto3-ds (1.17.8.0)"] -dynamodb = ["mypy-boto3-dynamodb (1.17.8.0)"] -dynamodbstreams = ["mypy-boto3-dynamodbstreams (1.17.8.0)"] -ebs = ["mypy-boto3-ebs (1.17.8.0)"] -ec2 = ["mypy-boto3-ec2 (1.17.8.0)"] -ec2-instance-connect = ["mypy-boto3-ec2-instance-connect (1.17.8.0)"] -ecr = ["mypy-boto3-ecr (1.17.8.0)"] -ecr-public = ["mypy-boto3-ecr-public (1.17.8.0)"] -ecs = ["mypy-boto3-ecs (1.17.8.0)"] -efs = ["mypy-boto3-efs (1.17.8.0)"] -eks = ["mypy-boto3-eks (1.17.8.0)"] -elastic-inference = ["mypy-boto3-elastic-inference (1.17.8.0)"] -elasticache = ["mypy-boto3-elasticache (1.17.8.0)"] -elasticbeanstalk = ["mypy-boto3-elasticbeanstalk (1.17.8.0)"] -elastictranscoder = ["mypy-boto3-elastictranscoder (1.17.8.0)"] -elb = ["mypy-boto3-elb (1.17.8.0)"] -elbv2 = ["mypy-boto3-elbv2 (1.17.8.0)"] -emr = ["mypy-boto3-emr (1.17.8.0)"] -emr-containers = ["mypy-boto3-emr-containers (1.17.8.0)"] -es = ["mypy-boto3-es (1.17.8.0)"] -essential = ["mypy-boto3-cloudformation (1.17.8.0)", "mypy-boto3-dynamodb (1.17.8.0)", "mypy-boto3-ec2 (1.17.8.0)", "mypy-boto3-lambda (1.17.8.0)", "mypy-boto3-rds (1.17.8.0)", "mypy-boto3-s3 (1.17.8.0)", "mypy-boto3-sqs (1.17.8.0)"] -events = ["mypy-boto3-events (1.17.8.0)"] -firehose = ["mypy-boto3-firehose (1.17.8.0)"] -fms = ["mypy-boto3-fms (1.17.8.0)"] -forecast = ["mypy-boto3-forecast (1.17.8.0)"] -forecastquery = ["mypy-boto3-forecastquery (1.17.8.0)"] -frauddetector = ["mypy-boto3-frauddetector (1.17.8.0)"] -fsx = ["mypy-boto3-fsx (1.17.8.0)"] -gamelift = ["mypy-boto3-gamelift (1.17.8.0)"] -glacier = ["mypy-boto3-glacier (1.17.8.0)"] -globalaccelerator = ["mypy-boto3-globalaccelerator (1.17.8.0)"] -glue = ["mypy-boto3-glue (1.17.8.0)"] -greengrass = ["mypy-boto3-greengrass (1.17.8.0)"] -greengrassv2 = ["mypy-boto3-greengrassv2 (1.17.8.0)"] -groundstation = ["mypy-boto3-groundstation (1.17.8.0)"] -guardduty = ["mypy-boto3-guardduty (1.17.8.0)"] -health = ["mypy-boto3-health (1.17.8.0)"] -healthlake = ["mypy-boto3-healthlake (1.17.8.0)"] -honeycode = ["mypy-boto3-honeycode (1.17.8.0)"] -iam = ["mypy-boto3-iam (1.17.8.0)"] -identitystore = ["mypy-boto3-identitystore (1.17.8.0)"] -imagebuilder = ["mypy-boto3-imagebuilder (1.17.8.0)"] -importexport = ["mypy-boto3-importexport (1.17.8.0)"] -inspector = ["mypy-boto3-inspector (1.17.8.0)"] -iot = ["mypy-boto3-iot (1.17.8.0)"] -iot-data = ["mypy-boto3-iot-data (1.17.8.0)"] -iot-jobs-data = ["mypy-boto3-iot-jobs-data (1.17.8.0)"] -iot1click-devices = ["mypy-boto3-iot1click-devices (1.17.8.0)"] -iot1click-projects = ["mypy-boto3-iot1click-projects (1.17.8.0)"] -iotanalytics = ["mypy-boto3-iotanalytics (1.17.8.0)"] -iotdeviceadvisor = ["mypy-boto3-iotdeviceadvisor (1.17.8.0)"] -iotevents = ["mypy-boto3-iotevents (1.17.8.0)"] -iotevents-data = ["mypy-boto3-iotevents-data (1.17.8.0)"] -iotfleethub = ["mypy-boto3-iotfleethub (1.17.8.0)"] -iotsecuretunneling = ["mypy-boto3-iotsecuretunneling (1.17.8.0)"] -iotsitewise = ["mypy-boto3-iotsitewise (1.17.8.0)"] -iotthingsgraph = ["mypy-boto3-iotthingsgraph (1.17.8.0)"] -iotwireless = ["mypy-boto3-iotwireless (1.17.8.0)"] -ivs = ["mypy-boto3-ivs (1.17.8.0)"] -kafka = ["mypy-boto3-kafka (1.17.8.0)"] -kendra = ["mypy-boto3-kendra (1.17.8.0)"] -kinesis = ["mypy-boto3-kinesis (1.17.8.0)"] -kinesis-video-archived-media = ["mypy-boto3-kinesis-video-archived-media (1.17.8.0)"] -kinesis-video-media = ["mypy-boto3-kinesis-video-media (1.17.8.0)"] -kinesis-video-signaling = ["mypy-boto3-kinesis-video-signaling (1.17.8.0)"] -kinesisanalytics = ["mypy-boto3-kinesisanalytics (1.17.8.0)"] -kinesisanalyticsv2 = ["mypy-boto3-kinesisanalyticsv2 (1.17.8.0)"] -kinesisvideo = ["mypy-boto3-kinesisvideo (1.17.8.0)"] -kms = ["mypy-boto3-kms (1.17.8.0)"] -lakeformation = ["mypy-boto3-lakeformation (1.17.8.0)"] -lambda = ["mypy-boto3-lambda (1.17.8.0)"] -lex-models = ["mypy-boto3-lex-models (1.17.8.0)"] -lex-runtime = ["mypy-boto3-lex-runtime (1.17.8.0)"] -lexv2-models = ["mypy-boto3-lexv2-models (1.17.8.0)"] -lexv2-runtime = ["mypy-boto3-lexv2-runtime (1.17.8.0)"] -license-manager = ["mypy-boto3-license-manager (1.17.8.0)"] -lightsail = ["mypy-boto3-lightsail (1.17.8.0)"] -location = ["mypy-boto3-location (1.17.8.0)"] -logs = ["mypy-boto3-logs (1.17.8.0)"] -lookoutvision = ["mypy-boto3-lookoutvision (1.17.8.0)"] -machinelearning = ["mypy-boto3-machinelearning (1.17.8.0)"] -macie = ["mypy-boto3-macie (1.17.8.0)"] -macie2 = ["mypy-boto3-macie2 (1.17.8.0)"] -managedblockchain = ["mypy-boto3-managedblockchain (1.17.8.0)"] -marketplace-catalog = ["mypy-boto3-marketplace-catalog (1.17.8.0)"] -marketplace-entitlement = ["mypy-boto3-marketplace-entitlement (1.17.8.0)"] -marketplacecommerceanalytics = ["mypy-boto3-marketplacecommerceanalytics (1.17.8.0)"] -mediaconnect = ["mypy-boto3-mediaconnect (1.17.8.0)"] -mediaconvert = ["mypy-boto3-mediaconvert (1.17.8.0)"] -medialive = ["mypy-boto3-medialive (1.17.8.0)"] -mediapackage = ["mypy-boto3-mediapackage (1.17.8.0)"] -mediapackage-vod = ["mypy-boto3-mediapackage-vod (1.17.8.0)"] -mediastore = ["mypy-boto3-mediastore (1.17.8.0)"] -mediastore-data = ["mypy-boto3-mediastore-data (1.17.8.0)"] -mediatailor = ["mypy-boto3-mediatailor (1.17.8.0)"] -meteringmarketplace = ["mypy-boto3-meteringmarketplace (1.17.8.0)"] -mgh = ["mypy-boto3-mgh (1.17.8.0)"] -migrationhub-config = ["mypy-boto3-migrationhub-config (1.17.8.0)"] -mobile = ["mypy-boto3-mobile (1.17.8.0)"] -mq = ["mypy-boto3-mq (1.17.8.0)"] -mturk = ["mypy-boto3-mturk (1.17.8.0)"] -mwaa = ["mypy-boto3-mwaa (1.17.8.0)"] -neptune = ["mypy-boto3-neptune (1.17.8.0)"] -network-firewall = ["mypy-boto3-network-firewall (1.17.8.0)"] -networkmanager = ["mypy-boto3-networkmanager (1.17.8.0)"] -opsworks = ["mypy-boto3-opsworks (1.17.8.0)"] -opsworkscm = ["mypy-boto3-opsworkscm (1.17.8.0)"] -organizations = ["mypy-boto3-organizations (1.17.8.0)"] -outposts = ["mypy-boto3-outposts (1.17.8.0)"] -personalize = ["mypy-boto3-personalize (1.17.8.0)"] -personalize-events = ["mypy-boto3-personalize-events (1.17.8.0)"] -personalize-runtime = ["mypy-boto3-personalize-runtime (1.17.8.0)"] -pi = ["mypy-boto3-pi (1.17.8.0)"] -pinpoint = ["mypy-boto3-pinpoint (1.17.8.0)"] -pinpoint-email = ["mypy-boto3-pinpoint-email (1.17.8.0)"] -pinpoint-sms-voice = ["mypy-boto3-pinpoint-sms-voice (1.17.8.0)"] -polly = ["mypy-boto3-polly (1.17.8.0)"] -pricing = ["mypy-boto3-pricing (1.17.8.0)"] -qldb = ["mypy-boto3-qldb (1.17.8.0)"] -qldb-session = ["mypy-boto3-qldb-session (1.17.8.0)"] -quicksight = ["mypy-boto3-quicksight (1.17.8.0)"] -ram = ["mypy-boto3-ram (1.17.8.0)"] -rds = ["mypy-boto3-rds (1.17.8.0)"] -rds-data = ["mypy-boto3-rds-data (1.17.8.0)"] -redshift = ["mypy-boto3-redshift (1.17.8.0)"] -redshift-data = ["mypy-boto3-redshift-data (1.17.8.0)"] -rekognition = ["mypy-boto3-rekognition (1.17.8.0)"] -resource-groups = ["mypy-boto3-resource-groups (1.17.8.0)"] -resourcegroupstaggingapi = ["mypy-boto3-resourcegroupstaggingapi (1.17.8.0)"] -robomaker = ["mypy-boto3-robomaker (1.17.8.0)"] -route53 = ["mypy-boto3-route53 (1.17.8.0)"] -route53domains = ["mypy-boto3-route53domains (1.17.8.0)"] -route53resolver = ["mypy-boto3-route53resolver (1.17.8.0)"] -s3 = ["mypy-boto3-s3 (1.17.8.0)"] -s3control = ["mypy-boto3-s3control (1.17.8.0)"] -s3outposts = ["mypy-boto3-s3outposts (1.17.8.0)"] -sagemaker = ["mypy-boto3-sagemaker (1.17.8.0)"] -sagemaker-a2i-runtime = ["mypy-boto3-sagemaker-a2i-runtime (1.17.8.0)"] -sagemaker-edge = ["mypy-boto3-sagemaker-edge (1.17.8.0)"] -sagemaker-featurestore-runtime = ["mypy-boto3-sagemaker-featurestore-runtime (1.17.8.0)"] -sagemaker-runtime = ["mypy-boto3-sagemaker-runtime (1.17.8.0)"] -savingsplans = ["mypy-boto3-savingsplans (1.17.8.0)"] -schemas = ["mypy-boto3-schemas (1.17.8.0)"] -sdb = ["mypy-boto3-sdb (1.17.8.0)"] -secretsmanager = ["mypy-boto3-secretsmanager (1.17.8.0)"] -securityhub = ["mypy-boto3-securityhub (1.17.8.0)"] -serverlessrepo = ["mypy-boto3-serverlessrepo (1.17.8.0)"] -service-quotas = ["mypy-boto3-service-quotas (1.17.8.0)"] -servicecatalog = ["mypy-boto3-servicecatalog (1.17.8.0)"] -servicecatalog-appregistry = ["mypy-boto3-servicecatalog-appregistry (1.17.8.0)"] -servicediscovery = ["mypy-boto3-servicediscovery (1.17.8.0)"] -ses = ["mypy-boto3-ses (1.17.8.0)"] -sesv2 = ["mypy-boto3-sesv2 (1.17.8.0)"] -shield = ["mypy-boto3-shield (1.17.8.0)"] -signer = ["mypy-boto3-signer (1.17.8.0)"] -sms = ["mypy-boto3-sms (1.17.8.0)"] -sms-voice = ["mypy-boto3-sms-voice (1.17.8.0)"] -snowball = ["mypy-boto3-snowball (1.17.8.0)"] -sns = ["mypy-boto3-sns (1.17.8.0)"] -sqs = ["mypy-boto3-sqs (1.17.8.0)"] -ssm = ["mypy-boto3-ssm (1.17.8.0)"] -sso = ["mypy-boto3-sso (1.17.8.0)"] -sso-admin = ["mypy-boto3-sso-admin (1.17.8.0)"] -sso-oidc = ["mypy-boto3-sso-oidc (1.17.8.0)"] -stepfunctions = ["mypy-boto3-stepfunctions (1.17.8.0)"] -storagegateway = ["mypy-boto3-storagegateway (1.17.8.0)"] -sts = ["mypy-boto3-sts (1.17.8.0)"] -support = ["mypy-boto3-support (1.17.8.0)"] -swf = ["mypy-boto3-swf (1.17.8.0)"] -synthetics = ["mypy-boto3-synthetics (1.17.8.0)"] -textract = ["mypy-boto3-textract (1.17.8.0)"] -timestream-query = ["mypy-boto3-timestream-query (1.17.8.0)"] -timestream-write = ["mypy-boto3-timestream-write (1.17.8.0)"] -transcribe = ["mypy-boto3-transcribe (1.17.8.0)"] -transfer = ["mypy-boto3-transfer (1.17.8.0)"] -translate = ["mypy-boto3-translate (1.17.8.0)"] -waf = ["mypy-boto3-waf (1.17.8.0)"] -waf-regional = ["mypy-boto3-waf-regional (1.17.8.0)"] -wafv2 = ["mypy-boto3-wafv2 (1.17.8.0)"] -wellarchitected = ["mypy-boto3-wellarchitected (1.17.8.0)"] -workdocs = ["mypy-boto3-workdocs (1.17.8.0)"] -worklink = ["mypy-boto3-worklink (1.17.8.0)"] -workmail = ["mypy-boto3-workmail (1.17.8.0)"] -workmailmessageflow = ["mypy-boto3-workmailmessageflow (1.17.8.0)"] -workspaces = ["mypy-boto3-workspaces (1.17.8.0)"] -xray = ["mypy-boto3-xray (1.17.8.0)"] +accessanalyzer = ["mypy-boto3-accessanalyzer (1.17.9.0)"] +acm = ["mypy-boto3-acm (1.17.9.0)"] +acm-pca = ["mypy-boto3-acm-pca (1.17.9.0)"] +alexaforbusiness = ["mypy-boto3-alexaforbusiness (1.17.9.0)"] +all = ["mypy-boto3-accessanalyzer (1.17.9.0)", "mypy-boto3-acm (1.17.9.0)", "mypy-boto3-acm-pca (1.17.9.0)", "mypy-boto3-alexaforbusiness (1.17.9.0)", "mypy-boto3-amp (1.17.9.0)", "mypy-boto3-amplify (1.17.9.0)", "mypy-boto3-amplifybackend (1.17.9.0)", "mypy-boto3-apigateway (1.17.9.0)", "mypy-boto3-apigatewaymanagementapi (1.17.9.0)", "mypy-boto3-apigatewayv2 (1.17.9.0)", "mypy-boto3-appconfig (1.17.9.0)", "mypy-boto3-appflow (1.17.9.0)", "mypy-boto3-appintegrations (1.17.9.0)", "mypy-boto3-application-autoscaling (1.17.9.0)", "mypy-boto3-application-insights (1.17.9.0)", "mypy-boto3-appmesh (1.17.9.0)", "mypy-boto3-appstream (1.17.9.0)", "mypy-boto3-appsync (1.17.9.0)", "mypy-boto3-athena (1.17.9.0)", "mypy-boto3-auditmanager (1.17.9.0)", "mypy-boto3-autoscaling (1.17.9.0)", "mypy-boto3-autoscaling-plans (1.17.9.0)", "mypy-boto3-backup (1.17.9.0)", "mypy-boto3-batch (1.17.9.0)", "mypy-boto3-braket (1.17.9.0)", "mypy-boto3-budgets (1.17.9.0)", "mypy-boto3-ce (1.17.9.0)", "mypy-boto3-chime (1.17.9.0)", "mypy-boto3-cloud9 (1.17.9.0)", "mypy-boto3-clouddirectory (1.17.9.0)", "mypy-boto3-cloudformation (1.17.9.0)", "mypy-boto3-cloudfront (1.17.9.0)", "mypy-boto3-cloudhsm (1.17.9.0)", "mypy-boto3-cloudhsmv2 (1.17.9.0)", "mypy-boto3-cloudsearch (1.17.9.0)", "mypy-boto3-cloudsearchdomain (1.17.9.0)", "mypy-boto3-cloudtrail (1.17.9.0)", "mypy-boto3-cloudwatch (1.17.9.0)", "mypy-boto3-codeartifact (1.17.9.0)", "mypy-boto3-codebuild (1.17.9.0)", "mypy-boto3-codecommit (1.17.9.0)", "mypy-boto3-codedeploy (1.17.9.0)", "mypy-boto3-codeguru-reviewer (1.17.9.0)", "mypy-boto3-codeguruprofiler (1.17.9.0)", "mypy-boto3-codepipeline (1.17.9.0)", "mypy-boto3-codestar (1.17.9.0)", "mypy-boto3-codestar-connections (1.17.9.0)", "mypy-boto3-codestar-notifications (1.17.9.0)", "mypy-boto3-cognito-identity (1.17.9.0)", "mypy-boto3-cognito-idp (1.17.9.0)", "mypy-boto3-cognito-sync (1.17.9.0)", "mypy-boto3-comprehend (1.17.9.0)", "mypy-boto3-comprehendmedical (1.17.9.0)", "mypy-boto3-compute-optimizer (1.17.9.0)", "mypy-boto3-config (1.17.9.0)", "mypy-boto3-connect (1.17.9.0)", "mypy-boto3-connect-contact-lens (1.17.9.0)", "mypy-boto3-connectparticipant (1.17.9.0)", "mypy-boto3-cur (1.17.9.0)", "mypy-boto3-customer-profiles (1.17.9.0)", "mypy-boto3-databrew (1.17.9.0)", "mypy-boto3-dataexchange (1.17.9.0)", "mypy-boto3-datapipeline (1.17.9.0)", "mypy-boto3-datasync (1.17.9.0)", "mypy-boto3-dax (1.17.9.0)", "mypy-boto3-detective (1.17.9.0)", "mypy-boto3-devicefarm (1.17.9.0)", "mypy-boto3-devops-guru (1.17.9.0)", "mypy-boto3-directconnect (1.17.9.0)", "mypy-boto3-discovery (1.17.9.0)", "mypy-boto3-dlm (1.17.9.0)", "mypy-boto3-dms (1.17.9.0)", "mypy-boto3-docdb (1.17.9.0)", "mypy-boto3-ds (1.17.9.0)", "mypy-boto3-dynamodb (1.17.9.0)", "mypy-boto3-dynamodbstreams (1.17.9.0)", "mypy-boto3-ebs (1.17.9.0)", "mypy-boto3-ec2 (1.17.9.0)", "mypy-boto3-ec2-instance-connect (1.17.9.0)", "mypy-boto3-ecr (1.17.9.0)", "mypy-boto3-ecr-public (1.17.9.0)", "mypy-boto3-ecs (1.17.9.0)", "mypy-boto3-efs (1.17.9.0)", "mypy-boto3-eks (1.17.9.0)", "mypy-boto3-elastic-inference (1.17.9.0)", "mypy-boto3-elasticache (1.17.9.0)", "mypy-boto3-elasticbeanstalk (1.17.9.0)", "mypy-boto3-elastictranscoder (1.17.9.0)", "mypy-boto3-elb (1.17.9.0)", "mypy-boto3-elbv2 (1.17.9.0)", "mypy-boto3-emr (1.17.9.0)", "mypy-boto3-emr-containers (1.17.9.0)", "mypy-boto3-es (1.17.9.0)", "mypy-boto3-events (1.17.9.0)", "mypy-boto3-firehose (1.17.9.0)", "mypy-boto3-fms (1.17.9.0)", "mypy-boto3-forecast (1.17.9.0)", "mypy-boto3-forecastquery (1.17.9.0)", "mypy-boto3-frauddetector (1.17.9.0)", "mypy-boto3-fsx (1.17.9.0)", "mypy-boto3-gamelift (1.17.9.0)", "mypy-boto3-glacier (1.17.9.0)", "mypy-boto3-globalaccelerator (1.17.9.0)", "mypy-boto3-glue (1.17.9.0)", "mypy-boto3-greengrass (1.17.9.0)", "mypy-boto3-greengrassv2 (1.17.9.0)", "mypy-boto3-groundstation (1.17.9.0)", "mypy-boto3-guardduty (1.17.9.0)", "mypy-boto3-health (1.17.9.0)", "mypy-boto3-healthlake (1.17.9.0)", "mypy-boto3-honeycode (1.17.9.0)", "mypy-boto3-iam (1.17.9.0)", "mypy-boto3-identitystore (1.17.9.0)", "mypy-boto3-imagebuilder (1.17.9.0)", "mypy-boto3-importexport (1.17.9.0)", "mypy-boto3-inspector (1.17.9.0)", "mypy-boto3-iot (1.17.9.0)", "mypy-boto3-iot-data (1.17.9.0)", "mypy-boto3-iot-jobs-data (1.17.9.0)", "mypy-boto3-iot1click-devices (1.17.9.0)", "mypy-boto3-iot1click-projects (1.17.9.0)", "mypy-boto3-iotanalytics (1.17.9.0)", "mypy-boto3-iotdeviceadvisor (1.17.9.0)", "mypy-boto3-iotevents (1.17.9.0)", "mypy-boto3-iotevents-data (1.17.9.0)", "mypy-boto3-iotfleethub (1.17.9.0)", "mypy-boto3-iotsecuretunneling (1.17.9.0)", "mypy-boto3-iotsitewise (1.17.9.0)", "mypy-boto3-iotthingsgraph (1.17.9.0)", "mypy-boto3-iotwireless (1.17.9.0)", "mypy-boto3-ivs (1.17.9.0)", "mypy-boto3-kafka (1.17.9.0)", "mypy-boto3-kendra (1.17.9.0)", "mypy-boto3-kinesis (1.17.9.0)", "mypy-boto3-kinesis-video-archived-media (1.17.9.0)", "mypy-boto3-kinesis-video-media (1.17.9.0)", "mypy-boto3-kinesis-video-signaling (1.17.9.0)", "mypy-boto3-kinesisanalytics (1.17.9.0)", "mypy-boto3-kinesisanalyticsv2 (1.17.9.0)", "mypy-boto3-kinesisvideo (1.17.9.0)", "mypy-boto3-kms (1.17.9.0)", "mypy-boto3-lakeformation (1.17.9.0)", "mypy-boto3-lambda (1.17.9.0)", "mypy-boto3-lex-models (1.17.9.0)", "mypy-boto3-lex-runtime (1.17.9.0)", "mypy-boto3-lexv2-models (1.17.9.0)", "mypy-boto3-lexv2-runtime (1.17.9.0)", "mypy-boto3-license-manager (1.17.9.0)", "mypy-boto3-lightsail (1.17.9.0)", "mypy-boto3-location (1.17.9.0)", "mypy-boto3-logs (1.17.9.0)", "mypy-boto3-lookoutvision (1.17.9.0)", "mypy-boto3-machinelearning (1.17.9.0)", "mypy-boto3-macie (1.17.9.0)", "mypy-boto3-macie2 (1.17.9.0)", "mypy-boto3-managedblockchain (1.17.9.0)", "mypy-boto3-marketplace-catalog (1.17.9.0)", "mypy-boto3-marketplace-entitlement (1.17.9.0)", "mypy-boto3-marketplacecommerceanalytics (1.17.9.0)", "mypy-boto3-mediaconnect (1.17.9.0)", "mypy-boto3-mediaconvert (1.17.9.0)", "mypy-boto3-medialive (1.17.9.0)", "mypy-boto3-mediapackage (1.17.9.0)", "mypy-boto3-mediapackage-vod (1.17.9.0)", "mypy-boto3-mediastore (1.17.9.0)", "mypy-boto3-mediastore-data (1.17.9.0)", "mypy-boto3-mediatailor (1.17.9.0)", "mypy-boto3-meteringmarketplace (1.17.9.0)", "mypy-boto3-mgh (1.17.9.0)", "mypy-boto3-migrationhub-config (1.17.9.0)", "mypy-boto3-mobile (1.17.9.0)", "mypy-boto3-mq (1.17.9.0)", "mypy-boto3-mturk (1.17.9.0)", "mypy-boto3-mwaa (1.17.9.0)", "mypy-boto3-neptune (1.17.9.0)", "mypy-boto3-network-firewall (1.17.9.0)", "mypy-boto3-networkmanager (1.17.9.0)", "mypy-boto3-opsworks (1.17.9.0)", "mypy-boto3-opsworkscm (1.17.9.0)", "mypy-boto3-organizations (1.17.9.0)", "mypy-boto3-outposts (1.17.9.0)", "mypy-boto3-personalize (1.17.9.0)", "mypy-boto3-personalize-events (1.17.9.0)", "mypy-boto3-personalize-runtime (1.17.9.0)", "mypy-boto3-pi (1.17.9.0)", "mypy-boto3-pinpoint (1.17.9.0)", "mypy-boto3-pinpoint-email (1.17.9.0)", "mypy-boto3-pinpoint-sms-voice (1.17.9.0)", "mypy-boto3-polly (1.17.9.0)", "mypy-boto3-pricing (1.17.9.0)", "mypy-boto3-qldb (1.17.9.0)", "mypy-boto3-qldb-session (1.17.9.0)", "mypy-boto3-quicksight (1.17.9.0)", "mypy-boto3-ram (1.17.9.0)", "mypy-boto3-rds (1.17.9.0)", "mypy-boto3-rds-data (1.17.9.0)", "mypy-boto3-redshift (1.17.9.0)", "mypy-boto3-redshift-data (1.17.9.0)", "mypy-boto3-rekognition (1.17.9.0)", "mypy-boto3-resource-groups (1.17.9.0)", "mypy-boto3-resourcegroupstaggingapi (1.17.9.0)", "mypy-boto3-robomaker (1.17.9.0)", "mypy-boto3-route53 (1.17.9.0)", "mypy-boto3-route53domains (1.17.9.0)", "mypy-boto3-route53resolver (1.17.9.0)", "mypy-boto3-s3 (1.17.9.0)", "mypy-boto3-s3control (1.17.9.0)", "mypy-boto3-s3outposts (1.17.9.0)", "mypy-boto3-sagemaker (1.17.9.0)", "mypy-boto3-sagemaker-a2i-runtime (1.17.9.0)", "mypy-boto3-sagemaker-edge (1.17.9.0)", "mypy-boto3-sagemaker-featurestore-runtime (1.17.9.0)", "mypy-boto3-sagemaker-runtime (1.17.9.0)", "mypy-boto3-savingsplans (1.17.9.0)", "mypy-boto3-schemas (1.17.9.0)", "mypy-boto3-sdb (1.17.9.0)", "mypy-boto3-secretsmanager (1.17.9.0)", "mypy-boto3-securityhub (1.17.9.0)", "mypy-boto3-serverlessrepo (1.17.9.0)", "mypy-boto3-service-quotas (1.17.9.0)", "mypy-boto3-servicecatalog (1.17.9.0)", "mypy-boto3-servicecatalog-appregistry (1.17.9.0)", "mypy-boto3-servicediscovery (1.17.9.0)", "mypy-boto3-ses (1.17.9.0)", "mypy-boto3-sesv2 (1.17.9.0)", "mypy-boto3-shield (1.17.9.0)", "mypy-boto3-signer (1.17.9.0)", "mypy-boto3-sms (1.17.9.0)", "mypy-boto3-sms-voice (1.17.9.0)", "mypy-boto3-snowball (1.17.9.0)", "mypy-boto3-sns (1.17.9.0)", "mypy-boto3-sqs (1.17.9.0)", "mypy-boto3-ssm (1.17.9.0)", "mypy-boto3-sso (1.17.9.0)", "mypy-boto3-sso-admin (1.17.9.0)", "mypy-boto3-sso-oidc (1.17.9.0)", "mypy-boto3-stepfunctions (1.17.9.0)", "mypy-boto3-storagegateway (1.17.9.0)", "mypy-boto3-sts (1.17.9.0)", "mypy-boto3-support (1.17.9.0)", "mypy-boto3-swf (1.17.9.0)", "mypy-boto3-synthetics (1.17.9.0)", "mypy-boto3-textract (1.17.9.0)", "mypy-boto3-timestream-query (1.17.9.0)", "mypy-boto3-timestream-write (1.17.9.0)", "mypy-boto3-transcribe (1.17.9.0)", "mypy-boto3-transfer (1.17.9.0)", "mypy-boto3-translate (1.17.9.0)", "mypy-boto3-waf (1.17.9.0)", "mypy-boto3-waf-regional (1.17.9.0)", "mypy-boto3-wafv2 (1.17.9.0)", "mypy-boto3-wellarchitected (1.17.9.0)", "mypy-boto3-workdocs (1.17.9.0)", "mypy-boto3-worklink (1.17.9.0)", "mypy-boto3-workmail (1.17.9.0)", "mypy-boto3-workmailmessageflow (1.17.9.0)", "mypy-boto3-workspaces (1.17.9.0)", "mypy-boto3-xray (1.17.9.0)"] +amp = ["mypy-boto3-amp (1.17.9.0)"] +amplify = ["mypy-boto3-amplify (1.17.9.0)"] +amplifybackend = ["mypy-boto3-amplifybackend (1.17.9.0)"] +apigateway = ["mypy-boto3-apigateway (1.17.9.0)"] +apigatewaymanagementapi = ["mypy-boto3-apigatewaymanagementapi (1.17.9.0)"] +apigatewayv2 = ["mypy-boto3-apigatewayv2 (1.17.9.0)"] +appconfig = ["mypy-boto3-appconfig (1.17.9.0)"] +appflow = ["mypy-boto3-appflow (1.17.9.0)"] +appintegrations = ["mypy-boto3-appintegrations (1.17.9.0)"] +application-autoscaling = ["mypy-boto3-application-autoscaling (1.17.9.0)"] +application-insights = ["mypy-boto3-application-insights (1.17.9.0)"] +appmesh = ["mypy-boto3-appmesh (1.17.9.0)"] +appstream = ["mypy-boto3-appstream (1.17.9.0)"] +appsync = ["mypy-boto3-appsync (1.17.9.0)"] +athena = ["mypy-boto3-athena (1.17.9.0)"] +auditmanager = ["mypy-boto3-auditmanager (1.17.9.0)"] +autoscaling = ["mypy-boto3-autoscaling (1.17.9.0)"] +autoscaling-plans = ["mypy-boto3-autoscaling-plans (1.17.9.0)"] +backup = ["mypy-boto3-backup (1.17.9.0)"] +batch = ["mypy-boto3-batch (1.17.9.0)"] +braket = ["mypy-boto3-braket (1.17.9.0)"] +budgets = ["mypy-boto3-budgets (1.17.9.0)"] +ce = ["mypy-boto3-ce (1.17.9.0)"] +chime = ["mypy-boto3-chime (1.17.9.0)"] +cloud9 = ["mypy-boto3-cloud9 (1.17.9.0)"] +clouddirectory = ["mypy-boto3-clouddirectory (1.17.9.0)"] +cloudformation = ["mypy-boto3-cloudformation (1.17.9.0)"] +cloudfront = ["mypy-boto3-cloudfront (1.17.9.0)"] +cloudhsm = ["mypy-boto3-cloudhsm (1.17.9.0)"] +cloudhsmv2 = ["mypy-boto3-cloudhsmv2 (1.17.9.0)"] +cloudsearch = ["mypy-boto3-cloudsearch (1.17.9.0)"] +cloudsearchdomain = ["mypy-boto3-cloudsearchdomain (1.17.9.0)"] +cloudtrail = ["mypy-boto3-cloudtrail (1.17.9.0)"] +cloudwatch = ["mypy-boto3-cloudwatch (1.17.9.0)"] +codeartifact = ["mypy-boto3-codeartifact (1.17.9.0)"] +codebuild = ["mypy-boto3-codebuild (1.17.9.0)"] +codecommit = ["mypy-boto3-codecommit (1.17.9.0)"] +codedeploy = ["mypy-boto3-codedeploy (1.17.9.0)"] +codeguru-reviewer = ["mypy-boto3-codeguru-reviewer (1.17.9.0)"] +codeguruprofiler = ["mypy-boto3-codeguruprofiler (1.17.9.0)"] +codepipeline = ["mypy-boto3-codepipeline (1.17.9.0)"] +codestar = ["mypy-boto3-codestar (1.17.9.0)"] +codestar-connections = ["mypy-boto3-codestar-connections (1.17.9.0)"] +codestar-notifications = ["mypy-boto3-codestar-notifications (1.17.9.0)"] +cognito-identity = ["mypy-boto3-cognito-identity (1.17.9.0)"] +cognito-idp = ["mypy-boto3-cognito-idp (1.17.9.0)"] +cognito-sync = ["mypy-boto3-cognito-sync (1.17.9.0)"] +comprehend = ["mypy-boto3-comprehend (1.17.9.0)"] +comprehendmedical = ["mypy-boto3-comprehendmedical (1.17.9.0)"] +compute-optimizer = ["mypy-boto3-compute-optimizer (1.17.9.0)"] +config = ["mypy-boto3-config (1.17.9.0)"] +connect = ["mypy-boto3-connect (1.17.9.0)"] +connect-contact-lens = ["mypy-boto3-connect-contact-lens (1.17.9.0)"] +connectparticipant = ["mypy-boto3-connectparticipant (1.17.9.0)"] +cur = ["mypy-boto3-cur (1.17.9.0)"] +customer-profiles = ["mypy-boto3-customer-profiles (1.17.9.0)"] +databrew = ["mypy-boto3-databrew (1.17.9.0)"] +dataexchange = ["mypy-boto3-dataexchange (1.17.9.0)"] +datapipeline = ["mypy-boto3-datapipeline (1.17.9.0)"] +datasync = ["mypy-boto3-datasync (1.17.9.0)"] +dax = ["mypy-boto3-dax (1.17.9.0)"] +detective = ["mypy-boto3-detective (1.17.9.0)"] +devicefarm = ["mypy-boto3-devicefarm (1.17.9.0)"] +devops-guru = ["mypy-boto3-devops-guru (1.17.9.0)"] +directconnect = ["mypy-boto3-directconnect (1.17.9.0)"] +discovery = ["mypy-boto3-discovery (1.17.9.0)"] +dlm = ["mypy-boto3-dlm (1.17.9.0)"] +dms = ["mypy-boto3-dms (1.17.9.0)"] +docdb = ["mypy-boto3-docdb (1.17.9.0)"] +ds = ["mypy-boto3-ds (1.17.9.0)"] +dynamodb = ["mypy-boto3-dynamodb (1.17.9.0)"] +dynamodbstreams = ["mypy-boto3-dynamodbstreams (1.17.9.0)"] +ebs = ["mypy-boto3-ebs (1.17.9.0)"] +ec2 = ["mypy-boto3-ec2 (1.17.9.0)"] +ec2-instance-connect = ["mypy-boto3-ec2-instance-connect (1.17.9.0)"] +ecr = ["mypy-boto3-ecr (1.17.9.0)"] +ecr-public = ["mypy-boto3-ecr-public (1.17.9.0)"] +ecs = ["mypy-boto3-ecs (1.17.9.0)"] +efs = ["mypy-boto3-efs (1.17.9.0)"] +eks = ["mypy-boto3-eks (1.17.9.0)"] +elastic-inference = ["mypy-boto3-elastic-inference (1.17.9.0)"] +elasticache = ["mypy-boto3-elasticache (1.17.9.0)"] +elasticbeanstalk = ["mypy-boto3-elasticbeanstalk (1.17.9.0)"] +elastictranscoder = ["mypy-boto3-elastictranscoder (1.17.9.0)"] +elb = ["mypy-boto3-elb (1.17.9.0)"] +elbv2 = ["mypy-boto3-elbv2 (1.17.9.0)"] +emr = ["mypy-boto3-emr (1.17.9.0)"] +emr-containers = ["mypy-boto3-emr-containers (1.17.9.0)"] +es = ["mypy-boto3-es (1.17.9.0)"] +essential = ["mypy-boto3-cloudformation (1.17.9.0)", "mypy-boto3-dynamodb (1.17.9.0)", "mypy-boto3-ec2 (1.17.9.0)", "mypy-boto3-lambda (1.17.9.0)", "mypy-boto3-rds (1.17.9.0)", "mypy-boto3-s3 (1.17.9.0)", "mypy-boto3-sqs (1.17.9.0)"] +events = ["mypy-boto3-events (1.17.9.0)"] +firehose = ["mypy-boto3-firehose (1.17.9.0)"] +fms = ["mypy-boto3-fms (1.17.9.0)"] +forecast = ["mypy-boto3-forecast (1.17.9.0)"] +forecastquery = ["mypy-boto3-forecastquery (1.17.9.0)"] +frauddetector = ["mypy-boto3-frauddetector (1.17.9.0)"] +fsx = ["mypy-boto3-fsx (1.17.9.0)"] +gamelift = ["mypy-boto3-gamelift (1.17.9.0)"] +glacier = ["mypy-boto3-glacier (1.17.9.0)"] +globalaccelerator = ["mypy-boto3-globalaccelerator (1.17.9.0)"] +glue = ["mypy-boto3-glue (1.17.9.0)"] +greengrass = ["mypy-boto3-greengrass (1.17.9.0)"] +greengrassv2 = ["mypy-boto3-greengrassv2 (1.17.9.0)"] +groundstation = ["mypy-boto3-groundstation (1.17.9.0)"] +guardduty = ["mypy-boto3-guardduty (1.17.9.0)"] +health = ["mypy-boto3-health (1.17.9.0)"] +healthlake = ["mypy-boto3-healthlake (1.17.9.0)"] +honeycode = ["mypy-boto3-honeycode (1.17.9.0)"] +iam = ["mypy-boto3-iam (1.17.9.0)"] +identitystore = ["mypy-boto3-identitystore (1.17.9.0)"] +imagebuilder = ["mypy-boto3-imagebuilder (1.17.9.0)"] +importexport = ["mypy-boto3-importexport (1.17.9.0)"] +inspector = ["mypy-boto3-inspector (1.17.9.0)"] +iot = ["mypy-boto3-iot (1.17.9.0)"] +iot-data = ["mypy-boto3-iot-data (1.17.9.0)"] +iot-jobs-data = ["mypy-boto3-iot-jobs-data (1.17.9.0)"] +iot1click-devices = ["mypy-boto3-iot1click-devices (1.17.9.0)"] +iot1click-projects = ["mypy-boto3-iot1click-projects (1.17.9.0)"] +iotanalytics = ["mypy-boto3-iotanalytics (1.17.9.0)"] +iotdeviceadvisor = ["mypy-boto3-iotdeviceadvisor (1.17.9.0)"] +iotevents = ["mypy-boto3-iotevents (1.17.9.0)"] +iotevents-data = ["mypy-boto3-iotevents-data (1.17.9.0)"] +iotfleethub = ["mypy-boto3-iotfleethub (1.17.9.0)"] +iotsecuretunneling = ["mypy-boto3-iotsecuretunneling (1.17.9.0)"] +iotsitewise = ["mypy-boto3-iotsitewise (1.17.9.0)"] +iotthingsgraph = ["mypy-boto3-iotthingsgraph (1.17.9.0)"] +iotwireless = ["mypy-boto3-iotwireless (1.17.9.0)"] +ivs = ["mypy-boto3-ivs (1.17.9.0)"] +kafka = ["mypy-boto3-kafka (1.17.9.0)"] +kendra = ["mypy-boto3-kendra (1.17.9.0)"] +kinesis = ["mypy-boto3-kinesis (1.17.9.0)"] +kinesis-video-archived-media = ["mypy-boto3-kinesis-video-archived-media (1.17.9.0)"] +kinesis-video-media = ["mypy-boto3-kinesis-video-media (1.17.9.0)"] +kinesis-video-signaling = ["mypy-boto3-kinesis-video-signaling (1.17.9.0)"] +kinesisanalytics = ["mypy-boto3-kinesisanalytics (1.17.9.0)"] +kinesisanalyticsv2 = ["mypy-boto3-kinesisanalyticsv2 (1.17.9.0)"] +kinesisvideo = ["mypy-boto3-kinesisvideo (1.17.9.0)"] +kms = ["mypy-boto3-kms (1.17.9.0)"] +lakeformation = ["mypy-boto3-lakeformation (1.17.9.0)"] +lambda = ["mypy-boto3-lambda (1.17.9.0)"] +lex-models = ["mypy-boto3-lex-models (1.17.9.0)"] +lex-runtime = ["mypy-boto3-lex-runtime (1.17.9.0)"] +lexv2-models = ["mypy-boto3-lexv2-models (1.17.9.0)"] +lexv2-runtime = ["mypy-boto3-lexv2-runtime (1.17.9.0)"] +license-manager = ["mypy-boto3-license-manager (1.17.9.0)"] +lightsail = ["mypy-boto3-lightsail (1.17.9.0)"] +location = ["mypy-boto3-location (1.17.9.0)"] +logs = ["mypy-boto3-logs (1.17.9.0)"] +lookoutvision = ["mypy-boto3-lookoutvision (1.17.9.0)"] +machinelearning = ["mypy-boto3-machinelearning (1.17.9.0)"] +macie = ["mypy-boto3-macie (1.17.9.0)"] +macie2 = ["mypy-boto3-macie2 (1.17.9.0)"] +managedblockchain = ["mypy-boto3-managedblockchain (1.17.9.0)"] +marketplace-catalog = ["mypy-boto3-marketplace-catalog (1.17.9.0)"] +marketplace-entitlement = ["mypy-boto3-marketplace-entitlement (1.17.9.0)"] +marketplacecommerceanalytics = ["mypy-boto3-marketplacecommerceanalytics (1.17.9.0)"] +mediaconnect = ["mypy-boto3-mediaconnect (1.17.9.0)"] +mediaconvert = ["mypy-boto3-mediaconvert (1.17.9.0)"] +medialive = ["mypy-boto3-medialive (1.17.9.0)"] +mediapackage = ["mypy-boto3-mediapackage (1.17.9.0)"] +mediapackage-vod = ["mypy-boto3-mediapackage-vod (1.17.9.0)"] +mediastore = ["mypy-boto3-mediastore (1.17.9.0)"] +mediastore-data = ["mypy-boto3-mediastore-data (1.17.9.0)"] +mediatailor = ["mypy-boto3-mediatailor (1.17.9.0)"] +meteringmarketplace = ["mypy-boto3-meteringmarketplace (1.17.9.0)"] +mgh = ["mypy-boto3-mgh (1.17.9.0)"] +migrationhub-config = ["mypy-boto3-migrationhub-config (1.17.9.0)"] +mobile = ["mypy-boto3-mobile (1.17.9.0)"] +mq = ["mypy-boto3-mq (1.17.9.0)"] +mturk = ["mypy-boto3-mturk (1.17.9.0)"] +mwaa = ["mypy-boto3-mwaa (1.17.9.0)"] +neptune = ["mypy-boto3-neptune (1.17.9.0)"] +network-firewall = ["mypy-boto3-network-firewall (1.17.9.0)"] +networkmanager = ["mypy-boto3-networkmanager (1.17.9.0)"] +opsworks = ["mypy-boto3-opsworks (1.17.9.0)"] +opsworkscm = ["mypy-boto3-opsworkscm (1.17.9.0)"] +organizations = ["mypy-boto3-organizations (1.17.9.0)"] +outposts = ["mypy-boto3-outposts (1.17.9.0)"] +personalize = ["mypy-boto3-personalize (1.17.9.0)"] +personalize-events = ["mypy-boto3-personalize-events (1.17.9.0)"] +personalize-runtime = ["mypy-boto3-personalize-runtime (1.17.9.0)"] +pi = ["mypy-boto3-pi (1.17.9.0)"] +pinpoint = ["mypy-boto3-pinpoint (1.17.9.0)"] +pinpoint-email = ["mypy-boto3-pinpoint-email (1.17.9.0)"] +pinpoint-sms-voice = ["mypy-boto3-pinpoint-sms-voice (1.17.9.0)"] +polly = ["mypy-boto3-polly (1.17.9.0)"] +pricing = ["mypy-boto3-pricing (1.17.9.0)"] +qldb = ["mypy-boto3-qldb (1.17.9.0)"] +qldb-session = ["mypy-boto3-qldb-session (1.17.9.0)"] +quicksight = ["mypy-boto3-quicksight (1.17.9.0)"] +ram = ["mypy-boto3-ram (1.17.9.0)"] +rds = ["mypy-boto3-rds (1.17.9.0)"] +rds-data = ["mypy-boto3-rds-data (1.17.9.0)"] +redshift = ["mypy-boto3-redshift (1.17.9.0)"] +redshift-data = ["mypy-boto3-redshift-data (1.17.9.0)"] +rekognition = ["mypy-boto3-rekognition (1.17.9.0)"] +resource-groups = ["mypy-boto3-resource-groups (1.17.9.0)"] +resourcegroupstaggingapi = ["mypy-boto3-resourcegroupstaggingapi (1.17.9.0)"] +robomaker = ["mypy-boto3-robomaker (1.17.9.0)"] +route53 = ["mypy-boto3-route53 (1.17.9.0)"] +route53domains = ["mypy-boto3-route53domains (1.17.9.0)"] +route53resolver = ["mypy-boto3-route53resolver (1.17.9.0)"] +s3 = ["mypy-boto3-s3 (1.17.9.0)"] +s3control = ["mypy-boto3-s3control (1.17.9.0)"] +s3outposts = ["mypy-boto3-s3outposts (1.17.9.0)"] +sagemaker = ["mypy-boto3-sagemaker (1.17.9.0)"] +sagemaker-a2i-runtime = ["mypy-boto3-sagemaker-a2i-runtime (1.17.9.0)"] +sagemaker-edge = ["mypy-boto3-sagemaker-edge (1.17.9.0)"] +sagemaker-featurestore-runtime = ["mypy-boto3-sagemaker-featurestore-runtime (1.17.9.0)"] +sagemaker-runtime = ["mypy-boto3-sagemaker-runtime (1.17.9.0)"] +savingsplans = ["mypy-boto3-savingsplans (1.17.9.0)"] +schemas = ["mypy-boto3-schemas (1.17.9.0)"] +sdb = ["mypy-boto3-sdb (1.17.9.0)"] +secretsmanager = ["mypy-boto3-secretsmanager (1.17.9.0)"] +securityhub = ["mypy-boto3-securityhub (1.17.9.0)"] +serverlessrepo = ["mypy-boto3-serverlessrepo (1.17.9.0)"] +service-quotas = ["mypy-boto3-service-quotas (1.17.9.0)"] +servicecatalog = ["mypy-boto3-servicecatalog (1.17.9.0)"] +servicecatalog-appregistry = ["mypy-boto3-servicecatalog-appregistry (1.17.9.0)"] +servicediscovery = ["mypy-boto3-servicediscovery (1.17.9.0)"] +ses = ["mypy-boto3-ses (1.17.9.0)"] +sesv2 = ["mypy-boto3-sesv2 (1.17.9.0)"] +shield = ["mypy-boto3-shield (1.17.9.0)"] +signer = ["mypy-boto3-signer (1.17.9.0)"] +sms = ["mypy-boto3-sms (1.17.9.0)"] +sms-voice = ["mypy-boto3-sms-voice (1.17.9.0)"] +snowball = ["mypy-boto3-snowball (1.17.9.0)"] +sns = ["mypy-boto3-sns (1.17.9.0)"] +sqs = ["mypy-boto3-sqs (1.17.9.0)"] +ssm = ["mypy-boto3-ssm (1.17.9.0)"] +sso = ["mypy-boto3-sso (1.17.9.0)"] +sso-admin = ["mypy-boto3-sso-admin (1.17.9.0)"] +sso-oidc = ["mypy-boto3-sso-oidc (1.17.9.0)"] +stepfunctions = ["mypy-boto3-stepfunctions (1.17.9.0)"] +storagegateway = ["mypy-boto3-storagegateway (1.17.9.0)"] +sts = ["mypy-boto3-sts (1.17.9.0)"] +support = ["mypy-boto3-support (1.17.9.0)"] +swf = ["mypy-boto3-swf (1.17.9.0)"] +synthetics = ["mypy-boto3-synthetics (1.17.9.0)"] +textract = ["mypy-boto3-textract (1.17.9.0)"] +timestream-query = ["mypy-boto3-timestream-query (1.17.9.0)"] +timestream-write = ["mypy-boto3-timestream-write (1.17.9.0)"] +transcribe = ["mypy-boto3-transcribe (1.17.9.0)"] +transfer = ["mypy-boto3-transfer (1.17.9.0)"] +translate = ["mypy-boto3-translate (1.17.9.0)"] +waf = ["mypy-boto3-waf (1.17.9.0)"] +waf-regional = ["mypy-boto3-waf-regional (1.17.9.0)"] +wafv2 = ["mypy-boto3-wafv2 (1.17.9.0)"] +wellarchitected = ["mypy-boto3-wellarchitected (1.17.9.0)"] +workdocs = ["mypy-boto3-workdocs (1.17.9.0)"] +worklink = ["mypy-boto3-worklink (1.17.9.0)"] +workmail = ["mypy-boto3-workmail (1.17.9.0)"] +workmailmessageflow = ["mypy-boto3-workmailmessageflow (1.17.9.0)"] +workspaces = ["mypy-boto3-workspaces (1.17.9.0)"] +xray = ["mypy-boto3-xray (1.17.9.0)"] [[package]] category = "main" @@ -395,7 +395,7 @@ description = "Low-level, data-driven core of boto 3." name = "botocore" optional = false python-versions = ">= 2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -version = "1.20.8" +version = "1.20.9" [package.dependencies] jmespath = ">=0.7.1,<1.0.0" @@ -493,7 +493,7 @@ description = "cryptography is a package which provides cryptographic recipes an name = "cryptography" optional = false python-versions = ">=3.6" -version = "3.4.5" +version = "3.4.6" [package.dependencies] cffi = ">=1.12" @@ -1999,7 +1999,7 @@ transaction = ">=1.6.0" test = ["zope.testing"] [metadata] -content-hash = "86b27c4ede18c241ab46a6e320f74c9ed7b54d549b783b7142b2e3fade326b2f" +content-hash = "c8eb3c61ab63f4f2bc017c19f7efd687b1500634f2f0d7d892020a9b9f33faee" lock-version = "1.0" python-versions = ">=3.6.1,<3.7" @@ -2025,8 +2025,8 @@ aws-xray-sdk = [ {file = "aws_xray_sdk-0.95-py2.py3-none-any.whl", hash = "sha256:72791618feb22eaff2e628462b0d58f398ce8c1bacfa989b7679817ab1fad60c"}, ] awscli = [ - {file = "awscli-1.19.8-py2.py3-none-any.whl", hash = "sha256:a2893a97ba30ef9c6a9c41b9c9d3bbecc03f71ee335aa92f162a003e69a4074c"}, - {file = "awscli-1.19.8.tar.gz", hash = "sha256:ae426af1dac71b5c9474344bb3a045f8a68f009db6559fa06f9849b19761b4f0"}, + {file = "awscli-1.19.9-py2.py3-none-any.whl", hash = "sha256:845baa941f10c93f7bf083350ee2ac91466040cb11667763ce3515e7671011cc"}, + {file = "awscli-1.19.9.tar.gz", hash = "sha256:0dcc69f31e6d6dbd73046af53761b4720c39dccac5dfc4d19064cbd00414c837"}, ] "backports.statistics" = [ {file = "backports.statistics-0.1.0-py2.py3-none-any.whl", hash = "sha256:2732e003151620762ba3ea25b881b5ca0debe2fcbf41b32b6eaff5842a8b99d7"}, @@ -2042,16 +2042,16 @@ boto = [ {file = "boto-2.49.0.tar.gz", hash = "sha256:ea0d3b40a2d852767be77ca343b58a9e3a4b00d9db440efb8da74b4e58025e5a"}, ] boto3 = [ - {file = "boto3-1.17.8-py2.py3-none-any.whl", hash = "sha256:c294eb103db0ab6c55a53f68cc87761ff7e564733e7b23e51dac475a18c0a12b"}, - {file = "boto3-1.17.8.tar.gz", hash = "sha256:819890e92268d730bdef1d8bac08fb069b148bec21f2172a1a99380798224e1b"}, + {file = "boto3-1.17.9-py2.py3-none-any.whl", hash = "sha256:3a8412020a59509e783755b5c9b910a4fc7f6b6f2b9473e7cd1e07b67672e0d1"}, + {file = "boto3-1.17.9.tar.gz", hash = "sha256:877f204dabe1bfa21aa9cfaacc72bd4b70a897d0fdcea799afa5c4743b6fc7ac"}, ] boto3-stubs = [ - {file = "boto3-stubs-1.17.8.0.tar.gz", hash = "sha256:749a93f17b2bae4f75c829acdffa5073c29c0f9e6d4e2936c825f183bbbed07a"}, - {file = "boto3_stubs-1.17.8.0-py3-none-any.whl", hash = "sha256:ef030363419e979b7f1e2eecbc62c63387ca8e72ee2e7aa71a483b24fd152e2e"}, + {file = "boto3-stubs-1.17.9.0.tar.gz", hash = "sha256:f251a77f27b5087a6dbb2aad2666e5573d63d4fa2fd558e27e7a8eb44b49983e"}, + {file = "boto3_stubs-1.17.9.0-py3-none-any.whl", hash = "sha256:b1586114ddabf2162f0d34a8d39afa69dec5654907b7e5c676fe8ce102acae08"}, ] botocore = [ - {file = "botocore-1.20.8-py2.py3-none-any.whl", hash = "sha256:65e2fb81f941dfefa8cc3ef72d46a62d4b6219b8eb6550062b644b36935f6e4f"}, - {file = "botocore-1.20.8.tar.gz", hash = "sha256:cd621cdd14a81d2c3c5276516066d9e6ea20a515cf3113a80ad74f3f8b04a093"}, + {file = "botocore-1.20.9-py2.py3-none-any.whl", hash = "sha256:d725840b881be62fc52e8e24a6ada651128cf7f1ed1639b87322a7a213ffdbad"}, + {file = "botocore-1.20.9.tar.gz", hash = "sha256:c8614c230e7a8e042a8c07d47caea50ad21cb51415289bd34fa6d0382beddad7"}, ] certifi = [ {file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"}, @@ -2167,13 +2167,13 @@ coveralls = [ {file = "coveralls-3.0.0.tar.gz", hash = "sha256:5399c0565ab822a70a477f7031f6c88a9dd196b3de2877b3facb43b51bd13434"}, ] cryptography = [ - {file = "cryptography-3.4.5-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:18d6f3ac1da14a01c95f4590ee58e96aa6628d231ce738e9eca330b9997127b6"}, - {file = "cryptography-3.4.5-cp36-abi3-manylinux2010_x86_64.whl", hash = "sha256:c8dc9859c5a046e1ca22da360dfd609c09064a4f974881cb5cba977c581088ec"}, - {file = "cryptography-3.4.5-cp36-abi3-manylinux2014_aarch64.whl", hash = "sha256:0bf49d5b38e4f3745a0eab0597fa97720dd49b30d65f534b49a82e303f149deb"}, - {file = "cryptography-3.4.5-cp36-abi3-manylinux2014_x86_64.whl", hash = "sha256:9c6f7552d4f2130542d488b9d9e5b1546204b5d1aa90c823d50cce8eed421363"}, - {file = "cryptography-3.4.5-cp36-abi3-win32.whl", hash = "sha256:b0873ac0c0e6bc6882cd285930cc382ec4e78786be71bdc113c06246eea61294"}, - {file = "cryptography-3.4.5-cp36-abi3-win_amd64.whl", hash = "sha256:8b3b79af57e12aabbc3db81e563eaa07870293a1ffdcc891d107035ce9a0dbff"}, - {file = "cryptography-3.4.5.tar.gz", hash = "sha256:4f6761a82b51fe02cda8f45af1c2f698a10f50003dc9c2572d8a49eda2e6d35b"}, + {file = "cryptography-3.4.6-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:57ad77d32917bc55299b16d3b996ffa42a1c73c6cfa829b14043c561288d2799"}, + {file = "cryptography-3.4.6-cp36-abi3-manylinux2010_x86_64.whl", hash = "sha256:93cfe5b7ff006de13e1e89830810ecbd014791b042cbe5eec253be11ac2b28f3"}, + {file = "cryptography-3.4.6-cp36-abi3-manylinux2014_aarch64.whl", hash = "sha256:5ecf2bcb34d17415e89b546dbb44e73080f747e504273e4d4987630493cded1b"}, + {file = "cryptography-3.4.6-cp36-abi3-manylinux2014_x86_64.whl", hash = "sha256:fec7fb46b10da10d9e1d078d1ff8ed9e05ae14f431fdbd11145edd0550b9a964"}, + {file = "cryptography-3.4.6-cp36-abi3-win32.whl", hash = "sha256:df186fcbf86dc1ce56305becb8434e4b6b7504bc724b71ad7a3239e0c9d14ef2"}, + {file = "cryptography-3.4.6-cp36-abi3-win_amd64.whl", hash = "sha256:66b57a9ca4b3221d51b237094b0303843b914b7d5afd4349970bb26518e350b0"}, + {file = "cryptography-3.4.6.tar.gz", hash = "sha256:2d32223e5b0ee02943f32b19245b61a62db83a882f0e76cc564e1cec60d48f87"}, ] dcicsnovault = [ {file = "dcicsnovault-4.3.1-py3-none-any.whl", hash = "sha256:bf83b07f439d959d531e5cfdad9f1a8d5971b2ea6f3a01cd73f6e67647e65f52"}, From 3c71f6bd3fd2042135dfba88a238573fdc54f5be Mon Sep 17 00:00:00 2001 From: Kent Pitman Date: Thu, 18 Feb 2021 18:53:23 -0500 Subject: [PATCH 35/35] A few more bits of leveling with cgap in test_indexing.py. --- src/encoded/tests/test_indexing.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/encoded/tests/test_indexing.py b/src/encoded/tests/test_indexing.py index c9cd50a5de..836838175c 100644 --- a/src/encoded/tests/test_indexing.py +++ b/src/encoded/tests/test_indexing.py @@ -24,13 +24,13 @@ build_index_record, compare_against_existing_mapping ) -from snovault.elasticsearch.interfaces import INDEXER_QUEUE from snovault.elasticsearch.indexer_utils import get_namespaced_index +from snovault.elasticsearch.interfaces import INDEXER_QUEUE from sqlalchemy import MetaData, func from timeit import default_timer as timer from unittest import mock from zope.sqlalchemy import mark_changed -from .. import main +from .. import main, loadxl from ..util import delay_rerun from ..verifier import verify_item from .workbook_fixtures import app_settings @@ -62,7 +62,9 @@ def test_postgres_version(session): def app(app_settings, request): # for now, don't run with mpindexer. Add `True` to params above to do so if request.param: - app_settings['mpindexer'] = True + # we disable the MPIndexer since the build runs on a small machine + # snovault should be testing the mpindexer - Will 12/12/2020 + app_settings['mpindexer'] = False app = main({}, **app_settings) yield app @@ -128,6 +130,7 @@ def test_indexing_simple(app, testapp, indexer_testapp): count += 1 assert res.json['total'] >= 2 assert uuid in uuids + namespaced_indexing = get_namespaced_index(app, 'indexing') indexing_doc = es.get(index=namespaced_indexing, doc_type='indexing', id='latest_indexing') indexing_source = indexing_doc['_source'] @@ -284,7 +287,7 @@ def test_real_validation_error(app, indexer_testapp, testapp, lab, award, file_f assert val_err_view['validation_errors'] == es_res['_source']['validation_errors'] -# @pytest.mark.performance +@pytest.mark.performance @pytest.mark.skip(reason="need to update perf-testing inserts") def test_load_and_index_perf_data(testapp, indexer_testapp): ''' @@ -316,7 +319,7 @@ def test_load_and_index_perf_data(testapp, indexer_testapp): # load -em up start = timer() - with mock.patch('encoded.loadxl.get_app') as mocked_app: + with mock.patch.object(loadxl, 'get_app') as mocked_app: mocked_app.return_value = testapp.app data = {'store': json_inserts} res = testapp.post_json('/load_data', data, # status=200