patternpythonMinor
Fast tag replacements
Viewed 0 times
fastreplacementstag
Problem
This uses the Stack Exchange API to quickly batch replace tags in questions.
I still need to fully comment and make the Wiki, but are there any glaring mistakes in it?
I have tried to use
```
# -- coding: utf-8 --
# Version 1.0.3
global HTML
global fetch
import requests
import webbrowser
import json
import sys
import os
import time
from time import sleep as update
import math as maths
try:
input = raw_input
except NameError:
input = input
try:
import HTMLParser
HTMLParser=HTMLParser
except NameError:
import html.parser
HTMLParser=html.parser
HTML=max
fetch=True*8**2-4
def kill_code(reason='No Message'):
sys.exit(reason)
exit(reason)
quit(reason)
# uses os.popen to get the terminal size.
def get_width():
global width
try:
width = os.popen('stty size', 'r').read().split()[1]
supported=True
except IndexError as error:
width = 50
supported=False
width = int(width)
return supported
# Prints out a spacer like ---------- the width of the console. If width is not supported, it will be 50 wide.
def spacer():
get_width()
print ('-'*width)
# Creates a loading bar like [======== ] the width of the console. Updates with get_width() each time it's called.
def loading_bar(n,i):
if get_width():
factor=(n/(width-2.0))
n=int(maths.floor((n)/factor))
i=int(maths.floor((i-1)/factor))
sys.stdout.write('['+'='(n-i)+' '(i)+']')
sys.stdout.flush()
sys.stdout.write('\r')
sys.stdout.flush()
else:
print ('=')
def check_for_error(response_JSON):
try:
kill_code('Got error message: '+response_JSON['error_message'])
except KeyError:
return False
# Checks that the API hasn't said to go away. If it has it sleeps for the time allocated.
def backoff(response_JSON):
tr
I still need to fully comment and make the Wiki, but are there any glaring mistakes in it?
I have tried to use
try: except: wherever I can to prevent any errors, and have attempted to make it compatible for Python 2 and Python 3.```
# -- coding: utf-8 --
# Version 1.0.3
global HTML
global fetch
import requests
import webbrowser
import json
import sys
import os
import time
from time import sleep as update
import math as maths
try:
input = raw_input
except NameError:
input = input
try:
import HTMLParser
HTMLParser=HTMLParser
except NameError:
import html.parser
HTMLParser=html.parser
HTML=max
fetch=True*8**2-4
def kill_code(reason='No Message'):
sys.exit(reason)
exit(reason)
quit(reason)
# uses os.popen to get the terminal size.
def get_width():
global width
try:
width = os.popen('stty size', 'r').read().split()[1]
supported=True
except IndexError as error:
width = 50
supported=False
width = int(width)
return supported
# Prints out a spacer like ---------- the width of the console. If width is not supported, it will be 50 wide.
def spacer():
get_width()
print ('-'*width)
# Creates a loading bar like [======== ] the width of the console. Updates with get_width() each time it's called.
def loading_bar(n,i):
if get_width():
factor=(n/(width-2.0))
n=int(maths.floor((n)/factor))
i=int(maths.floor((i-1)/factor))
sys.stdout.write('['+'='(n-i)+' '(i)+']')
sys.stdout.flush()
sys.stdout.write('\r')
sys.stdout.flush()
else:
print ('=')
def check_for_error(response_JSON):
try:
kill_code('Got error message: '+response_JSON['error_message'])
except KeyError:
return False
# Checks that the API hasn't said to go away. If it has it sleeps for the time allocated.
def backoff(response_JSON):
tr
Solution
- Introduction
There's quite a bit of code here, so I'm just going to review one of your functions (
get_width). You'll see that there's plenty here for one answer. Maybe some other reviewers will look at some of the rest of your code.# uses os.popen to get the terminal size.
def get_width():
global width
try:
width = os.popen('stty size', 'r').read().split()[1]
supported=True
except IndexError as error:
width = 50
supported=False
width = int(width)
return supported- Review
-
The name of the function is ambiguous: get the width of what? Something like
terminal_width would be better.-
There's a comment but it would be better if this were a docstring: then you could read it using
help(get_width) from the interactive interpreter.-
The comment says:
# uses os.popen to get the terminal size.but this is misleading. Someone who just read the comment might think that
get_width returned the terminal width, but in fact the function stores the terminal width in a global variable and returns something else.-
It's not clear what the "something else" is. The variable name is
supported. But what is it that's supported or not?-
It's a bad idea to use global variables to pass state around — it's all too easy to forget whether or not you've updated them. I presume that you're doing this because
get_width has two pieces of information to return (the terminal width, and whether something or other is supported). But in Python, functions can return multiple values using a tuple, like this:return supported, width-
The code says:
except IndexError as error:but
error is not used, so write:except IndexError:-
There's no need to call
int(width) in the IndexError case, as the code has already set width = 50.-
If
stty fails for some reason, for example:stty: stdin isn't a terminal
then
int(width) will raise ValueError. This needs to be handled.-
stty size reports 0 0 if it can't determine the terminal size. This needs to be handled.-
The mode argument to
os.popen defaults to 'r', so there's no need to specify it.-
The code opens a pipe using
os.popen but does not close it. It happens to be the case that CPython automatically closes files when the reference count of the associated file object goes to zero, but this is not something you want to get into the habit of relying on because other Python implementations have different behaviour. Use the with statement to ensure that the pipe is closed:with os.popen('stty size') as f:
try:
width = int(f.read().split()[1])
# etc.-
os.popen runs a subprocess using a shell. This wastes a process (you don't need any shell features, you only want to run stty) and is a bad habit to get into because the shell has to parse the command you give it, and in more complicated situations that can be a security risk. It would be better to use subprocess.check_output to run stty directly, bypassing the shell.-
Instead of calling the external process
stty, why not interrogate the terminal directly? The idea is to use the ioctl (I/O device control) system call via the Python interface fnctl.ioctl, passing the TIOCGWINSZ ("terminal I/O control: get window size") command, which returns a pair of unsigned short (16-bit) values that can be decoded using struct.unpack.rows, cols = unpack('hh', ioctl(sys.stdout, TIOCGWINSZ, '0000'))This is exactly what the
stty size command does, except that you are avoiding the extra process.-
If you can't determine the terminal size via the
ioctl call, it's a good idea to fall back to consulting the environment. Some shells set the LINES and COLUMNS environment variables.-
To make the function more generally usable, why not return the rows as well as the columns? You have the value in your hand, so why not return it?
-
You use the
supported flag to decide what kind of progress bar to draw. Presumably what you actually want to know is whether the standard output is connected to a terminal? But in that case you should just use the built-in os.isatty.- Revised code
from struct import unpack
from fcntl import ioctl
import os
import sys
from termios import TIOCGWINSZ
def terminal_size(fd=sys.stdout, default=(25, 80)):
"""Return the size of the terminal attached to fd, as a tuple (rows,
columns). If the size can't be determined, return default.
"""
def fallback(value, key, default):
if value > 0:
return value
try:
return int(os.environ.get(key, default))
except ValueError:
return default
size = unpack('hh', ioctl(fd, TIOCGWINSZ, '0000'))
return tuple(map(fallback, size, ('LINES', 'COLUMNS'), default))Code Snippets
# uses os.popen to get the terminal size.
def get_width():
global width
try:
width = os.popen('stty size', 'r').read().split()[1]
supported=True
except IndexError as error:
width = 50
supported=False
width = int(width)
return supported# uses os.popen to get the terminal size.return supported, widthexcept IndexError as error:except IndexError:Context
StackExchange Code Review Q#92101, answer score: 8
Revisions (0)
No revisions yet.