materials-commons-cli 2.1.8__tar.gz → 2.2.0__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.
Files changed (59) hide show
  1. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/PKG-INFO +1 -1
  2. materials_commons_cli-2.2.0/materials_commons/cli/__init__.py +1 -0
  3. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/functions.py +14 -6
  4. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/parser.py +9 -3
  5. materials_commons_cli-2.2.0/materials_commons/cli/subcommands/server.py +75 -0
  6. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/up.py +93 -12
  7. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/user_config.py +8 -5
  8. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons_cli.egg-info/PKG-INFO +1 -1
  9. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons_cli.egg-info/SOURCES.txt +1 -0
  10. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons_cli.egg-info/requires.txt +1 -0
  11. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/setup.py +1 -0
  12. materials_commons_cli-2.1.8/materials_commons/cli/__init__.py +0 -1
  13. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/LICENSE +0 -0
  14. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/README.md +0 -0
  15. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/LICENSE.txt +0 -0
  16. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/cloned_project.py +0 -0
  17. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/exceptions.py +0 -0
  18. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/file_functions.py +0 -0
  19. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/globus.py +0 -0
  20. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/list_objects.py +0 -0
  21. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/print_formatter.py +0 -0
  22. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/sqltable.py +0 -0
  23. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/__init__.py +0 -0
  24. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/clone.py +0 -0
  25. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/config.py +0 -0
  26. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/dataset.py +0 -0
  27. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/down.py +0 -0
  28. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/expt.py +0 -0
  29. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/fetch.py +0 -0
  30. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/globus.py +0 -0
  31. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/init.py +0 -0
  32. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/ls.py +0 -0
  33. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/mkdir.py +0 -0
  34. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/mv.py +0 -0
  35. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/proj.py +0 -0
  36. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/remote.py +0 -0
  37. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/rm.py +0 -0
  38. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/subcommands/versions.py +0 -0
  39. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/tmp_functions.py +0 -0
  40. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/tree_functions.py +0 -0
  41. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons/cli/treedb.py +0 -0
  42. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons_cli.egg-info/dependency_links.txt +0 -0
  43. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons_cli.egg-info/entry_points.txt +0 -0
  44. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons_cli.egg-info/not-zip-safe +0 -0
  45. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/materials_commons_cli.egg-info/top_level.txt +0 -0
  46. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/setup.cfg +0 -0
  47. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/test/test_api.py +0 -0
  48. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/test/test_functions.py +0 -0
  49. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/test/test_mc_dataset.py +0 -0
  50. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/test/test_mc_down.py +0 -0
  51. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/test/test_mc_mkdir.py +0 -0
  52. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/test/test_mc_mv.py +0 -0
  53. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/test/test_mc_proj.py +0 -0
  54. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/test/test_mc_rm.py +0 -0
  55. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/test/test_mc_up.py +0 -0
  56. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/test/test_treecompare_no_cache.py +0 -0
  57. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/test/test_treecompare_with_cache.py +0 -0
  58. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/test/test_treedb.py +0 -0
  59. {materials_commons_cli-2.1.8 → materials_commons_cli-2.2.0}/test/test_user_config.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: materials_commons_cli
3
- Version: 2.1.8
3
+ Version: 2.2.0
4
4
  Summary: Materials Commons CLI
5
5
  Home-page: https://materials-commons.github.io/materials-commons-cli/html/index.html
6
6
  Author: Materials Commons development team
@@ -0,0 +1 @@
1
+ __version__ = '2.2.0'
@@ -134,15 +134,23 @@ def format_time(time_value, fmt="%Y %b %d %H:%M:%S"):
134
134
  else:
135
135
  return str(type(time_value))
136
136
 
137
- def checksum(path, chunk_size=131072):
138
- """Generate MD5 checksum for the file at "path" """
137
+ def checksum(path, chunk_size=8192):
138
+ """Generate MD5 checksum for the file at "path"
139
+
140
+ Args:
141
+ path (str): Path to file
142
+ chunk_size (int): Size of chunks to read (default 8192 bytes)
143
+
144
+ Returns:
145
+ str: MD5 checksum hexdigest
146
+ """
139
147
  md5 = hashlib.md5()
140
148
  with open(path, 'rb') as f:
141
149
  while True:
142
- data = f.read(chunk_size)
143
- if not data:
150
+ chunk = f.read(chunk_size)
151
+ if not chunk:
144
152
  break
145
- md5.update(data)
153
+ md5.update(chunk)
146
154
  return md5.hexdigest()
147
155
 
148
156
  def random_name(n=3, max_letters=6, sep='-'):
@@ -449,7 +457,7 @@ def make_local_project(path, data=None):
449
457
  else:
450
458
  proj = models.Project(data=data)
451
459
  except requests.exceptions.ConnectionError as e:
452
- raise MCCLIException("Could not connect to " + remote.config.mcurl)
460
+ raise MCCLIException("Could not connect to " + project_config.remote.mcurl)
453
461
  except requests.exceptions.HTTPError as e:
454
462
  raise MCCLIException("HTTPError: " + str(e))
455
463
 
@@ -31,6 +31,7 @@ from materials_commons.cli.subcommands.rm import rm_subcommand
31
31
  from materials_commons.cli.subcommands.up import up_subcommand
32
32
  from materials_commons.cli.subcommands.versions import versions_subcommand
33
33
  from materials_commons.cli.user_config import Config
34
+ from materials_commons.cli.subcommands.server import server_subcommand
34
35
 
35
36
  standard_usage = [
36
37
  {'name': 'remote', 'desc': 'List servers', 'subcommand': remote_subcommand},
@@ -50,7 +51,8 @@ standard_usage = [
50
51
  {'name': 'versions', 'desc': 'List file versions', 'subcommand': versions_subcommand},
51
52
  # {'name': 'proc', 'desc': 'List processes', 'subcommand': ProcSubcommand()},
52
53
  # {'name': 'samp', 'desc': 'List samples', 'subcommand': SampSubcommand()},
53
- {'name': 'config', 'desc': 'Configure `mc`', 'subcommand': config_subcommand}
54
+ {'name': 'config', 'desc': 'Configure `mc`', 'subcommand': config_subcommand},
55
+ {'name': 'server', 'desc': 'Run MC Server', 'subcommand': server_subcommand}
54
56
  ]
55
57
  standard_interfaces = {d['name']: d for d in standard_usage}
56
58
 
@@ -60,8 +62,13 @@ def make_parser():
60
62
  usage_help.write("mc <command> [<args>]\n\n")
61
63
  usage_help.write("The standard mc commands are:\n")
62
64
 
65
+ beta = os.getenv('MC_BETA')
63
66
  for name, interface in standard_interfaces.items():
64
- usage_help.write(" {:10} {:40}\n".format(name, interface['desc']))
67
+ if name == 'server':
68
+ if beta:
69
+ usage_help.write(" {:10} {:40}\n".format(name, interface['desc']))
70
+ else:
71
+ usage_help.write(" {:10} {:40}\n".format(name, interface['desc']))
65
72
 
66
73
  parser = argparse.ArgumentParser(
67
74
  description='Materials Commons command line interface',
@@ -130,7 +137,6 @@ def main(argv=None, working_dir=None):
130
137
  if working_dir is None:
131
138
  working_dir = os.getcwd()
132
139
  try:
133
-
134
140
  config = Config()
135
141
  if config.REST_logging:
136
142
  mcapi.Client.set_debug_on()
@@ -0,0 +1,75 @@
1
+ import argparse
2
+ import asyncio
3
+ import signal
4
+ import uuid
5
+ from typing import Awaitable, Callable, Dict, Any
6
+
7
+ from materials_commons.cli.desktop.command_handlers import register_handlers
8
+ from materials_commons.cli.desktop.websocket_server import WebSocketCommandListener
9
+ from materials_commons.cli.user_config import Config
10
+ from materials_commons.cli.desktop.local_rest_server import LocalRestServer
11
+
12
+ CommandHandler = Callable[[Dict[str, Any]], Awaitable[None]]
13
+
14
+ DEFAULT_WS_URL = "wss://materialscommons.org/ws"
15
+ DEFAULT_RECONNECT_MIN_SEC = 1
16
+ DEFAULT_RECONNECT_MAX_SEC = 30
17
+
18
+
19
+ def _install_signal_handlers(loop: asyncio.AbstractEventLoop):
20
+ # Installs signal handlers for graceful shutdown
21
+ for sig in (signal.SIGINT, signal.SIGTERM):
22
+ try:
23
+ loop.add_signal_handler(sig, lambda s=sig: asyncio.create_task(_graceful_stop(loop)), None)
24
+ except NotImplementedError:
25
+ signal.signal(sig, lambda *_: asyncio.create_task(_graceful_stop(loop)))
26
+
27
+
28
+ async def _graceful_stop(loop: asyncio.AbstractEventLoop):
29
+ """Cancels pending tasks then stops the event loop"""
30
+ tasks = [t for t in asyncio.all_tasks(loop) if t is not asyncio.current_task(loop)]
31
+ for t in tasks:
32
+ t.cancel()
33
+ await asyncio.gather(*tasks, return_exceptions=True)
34
+ loop.stop()
35
+
36
+
37
+ def server_subcommand(argv, working_dir=None):
38
+ parser = argparse.ArgumentParser(description='Start the Materials Commons server')
39
+ parser.add_argument('--ws-url', type=str, default=DEFAULT_WS_URL, help='WebSocket URL for commands')
40
+ args = parser.parse_args(argv)
41
+
42
+ config = Config()
43
+ if config.client_uuid is None:
44
+ config.client_uuid = str(uuid.uuid4())
45
+ config.save()
46
+
47
+ # Runs local REST server and remote command listener
48
+ async def main():
49
+ queue = asyncio.Queue()
50
+ running_loop = asyncio.get_running_loop()
51
+ local_rest_server = LocalRestServer(loop=running_loop, queue=queue)
52
+ local_rest_server.start()
53
+
54
+ listener = WebSocketCommandListener(args.ws_url, config.default_remote.mcapikey, config.client_uuid,
55
+ register_handlers(), queue)
56
+ try:
57
+ await listener.run()
58
+ finally:
59
+ await listener.shutdown()
60
+ local_rest_server.stop()
61
+
62
+ # Creates event loop; runs main; handles interrupts
63
+ try:
64
+ loop = asyncio.new_event_loop()
65
+ asyncio.set_event_loop(loop)
66
+ _install_signal_handlers(loop)
67
+ loop.run_until_complete(main())
68
+ except KeyboardInterrupt:
69
+ pass
70
+ finally:
71
+ try:
72
+ loop.run_until_complete(_graceful_stop(loop))
73
+ except Exception:
74
+ pass
75
+ loop.close()
@@ -1,10 +1,16 @@
1
1
  import argparse
2
+ import logging
3
+ import sys
2
4
 
3
5
  import materials_commons.cli.exceptions as cliexcept
4
6
  import materials_commons.cli.functions as clifuncs
5
7
  import materials_commons.cli.globus as cliglobus
6
8
  import materials_commons.cli.tree_functions as treefuncs
7
9
  from materials_commons.cli.treedb import LocalTree, RemoteTree
10
+ from materials_commons.cli.subcommands.server import DEFAULT_WS_URL
11
+ from materials_commons.cli.desktop.uploader.api import ws_upload_synchronous
12
+ import os
13
+ from pathlib import Path
8
14
 
9
15
 
10
16
  def make_parser():
@@ -14,11 +20,14 @@ def make_parser():
14
20
 
15
21
  mc_up_usage = """
16
22
  mc up [-r] [--no-compare] [--limit] <pathspec> [<pathspec> ...]
17
- mc up -g [-r] [--no-compare] [--label] <pathspec> [<pathspec> ...]"""
23
+ mc up -g [-r] [--no-compare] [--label] <pathspec> [<pathspec> ...]
24
+ mc up --websocket [-r] <pathspec> [<pathspec> ...]"""
18
25
 
19
26
  globus_help = """Use globus to upload files. Uses the current active upload or creates a new upload.
20
27
  Use `globus task list` to monitor transfer tasks. Use `mc globus upload` to manage uploads."""
21
28
 
29
+ websocket_help = """Use websockets to upload files. Files are uploaded in parallel and progress is reported."""
30
+
22
31
  parser = argparse.ArgumentParser(
23
32
  description=mc_up_description,
24
33
  usage=mc_up_usage,
@@ -30,24 +39,40 @@ def make_parser():
30
39
  help='File size upload limit (MB). Default=750MB. Max size is also 750MB. Does not apply to Globus uploads.')
31
40
  parser.add_argument('-g', '--globus', action="store_true", default=False,
32
41
  help=globus_help)
42
+ parser.add_argument('--websocket', '--ws', action="store_true", default=False, help=websocket_help)
43
+ parser.add_argument('--ws-url', type=str, default=DEFAULT_WS_URL, help='WebSocket URL for commands')
33
44
  parser.add_argument('--label', nargs=1, type=str,
34
45
  help='Globus transfer label to make finding tasks simpler. Default is `<project name>-<upload name>.')
35
46
  parser.add_argument('--no-compare', action="store_true", default=False,
36
47
  help='Upload without checking if remote is equivalent.')
37
- parser.add_argument('--upload-as', nargs=1, default=None, help='Upload to a different location than standard upload. Specified as if it were a local path.')
48
+ parser.add_argument('--upload-as', nargs=1, default=None,
49
+ help='Upload to a different location than standard upload. Specified as if it were a local path.')
50
+ parser.add_argument('--chunk-size', type=int, default=1024 * 1024,
51
+ help='Chunk size for websocket uploads (default: 1MB)')
52
+ parser.add_argument('--max-concurrent', type=int, default=3,
53
+ help='Maximum concurrent uploads for websocket mode (default: 3)')
38
54
  return parser
39
55
 
56
+
40
57
  def up_subcommand(argv, working_dir):
41
58
  """
42
59
  upload files to Materials Commons
43
60
 
44
61
  mc up [-r] [--no-compare] [--limit] <pathspec> [<pathspec> ...]
45
62
  mc up -g [-r] [--no-compare] [--label] <pathspec> [<pathspec> ...]
46
-
63
+ mc up --ws [-r] <pathspec> [<pathspec> ...]
47
64
  """
48
65
  parser = make_parser()
49
66
  args = parser.parse_args(argv)
50
67
 
68
+ showLogs = os.getenv("MC_SHOW_LOGS")
69
+ if showLogs == "true":
70
+ logging.basicConfig(
71
+ level=logging.INFO,
72
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
73
+ handlers=[logging.StreamHandler(sys.stdout)]
74
+ )
75
+
51
76
  proj = clifuncs.make_local_project(working_dir)
52
77
 
53
78
  pconfig = clifuncs.read_project_config(proj.local_path)
@@ -62,6 +87,12 @@ def up_subcommand(argv, working_dir):
62
87
  if args.upload_as and args.globus:
63
88
  print("--upload-as option is not supported with --globus")
64
89
  raise cliexcept.MCCLIException("Invalid upload request")
90
+ if args.upload_as and args.websocket:
91
+ print("--upload-as option is not supported with --websocket")
92
+ raise cliexcept.MCCLIException("Invalid upload request")
93
+ if args.globus and args.websocket:
94
+ print("--globus option is not supported with --websocket")
95
+ raise cliexcept.MCCLIException("Invalid upload request")
65
96
 
66
97
  upload_as = None
67
98
  if args.upload_as:
@@ -69,7 +100,56 @@ def up_subcommand(argv, working_dir):
69
100
  args.upload_as,
70
101
  working_dir)[0]
71
102
 
72
- if args.globus:
103
+ if args.websocket:
104
+ # convert input paths (absolute or relative to working_dir) to local_abspath
105
+ local_abspaths = treefuncs.clipaths_to_local_abspaths(
106
+ proj.local_path, args.paths, working_dir)
107
+
108
+ # filter, skipping .mc, those specified by .mcignore
109
+ local_abspaths = treefuncs.filter_local_abspaths(
110
+ proj.local_path, local_abspaths, working_dir)
111
+
112
+ mcpaths = treefuncs.clipaths_to_mcpaths(proj.local_path, local_abspaths, working_dir)
113
+
114
+ file_paths = []
115
+ project_paths = []
116
+
117
+ for local_path, mc_path in zip(local_abspaths, mcpaths):
118
+ if treefuncs.os.path.isdir(local_path):
119
+ if args.recursive:
120
+ for root, dirs, files in os.walk(local_path):
121
+ for filename in files:
122
+ file_path = os.path.join(root, filename)
123
+
124
+ # Calculate relative path and construct mc_path
125
+ relative = Path(file_path).relative_to(local_path)
126
+ file_mc_path = str(Path(mc_path) / relative)
127
+ file_paths.append(file_path)
128
+ project_paths.append(file_mc_path)
129
+ else:
130
+ print("Skipping directory because --recursive option not specified: " + local_path)
131
+ else:
132
+ file_paths.append(local_path)
133
+ project_paths.append(mc_path)
134
+ if not file_paths:
135
+ print("No files to upload.")
136
+ return
137
+
138
+ status = ws_upload_synchronous(
139
+ file_paths=file_paths,
140
+ project_paths=project_paths,
141
+ project_id=proj.id,
142
+ chunk_size=args.chunk_size,
143
+ max_concurrent=args.max_concurrent,
144
+ ws_url=args.ws_url
145
+ )
146
+ if not status:
147
+ print("\nSome uploads failed.")
148
+ raise cliexcept.MCCLIException(
149
+ "Upload failed. Check server logs for details.")
150
+
151
+ print("\nAll uploads completed successfully!")
152
+ elif args.globus:
73
153
 
74
154
  # convert input paths (absolute or relative to working_dir) to local_abspath
75
155
  local_abspaths = treefuncs.clipaths_to_local_abspaths(
@@ -81,7 +161,7 @@ def up_subcommand(argv, working_dir):
81
161
 
82
162
  mcpaths = treefuncs.clipaths_to_mcpaths(proj.local_path, local_abspaths, working_dir)
83
163
 
84
- all_uploads = {upload.id:upload for upload in proj.remote.get_all_globus_upload_requests(proj.id)}
164
+ all_uploads = {upload.id: upload for upload in proj.remote.get_all_globus_upload_requests(proj.id)}
85
165
 
86
166
  globus_upload_id = None
87
167
  if pconfig.globus_upload_id:
@@ -99,8 +179,9 @@ def up_subcommand(argv, working_dir):
99
179
  upload = all_uploads[globus_upload_id]
100
180
  print("Using current globus upload (name=" + upload.name + ", id=" + str(upload.id) + ").")
101
181
 
102
- if upload.status != 2: # TODO clean up status code / message
103
- raise cliexcept.MCCLIException("Current Globus upload (id=" + str(globus_upload_id) + ") not ready for uploading.")
182
+ if upload.status != 2: # TODO clean up status code / message
183
+ raise cliexcept.MCCLIException(
184
+ "Current Globus upload (id=" + str(globus_upload_id) + ") not ready for uploading.")
104
185
 
105
186
  label = proj.name + "-" + upload.name
106
187
  if args.label:
@@ -117,7 +198,7 @@ def up_subcommand(argv, working_dir):
117
198
  print("Use `mc globus upload` to manage Globus uploads.")
118
199
  print("Multiple transfer tasks may be initiated.")
119
200
  print("When all tasks finish uploading, use `mc globus upload --id " + str(upload.id) +
120
- " --finish` " + "to import all uploaded files into the Materials Commons project.")
201
+ " --finish` " + "to import all uploaded files into the Materials Commons project.")
121
202
 
122
203
  else:
123
204
  localtree = None
@@ -125,9 +206,9 @@ def up_subcommand(argv, working_dir):
125
206
  localtree = LocalTree(proj.local_path)
126
207
 
127
208
  treefuncs.standard_upload_v2(proj, args.paths, working_dir,
128
- recursive=args.recursive, limit=args.limit[0],
129
- no_compare=args.no_compare,
130
- upload_as=upload_as, localtree=localtree,
131
- remotetree=remotetree)
209
+ recursive=args.recursive, limit=args.limit[0],
210
+ no_compare=args.no_compare,
211
+ upload_as=upload_as, localtree=localtree,
212
+ remotetree=remotetree)
132
213
 
133
214
  return
@@ -1,10 +1,10 @@
1
1
  import getpass
2
+ import json
2
3
  import os
3
- import requests
4
- import warnings
4
+ import re
5
5
  from os.path import join
6
- import json
7
6
 
7
+ import requests
8
8
  from materials_commons.api.client import Client
9
9
 
10
10
 
@@ -94,7 +94,8 @@ class Config(object):
94
94
  'mcurl': None,
95
95
  'email': None,
96
96
  'remotes': {},
97
- 'globus': {}
97
+ 'globus': {},
98
+ 'client_uuid': None,
98
99
  }
99
100
 
100
101
  # check for recognized environment variables
@@ -137,6 +138,7 @@ class Config(object):
137
138
 
138
139
  self.developer_mode = config.get('developer_mode', False)
139
140
  self.REST_logging = config.get('REST_logging', False)
141
+ self.client_uuid = config.get('client_uuid', None)
140
142
 
141
143
  def save(self):
142
144
  config = {
@@ -144,7 +146,8 @@ class Config(object):
144
146
  'remotes': [vars(value) for value in self.remotes],
145
147
  'globus': vars(self.globus),
146
148
  'developer_mode': self.developer_mode,
147
- 'REST_logging': self.REST_logging
149
+ 'REST_logging': self.REST_logging,
150
+ 'client_uuid': self.client_uuid or '',
148
151
  }
149
152
  if not os.path.exists(self.config_file):
150
153
  user = getpass.getuser()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: materials-commons-cli
3
- Version: 2.1.8
3
+ Version: 2.2.0
4
4
  Summary: Materials Commons CLI
5
5
  Home-page: https://materials-commons.github.io/materials-commons-cli/html/index.html
6
6
  Author: Materials Commons development team
@@ -32,6 +32,7 @@ materials_commons/cli/subcommands/mv.py
32
32
  materials_commons/cli/subcommands/proj.py
33
33
  materials_commons/cli/subcommands/remote.py
34
34
  materials_commons/cli/subcommands/rm.py
35
+ materials_commons/cli/subcommands/server.py
35
36
  materials_commons/cli/subcommands/up.py
36
37
  materials_commons/cli/subcommands/versions.py
37
38
  materials_commons_cli.egg-info/PKG-INFO
@@ -8,3 +8,4 @@ requests
8
8
  setuptools
9
9
  sortedcontainers
10
10
  tabulate
11
+ websockets
@@ -49,6 +49,7 @@ setup(
49
49
  ],
50
50
  keywords='materials science mc materials-commons prisms',
51
51
  install_requires=[
52
+ "websockets",
52
53
  "globus-cli",
53
54
  "globus-sdk",
54
55
  "igittigitt==2.1.0",
@@ -1 +0,0 @@
1
- __version__ = '2.1.8'