{ "info": { "author": "Pavlos Mitsoulis Ntompos, Ioakeim (Joakim) Lazakis", "author_email": "pavlos@kenza.ai, joakim@kenza.ai", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "Intended Audience :: Science/Research", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering :: Artificial Intelligence" ], "description": "**Build Status**\n\nmaster: [![Build Status](https://app.travis-ci.com/Kenza-AI/sagify.svg?branch=master)](https://app.travis-ci.com/github/Kenza-AI/sagify)\n\n# sagify\n\n![Sagify](docs/sagify@2x.png)\n\nA command-line utility to train and deploy Machine Learning/Deep Learning models on [AWS SageMaker](https://aws.amazon.com/sagemaker/) in a few simple steps! It hides all the details of Sagemaker so that you can focus 100% on Machine Learning, and not in low level engineering tasks.\n\nFor detailed reference to Sagify commands please go to: [Read the Docs](https://Kenza-AI.github.io/sagify/)\n\n## Installation\n\n### Prerequisites\n\nsagify requires the following:\n\n1. Python (3.7, 3.8)\n2. [Docker](https://www.docker.com/) installed and running\n3. Configured [awscli](https://pypi.python.org/pypi/awscli)\n\n### Install sagify\n\nAt the command line:\n\n pip install sagify\n\n\n## Getting started - No code deployment\n\n1. Create a file with name `huggingface_config.json` with the following content:\n\n {\n \"transformers_version\": \"4.6.1\",\n \"pytorch_version\": \"1.7.1\",\n \"hub\": {\n \"HF_MODEL_ID\": \"gpt2\",\n \"HF_TASK\": \"text-generation\"\n }\n }\n \n2. Then, make sure to configure your AWS account by following the instructions at section [Configure AWS Account](#configure-aws-account)\n \n3. Finally, run the following command:\n\n sagify cloud lightning-deploy --framework huggingface -n 1 -e ml.c4.2xlarge --extra-config-file huggingface_config.json --aws-region us-east-1 --aws-profile sagemaker-dev\n \nYou can change the values for ec2 type (-e), aws region and aws profile with your preferred ones.\n\n4. Once the Hugging Face model is deployed, you can go to https://console.aws.amazon.com/sagemaker/home?region=us-east-1#/endpoints (make sure you're on your preferred region) and find your deployed endpoint. For example:\n\n![Sagemaker-Endpoints-List](docs/sagemaker_endpoints_list.png)\n\n5. Then, you can click on your deployed endpoint and copy the endpoint url. For example:\n\n![Sagemaker-Endpoint](docs/sagemaker_endpoint.png)\n\n6. Postman is a good app to call the deployed endpoint. Here's an example on how to set up the AWS signature in order to call the endpoint:\n \n![Postman-AWS-Signature](docs/postman_aws_signature.png)\n\n7. Finally, you can call the endpoint from Postman:\n\n![Postman-Call-Endpoint](docs/postman_call_endpoint.png)\n\n## Getting started - Custom Training and Deployment\n\n### Step 1: Clone Machine Learning demo repository\n\nYou're going to clone and train a Machine Learning codebase to train a classifier for the Iris data set.\n\nClone repository:\n\n git clone https://github.com/Kenza-AI/sagify-demo.git \n \nCreate environment:\n \n mkvirtualenv -p python3.7 sagify-demo\n \nor\n\n mkvirtualenv -p python3.8 sagify-demo\n\nDon't forget to activate the virtualenv after the creation of environment by executing `workon sagify-demo`.\n\nInstall dependencies:\n\n make requirements\n\n\n### Step 2: Initialize sagify\n\n sagify init\n\nType in `sagify-demo` for SageMaker app name, `N` in question `Are you starting a new project?`, `src` for question `Type in the directory where your code lives` and make sure to choose your preferred Python version, AWS profile and region. Finally, type `requirements.txt` in question `Type in the path to requirements.txt`.\n\nA module called `sagify` is created under the directory you provided. The structure is:\n \n sagify_base/\n local_test/\n test_dir/\n input/\n config/\n hyperparameters.json\n data/\n training/\n model/\n output/\n deploy_local.sh\n train_local.sh\n prediction/\n __init__.py\n nginx.conf\n predict.py\n prediction.py\n predictor.py\n serve\n wsgi.py\n training/\n __init__.py\n train\n training.py\n __init__.py\n build.sh\n Dockerfile\n executor.sh\n push.sh\n\n### Step 3: Integrate sagify\n\nAs a Data Scientist, you only need to conduct a few actions. Sagify takes care of the rest:\n\n1. Copy a subset of training data under `sagify_base/local_test/test_dir/input/data/training/` to test that training works locally\n2. Implement `train(...)` function in `sagify_base/training/training.py`\n3. Implement `predict(...)` function in `sagify_base/prediction/prediction.py`\n4. Optionally, specify hyperparameters in `sagify_base/local_test/test_dir/input/config/hyperparameters.json` \n\nHence,\n\n1. Copy `iris.data` files from `data` to `sagify_base/local_test/test_dir/input/data/training/`\n\n2. Replace the `TODOs` in the `train(...)` function in `sagify_base/training/training.py` file with:\n\n ```python\n input_file_path = os.path.join(input_data_path, 'iris.data')\n clf, accuracy = training_logic(input_file_path=input_file_path)\n \n output_model_file_path = os.path.join(model_save_path, 'model.pkl')\n joblib.dump(clf, output_model_file_path)\n \n accuracy_report_file_path = os.path.join(model_save_path, 'report.txt')\n with open(accuracy_report_file_path, 'w') as _out:\n _out.write(str(accuracy))\n ```\n \n and at the top of the file, add:\n \n ```python\n import os\n \n import joblib\n \n from iris_training import train as training_logic\n ```\n\n3. Replace the body of `predict(...)` function in `sagify_base/prediction/prediction.py` with:\n\n ```python\n model_input = json_input['features']\n prediction = ModelService.predict(model_input)\n\n return {\n \"prediction\": prediction.item()\n }\n ```\n \n and replace the body of `get_model()` function in `ModelService` class in the same file with:\n \n ```python\n if cls.model is None:\n import joblib\n cls.model = joblib.load(os.path.join(_MODEL_PATH, 'model.pkl'))\n return cls.model\n ```\n \n\n### Step 4: Build Docker image\n\nIt's time to build the Docker image that will contain the Machine Learning codebase:\n\n sagify build\n\nIf you run `docker images | grep sagify-demo` in your terminal, you'll see the created Sagify-Demo image.\n\n### Step 5: Train model\n\nTime to train the model for the Iris data set in the newly built Docker image:\n\n sagify local train\n\nModel file `model.pkl` and report file `report.txt` are now under `sagify_base/local_test/test_dir/model/`\n\n### Step 6: Deploy model\n\nFinally, serve the model as a REST Service:\n\n sagify local deploy\n\nRun the following curl command on your terminal to verify that the REST Service works:\n\n ```bash\n curl -X POST \\\n http://localhost:8080/invocations \\\n -H 'Cache-Control: no-cache' \\\n -H 'Content-Type: application/json' \\\n -H 'Postman-Token: 41189b9a-40e2-abcf-b981-c31ae692072e' \\\n -d '{\n\t \"features\":[[0.34, 0.45, 0.45, 0.3]]\n }'\n ```\n\nIt will be slow in the first couple of calls as it loads the model in a lazy manner.\n\nVoila! That's a proof that this Machine Learning model is going to be trained and deployed on AWS SageMaker successfully. Now, go to the *Usage* section in [Sagify Docs](https://Kenza-AI.github.io/sagify/) to see how to train and deploy this Machine Learning model to AWS SageMaker!\n\n\n## Hyperparameter Optimization\n\nGiven that you have configured your AWS Account as described in the previous section, you're now ready to perform Bayesian Hyperparameter Optimization on AWS SageMaker! The process is similar to training step.\n\n### Step 1: Define Hyperparameter Configuration File\n\nDefine the Hyperparameter Configuration File. More specifically, you need to specify in a local JSON file the ranges for the hyperparameters, the name of the objective metric and its type (i.e. `Maximize` or `Minimize`). For example:\n\n```json\n{\n\t\"ParameterRanges\": {\n\t\t\"CategoricalParameterRanges\": [\n\t\t\t{\n\t\t\t\t\"Name\": \"kernel\",\n\t\t\t\t\"Values\": [\"linear\", \"rbf\"]\n\t\t\t}\n\t\t],\n\t\t\"ContinuousParameterRanges\": [\n\t\t{\n\t\t \"MinValue\": 0.001,\n\t\t \"MaxValue\": 10,\n\t\t \"Name\": \"gamma\"\n\t\t}\n\t\t],\n\t\t\"IntegerParameterRanges\": [\n\t\t\t{\n\t\t\t\t\"Name\": \"C\",\n\t\t\t\t\"MinValue\": 1,\n\t\t\t\t\"MaxValue\": 10\n\t\t\t}\n\t\t]\n },\n \"ObjectiveMetric\": {\n \t\"Name\": \"Precision\",\n \"Type\": \"Maximize\"\n }\n}\n```\n\n### Step 2: Implement Train function\n\nReplace the `TODOs` in the `train(...)` function in `sagify_base/training/training.py` file with your logic. For example:\n\n```python\n from sklearn import datasets\n iris = datasets.load_iris()\n\n # Read the hyperparameter config json file\n import json\n with open(hyperparams_path) as _in_file:\n hyperparams_dict = json.load(_in_file)\n\n from sklearn import svm\n clf = svm.SVC(\n gamma=float(hyperparams_dict['gamma']), # Values will be read as strings, so make sure to convert them to the right data type\n C=float(hyperparams_dict['C']),\n kernel=hyperparams_dict['kernel']\n )\n\n from sklearn.model_selection import train_test_split\n X_train, X_test, y_train, y_test = train_test_split(\n iris.data, iris.target, test_size=0.3, random_state=42)\n\n clf.fit(X_train, y_train)\n\n from sklearn.metrics import precision_score\n\n predictions = clf.predict(X_test)\n\n precision = precision_score(y_test, predictions, average='weighted')\n \n # Log the objective metric name with its calculated value. In tis example is Precision.\n # The objective name should be exactly the same with the one specified in the hyperparams congig json file.\n # The value must be a numeric (float or int).\n from sagify.api.hyperparameter_tuning import log_metric\n name = \"Precision\"\n log_metric(name, precision)\n\n from joblib import dump\n dump(clf, os.path.join(model_save_path, 'model.pkl'))\n\n print('Training complete.')\n```\n \n### Step 3: Build and Push Docker image\n\n1. `sagify build` Make sure sagify is in your `requirements.txt` file.\n2. `sagify push`\n\n### Step 4: Call The CLI Command\n\nAnd, finally, call the hyperparameter-optimization CLI command. For example:\n\n sagify cloud hyperparameter-optimization -i s3://my-bucket/training-data/ -o s3://my-bucket/output/ -e ml.m4.xlarge -h local/path/to/hyperparam_ranges.json \n \n### Step 5: Monitor Progress\n\nYou can monitor the progress via the SageMaker UI console. Here is an example of a finished Hyperparameter Optimization job:\n\n![Hyperparameter Optimization Results](docs/hyperparam_monitor.png)\n\n\n## Commands\n\n### Initialize\n\n#### Name\n\nInitializes a sagify module\n\n#### Synopsis\n\n sagify init\n \n#### Description\n\nThis command initializes a sagify module in the directory you provide when asked after you invoke the `init` command.\n\n### Example\n\n sagify init\n\n\n### Configure\n\n#### Description\n\nUpdates an existing configuration value e.g. `python version` or `AWS region`.\n\n#### Synopsis\n\n sagify configure [--aws-region AWS_REGION] [--aws-profile AWS_PROFILE] [--image-name IMAGE_NAME] [--python-version PYTHON_VERSION]\n\n#### Optional Flags\n\n`--aws-region AWS_REGION`: _AWS_ region where _Docker_ images are pushed and _SageMaker_ operations (_train_, _deploy_) are performed.\n\n`--aws-profile AWS_PROFILE`: _AWS_ profile to use when interacting with _AWS_.\n\n`--image-name IMAGE_NAME`: _Docker_ image name used when building for use with _SageMaker_. This shows up as an _AWS ECR_ repository on your _AWS_ account.\n\n`--python-version PYTHON_VERSION`: _Python_ version used when building _SageMaker's_ _Docker_ images. Currently supported versions: `3.6`.\n\n\n### Example\n\n sagify configure --aws-region us-east-2 --aws-profile default --image-name sage-docker-image-name --python-version 3.6\n\n\n### Build\n\n#### Name\n\nBuilds a Docker image\n\n#### Synopsis\n\n sagify build\n \n#### Description\n\nThis command builds a Docker image from code under the directory sagify is installed in. A `REQUIREMENTS_FILE` needs to be specified during `sagify init` or later via `sagify configure --requirements-dir` for all required dependencies to be installed in the Docker image.\n\n#### Example\n\n sagify build\n\n\n### Local Train\n\n#### Name\n\nExecutes a Docker image in train mode\n\n#### Synopsis\n\n sagify local train\n \n#### Description\n\nThis command executes a Docker image in train mode. More specifically, it executes the `train(...)` function in `sagify_base/training/training.py` inside an already built Docker image (see Build command section).\n\n#### Example\n\n sagify local train\n \n\n### Local Deploy\n\n#### Name\n\nExecutes a Docker image in serve mode\n\n#### Synopsis\n\n sagify local deploy\n \n#### Description\n\nThis command executes a Docker image in serve mode. More specifically, it runs a Flask REST app in Docker image and directs HTTP requests to `/invocations` endpoint. Then, the `/invocations` endpoint calls the `predict(...)` function in `sagify_base/prediction/prediction.py` (see Build command section on how to build a Docker image).\n \n#### Example\n\n sagify local deploy\n \n\n### Push\n\n#### Name\n\nPushes a Docker image to AWS Elastic Container Service\n\n#### Synopsis\n\n sagify push [--aws-profile PROFILE_NAME] [--aws-region AWS_REGION] [--iam-role-arn IAM_ROLE] [--external-id EXTERNAL_ID]\n\n#### Description\n\nThis command pushes an already built Docker image to AWS Elastic Container Service. Later on, AWS SageMaker will consume that image from AWS Elastic Container Service for train and serve mode.\n\n> Only one of _iam-role-arn_ and _aws_profile_ can be provided. _external-id_ is ignored when no _iam-role-arn_ is provided.\n\n#### Optional Flags\n\n`--iam-role-arn IAM_ROLE` or `-i IAM_ROLE`: AWS IAM role to use for pushing to ECR\n\n`--aws-region AWS_REGION` or `-r AWS_REGION`: The AWS region to push the image to\n\n`--aws-profile PROFILE_NAME` or `-p PROFILE_NAME`: AWS profile to use for pushing to ECR\n\n`--external-id EXTERNAL_ID` or `-e EXTERNAL_ID`: Optional external id used when using an IAM role\n\n#### Example\n\n sagify push\n \n\n### Cloud Upload Data\n\n#### Name\n\nUploads data to AWS S3\n\n#### Synopsis\n\n sagify cloud upload-data --input-dir LOCAL_INPUT_DATA_DIR --s3-dir S3_TARGET_DATA_LOCATION\n \n#### Description\n \nThis command uploads content under `LOCAL_INPUT_DATA_DIR` to S3 under `S3_TARGET_DATA_LOCATION`\n\n#### Required Flags\n\n`--input-dir LOCAL_INPUT_DATA_DIR` or `-i LOCAL_INPUT_DATA_DIR`: Local input directory\n\n`--s3-dir S3_TARGET_DATA_LOCATION` or `-s S3_TARGET_DATA_LOCATION`: S3 target location\n\n#### Example\n\n sagify cloud upload-data -i ./training_data/ -s s3://my-bucket/training-data/\n\n\n### Cloud Train\n\n#### Name\n\nTrains your ML/DL model using a Docker image on AWS SageMaker with input from S3\n\n#### Synopsis\n\n sagify cloud train --input-s3-dir INPUT_DATA_S3_LOCATION --output-s3-dir S3_LOCATION_TO_SAVE_OUTPUT --ec2-type EC2_TYPE [--hyperparams-file HYPERPARAMS_JSON_FILE] [--volume-size EBS_SIZE_IN_GB] [--time-out TIME_OUT_IN_SECS] [--aws-tags TAGS] [--iam-role-arn IAM_ROLE] [--external-id EXTERNAL_ID] [--base-job-name BASE_JOB_NAME] [--job-name JOB_NAME] [--metric-names COMMA_SEPARATED_METRIC_NAMES] [--use-spot-instances FLAG_TO_USE_SPOT_INSTANCES]\n\n#### Description\n\nThis command retrieves a Docker image from AWS Elastic Container Service and executes it on AWS SageMaker in train mode\n\n#### Required Flags\n\n`--input-s3-dir INPUT_DATA_S3_LOCATION` or `-i INPUT_DATA_S3_LOCATION`: S3 location to input data\n\n`--output-s3-dir S3_LOCATION_TO_SAVE_OUTPUT` or `-o S3_LOCATION_TO_SAVE_OUTPUT`: S3 location to save output (models, reports, etc). Make sure that the output bucket already exists. Any not existing key prefix will be created by sagify.\n\n`--ec2-type EC2_TYPE` or `-e EC2_TYPE`: ec2 type. Refer to \n\n#### Optional Flags\n\n`--hyperparams-file HYPERPARAMS_JSON_FILE` or `-h HYPERPARAMS_JSON_FILE`: Path to hyperparams JSON file\n \n`--volume-size EBS_SIZE_IN_GB` or `-v EBS_SIZE_IN_GB`: Size in GB of the EBS volume (default: 30)\n\n`--time-out TIME_OUT_IN_SECS` or `-s TIME_OUT_IN_SECS`: Time-out in seconds (default: 24 * 60 * 60)\n\n`--aws-tags TAGS` or `-a TAGS`: Tags for labeling a training job of the form `tag1=value1;tag2=value2`. For more, see https://docs.aws.amazon.com/sagemaker/latest/dg/API_Tag.html.\n\n`--iam-role-arn IAM_ROLE` or `-r IAM_ROLE`: AWS IAM role to use for training with *SageMaker*\n\n`--external-id EXTERNAL_ID` or `-x EXTERNAL_ID`: Optional external id used when using an IAM role\n\n`--base-job-name BASE_JOB_NAME` or `-n BASE_JOB_NAME`: Optional prefix for the SageMaker training job\n\n`--job-name JOB_NAME`: Optional name for the SageMaker training job. NOTE: if a `--base-job-name` is passed along with this option, it will be ignored.\n\n`--use-spot-instances FLAG_TO_USE_SPOT_INSTANCES`: Optional flag that specifies whether to use SageMaker Managed Spot instances for training. It should be used only for training jobs that take less than 1 hour. More information: https://docs.aws.amazon.com/sagemaker/latest/dg/model-managed-spot-training.html (default: False).\n\n`--metric-names COMMA_SEPARATED_METRIC_NAMES`: Optional comma-separated metric names for tracking performance of training jobs. Example: `Precision,Recall,AUC`. Then, make sure you log these metric values using the `log_metric` function in the `train` function:\n\n```python\n...\nfrom sagify.api.hyperparameter_tuning import log_metric\nlog_metric(\"Precision:, precision)\nlog_metric(\"Accuracy\", accuracy)\n...\n```\n \n When the training jobs finishes, they will be stored in the CloudWatch algorithm metrics logs of the SageMaker training job:\n \n ![Algorithm Metrics](docs/cloud_watch_metrics.png)\n\n#### Example\n\n sagify cloud train -i s3://my-bucket/training-data/ -o s3://my-bucket/output/ -e ml.m4.xlarge -h local/path/to/hyperparams.json -v 60 -t 86400 --metric-names Accuracy,Precision\n \n \n### Cloud Hyperparameter Optimization\n\n#### Name\n\nExecutes a Docker image in hyperparameter-optimization mode on AWS SageMaker\n\n#### Synopsis\n\n sagify cloud hyperparameter-optimization --input-s3-dir INPUT_DATA_S3_LOCATION --output-s3-dir S3_LOCATION_TO_SAVE_MULTIPLE_TRAINED_MODELS --ec2-type EC2_TYPE [--hyperparams-config-file HYPERPARAM_RANGES_JSON_FILE] [--max-jobs MAX_NUMBER_OF_TRAINING_JOBS] [--max-parallel-jobs MAX_NUMBER_OF_PARALLEL_TRAINING_JOBS] [--volume-size EBS_SIZE_IN_GB] [--time-out TIME_OUT_IN_SECS] [--aws-tags TAGS] [--iam-role-arn IAM_ROLE] [--external-id EXTERNAL_ID] [--base-job-name BASE_JOB_NAME] [--job-name JOB_NAME] [--wait WAIT_UNTIL_HYPERPARAM_JOB_IS_FINISHED] [--use-spot-instances FLAG_TO_USE_SPOT_INSTANCES]\n\n#### Description\n\nThis command retrieves a Docker image from AWS Elastic Container Service and executes it on AWS SageMaker in hyperparameter-optimization mode\n\n#### Required Flags\n\n`--input-s3-dir INPUT_DATA_S3_LOCATION` or `-i INPUT_DATA_S3_LOCATION`: S3 location to input data\n\n`--output-s3-dir S3_LOCATION_TO_SAVE_OUTPUT` or `-o S3_LOCATION_TO_SAVE_OUTPUT`: S3 location to save output (models, reports, etc). Make sure that the output bucket already exists. Any not existing key prefix will be created by sagify.\n\n`--ec2-type EC2_TYPE` or `-e EC2_TYPE`: ec2 type. Refer to \n\n`--hyperparams-config-file HYPERPARAM_RANGES_JSON_FILE` or `-h HYPERPARAM_RANGES_JSON_FILE`: Local path to hyperparameters configuration file. Example:\n\n```json\n{\n\t\"ParameterRanges\": {\n\t\t\"CategoricalParameterRanges\": [\n\t\t\t{\n\t\t\t\t\"Name\": \"kernel\",\n\t\t\t\t\"Values\": [\"linear\", \"rbf\"]\n\t\t\t}\n\t\t],\n\t\t\"ContinuousParameterRanges\": [\n\t\t{\n\t\t \"MinValue\": 0.001,\n\t\t \"MaxValue\": 10,\n\t\t \"Name\": \"gamma\"\n\t\t}\n\t\t],\n\t\t\"IntegerParameterRanges\": [\n\t\t\t{\n\t\t\t\t\"Name\": \"C\",\n\t\t\t\t\"MinValue\": 1,\n\t\t\t\t\"MaxValue\": 10\n\t\t\t}\n\t\t]\n },\n \"ObjectiveMetric\": {\n \t\"Name\": \"Precision\",\n \"Type\": \"Maximize\"\n }\n}\n```\n\n#### Optional Flags\n\n`--max-jobs MAX_NUMBER_OF_TRAINING_JOBS` or `-m MAX_NUMBER_OF_TRAINING_JOBS`: Maximum total number of training jobs to start for the hyperparameter tuning job (default: 3)\n\n`--max-parallel-jobs MAX_NUMBER_OF_PARALLEL_TRAINING_JOBS` or `-p MAX_NUMBER_OF_PARALLEL_TRAINING_JOBS`: Maximum number of parallel training jobs to start (default: 1)\n \n`--volume-size EBS_SIZE_IN_GB` or `-v EBS_SIZE_IN_GB`: Size in GB of the EBS volume (default: 30)\n\n`--time-out TIME_OUT_IN_SECS` or `-s TIME_OUT_IN_SECS`: Time-out in seconds (default: 24 * 60 * 60)\n\n`--aws-tags TAGS` or `-a TAGS`: Tags for labeling a training job of the form `tag1=value1;tag2=value2`. For more, see https://docs.aws.amazon.com/sagemaker/latest/dg/API_Tag.html.\n\n`--iam-role-arn IAM_ROLE` or `-r IAM_ROLE`: AWS IAM role to use for training with *SageMaker*\n\n`--external-id EXTERNAL_ID` or `-x EXTERNAL_ID`: Optional external id used when using an IAM role\n\n`--base-job-name BASE_JOB_NAME` or `-n BASE_JOB_NAME`: Optional prefix for the SageMaker training job\n\n`--job-name JOB_NAME`: Optional name for the SageMaker training job. NOTE: if a `--base-job-name` is passed along with this option, it will be ignored. \n\n`--wait WAIT_UNTIL_HYPERPARAM_JOB_IS_FINISHED` or `-w WAIT_UNTIL_HYPERPARAM_JOB_IS_FINISHED`: Optional flag to wait until Hyperparameter Tuning is finished. (default: don't wait)\n \n`--use-spot-instances FLAG_TO_USE_SPOT_INSTANCES`: Optional flag that specifies whether to use SageMaker Managed Spot instances for training. It should be used only for training jobs that take less than 1 hour. More information: https://docs.aws.amazon.com/sagemaker/latest/dg/model-managed-spot-training.html (default: False).\n\n#### Example\n\n sagify cloud hyperparameter-optimization -i s3://my-bucket/training-data/ -o s3://my-bucket/output/ -e ml.m4.xlarge -h local/path/to/hyperparam_ranges.json -v 60 -t 86400\n\n\n### Cloud Deploy\n\n#### Name\n\nExecutes a Docker image in serve mode on AWS SageMaker\n\n#### Synopsis\n\n sagify cloud deploy --s3-model-location S3_LOCATION_TO_MODEL_TAR_GZ --num-instance NUMBER_OF_EC2_INSTANCES --ec2-type EC2_TYPE [--aws-tags TAGS] [--iam-role-arn IAM_ROLE] [--external-id EXTERNAL_ID] [--endpoint-name ENDPOINT_NAME]\n\n#### Description\n\nThis command retrieves a Docker image from AWS Elastic Container Service and executes it on AWS SageMaker in serve mode. You can update an endpoint (model or number of instances) by specifying the endpoint-name. \n\n#### Required Flags\n\n`--s3-model-location S3_LOCATION_TO_MODEL_TAR_GZ` or `-m S3_LOCATION_TO_MODEL_TAR_GZ`: S3 location to to model tar.gz\n\n`--num-instances NUMBER_OF_EC2_INSTANCES` or `n NUMBER_OF_EC2_INSTANCES`: Number of ec2 instances\n\n`--ec2-type EC2_TYPE` or `e EC2_TYPE`: ec2 type. Refer to https://aws.amazon.com/sagemaker/pricing/instance-types/\n\n#### Optional Flags\n\n`--aws-tags TAGS` or `-a TAGS`: Tags for labeling a training job of the form `tag1=value1;tag2=value2`. For more, see https://docs.aws.amazon.com/sagemaker/latest/dg/API_Tag.html.\n\n`--iam-role-arn IAM_ROLE` or `-r IAM_ROLE`: AWS IAM role to use for deploying with *SageMaker*\n\n`--external-id EXTERNAL_ID` or `-x EXTERNAL_ID`: Optional external id used when using an IAM role\n\n`--endpoint-name ENDPOINT_NAME`: Optional name for the SageMaker endpoint\n\n#### Example\n\n sagify cloud deploy -m s3://my-bucket/output/model.tar.gz -n 3 -e ml.m4.xlarge\n\n \n### Cloud Batch Transform\n\n#### Name\n\nExecutes a Docker image in batch transform mode on AWS SageMaker, i.e. runs batch predictions on user defined S3 data\n\n#### Synopsis\n\n sagify cloud batch-transform --s3-model-location S3_LOCATION_TO_MODEL_TAR_GZ --s3-input-location S3_INPUT_LOCATION --s3-output-location S3_OUTPUT_LOCATION --num-instance NUMBER_OF_EC2_INSTANCES --ec2-type EC2_TYPE [--aws-tags TAGS] [--iam-role-arn IAM_ROLE] [--external-id EXTERNAL_ID] [--wait WAIT_UNTIL_BATCH_TRANSFORM_JOB_IS_FINISHED] [--job-name JOB_NAME]\n\n#### Description\n\nThis command retrieves a Docker image from AWS Elastic Container Service and executes it on AWS SageMaker in batch transform mode, i.e. runs batch predictions on user defined S3 data. SageMaker will spin up REST container(s) and call it/them with input data(features) from a user defined S3 path.\n\nThings to do:\n\n- You should implement the predict function that expects a JSON containing the required feature values. It's the same predict function used for deploying the model as a REST service. Example of a JSON:\n\n```json\n{\n \"features\": [5.1,3.5,1.4,0.2]\n}\n```\n- The input S3 path should contain a file or multiple files where each line is a JSON, the same JSON format as the one expected in the predict function. Example of a file:\n\n```json\n{\"features\": [[5.1,3.5,1.4,0.2]]}\n{\"features\": [[4.9,3.0,1.4,0.2]]}\n{\"features\": [[4.7,3.2,1.3,0.2]]}\n{\"features\": [[4.6,3.1,1.5,0.2]]}\n```\n\n#### Required Flags\n\n`--s3-model-location S3_LOCATION_TO_MODEL_TAR_GZ` or `-m S3_LOCATION_TO_MODEL_TAR_GZ`: S3 location to to model tar.gz\n\n`--s3-input-location S3_INPUT_LOCATION` or `-i S3_INPUT_LOCATION`: s3 input data location\n\n`--s3-output-location S3_OUTPUT_LOCATION` or `-o S3_OUTPUT_LOCATION`: s3 location to save predictions\n\n`--num-instances NUMBER_OF_EC2_INSTANCES` or `n NUMBER_OF_EC2_INSTANCES`: Number of ec2 instances\n\n`--ec2-type EC2_TYPE` or `e EC2_TYPE`: ec2 type. Refer to https://aws.amazon.com/sagemaker/pricing/instance-types/\n\n#### Optional Flags\n\n`--aws-tags TAGS` or `-a TAGS`: Tags for labeling a training job of the form `tag1=value1;tag2=value2`. For more, see https://docs.aws.amazon.com/sagemaker/latest/dg/API_Tag.html.\n\n`--iam-role-arn IAM_ROLE` or `-r IAM_ROLE`: AWS IAM role to use for deploying with *SageMaker*\n\n`--external-id EXTERNAL_ID` or `-x EXTERNAL_ID`: Optional external id used when using an IAM role\n\n`--wait WAIT_UNTIL_BATCH_TRANSFORM_JOB_IS_FINISHED` or `-w WAIT_UNTIL_BATCH_TRANSFORM_JOB_IS_FINISHED`: Optional flag to wait until Batch Transform is finished. (default: don't wait)\n\n`--job-name JOB_NAME`: Optional name for the SageMaker batch transform job\n\n#### Example\n\n sagify cloud batch-transform -m s3://my-bucket/output/model.tar.gz -i s3://my-bucket/input_features -o s3://my-bucket/predictions -n 3 -e ml.m4.xlarge\n\n\n### Cloud Create Streaming Inference\n\nNOTE: THIS IS AN EXPERIMENTAL FEATURE\n\nMake sure that the following 2 policies are attached to the role you created in section \"Configure AWS Account\":\n\n![lambda_full_access](docs/lambda_full_access.png)\n\n![sqs_full_access](docs/sqs_full_access.png)\n\n#### Name\n\nCreates streaming inference pipelines\n\n#### Synopsis\n\n sagify cloud create-streaming-inference --name WORKER_NAME --endpoint-name ENDPOINT_NAME --input-topic-name FEATURES_INPUT_TOPIC_NAME --output-topic-name PREDICTIONS_OUTPUT_TOPIC_NAME --type STREAMING_INFERENCE_TYPE\n\n#### Description\n\nThis command creates a worker as a Lambda function that listens to features in the `FEATURES_INPUT_TOPIC_NAME`, calls the the endpoint `ENDPOINT_NAME` and, finally, forwards predictions to `PREDICTIONS_OUTPUT_TOPIC_NAME`.\n\n#### Required Flags\n\n`--name WORKER_NAME`: The name of the Lambda function\n\n`--endpoint-name ENDPOINT_NAME`: The name of the endpoint of the deployed model\n\n`--input-topic-name FEATURES_INPUT_TOPIC_NAME`: Topic name where features will be landed\n\n`--output-topic-name PREDICTIONS_OUTPUT_TOPIC_NAME`: Topic name where model predictions will be forwarded\n\n`--type STREAMING_INFERENCE_TYPE`: The type of streaming inference. At the moment, only `SQS` is supported!\n\n#### Example\n\n sagify cloud create-streaming-inference --name recommender-worker --endpoint-name my-recommender-endpoint-1 --input-topic-name features --output-topic-name model-predictions --type SQS\n\n\n### Cloud Delete Streaming Inference\n\nNOTE: THIS IS AN EXPERIMENTAL FEATURE\n\nMake sure that the following 2 policies are attached to the role you created in section \"Configure AWS Account\":\n\n![lambda_full_access](lambda_full_access.png)\n\n![sqs_full_access](sqs_full_access.png)\n\n#### Name\n\nDeletes streaming inference pipelines\n\n#### Synopsis\n\n sagify cloud delete-streaming-inference --name WORKER_NAME --input-topic-name FEATURES_INPUT_TOPIC_NAME --output-topic-name PREDICTIONS_OUTPUT_TOPIC_NAME --type STREAMING_INFERENCE_TYPE\n\n#### Description\n\nThis command deletes the worker (i.e. Lambda function), input topic `FEATURES_INPUT_TOPIC_NAME` and output topic `PREDICTIONS_OUTPUT_TOPIC_NAME`.\n\n#### Required Flags\n\n`--name WORKER_NAME`: The name of the Lambda function\n\n`--input-topic-name FEATURES_INPUT_TOPIC_NAME`: Topic name where features will be landed\n\n`--output-topic-name PREDICTIONS_OUTPUT_TOPIC_NAME`: Topic name where model predictions will be forwarded\n\n`--type STREAMING_INFERENCE_TYPE`: The type of streaming inference. At the moment, only `SQS` is supported!\n\n#### Example\n\n sagify cloud delete-streaming-inference --name recommender-worker --input-topic-name features --output-topic-name model-predictions --type SQS\n\n\n### Cloud Lightning Deploy\n\n#### Name\n\nCommand for lightning deployment of pre-trained ML model(s) on AWS SageMaker without code\n\n#### Synopsis\n\n sagify cloud lightning-deploy --framework FRAMEWORK --num-instances NUMBER_OF_EC2_INSTANCES --ec2-type EC2_TYPE --aws-profile AWS_PROFILE --aws-region AWS_REGION --extra-config-file EXTRA_CONFIG_FILE [--model-server-workers MODEL_SERVER_WORKERS] [--s3-model-location S3_LOCATION_TO_MODEL_TAR_GZ] [--aws-tags TAGS] [--iam-role-arn IAM_ROLE] [--external-id EXTERNAL_ID] [--endpoint-name ENDPOINT_NAME]\n\n#### Description\n\nThis command deploys a pre-trained ML model without code. \n\n#### Required Flags\n\n`--framework FRAMEWORK`: Name of the ML framework. Valid values: `sklearn`, `huggingface`, `xgboost`\n\n`--num-instances NUMBER_OF_EC2_INSTANCES` or `n NUMBER_OF_EC2_INSTANCES`: Number of ec2 instances\n\n`--ec2-type EC2_TYPE` or `e EC2_TYPE`: ec2 type. Refer to https://aws.amazon.com/sagemaker/pricing/instance-types/\n\n`--aws-profile AWS_PROFILE`: The AWS profile to use for the lightning deploy command\n\n`--aws-region AWS_REGION`: The AWS region to use for the lightning deploy command\n\n`--extra-config-file EXTRA_CONFIG_FILE`: Json file with ML framework specific arguments\n\nFor SKLearn, you have to specify the `framework_version` in the EXTRA_CONFIG_FILE and specify the S3 location to model tar.gz (i.e. tar gzip your sklearn pickled file\n\n#### Optional Flags\n\n`--s3-model-location S3_LOCATION_TO_MODEL_TAR_GZ` or `-m S3_LOCATION_TO_MODEL_TAR_GZ`: Optional S3 location to model tar.gz\n\n`--aws-tags TAGS` or `-a TAGS`: Tags for labeling a training job of the form `tag1=value1;tag2=value2`. For more, see https://docs.aws.amazon.com/sagemaker/latest/dg/API_Tag.html.\n\n`--iam-role-arn IAM_ROLE` or `-r IAM_ROLE`: AWS IAM role to use for deploying with *SageMaker*\n\n`--external-id EXTERNAL_ID` or `-x EXTERNAL_ID`: Optional external id used when using an IAM role\n\n`--endpoint-name ENDPOINT_NAME`: Optional name for the SageMaker endpoint\n\n#### Example for SKLearn\n\nCompress your pre-trained sklearn model to a GZIP tar archive with command `!tar czvf model.tar.gz $your_sklearn_model_name`.\n\n sagify cloud lightning-deploy --framework sklearn -n 1 -e ml.c4.2xlarge --extra-config-file sklearn_config.json --aws-region us-east-1 --aws-profile sagemaker-dev -m s3://my-bucket/output/model.tar.gz\n\nThe `sklearn_config.json` must contain the following flag `framework_version`. Supported sklearn version(s): 0.20.0, 0.23-1.\n \nExample of `sklearn_config.json`:\n\n {\n \"framework_version\": \"0.23-1\"\n }\n\n#### Example for HuggingFace by specifying the `S3_LOCATION_TO_MODEL_TAR_GZ`\n\nCompress your pre-trained HuggingFace model to a GZIP tar archive with command `!tar czvf model.tar.gz $your_hg_model_name`.\n\n sagify cloud lightning-deploy --framework huggingface -n 1 -e ml.c4.2xlarge --extra-config-file huggingface_config.json --aws-region us-east-1 --aws-profile sagemaker-dev -m s3://my-bucket/output/model.tar.gz\n\nThe `huggingface_config.json` must contain the following flags `pytorch_version` or `tensorflow_version` (not both), and `transformers_version`. For more info: https://sagemaker.readthedocs.io/en/stable/frameworks/huggingface/sagemaker.huggingface.html#hugging-face-model.\n \nExample of `huggingface_config.json`:\n\n {\n \"transformers_version\": \"4.6.1\",\n \"pytorch_version\": \"1.7.1\"\n }\n\n#### Example for HuggingFace without specifying the `S3_LOCATION_TO_MODEL_TAR_GZ`\n\n sagify cloud lightning-deploy --framework huggingface -n 1 -e ml.c4.2xlarge --extra-config-file huggingface_config.json --aws-region us-east-1 --aws-profile sagemaker-dev\n\n\nThe `huggingface_config.json` must contain the following flags `pytorch_version` or `tensorflow_version` (not both), `transformers_version` and `hub`. For more info: https://sagemaker.readthedocs.io/en/stable/frameworks/huggingface/sagemaker.huggingface.html#hugging-face-model.\n \nExample of `huggingface_config.json`:\n\n {\n \"transformers_version\": \"4.6.1\",\n \"pytorch_version\": \"1.7.1\",\n \"hub\": {\n \"HF_MODEL_ID\": \"gpt2\",\n \"HF_TASK\": \"text-generation\"\n }\n }\n \n#### Example for XGBoost\n\nCompress your pre-trained XGBoost model to a GZIP tar archive with command `!tar czvf model.tar.gz $your_xgboost_model_name`.\n\n sagify cloud lightning-deploy --framework xgboost -n 1 -e ml.c4.2xlarge --extra-config-file xgboost_config.json --aws-region us-east-1 --aws-profile sagemaker-dev -m s3://my-bucket/output/model.tar.gz\n\nThe `xgboost_config.json` must contain the following flag `framework_version`. Supported xgboost version(s): 0.90-2, 1.0-1, and later.\n \nExample of `xgboost_config.json`:\n\n {\n \"framework_version\": \"0.23-1\"\n }\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/Kenza-AI/sagify", "keywords": "sagify machine-learning machine-learning-deploy machine-learning-production deep-learning-production deep-learning cli aws sagemaker tensorflow mxnet scikit-learn artificial-intelligence keras cntk deploy", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "sagify", "package_url": "https://pypi.org/project/sagify/", "platform": "", "project_url": "https://pypi.org/project/sagify/", "project_urls": { "Homepage": "https://github.com/Kenza-AI/sagify" }, "release_url": "https://pypi.org/project/sagify/0.23.0/", "requires_dist": null, "requires_python": "~=3.7", "summary": "Continuous Machine Learning Training and Deployment on AWS SageMaker", "version": "0.23.0", "yanked": false, "yanked_reason": null }, "last_serial": 12738493, "releases": { "0.10": [ { "comment_text": "", "digests": { "md5": "8913d89beeb46897cb0a464c7110612a", "sha256": "322424cad0f6c94f42f8e4458d5cf9de999fa0522d53bc46e63d9c96a6f32b2a" }, "downloads": -1, "filename": "sagify-0.10.tar.gz", "has_sig": false, "md5_digest": "8913d89beeb46897cb0a464c7110612a", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 26788, "upload_time": "2018-07-09T15:49:16", "upload_time_iso_8601": "2018-07-09T15:49:16.216284Z", "url": "https://files.pythonhosted.org/packages/ec/85/2ac7bc9e4296c76a525153cc0927e1ffdc844ae2018ab61b07a70308f330/sagify-0.10.tar.gz", "yanked": false, "yanked_reason": null } ], "0.11.0": [ { "comment_text": "", "digests": { "md5": "8fe3e1b753b49e273892880a7c0eb812", "sha256": "81b56f97e196c81fc44441d94e451a8e49e657460a4f3c86af796b95cd157bbb" }, "downloads": -1, "filename": "sagify-0.11.0.tar.gz", "has_sig": false, "md5_digest": "8fe3e1b753b49e273892880a7c0eb812", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 27030, "upload_time": "2018-07-29T15:19:18", "upload_time_iso_8601": "2018-07-29T15:19:18.553589Z", "url": "https://files.pythonhosted.org/packages/f4/ef/9d722617e6ea5fe5fc5b4ed47f2ca882ec120593fe37f25f32b57cecea17/sagify-0.11.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.12.0": [ { "comment_text": "", "digests": { "md5": "43361c66f7783c42d635b7b29d314158", "sha256": "0413f6dea4c1f728c305656152b41569b02ebff62aae7af98f139334f27aecb4" }, "downloads": -1, "filename": "sagify-0.12.0.tar.gz", "has_sig": false, "md5_digest": "43361c66f7783c42d635b7b29d314158", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 27026, "upload_time": "2018-09-30T16:35:44", "upload_time_iso_8601": "2018-09-30T16:35:44.436642Z", "url": "https://files.pythonhosted.org/packages/20/ae/886022af96ebb6de7113fe856945629a0fd73de00eca89481d6f7971cfe7/sagify-0.12.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.12.1": [ { "comment_text": "", "digests": { "md5": "a711e2395cf3aa02cbe08fbfa883d9c1", "sha256": "bcc7978644b7e237699dfd6ce2e8257e9601393b75a5c870744195d45444cec9" }, "downloads": -1, "filename": "sagify-0.12.1.tar.gz", "has_sig": false, "md5_digest": "a711e2395cf3aa02cbe08fbfa883d9c1", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 27181, "upload_time": "2018-11-05T19:31:28", "upload_time_iso_8601": "2018-11-05T19:31:28.015952Z", "url": "https://files.pythonhosted.org/packages/38/07/0967d10563d095f22235d630ea24bba98c78660cdc00f2903b45bfc15dc8/sagify-0.12.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.12.2": [ { "comment_text": "", "digests": { "md5": "f4bfb8c56a261b8ed61c831db0343757", "sha256": "a8b93c9d70e245bcb1a94858e6944c58b18f8aae490fbe0a8984ffa232186f8a" }, "downloads": -1, "filename": "sagify-0.12.2.tar.gz", "has_sig": false, "md5_digest": "f4bfb8c56a261b8ed61c831db0343757", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 27184, "upload_time": "2018-11-06T10:29:57", "upload_time_iso_8601": "2018-11-06T10:29:57.583320Z", "url": "https://files.pythonhosted.org/packages/c4/57/7ca3f3b372d0706737d8f6890b4a973ce234f9a4f2a47463551ea8c8c9b8/sagify-0.12.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.13.1": [ { "comment_text": "", "digests": { "md5": "b4be31c82e076b7c16fe0bf8d5c5edb2", "sha256": "c31786407b471907775d1a49fb11cee61e3afcd675bd38c2534407dd792b9d7a" }, "downloads": -1, "filename": "sagify-0.13.1.tar.gz", "has_sig": false, "md5_digest": "b4be31c82e076b7c16fe0bf8d5c5edb2", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 28587, "upload_time": "2018-11-12T16:07:04", "upload_time_iso_8601": "2018-11-12T16:07:04.142783Z", "url": "https://files.pythonhosted.org/packages/7e/75/7c33e08524feff07d5f64a843af783fd033006b6584e7a69c2474190917c/sagify-0.13.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.14.0": [ { "comment_text": "", "digests": { "md5": "44c5b8d54c1eca4ef60e29316aba8912", "sha256": "ef166e13d251ab2cd07e011007aa0127296112190df9a9ee274b1656c3828204" }, "downloads": -1, "filename": "sagify-0.14.0.tar.gz", "has_sig": false, "md5_digest": "44c5b8d54c1eca4ef60e29316aba8912", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 29333, "upload_time": "2018-11-15T21:55:39", "upload_time_iso_8601": "2018-11-15T21:55:39.641039Z", "url": "https://files.pythonhosted.org/packages/d2/e6/1ed6dba7f936df1e2202ee7bd9a37afddb02de2cf63da3761248c2962100/sagify-0.14.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.14.1": [ { "comment_text": "", "digests": { "md5": "9912a092eaea3a2685058c41d0eb90f9", "sha256": "0fb37a3ece7226d91a86b04239ce7d8d0f011e58318af85e1b53fdeaf9ffbbe0" }, "downloads": -1, "filename": "sagify-0.14.1.tar.gz", "has_sig": false, "md5_digest": "9912a092eaea3a2685058c41d0eb90f9", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 29453, "upload_time": "2018-11-25T20:11:43", "upload_time_iso_8601": "2018-11-25T20:11:43.803181Z", "url": "https://files.pythonhosted.org/packages/58/6d/6c1fadbf7f3a776a245147c6f986527a89c28f12bf32376df23c4c0022cf/sagify-0.14.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.15.0": [ { "comment_text": "", "digests": { "md5": "e9a500b5f05b5db0b502475300d1cbcb", "sha256": "aab9cf059fd1410c3f9a2abb4a09de8761cd210b863e68e08e4fce1162f15c04" }, "downloads": -1, "filename": "sagify-0.15.0.tar.gz", "has_sig": false, "md5_digest": "e9a500b5f05b5db0b502475300d1cbcb", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 31693, "upload_time": "2019-01-13T21:36:53", "upload_time_iso_8601": "2019-01-13T21:36:53.367069Z", "url": "https://files.pythonhosted.org/packages/22/45/b036998dc9ea4d2f7fdcae58e4795588d6cc0da10d01d5297910144362e9/sagify-0.15.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.15.1": [ { "comment_text": "", "digests": { "md5": "2c455e3efa0ca0e3e75ca7392b411a7d", "sha256": "bf495b4f096f842d945b13f85478b628ac91e1c72cc3ce451c9f19d505829264" }, "downloads": -1, "filename": "sagify-0.15.1.tar.gz", "has_sig": false, "md5_digest": "2c455e3efa0ca0e3e75ca7392b411a7d", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 31941, "upload_time": "2019-03-02T11:22:34", "upload_time_iso_8601": "2019-03-02T11:22:34.497208Z", "url": "https://files.pythonhosted.org/packages/82/68/3e502ef015fd9f01ef2b4dcee2bb4de362ec4c21f589fd66f9e19a88d723/sagify-0.15.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.16.0": [ { "comment_text": "", "digests": { "md5": "f5a08a6396dbcafa9bd381c487f6c59d", "sha256": "6c812157f49271c9b733ecc20f05ce22c390e2420552bab261f38ccb50f4f715" }, "downloads": -1, "filename": "sagify-0.16.0.tar.gz", "has_sig": false, "md5_digest": "f5a08a6396dbcafa9bd381c487f6c59d", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 37636, "upload_time": "2019-04-18T17:30:31", "upload_time_iso_8601": "2019-04-18T17:30:31.825230Z", "url": "https://files.pythonhosted.org/packages/b9/01/27ba64442b4e6ac4ce29b706831e360d7f2ee5411879b565b905f1d12dd9/sagify-0.16.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.16.1": [ { "comment_text": "", "digests": { "md5": "3a6c3b8ecb09573b999ba67b6b140664", "sha256": "58db1ffd8110a06976307f1d0c01e33e24844ccd6e6bc03c5bd20bc1f240f6ef" }, "downloads": -1, "filename": "sagify-0.16.1.tar.gz", "has_sig": false, "md5_digest": "3a6c3b8ecb09573b999ba67b6b140664", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39375, "upload_time": "2019-05-12T17:47:28", "upload_time_iso_8601": "2019-05-12T17:47:28.348674Z", "url": "https://files.pythonhosted.org/packages/8e/22/27e15d154e89b0731c7aaee8ba8168efd8884cacfe58efb05f5bc39b7010/sagify-0.16.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.17.0": [ { "comment_text": "", "digests": { "md5": "5b0f3498081ff2a47cbafa61710a5ccf", "sha256": "abc29e551c8332c33a5410c026cd247f25ef8ec11e560bf1c853cf120bc5d5d1" }, "downloads": -1, "filename": "sagify-0.17.0.tar.gz", "has_sig": false, "md5_digest": "5b0f3498081ff2a47cbafa61710a5ccf", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39030, "upload_time": "2019-05-14T08:53:41", "upload_time_iso_8601": "2019-05-14T08:53:41.114363Z", "url": "https://files.pythonhosted.org/packages/30/6b/6caf2ca316f16943a2d2f9ba5f01576d964829f97b5448ca60427645e880/sagify-0.17.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.17.1": [ { "comment_text": "", "digests": { "md5": "98a63bd972191a60bd8184f9b3ded524", "sha256": "801fa394259c0b248a1f8fc6cade04bb003c40eccf85fd381f95d242c00d76b0" }, "downloads": -1, "filename": "sagify-0.17.1.tar.gz", "has_sig": false, "md5_digest": "98a63bd972191a60bd8184f9b3ded524", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39254, "upload_time": "2019-05-27T15:04:03", "upload_time_iso_8601": "2019-05-27T15:04:03.440690Z", "url": "https://files.pythonhosted.org/packages/b8/da/b1fd5e58ad4d7e25157c4426e21653f174f16060b5d93ec296d9e4078b45/sagify-0.17.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.17.2": [ { "comment_text": "", "digests": { "md5": "429b80f6e3f7e5af075e46fe3125b22d", "sha256": "8f0944e9f14613ed19e63b7151f74bde8356cf8812be50913cfa30a5cdb43963" }, "downloads": -1, "filename": "sagify-0.17.2.tar.gz", "has_sig": false, "md5_digest": "429b80f6e3f7e5af075e46fe3125b22d", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39246, "upload_time": "2019-05-27T15:16:50", "upload_time_iso_8601": "2019-05-27T15:16:50.652237Z", "url": "https://files.pythonhosted.org/packages/9d/5d/daf59ce009f5dffd55cc22c043f5c7d473803559c39b83c72e1350c291fe/sagify-0.17.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.17.3": [ { "comment_text": "", "digests": { "md5": "d2a473e4bf74c996bc72d7769321b544", "sha256": "32f687dbd4e110028991e187841c0107de21440c6133b5e66e89cd7f12051393" }, "downloads": -1, "filename": "sagify-0.17.3.tar.gz", "has_sig": false, "md5_digest": "d2a473e4bf74c996bc72d7769321b544", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39248, "upload_time": "2019-05-27T15:20:42", "upload_time_iso_8601": "2019-05-27T15:20:42.246782Z", "url": "https://files.pythonhosted.org/packages/ad/19/bd956cd5ae6e99d714f10672e0435119bd47b1face38e5cf834b3a2c6c4f/sagify-0.17.3.tar.gz", "yanked": false, "yanked_reason": null } ], "0.17.4": [ { "comment_text": "", "digests": { "md5": "80640d447e91981c1ce14eb5087eead6", "sha256": "c87ba19283958821fc4561ccbbde23d773c1a8b670746aada4d9567148f17970" }, "downloads": -1, "filename": "sagify-0.17.4.tar.gz", "has_sig": false, "md5_digest": "80640d447e91981c1ce14eb5087eead6", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39527, "upload_time": "2019-06-03T13:21:31", "upload_time_iso_8601": "2019-06-03T13:21:31.214110Z", "url": "https://files.pythonhosted.org/packages/da/84/50e2e85f2e2e3306b0e57ceec7eea5890c5ae4b7e749b089b928a16d57a4/sagify-0.17.4.tar.gz", "yanked": false, "yanked_reason": null } ], "0.17.5": [ { "comment_text": "", "digests": { "md5": "f5c9dcec732f1420dc8d6ec08ae433ea", "sha256": "4c5dc08aaecb8200c4762cb862abac8bfec0898c927f9b079bfe40723733491e" }, "downloads": -1, "filename": "sagify-0.17.5.tar.gz", "has_sig": false, "md5_digest": "f5c9dcec732f1420dc8d6ec08ae433ea", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 40284, "upload_time": "2019-06-12T20:44:34", "upload_time_iso_8601": "2019-06-12T20:44:34.861951Z", "url": "https://files.pythonhosted.org/packages/11/61/f4feeaea95e418bbe8e02e8f85d7360bfe49a2f79c2fd017529066577a62/sagify-0.17.5.tar.gz", "yanked": false, "yanked_reason": null } ], "0.17.6": [ { "comment_text": "", "digests": { "md5": "6103aabd0393c9d836a8ea9daa82184e", "sha256": "fffee54bc502f994577e9b69fa7c85bc9381703f6e959f910bbef44d88843ca1" }, "downloads": -1, "filename": "sagify-0.17.6.tar.gz", "has_sig": false, "md5_digest": "6103aabd0393c9d836a8ea9daa82184e", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 40712, "upload_time": "2019-07-09T13:34:56", "upload_time_iso_8601": "2019-07-09T13:34:56.174324Z", "url": "https://files.pythonhosted.org/packages/c8/c6/40a3e5635d5c721eedfc22f798481b968187995d93e4c3bb907eef5b9871/sagify-0.17.6.tar.gz", "yanked": false, "yanked_reason": null } ], "0.17.7": [ { "comment_text": "", "digests": { "md5": "8e4aa5df2eedcb28bdd20a4ba4b5b2b8", "sha256": "c290ca749957450f1e4279b30997e695fa607979d274b06aeabff902a2b33ab7" }, "downloads": -1, "filename": "sagify-0.17.7.tar.gz", "has_sig": false, "md5_digest": "8e4aa5df2eedcb28bdd20a4ba4b5b2b8", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39388, "upload_time": "2019-09-01T12:59:14", "upload_time_iso_8601": "2019-09-01T12:59:14.205558Z", "url": "https://files.pythonhosted.org/packages/3c/80/932ad8c688837110761d208fbdce3bd17bb91a415491884cc72d10fe2234/sagify-0.17.7.tar.gz", "yanked": false, "yanked_reason": null } ], "0.17.8": [ { "comment_text": "", "digests": { "md5": "37961e57a435ee3de8a920f44e375c1e", "sha256": "666790c377dd1a5a5b7c9a1220e000a8e9b20a346595ded8f8ba0389bc6582b9" }, "downloads": -1, "filename": "sagify-0.17.8.tar.gz", "has_sig": false, "md5_digest": "37961e57a435ee3de8a920f44e375c1e", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39389, "upload_time": "2019-09-12T20:45:18", "upload_time_iso_8601": "2019-09-12T20:45:18.959243Z", "url": "https://files.pythonhosted.org/packages/4e/22/fb663be9e8578a80605af42ca3f4aa827d7254d13c380fcfc11dba3d723f/sagify-0.17.8.tar.gz", "yanked": false, "yanked_reason": null } ], "0.17.9": [ { "comment_text": "", "digests": { "md5": "b446e5c12572a6968301704a545e0662", "sha256": "383098392362ed69b224aed2c72c0e7758d15cae512315cc78d55583ab8e2560" }, "downloads": -1, "filename": "sagify-0.17.9.tar.gz", "has_sig": false, "md5_digest": "b446e5c12572a6968301704a545e0662", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39396, "upload_time": "2019-09-29T16:39:52", "upload_time_iso_8601": "2019-09-29T16:39:52.767311Z", "url": "https://files.pythonhosted.org/packages/25/b1/e06a43dbfeeebbe62a3b8a0822aae9c8640d83a151e965cc854488965475/sagify-0.17.9.tar.gz", "yanked": false, "yanked_reason": null } ], "0.18.0": [ { "comment_text": "", "digests": { "md5": "727d059360b4d05f44bd6667f8e02dd5", "sha256": "ef61099f932d6850550f26fa3e7a9378705c6a922543a5ca065c7efb82115a4e" }, "downloads": -1, "filename": "sagify-0.18.0.tar.gz", "has_sig": false, "md5_digest": "727d059360b4d05f44bd6667f8e02dd5", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39524, "upload_time": "2019-10-27T16:04:57", "upload_time_iso_8601": "2019-10-27T16:04:57.870422Z", "url": "https://files.pythonhosted.org/packages/ce/6d/981daee1080f811241a170da19b15d26f8ac60c992767131fa1c1c9081d9/sagify-0.18.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.18.1": [ { "comment_text": "", "digests": { "md5": "8006bfc827931d21361c39ac7e59b2e1", "sha256": "8080789bcadf516f5bf8b4374541a275b86414a2e2f833275135dd5e215b9554" }, "downloads": -1, "filename": "sagify-0.18.1.tar.gz", "has_sig": false, "md5_digest": "8006bfc827931d21361c39ac7e59b2e1", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39045, "upload_time": "2019-10-27T18:09:59", "upload_time_iso_8601": "2019-10-27T18:09:59.493356Z", "url": "https://files.pythonhosted.org/packages/4f/91/f487dc68bedf562f5a04d4f0b4a0bc934b936c94c94a5242e4431ce65c69/sagify-0.18.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.19.0": [ { "comment_text": "", "digests": { "md5": "aa53c090431f500cd652763190ceb19c", "sha256": "4e3a035cc39e2ba9234018fb0aad0d2784927de7a50fc912c92bbbbaf547a2bb" }, "downloads": -1, "filename": "sagify-0.19.0.tar.gz", "has_sig": false, "md5_digest": "aa53c090431f500cd652763190ceb19c", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39068, "upload_time": "2019-12-31T15:58:12", "upload_time_iso_8601": "2019-12-31T15:58:12.313823Z", "url": "https://files.pythonhosted.org/packages/72/79/833bda63c57b5751213e98fa637ea6659a1ef8feb700fda22905106ef63d/sagify-0.19.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.20.0": [ { "comment_text": "", "digests": { "md5": "fe1e1acc8213367138c33b22586c4c5c", "sha256": "9788ececac1f95c560f02550fe5f4ad9f84180f4aab2bd98ea5e0bb044c5c91f" }, "downloads": -1, "filename": "sagify-0.20.0.tar.gz", "has_sig": false, "md5_digest": "fe1e1acc8213367138c33b22586c4c5c", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39139, "upload_time": "2020-01-12T10:52:56", "upload_time_iso_8601": "2020-01-12T10:52:56.307116Z", "url": "https://files.pythonhosted.org/packages/1b/ce/162f923064bd81f04adce8c37bc1ec908ccefcbf0bd1d614ee26ddcbf4f6/sagify-0.20.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.20.1": [ { "comment_text": "", "digests": { "md5": "0342556543b55fc41f7ee3da2634abb0", "sha256": "dc29d95b0f86b0d6af110e0e484f081a6d4a8d913e33752fa325d724672f72f4" }, "downloads": -1, "filename": "sagify-0.20.1.tar.gz", "has_sig": false, "md5_digest": "0342556543b55fc41f7ee3da2634abb0", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39090, "upload_time": "2020-01-25T15:37:05", "upload_time_iso_8601": "2020-01-25T15:37:05.926540Z", "url": "https://files.pythonhosted.org/packages/59/97/94aabad78dd20e3e5bac4a195136ac5697dd2a4577a1a54dd7b432fbb28a/sagify-0.20.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.20.2": [ { "comment_text": "", "digests": { "md5": "716bbcb0fc5d20334a382f724ebd21d2", "sha256": "cbb219aed04adaa0e0abefcd6d3a3f164aee5199517cb6467b8f63c7c9882cd3" }, "downloads": -1, "filename": "sagify-0.20.2.tar.gz", "has_sig": false, "md5_digest": "716bbcb0fc5d20334a382f724ebd21d2", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39112, "upload_time": "2020-01-27T20:46:08", "upload_time_iso_8601": "2020-01-27T20:46:08.676491Z", "url": "https://files.pythonhosted.org/packages/2c/74/96980c264d139c3b5f1f613d4ffdd9b15a2f6f19f54435e8b887a336a458/sagify-0.20.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.20.3": [ { "comment_text": "", "digests": { "md5": "e9a78e9bc60606a830403872972a87dd", "sha256": "223b8fd18520c7c7b54af034b2db576fbcf994cc958a5386478fdbe2e0a29dae" }, "downloads": -1, "filename": "sagify-0.20.3.tar.gz", "has_sig": false, "md5_digest": "e9a78e9bc60606a830403872972a87dd", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39137, "upload_time": "2020-01-29T22:26:27", "upload_time_iso_8601": "2020-01-29T22:26:27.713971Z", "url": "https://files.pythonhosted.org/packages/4d/49/4164631576bacba0d1a4d3444e521c3355041a26c5bfe8a4b24ef2245843/sagify-0.20.3.tar.gz", "yanked": false, "yanked_reason": null } ], "0.20.4": [ { "comment_text": "", "digests": { "md5": "405e634ad15c0bc48f5f62867704a65d", "sha256": "3644ded901437b2b7b9a4f79b4b682343641c783a11d6ef08a4f6617e513ecab" }, "downloads": -1, "filename": "sagify-0.20.4.tar.gz", "has_sig": false, "md5_digest": "405e634ad15c0bc48f5f62867704a65d", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39778, "upload_time": "2020-02-17T19:52:13", "upload_time_iso_8601": "2020-02-17T19:52:13.650281Z", "url": "https://files.pythonhosted.org/packages/15/cb/95600e705938455dfcb736696e2de0ca9cb9794429e8c555c683dc717a0a/sagify-0.20.4.tar.gz", "yanked": false, "yanked_reason": null } ], "0.20.5": [ { "comment_text": "", "digests": { "md5": "09c281dd9175cfcfb6745dd382494926", "sha256": "c5dc549ecdf60eee592cb4c056ce140c7e04219efeb2d4922d93632b058ebaee" }, "downloads": -1, "filename": "sagify-0.20.5.tar.gz", "has_sig": false, "md5_digest": "09c281dd9175cfcfb6745dd382494926", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 39785, "upload_time": "2020-02-21T17:41:15", "upload_time_iso_8601": "2020-02-21T17:41:15.979655Z", "url": "https://files.pythonhosted.org/packages/d3/9c/38083ad247cef9877052a75dcf8c7005bd8403174aca9d6dd1022f2395b2/sagify-0.20.5.tar.gz", "yanked": false, "yanked_reason": null } ], "0.20.6": [ { "comment_text": "", "digests": { "md5": "3ac96852694d28f03adbb5aa6d7b31f5", "sha256": "e499fa14a6bf01834c80e58668679c790b066ee175485ea5d5d6fef2d3b733bc" }, "downloads": -1, "filename": "sagify-0.20.6.tar.gz", "has_sig": false, "md5_digest": "3ac96852694d28f03adbb5aa6d7b31f5", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.5", "size": 39774, "upload_time": "2020-02-22T11:33:07", "upload_time_iso_8601": "2020-02-22T11:33:07.204746Z", "url": "https://files.pythonhosted.org/packages/f6/be/2a9fcc11a2143f7731e955107dc02e890ff95578b82fd6e1337d14d36a2e/sagify-0.20.6.tar.gz", "yanked": false, "yanked_reason": null } ], "0.20.7": [ { "comment_text": "", "digests": { "md5": "a64c04c77998d6f117a3c6f3f823f685", "sha256": "e8692b0814476c005b1617867356d9f2daea5c88554a6df7a3c0c6291704784a" }, "downloads": -1, "filename": "sagify-0.20.7.tar.gz", "has_sig": false, "md5_digest": "a64c04c77998d6f117a3c6f3f823f685", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.5", "size": 39893, "upload_time": "2020-12-31T17:24:55", "upload_time_iso_8601": "2020-12-31T17:24:55.847309Z", "url": "https://files.pythonhosted.org/packages/96/d5/f36ab4241e98aa15e6a901f5c0d8f2a3f0aab9a28f0ea0bae03867b0ad4d/sagify-0.20.7.tar.gz", "yanked": false, "yanked_reason": null } ], "0.20.8": [ { "comment_text": "", "digests": { "md5": "27f644528ad0f96f7f39afa2b0ec4b71", "sha256": "b54613c9f12834e636b9df1d864623f66692b1423b5b4919058188b899e8e759" }, "downloads": -1, "filename": "sagify-0.20.8.tar.gz", "has_sig": false, "md5_digest": "27f644528ad0f96f7f39afa2b0ec4b71", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.5", "size": 39991, "upload_time": "2021-01-21T18:28:56", "upload_time_iso_8601": "2021-01-21T18:28:56.616087Z", "url": "https://files.pythonhosted.org/packages/40/6b/365b59bbcccaf8e67c1a5e1a3ba1376834e1faeafb576f045f06994a56af/sagify-0.20.8.tar.gz", "yanked": false, "yanked_reason": null } ], "0.20.9": [ { "comment_text": "", "digests": { "md5": "02b2bc0e8c44e5b97348556d956fd9fe", "sha256": "dca428747f8edc507bb7c7747bc6def200d8b9acce8c6fdc8c6197c2a571e700" }, "downloads": -1, "filename": "sagify-0.20.9.tar.gz", "has_sig": false, "md5_digest": "02b2bc0e8c44e5b97348556d956fd9fe", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.5", "size": 40545, "upload_time": "2021-01-29T11:18:43", "upload_time_iso_8601": "2021-01-29T11:18:43.192586Z", "url": "https://files.pythonhosted.org/packages/31/36/75fcfac4b702342322c03e272d56a5637d12d08447f53ebed8b624ab43c0/sagify-0.20.9.tar.gz", "yanked": false, "yanked_reason": null } ], "0.21.0": [ { "comment_text": "", "digests": { "md5": "01397b4807f91cb86d71a5295193109e", "sha256": "7e7ed1df1f3419c4c173497463c27595d8039f3074a34b481fc9d74e7dd4dbe8" }, "downloads": -1, "filename": "sagify-0.21.0.tar.gz", "has_sig": false, "md5_digest": "01397b4807f91cb86d71a5295193109e", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.5", "size": 44823, "upload_time": "2021-02-23T21:00:42", "upload_time_iso_8601": "2021-02-23T21:00:42.671873Z", "url": "https://files.pythonhosted.org/packages/38/7e/3da1be50493ee22ca2c26951abfb00944a554195e65bfa7567e4bf820841/sagify-0.21.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.21.1": [ { "comment_text": "", "digests": { "md5": "4f63fd0e0dacfce23482a845d96ead81", "sha256": "75e201771ffce23ee1384df26fe95c7993dbfbdd629fbdd70033121e6a6e9434" }, "downloads": -1, "filename": "sagify-0.21.1.tar.gz", "has_sig": false, "md5_digest": "4f63fd0e0dacfce23482a845d96ead81", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.6", "size": 41642, "upload_time": "2022-01-03T17:56:47", "upload_time_iso_8601": "2022-01-03T17:56:47.320898Z", "url": "https://files.pythonhosted.org/packages/f1/b5/08600e2abd4861daa1a300f227eaff5fa92d58b533fc9b60bcfb99271f71/sagify-0.21.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.21.2": [ { "comment_text": "", "digests": { "md5": "da20fda3dc2c400f45acd1fd4f37bc14", "sha256": "280adf28cb60a93f18c1eea8448e65f9105aac6e310aba16d1393d8b33ca6fab" }, "downloads": -1, "filename": "sagify-0.21.2.tar.gz", "has_sig": false, "md5_digest": "da20fda3dc2c400f45acd1fd4f37bc14", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.7", "size": 45898, "upload_time": "2022-01-05T12:23:57", "upload_time_iso_8601": "2022-01-05T12:23:57.141442Z", "url": "https://files.pythonhosted.org/packages/67/58/28dca3c28c8f7dd0b6b401a2f87efd1a857f84c29cd76a8d757598562fe4/sagify-0.21.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.21.3": [ { "comment_text": "", "digests": { "md5": "e905ae2999f31cf73c3df16ab8b5c02b", "sha256": "ba5000d0fc897c6e9cd92fbc8c3e7631688e5a60f418efc7ff9cb0aa99eb1eca" }, "downloads": -1, "filename": "sagify-0.21.3.tar.gz", "has_sig": false, "md5_digest": "e905ae2999f31cf73c3df16ab8b5c02b", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.7", "size": 45864, "upload_time": "2022-01-05T13:18:21", "upload_time_iso_8601": "2022-01-05T13:18:21.616499Z", "url": "https://files.pythonhosted.org/packages/ac/89/ed26c2a9b12ab6ea9d2722587f659b206c658322c202a144efe2196a5c9c/sagify-0.21.3.tar.gz", "yanked": false, "yanked_reason": null } ], "0.22.0": [ { "comment_text": "", "digests": { "md5": "2896ee38381abb407b21f36f8533d488", "sha256": "46c3ed9aab663b8b1ac3b5ab094fc5c9eac84dafe3107ca044074394b49502ba" }, "downloads": -1, "filename": "sagify-0.22.0.tar.gz", "has_sig": false, "md5_digest": "2896ee38381abb407b21f36f8533d488", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.7", "size": 56302, "upload_time": "2022-01-16T13:22:59", "upload_time_iso_8601": "2022-01-16T13:22:59.696631Z", "url": "https://files.pythonhosted.org/packages/9a/14/ef8046e446eb79ab1ce16cb74514dd1e1241cafb0a95a089c0fd55426a1b/sagify-0.22.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.23.0": [ { "comment_text": "", "digests": { "md5": "edf82cda903376c67cca61143be27fae", "sha256": "1887868bc44bcdb313e85b595178374caf6b346c9ab858924293b8a4b1b9e25e" }, "downloads": -1, "filename": "sagify-0.23.0.tar.gz", "has_sig": false, "md5_digest": "edf82cda903376c67cca61143be27fae", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.7", "size": 56826, "upload_time": "2022-01-30T17:58:25", "upload_time_iso_8601": "2022-01-30T17:58:25.343673Z", "url": "https://files.pythonhosted.org/packages/27/10/243ce6e20a73ac6b6959481355c70f2c927fd82f19d4519d93d7165cd495/sagify-0.23.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4": [ { "comment_text": "", "digests": { "md5": "d52850e53b0d98f22481e3ed4d64fe78", "sha256": "660cc9a0569c4948d6a85839acf906084bf14540bb9bade19201f6e813a0c323" }, "downloads": -1, "filename": "sagify-0.4.tar.gz", "has_sig": false, "md5_digest": "d52850e53b0d98f22481e3ed4d64fe78", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 24246, "upload_time": "2018-05-03T10:51:27", "upload_time_iso_8601": "2018-05-03T10:51:27.816440Z", "url": "https://files.pythonhosted.org/packages/dd/6f/c76fb26ea57343b281811072e6024fa53e1d0180b60bb0a904427d520b44/sagify-0.4.tar.gz", "yanked": false, "yanked_reason": null } ], "0.5": [ { "comment_text": "", "digests": { "md5": "e6be092ebd7e94fbd44534bb342169f5", "sha256": "edc36489a5eb62cba7bca6a3d8141b2618c4b8c6046fc8ee16293b4f1c043c37" }, "downloads": -1, "filename": "sagify-0.5.tar.gz", "has_sig": false, "md5_digest": "e6be092ebd7e94fbd44534bb342169f5", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 24247, "upload_time": "2018-05-13T16:46:43", "upload_time_iso_8601": "2018-05-13T16:46:43.802531Z", "url": "https://files.pythonhosted.org/packages/37/06/86172b32c22b847752abddaecea5fd09cfad3b2e963dc540c2cd537083e7/sagify-0.5.tar.gz", "yanked": false, "yanked_reason": null } ], "0.6": [ { "comment_text": "", "digests": { "md5": "ef1bbf9fc2ffe95712482bbebd691610", "sha256": "26f4bda90a76a5133cb38323de4202a941fd0e14a23eca5435e1b149b4aaebf5" }, "downloads": -1, "filename": "sagify-0.6.tar.gz", "has_sig": false, "md5_digest": "ef1bbf9fc2ffe95712482bbebd691610", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 25127, "upload_time": "2018-06-16T20:33:40", "upload_time_iso_8601": "2018-06-16T20:33:40.506076Z", "url": "https://files.pythonhosted.org/packages/31/dd/6bc7c8a0208c6e0a9c048a9fbee1e31d589bea5ffa7eaad6a6a44604e75a/sagify-0.6.tar.gz", "yanked": false, "yanked_reason": null } ], "0.7": [ { "comment_text": "", "digests": { "md5": "e2d33a10f9380eae1fa254145a153aa0", "sha256": "c17c24e281fbf0335dedbbdcadb61fb4ef283924366de982d4ab67421ea0add1" }, "downloads": -1, "filename": "sagify-0.7.tar.gz", "has_sig": false, "md5_digest": "e2d33a10f9380eae1fa254145a153aa0", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 25139, "upload_time": "2018-06-20T21:25:35", "upload_time_iso_8601": "2018-06-20T21:25:35.734152Z", "url": "https://files.pythonhosted.org/packages/19/dc/286e6eb3f41ebf1bd1489ffc1d4901b1550d4453eb8d66ef52dc670d03d9/sagify-0.7.tar.gz", "yanked": false, "yanked_reason": null } ], "0.8": [ { "comment_text": "", "digests": { "md5": "bcd017ba40fda38ff5f9d00a9ad20616", "sha256": "336fb6052b6051bec8f4008020a8d5c67a25ea72a81ecb45239d27ef72d8ad17" }, "downloads": -1, "filename": "sagify-0.8.tar.gz", "has_sig": false, "md5_digest": "bcd017ba40fda38ff5f9d00a9ad20616", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 25175, "upload_time": "2018-06-22T07:33:32", "upload_time_iso_8601": "2018-06-22T07:33:32.433953Z", "url": "https://files.pythonhosted.org/packages/c3/dd/91985a81dd310b980a84ca16fc57ffaac5201208026d09baabb9378c3372/sagify-0.8.tar.gz", "yanked": false, "yanked_reason": null } ], "0.9": [ { "comment_text": "", "digests": { "md5": "075e51fe9ab881f1d35f4b853135dbe5", "sha256": "ad35cdb06e55533365821b309b49b5347a4c6632b614e7d756d599e8d175400c" }, "downloads": -1, "filename": "sagify-0.9.tar.gz", "has_sig": false, "md5_digest": "075e51fe9ab881f1d35f4b853135dbe5", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 26544, "upload_time": "2018-07-03T07:02:58", "upload_time_iso_8601": "2018-07-03T07:02:58.288734Z", "url": "https://files.pythonhosted.org/packages/ec/8c/7de4bbb954a9a251ee39f1928a5fca4448fa4ff5edc2501a42cb0b6ece3c/sagify-0.9.tar.gz", "yanked": false, "yanked_reason": null } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "edf82cda903376c67cca61143be27fae", "sha256": "1887868bc44bcdb313e85b595178374caf6b346c9ab858924293b8a4b1b9e25e" }, "downloads": -1, "filename": "sagify-0.23.0.tar.gz", "has_sig": false, "md5_digest": "edf82cda903376c67cca61143be27fae", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.7", "size": 56826, "upload_time": "2022-01-30T17:58:25", "upload_time_iso_8601": "2022-01-30T17:58:25.343673Z", "url": "https://files.pythonhosted.org/packages/27/10/243ce6e20a73ac6b6959481355c70f2c927fd82f19d4519d93d7165cd495/sagify-0.23.0.tar.gz", "yanked": false, "yanked_reason": null } ], "vulnerabilities": [] }