Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
428be1289c
|
|||
|
4283481695
|
|||
|
ddb4300d85
|
|||
|
68670a6588
|
|||
| 6d8fd0a598 |
@@ -18,6 +18,32 @@ Create remote host configuration
|
||||
mdrs config create neurodata https://neurodata.riken.jp/api
|
||||
```
|
||||
|
||||
### config update
|
||||
|
||||
Update the URL of a registered remote host.
|
||||
|
||||
```shell
|
||||
mdrs config update neurodata https://neurodata.riken.jp/api
|
||||
```
|
||||
|
||||
### config list
|
||||
|
||||
List registered remote hosts.
|
||||
|
||||
```shell
|
||||
mdrs config list
|
||||
mdrs config ls
|
||||
```
|
||||
|
||||
### config delete
|
||||
|
||||
Remove a registered remote host.
|
||||
|
||||
```shell
|
||||
mdrs config delete neurodata
|
||||
mdrs config rm neurodata
|
||||
```
|
||||
|
||||
### login
|
||||
|
||||
Login to remote host
|
||||
@@ -150,6 +176,14 @@ mdrs file-metadata neurodata:/NIU/Repository/TEST/dataset/sample.dat
|
||||
mdrs file-metadata -p SHARING_PASSWORD neurodata:/NIU/Repository/PW_Open/Readme.txt
|
||||
```
|
||||
|
||||
### version
|
||||
|
||||
Show the tool name and version number
|
||||
|
||||
```shell
|
||||
mdrs version
|
||||
```
|
||||
|
||||
### help
|
||||
|
||||
Show the help message and exit
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
1.3.13
|
||||
@@ -17,6 +17,7 @@ from mdrsclient.commands import (
|
||||
MvCommand,
|
||||
RmCommand,
|
||||
UploadCommand,
|
||||
VersionCommand,
|
||||
WhoamiCommand,
|
||||
)
|
||||
from mdrsclient.exceptions import MDRSException
|
||||
@@ -29,6 +30,7 @@ def main() -> None:
|
||||
parsers = parser.add_subparsers(title="subcommands")
|
||||
|
||||
ConfigCommand.register(parsers)
|
||||
VersionCommand.register(parsers)
|
||||
LoginCommand.register(parsers)
|
||||
LogoutCommand.register(parsers)
|
||||
WhoamiCommand.register(parsers)
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import os
|
||||
from importlib.metadata import version
|
||||
|
||||
here = os.path.realpath(os.path.dirname(__file__))
|
||||
|
||||
with open(os.path.join(here, "VERSION")) as version_file:
|
||||
__version__ = version_file.read().strip()
|
||||
__version__ = version("mdrs-client-python")
|
||||
|
||||
__all__ = ["__version__"]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import mimetypes
|
||||
import os
|
||||
from typing import Any, Final
|
||||
from unicodedata import normalize
|
||||
|
||||
from pydantic import TypeAdapter
|
||||
from pydantic.dataclasses import dataclass
|
||||
@@ -53,7 +54,7 @@ class FilesApi(BaseApi):
|
||||
try:
|
||||
with open(os.path.realpath(path), mode="rb") as fp:
|
||||
data = MultipartEncoder(
|
||||
fields={"folder_id": folder_id, "file": (os.path.basename(path), fp, self._get_mime_type(path))}
|
||||
fields={"folder_id": folder_id, "file": (normalize("NFC", os.path.basename(path)), fp, self._get_mime_type(path))}
|
||||
)
|
||||
response = self.connection.post(url, data=data, headers={"Content-Type": data.content_type})
|
||||
self._raise_response_error(response)
|
||||
@@ -75,7 +76,7 @@ class FilesApi(BaseApi):
|
||||
# update file body
|
||||
try:
|
||||
with open(os.path.realpath(path), mode="rb") as fp:
|
||||
data = MultipartEncoder(fields={"file": (os.path.basename(path), fp, self._get_mime_type(path))})
|
||||
data = MultipartEncoder(fields={"file": (normalize("NFC", os.path.basename(path)), fp, self._get_mime_type(path))})
|
||||
response = self.connection.put(url, data=data, headers={"Content-Type": data.content_type})
|
||||
except OSError:
|
||||
raise UnexpectedException(f"Could not open `{path}` file.")
|
||||
|
||||
@@ -12,6 +12,7 @@ from mdrsclient.commands.mkdir import MkdirCommand
|
||||
from mdrsclient.commands.mv import MvCommand
|
||||
from mdrsclient.commands.rm import RmCommand
|
||||
from mdrsclient.commands.upload import UploadCommand
|
||||
from mdrsclient.commands.version import VersionCommand
|
||||
from mdrsclient.commands.whoami import WhoamiCommand
|
||||
|
||||
__all__ = [
|
||||
@@ -29,5 +30,6 @@ __all__ = [
|
||||
"MvCommand",
|
||||
"RmCommand",
|
||||
"UploadCommand",
|
||||
"VersionCommand",
|
||||
"WhoamiCommand",
|
||||
]
|
||||
|
||||
@@ -26,10 +26,9 @@ class ConfigCommand(BaseCommand):
|
||||
update_parser.set_defaults(func=cls.func_update)
|
||||
# config list
|
||||
list_parser = config_parsers.add_parser("list", help="list all the remote hosts", aliases=["ls"])
|
||||
list_parser.add_argument("-l", "--long", help="show the api url", action="store_true")
|
||||
list_parser.set_defaults(func=cls.func_list)
|
||||
# config delete
|
||||
delete_parser = config_parsers.add_parser("delete", help="delete an existing remote host", aliases=["remove"])
|
||||
delete_parser = config_parsers.add_parser("delete", help="delete an existing remote host", aliases=["remove", "rm"])
|
||||
delete_parser.add_argument("remote", help="label of remote host")
|
||||
delete_parser.set_defaults(func=cls.func_delete)
|
||||
|
||||
@@ -47,8 +46,7 @@ class ConfigCommand(BaseCommand):
|
||||
|
||||
@classmethod
|
||||
def func_list(cls, args: Namespace) -> None:
|
||||
is_long = bool(args.long)
|
||||
cls.list(is_long)
|
||||
cls.list()
|
||||
|
||||
@classmethod
|
||||
def func_delete(cls, args: Namespace) -> None:
|
||||
@@ -74,13 +72,10 @@ class ConfigCommand(BaseCommand):
|
||||
config.url = url
|
||||
|
||||
@classmethod
|
||||
def list(cls, is_long: bool) -> None:
|
||||
def list(cls) -> None:
|
||||
config = ConfigFile("")
|
||||
for remote, url in config.list():
|
||||
line = f"{remote}:"
|
||||
if is_long:
|
||||
line += f"\t{url}"
|
||||
print(line)
|
||||
print(f"{remote}:\t{url}")
|
||||
|
||||
@classmethod
|
||||
def delete(cls, remote: str) -> None:
|
||||
|
||||
@@ -23,7 +23,7 @@ class LsCommandContext:
|
||||
laboratory: Laboratory
|
||||
password: str
|
||||
is_json: bool
|
||||
is_quick: bool
|
||||
is_quiet: bool
|
||||
is_recursive: bool
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ class LsCommand(BaseCommand):
|
||||
ls_parser.add_argument("-J", "--json", help="turn on json output", action="store_true")
|
||||
ls_parser.add_argument(
|
||||
"-q",
|
||||
"--quick",
|
||||
"--quiet",
|
||||
help="don't output header row. this option is forced if the -r option is specified",
|
||||
action="store_true",
|
||||
)
|
||||
@@ -49,11 +49,11 @@ class LsCommand(BaseCommand):
|
||||
password = str(args.password) if args.password else None
|
||||
is_json = bool(args.json)
|
||||
is_recursive = bool(args.recursive)
|
||||
is_quick = bool(args.quick) if not is_recursive else True
|
||||
cls.ls(remote_path, password, is_json, is_recursive, is_quick)
|
||||
is_quiet = bool(args.quiet) if not is_recursive else True
|
||||
cls.ls(remote_path, password, is_json, is_recursive, is_quiet)
|
||||
|
||||
@classmethod
|
||||
def ls(cls, remote_path: str, password: str | None, is_json: bool, is_recursive: bool, is_quick: bool) -> None:
|
||||
def ls(cls, remote_path: str, password: str | None, is_json: bool, is_recursive: bool, is_quiet: bool) -> None:
|
||||
(remote, laboratory_name, r_path) = cls._parse_remote_host_with_path(remote_path)
|
||||
connection = cls._create_connection(remote)
|
||||
laboratory = cls._find_laboratory(connection, laboratory_name)
|
||||
@@ -63,7 +63,7 @@ class LsCommand(BaseCommand):
|
||||
laboratory,
|
||||
password if password is not None else "",
|
||||
is_json,
|
||||
is_quick,
|
||||
is_quiet,
|
||||
is_recursive,
|
||||
)
|
||||
folder = cls._find_folder(connection, laboratory, r_path, password)
|
||||
@@ -89,7 +89,7 @@ class LsCommand(BaseCommand):
|
||||
}
|
||||
length: dict[str, int] = {}
|
||||
for key in label.keys():
|
||||
length[key] = len(label[key]) if not context.is_quick else 0
|
||||
length[key] = len(label[key]) if not context.is_quiet else 0
|
||||
for sub_folder in folder.sub_folders:
|
||||
sub_laboratory = context.connection.laboratories.find_by_id(sub_folder.laboratory_id)
|
||||
sub_laboratory_name = sub_laboratory.name if sub_laboratory is not None else "(invalid)"
|
||||
@@ -114,7 +114,7 @@ class LsCommand(BaseCommand):
|
||||
print(f"{context.prefix}{folder.path}:")
|
||||
print(f"total {sum(f.size for f in files)}")
|
||||
|
||||
if not context.is_quick:
|
||||
if not context.is_quiet:
|
||||
print(header)
|
||||
print("-" * len(header.expandtabs()))
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import os
|
||||
from argparse import Namespace
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from typing import Any
|
||||
from unicodedata import normalize
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
|
||||
@@ -81,7 +82,7 @@ class UploadCommand(BaseCommand):
|
||||
if folder_map.get(d_dirname) is None:
|
||||
d_folder = folder_map[d_parent_dirname].find_sub_folder(d_basename)
|
||||
if d_folder is None:
|
||||
d_folder_id = folder_api.create(d_basename, folder_map[d_parent_dirname].id)
|
||||
d_folder_id = folder_api.create(normalize("NFC", d_basename), folder_map[d_parent_dirname].id)
|
||||
else:
|
||||
d_folder_id = d_folder.id
|
||||
print(d_dirname)
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
from argparse import Namespace
|
||||
from typing import Any
|
||||
|
||||
from mdrsclient.__version__ import __version__
|
||||
from mdrsclient.commands.base import BaseCommand
|
||||
|
||||
|
||||
class VersionCommand(BaseCommand):
|
||||
@classmethod
|
||||
def register(cls, parsers: Any) -> None:
|
||||
version_parser = parsers.add_parser("version", help="show the version of this tool")
|
||||
version_parser.set_defaults(func=cls.func)
|
||||
|
||||
@classmethod
|
||||
def func(cls, args: Namespace) -> None:
|
||||
cls.version()
|
||||
|
||||
@classmethod
|
||||
def version(cls) -> None:
|
||||
print(f"mdrs {__version__}")
|
||||
+3
-2
@@ -1,12 +1,12 @@
|
||||
[tool.poetry]
|
||||
name = "mdrs-client-python"
|
||||
version = "1.3.13"
|
||||
version = "1.3.15"
|
||||
description = "The mdrs-client-python is python library and a command-line client for up- and downloading files to and from MDRS based repository."
|
||||
authors = ["Yoshihiro OKUMURA <yoshihiro.okumura@riken.jp>"]
|
||||
license = "MIT"
|
||||
readme = "README.md"
|
||||
classifiers=[
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Development Status :: 4 - Beta",
|
||||
"Environment :: Console",
|
||||
"Intended Audience :: Developers",
|
||||
"Intended Audience :: Science/Research",
|
||||
@@ -14,6 +14,7 @@ classifiers=[
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3.14",
|
||||
"OSI Approved :: MIT License",
|
||||
"Topic :: Utilities",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user