diff --git a/.gitmodules b/.gitmodules index 1cb8fec..96af25c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,8 @@ -[submodule "pyfluigi"] - path = pyfluigi - url = https://github.com/CIDARLAB/pyFluigi.git [submodule "primitives-server"] path = primitives-server - url = https://github.com/cidarlab/3duf.git + url = https://github.com/cidarlab/3duf + branch = primitives-server +[submodule "pyfluigi"] + path = pyfluigi + url = https://github.com/cidarlab/pyfluigi + branch = master diff --git a/README.md b/README.md index db54770..084edcd 100644 --- a/README.md +++ b/README.md @@ -24,3 +24,14 @@ TBA Rest of the guide... ### Contact Reach out to [@rkrishnasanka](https://github.com/rkrishnasanka) for more details. + + +### Running individual services + +```bash +docker run -i containername:dev --env-file=myenvfile +``` + +```bash +docker exec -ti /bin/bash +``` \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index e70d00c..8cf9a76 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,45 +22,66 @@ services: - "9000:9000" - "9001:9001" volumes: - - mino_data:/data/s3 + - minio_data_container:/data/s3 environment: - - MINIO_ACCESS_KEY=minio - - MINIO_SECRET_KEY=minio123 + MINIO_ROOT_USER: ${AWS_ACCESS_KEY_ID} + MINIO_ROOT_PASSWORD: ${AWS_SECRET_ACCESS_KEY} command: server /data/s3 --console-address ":9001" restart: unless-stopped + networks: + - main_network broker: image: redis:latest container_name: realtime-comm-server ports: - "6379:6379" + restart: unless-stopped + networks: + - main_network - backend_database: + backend-database: image: mongo:latest environment: - AUTH: "yes" - MONGO_INITDB_ROOT_USERNAME: root - MONGO_INITDB_ROOT_PASSWORD: rootpassword + MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME} + MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD} ports: - 27017:27017 volumes: - mongodb_data_container:/data/db + restart: unless-stopped + networks: + - main_network worker: build: context: . dockerfile: ./job-runner/Dockerfile - container_name: demo_worker - command: celery --app=simple worker --loglevel=info + container_name: async-worker + command: python /runner/job_runner/server.py #celery --app=simple worker --loglevel=info volumes: - .:/usr/src environment: - - CELERY_BROKER_URL=redis://broker:6379 + MONGO_INITDB_NAME: ${MONGO_INITDB_NAME} + MONGO_HOST: ${MONGO_HOST} + MONGO_PORT: ${MONGO_PORT} + MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME} + MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD} + CELERY_BROKER_URL: ${CELERY_BROKER_URL} + AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID} + AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY} + AWS_S3_BUCKET_NAME: ${AWS_S3_BUCKET_NAME} + AWS_ENDPOINT_URL: ${AWS_ENDPOINT_URL} + SOCKETIO_REDIS_HOST: ${SOCKETIO_REDIS_HOST} + SOCKETIO_REDIS_PORT: ${SOCKETIO_REDIS_PORT} # - CELERY_RESULT_BACKEND=db+postgresql://dbc:dbc@backend:5432/celery depends_on: - broker - - backend_database + - backend-database - s3local + restart: unless-stopped + networks: + - main_network primitives-server: build: @@ -68,8 +89,15 @@ services: dockerfile: ./primitives-server.Dockerfile restart: unless-stopped ports: - - "6060:5555" - + - 6060:6060 + command: npm run start + networks: + - main_network + volumes: mongodb_data_container: - mino_data: + minio_data_container: + +networks: + main_network: + driver: bridge diff --git a/job-runner/Dockerfile b/job-runner/Dockerfile index eca4837..f4b3404 100644 --- a/job-runner/Dockerfile +++ b/job-runner/Dockerfile @@ -1,40 +1,39 @@ -FROM --platform=linux/amd64 python:3.8-buster as runner +FROM --platform=linux/amd64 python:3.8-buster as base ENV PYTHONFAULTHANDLER=1 \ PYTHONUNBUFFERED=1 \ PYTHONHASHSEED=random \ PIP_NO_CACHE_DIR=off \ PIP_DISABLE_PIP_VERSION_CHECK=on \ - PIP_DEFAULT_TIMEOUT=100 + PIP_DEFAULT_TIMEOUT=100 \ + POETRY_VERSION=1.1.14 RUN apt-get update RUN apt-get install -y \ software-properties-common make build-essential python3-pip \ python-dev libssl-dev zlib1g-dev libbz2-dev libreadline-dev \ libsqlite3-dev curl libffi-dev graphviz libgraphviz-dev \ -libcairo2-dev pkg-config python3-dev \ -graphviz libgraphviz-dev -#python3-pygraphviz pygraphviz +libcairo2-dev pkg-config python3-dev python3-pygraphviz apt-utils +# pygraphviz +RUN pip install "poetry==$POETRY_VERSION" +# Project initialization: +RUN poetry config virtualenvs.create false + - -RUN pip install -U celery +FROM base as runner WORKDIR /main ADD ./pyfluigi ./pyfluigi -RUN pip install ./pyfluigi/pylfr -RUN pip install ./pyfluigi +WORKDIR /main/pyfluigi + +RUN poetry install --no-dev --no-interaction --no-ansi WORKDIR /runner/ -# ADD ./job-runner /main/runner -COPY ./job-runner /runner/ +COPY ./job-runner . RUN pip install . -# RUN pip install - - - RUN fluigi --help diff --git a/job-runner/README.md b/job-runner/README.md index 28ba60b..95e5a58 100644 --- a/job-runner/README.md +++ b/job-runner/README.md @@ -3,3 +3,12 @@ Async Task Running infrastructure for the fluigi command line tool. + +# Getting Started with Dev + + +## Load the Enviroment Variables + +```bash +set -a; source .env; set +a +``` \ No newline at end of file diff --git a/job-runner/job_runner/filesystem.py b/job-runner/job_runner/filesystem.py new file mode 100644 index 0000000..c51d652 --- /dev/null +++ b/job-runner/job_runner/filesystem.py @@ -0,0 +1,48 @@ +from typing import List +import uuid +import boto3 +from pprint import pprint +from pathlib import Path + +from job_runner.setting import AWS_ENDPOINT_URL, AWS_S3_BUCKET_NAME + +S3_CLIENT = boto3.client( + "s3", + endpoint_url=AWS_ENDPOINT_URL + ) + +def upload_file_using_client(file_location: Path) -> str: + """ Uploads file to S3 bucket using S3 client object + + Args: + file_location (Path): Location of the file to upload + + Returns: + str: S3 object name + """ + bucket_name = AWS_S3_BUCKET_NAME + file_name = file_location.name + file_path = str(file_location.absolute()) + s3_object_name = f"{str(uuid.uuid4())}-{file_name}" + S3_CLIENT.upload_file(file_path, bucket_name, s3_object_name) + + print(f"Uploaded {file_path} to {bucket_name}/{file_name}") + + return s3_object_name + +def download_file_using_client(s3_object_name: str, local_file_name: str, download_directory: Path) -> None: + """ Downloads file from S3 bucket using S3 client object + + Args: + s3_object_name (str): name of the S3 object to download + local_file_name (str): name of the local file to download to + download_directory (Path): location of the file to download + + Returns: + None: None + """ + local_file_path_location = str(download_directory.joinpath(local_file_name).absolute()) + S3_CLIENT.download_file(AWS_S3_BUCKET_NAME, s3_object_name, local_file_path_location) + + print(f"Downloaded {s3_object_name} from {AWS_S3_BUCKET_NAME} to {local_file_path_location}") + \ No newline at end of file diff --git a/job-runner/job_runner/server.py b/job-runner/job_runner/server.py new file mode 100644 index 0000000..814b451 --- /dev/null +++ b/job-runner/job_runner/server.py @@ -0,0 +1,34 @@ +import imp +import os +import time +import mongoengine +from celery import Celery + +from job_runner.setting import CELERY_BROKER_URL, CELERY_BACKEND_URL, MONGO_HOST, MONGO_PORT, MONGODB_JOBS_DB, MONGODB_PASSWORD, MONGODB_USER + +print("Connecting to MongoDB") +print("MongoDB_USER:", MONGODB_USER) +print("MongoDB_PASSWORD:", MONGODB_PASSWORD) +print("MongoDB_PORT:", MONGO_PORT) +print("MongoDB_HOST:", MONGO_HOST) +print("MongoDB_JOBS_DB:", MONGODB_JOBS_DB) +connection = mongoengine.connect( + db=MONGODB_JOBS_DB, + username=MONGODB_USER, + password=MONGODB_PASSWORD, + host=MONGO_HOST, + port=MONGO_PORT +) + +# print("Databases") +# print(connection.list_database_names()) + +print("Connecting to Celery") +celery_app = Celery( + "job_runner", + broker=CELERY_BROKER_URL, + backend=CELERY_BACKEND_URL, + include=["job_runner.tasks"] +) + +celery_app.start(["-A", "job_runner.server" ,"worker", "-E","--concurrency=1", "--loglevel=INFO"]) diff --git a/job-runner/job_runner/setting.py b/job-runner/job_runner/setting.py new file mode 100644 index 0000000..87de9ad --- /dev/null +++ b/job-runner/job_runner/setting.py @@ -0,0 +1,30 @@ +import os + +# SOCKETIO REDIS CONFIGURATION +SOCKETIO_REDIS_HOST = os.getenv('SOCKETIO_REDIS_HOST') +SOCKETIO_REDIS_PORT = int(os.getenv('SOCKETIO_REDIS_PORT', 6379)) + + +# CELERY SETTINGS +CELERY_BROKER_URL = os.getenv('CELERY_BROKER_URL') +CELERY_ACCEPT_CONTENT = ['json'] +CELERY_TASK_SERIALIZER = 'json' +CELERY_RESULT_SERIALIZER = 'json' + + +# CELERY MONGO SETTINGS +MONGODB_USER = os.getenv('MONGO_INITDB_ROOT_USERNAME') +MONGODB_PASSWORD = os.getenv('MONGO_INITDB_ROOT_PASSWORD') +MONGODB_JOBS_DB = os.getenv('MONGO_INITDB_NAME') +MONGO_HOST = os.getenv('MONGO_HOST') +MONGO_PORT = int(os.getenv('MONGO_PORT', 27017)) + +CELERY_BACKEND_URL = f'mongodb://{MONGODB_USER}:{MONGODB_PASSWORD}@{MONGO_HOST}:{MONGO_PORT}/{MONGODB_JOBS_DB}' + + + +# AWS S3 SETTINGS +AWS_S3_BUCKET_NAME = os.getenv('AWS_S3_BUCKET_NAME') +AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID') +AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY') +AWS_ENDPOINT_URL = os.getenv('AWS_ENDPOINT_URL') diff --git a/job-runner/job_runner/tasks.py b/job-runner/job_runner/tasks.py index 4d3c717..e92205d 100644 --- a/job-runner/job_runner/tasks.py +++ b/job-runner/job_runner/tasks.py @@ -1,20 +1,100 @@ # import os -# from celery import Celery -# import time +from pathlib import Path +import subprocess +from sys import stdout +from typing import Dict, List, Optional, Tuple +from job_runner.filesystem import download_file_using_client, upload_file_using_client -# # broker_url = os.environ.get("CELERY_BROKER_URL", -# # "redis://localhost:6379"), -# # res_backend = os.environ.get("CELERY_RESULT_BACKEND", -# # "db+postgresql://dbc:dbc@localhost:5434/celery") +from job_runner.server import celery_app +import time +from socket_io_emitter import Emitter +import shutil -# celery_app = Celery(name = "tasks", -# broker = "redis://localhost:6379", -# # result_backend = res_backend -# ) +from .setting import SOCKETIO_REDIS_HOST, SOCKETIO_REDIS_PORT -# @celery_app.task -# def add(x, y): -# for i in range(5): -# time.sleep(1) -# print(i) -# print(x + y) + +@celery_app.task(name="add_task") +def add(x, y): + for i in range(5): + time.sleep(1) + print(i) + print(x + y) + + return x + y + +@celery_app.task(name="execute_task") +def execute( + job_id:str, + command: List[str], + input_file_s3_objects:List[Tuple[str,str]] = [], + config_file_s3_object:Optional[Tuple[str, str]] = None, +) -> Dict[str, str]: + """ Executes a command in a subprocess and returns a dictionary with the output file names and their corresponding s3 object names + + Args: + job_id (str): Unique identifier for the job + command (List[str]): Command to execute in a subprocess + input_file_s3_objects (List[Tuple[str,str]]): List of tuples containing the input file name and its corresponding s3 object name + config_file_s3_object (Tuple[str, str]): Tuple containing the config file name and its corresponding s3 object name + + Returns: + Dict[str, str]: Dictionary with the output file names and their corresponding s3 object names + """ + print("Executing task") + print(f"job_id: {job_id}") + print(f"command: {command}") + print(f"input_file_s3_objects: {input_file_s3_objects}") + print(f"config_file_s3_object: {config_file_s3_object}") + + # Create a new directory for the job and download all the input files to the directory + path = Path(f"./jobs-tmp/{job_id}") + output_path = path.joinpath("output") + path.mkdir(parents=True, exist_ok=True) + output_path.mkdir(parents=True, exist_ok=True) + + # Download all the input files to the directory + for (s3_object_name, local_file_name) in input_file_s3_objects: + download_file_using_client(s3_object_name, local_file_name, path) + + # Download the config file to the directory + if config_file_s3_object is not None and len(config_file_s3_object) == 2: + download_file_using_client(config_file_s3_object[0], config_file_s3_object[1], path) + + # Start a subprocess to execute the test.sh script and pipe the output to a variable. + io = Emitter({'host': SOCKETIO_REDIS_HOST, 'port': SOCKETIO_REDIS_PORT}) + with subprocess.Popen( + command, + # ["/bin/bash", "test.sh", str(output_path.absolute())], + # bufsize=1, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) as process, open(str(output_path.joinpath('output.log')), 'a+') as logfile: + while process.poll() is None: + stdout_line = "" + stderr_line = "" + if process.stdout is not None: + stdout_line = process.stdout.readline().decode("utf-8") + if process.stderr is not None: + stderr_line = process.stderr.readline().decode("utf-8") + stdout_data = stdout_line + stderr_line + logfile.write(stdout_data) + io.To(job_id).Emit('stdout', stdout_data) + + logfile.close() + + # Upload the output files from the job directory to the s3 bucket + # Loop through all the files in the output directory and upload them to the s3 bucket + s3_object_names: Dict[str, str] = {} + for file in output_path.glob("*"): + s3_object_name = upload_file_using_client(file.absolute()) + + s3_object_names[file.name]=s3_object_name + + # Delete the job directory and all its contents + shutil.rmtree(str(path.absolute())) + + # Send the final Signal to the monitor that the job is complete + io.Emit('EOP', "This is finished !") + + return s3_object_names + diff --git a/job-runner/poetry.lock b/job-runner/poetry.lock index 91408c5..23e6b42 100644 --- a/job-runner/poetry.lock +++ b/job-runner/poetry.lock @@ -17,6 +17,14 @@ category = "main" optional = false python-versions = ">=3.6" +[[package]] +name = "asyncio" +version = "3.4.3" +description = "reference implementation of PEP 3156" +category = "main" +optional = false +python-versions = "*" + [[package]] name = "atomicwrites" version = "1.4.1" @@ -27,17 +35,17 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "attrs" -version = "21.4.0" +version = "22.1.0" description = "Classes Without Boilerplate" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.5" [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] -docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] +tests_no_zope = ["cloudpickle", "pytest-mypy-plugins", "mypy (>=0.900,!=0.940)", "pytest (>=4.3.0)", "pympler", "hypothesis", "coverage[toml] (>=5.0.2)"] +tests = ["cloudpickle", "zope.interface", "pytest-mypy-plugins", "mypy (>=0.900,!=0.940)", "pytest (>=4.3.0)", "pympler", "hypothesis", "coverage[toml] (>=5.0.2)"] +docs = ["sphinx-notfound-page", "zope.interface", "sphinx", "furo"] +dev = ["cloudpickle", "pre-commit", "sphinx-notfound-page", "sphinx", "furo", "zope.interface", "pytest-mypy-plugins", "mypy (>=0.900,!=0.940)", "pytest (>=4.3.0)", "pympler", "hypothesis", "coverage[toml] (>=5.0.2)"] [[package]] name = "billiard" @@ -47,6 +55,50 @@ category = "main" optional = false python-versions = "*" +[[package]] +name = "boto-s3-router" +version = "0.0.3" +description = "Provides a Boto3-like client routing requests to multiple S3 clients" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +boto3 = "*" +fnmatch2 = "*" + +[[package]] +name = "boto3" +version = "1.24.50" +description = "The AWS SDK for Python" +category = "main" +optional = false +python-versions = ">= 3.7" + +[package.dependencies] +botocore = ">=1.27.50,<1.28.0" +jmespath = ">=0.7.1,<2.0.0" +s3transfer = ">=0.6.0,<0.7.0" + +[package.extras] +crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] + +[[package]] +name = "botocore" +version = "1.27.50" +description = "Low-level, data-driven core of boto 3." +category = "main" +optional = false +python-versions = ">= 3.7" + +[package.dependencies] +jmespath = ">=0.7.1,<2.0.0" +python-dateutil = ">=2.1,<3.0.0" +urllib3 = ">=1.25.4,<1.27" + +[package.extras] +crt = ["awscrt (==0.13.8)"] + [[package]] name = "celery" version = "5.2.7" @@ -69,11 +121,11 @@ vine = ">=5.0.0,<6.0" [package.extras] arangodb = ["pyArango (>=1.3.2)"] auth = ["cryptography"] -azureblockblob = ["azure-storage-blob (12.9.0)"] +azureblockblob = ["azure-storage-blob (==12.9.0)"] brotli = ["brotli (>=1.0.0)", "brotlipy (>=0.7.0)"] cassandra = ["cassandra-driver (<3.21.0)"] consul = ["python-consul2"] -cosmosdbsql = ["pydocumentdb (2.3.2)"] +cosmosdbsql = ["pydocumentdb (==2.3.2)"] couchbase = ["couchbase (>=3.0.0)"] couchdb = ["pycouchdb"] django = ["Django (>=1.11)"] @@ -88,7 +140,7 @@ msgpack = ["msgpack"] pymemcache = ["python-memcached"] pyro = ["pyro4"] pytest = ["pytest-celery"] -redis = ["redis (>=3.4.1,<4.0.0 || >4.0.0,<4.0.1 || >4.0.1)"] +redis = ["redis (>=3.4.1,!=4.0.0,!=4.0.1)"] s3 = ["boto3 (>=1.9.125)"] slmq = ["softlayer-messaging (>=1.0.3)"] solar = ["ephem"] @@ -99,6 +151,19 @@ yaml = ["PyYAML (>=3.10)"] zookeeper = ["kazoo (>=1.3.1)"] zstd = ["zstandard"] +[[package]] +name = "celerybeat-mongo" +version = "0.2.0" +description = "A Celery Beat Scheduler that uses MongoDB to store both schedule definitions and status information" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +celery = "*" +mongoengine = "*" +pymongo = "*" + [[package]] name = "click" version = "8.1.3" @@ -170,6 +235,25 @@ wrapt = ">=1.10,<2" [package.extras] dev = ["tox", "bump2version (<1)", "sphinx (<2)", "importlib-metadata (<3)", "importlib-resources (<4)", "configparser (<5)", "sphinxcontrib-websupport (<2)", "zipp (<2)", "PyTest (<5)", "PyTest-Cov (<2.6)", "pytest", "pytest-cov"] +[[package]] +name = "fnmatch2" +version = "0.0.8" +description = "An improved Unix filename pattern matching" +category = "main" +optional = false +python-versions = "*" + +[package.extras] +dev = ["coveralls (>=1.1)", "pytest (>=3.0.3)"] + +[[package]] +name = "jmespath" +version = "1.0.1" +description = "JSON Matching Expressions" +category = "main" +optional = false +python-versions = ">=3.7" + [[package]] name = "kombu" version = "5.2.4" @@ -191,21 +275,40 @@ mongodb = ["pymongo (>=3.3.0,<3.12.1)"] msgpack = ["msgpack"] pyro = ["pyro4"] qpid = ["qpid-python (>=0.26)", "qpid-tools (>=0.26)"] -redis = ["redis (>=3.4.1,<4.0.0 || >4.0.0,<4.0.1 || >4.0.1)"] +redis = ["redis (>=3.4.1,!=4.0.0,!=4.0.1)"] slmq = ["softlayer-messaging (>=1.0.3)"] sqlalchemy = ["sqlalchemy"] sqs = ["boto3 (>=1.9.12)", "pycurl (>=7.44.1,<7.45.0)", "urllib3 (>=1.26.7)"] yaml = ["PyYAML (>=3.10)"] zookeeper = ["kazoo (>=1.3.1)"] +[[package]] +name = "mongoengine" +version = "0.24.2" +description = "MongoEngine is a Python Object-Document Mapper for working with MongoDB." +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +pymongo = ">=3.4,<5.0" + [[package]] name = "more-itertools" -version = "8.13.0" +version = "8.14.0" description = "More routines for operating on iterables, beyond itertools" category = "dev" optional = false python-versions = ">=3.5" +[[package]] +name = "msgpack-python" +version = "0.5.6" +description = "MessagePack (de)serializer." +category = "main" +optional = false +python-versions = "*" + [[package]] name = "packaging" version = "21.3" @@ -247,6 +350,23 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +[[package]] +name = "pymongo" +version = "4.2.0" +description = "Python driver for MongoDB " +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +zstd = ["zstandard"] +srv = ["dnspython (>=1.16.0,<3.0.0)"] +snappy = ["python-snappy"] +ocsp = ["certifi", "service-identity (>=18.1.0)", "requests (<3.0.0)", "pyopenssl (>=17.2.0)"] +gssapi = ["pykerberos"] +encryption = ["pymongocrypt (>=1.3.0,<2.0.0)"] +aws = ["pymongo-auth-aws (<2.0.0)"] + [[package]] name = "pyparsing" version = "3.0.9" @@ -277,9 +397,31 @@ py = ">=1.5.0" wcwidth = "*" [package.extras] -checkqa-mypy = ["mypy (v0.761)"] +checkqa-mypy = ["mypy (==v0.761)"] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "python-dotenv" +version = "0.20.0" +description = "Read key-value pairs from a .env file and set them as environment variables" +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.extras] +cli = ["click (>=5.0)"] + [[package]] name = "pytz" version = "2022.1" @@ -303,7 +445,21 @@ packaging = ">=20.4" [package.extras] hiredis = ["hiredis (>=1.0.0)"] -ocsp = ["cryptography (>=36.0.1)", "pyopenssl (20.0.1)", "requests (>=2.26.0)"] +ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"] + +[[package]] +name = "s3transfer" +version = "0.6.0" +description = "An Amazon S3 Transfer Manager" +category = "main" +optional = false +python-versions = ">= 3.7" + +[package.dependencies] +botocore = ">=1.12.36,<2.0a.0" + +[package.extras] +crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] [[package]] name = "six" @@ -313,6 +469,31 @@ category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +[[package]] +name = "socket.io-emitter" +version = "0.1.5.1" +description = "Python implementation of socket.io-emitter." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +msgpack-python = "*" +redis = "*" + +[[package]] +name = "urllib3" +version = "1.26.11" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +secure = ["ipaddress", "certifi", "idna (>=2.0.0)", "cryptography (>=1.3.4)", "pyOpenSSL (>=0.14)"] +brotli = ["brotlipy (>=0.6.0)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] + [[package]] name = "vine" version = "5.0.0" @@ -340,18 +521,39 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [metadata] lock-version = "1.1" python-versions = ">=3.8,<3.11" -content-hash = "01f0109c13f1cbe6d634f31e2c043480f6e40749e1b017b358bb7b45977bfdb0" +content-hash = "d562eb6a4735f9f183f1ce34f722c5b0285d065a1de7ef34a42fceccbb0021be" [metadata.files] amqp = [] async-timeout = [] +asyncio = [ + {file = "asyncio-3.4.3-cp33-none-win32.whl", hash = "sha256:b62c9157d36187eca799c378e572c969f0da87cd5fc42ca372d92cdb06e7e1de"}, + {file = "asyncio-3.4.3-cp33-none-win_amd64.whl", hash = "sha256:c46a87b48213d7464f22d9a497b9eef8c1928b68320a2fa94240f969f6fec08c"}, + {file = "asyncio-3.4.3-py3-none-any.whl", hash = "sha256:c4d18b22701821de07bd6aea8b53d21449ec0ec5680645e5317062ea21817d2d"}, + {file = "asyncio-3.4.3.tar.gz", hash = "sha256:83360ff8bc97980e4ff25c964c7bd3923d333d177aa4f7fb736b019f26c7cb41"}, +] atomicwrites = [] attrs = [ - {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, - {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, + {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, + {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, ] billiard = [] +boto-s3-router = [ + {file = "boto-s3-router-0.0.3.tar.gz", hash = "sha256:9b920f34725edda5ebe9259438cd6e46bb1dbac7e32c2a03f689f268ff761fd2"}, + {file = "boto_s3_router-0.0.3-py3-none-any.whl", hash = "sha256:cb46173e54969a85317e5ebdd2a0818bb2fdec74cbc37c2ddc17206ab186a24d"}, +] +boto3 = [ + {file = "boto3-1.24.50-py3-none-any.whl", hash = "sha256:c312c6ffb0c4eb94c6be2ab4471ca18ebcadc4a3abe048d1c9b437b7c6f1af10"}, + {file = "boto3-1.24.50.tar.gz", hash = "sha256:28fefb77fb85b521a87ffd932621b14aabf4bb65ec4f9d9ce7399d093b2ad8bd"}, +] +botocore = [ + {file = "botocore-1.27.50-py3-none-any.whl", hash = "sha256:697b76a58cfafa8ccbadcbf003efc693cf52170e562a8e2cfda9162d7d5aed20"}, + {file = "botocore-1.27.50.tar.gz", hash = "sha256:0a3e2eef7a60c20e46be47eaf45cf5ea7a946aecdb68d829886d4f2506ac657c"}, +] celery = [] +celerybeat-mongo = [ + {file = "celerybeat-mongo-0.2.0.tar.gz", hash = "sha256:e65b2ec62da522b3d08987175e22c620b75c7c779d45bb15266da1925fda1f6f"}, +] click = [ {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, @@ -364,10 +566,25 @@ colorama = [ {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, ] deprecated = [] +fnmatch2 = [ + {file = "fnmatch2-0.0.8-py2.py3-none-any.whl", hash = "sha256:0430ba2b285638d635615317eea3acf5572c457ab885921064d3669923191591"}, + {file = "fnmatch2-0.0.8.tar.gz", hash = "sha256:12e7e658ae49ec1973893667dcbccaf63d7f6d25a62b05a56ec0db3fd26db9ed"}, +] +jmespath = [ + {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, + {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, +] kombu = [] +mongoengine = [ + {file = "mongoengine-0.24.2-py3-none-any.whl", hash = "sha256:f5c4e1b206b2ccffe4adc7a6283ed26dd799bd115a5fb1d2e885a075132cdb88"}, + {file = "mongoengine-0.24.2.tar.gz", hash = "sha256:c76d49658575bb995682e2e77c8ef7cda63faf939415b32ee923745d120f8b02"}, +] more-itertools = [ - {file = "more-itertools-8.13.0.tar.gz", hash = "sha256:a42901a0a5b169d925f6f217cd5a190e32ef54360905b9c39ee7db5313bfec0f"}, - {file = "more_itertools-8.13.0-py3-none-any.whl", hash = "sha256:c5122bffc5f104d37c1626b8615b511f3427aa5389b94d61e5ef8236bfbc3ddb"}, + {file = "more-itertools-8.14.0.tar.gz", hash = "sha256:c09443cd3d5438b8dafccd867a6bc1cb0894389e90cb53d227456b0b0bccb750"}, + {file = "more_itertools-8.14.0-py3-none-any.whl", hash = "sha256:1bc4f91ee5b1b31ac7ceacc17c09befe6a40a503907baf9c839c229b5095cfd2"}, +] +msgpack-python = [ + {file = "msgpack-python-0.5.6.tar.gz", hash = "sha256:378cc8a6d3545b532dfd149da715abae4fda2a3adb6d74e525d0d5e51f46909b"}, ] packaging = [ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, @@ -382,6 +599,74 @@ py = [ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, ] +pymongo = [ + {file = "pymongo-4.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1c81414b706627f15e921e29ae2403aab52e33e36ed92ed989c602888d7c3b90"}, + {file = "pymongo-4.2.0-cp310-cp310-manylinux1_i686.whl", hash = "sha256:c549bb519456ee230e92f415c5b4d962094caac0fdbcc4ed22b576f66169764e"}, + {file = "pymongo-4.2.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:70216ec4c248213ae95ea499b6314c385ce01a5946c448fb22f6c8395806e740"}, + {file = "pymongo-4.2.0-cp310-cp310-manylinux2014_i686.whl", hash = "sha256:8a86e8c2ac2ec87141e1c6cb00bdb18a4560f06e5f96769abcd1dda24dc0e764"}, + {file = "pymongo-4.2.0-cp310-cp310-manylinux2014_ppc64le.whl", hash = "sha256:314b556afd72eb21a6a10bd1f45ef252509f014f80207db59c97372103c88237"}, + {file = "pymongo-4.2.0-cp310-cp310-manylinux2014_s390x.whl", hash = "sha256:902e2c9030cb042c49750bc70d72d830d42c64ea0df5ff8630c171e065c93dd7"}, + {file = "pymongo-4.2.0-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:c69ef5906dcd6ec565d4d887ba97ceb2a84f3b614307ee3b4780cb1ea40b1867"}, + {file = "pymongo-4.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07564178ecc203a84f63e72972691af6c0c82d2dc0c9da66ba711695276089ba"}, + {file = "pymongo-4.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f47d5f10922cf7f7dfcd1406bd0926cef6d866a75953c3745502dffd7ac197dd"}, + {file = "pymongo-4.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4cadaaa5c19ad23fc84559e90284f2eb003c36958ebb2c06f286b678f441285f"}, + {file = "pymongo-4.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d94f535df9f539615bc3dbbef185ded3b609373bb44ca1afffcabac70202678a"}, + {file = "pymongo-4.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:147a23cd96feb67606ac957744d8d25b013426cdc3c7164a4f99bd8253f649e3"}, + {file = "pymongo-4.2.0-cp310-cp310-win32.whl", hash = "sha256:ecdcb0d4e9b08b739035f57a09330efc6f464bd7f942b63897395d996ca6ebd5"}, + {file = "pymongo-4.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:8c223aea52c359cc8fdee5bd3475532590755c269ec4d4fe581acd47a44e9952"}, + {file = "pymongo-4.2.0-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:fe0820d169635e41c14a5d21514282e0b93347878666ec9d5d3bf0eed0649948"}, + {file = "pymongo-4.2.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:e39cacee70a98758f9b2da53ee175378f07c60113b1fa4fae40cbaee5583181e"}, + {file = "pymongo-4.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:701d331060dae72bf3ebdb82924405d14136a69282ccb00c89fc69dee21340b4"}, + {file = "pymongo-4.2.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:e08fe1731f5429435b8dea1db9663f9ed1812915ff803fc9991c7c4841ed62ad"}, + {file = "pymongo-4.2.0-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:60c470a58c5b62b1b12a5f5458f8e2f2f67b94e198d03dc5352f854d9230c394"}, + {file = "pymongo-4.2.0-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:b211e161b6cc2790e0d640ad38e0429d06c944e5da23410f4dc61809dba25095"}, + {file = "pymongo-4.2.0-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:ed90a9de4431cbfb2f3b2ef0c5fd356e61c85117b2be4db3eae28cb409f6e2d5"}, + {file = "pymongo-4.2.0-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:68e1e49a5675748233f7b05330f092582cd52f2850b4244939fd75ba640593ed"}, + {file = "pymongo-4.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:764fc15418d94bce5c2f8ebdbf66544f96f42efb1364b61e715e5b33281b388d"}, + {file = "pymongo-4.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e64442aba81ed4df1ca494b87bf818569a1280acaa73071c68014f7a884e83f1"}, + {file = "pymongo-4.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:83168126ae2457d1a19b2af665cafa7ef78c2dcff192d7d7b5dad6b36c73ae24"}, + {file = "pymongo-4.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69d0180bca594e81cdb4a2af328bdb4046f59e10aaeef7619496fe64f2ec918c"}, + {file = "pymongo-4.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80cbf0b043061451660099fff9001a7faacb2c9c983842b4819526e2f944dc6c"}, + {file = "pymongo-4.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e1b8f5e2f9637492b0da4d51f78ecb17786e61d6c461ead8542c944750faf4f9"}, + {file = "pymongo-4.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1a957cdc2b26eeed4d8f1889a40c6023dd1bd94672dd0f5ce327314f2caaefd4"}, + {file = "pymongo-4.2.0-cp37-cp37m-win32.whl", hash = "sha256:6bd5888997ea3eae9830c6cc7964b61dcfbc50eb3a5a6ce56ad5f86d5579b11c"}, + {file = "pymongo-4.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:dc24737d24ce0de762bee9c2a884639819485f679bbac8ab5be9c161ef6f9b2c"}, + {file = "pymongo-4.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:193cc97d44b1e6d2253ea94e30c6f94f994efb7166e2452af4df55825266e88b"}, + {file = "pymongo-4.2.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e152c26ffc30331e9d57591fc4c05453c209aa20ba299d1deb7173f7d1958c22"}, + {file = "pymongo-4.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8a9bc4dcfc2bda69ee88cdb7a89b03f2b8eca668519b704384a264dea2db4209"}, + {file = "pymongo-4.2.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8cbb868e88c4eee1c53364bb343d226a3c0e959e791e6828030cb78f46cfcbe3"}, + {file = "pymongo-4.2.0-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:2bfe6b59f431f40fa545547616f4acf0c0c4b64518b1f951083e3bad06eb368b"}, + {file = "pymongo-4.2.0-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:ff66014687598823b6b23751884b4aa67eb934445406d95894dfc60cb7bfcc18"}, + {file = "pymongo-4.2.0-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:31c50da4a080166bc29403aa91f4c76e0889b4f24928d1b60508a37c1bf87f9a"}, + {file = "pymongo-4.2.0-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:ccfdc7722df445c49dc6b5d514c3544cad99b53189165f7546793933050ac7fb"}, + {file = "pymongo-4.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc7ebc37b03956a070260665079665eae69e5e96007694214f3a2107af96816a"}, + {file = "pymongo-4.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c8b4a782aac43948308087b962c9ecb030ba98886ce6dee3ad7aafe8c5e1ce80"}, + {file = "pymongo-4.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1c23527f8e13f526fededbb96f2e7888f179fe27c51d41c2724f7059b75b2fa"}, + {file = "pymongo-4.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83cc3c35aeeceb67143914db67f685206e1aa37ea837d872f4bc28d7f80917c9"}, + {file = "pymongo-4.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e09cdf5aad507c8faa30d97884cc42932ed3a9c2b7f22cc3ccc607bae03981b3"}, + {file = "pymongo-4.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0f53253f4777cbccc426e669a2af875f26c95bd090d88593287b9a0a8ac7fa25"}, + {file = "pymongo-4.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:21238b19243a42f9a34a6d39e7580ceebc6da6d2f3cf729c1cff9023cb61a5f1"}, + {file = "pymongo-4.2.0-cp38-cp38-win32.whl", hash = "sha256:766acb5b1a19eae0f7467bcd3398748f110ea5309cdfc59faa5185dcc7fd4dca"}, + {file = "pymongo-4.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:10f09c4f09757c2e2a707ad7304f5d69cb8fdf7cbfb644dbacfe5bbe8afe311b"}, + {file = "pymongo-4.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a6bf01b9237f794fa3bdad5089474067d28be7e199b356a18d3f247a45775f26"}, + {file = "pymongo-4.2.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:d8bb745321716e7a11220a67c88212ecedde4021e1de4802e563baef9df921d2"}, + {file = "pymongo-4.2.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:3be53e9888e759c49ae35d747ff77a04ff82b894dd64601e0f3a5a159b406245"}, + {file = "pymongo-4.2.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:a3efdf154844244e0dabe902cf1827fdced55fa5b144adec2a86e5ce50a99b97"}, + {file = "pymongo-4.2.0-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:a7eb5b06744b911b6668b427c8abc71b6d624e72d3dfffed00988fa1b4340f97"}, + {file = "pymongo-4.2.0-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:b0be613d926c5dbb0d3fc6b58e4f2be4979f80ae76fda6e47309f011b388fe0c"}, + {file = "pymongo-4.2.0-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:e7dcb73f683c155885a3488646fcead3a895765fed16e93c9b80000bc69e96cb"}, + {file = "pymongo-4.2.0-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:b537dd282de1b53d9ae7cf9f3df36420c8618390f2da92100391f3ba8f3c141a"}, + {file = "pymongo-4.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d98d2a8283c9928a9e5adf2f3c0181e095579e9732e1613aaa55d386e2bcb6c5"}, + {file = "pymongo-4.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76892bbce743eb9f90360b3626ea92f13d338010a1004b4488e79e555b339921"}, + {file = "pymongo-4.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:124d0e880b66f9b0778613198e89984984fdd37a3030a9007e5f459a42dfa2d3"}, + {file = "pymongo-4.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:773467d25c293f8e981b092361dab5fd800e1ba318403b7959d35004c67faedc"}, + {file = "pymongo-4.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6673ab3fbf3135cc1a8c0f70d480db5b2378c3a70af8d602f73f76b8338bdf97"}, + {file = "pymongo-4.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:153b8f8705970756226dfeeb7bb9637e0ad54a4d79b480b4c8244e34e16e1662"}, + {file = "pymongo-4.2.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:01721da74558f2f64a9f162ee063df403ed656b7d84229268d8e4ae99cfba59c"}, + {file = "pymongo-4.2.0-cp39-cp39-win32.whl", hash = "sha256:a25c0eb2d610b20e276e684be61c337396813b636b69373c17314283cb1a3b14"}, + {file = "pymongo-4.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:44b36ccb90aac5ea50be23c1a6e8f24fbfc78afabdef114af16c6e0a80981364"}, + {file = "pymongo-4.2.0.tar.gz", hash = "sha256:72f338f6aabd37d343bd9d1fdd3de921104d395766bcc5cdc4039e4c2dd97766"}, +] pyparsing = [ {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, @@ -390,15 +675,34 @@ pytest = [ {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"}, {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"}, ] +python-dateutil = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] +python-dotenv = [ + {file = "python-dotenv-0.20.0.tar.gz", hash = "sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f"}, + {file = "python_dotenv-0.20.0-py3-none-any.whl", hash = "sha256:d92a187be61fe482e4fd675b6d52200e7be63a12b724abbf931a40ce4fa92938"}, +] pytz = [ {file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"}, {file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"}, ] redis = [] +s3transfer = [ + {file = "s3transfer-0.6.0-py3-none-any.whl", hash = "sha256:06176b74f3a15f61f1b4f25a1fc29a4429040b7647133a463da8fa5bd28d5ecd"}, + {file = "s3transfer-0.6.0.tar.gz", hash = "sha256:2ed07d3866f523cc561bf4a00fc5535827981b117dd7876f036b0c1aca42c947"}, +] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] +"socket.io-emitter" = [ + {file = "socket.io_emitter-0.1.5.1-py2.py3-none-any.whl", hash = "sha256:e2c245195a100db79edc5bacbab5ba261c1a449ec5d1849296f93d48690f3028"}, +] +urllib3 = [ + {file = "urllib3-1.26.11-py2.py3-none-any.whl", hash = "sha256:c33ccba33c819596124764c23a97d25f32b28433ba0dedeb77d873a38722c9bc"}, + {file = "urllib3-1.26.11.tar.gz", hash = "sha256:ea6e8fb210b19d950fab93b60c9009226c63a28808bc8386e05301e25883ac0a"}, +] vine = [] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, diff --git a/job-runner/pyproject.toml b/job-runner/pyproject.toml index 07bbfd2..9e51ba4 100644 --- a/job-runner/pyproject.toml +++ b/job-runner/pyproject.toml @@ -8,9 +8,16 @@ authors = ["Radhakrishna Sanka "] python = ">=3.8,<3.11" redis = "^4.3.4" celery = {extras = ["redis"], version = "^5.2.7"} +celerybeat-mongo = "^0.2.0" +mongoengine = "^0.24.2" +asyncio = "^3.4.3" +"socket.io-emitter" = "^0.1.5" +boto3 = "^1.24.50" +boto-s3-router = "^0.0.3" [tool.poetry.dev-dependencies] pytest = "^5.2" +python-dotenv = "^0.20.0" [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/job-runner/send_test.py b/job-runner/send_test.py new file mode 100644 index 0000000..95554fc --- /dev/null +++ b/job-runner/send_test.py @@ -0,0 +1,23 @@ +from celery import Celery +import time +import asyncio + +async def print_result(result): + output = result.get() + return output + + +async def do_it_all(): + celery = Celery( + broker="redis://localhost:6379/0", backend="mongodb://root:rootpassword@localhost:27017/jobs" + ) + + result = celery.send_task("add_task", (1, 4)) + result2 = celery.send_task("add_task", (2, 4)) + + print(await print_result(result)) + print(await print_result(result2)) + + +if __name__ == "__main__": + asyncio.run(do_it_all()) \ No newline at end of file diff --git a/job-runner/send_test2.py b/job-runner/send_test2.py new file mode 100644 index 0000000..c9680c1 --- /dev/null +++ b/job-runner/send_test2.py @@ -0,0 +1,17 @@ +from celery import Celery +import time +import asyncio +import uuid + + +job_id = str(uuid.uuid4()) + +print("job_id:", job_id) + +celery = Celery( + broker="redis://localhost:6379/0", backend="mongodb://root:rootpassword@localhost:27017/jobs" +) + +result = celery.send_task("execute_task", (job_id,)) + +print(result.get()) diff --git a/job-runner/simple.py b/job-runner/simple.py deleted file mode 100644 index 53a892c..0000000 --- a/job-runner/simple.py +++ /dev/null @@ -1,8 +0,0 @@ -from celery import Celery - -app = Celery('hello', backend='redis://localhost:6379', broker='redis://localhost:6379') - -@app.task -def hello(): - print("Hello World!") - return "Hello World!" \ No newline at end of file diff --git a/job-runner/test.py b/job-runner/test.py index dc60d7d..96d4ee7 100644 --- a/job-runner/test.py +++ b/job-runner/test.py @@ -1 +1,26 @@ -print("TESTING") \ No newline at end of file +import boto3 +import os +import pathlib +from pprint import pprint + + +AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID') +AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY') +AWS_ENDPOINT_URL = os.getenv('AWS_ENDPOINT_URL') + +print("AWS_ACCESS_KEY_ID:", AWS_ACCESS_KEY_ID) +print("AWS_SECRET_ACCESS_KEY:", AWS_SECRET_ACCESS_KEY) +print("AWS_ENDPOINT_URL:", AWS_ENDPOINT_URL) + +s3 = boto3.client( + "s3", + endpoint_url=AWS_ENDPOINT_URL, + aws_access_key_id=AWS_ACCESS_KEY_ID, + aws_secret_access_key=AWS_SECRET_ACCESS_KEY +) +bucket_name = "fluigi" +object_name = "sample1.txt" +file_name = os.path.join(pathlib.Path(__file__).parent.resolve(), "sample_file.txt") + +response = s3.upload_file(file_name, bucket_name, object_name) +pprint(response) # prints None diff --git a/job-runner/test.sh b/job-runner/test.sh new file mode 100755 index 0000000..7e15557 --- /dev/null +++ b/job-runner/test.sh @@ -0,0 +1,10 @@ +#!/bin/bash + + +mkdir $1 +cd $1 +#Loop from 1 to 500 and print the number +for i in {1..10}; do + + touch "${i}.txt" +done \ No newline at end of file diff --git a/neptune.code-workspace b/neptune.code-workspace new file mode 100644 index 0000000..da29725 --- /dev/null +++ b/neptune.code-workspace @@ -0,0 +1,17 @@ +{ + "folders": [ + { + "path": "." + }, + { + "path": "primitives-server" + }, + { + "path": "job-runner" + }, + { + "path": "pyfluigi" + } + ], + "settings": {} +} \ No newline at end of file diff --git a/primitives-server b/primitives-server index d56773c..69788d8 160000 --- a/primitives-server +++ b/primitives-server @@ -1 +1 @@ -Subproject commit d56773cb73035dfc80d34267d3159e93d9548cb8 +Subproject commit 69788d8728146a9c245aaa5ef5fe76f8780986ec diff --git a/pyfluigi b/pyfluigi index f85ecab..83ac859 160000 --- a/pyfluigi +++ b/pyfluigi @@ -1 +1 @@ -Subproject commit f85ecab8bf54a032421890c80493dd2e684f3296 +Subproject commit 83ac859aa31aabe8deeeeac44ed192e87032c68f