Merge branch 'master' of ssh://bitbucket.org/MoonQ/q-tools

This commit is contained in:
Q
2021-07-11 21:58:59 +03:00
26 changed files with 319 additions and 259 deletions

View File

@@ -22,7 +22,7 @@ Many of the tools use common unix tools. Some extra tools are required. Here are
the installation commands.
```
sudo apt-get install git sqlite3 python python-magic python-pip python-gtk2 sc \
sudo apt-get install git sqlite3 python3 python3-magic python3-pip python3-gtk2 sc \
gnuplot wget vim rsync curl pv
pip2 install csvkit ncsv

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import sys,os
sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__),

View File

@@ -1,10 +1,10 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import curses
import os,sys
import time,datetime
import math
import signal
from optparse import OptionParser
from optparse import OptionParser
def termsize():
@@ -20,7 +20,7 @@ def saddstr(win,y,x,s):
win.addstr(y,x,s)
except:
pass
def drawcircle(win,cy,cx,r):
precision=360
for a in range(precision):
@@ -37,9 +37,9 @@ def drawline(win,cy,cx,a,s,r,char):
ly=int(round(cy-float(l)*math.cos(a)/prec))
lx=int(round(cx+2.0*float(l)*math.sin(a)/prec))
saddstr(win,ly,lx,char)
return
def drawdigit(win,y,x,d):
s=' '
if d=='0':
@@ -98,7 +98,7 @@ def readinput(win):
return ""
class timer_struct:
""" Class for storing timer. """
""" Class for storing timer. """
def __init__(self,h,m,s):
self.tm_hour=int(h)
self.tm_min=int(m)
@@ -149,7 +149,7 @@ def main():
stdscr.keypad(0)
curses.endwin()
sys.exit(0)
except KeyboardInterrupt:
curses.nocbreak()
stdscr.keypad(0)
@@ -159,7 +159,7 @@ def main():
usage='''Usage: %prog [options]
Display a clockface
Display a clockface
'''
parser=OptionParser(usage=usage)
parser.add_option("-s",action="store_true",dest="seconds",default=False,

View File

@@ -190,8 +190,9 @@ if method == "regexp":
(outFolders, uniqlabel, matcher) = regexmatches(inFiles, options)
input("correct?")
else:
padding = "{:0" + str(len(str(options.n))) + "d}"
for x in range(options.n):
outFolders.append(os.path.join(options.path, "folder" + str(x + 1)))
outFolders.append(os.path.join(options.path, ("folder-" + padding).format(x + 1)))
for x in outFolders:
if not os.path.isdir(x):

View File

@@ -19,7 +19,7 @@ function listfiles() {
}
function count_size() {
cat - | python -c "import sys
cat - | python3 -c "import sys
def sizeof_fmt(num, suffix='B'):
for unit in ['','K','M','G','T','P','E','Z']:
if num < 1024.0:

View File

@@ -22,7 +22,7 @@ function listfolders() {
}
function count_size() {
cat - | python -c "import sys
cat - | python3 -c "import sys
def sizeof_fmt(num, suffix='B'):
for unit in ['','K','M','G','T','P','E','Z']:
if num < 1024.0:

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import sys
import scipy.misc
import numpy as n

View File

@@ -11,6 +11,7 @@ Usage: file-enumerate [-k] [-p #] [-o folder]
-p Pad numbers, defaults to 4
-o Output folder name, default: enumerated
-c Copy instead of hard link
-i Offset. start from number (default 1)
'
exit
}
@@ -18,6 +19,7 @@ keep=false
pad=4
output=enumerated
hardlink="-l"
offset=1
for (( i=1; i<=$#; i++ )); do
j=$(( i + 1 ))
[[ "${!i}" = "-h" ]] && _help
@@ -26,12 +28,14 @@ for (( i=1; i<=$#; i++ )); do
[[ "${!i}" = "-k" ]] && keep=true
[[ "${!i}" = "-p" ]] && { pad=${!j}; i=$(( i + 1 )); }
[[ "${!i}" = "-o" ]] && { output=${!j}; i=$(( i + 1 )); }
[[ "${!i}" = "-i" ]] && { offset=${!j}; i=$(( i + 1 )); }
done
printf -v padstr "%%0%dd" $pad
_drive() {
ls -1p | grep -v "/$" | sort -V | cat -n | while read n f; do
n=$(( n + $offset - 1 ))
printf -v padded $padstr $n
if [[ $keep = true ]]; then
printf -v outname "%s.%s" "$padded" "$f"

View File

@@ -1,5 +1,12 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: latin-1 -*-
from __future__ import division
from __future__ import print_function
from future import standard_library
standard_library.install_aliases()
from builtins import zip
from builtins import str
from past.utils import old_div
import sys
import os
import re
@@ -8,7 +15,8 @@ import subprocess
import hashlib
import magic
from argparse import ArgumentParser
import ConfigParser,StringIO,io
import configparser
import io
import datetime
SQLFILE='list_of_files.sqlite'
@@ -67,7 +75,7 @@ def setup_options():
BADDIRS.extend(options.exclude)
if options.duplicate:
options.add=not options.add
options.startpath=unicode(options.startpath, "UTF-8")
options.sqlpath=os.path.dirname(os.path.realpath(options.sqlfile))
return options
@@ -78,7 +86,7 @@ def add_recurse(options):
db=conn.cursor()
prev_path_len=0
for path,dirs,files in os.walk(options.startpath,followlinks=options.symlinks):
sys.stdout.write(("\r%s%s"%(filename_join(path,".",options),(prev_path_len-len(path))*' ')).encode('utf-8'))
sys.stdout.write(("\r%s%s"%(filename_join(path,".",options),(prev_path_len-len(path))*' ')))
prev_path_len=len(path)
dirs=clean_dirs(dirs)
dirs.sort()
@@ -218,11 +226,11 @@ def createdb(options):
object TEXT)')
conn.commit()
config = ConfigParser.RawConfigParser()
config = configparser.RawConfigParser()
config.add_section("General")
config.set("General","Relative",str(options.relative))
config.set("General","FullFile",str(options.fullfile))
store=StringIO.StringIO()
store=io.StringIO()
config.write(store)
db.execute("INSERT INTO config (object) values (?)",(store.getvalue(),))
conn.commit()
@@ -317,7 +325,7 @@ def get_folder_contents(db,path):
db.execute("SELECT file FROM list where file LIKE ?",(path+'%',))
for row in db:
try:
base=row[0].decode('utf-8').replace(path,'',1)
base=row[0].replace(path,'',1)
except UnicodeDecodeError:
print(row[0]+" is giving me trouble.")
try:
@@ -337,7 +345,7 @@ def get_md5(filename,fullfile=False):
anim_i=0
anim_len=len(ANIM)
block_size=2**24
percents_per_block=100/(float(fsize)/block_size)
percents_per_block=old_div(100,(old_div(float(fsize),block_size)))
md5 = hashlib.md5()
with open(filename,'rb') as f:
for chunk in iter(lambda: f.read(block_size), b''):
@@ -425,7 +433,7 @@ def humanize_size(size,precision=1):
defPrecision=0
while size > 1024:
suffixIndex += 1 #increment the index of the suffix
size = size/1024.0 #apply the division
size = old_div(size,1024.0) #apply the division
defPrecision=precision
return "%.*f%s"%(defPrecision,size,suffixes[suffixIndex])
@@ -510,7 +518,7 @@ def stored_options(options):
store=""
for row in db:
store+=row[0]+'\n'
config = ConfigParser.RawConfigParser()
config = configparser.RawConfigParser()
config.readfp(io.BytesIO(store))
options.relative=config.getboolean("General","Relative")
options.fullfile=config.getboolean("General","FullFile")

View File

@@ -1,9 +1,9 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import sys,os
from Tkinter import *
from PIL import Image,ImageTk, ImageDraw
import math
from argparse import ArgumentParser
from argparse import ArgumentParser
import sqlite3
SQLFILE='list_of_images.sqlite'
@@ -16,9 +16,9 @@ def setup_options():
parser.add_argument("-t",action="store",dest="tags",default="thisIsGood,thisIsBad",
help="Comma separated list of tags")
parser.add_argument("-n",action="store",type=int,dest="number",default=0,
help="Number of tags expected. 0 is any amount.")
help="Number of tags expected. 0 is any amount.")
parser.add_argument('path', action="store",default='.', nargs='?')
options=parser.parse_args()
options.tags=[x.strip() for x in options.tags.split(",")]
return options
@@ -26,7 +26,7 @@ def setup_options():
class Click:
def __init__(self, image,tags,sqlfile,title,number):
self.title=title
self.root=Tk()
self.root.geometry("1024x768+220+0")
@@ -40,7 +40,7 @@ class Click:
self.img_copy= self.image.copy()
self.pixels = self.img_copy.load()
self.background_image = ImageTk.PhotoImage(self.image)
self.background = Label(self.root, image=self.background_image, cursor='cross')
self.background.pack(fill="both", expand=True, side="left")
self.background.bind('<Configure>', self._resize_image)
@@ -68,14 +68,14 @@ class Click:
self.tags[t+1].bind("<Return>", self._tag_key)
self.tags.append(Button(self.top, text="Custom", command=self._tag_button("custom")))
self.tags[t+2].pack(fill="both", side="top")
self.top.geometry("220x%d+0+0"%(self.root.winfo_screenheight()-150,))
self._resize_init()
self._init_db(sqlfile)
self._print_tags()
self.root.mainloop()
def _tag_key(self,event):
@@ -102,12 +102,12 @@ class Click:
self.image = self.img_copy.resize((new_width, new_height))
self.background_image = ImageTk.PhotoImage(self.image)
self.background.configure(image = self.background_image)
def _resize_init(self):
event = self._get_max_size()
self.root.geometry("%dx%d+220+0"% (event.width, event.height))
self._resize_image(event)
def _get_max_size(self,refer_size=None):
""" return max size for image that fits the refer_size,.
otherwise, return max size for the screen """
@@ -122,14 +122,14 @@ class Click:
if new_width>refer_width:
new_width=refer_width
new_height=int(float(self.img_copy.size[1])/float(self.img_copy.size[0])*new_width)
event = type('eventclass', (object,),
event = type('eventclass', (object,),
{'width':new_width, 'height':new_height})()
return event
def _quit(self,event):
self.root.destroy()
sys.exit(0)
def _next(self,event):
self.root.destroy()
@@ -155,7 +155,7 @@ class Click:
if self.numberLimit>0 and self.numberLimit<self.numberCurrent:
self._next(0)
return
def _print_tags(self):
self.db[0].execute("SELECT hash FROM list WHERE file = ?",( os.path.realpath( self.image_name), ))
hashes=self.db[0].fetchall()
@@ -164,10 +164,10 @@ class Click:
self._next(None)
return
self.db[0].execute("SELECT tag FROM tags WHERE hash = ?",( hashes[0][0], ))
print("tags: "+",".join([x[0] for x in self.db[0]]))
return
def _init_db(self, sqlfile):
if not os.path.exists(sqlfile):
print("Cannot find SQLite file: "+sqlfile)
@@ -176,12 +176,12 @@ class Click:
conn.text_factory=str
db=conn.cursor()
self.db=[db,conn]
def get_tags(self):
return self.tagTexts
def _hotkey(self,i):
# return string number for 1-9
# return string number for 1-9
# a-l if i>9
if i<10:
return str(i)
@@ -201,7 +201,7 @@ if os.path.isfile(opt.path):
imagelist=[opt.path]
else:
imagelist=sorted([os.path.join(opt.path,f) for f in os.listdir(opt.path) if IMGMATCH.match(f)])
for i,l in enumerate(imagelist):
(p,b)=os.path.split( os.path.abspath(l) )
(f,p)=os.path.split( p )

View File

@@ -1,10 +1,11 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# coding=UTF-8
from __future__ import print_function
import sys
import os,time,datetime
import sqlite3
import subprocess,shlex
from argparse import ArgumentParser
from argparse import ArgumentParser
SQLFILE=os.path.expandvars('$HOME/.rsync-queue.sqlite')
@@ -55,7 +56,7 @@ def createdb(fname):
conn.text_factory=str
db.execute('CREATE TABLE list (id INTEGER PRIMARY KEY AUTOINCREMENT,\
SRC TEXT,TGT TEXT, exitcode INTEGER)')
conn.commit()
conn.commit()
return
def mark_done(options, SRC,TGT, exitcode):
@@ -105,9 +106,9 @@ def list_URLs(options):
db.execute("SELECT * FROM list ORDER BY id")
else:
db.execute("SELECT * FROM list WHERE exitcode > 0 ORDER BY id")
print "EC\tSRC\tTGT"
print("EC\tSRC\tTGT")
for row in db:
print "%s\t%s\t%s" % (row[3],row[1],row[2])
print("%s\t%s\t%s" % (row[3],row[1],row[2]))
return
def start_sync(options):
@@ -121,7 +122,7 @@ def start_sync(options):
command=['rsync']
command.extend(syncopts)
command.extend([SRC,TGT])
popen = subprocess.Popen(command,
popen = subprocess.Popen(command,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=8)
j=1
try:

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import sys
from argparse import ArgumentParser

View File

@@ -13,7 +13,7 @@ function gcd() {
darwin*) QCDPATH=$( dirname $( realpath ${BASH_SOURCE[0]} ) ) ;;
*) QCDPATH=$( dirname $( readlink -f ${BASH_SOURCE[0]} ) ) ;;
esac
cdto=$( python "$QCDPATH"/files/gcd-findmatch.py "$@" )
cdto=$( python3 "$QCDPATH"/files/gcd-findmatch.py "$@" )
[[ -z "$cdto" ]] && return
\cd "$cdto"
} # gcd ends

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import os
import sys
@@ -36,16 +36,16 @@ class bc:
self.CLR = ''
self.CYA = ''
self.WHI = ''
def pos(self,y,x):
return "\033["+str(y)+";"+str(x)+"H"
class getch:
def __init__(self):
import sys, tty, termios
def get(self):
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
@@ -57,7 +57,7 @@ class getch:
def ichr(i):
''' convert integer to 1-9, a-z, A-Z, omitting x '''
''' convert integer to 1-9, a-z, A-Z, omitting x '''
if i < 10:
return str(i)
@@ -75,7 +75,7 @@ def drawmenu(entries):
twocol=False
co=bc()
helptext=""
print(co.END+co.CLR+co.pos(1,3)+co.YEL+'XRandrMenu x:exit '+helptext+co.END)
if len(entries)>20:
twocol=True
@@ -127,7 +127,7 @@ def read_displays():
entries.sort(key=lambda x: x[0])
return entries
def append_index(entries,offset=0,color=None):
e=1+offset
for el in range(len(entries)):
@@ -153,7 +153,7 @@ def initialize():
entries=read_displays()
entries=append_index(entries,offset=0,color=bc.CYA)
return entries
def main():
entries=initialize()
print(entries)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# Copyright 2015 Ville Rantanen
#
@@ -17,13 +17,14 @@
#
'''simple head for tsv/csv files.'''
from __future__ import print_function
__author__ = "Ville Rantanen <ville.q.rantanen@gmail.com>"
__version__ = "0.1"
import sys,os,argparse
from argparse import ArgumentParser
from argparse import ArgumentParser
def setup_options():
''' Create command line options '''
@@ -31,7 +32,7 @@ def setup_options():
Simple implementation of head that keeps the header row.
'''
parser=ArgumentParser(description=usage,
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="\n".join(["Version: "+__version__,__author__]))
@@ -60,7 +61,7 @@ def behead(fileob,opts):
head_ordinary(fileob, opts.lines)
else:
head_allbutlast(fileob, opts.lines)
def head_ordinary(fileob, lines):
for i,row in enumerate(fileob):
if i>lines-1:
@@ -82,12 +83,13 @@ def main():
behead(sys.stdin, opts)
for fi in opts.file:
behead(open(fi,'r'), opts)
except IOError as (n,e):
except IOError as xxx_todo_changeme:
(n,e) = xxx_todo_changeme.args
if n==32:
pass
else:
import traceback
print traceback.format_exc()
print(traceback.format_exc())
except KeyboardInterrupt:
pass

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# Copyright 2015 Ville Rantanen
#
@@ -17,13 +17,14 @@
#
'''simple tail for tsv/csv files.'''
from __future__ import print_function
__author__ = "Ville Rantanen <ville.q.rantanen@gmail.com>"
__version__ = "0.1"
import sys,os,argparse
from argparse import ArgumentParser
from argparse import ArgumentParser
def setup_options():
''' Create command line options '''
@@ -31,7 +32,7 @@ def setup_options():
simple implementation of tail, keeping the header row
'''
parser=ArgumentParser(description=usage,
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="\n".join(["Version: "+__version__,__author__]))
@@ -64,7 +65,7 @@ def tail(fileob,opts):
tail_ordinary(fileob, opts.lines)
else:
tail_allbutfirst(fileob, -opts.lines)
def tail_allbutfirst(fileob, lines):
for i,row in enumerate(fileob):
if i<lines-1:
@@ -86,12 +87,13 @@ def main():
tail(sys.stdin, opts)
for fi in opts.file:
tail(open(fi,'r'), opts)
except IOError as (n,e):
except IOError as xxx_todo_changeme:
(n,e) = xxx_todo_changeme.args
if n==32:
pass
else:
import traceback
print traceback.format_exc()
print(traceback.format_exc())
except KeyboardInterrupt:
pass

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# Copyright 2017 Ville Rantanen
#
@@ -23,7 +23,7 @@ __author__ = "Ville Rantanen"
__version__ = "0.1"
import sys
from argparse import ArgumentParser
from argparse import ArgumentParser
import unicodedata, re
import subprocess
@@ -46,12 +46,12 @@ def which(program):
class SCReader:
""" Class for reading SC files.
"""
"""
def __init__(self,data):
self.data=data.split('\n')
self.parserre=re.compile('.* ([A-Z]+)([0-9]+) = (.*)')
def _parse_row(self,string):
col=None
row=None
@@ -62,14 +62,14 @@ class SCReader:
row=self.try_int(m.group(2))
content=m.group(3)
return col,row,content
def try_int(self,string):
try:
return int(string)
except:
return string
def alpha_to_column(self,alpha):
''' Returns a column number from spreadsheet column alphabet '''
n=0
@@ -78,7 +78,7 @@ class SCReader:
o+=(ord(char.upper())-64)*(26**n)
n+=1
return int(o-1)
def next(self):
''' Returns the next row in the table, three items: column, row, content'''
return self._parse_row(self.reader.next())
@@ -89,7 +89,7 @@ class SCReader:
def setup_options():
''' Setup the command line options '''
parser=ArgumentParser()
parser.add_argument("-v","--version",action='version', version=__version__)
parser.add_argument("-d",type=str,dest="delimiter",default="\t",
@@ -97,8 +97,8 @@ def setup_options():
parser.add_argument("sc",type=str,action="store",
help="SC file to convert")
options=parser.parse_args()
return options
return options
def tsv_write(screader,fileout,delim):
''' writes a TSV from SCReader iterator '''
content=[]

View File

@@ -37,7 +37,7 @@ sqlfile="$1"
}
VIEWER=ncsv
which ncsv > /dev/null || {
VIEWER="tabview -"
VIEWER="tabview -w max -"
which tabview > /dev/null || VIEWER="cat -"
}

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# Copyright 2017 Ville Rantanen
#
@@ -17,14 +17,21 @@
#
'''TSV 2 SC convert.'''
from __future__ import division
from __future__ import print_function
from builtins import chr
from builtins import str
from builtins import range
from builtins import object
from past.utils import old_div
__author__ = "Ville Rantanen"
__version__ = "0.2"
import sys,os
import csv
from argparse import ArgumentParser
from argparse import ArgumentParser
import unicodedata, re
import subprocess
@@ -45,10 +52,10 @@ def which(program):
return None
class SCWriter:
class SCWriter(object):
""" Class for writing SC files.
"""
"""
def __init__(self,file,alignright,float_precision):
self.file=file
self.row=0
@@ -61,9 +68,9 @@ class SCWriter:
self.alignstring="rightstring"
else:
self.alignstring="leftstring"
def parse_row(self,string):
self.col=0
for el in row:
self.write_element(self.row,self.col,el)
@@ -78,30 +85,30 @@ class SCWriter:
self.col_lengths[self.col]=max(len(el_str)+1,self.col_lengths[self.col])
self.col+=1
self.row+=1
def write_element(self,row,col,content):
colalpha=self.column_to_alpha(col)
content=content.strip('"')
if self.is_num(content):
self.file.write('let '+colalpha+str(row)+' = ' + str(self.to_num(content))+'\n')
else:
self.file.write(self.alignstring+' '+colalpha+str(row)+' = "' + content + '"\n')
def column_to_alpha(self,column):
''' Returns a column alphabet from column number '''
o=chr(column+64+1)
if column>25:
return self.column_to_alpha((column / 26) -1) + self.column_to_alpha(column % 26);
return self.column_to_alpha((old_div(column, 26)) -1) + self.column_to_alpha(column % 26);
return o
def write_row(self,row):
''' Writes a row as a SC file part '''
self.parse_row(row)
def write_formats(self):
for col in range(len(self.col_lengths)):
precision="0"
if self.col_types[col]=='float':
@@ -117,7 +124,7 @@ class SCWriter:
return True
except:
pass
return False
return False
def is_int(self,string):
try:
@@ -125,7 +132,7 @@ class SCWriter:
return True
except:
pass
return False
return False
def is_num(self,string):
@@ -149,12 +156,12 @@ class SCWriter:
return num
except:
pass
return string
def setup_options():
''' Setup the command line options '''
parser=ArgumentParser()
parser.add_argument("-v","--version",action='version', version=__version__)
parser.add_argument("-f",type=int,dest="precision",default=2,
@@ -166,8 +173,8 @@ def setup_options():
parser.add_argument("tsv",type=str,action="store",
help="TSV file to convert")
options=parser.parse_args()
return options
return options
if not which('sc'):
print('You don\'t seem to have "sc" installed!')
print('sudo apt-get install sc')

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# Copyright 2014 Ville Rantanen
#
@@ -17,14 +17,13 @@
#
'''SC based CSV editor.'''
__author__ = "Ville Rantanen"
__version__ = "0.2"
import sys,os
import csv
from argparse import ArgumentParser
from argparse import ArgumentParser
import unicodedata, re
import subprocess
import shutil
@@ -46,14 +45,14 @@ def which(program):
return None
class SCReader:
class SCReader(object):
""" Class for reading SC files.
"""
"""
def __init__(self,fileobject):
self.file=fileobject
self.parserre=re.compile('.* ([A-Z]+)([0-9]+) = (.*)')
def _parse_row(self,string):
col=None
row=None
@@ -64,14 +63,14 @@ class SCReader:
row=self.try_int(m.group(2))
content=m.group(3)
return col,row,content
def try_int(self,string):
try:
return int(string)
except:
return string
def alpha_to_column(self,alpha):
''' Returns a column number from spreadsheet column alphabet '''
n=0
@@ -80,28 +79,28 @@ class SCReader:
o+=(ord(char.upper())-64)*(26**n)
n+=1
return int(o-1)
def next(self):
def __next__(self):
''' Returns the next row in the table, three items: column, row, content'''
return self._parse_row(self.reader.next())
return self._parse_row(next(self.reader))
def __iter__(self):
for row in self.file:
yield self._parse_row(row)
class SCWriter:
class SCWriter(object):
""" Class for writing SC files.
"""
"""
def __init__(self,fileobject):
self.file=fileobject
self.row=0
self.col=0
self.col_lengths=[]
def parse_row(self,string):
self.col=0
for el in row:
self.write_element(self.row,self.col,el)
@@ -111,34 +110,34 @@ class SCWriter:
self.col_lengths[self.col]=max(len(el),self.col_lengths[self.col])
self.col+=1
self.row+=1
def write_element(self,row,col,content):
colalpha=self.column_to_alpha(col)
content=content.strip('"')
if self.is_num(content):
self.file.write('let '+colalpha+str(row)+' = ' + str(self.to_num(content))+'\n')
else:
self.file.write('rightstring '+colalpha+str(row)+' = "' + content + '"\n')
def column_to_alpha(self,column):
''' Returns a column alphabet from column number '''
o=chr(column+64+1)
if column>25:
return self.column_to_alpha((column / 26) -1) + self.column_to_alpha(column % 26);
return self.column_to_alpha((column // 26) -1) + self.column_to_alpha(column % 26)
return o
def write_row(self,row):
''' Writes a row as a SC file part '''
self.parse_row(row)
def write_formats(self):
for col in range(len(self.col_lengths)):
self.file.write('format '+self.column_to_alpha(col)+' '+str(self.col_lengths[col])+' 2 0\n')
def is_num(self,string):
''' returns the True if string can be converted to number safely '''
try:
@@ -152,7 +151,7 @@ class SCWriter:
return True
except:
pass
return False
def to_num(self,string):
@@ -168,12 +167,12 @@ class SCWriter:
return num
except:
pass
return string
def setup_options():
''' Setup the command line options '''
parser=ArgumentParser()
parser.add_argument("-v","--version",action='version', version=__version__)
parser.add_argument("-b",action="store_false",dest="backup",default=True,
@@ -185,8 +184,8 @@ def setup_options():
parser.add_argument("tsv",type=str,action="store",
help="TSV file to edit")
options=parser.parse_args()
return options
return options
def csv_write(screader,fileout):
''' writes a CSV from SCReader iterator '''
content=[]
@@ -250,7 +249,7 @@ subprocess.call(['sc',f_sc])
process = subprocess.Popen(['sc','-v','-P','%',f_sc], shell=False, stdout=subprocess.PIPE)
f_cs_tmp_w=open(f_sc_tmp,'wt')
for l in process.stdout.readlines():
f_cs_tmp_w.write(l)
f_cs_tmp_w.write(l.decode('utf8'))
f_cs_tmp_w.close()
# Convert SC -> CSV

View File

@@ -7,7 +7,7 @@ function c2t {
# Convert comma separated stream in to tab separated stream
# Usage: echo "foo,bar" | c2t
python -c 'import sys,csv
python3 -c 'import sys,csv
try:
csv.writer(sys.stdout, dialect=csv.excel_tab, lineterminator="\n").writerows(csv.reader(sys.stdin, dialect=csv.excel))
except IOError:
@@ -15,15 +15,15 @@ except IOError:
}
function header {
# Print only the first line of input
# Print only the first line of input
# Usage: header file.csv
# Usage: cat file.csv | header
# Usage: cat file.csv | header
head -n 1 "$@"
}
function noheader {
# Strip first row of input
# Strip first row of input
# Usage: noheader file.csv
# Usage: cat file.csv | noheader
@@ -33,7 +33,7 @@ function noheader {
function tsvecho {
# Echo with tab separated values, quoted
# Usage: tsvecho value1 value2 "some value" > header.csv
# Usage: echo value1 value2 | tsvecho
# Usage: echo value1 value2 | tsvecho
local HEAD
[[ -t 0 ]] && {
@@ -48,7 +48,7 @@ function tsvstrip {
# Strip tsv of quotes
# Usage: cat file.csv | tsvstrip
python -c 'import sys,csv
python3 -c 'import sys,csv
try:
csv.writer(sys.stdout, dialect=csv.excel_tab, quoting=csv.QUOTE_NONE).writerows(csv.reader(sys.stdin, dialect=csv.excel_tab))
except IOError:
@@ -59,7 +59,7 @@ function tsvtranspose {
# Transpose a tsv file
# Usage: cat file.csv | tsvtranspose
python -c 'import sys,csv
python3 -c 'import sys,csv
try:
csv.writer(sys.stdout, dialect=csv.excel_tab, quoting=csv.QUOTE_NONE).writerows(map(None,*csv.reader(sys.stdin, dialect=csv.excel_tab)))
except IOError:
@@ -71,9 +71,9 @@ function tsvhead {
# Usage: cat file | tsvhead -n 30
if [ -t 0 ]; then
python "${TSVDIR}"/lib/tsvhead "$@"
python3 "${TSVDIR}"/lib/tsvhead "$@"
else
cat - | python "${TSVDIR}"/lib/tsvhead "$@"
cat - | python3 "${TSVDIR}"/lib/tsvhead "$@"
fi
}
@@ -82,9 +82,9 @@ function tsvtail {
# Usage: cat file | tsvtail -n 30
if [ -t 0 ]; then
python "${TSVDIR}"/lib/tsvtail "$@"
python3 "${TSVDIR}"/lib/tsvtail "$@"
else
cat - | python "${TSVDIR}"/lib/tsvtail "$@"
cat - | python3 "${TSVDIR}"/lib/tsvtail "$@"
fi
}
@@ -94,7 +94,7 @@ function tsvcut {
# csvcut with tab-delimited dialect, see original script for options
# Usage: tsvcut -c Col1,Col3 input1.tsv
csvcut -t "$@" | c2t
}
@@ -102,7 +102,7 @@ function tsvformat {
# csvformat with tab-delimited dialect, see original script for options
# Usage: tsvformat -c Col2 -m searchString input1.tsv
csvformat -t -T "$@"
}
@@ -110,7 +110,7 @@ function tsvgrep {
# csvgrep with tab-delimited dialect, see original script for options
# Usage: tsvgrep -c Col2 -m searchString input1.tsv
csvgrep -t "$@" | c2t
}
@@ -118,7 +118,7 @@ function tsvjoin {
# csvjoin with tab-delimited dialect, see original script for options
# Usage: tsvjoin -c 1,1 input1.tsv input2.tsv
csvjoin -t "$@" | c2t
}
@@ -126,7 +126,7 @@ function tsvlook {
# csvlook with tab-delimited dialect, see original script for options
# Usage: tsvlook file1.tsv
csvlook -t "$@"
}
@@ -147,8 +147,8 @@ function tsvquery {
When defining a database with -d it is kept, and can be
inserted with more data later. Otherwise the DB is created in /tmp/
and deleted afterwards.
If not using name=data.tsv syntax, tables are named tsv1, tsv2...
Note: You have to give an SQL query. If you just want to
If not using name=data.tsv syntax, tables are named tsv1, tsv2...
Note: You have to give an SQL query. If you just want to
populate a database, add " " as an empty query.
'
return 0
@@ -167,7 +167,7 @@ function tsvquery {
# Add table with unique numbering
local OLDTBLS=$( sqlite3 "$DBTEMP" ".tables" )
local TBLNO=1
while :
while :
do echo $OLDTBLS | grep tsv$TBLNO > /dev/null || break
TBLNO=$(( $TBLNO + 1 ))
done
@@ -178,7 +178,7 @@ function tsvquery {
local FIL
TBL=$( echo ${!i} | sed 's,=.*,,' )
FIL=$( echo ${!i} | sed "s,^$TBL=,," )
[ -f "$FIL" ] && {
[ -f "$FIL" ] && {
cat "$FIL" | csvsql -t --db "sqlite:///$DBTEMP" --insert --table "$TBL"
} || {
echo File "${!i}" not found
@@ -191,7 +191,7 @@ function tsvquery {
local EC=$?
# remove DB if using temporary
[ -z "$j" ] && {
rm -f "$DBTEMP"
rm -f "$DBTEMP"
}
return $EC
}
@@ -200,7 +200,7 @@ function tsvsort {
# csvsort with tab-delimited dialect, see original script for options
# Usage: tsvsort -c Col3 input.tsv
csvsort -t "$@" | c2t
}
@@ -208,7 +208,7 @@ function tsvstack {
# csvstack with tab-delimited dialect, see original script for options
# Usage: tsvstack file1.tsv file2.tsv
csvstack -t "$@" | c2t
}
@@ -240,9 +240,9 @@ function tsvfold {
function tsvdims {
# Print dimensions of a TSV
# Usage: tsvdims file.txt
# Usage: cat file.txt | tsvdims
# Usage: cat file.txt | tsvdims
python -c 'import sys,csv
python3 -c 'import sys,csv
if sys.argv[1]=="":
input=sys.stdin
else:

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# Copyright 2016 Ville Rantanen
#
@@ -16,8 +16,10 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from __future__ import print_function
from __future__ import division
from past.utils import old_div
import sys, os, math, csv, subprocess
from argparse import ArgumentParser
from argparse import ArgumentParser
'''Plot CSV files with GNUPLOT.'''
__author__ = "Ville Rantanen"
@@ -29,7 +31,7 @@ def get_data_scatter(opts):
try:
for row in reader:
data.append(",".join([row[c] for c in opts.columns]))
except KeyError,ME:
except KeyError as ME:
print("Column {} not found.".format(ME),file=sys.stderr)
print("Columns in the file:"+",".join(reader.fieldnames),file=sys.stderr)
sys.exit(1)
@@ -45,12 +47,12 @@ def get_data_histogram(opts):
data.append(row[opts.columns[0]])
except ValueError:
continue
except KeyError,ME:
except KeyError as ME:
print("Column {} not found.".format(ME),file=sys.stderr)
print("Columns in the file:"+",".join(reader.fieldnames),file=sys.stderr)
sys.exit(1)
return "\n".join(data)
def get_stats(opts):
reader=csv.DictReader(open(os.path.join(*opts.csv),'rb'), dialect=csv.excel_tab, lineterminator="\n")
values_min=float('nan')
@@ -65,13 +67,13 @@ def get_stats(opts):
values_n+=1
values_min=min(f,values_min)
values_max=max(f,values_max)
except KeyError,ME:
except KeyError as ME:
print("Column {} not found.".format(ME),file=sys.stderr)
print("Columns in the file:"+",".join(reader.fieldnames),file=sys.stderr)
sys.exit(1)
return (values_min,values_max,values_n)
def get_plotterm(opts):
def get_plotterm(opts):
if opts.X11:
plotterm=""
else:
@@ -95,9 +97,9 @@ def get_histogram_template(opts):
(height,width)=termsize()
if opts.width:
width=opts.width
bins=min(int(float(width)/4),bins)
bins=min(int(old_div(float(width),4)),bins)
template='''{}
set datafile separator ",";
set datafile separator ",";
set xlabel '{}';
Min = {};
Max = {};
@@ -119,8 +121,8 @@ plot '<cat' u (bin($1)):(1.0) smooth freq title '' {};
def get_scatterplot_template(opts):
plotterm=get_plotterm(opts)
template = '''{}
set datafile separator ",";
set xlabel '{}';
set datafile separator ",";
set xlabel '{}';
set ylabel '{}';
{}
plot '<cat' using 1:2 title '' {};'''.format(
@@ -131,7 +133,7 @@ plot '<cat' using 1:2 title '' {};'''.format(
opts.style
)
return template
def run_gnuplot(opts, template, get_data):
p = subprocess.Popen(['gnuplot','-p','-e',template], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
comm=p.communicate(input=get_data(opts))
@@ -163,7 +165,7 @@ def which(program):
def setup_options():
''' Setup the command line options '''
parser=ArgumentParser(description="Plot CSV columns to 2D scatter plot, or a histogram. Uses GNUPLOT command line utility to draw plots.")
parser.add_argument("-v","--version",action='version', version=__version__)
parser.add_argument("-c",action="store",dest="columns",type=str,required=True,
@@ -175,7 +177,7 @@ def setup_options():
parser.add_argument("-p",action="store",dest="pre",default="",
help="Gnuplot commands to execute before plotting.")
parser.add_argument("-s",action="store",dest="style",default=None,
help="Plotting style, e.g. 'with lines'. Defaults to points for 2D plot, boxes for histogram.")
help="Plotting style, e.g. 'with lines'. Defaults to points for 2D plot, boxes for histogram.")
parser.add_argument("--width",action="store",type=int,dest="width",default=False,
help="Console width. Default: fullscreen")
parser.add_argument("--height",action="store",type=int,dest="height",default=False,
@@ -184,7 +186,7 @@ def setup_options():
help="Show plot in X11 window, instead of console.")
parser.add_argument("-D",action="store_true",dest="debug",default=False,
help="Print commands before execution")
parser.add_argument("csv",type=str,action="store",
help="CSV file to plot")
options=parser.parse_args()
@@ -197,7 +199,7 @@ def setup_options():
options.style="with boxes;"
else:
options.style="pt '*'"
return options
return options
def termsize():
try:
@@ -205,7 +207,7 @@ def termsize():
except:
(rows,columns)=(25,80)
return (int(rows),int(columns))
if not which('gnuplot'):
print('You don\'t seem to have "gnuplot" installed!')
sys.exit(1)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import os
import sys
@@ -36,16 +36,16 @@ class bc:
self.CLR = ''
self.CYA = ''
self.WHI = ''
def pos(self,y,x):
return "\033["+str(y)+";"+str(x)+"H"
class getch:
def __init__(self):
import sys, tty, termios
def get(self):
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
@@ -57,7 +57,7 @@ class getch:
def ichr(i):
''' convert integer to 1-9, a-z, A-Z, omitting x '''
''' convert integer to 1-9, a-z, A-Z, omitting x '''
if i < 10:
return str(i)
@@ -75,7 +75,7 @@ def drawmenu(entries):
twocol=False
co=bc()
helptext=""
print(co.END+co.CLR+co.pos(1,3)+co.YEL+'XRandrMenu x:exit '+helptext+co.END)
if len(entries)>20:
twocol=True
@@ -115,7 +115,7 @@ def read_displays():
pass
return entries
def append_index(entries,offset=0,color=None):
e=1+offset
for el in range(len(entries)):
@@ -138,7 +138,7 @@ def initialize():
entries=read_displays()
entries=append_index(entries,offset=0,color=bc.CYA)
return entries
def main():
arg_input=None
if (len(sys.argv)>1):

View File

@@ -199,6 +199,7 @@ def generate_index(opts):
files = [f for f in files if f != opts.filename]
files = [f for f in files if f != opts.password_filename]
files = match_files(files, opts.includes)
dirs = match_files(dirs, opts.includes)
dirs.sort()
files.sort()
files.sort(key=lambda x: x.find("/") > 0)
@@ -270,7 +271,7 @@ def get_filelink(path, fname, images=False, media=False):
if media and is_videofile(fname):
fname_str = get_videostr(fname)
return (
'<tr><td><a class="link_file" href="%s">%s</a><td class="right">%s</td><td class="right bytes">%s</td><td class="right">%s</td></tr>\n'
'<tr class="row_file"><td><a class="link_file" href="%s">&nbsp;&nbsp;%s</a><td class="right">%s</td><td class="right bytes">%s</td><td class="right">%s</td></tr>\n'
% (urllib.parse.quote(fname), fname_str, fsstr, fsstrb, fdstr)
)
@@ -306,7 +307,7 @@ def get_pathlink(path, dname):
fdate = time.localtime(os.path.getmtime(os.path.join(path, dname)))
fdstr = time.strftime("%Y/%m/%d %H:%M:%S", fdate)
return (
'<tr><td><a class="link_dir" href="%s">&#8627;&nbsp;%s/</a><td class="right">[DIR]</td><td class="right bytes">0</td><td class="right">%s</td></tr>\n'
'<tr class="row_dir"><td><a class="link_dir" href="%s">&#8627;&nbsp;%s/</a><td class="right">[DIR]</td><td class="right bytes">0</td><td class="right">%s</td></tr>\n'
% (urllib.parse.quote(dname), dname, fdstr)
)
@@ -318,7 +319,7 @@ def get_password_page(secret, target_base, target_ext):
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1, height=device-height, viewport-fit=cover">
<title>Password required</title>
<script language="JavaScript">
Object.defineProperty(String.prototype, 'hashCode', {
@@ -332,6 +333,9 @@ Object.defineProperty(String.prototype, 'hashCode', {
return hash;
}
});
function isMobile () {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
}
function scramble(p,t) {
p += t;
var sstr = '';
@@ -360,7 +364,15 @@ function pw(element) {
if (element.value) {
pw = pw.split(':',2);
if (element.value.hashCode() == parseInt(pw[0])) {
this.location.href = "TARGET_BASE." + unscramble(element.value, atob(pw[1])) + "TARGET_EXT";
let unscrambled = "TARGET_BASE." + unscramble(element.value, atob(pw[1])) + "TARGET_EXT"
if (isMobile()) {
document.location.replace(unscrambled);
return
}
document.getElementById("body").innerHTML = '';
var frame = document.createElement("iframe");
frame.src = unscrambled;
document.getElementById("body").appendChild(frame);
} else {
document.getElementById("message").innerHTML = "No match";
setTimeout(clear_message, 5000);
@@ -379,6 +391,15 @@ function newPass(password, target) {
//console.log("Use newPass('pass','page.html'); to get a new hash");
</script>
<style>
iframe {
width: 100vw;
height: 100vh;
}
#body {
margin: 0;
overflow-x: hidden;
overflow-y: hidden;
}
#content {
text-align: center;
padding-top: 4rem;
@@ -393,7 +414,7 @@ function newPass(password, target) {
}
</style>
</head>
<body>
<body id="body">
<div id="content">
<input type="password" placeholder="Password" class="password" onkeydown="pw_event(this)" id="password" onFocus="this.select()" autofocus/>
<br><button id="button" type="button" onclick="pw(document.getElementById('password'));">Enter</button>
@@ -415,6 +436,7 @@ def get_header(opts):
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, height=device-height, viewport-fit=cover">
<meta name="generator" content="SimpleWebPage """
+ VERSION
+ """" />
@@ -433,20 +455,22 @@ def get_header(opts):
body {
color: #222;
font: 14px monospace;
padding: 20px;
padding: 0;
background: #CCC;
}
h1 {
text-align: center;
padding: 20px 0 12px 0;
margin: 0;
margin: 0 0 0 70px;
font-family: sans-serif;
}
.container {
margin: 20px;
box-shadow: 0 5px 10px -5px rgba(0,0,0,0.5);
position: relative;
background: #eee;
border-top-left-radius: 6em;
border-top-left-radius: 70px;
display: inline-block;
min-width: calc(100% - 40px);
}
table {
background-color: #F3F3F3;
@@ -472,6 +496,9 @@ def get_header(opts):
display: block;
padding: 5px 10px;
}
td a.link_dir {
font-weight: bold;
}
th a {
padding-left: 0
}
@@ -482,10 +509,13 @@ def get_header(opts):
padding-left: 5px;
}
tr:nth-of-type(odd) {
background-color: #DDD;
background-color: #e1e1e1;
}
tr:hover td {
background-color:#BBB;
tr.row_dir:hover td {
background-color: #fbe6b3;
}
tr.row_file:hover td {
background-color: #f9cba2;
}
tr:hover td a {
color: #222;

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Droopy (http://stackp.online.fr/droopy)
# Copyright 2008-2012 (c) Pierre Duquesne <stackp@online.fr>
@@ -52,8 +52,12 @@
# * German translation by Michael.
# 20080408 * First release.
import BaseHTTPServer
import SocketServer
from __future__ import print_function
from future import standard_library
standard_library.install_aliases()
from builtins import str
import http.server
import socketserver
import cgi
import os
import posixpath
@@ -67,10 +71,10 @@ import shutil
import tempfile
import socket
import locale
import urllib
import urllib.request, urllib.parse, urllib.error
LOGO = '''\
_____
_____
| \.----.-----.-----.-----.--.--.
| -- | _| _ | _ | _ | | |
|_____/|__| |_____|_____| __|___ |
@@ -88,10 +92,10 @@ Options:
--dl provide download links
--save-config save options in a configuration file
--delete-config delete the configuration file and exit
Example:
droopy -m "Hi, this is Bob. You can send me a file." -p avatar.png
'''
'''
picture = None
message = ""
@@ -200,7 +204,7 @@ function update() {
}
function onunload() {
document.getElementById("form").style.display = "block";
document.getElementById("sending").style.display = "none";
document.getElementById("sending").style.display = "none";
}
</script></head>
<body>
@@ -256,7 +260,7 @@ errortmpl = '''
''' + userinfo + '''
</body>
</html>
'''
'''
linkurltmpl = '''<div id="linkurl" class="box">
<a href="http://stackp.online.fr/droopy-ip.php?port=%(port)d"> %(discover)s
@@ -611,7 +615,7 @@ class DroopyFieldStorage(cgi.FieldStorage):
return self.tmpfile
class HTTPUploadHandler(BaseHTTPServer.BaseHTTPRequestHandler):
class HTTPUploadHandler(http.server.BaseHTTPRequestHandler):
protocol_version = 'HTTP/1.0'
form_field = 'upfile'
@@ -624,9 +628,9 @@ class HTTPUploadHandler(BaseHTTPServer.BaseHTTPRequestHandler):
page can be "main", "success", or "error"
returns an html page (in the appropriate language) as a string
"""
# -- Parse accept-language header
if not self.headers.has_key("accept-language"):
if "accept-language" not in self.headers:
a = []
else:
a = self.headers["accept-language"]
@@ -638,11 +642,11 @@ class HTTPUploadHandler(BaseHTTPServer.BaseHTTPRequestHandler):
a.reverse()
a = [x[1] for x in a]
# now a is an ordered list of preferred languages
# -- Choose the appropriate translation dictionary (default is english)
lang = "en"
for l in a:
if translations.has_key(l):
if l in translations:
lang = l
break
dico = copy.copy(translations[lang])
@@ -665,7 +669,7 @@ class HTTPUploadHandler(BaseHTTPServer.BaseHTTPRequestHandler):
if names:
for name in names:
links += '<a href="/%s">%s</a><br/>' % (
urllib.quote(name.encode('utf-8')),
urllib.parse.quote(name.encode('utf-8')),
name)
links = '<div id="files">' + links + '</div>'
dico["files"] = links
@@ -682,7 +686,7 @@ class HTTPUploadHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
name = self.path.lstrip('/')
name = urllib.unquote(name)
name = urllib.parse.unquote(name)
name = name.decode('utf-8')
if picture != None and self.path == '/__droopy/picture':
@@ -701,7 +705,7 @@ class HTTPUploadHandler(BaseHTTPServer.BaseHTTPRequestHandler):
# Do some browsers /really/ use multipart ? maybe Opera ?
try:
self.log_message("Started file transfer")
# -- Set up environment for cgi.FieldStorage
env = {}
env['REQUEST_METHOD'] = self.command
@@ -714,25 +718,25 @@ class HTTPUploadHandler(BaseHTTPServer.BaseHTTPRequestHandler):
form = DroopyFieldStorage(fp = self.rfile, environ = env);
fileitem = form[self.form_field]
realname=""
if self.form_realname in form.keys():
if self.form_realname in list(form.keys()):
realname = form[self.form_realname].value.decode('utf-8')
if realname=="":
filename = self.basename(fileitem.filename).decode('utf-8')
else:
self.log_message("Got realname: %s", realname)
filename=self.basename(realname)
if filename == "":
self.send_response(303)
self.send_header('Location', '/')
self.end_headers()
return
localpath = os.path.join(directory, filename).encode('utf-8')
root, ext = os.path.splitext(localpath)
i = 1
# race condition, but hey...
while (os.path.exists(localpath)):
while (os.path.exists(localpath)):
localpath = "%s-%d%s" % (root, i, ext)
i = i+1
if hasattr(fileitem, 'tmpfile'):
@@ -757,7 +761,7 @@ class HTTPUploadHandler(BaseHTTPServer.BaseHTTPRequestHandler):
else:
self.send_html(self.html("success"))
except Exception, e:
except Exception as e:
self.log_message(repr(e))
self.send_html(self.html("error"))
@@ -792,7 +796,7 @@ class HTTPUploadHandler(BaseHTTPServer.BaseHTTPRequestHandler):
if publish_files:
# os.listdir() returns a list of unicode strings when the
# directory is passed as an unicode string itself.
names = [name for name in os.listdir(unicode(directory))
names = [name for name in os.listdir(str(directory))
if os.path.isfile(os.path.join(directory, name))
and not name.startswith(DroopyFieldStorage.TMPPREFIX)]
names.sort()
@@ -802,8 +806,8 @@ class HTTPUploadHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def handle(self):
try:
BaseHTTPServer.BaseHTTPRequestHandler.handle(self)
except socket.error, e:
http.server.BaseHTTPRequestHandler.handle(self)
except socket.error as e:
self.log_message(str(e))
raise Abort()
@@ -811,14 +815,14 @@ class HTTPUploadHandler(BaseHTTPServer.BaseHTTPRequestHandler):
class Abort(Exception): pass
class ThreadedHTTPServer(SocketServer.ThreadingMixIn,
BaseHTTPServer.HTTPServer):
class ThreadedHTTPServer(socketserver.ThreadingMixIn,
http.server.HTTPServer):
def handle_error(self, request, client_address):
# Override SocketServer.handle_error
exctype = sys.exc_info()[0]
if not exctype is Abort:
BaseHTTPServer.HTTPServer.handle_error(self,request,client_address)
http.server.HTTPServer.handle_error(self,request,client_address)
# -- Options
@@ -858,7 +862,7 @@ def save_options():
f.write('\n'.join(opt).encode('utf8'))
f.close()
def load_options():
try:
f = open(configfile())
@@ -867,7 +871,7 @@ def load_options():
parse_args(cmd)
f.close()
return True
except IOError, e:
except IOError as e:
return False
@@ -883,7 +887,7 @@ def parse_args(cmd=None):
lang, encoding = locale.getdefaultlocale()
if encoding != None:
cmd = [a.decode(encoding) for a in cmd]
opts, args = None, None
try:
opts, args = getopt.gnu_getopt(cmd, "p:m:d:h",
@@ -891,8 +895,8 @@ def parse_args(cmd=None):
"directory=", "help",
"save-config","delete-config",
"dl"])
except Exception, e:
print e
except Exception as e:
print(e)
sys.exit(1)
for o,a in opts:
@@ -904,7 +908,7 @@ def parse_args(cmd=None):
elif o in ['-d', '--directory']:
directory = a
elif o in ['--save-config']:
must_save_options = True
@@ -912,16 +916,16 @@ def parse_args(cmd=None):
try:
filename = configfile()
os.remove(filename)
print 'Deleted ' + filename
except Exception, e:
print e
print('Deleted ' + filename)
except Exception as e:
print(e)
sys.exit(0)
elif o in ['--dl']:
publish_files = True
elif o in ['-h', '--help']:
print USAGE
print(USAGE)
sys.exit(0)
# port number
@@ -929,11 +933,11 @@ def parse_args(cmd=None):
if args[0:]:
port = int(args[0])
except ValueError:
print args[0], "is not a valid port number"
print(args[0], "is not a valid port number")
sys.exit(1)
# --
# --
def run():
"""Run the webserver."""
@@ -944,25 +948,25 @@ def run():
if __name__ == '__main__':
print LOGO
print(LOGO)
config_found = load_options()
parse_args()
if config_found:
print 'Configuration found in %s' % configfile()
print('Configuration found in %s' % configfile())
else:
print "No configuration file found."
print("No configuration file found.")
if must_save_options:
save_options()
print "Options saved in %s" % configfile()
print("Options saved in %s" % configfile())
print "Files will be uploaded to %s" % directory
print("Files will be uploaded to %s" % directory)
try:
print
print "HTTP server running... Check it out at http://localhost:%d"%port
print()
print("HTTP server running... Check it out at http://localhost:%d"%port)
run()
except KeyboardInterrupt:
print '^C received, shutting down server'
print('^C received, shutting down server')
# some threads may run until they terminate

View File

@@ -1,8 +1,8 @@
#!/bin/sh
python -c "import pyftpdlib" >/dev/null 2>&1 || {
python3 -c "import pyftpdlib" >/dev/null 2>&1 || {
echo "pyftpdlib is not installed:"
echo " pip install --user pyftpdlib"
exit
echo " pip3 install --user pyftpdlib"
exit
}
python -m pyftpdlib "$@"
python3 -m pyftpdlib "$@"