...
 
Commits (3)
Pypftp
pypftp
======
A python interface to interact with HPSS via pftp.
\ No newline at end of file
Python interface to HPSS
`pftp` client program is the default way to interact with HPSS system. It supports both interactive mode and non-interactive mode. In non-interactive mode, a bash script is piped as input to `pftp` program to carry out the execution of the commands. Although `pftp` program is sufficient to address most of user requirements, it lacks a python interface. `pypftp` tries to fill this gap.
`pypftp` is neither replacement of `pftp` program nor an enhancement over it. In-fact, it relies on `pftp` to carry out the file transfers (upload and download) and uses python's ftplib (from standard library) for administrative tasks.
# -*- coding: utf-8 -*-
from .pypftp import Pftp, upload, download
# cli.py
'''command line interface to HPSS'''
import os
import re
import click
@click.group()
def main():
'command line interface to HPSS'
@main.command()
@click.option('-l', default=False, is_flag=True, help="long listing")
@click.argument('path')
def ls(path, l):
"""List directory contents on tape.
\b
PATH: path on tape
"""
with Pftp() as p:
long_listing = True if l else False
contents = p.listdir(path, long_listing=long_listing)
for line in contents:
click.echo(line)
return
@main.command()
@click.argument('path')
def exists(path):
"""check if PATH exists on tape.
\b
PATH: path on tape
"""
with Pftp() as p:
if not p.exists(path):
click.echo('False')
else:
click.echo('True')
@main.command()
@click.option('-h', is_flag=True, help='human readable format')
@click.argument('path')
def size(path, h):
"""Prints file size in bytes. Use -h option for human readable format.
\b
PATH: path on tape
"""
with Pftp() as p:
if not p.exists(path):
click.echo('File not found')
else:
fsize = p.size(path)
if h:
fsize = sizeof_fmt(fsize)
click.echo("{}".format(fsize))
@main.command()
@click.argument('path')
def mkdir(path):
"""creates PATH on tape.
\b
PATH: path on tape
"""
with Pftp() as p:
if p.exists(path):
click.echo('Already exists')
else:
p.makedirs(path)
@main.command()
@click.argument('path')
def isdir(path):
"""checks if PATH is a directory.
\b
PATH: path on tape
"""
with Pftp() as p:
if not p.exists(path):
click.echo('path not found')
elif p.isdir(path):
click.echo('True')
else:
click.echo('False')
@main.command()
@click.argument('path')
def isfile(path):
"""checks if PATH is a file.
\b
PATH: path on tape
"""
res = 1
with Pftp() as p:
if not p.exists(path):
click.echo('path not found')
elif p.isfile(path):
click.echo('True')
res = 0
else:
click.echo('False')
sys.exit(res)
@main.command()
@click.argument('path')
def islink(path):
"""checks if PATH is a link.
\b
PATH: path on tape
"""
with Pftp() as p:
if not p.exists(path):
click.echo('path not found')
elif p.islink(path):
click.echo('True')
else:
click.echo('False')
......@@ -23,6 +23,7 @@ import posixpath
import subprocess as sp
from concurrent.futures import ProcessPoolExecutor
from .utils import has_wildcard
HOST = 'tape.dkrz.de'
......@@ -142,6 +143,21 @@ class Pftp(object):
'present working directory'
return self.ftp_obj.pwd()
@property
def current_directory(self):
"show current working directory"
return self.ftp_obj.pwd()
@current_directory.setter
def current_directory(self, path):
"change working directory"
try:
if path.startswith(self.pwd()):
path = path.replace(self.pwd(), '').lstrip('/')
self.ftp_obj.cwd(path)
except:
raise ValueError('Path does not exists: ' + path)
def cwd(self, path):
'change working directory'
try:
......@@ -222,20 +238,17 @@ class Pftp(object):
return True
return False
def listing(self, path=None):
def listdir(self, path=None, long_listing=False):
"list directory contents"
path = path or self.pwd()
path = path or self.current_directory
if not has_wildcard(path) and not self.exists(path):
raise ValueError("Path does not exists: {}".format(path))
if long_listing:
tmp = []
self.ftp_obj.dir(path, tmp.append)
return tmp
return self.ftp_obj.nlst(path)
listdir = listing
def listing2(self, path=None):
'directory listing in long form. similar to "ls -l"'
path = path or self.pwd()
tmp = []
self.ftp_obj.dir(path, tmp.append)
return tmp
def files(self, path=None):
"gather files at the given path"
path = path or self.pwd()
......
# utils.py
import re
wildcard_check = re.compile('[*?[]')
def has_wildcard(path):
return wildcard_check.search(path) is not None
def human_readable_size(num, suffix='B'):
for unit in ('', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi'):
if abs(num) < 1024.0:
return "%3.1f %s%s" % (num, unit, suffix)
num /= 1024.0
return "%.1f %s%s" % (num, 'Yi', suffix)
from setuptools import setup
import os
readme_filename = os.path.join(os.path.dirname(__file__), "README.md")
with open(readme_filename) as f:
readme = f.read()
setup(
name="pypftp",
version="0.1",
description="Python interface to HPSS",
author="Pavan Siligam",
author_email="siligam@dkrz.de",
long_description=readme,
py_modules=["pypftp"],
install_requires=[
"click",
],
entry_points="""
[console_scripts]
pypftp=pypftp.cli:main
""",
)