# Path: sacred/commandline_options.py
# def cli_option(short_flag: str, long_flag: str, is_flag=False):
#     def wrapper(f: CLIFunction):
#         return CLIOption(f, short_flag, long_flag, is_flag)
# 
#     return wrapper
# 
# Path: sacred/dependencies.py
# def get_digest(filename):
#     """Compute the MD5 hash for a given file."""
#     h = hashlib.md5()
#     with open(filename, "rb") as f:
#         data = f.read(1 * MB)
#         while data:
#             h.update(data)
#             data = f.read(1 * MB)
#         return h.hexdigest()
# 
# Path: sacred/observers/base.py
# class RunObserver:
#     """Defines the interface for all run observers."""
# 
#     priority = 0
# 
#     def queued_event(
#         self, ex_info, command, host_info, queue_time, config, meta_info, _id
#     ):
#         pass
# 
#     def started_event(
#         self, ex_info, command, host_info, start_time, config, meta_info, _id
#     ):
#         pass
# 
#     def heartbeat_event(self, info, captured_out, beat_time, result):
#         pass
# 
#     def completed_event(self, stop_time, result):
#         pass
# 
#     def interrupted_event(self, interrupt_time, status):
#         pass
# 
#     def failed_event(self, fail_time, fail_trace):
#         pass
# 
#     def resource_event(self, filename):
#         pass
# 
#     def artifact_event(self, name, filename, metadata=None, content_type=None):
#         pass
# 
#     def log_metrics(self, metrics_by_name, info):
#         pass
# 
#     def join(self):
#         pass
# 
# Path: sacred/serializer.py
# def flatten(obj):
#     return _json.loads(json.encode(obj, keys=True))


import json
import os
import os.path
import re
import socket
        import boto3
        import boto3
from sacred.commandline_options import cli_option
from sacred.dependencies import get_digest
from sacred.observers.base import RunObserver
from sacred.serializer import flatten
        from botocore.errorfactory import ClientError

DEFAULT_S3_PRIORITY = 20


def _is_valid_bucket(bucket_name):
    # See https://docs.aws.amazon.com/awscloudtrail/latest/userguide/
    # cloudtrail-s3-bucket-naming-requirements.html
    if len(bucket_name) < 3 or len(bucket_name) > 63:
        return False

    labels = bucket_name.split(".")
    # A bucket name consists of "labels" separated by periods
    for label in labels:
        if len(label) == 0 or label[0] == "-" or label[-1] == "-":
            # Labels must be of nonzero length,
            # and cannot begin or end with a hyphen
            return False
        for char in label:
            # Labels can only contain digits, lowercase letters, or hyphens.
            # Anything else will fail here
            if not (char.isdigit() or char.islower() or char == "-"):
                return False
    try:
        # If a name is a valid IP address, it cannot be a bucket name
        socket.inet_aton(bucket_name)
    except socket.error:
        return True


def s3_join(*args):

# Path: sacred/commandline_options.py
# def cli_option(short_flag: str, long_flag: str, is_flag=False):
#     def wrapper(f: CLIFunction):
#         return CLIOption(f, short_flag, long_flag, is_flag)
# 
#     return wrapper
# 
# Path: sacred/dependencies.py
# def get_digest(filename):
#     """Compute the MD5 hash for a given file."""
#     h = hashlib.md5()
#     with open(filename, "rb") as f:
#         data = f.read(1 * MB)
#         while data:
#             h.update(data)
#             data = f.read(1 * MB)
#         return h.hexdigest()
# 
# Path: sacred/observers/base.py
# class RunObserver:
#     """Defines the interface for all run observers."""
# 
#     priority = 0
# 
#     def queued_event(
#         self, ex_info, command, host_info, queue_time, config, meta_info, _id
#     ):
#         pass
# 
#     def started_event(
#         self, ex_info, command, host_info, start_time, config, meta_info, _id
#     ):
#         pass
# 
#     def heartbeat_event(self, info, captured_out, beat_time, result):
#         pass
# 
#     def completed_event(self, stop_time, result):
#         pass
# 
#     def interrupted_event(self, interrupt_time, status):
#         pass
# 
#     def failed_event(self, fail_time, fail_trace):
#         pass
# 
#     def resource_event(self, filename):
#         pass
# 
#     def artifact_event(self, name, filename, metadata=None, content_type=None):
#         pass
# 
#     def log_metrics(self, metrics_by_name, info):
#         pass
# 
#     def join(self):
#         pass
# 
# Path: sacred/serializer.py
# def flatten(obj):
#     return _json.loads(json.encode(obj, keys=True))


# Path: sacred/observers/s3_observer.py
import json
import os
import os.path
import re
import socket
        import boto3
        import boto3
from sacred.commandline_options import cli_option
from sacred.dependencies import get_digest
from sacred.observers.base import RunObserver
from sacred.serializer import flatten
        from botocore.errorfactory import ClientError


DEFAULT_S3_PRIORITY = 20


def _is_valid_bucket(bucket_name):
    # See https://docs.aws.amazon.com/awscloudtrail/latest/userguide/
    # cloudtrail-s3-bucket-naming-requirements.html
    if len(bucket_name) < 3 or len(bucket_name) > 63:
        return False

    labels = bucket_name.split(".")
    # A bucket name consists of "labels" separated by periods
    for label in labels:
        if len(label) == 0 or label[0] == "-" or label[-1] == "-":
            # Labels must be of nonzero length,
            # and cannot begin or end with a hyphen
            return False
        for char in label:
            # Labels can only contain digits, lowercase letters, or hyphens.
            # Anything else will fail here
            if not (char.isdigit() or char.islower() or char == "-"):
                return False
    try:
        # If a name is a valid IP address, it cannot be a bucket name
        socket.inet_aton(bucket_name)
    except socket.error:
        return True


def s3_join(*args):

    return "/".join(args)