def cells_to_series(cells, args):
    """Convert a CellImpl into a Series.

    `args` must be a sequence of argkeys.

    `args` can be longer or shorter then the number of cell's parameters.
    If shorter, then defaults are filled if any, else raise error.
    If longer, then redundant args are ignored.
    """

    paramlen = len(cells.formula.parameters)
    is_multidx = paramlen > 1

    if len(cells.data) == 0:
        data = {}
        indexes = None

    elif paramlen == 0:  # Const Cells
        data = list(cells.data.values())
        indexes = [np.nan]

    else:

        if len(args) > 0:
            defaults = tuple(
                param.default
                for param in cells.formula.signature.parameters.values()
            )
            updated_args = []
            for arg in args:

                if len(arg) > paramlen:
                    arg = arg[:paramlen]
                elif len(arg) < paramlen:
                    arg += defaults[len(arg) :]

                updated_args.append(arg)

            items = [
                (arg, cells.data[arg])
                for arg in updated_args
                if arg in cells.data
            ]
        else:
            items = [(key, value) for key, value in cells.data.items()]

        if not is_multidx:  # Peel 1-element tuple
            items = [(key[0], value) for key, value in items]

        if len(items) == 0:
            indexes, data = None, {}
        else:
            indexes, data = zip(*items)
            if is_multidx:
                indexes = pd.MultiIndex.from_tuples(indexes)

    result = pd.Series(data=data, name=cells.name, index=indexes)

    if indexes is not None and any(i is not np.nan for i in indexes):
        result.index.names = list(cells.formula.parameters)

    return result

def
cells_to_series
(
cells
,
args
)
:
paramlen
=
len
(
cells
.
formula
.
parameters
)
is_multidx
=
paramlen
>
1
if
len
(
cells
.
data
)
==
0
:
data
=
{
}
indexes
=
elif
paramlen
==
0
:
# Const Cells
data
=
list
(
cells
.
data
.
values
(
)
)
indexes
=
[
np
.
]
else
:
if
len
(
args
)
>
0
:
defaults
=
tuple
(
param
.
default
for
param
in
cells
.
formula
.
signature
.
parameters
.
values
(
)
)
updated_args
=
[
]
for
arg
in
args
:
if
len
(
arg
)
>
paramlen
:
arg
=
arg
[
:
paramlen
]
elif
len
(
arg
)
<
paramlen
:
arg
+=
defaults
[
len
(
arg
)
:
]
updated_args
.
append
(
arg
)
items
=
[
(
arg
,
cells
.
data
[
arg
]
)
for
arg
in
updated_args
if
arg
in
cells
.
data
]
else
:
items
=
[
(
key
,
value
)
for
key
,
value
in
cells
.
data
.
items
(
)
]
if
not
is_multidx
:
# Peel 1-element tuple
items
=
[
(
key
[
0
]
,
value
)
for
key
,
value
in
items
]
if
len
(
items
)
==
0
:
indexes
,
data
=
,
{
}
else
:
indexes
,
data
=
zip
(
*
items
)
if
is_multidx
:
indexes
=
pd
.
MultiIndex
.
from_tuples
(
indexes
)
result
=
pd
.
Series
(
data
=
data
,
name
=
cells
.
name
,
index
=
indexes
)
if
indexes
is
not
and
any
(
i
is
not
np
.
for
i
in
indexes
)
:
result
.
index
.
names
=
list
(
cells
.
formula
.
parameters
)
return
result


def clear_obj(self, obj):
        """"Remove all nodes with `obj` and their descendants."""
        obj_nodes = self.get_nodes_with(obj)
        removed = set()
        for node in obj_nodes:
            if self.has_node(node):
                removed.update(self.clear_descendants(node))
        return removed

def clear_obj ( self , obj ) : obj_nodes = self . get_nodes_with ( obj ) removed = set ( ) for node in obj_nodes : if self . has_node ( node ) : removed . update ( self . clear_descendants ( node ) ) return removed

Remove all nodes with obj and their descendants .


def get_nodes_with(self, obj):
        """Return nodes with `obj`."""
        result = set()

        if nx.__version__[0] == "1":
            nodes = self.nodes_iter()
        else:
            nodes = self.nodes

        for node in nodes:
            if node[OBJ] == obj:
                result.add(node)
        return result

def get_nodes_with ( self , obj ) : result = set ( ) if nx . __version__ [ 0 ] == "1" : nodes = self . nodes_iter ( ) else : nodes = self . nodes for node in nodes : if node [ OBJ ] == obj : result . add ( node ) return result


def add_path(self, nodes, **attr):
        """In replacement for Deprecated add_path method"""
        if nx.__version__[0] == "1":
            return super().add_path(nodes, **attr)
        else:
            return nx.add_path(self, nodes, **attr)

def add_path ( self , nodes , * * attr ) : if nx . __version__ [ 0 ] == "1" : return super ( ) . add_path ( nodes , * * attr ) else : return nx . add_path ( self , nodes , * * attr )


def rename(self, name):
        """Rename the model itself"""
        self._impl.system.rename_model(new_name=name, old_name=self.name)

def rename ( self , name ) : self . _impl . system . rename_model ( new_name = name , old_name = self . name )


def rename(self, name):
        """Rename self. Must be called only by its system."""
        if is_valid_name(name):
            if name not in self.system.models:
                self.name = name
                return True  # Rename success
            else:  # Model name already exists
                return False
        else:
            raise ValueError("Invalid name '%s'." % name)

def
rename
(
self
,
name
)
:
if
is_valid_name
(
name
)
:
if
name
not
in
self
.
system
.
models
:
self
.
name
=
name
return
True
# Rename success
else
:
# Model name already exists
return
False
else
:
raise
ValueError
(
"Invalid name '%s'."
%
name
)

Rename self . Must be called only by its system .


def clear_descendants(self, source, clear_source=True):
        """Clear values and nodes calculated from `source`."""
        removed = self.cellgraph.clear_descendants(source, clear_source)
        for node in removed:
            del node[OBJ].data[node[KEY]]

def clear_descendants ( self , source , clear_source = True ) : removed = self . cellgraph . clear_descendants ( source , clear_source ) for node in removed : del node [ OBJ ] . data [ node [ KEY ] ]

Clear values and nodes calculated from source .


def clear_obj(self, obj):
        """Clear values and nodes of `obj` and their dependants."""
        removed = self.cellgraph.clear_obj(obj)
        for node in removed:
            del node[OBJ].data[node[KEY]]

def clear_obj ( self , obj ) : removed = self . cellgraph . clear_obj ( obj ) for node in removed : del node [ OBJ ] . data [ node [ KEY ] ]

Clear values and nodes of obj and their dependants .


def get_object(self, name):
        """Retrieve an object by a dotted name relative to the model."""
        parts = name.split(".")
        space = self.spaces[parts.pop(0)]
        if parts:
            return space.get_object(".".join(parts))
        else:
            return space

def get_object ( self , name ) : parts = name . split ( "." ) space = self . spaces [ parts . pop ( 0 ) ] if parts : return space . get_object ( "." . join ( parts ) ) else : return space

Retrieve an object by a dotted name relative to the model .


def get_dynamic_base(self, bases: tuple):
        """Create of get a base space for a tuple of bases"""

        try:
            return self._dynamic_bases_inverse[bases]
        except KeyError:
            name = self._dynamic_base_namer.get_next(self._dynamic_bases)
            base = self._new_space(name=name)
            self.spacegraph.add_space(base)
            self._dynamic_bases[name] = base
            self._dynamic_bases_inverse[bases] = base
            base.add_bases(bases)
            return base

def get_dynamic_base ( self , bases : tuple ) : try : return self . _dynamic_bases_inverse [ bases ] except KeyError : name = self . _dynamic_base_namer . get_next ( self . _dynamic_bases ) base = self . _new_space ( name = name ) self . spacegraph . add_space ( base ) self . _dynamic_bases [ name ] = base self . _dynamic_bases_inverse [ bases ] = base base . add_bases ( bases ) return base


def check_mro(self, bases):
        """Check if C3 MRO is possible with given bases"""

        try:
            self.add_node("temp")
            for base in bases:
                nx.DiGraph.add_edge(self, base, "temp")
            result = self.get_mro("temp")[1:]

        finally:
            self.remove_node("temp")

        return result

def check_mro ( self , bases ) : try : self . add_node ( "temp" ) for base in bases : nx . DiGraph . add_edge ( self , base , "temp" ) result = self . get_mro ( "temp" ) [ 1 : ] finally : self . remove_node ( "temp" ) return result


def get_command_names():
    """
    Returns a list of command names supported
    """
    ret = []
    for f in os.listdir(COMMAND_MODULE_PATH):
        if os.path.isfile(os.path.join(COMMAND_MODULE_PATH, f)) and f.endswith(COMMAND_MODULE_SUFFIX):
            ret.append(f[:-len(COMMAND_MODULE_SUFFIX)])
    return ret

def get_command_names ( ) : ret = [ ] for f in os . listdir ( COMMAND_MODULE_PATH ) : if os . path . isfile ( os . path . join ( COMMAND_MODULE_PATH , f ) ) and f . endswith ( COMMAND_MODULE_SUFFIX ) : ret . append ( f [ : - len ( COMMAND_MODULE_SUFFIX ) ] ) return ret


def get(vals, key, default_val=None):
    """
    Returns a dictionary value
    """
    val = vals
    for part in key.split('.'):
        if isinstance(val, dict):
            val = val.get(part, None)
            if val is None:
                return default_val
        else:
            return default_val
    return val

def get ( vals , key , default_val = None ) : val = vals for part in key . split ( '.' ) : if isinstance ( val , dict ) : val = val . get ( part , None ) if val is None : return default_val else : return default_val return val


def parse_option_settings(option_settings):
    """
    Parses option_settings as they are defined in the configuration file
    """
    ret = []
    for namespace, params in list(option_settings.items()):
        for key, value in list(params.items()):
            ret.append((namespace, key, value))
    return ret

def parse_option_settings ( option_settings ) : ret = [ ] for namespace , params in list ( option_settings . items ( ) ) : for key , value in list ( params . items ( ) ) : ret . append ( ( namespace , key , value ) ) return ret


def parse_env_config(config, env_name):
    """
    Parses an environment config
    """
    all_env = get(config, 'app.all_environments', {})
    env = get(config, 'app.environments.' + str(env_name), {})
    return merge_dict(all_env, env)

def parse_env_config ( config , env_name ) : all_env = get ( config , 'app.all_environments' , { } ) env = get ( config , 'app.environments.' + str ( env_name ) , { } ) return merge_dict ( all_env , env )


def create_archive(directory, filename, config={}, ignore_predicate=None, ignored_files=['.git', '.svn']):
    """
    Creates an archive from a directory and returns
    the file that was created.
    """
    with zipfile.ZipFile(filename, 'w', compression=zipfile.ZIP_DEFLATED) as zip_file:
        root_len = len(os.path.abspath(directory))

        # create it
        out("Creating archive: " + str(filename))
        for root, dirs, files in os.walk(directory, followlinks=True):
            archive_root = os.path.abspath(root)[root_len + 1:]
            for f in files:
                fullpath = os.path.join(root, f)
                archive_name = os.path.join(archive_root, f)

                # ignore the file we're creating
                if filename in fullpath:
                    continue

                # ignored files
                if ignored_files is not None:
                    for name in ignored_files:
                        if fullpath.endswith(name):
                            out("Skipping: " + str(name))
                            continue

                # do predicate
                if ignore_predicate is not None:
                    if not ignore_predicate(archive_name):
                        out("Skipping: " + str(archive_name))
                        continue

                out("Adding: " + str(archive_name))
                zip_file.write(fullpath, archive_name, zipfile.ZIP_DEFLATED)

    return filename

def
create_archive
(
directory
,
filename
,
config
=
{
}
,
ignore_predicate
=
,
ignored_files
=
[
'.git'
,
'.svn'
]
)
:
with
zipfile
.
ZipFile
(
filename
,
'w'
,
compression
=
zipfile
.
ZIP_DEFLATED
)
as
zip_file
:
root_len
=
len
(
os
.
path
.
abspath
(
directory
)
)
# create it
out
(
"Creating archive: "
+
str
(
filename
)
)
for
root
,
dirs
,
files
in
os
.
walk
(
directory
,
followlinks
=
True
)
:
archive_root
=
os
.
path
.
abspath
(
root
)
[
root_len
+
1
:
]
for
f
in
files
:
fullpath
=
os
.
path
.
join
(
root
,
f
)
archive_name
=
os
.
path
.
join
(
archive_root
,
f
)
# ignore the file we're creating
if
filename
in
fullpath
:
continue
# ignored files
if
ignored_files
is
not
:
for
name
in
ignored_files
:
if
fullpath
.
endswith
(
name
)
:
out
(
"Skipping: "
+
str
(
name
)
)
continue
# do predicate
if
ignore_predicate
is
not
:
if
not
ignore_predicate
(
archive_name
)
:
out
(
"Skipping: "
+
str
(
archive_name
)
)
continue
out
(
"Adding: "
+
str
(
archive_name
)
)
zip_file
.
write
(
fullpath
,
archive_name
,
zipfile
.
ZIP_DEFLATED
)
return
filename

Creates an archive from a directory and returns the file that was created .


def add_config_files_to_archive(directory, filename, config={}):
    """
    Adds configuration files to an existing archive
    """
    with zipfile.ZipFile(filename, 'a') as zip_file:
        for conf in config:
            for conf, tree in list(conf.items()):
                if 'yaml' in tree:
                    content = yaml.dump(tree['yaml'], default_flow_style=False)
                else:
                    content = tree.get('content', '')
                out("Adding file " + str(conf) + " to archive " + str(filename))
                file_entry = zipfile.ZipInfo(conf)
                file_entry.external_attr = tree.get('permissions', 0o644) << 16
                zip_file.writestr(file_entry, content)

    return filename

def
add_config_files_to_archive
(
directory
,
filename
,
config
=
{
}
)
:
with
zipfile
.
ZipFile
(
filename
,
'a'
)
as
zip_file
:
for
conf
in
config
:
for
conf
,
tree
in
list
(
conf
.
items
(
)
)
:
if
'yaml'
in
tree
:
content
=
yaml
.
dump
(
tree
[
'yaml'
]
,
default_flow_style
=
False
)
else
:
content
=
tree
.
get
(
'content'
,
''
)
out
(
"Adding file "
+
str
(
conf
)
+
" to archive "
+
str
(
filename
)
)
file_entry
=
zipfile
.
ZipInfo
(
conf
)
file_entry
.
external_attr
=
tree
.
get
(
'permissions'
,
0o644
)
<<
16
zip_file
.
writestr
(
file_entry
,
content
)
return
filename


def swap_environment_cnames(self, from_env_name, to_env_name):
        """
        Swaps cnames for an environment
        """
        self.ebs.swap_environment_cnames(source_environment_name=from_env_name,
                                         destination_environment_name=to_env_name)

def swap_environment_cnames ( self , from_env_name , to_env_name ) : self . ebs . swap_environment_cnames ( source_environment_name = from_env_name , destination_environment_name = to_env_name )


def upload_archive(self, filename, key, auto_create_bucket=True):
        """
        Uploads an application archive version to s3
        """
        try:
            bucket = self.s3.get_bucket(self.aws.bucket)
            if ((
                  self.aws.region != 'us-east-1' and self.aws.region != 'eu-west-1') and bucket.get_location() != self.aws.region) or (
                  self.aws.region == 'us-east-1' and bucket.get_location() != '') or (
                  self.aws.region == 'eu-west-1' and bucket.get_location() != 'eu-west-1'):
                raise Exception("Existing bucket doesn't match region")
        except S3ResponseError:
            bucket = self.s3.create_bucket(self.aws.bucket, location=self.aws.region)

        def __report_upload_progress(sent, total):
            if not sent:
                sent = 0
            if not total:
                total = 0
            out("Uploaded " + str(sent) + " bytes of " + str(total) \
                + " (" + str(int(float(max(1, sent)) / float(total) * 100)) + "%)")

        # upload the new version
        k = Key(bucket)
        k.key = self.aws.bucket_path + key
        k.set_metadata('time', str(time()))
        k.set_contents_from_filename(filename, cb=__report_upload_progress, num_cb=10)

def
upload_archive
(
self
,
filename
,
key
,
auto_create_bucket
=
True
)
:
try
:
bucket
=
self
.
s3
.
get_bucket
(
self
.
aws
.
bucket
)
if
(
(
self
.
aws
.
region
!=
'us-east-1'
and
self
.
aws
.
region
!=
'eu-west-1'
)
and
bucket
.
get_location
(
)
!=
self
.
aws
.
region
)
or
(
self
.
aws
.
region
==
'us-east-1'
and
bucket
.
get_location
(
)
!=
''
)
or
(
self
.
aws
.
region
==
'eu-west-1'
and
bucket
.
get_location
(
)
!=
'eu-west-1'
)
:
raise
Exception
(
"Existing bucket doesn't match region"
)
except
S3ResponseError
:
bucket
=
self
.
s3
.
create_bucket
(
self
.
aws
.
bucket
,
location
=
self
.
aws
.
region
)
def
__report_upload_progress
(
sent
,
total
)
:
if
not
sent
:
sent
=
0
if
not
total
:
total
=
0
out
(
"Uploaded "
+
str
(
sent
)
+
" bytes of "
+
str
(
total
)
+
" ("
+
str
(
int
(
float
(
max
(
1
,
sent
)
)
/
float
(
total
)
*
100
)
)
+
"%)"
)
# upload the new version
k
=
Key
(
bucket
)
k
.
key
=
self
.
aws
.
bucket_path
+
key
k
.
set_metadata
(
'time'
,
str
(
time
(
)
)
)
k
.
set_contents_from_filename
(
filename
,
cb
=
__report_upload_progress
,
num_cb
=
10
)


def application_exists(self):
        """
        Returns whether or not the given app_name exists
        """
        response = self.ebs.describe_applications(application_names=[self.app_name])
        return len(response['DescribeApplicationsResponse']['DescribeApplicationsResult']['Applications']) > 0

def application_exists ( self ) : response = self . ebs . describe_applications ( application_names = [ self . app_name ] ) return len ( response [ 'DescribeApplicationsResponse' ] [ 'DescribeApplicationsResult' ] [ 'Applications' ] ) > 0


def create_environment(self, env_name, version_label=None,
                           solution_stack_name=None, cname_prefix=None, description=None,
                           option_settings=None, tier_name='WebServer', tier_type='Standard', tier_version='1.1'):
        """
        Creates a new environment
        """
        out("Creating environment: " + str(env_name) + ", tier_name:" + str(tier_name) + ", tier_type:" + str(tier_type))
        self.ebs.create_environment(self.app_name, env_name,
                                    version_label=version_label,
                                    solution_stack_name=solution_stack_name,
                                    cname_prefix=cname_prefix,
                                    description=description,
                                    option_settings=option_settings,
                                    tier_type=tier_type,
                                    tier_name=tier_name,
                                    tier_version=tier_version)

def
create_environment
(
self
,
env_name
,
version_label
=
,
solution_stack_name
=
,
cname_prefix
=
,
description
=
,
option_settings
=
,
tier_name
=
'WebServer'
,
tier_type
=
'Standard'
,
tier_version
=
'1.1'
)
:
out
(
"Creating environment: "
+
str
(
env_name
)
+
", tier_name:"
+
str
(
tier_name
)
+
", tier_type:"
+
str
(
tier_type
)
)
self
.
ebs
.
create_environment
(
self
.
app_name
,
env_name
,
version_label
=
version_label
,
solution_stack_name
=
solution_stack_name
,
cname_prefix
=
cname_prefix
,
description
=
description
,
option_settings
=
option_settings
,
tier_type
=
tier_type
,
tier_name
=
tier_name
,
tier_version
=
tier_version
)


def environment_exists(self, env_name):
        """
        Returns whether or not the given environment exists
        """
        response = self.ebs.describe_environments(application_name=self.app_name, environment_names=[env_name],
                                                  include_deleted=False)
        return len(response['DescribeEnvironmentsResponse']['DescribeEnvironmentsResult']['Environments']) > 0 \
               and response['DescribeEnvironmentsResponse']['DescribeEnvironmentsResult']['Environments'][0][
                       'Status'] != 'Terminated'

def environment_exists ( self , env_name ) : response = self . ebs . describe_environments ( application_name = self . app_name , environment_names = [ env_name ] , include_deleted = False ) return len ( response [ 'DescribeEnvironmentsResponse' ] [ 'DescribeEnvironmentsResult' ] [ 'Environments' ] ) > 0 and response [ 'DescribeEnvironmentsResponse' ] [ 'DescribeEnvironmentsResult' ] [ 'Environments' ] [ 0 ] [ 'Status' ] != 'Terminated'


def get_environments(self):
        """
        Returns the environments
        """
        response = self.ebs.describe_environments(application_name=self.app_name, include_deleted=False)
        return response['DescribeEnvironmentsResponse']['DescribeEnvironmentsResult']['Environments']

def get_environments ( self ) : response = self . ebs . describe_environments ( application_name = self . app_name , include_deleted = False ) return response [ 'DescribeEnvironmentsResponse' ] [ 'DescribeEnvironmentsResult' ] [ 'Environments' ]


def update_environment(self, environment_name, description=None, option_settings=[], tier_type=None, tier_name=None,
                           tier_version='1.0'):
        """
        Updates an application version
        """
        out("Updating environment: " + str(environment_name))
        messages = self.ebs.validate_configuration_settings(self.app_name, option_settings,
                                                            environment_name=environment_name)
        messages = messages['ValidateConfigurationSettingsResponse']['ValidateConfigurationSettingsResult']['Messages']
        ok = True
        for message in messages:
            if message['Severity'] == 'error':
                ok = False
            out("[" + message['Severity'] + "] " + str(environment_name) + " - '" \
                + message['Namespace'] + ":" + message['OptionName'] + "': " + message['Message'])
        self.ebs.update_environment(
            environment_name=environment_name,
            description=description,
            option_settings=option_settings,
            tier_type=tier_type,
            tier_name=tier_name,
            tier_version=tier_version)

def
update_environment
(
self
,
environment_name
,
description
=
,
option_settings
=
[
]
,
tier_type
=
,
tier_name
=
,
tier_version
=
'1.0'
)
:
out
(
"Updating environment: "
+
str
(
environment_name
)
)
messages
=
self
.
ebs
.
validate_configuration_settings
(
self
.
app_name
,
option_settings
,
environment_name
=
environment_name
)
messages
=
messages
[
'ValidateConfigurationSettingsResponse'
]
[
'ValidateConfigurationSettingsResult'
]
[
'Messages'
]
ok
=
True
for
message
in
messages
:
if
message
[
'Severity'
]
==
'error'
:
ok
=
False
out
(
"["
+
message
[
'Severity'
]
+
"] "
+
str
(
environment_name
)
+
" - '"
+
message
[
'Namespace'
]
+
":"
+
message
[
'OptionName'
]
+
"': "
+
message
[
'Message'
]
)
self
.
ebs
.
update_environment
(
environment_name
=
environment_name
,
description
=
description
,
option_settings
=
option_settings
,
tier_type
=
tier_type
,
tier_name
=
tier_name
,
tier_version
=
tier_version
)


def environment_name_for_cname(self, env_cname):
        """
        Returns an environment name for the given cname
        """
        envs = self.get_environments()
        for env in envs:
            if env['Status'] != 'Terminated' \
                and 'CNAME' in env \
                and env['CNAME'] \
                and env['CNAME'].lower().startswith(env_cname.lower() + '.'):
                return env['EnvironmentName']
        return None

def environment_name_for_cname ( self , env_cname ) : envs = self . get_environments ( ) for env in envs : if env [ 'Status' ] != 'Terminated' and 'CNAME' in env and env [ 'CNAME' ] and env [ 'CNAME' ] . lower ( ) . startswith ( env_cname . lower ( ) + '.' ) : return env [ 'EnvironmentName' ] return None


def deploy_version(self, environment_name, version_label):
        """
        Deploys a version to an environment
        """
        out("Deploying " + str(version_label) + " to " + str(environment_name))
        self.ebs.update_environment(environment_name=environment_name, version_label=version_label)

def
deploy_version
(
self
,
environment_name
,
version_label
)
:
out
(
"Deploying "
+
str
(
version_label
)
+
" to "
+
str
(
environment_name
)
)
self
.
ebs
.
update_environment
(
environment_name
=
environment_name
,
version_label
=
version_label
)


def get_versions(self):
        """
        Returns the versions available
        """
        response = self.ebs.describe_application_versions(application_name=self.app_name)
        return response['DescribeApplicationVersionsResponse']['DescribeApplicationVersionsResult']['ApplicationVersions']

def get_versions ( self ) : response = self . ebs . describe_application_versions ( application_name = self . app_name ) return response [ 'DescribeApplicationVersionsResponse' ] [ 'DescribeApplicationVersionsResult' ] [ 'ApplicationVersions' ]


def create_application_version(self, version_label, key):
        """
        Creates an application version
        """
        out("Creating application version " + str(version_label) + " for " + str(key))
        self.ebs.create_application_version(self.app_name, version_label,
                                            s3_bucket=self.aws.bucket, s3_key=self.aws.bucket_path+key)

def
create_application_version
(
self
,
version_label
,
key
)
:
out
(
"Creating application version "
+
str
(
version_label
)
+
" for "
+
str
(
key
)
)
self
.
ebs
.
create_application_version
(
self
.
app_name
,
version_label
,
s3_bucket
=
self
.
aws
.
bucket
,
s3_key
=
self
.
aws
.
bucket_path
+
key
)


def delete_unused_versions(self, versions_to_keep=10):
        """
        Deletes unused versions
        """

        # get versions in use
        environments = self.ebs.describe_environments(application_name=self.app_name, include_deleted=False)
        environments = environments['DescribeEnvironmentsResponse']['DescribeEnvironmentsResult']['Environments']
        versions_in_use = []
        for env in environments:
            versions_in_use.append(env['VersionLabel'])

        # get all versions
        versions = self.ebs.describe_application_versions(application_name=self.app_name)
        versions = versions['DescribeApplicationVersionsResponse']['DescribeApplicationVersionsResult'][
            'ApplicationVersions']
        versions = sorted(versions, reverse=True, key=functools.cmp_to_key(lambda x, y: (x['DateCreated'] > y['DateCreated']) - (x['DateCreated'] < y['DateCreated'])))

        # delete versions in use
        for version in versions[versions_to_keep:]:
            if version['VersionLabel'] in versions_in_use:
                out("Not deleting " + version["VersionLabel"] + " because it is in use")
            else:
                out("Deleting unused version: " + version["VersionLabel"])
                self.ebs.delete_application_version(application_name=self.app_name,
                                                    version_label=version['VersionLabel'])
                sleep(2)

def
delete_unused_versions
(
self
,
versions_to_keep
=
10
)
:
# get versions in use
environments
=
self
.
ebs
.
describe_environments
(
application_name
=
self
.
app_name
,
include_deleted
=
False
)
environments
=
environments
[
'DescribeEnvironmentsResponse'
]
[
'DescribeEnvironmentsResult'
]
[
'Environments'
]
versions_in_use
=
[
]
for
env
in
environments
:
versions_in_use
.
append
(
env
[
'VersionLabel'
]
)
# get all versions
versions
=
self
.
ebs
.
describe_application_versions
(
application_name
=
self
.
app_name
)
versions
=
versions
[
'DescribeApplicationVersionsResponse'
]
[
'DescribeApplicationVersionsResult'
]
[
'ApplicationVersions'
]
versions
=
sorted
(
versions
,
reverse
=
True
,
key
=
functools
.
cmp_to_key
(
lambda
x
,
y
:
(
x
[
'DateCreated'
]
>
y
[
'DateCreated'
]
)
(
x
[
'DateCreated'
]
<
y
[
'DateCreated'
]
)
)
)
# delete versions in use
for
version
in
versions
[
versions_to_keep
:
]
:
if
version
[
'VersionLabel'
]
in
versions_in_use
:
out
(
"Not deleting "
+
version
[
"VersionLabel"
]
+
" because it is in use"
)
else
:
out
(
"Deleting unused version: "
+
version
[
"VersionLabel"
]
)
self
.
ebs
.
delete_application_version
(
application_name
=
self
.
app_name
,
version_label
=
version
[
'VersionLabel'
]
)
sleep
(
2
)


def describe_events(self, environment_name, next_token=None, start_time=None):
        """
        Describes events from the given environment
        """
        events = self.ebs.describe_events(
            application_name=self.app_name,
            environment_name=environment_name,
            next_token=next_token,
            start_time=start_time + 'Z')

        return (events['DescribeEventsResponse']['DescribeEventsResult']['Events'], events['DescribeEventsResponse']['DescribeEventsResult']['NextToken'])

def describe_events ( self , environment_name , next_token = None , start_time = None ) : events = self . ebs . describe_events ( application_name = self . app_name , environment_name = environment_name , next_token = next_token , start_time = start_time + 'Z' ) return ( events [ 'DescribeEventsResponse' ] [ 'DescribeEventsResult' ] [ 'Events' ] , events [ 'DescribeEventsResponse' ] [ 'DescribeEventsResult' ] [ 'NextToken' ] )


def add_arguments(parser):
    """
    adds arguments for the swap urls command
    """
    parser.add_argument('-o', '--old-environment', help='Old environment name', required=True)
    parser.add_argument('-n', '--new-environment', help='New environment name', required=True)

def
add_arguments
(
parser
)
:
parser
.
add_argument
(
'-o'
,
'--old-environment'
,
help
=
'Old environment name'
,
required
=
True
)
parser
.
add_argument
(
'-n'
,
'--new-environment'
,
help
=
'New environment name'
,
required
=
True
)


def execute(helper, config, args):
    """
    Swaps old and new URLs.
    If old_environment was active, new_environment will become the active environment
    """
    old_env_name = args.old_environment
    new_env_name = args.new_environment

    # swap C-Names
    out("Assuming that {} is the currently active environment...".format(old_env_name))
    out("Swapping environment cnames: {} will become active, {} will become inactive.".format(new_env_name,
                                                                                old_env_name))
    helper.swap_environment_cnames(old_env_name, new_env_name)
    helper.wait_for_environments([old_env_name, new_env_name], status='Ready', include_deleted=False)

Swaps old and new URLs . If old_environment was active new_environment will become the active environment


def execute(helper, config, args):
    """
    dump command dumps things
    """
    env = parse_env_config(config, args.environment)
    option_settings = env.get('option_settings', {})
    settings = parse_option_settings(option_settings)
    for setting in settings:
        out(str(setting))

def execute ( helper , config , args ) : env = parse_env_config ( config , args . environment ) option_settings = env . get ( 'option_settings' , { } ) settings = parse_option_settings ( option_settings ) for setting in settings : out ( str ( setting ) )


def execute(helper, config, args):
    """
    The init command
    """

    # check to see if the application exists
    if not helper.application_exists():
        helper.create_application(get(config, 'app.description'))
    else:
        out("Application "+get(config, 'app.app_name')+" exists")

    # create environments
    environment_names = []
    environments_to_wait_for_green = []
    for env_name, env_config in list(get(config, 'app.environments').items()):
        environment_names.append(env_name)
        env_config = parse_env_config(config, env_name)
        if not helper.environment_exists(env_name):
            option_settings = parse_option_settings(env_config.get('option_settings', {}))
            helper.create_environment(env_name,
                solution_stack_name=env_config.get('solution_stack_name'),
                cname_prefix=env_config.get('cname_prefix', None),
                description=env_config.get('description', None),
                option_settings=option_settings,
                tier_name=env_config.get('tier_name'),
                tier_type=env_config.get('tier_type'),
                tier_version=env_config.get('tier_version'),
                version_label=args.version_label)
            environments_to_wait_for_green.append(env_name)
        else:
            out("Environment "+env_name)

    # get the environments
    environments_to_wait_for_term = []
    if args.delete:
        environments = helper.get_environments()
        for env in environments:
            if env['EnvironmentName'] not in environment_names:
                if env['Status'] != 'Ready':
                    out("Unable to delete "+env['EnvironmentName']+" because it's not in status Ready ("+env['Status']+")")
                else:
                    out("Deleting environment: "+env['EnvironmentName'])
                    helper.delete_environment(env['EnvironmentName'])
                    environments_to_wait_for_term.append(env['EnvironmentName'])

    # wait
    if not args.dont_wait and len(environments_to_wait_for_green)>0:
        helper.wait_for_environments(environments_to_wait_for_green, status='Ready', include_deleted=False)
    if not args.dont_wait and len(environments_to_wait_for_term)>0:
        helper.wait_for_environments(environments_to_wait_for_term, status='Terminated', include_deleted=False)

    out("Application initialized")
    return 0


def join_phonemes(*args):
    """Joins a Hangul letter from Korean phonemes."""
    # Normalize arguments as onset, nucleus, coda.
    if len(args) == 1:
        # tuple of (onset, nucleus[, coda])
        args = args[0]
    if len(args) == 2:
        args += (CODAS[0],)
    try:
        onset, nucleus, coda = args
    except ValueError:
        raise TypeError('join_phonemes() takes at most 3 arguments')
    offset = (
        (ONSETS.index(onset) * NUM_NUCLEUSES + NUCLEUSES.index(nucleus)) *
        NUM_CODAS + CODAS.index(coda)
    )
    return unichr(FIRST_HANGUL_OFFSET + offset)

Joins a Hangul letter from Korean phonemes .


def execute(helper, config, args):
    """
    Waits for an environment to be healthy
    """
    helper.wait_for_environments(args.environment, health=args.health)

def execute ( helper , config , args ) : helper . wait_for_environments ( args . environment , health = args . health )


def add_arguments(parser):
    """
    Args for the init command
    """
    parser.add_argument('-e', '--environment',  help='Environment name', required=False, nargs='+')
    parser.add_argument('-w', '--dont-wait', help='Skip waiting for the app to be deleted', action='store_true')


def execute(helper, config, args):
    """
    Describes recent events for an environment.
    """
    environment_name = args.environment

    (events, next_token) = helper.describe_events(environment_name, start_time=datetime.now().isoformat())

    # swap C-Names
    for event in events:
        print(("["+event['Severity']+"] "+event['Message']))

def
execute
(
helper
,
config
,
args
)
:
environment_name
=
args
.
environment
(
events
,
next_token
)
=
helper
.
describe_events
(
environment_name
,
start_time
=
datetime
.
now
(
)
.
isoformat
(
)
)
# swap C-Names
for
event
in
events
:
print
(
(
"["
+
event
[
'Severity'
]
+
"] "
+
event
[
'Message'
]
)
)

Describes recent events for an environment .


def execute(helper, config, args):
    """
    Lists solution stacks
    """
    out("Available solution stacks")
    for stack in helper.list_available_solution_stacks():
        out("    "+str(stack))
    return 0

def
execute
(
helper
,
config
,
args
)
:
out
(
"Available solution stacks"
)
for
stack
in
helper
.
list_available_solution_stacks
(
)
:
out
(
"    "
+
str
(
stack
)
)
return
0


def pick_coda_from_letter(letter):
    """Picks only a coda from a Hangul letter.  It returns ``None`` if the
    given letter is not Hangul.
    """
    try:
        __, __, coda = \
            split_phonemes(letter, onset=False, nucleus=False, coda=True)
    except ValueError:
        return None
    else:
        return coda

def pick_coda_from_letter ( letter ) : try : __ , __ , coda = split_phonemes ( letter , onset = False , nucleus = False , coda = True ) except ValueError : return None else : return coda

Picks only a coda from a Hangul letter . It returns None if the given letter is not Hangul .


def pick_coda_from_decimal(decimal):
    """Picks only a coda from a decimal."""
    decimal = Decimal(decimal)
    __, digits, exp = decimal.as_tuple()
    if exp < 0:
        return DIGIT_CODAS[digits[-1]]
    __, digits, exp = decimal.normalize().as_tuple()
    index = bisect_right(EXP_INDICES, exp) - 1
    if index < 0:
        return DIGIT_CODAS[digits[-1]]
    else:
        return EXP_CODAS[EXP_INDICES[index]]

def pick_coda_from_decimal ( decimal ) : decimal = Decimal ( decimal ) __ , digits , exp = decimal . as_tuple ( ) if exp < 0 : return DIGIT_CODAS [ digits [ - 1 ] ] __ , digits , exp = decimal . normalize ( ) . as_tuple ( ) index = bisect_right ( EXP_INDICES , exp ) - 1 if index < 0 : return DIGIT_CODAS [ digits [ - 1 ] ] else : return EXP_CODAS [ EXP_INDICES [ index ] ]


def deposit_fetcher(record_uuid, data):
    """Fetch a deposit identifier.

    :param record_uuid: Record UUID.
    :param data: Record content.
    :returns: A :class:`invenio_pidstore.fetchers.FetchedPID` that contains
        data['_deposit']['id'] as pid_value.
    """
    return FetchedPID(
        provider=DepositProvider,
        pid_type=DepositProvider.pid_type,
        pid_value=str(data['_deposit']['id']),
    )

def deposit_fetcher ( record_uuid , data ) : return FetchedPID ( provider = DepositProvider , pid_type = DepositProvider . pid_type , pid_value = str ( data [ '_deposit' ] [ 'id' ] ) , )


def deposit_minter(record_uuid, data):
    """Mint a deposit identifier.

    A PID with the following characteristics is created:

    .. code-block:: python

        {
            "object_type": "rec",
            "object_uuid": record_uuid,
            "pid_value": "<new-pid-value>",
            "pid_type": "depid",
        }

    The following deposit meta information are updated:

    .. code-block:: python

        deposit['_deposit'] = {
            "id": "<new-pid-value>",
            "status": "draft",
        }

    :param record_uuid: Record UUID.
    :param data: Record content.
    :returns: A :class:`invenio_pidstore.models.PersistentIdentifier` object.
    """
    provider = DepositProvider.create(
        object_type='rec',
        object_uuid=record_uuid,
        pid_value=uuid.uuid4().hex,
    )
    data['_deposit'] = {
        'id': provider.pid.pid_value,
        'status': 'draft',
    }
    return provider.pid

def deposit_minter ( record_uuid , data ) : provider = DepositProvider . create ( object_type = 'rec' , object_uuid = record_uuid , pid_value = uuid . uuid4 ( ) . hex , ) data [ '_deposit' ] = { 'id' : provider . pid . pid_value , 'status' : 'draft' , } return provider . pid


def admin_permission_factory():
    """Factory for creating a permission for an admin `deposit-admin-access`.

    If `invenio-access` module is installed, it returns a
    :class:`invenio_access.permissions.DynamicPermission` object.
    Otherwise, it returns a :class:`flask_principal.Permission` object.

    :returns: Permission instance.
    """
    try:
        pkg_resources.get_distribution('invenio-access')
        from invenio_access.permissions import DynamicPermission as Permission
    except pkg_resources.DistributionNotFound:
        from flask_principal import Permission

    return Permission(action_admin_access)

def admin_permission_factory ( ) : try : pkg_resources . get_distribution ( 'invenio-access' ) from invenio_access . permissions import DynamicPermission as Permission except pkg_resources . DistributionNotFound : from flask_principal import Permission return Permission ( action_admin_access )

Factory for creating a permission for an admin deposit - admin - access .


def create_blueprint(endpoints):
    """Create Invenio-Deposit-UI blueprint.

    See: :data:`invenio_deposit.config.DEPOSIT_RECORDS_UI_ENDPOINTS`.

    :param endpoints: List of endpoints configuration.
    :returns: The configured blueprint.
    """
    from invenio_records_ui.views import create_url_rule

    blueprint = Blueprint(
        'invenio_deposit_ui',
        __name__,
        static_folder='../static',
        template_folder='../templates',
        url_prefix='',
    )

    @blueprint.errorhandler(PIDDeletedError)
    def tombstone_errorhandler(error):
        """Render tombstone page."""
        return render_template(
            current_app.config['DEPOSIT_UI_TOMBSTONE_TEMPLATE'],
            pid=error.pid,
            record=error.record or {},
        ), 410

    for endpoint, options in (endpoints or {}).items():
        options = deepcopy(options)
        options.pop('jsonschema', None)
        options.pop('schemaform', None)
        blueprint.add_url_rule(**create_url_rule(endpoint, **options))

    @blueprint.route('/deposit')
    @login_required
    def index():
        """List user deposits."""
        return render_template(current_app.config['DEPOSIT_UI_INDEX_TEMPLATE'])

    @blueprint.route('/deposit/new')
    @login_required
    def new():
        """Create new deposit."""
        deposit_type = request.values.get('type')
        return render_template(
            current_app.config['DEPOSIT_UI_NEW_TEMPLATE'],
            record={'_deposit': {'id': None}},
            jsonschema=current_deposit.jsonschemas[deposit_type],
            schemaform=current_deposit.schemaforms[deposit_type],
        )

    return blueprint

def
create_blueprint
(
endpoints
)
:
from
invenio_records_ui
.
views
import
create_url_rule
blueprint
=
Blueprint
(
'invenio_deposit_ui'
,
__name__
,
static_folder
=
'../static'
,
template_folder
=
'../templates'
,
url_prefix
=
''
,
)
@
blueprint
.
errorhandler
(
PIDDeletedError
)
def
tombstone_errorhandler
(
error
)
:
"""Render tombstone page."""
return
render_template
(
current_app
.
config
[
'DEPOSIT_UI_TOMBSTONE_TEMPLATE'
]
,
pid
=
error
.
pid
,
record
=
error
.
record
or
{
}
,
)
,
410
for
endpoint
,
options
in
(
endpoints
or
{
}
)
.
items
(
)
:
options
=
deepcopy
(
options
)
options
.
pop
(
'jsonschema'
,
)
options
.
pop
(
'schemaform'
,
)
blueprint
.
add_url_rule
(
*
*
create_url_rule
(
endpoint
,
*
*
options
)
)
@
blueprint
.
route
(
'/deposit'
)
@
login_required
def
index
(
)
:
"""List user deposits."""
return
render_template
(
current_app
.
config
[
'DEPOSIT_UI_INDEX_TEMPLATE'
]
)
@
blueprint
.
route
(
'/deposit/new'
)
@
login_required
def
new
(
)
:
"""Create new deposit."""
deposit_type
=
request
.
values
.
get
(
'type'
)
return
render_template
(
current_app
.
config
[
'DEPOSIT_UI_NEW_TEMPLATE'
]
,
record
=
{
'_deposit'
:
{
'id'
:
}
}
,
jsonschema
=
current_deposit
.
jsonschemas
[
deposit_type
]
,
schemaform
=
current_deposit
.
schemaforms
[
deposit_type
]
,
)
return
blueprint

Create Invenio - Deposit - UI blueprint .


def default_view_method(pid, record, template=None):
    """Default view method.

    Sends ``record_viewed`` signal and renders template.
    """
    record_viewed.send(
        current_app._get_current_object(),
        pid=pid,
        record=record,
    )

    deposit_type = request.values.get('type')

    return render_template(
        template,
        pid=pid,
        record=record,
        jsonschema=current_deposit.jsonschemas[deposit_type],
        schemaform=current_deposit.schemaforms[deposit_type],
    )

def default_view_method ( pid , record , template = None ) : record_viewed . send ( current_app . _get_current_object ( ) , pid = pid , record = record , ) deposit_type = request . values . get ( 'type' ) return render_template ( template , pid = pid , record = record , jsonschema = current_deposit . jsonschemas [ deposit_type ] , schemaform = current_deposit . schemaforms [ deposit_type ] , )


def create(cls, object_type=None, object_uuid=None, **kwargs):
        """Create a new deposit identifier.

        :param object_type: The object type (Default: ``None``)
        :param object_uuid: The object UUID (Default: ``None``)
        :param kwargs: It contains the pid value.
        """
        assert 'pid_value' in kwargs
        kwargs.setdefault('status', cls.default_status)
        return super(DepositProvider, cls).create(
            object_type=object_type, object_uuid=object_uuid, **kwargs)

def create ( cls , object_type = None , object_uuid = None , * * kwargs ) : assert 'pid_value' in kwargs kwargs . setdefault ( 'status' , cls . default_status ) return super ( DepositProvider , cls ) . create ( object_type = object_type , object_uuid = object_uuid , * * kwargs )


def extract_actions_from_class(record_class):
    """Extract actions from class."""
    for name in dir(record_class):
        method = getattr(record_class, name, None)
        if method and getattr(method, '__deposit_action__', False):
            yield method.__name__

def extract_actions_from_class ( record_class ) : for name in dir ( record_class ) : method = getattr ( record_class , name , None ) if method and getattr ( method , '__deposit_action__' , False ) : yield method . __name__


def check_oauth2_scope(can_method, *myscopes):
    """Base permission factory that check OAuth2 scope and can_method.

    :param can_method: Permission check function that accept a record in input
        and return a boolean.
    :param myscopes: List of scopes required to permit the access.
    :returns: A :class:`flask_principal.Permission` factory.
    """
    def check(record, *args, **kwargs):
        @require_api_auth()
        @require_oauth_scopes(*myscopes)
        def can(self):
            return can_method(record)

        return type('CheckOAuth2Scope', (), {'can': can})()
    return check

def check_oauth2_scope ( can_method , * myscopes ) : def check ( record , * args , * * kwargs ) : @ require_api_auth ( ) @ require_oauth_scopes ( * myscopes ) def can ( self ) : return can_method ( record ) return type ( 'CheckOAuth2Scope' , ( ) , { 'can' : can } ) ( ) return check

Base permission factory that check OAuth2 scope and can_method .


def can_elasticsearch(record):
    """Check if a given record is indexed.

    :param record: A record object.
    :returns: If the record is indexed returns `True`, otherwise `False`.
    """
    search = request._methodview.search_class()
    search = search.get_record(str(record.id))
    return search.count() == 1

def can_elasticsearch ( record ) : search = request . _methodview . search_class ( ) search = search . get_record ( str ( record . id ) ) return search . count ( ) == 1


def create_error_handlers(blueprint):
    """Create error handlers on blueprint."""
    blueprint.errorhandler(PIDInvalidAction)(create_api_errorhandler(
        status=403, message='Invalid action'
    ))
    records_rest_error_handlers(blueprint)

def
create_error_handlers
(
blueprint
)
:
blueprint
.
errorhandler
(
PIDInvalidAction
)
(
create_api_errorhandler
(
status
=
403
,
message
=
'Invalid action'
)
)
records_rest_error_handlers
(
blueprint
)


def create_blueprint(endpoints):
    """Create Invenio-Deposit-REST blueprint.

    See: :data:`invenio_deposit.config.DEPOSIT_REST_ENDPOINTS`.

    :param endpoints: List of endpoints configuration.
    :returns: The configured blueprint.
    """
    blueprint = Blueprint(
        'invenio_deposit_rest',
        __name__,
        url_prefix='',
    )
    create_error_handlers(blueprint)

    for endpoint, options in (endpoints or {}).items():
        options = deepcopy(options)

        if 'files_serializers' in options:
            files_serializers = options.get('files_serializers')
            files_serializers = {mime: obj_or_import_string(func)
                                 for mime, func in files_serializers.items()}
            del options['files_serializers']
        else:
            files_serializers = {}

        if 'record_serializers' in options:
            serializers = options.get('record_serializers')
            serializers = {mime: obj_or_import_string(func)
                           for mime, func in serializers.items()}
        else:
            serializers = {}

        file_list_route = options.pop(
            'file_list_route',
            '{0}/files'.format(options['item_route'])
        )
        file_item_route = options.pop(
            'file_item_route',
            '{0}/files/<path:key>'.format(options['item_route'])
        )

        options.setdefault('search_class', DepositSearch)
        search_class = obj_or_import_string(options['search_class'])

        # records rest endpoints will use the deposit class as record class
        options.setdefault('record_class', Deposit)
        record_class = obj_or_import_string(options['record_class'])

        # backward compatibility for indexer class
        options.setdefault('indexer_class', None)

        for rule in records_rest_url_rules(endpoint, **options):
            blueprint.add_url_rule(**rule)

        search_class_kwargs = {}
        if options.get('search_index'):
            search_class_kwargs['index'] = options['search_index']

        if options.get('search_type'):
            search_class_kwargs['doc_type'] = options['search_type']

        ctx = dict(
            read_permission_factory=obj_or_import_string(
                options.get('read_permission_factory_imp')
            ),
            create_permission_factory=obj_or_import_string(
                options.get('create_permission_factory_imp')
            ),
            update_permission_factory=obj_or_import_string(
                options.get('update_permission_factory_imp')
            ),
            delete_permission_factory=obj_or_import_string(
                options.get('delete_permission_factory_imp')
            ),
            record_class=record_class,
            search_class=partial(search_class, **search_class_kwargs),
            default_media_type=options.get('default_media_type'),
        )

        deposit_actions = DepositActionResource.as_view(
            DepositActionResource.view_name.format(endpoint),
            serializers=serializers,
            pid_type=options['pid_type'],
            ctx=ctx,
        )

        blueprint.add_url_rule(
            '{0}/actions/<any({1}):action>'.format(
                options['item_route'],
                ','.join(extract_actions_from_class(record_class)),
            ),
            view_func=deposit_actions,
            methods=['POST'],
        )

        deposit_files = DepositFilesResource.as_view(
            DepositFilesResource.view_name.format(endpoint),
            serializers=files_serializers,
            pid_type=options['pid_type'],
            ctx=ctx,
        )

        blueprint.add_url_rule(
            file_list_route,
            view_func=deposit_files,
            methods=['GET', 'POST', 'PUT'],
        )

        deposit_file = DepositFileResource.as_view(
            DepositFileResource.view_name.format(endpoint),
            serializers=files_serializers,
            pid_type=options['pid_type'],
            ctx=ctx,
        )

        blueprint.add_url_rule(
            file_item_route,
            view_func=deposit_file,
            methods=['GET', 'PUT', 'DELETE'],
        )
    return blueprint

Create Invenio - Deposit - REST blueprint .


def post(self, pid, record, action):
        """Handle deposit action.

        After the action is executed, a
        :class:`invenio_deposit.signals.post_action` signal is sent.

        Permission required: `update_permission_factory`.

        :param pid: Pid object (from url).
        :param record: Record object resolved from the pid.
        :param action: The action to execute.
        """
        record = getattr(record, action)(pid=pid)

        db.session.commit()
        # Refresh the PID and record metadata
        db.session.refresh(pid)
        db.session.refresh(record.model)
        post_action.send(current_app._get_current_object(), action=action,
                         pid=pid, deposit=record)
        response = self.make_response(pid, record,
                                      202 if action == 'publish' else 201)
        endpoint = '.{0}_item'.format(pid.pid_type)
        location = url_for(endpoint, pid_value=pid.pid_value, _external=True)
        response.headers.extend(dict(Location=location))
        return response

def
post
(
self
,
pid
,
record
,
action
)
:
record
=
getattr
(
record
,
action
)
(
pid
=
pid
)
db
.
session
.
commit
(
)
# Refresh the PID and record metadata
db
.
session
.
refresh
(
pid
)
db
.
session
.
refresh
(
record
.
model
)
post_action
.
send
(
current_app
.
_get_current_object
(
)
,
action
=
action
,
pid
=
pid
,
deposit
=
record
)
response
=
self
.
make_response
(
pid
,
record
,
202
if
action
==
'publish'
else
201
)
endpoint
=
'.{0}_item'
.
format
(
pid
.
pid_type
)
location
=
url_for
(
endpoint
,
pid_value
=
pid
.
pid_value
,
_external
=
True
)
response
.
headers
.
extend
(
dict
(
Location
=
location
)
)
return
response


def get(self, pid, record):
        """Get files.

        Permission required: `read_permission_factory`.

        :param pid: Pid object (from url).
        :param record: Record object resolved from the pid.
        :returns: The files.
        """
        return self.make_response(obj=record.files, pid=pid, record=record)

def get ( self , pid , record ) : return self . make_response ( obj = record . files , pid = pid , record = record )


def post(self, pid, record):
        """Handle POST deposit files.

        Permission required: `update_permission_factory`.

        :param pid: Pid object (from url).
        :param record: Record object resolved from the pid.
        """
        # load the file
        uploaded_file = request.files['file']
        # file name
        key = secure_filename(
            request.form.get('name') or uploaded_file.filename
        )
        # check if already exists a file with this name
        if key in record.files:
            raise FileAlreadyExists()
        # add it to the deposit
        record.files[key] = uploaded_file.stream
        record.commit()
        db.session.commit()
        return self.make_response(
            obj=record.files[key].obj, pid=pid, record=record, status=201)


def put(self, pid, record):
        """Handle the sort of the files through the PUT deposit files.

        Expected input in body PUT:

        .. code-block:: javascript

            [
                {
                    "id": 1
                },
                {
                    "id": 2
                },
                ...
            }

        Permission required: `update_permission_factory`.

        :param pid: Pid object (from url).
        :param record: Record object resolved from the pid.
        :returns: The files.
        """
        try:
            ids = [data['id'] for data in json.loads(
                request.data.decode('utf-8'))]
        except KeyError:
            raise WrongFile()

        record.files.sort_by(*ids)
        record.commit()
        db.session.commit()
        return self.make_response(obj=record.files, pid=pid, record=record)

def put ( self , pid , record ) : try : ids = [ data [ 'id' ] for data in json . loads ( request . data . decode ( 'utf-8' ) ) ] except KeyError : raise WrongFile ( ) record . files . sort_by ( * ids ) record . commit ( ) db . session . commit ( ) return self . make_response ( obj = record . files , pid = pid , record = record )

Handle the sort of the files through the PUT deposit files .


def get(self, pid, record, key, version_id, **kwargs):
        """Get file.

        Permission required: `read_permission_factory`.

        :param pid: Pid object (from url).
        :param record: Record object resolved from the pid.
        :param key: Unique identifier for the file in the deposit.
        :param version_id: File version. Optional. If no version is provided,
            the last version is retrieved.
        :returns: the file content.
        """
        try:
            obj = record.files[str(key)].get_version(version_id=version_id)
            return self.make_response(
                obj=obj or abort(404), pid=pid, record=record)
        except KeyError:
            abort(404)

def get ( self , pid , record , key , version_id , * * kwargs ) : try : obj = record . files [ str ( key ) ] . get_version ( version_id = version_id ) return self . make_response ( obj = obj or abort ( 404 ) , pid = pid , record = record ) except KeyError : abort ( 404 )


def put(self, pid, record, key):
        """Handle the file rename through the PUT deposit file.

        Permission required: `update_permission_factory`.

        :param pid: Pid object (from url).
        :param record: Record object resolved from the pid.
        :param key: Unique identifier for the file in the deposit.
        """
        try:
            data = json.loads(request.data.decode('utf-8'))
            new_key = data['filename']
        except KeyError:
            raise WrongFile()
        new_key_secure = secure_filename(new_key)
        if not new_key_secure or new_key != new_key_secure:
            raise WrongFile()
        try:
            obj = record.files.rename(str(key), new_key_secure)
        except KeyError:
            abort(404)
        record.commit()
        db.session.commit()
        return self.make_response(obj=obj, pid=pid, record=record)

def put ( self , pid , record , key ) : try : data = json . loads ( request . data . decode ( 'utf-8' ) ) new_key = data [ 'filename' ] except KeyError : raise WrongFile ( ) new_key_secure = secure_filename ( new_key ) if not new_key_secure or new_key != new_key_secure : raise WrongFile ( ) try : obj = record . files . rename ( str ( key ) , new_key_secure ) except KeyError : abort ( 404 ) record . commit ( ) db . session . commit ( ) return self . make_response ( obj = obj , pid = pid , record = record )

Handle the file rename through the PUT deposit file .


def delete(self, pid, record, key):
        """Handle DELETE deposit file.

        Permission required: `update_permission_factory`.

        :param pid: Pid object (from url).
        :param record: Record object resolved from the pid.
        :param key: Unique identifier for the file in the deposit.
        """
        try:
            del record.files[str(key)]
            record.commit()
            db.session.commit()
            return make_response('', 204)
        except KeyError:
            abort(404, 'The specified object does not exist or has already '
                  'been deleted.')


def records():
    """Load records."""
    import pkg_resources
    from dojson.contrib.marc21 import marc21
    from dojson.contrib.marc21.utils import create_record, split_blob
    from flask_login import login_user, logout_user
    from invenio_accounts.models import User
    from invenio_deposit.api import Deposit

    users = User.query.all()

    # pkg resources the demodata
    data_path = pkg_resources.resource_filename(
        'invenio_records', 'data/marc21/bibliographic.xml'
    )
    with open(data_path) as source:
        with current_app.test_request_context():
            indexer = RecordIndexer()
            with db.session.begin_nested():
                for index, data in enumerate(split_blob(source.read()),
                                             start=1):
                    login_user(users[index % len(users)])
                    # do translate
                    record = marc21.do(create_record(data))
                    # create record
                    indexer.index(Deposit.create(record))
                    logout_user()
            db.session.commit()

def
records
(
)
:
import
pkg_resources
from
dojson
.
contrib
.
marc21
import
marc21
from
dojson
.
contrib
.
marc21
.
utils
import
create_record
,
split_blob
from
flask_login
import
login_user
,
logout_user
from
invenio_accounts
.
models
import
User
from
invenio_deposit
.
api
import
Deposit
users
=
User
.
query
.
all
(
)
# pkg resources the demodata
data_path
=
pkg_resources
.
resource_filename
(
'invenio_records'
,
'data/marc21/bibliographic.xml'
)
with
open
(
data_path
)
as
source
:
with
current_app
.
test_request_context
(
)
:
indexer
=
RecordIndexer
(
)
with
db
.
session
.
begin_nested
(
)
:
for
index
,
data
in
enumerate
(
split_blob
(
source
.
read
(
)
)
,
start
=
1
)
:
login_user
(
users
[
index
%
len
(
users
)
]
)
# do translate
record
=
marc21
.
do
(
create_record
(
data
)
)
# create record
indexer
.
index
(
Deposit
.
create
(
record
)
)
logout_user
(
)
db
.
session
.
commit
(
)


def location():
    """Load default location."""
    d = current_app.config['DATADIR']
    with db.session.begin_nested():
        Location.query.delete()
        loc = Location(name='local', uri=d, default=True)
        db.session.add(loc)
    db.session.commit()

def location ( ) : d = current_app . config [ 'DATADIR' ] with db . session . begin_nested ( ) : Location . query . delete ( ) loc = Location ( name = 'local' , uri = d , default = True ) db . session . add ( loc ) db . session . commit ( )


def jsonschemas(self):
        """Load deposit JSON schemas."""
        _jsonschemas = {
            k: v['jsonschema']
            for k, v in self.app.config['DEPOSIT_RECORDS_UI_ENDPOINTS'].items()
            if 'jsonschema' in v
        }
        return defaultdict(
            lambda: self.app.config['DEPOSIT_DEFAULT_JSONSCHEMA'], _jsonschemas
        )

def jsonschemas ( self ) : _jsonschemas = { k : v [ 'jsonschema' ] for k , v in self . app . config [ 'DEPOSIT_RECORDS_UI_ENDPOINTS' ] . items ( ) if 'jsonschema' in v } return defaultdict ( lambda : self . app . config [ 'DEPOSIT_DEFAULT_JSONSCHEMA' ] , _jsonschemas )


def schemaforms(self):
        """Load deposit schema forms."""
        _schemaforms = {
            k: v['schemaform']
            for k, v in self.app.config['DEPOSIT_RECORDS_UI_ENDPOINTS'].items()
            if 'schemaform' in v
        }
        return defaultdict(
            lambda: self.app.config['DEPOSIT_DEFAULT_SCHEMAFORM'], _schemaforms
        )

def schemaforms ( self ) : _schemaforms = { k : v [ 'schemaform' ] for k , v in self . app . config [ 'DEPOSIT_RECORDS_UI_ENDPOINTS' ] . items ( ) if 'schemaform' in v } return defaultdict ( lambda : self . app . config [ 'DEPOSIT_DEFAULT_SCHEMAFORM' ] , _schemaforms )


def deposit_links_factory(pid):
    """Factory for record links generation.

    The dictionary is formed as:

    .. code-block:: python

        {
            'files': '/url/to/files',
            'publish': '/url/to/publish',
            'edit': '/url/to/edit',
            'discard': '/url/to/discard',
            ...
        }

    :param pid: The record PID object.
    :returns: A dictionary that contains all the links.
    """
    links = default_links_factory(pid)

    def _url(name, **kwargs):
        """URL builder."""
        endpoint = '.{0}_{1}'.format(
            current_records_rest.default_endpoint_prefixes[pid.pid_type],
            name,
        )
        return url_for(endpoint, pid_value=pid.pid_value, _external=True,
                       **kwargs)

    links['files'] = _url('files')

    ui_endpoint = current_app.config.get('DEPOSIT_UI_ENDPOINT')
    if ui_endpoint is not None:
        links['html'] = ui_endpoint.format(
            host=request.host,
            scheme=request.scheme,
            pid_value=pid.pid_value,
        )

    deposit_cls = Deposit
    if 'pid_value' in request.view_args:
        deposit_cls = request.view_args['pid_value'].data[1].__class__

    for action in extract_actions_from_class(deposit_cls):
        links[action] = _url('actions', action=action)
    return links

def
deposit_links_factory
(
pid
)
:
links
=
default_links_factory
(
pid
)
def
_url
(
name
,
*
*
kwargs
)
:
"""URL builder."""
endpoint
=
'.{0}_{1}'
.
format
(
current_records_rest
.
default_endpoint_prefixes
[
pid
.
pid_type
]
,
name
,
)
return
url_for
(
endpoint
,
pid_value
=
pid
.
pid_value
,
_external
=
True
,
*
*
kwargs
)
links
[
'files'
]
=
_url
(
'files'
)
ui_endpoint
=
current_app
.
config
.
get
(
'DEPOSIT_UI_ENDPOINT'
)
if
ui_endpoint
is
not
:
links
[
'html'
]
=
ui_endpoint
.
format
(
host
=
request
.
host
,
scheme
=
request
.
scheme
,
pid_value
=
pid
.
pid_value
,
)
deposit_cls
=
Deposit
if
'pid_value'
in
request
.
view_args
:
deposit_cls
=
request
.
view_args
[
'pid_value'
]
.
data
[
1
]
.
__class__
for
action
in
extract_actions_from_class
(
deposit_cls
)
:
links
[
action
]
=
_url
(
'actions'
,
action
=
action
)
return
links


def process_minter(value):
    """Load minter from PIDStore registry based on given value.

    :param value: Name of the minter.
    :returns: The minter.
    """
    try:
        return current_pidstore.minters[value]
    except KeyError:
        raise click.BadParameter(
            'Unknown minter {0}. Please use one of {1}.'.format(
                value, ', '.join(current_pidstore.minters.keys())
            )
        )

Load minter from PIDStore registry based on given value .


def process_schema(value):
    """Load schema from JSONSchema registry based on given value.

    :param value: Schema path, relative to the directory when it was
        registered.
    :returns: The schema absolute path.
    """
    schemas = current_app.extensions['invenio-jsonschemas'].schemas
    try:
        return schemas[value]
    except KeyError:
        raise click.BadParameter(
            'Unknown schema {0}. Please use one of:\n {1}'.format(
                value, '\n'.join(schemas.keys())
            )
        )

Load schema from JSONSchema registry based on given value .


def json_serializer(pid, data, *args):
    """Build a JSON Flask response using the given data.

    :param pid: The `invenio_pidstore.models.PersistentIdentifier` of the
        record.
    :param data: The record metadata.
    :returns: A Flask response with JSON data.
    :rtype: :py:class:`flask.Response`.
    """
    if data is not None:
        response = Response(
            json.dumps(data.dumps()),
            mimetype='application/json'
        )
    else:
        response = Response(mimetype='application/json')
    return response

def json_serializer ( pid , data , * args ) : if data is not None : response = Response ( json . dumps ( data . dumps ( ) ) , mimetype = 'application/json' ) else : response = Response ( mimetype = 'application/json' ) return response

Build a JSON Flask response using the given data .


def file_serializer(obj):
    """Serialize a object.

    :param obj: A :class:`invenio_files_rest.models.ObjectVersion` instance.
    :returns: A dictionary with the fields to serialize.
    """
    return {
        "id": str(obj.file_id),
        "filename": obj.key,
        "filesize": obj.file.size,
        "checksum": obj.file.checksum,
    }

def file_serializer ( obj ) : return { "id" : str ( obj . file_id ) , "filename" : obj . key , "filesize" : obj . file . size , "checksum" : obj . file . checksum , }


def json_files_serializer(objs, status=None):
    """JSON Files Serializer.

    :parma objs: A list of:class:`invenio_files_rest.models.ObjectVersion`
        instances.
    :param status: A HTTP Status. (Default: ``None``)
    :returns: A Flask response with JSON data.
    :rtype: :py:class:`flask.Response`.
    """
    files = [file_serializer(obj) for obj in objs]
    return make_response(json.dumps(files), status)

def json_files_serializer ( objs , status = None ) : files = [ file_serializer ( obj ) for obj in objs ] return make_response ( json . dumps ( files ) , status )


def index_deposit_after_publish(sender, action=None, pid=None, deposit=None):
    """Index the record after publishing.

    .. note:: if the record is not published, it doesn't index.

    :param sender: Who send the signal.
    :param action: Action executed by the sender. (Default: ``None``)
    :param pid: PID object. (Default: ``None``)
    :param deposit: Deposit object. (Default: ``None``)
    """
    if action == 'publish':
        _, record = deposit.fetch_published()
        index_record.delay(str(record.id))

def index_deposit_after_publish ( sender , action = None , pid = None , deposit = None ) : if action == 'publish' : _ , record = deposit . fetch_published ( ) index_record . delay ( str ( record . id ) )


def index(method=None, delete=False):
    """Decorator to update index.

    :param method: Function wrapped. (Default: ``None``)
    :param delete: If `True` delete the indexed record. (Default: ``None``)
    """
    if method is None:
        return partial(index, delete=delete)

    @wraps(method)
    def wrapper(self_or_cls, *args, **kwargs):
        """Send record for indexing."""
        result = method(self_or_cls, *args, **kwargs)
        try:
            if delete:
                self_or_cls.indexer.delete(result)
            else:
                self_or_cls.indexer.index(result)
        except RequestError:
            current_app.logger.exception('Could not index {0}.'.format(result))
        return result
    return wrapper

def
index
(
method
=
,
delete
=
False
)
:
if
method
is
:
return
partial
(
index
,
delete
=
delete
)
@
wraps
(
method
)
def
wrapper
(
self_or_cls
,
*
args
,
*
*
kwargs
)
:
"""Send record for indexing."""
result
=
method
(
self_or_cls
,
*
args
,
*
*
kwargs
)
try
:
if
delete
:
self_or_cls
.
indexer
.
delete
(
result
)
else
:
self_or_cls
.
indexer
.
index
(
result
)
except
RequestError
:
current_app
.
logger
.
exception
(
'Could not index {0}.'
.
format
(
result
)
)
return
result
return
wrapper


def preserve(method=None, result=True, fields=None):
    """Preserve fields in deposit.

    :param method: Function to execute. (Default: ``None``)
    :param result: If `True` returns the result of method execution,
        otherwise `self`. (Default: ``True``)
    :param fields: List of fields to preserve (default: ``('_deposit',)``).
    """
    if method is None:
        return partial(preserve, result=result, fields=fields)

    fields = fields or ('_deposit', )

    @wraps(method)
    def wrapper(self, *args, **kwargs):
        """Check current deposit status."""
        data = {field: self[field] for field in fields if field in self}
        result_ = method(self, *args, **kwargs)
        replace = result_ if result else self
        for field in data:
            replace[field] = data[field]
        return result_
    return wrapper

def
preserve
(
method
=
,
result
=
True
,
fields
=
)
:
if
method
is
:
return
partial
(
preserve
,
result
=
result
,
fields
=
fields
)
fields
=
fields
or
(
'_deposit'
,
)
@
wraps
(
method
)
def
wrapper
(
self
,
*
args
,
*
*
kwargs
)
:
"""Check current deposit status."""
data
=
{
field
:
self
[
field
]
for
field
in
fields
if
field
in
self
}
result_
=
method
(
self
,
*
args
,
*
*
kwargs
)
replace
=
result_
if
result
else
self
for
field
in
data
:
replace
[
field
]
=
data
[
field
]
return
result_
return
wrapper


def pid(self):
        """Return an instance of deposit PID."""
        pid = self.deposit_fetcher(self.id, self)
        return PersistentIdentifier.get(pid.pid_type,
                                        pid.pid_value)

def pid ( self ) : pid = self . deposit_fetcher ( self . id , self ) return PersistentIdentifier . get ( pid . pid_type , pid . pid_value )


def record_schema(self):
        """Convert deposit schema to a valid record schema."""
        schema_path = current_jsonschemas.url_to_path(self['$schema'])
        schema_prefix = current_app.config['DEPOSIT_JSONSCHEMAS_PREFIX']
        if schema_path and schema_path.startswith(schema_prefix):
            return current_jsonschemas.path_to_url(
                schema_path[len(schema_prefix):]
            )

def record_schema ( self ) : schema_path = current_jsonschemas . url_to_path ( self [ '$schema' ] ) schema_prefix = current_app . config [ 'DEPOSIT_JSONSCHEMAS_PREFIX' ] if schema_path and schema_path . startswith ( schema_prefix ) : return current_jsonschemas . path_to_url ( schema_path [ len ( schema_prefix ) : ] )

Convert deposit schema to a valid record schema .


def build_deposit_schema(self, record):
        """Convert record schema to a valid deposit schema.

        :param record: The record used to build deposit schema.
        :returns: The absolute URL to the schema or `None`.
        """
        schema_path = current_jsonschemas.url_to_path(record['$schema'])
        schema_prefix = current_app.config['DEPOSIT_JSONSCHEMAS_PREFIX']
        if schema_path:
            return current_jsonschemas.path_to_url(
                schema_prefix + schema_path
            )

def build_deposit_schema ( self , record ) : schema_path = current_jsonschemas . url_to_path ( record [ '$schema' ] ) schema_prefix = current_app . config [ 'DEPOSIT_JSONSCHEMAS_PREFIX' ] if schema_path : return current_jsonschemas . path_to_url ( schema_prefix + schema_path )

Convert record schema to a valid deposit schema .


def fetch_published(self):
        """Return a tuple with PID and published record."""
        pid_type = self['_deposit']['pid']['type']
        pid_value = self['_deposit']['pid']['value']

        resolver = Resolver(
            pid_type=pid_type, object_type='rec',
            getter=partial(self.published_record_class.get_record,
                           with_deleted=True)
        )
        return resolver.resolve(pid_value)

def fetch_published ( self ) : pid_type = self [ '_deposit' ] [ 'pid' ] [ 'type' ] pid_value = self [ '_deposit' ] [ 'pid' ] [ 'value' ] resolver = Resolver ( pid_type = pid_type , object_type = 'rec' , getter = partial ( self . published_record_class . get_record , with_deleted = True ) ) return resolver . resolve ( pid_value )

Return a tuple with PID and published record .


def merge_with_published(self):
        """Merge changes with latest published version."""
        pid, first = self.fetch_published()
        lca = first.revisions[self['_deposit']['pid']['revision_id']]
        # ignore _deposit and $schema field
        args = [lca.dumps(), first.dumps(), self.dumps()]
        for arg in args:
            del arg['$schema'], arg['_deposit']
        args.append({})
        m = Merger(*args)
        try:
            m.run()
        except UnresolvedConflictsException:
            raise MergeConflict()
        return patch(m.unified_patches, lca)

def
merge_with_published
(
self
)
:
pid
,
first
=
self
.
fetch_published
(
)
lca
=
first
.
revisions
[
self
[
'_deposit'
]
[
'pid'
]
[
'revision_id'
]
]
# ignore _deposit and $schema field
args
=
[
lca
.
dumps
(
)
,
first
.
dumps
(
)
,
self
.
dumps
(
)
]
for
arg
in
args
:
del
arg
[
'$schema'
]
,
arg
[
'_deposit'
]
args
.
append
(
{
}
)
m
=
Merger
(
*
args
)
try
:
m
.
run
(
)
except
UnresolvedConflictsException
:
raise
MergeConflict
(
)
return
patch
(
m
.
unified_patches
,
lca
)

Merge changes with latest published version .


def commit(self, *args, **kwargs):
        """Store changes on current instance in database and index it."""
        return super(Deposit, self).commit(*args, **kwargs)

def commit ( self , * args , * * kwargs ) : return super ( Deposit , self ) . commit ( * args , * * kwargs )

Store changes on current instance in database and index it .


def create(cls, data, id_=None):
        """Create a deposit.

        Initialize the follow information inside the deposit:

        .. code-block:: python

            deposit['_deposit'] = {
                'id': pid_value,
                'status': 'draft',
                'owners': [user_id],
                'created_by': user_id,
            }

        The deposit index is updated.

        :param data: Input dictionary to fill the deposit.
        :param id_: Default uuid for the deposit.
        :returns: The new created deposit.
        """
        data.setdefault('$schema', current_jsonschemas.path_to_url(
            current_app.config['DEPOSIT_DEFAULT_JSONSCHEMA']
        ))
        if '_deposit' not in data:
            id_ = id_ or uuid.uuid4()
            cls.deposit_minter(id_, data)

        data['_deposit'].setdefault('owners', list())
        if current_user and current_user.is_authenticated:
            creator_id = int(current_user.get_id())

            if creator_id not in data['_deposit']['owners']:
                data['_deposit']['owners'].append(creator_id)

            data['_deposit']['created_by'] = creator_id

        return super(Deposit, cls).create(data, id_=id_)

def create ( cls , data , id_ = None ) : data . setdefault ( '$schema' , current_jsonschemas . path_to_url ( current_app . config [ 'DEPOSIT_DEFAULT_JSONSCHEMA' ] ) ) if '_deposit' not in data : id_ = id_ or uuid . uuid4 ( ) cls . deposit_minter ( id_ , data ) data [ '_deposit' ] . setdefault ( 'owners' , list ( ) ) if current_user and current_user . is_authenticated : creator_id = int ( current_user . get_id ( ) ) if creator_id not in data [ '_deposit' ] [ 'owners' ] : data [ '_deposit' ] [ 'owners' ] . append ( creator_id ) data [ '_deposit' ] [ 'created_by' ] = creator_id return super ( Deposit , cls ) . create ( data , id_ = id_ )


def _process_files(self, record_id, data):
        """Snapshot bucket and add files in record during first publishing."""
        if self.files:
            assert not self.files.bucket.locked
            self.files.bucket.locked = True
            snapshot = self.files.bucket.snapshot(lock=True)
            data['_files'] = self.files.dumps(bucket=snapshot.id)
            yield data
            db.session.add(RecordsBuckets(
                record_id=record_id, bucket_id=snapshot.id
            ))
        else:
            yield data

def _process_files ( self , record_id , data ) : if self . files : assert not self . files . bucket . locked self . files . bucket . locked = True snapshot = self . files . bucket . snapshot ( lock = True ) data [ '_files' ] = self . files . dumps ( bucket = snapshot . id ) yield data db . session . add ( RecordsBuckets ( record_id = record_id , bucket_id = snapshot . id ) ) else : yield data

Snapshot bucket and add files in record during first publishing .


def _publish_new(self, id_=None):
        """Publish new deposit.

        :param id_: The forced record UUID.
        """
        minter = current_pidstore.minters[
            current_app.config['DEPOSIT_PID_MINTER']
        ]
        id_ = id_ or uuid.uuid4()
        record_pid = minter(id_, self)

        self['_deposit']['pid'] = {
            'type': record_pid.pid_type,
            'value': record_pid.pid_value,
            'revision_id': 0,
        }

        data = dict(self.dumps())
        data['$schema'] = self.record_schema

        with self._process_files(id_, data):
            record = self.published_record_class.create(data, id_=id_)

        return record

def _publish_new ( self , id_ = None ) : minter = current_pidstore . minters [ current_app . config [ 'DEPOSIT_PID_MINTER' ] ] id_ = id_ or uuid . uuid4 ( ) record_pid = minter ( id_ , self ) self [ '_deposit' ] [ 'pid' ] = { 'type' : record_pid . pid_type , 'value' : record_pid . pid_value , 'revision_id' : 0 , } data = dict ( self . dumps ( ) ) data [ '$schema' ] = self . record_schema with self . _process_files ( id_ , data ) : record = self . published_record_class . create ( data , id_ = id_ ) return record


def _publish_edited(self):
        """Publish the deposit after for editing."""
        record_pid, record = self.fetch_published()
        if record.revision_id == self['_deposit']['pid']['revision_id']:
            data = dict(self.dumps())
        else:
            data = self.merge_with_published()

        data['$schema'] = self.record_schema
        data['_deposit'] = self['_deposit']
        record = record.__class__(data, model=record.model)
        return record

def _publish_edited ( self ) : record_pid , record = self . fetch_published ( ) if record . revision_id == self [ '_deposit' ] [ 'pid' ] [ 'revision_id' ] : data = dict ( self . dumps ( ) ) else : data = self . merge_with_published ( ) data [ '$schema' ] = self . record_schema data [ '_deposit' ] = self [ '_deposit' ] record = record . __class__ ( data , model = record . model ) return record


def publish(self, pid=None, id_=None):
        """Publish a deposit.

        If it's the first time:

        * it calls the minter and set the following meta information inside
            the deposit:

        .. code-block:: python

            deposit['_deposit'] = {
                'type': pid_type,
                'value': pid_value,
                'revision_id': 0,
            }

        * A dump of all information inside the deposit is done.

        * A snapshot of the files is done.

        Otherwise, published the new edited version.
        In this case, if in the mainwhile someone already published a new
        version, it'll try to merge the changes with the latest version.

        .. note:: no need for indexing as it calls `self.commit()`.

        Status required: ``'draft'``.

        :param pid: Force the new pid value. (Default: ``None``)
        :param id_: Force the new uuid value as deposit id. (Default: ``None``)
        :returns: Returns itself.
        """
        pid = pid or self.pid

        if not pid.is_registered():
            raise PIDInvalidAction()

        self['_deposit']['status'] = 'published'

        if self['_deposit'].get('pid') is None:  # First publishing
            self._publish_new(id_=id_)
        else:  # Update after edit
            record = self._publish_edited()
            record.commit()
        self.commit()
        return self

def
publish
(
self
,
pid
=
,
id_
=
)
:
pid
=
pid
or
self
.
pid
if
not
pid
.
is_registered
(
)
:
raise
PIDInvalidAction
(
)
self
[
'_deposit'
]
[
'status'
]
=
'published'
if
self
[
'_deposit'
]
.
get
(
'pid'
)
is
:
# First publishing
self
.
_publish_new
(
id_
=
id_
)
else
:
# Update after edit
record
=
self
.
_publish_edited
(
)
record
.
commit
(
)
self
.
commit
(
)
return
self


def _prepare_edit(self, record):
        """Update selected keys.

        :param record: The record to prepare.
        """
        data = record.dumps()
        # Keep current record revision for merging.
        data['_deposit']['pid']['revision_id'] = record.revision_id
        data['_deposit']['status'] = 'draft'
        data['$schema'] = self.build_deposit_schema(record)
        return data


def edit(self, pid=None):
        """Edit deposit.

        #. The signal :data:`invenio_records.signals.before_record_update`
           is sent before the edit execution.

        #. The following meta information are saved inside the deposit:

        .. code-block:: python

            deposit['_deposit']['pid'] = record.revision_id
            deposit['_deposit']['status'] = 'draft'
            deposit['$schema'] = deposit_schema_from_record_schema

        #. The signal :data:`invenio_records.signals.after_record_update` is
            sent after the edit execution.

        #. The deposit index is updated.

        Status required: `published`.

        .. note:: the process fails if the pid has status
            :attr:`invenio_pidstore.models.PIDStatus.REGISTERED`.

        :param pid: Force a pid object. (Default: ``None``)
        :returns: A new Deposit object.
        """
        pid = pid or self.pid

        with db.session.begin_nested():
            before_record_update.send(
                current_app._get_current_object(), record=self)

            record_pid, record = self.fetch_published()
            assert PIDStatus.REGISTERED == record_pid.status
            assert record['_deposit'] == self['_deposit']

            self.model.json = self._prepare_edit(record)

            flag_modified(self.model, 'json')
            db.session.merge(self.model)

        after_record_update.send(
            current_app._get_current_object(), record=self)
        return self.__class__(self.model.json, model=self.model)

def edit ( self , pid = None ) : pid = pid or self . pid with db . session . begin_nested ( ) : before_record_update . send ( current_app . _get_current_object ( ) , record = self ) record_pid , record = self . fetch_published ( ) assert PIDStatus . REGISTERED == record_pid . status assert record [ '_deposit' ] == self [ '_deposit' ] self . model . json = self . _prepare_edit ( record ) flag_modified ( self . model , 'json' ) db . session . merge ( self . model ) after_record_update . send ( current_app . _get_current_object ( ) , record = self ) return self . __class__ ( self . model . json , model = self . model )


def discard(self, pid=None):
        """Discard deposit changes.

        #. The signal :data:`invenio_records.signals.before_record_update` is
            sent before the edit execution.

        #. It restores the last published version.

        #. The following meta information are saved inside the deposit:

        .. code-block:: python

            deposit['$schema'] = deposit_schema_from_record_schema

        #. The signal :data:`invenio_records.signals.after_record_update` is
            sent after the edit execution.

        #. The deposit index is updated.

        Status required: ``'draft'``.

        :param pid: Force a pid object. (Default: ``None``)
        :returns: A new Deposit object.
        """
        pid = pid or self.pid

        with db.session.begin_nested():
            before_record_update.send(
                current_app._get_current_object(), record=self)

            _, record = self.fetch_published()
            self.model.json = deepcopy(record.model.json)
            self.model.json['$schema'] = self.build_deposit_schema(record)

            flag_modified(self.model, 'json')
            db.session.merge(self.model)

        after_record_update.send(
            current_app._get_current_object(), record=self)
        return self.__class__(self.model.json, model=self.model)

def discard ( self , pid = None ) : pid = pid or self . pid with db . session . begin_nested ( ) : before_record_update . send ( current_app . _get_current_object ( ) , record = self ) _ , record = self . fetch_published ( ) self . model . json = deepcopy ( record . model . json ) self . model . json [ '$schema' ] = self . build_deposit_schema ( record ) flag_modified ( self . model , 'json' ) db . session . merge ( self . model ) after_record_update . send ( current_app . _get_current_object ( ) , record = self ) return self . __class__ ( self . model . json , model = self . model )


def delete(self, force=True, pid=None):
        """Delete deposit.

        Status required: ``'draft'``.

        :param force: Force deposit delete.  (Default: ``True``)
        :param pid: Force pid object.  (Default: ``None``)
        :returns: A new Deposit object.
        """
        pid = pid or self.pid

        if self['_deposit'].get('pid'):
            raise PIDInvalidAction()
        if pid:
            pid.delete()
        return super(Deposit, self).delete(force=force)

def delete ( self , force = True , pid = None ) : pid = pid or self . pid if self [ '_deposit' ] . get ( 'pid' ) : raise PIDInvalidAction ( ) if pid : pid . delete ( ) return super ( Deposit , self ) . delete ( force = force )


def clear(self, *args, **kwargs):
        """Clear only drafts.

        Status required: ``'draft'``.

        Meta information inside `_deposit` are preserved.
        """
        super(Deposit, self).clear(*args, **kwargs)

def clear ( self , * args , * * kwargs ) : super ( Deposit , self ) . clear ( * args , * * kwargs )


def update(self, *args, **kwargs):
        """Update only drafts.

        Status required: ``'draft'``.

        Meta information inside `_deposit` are preserved.
        """
        super(Deposit, self).update(*args, **kwargs)

def update ( self , * args , * * kwargs ) : super ( Deposit , self ) . update ( * args , * * kwargs )


def patch(self, *args, **kwargs):
        """Patch only drafts.

        Status required: ``'draft'``.

        Meta information inside `_deposit` are preserved.
        """
        return super(Deposit, self).patch(*args, **kwargs)

def patch ( self , * args , * * kwargs ) : return super ( Deposit , self ) . patch ( * args , * * kwargs )


def files(self):
        """List of Files inside the deposit.

        Add validation on ``sort_by`` method: if, at the time of files access,
        the record is not a ``'draft'`` then a
        :exc:`invenio_pidstore.errors.PIDInvalidAction` is rised.
        """
        files_ = super(Deposit, self).files

        if files_:
            sort_by_ = files_.sort_by

            def sort_by(*args, **kwargs):
                """Only in draft state."""
                if 'draft' != self.status:
                    raise PIDInvalidAction()
                return sort_by_(*args, **kwargs)

            files_.sort_by = sort_by

        return files_

def
files
(
self
)
:
files_
=
super
(
Deposit
,
self
)
.
files
if
files_
:
sort_by_
=
files_
.
sort_by
def
sort_by
(
*
args
,
*
*
kwargs
)
:
"""Only in draft state."""
if
'draft'
!=
self
.
status
:
raise
PIDInvalidAction
(
)
return
sort_by_
(
*
args
,
*
*
kwargs
)
files_
.
sort_by
=
sort_by
return
files_


def rst2node(doc_name, data):
    """Converts a reStructuredText into its node
    """
    if not data:
        return
    parser = docutils.parsers.rst.Parser()
    document = docutils.utils.new_document('<%s>' % doc_name)
    document.settings = docutils.frontend.OptionParser().get_default_values()
    document.settings.tab_width = 4
    document.settings.pep_references = False
    document.settings.rfc_references = False
    document.settings.env = Env()
    parser.parse(data, document)
    if len(document.children) == 1:
        return document.children[0]
    else:
        par = docutils.nodes.paragraph()
        for child in document.children:
            par += child
        return par

def rst2node ( doc_name , data ) : if not data : return parser = docutils . parsers . rst . Parser ( ) document = docutils . utils . new_document ( '<%s>' % doc_name ) document . settings = docutils . frontend . OptionParser ( ) . get_default_values ( ) document . settings . tab_width = 4 document . settings . pep_references = False document . settings . rfc_references = False document . settings . env = Env ( ) parser . parse ( data , document ) if len ( document . children ) == 1 : return document . children [ 0 ] else : par = docutils . nodes . paragraph ( ) for child in document . children : par += child return par


def setup(app):
    """Hook the directives when Sphinx ask for it."""
    if 'http' not in app.domains:
        httpdomain.setup(app)

    app.add_directive('autopyramid', RouteDirective)

def setup ( app ) : if 'http' not in app . domains : httpdomain . setup ( app ) app . add_directive ( 'autopyramid' , RouteDirective )

Hook the directives when Sphinx ask for it .


def _parse_response(self, response):
        """Parses the API response and raises appropriate errors if
        raise_errors was set to True
        """
        if not self._raise_errors:
            return response

        is_4xx_error = str(response.status_code)[0] == '4'
        is_5xx_error = str(response.status_code)[0] == '5'
        content = response.content

        if response.status_code == 403:
            raise AuthenticationError(content)
        elif is_4xx_error:
            raise APIError(content)
        elif is_5xx_error:
            raise ServerError(content)

        return response

def _parse_response ( self , response ) : if not self . _raise_errors : return response is_4xx_error = str ( response . status_code ) [ 0 ] == '4' is_5xx_error = str ( response . status_code ) [ 0 ] == '5' content = response . content if response . status_code == 403 : raise AuthenticationError ( content ) elif is_4xx_error : raise APIError ( content ) elif is_5xx_error : raise ServerError ( content ) return response


def templates(self, timeout=None):
        """ API call to get a list of templates """
        return self._api_request(
            self.TEMPLATES_ENDPOINT,
            self.HTTP_GET,
            timeout=timeout
        )

def templates ( self , timeout = None ) : return self . _api_request ( self . TEMPLATES_ENDPOINT , self . HTTP_GET , timeout = timeout )


def get_template(self, template_id, version=None, timeout=None):
        """ API call to get a specific template """
        if (version):
            return self._api_request(
                self.TEMPLATES_VERSION_ENDPOINT % (template_id, version),
                self.HTTP_GET,
                timeout=timeout
            )
        else:
            return self._api_request(
                self.TEMPLATES_SPECIFIC_ENDPOINT % template_id,
                self.HTTP_GET,
                timeout=timeout
            )

def get_template ( self , template_id , version = None , timeout = None ) : if ( version ) : return self . _api_request ( self . TEMPLATES_VERSION_ENDPOINT % ( template_id , version ) , self . HTTP_GET , timeout = timeout ) else : return self . _api_request ( self . TEMPLATES_SPECIFIC_ENDPOINT % template_id , self . HTTP_GET , timeout = timeout )


def create_template(
        self,
        name,
        subject,
        html,
        text='',
        timeout=None
    ):
        """ API call to create a template """
        payload = {
            'name': name,
            'subject': subject,
            'html': html,
            'text': text
        }

        return self._api_request(
            self.TEMPLATES_ENDPOINT,
            self.HTTP_POST,
            payload=payload,
            timeout=timeout
        )

def create_template ( self , name , subject , html , text = '' , timeout = None ) : payload = { 'name' : name , 'subject' : subject , 'html' : html , 'text' : text } return self . _api_request ( self . TEMPLATES_ENDPOINT , self . HTTP_POST , payload = payload , timeout = timeout )


def create_new_locale(
        self,
        template_id,
        locale,
        version_name,
        subject,
        text='',
        html='',
        timeout=None
    ):
        """ API call to create a new locale and version of a template """
        payload = {
            'locale': locale,
            'name': version_name,
            'subject': subject
        }

        if html:
            payload['html'] = html
        if text:
            payload['text'] = text

        return self._api_request(
            self.TEMPLATES_LOCALES_ENDPOINT % template_id,
            self.HTTP_POST,
            payload=payload,
            timeout=timeout
        )

def create_new_locale ( self , template_id , locale , version_name , subject , text = '' , html = '' , timeout = None ) : payload = { 'locale' : locale , 'name' : version_name , 'subject' : subject } if html : payload [ 'html' ] = html if text : payload [ 'text' ] = text return self . _api_request ( self . TEMPLATES_LOCALES_ENDPOINT % template_id , self . HTTP_POST , payload = payload , timeout = timeout )


def create_new_version(
        self,
        name,
        subject,
        text='',
        template_id=None,
        html=None,
        locale=None,
        timeout=None
    ):
        """ API call to create a new version of a template """
        if(html):
            payload = {
                'name': name,
                'subject': subject,
                'html': html,
                'text': text
            }
        else:
            payload = {
                'name': name,
                'subject': subject,
                'text': text
            }

        if locale:
            url = self.TEMPLATES_SPECIFIC_LOCALE_VERSIONS_ENDPOINT % (
                template_id,
                locale
            )
        else:
            url = self.TEMPLATES_NEW_VERSION_ENDPOINT % template_id

        return self._api_request(
            url,
            self.HTTP_POST,
            payload=payload,
            timeout=timeout
        )


def update_template_version(
        self,
        name,
        subject,
        template_id,
        version_id,
        text='',
        html=None,
        timeout=None
    ):
        """ API call to update a template version """
        if(html):
            payload = {
                'name': name,
                'subject': subject,
                'html': html,
                'text': text
            }
        else:
            payload = {
                'name': name,
                'subject': subject,
                'text': text
            }

        return self._api_request(
            self.TEMPLATES_VERSION_ENDPOINT % (template_id, version_id),
            self.HTTP_PUT,
            payload=payload,
            timeout=timeout
        )

def update_template_version ( self , name , subject , template_id , version_id , text = '' , html = None , timeout = None ) : if ( html ) : payload = { 'name' : name , 'subject' : subject , 'html' : html , 'text' : text } else : payload = { 'name' : name , 'subject' : subject , 'text' : text } return self . _api_request ( self . TEMPLATES_VERSION_ENDPOINT % ( template_id , version_id ) , self . HTTP_PUT , payload = payload , timeout = timeout )


def snippets(self, timeout=None):
        """ API call to get list of snippets """
        return self._api_request(
            self.SNIPPETS_ENDPOINT,
            self.HTTP_GET,
            timeout=timeout
        )

def snippets ( self , timeout = None ) : return self . _api_request ( self . SNIPPETS_ENDPOINT , self . HTTP_GET , timeout = timeout )


def get_snippet(self, snippet_id, timeout=None):
        """ API call to get a specific Snippet """
        return self._api_request(
            self.SNIPPET_ENDPOINT % (snippet_id),
            self.HTTP_GET,
            timeout=timeout
        )

def get_snippet ( self , snippet_id , timeout = None ) : return self . _api_request ( self . SNIPPET_ENDPOINT % ( snippet_id ) , self . HTTP_GET , timeout = timeout )


def create_snippet(self, name, body, timeout=None):
        """ API call to create a Snippet """
        payload = {
            'name': name,
            'body': body
        }
        return self._api_request(
            self.SNIPPETS_ENDPOINT,
            self.HTTP_POST,
            payload=payload,
            timeout=timeout
        )

def create_snippet ( self , name , body , timeout = None ) : payload = { 'name' : name , 'body' : body } return self . _api_request ( self . SNIPPETS_ENDPOINT , self . HTTP_POST , payload = payload , timeout = timeout )