# Path: src/artifactcli/artifact/artifact.py
# class Artifact(BaseInfo):
#     keys = ['basic_info', 'file_info', 'scm_info']
# 
#     def __init__(self, basic_info, file_info, scm_info=None):
#         super(Artifact, self).__init__(Artifact.keys)
#         self.basic_info = basic_info
#         self.file_info = file_info
#         self.scm_info = scm_info
# 
#     def __str__(self):
#         buf = [self.basic_info, self.file_info] + ([self.scm_info] if self.scm_info else [])
#         return '\n'.join(map(str, buf))
# 
#     def to_dict(self):
#         ret = {
#             'basic_info': self.basic_info.to_dict(),
#             'file_info': self.file_info.to_dict(),
#         }
#         if self.scm_info:
#             ret.update({'scm_info': self.scm_info.to_dict()})
#         return ret
# 
#     @staticmethod
#     def from_dict(d):
#         bi = BasicInfo.from_dict(d['basic_info'])
#         fi = FileInfo.from_dict(d['file_info'])
#         si = None
#         if 'scm_info' in d:
#             if d['scm_info']['system'] == 'git':
#                 si = GitInfo.from_dict(d['scm_info'])
#         return Artifact(bi, fi, si)
# 
#     @staticmethod
#     def from_path(group_id, path):
#         # revision will be set to None
#         return Artifact(BasicInfo.from_path(group_id, path), FileInfo.from_path(path), GitInfo.from_path(path))
# 
# Path: src/artifactcli/artifact/basicinfo.py
# class BasicInfo(BaseInfo):
#     keys = ['group_id', 'artifact_id', 'version', 'packaging', 'revision']
# 
#     def __init__(self, group_id, artifact_id, version, packaging, revision):
#         super(BasicInfo, self).__init__(BasicInfo.keys)
#         self.group_id = group_id
#         self.artifact_id = artifact_id
#         self.version = version
#         self.packaging = packaging
#         self.revision = revision
# 
#     def __str__(self):
#         buf = [
#             'Basic Info:',
#             '  Group ID   : %s' % self.group_id,
#             '  Artifact ID: %s' % self.artifact_id,
#             '  Version    : %s' % self.version,
#             '  Packaging  : %s' % self.packaging,
#             '  Revision   : %s' % self.revision
#         ]
#         return '\n'.join(buf)
# 
#     def filename(self):
#         return '%s-%s.%s' % (self.artifact_id, self.version, self.packaging)
# 
#     def s3_path(self):
#         if self.revision is None:
#             raise ValueError('Revision is not defined')
#         else:
#             xs = (str(x) for x in [self.group_id, self.artifact_id, self.version, self.revision, self.filename()])
#             return '/'.join(xs)
# 
#     @staticmethod
#     def from_dict(d):
#         return BasicInfo(*[d[k] for k in BasicInfo.keys])
# 
#     @staticmethod
#     def from_path(group_id, path, revision=None):
#         basename = os.path.basename(path)
#         prefix, extension = os.path.splitext(basename)
#         extension = extension[1:]  # remove dot
#         tokens = reversed(prefix.split('-'))
# 
#         artifact_tokens = []
#         version_tokens = []
#         version_found = False
#         for token in tokens:
#             if version_found:
#                 artifact_tokens.append(token)
#             else:
#                 version_tokens.append(token)
#                 if BasicInfo._is_version_like(token):
#                     version_found = True
# 
#         artifact_id = '-'.join(reversed(artifact_tokens))
#         version = '-'.join(reversed(version_tokens))
# 
#         # validate values
#         if not version_found:
#             raise ValueError('Could not parse version from path: %s' % path)
#         if not artifact_id:
#             raise ValueError('Could not parse artifact id from path: %s' % path)
#         if not extension:
#             raise ValueError('Could not parse extension from path: %s' % path)
# 
#         return BasicInfo(group_id, artifact_id, version, extension, revision)
# 
#     @staticmethod
#     def _is_version_like(s):
#         return re.match("^[0-9]+(?:[.][0-9]+)*$", s) is not None


import json
import logging
import sys
from copy import deepcopy
from collections import defaultdict
from .artifact import Artifact, BasicInfo
from .util import *
        """
        self.artifacts = defaultdict(list)
        for artifact_id in self.driver.artifact_ids():
            self.load(artifact_id)

    def save(self, artifact_id):
        """
        Persist current artifacts index for specified artifact id to storage

        :param artifact_id: artifact id to save
        :return: None
        """
        xs = [x.to_dict() for x in self.artifacts[artifact_id]]
        s = json.dumps(xs, ensure_ascii=False)
        self.driver.write_index(artifact_id, s)

    def upload(self, local_path, artifact=None, force=False, print_only=False):
        """
        Upload local artifact and update index

        :param local_path: source file path to upload
        :param artifact: artifact object to upload
                         If artifact is None, generate artifact object from local_path.
                         Revision will be updated.
        :param force:
        :param print_only:
        :return: None
        """
        art = deepcopy(artifact)
        if not artifact:

# Path: src/artifactcli/artifact/artifact.py
# class Artifact(BaseInfo):
#     keys = ['basic_info', 'file_info', 'scm_info']
# 
#     def __init__(self, basic_info, file_info, scm_info=None):
#         super(Artifact, self).__init__(Artifact.keys)
#         self.basic_info = basic_info
#         self.file_info = file_info
#         self.scm_info = scm_info
# 
#     def __str__(self):
#         buf = [self.basic_info, self.file_info] + ([self.scm_info] if self.scm_info else [])
#         return '\n'.join(map(str, buf))
# 
#     def to_dict(self):
#         ret = {
#             'basic_info': self.basic_info.to_dict(),
#             'file_info': self.file_info.to_dict(),
#         }
#         if self.scm_info:
#             ret.update({'scm_info': self.scm_info.to_dict()})
#         return ret
# 
#     @staticmethod
#     def from_dict(d):
#         bi = BasicInfo.from_dict(d['basic_info'])
#         fi = FileInfo.from_dict(d['file_info'])
#         si = None
#         if 'scm_info' in d:
#             if d['scm_info']['system'] == 'git':
#                 si = GitInfo.from_dict(d['scm_info'])
#         return Artifact(bi, fi, si)
# 
#     @staticmethod
#     def from_path(group_id, path):
#         # revision will be set to None
#         return Artifact(BasicInfo.from_path(group_id, path), FileInfo.from_path(path), GitInfo.from_path(path))
# 
# Path: src/artifactcli/artifact/basicinfo.py
# class BasicInfo(BaseInfo):
#     keys = ['group_id', 'artifact_id', 'version', 'packaging', 'revision']
# 
#     def __init__(self, group_id, artifact_id, version, packaging, revision):
#         super(BasicInfo, self).__init__(BasicInfo.keys)
#         self.group_id = group_id
#         self.artifact_id = artifact_id
#         self.version = version
#         self.packaging = packaging
#         self.revision = revision
# 
#     def __str__(self):
#         buf = [
#             'Basic Info:',
#             '  Group ID   : %s' % self.group_id,
#             '  Artifact ID: %s' % self.artifact_id,
#             '  Version    : %s' % self.version,
#             '  Packaging  : %s' % self.packaging,
#             '  Revision   : %s' % self.revision
#         ]
#         return '\n'.join(buf)
# 
#     def filename(self):
#         return '%s-%s.%s' % (self.artifact_id, self.version, self.packaging)
# 
#     def s3_path(self):
#         if self.revision is None:
#             raise ValueError('Revision is not defined')
#         else:
#             xs = (str(x) for x in [self.group_id, self.artifact_id, self.version, self.revision, self.filename()])
#             return '/'.join(xs)
# 
#     @staticmethod
#     def from_dict(d):
#         return BasicInfo(*[d[k] for k in BasicInfo.keys])
# 
#     @staticmethod
#     def from_path(group_id, path, revision=None):
#         basename = os.path.basename(path)
#         prefix, extension = os.path.splitext(basename)
#         extension = extension[1:]  # remove dot
#         tokens = reversed(prefix.split('-'))
# 
#         artifact_tokens = []
#         version_tokens = []
#         version_found = False
#         for token in tokens:
#             if version_found:
#                 artifact_tokens.append(token)
#             else:
#                 version_tokens.append(token)
#                 if BasicInfo._is_version_like(token):
#                     version_found = True
# 
#         artifact_id = '-'.join(reversed(artifact_tokens))
#         version = '-'.join(reversed(version_tokens))
# 
#         # validate values
#         if not version_found:
#             raise ValueError('Could not parse version from path: %s' % path)
#         if not artifact_id:
#             raise ValueError('Could not parse artifact id from path: %s' % path)
#         if not extension:
#             raise ValueError('Could not parse extension from path: %s' % path)
# 
#         return BasicInfo(group_id, artifact_id, version, extension, revision)
# 
#     @staticmethod
#     def _is_version_like(s):
#         return re.match("^[0-9]+(?:[.][0-9]+)*$", s) is not None


# Path: src/artifactcli/repository.py
import json
import logging
import sys
from copy import deepcopy
from collections import defaultdict
from .artifact import Artifact, BasicInfo
from .util import *

        """
        self.artifacts = defaultdict(list)
        for artifact_id in self.driver.artifact_ids():
            self.load(artifact_id)

    def save(self, artifact_id):
        """
        Persist current artifacts index for specified artifact id to storage

        :param artifact_id: artifact id to save
        :return: None
        """
        xs = [x.to_dict() for x in self.artifacts[artifact_id]]
        s = json.dumps(xs, ensure_ascii=False)
        self.driver.write_index(artifact_id, s)

    def upload(self, local_path, artifact=None, force=False, print_only=False):
        """
        Upload local artifact and update index

        :param local_path: source file path to upload
        :param artifact: artifact object to upload
                         If artifact is None, generate artifact object from local_path.
                         Revision will be updated.
        :param force:
        :param print_only:
        :return: None
        """
        art = deepcopy(artifact)
        if not artifact:

            art = Artifact.from_path(self.group_id, local_path)