Skip to content

Commit

Permalink
Make everything work for Python 2 and 3
Browse files Browse the repository at this point in the history
  • Loading branch information
fschaeck committed Apr 22, 2021
1 parent 749b6b9 commit d98010b
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 64 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
*.pyc
__pycache__

# pyenv files
.python-version

# generated test files
test-tmp-*
tests/script.good
Expand Down
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ install:
- pip install coveralls

script:
- if [ $TRAVIS_PYTHON_VERSION != '2.7' ]; then coverage run tests/test_script_io.py; fi
- coverage run tests/test_script_io.py
- coverage run tests/test_script_inplace.py
- coverage run tests/test-suite.py @all-tests.suites -x test-python-sed.exclude
- coverage run tests/test_suite.py @all-tests.suites -x test-python-sed.exclude

after_success:
- coveralls
90 changes: 52 additions & 38 deletions PythonSed/sed.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,17 @@
import re
import sys
import os
import io
import ast
import argparse
import string
import webbrowser

if sys.version_info[0]==2:
PY2 = True
else:
PY2 = False
from io import open as open

class ScriptLine (object):
debug = 0

Expand Down Expand Up @@ -324,7 +329,8 @@ def add_file(self, filename, encoding):
self.file_idx += 1
lineno = 0
try:
with io.open(filename, 'r',encoding=encoding) as f:
args = {} if PY2 else { 'encoding': encoding }
with open(filename, 'rt', **args) as f:
for line in f.readlines():
lineno += 1
self._add(ScriptLine(
Expand Down Expand Up @@ -1073,7 +1079,7 @@ def normalize_string(strng,line_length):

x = ''
for c in strng:
if chr(32) <= c < chr(128):
if 32 <= ord(c) <= 127:
if c=='\\':
x += c
x += c
Expand All @@ -1082,7 +1088,7 @@ def normalize_string(strng,line_length):
elif c=='\t':
x += '\\t'
else:
x += '\\'+('00'+oct(ord(c))[2:])[-3:]
x += '\\'+('00'+oct(ord(c))[1:])[-3:]

width = line_length-1
while len(x)>width:
Expand Down Expand Up @@ -1132,7 +1138,7 @@ def printline(self, source, line):
def flush_append_buffer(self):
for line in self.append_buffer:
self.printline('appnd',line)
self.append_buffer.clear()
self.append_buffer = []

def getReader(self,
source_files,
Expand Down Expand Up @@ -1299,7 +1305,8 @@ def __init__(self,output,encoding,in_place,debug=0):
if type(output)==str:
self.current_filename = output
try:
self.current_output = io.open(output, 'wt', encoding=self.encoding)
args = {} if PY2 else { 'encoding': self.encoding }
self.current_output = open(output, 'wt', **args)
self.current_output_opened = True
except Exception as e:
raise SedException('',"Can not open output file {file}: {err}",file=output,err=str(e))
Expand All @@ -1312,27 +1319,28 @@ def is_inplace(self):
def printline(self, line):
line += '\n'
if self.current_output:
print(line,end='',file=self.current_output)
self.current_output.write(line)
self.output_lines.append(line)

def add_write_file(self,filename):
if self.open_files.get(filename) is None:
self.open_files[filename] = io.open(filename, 'wt', encoding=self.encoding)
args = {} if PY2 else { 'encoding':self.encoding }
self.open_files[filename] = open(filename, 'wt', **args)

def write_to_file(self,filename,line):
file = self.open_files.get(filename)
if file is None:
open_file = self.open_files.get(filename)
if open_file is None:
if filename=='/dev/stdout' or filename=='-':
file = sys.stdout
open_file = sys.stdout
elif filename=='/dev/stderr':
file = sys.stderr
open_file = sys.stderr
else:
raise SedException('','File {file} not opened for writing.',file=filename)
if not line.endswith('\n'):
line += '\n'
if self.debug>0:
print('writing to '+filename+': '+line,end='',file=sys.stderr)
print(line,end='',file=file)
open_file.write(line)

def open_inplace(self,file_name):
self.current_filename = os.path.abspath(file_name)
Expand Down Expand Up @@ -1374,9 +1382,9 @@ def finish(self):
self.current_output.close()
except:
pass
for file in self.open_files.values():
for open_file in self.open_files.values():
try:
file.close()
open_file.close()
except:
pass
return self.output_lines
Expand Down Expand Up @@ -1423,7 +1431,8 @@ def open_next(self):
self.input_stream_opened = False
else:
try:
self.input_stream = io.open(source_file, encoding=self.encoding)
args = {} if PY2 else { 'encoding': self.encoding }
self.input_stream = open(source_file, mode='rt', **args)
self.source_file_name = source_file
self.input_stream_opened = True
except IOError as e:
Expand Down Expand Up @@ -1459,11 +1468,11 @@ def next_line(self):

def readline_from_file(self,filename):
if filename in self.open_files:
file = self.open_files.get(filename)
if file is not None:
line = file.readline()
open_file = self.open_files.get(filename)
if open_file is not None:
line = open_file.readline()
if len(line)==0:
file.close()
open_file.close()
self.open_files[filename] = None
return ''
return line
Expand All @@ -1472,14 +1481,15 @@ def readline_from_file(self,filename):
elif filename=='/dev/stdin' or filename=='-':
return sys.stdin.readline()
else:
file = None
open_file = None
try:
file = io.open(filename,encoding=self.encoding)
self.open_files[filename] = file
return file.readline()
args = {} if PY2 else { 'encoding': self.encoding }
open_file = open(filename,mode='rt',**args)
self.open_files[filename] = open_file
return open_file.readline()
except:
if file:
file.close()
if open_file:
open_file.close()
self.open_files[filename] = None
return ''

Expand All @@ -1489,10 +1499,10 @@ def close(self):
self.input_stream.close()
except:
pass
for file in self.open_files.values():
if file:
for open_file in self.open_files.values():
if open_file:
try:
file.close()
open_file.close()
except:
pass

Expand All @@ -1510,10 +1520,10 @@ def __init__(self, source_files,encoding,writer):
files = [ source_files ]
if len(files)==0:
raise SedException('','Can not use stdin as input for inplace-editing.')
for file in files:
if file is None or file=='-':
for open_file in files:
if open_file is None or open_file=='-':
raise SedException('','Can not use stdin as input for inplace-editing.')
elif type(file)!=str:
elif type(open_file)!=str:
raise SedException('','Can not use streams or files as input for inplace-editing.')

self.writer = writer
Expand Down Expand Up @@ -1564,10 +1574,10 @@ def __init__(self, source_files,encoding,writer):
files = [ source_files ]
if len(files)==0:
raise SedException('','Can not use stdin as input for inplace-editing.')
for file in files:
if file is None or file=='-':
for filename in files:
if filename is None or filename=='-':
raise SedException('','Can not use stdin as input for inplace-editing.')
elif type(file)!=str:
elif type(filename)!=str:
raise SedException('','Can not use streams or files as input for inplace-editing.')
self.writer = writer
super(ReaderBufSepInplace,self). __init__(source_files,encoding)
Expand Down Expand Up @@ -1879,7 +1889,8 @@ def parse_arguments(self,script):
def apply(self, sed):
# https://groups.yahoo.com/neo/groups/sed-users/conversations/topics/9096
try:
with io.open(self.filename, encoding=sed.encoding) as f:
args = {} if PY2 else { 'encoding': sed.encoding }
with open(self.filename, 'rt', **args) as f:
for line in f:
sed.append_buffer.append(line[:-1] if line.endswith('\n') else line)
except:
Expand Down Expand Up @@ -1988,7 +1999,7 @@ def str_arguments(self):

return "{regex}{repl}{delim}{flags}".format(
delim=self.delim,
regex=str(self.regexp),
regex=self.regexp.toString(),
repl=self.repl.string,
flags=flags)

Expand Down Expand Up @@ -2033,7 +2044,7 @@ def apply(self, sed):
return None

class Command_v(Command):
def apply(self, sed):
def apply(self, sed): # @UnusedVariable
pass
return self.next

Expand Down Expand Up @@ -2316,6 +2327,9 @@ def __init__(self, position, delim, pattern, py_pattern, dollars, address=True):
self.compiled = None

def __str__(self):
return self.toString()

def toString(self):
result = '' if self.delim=='/' else '\\'
result += self.delim+self.pattern+self.delim
if self.address:
Expand Down
4 changes: 3 additions & 1 deletion tests/test_script_inplace.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import print_function

"""
Test input and output arguments of sed.apply (filenames, files or streams)
"""
Expand Down Expand Up @@ -39,7 +41,7 @@ def remove_file(filename):
def main():
exit_code = test_inplace(SED_SCRIPT,'.bkup',0)
if exit_code==0:
exit_code += test_inplace(SED_SCRIPT2,'*.bkup',2)
exit_code += test_inplace(SED_SCRIPT2,'*.bkup',0)

if exit_code==0:
# ok
Expand Down
32 changes: 24 additions & 8 deletions tests/test_script_io.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
from __future__ import print_function

"""
Test input and output arguments of sed.apply (filenames, files or streams)
"""

import os
import sys
import io
from PythonSed import Sed

if sys.version_info[0]==2:
# python2
from StringIO import StringIO
else:
# python3
from io import StringIO

INPUT_STRING = 'In Xanadu did Kubla Khan\n'
OUTPUT_STRING = 'In XANadu did Kubla KhAN\n'
Expand Down Expand Up @@ -49,15 +56,24 @@ def main():
exit_code += 4

# input and output arguments are streams
with io.StringIO(INPUT_STRING) as stream_in, io.StringIO() as stream_out:
stream_in = None
stream_out = None
try:
stream_in = StringIO(INPUT_STRING)
stream_out = StringIO()
sed.apply(stream_in, stream_out)
s = stream_out.getvalue()
if s != OUTPUT_STRING:
print('Input and output arguments are stream objects:')
print('|' + s + '|')
print('|' + OUTPUT_STRING + '|')
exit_code += 8

if s != OUTPUT_STRING:
print('Input and output arguments are stream objects:')
print('|' + s + '|')
print('|' + OUTPUT_STRING + '|')
exit_code += 8
finally:
if stream_in is not None:
stream_in.close()
if stream_out is not None:
stream_out.close()

finally:
if os.path.exists(INPUT_FILENAME):
os.remove(INPUT_FILENAME)
Expand Down

0 comments on commit d98010b

Please sign in to comment.