materials-commons-cli 2.3.0b3__tar.gz → 2.3.0b4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/PKG-INFO +1 -1
- materials_commons_cli-2.3.0b4/materials_commons/cli/__init__.py +1 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/old/cloned_project.py +223 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/old/exceptions.py +12 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/old/file_functions.py +137 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/old/functions.py +775 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/old/globus.py +418 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/old/list_objects.py +404 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/old/print_formatter.py +105 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/old/sqltable.py +213 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/old/tmp_functions.py +39 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/old/tree_functions.py +1736 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/old/treedb.py +644 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/old/user_config.py +216 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/server/command_handlers/admin_handler_lookup.py +26 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/server/command_handlers/download_handler_lookup.py +124 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/server/command_handlers/list_handler_lookup.py +158 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/server/command_handlers/multi_handler_lookup.py +16 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/server/command_handlers/protocol.py +7 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/server/command_handlers/search_find_handler_lookup.py +77 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/server/command_handlers/upload_handler_lookup.py +221 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/server/db/db_manager.py +54 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/server/indexer/__init__.py +0 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/server/uploader/__init__.py +0 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/subcommands/__init__.py +0 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/subcommands/runners/__init__.py +0 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/subcommands/runners/download_globus_runner.py +86 -0
- materials_commons_cli-2.3.0b4/materials_commons/cli/subcommands/runners/download_v1_runner.py +176 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons_cli.egg-info/PKG-INFO +1 -1
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons_cli.egg-info/SOURCES.txt +26 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/setup.py +11 -1
- materials_commons_cli-2.3.0b3/materials_commons/cli/__init__.py +0 -1
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/LICENSE +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/README.md +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/LICENSE.txt +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/async_reconciler.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/config.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/downloader.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/filedb.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/local_project.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/models.py +0 -0
- {materials_commons_cli-2.3.0b3/materials_commons/cli/server/downloader → materials_commons_cli-2.3.0b4/materials_commons/cli/old}/__init__.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/parser.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/reconcile2.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/reconcile3.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/requests.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/run.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/__init__.py +0 -0
- {materials_commons_cli-2.3.0b3/materials_commons/cli/server/indexer → materials_commons_cli-2.3.0b4/materials_commons/cli/server/command_handlers}/__init__.py +0 -0
- {materials_commons_cli-2.3.0b3/materials_commons/cli/server/uploader → materials_commons_cli-2.3.0b4/materials_commons/cli/server/db}/__init__.py +0 -0
- {materials_commons_cli-2.3.0b3/materials_commons/cli/subcommands → materials_commons_cli-2.3.0b4/materials_commons/cli/server/downloader}/__init__.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/downloader/file_download_manager.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/downloader/file_downloader.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/indexer/file_index_manager.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/local_rest_server.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/ocommand_handlers.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/project_filedbs.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/projects.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/service_container.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/service_runtime.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/uploader/client_api.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/uploader/file_upload_manager.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/uploader/file_uploader.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/websocket_server.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/clone.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/config.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/dataset.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/down.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/down2.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/expt.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/fetch.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/globus.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/init.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/ls.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/ls2.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/mkdir.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/mv.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/proj.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/remote.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/rm.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/scan.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/server.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/up.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/versions.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/walk.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons_cli.egg-info/dependency_links.txt +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons_cli.egg-info/entry_points.txt +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons_cli.egg-info/not-zip-safe +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons_cli.egg-info/requires.txt +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons_cli.egg-info/top_level.txt +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/setup.cfg +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_api.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_functions.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_mc_dataset.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_mc_down.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_mc_mkdir.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_mc_mv.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_mc_proj.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_mc_rm.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_mc_up.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_treecompare_no_cache.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_treecompare_with_cache.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_treedb.py +0 -0
- {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_user_config.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '2.3.0b4'
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pathlib
|
|
3
|
+
import tempfile
|
|
4
|
+
|
|
5
|
+
import materials_commons.cli.old.exceptions as cliexcept
|
|
6
|
+
import materials_commons.cli.old.functions as clifuncs
|
|
7
|
+
from materials_commons.cli.old.user_config import Config, \
|
|
8
|
+
get_remote_config_and_login_if_necessary
|
|
9
|
+
from materials_commons.cli.subcommands.down import down_subcommand
|
|
10
|
+
from materials_commons.cli.subcommands.up import up_subcommand
|
|
11
|
+
|
|
12
|
+
# TODO: only call os.getcwd() from parser::main
|
|
13
|
+
|
|
14
|
+
class ClonedProject(object):
|
|
15
|
+
"""A cloned Materials Commons project instance
|
|
16
|
+
|
|
17
|
+
Attributes:
|
|
18
|
+
local_path (pathlib.Path): Location of the cloned Materials Commons
|
|
19
|
+
project
|
|
20
|
+
proj (materials_commons.api.models.Project): Materials Commons project
|
|
21
|
+
object
|
|
22
|
+
tmpdir (tempfile.TemporaryDirectory or None): Temporary directory
|
|
23
|
+
instance. If not None, the temporary directory is the parent of the
|
|
24
|
+
cloned Materials Commons project directory.
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, email=None, mcurl=None, proj_id=None, path=None,
|
|
29
|
+
parent_path=None, name=None):
|
|
30
|
+
"""Construct a cloned Materials Commons project instance
|
|
31
|
+
|
|
32
|
+
Examples:
|
|
33
|
+
|
|
34
|
+
Open a project that has already been cloned:
|
|
35
|
+
|
|
36
|
+
.. code-block:: python
|
|
37
|
+
|
|
38
|
+
path = "/path/to/materials_commons_projects/ProjectName"
|
|
39
|
+
mc_proj = ClonedProject(path=path)
|
|
40
|
+
|
|
41
|
+
Clone project to a particular directory or open if already cloned:
|
|
42
|
+
|
|
43
|
+
.. code-block:: python
|
|
44
|
+
|
|
45
|
+
email = "username@domain.com"
|
|
46
|
+
mcurl = "https://materialscommons.org/api"
|
|
47
|
+
proj_id = 25
|
|
48
|
+
parent_path = "/path/to/materials_commons_projects"
|
|
49
|
+
name = None # default uses remote project name
|
|
50
|
+
mc_proj = ClonedProject(email=email,
|
|
51
|
+
mcurl=mcurl,
|
|
52
|
+
proj_id=proj_id,
|
|
53
|
+
parent_path=parent_path,
|
|
54
|
+
name=name)
|
|
55
|
+
|
|
56
|
+
Clone project to a temporary directory:
|
|
57
|
+
|
|
58
|
+
.. code-block:: python
|
|
59
|
+
|
|
60
|
+
email = "username@domain.com"
|
|
61
|
+
mcurl = "https://materialscommons.org/api"
|
|
62
|
+
proj_id = 25
|
|
63
|
+
mc_proj = ClonedProject(email=email, mcurl=mcurl, proj_id=proj_id)
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
email (str): User account email
|
|
67
|
+
mcurl (str): URL for Materials Commons remote instance containing
|
|
68
|
+
the project. Example: "https://materialscommons.org/api".
|
|
69
|
+
proj_id (int): ID of project to clone.
|
|
70
|
+
path (str): Path where the project exists, if already cloned.
|
|
71
|
+
parent_path (str): Path to parent directory where the project should
|
|
72
|
+
be cloned if path is None. If neither path nor parent_path are
|
|
73
|
+
given, uses a tempfile.TemporaryDirectory for parent_path.
|
|
74
|
+
name (str): Name of created project directory. Default is remote
|
|
75
|
+
project name.
|
|
76
|
+
"""
|
|
77
|
+
self.local_path = None
|
|
78
|
+
self.proj = None
|
|
79
|
+
self.tmpdir = None
|
|
80
|
+
|
|
81
|
+
if path is not None:
|
|
82
|
+
if clifuncs.project_exists(path):
|
|
83
|
+
self.proj = clifuncs.make_local_project(path)
|
|
84
|
+
else:
|
|
85
|
+
raise cliexcept.MCCLIException("No project found at " + path)
|
|
86
|
+
else:
|
|
87
|
+
if proj_id is None:
|
|
88
|
+
raise cliexcept.MCCLIException("`proj_id` is required if `path` is not provided")
|
|
89
|
+
|
|
90
|
+
if email is None or mcurl is None:
|
|
91
|
+
config = Config()
|
|
92
|
+
if not config.default_remote.mcurl or not config.default_remote.mcapikey:
|
|
93
|
+
raise cliexcept.NoDefaultRemoteException("Default remote not set")
|
|
94
|
+
remote_config = config.default_remote
|
|
95
|
+
else:
|
|
96
|
+
remote_config = get_remote_config_and_login_if_necessary(
|
|
97
|
+
mcurl=mcurl, email=email)
|
|
98
|
+
|
|
99
|
+
if parent_path is None:
|
|
100
|
+
self.tmpdir = tempfile.TemporaryDirectory()
|
|
101
|
+
self.proj = clifuncs.clone_project(remote_config, proj_id, self.tmpdir.name)
|
|
102
|
+
|
|
103
|
+
else:
|
|
104
|
+
self.tmpdir = None
|
|
105
|
+
parent_path = str(parent_path)
|
|
106
|
+
|
|
107
|
+
# check if project already exists, then construct or clone
|
|
108
|
+
client = remote_config.make_client()
|
|
109
|
+
proj = client.get_project(proj_id)
|
|
110
|
+
path = os.path.join(parent_path, proj.name)
|
|
111
|
+
if clifuncs.project_exists(path):
|
|
112
|
+
self.proj = clifuncs.make_local_project(path, proj._data)
|
|
113
|
+
else:
|
|
114
|
+
self.proj = clifuncs.clone_project(remote_config, proj_id, parent_path)
|
|
115
|
+
|
|
116
|
+
self.local_path = pathlib.Path(self.proj.local_path)
|
|
117
|
+
|
|
118
|
+
def glob(self, pattern):
|
|
119
|
+
"""Helper to construct paths for upload or download
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
pattern (str): Pattern, relative to local project directory root,
|
|
123
|
+
passed as argument to `self.local_path.glob(pattern)`.
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
List of str, File paths found from use of `glob`, made relative to
|
|
127
|
+
self.local_path and converted to str.
|
|
128
|
+
|
|
129
|
+
"""
|
|
130
|
+
return [str(file.relative_to(self.local_path)) for file in self.local_path.glob(pattern)]
|
|
131
|
+
|
|
132
|
+
def download(self, *paths, recursive=False, only_print=False, force=False,
|
|
133
|
+
output=None, globus=False, label=None, no_compare=False):
|
|
134
|
+
"""Download requested files from the Materials Commons project
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
recursive (bool): Download directory contents recursively
|
|
138
|
+
force (bool): Force overwrite of existing files
|
|
139
|
+
only_print (bool): Print file, do not write
|
|
140
|
+
output (str): Download file name. Only allowed if `len(paths) == 1`.
|
|
141
|
+
globus (bool): Use globus to download files
|
|
142
|
+
label (str): Globus transfer label to make finding tasks simpler
|
|
143
|
+
no_compare (bool): Download remote without checking if local is
|
|
144
|
+
equivalent
|
|
145
|
+
*paths (str): Files or directories to download, specified either
|
|
146
|
+
using absolute paths or paths relative to the project root
|
|
147
|
+
directory (`self.local_path`).
|
|
148
|
+
"""
|
|
149
|
+
# TODO: convert to direct function calls rather than arg parsing
|
|
150
|
+
|
|
151
|
+
working_dir = self.local_path
|
|
152
|
+
|
|
153
|
+
argv = []
|
|
154
|
+
if recursive is True:
|
|
155
|
+
argv.append("-r")
|
|
156
|
+
if only_print is True:
|
|
157
|
+
argv.append("-p")
|
|
158
|
+
if force is True:
|
|
159
|
+
argv.append("-f")
|
|
160
|
+
if output is not None:
|
|
161
|
+
argv.append("-o")
|
|
162
|
+
argv.append(str(output))
|
|
163
|
+
if globus is True:
|
|
164
|
+
argv.append("-g")
|
|
165
|
+
if label is not None:
|
|
166
|
+
argv.append("--label")
|
|
167
|
+
argv.append(str(label))
|
|
168
|
+
if no_compare is True:
|
|
169
|
+
argv.append("--no-compare")
|
|
170
|
+
if len(paths):
|
|
171
|
+
# using relpaths is more robust within the working_dir context
|
|
172
|
+
# argv += [str(os.path.relpath(os.path.abspath(path), self.local_path)) for path in paths]
|
|
173
|
+
argv += [os.path.normpath(os.path.join(working_dir, path)) for path in paths]
|
|
174
|
+
try:
|
|
175
|
+
down_subcommand(argv, working_dir)
|
|
176
|
+
except SystemExit as e:
|
|
177
|
+
print("Invalid download request")
|
|
178
|
+
|
|
179
|
+
def upload(self, *paths, recursive=False, limit=None, globus=False,
|
|
180
|
+
label=None, no_compare=False, upload_as=None):
|
|
181
|
+
"""Upload requested files to Materials Commons
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
recursive (bool): Download directory contents recursively
|
|
185
|
+
limit (str): File size upload limit (MB). Default="750" (750MB). Does
|
|
186
|
+
not apply to Globus uploads.
|
|
187
|
+
globus (bool): Use globus to download files
|
|
188
|
+
label (str): Globus transfer label to make finding tasks simpler
|
|
189
|
+
no_compare (bool): Download remote without checking if local is
|
|
190
|
+
equivalent
|
|
191
|
+
upload_as (str): Upload a file or directory to a particular location in the project. Raises if `len(paths) != 1`.
|
|
192
|
+
*paths (str): Files or directories to upload, specified either
|
|
193
|
+
using absolute paths or paths relative to the project root
|
|
194
|
+
directory (`self.local_path`).
|
|
195
|
+
"""
|
|
196
|
+
# TODO: convert to direct function calls rather than arg parsing
|
|
197
|
+
|
|
198
|
+
working_dir = self.local_path
|
|
199
|
+
|
|
200
|
+
argv = []
|
|
201
|
+
if recursive is True:
|
|
202
|
+
argv.append("-r")
|
|
203
|
+
if limit is not None:
|
|
204
|
+
argv.append("--limit")
|
|
205
|
+
argv.append(str(limit))
|
|
206
|
+
if globus is True:
|
|
207
|
+
argv.append("-g")
|
|
208
|
+
if label is not None:
|
|
209
|
+
argv.append("--label")
|
|
210
|
+
argv.append(str(label))
|
|
211
|
+
if no_compare is True:
|
|
212
|
+
argv.append("--no-compare")
|
|
213
|
+
if upload_as is not None:
|
|
214
|
+
argv.append("--upload-as")
|
|
215
|
+
argv.append(str(upload_as))
|
|
216
|
+
if len(paths):
|
|
217
|
+
# using relpaths is more robust within the working_dir context
|
|
218
|
+
# argv += [str(os.path.relpath(os.path.abspath(path), self.local_path)) for path in paths]
|
|
219
|
+
argv += [os.path.normpath(os.path.join(working_dir, path)) for path in paths]
|
|
220
|
+
try:
|
|
221
|
+
up_subcommand(argv, working_dir)
|
|
222
|
+
except SystemExit as e:
|
|
223
|
+
print("Invalid upload request")
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import os.path
|
|
3
|
+
import requests
|
|
4
|
+
import materials_commons.api as mcapi
|
|
5
|
+
from materials_commons.cli.old.exceptions import MCCLIException
|
|
6
|
+
|
|
7
|
+
def isfile(file_or_dir):
|
|
8
|
+
return isinstance(file_or_dir, mcapi.File) and file_or_dir.mime_type != "directory"
|
|
9
|
+
|
|
10
|
+
def isdir(file_or_dir):
|
|
11
|
+
return isinstance(file_or_dir, mcapi.File) and file_or_dir.mime_type == "directory"
|
|
12
|
+
|
|
13
|
+
def get_parent_id(file_or_dir):
|
|
14
|
+
"""Get file_or_dir.directory_id, else raise"""
|
|
15
|
+
if hasattr(file_or_dir, 'directory_id'):
|
|
16
|
+
if file_or_dir.directory_id == file_or_dir.id:
|
|
17
|
+
raise MCCLIException("directory_id == id")
|
|
18
|
+
return file_or_dir.directory_id
|
|
19
|
+
else:
|
|
20
|
+
raise MCCLIException("file_or_dir is missing attribute directory_id")
|
|
21
|
+
|
|
22
|
+
def make_local_abspath(proj_local_path, mcpath):
|
|
23
|
+
return os.path.normpath(os.path.join(proj_local_path, os.path.relpath(mcpath, "/")))
|
|
24
|
+
|
|
25
|
+
def path_in_project(proj_local_path, local_abspath):
|
|
26
|
+
"""Check if local path is within the local project directory
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
proj_local_path (str): Path to project, i.e. "/path/to/project"
|
|
30
|
+
local_abspath (str): Path to file in project, i.e. "/path/to/project/
|
|
31
|
+
path/to/file"
|
|
32
|
+
|
|
33
|
+
Returns: True, if local_abspath is within the local project directory.
|
|
34
|
+
"""
|
|
35
|
+
return os.path.commonpath([proj_local_path, local_abspath]) == os.path.normpath(proj_local_path)
|
|
36
|
+
|
|
37
|
+
def make_mcpath(proj_local_path, local_abspath):
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
proj_local_path (str): Path to project, i.e. "/path/to/project"
|
|
42
|
+
local_abspath (str): Path to file in project, i.e. "/path/to/project/
|
|
43
|
+
path/to/file"
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
mcpath (str): Returns a Materials Commons style path, i.e. "/path/to/
|
|
47
|
+
file"
|
|
48
|
+
|
|
49
|
+
Raises:
|
|
50
|
+
MCCLIException, if any path in clipaths is not within the local project
|
|
51
|
+
directory.
|
|
52
|
+
"""
|
|
53
|
+
if not path_in_project(proj_local_path, local_abspath):
|
|
54
|
+
raise MCCLIException("make_mcpath error: path not in project")
|
|
55
|
+
relpath = os.path.relpath(local_abspath, proj_local_path)
|
|
56
|
+
if relpath == ".":
|
|
57
|
+
mcpath = "/"
|
|
58
|
+
else:
|
|
59
|
+
mcpath = os.path.join("/", relpath)
|
|
60
|
+
return mcpath
|
|
61
|
+
|
|
62
|
+
def get_by_path_if_exists(client, project_id, file_path):
|
|
63
|
+
"""
|
|
64
|
+
Get file (or directory) by path in project, if it exists.
|
|
65
|
+
:param int project_id: The id of the project containing the file or directory
|
|
66
|
+
:param file_path: The Materials Commons path to the file or directory
|
|
67
|
+
:return: The file or None
|
|
68
|
+
:rtype File or None
|
|
69
|
+
"""
|
|
70
|
+
try:
|
|
71
|
+
return client.get_file_by_path(project_id, file_path)
|
|
72
|
+
except mcapi.MCAPIError as e:
|
|
73
|
+
if e.response.status_code == 404:
|
|
74
|
+
return None
|
|
75
|
+
raise e
|
|
76
|
+
|
|
77
|
+
def _check_file_selection_dirs(path, file_selection, orig_path=None):
|
|
78
|
+
"""Recursively checks if a path is included in a dataset file selection, and why"""
|
|
79
|
+
if path == orig_path:
|
|
80
|
+
selected_by = "(self)"
|
|
81
|
+
else:
|
|
82
|
+
selected_by = path
|
|
83
|
+
if path in file_selection['include_dirs']:
|
|
84
|
+
return (True, selected_by)
|
|
85
|
+
elif path in file_selection['exclude_dirs']:
|
|
86
|
+
return (False, selected_by)
|
|
87
|
+
else:
|
|
88
|
+
parent = os.path.dirname(path)
|
|
89
|
+
if parent == "/":
|
|
90
|
+
return (False, None)
|
|
91
|
+
else:
|
|
92
|
+
return _check_file_selection_dirs(parent, file_selection, orig_path=orig_path)
|
|
93
|
+
|
|
94
|
+
def check_file_selection(path, file_selection):
|
|
95
|
+
"""Check if a file or directory is selected in a dataset file selection, and why.
|
|
96
|
+
|
|
97
|
+
Notes:
|
|
98
|
+
A file is selected in a dataset's file selection if it is listed explicitly in "include_files". It is not selected if it is listed in "exclude_files". If it is neither explicitly included or excluded, its parent directories are searched up to the project root directory to see if they are included or excluded. If the first parent directory listed is in "include_dirs", then the file is also selected. If the first parent directory listed is in "exclude_dirs", or if no parent directory is listed at all, the file is not selected.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
path (str): Materials Commons path of file or directory to check
|
|
102
|
+
file_selection (dict): A file selection dict. Expected format: ::
|
|
103
|
+
|
|
104
|
+
{
|
|
105
|
+
"include_files": [... list of file paths ...],
|
|
106
|
+
"exclude_files": [... list of file paths ...],
|
|
107
|
+
"include_dirs": [... list of directory paths ...],
|
|
108
|
+
"exclude_dirs": [... list of directory paths ...]
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
(selected, selected_by):
|
|
113
|
+
|
|
114
|
+
selected (bool): True if selected, False if not selected
|
|
115
|
+
|
|
116
|
+
selected_by (str or None): One of "(self)" if included/excluded explicitly; Else, "<path>", the path of the first parent directory that is included or excluded; Otherwise, None, to indicate that it is not selected, but neither included nor excluded.
|
|
117
|
+
"""
|
|
118
|
+
result = None
|
|
119
|
+
if path in file_selection['include_files']:
|
|
120
|
+
result = (True, "(self)")
|
|
121
|
+
elif path in file_selection['exclude_files']:
|
|
122
|
+
result = (False, "(self)")
|
|
123
|
+
else:
|
|
124
|
+
result = _check_file_selection_dirs(path, file_selection, orig_path=path)
|
|
125
|
+
return result
|
|
126
|
+
|
|
127
|
+
def download_file_as_string(client, project_id, file_id):
|
|
128
|
+
f = io.BytesIO()
|
|
129
|
+
client._throttle()
|
|
130
|
+
urlpart = "/projects/" + str(project_id) + "/files/" + str(file_id) + "/download"
|
|
131
|
+
url = client.base_url + urlpart
|
|
132
|
+
with requests.get(url, stream=True, verify=False, headers=client.headers) as r:
|
|
133
|
+
client._handle(r)
|
|
134
|
+
for chunk in r.iter_content(chunk_size=8192):
|
|
135
|
+
if chunk:
|
|
136
|
+
f.write(chunk)
|
|
137
|
+
return f.getvalue().decode('utf-8')
|